1
0
Fork 0

Finalize interpreter for now

This commit is contained in:
Vili Sinervä 2025-02-03 23:04:36 +02:00
parent f4b208dfde
commit 38dd3f523b
No known key found for this signature in database
GPG key ID: DF8FEAF54EFAC996
3 changed files with 146 additions and 104 deletions

View file

@ -24,22 +24,20 @@ impl<'source> Interpreter<'source> {
BoolLiteral(_, val) => Value::Bool(*val), BoolLiteral(_, val) => Value::Bool(*val),
Identifier(_, name) => *self.symbols.get(name), Identifier(_, name) => *self.symbols.get(name),
UnaryOp(_, op, expr) => match *op { UnaryOp(_, op, expr) => match *op {
"-" => -self.interpret(expr), "-" => {
"not" => !self.interpret(expr), let Value::Func(op_fn) = self.symbols.get("neg") else {
_ => panic!("Unrecognized unary op {}", op), panic!("Operator {} does not correspond to a function!", op);
};
op_fn(&[self.interpret(expr)])
}
_ => {
let Value::Func(op_fn) = self.symbols.get(op) else {
panic!("Operator {} does not correspond to a function!", op);
};
op_fn(&[self.interpret(expr)])
}
}, },
BinaryOp(_, left, op, right) => match *op { BinaryOp(_, left, op, right) => match *op {
"+" => self.interpret(left) + self.interpret(right),
"*" => self.interpret(left) * self.interpret(right),
"-" => self.interpret(left) - self.interpret(right),
"/" => self.interpret(left) / self.interpret(right),
"%" => self.interpret(left) % self.interpret(right),
"==" => Value::Bool(self.interpret(left) == self.interpret(right)),
"!=" => Value::Bool(self.interpret(left) != self.interpret(right)),
"<" => Value::Bool(self.interpret(left) < self.interpret(right)),
"<=" => Value::Bool(self.interpret(left) <= self.interpret(right)),
">" => Value::Bool(self.interpret(left) > self.interpret(right)),
">=" => Value::Bool(self.interpret(left) >= self.interpret(right)),
"and" => { "and" => {
let left_val = self.interpret(left); let left_val = self.interpret(left);
if let Value::Bool(val_l) = left_val { if let Value::Bool(val_l) = left_val {
@ -83,7 +81,12 @@ impl<'source> Interpreter<'source> {
panic!("Assignment must have identifier as left expr!"); panic!("Assignment must have identifier as left expr!");
} }
} }
_ => panic!("Unrecognized binary op {}", op), _ => {
let Value::Func(op_fn) = self.symbols.get(op) else {
panic!("Operator {} does not correspond to a function!", op);
};
op_fn(&[self.interpret(left), self.interpret(right)])
}
}, },
VarDeclaration(_, name, expr) => { VarDeclaration(_, name, expr) => {
let value = self.interpret(expr); let value = self.interpret(expr);
@ -121,7 +124,18 @@ impl<'source> Interpreter<'source> {
} }
val val
} }
FunCall(_, name, args) => todo!(), // Functions are TODO FunCall(_, name, args) => {
let mut arg_values = Vec::new();
for arg in args {
arg_values.push(self.interpret(arg));
}
let Value::Func(function) = self.symbols.get(name) else {
panic!("Identifier {} does not correspond to a function!", name);
};
function(&arg_values)
}
Block(_, expressions) => { Block(_, expressions) => {
self.symbols = SymTab { self.symbols = SymTab {
locals: HashMap::new(), locals: HashMap::new(),

View file

@ -19,8 +19,24 @@ impl<'source> SymTab<'source> {
} }
pub fn new_global() -> SymTab<'source> { pub fn new_global() -> SymTab<'source> {
let locals = HashMap::from([
("+", Value::Func(Value::add)),
("*", Value::Func(Value::mul)),
("-", Value::Func(Value::sub)),
("/", Value::Func(Value::div)),
("%", Value::Func(Value::rem)),
("==", Value::Func(Value::eq)),
("!=", Value::Func(Value::neq)),
("<", Value::Func(Value::lt)),
("<=", Value::Func(Value::le)),
(">", Value::Func(Value::gt)),
(">=", Value::Func(Value::ge)),
("not", Value::Func(Value::not)),
("neg", Value::Func(Value::neg)),
]);
SymTab { SymTab {
locals: HashMap::new(), locals,
parent: None, parent: None,
} }
} }

View file

@ -1,12 +1,10 @@
use std::{ use std::fmt;
fmt,
ops::{Add, Div, Mul, Neg, Not, Rem, Sub},
};
#[derive(PartialEq, PartialOrd, Debug, Copy, Clone)] #[derive(PartialEq, PartialOrd, Debug, Copy, Clone)]
pub enum Value { pub enum Value {
Int(i64), Int(i64),
Bool(bool), Bool(bool),
Func(fn(&[Value]) -> Value),
None(), None(),
} }
@ -15,111 +13,125 @@ impl fmt::Display for Value {
match self { match self {
Value::Int(val) => write!(f, "{}", val), Value::Int(val) => write!(f, "{}", val),
Value::Bool(val) => write!(f, "{}", val), Value::Bool(val) => write!(f, "{}", val),
Value::Func(_) => write!(f, "<FunctionCall>"),
Value::None() => write!(f, "<Unit>"), Value::None() => write!(f, "<Unit>"),
} }
} }
} }
impl Add for Value { impl Value {
type Output = Self; pub fn add(args: &[Self]) -> Self {
assert_eq!(args.len(), 2);
fn add(self, other: Self) -> Self::Output { let Value::Int(lhs) = args[0] else {
if let Value::Int(val1) = self {
if let Value::Int(val2) = other {
Value::Int(val1 + val2)
} else {
panic!("Can't apply + to non-ints!") panic!("Can't apply + to non-ints!")
} };
} else { let Value::Int(rhs) = args[1] else {
panic!("Can't apply + to non-ints!") panic!("Can't apply + to non-ints!")
} };
}
}
impl Mul for Value { Value::Int(lhs + rhs)
type Output = Self; }
fn mul(self, other: Self) -> Self::Output { pub fn mul(args: &[Self]) -> Self {
if let Value::Int(val1) = self { assert_eq!(args.len(), 2);
if let Value::Int(val2) = other {
Value::Int(val1 * val2) let Value::Int(lhs) = args[0] else {
} else {
panic!("Can't apply * to non-ints!") panic!("Can't apply * to non-ints!")
} };
} else { let Value::Int(rhs) = args[1] else {
panic!("Can't apply * to non-ints!") panic!("Can't apply * to non-ints!")
} };
}
}
impl Sub for Value { Value::Int(lhs * rhs)
type Output = Self; }
fn sub(self, other: Self) -> Self::Output { pub fn sub(args: &[Self]) -> Self {
if let Value::Int(val1) = self { assert_eq!(args.len(), 2);
if let Value::Int(val2) = other {
Value::Int(val1 - val2) let Value::Int(lhs) = args[0] else {
} else {
panic!("Can't apply - to non-ints!") panic!("Can't apply - to non-ints!")
} };
} else { let Value::Int(rhs) = args[1] else {
panic!("Can't apply - to non-ints!") panic!("Can't apply - to non-ints!")
} };
}
}
impl Div for Value { Value::Int(lhs - rhs)
type Output = Self; }
fn div(self, other: Self) -> Self::Output { pub fn div(args: &[Self]) -> Self {
if let Value::Int(val1) = self { assert_eq!(args.len(), 2);
if let Value::Int(val2) = other {
Value::Int(val1 / val2) let Value::Int(lhs) = args[0] else {
} else {
panic!("Can't apply / to non-ints!") panic!("Can't apply / to non-ints!")
} };
} else { let Value::Int(rhs) = args[1] else {
panic!("Can't apply / to non-ints!") panic!("Can't apply / to non-ints!")
} };
}
}
impl Rem for Value { Value::Int(lhs / rhs)
type Output = Self; }
fn rem(self, other: Self) -> Self::Output { pub fn rem(args: &[Self]) -> Self {
if let Value::Int(val1) = self { assert_eq!(args.len(), 2);
if let Value::Int(val2) = other {
Value::Int(val1 % val2) let Value::Int(lhs) = args[0] else {
} else {
panic!("Can't apply % to non-ints!") panic!("Can't apply % to non-ints!")
} };
} else { let Value::Int(rhs) = args[1] else {
panic!("Can't apply % to non-ints!") panic!("Can't apply % to non-ints!")
} };
}
}
impl Neg for Value { Value::Int(lhs / rhs)
type Output = Self;
fn neg(self) -> Self::Output {
if let Value::Int(val) = self {
Value::Int(-val)
} else {
panic!("Can't apply - to non-ints!")
} }
pub fn eq(args: &[Self]) -> Self {
assert_eq!(args.len(), 2);
Value::Bool(args[0] == args[1])
} }
}
impl Not for Value { pub fn neq(args: &[Self]) -> Self {
type Output = Self; assert_eq!(args.len(), 2);
Value::Bool(args[0] != args[1])
}
pub fn lt(args: &[Self]) -> Self {
assert_eq!(args.len(), 2);
Value::Bool(args[0] < args[1])
}
pub fn le(args: &[Self]) -> Self {
assert_eq!(args.len(), 2);
Value::Bool(args[0] <= args[1])
}
pub fn gt(args: &[Self]) -> Self {
assert_eq!(args.len(), 2);
Value::Bool(args[0] > args[1])
}
pub fn ge(args: &[Self]) -> Self {
assert_eq!(args.len(), 2);
Value::Bool(args[0] >= args[1])
}
pub fn not(args: &[Self]) -> Self {
assert_eq!(args.len(), 1);
let Value::Bool(val) = args[0] else {
panic!("Can't apply 'not' to non-bools!")
};
fn not(self) -> Self::Output {
if let Value::Bool(val) = self {
Value::Bool(!val) Value::Bool(!val)
} else {
panic!("Can't apply ! to non-bools!")
} }
pub fn neg(args: &[Self]) -> Self {
assert_eq!(args.len(), 1);
let Value::Int(val) = args[0] else {
panic!("Can't apply negation to non-ints!")
};
Value::Int(-val)
} }
} }