plang-2/plang2_lib/src/interpreter.rs
Daniel M 12e95ed822 Remove BinOpType::Not from ast
- Impl. Display for BinOpType & UnOpType
- Impl. scuffed Display for Ast that just uses Debug pretty print
2021-12-29 02:22:03 +01:00

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!(),
}
}
}
}
}