pk_compiler/
symbols_table.rs1use 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}