1use log::trace;
2use std::fmt;
3
4use super::declarations::Declarations;
5use super::ir::*;
6use super::degree_meta::{Degree, DegreeEnvironment, DegreeMeta};
7use super::type_meta::TypeMeta;
8use super::value_meta::{ValueEnvironment, ValueMeta};
9use super::variable_meta::{VariableMeta, VariableUse, VariableUses};
10
11impl Statement {
12 #[must_use]
13 pub fn meta(&self) -> &Meta {
14 use Statement::*;
15 match self {
16 Declaration { meta, .. }
17 | IfThenElse { meta, .. }
18 | Return { meta, .. }
19 | Substitution { meta, .. }
20 | LogCall { meta, .. }
21 | Assert { meta, .. }
22 | ConstraintEquality { meta, .. } => meta,
23 }
24 }
25
26 #[must_use]
27 pub fn meta_mut(&mut self) -> &mut Meta {
28 use Statement::*;
29 match self {
30 Declaration { meta, .. }
31 | IfThenElse { meta, .. }
32 | Return { meta, .. }
33 | Substitution { meta, .. }
34 | LogCall { meta, .. }
35 | Assert { meta, .. }
36 | ConstraintEquality { meta, .. } => meta,
37 }
38 }
39
40 pub fn propagate_degrees(&mut self, env: &mut DegreeEnvironment) -> bool {
41 let mut result = false;
42
43 use Degree::*;
44 use Statement::*;
45 use VariableType::*;
46 match self {
47 Declaration { names, var_type, .. } => {
48 for name in names.iter() {
49 if matches!(var_type, Signal(_, _) | Component | AnonymousComponent) {
51 result = result || env.set_degree(name, &Linear.into());
52 }
53 env.set_type(name, var_type);
54 }
55 result
56 }
57 Substitution { var, rhe, .. } => {
58 result = result || rhe.propagate_degrees(env);
59 if env.is_local(var) {
60 if let Some(range) = rhe.degree() {
61 result = result || env.set_degree(var, range);
62 }
63 }
64 result
65 }
66 LogCall { args, .. } => {
67 use LogArgument::*;
68 for arg in args {
69 if let Expr(value) = arg {
70 result = result || value.propagate_degrees(env);
71 }
72 }
73 result
74 }
75 IfThenElse { cond, .. } => cond.propagate_degrees(env),
76 Return { value, .. } => value.propagate_degrees(env),
77 Assert { arg, .. } => arg.propagate_degrees(env),
78 ConstraintEquality { lhe, rhe, .. } => {
79 result = result || lhe.propagate_degrees(env);
80 result = result || rhe.propagate_degrees(env);
81 result
82 }
83 }
84 }
85
86 #[must_use]
87 pub fn propagate_values(&mut self, env: &mut ValueEnvironment) -> bool {
88 use Statement::*;
89 use Expression::*;
90 match self {
91 Declaration { dimensions, .. } => {
92 let mut result = false;
93 for size in dimensions {
94 result = result || size.propagate_values(env);
95 }
96 result
97 }
98 Substitution { meta, var, rhe, .. } => {
99 let mut result = rhe.propagate_values(env);
100
101 if !matches!(rhe, Update { .. }) {
103 if let Some(value) = rhe.value() {
104 env.add_variable(var, value);
105 result = result || meta.value_knowledge_mut().set_reduces_to(value.clone());
106 }
107 }
108 trace!("Substitution returned {result}");
109 result
110 }
111 LogCall { args, .. } => {
112 let mut result = false;
113 use LogArgument::*;
114 for arg in args {
115 if let Expr(value) = arg {
116 result = result || value.propagate_values(env);
117 }
118 }
119 result
120 }
121 IfThenElse { cond, .. } => cond.propagate_values(env),
122 Return { value, .. } => value.propagate_values(env),
123 Assert { arg, .. } => arg.propagate_values(env),
124 ConstraintEquality { lhe, rhe, .. } => {
125 lhe.propagate_values(env) || rhe.propagate_values(env)
126 }
127 }
128 }
129
130 pub fn propagate_types(&mut self, vars: &Declarations) {
131 use Statement::*;
132 match self {
133 Declaration { meta, var_type, dimensions, .. } => {
134 meta.type_knowledge_mut().set_variable_type(var_type);
136 for size in dimensions {
137 size.propagate_types(vars);
138 }
139 }
140 Substitution { meta, var, rhe, .. } => {
141 rhe.propagate_types(vars);
143 if let Some(var_type) = vars.get_type(var) {
144 meta.type_knowledge_mut().set_variable_type(var_type);
145 }
146 }
147 LogCall { args, .. } => {
148 use LogArgument::*;
149 for arg in args {
150 if let Expr(value) = arg {
151 value.propagate_types(vars);
152 }
153 }
154 }
155 ConstraintEquality { lhe, rhe, .. } => {
156 lhe.propagate_types(vars);
157 rhe.propagate_types(vars);
158 }
159 IfThenElse { cond, .. } => {
160 cond.propagate_types(vars);
161 }
162 Return { value, .. } => {
163 value.propagate_types(vars);
164 }
165 Assert { arg, .. } => {
166 arg.propagate_types(vars);
167 }
168 }
169 }
170}
171
172impl fmt::Debug for Statement {
173 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
174 use Statement::*;
175 match self {
176 Declaration { names, var_type, dimensions, .. } => {
177 write!(f, "{var_type} ")?;
178 let mut first = true;
179 for name in names {
180 if first {
181 first = false;
182 } else {
183 write!(f, ", ")?;
184 }
185 write!(f, "{name:?}")?;
186 for size in dimensions {
187 write!(f, "[{size:?}]")?;
188 }
189 }
190 Ok(())
191 }
192 Substitution { var, op, rhe, .. } => write!(f, "{var:?} {op} {rhe:?}"),
193 ConstraintEquality { lhe, rhe, .. } => write!(f, "{lhe:?} === {rhe:?}"),
194 IfThenElse { cond, true_index, false_index, .. } => match false_index {
195 Some(false_index) => write!(f, "if {cond:?} then {true_index} else {false_index}"),
196 None => write!(f, "if {cond:?} then {true_index}"),
197 },
198 Return { value, .. } => write!(f, "return {value:?}"),
199 Assert { arg, .. } => write!(f, "assert({arg:?})"),
200 LogCall { args, .. } => write!(f, "log({:?})", vec_to_debug(args, ", ")),
201 }
202 }
203}
204
205impl fmt::Display for Statement {
206 fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
207 use Statement::*;
208 match self {
209 Declaration { names, var_type, dimensions, .. } => {
210 write!(f, "{var_type} {}", names.first())?;
213 for size in dimensions {
214 write!(f, "[{size}]")?;
215 }
216 Ok(())
217 }
218 Substitution { var, op, rhe, .. } => {
219 match rhe {
220 Expression::Update { access, rhe, .. } => {
222 write!(f, "{var}")?;
223 for access in access {
224 write!(f, "{access}")?;
225 }
226 write!(f, " {op} {rhe}")
227 }
228 _ => write!(f, "{var} {op} {rhe}"),
230 }
231 }
232 ConstraintEquality { lhe, rhe, .. } => write!(f, "{lhe} === {rhe}"),
233 IfThenElse { cond, .. } => write!(f, "if {cond}"),
234 Return { value, .. } => write!(f, "return {value}"),
235 Assert { arg, .. } => write!(f, "assert({arg})"),
236 LogCall { args, .. } => write!(f, "log({})", vec_to_display(args, ", ")),
237 }
238 }
239}
240
241impl fmt::Display for AssignOp {
242 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
243 use AssignOp::*;
244 match self {
245 AssignSignal => write!(f, "<--"),
246 AssignConstraintSignal => write!(f, "<=="),
247 AssignLocalOrComponent => write!(f, "="),
248 }
249 }
250}
251
252impl fmt::Display for LogArgument {
253 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
254 use LogArgument::*;
255 match self {
256 String(message) => write!(f, "{message}"),
257 Expr(value) => write!(f, "{value}"),
258 }
259 }
260}
261
262impl fmt::Debug for LogArgument {
263 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
264 use LogArgument::*;
265 match self {
266 String(message) => write!(f, "{message:?}"),
267 Expr(value) => write!(f, "{value:?}"),
268 }
269 }
270}
271
272impl VariableMeta for Statement {
273 fn cache_variable_use(&mut self) {
274 let mut locals_read = VariableUses::new();
275 let mut locals_written = VariableUses::new();
276 let mut signals_read = VariableUses::new();
277 let mut signals_written = VariableUses::new();
278 let mut components_read = VariableUses::new();
279 let mut components_written = VariableUses::new();
280
281 use Statement::*;
282 use Expression::*;
283 match self {
284 Declaration { dimensions, .. } => {
285 for size in dimensions {
286 size.cache_variable_use();
287 locals_read.extend(size.locals_read().clone());
288 signals_read.extend(size.signals_read().clone());
289 components_read.extend(size.components_read().clone());
290 }
291 }
292 Substitution { meta, var, op, rhe } => {
293 rhe.cache_variable_use();
294 locals_read.extend(rhe.locals_read().clone());
295 signals_read.extend(rhe.signals_read().clone());
296 components_read.extend(rhe.components_read().clone());
297
298 let access = match rhe {
299 Update { access, .. } => access.clone(),
300 _ => Vec::new(),
301 };
302 match meta.type_knowledge().variable_type() {
303 Some(VariableType::Local) => {
304 trace!("adding `{var:?}` to local variables written");
305 locals_written.insert(VariableUse::new(meta, var, &access));
306 }
307 Some(VariableType::Signal(_, _)) => {
308 trace!("adding `{var:?}` to signals written");
309 signals_written.insert(VariableUse::new(meta, var, &access));
310 if matches!(op, AssignOp::AssignConstraintSignal) {
311 trace!("adding `{var:?}` to signals read");
314 signals_read.insert(VariableUse::new(meta, var, &access));
315 }
316 }
317 Some(VariableType::Component | VariableType::AnonymousComponent) => {
318 trace!("adding `{var:?}` to components written");
319 components_written.insert(VariableUse::new(meta, var, &access));
320 }
321 None => {
322 trace!("variable `{var:?}` of unknown type written");
323 }
324 }
325 }
326 LogCall { args, .. } => {
327 use LogArgument::*;
328 for arg in args {
329 if let Expr(value) = arg {
330 value.cache_variable_use();
331 locals_read.extend(value.locals_read().clone());
332 signals_read.extend(value.signals_read().clone());
333 components_read.extend(value.components_read().clone());
334 }
335 }
336 }
337 IfThenElse { cond, .. } => {
338 cond.cache_variable_use();
339 locals_read.extend(cond.locals_read().clone());
340 signals_read.extend(cond.signals_read().clone());
341 components_read.extend(cond.components_read().clone());
342 }
343 Return { value, .. } => {
344 value.cache_variable_use();
345 locals_read.extend(value.locals_read().clone());
346 signals_read.extend(value.signals_read().clone());
347 components_read.extend(value.components_read().clone());
348 }
349 Assert { arg, .. } => {
350 arg.cache_variable_use();
351 locals_read.extend(arg.locals_read().clone());
352 signals_read.extend(arg.signals_read().clone());
353 components_read.extend(arg.components_read().clone());
354 }
355 ConstraintEquality { lhe, rhe, .. } => {
356 lhe.cache_variable_use();
357 rhe.cache_variable_use();
358 locals_read.extend(lhe.locals_read().iter().cloned());
359 locals_read.extend(rhe.locals_read().iter().cloned());
360 signals_read.extend(lhe.signals_read().iter().cloned());
361 signals_read.extend(rhe.signals_read().iter().cloned());
362 components_read.extend(lhe.components_read().iter().cloned());
363 components_read.extend(rhe.components_read().iter().cloned());
364 }
365 }
366 self.meta_mut()
367 .variable_knowledge_mut()
368 .set_locals_read(&locals_read)
369 .set_locals_written(&locals_written)
370 .set_signals_read(&signals_read)
371 .set_signals_written(&signals_written)
372 .set_components_read(&components_read)
373 .set_components_written(&components_written);
374 }
375
376 fn locals_read(&self) -> &VariableUses {
377 self.meta().variable_knowledge().locals_read()
378 }
379
380 fn locals_written(&self) -> &VariableUses {
381 self.meta().variable_knowledge().locals_written()
382 }
383
384 fn signals_read(&self) -> &VariableUses {
385 self.meta().variable_knowledge().signals_read()
386 }
387
388 fn signals_written(&self) -> &VariableUses {
389 self.meta().variable_knowledge().signals_written()
390 }
391
392 fn components_read(&self) -> &VariableUses {
393 self.meta().variable_knowledge().components_read()
394 }
395
396 fn components_written(&self) -> &VariableUses {
397 self.meta().variable_knowledge().components_written()
398 }
399}
400
401#[must_use]
402fn vec_to_debug<T: fmt::Debug>(elems: &[T], sep: &str) -> String {
403 elems.iter().map(|elem| format!("{elem:?}")).collect::<Vec<String>>().join(sep)
404}
405
406#[must_use]
407fn vec_to_display<T: fmt::Display>(elems: &[T], sep: &str) -> String {
408 elems.iter().map(|elem| format!("{elem}")).collect::<Vec<String>>().join(sep)
409}