From 1ec86d4845ea4d613408f59debe34840a9f95df3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vili=20Sinerv=C3=A4?= Date: Tue, 4 Feb 2025 00:34:56 +0200 Subject: [PATCH] Refactor symbol table to be non-horrible :D --- src/compiler/interpreter.rs | 22 +++++--------------- src/compiler/symtab.rs | 41 ++++++++++++++++++++++++++----------- 2 files changed, 34 insertions(+), 29 deletions(-) diff --git a/src/compiler/interpreter.rs b/src/compiler/interpreter.rs index 888a648..bbc9a48 100644 --- a/src/compiler/interpreter.rs +++ b/src/compiler/interpreter.rs @@ -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 } } diff --git a/src/compiler/symtab.rs b/src/compiler/symtab.rs index 1f90f20..0ccd020 100644 --- a/src/compiler/symtab.rs +++ b/src/compiler/symtab.rs @@ -3,23 +3,21 @@ use std::collections::HashMap; #[derive(Default)] pub struct SymTab<'source> { - pub locals: HashMap<&'source str, Value>, - pub parent: Option>>, + tables: Vec>, } 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) } } }