compiler/
symbol_table.rs

1use std::collections::HashMap;
2use std::rc::Rc;
3
4#[derive(Clone, Debug, Eq, PartialEq)]
5pub enum SymbolScope {
6    LOCAL,
7    Global,
8    Builtin,
9    Free,
10    Function,
11}
12
13#[derive(Clone, Debug, Eq, PartialEq)]
14pub struct Symbol {
15    pub name: String,
16    pub scope: SymbolScope,
17    pub index: usize,
18}
19
20#[derive(Clone, Debug, Eq, PartialEq)]
21pub struct SymbolTable {
22    pub outer: Option<Rc<SymbolTable>>,
23    symbols: HashMap<String, Rc<Symbol>>,
24    pub free_symbols: Vec<Rc<Symbol>>,
25    pub num_definitions: usize,
26}
27
28impl SymbolTable {
29    pub fn new() -> SymbolTable {
30        SymbolTable { symbols: HashMap::new(), free_symbols: vec![], num_definitions: 0, outer: None }
31    }
32
33    pub fn new_enclosed_symbol_table(outer: SymbolTable) -> SymbolTable {
34        SymbolTable { symbols: HashMap::new(), free_symbols: vec![], num_definitions: 0, outer: Some(Rc::new(outer)) }
35    }
36
37    pub fn define(&mut self, name: String) -> Rc<Symbol> {
38        let mut scope = SymbolScope::LOCAL;
39        if self.outer.is_none() {
40            scope = SymbolScope::Global;
41        }
42
43        let symbol = Rc::new(Symbol { name: name.clone(), index: self.num_definitions, scope });
44
45        self.num_definitions += 1;
46        self.symbols.insert(name.clone(), Rc::clone(&symbol));
47        return symbol;
48    }
49
50    pub fn resolve(&self, name: String) -> Option<Rc<Symbol>> {
51        let symbol = self.symbols.get(&name);
52        if symbol.is_none() && self.outer.is_some() {
53            return self.outer.as_ref().unwrap().resolve(name);
54        }
55        return symbol.cloned();
56    }
57
58    pub fn define_builtin(&mut self, index: usize, name: String) -> Rc<Symbol> {
59        let symbol = Rc::new(Symbol { name: name.clone(), index, scope: SymbolScope::Builtin });
60        self.symbols.insert(name.clone(), Rc::clone(&symbol));
61        return symbol;
62    }
63
64    pub fn define_function_name(&mut self, name: String) -> Rc<Symbol> {
65        let symbol = Rc::new(Symbol { name: name.clone(), index: 0, scope: SymbolScope::Function });
66        self.symbols.insert(name.clone(), Rc::clone(&symbol));
67        return symbol;
68    }
69
70    pub fn define_free(&mut self, original: Rc<Symbol>) -> Rc<Symbol> {
71        self.free_symbols.push(Rc::clone(&original));
72        let symbol = Rc::new(Symbol { name: original.name.clone(), index: self.free_symbols.len() - 1, scope: SymbolScope::Free });
73        self.symbols.insert(original.name.clone(), Rc::clone(&symbol));
74        return symbol;
75    }
76}