From 38dd3f523b4a0bda2af307229d6aa52b65b7a5bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vili=20Sinerv=C3=A4?= Date: Mon, 3 Feb 2025 23:04:36 +0200 Subject: [PATCH] Finalize interpreter for now --- src/compiler/interpreter.rs | 46 +++++---- src/compiler/symtab.rs | 18 +++- src/compiler/value.rs | 186 +++++++++++++++++++----------------- 3 files changed, 146 insertions(+), 104 deletions(-) diff --git a/src/compiler/interpreter.rs b/src/compiler/interpreter.rs index 3652f7e..888a648 100644 --- a/src/compiler/interpreter.rs +++ b/src/compiler/interpreter.rs @@ -24,22 +24,20 @@ impl<'source> Interpreter<'source> { BoolLiteral(_, val) => Value::Bool(*val), Identifier(_, name) => *self.symbols.get(name), UnaryOp(_, op, expr) => match *op { - "-" => -self.interpret(expr), - "not" => !self.interpret(expr), - _ => panic!("Unrecognized unary op {}", op), + "-" => { + let Value::Func(op_fn) = self.symbols.get("neg") else { + 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 { - "+" => 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" => { let left_val = self.interpret(left); 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!("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) => { let value = self.interpret(expr); @@ -121,7 +124,18 @@ impl<'source> Interpreter<'source> { } 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) => { self.symbols = SymTab { locals: HashMap::new(), diff --git a/src/compiler/symtab.rs b/src/compiler/symtab.rs index f712178..1f90f20 100644 --- a/src/compiler/symtab.rs +++ b/src/compiler/symtab.rs @@ -19,8 +19,24 @@ impl<'source> 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 { - locals: HashMap::new(), + locals, parent: None, } } diff --git a/src/compiler/value.rs b/src/compiler/value.rs index 7325c68..e4e8d97 100644 --- a/src/compiler/value.rs +++ b/src/compiler/value.rs @@ -1,12 +1,10 @@ -use std::{ - fmt, - ops::{Add, Div, Mul, Neg, Not, Rem, Sub}, -}; +use std::fmt; #[derive(PartialEq, PartialOrd, Debug, Copy, Clone)] pub enum Value { Int(i64), Bool(bool), + Func(fn(&[Value]) -> Value), None(), } @@ -15,111 +13,125 @@ impl fmt::Display for Value { match self { Value::Int(val) => write!(f, "{}", val), Value::Bool(val) => write!(f, "{}", val), + Value::Func(_) => write!(f, ""), Value::None() => write!(f, ""), } } } -impl Add for Value { - type Output = Self; +impl Value { + pub fn add(args: &[Self]) -> Self { + assert_eq!(args.len(), 2); - fn add(self, other: Self) -> Self::Output { - if let Value::Int(val1) = self { - if let Value::Int(val2) = other { - Value::Int(val1 + val2) - } else { - panic!("Can't apply + to non-ints!") - } - } else { + let Value::Int(lhs) = args[0] else { panic!("Can't apply + to non-ints!") - } + }; + let Value::Int(rhs) = args[1] else { + panic!("Can't apply + to non-ints!") + }; + + Value::Int(lhs + rhs) } -} -impl Mul for Value { - type Output = Self; + pub fn mul(args: &[Self]) -> Self { + assert_eq!(args.len(), 2); - fn mul(self, other: Self) -> Self::Output { - if let Value::Int(val1) = self { - if let Value::Int(val2) = other { - Value::Int(val1 * val2) - } else { - panic!("Can't apply * to non-ints!") - } - } else { + let Value::Int(lhs) = args[0] else { panic!("Can't apply * to non-ints!") - } + }; + let Value::Int(rhs) = args[1] else { + panic!("Can't apply * to non-ints!") + }; + + Value::Int(lhs * rhs) } -} -impl Sub for Value { - type Output = Self; + pub fn sub(args: &[Self]) -> Self { + assert_eq!(args.len(), 2); - fn sub(self, other: Self) -> Self::Output { - if let Value::Int(val1) = self { - if let Value::Int(val2) = other { - Value::Int(val1 - val2) - } else { - panic!("Can't apply - to non-ints!") - } - } else { + let Value::Int(lhs) = args[0] else { panic!("Can't apply - to non-ints!") - } + }; + let Value::Int(rhs) = args[1] else { + panic!("Can't apply - to non-ints!") + }; + + Value::Int(lhs - rhs) } -} -impl Div for Value { - type Output = Self; + pub fn div(args: &[Self]) -> Self { + assert_eq!(args.len(), 2); - fn div(self, other: Self) -> Self::Output { - if let Value::Int(val1) = self { - if let Value::Int(val2) = other { - Value::Int(val1 / val2) - } else { - panic!("Can't apply / to non-ints!") - } - } else { + let Value::Int(lhs) = args[0] else { panic!("Can't apply / to non-ints!") - } + }; + let Value::Int(rhs) = args[1] else { + panic!("Can't apply / to non-ints!") + }; + + Value::Int(lhs / rhs) } -} -impl Rem for Value { - type Output = Self; + pub fn rem(args: &[Self]) -> Self { + assert_eq!(args.len(), 2); - fn rem(self, other: Self) -> Self::Output { - if let Value::Int(val1) = self { - if let Value::Int(val2) = other { - Value::Int(val1 % val2) - } else { - panic!("Can't apply % to non-ints!") - } - } else { + let Value::Int(lhs) = args[0] else { panic!("Can't apply % to non-ints!") - } - } -} - -impl Neg for Value { - 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!") - } - } -} - -impl Not for Value { - type Output = Self; - - fn not(self) -> Self::Output { - if let Value::Bool(val) = self { - Value::Bool(!val) - } else { - panic!("Can't apply ! to non-bools!") - } + }; + let Value::Int(rhs) = args[1] else { + panic!("Can't apply % to non-ints!") + }; + + Value::Int(lhs / rhs) + } + + pub fn eq(args: &[Self]) -> Self { + assert_eq!(args.len(), 2); + Value::Bool(args[0] == args[1]) + } + + pub fn neq(args: &[Self]) -> 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!") + }; + + Value::Bool(!val) + } + + 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) } }