Refactor symbol table to be non-horrible :D
This commit is contained in:
parent
38dd3f523b
commit
1ec86d4845
2 changed files with 34 additions and 29 deletions
|
@ -1,5 +1,3 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use crate::compiler::{
|
||||
ast::Expression::{self, *},
|
||||
symtab::SymTab,
|
||||
|
@ -13,7 +11,7 @@ pub struct Interpreter<'source> {
|
|||
impl<'source> Interpreter<'source> {
|
||||
pub fn new() -> Self {
|
||||
Interpreter {
|
||||
symbols: SymTab::new_global(),
|
||||
symbols: SymTab::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,10 +87,8 @@ impl<'source> Interpreter<'source> {
|
|||
}
|
||||
},
|
||||
VarDeclaration(_, name, expr) => {
|
||||
let value = self.interpret(expr);
|
||||
if self.symbols.locals.insert(name, value).is_some() {
|
||||
panic!("Variable {} already defined in this scope!", name)
|
||||
}
|
||||
let val = self.interpret(expr);
|
||||
self.symbols.insert(name, val);
|
||||
Value::None()
|
||||
}
|
||||
Conditional(_, condition_expr, then_expr, else_expr) => {
|
||||
|
@ -137,22 +133,14 @@ impl<'source> Interpreter<'source> {
|
|||
function(&arg_values)
|
||||
}
|
||||
Block(_, expressions) => {
|
||||
self.symbols = SymTab {
|
||||
locals: HashMap::new(),
|
||||
parent: Some(Box::new(std::mem::take(&mut self.symbols))),
|
||||
};
|
||||
self.symbols.push_level();
|
||||
|
||||
let mut val = Value::None();
|
||||
for expression in expressions {
|
||||
val = self.interpret(expression);
|
||||
}
|
||||
|
||||
if let Some(symbols) = &mut self.symbols.parent {
|
||||
self.symbols = std::mem::take(symbols);
|
||||
} else {
|
||||
panic!("Non-global symbol table without parent!");
|
||||
}
|
||||
|
||||
self.symbols.remove_level();
|
||||
val
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,23 +3,21 @@ use std::collections::HashMap;
|
|||
|
||||
#[derive(Default)]
|
||||
pub struct SymTab<'source> {
|
||||
pub locals: HashMap<&'source str, Value>,
|
||||
pub parent: Option<Box<SymTab<'source>>>,
|
||||
tables: Vec<HashMap<&'source str, Value>>,
|
||||
}
|
||||
|
||||
impl<'source> SymTab<'source> {
|
||||
pub fn get(&mut self, symbol: &str) -> &mut Value {
|
||||
if let Some(val) = self.locals.get_mut(symbol) {
|
||||
val
|
||||
} else if let Some(parent) = &mut self.parent {
|
||||
parent.get(symbol)
|
||||
} else {
|
||||
panic!("No symbol {} found!", symbol);
|
||||
for i in (0..self.tables.len()).rev() {
|
||||
if self.tables[i].contains_key(symbol) {
|
||||
return self.tables[i].get_mut(symbol).unwrap();
|
||||
}
|
||||
}
|
||||
panic!("No symbol {} found!", symbol);
|
||||
}
|
||||
|
||||
pub fn new_global() -> SymTab<'source> {
|
||||
let locals = HashMap::from([
|
||||
pub fn new() -> SymTab<'source> {
|
||||
let globals = HashMap::from([
|
||||
("+", Value::Func(Value::add)),
|
||||
("*", Value::Func(Value::mul)),
|
||||
("-", Value::Func(Value::sub)),
|
||||
|
@ -36,8 +34,27 @@ impl<'source> SymTab<'source> {
|
|||
]);
|
||||
|
||||
SymTab {
|
||||
locals,
|
||||
parent: None,
|
||||
tables: vec![globals],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push_level(&mut self) {
|
||||
self.tables.push(HashMap::new());
|
||||
}
|
||||
|
||||
pub fn remove_level(&mut self) {
|
||||
self.tables.pop();
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, name: &'source str, val: Value) {
|
||||
if self
|
||||
.tables
|
||||
.last_mut()
|
||||
.expect("Symbols table should never be empty!")
|
||||
.insert(name, val)
|
||||
.is_some()
|
||||
{
|
||||
panic!("Variable {} already defined in this scope!", name)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Reference in a new issue