pk_compiler/
symbols_table.rs

1use std::{cell::RefCell, collections::HashMap, rc::Rc};
2
3use crate::objects::Object;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub enum SymbolScope {
7    Public,
8    Global,
9    Local,
10    Free,
11    Function,
12}
13
14#[derive(Debug, Clone)]
15pub struct Symbol {
16    pub name: String,
17    pub scope: SymbolScope,
18    pub index: usize,
19}
20
21#[derive(Debug, Clone)]
22pub struct SymbolTable {
23    pub outer: Option<Box<RefCell<SymbolTable>>>,
24    pub num_defs: usize,
25    store: HashMap<String, Symbol>,
26    pub free: Vec<Symbol>,
27}
28
29impl SymbolTable {
30    pub fn new() -> Self {
31        Self {
32            outer: None,
33            store: HashMap::new(),
34            num_defs: 0,
35            free: vec![],
36        }
37    }
38
39    pub fn new_enclosed(outer: Self) -> Self {
40        Self {
41            outer: Some(Box::new(RefCell::new(outer))),
42            store: HashMap::new(),
43            num_defs: 0,
44            free: vec![],
45        }
46    }
47
48    pub fn define_function(&mut self, name: &str) -> Symbol {
49        let symbol = Symbol {
50            index: 0,
51            scope: SymbolScope::Function,
52            name: name.to_string(),
53        };
54        self.store.insert(name.to_string(), symbol.clone());
55        symbol
56    }
57
58    pub fn define(&mut self, name: &str) -> Symbol {
59        let scope = match self.outer {
60            Some(_) => SymbolScope::Local,
61            None => SymbolScope::Global,
62        };
63        let symbol = Symbol {
64            index: self.num_defs,
65            scope,
66            name: name.to_string(),
67        };
68        if !self.store.contains_key(&name.to_string()) {
69            self.num_defs += 1;
70        }
71        self.store.insert(name.to_string(), symbol.clone());
72        symbol
73    }
74
75    pub fn define_public(&mut self, name: &str) -> Symbol {
76        let symbol = Symbol {
77            index: self.num_defs,
78            scope: SymbolScope::Public,
79            name: name.to_string(),
80        };
81        self.num_defs += 1;
82        self.store.insert(name.to_string(), symbol.clone());
83        symbol
84    }
85
86    pub fn define_free(&mut self, original: &Symbol) -> Symbol {
87        self.free.push(original.clone());
88        let symbol = Symbol {
89            index: self.free.len() - 1,
90            scope: SymbolScope::Free,
91            name: original.name.clone(),
92        };
93        self.store.insert(symbol.name.clone(), symbol.clone());
94        symbol
95    }
96
97    pub fn resolve(&mut self, name: &str) -> Option<Symbol> {
98        let inner = self.store.get(name).cloned();
99        match (&self.outer, &inner) {
100            (Some(outer), None) => {
101                let symbol = outer.borrow_mut().resolve(name);
102                match symbol {
103                    Some(obj) => match obj.scope.clone() {
104                        SymbolScope::Global => Some(obj.clone()),
105                        _ => Some(self.define_free(&obj)),
106                    },
107                    None => inner,
108                }
109            }
110            _ => inner,
111        }
112    }
113
114    pub fn get_public_symbols(&self) -> Vec<Symbol> {
115        self.store
116            .iter()
117            .filter(|(_, v)| v.scope == SymbolScope::Public)
118            .map(|(_, v)| v.clone())
119            .collect()
120    }
121
122    pub fn get_public_objects(&self, globals: Vec<Option<Object>>) -> HashMap<String, Object> {
123        let symbols = self.get_public_symbols();
124        let mut hash = HashMap::new();
125        for (idx, obj) in globals.iter().enumerate() {
126            let obj = obj.clone().unwrap_or(Object::Nil);
127            let matched = symbols.iter().find(|v| v.index == idx);
128            if matched.is_some() {
129                hash.insert(matched.unwrap().name.clone(), obj);
130            }
131        }
132        hash
133    }
134}
135
136#[derive(Debug, Clone)]
137pub struct ConstantsPool {
138    pub objects: Vec<Rc<Object>>,
139    pub size: usize,
140}
141
142impl ConstantsPool {
143    pub fn new() -> ConstantsPool {
144        return ConstantsPool {
145            objects: vec![],
146            size: 0,
147        };
148    }
149
150    pub fn get_object(&self, idx: usize) -> Option<Rc<Object>> {
151        if idx < self.size {
152            return Some(self.objects[idx].clone());
153        }
154        return None;
155    }
156
157    pub fn set_object(&mut self, object: Rc<Object>) -> usize {
158        self.objects.push(object);
159        self.size += 1;
160        return self.size - 1;
161    }
162
163    pub fn get_size(&self) -> usize {
164        self.size
165    }
166}