Skip to main content

leo_ast/passes/
reconstructor.rs

1// Copyright (C) 2019-2026 Provable Inc.
2// This file is part of the Leo library.
3
4// The Leo library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// The Leo library is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
16
17//! This module contains a Reconstructor trait for the AST.
18//! It implements default methods for each node to be made
19//! given the information of the old node.
20
21use crate::*;
22
23/// A Reconstructor trait for types in the AST.
24pub trait AstReconstructor {
25    type AdditionalOutput: Default;
26    type AdditionalInput: Default;
27
28    fn interner(&self) -> &TypeInterner;
29
30    /* Types */
31    fn reconstruct_type(&mut self, input: TypeKind) -> (TypeKind, Self::AdditionalOutput) {
32        match input {
33            TypeKind::Array(array_type) => self.reconstruct_array_type(array_type),
34            TypeKind::Composite(composite_type) => self.reconstruct_composite_type(composite_type),
35            TypeKind::Future(future_type) => self.reconstruct_future_type(future_type),
36            TypeKind::Mapping(mapping_type) => self.reconstruct_mapping_type(mapping_type),
37            TypeKind::Optional(optional_type) => self.reconstruct_optional_type(optional_type),
38            TypeKind::Tuple(tuple_type) => self.reconstruct_tuple_type(tuple_type),
39            TypeKind::Vector(vector_type) => self.reconstruct_vector_type(vector_type),
40            TypeKind::Address
41            | TypeKind::Boolean
42            | TypeKind::Field
43            | TypeKind::Group
44            | TypeKind::Ident(_)
45            | TypeKind::Integer(_)
46            | TypeKind::Identifier
47            | TypeKind::DynRecord
48            | TypeKind::Scalar
49            | TypeKind::Signature
50            | TypeKind::String
51            | TypeKind::Numeric
52            | TypeKind::Unit
53            | TypeKind::Err => (input.clone(), Default::default()),
54        }
55    }
56
57    /// Re-interns after `reconstruct_type` so the cached canonical handle stays consistent
58    /// with `kind` — overrides that only touch `kind` inherit that guarantee for free.
59    fn reconstruct_type_node(&mut self, input: TypeNode) -> (TypeNode, Self::AdditionalOutput) {
60        let (kind, span, _) = input.into_parts();
61        let (new_kind, additional) = self.reconstruct_type(kind);
62        (TypeNode::new(self.interner(), new_kind, span), additional)
63    }
64
65    fn reconstruct_array_type(&mut self, input: ArrayType) -> (TypeKind, Self::AdditionalOutput) {
66        (
67            TypeKind::Array(ArrayType {
68                element_type: Box::new(self.reconstruct_type(*input.element_type).0),
69                length: Box::new(self.reconstruct_expression(*input.length, &Default::default()).0),
70            }),
71            Default::default(),
72        )
73    }
74
75    fn reconstruct_composite_type(&mut self, input: CompositeType) -> (TypeKind, Self::AdditionalOutput) {
76        (
77            TypeKind::Composite(CompositeType {
78                const_arguments: input
79                    .const_arguments
80                    .into_iter()
81                    .map(|arg| self.reconstruct_expression(arg, &Default::default()).0)
82                    .collect(),
83                ..input
84            }),
85            Default::default(),
86        )
87    }
88
89    fn reconstruct_future_type(&mut self, input: FutureType) -> (TypeKind, Self::AdditionalOutput) {
90        (
91            TypeKind::Future(FutureType {
92                inputs: input.inputs.into_iter().map(|input| self.reconstruct_type(input).0).collect(),
93                ..input
94            }),
95            Default::default(),
96        )
97    }
98
99    fn reconstruct_mapping_type(&mut self, input: MappingType) -> (TypeKind, Self::AdditionalOutput) {
100        (
101            TypeKind::Mapping(MappingType {
102                key: Box::new(self.reconstruct_type(*input.key).0),
103                value: Box::new(self.reconstruct_type(*input.value).0),
104            }),
105            Default::default(),
106        )
107    }
108
109    fn reconstruct_optional_type(&mut self, input: OptionalType) -> (TypeKind, Self::AdditionalOutput) {
110        (
111            TypeKind::Optional(OptionalType { inner: Box::new(self.reconstruct_type(*input.inner).0) }),
112            Default::default(),
113        )
114    }
115
116    fn reconstruct_tuple_type(&mut self, input: TupleType) -> (TypeKind, Self::AdditionalOutput) {
117        (
118            TypeKind::Tuple(TupleType {
119                elements: input.elements.into_iter().map(|element| self.reconstruct_type(element).0).collect(),
120            }),
121            Default::default(),
122        )
123    }
124
125    fn reconstruct_vector_type(&mut self, input: VectorType) -> (TypeKind, Self::AdditionalOutput) {
126        (
127            TypeKind::Vector(VectorType { element_type: Box::new(self.reconstruct_type(*input.element_type).0) }),
128            Default::default(),
129        )
130    }
131
132    /* Expressions */
133    fn reconstruct_expression(
134        &mut self,
135        input: Expression,
136        additional: &Self::AdditionalInput,
137    ) -> (Expression, Self::AdditionalOutput) {
138        match input {
139            Expression::Async(async_) => self.reconstruct_async(async_, additional),
140            Expression::Array(array) => self.reconstruct_array(array, additional),
141            Expression::ArrayAccess(access) => self.reconstruct_array_access(*access, additional),
142            Expression::Binary(binary) => self.reconstruct_binary(*binary, additional),
143            Expression::Call(call) => self.reconstruct_call(*call, additional),
144            Expression::DynamicOp(op) => self.reconstruct_dynamic_op(*op, additional),
145            Expression::Cast(cast) => self.reconstruct_cast(*cast, additional),
146            Expression::Composite(composite_) => self.reconstruct_composite_init(composite_, additional),
147            Expression::Err(err) => self.reconstruct_err(err, additional),
148            Expression::Path(path) => self.reconstruct_path(path, additional),
149            Expression::Literal(value) => self.reconstruct_literal(value, additional),
150            Expression::MemberAccess(access) => self.reconstruct_member_access(*access, additional),
151            Expression::Repeat(repeat) => self.reconstruct_repeat(*repeat, additional),
152            Expression::Ternary(ternary) => self.reconstruct_ternary(*ternary, additional),
153            Expression::Tuple(tuple) => self.reconstruct_tuple(tuple, additional),
154            Expression::TupleAccess(access) => self.reconstruct_tuple_access(*access, additional),
155            Expression::Unary(unary) => self.reconstruct_unary(*unary, additional),
156            Expression::Unit(unit) => self.reconstruct_unit(unit, additional),
157            Expression::Intrinsic(intr) => self.reconstruct_intrinsic(*intr, additional),
158        }
159    }
160
161    fn reconstruct_array_access(
162        &mut self,
163        input: ArrayAccess,
164        _additional: &Self::AdditionalInput,
165    ) -> (Expression, Self::AdditionalOutput) {
166        (
167            ArrayAccess {
168                array: self.reconstruct_expression(input.array, &Default::default()).0,
169                index: self.reconstruct_expression(input.index, &Default::default()).0,
170                ..input
171            }
172            .into(),
173            Default::default(),
174        )
175    }
176
177    fn reconstruct_async(
178        &mut self,
179        input: AsyncExpression,
180        _additional: &Self::AdditionalInput,
181    ) -> (Expression, Self::AdditionalOutput) {
182        (AsyncExpression { block: self.reconstruct_block(input.block).0, ..input }.into(), Default::default())
183    }
184
185    fn reconstruct_member_access(
186        &mut self,
187        input: MemberAccess,
188        _additional: &Self::AdditionalInput,
189    ) -> (Expression, Self::AdditionalOutput) {
190        (
191            MemberAccess { inner: self.reconstruct_expression(input.inner, &Default::default()).0, ..input }.into(),
192            Default::default(),
193        )
194    }
195
196    fn reconstruct_repeat(
197        &mut self,
198        input: RepeatExpression,
199        _additional: &Self::AdditionalInput,
200    ) -> (Expression, Self::AdditionalOutput) {
201        (
202            RepeatExpression {
203                expr: self.reconstruct_expression(input.expr, &Default::default()).0,
204                count: self.reconstruct_expression(input.count, &Default::default()).0,
205                ..input
206            }
207            .into(),
208            Default::default(),
209        )
210    }
211
212    fn reconstruct_intrinsic(
213        &mut self,
214        mut input: IntrinsicExpression,
215        _additional: &Self::AdditionalInput,
216    ) -> (Expression, Self::AdditionalOutput) {
217        input.type_parameters =
218            input.type_parameters.into_iter().map(|(ty, span)| (self.reconstruct_type(ty).0, span)).collect();
219        // `input_types` and `return_types` are derived from `type_parameters` at parse time and
220        // must be reconstructed independently so that composite type paths are resolved.
221        input.input_types =
222            input.input_types.into_iter().map(|(mode, ty, span)| (mode, self.reconstruct_type(ty).0, span)).collect();
223        input.return_types =
224            input.return_types.into_iter().map(|(mode, ty, span)| (mode, self.reconstruct_type(ty).0, span)).collect();
225        input.arguments =
226            input.arguments.into_iter().map(|arg| self.reconstruct_expression(arg, &Default::default()).0).collect();
227        (input.into(), Default::default())
228    }
229
230    fn reconstruct_tuple_access(
231        &mut self,
232        input: TupleAccess,
233        _additional: &Self::AdditionalInput,
234    ) -> (Expression, Self::AdditionalOutput) {
235        (
236            TupleAccess { tuple: self.reconstruct_expression(input.tuple, &Default::default()).0, ..input }.into(),
237            Default::default(),
238        )
239    }
240
241    fn reconstruct_array(
242        &mut self,
243        input: ArrayExpression,
244        _additional: &Self::AdditionalInput,
245    ) -> (Expression, Self::AdditionalOutput) {
246        (
247            ArrayExpression {
248                elements: input
249                    .elements
250                    .into_iter()
251                    .map(|element| self.reconstruct_expression(element, &Default::default()).0)
252                    .collect(),
253                ..input
254            }
255            .into(),
256            Default::default(),
257        )
258    }
259
260    fn reconstruct_binary(
261        &mut self,
262        input: BinaryExpression,
263        _additional: &Self::AdditionalInput,
264    ) -> (Expression, Self::AdditionalOutput) {
265        (
266            BinaryExpression {
267                left: self.reconstruct_expression(input.left, &Default::default()).0,
268                right: self.reconstruct_expression(input.right, &Default::default()).0,
269                ..input
270            }
271            .into(),
272            Default::default(),
273        )
274    }
275
276    fn reconstruct_call(
277        &mut self,
278        input: CallExpression,
279        _additional: &Self::AdditionalInput,
280    ) -> (Expression, Self::AdditionalOutput) {
281        (
282            CallExpression {
283                const_arguments: input
284                    .const_arguments
285                    .into_iter()
286                    .map(|arg| self.reconstruct_expression(arg, &Default::default()).0)
287                    .collect(),
288                arguments: input
289                    .arguments
290                    .into_iter()
291                    .map(|arg| self.reconstruct_expression(arg, &Default::default()).0)
292                    .collect(),
293                ..input
294            }
295            .into(),
296            Default::default(),
297        )
298    }
299
300    fn reconstruct_dynamic_op(
301        &mut self,
302        input: DynamicOpExpression,
303        _additional: &Self::AdditionalInput,
304    ) -> (Expression, Self::AdditionalOutput) {
305        let interface = self.reconstruct_type(input.interface).0;
306        let target_program = self.reconstruct_expression(input.target_program, &Default::default()).0;
307        let network = input.network.map(|n| self.reconstruct_expression(n, &Default::default()).0);
308        let kind = match input.kind {
309            DynamicOpKind::Call { function, arguments } => DynamicOpKind::Call {
310                function,
311                arguments: arguments
312                    .into_iter()
313                    .map(|arg| self.reconstruct_expression(arg, &Default::default()).0)
314                    .collect(),
315            },
316            DynamicOpKind::Read { storage } => DynamicOpKind::Read { storage },
317            DynamicOpKind::Op { member, op, arguments } => DynamicOpKind::Op {
318                member,
319                op,
320                arguments: arguments
321                    .into_iter()
322                    .map(|arg| self.reconstruct_expression(arg, &Default::default()).0)
323                    .collect(),
324            },
325        };
326        (
327            DynamicOpExpression { interface, target_program, network, kind, span: input.span, id: input.id }.into(),
328            Default::default(),
329        )
330    }
331
332    fn reconstruct_cast(
333        &mut self,
334        input: CastExpression,
335        _additional: &Self::AdditionalInput,
336    ) -> (Expression, Self::AdditionalOutput) {
337        (
338            CastExpression {
339                expression: self.reconstruct_expression(input.expression, &Default::default()).0,
340                ..input
341            }
342            .into(),
343            Default::default(),
344        )
345    }
346
347    fn reconstruct_composite_init(
348        &mut self,
349        input: CompositeExpression,
350        _additional: &Self::AdditionalInput,
351    ) -> (Expression, Self::AdditionalOutput) {
352        (
353            CompositeExpression {
354                const_arguments: input
355                    .const_arguments
356                    .into_iter()
357                    .map(|arg| self.reconstruct_expression(arg, &Default::default()).0)
358                    .collect(),
359                members: input
360                    .members
361                    .into_iter()
362                    .map(|member| CompositeFieldInitializer {
363                        identifier: member.identifier,
364                        expression: member
365                            .expression
366                            .map(|expr| self.reconstruct_expression(expr, &Default::default()).0),
367                        span: member.span,
368                        id: member.id,
369                    })
370                    .collect(),
371                base: input.base.map(|base| Box::new(self.reconstruct_expression(*base, &Default::default()).0)),
372                ..input
373            }
374            .into(),
375            Default::default(),
376        )
377    }
378
379    fn reconstruct_err(
380        &mut self,
381        _input: ErrExpression,
382        _additional: &Self::AdditionalInput,
383    ) -> (Expression, Self::AdditionalOutput) {
384        panic!("`ErrExpression`s should not be in the AST at this phase of compilation.")
385    }
386
387    fn reconstruct_path(
388        &mut self,
389        input: Path,
390        _additional: &Self::AdditionalInput,
391    ) -> (Expression, Self::AdditionalOutput) {
392        (input.into(), Default::default())
393    }
394
395    fn reconstruct_literal(
396        &mut self,
397        input: Literal,
398        _additional: &Self::AdditionalInput,
399    ) -> (Expression, Self::AdditionalOutput) {
400        (input.into(), Default::default())
401    }
402
403    fn reconstruct_ternary(
404        &mut self,
405        input: TernaryExpression,
406        _additional: &Self::AdditionalInput,
407    ) -> (Expression, Self::AdditionalOutput) {
408        (
409            TernaryExpression {
410                condition: self.reconstruct_expression(input.condition, &Default::default()).0,
411                if_true: self.reconstruct_expression(input.if_true, &Default::default()).0,
412                if_false: self.reconstruct_expression(input.if_false, &Default::default()).0,
413                span: input.span,
414                id: input.id,
415            }
416            .into(),
417            Default::default(),
418        )
419    }
420
421    fn reconstruct_tuple(
422        &mut self,
423        input: TupleExpression,
424        _additional: &Self::AdditionalInput,
425    ) -> (Expression, Self::AdditionalOutput) {
426        (
427            TupleExpression {
428                elements: input
429                    .elements
430                    .into_iter()
431                    .map(|element| self.reconstruct_expression(element, &Default::default()).0)
432                    .collect(),
433                ..input
434            }
435            .into(),
436            Default::default(),
437        )
438    }
439
440    fn reconstruct_unary(
441        &mut self,
442        input: UnaryExpression,
443        _additional: &Self::AdditionalInput,
444    ) -> (Expression, Self::AdditionalOutput) {
445        (
446            UnaryExpression { receiver: self.reconstruct_expression(input.receiver, &Default::default()).0, ..input }
447                .into(),
448            Default::default(),
449        )
450    }
451
452    fn reconstruct_unit(
453        &mut self,
454        input: UnitExpression,
455        _additional: &Self::AdditionalInput,
456    ) -> (Expression, Self::AdditionalOutput) {
457        (input.into(), Default::default())
458    }
459
460    /* Statements */
461    fn reconstruct_statement(&mut self, input: Statement) -> (Statement, Self::AdditionalOutput) {
462        match input {
463            Statement::Assert(assert) => self.reconstruct_assert(assert),
464            Statement::Assign(stmt) => self.reconstruct_assign(*stmt),
465            Statement::Block(stmt) => {
466                let (stmt, output) = self.reconstruct_block(stmt);
467                (stmt.into(), output)
468            }
469            Statement::Conditional(stmt) => self.reconstruct_conditional(stmt),
470            Statement::Const(stmt) => self.reconstruct_const(stmt),
471            Statement::Definition(stmt) => self.reconstruct_definition(stmt),
472            Statement::Expression(stmt) => self.reconstruct_expression_statement(stmt),
473            Statement::Iteration(stmt) => self.reconstruct_iteration(*stmt),
474            Statement::Return(stmt) => self.reconstruct_return(stmt),
475        }
476    }
477
478    fn reconstruct_assert(&mut self, input: AssertStatement) -> (Statement, Self::AdditionalOutput) {
479        (
480            AssertStatement {
481                variant: match input.variant {
482                    AssertVariant::Assert(expr) => {
483                        AssertVariant::Assert(self.reconstruct_expression(expr, &Default::default()).0)
484                    }
485                    AssertVariant::AssertEq(left, right) => AssertVariant::AssertEq(
486                        self.reconstruct_expression(left, &Default::default()).0,
487                        self.reconstruct_expression(right, &Default::default()).0,
488                    ),
489                    AssertVariant::AssertNeq(left, right) => AssertVariant::AssertNeq(
490                        self.reconstruct_expression(left, &Default::default()).0,
491                        self.reconstruct_expression(right, &Default::default()).0,
492                    ),
493                },
494                ..input
495            }
496            .into(),
497            Default::default(),
498        )
499    }
500
501    fn reconstruct_assign(&mut self, input: AssignStatement) -> (Statement, Self::AdditionalOutput) {
502        (
503            AssignStatement {
504                place: self.reconstruct_expression(input.place, &Default::default()).0,
505                value: self.reconstruct_expression(input.value, &Default::default()).0,
506                ..input
507            }
508            .into(),
509            Default::default(),
510        )
511    }
512
513    fn reconstruct_block(&mut self, input: Block) -> (Block, Self::AdditionalOutput) {
514        (
515            Block {
516                statements: input.statements.into_iter().map(|s| self.reconstruct_statement(s).0).collect(),
517                span: input.span,
518                id: input.id,
519            },
520            Default::default(),
521        )
522    }
523
524    fn reconstruct_conditional(&mut self, input: ConditionalStatement) -> (Statement, Self::AdditionalOutput) {
525        (
526            ConditionalStatement {
527                condition: self.reconstruct_expression(input.condition, &Default::default()).0,
528                then: self.reconstruct_block(input.then).0,
529                otherwise: input.otherwise.map(|n| Box::new(self.reconstruct_statement(*n).0)),
530                ..input
531            }
532            .into(),
533            Default::default(),
534        )
535    }
536
537    fn reconstruct_const(&mut self, input: ConstDeclaration) -> (Statement, Self::AdditionalOutput) {
538        (
539            ConstDeclaration {
540                type_: self.reconstruct_type_node(input.type_).0,
541                value: self.reconstruct_expression(input.value, &Default::default()).0,
542                ..input
543            }
544            .into(),
545            Default::default(),
546        )
547    }
548
549    fn reconstruct_definition(&mut self, input: DefinitionStatement) -> (Statement, Self::AdditionalOutput) {
550        (
551            DefinitionStatement {
552                type_: input.type_.map(|ty| self.reconstruct_type_node(ty).0),
553                value: self.reconstruct_expression(input.value, &Default::default()).0,
554                ..input
555            }
556            .into(),
557            Default::default(),
558        )
559    }
560
561    fn reconstruct_expression_statement(&mut self, input: ExpressionStatement) -> (Statement, Self::AdditionalOutput) {
562        (
563            ExpressionStatement {
564                expression: self.reconstruct_expression(input.expression, &Default::default()).0,
565                ..input
566            }
567            .into(),
568            Default::default(),
569        )
570    }
571
572    fn reconstruct_iteration(&mut self, input: IterationStatement) -> (Statement, Self::AdditionalOutput) {
573        (
574            IterationStatement {
575                type_: input.type_.map(|ty| self.reconstruct_type_node(ty).0),
576                start: self.reconstruct_expression(input.start, &Default::default()).0,
577                stop: self.reconstruct_expression(input.stop, &Default::default()).0,
578                block: self.reconstruct_block(input.block).0,
579                ..input
580            }
581            .into(),
582            Default::default(),
583        )
584    }
585
586    fn reconstruct_return(&mut self, input: ReturnStatement) -> (Statement, Self::AdditionalOutput) {
587        (
588            ReturnStatement {
589                expression: self.reconstruct_expression(input.expression, &Default::default()).0,
590                ..input
591            }
592            .into(),
593            Default::default(),
594        )
595    }
596}
597
598/// A Reconstructor trait for a compilation unit (program or library) represented by the AST.
599pub trait UnitReconstructor: AstReconstructor {
600    fn reconstruct_program(&mut self, input: Program) -> Program {
601        let stubs = input.stubs.into_iter().map(|(id, stub)| (id, self.reconstruct_stub(stub))).collect();
602        let program_scopes =
603            input.program_scopes.into_iter().map(|(id, scope)| (id, self.reconstruct_program_scope(scope))).collect();
604        let modules = input.modules.into_iter().map(|(id, module)| (id, self.reconstruct_module(module))).collect();
605
606        Program { modules, imports: input.imports, stubs, program_scopes }
607    }
608
609    fn reconstruct_aleo_program(&mut self, input: AleoProgram) -> AleoProgram {
610        AleoProgram {
611            imports: input.imports,
612            stub_id: input.stub_id,
613            consts: input.consts,
614            composites: input.composites,
615            mappings: input.mappings,
616            functions: input.functions.into_iter().map(|(i, f)| (i, self.reconstruct_function_stub(f))).collect(),
617            span: input.span,
618        }
619    }
620
621    fn reconstruct_library(&mut self, input: Library) -> Library {
622        Library {
623            name: input.name,
624            modules: input.modules.into_iter().map(|(id, m)| (id, self.reconstruct_module(m))).collect(),
625            consts: input
626                .consts
627                .into_iter()
628                .map(|(i, c)| match self.reconstruct_const(c) {
629                    (Statement::Const(declaration), _) => (i, declaration),
630                    _ => panic!("`reconstruct_const` can only return `Statement::Const`"),
631                })
632                .collect(),
633            structs: input.structs.into_iter().map(|(i, s)| (i, self.reconstruct_composite(s))).collect(),
634            functions: input.functions.into_iter().map(|(i, f)| (i, self.reconstruct_function(f))).collect(),
635            interfaces: input.interfaces.into_iter().map(|(i, int)| (i, self.reconstruct_interface(int))).collect(),
636            stubs: input.stubs.into_iter().map(|(id, stub)| (id, self.reconstruct_stub(stub))).collect(),
637        }
638    }
639
640    fn reconstruct_stub(&mut self, input: Stub) -> Stub {
641        match input {
642            Stub::FromLeo { program, parents } => Stub::FromLeo { program: self.reconstruct_program(program), parents },
643            Stub::FromAleo { program, parents } => {
644                Stub::FromAleo { program: self.reconstruct_aleo_program(program), parents }
645            }
646            Stub::FromLibrary { library, parents } => {
647                Stub::FromLibrary { library: self.reconstruct_library(library), parents }
648            }
649        }
650    }
651
652    fn reconstruct_program_scope(&mut self, input: ProgramScope) -> ProgramScope {
653        ProgramScope {
654            program_id: input.program_id,
655            parents: input.parents.into_iter().map(|(s, t)| (s, self.reconstruct_type(t).0)).collect(),
656            consts: input
657                .consts
658                .into_iter()
659                .map(|(i, c)| match self.reconstruct_const(c) {
660                    (Statement::Const(declaration), _) => (i, declaration),
661                    _ => panic!("`reconstruct_const` can only return `Statement::Const`"),
662                })
663                .collect(),
664            composites: input.composites.into_iter().map(|(i, c)| (i, self.reconstruct_composite(c))).collect(),
665            mappings: input.mappings.into_iter().map(|(id, mapping)| (id, self.reconstruct_mapping(mapping))).collect(),
666            storage_variables: input
667                .storage_variables
668                .into_iter()
669                .map(|(id, storage_variable)| (id, self.reconstruct_storage_variable(storage_variable)))
670                .collect(),
671            functions: input.functions.into_iter().map(|(i, f)| (i, self.reconstruct_function(f))).collect(),
672            interfaces: input.interfaces.into_iter().map(|(i, int)| (i, self.reconstruct_interface(int))).collect(),
673            constructor: input.constructor.map(|c| self.reconstruct_constructor(c)),
674            span: input.span,
675        }
676    }
677
678    fn reconstruct_module(&mut self, input: Module) -> Module {
679        Module {
680            unit_name: input.unit_name,
681            path: input.path,
682            consts: input
683                .consts
684                .into_iter()
685                .map(|(i, c)| match self.reconstruct_const(c) {
686                    (Statement::Const(declaration), _) => (i, declaration),
687                    _ => panic!("`reconstruct_const` can only return `Statement::Const`"),
688                })
689                .collect(),
690            composites: input.composites.into_iter().map(|(i, c)| (i, self.reconstruct_composite(c))).collect(),
691            functions: input.functions.into_iter().map(|(i, f)| (i, self.reconstruct_function(f))).collect(),
692            interfaces: input.interfaces.into_iter().map(|(i, int)| (i, self.reconstruct_interface(int))).collect(),
693        }
694    }
695
696    fn reconstruct_interface(&mut self, input: Interface) -> Interface {
697        Interface {
698            is_exported: input.is_exported,
699            identifier: input.identifier,
700            parents: input.parents.into_iter().map(|(s, t)| (s, self.reconstruct_type(t).0)).collect(),
701            span: input.span,
702            id: input.id,
703            functions: input.functions.into_iter().map(|(i, f)| (i, self.reconstruct_function_prototype(f))).collect(),
704            records: input.records.into_iter().map(|(i, f)| (i, self.reconstruct_record_prototype(f))).collect(),
705            mappings: input.mappings.into_iter().map(|m| self.reconstruct_mapping_prototype(m)).collect(),
706            storages: input.storages.into_iter().map(|s| self.reconstruct_storage_variable_prototype(s)).collect(),
707        }
708    }
709
710    fn reconstruct_mapping_prototype(&mut self, input: MappingPrototype) -> MappingPrototype {
711        MappingPrototype {
712            identifier: input.identifier,
713            key_type: self.reconstruct_type(input.key_type).0,
714            value_type: self.reconstruct_type(input.value_type).0,
715            span: input.span,
716            id: input.id,
717        }
718    }
719
720    fn reconstruct_storage_variable_prototype(&mut self, input: StorageVariablePrototype) -> StorageVariablePrototype {
721        StorageVariablePrototype {
722            identifier: input.identifier,
723            type_: self.reconstruct_type_node(input.type_).0,
724            span: input.span,
725            id: input.id,
726        }
727    }
728
729    fn reconstruct_function_prototype(&mut self, input: FunctionPrototype) -> FunctionPrototype {
730        FunctionPrototype {
731            annotations: input.annotations,
732            variant: input.variant,
733            identifier: input.identifier,
734            const_parameters: input
735                .const_parameters
736                .iter()
737                .map(|param| {
738                    let mut param = param.clone();
739                    param.type_ = self.reconstruct_type_node(param.type_).0;
740                    param
741                })
742                .collect(),
743            input: input
744                .input
745                .iter()
746                .map(|input| {
747                    let mut input = input.clone();
748                    input.type_ = self.reconstruct_type_node(input.type_).0;
749                    input
750                })
751                .collect(),
752            output: input
753                .output
754                .iter()
755                .map(|output| {
756                    let mut output = output.clone();
757                    output.type_ = self.reconstruct_type_node(output.type_).0;
758                    output
759                })
760                .collect(),
761            output_type: self.reconstruct_type(input.output_type).0,
762            span: input.span,
763            id: input.id,
764        }
765    }
766
767    fn reconstruct_record_prototype(&mut self, input: RecordPrototype) -> RecordPrototype {
768        RecordPrototype {
769            identifier: input.identifier,
770            span: input.span,
771            id: input.id,
772            members: input
773                .members
774                .iter()
775                .map(|member| {
776                    let mut member = member.clone();
777                    member.type_ = self.reconstruct_type_node(member.type_).0;
778                    member
779                })
780                .collect(),
781        }
782    }
783
784    fn reconstruct_function(&mut self, input: Function) -> Function {
785        Function {
786            is_exported: input.is_exported,
787            annotations: input.annotations,
788            variant: input.variant,
789            identifier: input.identifier,
790            const_parameters: input
791                .const_parameters
792                .iter()
793                .map(|param| {
794                    let mut param = param.clone();
795                    param.type_ = self.reconstruct_type_node(param.type_).0;
796                    param
797                })
798                .collect(),
799            input: input
800                .input
801                .iter()
802                .map(|input| {
803                    let mut input = input.clone();
804                    input.type_ = self.reconstruct_type_node(input.type_).0;
805                    input
806                })
807                .collect(),
808            output: input
809                .output
810                .iter()
811                .map(|output| {
812                    let mut output = output.clone();
813                    output.type_ = self.reconstruct_type_node(output.type_).0;
814                    output
815                })
816                .collect(),
817            output_type: self.reconstruct_type(input.output_type).0,
818            block: self.reconstruct_block(input.block).0,
819            span: input.span,
820            id: input.id,
821        }
822    }
823
824    fn reconstruct_constructor(&mut self, input: Constructor) -> Constructor {
825        Constructor {
826            annotations: input.annotations,
827            block: self.reconstruct_block(input.block).0,
828            span: input.span,
829            id: input.id,
830        }
831    }
832
833    fn reconstruct_function_stub(&mut self, input: FunctionStub) -> FunctionStub {
834        input
835    }
836
837    fn reconstruct_composite(&mut self, input: Composite) -> Composite {
838        Composite {
839            const_parameters: input
840                .const_parameters
841                .iter()
842                .map(|param| {
843                    let mut param = param.clone();
844                    param.type_ = self.reconstruct_type_node(param.type_).0;
845                    param
846                })
847                .collect(),
848            members: input
849                .members
850                .iter()
851                .map(|member| {
852                    let mut member = member.clone();
853                    member.type_ = self.reconstruct_type_node(member.type_).0;
854                    member
855                })
856                .collect(),
857            ..input
858        }
859    }
860
861    fn reconstruct_mapping(&mut self, input: Mapping) -> Mapping {
862        Mapping {
863            key_type: self.reconstruct_type(input.key_type).0,
864            value_type: self.reconstruct_type(input.value_type).0,
865            ..input
866        }
867    }
868
869    fn reconstruct_storage_variable(&mut self, input: StorageVariable) -> StorageVariable {
870        StorageVariable { type_: self.reconstruct_type_node(input.type_).0, ..input }
871    }
872}