1use std::fmt::{Debug, Display, Error, Formatter};
2
3use super::ast::*;
4
5impl Statement {
6 pub fn get_meta(&self) -> &Meta {
7 use Statement::*;
8 match self {
9 IfThenElse { meta, .. }
10 | While { meta, .. }
11 | Return { meta, .. }
12 | Declaration { meta, .. }
13 | Substitution { meta, .. }
14 | MultiSubstitution { meta, .. }
15 | LogCall { meta, .. }
16 | Block { meta, .. }
17 | Assert { meta, .. }
18 | ConstraintEquality { meta, .. }
19 | InitializationBlock { meta, .. } => meta,
20 }
21 }
22 pub fn get_mut_meta(&mut self) -> &mut Meta {
23 use Statement::*;
24 match self {
25 IfThenElse { meta, .. }
26 | While { meta, .. }
27 | Return { meta, .. }
28 | Declaration { meta, .. }
29 | Substitution { meta, .. }
30 | MultiSubstitution { meta, .. }
31 | LogCall { meta, .. }
32 | Block { meta, .. }
33 | Assert { meta, .. }
34 | ConstraintEquality { meta, .. }
35 | InitializationBlock { meta, .. } => meta,
36 }
37 }
38
39 pub fn is_if_then_else(&self) -> bool {
40 use Statement::*;
41 matches!(self, IfThenElse { .. })
42 }
43
44 pub fn is_while(&self) -> bool {
45 use Statement::*;
46 matches!(self, While { .. })
47 }
48
49 pub fn is_return(&self) -> bool {
50 use Statement::*;
51 matches!(self, Return { .. })
52 }
53
54 pub fn is_initialization_block(&self) -> bool {
55 use Statement::*;
56 matches!(self, InitializationBlock { .. })
57 }
58
59 pub fn is_declaration(&self) -> bool {
60 use Statement::*;
61 matches!(self, Declaration { .. })
62 }
63
64 pub fn is_substitution(&self) -> bool {
65 use Statement::*;
66 matches!(self, Substitution { .. })
67 }
68
69 pub fn is_multi_substitution(&self) -> bool {
70 use Statement::*;
71 matches!(self, MultiSubstitution { .. })
72 }
73
74 pub fn is_constraint_equality(&self) -> bool {
75 use Statement::*;
76 matches!(self, ConstraintEquality { .. })
77 }
78
79 pub fn is_log_call(&self) -> bool {
80 use Statement::*;
81 matches!(self, LogCall { .. })
82 }
83
84 pub fn is_block(&self) -> bool {
85 use Statement::*;
86 matches!(self, Block { .. })
87 }
88
89 pub fn is_assert(&self) -> bool {
90 use Statement::*;
91 matches!(self, Assert { .. })
92 }
93}
94
95impl FillMeta for Statement {
96 fn fill(&mut self, file_id: usize, element_id: &mut usize) {
97 use Statement::*;
98 self.get_mut_meta().elem_id = *element_id;
99 *element_id += 1;
100 match self {
101 IfThenElse { meta, cond, if_case, else_case, .. } => {
102 fill_conditional(meta, cond, if_case, else_case, file_id, element_id)
103 }
104 While { meta, cond, stmt } => fill_while(meta, cond, stmt, file_id, element_id),
105 Return { meta, value } => fill_return(meta, value, file_id, element_id),
106 InitializationBlock { meta, initializations, .. } => {
107 fill_initialization(meta, initializations, file_id, element_id)
108 }
109 Declaration { meta, dimensions, .. } => {
110 fill_declaration(meta, dimensions, file_id, element_id)
111 }
112 Substitution { meta, access, rhe, .. } => {
113 fill_substitution(meta, access, rhe, file_id, element_id)
114 }
115 MultiSubstitution { meta, lhe, rhe, .. } => {
116 fill_multi_substitution(meta, lhe, rhe, file_id, element_id);
117 }
118 ConstraintEquality { meta, lhe, rhe } => {
119 fill_constraint_equality(meta, lhe, rhe, file_id, element_id)
120 }
121 LogCall { meta, args, .. } => fill_log_call(meta, args, file_id, element_id),
122 Block { meta, stmts, .. } => fill_block(meta, stmts, file_id, element_id),
123 Assert { meta, arg, .. } => fill_assert(meta, arg, file_id, element_id),
124 }
125 }
126}
127
128fn fill_conditional(
129 meta: &mut Meta,
130 cond: &mut Expression,
131 if_case: &mut Statement,
132 else_case: &mut Option<Box<Statement>>,
133 file_id: usize,
134 element_id: &mut usize,
135) {
136 meta.set_file_id(file_id);
137 cond.fill(file_id, element_id);
138 if_case.fill(file_id, element_id);
139 if let Option::Some(s) = else_case {
140 s.fill(file_id, element_id);
141 }
142}
143
144fn fill_while(
145 meta: &mut Meta,
146 cond: &mut Expression,
147 stmt: &mut Statement,
148 file_id: usize,
149 element_id: &mut usize,
150) {
151 meta.set_file_id(file_id);
152 cond.fill(file_id, element_id);
153 stmt.fill(file_id, element_id);
154}
155
156fn fill_return(meta: &mut Meta, value: &mut Expression, file_id: usize, element_id: &mut usize) {
157 meta.set_file_id(file_id);
158 value.fill(file_id, element_id);
159}
160
161fn fill_initialization(
162 meta: &mut Meta,
163 initializations: &mut [Statement],
164 file_id: usize,
165 element_id: &mut usize,
166) {
167 meta.set_file_id(file_id);
168 for init in initializations {
169 init.fill(file_id, element_id);
170 }
171}
172
173fn fill_declaration(
174 meta: &mut Meta,
175 dimensions: &mut [Expression],
176 file_id: usize,
177 element_id: &mut usize,
178) {
179 meta.set_file_id(file_id);
180 for d in dimensions {
181 d.fill(file_id, element_id);
182 }
183}
184
185fn fill_substitution(
186 meta: &mut Meta,
187 access: &mut [Access],
188 rhe: &mut Expression,
189 file_id: usize,
190 element_id: &mut usize,
191) {
192 meta.set_file_id(file_id);
193 rhe.fill(file_id, element_id);
194 for a in access {
195 if let Access::ArrayAccess(e) = a {
196 e.fill(file_id, element_id);
197 }
198 }
199}
200
201fn fill_multi_substitution(
202 meta: &mut Meta,
203 lhe: &mut Expression,
204 rhe: &mut Expression,
205 file_id: usize,
206 element_id: &mut usize,
207) {
208 meta.set_file_id(file_id);
209 rhe.fill(file_id, element_id);
210 lhe.fill(file_id, element_id);
211}
212
213fn fill_constraint_equality(
214 meta: &mut Meta,
215 lhe: &mut Expression,
216 rhe: &mut Expression,
217 file_id: usize,
218 element_id: &mut usize,
219) {
220 meta.set_file_id(file_id);
221 lhe.fill(file_id, element_id);
222 rhe.fill(file_id, element_id);
223}
224
225fn fill_log_call(
226 meta: &mut Meta,
227 args: &mut Vec<LogArgument>,
228 file_id: usize,
229 element_id: &mut usize,
230) {
231 meta.set_file_id(file_id);
232 for arg in args {
233 if let LogArgument::LogExp(e) = arg {
234 e.fill(file_id, element_id);
235 }
236 }
237}
238
239fn fill_block(meta: &mut Meta, stmts: &mut [Statement], file_id: usize, element_id: &mut usize) {
240 meta.set_file_id(file_id);
241 for s in stmts {
242 s.fill(file_id, element_id);
243 }
244}
245
246fn fill_assert(meta: &mut Meta, arg: &mut Expression, file_id: usize, element_id: &mut usize) {
247 meta.set_file_id(file_id);
248 arg.fill(file_id, element_id);
249}
250
251impl Debug for Statement {
252 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
253 use Statement::*;
254 match self {
255 IfThenElse { .. } => write!(f, "Statement::IfThenElse"),
256 While { .. } => write!(f, "Statement::While"),
257 Return { .. } => write!(f, "Statement::Return"),
258 Declaration { .. } => write!(f, "Statement::Declaration"),
259 Substitution { .. } => write!(f, "Statement::Substitution"),
260 MultiSubstitution { .. } => write!(f, "Statement::MultiSubstitution"),
261 LogCall { .. } => write!(f, "Statement::LogCall"),
262 Block { .. } => write!(f, "Statement::Block"),
263 Assert { .. } => write!(f, "Statement::Assert"),
264 ConstraintEquality { .. } => write!(f, "Statement::ConstraintEquality"),
265 InitializationBlock { .. } => write!(f, "Statement::InitializationBlock"),
266 }
267 }
268}
269
270impl Display for Statement {
271 fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
272 use Statement::*;
273 match self {
274 IfThenElse { cond, else_case, .. } => match else_case {
275 Some(_) => write!(f, "if {cond} else"),
276 None => write!(f, "if {cond}"),
277 },
278 While { cond, .. } => write!(f, "while {cond}"),
279 Return { value, .. } => write!(f, "return {value}"),
280 Declaration { name, xtype, .. } => write!(f, "{xtype} {name}"),
281 Substitution { var, access, op, rhe, .. } => {
282 write!(f, "{var}")?;
283 for access in access {
284 write!(f, "{access}")?;
285 }
286 write!(f, " {op} {rhe}")
287 }
288 MultiSubstitution { lhe, op, rhe, .. } => write!(f, "{lhe} {op} {rhe}"),
289 LogCall { args, .. } => write!(f, "log({})", vec_to_string(args)),
290 Block { .. } => Ok(()),
291 Assert { arg, .. } => write!(f, "assert({arg})"),
292 ConstraintEquality { lhe, rhe, .. } => write!(f, "{lhe} === {rhe}"),
293 InitializationBlock { .. } => Ok(()),
294 }
295 }
296}
297
298impl Display for AssignOp {
299 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
300 use AssignOp::*;
301 match self {
302 AssignVar => write!(f, "="),
303 AssignSignal => write!(f, "<--"),
304 AssignConstraintSignal => write!(f, "<=="),
305 }
306 }
307}
308
309impl Display for VariableType {
310 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
311 use SignalType::*;
312 use VariableType::*;
313 match self {
314 Var => write!(f, "var"),
315 Signal(signal_type, tag_list) => {
316 if matches!(signal_type, Intermediate) {
317 write!(f, "signal")?;
318 } else {
319 write!(f, "signal {signal_type}")?;
320 }
321 if !tag_list.is_empty() {
322 write!(f, " {{{}}}", tag_list.join("}} {{"))
323 } else {
324 Ok(())
325 }
326 }
327 Component => write!(f, "component"),
328 AnonymousComponent => write!(f, "anonymous component"),
329 }
330 }
331}
332
333impl Display for SignalType {
334 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
335 use SignalType::*;
336 match self {
337 Input => write!(f, "input"),
338 Output => write!(f, "output"),
339 Intermediate => write!(f, ""),
340 }
341 }
342}
343
344impl Display for LogArgument {
345 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
346 use LogArgument::*;
347 match self {
348 LogStr(message) => write!(f, "{message}"),
349 LogExp(value) => write!(f, "{value}"),
350 }
351 }
352}
353
354fn vec_to_string<T: ToString>(elems: &[T]) -> String {
355 elems.iter().map(|arg| arg.to_string()).collect::<Vec<String>>().join(", ")
356}