- Impl. Display for BinOpType & UnOpType - Impl. scuffed Display for Ast that just uses Debug pretty print
110 lines
3.6 KiB
Rust
110 lines
3.6 KiB
Rust
use std::collections::HashMap;
|
|
|
|
use crate::{ast::{Statement, Expr, Ast, BinOpType, UnOpType}, token::Literal};
|
|
|
|
pub struct Interpreter {
|
|
prog: Vec<Statement>,
|
|
|
|
// TODO: Those varibales are global only, so this will have to change with functions. Also Literal is reused as variable type
|
|
variables: HashMap<String, Literal>,
|
|
|
|
// 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!(),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|