Refactor interpreter get symtab as argument
This commit is contained in:
parent
1ec86d4845
commit
77b89dbf37
2 changed files with 116 additions and 127 deletions
|
@ -1,7 +1,8 @@
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use interpreter::Interpreter;
|
use interpreter::interpret;
|
||||||
use parser::parse;
|
use parser::parse;
|
||||||
|
use symtab::SymTab;
|
||||||
use tokenizer::tokenize;
|
use tokenizer::tokenize;
|
||||||
|
|
||||||
mod ast;
|
mod ast;
|
||||||
|
@ -10,6 +11,7 @@ mod parser;
|
||||||
mod symtab;
|
mod symtab;
|
||||||
mod token;
|
mod token;
|
||||||
mod tokenizer;
|
mod tokenizer;
|
||||||
|
//mod type_checker;
|
||||||
mod value;
|
mod value;
|
||||||
|
|
||||||
pub fn compile(code: &str) {
|
pub fn compile(code: &str) {
|
||||||
|
@ -25,8 +27,7 @@ pub fn start_interpreter() {
|
||||||
let tokens = tokenize(&code);
|
let tokens = tokenize(&code);
|
||||||
let ast = parse(&tokens);
|
let ast = parse(&tokens);
|
||||||
|
|
||||||
let mut interpreter = Interpreter::new();
|
let val = interpret(&ast, &mut SymTab::new());
|
||||||
let val = interpreter.interpret(&ast);
|
|
||||||
println!("{}", val);
|
println!("{}", val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,45 +4,34 @@ use crate::compiler::{
|
||||||
value::Value,
|
value::Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Interpreter<'source> {
|
pub fn interpret<'source>(ast: &Expression<'source>, symbols: &mut SymTab<'source>) -> Value {
|
||||||
symbols: SymTab<'source>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'source> Interpreter<'source> {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Interpreter {
|
|
||||||
symbols: SymTab::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn interpret(&mut self, ast: &Expression<'source>) -> Value {
|
|
||||||
match ast {
|
match ast {
|
||||||
EmptyLiteral(_) => Value::None(),
|
EmptyLiteral(_) => Value::None(),
|
||||||
IntLiteral(_, val) => Value::Int(*val),
|
IntLiteral(_, val) => Value::Int(*val),
|
||||||
BoolLiteral(_, val) => Value::Bool(*val),
|
BoolLiteral(_, val) => Value::Bool(*val),
|
||||||
Identifier(_, name) => *self.symbols.get(name),
|
Identifier(_, name) => *symbols.get(name),
|
||||||
UnaryOp(_, op, expr) => match *op {
|
UnaryOp(_, op, expr) => match *op {
|
||||||
"-" => {
|
"-" => {
|
||||||
let Value::Func(op_fn) = self.symbols.get("neg") else {
|
let Value::Func(op_fn) = symbols.get("neg") else {
|
||||||
panic!("Operator {} does not correspond to a function!", op);
|
panic!("Operator {} does not correspond to a function!", op);
|
||||||
};
|
};
|
||||||
op_fn(&[self.interpret(expr)])
|
op_fn(&[interpret(expr, symbols)])
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let Value::Func(op_fn) = self.symbols.get(op) else {
|
let Value::Func(op_fn) = symbols.get(op) else {
|
||||||
panic!("Operator {} does not correspond to a function!", op);
|
panic!("Operator {} does not correspond to a function!", op);
|
||||||
};
|
};
|
||||||
op_fn(&[self.interpret(expr)])
|
op_fn(&[interpret(expr, symbols)])
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
BinaryOp(_, left, op, right) => match *op {
|
BinaryOp(_, left, op, right) => match *op {
|
||||||
"and" => {
|
"and" => {
|
||||||
let left_val = self.interpret(left);
|
let left_val = interpret(left, symbols);
|
||||||
if let Value::Bool(val_l) = left_val {
|
if let Value::Bool(val_l) = left_val {
|
||||||
if !val_l {
|
if !val_l {
|
||||||
Value::Bool(false)
|
Value::Bool(false)
|
||||||
} else {
|
} else {
|
||||||
let right_val = self.interpret(right);
|
let right_val = interpret(right, symbols);
|
||||||
if let Value::Bool(val_r) = right_val {
|
if let Value::Bool(val_r) = right_val {
|
||||||
Value::Bool(val_r)
|
Value::Bool(val_r)
|
||||||
} else {
|
} else {
|
||||||
|
@ -54,12 +43,12 @@ impl<'source> Interpreter<'source> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"or" => {
|
"or" => {
|
||||||
let left_val = self.interpret(left);
|
let left_val = interpret(left, symbols);
|
||||||
if let Value::Bool(val_l) = left_val {
|
if let Value::Bool(val_l) = left_val {
|
||||||
if val_l {
|
if val_l {
|
||||||
Value::Bool(true)
|
Value::Bool(true)
|
||||||
} else {
|
} else {
|
||||||
let right_val = self.interpret(right);
|
let right_val = interpret(right, symbols);
|
||||||
if let Value::Bool(val_r) = right_val {
|
if let Value::Bool(val_r) = right_val {
|
||||||
Value::Bool(val_r)
|
Value::Bool(val_r)
|
||||||
} else {
|
} else {
|
||||||
|
@ -72,31 +61,31 @@ impl<'source> Interpreter<'source> {
|
||||||
}
|
}
|
||||||
"=" => {
|
"=" => {
|
||||||
if let Expression::Identifier(_, name) = **left {
|
if let Expression::Identifier(_, name) = **left {
|
||||||
let val = self.interpret(right);
|
let val = interpret(right, symbols);
|
||||||
*self.symbols.get(name) = val;
|
*symbols.get(name) = val;
|
||||||
val
|
val
|
||||||
} else {
|
} else {
|
||||||
panic!("Assignment must have identifier as left expr!");
|
panic!("Assignment must have identifier as left expr!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let Value::Func(op_fn) = self.symbols.get(op) else {
|
let Value::Func(op_fn) = symbols.get(op) else {
|
||||||
panic!("Operator {} does not correspond to a function!", op);
|
panic!("Operator {} does not correspond to a function!", op);
|
||||||
};
|
};
|
||||||
op_fn(&[self.interpret(left), self.interpret(right)])
|
op_fn(&[interpret(left, symbols), interpret(right, symbols)])
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
VarDeclaration(_, name, expr) => {
|
VarDeclaration(_, name, expr) => {
|
||||||
let val = self.interpret(expr);
|
let val = interpret(expr, symbols);
|
||||||
self.symbols.insert(name, val);
|
symbols.insert(name, val);
|
||||||
Value::None()
|
Value::None()
|
||||||
}
|
}
|
||||||
Conditional(_, condition_expr, then_expr, else_expr) => {
|
Conditional(_, condition_expr, then_expr, else_expr) => {
|
||||||
if let Value::Bool(condition) = self.interpret(condition_expr) {
|
if let Value::Bool(condition) = interpret(condition_expr, symbols) {
|
||||||
if condition {
|
if condition {
|
||||||
self.interpret(then_expr)
|
interpret(then_expr, symbols)
|
||||||
} else if let Some(expr) = else_expr {
|
} else if let Some(expr) = else_expr {
|
||||||
self.interpret(expr)
|
interpret(expr, symbols)
|
||||||
} else {
|
} else {
|
||||||
Value::None()
|
Value::None()
|
||||||
}
|
}
|
||||||
|
@ -107,10 +96,10 @@ impl<'source> Interpreter<'source> {
|
||||||
While(_, condition, do_expr) => {
|
While(_, condition, do_expr) => {
|
||||||
let mut val = Value::None();
|
let mut val = Value::None();
|
||||||
loop {
|
loop {
|
||||||
let condition = self.interpret(condition);
|
let condition = interpret(condition, symbols);
|
||||||
if let Value::Bool(cond) = condition {
|
if let Value::Bool(cond) = condition {
|
||||||
if cond {
|
if cond {
|
||||||
val = self.interpret(do_expr);
|
val = interpret(do_expr, symbols);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -123,26 +112,25 @@ impl<'source> Interpreter<'source> {
|
||||||
FunCall(_, name, args) => {
|
FunCall(_, name, args) => {
|
||||||
let mut arg_values = Vec::new();
|
let mut arg_values = Vec::new();
|
||||||
for arg in args {
|
for arg in args {
|
||||||
arg_values.push(self.interpret(arg));
|
arg_values.push(interpret(arg, symbols));
|
||||||
}
|
}
|
||||||
|
|
||||||
let Value::Func(function) = self.symbols.get(name) else {
|
let Value::Func(function) = symbols.get(name) else {
|
||||||
panic!("Identifier {} does not correspond to a function!", name);
|
panic!("Identifier {} does not correspond to a function!", name);
|
||||||
};
|
};
|
||||||
|
|
||||||
function(&arg_values)
|
function(&arg_values)
|
||||||
}
|
}
|
||||||
Block(_, expressions) => {
|
Block(_, expressions) => {
|
||||||
self.symbols.push_level();
|
symbols.push_level();
|
||||||
|
|
||||||
let mut val = Value::None();
|
let mut val = Value::None();
|
||||||
for expression in expressions {
|
for expression in expressions {
|
||||||
val = self.interpret(expression);
|
val = interpret(expression, symbols);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.symbols.remove_level();
|
symbols.remove_level();
|
||||||
val
|
val
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
Reference in a new issue