diff options
| author | Cody <cody@codyq.dev> | 2023-06-20 04:13:45 -0500 |
|---|---|---|
| committer | Cody <cody@codyq.dev> | 2023-06-20 04:13:45 -0500 |
| commit | 3bceb8ff306775a4204063de765cce730a31ffb2 (patch) | |
| tree | 247f5ea51e08e0edd16e22c42ee37c29d1b4136e | |
| parent | c22410c6f334497a404f0b708ae94be527a8f0ee (diff) | |
| download | sloth-3bceb8ff306775a4204063de765cce730a31ffb2.tar.gz | |
Symbol tables
| -rw-r--r-- | sloth/src/main.rs | 2 | ||||
| -rw-r--r-- | sloth/src/symbol.rs | 90 | ||||
| -rw-r--r-- | sloth/src/symtable.rs | 114 |
3 files changed, 115 insertions, 91 deletions
diff --git a/sloth/src/main.rs b/sloth/src/main.rs index 6ae01ec..a85a8d5 100644 --- a/sloth/src/main.rs +++ b/sloth/src/main.rs @@ -9,7 +9,7 @@ pub mod lexer; pub mod parser; pub mod sloth_std; -pub mod symbol; +pub mod symtable; use std::{env, fs}; diff --git a/sloth/src/symbol.rs b/sloth/src/symbol.rs deleted file mode 100644 index 416b042..0000000 --- a/sloth/src/symbol.rs +++ /dev/null @@ -1,90 +0,0 @@ -use std::collections::HashMap; - -// TODO: Change name with some sort of path to make modules possible - -#[derive(Debug)] -pub struct SymbolTableStack { - tables: Vec<SymbolTable>, -} - -impl Default for SymbolTableStack { - fn default() -> Self { - Self { - tables: vec![SymbolTable::default()], - } - } -} - -impl SymbolTableStack { - pub fn new() -> Self { - Self::default() - } - - pub fn get(&self, name: &str) -> Option<&Symbol> { - for table in self.tables.iter().rev() { - if let Some(symbol) = table.get(name) { - return Some(symbol); - } - } - - None - } - - /// Returning true means a symbol was overriden - pub fn insert(&mut self, name: impl Into<String>, symbol: Symbol) -> bool { - let head = self.tables.len() - 1; - self.tables[head].insert(name, symbol) - } - - pub fn push(&mut self) { - self.tables.push(SymbolTable::default()); - } - - pub fn pop(&mut self) -> bool { - if self.tables.len() <= 1 { - // Symbol table stacks must always have atleast 1 stack - return false; - } - - self.tables.pop(); - true - } - - pub fn root(&self) -> &SymbolTable { - &self.tables[0] - } - - pub fn root_mut(&mut self) -> &mut SymbolTable { - &mut self.tables[0] - } -} - -#[derive(Debug, Default)] -pub struct SymbolTable { - symbols: HashMap<String, Symbol>, -} - -impl SymbolTable { - pub fn new() -> Self { - Self::default() - } - - pub fn get(&self, name: &str) -> Option<&Symbol> { - self.symbols.get(name) - } - - /// Returning true means a symbol was overriden - pub fn insert(&mut self, name: impl Into<String>, symbol: Symbol) -> bool { - self.symbols.insert(name.into(), symbol).is_some() - } -} - -#[derive(Debug)] -pub struct Symbol { - pub typ: Option<SymbolType>, -} - -#[derive(Debug)] -pub enum SymbolType { - Function, -} diff --git a/sloth/src/symtable.rs b/sloth/src/symtable.rs new file mode 100644 index 0000000..29ea210 --- /dev/null +++ b/sloth/src/symtable.rs @@ -0,0 +1,114 @@ +use std::cell::{Ref, RefCell, RefMut}; +use std::collections::hash_map::Entry::Vacant; +use std::collections::HashMap; +use std::rc::Rc; + +#[derive(Debug, Default)] +struct Scope { + parent: Option<Rc<Scope>>, + symbols: RefCell<HashMap<String, Symbol>>, +} + +#[derive(Debug)] +pub struct SymbolTable(Rc<Scope>); + +impl SymbolTable { + pub fn new() -> Self { + Self(Rc::new(Scope { + parent: None, + ..Default::default() + })) + } + + pub fn make_child(&self) -> Self { + Self(Rc::new(Scope { + parent: Some(self.0.clone()), + ..Default::default() + })) + } + + pub fn contains(&self, identifier: &str) -> bool { + for scope in self.iter() { + if scope.symbols.borrow().contains_key(identifier) { + return true; + } + } + + false + } + + pub fn get(&self, identifier: &str) -> Option<Ref<'_, Symbol>> { + for scope in self.iter() { + let reference = scope.symbols.borrow(); + if let Ok(symbol) = Ref::filter_map(reference, |it| it.get(identifier)) { + return Some(symbol); + } + } + + None + } + + pub fn get_mut(&self, identifier: &str) -> Option<RefMut<'_, Symbol>> { + for scope in self.iter() { + let reference = scope.symbols.borrow_mut(); + if let Ok(symbol) = RefMut::filter_map(reference, |it| it.get_mut(identifier)) { + return Some(symbol); + } + } + + None + } + + pub fn insert(&self, identifier: String, symbol: Symbol) -> bool { + let mut reference = self.0.symbols.borrow_mut(); + if let Vacant(e) = reference.entry(identifier) { + e.insert(symbol); + return true; + } + + false + } + + fn iter(&self) -> Iter<'_> { + Iter { + next: Some(&self.0), + } + } +} + +impl Default for SymbolTable { + fn default() -> Self { + Self::new() + } +} + +impl Clone for SymbolTable { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +struct Iter<'a> { + next: Option<&'a Scope>, +} + +impl<'a> Iterator for Iter<'a> { + type Item = &'a Scope; + + fn next(&mut self) -> Option<Self::Item> { + self.next.map(|scope| { + self.next = scope.parent.as_deref(); + scope + }) + } +} + +#[derive(Debug)] +pub struct Symbol { + pub typ: Option<SymbolType>, +} + +#[derive(Debug)] +pub enum SymbolType { + Function, +} |
