1use crate::{device::Device, expr::Expr, instruction::register::Reg8, parser::SegmentType};
2
3use std::{cell::RefCell, collections::HashMap, rc::Rc};
4
5use maplit::hashmap;
6
7pub trait Context {
8 fn get_define(&self, _name: &String) -> Option<Expr>;
9 fn get_equ(&self, _name: &String) -> Option<Expr>;
10 fn get_label(&self, _name: &String) -> Option<(SegmentType, u32)>;
11 fn get_def(&self, _name: &String) -> Option<Reg8>;
12 fn get_set(&self, _name: &String) -> Option<Expr>;
13 fn get_special(&self, _name: &String) -> Option<Expr>;
14 fn get_device(&self) -> Device;
15
16 fn set_define(&self, _name: String, _value: Expr) -> Option<Expr>;
17 fn set_equ(&self, _name: String, _value: Expr) -> Option<Expr>;
18 fn set_label(&self, _name: String, _value: (SegmentType, u32)) -> Option<(SegmentType, u32)>;
19 fn set_def(&self, _name: String, _value: Reg8) -> Option<Reg8>;
20 fn set_special(&self, _name: String, _value: Expr) -> Option<Expr>;
21
22 fn get_expr(&self, name: &String) -> Option<Expr> {
23 if let Some(expr) = self.get_define(name) {
24 Some(expr)
25 } else if let Some(expr) = self.get_equ(name) {
26 Some(expr)
27 } else if let Some(expr) = self.get_set(name) {
28 Some(expr)
29 } else if let Some(expr) = self.get_special(name) {
30 Some(expr)
31 } else {
32 self.get_label(name).map(|x| Expr::Const(x.1 as i64))
33 }
34 }
35
36 fn exist(&self, name: &String) -> bool {
37 if let Some(_) = self.get_expr(name) {
38 true
39 } else if let Some(_) = self.get_def(name) {
40 true
41 } else {
42 false
43 }
44 }
45}
46
47#[derive(Clone, PartialEq, Eq, Debug)]
48pub struct CommonContext {
49 pub defines: Rc<RefCell<HashMap<String, Expr>>>,
51 pub equs: Rc<RefCell<HashMap<String, Expr>>>,
53 pub labels: Rc<RefCell<HashMap<String, (SegmentType, u32)>>>,
55 pub defs: Rc<RefCell<HashMap<String, Reg8>>>,
57 pub sets: Rc<RefCell<HashMap<String, Expr>>>,
59 pub special: Rc<RefCell<HashMap<String, Expr>>>,
61 pub device: Rc<RefCell<Option<Device>>>,
63}
64
65impl CommonContext {
66 pub fn new() -> Self {
67 Self {
68 defines: Rc::new(RefCell::new(hashmap! {})),
69 equs: Rc::new(RefCell::new(hashmap! {})),
70 labels: Rc::new(RefCell::new(hashmap! {})),
71 defs: Rc::new(RefCell::new(hashmap! {})),
72 sets: Rc::new(RefCell::new(hashmap! {})),
73 special: Rc::new(RefCell::new(hashmap! {})),
74 device: Rc::new(RefCell::new(Some(Device::new(0)))),
75 }
76 }
77}
78
79impl Context for CommonContext {
80 fn get_define(&self, name: &String) -> Option<Expr> {
81 self.defines.borrow().get(name).map(|x| x.clone())
82 }
83
84 fn get_equ(&self, name: &String) -> Option<Expr> {
85 self.equs
86 .borrow()
87 .get(&name.to_lowercase())
88 .map(|x| x.clone())
89 }
90
91 fn get_label(&self, name: &String) -> Option<(SegmentType, u32)> {
92 self.labels
93 .borrow()
94 .get(&name.to_lowercase())
95 .map(|x| x.clone())
96 }
97
98 fn get_def(&self, name: &String) -> Option<Reg8> {
99 self.defs
100 .borrow()
101 .get(&name.to_lowercase())
102 .map(|x| x.clone())
103 }
104
105 fn get_set(&self, name: &String) -> Option<Expr> {
106 self.sets.borrow().get(name).map(|x| x.clone())
107 }
108
109 fn get_special(&self, name: &String) -> Option<Expr> {
110 self.special
111 .borrow()
112 .get(&name.to_lowercase())
113 .map(|x| x.clone())
114 }
115
116 fn get_device(&self) -> Device {
117 self.device
118 .borrow()
119 .as_ref()
120 .unwrap_or(&Device::new(0))
121 .clone()
122 }
123
124 fn set_define(&self, name: String, expr: Expr) -> Option<Expr> {
125 self.defines.borrow_mut().insert(name, expr)
126 }
127
128 fn set_equ(&self, name: String, expr: Expr) -> Option<Expr> {
129 self.equs.borrow_mut().insert(name.to_lowercase(), expr)
130 }
131
132 fn set_label(&self, name: String, value: (SegmentType, u32)) -> Option<(SegmentType, u32)> {
133 self.labels.borrow_mut().insert(name, value)
134 }
135
136 fn set_def(&self, name: String, value: Reg8) -> Option<Reg8> {
137 if self.exist(&name) {
138 None
139 } else {
140 self.defs.borrow_mut().insert(name.to_lowercase(), value)
141 }
142 }
143
144 fn set_special(&self, name: String, value: Expr) -> Option<Expr> {
145 self.special.borrow_mut().insert(name, value)
146 }
147}