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::{ use crate::compiler::{
ast::Expression::{self, *}, ast::Expression::{self, *},
symtab::SymTab, symtab::SymTab,
@ -13,7 +11,7 @@ pub struct Interpreter<'source> {
impl<'source> Interpreter<'source> { impl<'source> Interpreter<'source> {
pub fn new() -> Self { pub fn new() -> Self {
Interpreter { Interpreter {
symbols: SymTab::new_global(), symbols: SymTab::new(),
} }
} }
@ -89,10 +87,8 @@ impl<'source> Interpreter<'source> {
} }
}, },
VarDeclaration(_, name, expr) => { VarDeclaration(_, name, expr) => {
let value = self.interpret(expr); let val = self.interpret(expr);
if self.symbols.locals.insert(name, value).is_some() { self.symbols.insert(name, val);
panic!("Variable {} already defined in this scope!", name)
}
Value::None() Value::None()
} }
Conditional(_, condition_expr, then_expr, else_expr) => { Conditional(_, condition_expr, then_expr, else_expr) => {
@ -137,22 +133,14 @@ impl<'source> Interpreter<'source> {
function(&arg_values) function(&arg_values)
} }
Block(_, expressions) => { Block(_, expressions) => {
self.symbols = SymTab { self.symbols.push_level();
locals: HashMap::new(),
parent: Some(Box::new(std::mem::take(&mut self.symbols))),
};
let mut val = Value::None(); let mut val = Value::None();
for expression in expressions { for expression in expressions {
val = self.interpret(expression); val = self.interpret(expression);
} }
if let Some(symbols) = &mut self.symbols.parent { self.symbols.remove_level();
self.symbols = std::mem::take(symbols);
} else {
panic!("Non-global symbol table without parent!");
}
val val
} }
} }

View file

@ -3,23 +3,21 @@ use std::collections::HashMap;
#[derive(Default)] #[derive(Default)]
pub struct SymTab<'source> { pub struct SymTab<'source> {
pub locals: HashMap<&'source str, Value>, tables: Vec<HashMap<&'source str, Value>>,
pub parent: Option<Box<SymTab<'source>>>,
} }
impl<'source> SymTab<'source> { impl<'source> SymTab<'source> {
pub fn get(&mut self, symbol: &str) -> &mut Value { pub fn get(&mut self, symbol: &str) -> &mut Value {
if let Some(val) = self.locals.get_mut(symbol) { for i in (0..self.tables.len()).rev() {
val if self.tables[i].contains_key(symbol) {
} else if let Some(parent) = &mut self.parent { return self.tables[i].get_mut(symbol).unwrap();
parent.get(symbol) }
} else {
panic!("No symbol {} found!", symbol);
} }
panic!("No symbol {} found!", symbol);
} }
pub fn new_global() -> SymTab<'source> { pub fn new() -> SymTab<'source> {
let locals = HashMap::from([ let globals = HashMap::from([
("+", Value::Func(Value::add)), ("+", Value::Func(Value::add)),
("*", Value::Func(Value::mul)), ("*", Value::Func(Value::mul)),
("-", Value::Func(Value::sub)), ("-", Value::Func(Value::sub)),
@ -36,8 +34,27 @@ impl<'source> SymTab<'source> {
]); ]);
SymTab { SymTab {
locals, tables: vec![globals],
parent: None, }
}
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)
} }
} }
} }