1use std::fmt::{Debug, Display, Error, Formatter};
2
3use super::ast::*;
4use super::expression_builders::build_anonymous_component;
5
6impl Expression {
7 pub fn meta(&self) -> &Meta {
8 use Expression::*;
9 match self {
10 InfixOp { meta, .. }
11 | PrefixOp { meta, .. }
12 | InlineSwitchOp { meta, .. }
13 | Variable { meta, .. }
14 | ParallelOp { meta, .. }
15 | Number(meta, ..)
16 | Call { meta, .. }
17 | AnonymousComponent { meta, .. }
18 | ArrayInLine { meta, .. }
19 | Tuple { meta, .. } => meta,
20 }
21 }
22 pub fn meta_mut(&mut self) -> &mut Meta {
23 use Expression::*;
24 match self {
25 InfixOp { meta, .. }
26 | PrefixOp { meta, .. }
27 | InlineSwitchOp { meta, .. }
28 | Variable { meta, .. }
29 | ParallelOp { meta, .. }
30 | Number(meta, ..)
31 | Call { meta, .. }
32 | AnonymousComponent { meta, .. }
33 | ArrayInLine { meta, .. }
34 | Tuple { meta, .. } => meta,
35 }
36 }
37
38 pub fn is_array(&self) -> bool {
39 use Expression::*;
40 matches!(self, ArrayInLine { .. })
41 }
42
43 pub fn is_infix(&self) -> bool {
44 use Expression::*;
45 matches!(self, InfixOp { .. })
46 }
47
48 pub fn is_prefix(&self) -> bool {
49 use Expression::*;
50 matches!(self, PrefixOp { .. })
51 }
52
53 pub fn is_switch(&self) -> bool {
54 use Expression::*;
55 matches!(self, InlineSwitchOp { .. })
56 }
57
58 pub fn is_variable(&self) -> bool {
59 use Expression::*;
60 matches!(self, Variable { .. })
61 }
62
63 pub fn is_number(&self) -> bool {
64 use Expression::*;
65 matches!(self, Number(..))
66 }
67
68 pub fn is_call(&self) -> bool {
69 use Expression::*;
70 matches!(self, Call { .. })
71 }
72
73 pub fn is_parallel(&self) -> bool {
74 use Expression::*;
75 matches!(self, ParallelOp { .. })
76 }
77
78 pub fn is_tuple(&self) -> bool {
79 use Expression::*;
80 matches!(self, Tuple { .. })
81 }
82
83 pub fn is_anonymous_component(&self) -> bool {
84 use Expression::*;
85 matches!(self, AnonymousComponent { .. })
86 }
87
88 pub fn make_anonymous_parallel(self) -> Expression {
89 use Expression::*;
90 match self {
91 AnonymousComponent { meta, id, params, signals, names, .. } => {
92 build_anonymous_component(meta, id, params, signals, names, true)
93 }
94 _ => self,
95 }
96 }
97}
98
99impl FillMeta for Expression {
100 fn fill(&mut self, file_id: usize, element_id: &mut usize) {
101 use Expression::*;
102 self.meta_mut().elem_id = *element_id;
103 *element_id += 1;
104 match self {
105 Tuple { meta, values } => fill_tuple(meta, values, file_id, element_id),
106 Number(meta, _) => fill_number(meta, file_id, element_id),
107 Variable { meta, access, .. } => fill_variable(meta, access, file_id, element_id),
108 InfixOp { meta, lhe, rhe, .. } => fill_infix(meta, lhe, rhe, file_id, element_id),
109 PrefixOp { meta, rhe, .. } => fill_prefix(meta, rhe, file_id, element_id),
110 ParallelOp { meta, rhe, .. } => fill_parallel(meta, rhe, file_id, element_id),
111 InlineSwitchOp { meta, cond, if_false, if_true, .. } => {
112 fill_inline_switch_op(meta, cond, if_true, if_false, file_id, element_id)
113 }
114 Call { meta, args, .. } => fill_call(meta, args, file_id, element_id),
115 ArrayInLine { meta, values, .. } => {
116 fill_array_inline(meta, values, file_id, element_id)
117 }
118 AnonymousComponent { meta, params, signals, .. } => {
119 fill_anonymous_component(meta, params, signals, file_id, element_id)
120 }
121 }
122 }
123}
124
125fn fill_number(meta: &mut Meta, file_id: usize, _element_id: &mut usize) {
126 meta.set_file_id(file_id);
127}
128
129fn fill_variable(meta: &mut Meta, access: &mut [Access], file_id: usize, element_id: &mut usize) {
130 meta.set_file_id(file_id);
131 for acc in access {
132 if let Access::ArrayAccess(e) = acc {
133 e.fill(file_id, element_id)
134 }
135 }
136}
137
138fn fill_infix(
139 meta: &mut Meta,
140 lhe: &mut Expression,
141 rhe: &mut Expression,
142 file_id: usize,
143 element_id: &mut usize,
144) {
145 meta.set_file_id(file_id);
146 lhe.fill(file_id, element_id);
147 rhe.fill(file_id, element_id);
148}
149
150fn fill_prefix(meta: &mut Meta, rhe: &mut Expression, file_id: usize, element_id: &mut usize) {
151 meta.set_file_id(file_id);
152 rhe.fill(file_id, element_id);
153}
154
155fn fill_inline_switch_op(
156 meta: &mut Meta,
157 cond: &mut Expression,
158 if_true: &mut Expression,
159 if_false: &mut Expression,
160 file_id: usize,
161 element_id: &mut usize,
162) {
163 meta.set_file_id(file_id);
164 cond.fill(file_id, element_id);
165 if_true.fill(file_id, element_id);
166 if_false.fill(file_id, element_id);
167}
168
169fn fill_call(meta: &mut Meta, args: &mut [Expression], file_id: usize, element_id: &mut usize) {
170 meta.set_file_id(file_id);
171 for a in args {
172 a.fill(file_id, element_id);
173 }
174}
175
176fn fill_array_inline(
177 meta: &mut Meta,
178 values: &mut [Expression],
179 file_id: usize,
180 element_id: &mut usize,
181) {
182 meta.set_file_id(file_id);
183 for v in values {
184 v.fill(file_id, element_id);
185 }
186}
187
188fn fill_anonymous_component(
189 meta: &mut Meta,
190 params: &mut [Expression],
191 signals: &mut [Expression],
192 file_id: usize,
193 element_id: &mut usize,
194) {
195 meta.set_file_id(file_id);
196 for param in params {
197 param.fill(file_id, element_id);
198 }
199 for signal in signals {
200 signal.fill(file_id, element_id);
201 }
202}
203
204fn fill_tuple(meta: &mut Meta, values: &mut [Expression], file_id: usize, element_id: &mut usize) {
205 meta.set_file_id(file_id);
206 for value in values {
207 value.fill(file_id, element_id);
208 }
209}
210
211fn fill_parallel(meta: &mut Meta, rhe: &mut Expression, file_id: usize, element_id: &mut usize) {
212 meta.set_file_id(file_id);
213 rhe.fill(file_id, element_id);
214}
215
216impl Debug for Expression {
217 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
218 use Expression::*;
219 match self {
220 InfixOp { .. } => write!(f, "Expression::InfixOp"),
221 PrefixOp { .. } => write!(f, "Expression::PrefixOp"),
222 InlineSwitchOp { .. } => write!(f, "Expression::InlineSwitchOp"),
223 Variable { .. } => write!(f, "Expression::Variable"),
224 ParallelOp { .. } => write!(f, "Expression::ParallelOp"),
225 Number(..) => write!(f, "Expression::Number"),
226 Call { .. } => write!(f, "Expression::Call"),
227 AnonymousComponent { .. } => write!(f, "Expression::AnonymousComponent"),
228 ArrayInLine { .. } => write!(f, "Expression::ArrayInline"),
229 Tuple { .. } => write!(f, "Expression::Tuple"),
230 }
231 }
232}
233
234impl Display for Expression {
235 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
236 use Expression::*;
237 match self {
238 Tuple { values, .. } => write!(f, "({})", vec_to_string(values)),
239 Number(_, value) => write!(f, "{value}"),
240 Variable { name, access, .. } => {
241 write!(f, "{name}")?;
242 for access in access {
243 write!(f, "{access}")?;
244 }
245 Ok(())
246 }
247 ParallelOp { rhe, .. } => write!(f, "parallel {rhe}"),
248 InfixOp { lhe, infix_op, rhe, .. } => write!(f, "({lhe} {infix_op} {rhe})"),
249 PrefixOp { prefix_op, rhe, .. } => write!(f, "{prefix_op}({rhe})"),
250 InlineSwitchOp { cond, if_true, if_false, .. } => {
251 write!(f, "({cond}? {if_true} : {if_false})")
252 }
253 Call { id, args, .. } => write!(f, "{id}({})", vec_to_string(args)),
254 ArrayInLine { values, .. } => write!(f, "[{}]", vec_to_string(values)),
255 AnonymousComponent { id, params, signals, names, .. } => {
256 write!(f, "{id}({})({})", vec_to_string(params), signals_to_string(names, signals))
257 }
258 }
259 }
260}
261
262impl Display for ExpressionInfixOpcode {
263 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
264 use ExpressionInfixOpcode::*;
265 match self {
266 Mul => f.write_str("*"),
267 Div => f.write_str("/"),
268 Add => f.write_str("+"),
269 Sub => f.write_str("-"),
270 Pow => f.write_str("**"),
271 IntDiv => f.write_str("\\"),
272 Mod => f.write_str("%"),
273 ShiftL => f.write_str("<<"),
274 ShiftR => f.write_str(">>"),
275 LesserEq => f.write_str("<="),
276 GreaterEq => f.write_str(">="),
277 Lesser => f.write_str("<"),
278 Greater => f.write_str(">"),
279 Eq => f.write_str("=="),
280 NotEq => f.write_str("!="),
281 BoolOr => f.write_str("||"),
282 BoolAnd => f.write_str("&&"),
283 BitOr => f.write_str("|"),
284 BitAnd => f.write_str("&"),
285 BitXor => f.write_str("^"),
286 }
287 }
288}
289
290impl Display for ExpressionPrefixOpcode {
291 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
292 use ExpressionPrefixOpcode::*;
293 match self {
294 Sub => f.write_str("-"),
295 BoolNot => f.write_str("!"),
296 Complement => f.write_str("~"),
297 }
298 }
299}
300
301impl Display for Access {
302 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
303 use Access::*;
304 match self {
305 ArrayAccess(index) => write!(f, "[{index}]"),
306 ComponentAccess(name) => write!(f, ".{name}"),
307 }
308 }
309}
310
311fn vec_to_string(elems: &[Expression]) -> String {
312 elems.iter().map(|arg| arg.to_string()).collect::<Vec<String>>().join(", ")
313}
314
315fn signals_to_string(names: &Option<Vec<(AssignOp, String)>>, signals: &[Expression]) -> String {
316 if let Some(names) = names {
317 names
318 .iter()
319 .zip(signals.iter())
320 .map(|((op, name), signal)| format!("{name} {op} {signal}"))
321 .collect::<Vec<_>>()
322 } else {
323 signals.iter().map(|signal| signal.to_string()).collect::<Vec<_>>()
324 }
325 .join(", ")
326}