aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sloth/src/main.rs2
-rw-r--r--sloth/src/symbol.rs90
-rw-r--r--sloth/src/symtable.rs114
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,
+}