1use super::air::{Air, ExpectLevel, FunctionVariants};
2use crate::{
3 ast::{BinOp, Curve, Span, UnOp},
4 tipo::{Type, ValueConstructor, ValueConstructorVariant},
5};
6
7use itertools::Itertools;
8use std::{borrow::BorrowMut, rc::Rc, slice::Iter};
9use uplc::{builder::INNER_EXPECT_ON_LIST, builtins::DefaultFunction};
10
11#[derive(Clone, Debug, PartialEq, Copy)]
12pub enum Fields {
13 FirstField,
14 SecondField,
15 ThirdField,
16 FourthField,
17 FifthField,
18 SixthField,
19 SeventhField,
20 EighthField,
21 ArgsField(usize),
22}
23
24#[derive(Clone, Debug, PartialEq)]
25pub struct TreePath {
26 path: Vec<(usize, Fields)>,
27 set_flag: bool,
28}
29
30impl TreePath {
31 pub fn new() -> Self {
32 TreePath {
33 path: vec![],
34 set_flag: false,
35 }
36 }
37
38 pub fn was_set(&self) -> bool {
39 self.set_flag
40 }
41
42 pub fn push(&mut self, depth: usize, index: Fields) {
43 self.path.push((depth, index));
44 self.set_flag = true;
45 }
46
47 pub fn pop(&mut self) -> Option<(usize, Fields)> {
48 self.path.pop()
49 }
50
51 pub fn common_ancestor(&self, other: &Self) -> Self {
52 let mut common_ancestor = TreePath::new();
53
54 let mut self_iter = self.path.iter();
55 let mut other_iter = other.path.iter();
56
57 let mut self_next = self_iter.next();
58 let mut other_next = other_iter.next();
59
60 while self_next.is_some() && other_next.is_some() {
61 let self_next_level = self_next.unwrap();
62 let other_next_level = other_next.unwrap();
63
64 if self_next_level == other_next_level {
65 common_ancestor.push(self_next_level.0, self_next_level.1);
66 } else {
67 break;
68 }
69
70 self_next = self_iter.next();
71 other_next = other_iter.next();
72 }
73
74 common_ancestor
75 }
76}
77
78impl Default for TreePath {
79 fn default() -> Self {
80 Self::new()
81 }
82}
83
84#[derive(Clone, Debug, PartialEq)]
85pub struct IndexCounter {
86 current_index: usize,
87}
88
89impl IndexCounter {
90 pub fn new() -> Self {
91 IndexCounter { current_index: 0 }
92 }
93
94 pub fn next_number(&mut self) -> usize {
96 let current_index = self.current_index;
97 self.current_index += 1;
98 current_index
99 }
100}
101
102impl Default for IndexCounter {
103 fn default() -> Self {
104 Self::new()
105 }
106}
107
108#[derive(Debug, Clone, PartialEq)]
109pub enum AirMsg {
110 LocalVar(String),
111 Msg(String),
112}
113
114impl AirMsg {
115 pub fn to_air_tree(&self) -> AirTree {
116 match self {
117 AirMsg::LocalVar(name) => AirTree::local_var(name, Type::string()),
118 AirMsg::Msg(msg) => AirTree::string(msg),
119 }
120 }
121}
122
123#[derive(Debug, Clone, PartialEq)]
124pub enum AirTree {
125 Let {
127 name: String,
128 value: Box<AirTree>,
129 then: Box<AirTree>,
130 },
131 SoftCastLet {
132 name: String,
133 tipo: Rc<Type>,
134 value: Box<AirTree>,
135 then: Box<AirTree>,
136 otherwise: Box<AirTree>,
137 },
138 DefineFunc {
139 func_name: String,
140 module_name: String,
141 variant_name: String,
142 params: Vec<String>,
144 recursive: bool,
145 recursive_nonstatic_params: Vec<String>,
146 func_body: Box<AirTree>,
147 then: Box<AirTree>,
148 },
149 DefineCyclicFuncs {
150 func_name: String,
151 module_name: String,
152 variant_name: String,
153 contained_functions: Vec<(Vec<String>, AirTree)>,
155 then: Box<AirTree>,
156 },
157 AssertBool {
158 is_true: bool,
159 value: Box<AirTree>,
160 then: Box<AirTree>,
161 otherwise: Box<AirTree>,
162 },
163 FieldsExpose {
165 list_decorator: bool,
166 indices: Vec<(usize, String, Rc<Type>)>,
167 record: Box<AirTree>,
168 is_expect: bool,
169 then: Box<AirTree>,
170 otherwise: Box<AirTree>,
171 },
172 ListAccessor {
174 tipo: Rc<Type>,
175 names: Vec<String>,
176 tail: bool,
177 list: Box<AirTree>,
178 expect_level: ExpectLevel,
179 then: Box<AirTree>,
180 otherwise: Box<AirTree>,
181 },
182 TupleAccessor {
184 names: Vec<String>,
185 tipo: Rc<Type>,
186 tuple: Box<AirTree>,
187 is_expect: bool,
188 then: Box<AirTree>,
189 otherwise: Box<AirTree>,
190 },
191 PairAccessor {
193 fst: Option<String>,
194 snd: Option<String>,
195 tipo: Rc<Type>,
196 is_expect: bool,
197 pair: Box<AirTree>,
198 then: Box<AirTree>,
199 otherwise: Box<AirTree>,
200 },
201 ExtractField {
202 tipo: Rc<Type>,
203 arg: Box<AirTree>,
204 },
205 FieldsEmpty {
207 constr: Box<AirTree>,
208 then: Box<AirTree>,
209 otherwise: Box<AirTree>,
210 list_decorator: bool,
211 },
212 ListEmpty {
213 list: Box<AirTree>,
214 then: Box<AirTree>,
215 otherwise: Box<AirTree>,
216 },
217 NoOp {
218 then: Box<AirTree>,
219 },
220 Int {
225 value: String,
226 },
227 String {
228 value: String,
229 },
230 ByteArray {
231 bytes: Vec<u8>,
232 },
233 CurvePoint {
234 point: Curve,
235 },
236 Bool {
237 value: bool,
238 },
239 List {
240 tipo: Rc<Type>,
241 tail: bool,
242 items: Vec<AirTree>,
243 },
244 Tuple {
245 tipo: Rc<Type>,
246 items: Vec<AirTree>,
247 },
248 Pair {
249 tipo: Rc<Type>,
250 fst: Box<AirTree>,
251 snd: Box<AirTree>,
252 },
253 Void,
254 Var {
255 constructor: ValueConstructor,
256 name: String,
257 variant_name: String,
258 },
259 Call {
261 tipo: Rc<Type>,
262 func: Box<AirTree>,
263 args: Vec<AirTree>,
264 },
265
266 Fn {
267 params: Vec<String>,
268 func_body: Box<AirTree>,
269 allow_inline: bool,
270 },
271 Builtin {
272 func: DefaultFunction,
273 tipo: Rc<Type>,
274 args: Vec<AirTree>,
275 },
276 BinOp {
278 name: BinOp,
279 tipo: Rc<Type>,
280 left: Box<AirTree>,
281 right: Box<AirTree>,
282 left_tipo: Rc<Type>,
283 right_tipo: Rc<Type>,
284 },
285 UnOp {
286 op: UnOp,
287 arg: Box<AirTree>,
288 },
289
290 CastFromData {
291 tipo: Rc<Type>,
292 value: Box<AirTree>,
293 full_cast: bool,
294 },
295 CastToData {
296 tipo: Rc<Type>,
297 value: Box<AirTree>,
298 },
299
300 When {
302 tipo: Rc<Type>,
303 subject_name: String,
304 subject: Box<AirTree>,
305 subject_tipo: Rc<Type>,
306 clauses: Box<AirTree>,
307 },
308 Clause {
309 subject_tipo: Rc<Type>,
310 subject_name: String,
311 pattern: Box<AirTree>,
312 then: Box<AirTree>,
313 otherwise: Box<AirTree>,
314 },
315 ListClause {
316 subject_tipo: Rc<Type>,
317 tail_name: String,
318 next_tail_name: Option<(String, String)>,
319 then: Box<AirTree>,
320 otherwise: Box<AirTree>,
321 },
322 If {
324 tipo: Rc<Type>,
325 condition: Box<AirTree>,
326 then: Box<AirTree>,
327 otherwise: Box<AirTree>,
328 },
329 Constr {
331 tag: Option<usize>,
332 tipo: Rc<Type>,
333 args: Vec<AirTree>,
334 },
335 RecordUpdate {
336 highest_index: usize,
337 indices: Vec<(usize, Rc<Type>)>,
338 tipo: Rc<Type>,
339 record: Box<AirTree>,
340 args: Vec<AirTree>,
341 },
342 ErrorTerm {
344 tipo: Rc<Type>,
345 validator: bool,
346 },
347 Trace {
348 tipo: Rc<Type>,
349 msg: Box<AirTree>,
350 then: Box<AirTree>,
351 },
352}
353
354impl AirTree {
355 pub fn is_error(&self) -> bool {
356 matches!(self, AirTree::ErrorTerm { .. })
357 }
358
359 pub fn int(value: impl ToString) -> AirTree {
360 AirTree::Int {
361 value: value.to_string(),
362 }
363 }
364
365 pub fn string(value: impl ToString) -> AirTree {
366 AirTree::String {
367 value: value.to_string(),
368 }
369 }
370
371 pub fn byte_array(bytes: Vec<u8>) -> AirTree {
372 AirTree::ByteArray { bytes }
373 }
374
375 pub fn curve(point: Curve) -> AirTree {
376 AirTree::CurvePoint { point }
377 }
378
379 pub fn bool(value: bool) -> AirTree {
380 AirTree::Bool { value }
381 }
382
383 pub fn list(mut items: Vec<AirTree>, tipo: Rc<Type>, tail: Option<AirTree>) -> AirTree {
384 if let Some(tail) = tail {
385 items.push(tail);
386
387 AirTree::List {
388 tipo,
389 tail: true,
390 items,
391 }
392 } else {
393 AirTree::List {
394 tipo,
395 tail: false,
396 items,
397 }
398 }
399 }
400
401 pub fn tuple(items: Vec<AirTree>, tipo: Rc<Type>) -> AirTree {
402 AirTree::Tuple { tipo, items }
403 }
404
405 pub fn pair(fst: AirTree, snd: AirTree, tipo: Rc<Type>) -> AirTree {
406 AirTree::Pair {
407 tipo,
408 fst: fst.into(),
409 snd: snd.into(),
410 }
411 }
412
413 pub fn void() -> AirTree {
414 AirTree::Void
415 }
416
417 pub fn var(
418 constructor: ValueConstructor,
419 name: impl ToString,
420 variant_name: impl ToString,
421 ) -> AirTree {
422 AirTree::Var {
423 constructor,
424 name: name.to_string(),
425 variant_name: variant_name.to_string(),
426 }
427 }
428
429 pub fn local_var(name: impl ToString, tipo: Rc<Type>) -> AirTree {
430 AirTree::Var {
431 constructor: ValueConstructor::public(
432 tipo,
433 ValueConstructorVariant::LocalVariable {
434 location: Span::empty(),
435 },
436 ),
437 name: name.to_string(),
438 variant_name: "".to_string(),
439 }
440 }
441
442 pub fn call(func: AirTree, tipo: Rc<Type>, args: Vec<AirTree>) -> AirTree {
443 AirTree::Call {
444 tipo,
445 func: func.into(),
446 args,
447 }
448 }
449
450 #[allow(clippy::too_many_arguments)]
451 pub fn define_func(
452 func_name: impl ToString,
453 module_name: impl ToString,
454 variant_name: impl ToString,
455 params: Vec<String>,
456 recursive: bool,
457 recursive_nonstatic_params: Vec<String>,
458 func_body: AirTree,
459 then: AirTree,
460 ) -> AirTree {
461 AirTree::DefineFunc {
462 func_name: func_name.to_string(),
463 module_name: module_name.to_string(),
464 params,
465 recursive,
466 recursive_nonstatic_params,
467
468 variant_name: variant_name.to_string(),
469 func_body: func_body.into(),
470 then: then.into(),
471 }
472 }
473
474 pub fn define_cyclic_func(
475 func_name: impl ToString,
476 module_name: impl ToString,
477 variant_name: impl ToString,
478 contained_functions: Vec<(Vec<String>, AirTree)>,
479 then: AirTree,
480 ) -> AirTree {
481 AirTree::DefineCyclicFuncs {
482 func_name: func_name.to_string(),
483 module_name: module_name.to_string(),
484 variant_name: variant_name.to_string(),
485 contained_functions,
486 then: then.into(),
487 }
488 }
489
490 pub fn anon_func(params: Vec<String>, func_body: AirTree, allow_inline: bool) -> AirTree {
491 AirTree::Fn {
492 params,
493 func_body: func_body.into(),
494 allow_inline,
495 }
496 }
497
498 pub fn builtin(func: DefaultFunction, tipo: Rc<Type>, args: Vec<AirTree>) -> AirTree {
499 AirTree::Builtin { func, tipo, args }
500 }
501
502 pub fn binop(
503 op: BinOp,
504 tipo: Rc<Type>,
505 left: AirTree,
506 right: AirTree,
507 left_tipo: Rc<Type>,
508 right_tipo: Rc<Type>,
509 ) -> AirTree {
510 AirTree::BinOp {
511 name: op,
512 tipo,
513 left: left.into(),
514 right: right.into(),
515 left_tipo,
516 right_tipo,
517 }
518 }
519
520 pub fn unop(op: UnOp, arg: AirTree) -> AirTree {
521 AirTree::UnOp {
522 op,
523 arg: arg.into(),
524 }
525 }
526
527 pub fn let_assignment(name: impl ToString, value: AirTree, then: AirTree) -> AirTree {
528 AirTree::Let {
529 name: name.to_string(),
530 value: value.into(),
531 then: then.into(),
532 }
533 }
534
535 pub fn soft_cast_assignment(
536 name: impl ToString,
537 tipo: Rc<Type>,
538 value: AirTree,
539 then: AirTree,
540 otherwise: AirTree,
541 ) -> AirTree {
542 AirTree::SoftCastLet {
543 name: name.to_string(),
544 tipo,
545 value: value.into(),
546 then: then.into(),
547 otherwise: otherwise.into(),
548 }
549 }
550
551 pub fn cast_from_data(value: AirTree, tipo: Rc<Type>, full_cast: bool) -> AirTree {
552 AirTree::CastFromData {
553 tipo,
554 value: value.into(),
555 full_cast,
556 }
557 }
558
559 pub fn cast_to_data(value: AirTree, tipo: Rc<Type>) -> AirTree {
560 AirTree::CastToData {
561 tipo,
562 value: value.into(),
563 }
564 }
565
566 pub fn assert_bool(
567 is_true: bool,
568 value: AirTree,
569 then: AirTree,
570 otherwise: AirTree,
571 ) -> AirTree {
572 AirTree::AssertBool {
573 is_true,
574 value: value.into(),
575 then: then.into(),
576 otherwise: otherwise.into(),
577 }
578 }
579
580 pub fn when(
581 subject_name: impl ToString,
582 tipo: Rc<Type>,
583 subject_tipo: Rc<Type>,
584 subject: AirTree,
585 clauses: AirTree,
586 ) -> AirTree {
587 AirTree::When {
588 tipo,
589 subject_name: subject_name.to_string(),
590 subject: subject.into(),
591 subject_tipo,
592 clauses: clauses.into(),
593 }
594 }
595
596 pub fn clause(
597 subject_name: impl ToString,
598 pattern: AirTree,
599 subject_tipo: Rc<Type>,
600 then: AirTree,
601 otherwise: AirTree,
602 ) -> AirTree {
603 AirTree::Clause {
604 subject_tipo,
605 subject_name: subject_name.to_string(),
606 pattern: pattern.into(),
607 then: then.into(),
608 otherwise: otherwise.into(),
609 }
610 }
611
612 pub fn list_clause(
613 tail_name: impl ToString,
614 subject_tipo: Rc<Type>,
615 then: AirTree,
616 otherwise: AirTree,
617 next_tail_name: Option<(String, String)>,
618 ) -> AirTree {
619 AirTree::ListClause {
620 subject_tipo,
621 tail_name: tail_name.to_string(),
622 next_tail_name,
623 then: then.into(),
624 otherwise: otherwise.into(),
625 }
626 }
627
628 pub fn if_branch(
629 tipo: Rc<Type>,
630 condition: AirTree,
631 branch: AirTree,
632 otherwise: AirTree,
633 ) -> AirTree {
634 AirTree::If {
635 tipo,
636 condition: condition.into(),
637 then: branch.into(),
638 otherwise: otherwise.into(),
639 }
640 }
641
642 pub fn create_constr(tag: Option<usize>, tipo: Rc<Type>, args: Vec<AirTree>) -> AirTree {
643 AirTree::Constr { tag, tipo, args }
644 }
645
646 pub fn record_update(
647 indices: Vec<(usize, Rc<Type>)>,
648 highest_index: usize,
649 tipo: Rc<Type>,
650 record: AirTree,
651 args: Vec<AirTree>,
652 ) -> AirTree {
653 AirTree::RecordUpdate {
654 highest_index,
655 indices,
656 tipo,
657 record: record.into(),
658 args,
659 }
660 }
661
662 pub fn index_access(function_name: String, tipo: Rc<Type>, list_of_fields: AirTree) -> AirTree {
663 AirTree::cast_from_data(
664 AirTree::call(
665 AirTree::var(
666 ValueConstructor::public(
667 Type::Fn {
668 args: vec![Type::list(Type::data())],
669 ret: Type::data(),
670 alias: None,
671 }
672 .into(),
673 ValueConstructorVariant::ModuleFn {
674 name: function_name.clone(),
675 field_map: None,
676 module: "".to_string(),
677 arity: 1,
678 location: Span::empty(),
679 builtin: None,
680 },
681 ),
682 function_name,
683 "",
684 ),
685 Type::data(),
686 vec![list_of_fields],
687 ),
688 tipo.clone(),
689 false,
690 )
691 }
692
693 pub fn fields_expose(
694 indices: Vec<(usize, String, Rc<Type>)>,
695 record: AirTree,
696 is_expect: bool,
697 then: AirTree,
698 otherwise: AirTree,
699 list_decorator: bool,
700 ) -> AirTree {
701 AirTree::FieldsExpose {
702 indices,
703 record: record.into(),
704 is_expect,
705 then: then.into(),
706 otherwise: otherwise.into(),
707 list_decorator,
708 }
709 }
710
711 pub fn list_access(
712 names: Vec<String>,
713 tipo: Rc<Type>,
714 tail: bool,
715 list: AirTree,
716
717 expect_level: ExpectLevel,
718 then: AirTree,
719 otherwise: AirTree,
720 ) -> AirTree {
721 AirTree::ListAccessor {
722 tipo,
723 names,
724 tail,
725 list: list.into(),
726 expect_level,
727 then: then.into(),
728 otherwise: otherwise.into(),
729 }
730 }
731
732 pub fn tuple_access(
733 names: Vec<String>,
734 tipo: Rc<Type>,
735 tuple: AirTree,
736 is_expect: bool,
737 then: AirTree,
738 otherwise: AirTree,
739 ) -> AirTree {
740 AirTree::TupleAccessor {
741 names,
742 tipo,
743 tuple: tuple.into(),
744 is_expect,
745 then: then.into(),
746 otherwise: otherwise.into(),
747 }
748 }
749
750 pub fn pair_access(
751 fst: Option<String>,
752 snd: Option<String>,
753 tipo: Rc<Type>,
754 pair: AirTree,
755 is_expect: bool,
756 then: AirTree,
757 otherwise: AirTree,
758 ) -> AirTree {
759 AirTree::PairAccessor {
760 fst,
761 snd,
762 tipo,
763 is_expect,
764 pair: pair.into(),
765 then: then.into(),
766 otherwise: otherwise.into(),
767 }
768 }
769
770 pub fn extract_field(tipo: Rc<Type>, arg: AirTree) -> AirTree {
771 AirTree::ExtractField {
772 tipo,
773 arg: arg.into(),
774 }
775 }
776
777 pub fn pair_index(index: usize, tipo: Rc<Type>, tuple: AirTree) -> AirTree {
778 AirTree::cast_from_data(
779 AirTree::builtin(
780 if index == 0 {
781 DefaultFunction::FstPair
782 } else {
783 DefaultFunction::SndPair
784 },
785 Type::data(),
786 vec![tuple],
787 ),
788 tipo.clone(),
789 false,
790 )
791 }
792
793 pub fn error(tipo: Rc<Type>, validator: bool) -> AirTree {
794 AirTree::ErrorTerm { tipo, validator }
795 }
796
797 pub fn trace(msg: AirTree, tipo: Rc<Type>, then: AirTree) -> AirTree {
798 AirTree::Trace {
799 tipo,
800 msg: msg.into(),
801 then: then.into(),
802 }
803 }
804 pub fn no_op(then: AirTree) -> AirTree {
805 AirTree::NoOp { then: then.into() }
806 }
807
808 pub fn fields_empty(
809 constr: AirTree,
810 then: AirTree,
811 otherwise: AirTree,
812 list_decorator: bool,
813 ) -> AirTree {
814 AirTree::FieldsEmpty {
815 constr: constr.into(),
816 then: then.into(),
817 otherwise: otherwise.into(),
818 list_decorator,
819 }
820 }
821
822 pub fn list_empty(list: AirTree, then: AirTree, otherwise: AirTree) -> AirTree {
823 AirTree::ListEmpty {
824 list: list.into(),
825
826 then: then.into(),
827 otherwise: otherwise.into(),
828 }
829 }
830
831 pub fn expect_on_list2() -> AirTree {
832 let inner_expect_on_list = AirTree::local_var(INNER_EXPECT_ON_LIST, Type::void());
833
834 let list_var = AirTree::local_var("__list_to_check", Type::list(Type::data()));
835
836 AirTree::let_assignment(
837 INNER_EXPECT_ON_LIST,
838 AirTree::anon_func(
839 vec![
840 INNER_EXPECT_ON_LIST.to_string(),
841 "__list_to_check".to_string(),
842 ],
843 AirTree::call(
844 AirTree::local_var("__check_with", Type::void()),
845 Type::void(),
846 vec![
847 list_var.clone(),
848 AirTree::call(
849 inner_expect_on_list.clone(),
850 Type::void(),
851 vec![inner_expect_on_list.clone()],
852 ),
853 ],
854 ),
855 false,
856 ),
857 AirTree::call(
858 inner_expect_on_list.clone(),
859 Type::void(),
860 vec![inner_expect_on_list, list_var],
861 ),
862 )
863 }
864
865 pub fn to_vec(&self) -> Vec<Air> {
866 let mut air_vec = vec![];
867 self.create_air_vec(&mut air_vec);
868 air_vec
869 }
870
871 fn create_air_vec(&self, air_vec: &mut Vec<Air>) {
872 match self {
873 AirTree::Let { name, value, then } => {
874 air_vec.push(Air::Let { name: name.clone() });
875 value.create_air_vec(air_vec);
876 then.create_air_vec(air_vec);
877 }
878 AirTree::SoftCastLet {
879 name,
880 tipo,
881 value,
882 then,
883 otherwise,
884 } => {
885 air_vec.push(Air::SoftCastLet {
886 name: name.clone(),
887 tipo: tipo.clone(),
888 });
889 value.create_air_vec(air_vec);
890 then.create_air_vec(air_vec);
891 otherwise.create_air_vec(air_vec);
892 }
893 AirTree::DefineFunc {
894 func_name,
895 module_name,
896 params,
897 recursive,
898 recursive_nonstatic_params,
899 variant_name,
900 func_body,
901 then,
902 } => {
903 let variant = if *recursive {
904 FunctionVariants::Recursive {
905 params: params.clone(),
906 recursive_nonstatic_params: recursive_nonstatic_params.clone(),
907 }
908 } else {
909 assert_eq!(params, recursive_nonstatic_params);
910 FunctionVariants::Standard(params.clone())
911 };
912
913 air_vec.push(Air::DefineFunc {
914 func_name: func_name.clone(),
915 module_name: module_name.clone(),
916 variant_name: variant_name.clone(),
917 variant,
918 });
919 func_body.create_air_vec(air_vec);
920 then.create_air_vec(air_vec);
921 }
922 AirTree::DefineCyclicFuncs {
923 func_name,
924 module_name,
925 variant_name,
926 contained_functions,
927 then,
928 } => {
929 let variant = FunctionVariants::Cyclic(
930 contained_functions
931 .iter()
932 .map(|(params, _)| params.clone())
933 .collect_vec(),
934 );
935
936 air_vec.push(Air::DefineFunc {
937 func_name: func_name.clone(),
938 module_name: module_name.clone(),
939 variant_name: variant_name.clone(),
940 variant,
941 });
942
943 for (_, func_body) in contained_functions {
944 func_body.create_air_vec(air_vec);
945 }
946 then.create_air_vec(air_vec);
947 }
948 AirTree::AssertBool {
949 is_true,
950 value,
951 then,
952 otherwise,
953 } => {
954 air_vec.push(Air::AssertBool { is_true: *is_true });
955
956 value.create_air_vec(air_vec);
957 then.create_air_vec(air_vec);
958 otherwise.create_air_vec(air_vec);
959 }
960 AirTree::FieldsExpose {
961 indices,
962 record,
963 is_expect,
964 then,
965 otherwise,
966 list_decorator,
967 } => {
968 air_vec.push(Air::FieldsExpose {
969 indices: indices.clone(),
970 is_expect: *is_expect,
971 list_decorator: *list_decorator,
972 });
973
974 record.create_air_vec(air_vec);
975 then.create_air_vec(air_vec);
976 if *is_expect {
977 otherwise.create_air_vec(air_vec);
978 }
979 }
980 AirTree::ListAccessor {
981 tipo,
982 names,
983 tail,
984 list,
985 expect_level,
986 then,
987 otherwise,
988 } => {
989 air_vec.push(Air::ListAccessor {
990 tipo: tipo.clone(),
991 names: names.clone(),
992 tail: *tail,
993 expect_level: *expect_level,
994 });
995
996 list.create_air_vec(air_vec);
997 then.create_air_vec(air_vec);
998 if matches!(expect_level, ExpectLevel::Full | ExpectLevel::Items) {
999 otherwise.create_air_vec(air_vec);
1000 }
1001 }
1002 AirTree::TupleAccessor {
1003 names,
1004 tipo,
1005 tuple,
1006 is_expect,
1007 then,
1008 otherwise,
1009 } => {
1010 air_vec.push(Air::TupleAccessor {
1011 names: names.clone(),
1012 tipo: tipo.clone(),
1013 is_expect: *is_expect,
1014 });
1015
1016 tuple.create_air_vec(air_vec);
1017 then.create_air_vec(air_vec);
1018 if *is_expect {
1019 otherwise.create_air_vec(air_vec);
1020 }
1021 }
1022 AirTree::PairAccessor {
1023 fst,
1024 snd,
1025 tipo,
1026 is_expect,
1027 pair,
1028 then,
1029 otherwise,
1030 } => {
1031 air_vec.push(Air::PairAccessor {
1032 fst: fst.clone(),
1033 snd: snd.clone(),
1034 tipo: tipo.clone(),
1035 is_expect: *is_expect,
1036 });
1037
1038 pair.create_air_vec(air_vec);
1039 then.create_air_vec(air_vec);
1040 if *is_expect {
1041 otherwise.create_air_vec(air_vec);
1042 }
1043 }
1044 AirTree::FieldsEmpty {
1045 constr,
1046 then,
1047 otherwise,
1048 list_decorator,
1049 } => {
1050 air_vec.push(Air::FieldsEmpty {
1051 list_decorator: *list_decorator,
1052 });
1053
1054 constr.create_air_vec(air_vec);
1055 then.create_air_vec(air_vec);
1056 otherwise.create_air_vec(air_vec);
1057 }
1058 AirTree::ListEmpty {
1059 list,
1060 then,
1061 otherwise,
1062 } => {
1063 air_vec.push(Air::ListEmpty);
1064
1065 list.create_air_vec(air_vec);
1066 then.create_air_vec(air_vec);
1067 otherwise.create_air_vec(air_vec);
1068 }
1069 AirTree::NoOp { then } => {
1070 air_vec.push(Air::NoOp);
1071 then.create_air_vec(air_vec);
1072 }
1073 AirTree::Int { value } => air_vec.push(Air::Int {
1074 value: value.clone(),
1075 }),
1076
1077 AirTree::String { value } => air_vec.push(Air::String {
1078 value: value.clone(),
1079 }),
1080 AirTree::ByteArray { bytes } => air_vec.push(Air::ByteArray {
1081 bytes: bytes.clone(),
1082 }),
1083 AirTree::CurvePoint { point } => air_vec.push(Air::CurvePoint { point: *point }),
1084 AirTree::Bool { value } => air_vec.push(Air::Bool { value: *value }),
1085 AirTree::List { tipo, tail, items } => {
1086 air_vec.push(Air::List {
1087 count: items.len(),
1088 tipo: tipo.clone(),
1089 tail: *tail,
1090 });
1091 for item in items {
1092 item.create_air_vec(air_vec);
1093 }
1094 }
1095 AirTree::Tuple { tipo, items } => {
1096 air_vec.push(Air::Tuple {
1097 tipo: tipo.clone(),
1098 count: items.len(),
1099 });
1100 for item in items {
1101 item.create_air_vec(air_vec);
1102 }
1103 }
1104 AirTree::Pair { tipo, fst, snd } => {
1105 air_vec.push(Air::Pair { tipo: tipo.clone() });
1106 fst.create_air_vec(air_vec);
1107 snd.create_air_vec(air_vec);
1108 }
1109 AirTree::Void => air_vec.push(Air::Void),
1110 AirTree::Var {
1111 constructor,
1112 name,
1113 variant_name,
1114 } => air_vec.push(Air::Var {
1115 constructor: constructor.clone(),
1116 name: name.clone(),
1117 variant_name: variant_name.clone(),
1118 }),
1119 AirTree::Call { tipo, func, args } => {
1120 air_vec.push(Air::Call {
1121 count: args.len(),
1122 tipo: tipo.clone(),
1123 });
1124 func.create_air_vec(air_vec);
1125 for arg in args {
1126 arg.create_air_vec(air_vec);
1127 }
1128 }
1129 AirTree::Fn {
1130 params,
1131 func_body,
1132 allow_inline,
1133 } => {
1134 air_vec.push(Air::Fn {
1135 params: params.clone(),
1136 allow_inline: *allow_inline,
1137 });
1138 func_body.create_air_vec(air_vec);
1139 }
1140 AirTree::Builtin { func, tipo, args } => {
1141 air_vec.push(Air::Builtin {
1142 count: args.len(),
1143 func: *func,
1144 tipo: tipo.clone(),
1145 });
1146
1147 for arg in args {
1148 arg.create_air_vec(air_vec);
1149 }
1150 }
1151 AirTree::BinOp {
1152 name,
1153 tipo,
1154 left,
1155 right,
1156 left_tipo,
1157 right_tipo,
1158 } => {
1159 air_vec.push(Air::BinOp {
1160 name: *name,
1161 tipo: tipo.clone(),
1162 left_tipo: left_tipo.clone(),
1163 right_tipo: right_tipo.clone(),
1164 });
1165 left.create_air_vec(air_vec);
1166 right.create_air_vec(air_vec);
1167 }
1168 AirTree::UnOp { op, arg } => {
1169 air_vec.push(Air::UnOp { op: *op });
1170 arg.create_air_vec(air_vec);
1171 }
1172 AirTree::CastFromData {
1173 tipo,
1174 value,
1175 full_cast,
1176 } => {
1177 air_vec.push(Air::CastFromData {
1178 tipo: tipo.clone(),
1179 full_cast: *full_cast,
1180 });
1181
1182 value.create_air_vec(air_vec);
1183 }
1184 AirTree::CastToData { tipo, value } => {
1185 air_vec.push(Air::CastToData { tipo: tipo.clone() });
1186 value.create_air_vec(air_vec);
1187 }
1188 AirTree::When {
1189 tipo,
1190 subject_name,
1191 subject,
1192 subject_tipo,
1193 clauses,
1194 } => {
1195 air_vec.push(Air::When {
1196 tipo: tipo.clone(),
1197 subject_name: subject_name.clone(),
1198 subject_tipo: subject_tipo.clone(),
1199 });
1200 subject.create_air_vec(air_vec);
1201 clauses.create_air_vec(air_vec);
1202 }
1203 AirTree::Clause {
1204 subject_tipo,
1205 subject_name,
1206 pattern,
1207 then,
1208 otherwise,
1209 } => {
1210 air_vec.push(Air::Clause {
1211 subject_tipo: subject_tipo.clone(),
1212 subject_name: subject_name.clone(),
1213 });
1214 pattern.create_air_vec(air_vec);
1215 then.create_air_vec(air_vec);
1216 otherwise.create_air_vec(air_vec);
1217 }
1218 AirTree::ListClause {
1219 subject_tipo,
1220 tail_name,
1221 next_tail_name,
1222
1223 then,
1224 otherwise,
1225 } => {
1226 air_vec.push(Air::ListClause {
1227 subject_tipo: subject_tipo.clone(),
1228 tail_name: tail_name.clone(),
1229 next_tail_name: next_tail_name.clone(),
1230 });
1231 then.create_air_vec(air_vec);
1232 otherwise.create_air_vec(air_vec);
1233 }
1234 AirTree::If {
1235 tipo,
1236 condition: pattern,
1237 then,
1238 otherwise,
1239 } => {
1240 air_vec.push(Air::If { tipo: tipo.clone() });
1241 pattern.create_air_vec(air_vec);
1242 then.create_air_vec(air_vec);
1243 otherwise.create_air_vec(air_vec);
1244 }
1245 AirTree::Constr { tag, tipo, args } => {
1246 air_vec.push(Air::Constr {
1247 tag: *tag,
1248 tipo: tipo.clone(),
1249 count: args.len(),
1250 });
1251 for arg in args {
1252 arg.create_air_vec(air_vec);
1253 }
1254 }
1255 AirTree::RecordUpdate {
1256 highest_index,
1257 indices,
1258 tipo,
1259 record,
1260 args,
1261 } => {
1262 air_vec.push(Air::RecordUpdate {
1263 highest_index: *highest_index,
1264 indices: indices.clone(),
1265 tipo: tipo.clone(),
1266 });
1267 record.create_air_vec(air_vec);
1268 for arg in args {
1269 arg.create_air_vec(air_vec);
1270 }
1271 }
1272 AirTree::ErrorTerm { tipo, validator } => air_vec.push(Air::ErrorTerm {
1273 tipo: tipo.clone(),
1274 validator: *validator,
1275 }),
1276 AirTree::Trace { tipo, msg, then } => {
1277 air_vec.push(Air::Trace { tipo: tipo.clone() });
1278 msg.create_air_vec(air_vec);
1279 then.create_air_vec(air_vec);
1280 }
1281 AirTree::ExtractField {
1282 tipo,
1283 arg: args_list,
1284 } => {
1285 air_vec.push(Air::ExtractField { tipo: tipo.clone() });
1286 args_list.create_air_vec(air_vec);
1287 }
1288 }
1289 }
1290
1291 pub fn return_type(&self) -> Rc<Type> {
1292 match self {
1293 AirTree::Int { .. } => Type::int(),
1294 AirTree::String { .. } => Type::string(),
1295 AirTree::ByteArray { .. } => Type::byte_array(),
1296 AirTree::Bool { .. } => Type::bool(),
1297 AirTree::CurvePoint { point } => point.tipo(),
1298 AirTree::List { tipo, .. }
1299 | AirTree::Tuple { tipo, .. }
1300 | AirTree::Pair { tipo, .. }
1301 | AirTree::Call { tipo, .. }
1302 | AirTree::Builtin { tipo, .. }
1303 | AirTree::ExtractField { tipo, .. }
1304 | AirTree::BinOp { tipo, .. }
1305 | AirTree::CastFromData { tipo, .. }
1306 | AirTree::When { tipo, .. }
1307 | AirTree::If { tipo, .. }
1308 | AirTree::Constr { tipo, .. }
1309 | AirTree::RecordUpdate { tipo, .. }
1310 | AirTree::ErrorTerm { tipo, .. }
1311 | AirTree::Trace { tipo, .. } => tipo.clone(),
1312 AirTree::Void => Type::void(),
1313 AirTree::Var { constructor, .. } => constructor.tipo.clone(),
1314 AirTree::Fn { func_body, .. } => func_body.return_type(),
1315 AirTree::UnOp { op, .. } => match op {
1316 UnOp::Not => Type::bool(),
1317 UnOp::Negate => Type::int(),
1318 },
1319 AirTree::CastToData { .. } => Type::data(),
1320 AirTree::Clause { then, .. }
1321 | AirTree::ListClause { then, .. }
1322 | AirTree::Let { then, .. }
1323 | AirTree::SoftCastLet { then, .. }
1324 | AirTree::DefineFunc { then, .. }
1325 | AirTree::DefineCyclicFuncs { then, .. }
1326 | AirTree::AssertBool { then, .. }
1327 | AirTree::FieldsExpose { then, .. }
1328 | AirTree::ListAccessor { then, .. }
1329 | AirTree::TupleAccessor { then, .. }
1330 | AirTree::PairAccessor { then, .. }
1331 | AirTree::FieldsEmpty { then, .. }
1332 | AirTree::ListEmpty { then, .. }
1333 | AirTree::NoOp { then } => then.return_type(),
1334 }
1335 }
1336
1337 pub fn mut_held_types(&mut self) -> Vec<&mut Rc<Type>> {
1338 match self {
1339 AirTree::Clause { subject_tipo, .. } | AirTree::ListClause { subject_tipo, .. } => {
1340 vec![subject_tipo]
1341 }
1342
1343 AirTree::ListAccessor { tipo, .. }
1344 | AirTree::TupleAccessor { tipo, .. }
1345 | AirTree::PairAccessor { tipo, .. }
1346 | AirTree::List { tipo, .. }
1347 | AirTree::Tuple { tipo, .. }
1348 | AirTree::Call { tipo, .. }
1349 | AirTree::Builtin { tipo, .. }
1350 | AirTree::ExtractField { tipo, .. }
1351 | AirTree::CastFromData { tipo, .. }
1352 | AirTree::CastToData { tipo, .. }
1353 | AirTree::If { tipo, .. }
1354 | AirTree::Constr { tipo, .. }
1355 | AirTree::ErrorTerm { tipo, .. }
1356 | AirTree::Trace { tipo, .. }
1357 | AirTree::Pair { tipo, .. }
1358 | AirTree::SoftCastLet { tipo, .. } => vec![tipo],
1359
1360 AirTree::FieldsExpose { indices, .. } => {
1361 let mut types = vec![];
1362 for (_, _, tipo) in indices {
1363 types.push(tipo);
1364 }
1365 types
1366 }
1367
1368 AirTree::Var { constructor, .. } => {
1369 vec![constructor.tipo.borrow_mut()]
1370 }
1371 AirTree::BinOp {
1372 tipo,
1373 left_tipo,
1374 right_tipo,
1375 ..
1376 } => {
1377 vec![tipo, left_tipo, right_tipo]
1378 }
1379 AirTree::When {
1380 tipo, subject_tipo, ..
1381 } => vec![tipo, subject_tipo],
1382
1383 AirTree::RecordUpdate { tipo, indices, .. } => {
1384 let mut types = vec![tipo];
1385 for (_, tipo) in indices {
1386 types.push(tipo);
1387 }
1388 types
1389 }
1390 AirTree::Let { .. }
1391 | AirTree::DefineFunc { .. }
1392 | AirTree::DefineCyclicFuncs { .. }
1393 | AirTree::AssertBool { .. }
1394 | AirTree::FieldsEmpty { .. }
1395 | AirTree::ListEmpty { .. }
1396 | AirTree::NoOp { .. }
1397 | AirTree::Int { .. }
1398 | AirTree::String { .. }
1399 | AirTree::ByteArray { .. }
1400 | AirTree::CurvePoint { .. }
1401 | AirTree::Bool { .. }
1402 | AirTree::Void
1403 | AirTree::Fn { .. }
1404 | AirTree::UnOp { .. } => vec![],
1405 }
1406 }
1407
1408 pub fn traverse_tree_with(&mut self, with: &mut impl FnMut(&mut AirTree, &TreePath)) {
1409 let mut tree_path = TreePath::new();
1410 self.do_traverse_tree_with(&mut tree_path, 0, Fields::FirstField, with);
1411 }
1412
1413 pub fn traverse_tree_with_path(
1414 &mut self,
1415 path: &mut TreePath,
1416 current_depth: usize,
1417 depth_index: Fields,
1418 with: &mut impl FnMut(&mut AirTree, &TreePath),
1419 ) {
1420 self.do_traverse_tree_with(path, current_depth, depth_index, with);
1421 }
1422
1423 fn do_traverse_tree_with(
1424 &mut self,
1425 tree_path: &mut TreePath,
1426 current_depth: usize,
1427 field_index: Fields,
1428 with: &mut impl FnMut(&mut AirTree, &TreePath),
1429 ) {
1430 tree_path.push(current_depth, field_index);
1431
1432 match self {
1435 AirTree::Let {
1436 name: _,
1437 value,
1438 then: _,
1439 } => {
1440 value.do_traverse_tree_with(
1441 tree_path,
1442 current_depth + 1,
1443 Fields::SecondField,
1444 with,
1445 );
1446 }
1447
1448 AirTree::SoftCastLet {
1449 name: _,
1450 tipo: _,
1451 value,
1452 then: _,
1453 otherwise,
1454 } => {
1455 value.do_traverse_tree_with(tree_path, current_depth + 1, Fields::ThirdField, with);
1456
1457 otherwise.do_traverse_tree_with(
1458 tree_path,
1459 current_depth + 1,
1460 Fields::FifthField,
1461 with,
1462 );
1463 }
1464
1465 AirTree::AssertBool {
1466 is_true: _,
1467 value,
1468 then: _,
1469 otherwise,
1470 } => {
1471 value.do_traverse_tree_with(
1472 tree_path,
1473 current_depth + 1,
1474 Fields::SecondField,
1475 with,
1476 );
1477 otherwise.do_traverse_tree_with(
1478 tree_path,
1479 current_depth + 1,
1480 Fields::FourthField,
1481 with,
1482 )
1483 }
1484 AirTree::FieldsExpose {
1485 indices: _,
1486 record,
1487 is_expect: _,
1488 then: _,
1489 otherwise,
1490 list_decorator: _,
1491 } => {
1492 record.do_traverse_tree_with(
1493 tree_path,
1494 current_depth + 1,
1495 Fields::SecondField,
1496 with,
1497 );
1498 otherwise.do_traverse_tree_with(
1499 tree_path,
1500 current_depth + 1,
1501 Fields::FifthField,
1502 with,
1503 )
1504 }
1505 AirTree::ListAccessor {
1506 tipo: _,
1507 names: _,
1508 tail: _,
1509 list,
1510 expect_level: _,
1511 then: _,
1512 otherwise,
1513 } => {
1514 list.do_traverse_tree_with(tree_path, current_depth + 1, Fields::FourthField, with);
1515 otherwise.do_traverse_tree_with(
1516 tree_path,
1517 current_depth + 1,
1518 Fields::SeventhField,
1519 with,
1520 )
1521 }
1522 AirTree::TupleAccessor {
1523 names: _,
1524 tipo: _,
1525 tuple,
1526 is_expect: _,
1527 then: _,
1528 otherwise,
1529 } => {
1530 tuple.do_traverse_tree_with(tree_path, current_depth + 1, Fields::ThirdField, with);
1531 otherwise.do_traverse_tree_with(
1532 tree_path,
1533 current_depth + 1,
1534 Fields::SixthField,
1535 with,
1536 )
1537 }
1538 AirTree::PairAccessor {
1539 fst: _,
1540 snd: _,
1541 tipo: _,
1542 is_expect: _,
1543 pair,
1544 then: _,
1545 otherwise,
1546 } => {
1547 pair.do_traverse_tree_with(tree_path, current_depth + 1, Fields::FifthField, with);
1548 otherwise.do_traverse_tree_with(
1549 tree_path,
1550 current_depth + 1,
1551 Fields::SeventhField,
1552 with,
1553 )
1554 }
1555 AirTree::FieldsEmpty {
1556 constr,
1557 then: _,
1558 otherwise,
1559 list_decorator: _,
1560 } => {
1561 constr.do_traverse_tree_with(
1562 tree_path,
1563 current_depth + 1,
1564 Fields::FirstField,
1565 with,
1566 );
1567
1568 otherwise.do_traverse_tree_with(
1569 tree_path,
1570 current_depth + 1,
1571 Fields::ThirdField,
1572 with,
1573 );
1574 }
1575 AirTree::ListEmpty {
1576 list,
1577 then: _,
1578 otherwise,
1579 } => {
1580 list.do_traverse_tree_with(tree_path, current_depth + 1, Fields::FirstField, with);
1581 otherwise.do_traverse_tree_with(
1582 tree_path,
1583 current_depth + 1,
1584 Fields::ThirdField,
1585 with,
1586 )
1587 }
1588
1589 AirTree::When {
1590 tipo: _,
1591 subject_name: _,
1592 subject,
1593 subject_tipo: _,
1594 clauses: _,
1595 } => subject.do_traverse_tree_with(
1596 tree_path,
1597 current_depth + 1,
1598 Fields::ThirdField,
1599 with,
1600 ),
1601 AirTree::DefineFunc { .. }
1602 | AirTree::DefineCyclicFuncs { .. }
1603 | AirTree::NoOp { .. }
1604 | AirTree::Int { .. }
1605 | AirTree::String { .. }
1606 | AirTree::ByteArray { .. }
1607 | AirTree::CurvePoint { .. }
1608 | AirTree::Bool { .. }
1609 | AirTree::List { .. }
1610 | AirTree::Tuple { .. }
1611 | AirTree::Pair { .. }
1612 | AirTree::Void
1613 | AirTree::Var { .. }
1614 | AirTree::Call { .. }
1615 | AirTree::Fn { .. }
1616 | AirTree::Builtin { .. }
1617 | AirTree::BinOp { .. }
1618 | AirTree::UnOp { .. }
1619 | AirTree::CastFromData { .. }
1620 | AirTree::CastToData { .. }
1621 | AirTree::Clause { .. }
1622 | AirTree::ListClause { .. }
1623 | AirTree::If { .. }
1624 | AirTree::Constr { .. }
1625 | AirTree::RecordUpdate { .. }
1626 | AirTree::ErrorTerm { .. }
1627 | AirTree::Trace { .. }
1628 | AirTree::ExtractField { .. } => {}
1629 }
1630
1631 match self {
1632 AirTree::NoOp { then } => {
1633 then.do_traverse_tree_with(tree_path, current_depth + 1, Fields::FirstField, with);
1634 }
1635 AirTree::When {
1636 tipo: _,
1637 subject_name: _,
1638 subject: _,
1639 subject_tipo: _,
1640 clauses,
1641 } => {
1642 clauses.do_traverse_tree_with(
1643 tree_path,
1644 current_depth + 1,
1645 Fields::FifthField,
1646 with,
1647 );
1648 }
1649 AirTree::List {
1650 tipo: _,
1651 tail: _,
1652 items,
1653 } => {
1654 for (index, item) in items.iter_mut().enumerate() {
1655 item.do_traverse_tree_with(
1656 tree_path,
1657 current_depth + 1,
1658 Fields::ArgsField(index),
1659 with,
1660 );
1661 }
1662 }
1663 AirTree::Tuple { tipo: _, items } => {
1664 for (index, item) in items.iter_mut().enumerate() {
1665 item.do_traverse_tree_with(
1666 tree_path,
1667 current_depth + 1,
1668 Fields::ArgsField(index),
1669 with,
1670 );
1671 }
1672 }
1673 AirTree::Pair { tipo: _, fst, snd } => {
1674 fst.do_traverse_tree_with(tree_path, current_depth + 1, Fields::SecondField, with);
1675
1676 snd.do_traverse_tree_with(tree_path, current_depth + 1, Fields::ThirdField, with);
1677 }
1678 AirTree::Call {
1679 tipo: _,
1680 func,
1681 args,
1682 } => {
1683 func.do_traverse_tree_with(tree_path, current_depth + 1, Fields::SecondField, with);
1684
1685 for (index, arg) in args.iter_mut().enumerate() {
1686 arg.do_traverse_tree_with(
1687 tree_path,
1688 current_depth + 1,
1689 Fields::ArgsField(index),
1690 with,
1691 );
1692 }
1693 }
1694 AirTree::Fn {
1695 params: _,
1696 func_body,
1697 allow_inline: _,
1698 } => {
1699 func_body.do_traverse_tree_with(
1700 tree_path,
1701 current_depth + 1,
1702 Fields::SecondField,
1703 with,
1704 );
1705 }
1706 AirTree::Builtin {
1707 func: _,
1708 tipo: _,
1709 args,
1710 } => {
1711 for (index, arg) in args.iter_mut().enumerate() {
1712 arg.do_traverse_tree_with(
1713 tree_path,
1714 current_depth + 1,
1715 Fields::ArgsField(index),
1716 with,
1717 );
1718 }
1719 }
1720 AirTree::ExtractField { tipo: _, arg } => {
1721 arg.do_traverse_tree_with(tree_path, current_depth + 1, Fields::SecondField, with);
1722 }
1723 AirTree::BinOp {
1724 name: _,
1725 tipo: _,
1726 left,
1727 right,
1728 left_tipo: _,
1729 right_tipo: _,
1730 } => {
1731 left.do_traverse_tree_with(tree_path, current_depth + 1, Fields::ThirdField, with);
1732
1733 right.do_traverse_tree_with(
1734 tree_path,
1735 current_depth + 1,
1736 Fields::FourthField,
1737 with,
1738 );
1739 }
1740 AirTree::UnOp { op: _, arg } => {
1741 arg.do_traverse_tree_with(tree_path, current_depth + 1, Fields::SecondField, with);
1742 }
1743 AirTree::CastFromData {
1744 tipo: _,
1745 value,
1746 full_cast: _,
1747 } => {
1748 value.do_traverse_tree_with(
1749 tree_path,
1750 current_depth + 1,
1751 Fields::SecondField,
1752 with,
1753 );
1754 }
1755 AirTree::CastToData { tipo: _, value } => {
1756 value.do_traverse_tree_with(
1757 tree_path,
1758 current_depth + 1,
1759 Fields::SecondField,
1760 with,
1761 );
1762 }
1763
1764 AirTree::Clause {
1765 subject_tipo: _,
1766 subject_name: _,
1767 pattern,
1768 then,
1769 otherwise,
1770 } => {
1771 pattern.do_traverse_tree_with(
1772 tree_path,
1773 current_depth + 1,
1774 Fields::ThirdField,
1775 with,
1776 );
1777
1778 then.do_traverse_tree_with(tree_path, current_depth + 1, Fields::FourthField, with);
1779
1780 otherwise.do_traverse_tree_with(
1781 tree_path,
1782 current_depth + 1,
1783 Fields::FifthField,
1784 with,
1785 );
1786 }
1787 AirTree::ListClause {
1788 subject_tipo: _,
1789 tail_name: _,
1790 next_tail_name: _,
1791 then,
1792 otherwise,
1793 } => {
1794 then.do_traverse_tree_with(tree_path, current_depth + 1, Fields::FourthField, with);
1795
1796 otherwise.do_traverse_tree_with(
1797 tree_path,
1798 current_depth + 1,
1799 Fields::FifthField,
1800 with,
1801 );
1802 }
1803 AirTree::If {
1804 tipo: _,
1805 condition: pattern,
1806 then,
1807 otherwise,
1808 } => {
1809 pattern.do_traverse_tree_with(
1810 tree_path,
1811 current_depth + 1,
1812 Fields::SecondField,
1813 with,
1814 );
1815
1816 then.do_traverse_tree_with(tree_path, current_depth + 1, Fields::ThirdField, with);
1817
1818 otherwise.do_traverse_tree_with(
1819 tree_path,
1820 current_depth + 1,
1821 Fields::FourthField,
1822 with,
1823 );
1824 }
1825 AirTree::Constr {
1826 tag: _,
1827 tipo: _,
1828 args,
1829 } => {
1830 for (index, arg) in args.iter_mut().enumerate() {
1831 arg.do_traverse_tree_with(
1832 tree_path,
1833 current_depth + 1,
1834 Fields::ArgsField(index),
1835 with,
1836 );
1837 }
1838 }
1839 AirTree::RecordUpdate {
1840 highest_index: _,
1841 indices: _,
1842 tipo: _,
1843 record,
1844 args,
1845 } => {
1846 record.do_traverse_tree_with(
1847 tree_path,
1848 current_depth + 1,
1849 Fields::FourthField,
1850 with,
1851 );
1852
1853 for (index, arg) in args.iter_mut().enumerate() {
1854 arg.do_traverse_tree_with(
1855 tree_path,
1856 current_depth + 1,
1857 Fields::ArgsField(index),
1858 with,
1859 );
1860 }
1861 }
1862 AirTree::Trace { tipo: _, msg, then } => {
1863 msg.do_traverse_tree_with(tree_path, current_depth + 1, Fields::SecondField, with);
1864
1865 then.do_traverse_tree_with(tree_path, current_depth + 1, Fields::ThirdField, with);
1866 }
1867 AirTree::DefineFunc {
1868 func_name: _,
1869 module_name: _,
1870 params: _,
1871 recursive: _,
1872 recursive_nonstatic_params: _,
1873 variant_name: _,
1874 func_body,
1875 then,
1876 } => {
1877 func_body.do_traverse_tree_with(
1878 tree_path,
1879 current_depth + 1,
1880 Fields::SeventhField,
1881 with,
1882 );
1883 then.do_traverse_tree_with(tree_path, current_depth + 1, Fields::EighthField, with)
1884 }
1885 AirTree::DefineCyclicFuncs {
1886 func_name: _,
1887 module_name: _,
1888 variant_name: _,
1889 contained_functions,
1890 then,
1891 } => {
1892 for (index, (_, func_body)) in contained_functions.iter_mut().enumerate() {
1893 func_body.do_traverse_tree_with(
1894 tree_path,
1895 current_depth + 1,
1896 Fields::ArgsField(index),
1897 with,
1898 );
1899 }
1900 then.do_traverse_tree_with(tree_path, current_depth + 1, Fields::FifthField, with);
1901 }
1902 AirTree::Int { .. }
1903 | AirTree::String { .. }
1904 | AirTree::ByteArray { .. }
1905 | AirTree::CurvePoint { .. }
1906 | AirTree::Bool { .. }
1907 | AirTree::Void
1908 | AirTree::Var { .. }
1909 | AirTree::ErrorTerm { .. } => {}
1910 AirTree::Let {
1911 name: _,
1912 value: _,
1913 then,
1914 } => {
1915 then.do_traverse_tree_with(tree_path, current_depth + 1, Fields::ThirdField, with);
1916 }
1917 AirTree::SoftCastLet {
1918 name: _,
1919 tipo: _,
1920 value: _,
1921 then,
1922 otherwise: _,
1923 } => {
1924 then.do_traverse_tree_with(tree_path, current_depth + 1, Fields::FourthField, with);
1925 }
1926 AirTree::AssertBool {
1927 is_true: _,
1928 value: _,
1929 then,
1930 otherwise: _,
1931 } => {
1932 then.do_traverse_tree_with(tree_path, current_depth + 1, Fields::ThirdField, with);
1933 }
1934 AirTree::FieldsExpose {
1935 indices: _,
1936 record: _,
1937 is_expect: _,
1938 then,
1939 otherwise: _,
1940 list_decorator: _,
1941 } => {
1942 then.do_traverse_tree_with(tree_path, current_depth + 1, Fields::FourthField, with);
1943 }
1944 AirTree::ListAccessor {
1945 tipo: _,
1946 names: _,
1947 tail: _,
1948 list: _,
1949 expect_level: _,
1950 then,
1951 otherwise: _,
1952 } => {
1953 then.do_traverse_tree_with(tree_path, current_depth + 1, Fields::SixthField, with);
1954 }
1955 AirTree::TupleAccessor {
1956 names: _,
1957 tipo: _,
1958 tuple: _,
1959 is_expect: _,
1960 then,
1961 otherwise: _,
1962 } => {
1963 then.do_traverse_tree_with(tree_path, current_depth + 1, Fields::FifthField, with);
1964 }
1965 AirTree::PairAccessor {
1966 fst: _,
1967 snd: _,
1968 tipo: _,
1969 is_expect: _,
1970 pair: _,
1971 then,
1972 otherwise: _,
1973 } => {
1974 then.do_traverse_tree_with(tree_path, current_depth + 1, Fields::SixthField, with);
1975 }
1976 AirTree::FieldsEmpty {
1977 constr: _,
1978 then,
1979 otherwise: _,
1980 list_decorator: _,
1981 } => {
1982 then.do_traverse_tree_with(tree_path, current_depth + 1, Fields::SecondField, with);
1983 }
1984 AirTree::ListEmpty {
1985 list: _,
1986 then,
1987 otherwise: _,
1988 } => {
1989 then.do_traverse_tree_with(tree_path, current_depth + 1, Fields::SecondField, with);
1990 }
1991 }
1992
1993 with(self, tree_path);
1994
1995 tree_path.pop();
1996 }
1997
1998 pub fn find_air_tree_node<'a>(&'a mut self, tree_path: &TreePath) -> &'a mut AirTree {
2000 let mut path_iter = tree_path.path.iter();
2001 path_iter.next();
2002 self.do_find_air_tree_node(&mut path_iter)
2003 }
2004
2005 fn do_find_air_tree_node<'a>(
2006 &'a mut self,
2007 tree_path_iter: &mut Iter<(usize, Fields)>,
2008 ) -> &'a mut AirTree {
2009 if let AirTree::DefineFunc { then, .. } | AirTree::DefineCyclicFuncs { then, .. } = self {
2011 then.as_mut().do_find_air_tree_node(tree_path_iter)
2012 } else if let Some((_depth, field)) = tree_path_iter.next() {
2013 match self {
2014 AirTree::Let {
2015 name: _,
2016 value,
2017 then,
2018 } => match field {
2019 Fields::SecondField => value.as_mut().do_find_air_tree_node(tree_path_iter),
2020 Fields::ThirdField => then.as_mut().do_find_air_tree_node(tree_path_iter),
2021 _ => panic!("Tree Path index outside tree children nodes"),
2022 },
2023 AirTree::SoftCastLet {
2024 name: _,
2025 tipo: _,
2026 value,
2027 then,
2028 otherwise,
2029 } => match field {
2030 Fields::ThirdField => value.as_mut().do_find_air_tree_node(tree_path_iter),
2031 Fields::FourthField => then.as_mut().do_find_air_tree_node(tree_path_iter),
2032 Fields::FifthField => otherwise.as_mut().do_find_air_tree_node(tree_path_iter),
2033 _ => panic!("Tree Path index outside tree children nodes"),
2034 },
2035 AirTree::AssertBool {
2036 is_true: _,
2037 value,
2038 then,
2039 otherwise,
2040 } => match field {
2041 Fields::SecondField => value.as_mut().do_find_air_tree_node(tree_path_iter),
2042 Fields::ThirdField => then.as_mut().do_find_air_tree_node(tree_path_iter),
2043 Fields::FourthField => otherwise.as_mut().do_find_air_tree_node(tree_path_iter),
2044 _ => panic!("Tree Path index outside tree children nodes"),
2045 },
2046 AirTree::FieldsExpose {
2047 indices: _,
2048 record,
2049 is_expect: _,
2050 then,
2051 otherwise,
2052 list_decorator: _,
2053 } => match field {
2054 Fields::SecondField => record.as_mut().do_find_air_tree_node(tree_path_iter),
2055 Fields::FourthField => then.as_mut().do_find_air_tree_node(tree_path_iter),
2056 Fields::FifthField => otherwise.as_mut().do_find_air_tree_node(tree_path_iter),
2057 _ => panic!("Tree Path index outside tree children nodes"),
2058 },
2059 AirTree::ListAccessor {
2060 tipo: _,
2061 names: _,
2062 tail: _,
2063 list,
2064 expect_level: _,
2065 then,
2066 otherwise,
2067 } => match field {
2068 Fields::FourthField => list.as_mut().do_find_air_tree_node(tree_path_iter),
2069 Fields::SixthField => then.as_mut().do_find_air_tree_node(tree_path_iter),
2070 Fields::SeventhField => {
2071 otherwise.as_mut().do_find_air_tree_node(tree_path_iter)
2072 }
2073 _ => panic!("Tree Path index outside tree children nodes"),
2074 },
2075 AirTree::TupleAccessor {
2076 names: _,
2077 tipo: _,
2078 tuple,
2079 is_expect: _,
2080 then,
2081 otherwise,
2082 } => match field {
2083 Fields::ThirdField => tuple.as_mut().do_find_air_tree_node(tree_path_iter),
2084 Fields::FifthField => then.as_mut().do_find_air_tree_node(tree_path_iter),
2085 Fields::SixthField => otherwise.as_mut().do_find_air_tree_node(tree_path_iter),
2086 _ => panic!("Tree Path index outside tree children nodes"),
2087 },
2088 AirTree::PairAccessor {
2089 fst: _,
2090 snd: _,
2091 tipo: _,
2092 is_expect: _,
2093 pair,
2094 then,
2095 otherwise,
2096 } => match field {
2097 Fields::FifthField => pair.as_mut().do_find_air_tree_node(tree_path_iter),
2098 Fields::SixthField => then.as_mut().do_find_air_tree_node(tree_path_iter),
2099 Fields::SeventhField => {
2100 otherwise.as_mut().do_find_air_tree_node(tree_path_iter)
2101 }
2102 _ => panic!("Tree Path index outside tree children nodes"),
2103 },
2104 AirTree::NoOp { then } => match field {
2105 Fields::FirstField => then.as_mut().do_find_air_tree_node(tree_path_iter),
2106 _ => panic!("Tree Path index outside tree children nodes"),
2107 },
2108 AirTree::DefineFunc { .. } | AirTree::DefineCyclicFuncs { .. } => unreachable!(),
2109 AirTree::FieldsEmpty {
2110 constr,
2111 then,
2112 otherwise,
2113 list_decorator: _,
2114 } => match field {
2115 Fields::FirstField => constr.as_mut().do_find_air_tree_node(tree_path_iter),
2116 Fields::SecondField => then.as_mut().do_find_air_tree_node(tree_path_iter),
2117 Fields::ThirdField => otherwise.as_mut().do_find_air_tree_node(tree_path_iter),
2118 _ => panic!("Tree Path index outside tree children nodes"),
2119 },
2120 AirTree::ListEmpty {
2121 list,
2122 then,
2123 otherwise,
2124 } => match field {
2125 Fields::FirstField => list.as_mut().do_find_air_tree_node(tree_path_iter),
2126 Fields::SecondField => then.as_mut().do_find_air_tree_node(tree_path_iter),
2127 Fields::ThirdField => otherwise.as_mut().do_find_air_tree_node(tree_path_iter),
2128 _ => panic!("Tree Path index outside tree children nodes"),
2129 },
2130 AirTree::List { items, .. }
2131 | AirTree::Tuple { items, .. }
2132 | AirTree::Builtin { args: items, .. }
2133 | AirTree::Constr { args: items, .. } => match field {
2134 Fields::ArgsField(index) => items
2135 .get_mut(*index)
2136 .expect("Tree Path index outside tree children nodes")
2137 .do_find_air_tree_node(tree_path_iter),
2138 _ => panic!("Tree Path index outside tree children nodes"),
2139 },
2140 AirTree::ExtractField { tipo: _, arg } => match field {
2141 Fields::SecondField => arg.as_mut().do_find_air_tree_node(tree_path_iter),
2142 _ => panic!("Tree Path index outside tree children nodes"),
2143 },
2144 AirTree::Pair { tipo: _, fst, snd } => match field {
2145 Fields::SecondField => fst.as_mut().do_find_air_tree_node(tree_path_iter),
2146 Fields::ThirdField => snd.as_mut().do_find_air_tree_node(tree_path_iter),
2147 _ => panic!("Tree Path index outside tree children nodes"),
2148 },
2149 AirTree::Call {
2150 tipo: _,
2151 func,
2152 args,
2153 } => match field {
2154 Fields::SecondField => func.as_mut().do_find_air_tree_node(tree_path_iter),
2155 Fields::ArgsField(index) => args
2156 .get_mut(*index)
2157 .expect("Tree Path index outside tree children nodes")
2158 .do_find_air_tree_node(tree_path_iter),
2159 _ => panic!("Tree Path index outside tree children nodes"),
2160 },
2161 AirTree::Fn {
2162 params: _,
2163 func_body,
2164 allow_inline: _,
2165 } => match field {
2166 Fields::SecondField => func_body.as_mut().do_find_air_tree_node(tree_path_iter),
2167 _ => panic!("Tree Path index outside tree children nodes"),
2168 },
2169 AirTree::BinOp {
2170 name: _,
2171 tipo: _,
2172 left,
2173 right,
2174 left_tipo: _,
2175 right_tipo: _,
2176 } => match field {
2177 Fields::ThirdField => left.as_mut().do_find_air_tree_node(tree_path_iter),
2178 Fields::FourthField => right.as_mut().do_find_air_tree_node(tree_path_iter),
2179 _ => panic!("Tree Path index outside tree children nodes"),
2180 },
2181 AirTree::UnOp { op: _, arg } => match field {
2182 Fields::SecondField => arg.as_mut().do_find_air_tree_node(tree_path_iter),
2183 _ => panic!("Tree Path index outside tree children nodes"),
2184 },
2185 AirTree::CastFromData {
2186 tipo: _,
2187 value,
2188 full_cast: _,
2189 } => match field {
2190 Fields::SecondField => value.as_mut().do_find_air_tree_node(tree_path_iter),
2191 _ => panic!("Tree Path index outside tree children nodes"),
2192 },
2193 AirTree::CastToData { tipo: _, value } => match field {
2194 Fields::SecondField => value.as_mut().do_find_air_tree_node(tree_path_iter),
2195 _ => panic!("Tree Path index outside tree children nodes"),
2196 },
2197 AirTree::When {
2198 tipo: _,
2199 subject_name: _,
2200 subject,
2201 subject_tipo: _,
2202 clauses,
2203 } => match field {
2204 Fields::ThirdField => subject.as_mut().do_find_air_tree_node(tree_path_iter),
2205 Fields::FifthField => clauses.as_mut().do_find_air_tree_node(tree_path_iter),
2206 _ => panic!("Tree Path index outside tree children nodes"),
2207 },
2208 AirTree::Clause {
2209 subject_tipo: _,
2210 subject_name: _,
2211 pattern,
2212 then,
2213 otherwise,
2214 } => match field {
2215 Fields::ThirdField => pattern.as_mut().do_find_air_tree_node(tree_path_iter),
2216 Fields::FourthField => then.as_mut().do_find_air_tree_node(tree_path_iter),
2217 Fields::FifthField => otherwise.as_mut().do_find_air_tree_node(tree_path_iter),
2218 _ => panic!("Tree Path index outside tree children nodes"),
2219 },
2220 AirTree::ListClause {
2221 subject_tipo: _,
2222 tail_name: _,
2223 next_tail_name: _,
2224 then,
2225 otherwise,
2226 } => match field {
2227 Fields::FourthField => then.as_mut().do_find_air_tree_node(tree_path_iter),
2228 Fields::FifthField => otherwise.as_mut().do_find_air_tree_node(tree_path_iter),
2229 _ => panic!("Tree Path index outside tree children nodes"),
2230 },
2231 AirTree::If {
2232 tipo: _,
2233 condition: pattern,
2234 then,
2235 otherwise,
2236 } => match field {
2237 Fields::SecondField => pattern.as_mut().do_find_air_tree_node(tree_path_iter),
2238 Fields::ThirdField => then.as_mut().do_find_air_tree_node(tree_path_iter),
2239 Fields::FourthField => otherwise.as_mut().do_find_air_tree_node(tree_path_iter),
2240 _ => panic!("Tree Path index outside tree children nodes"),
2241 },
2242 AirTree::RecordUpdate {
2243 highest_index: _,
2244 indices: _,
2245 tipo: _,
2246 record,
2247 args,
2248 } => match field {
2249 Fields::FourthField => record.as_mut().do_find_air_tree_node(tree_path_iter),
2250 Fields::ArgsField(index) => args
2251 .get_mut(*index)
2252 .expect("Tree Path index outside tree children nodes")
2253 .do_find_air_tree_node(tree_path_iter),
2254 _ => panic!("Tree Path index outside tree children nodes"),
2255 },
2256 AirTree::Trace { tipo: _, msg, then } => match field {
2257 Fields::SecondField => msg.as_mut().do_find_air_tree_node(tree_path_iter),
2258 Fields::ThirdField => then.as_mut().do_find_air_tree_node(tree_path_iter),
2259 _ => panic!("Tree Path index outside tree children nodes"),
2260 },
2261 AirTree::Int { .. }
2262 | AirTree::String { .. }
2263 | AirTree::ByteArray { .. }
2264 | AirTree::CurvePoint { .. }
2265 | AirTree::Bool { .. }
2266 | AirTree::Void
2267 | AirTree::Var { .. }
2268 | AirTree::ErrorTerm { .. } => {
2269 panic!("A tree node with no children was encountered with a longer tree path.")
2270 }
2271 }
2272 } else {
2273 self
2274 }
2275 }
2276}