1
0
Fork 0

Refactor symbol table to be non-horrible :D

This commit is contained in:
Vili Sinervä 2025-02-04 00:34:56 +02:00
parent 38dd3f523b
commit 1ec86d4845
No known key found for this signature in database
GPG key ID: DF8FEAF54EFAC996
2 changed files with 34 additions and 29 deletions

View file

@ -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
}
}

View file

@ -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)
}
}
}