1use crate::file_definition::FileLocation;
2use num_bigint::BigInt;
3use serde_derive::{Deserialize, Serialize};
4
5pub trait FillMeta {
6 fn fill(&mut self, file_id: usize, elem_id: &mut usize);
7}
8
9pub type MainComponent = (Vec<String>, Expression);
10
11pub fn build_main_component(public: Vec<String>, call: Expression) -> MainComponent {
12 (public, call)
13}
14
15pub type Version = (usize, usize, usize);
16pub type TagList = Vec<String>;
17
18#[derive(Clone)]
19pub struct Include {
20 pub meta: Meta,
21 pub path: String,
22}
23
24pub fn build_include(meta: Meta, path: String) -> Include {
25 Include { meta, path }
26}
27
28#[derive(Clone)]
29pub struct Meta {
30 pub elem_id: usize,
31 pub start: usize,
32 pub end: usize,
33 pub location: FileLocation,
34 pub file_id: Option<usize>,
35 pub component_inference: Option<String>,
36 type_knowledge: TypeKnowledge,
37 memory_knowledge: MemoryKnowledge,
38}
39impl Meta {
40 pub fn new(start: usize, end: usize) -> Meta {
41 Meta {
42 end,
43 start,
44 elem_id: 0,
45 location: start..end,
46 file_id: Option::None,
47 component_inference: None,
48 type_knowledge: TypeKnowledge::default(),
49 memory_knowledge: MemoryKnowledge::default(),
50 }
51 }
52 pub fn change_location(&mut self, location: FileLocation, file_id: Option<usize>) {
53 self.location = location;
54 self.file_id = file_id;
55 }
56 pub fn get_start(&self) -> usize {
57 self.location.start
58 }
59 pub fn get_end(&self) -> usize {
60 self.location.end
61 }
62 pub fn get_file_id(&self) -> usize {
63 if let Option::Some(id) = self.file_id {
64 id
65 } else {
66 panic!("Empty file id accessed")
67 }
68 }
69 pub fn get_memory_knowledge(&self) -> &MemoryKnowledge {
70 &self.memory_knowledge
71 }
72 pub fn get_type_knowledge(&self) -> &TypeKnowledge {
73 &self.type_knowledge
74 }
75 pub fn get_mut_memory_knowledge(&mut self) -> &mut MemoryKnowledge {
76 &mut self.memory_knowledge
77 }
78 pub fn get_mut_type_knowledge(&mut self) -> &mut TypeKnowledge {
79 &mut self.type_knowledge
80 }
81 pub fn file_location(&self) -> FileLocation {
82 self.location.clone()
83 }
84 pub fn set_file_id(&mut self, file_id: usize) {
85 self.file_id = Option::Some(file_id);
86 }
87}
88
89#[derive(Clone)]
90pub struct AST {
91 pub meta: Meta,
92 pub compiler_version: Option<Version>,
93 pub custom_gates: bool,
94 pub custom_gates_declared: bool,
95 pub includes: Vec<Include>,
96 pub definitions: Vec<Definition>,
97 pub main_component: Option<MainComponent>,
98}
99impl AST {
100 pub fn new(
101 meta: Meta,
102 compiler_version: Option<Version>,
103 custom_gates: bool,
104 includes: Vec<Include>,
105 definitions: Vec<Definition>,
106 main_component: Option<MainComponent>,
107 ) -> AST {
108 let custom_gates_declared = definitions.iter().any(|definition| {
109 matches!(definition, Definition::Template { is_custom_gate: true, .. })
110 });
111 AST {
112 meta,
113 compiler_version,
114 custom_gates,
115 custom_gates_declared,
116 includes,
117 definitions,
118 main_component,
119 }
120 }
121}
122
123#[derive(Clone)]
124pub enum Definition {
125 Template {
126 meta: Meta,
127 name: String,
128 args: Vec<String>,
129 arg_location: FileLocation,
130 body: Statement,
131 parallel: bool,
132 is_custom_gate: bool,
133 },
134 Function {
135 meta: Meta,
136 name: String,
137 args: Vec<String>,
138 arg_location: FileLocation,
139 body: Statement,
140 },
141}
142pub fn build_template(
143 meta: Meta,
144 name: String,
145 args: Vec<String>,
146 arg_location: FileLocation,
147 body: Statement,
148 parallel: bool,
149 is_custom_gate: bool,
150) -> Definition {
151 Definition::Template { meta, name, args, arg_location, body, parallel, is_custom_gate }
152}
153
154pub fn build_function(
155 meta: Meta,
156 name: String,
157 args: Vec<String>,
158 arg_location: FileLocation,
159 body: Statement,
160) -> Definition {
161 Definition::Function { meta, name, args, arg_location, body }
162}
163
164impl Definition {
165 pub fn name(&self) -> String {
166 match self {
167 Self::Template { name, .. } => name.clone(),
168 Self::Function { name, .. } => name.clone(),
169 }
170 }
171}
172
173#[derive(Clone)]
174pub enum Statement {
175 IfThenElse {
176 meta: Meta,
177 cond: Expression,
178 if_case: Box<Statement>,
179 else_case: Option<Box<Statement>>,
180 },
181 While {
182 meta: Meta,
183 cond: Expression,
184 stmt: Box<Statement>,
185 },
186 Return {
187 meta: Meta,
188 value: Expression,
189 },
190 InitializationBlock {
191 meta: Meta,
192 xtype: VariableType,
193 initializations: Vec<Statement>,
194 },
195 Declaration {
196 meta: Meta,
197 xtype: VariableType,
198 name: String,
199 dimensions: Vec<Expression>,
200 is_constant: bool,
201 },
202 Substitution {
203 meta: Meta,
204 var: String,
205 access: Vec<Access>,
206 op: AssignOp,
207 rhe: Expression,
208 },
209 MultiSubstitution {
210 meta: Meta,
211 lhe: Expression,
212 op: AssignOp,
213 rhe: Expression,
214 },
215 ConstraintEquality {
216 meta: Meta,
217 lhe: Expression,
218 rhe: Expression,
219 },
220 LogCall {
221 meta: Meta,
222 args: Vec<LogArgument>,
223 },
224 Block {
225 meta: Meta,
226 stmts: Vec<Statement>,
227 },
228 Assert {
229 meta: Meta,
230 arg: Expression,
231 },
232}
233
234#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
235pub enum SignalElementType {
236 Empty,
237 Binary,
238 FieldElement,
239}
240
241#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
242pub enum SignalType {
243 Output,
244 Input,
245 Intermediate,
246}
247
248#[derive(Clone, PartialEq, Ord, PartialOrd, Eq)]
249pub enum VariableType {
250 Var,
251 Signal(SignalType, TagList),
252 Component,
253 AnonymousComponent,
254}
255
256#[derive(Clone)]
257pub enum Expression {
258 InfixOp {
259 meta: Meta,
260 lhe: Box<Expression>,
261 infix_op: ExpressionInfixOpcode,
262 rhe: Box<Expression>,
263 },
264 PrefixOp {
265 meta: Meta,
266 prefix_op: ExpressionPrefixOpcode,
267 rhe: Box<Expression>,
268 },
269 InlineSwitchOp {
270 meta: Meta,
271 cond: Box<Expression>,
272 if_true: Box<Expression>,
273 if_false: Box<Expression>,
274 },
275 ParallelOp {
276 meta: Meta,
277 rhe: Box<Expression>,
278 },
279 Variable {
280 meta: Meta,
281 name: String,
282 access: Vec<Access>,
283 },
284 Number(Meta, BigInt),
285 Call {
286 meta: Meta,
287 id: String,
288 args: Vec<Expression>,
289 },
290 AnonymousComponent {
291 meta: Meta,
292 id: String,
293 is_parallel: bool,
294 params: Vec<Expression>,
295 signals: Vec<Expression>,
296 names: Option<Vec<(AssignOp, String)>>,
297 },
298 ArrayInLine {
306 meta: Meta,
307 values: Vec<Expression>,
308 },
309 Tuple {
310 meta: Meta,
311 values: Vec<Expression>,
312 },
313}
314
315#[derive(Clone)]
316pub enum Access {
317 ComponentAccess(String),
318 ArrayAccess(Expression),
319}
320pub fn build_component_access(acc: String) -> Access {
321 Access::ComponentAccess(acc)
322}
323pub fn build_array_access(expr: Expression) -> Access {
324 Access::ArrayAccess(expr)
325}
326
327#[derive(Copy, Clone, Eq, PartialEq)]
328pub enum AssignOp {
329 AssignVar,
330 AssignSignal,
331 AssignConstraintSignal,
332}
333
334#[derive(Copy, Clone, PartialEq, Eq)]
335pub enum ExpressionInfixOpcode {
336 Mul,
337 Div,
338 Add,
339 Sub,
340 Pow,
341 IntDiv,
342 Mod,
343 ShiftL,
344 ShiftR,
345 LesserEq,
346 GreaterEq,
347 Lesser,
348 Greater,
349 Eq,
350 NotEq,
351 BoolOr,
352 BoolAnd,
353 BitOr,
354 BitAnd,
355 BitXor,
356}
357
358#[derive(Copy, Clone, PartialEq, Eq)]
359pub enum ExpressionPrefixOpcode {
360 Sub,
361 BoolNot,
362 Complement,
363}
364
365#[derive(Clone)]
366pub enum LogArgument {
367 LogStr(String),
368 LogExp(Expression),
369}
370
371pub fn build_log_string(acc: String) -> LogArgument {
372 LogArgument::LogStr(acc)
373}
374
375pub fn build_log_expression(expr: Expression) -> LogArgument {
376 LogArgument::LogExp(expr)
377}
378
379#[derive(Copy, Clone, PartialOrd, PartialEq, Ord, Eq)]
381pub enum TypeReduction {
382 Variable,
383 Component,
384 Signal,
385 Tag,
386}
387
388#[derive(Default, Clone)]
389pub struct TypeKnowledge {
390 reduces_to: Option<TypeReduction>,
391}
392impl TypeKnowledge {
393 pub fn new() -> TypeKnowledge {
394 TypeKnowledge::default()
395 }
396 pub fn set_reduces_to(&mut self, reduces_to: TypeReduction) {
397 self.reduces_to = Option::Some(reduces_to);
398 }
399 pub fn reduces_to(&self) -> TypeReduction {
400 if let Option::Some(t) = &self.reduces_to {
401 *t
402 } else {
403 panic!("Type knowledge accessed before it is initialized.");
404 }
405 }
406 pub fn is_var(&self) -> bool {
407 self.reduces_to() == TypeReduction::Variable
408 }
409 pub fn is_component(&self) -> bool {
410 self.reduces_to() == TypeReduction::Component
411 }
412 pub fn is_signal(&self) -> bool {
413 self.reduces_to() == TypeReduction::Signal
414 }
415 pub fn is_tag(&self) -> bool {
416 self.reduces_to() == TypeReduction::Tag
417 }
418}
419
420#[derive(Default, Clone)]
421pub struct MemoryKnowledge {
422 concrete_dimensions: Option<Vec<usize>>,
423 full_length: Option<usize>,
424 abstract_memory_address: Option<usize>,
425}
426impl MemoryKnowledge {
427 pub fn new() -> MemoryKnowledge {
428 MemoryKnowledge::default()
429 }
430 pub fn set_concrete_dimensions(&mut self, value: Vec<usize>) {
431 self.full_length = Option::Some(value.iter().fold(1, |p, v| p * (*v)));
432 self.concrete_dimensions = Option::Some(value);
433 }
434 pub fn set_abstract_memory_address(&mut self, value: usize) {
435 self.abstract_memory_address = Option::Some(value);
436 }
437 pub fn concrete_dimensions(&self) -> &[usize] {
438 if let Option::Some(v) = &self.concrete_dimensions {
439 v
440 } else {
441 panic!("Concrete dimensions accessed before it is initialized.");
442 }
443 }
444 pub fn full_length(&self) -> usize {
445 if let Option::Some(v) = &self.full_length {
446 *v
447 } else {
448 panic!("Full dimension accessed before it is initialized.");
449 }
450 }
451 pub fn abstract_memory_address(&self) -> usize {
452 if let Option::Some(v) = &self.abstract_memory_address {
453 *v
454 } else {
455 panic!("Abstract memory address accessed before it is initialized.");
456 }
457 }
458}