rs_asm6805/
symbol_table.rs1use std::collections::HashMap;
2use std::rc::{Rc, Weak};
3use std::cell::RefCell;
4
5#[derive(Debug)]
6pub struct SourceLine {
7 pub definition: Option<Weak<RefCell<Symbol>>>,
8 pub references: Vec<Weak<RefCell<Symbol>>>,
9 pub is_dirty: bool,
10 pub line_offset: i32,
11 pub is_origin: bool,
12 pub data_bytes: Vec<u8>,
13 pub relative_offset: i32,
14 pub include_bytes_read: Option<usize>,
15}
16
17impl SourceLine {
18 pub fn new() -> Self {
19 Self {
20 definition: None,
21 references: Vec::new(),
22 is_dirty: false,
23 line_offset: 0,
24 is_origin: false,
25 data_bytes: Vec::new(),
26 relative_offset: -1,
27 include_bytes_read: None,
28 }
29 }
30
31 pub fn get_offset(&self) -> i32 {
32 self.line_offset
33 }
34
35 pub fn get_byte_count(&self) -> usize {
36 self.data_bytes.len()
37 }
38
39 pub fn set_data(&mut self, data: &[u8]) -> i32 {
40 let delta = data.len() as i32 - self.data_bytes.len() as i32;
41 self.data_bytes = data.to_vec();
42 delta
43 }
44
45 pub fn get_data(&self) -> &[u8] {
46 &self.data_bytes
47 }
48
49 pub fn set_offset(&mut self, byte_offset: i32, is_origin: bool) {
50 self.line_offset = byte_offset;
51 self.is_origin = is_origin;
52 }
53
54 pub fn adjust_offset(&mut self, offset: i32) {
55 self.set_offset(self.line_offset + offset, false);
56 }
57
58 pub fn mark_dirty(&mut self, is_dirty: bool) {
59 self.is_dirty = is_dirty;
60 }
61
62 pub fn is_dirty(&self) -> bool {
63 self.is_dirty
64 }
65
66 pub fn is_origin(&self) -> bool {
67 self.is_origin
68 }
69
70 pub fn set_relative(&mut self, offset: i32) {
71 self.relative_offset = offset;
72 }
73
74 pub fn get_relative_offset(&self) -> i32 {
75 self.relative_offset
76 }
77
78 pub fn reset_references(&mut self, self_ref: Weak<RefCell<SourceLine>>) {
79 for weak_symbol in &self.references {
81 if let Some(symbol) = weak_symbol.upgrade() {
82 symbol.borrow_mut().remove_reference(self_ref.clone());
83 }
84 }
85 self.references.clear();
87 }
88
89 pub fn add_reference(&mut self, symbol: Weak<RefCell<Symbol>>) {
90 self.references.push(symbol);
91 }
92
93 pub fn set_include_bytes_read(&mut self, bytes: usize) {
94 self.include_bytes_read = Some(bytes);
95 }
96
97 pub fn set_definition(&mut self, symbol: Option<Weak<RefCell<Symbol>>>, self_ref: Weak<RefCell<SourceLine>>) {
98 if let Some(old_def) = &self.definition {
100 if let Some(old_symbol) = old_def.upgrade() {
101 old_symbol.borrow_mut().remove_definition_for_line(self_ref.clone());
102 }
103 }
104 self.definition = symbol;
105 }
106}
107
108#[derive(Debug)]
109pub struct Symbol {
110 pub value: i32,
111 pub definitions: u32,
112 pub is_keyword: bool,
113 pub defined_lines: Vec<Weak<RefCell<SourceLine>>>,
114 pub referenced_lines: Vec<Weak<RefCell<SourceLine>>>,
115}
116
117impl Symbol {
118 pub fn new() -> Self {
119 Self {
120 value: 0,
121 definitions: 0,
122 is_keyword: false,
123 defined_lines: Vec::new(),
124 referenced_lines: Vec::new(),
125 }
126 }
127
128 pub fn set_keyword(&mut self, value: i32) {
129 self.is_keyword = true;
130 self.value = value;
131 }
132
133 pub fn is_keyword(&self) -> bool {
134 self.is_keyword
135 }
136
137 pub fn is_referenced(&self) -> bool {
138 !self.referenced_lines.is_empty()
139 }
140
141 pub fn get_value(&self) -> i32 {
142 self.value
143 }
144
145 pub fn set_value(&mut self, value: i32) {
146 if value == self.value {
147 return;
148 }
149 self.value = value;
150 self.referenced_lines.retain(|weak_ref| {
152 if let Some(line) = weak_ref.upgrade() {
153 line.borrow_mut().mark_dirty(true);
154 true
155 } else {
156 false
157 }
158 });
159 }
160
161 pub fn add_definition(&mut self, source_line: Weak<RefCell<SourceLine>>) {
162 self.definitions += 1;
163 self.defined_lines.push(source_line);
164 }
165
166 pub fn add_reference(&mut self, source_line: Weak<RefCell<SourceLine>>) {
167 self.referenced_lines.push(source_line);
168 }
169
170 pub fn get_definition_count(&self) -> u32 {
171 self.definitions
172 }
173
174 pub fn remove_definition_for_line(&mut self, source_line: Weak<RefCell<SourceLine>>) {
175 self.defined_lines.retain(|weak_ref| {
177 if let (Some(existing), Some(target)) = (weak_ref.upgrade(), source_line.upgrade()) {
178 !Rc::ptr_eq(&existing, &target)
179 } else {
180 false }
182 });
183
184 self.definitions = self.defined_lines.len() as u32;
186
187 for weak_def in &self.defined_lines {
189 if let Some(def_line) = weak_def.upgrade() {
190 def_line.borrow_mut().mark_dirty(true);
191 }
192 }
193 }
194
195 pub fn remove_reference(&mut self, source_line: Weak<RefCell<SourceLine>>) {
196 self.referenced_lines.retain(|weak_ref| {
198 if let (Some(existing), Some(target)) = (weak_ref.upgrade(), source_line.upgrade()) {
199 !Rc::ptr_eq(&existing, &target)
200 } else {
201 false }
203 });
204 }
205}
206
207pub struct SymbolTable {
208 symbols: HashMap<String, Rc<RefCell<Symbol>>>,
209}
210
211impl SymbolTable {
212 pub fn new() -> Self {
213 Self {
214 symbols: HashMap::new(),
215 }
216 }
217
218 pub fn lookup_symbol(&mut self, name: &str) -> Rc<RefCell<Symbol>> {
219 let symbol_name = name.to_uppercase();
220 if let Some(symbol) = self.symbols.get(&symbol_name) {
221 symbol.clone()
222 } else {
223 let symbol = Rc::new(RefCell::new(Symbol::new()));
224 self.symbols.insert(symbol_name, symbol.clone());
225 symbol
226 }
227 }
228
229 pub fn lookup_symbol_with_reference(&mut self, name: &str, source_line: Weak<RefCell<SourceLine>>) -> Rc<RefCell<Symbol>> {
230 let symbol_name = name.to_uppercase();
231 let symbol = if let Some(existing) = self.symbols.get(&symbol_name) {
232 existing.clone()
233 } else {
234 let new_symbol = Rc::new(RefCell::new(Symbol::new()));
235 self.symbols.insert(symbol_name, new_symbol.clone());
236 new_symbol
237 };
238
239 if !symbol.borrow().is_keyword() {
241 symbol.borrow_mut().add_reference(source_line.clone());
242 if let Some(line) = source_line.upgrade() {
244 line.borrow_mut().add_reference(Rc::downgrade(&symbol));
245 }
246 }
247
248 symbol
249 }
250
251 pub fn lookup_keyword(&self, name: &str) -> Option<i32> {
252 let symbol_name = name.to_uppercase();
253 if let Some(symbol) = self.symbols.get(&symbol_name) {
254 let symbol_ref = symbol.borrow();
255 if symbol_ref.is_keyword() {
256 Some(symbol_ref.get_value())
257 } else {
258 None
259 }
260 } else {
261 None
262 }
263 }
264
265 pub fn define_symbol(&mut self, name: &str, source_line: Weak<RefCell<SourceLine>>, value: i32) -> Rc<RefCell<Symbol>> {
266 let symbol = self.lookup_symbol(name);
267 {
268 let mut symbol_ref = symbol.borrow_mut();
269 symbol_ref.set_value(value);
270 symbol_ref.add_definition(source_line.clone());
271 }
272
273 if let Some(line) = source_line.upgrade() {
275 line.borrow_mut().set_definition(Some(Rc::downgrade(&symbol)), source_line.clone());
276 }
277
278 symbol
279 }
280
281 pub fn define_keyword(&mut self, name: &str, value: i32) -> Rc<RefCell<Symbol>> {
282 let symbol_name = name.to_uppercase();
283 let symbol = if let Some(existing) = self.symbols.get(&symbol_name) {
284 existing.clone()
285 } else {
286 let new_symbol = Rc::new(RefCell::new(Symbol::new()));
287 self.symbols.insert(symbol_name, new_symbol.clone());
288 new_symbol
289 };
290
291 symbol.borrow_mut().set_keyword(value);
292 symbol
293 }
294}