Skip to main content

rib/
expr_arena.rs

1// Copyright 2024-2025 Golem Cloud
2//
3// Licensed under the Golem Source License v1.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://license.golem.cloud/LICENSE
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use la_arena::{Arena, Idx};
16use std::collections::HashMap;
17use std::fmt;
18
19use crate::call_type::{CallType, InstanceCreationType, InstanceIdentifier};
20use crate::expr::{ArmPattern, Expr, MatchArm, Number, Range};
21use crate::parser::type_name::TypeName;
22use crate::rib_source_span::SourceSpan;
23use crate::{InferredType, VariableId};
24
25// ---------------------------------------------------------------------------
26// Index types
27// ---------------------------------------------------------------------------
28
29/// Stable index into [`ExprArena`] identifying a single expression node.
30pub type ExprId = Idx<ExprNode>;
31
32/// Stable index into the arm-pattern arena.
33pub type ArmPatternId = Idx<ArmPatternNode>;
34
35// ---------------------------------------------------------------------------
36// Structural node — no InferredType, children are IDs
37// ---------------------------------------------------------------------------
38
39/// A single expression node stripped of its inferred type.
40/// Child expressions are referenced by [`ExprId`] rather than owned.
41#[derive(Debug, Clone)]
42pub struct ExprNode {
43    pub kind: ExprKind,
44    pub source_span: SourceSpan,
45    pub type_annotation: Option<TypeName>,
46}
47
48/// The shape of an expression node.  
49/// This mirrors [`Expr`] exactly, replacing every `Box<Expr>` / `Vec<Expr>`
50/// with `ExprId` / `Vec<ExprId>` and every `ArmPattern` with `ArmPatternId`.
51#[derive(Debug, Clone)]
52pub enum ExprKind {
53    Let {
54        variable_id: VariableId,
55        expr: ExprId,
56    },
57    SelectField {
58        expr: ExprId,
59        field: String,
60    },
61    SelectIndex {
62        expr: ExprId,
63        index: ExprId,
64    },
65    Sequence {
66        exprs: Vec<ExprId>,
67    },
68    Range {
69        range: RangeKind,
70    },
71    Record {
72        fields: Vec<(String, ExprId)>,
73    },
74    Tuple {
75        exprs: Vec<ExprId>,
76    },
77    Literal {
78        value: String,
79    },
80    Number {
81        number: Number,
82    },
83    Flags {
84        flags: Vec<String>,
85    },
86    Identifier {
87        variable_id: VariableId,
88    },
89    Boolean {
90        value: bool,
91    },
92    Concat {
93        exprs: Vec<ExprId>,
94    },
95    ExprBlock {
96        exprs: Vec<ExprId>,
97    },
98    Not {
99        expr: ExprId,
100    },
101    GreaterThan {
102        lhs: ExprId,
103        rhs: ExprId,
104    },
105    GreaterThanOrEqualTo {
106        lhs: ExprId,
107        rhs: ExprId,
108    },
109    LessThanOrEqualTo {
110        lhs: ExprId,
111        rhs: ExprId,
112    },
113    EqualTo {
114        lhs: ExprId,
115        rhs: ExprId,
116    },
117    LessThan {
118        lhs: ExprId,
119        rhs: ExprId,
120    },
121    And {
122        lhs: ExprId,
123        rhs: ExprId,
124    },
125    Or {
126        lhs: ExprId,
127        rhs: ExprId,
128    },
129    Plus {
130        lhs: ExprId,
131        rhs: ExprId,
132    },
133    Minus {
134        lhs: ExprId,
135        rhs: ExprId,
136    },
137    Multiply {
138        lhs: ExprId,
139        rhs: ExprId,
140    },
141    Divide {
142        lhs: ExprId,
143        rhs: ExprId,
144    },
145    Cond {
146        cond: ExprId,
147        lhs: ExprId,
148        rhs: ExprId,
149    },
150    PatternMatch {
151        predicate: ExprId,
152        match_arms: Vec<MatchArmNode>,
153    },
154    Option {
155        expr: Option<ExprId>,
156    },
157    Result {
158        expr: ResultExprKind,
159    },
160    Call {
161        call_type: CallTypeNode,
162        args: Vec<ExprId>,
163    },
164    InvokeMethodLazy {
165        lhs: ExprId,
166        method: String,
167        args: Vec<ExprId>,
168    },
169    Unwrap {
170        expr: ExprId,
171    },
172    Throw {
173        message: String,
174    },
175    GetTag {
176        expr: ExprId,
177    },
178    ListComprehension {
179        iterated_variable: VariableId,
180        iterable_expr: ExprId,
181        yield_expr: ExprId,
182    },
183    ListReduce {
184        reduce_variable: VariableId,
185        iterated_variable: VariableId,
186        iterable_expr: ExprId,
187        init_value_expr: ExprId,
188        yield_expr: ExprId,
189    },
190    Length {
191        expr: ExprId,
192    },
193    GenerateWorkerName {
194        variable_id: Option<VariableId>,
195    },
196}
197
198/// Arena-friendly version of [`Range`].
199#[derive(Debug, Clone)]
200pub enum RangeKind {
201    Range { from: ExprId, to: ExprId },
202    RangeInclusive { from: ExprId, to: ExprId },
203    RangeFrom { from: ExprId },
204}
205
206/// Arena-friendly version of `Result<Box<Expr>, Box<Expr>>` in [`Expr::Result`].
207#[derive(Debug, Clone)]
208pub enum ResultExprKind {
209    Ok(ExprId),
210    Err(ExprId),
211}
212
213/// Arena-friendly version of [`CallType`].
214/// [`InstanceIdentifier`] embeds `Option<Box<Expr>>` for the worker name;
215/// we replace that with `Option<ExprId>`.
216#[derive(Debug, Clone)]
217pub enum CallTypeNode {
218    Function {
219        component_info: Option<crate::ComponentDependencyKey>,
220        instance_identifier: Option<InstanceIdentifierNode>,
221        function_name: crate::DynamicParsedFunctionName,
222    },
223    VariantConstructor(String),
224    EnumConstructor(String),
225    InstanceCreation(InstanceCreationNode),
226}
227
228impl CallTypeNode {
229    /// Same notion as [`crate::CallType::is_resource_method`], without lowering to [`crate::CallType`].
230    pub fn is_resource_method(&self) -> bool {
231        match self {
232            CallTypeNode::Function { function_name, .. } => function_name
233                .to_parsed_function_name()
234                .function
235                .resource_method_name()
236                .is_some(),
237            _ => false,
238        }
239    }
240}
241
242impl fmt::Display for CallTypeNode {
243    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
244        match self {
245            CallTypeNode::Function { function_name, .. } => write!(f, "{function_name}"),
246            CallTypeNode::VariantConstructor(name) => write!(f, "{name}"),
247            CallTypeNode::EnumConstructor(name) => write!(f, "{name}"),
248            CallTypeNode::InstanceCreation(InstanceCreationNode::WitWorker { .. }) => {
249                write!(f, "instance")
250            }
251            CallTypeNode::InstanceCreation(InstanceCreationNode::WitResource {
252                resource_name,
253                ..
254            }) => write!(f, "{}", resource_name.resource_name),
255        }
256    }
257}
258
259#[derive(Debug, Clone)]
260pub enum InstanceIdentifierNode {
261    WitWorker {
262        variable_id: Option<VariableId>,
263        worker_name: Option<ExprId>,
264    },
265    WitResource {
266        variable_id: Option<VariableId>,
267        worker_name: Option<ExprId>,
268        resource_name: String,
269    },
270}
271
272#[derive(Debug, Clone)]
273pub enum InstanceCreationNode {
274    WitWorker {
275        component_info: Option<crate::ComponentDependencyKey>,
276        worker_name: Option<ExprId>,
277    },
278    WitResource {
279        component_info: Option<crate::ComponentDependencyKey>,
280        module: Option<InstanceIdentifierNode>,
281        resource_name: crate::FullyQualifiedResourceConstructor,
282    },
283}
284
285#[derive(Debug, Clone)]
286pub struct MatchArmNode {
287    pub arm_pattern: ArmPatternId,
288    pub arm_resolution_expr: ExprId,
289}
290
291#[derive(Debug, Clone)]
292pub enum ArmPatternNode {
293    WildCard,
294    As(String, ArmPatternId),
295    Constructor(String, Vec<ArmPatternId>),
296    TupleConstructor(Vec<ArmPatternId>),
297    RecordConstructor(Vec<(String, ArmPatternId)>),
298    ListConstructor(Vec<ArmPatternId>),
299    /// A literal pattern (identifier, option node, result node, etc.) is just
300    /// an expression embedded in the pattern — we keep the `ExprId` reference.
301    Literal(ExprId),
302}
303
304#[derive(Debug, Clone)]
305pub struct TypeTable {
306    types: HashMap<ExprId, InferredType>,
307}
308
309impl TypeTable {
310    pub fn new() -> Self {
311        TypeTable {
312            types: HashMap::new(),
313        }
314    }
315
316    pub fn get(&self, id: ExprId) -> &InferredType {
317        self.types
318            .get(&id)
319            .expect("TypeTable: ExprId not found — was it allocated in this arena?")
320    }
321
322    pub fn get_opt(&self, id: ExprId) -> Option<&InferredType> {
323        self.types.get(&id)
324    }
325
326    pub fn set(&mut self, id: ExprId, ty: InferredType) {
327        self.types.insert(id, ty);
328    }
329
330    /// Returns a snapshot of all types. The snapshot is a `Vec` ordered by
331    /// insertion — used for fix-point convergence checks (O(n) clone of
332    /// `InferredType` values, **not** a tree clone).
333    pub fn snapshot(&self) -> Vec<(ExprId, InferredType)> {
334        self.types.iter().map(|(k, v)| (*k, v.clone())).collect()
335    }
336
337    /// Returns `true` if this `TypeTable` has the same types as `other`.
338    /// Used to detect convergence in the fix-point loop.
339    pub fn same_as(&self, other: &TypeTable) -> bool {
340        if self.types.len() != other.types.len() {
341            return false;
342        }
343        self.types
344            .iter()
345            .all(|(id, ty)| other.types.get(id) == Some(ty))
346    }
347
348    /// Returns `true` if the current state matches a previously taken snapshot.
349    pub fn same_as_snapshot(&self, snapshot: &[(ExprId, InferredType)]) -> bool {
350        if self.types.len() != snapshot.len() {
351            return false;
352        }
353        snapshot
354            .iter()
355            .all(|(id, ty)| self.types.get(id) == Some(ty))
356    }
357}
358
359impl Default for TypeTable {
360    fn default() -> Self {
361        TypeTable::new()
362    }
363}
364
365// ---------------------------------------------------------------------------
366// ExprArena — structural storage
367// ---------------------------------------------------------------------------
368
369/// Owns all [`ExprNode`]s and [`ArmPatternNode`]s for a single compiled Rib
370/// expression.  Children are referenced by index, never by pointer.
371#[derive(Debug, Default)]
372pub struct ExprArena {
373    pub exprs: Arena<ExprNode>,
374    pub patterns: Arena<ArmPatternNode>,
375}
376
377impl ExprArena {
378    pub fn new() -> Self {
379        ExprArena::default()
380    }
381
382    /// Allocate a new expression node, returning its stable `ExprId`.
383    pub fn alloc_expr(&mut self, node: ExprNode) -> ExprId {
384        self.exprs.alloc(node)
385    }
386
387    /// Allocate a new arm-pattern node, returning its stable `ArmPatternId`.
388    pub fn alloc_pattern(&mut self, node: ArmPatternNode) -> ArmPatternId {
389        self.patterns.alloc(node)
390    }
391
392    /// Look up an expression node by id.
393    pub fn expr(&self, id: ExprId) -> &ExprNode {
394        &self.exprs[id]
395    }
396
397    /// Look up an expression node mutably by id.
398    /// Used by passes that perform structural mutations (e.g. converting an
399    /// `Identifier` node into a `Call` node during enum/variant inference).
400    pub fn expr_mut(&mut self, id: ExprId) -> &mut ExprNode {
401        &mut self.exprs[id]
402    }
403
404    /// Look up a pattern node by id.
405    pub fn pattern(&self, id: ArmPatternId) -> &ArmPatternNode {
406        &self.patterns[id]
407    }
408
409    /// Look up a pattern node mutably by id.
410    pub fn pattern_mut(&mut self, id: ArmPatternId) -> &mut ArmPatternNode {
411        &mut self.patterns[id]
412    }
413}
414
415/// Lower the recursive `Expr` tree into an arena representation.
416///
417/// Returns `(arena, type_table, root_id)`.  The caller can discard the old
418/// `Expr` once this call returns.
419///
420/// # Panics
421/// Does not panic under normal circumstances.
422pub fn lower(expr: &Expr) -> (ExprArena, TypeTable, ExprId) {
423    let mut arena = ExprArena::new();
424    let mut types = TypeTable::new();
425    let root = lower_expr(expr, &mut arena, &mut types);
426    (arena, types, root)
427}
428
429/// Lower `expr` into an existing arena, allocating fresh [`ExprId`]s and wiring
430/// child pointers within `arena` only (unlike naïvely cloning nodes from a
431/// separate lowered arena, which would leave stale child ids).
432pub fn lower_into(arena: &mut ExprArena, types: &mut TypeTable, expr: &Expr) -> ExprId {
433    lower_expr(expr, arena, types)
434}
435
436// ---------------------------------------------------------------------------
437// Rebuild: ExprArena + TypeTable  →  Expr tree
438// ---------------------------------------------------------------------------
439
440/// Reconstruct a full `Expr` tree from the arena, applying the current
441/// `TypeTable` values.  This is the inverse of [`lower`] and handles
442/// structural mutations (e.g. `InvokeMethodLazy` → `Call`) that occurred
443/// during arena-based inference.
444pub fn rebuild_expr(id: ExprId, arena: &ExprArena, types: &TypeTable) -> Expr {
445    let node = arena.expr(id);
446    let inferred = types
447        .get_opt(id)
448        .cloned()
449        .unwrap_or_else(InferredType::unknown);
450    let span = node.source_span.clone();
451    let annotation = node.type_annotation.clone();
452
453    match &node.kind.clone() {
454        ExprKind::Let {
455            variable_id,
456            expr: rhs_id,
457        } => Expr::Let {
458            variable_id: variable_id.clone(),
459            type_annotation: annotation,
460            expr: Box::new(rebuild_expr(*rhs_id, arena, types)),
461            inferred_type: inferred,
462            source_span: span,
463        },
464        ExprKind::SelectField {
465            expr: inner_id,
466            field,
467        } => Expr::SelectField {
468            expr: Box::new(rebuild_expr(*inner_id, arena, types)),
469            field: field.clone(),
470            type_annotation: annotation,
471            inferred_type: inferred,
472            source_span: span,
473        },
474        ExprKind::SelectIndex {
475            expr: e_id,
476            index: i_id,
477        } => Expr::SelectIndex {
478            expr: Box::new(rebuild_expr(*e_id, arena, types)),
479            index: Box::new(rebuild_expr(*i_id, arena, types)),
480            type_annotation: annotation,
481            inferred_type: inferred,
482            source_span: span,
483        },
484        ExprKind::Sequence { exprs } => Expr::Sequence {
485            exprs: exprs
486                .iter()
487                .map(|&e| rebuild_expr(e, arena, types))
488                .collect(),
489            type_annotation: annotation,
490            inferred_type: inferred,
491            source_span: span,
492        },
493        ExprKind::Tuple { exprs } => Expr::Tuple {
494            exprs: exprs
495                .iter()
496                .map(|&e| rebuild_expr(e, arena, types))
497                .collect(),
498            type_annotation: annotation,
499            inferred_type: inferred,
500            source_span: span,
501        },
502        ExprKind::Concat { exprs } => Expr::Concat {
503            exprs: exprs
504                .iter()
505                .map(|&e| rebuild_expr(e, arena, types))
506                .collect(),
507            type_annotation: annotation,
508            inferred_type: inferred,
509            source_span: span,
510        },
511        ExprKind::ExprBlock { exprs } => Expr::ExprBlock {
512            exprs: exprs
513                .iter()
514                .map(|&e| rebuild_expr(e, arena, types))
515                .collect(),
516            type_annotation: annotation,
517            inferred_type: inferred,
518            source_span: span,
519        },
520        ExprKind::Record { fields } => Expr::Record {
521            exprs: fields
522                .iter()
523                .map(|(name, e)| (name.clone(), Box::new(rebuild_expr(*e, arena, types))))
524                .collect(),
525            type_annotation: annotation,
526            inferred_type: inferred,
527            source_span: span,
528        },
529        ExprKind::Range { range } => {
530            let range_val = match range {
531                RangeKind::Range { from, to } => crate::expr::Range::Range {
532                    from: Box::new(rebuild_expr(*from, arena, types)),
533                    to: Box::new(rebuild_expr(*to, arena, types)),
534                },
535                RangeKind::RangeInclusive { from, to } => crate::expr::Range::RangeInclusive {
536                    from: Box::new(rebuild_expr(*from, arena, types)),
537                    to: Box::new(rebuild_expr(*to, arena, types)),
538                },
539                RangeKind::RangeFrom { from } => crate::expr::Range::RangeFrom {
540                    from: Box::new(rebuild_expr(*from, arena, types)),
541                },
542            };
543            Expr::Range {
544                range: range_val,
545                type_annotation: annotation,
546                inferred_type: inferred,
547                source_span: span,
548            }
549        }
550        ExprKind::Literal { value } => Expr::Literal {
551            value: value.clone(),
552            type_annotation: annotation,
553            inferred_type: inferred,
554            source_span: span,
555        },
556        ExprKind::Number { number } => Expr::Number {
557            number: number.clone(),
558            type_annotation: annotation,
559            inferred_type: inferred,
560            source_span: span,
561        },
562        ExprKind::Flags { flags } => Expr::Flags {
563            flags: flags.clone(),
564            type_annotation: annotation,
565            inferred_type: inferred,
566            source_span: span,
567        },
568        ExprKind::Identifier { variable_id } => Expr::Identifier {
569            variable_id: variable_id.clone(),
570            type_annotation: annotation,
571            inferred_type: inferred,
572            source_span: span,
573        },
574        ExprKind::Boolean { value } => Expr::Boolean {
575            value: *value,
576            type_annotation: annotation,
577            inferred_type: inferred,
578            source_span: span,
579        },
580        ExprKind::Not { expr: inner } => Expr::Not {
581            expr: Box::new(rebuild_expr(*inner, arena, types)),
582            type_annotation: annotation,
583            inferred_type: inferred,
584            source_span: span,
585        },
586        ExprKind::Length { expr: inner } => Expr::Length {
587            expr: Box::new(rebuild_expr(*inner, arena, types)),
588            type_annotation: annotation,
589            inferred_type: inferred,
590            source_span: span,
591        },
592        ExprKind::Unwrap { expr: inner } => Expr::Unwrap {
593            expr: Box::new(rebuild_expr(*inner, arena, types)),
594            type_annotation: annotation,
595            inferred_type: inferred,
596            source_span: span,
597        },
598        ExprKind::GetTag { expr: inner } => Expr::GetTag {
599            expr: Box::new(rebuild_expr(*inner, arena, types)),
600            type_annotation: annotation,
601            inferred_type: inferred,
602            source_span: span,
603        },
604        ExprKind::GreaterThan { lhs, rhs } => Expr::GreaterThan {
605            lhs: Box::new(rebuild_expr(*lhs, arena, types)),
606            rhs: Box::new(rebuild_expr(*rhs, arena, types)),
607            type_annotation: annotation,
608            inferred_type: inferred,
609            source_span: span,
610        },
611        ExprKind::GreaterThanOrEqualTo { lhs, rhs } => Expr::GreaterThanOrEqualTo {
612            lhs: Box::new(rebuild_expr(*lhs, arena, types)),
613            rhs: Box::new(rebuild_expr(*rhs, arena, types)),
614            type_annotation: annotation,
615            inferred_type: inferred,
616            source_span: span,
617        },
618        ExprKind::LessThanOrEqualTo { lhs, rhs } => Expr::LessThanOrEqualTo {
619            lhs: Box::new(rebuild_expr(*lhs, arena, types)),
620            rhs: Box::new(rebuild_expr(*rhs, arena, types)),
621            type_annotation: annotation,
622            inferred_type: inferred,
623            source_span: span,
624        },
625        ExprKind::EqualTo { lhs, rhs } => Expr::EqualTo {
626            lhs: Box::new(rebuild_expr(*lhs, arena, types)),
627            rhs: Box::new(rebuild_expr(*rhs, arena, types)),
628            type_annotation: annotation,
629            inferred_type: inferred,
630            source_span: span,
631        },
632        ExprKind::LessThan { lhs, rhs } => Expr::LessThan {
633            lhs: Box::new(rebuild_expr(*lhs, arena, types)),
634            rhs: Box::new(rebuild_expr(*rhs, arena, types)),
635            type_annotation: annotation,
636            inferred_type: inferred,
637            source_span: span,
638        },
639        ExprKind::And { lhs, rhs } => Expr::And {
640            lhs: Box::new(rebuild_expr(*lhs, arena, types)),
641            rhs: Box::new(rebuild_expr(*rhs, arena, types)),
642            type_annotation: annotation,
643            inferred_type: inferred,
644            source_span: span,
645        },
646        ExprKind::Or { lhs, rhs } => Expr::Or {
647            lhs: Box::new(rebuild_expr(*lhs, arena, types)),
648            rhs: Box::new(rebuild_expr(*rhs, arena, types)),
649            type_annotation: annotation,
650            inferred_type: inferred,
651            source_span: span,
652        },
653        ExprKind::Plus { lhs, rhs } => Expr::Plus {
654            lhs: Box::new(rebuild_expr(*lhs, arena, types)),
655            rhs: Box::new(rebuild_expr(*rhs, arena, types)),
656            type_annotation: annotation,
657            inferred_type: inferred,
658            source_span: span,
659        },
660        ExprKind::Minus { lhs, rhs } => Expr::Minus {
661            lhs: Box::new(rebuild_expr(*lhs, arena, types)),
662            rhs: Box::new(rebuild_expr(*rhs, arena, types)),
663            type_annotation: annotation,
664            inferred_type: inferred,
665            source_span: span,
666        },
667        ExprKind::Multiply { lhs, rhs } => Expr::Multiply {
668            lhs: Box::new(rebuild_expr(*lhs, arena, types)),
669            rhs: Box::new(rebuild_expr(*rhs, arena, types)),
670            type_annotation: annotation,
671            inferred_type: inferred,
672            source_span: span,
673        },
674        ExprKind::Divide { lhs, rhs } => Expr::Divide {
675            lhs: Box::new(rebuild_expr(*lhs, arena, types)),
676            rhs: Box::new(rebuild_expr(*rhs, arena, types)),
677            type_annotation: annotation,
678            inferred_type: inferred,
679            source_span: span,
680        },
681        ExprKind::Cond { cond, lhs, rhs } => Expr::Cond {
682            cond: Box::new(rebuild_expr(*cond, arena, types)),
683            lhs: Box::new(rebuild_expr(*lhs, arena, types)),
684            rhs: Box::new(rebuild_expr(*rhs, arena, types)),
685            type_annotation: annotation,
686            inferred_type: inferred,
687            source_span: span,
688        },
689        ExprKind::PatternMatch {
690            predicate,
691            match_arms,
692        } => Expr::PatternMatch {
693            predicate: Box::new(rebuild_expr(*predicate, arena, types)),
694            match_arms: match_arms
695                .iter()
696                .map(|arm| crate::expr::MatchArm {
697                    arm_pattern: rebuild_arm_pattern(arm.arm_pattern, arena, types),
698                    arm_resolution_expr: Box::new(rebuild_expr(
699                        arm.arm_resolution_expr,
700                        arena,
701                        types,
702                    )),
703                })
704                .collect(),
705            type_annotation: annotation,
706            inferred_type: inferred,
707            source_span: span,
708        },
709        ExprKind::Option { expr: None } => Expr::Option {
710            expr: None,
711            type_annotation: annotation,
712            inferred_type: inferred,
713            source_span: span,
714        },
715        ExprKind::Option { expr: Some(inner) } => Expr::Option {
716            expr: Some(Box::new(rebuild_expr(*inner, arena, types))),
717            type_annotation: annotation,
718            inferred_type: inferred,
719            source_span: span,
720        },
721        ExprKind::Result {
722            expr: ResultExprKind::Ok(inner),
723        } => Expr::Result {
724            expr: Ok(Box::new(rebuild_expr(*inner, arena, types))),
725            type_annotation: annotation,
726            inferred_type: inferred,
727            source_span: span,
728        },
729        ExprKind::Result {
730            expr: ResultExprKind::Err(inner),
731        } => Expr::Result {
732            expr: Err(Box::new(rebuild_expr(*inner, arena, types))),
733            type_annotation: annotation,
734            inferred_type: inferred,
735            source_span: span,
736        },
737        ExprKind::Call { call_type, args } => {
738            let old_call_type = rebuild_call_type(call_type, arena, types);
739            Expr::Call {
740                call_type: old_call_type,
741                args: args
742                    .iter()
743                    .map(|&a| rebuild_expr(a, arena, types))
744                    .collect(),
745                type_annotation: annotation,
746                inferred_type: inferred,
747                source_span: span,
748            }
749        }
750        ExprKind::InvokeMethodLazy { lhs, method, args } => Expr::InvokeMethodLazy {
751            lhs: Box::new(rebuild_expr(*lhs, arena, types)),
752            method: method.clone(),
753            args: args
754                .iter()
755                .map(|&a| rebuild_expr(a, arena, types))
756                .collect(),
757            type_annotation: annotation,
758            inferred_type: inferred,
759            source_span: span,
760        },
761        ExprKind::Throw { message } => Expr::Throw {
762            message: message.clone(),
763            type_annotation: annotation,
764            inferred_type: inferred,
765            source_span: span,
766        },
767        ExprKind::ListComprehension {
768            iterated_variable,
769            iterable_expr,
770            yield_expr,
771        } => Expr::ListComprehension {
772            iterated_variable: iterated_variable.clone(),
773            iterable_expr: Box::new(rebuild_expr(*iterable_expr, arena, types)),
774            yield_expr: Box::new(rebuild_expr(*yield_expr, arena, types)),
775            type_annotation: annotation,
776            inferred_type: inferred,
777            source_span: span,
778        },
779        ExprKind::ListReduce {
780            reduce_variable,
781            iterated_variable,
782            iterable_expr,
783            init_value_expr,
784            yield_expr,
785        } => Expr::ListReduce {
786            reduce_variable: reduce_variable.clone(),
787            iterated_variable: iterated_variable.clone(),
788            iterable_expr: Box::new(rebuild_expr(*iterable_expr, arena, types)),
789            init_value_expr: Box::new(rebuild_expr(*init_value_expr, arena, types)),
790            yield_expr: Box::new(rebuild_expr(*yield_expr, arena, types)),
791            type_annotation: annotation,
792            inferred_type: inferred,
793            source_span: span,
794        },
795        ExprKind::GenerateWorkerName { variable_id } => Expr::GenerateWorkerName {
796            variable_id: variable_id.clone(),
797            type_annotation: annotation,
798            inferred_type: inferred,
799            source_span: span,
800        },
801    }
802}
803
804pub(crate) fn rebuild_arm_pattern(
805    pat_id: ArmPatternId,
806    arena: &ExprArena,
807    types: &TypeTable,
808) -> crate::expr::ArmPattern {
809    match arena.pattern(pat_id) {
810        ArmPatternNode::WildCard => crate::expr::ArmPattern::WildCard,
811        ArmPatternNode::As(name, inner) => {
812            let inner = *inner;
813            crate::expr::ArmPattern::As(
814                name.clone(),
815                Box::new(rebuild_arm_pattern(inner, arena, types)),
816            )
817        }
818        ArmPatternNode::Literal(expr_id) => {
819            crate::expr::ArmPattern::Literal(Box::new(rebuild_expr(*expr_id, arena, types)))
820        }
821        ArmPatternNode::Constructor(name, children) => {
822            let children = children.clone();
823            crate::expr::ArmPattern::Constructor(
824                name.clone(),
825                children
826                    .iter()
827                    .map(|&c| rebuild_arm_pattern(c, arena, types))
828                    .collect(),
829            )
830        }
831        ArmPatternNode::TupleConstructor(children) => {
832            let children = children.clone();
833            crate::expr::ArmPattern::TupleConstructor(
834                children
835                    .iter()
836                    .map(|&c| rebuild_arm_pattern(c, arena, types))
837                    .collect(),
838            )
839        }
840        ArmPatternNode::ListConstructor(children) => {
841            let children = children.clone();
842            crate::expr::ArmPattern::ListConstructor(
843                children
844                    .iter()
845                    .map(|&c| rebuild_arm_pattern(c, arena, types))
846                    .collect(),
847            )
848        }
849        ArmPatternNode::RecordConstructor(fields) => {
850            let fields = fields.clone();
851            crate::expr::ArmPattern::RecordConstructor(
852                fields
853                    .iter()
854                    .map(|(name, c)| (name.clone(), rebuild_arm_pattern(*c, arena, types)))
855                    .collect(),
856            )
857        }
858    }
859}
860
861pub(crate) fn rebuild_call_type(
862    call_type: &CallTypeNode,
863    arena: &ExprArena,
864    types: &TypeTable,
865) -> crate::call_type::CallType {
866    use crate::call_type::{CallType, InstanceCreationType};
867    match call_type {
868        CallTypeNode::Function {
869            component_info,
870            instance_identifier,
871            function_name,
872        } => CallType::Function {
873            component_info: component_info.clone(),
874            instance_identifier: instance_identifier
875                .as_ref()
876                .map(|ii| Box::new(rebuild_instance_identifier(ii, arena, types))),
877            function_name: function_name.clone(),
878        },
879        CallTypeNode::VariantConstructor(name) => CallType::VariantConstructor(name.clone()),
880        CallTypeNode::EnumConstructor(name) => CallType::EnumConstructor(name.clone()),
881        CallTypeNode::InstanceCreation(creation) => {
882            let ict = match creation {
883                InstanceCreationNode::WitWorker {
884                    component_info,
885                    worker_name,
886                } => InstanceCreationType::WitWorker {
887                    component_info: component_info.clone(),
888                    worker_name: worker_name
889                        .map(|wn_id| Box::new(rebuild_expr(wn_id, arena, types))),
890                },
891                InstanceCreationNode::WitResource {
892                    component_info,
893                    module,
894                    resource_name,
895                } => InstanceCreationType::WitResource {
896                    component_info: component_info.clone(),
897                    module: module
898                        .as_ref()
899                        .map(|m| rebuild_instance_identifier(m, arena, types)),
900                    resource_name: resource_name.clone(),
901                },
902            };
903            CallType::InstanceCreation(ict)
904        }
905    }
906}
907
908fn rebuild_instance_identifier(
909    ii: &InstanceIdentifierNode,
910    arena: &ExprArena,
911    types: &TypeTable,
912) -> crate::call_type::InstanceIdentifier {
913    use crate::call_type::InstanceIdentifier;
914    match ii {
915        InstanceIdentifierNode::WitWorker {
916            variable_id,
917            worker_name,
918        } => InstanceIdentifier::WitWorker {
919            variable_id: variable_id.clone(),
920            worker_name: worker_name.map(|wn_id| Box::new(rebuild_expr(wn_id, arena, types))),
921        },
922        InstanceIdentifierNode::WitResource {
923            variable_id,
924            worker_name,
925            resource_name,
926        } => InstanceIdentifier::WitResource {
927            variable_id: variable_id.clone(),
928            worker_name: worker_name.map(|wn_id| Box::new(rebuild_expr(wn_id, arena, types))),
929            resource_name: resource_name.clone(),
930        },
931    }
932}
933
934fn lower_expr(expr: &Expr, arena: &mut ExprArena, types: &mut TypeTable) -> ExprId {
935    let (kind, span, annotation, inferred) = match expr {
936        Expr::Let {
937            variable_id,
938            type_annotation,
939            expr,
940            inferred_type,
941            source_span,
942        } => {
943            let child = lower_expr(expr, arena, types);
944            (
945                ExprKind::Let {
946                    variable_id: variable_id.clone(),
947                    expr: child,
948                },
949                source_span.clone(),
950                type_annotation.clone(),
951                inferred_type.clone(),
952            )
953        }
954
955        Expr::SelectField {
956            expr,
957            field,
958            type_annotation,
959            inferred_type,
960            source_span,
961        } => {
962            let child = lower_expr(expr, arena, types);
963            (
964                ExprKind::SelectField {
965                    expr: child,
966                    field: field.clone(),
967                },
968                source_span.clone(),
969                type_annotation.clone(),
970                inferred_type.clone(),
971            )
972        }
973
974        Expr::SelectIndex {
975            expr,
976            index,
977            type_annotation,
978            inferred_type,
979            source_span,
980        } => {
981            let e = lower_expr(expr, arena, types);
982            let i = lower_expr(index, arena, types);
983            (
984                ExprKind::SelectIndex { expr: e, index: i },
985                source_span.clone(),
986                type_annotation.clone(),
987                inferred_type.clone(),
988            )
989        }
990
991        Expr::Sequence {
992            exprs,
993            type_annotation,
994            inferred_type,
995            source_span,
996        } => {
997            let ids = exprs.iter().map(|e| lower_expr(e, arena, types)).collect();
998            (
999                ExprKind::Sequence { exprs: ids },
1000                source_span.clone(),
1001                type_annotation.clone(),
1002                inferred_type.clone(),
1003            )
1004        }
1005
1006        Expr::Range {
1007            range,
1008            type_annotation,
1009            inferred_type,
1010            source_span,
1011        } => {
1012            let range_kind = lower_range(range, arena, types);
1013            (
1014                ExprKind::Range { range: range_kind },
1015                source_span.clone(),
1016                type_annotation.clone(),
1017                inferred_type.clone(),
1018            )
1019        }
1020
1021        Expr::Record {
1022            exprs,
1023            type_annotation,
1024            inferred_type,
1025            source_span,
1026        } => {
1027            let fields = exprs
1028                .iter()
1029                .map(|(name, e)| (name.clone(), lower_expr(e, arena, types)))
1030                .collect();
1031            (
1032                ExprKind::Record { fields },
1033                source_span.clone(),
1034                type_annotation.clone(),
1035                inferred_type.clone(),
1036            )
1037        }
1038
1039        Expr::Tuple {
1040            exprs,
1041            type_annotation,
1042            inferred_type,
1043            source_span,
1044        } => {
1045            let ids = exprs.iter().map(|e| lower_expr(e, arena, types)).collect();
1046            (
1047                ExprKind::Tuple { exprs: ids },
1048                source_span.clone(),
1049                type_annotation.clone(),
1050                inferred_type.clone(),
1051            )
1052        }
1053
1054        Expr::Literal {
1055            value,
1056            type_annotation,
1057            inferred_type,
1058            source_span,
1059        } => (
1060            ExprKind::Literal {
1061                value: value.clone(),
1062            },
1063            source_span.clone(),
1064            type_annotation.clone(),
1065            inferred_type.clone(),
1066        ),
1067
1068        Expr::Number {
1069            number,
1070            type_annotation,
1071            inferred_type,
1072            source_span,
1073        } => (
1074            ExprKind::Number {
1075                number: number.clone(),
1076            },
1077            source_span.clone(),
1078            type_annotation.clone(),
1079            inferred_type.clone(),
1080        ),
1081
1082        Expr::Flags {
1083            flags,
1084            type_annotation,
1085            inferred_type,
1086            source_span,
1087        } => (
1088            ExprKind::Flags {
1089                flags: flags.clone(),
1090            },
1091            source_span.clone(),
1092            type_annotation.clone(),
1093            inferred_type.clone(),
1094        ),
1095
1096        Expr::Identifier {
1097            variable_id,
1098            type_annotation,
1099            inferred_type,
1100            source_span,
1101        } => (
1102            ExprKind::Identifier {
1103                variable_id: variable_id.clone(),
1104            },
1105            source_span.clone(),
1106            type_annotation.clone(),
1107            inferred_type.clone(),
1108        ),
1109
1110        Expr::Boolean {
1111            value,
1112            type_annotation,
1113            inferred_type,
1114            source_span,
1115        } => (
1116            ExprKind::Boolean { value: *value },
1117            source_span.clone(),
1118            type_annotation.clone(),
1119            inferred_type.clone(),
1120        ),
1121
1122        Expr::Concat {
1123            exprs,
1124            type_annotation,
1125            inferred_type,
1126            source_span,
1127        } => {
1128            let ids = exprs.iter().map(|e| lower_expr(e, arena, types)).collect();
1129            (
1130                ExprKind::Concat { exprs: ids },
1131                source_span.clone(),
1132                type_annotation.clone(),
1133                inferred_type.clone(),
1134            )
1135        }
1136
1137        Expr::ExprBlock {
1138            exprs,
1139            type_annotation,
1140            inferred_type,
1141            source_span,
1142        } => {
1143            let ids = exprs.iter().map(|e| lower_expr(e, arena, types)).collect();
1144            (
1145                ExprKind::ExprBlock { exprs: ids },
1146                source_span.clone(),
1147                type_annotation.clone(),
1148                inferred_type.clone(),
1149            )
1150        }
1151
1152        Expr::Not {
1153            expr,
1154            type_annotation,
1155            inferred_type,
1156            source_span,
1157        } => {
1158            let child = lower_expr(expr, arena, types);
1159            (
1160                ExprKind::Not { expr: child },
1161                source_span.clone(),
1162                type_annotation.clone(),
1163                inferred_type.clone(),
1164            )
1165        }
1166
1167        Expr::GreaterThan {
1168            lhs,
1169            rhs,
1170            type_annotation,
1171            inferred_type,
1172            source_span,
1173        } => {
1174            let l = lower_expr(lhs, arena, types);
1175            let r = lower_expr(rhs, arena, types);
1176            (
1177                ExprKind::GreaterThan { lhs: l, rhs: r },
1178                source_span.clone(),
1179                type_annotation.clone(),
1180                inferred_type.clone(),
1181            )
1182        }
1183
1184        Expr::GreaterThanOrEqualTo {
1185            lhs,
1186            rhs,
1187            type_annotation,
1188            inferred_type,
1189            source_span,
1190        } => {
1191            let l = lower_expr(lhs, arena, types);
1192            let r = lower_expr(rhs, arena, types);
1193            (
1194                ExprKind::GreaterThanOrEqualTo { lhs: l, rhs: r },
1195                source_span.clone(),
1196                type_annotation.clone(),
1197                inferred_type.clone(),
1198            )
1199        }
1200
1201        Expr::LessThanOrEqualTo {
1202            lhs,
1203            rhs,
1204            type_annotation,
1205            inferred_type,
1206            source_span,
1207        } => {
1208            let l = lower_expr(lhs, arena, types);
1209            let r = lower_expr(rhs, arena, types);
1210            (
1211                ExprKind::LessThanOrEqualTo { lhs: l, rhs: r },
1212                source_span.clone(),
1213                type_annotation.clone(),
1214                inferred_type.clone(),
1215            )
1216        }
1217
1218        Expr::EqualTo {
1219            lhs,
1220            rhs,
1221            type_annotation,
1222            inferred_type,
1223            source_span,
1224        } => {
1225            let l = lower_expr(lhs, arena, types);
1226            let r = lower_expr(rhs, arena, types);
1227            (
1228                ExprKind::EqualTo { lhs: l, rhs: r },
1229                source_span.clone(),
1230                type_annotation.clone(),
1231                inferred_type.clone(),
1232            )
1233        }
1234
1235        Expr::LessThan {
1236            lhs,
1237            rhs,
1238            type_annotation,
1239            inferred_type,
1240            source_span,
1241        } => {
1242            let l = lower_expr(lhs, arena, types);
1243            let r = lower_expr(rhs, arena, types);
1244            (
1245                ExprKind::LessThan { lhs: l, rhs: r },
1246                source_span.clone(),
1247                type_annotation.clone(),
1248                inferred_type.clone(),
1249            )
1250        }
1251
1252        Expr::And {
1253            lhs,
1254            rhs,
1255            type_annotation,
1256            inferred_type,
1257            source_span,
1258        } => {
1259            let l = lower_expr(lhs, arena, types);
1260            let r = lower_expr(rhs, arena, types);
1261            (
1262                ExprKind::And { lhs: l, rhs: r },
1263                source_span.clone(),
1264                type_annotation.clone(),
1265                inferred_type.clone(),
1266            )
1267        }
1268
1269        Expr::Or {
1270            lhs,
1271            rhs,
1272            type_annotation,
1273            inferred_type,
1274            source_span,
1275        } => {
1276            let l = lower_expr(lhs, arena, types);
1277            let r = lower_expr(rhs, arena, types);
1278            (
1279                ExprKind::Or { lhs: l, rhs: r },
1280                source_span.clone(),
1281                type_annotation.clone(),
1282                inferred_type.clone(),
1283            )
1284        }
1285
1286        Expr::Plus {
1287            lhs,
1288            rhs,
1289            type_annotation,
1290            inferred_type,
1291            source_span,
1292        } => {
1293            let l = lower_expr(lhs, arena, types);
1294            let r = lower_expr(rhs, arena, types);
1295            (
1296                ExprKind::Plus { lhs: l, rhs: r },
1297                source_span.clone(),
1298                type_annotation.clone(),
1299                inferred_type.clone(),
1300            )
1301        }
1302
1303        Expr::Minus {
1304            lhs,
1305            rhs,
1306            type_annotation,
1307            inferred_type,
1308            source_span,
1309        } => {
1310            let l = lower_expr(lhs, arena, types);
1311            let r = lower_expr(rhs, arena, types);
1312            (
1313                ExprKind::Minus { lhs: l, rhs: r },
1314                source_span.clone(),
1315                type_annotation.clone(),
1316                inferred_type.clone(),
1317            )
1318        }
1319
1320        Expr::Multiply {
1321            lhs,
1322            rhs,
1323            type_annotation,
1324            inferred_type,
1325            source_span,
1326        } => {
1327            let l = lower_expr(lhs, arena, types);
1328            let r = lower_expr(rhs, arena, types);
1329            (
1330                ExprKind::Multiply { lhs: l, rhs: r },
1331                source_span.clone(),
1332                type_annotation.clone(),
1333                inferred_type.clone(),
1334            )
1335        }
1336
1337        Expr::Divide {
1338            lhs,
1339            rhs,
1340            type_annotation,
1341            inferred_type,
1342            source_span,
1343        } => {
1344            let l = lower_expr(lhs, arena, types);
1345            let r = lower_expr(rhs, arena, types);
1346            (
1347                ExprKind::Divide { lhs: l, rhs: r },
1348                source_span.clone(),
1349                type_annotation.clone(),
1350                inferred_type.clone(),
1351            )
1352        }
1353
1354        Expr::Cond {
1355            cond,
1356            lhs,
1357            rhs,
1358            type_annotation,
1359            inferred_type,
1360            source_span,
1361        } => {
1362            let c = lower_expr(cond, arena, types);
1363            let l = lower_expr(lhs, arena, types);
1364            let r = lower_expr(rhs, arena, types);
1365            (
1366                ExprKind::Cond {
1367                    cond: c,
1368                    lhs: l,
1369                    rhs: r,
1370                },
1371                source_span.clone(),
1372                type_annotation.clone(),
1373                inferred_type.clone(),
1374            )
1375        }
1376
1377        Expr::PatternMatch {
1378            predicate,
1379            match_arms,
1380            type_annotation,
1381            inferred_type,
1382            source_span,
1383        } => {
1384            let pred = lower_expr(predicate, arena, types);
1385            let arms = match_arms
1386                .iter()
1387                .map(|arm| lower_match_arm(arm, arena, types))
1388                .collect();
1389            (
1390                ExprKind::PatternMatch {
1391                    predicate: pred,
1392                    match_arms: arms,
1393                },
1394                source_span.clone(),
1395                type_annotation.clone(),
1396                inferred_type.clone(),
1397            )
1398        }
1399
1400        Expr::Option {
1401            expr,
1402            type_annotation,
1403            inferred_type,
1404            source_span,
1405        } => {
1406            let child = expr.as_ref().map(|e| lower_expr(e, arena, types));
1407            (
1408                ExprKind::Option { expr: child },
1409                source_span.clone(),
1410                type_annotation.clone(),
1411                inferred_type.clone(),
1412            )
1413        }
1414
1415        Expr::Result {
1416            expr,
1417            type_annotation,
1418            inferred_type,
1419            source_span,
1420        } => {
1421            let kind = match expr {
1422                Ok(e) => ResultExprKind::Ok(lower_expr(e, arena, types)),
1423                Err(e) => ResultExprKind::Err(lower_expr(e, arena, types)),
1424            };
1425            (
1426                ExprKind::Result { expr: kind },
1427                source_span.clone(),
1428                type_annotation.clone(),
1429                inferred_type.clone(),
1430            )
1431        }
1432
1433        Expr::Call {
1434            call_type,
1435            args,
1436            type_annotation,
1437            inferred_type,
1438            source_span,
1439        } => {
1440            let call_node = lower_call_type(call_type, arena, types);
1441            let arg_ids = args.iter().map(|a| lower_expr(a, arena, types)).collect();
1442            (
1443                ExprKind::Call {
1444                    call_type: call_node,
1445                    args: arg_ids,
1446                },
1447                source_span.clone(),
1448                type_annotation.clone(),
1449                inferred_type.clone(),
1450            )
1451        }
1452
1453        Expr::InvokeMethodLazy {
1454            lhs,
1455            method,
1456            args,
1457            type_annotation,
1458            inferred_type,
1459            source_span,
1460        } => {
1461            let lhs_id = lower_expr(lhs, arena, types);
1462            let arg_ids = args.iter().map(|a| lower_expr(a, arena, types)).collect();
1463            (
1464                ExprKind::InvokeMethodLazy {
1465                    lhs: lhs_id,
1466                    method: method.clone(),
1467                    args: arg_ids,
1468                },
1469                source_span.clone(),
1470                type_annotation.clone(),
1471                inferred_type.clone(),
1472            )
1473        }
1474
1475        Expr::Unwrap {
1476            expr,
1477            type_annotation,
1478            inferred_type,
1479            source_span,
1480        } => {
1481            let child = lower_expr(expr, arena, types);
1482            (
1483                ExprKind::Unwrap { expr: child },
1484                source_span.clone(),
1485                type_annotation.clone(),
1486                inferred_type.clone(),
1487            )
1488        }
1489
1490        Expr::Throw {
1491            message,
1492            type_annotation,
1493            inferred_type,
1494            source_span,
1495        } => (
1496            ExprKind::Throw {
1497                message: message.clone(),
1498            },
1499            source_span.clone(),
1500            type_annotation.clone(),
1501            inferred_type.clone(),
1502        ),
1503
1504        Expr::GetTag {
1505            expr,
1506            type_annotation,
1507            inferred_type,
1508            source_span,
1509        } => {
1510            let child = lower_expr(expr, arena, types);
1511            (
1512                ExprKind::GetTag { expr: child },
1513                source_span.clone(),
1514                type_annotation.clone(),
1515                inferred_type.clone(),
1516            )
1517        }
1518
1519        Expr::ListComprehension {
1520            iterated_variable,
1521            iterable_expr,
1522            yield_expr,
1523            type_annotation,
1524            inferred_type,
1525            source_span,
1526        } => {
1527            let iterable = lower_expr(iterable_expr, arena, types);
1528            let yield_ = lower_expr(yield_expr, arena, types);
1529            (
1530                ExprKind::ListComprehension {
1531                    iterated_variable: iterated_variable.clone(),
1532                    iterable_expr: iterable,
1533                    yield_expr: yield_,
1534                },
1535                source_span.clone(),
1536                type_annotation.clone(),
1537                inferred_type.clone(),
1538            )
1539        }
1540
1541        Expr::ListReduce {
1542            reduce_variable,
1543            iterated_variable,
1544            iterable_expr,
1545            init_value_expr,
1546            yield_expr,
1547            type_annotation,
1548            inferred_type,
1549            source_span,
1550        } => {
1551            let iterable = lower_expr(iterable_expr, arena, types);
1552            let init = lower_expr(init_value_expr, arena, types);
1553            let yield_ = lower_expr(yield_expr, arena, types);
1554            (
1555                ExprKind::ListReduce {
1556                    reduce_variable: reduce_variable.clone(),
1557                    iterated_variable: iterated_variable.clone(),
1558                    iterable_expr: iterable,
1559                    init_value_expr: init,
1560                    yield_expr: yield_,
1561                },
1562                source_span.clone(),
1563                type_annotation.clone(),
1564                inferred_type.clone(),
1565            )
1566        }
1567
1568        Expr::Length {
1569            expr,
1570            type_annotation,
1571            inferred_type,
1572            source_span,
1573        } => {
1574            let child = lower_expr(expr, arena, types);
1575            (
1576                ExprKind::Length { expr: child },
1577                source_span.clone(),
1578                type_annotation.clone(),
1579                inferred_type.clone(),
1580            )
1581        }
1582
1583        Expr::GenerateWorkerName {
1584            variable_id,
1585            type_annotation,
1586            inferred_type,
1587            source_span,
1588        } => (
1589            ExprKind::GenerateWorkerName {
1590                variable_id: variable_id.clone(),
1591            },
1592            source_span.clone(),
1593            type_annotation.clone(),
1594            inferred_type.clone(),
1595        ),
1596    };
1597
1598    let id = arena.alloc_expr(ExprNode {
1599        kind,
1600        source_span: span,
1601        type_annotation: annotation,
1602    });
1603    types.set(id, inferred);
1604    id
1605}
1606
1607fn lower_range(range: &Range, arena: &mut ExprArena, types: &mut TypeTable) -> RangeKind {
1608    match range {
1609        Range::Range { from, to } => RangeKind::Range {
1610            from: lower_expr(from, arena, types),
1611            to: lower_expr(to, arena, types),
1612        },
1613        Range::RangeInclusive { from, to } => RangeKind::RangeInclusive {
1614            from: lower_expr(from, arena, types),
1615            to: lower_expr(to, arena, types),
1616        },
1617        Range::RangeFrom { from } => RangeKind::RangeFrom {
1618            from: lower_expr(from, arena, types),
1619        },
1620    }
1621}
1622
1623fn lower_match_arm(arm: &MatchArm, arena: &mut ExprArena, types: &mut TypeTable) -> MatchArmNode {
1624    let pattern_id = lower_arm_pattern(&arm.arm_pattern, arena, types);
1625    let resolution_id = lower_expr(&arm.arm_resolution_expr, arena, types);
1626    MatchArmNode {
1627        arm_pattern: pattern_id,
1628        arm_resolution_expr: resolution_id,
1629    }
1630}
1631
1632fn lower_arm_pattern(
1633    pattern: &ArmPattern,
1634    arena: &mut ExprArena,
1635    types: &mut TypeTable,
1636) -> ArmPatternId {
1637    let node = match pattern {
1638        ArmPattern::WildCard => ArmPatternNode::WildCard,
1639
1640        ArmPattern::As(name, inner) => {
1641            let inner_id = lower_arm_pattern(inner, arena, types);
1642            ArmPatternNode::As(name.clone(), inner_id)
1643        }
1644
1645        ArmPattern::Constructor(name, patterns) => {
1646            let ids = patterns
1647                .iter()
1648                .map(|p| lower_arm_pattern(p, arena, types))
1649                .collect();
1650            ArmPatternNode::Constructor(name.clone(), ids)
1651        }
1652
1653        ArmPattern::TupleConstructor(patterns) => {
1654            let ids = patterns
1655                .iter()
1656                .map(|p| lower_arm_pattern(p, arena, types))
1657                .collect();
1658            ArmPatternNode::TupleConstructor(ids)
1659        }
1660
1661        ArmPattern::RecordConstructor(fields) => {
1662            let pairs = fields
1663                .iter()
1664                .map(|(name, p)| (name.clone(), lower_arm_pattern(p, arena, types)))
1665                .collect();
1666            ArmPatternNode::RecordConstructor(pairs)
1667        }
1668
1669        ArmPattern::ListConstructor(patterns) => {
1670            let ids = patterns
1671                .iter()
1672                .map(|p| lower_arm_pattern(p, arena, types))
1673                .collect();
1674            ArmPatternNode::ListConstructor(ids)
1675        }
1676
1677        ArmPattern::Literal(expr) => {
1678            let expr_id = lower_expr(expr, arena, types);
1679            ArmPatternNode::Literal(expr_id)
1680        }
1681    };
1682
1683    arena.alloc_pattern(node)
1684}
1685
1686fn lower_call_type(
1687    call_type: &CallType,
1688    arena: &mut ExprArena,
1689    types: &mut TypeTable,
1690) -> CallTypeNode {
1691    match call_type {
1692        CallType::Function {
1693            component_info,
1694            instance_identifier,
1695            function_name,
1696        } => CallTypeNode::Function {
1697            component_info: component_info.clone(),
1698            instance_identifier: instance_identifier
1699                .as_ref()
1700                .map(|ii| lower_instance_identifier(ii, arena, types)),
1701            function_name: function_name.clone(),
1702        },
1703
1704        CallType::VariantConstructor(name) => CallTypeNode::VariantConstructor(name.clone()),
1705        CallType::EnumConstructor(name) => CallTypeNode::EnumConstructor(name.clone()),
1706
1707        CallType::InstanceCreation(creation) => {
1708            CallTypeNode::InstanceCreation(lower_instance_creation(creation, arena, types))
1709        }
1710    }
1711}
1712
1713fn lower_instance_identifier(
1714    ii: &InstanceIdentifier,
1715    arena: &mut ExprArena,
1716    types: &mut TypeTable,
1717) -> InstanceIdentifierNode {
1718    match ii {
1719        InstanceIdentifier::WitWorker {
1720            variable_id,
1721            worker_name,
1722        } => InstanceIdentifierNode::WitWorker {
1723            variable_id: variable_id.clone(),
1724            worker_name: worker_name
1725                .as_ref()
1726                .map(|wn| lower_expr(wn.as_ref(), arena, types)),
1727        },
1728        InstanceIdentifier::WitResource {
1729            variable_id,
1730            worker_name,
1731            resource_name,
1732        } => InstanceIdentifierNode::WitResource {
1733            variable_id: variable_id.clone(),
1734            worker_name: worker_name
1735                .as_ref()
1736                .map(|wn| lower_expr(wn.as_ref(), arena, types)),
1737            resource_name: resource_name.clone(),
1738        },
1739    }
1740}
1741
1742fn lower_instance_creation(
1743    creation: &InstanceCreationType,
1744    arena: &mut ExprArena,
1745    types: &mut TypeTable,
1746) -> InstanceCreationNode {
1747    match creation {
1748        InstanceCreationType::WitWorker {
1749            component_info,
1750            worker_name,
1751        } => InstanceCreationNode::WitWorker {
1752            component_info: component_info.clone(),
1753            worker_name: worker_name
1754                .as_ref()
1755                .map(|wn| lower_expr(wn.as_ref(), arena, types)),
1756        },
1757        InstanceCreationType::WitResource {
1758            component_info,
1759            module,
1760            resource_name,
1761        } => InstanceCreationNode::WitResource {
1762            component_info: component_info.clone(),
1763            module: module
1764                .as_ref()
1765                .map(|m| lower_instance_identifier(m, arena, types)),
1766            resource_name: resource_name.clone(),
1767        },
1768    }
1769}
1770
1771// ---------------------------------------------------------------------------
1772// Tests
1773// ---------------------------------------------------------------------------
1774
1775#[cfg(test)]
1776mod tests {
1777    use test_r::test;
1778
1779    use super::*;
1780    use crate::Expr;
1781
1782    #[test]
1783    fn test_lower_literal() {
1784        let expr = Expr::from_text(r#""hello""#).unwrap();
1785        let (arena, types, root) = lower(&expr);
1786        let node = arena.expr(root);
1787        assert!(matches!(node.kind, ExprKind::Literal { .. }));
1788        // TypeTable must contain an entry for the root
1789        assert!(types.get_opt(root).is_some());
1790    }
1791
1792    #[test]
1793    fn test_lower_let_binding() {
1794        let expr = Expr::from_text("let x = 1; x").unwrap();
1795        let (arena, types, root) = lower(&expr);
1796        // root should be an ExprBlock
1797        let node = arena.expr(root);
1798        assert!(matches!(node.kind, ExprKind::ExprBlock { .. }));
1799        // All nodes must have a type entry
1800        for (id, _) in arena.exprs.iter() {
1801            assert!(types.get_opt(id).is_some(), "missing type for expr node");
1802        }
1803    }
1804
1805    #[test]
1806    fn test_lower_pattern_match() {
1807        let src = r#"
1808            let x = some("hello");
1809            match x {
1810              some(v) => v,
1811              none => "default"
1812            }
1813        "#;
1814        let expr = Expr::from_text(src).unwrap();
1815        let (arena, types, root) = lower(&expr);
1816        // Verify every node and every pattern has a type / exists
1817        for (id, _) in arena.exprs.iter() {
1818            assert!(types.get_opt(id).is_some());
1819        }
1820        // Patterns should all be allocated
1821        assert!(arena.patterns.iter().count() > 0);
1822        let _ = root;
1823    }
1824
1825    #[test]
1826    fn test_type_table_snapshot_and_same_as() {
1827        let expr = Expr::from_text(r#"1 + 2"#).unwrap();
1828        let (_arena, types, _root) = lower(&expr);
1829        let snap = types.snapshot();
1830        // Reconstruct a TypeTable from the snapshot and verify same_as
1831        let mut reconstructed = TypeTable::new();
1832        for (id, ty) in snap {
1833            reconstructed.set(id, ty);
1834        }
1835        assert!(types.same_as(&reconstructed));
1836    }
1837
1838    #[test]
1839    fn test_node_count_matches() {
1840        // A simple expr "1" has exactly 1 node
1841        let expr = Expr::from_text(r#"1"#).unwrap();
1842        let (arena, types, _root) = lower(&expr);
1843        assert_eq!(arena.exprs.iter().count(), types.snapshot().len());
1844    }
1845}