use std::collections::HashMap; use crate::{ast::{Statement, Expr, Ast, BinOpType, UnOpType}, token::Literal}; pub struct Interpreter { prog: Vec, // TODO: Those varibales are global only, so this will have to change with functions. Also Literal is reused as variable type variables: HashMap, // Print expression statements to stdout debug: bool, } impl Interpreter { pub fn new(prog: Ast) -> Self { let variables = Default::default(); Self { prog: prog.prog, variables, debug: true } } pub fn run(&mut self) { for idx in 0..self.prog.len() { self.execute_stmt(idx); } } pub fn execute_stmt(&mut self, idx: usize) { // TODO: The clone here is not optimal match self.prog[idx].clone() { Statement::Expr(expr) => { let expr_result = self.execute_expr(expr.clone()); if self.debug { println!("{:?}", expr_result); } } Statement::LetBinding(var_name, expr) => { let rhs = self.execute_expr(expr); self.variables.insert(var_name, rhs); } Statement::Assignment(var_name, expr) => { let rhs = self.execute_expr(expr); *self.variables.get_mut(&var_name).expect("Assigning variable before declaration") = rhs; }, Statement::FnDef(_) => todo!(), Statement::IfStmt(_) => todo!(), Statement::WhileStmt(_) => todo!(), } } fn execute_expr(&mut self, expr: Expr) -> Literal { match expr { Expr::Literal(lit) => lit, Expr::Variable(name) => self.variables.get(&name).expect("Using variable before declaration").clone(), Expr::FnCall(_) => todo!(), Expr::BinOp(bot, lhs, rhs) => { let lhs = match self.execute_expr(*lhs) { Literal::Int64(val) => val, _ => panic!("Binary operators for non i64 not yet implemented") }; let rhs = match self.execute_expr(*rhs) { Literal::Int64(val) => val, _ => panic!("Binary operators for non i64 not yet implemented") }; let res = match bot { BinOpType::Add => lhs + rhs, BinOpType::Sub => lhs - rhs, BinOpType::Mul => lhs * rhs, BinOpType::Div => lhs / rhs, BinOpType::Mod => lhs % rhs, BinOpType::Eq => todo!(), BinOpType::Neq => todo!(), BinOpType::Gt => todo!(), BinOpType::Lt => todo!(), BinOpType::Ge => todo!(), BinOpType::Le => todo!(), BinOpType::And => todo!(), BinOpType::Or => todo!(), BinOpType::Xor => todo!(), }; Literal::Int64(res) } Expr::UnOp(uot, expr) => { match uot { UnOpType::Neg => { let mut res = self.execute_expr(*expr); match &mut res { Literal::Boolean(_) => panic!("Can't negate bool"), Literal::Int64(val) => *val *= -1, Literal::String(_) => panic!("Can't negate string"), }; res } UnOpType::Not => todo!(), } } } } }