diff --git a/src/semantic/mod.rs b/src/semantic/mod.rs index 8956ea2..cf28d6c 100644 --- a/src/semantic/mod.rs +++ b/src/semantic/mod.rs @@ -10,6 +10,8 @@ use symbol_table::{SymbolEntry, SymbolTable}; #[cfg(test)] mod tests { + use std::{borrow::BorrowMut, rc::Rc}; + use super::*; #[test] @@ -24,17 +26,18 @@ mod tests { #[test] fn test_2() { - let mut global_scope = SymbolTable::new(); + let global_scope = SymbolTable::new(); + let main_function = SymbolEntry::new_function(vec![], String::from("Unit")); global_scope.insert("main".into(), main_function); global_scope.insert("db_url".into(), SymbolEntry::Variable("String".into())); let add_function = SymbolEntry::new_function(vec!["Int".into(), "Int".into()], "Int".into()); + global_scope.insert("add".into(), add_function); - let mut main_function_scope = SymbolTable::new_from_parent(&global_scope); - + let main_function_scope = SymbolTable::new_from_parent(&global_scope); main_function_scope.insert("message".into(), SymbolEntry::Variable("String".into())); assert!(main_function_scope.test(&"message".into())); @@ -42,11 +45,11 @@ mod tests { assert_eq!(main_function_scope.test(&"non_existant".into()), false); let mut add_function_scope = SymbolTable::new_from_parent(&global_scope); + add_function_scope.insert("a".into(), SymbolEntry::Variable("Int".into())); add_function_scope.insert("b".into(), SymbolEntry::Variable("Int".into())); assert!(add_function_scope.test(&"a".into())); - global_scope.insert("test".into(), SymbolEntry::Variable("Int".into())); } } diff --git a/src/semantic/symbol_table.rs b/src/semantic/symbol_table.rs index 779169b..de7a0f7 100644 --- a/src/semantic/symbol_table.rs +++ b/src/semantic/symbol_table.rs @@ -1,9 +1,14 @@ -use std::{collections::HashMap, rc::Rc, cell::RefCell}; +use std::{cell::RefCell, collections::HashMap, rc::Rc}; + +/// Public interface for the symbol table +pub struct SymbolTable { + node: Rc>, +} // struct for a symbol table -pub struct SymbolTable<'a> { +struct SymbolTableNode { // the parent scope - parent: Option>>>, + parent: Option>>, // the current scope scope: HashMap, } @@ -15,19 +20,46 @@ pub enum SymbolEntry { Function(Vec, String), } -impl SymbolTable<'_> { +impl SymbolTable { /// Creates a new, global symbol table - pub fn new<'a>() -> SymbolTable<'a> { + pub fn new() -> SymbolTable { SymbolTable { + node: Rc::new(RefCell::new(SymbolTableNode::new())), + } + } + + pub fn new_from_parent(parent: &SymbolTable) -> SymbolTable { + let new_table = SymbolTableNode::new_from_parent(&parent.node); + + SymbolTable { + node: Rc::new(RefCell::new(new_table)), + } + } + + /// Inserts a new symbol into the current table scope + pub fn insert(&self, key: String, value: SymbolEntry) { + self.node.borrow_mut().insert(key, value); + } + + /// Tests if a symbol is declared in the current or parent scopes + pub fn test(&self, key: &String) -> bool { + self.node.borrow_mut().test(key) + } +} + +impl SymbolTableNode { + /// Creates a new, global symbol table + pub fn new<'a>() -> SymbolTableNode { + SymbolTableNode { parent: None, scope: HashMap::new(), } } /// Creates a new symbol table with a parent - pub fn new_from_parent<'a>(parent: &'a SymbolTable<'a>) -> SymbolTable<'a> { - SymbolTable { - parent: Some(Rc::new(RefCell::new(parent))), + pub fn new_from_parent<'a>(parent: &Rc>) -> SymbolTableNode { + SymbolTableNode { + parent: Some(Rc::clone(&parent)), scope: HashMap::new(), } } @@ -38,16 +70,16 @@ impl SymbolTable<'_> { } /// Tests if a symbol is declared in the current or parent scopes - pub fn test(&self, key: &String) -> bool { + pub fn test(&mut self, key: &String) -> bool { if self.scope.contains_key(key) { return true; } match &self.parent { Some(parent) => { - let parent = parent.borrow(); + let mut parent = parent.as_ref().borrow_mut(); parent.test(key) - }, + } None => false, } } diff --git a/src/syntax/functions/function_declaration.rs b/src/syntax/functions/function_declaration.rs index d1fd55a..128167a 100644 --- a/src/syntax/functions/function_declaration.rs +++ b/src/syntax/functions/function_declaration.rs @@ -4,12 +4,15 @@ use crate::{ utils::Result3, }; -use super::{super::{ - ast::FunctionDeclaration, - block::parse_block, - utils::{parse_token_type, try_token_type}, - ParseResult, -}, params_list::parse_params_list}; +use super::{ + super::{ + ast::FunctionDeclaration, + block::parse_block, + utils::{parse_token_type, try_token_type}, + ParseResult, + }, + params_list::parse_params_list, +}; pub fn try_parse<'a>(tokens: &'a Vec, pos: usize) -> ParseResult { let mut current_pos = pos; diff --git a/src/syntax/functions/mod.rs b/src/syntax/functions/mod.rs index 6bdfe94..1546abe 100644 --- a/src/syntax/functions/mod.rs +++ b/src/syntax/functions/mod.rs @@ -2,4 +2,3 @@ pub mod arguments_list; pub mod function_declaration; pub mod params_list; -