circom_lsp_program_structure/abstract_syntax_tree/
expression_impl.rs

1use crate::expression_builders::build_anonymous_component;
2
3use super::ast::*;
4
5impl Expression {
6    pub fn get_meta(&self) -> &Meta {
7        use Expression::*;
8        match self {
9            InfixOp { meta, .. }
10            | PrefixOp { meta, .. }
11            | InlineSwitchOp { meta, .. }
12            | ParallelOp {meta, .. }
13            | Variable { meta, .. }
14            | Number(meta, ..)
15            | Call { meta, .. }
16            | AnonymousComp { meta, ..}
17            | ArrayInLine { meta, .. } => meta,
18            | UniformArray { meta, .. } => meta,
19            | Tuple {meta, ..} => meta,
20        }
21    }
22    pub fn get_mut_meta(&mut self) -> &mut Meta {
23        use Expression::*;
24        match self {
25            InfixOp { meta, .. }
26            | PrefixOp { meta, .. }
27            | InlineSwitchOp { meta, .. }
28            | ParallelOp {meta, .. }
29            | Variable { meta, .. }
30            | Number(meta, ..)
31            | Call { meta, .. }
32            | AnonymousComp {meta, ..}
33            | ArrayInLine { meta, .. } => meta,
34            | UniformArray { meta, .. } => meta,
35            | Tuple {meta, ..} => meta,
36        }
37    }
38
39    pub fn is_array(&self) -> bool {
40        use Expression::*;
41        if let ArrayInLine { .. } = self {
42            true
43        } else if let UniformArray { .. } = self{
44            true
45        } else {
46            false
47        }
48    }
49
50    pub fn is_infix(&self) -> bool {
51        use Expression::*;
52        if let InfixOp { .. } = self {
53            true
54        } else {
55            false
56        }
57    }
58
59    pub fn is_prefix(&self) -> bool {
60        use Expression::*;
61        if let PrefixOp { .. } = self {
62            true
63        } else {
64            false
65        }
66    }
67    
68    pub fn is_tuple(&self) -> bool {
69        use Expression::*;
70        if let Tuple { .. } = self {
71            true
72        } else {
73            false
74        }
75    }
76    pub fn is_switch(&self) -> bool {
77        use Expression::*;
78        if let InlineSwitchOp { .. } = self {
79            true
80        } else {
81            false
82        }
83    }
84
85    pub fn is_parallel(&self) -> bool {
86        use Expression::*;
87        if let ParallelOp { .. } = self {
88            true
89        } else {
90            false
91        }
92    }
93
94    pub fn is_variable(&self) -> bool {
95        use Expression::*;
96        if let Variable { .. } = self {
97            true
98        } else {
99            false
100        }
101    }
102
103    pub fn is_number(&self) -> bool {
104        use Expression::*;
105        if let Number(..) = self {
106            true
107        } else {
108            false
109        }
110    }
111
112    pub fn is_call(&self) -> bool {
113        use Expression::*;
114        if let Call { .. } = self {
115            true
116        } else {
117            false
118        }
119    }
120
121    pub fn is_anonymous_comp(&self) -> bool {
122        use Expression::*;
123        if let AnonymousComp { .. } = self {
124            true
125        } else {
126            false
127        }
128    }
129
130    pub fn make_anonymous_parallel(self) -> Expression {
131        use Expression::*;
132        match self {
133            AnonymousComp { meta, id, params, signals, names, .. } => {
134                build_anonymous_component(meta, id, params, signals, names, true)
135            }
136            _ => self,
137        } 
138    } 
139
140    pub fn contains_anonymous_comp(&self) -> bool {
141        use Expression::*;
142        match &self {
143            InfixOp {  lhe, rhe , ..} |  UniformArray { value : lhe, dimension : rhe, .. } => {
144                 lhe.contains_anonymous_comp() || rhe.contains_anonymous_comp()
145            },
146            PrefixOp {  rhe, .. } => {
147                 rhe.contains_anonymous_comp()
148            },
149            InlineSwitchOp {  cond, if_true, if_false, .. } => {
150                 cond.contains_anonymous_comp() || if_true.contains_anonymous_comp() || if_false.contains_anonymous_comp()
151            },
152            Call { args, .. } | Tuple {values: args, ..} | ArrayInLine {  values : args, .. } => {
153                for arg in args{
154                    if arg.contains_anonymous_comp() {  return true;}
155                }
156                false
157            },
158            AnonymousComp { .. } => { true },
159            Variable { access, .. } => {
160                for ac in access{
161                    match ac {
162                        Access::ComponentAccess(_) => {},
163                        Access::ArrayAccess( exp ) => if exp.contains_anonymous_comp() {return true;},
164                    }
165                }
166                false
167            },
168            Number(_, _) => {false }
169            ParallelOp { rhe , .. } => { rhe.contains_anonymous_comp() },
170         }
171    }
172
173    pub fn contains_tuple(&self) -> bool {
174        use Expression::*;
175        match &self {
176            InfixOp {  lhe, rhe , ..} |  UniformArray { value : lhe, dimension : rhe, .. } => {
177                 lhe.contains_tuple() || rhe.contains_tuple()
178            },
179            PrefixOp {  rhe, .. } => {
180                 rhe.contains_tuple()
181            },
182            InlineSwitchOp {  cond, if_true, if_false, .. } => {
183                 cond.contains_tuple() || if_true.contains_tuple() || if_false.contains_tuple()
184            },
185            Call { args, .. } | ArrayInLine {  values : args, .. } => {
186                for arg in args{
187                    if arg.contains_tuple() {  return true;}
188                }
189                false
190            },
191            AnonymousComp { params, signals, .. } => { 
192                for ac in params{
193                    if ac.contains_tuple() {return true;}
194                }
195                for ac in signals{
196                    if ac.contains_tuple() {return true;}
197                }
198                false
199             },
200            Variable { access, .. } => {
201                for ac in access{
202                    match ac {
203                        Access::ComponentAccess(_) => {},
204                        Access::ArrayAccess( exp ) => if exp.contains_tuple() {return true;},
205                    }
206                }
207                false
208            },
209            Number(_, _) => {false },
210            Tuple { .. } => {true},
211            ParallelOp { rhe, .. } => {rhe.contains_tuple()},
212         }
213    }
214}
215
216impl FillMeta for Expression {
217    fn fill(&mut self, file_id: usize, element_id: &mut usize) {
218        use Expression::*;
219        self.get_mut_meta().elem_id = *element_id;
220        *element_id += 1;
221        match self {
222            Number(meta, _) => fill_number(meta, file_id, element_id),
223            Variable { meta, access, .. } => fill_variable(meta, access, file_id, element_id),
224            InfixOp { meta, lhe, rhe, .. } => fill_infix(meta, lhe, rhe, file_id, element_id),
225            PrefixOp { meta, rhe, .. } => fill_prefix(meta, rhe, file_id, element_id),
226            ParallelOp{ meta, rhe, ..} => fill_parallel(meta, rhe, file_id, element_id),
227            InlineSwitchOp { meta, cond, if_false, if_true, .. } => {
228                fill_inline_switch_op(meta, cond, if_true, if_false, file_id, element_id)
229            }
230            Call { meta, args, .. } => fill_call(meta, args, file_id, element_id),
231            ArrayInLine { meta, values, .. } => {
232                fill_array_inline(meta, values, file_id, element_id)
233            }
234            UniformArray { meta, value, dimension, .. } => {
235                fill_uniform_array(meta, value, dimension, file_id, element_id)
236            }
237            AnonymousComp { meta,  params, signals, .. } => {
238                    fill_anonymous_comp(meta, params, signals, file_id, element_id)
239            },
240            Tuple { meta, values} => {fill_tuple(meta,values,file_id,element_id)}
241        }
242    }
243}
244
245fn fill_number(meta: &mut Meta, file_id: usize, _element_id: &mut usize) {
246    meta.set_file_id(file_id);
247}
248
249fn fill_variable(meta: &mut Meta, access: &mut [Access], file_id: usize, element_id: &mut usize) {
250    meta.set_file_id(file_id);
251    for acc in access {
252        if let Access::ArrayAccess(e) = acc {
253            e.fill(file_id, element_id)
254        }
255    }
256}
257
258fn fill_infix(
259    meta: &mut Meta,
260    lhe: &mut Expression,
261    rhe: &mut Expression,
262    file_id: usize,
263    element_id: &mut usize,
264) {
265    meta.set_file_id(file_id);
266    lhe.fill(file_id, element_id);
267    rhe.fill(file_id, element_id);
268}
269
270fn fill_prefix(meta: &mut Meta, rhe: &mut Expression, file_id: usize, element_id: &mut usize) {
271    meta.set_file_id(file_id);
272    rhe.fill(file_id, element_id);
273}
274
275fn fill_parallel(meta: &mut Meta, rhe: &mut Expression, file_id: usize, element_id: &mut usize) {
276    meta.set_file_id(file_id);
277    rhe.fill(file_id, element_id);
278}
279
280fn fill_inline_switch_op(
281    meta: &mut Meta,
282    cond: &mut Expression,
283    if_true: &mut Expression,
284    if_false: &mut Expression,
285    file_id: usize,
286    element_id: &mut usize,
287) {
288    meta.set_file_id(file_id);
289    cond.fill(file_id, element_id);
290    if_true.fill(file_id, element_id);
291    if_false.fill(file_id, element_id);
292}
293
294fn fill_call(meta: &mut Meta, args: &mut [Expression], file_id: usize, element_id: &mut usize) {
295    meta.set_file_id(file_id);
296    for a in args {
297        a.fill(file_id, element_id);
298    }
299}
300
301fn fill_anonymous_comp(meta: &mut Meta, params: &mut [Expression],signals: &mut [Expression], file_id: usize, element_id: &mut usize) {
302    meta.set_file_id(file_id);
303    for a in params {
304        a.fill(file_id, element_id);
305    }
306    for a in signals {
307        a.fill(file_id, element_id);
308    }
309}
310fn fill_array_inline(
311    meta: &mut Meta,
312    values: &mut [Expression],
313    file_id: usize,
314    element_id: &mut usize,
315) {
316    meta.set_file_id(file_id);
317    for v in values {
318        v.fill(file_id, element_id);
319    }
320}
321
322fn fill_tuple(
323    meta: &mut Meta,
324    values: &mut [Expression],
325    file_id: usize,
326    element_id: &mut usize,
327) {
328    meta.set_file_id(file_id);
329    for v in values {
330        v.fill(file_id, element_id);
331    }
332}
333
334fn fill_uniform_array(
335    meta: &mut Meta,
336    value: &mut Expression,
337    dimensions: &mut Expression,
338    file_id: usize,
339    element_id: &mut usize,
340) {
341    meta.set_file_id(file_id);
342    value.fill(file_id, element_id);
343    dimensions.fill(file_id, element_id);
344}