Skip to main content

aiken_lang/gen_uplc/
tree.rs

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    /// Returns the next of this [`IndexCounter`].
95    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    // Statements
126    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 and other parts of a function
143        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        // params and body
154        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    // Field Access
164    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    // List Access
173    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    // Tuple Access
183    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    // Pair Access
192    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    // Misc.
206    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    // End Statements
221
222    // Expressions
223    // Primitives
224    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    // Functions
260    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    // Operators
277    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
301    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
323    If {
324        tipo: Rc<Type>,
325        condition: Box<AirTree>,
326        then: Box<AirTree>,
327        otherwise: Box<AirTree>,
328    },
329    // Record Creation
330    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    // Misc.
343    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        // TODO: Merge together the 2 match statements
1433
1434        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    /// Used in function hoisting to find the exact node to hoist over
1999    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        // For finding the air node we skip over the define func ops since those are added later on.
2010        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}