fips_md/codegen/analysis/
symbol.rs1use anyhow::{anyhow, Result};
4
5use std::collections::HashMap;
6
7use crate::{parser::{FipsType, SubstitutionValue}, runtime::{FunctionID, MemberID, ParticleIndexEntry}, utils::FipsValue};
8
9#[derive(Clone)]
11pub struct SymbolTable<T> {
12 symbols: HashMap<String, FipsSymbol<T>>,
14 subtables: Vec<SymbolTable<T>>
17}
18
19macro_rules! insert_or_error {
21 ($map:expr, $key:expr, $val:expr, $err:expr) => {
22 if $map.contains_key(&$key) { Err($err) }
25 else {
26 $map.insert($key, $val); Ok(())
28 }
29 }
30}
31
32impl<T> SymbolTable<T> {
33 pub fn new() -> Self {
34 Self {
35 symbols: HashMap::new(),
36 subtables: vec![]
37 }
38 }
39
40 pub fn from_particle(particle_def: &ParticleIndexEntry) -> Self {
42 let mut symbol_table = Self::new();
43 for (member_id, member_def) in particle_def.get_members() {
44 symbol_table.add_particle_member(member_def.get_name().into(), member_id)
45 .expect("Inconsistent member names!");
46 }
47 symbol_table
48 }
49
50 pub fn add_constant_from_substitution(&mut self, name: String, value: &SubstitutionValue) -> Result<()> {
52 insert_or_error!(self.symbols, name,
53 FipsSymbol::from_substitution(&value),
54 anyhow!("Cannot redefine constant with name {}", name))
55 }
56
57 pub fn add_constant_f64(&mut self, name: String, value: f64) -> Result<()> {
58 insert_or_error!(self.symbols, name,
59 FipsSymbol::from_f64(value),
60 anyhow!("Cannot redefine constant with name {}", name))
61 }
62
63 pub fn add_local_symbol(&mut self, name: String, typ: FipsType) -> Result<()> {
64 insert_or_error!(self.symbols, name,
65 FipsSymbol::new_local(typ),
66 anyhow!("Cannot redefine local variable with name {}", name)
67 )
68 }
69
70 pub fn add_local_symbol_with_value(&mut self, name: String, typ: FipsType, value: T) -> Result<()> {
71 insert_or_error!(self.symbols, name,
72 FipsSymbol::new_local_with_value(typ, value),
73 anyhow!("Cannot redefine local variable with name {}", name)
74 )
75 }
76
77 pub fn add_particle_member(&mut self, name: String, member_id: MemberID) -> Result<()> {
78 insert_or_error!(self.symbols, name,
79 FipsSymbol::new_particle_member(member_id),
80 anyhow!("Cannot redefine particle member variable with name {}", name)
81 )
82 }
83
84 pub fn add_function(&mut self, name: String, function_id: FunctionID) -> Result<()> {
85 insert_or_error!(self.symbols, name,
86 FipsSymbol::new_function(function_id),
87 anyhow!("Cannot redefine function with name {}", name)
88 )
89 }
90
91 pub fn push_table(&mut self, symbols: SymbolTable<T>) {
93 self.subtables.push(symbols)
94 }
95
96 pub fn pop_table(&mut self) -> Option<SymbolTable<T>> {
98 self.subtables.pop()
99 }
100
101 pub fn convert<U>(self) -> SymbolTable<U> {
103 let symbols = self.symbols.into_iter()
104 .map(|(name, symbol)| (name, symbol.convert()))
105 .collect::<HashMap<_,_>>();
106 let subtables = self.subtables.into_iter()
107 .map(|table| table.convert())
108 .collect::<Vec<_>>();
109 SymbolTable {
110 symbols,
111 subtables
112 }
113 }
114
115 pub fn iter_mut(&mut self) -> impl Iterator<Item=(&String, &mut FipsSymbol<T>)> {
117 let mut total_symbols = vec![];
121 for symbol_pair in &mut self.symbols {
122 total_symbols.push(symbol_pair)
123 }
124 for subtable in &mut self.subtables {
125 for symbol_pair in subtable.iter_mut() {
126 total_symbols.push(symbol_pair);
127 }
128 }
129 total_symbols.into_iter()
130 }
131
132 pub fn iter(&self) -> impl Iterator<Item=(&String, &FipsSymbol<T>)> {
134 let mut total_symbols = vec![];
138 for symbol_pair in &self.symbols {
139 total_symbols.push(symbol_pair)
140 }
141 for subtable in &self.subtables {
142 for symbol_pair in subtable.iter() {
143 total_symbols.push(symbol_pair);
144 }
145 }
146 total_symbols.into_iter()
147 }
148
149 pub fn resolve_symbol(&self, name: &str) -> Option<&FipsSymbol<T>> {
150 if let Some(symbol) = self.symbols.get(name) {
152 return Some(symbol)
153 };
154 for subtable in self.subtables.iter().rev() {
155 if let Some(symbol) = subtable.resolve_symbol(name) {
156 return Some(symbol)
157 }
158 };
159 None
160 }
161}
162
163
164
165#[derive(Clone)]
167pub struct FipsSymbol<T> {
168 pub(crate) kind: FipsSymbolKind,
169 pub(crate) value: Option<T>
170}
171
172impl<T> FipsSymbol<T> {
173 pub fn from_substitution(value: &SubstitutionValue) -> Self {
174 Self {
175 kind: FipsSymbolKind::from_subsitution(value),
176 value: None
177 }
178 }
179
180 pub fn from_f64(value: f64) -> Self {
181 Self {
182 kind: FipsSymbolKind::from_f64(value),
183 value: None
184 }
185 }
186
187 pub fn new_local(typ: FipsType) -> Self {
188 Self {
189 kind: FipsSymbolKind::LocalVariable(typ),
190 value: None
191 }
192 }
193
194 pub fn new_local_with_value(typ: FipsType, value: T) -> Self {
195 Self {
196 kind: FipsSymbolKind::LocalVariable(typ),
197 value: Some(value)
198 }
199 }
200
201 pub fn new_particle_member(member_id: MemberID) -> Self {
202 Self {
203 kind: FipsSymbolKind::ParticleMember(member_id),
204 value: None
205 }
206 }
207
208 pub fn new_function(function_id: FunctionID) -> Self {
209 Self {
210 kind: FipsSymbolKind::Function(function_id),
211 value: None
212 }
213 }
214
215 pub fn convert<U>(self) -> FipsSymbol<U> {
216 FipsSymbol {
217 kind: self.kind,
218 value: None
219 }
220 }
221
222 pub fn set_value(&mut self, value: T) {
223 self.value = Some(value)
224 }
225}
226
227#[derive(Clone)]
229pub enum FipsSymbolKind {
230 Constant(FipsValue),
232 LocalVariable(FipsType),
234 ParticleMember(MemberID),
237 Function(FunctionID)
239}
240
241impl FipsSymbolKind {
242 pub fn from_subsitution(val: &SubstitutionValue) -> Self {
244 Self::Constant(val.clone().into())
245 }
246
247 pub fn from_f64(val: f64) -> Self {
248 Self::Constant(val.into())
249 }
250}