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::{
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue