rib/
expr.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 crate::call_type::{CallType, InstanceCreationType};
16use crate::generic_type_parameter::GenericTypeParameter;
17use crate::inferred_type::{DefaultType, TypeOrigin};
18use crate::parser::block::block;
19use crate::parser::type_name::TypeName;
20use crate::rib_source_span::SourceSpan;
21use crate::rib_type_error::RibTypeErrorInternal;
22use crate::{
23    from_string, text, type_checker, type_inference, ComponentDependencies, ComponentDependencyKey,
24    DynamicParsedFunctionName, ExprVisitor, GlobalVariableTypeSpec, InferredType,
25    InstanceIdentifier, ParsedFunctionName, VariableId,
26};
27use bigdecimal::{BigDecimal, FromPrimitive, ToPrimitive};
28use combine::parser::char::spaces;
29use combine::stream::position;
30use combine::Parser;
31use combine::{eof, EasyParser};
32use golem_api_grpc::proto::golem::rib::range_expr::RangeExpr;
33use golem_wasm_ast::analysis::AnalysedType;
34use golem_wasm_rpc::{IntoValueAndType, ValueAndType};
35use serde::{Deserialize, Serialize, Serializer};
36use serde_json::Value;
37use std::collections::VecDeque;
38use std::fmt::Display;
39use std::ops::Deref;
40use std::str::FromStr;
41
42#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord)]
43pub enum Expr {
44    Let {
45        variable_id: VariableId,
46        type_annotation: Option<TypeName>,
47        expr: Box<Expr>,
48        inferred_type: InferredType,
49        source_span: SourceSpan,
50    },
51    SelectField {
52        expr: Box<Expr>,
53        field: String,
54        type_annotation: Option<TypeName>,
55        inferred_type: InferredType,
56        source_span: SourceSpan,
57    },
58    SelectIndex {
59        expr: Box<Expr>,
60        index: Box<Expr>,
61        type_annotation: Option<TypeName>,
62        inferred_type: InferredType,
63        source_span: SourceSpan,
64    },
65    Sequence {
66        exprs: Vec<Expr>,
67        type_annotation: Option<TypeName>,
68        inferred_type: InferredType,
69        source_span: SourceSpan,
70    },
71    Range {
72        range: Range,
73        type_annotation: Option<TypeName>,
74        inferred_type: InferredType,
75        source_span: SourceSpan,
76    },
77    Record {
78        exprs: Vec<(String, Box<Expr>)>,
79        type_annotation: Option<TypeName>,
80        inferred_type: InferredType,
81        source_span: SourceSpan,
82    },
83    Tuple {
84        exprs: Vec<Expr>,
85        type_annotation: Option<TypeName>,
86        inferred_type: InferredType,
87        source_span: SourceSpan,
88    },
89    Literal {
90        value: String,
91        type_annotation: Option<TypeName>,
92        inferred_type: InferredType,
93        source_span: SourceSpan,
94    },
95    Number {
96        number: Number,
97        type_annotation: Option<TypeName>,
98        inferred_type: InferredType,
99        source_span: SourceSpan,
100    },
101    Flags {
102        flags: Vec<String>,
103        type_annotation: Option<TypeName>,
104        inferred_type: InferredType,
105        source_span: SourceSpan,
106    },
107    Identifier {
108        variable_id: VariableId,
109        type_annotation: Option<TypeName>,
110        inferred_type: InferredType,
111        source_span: SourceSpan,
112    },
113    Boolean {
114        value: bool,
115        type_annotation: Option<TypeName>,
116        inferred_type: InferredType,
117        source_span: SourceSpan,
118    },
119    Concat {
120        exprs: Vec<Expr>,
121        type_annotation: Option<TypeName>,
122        inferred_type: InferredType,
123        source_span: SourceSpan,
124    },
125    ExprBlock {
126        exprs: Vec<Expr>,
127        type_annotation: Option<TypeName>,
128        inferred_type: InferredType,
129        source_span: SourceSpan,
130    },
131    Not {
132        expr: Box<Expr>,
133        inferred_type: InferredType,
134        type_annotation: Option<TypeName>,
135        source_span: SourceSpan,
136    },
137    GreaterThan {
138        lhs: Box<Expr>,
139        rhs: Box<Expr>,
140        type_annotation: Option<TypeName>,
141        inferred_type: InferredType,
142        source_span: SourceSpan,
143    },
144    And {
145        lhs: Box<Expr>,
146        rhs: Box<Expr>,
147        type_annotation: Option<TypeName>,
148        inferred_type: InferredType,
149        source_span: SourceSpan,
150    },
151    Or {
152        lhs: Box<Expr>,
153        rhs: Box<Expr>,
154        type_annotation: Option<TypeName>,
155        inferred_type: InferredType,
156        source_span: SourceSpan,
157    },
158    GreaterThanOrEqualTo {
159        lhs: Box<Expr>,
160        rhs: Box<Expr>,
161        type_annotation: Option<TypeName>,
162        inferred_type: InferredType,
163        source_span: SourceSpan,
164    },
165    LessThanOrEqualTo {
166        lhs: Box<Expr>,
167        rhs: Box<Expr>,
168        type_annotation: Option<TypeName>,
169        inferred_type: InferredType,
170        source_span: SourceSpan,
171    },
172    Plus {
173        lhs: Box<Expr>,
174        rhs: Box<Expr>,
175        type_annotation: Option<TypeName>,
176        inferred_type: InferredType,
177        source_span: SourceSpan,
178    },
179    Multiply {
180        lhs: Box<Expr>,
181        rhs: Box<Expr>,
182        type_annotation: Option<TypeName>,
183        inferred_type: InferredType,
184        source_span: SourceSpan,
185    },
186    Minus {
187        lhs: Box<Expr>,
188        rhs: Box<Expr>,
189        type_annotation: Option<TypeName>,
190        inferred_type: InferredType,
191        source_span: SourceSpan,
192    },
193    Divide {
194        lhs: Box<Expr>,
195        rhs: Box<Expr>,
196        type_annotation: Option<TypeName>,
197        inferred_type: InferredType,
198        source_span: SourceSpan,
199    },
200    EqualTo {
201        lhs: Box<Expr>,
202        rhs: Box<Expr>,
203        type_annotation: Option<TypeName>,
204        inferred_type: InferredType,
205        source_span: SourceSpan,
206    },
207    LessThan {
208        lhs: Box<Expr>,
209        rhs: Box<Expr>,
210        type_annotation: Option<TypeName>,
211        inferred_type: InferredType,
212        source_span: SourceSpan,
213    },
214    Cond {
215        cond: Box<Expr>,
216        lhs: Box<Expr>,
217        rhs: Box<Expr>,
218        type_annotation: Option<TypeName>,
219        inferred_type: InferredType,
220        source_span: SourceSpan,
221    },
222    PatternMatch {
223        predicate: Box<Expr>,
224        match_arms: Vec<MatchArm>,
225        type_annotation: Option<TypeName>,
226        inferred_type: InferredType,
227        source_span: SourceSpan,
228    },
229    Option {
230        expr: Option<Box<Expr>>,
231        type_annotation: Option<TypeName>,
232        inferred_type: InferredType,
233        source_span: SourceSpan,
234    },
235    Result {
236        expr: Result<Box<Expr>, Box<Expr>>,
237        type_annotation: Option<TypeName>,
238        inferred_type: InferredType,
239        source_span: SourceSpan,
240    },
241    // instance[t]("my-worker") will be parsed sd Expr::Call { "instance", Some(t }, vec!["my-worker"] }
242    // will be parsed as Expr::Call { "instance", vec!["my-worker"] }.
243    // During function call inference phase, the type of this `Expr::Call` will be `Expr::Call { InstanceCreation,.. }
244    // with inferred-type as `InstanceType`. This way any variables attached to the instance creation
245    // will be having the `InstanceType`.
246    Call {
247        call_type: CallType,
248        generic_type_parameter: Option<GenericTypeParameter>,
249        args: Vec<Expr>,
250        type_annotation: Option<TypeName>,
251        inferred_type: InferredType,
252        source_span: SourceSpan,
253    },
254    // Any calls such as `my-worker-variable-expr.function_name()` will be parsed as Expr::Invoke
255    // such that `my-worker-variable-expr` (lhs) will be of the type `InferredType::InstanceType`. `lhs` will
256    // be `Expr::Call { InstanceCreation }` with type `InferredType::InstanceType`.
257    // As part of a separate type inference phase this will be converted back to `Expr::Call` with fully
258    // qualified function names (the complex version) which further takes part in all other type inference phases.
259    InvokeMethodLazy {
260        lhs: Box<Expr>,
261        method: String,
262        generic_type_parameter: Option<GenericTypeParameter>,
263        args: Vec<Expr>,
264        type_annotation: Option<TypeName>,
265        inferred_type: InferredType,
266        source_span: SourceSpan,
267    },
268    Unwrap {
269        expr: Box<Expr>,
270        inferred_type: InferredType,
271        type_annotation: Option<TypeName>,
272        source_span: SourceSpan,
273    },
274    Throw {
275        message: String,
276        inferred_type: InferredType,
277        type_annotation: Option<TypeName>,
278        source_span: SourceSpan,
279    },
280    GetTag {
281        expr: Box<Expr>,
282        inferred_type: InferredType,
283        type_annotation: Option<TypeName>,
284        source_span: SourceSpan,
285    },
286    ListComprehension {
287        iterated_variable: VariableId,
288        iterable_expr: Box<Expr>,
289        yield_expr: Box<Expr>,
290        type_annotation: Option<TypeName>,
291        inferred_type: InferredType,
292        source_span: SourceSpan,
293    },
294    ListReduce {
295        reduce_variable: VariableId,
296        iterated_variable: VariableId,
297        iterable_expr: Box<Expr>,
298        type_annotation: Option<TypeName>,
299        yield_expr: Box<Expr>,
300        init_value_expr: Box<Expr>,
301        inferred_type: InferredType,
302        source_span: SourceSpan,
303    },
304    Length {
305        expr: Box<Expr>,
306        inferred_type: InferredType,
307        type_annotation: Option<TypeName>,
308        source_span: SourceSpan,
309    },
310
311    GenerateWorkerName {
312        inferred_type: InferredType,
313        type_annotation: Option<TypeName>,
314        source_span: SourceSpan,
315        variable_id: Option<VariableId>,
316    },
317}
318
319impl Expr {
320    pub fn as_record(&self) -> Option<Vec<(String, Expr)>> {
321        match self {
322            Expr::Record { exprs: fields, .. } => Some(
323                fields
324                    .iter()
325                    .map(|(k, v)| (k.clone(), v.deref().clone()))
326                    .collect::<Vec<_>>(),
327            ),
328            _ => None,
329        }
330    }
331    /// Parse a text directly as Rib expression
332    /// Example of a Rib expression:
333    ///
334    /// ```rib
335    ///   let shopping-cart-worker = instance("my-worker");
336    ///   let result = shopping-cart-worker.add-to-cart({product-name: "apple", quantity: 2});
337    ///
338    ///   match result {
339    ///     ok(id) => "product-id-${id}",
340    ///     err(error_msg) => "Error: ${error_msg}"
341    ///   }
342    /// ```
343    ///
344    /// Rib supports conditional calls, function calls, pattern-matching,
345    /// string interpolation (see error_message above) etc.
346    ///
347    pub fn from_text(input: &str) -> Result<Expr, String> {
348        if input.trim().ends_with(';') {
349            return Err("unexpected `;` at the end of rib expression. \nnote: `;` is used to separate expressions, but it should not appear after the last expression (which is the return value)".to_string());
350        }
351
352        spaces()
353            .with(block().skip(eof()))
354            .easy_parse(position::Stream::new(input))
355            .map(|t| t.0)
356            .map_err(|err| format!("{err}"))
357    }
358
359    pub fn lookup(&self, source_span: &SourceSpan) -> Option<Expr> {
360        let mut expr = self.clone();
361        find_expr(&mut expr, source_span)
362    }
363
364    pub fn is_literal(&self) -> bool {
365        matches!(self, Expr::Literal { .. })
366    }
367
368    pub fn is_block(&self) -> bool {
369        matches!(self, Expr::ExprBlock { .. })
370    }
371
372    pub fn is_number(&self) -> bool {
373        matches!(self, Expr::Number { .. })
374    }
375
376    pub fn is_record(&self) -> bool {
377        matches!(self, Expr::Record { .. })
378    }
379
380    pub fn is_result(&self) -> bool {
381        matches!(self, Expr::Result { .. })
382    }
383
384    pub fn is_option(&self) -> bool {
385        matches!(self, Expr::Option { .. })
386    }
387
388    pub fn is_tuple(&self) -> bool {
389        matches!(self, Expr::Tuple { .. })
390    }
391
392    pub fn is_list(&self) -> bool {
393        matches!(self, Expr::Sequence { .. })
394    }
395
396    pub fn is_flags(&self) -> bool {
397        matches!(self, Expr::Flags { .. })
398    }
399
400    pub fn is_identifier(&self) -> bool {
401        matches!(self, Expr::Identifier { .. })
402    }
403
404    pub fn is_select_field(&self) -> bool {
405        matches!(self, Expr::SelectField { .. })
406    }
407
408    pub fn is_if_else(&self) -> bool {
409        matches!(self, Expr::Cond { .. })
410    }
411
412    pub fn is_function_call(&self) -> bool {
413        matches!(self, Expr::Call { .. })
414    }
415
416    pub fn is_match_expr(&self) -> bool {
417        matches!(self, Expr::PatternMatch { .. })
418    }
419
420    pub fn is_boolean(&self) -> bool {
421        matches!(self, Expr::Boolean { .. })
422    }
423
424    pub fn is_comparison(&self) -> bool {
425        matches!(
426            self,
427            Expr::GreaterThan { .. }
428                | Expr::GreaterThanOrEqualTo { .. }
429                | Expr::LessThanOrEqualTo { .. }
430                | Expr::EqualTo { .. }
431                | Expr::LessThan { .. }
432        )
433    }
434
435    pub fn is_concat(&self) -> bool {
436        matches!(self, Expr::Concat { .. })
437    }
438
439    pub fn is_multiple(&self) -> bool {
440        matches!(self, Expr::ExprBlock { .. })
441    }
442
443    pub fn inbuilt_variant(&self) -> Option<(String, Option<Expr>)> {
444        match self {
445            Expr::Option {
446                expr: Some(expr), ..
447            } => Some(("some".to_string(), Some(expr.deref().clone()))),
448            Expr::Option { expr: None, .. } => Some(("some".to_string(), None)),
449            Expr::Result { expr: Ok(expr), .. } => {
450                Some(("ok".to_string(), Some(expr.deref().clone())))
451            }
452            Expr::Result {
453                expr: Err(expr), ..
454            } => Some(("err".to_string(), Some(expr.deref().clone()))),
455            _ => None,
456        }
457    }
458    pub fn unwrap(&self) -> Self {
459        Expr::Unwrap {
460            expr: Box::new(self.clone()),
461            inferred_type: InferredType::unknown(),
462            source_span: SourceSpan::default(),
463            type_annotation: None,
464        }
465    }
466
467    pub fn length(expr: Expr) -> Self {
468        Expr::Length {
469            expr: Box::new(expr),
470            inferred_type: InferredType::u64(),
471            source_span: SourceSpan::default(),
472            type_annotation: None,
473        }
474    }
475
476    pub fn boolean(value: bool) -> Self {
477        Expr::Boolean {
478            value,
479            inferred_type: InferredType::bool(),
480            source_span: SourceSpan::default(),
481            type_annotation: None,
482        }
483    }
484
485    pub fn and(left: Expr, right: Expr) -> Self {
486        Expr::And {
487            lhs: Box::new(left),
488            rhs: Box::new(right),
489            inferred_type: InferredType::bool(),
490            source_span: SourceSpan::default(),
491            type_annotation: None,
492        }
493    }
494
495    pub fn throw(message: impl AsRef<str>) -> Self {
496        Expr::Throw {
497            message: message.as_ref().to_string(),
498            inferred_type: InferredType::unknown(),
499            source_span: SourceSpan::default(),
500            type_annotation: None,
501        }
502    }
503
504    pub fn generate_worker_name(variable_id: Option<VariableId>) -> Self {
505        Expr::GenerateWorkerName {
506            inferred_type: InferredType::string(),
507            type_annotation: None,
508            source_span: SourceSpan::default(),
509            variable_id,
510        }
511    }
512
513    pub fn plus(left: Expr, right: Expr) -> Self {
514        Expr::Plus {
515            lhs: Box::new(left),
516            rhs: Box::new(right),
517            inferred_type: InferredType::unknown(),
518            source_span: SourceSpan::default(),
519            type_annotation: None,
520        }
521    }
522
523    pub fn minus(left: Expr, right: Expr) -> Self {
524        Expr::Minus {
525            lhs: Box::new(left),
526            rhs: Box::new(right),
527            inferred_type: InferredType::unknown(),
528            source_span: SourceSpan::default(),
529            type_annotation: None,
530        }
531    }
532
533    pub fn divide(left: Expr, right: Expr) -> Self {
534        Expr::Divide {
535            lhs: Box::new(left),
536            rhs: Box::new(right),
537            inferred_type: InferredType::unknown(),
538            source_span: SourceSpan::default(),
539            type_annotation: None,
540        }
541    }
542
543    pub fn multiply(left: Expr, right: Expr) -> Self {
544        Expr::Multiply {
545            lhs: Box::new(left),
546            rhs: Box::new(right),
547            inferred_type: InferredType::unknown(),
548            source_span: SourceSpan::default(),
549            type_annotation: None,
550        }
551    }
552
553    pub fn and_combine(conditions: Vec<Expr>) -> Option<Expr> {
554        let mut cond: Option<Expr> = None;
555
556        for i in conditions {
557            let left = Box::new(cond.clone().unwrap_or(Expr::boolean(true)));
558            cond = Some(Expr::And {
559                lhs: left,
560                rhs: Box::new(i),
561                inferred_type: InferredType::bool(),
562                source_span: SourceSpan::default(),
563                type_annotation: None,
564            });
565        }
566
567        cond
568    }
569
570    pub fn call_worker_function(
571        dynamic_parsed_fn_name: DynamicParsedFunctionName,
572        generic_type_parameter: Option<GenericTypeParameter>,
573        module_identifier: Option<InstanceIdentifier>,
574        args: Vec<Expr>,
575        component_info: Option<ComponentDependencyKey>,
576    ) -> Self {
577        Expr::Call {
578            call_type: CallType::Function {
579                function_name: dynamic_parsed_fn_name,
580                instance_identifier: module_identifier.map(Box::new),
581                component_info,
582            },
583            generic_type_parameter,
584            args,
585            inferred_type: InferredType::unknown(),
586            source_span: SourceSpan::default(),
587            type_annotation: None,
588        }
589    }
590
591    pub fn call(
592        call_type: CallType,
593        generic_type_parameter: Option<GenericTypeParameter>,
594        args: Vec<Expr>,
595    ) -> Self {
596        Expr::Call {
597            call_type,
598            generic_type_parameter,
599            args,
600            inferred_type: InferredType::unknown(),
601            source_span: SourceSpan::default(),
602            type_annotation: None,
603        }
604    }
605
606    pub fn invoke_worker_function(
607        lhs: Expr,
608        function_name: String,
609        generic_type_parameter: Option<GenericTypeParameter>,
610        args: Vec<Expr>,
611    ) -> Self {
612        Expr::InvokeMethodLazy {
613            lhs: Box::new(lhs),
614            method: function_name,
615            generic_type_parameter,
616            args,
617            inferred_type: InferredType::unknown(),
618            source_span: SourceSpan::default(),
619            type_annotation: None,
620        }
621    }
622
623    pub fn concat(expressions: Vec<Expr>) -> Self {
624        Expr::Concat {
625            exprs: expressions,
626            inferred_type: InferredType::string(),
627            source_span: SourceSpan::default(),
628            type_annotation: None,
629        }
630    }
631
632    pub fn cond(cond: Expr, lhs: Expr, rhs: Expr) -> Self {
633        Expr::Cond {
634            cond: Box::new(cond),
635            lhs: Box::new(lhs),
636            rhs: Box::new(rhs),
637            inferred_type: InferredType::unknown(),
638            source_span: SourceSpan::default(),
639            type_annotation: None,
640        }
641    }
642
643    pub fn equal_to(left: Expr, right: Expr) -> Self {
644        Expr::EqualTo {
645            lhs: Box::new(left),
646            rhs: Box::new(right),
647            inferred_type: InferredType::bool(),
648            source_span: SourceSpan::default(),
649            type_annotation: None,
650        }
651    }
652
653    pub fn err(expr: Expr, type_annotation: Option<TypeName>) -> Self {
654        let inferred_type = expr.inferred_type();
655        Expr::Result {
656            expr: Err(Box::new(expr)),
657            type_annotation,
658            inferred_type: InferredType::result(Some(InferredType::unknown()), Some(inferred_type)),
659            source_span: SourceSpan::default(),
660        }
661    }
662
663    pub fn flags(flags: Vec<String>) -> Self {
664        Expr::Flags {
665            flags: flags.clone(),
666            inferred_type: InferredType::flags(flags),
667            source_span: SourceSpan::default(),
668            type_annotation: None,
669        }
670    }
671
672    pub fn greater_than(left: Expr, right: Expr) -> Self {
673        Expr::GreaterThan {
674            lhs: Box::new(left),
675            rhs: Box::new(right),
676            inferred_type: InferredType::bool(),
677            source_span: SourceSpan::default(),
678            type_annotation: None,
679        }
680    }
681
682    pub fn greater_than_or_equal_to(left: Expr, right: Expr) -> Self {
683        Expr::GreaterThanOrEqualTo {
684            lhs: Box::new(left),
685            rhs: Box::new(right),
686            inferred_type: InferredType::bool(),
687            source_span: SourceSpan::default(),
688            type_annotation: None,
689        }
690    }
691
692    // An identifier by default is global until name-binding phase is run
693    pub fn identifier_global(name: impl AsRef<str>, type_annotation: Option<TypeName>) -> Self {
694        Expr::Identifier {
695            variable_id: VariableId::global(name.as_ref().to_string()),
696            type_annotation,
697            inferred_type: InferredType::unknown(),
698            source_span: SourceSpan::default(),
699        }
700    }
701
702    pub fn identifier_local(
703        name: impl AsRef<str>,
704        id: u32,
705        type_annotation: Option<TypeName>,
706    ) -> Self {
707        Expr::Identifier {
708            variable_id: VariableId::local(name.as_ref(), id),
709            type_annotation,
710            inferred_type: InferredType::unknown(),
711            source_span: SourceSpan::default(),
712        }
713    }
714
715    pub fn identifier_with_variable_id(
716        variable_id: VariableId,
717        type_annotation: Option<TypeName>,
718    ) -> Self {
719        Expr::Identifier {
720            variable_id,
721            type_annotation,
722            inferred_type: InferredType::unknown(),
723            source_span: SourceSpan::default(),
724        }
725    }
726
727    pub fn less_than(left: Expr, right: Expr) -> Self {
728        Expr::LessThan {
729            lhs: Box::new(left),
730            rhs: Box::new(right),
731            inferred_type: InferredType::bool(),
732            source_span: SourceSpan::default(),
733            type_annotation: None,
734        }
735    }
736
737    pub fn less_than_or_equal_to(left: Expr, right: Expr) -> Self {
738        Expr::LessThanOrEqualTo {
739            lhs: Box::new(left),
740            rhs: Box::new(right),
741            inferred_type: InferredType::bool(),
742            source_span: SourceSpan::default(),
743            type_annotation: None,
744        }
745    }
746
747    pub fn range(from: Expr, to: Expr) -> Self {
748        Expr::Range {
749            range: Range::Range {
750                from: Box::new(from.clone()),
751                to: Box::new(to.clone()),
752            },
753            inferred_type: InferredType::range(from.inferred_type(), Some(to.inferred_type())),
754            source_span: SourceSpan::default(),
755            type_annotation: None,
756        }
757    }
758
759    pub fn range_from(from: Expr) -> Self {
760        Expr::Range {
761            range: Range::RangeFrom {
762                from: Box::new(from.clone()),
763            },
764            inferred_type: InferredType::range(from.inferred_type(), None),
765            source_span: SourceSpan::default(),
766            type_annotation: None,
767        }
768    }
769
770    pub fn range_inclusive(from: Expr, to: Expr) -> Self {
771        Expr::Range {
772            range: Range::RangeInclusive {
773                from: Box::new(from.clone()),
774                to: Box::new(to.clone()),
775            },
776            inferred_type: InferredType::range(from.inferred_type(), Some(to.inferred_type())),
777            source_span: SourceSpan::default(),
778            type_annotation: None,
779        }
780    }
781
782    pub fn let_binding(
783        name: impl AsRef<str>,
784        expr: Expr,
785        type_annotation: Option<TypeName>,
786    ) -> Self {
787        Expr::Let {
788            variable_id: VariableId::global(name.as_ref().to_string()),
789            type_annotation,
790            expr: Box::new(expr),
791            source_span: SourceSpan::default(),
792            inferred_type: InferredType::tuple(vec![]),
793        }
794    }
795
796    pub fn let_binding_with_variable_id(
797        variable_id: VariableId,
798        expr: Expr,
799        type_annotation: Option<TypeName>,
800    ) -> Self {
801        Expr::Let {
802            variable_id,
803            type_annotation,
804            expr: Box::new(expr),
805            source_span: SourceSpan::default(),
806            inferred_type: InferredType::tuple(vec![]),
807        }
808    }
809
810    pub fn typed_list_reduce(
811        reduce_variable: VariableId,
812        iterated_variable: VariableId,
813        iterable_expr: Expr,
814        init_value_expr: Expr,
815        yield_expr: Expr,
816        inferred_type: InferredType,
817    ) -> Self {
818        Expr::ListReduce {
819            reduce_variable,
820            iterated_variable,
821            iterable_expr: Box::new(iterable_expr),
822            yield_expr: Box::new(yield_expr),
823            init_value_expr: Box::new(init_value_expr),
824            inferred_type,
825            source_span: SourceSpan::default(),
826            type_annotation: None,
827        }
828    }
829
830    pub fn list_reduce(
831        reduce_variable: VariableId,
832        iterated_variable: VariableId,
833        iterable_expr: Expr,
834        init_value_expr: Expr,
835        yield_expr: Expr,
836    ) -> Self {
837        Expr::typed_list_reduce(
838            reduce_variable,
839            iterated_variable,
840            iterable_expr,
841            init_value_expr,
842            yield_expr,
843            InferredType::unknown(),
844        )
845    }
846
847    pub fn list_comprehension_typed(
848        iterated_variable: VariableId,
849        iterable_expr: Expr,
850        yield_expr: Expr,
851        inferred_type: InferredType,
852    ) -> Self {
853        Expr::ListComprehension {
854            iterated_variable,
855            iterable_expr: Box::new(iterable_expr),
856            yield_expr: Box::new(yield_expr),
857            inferred_type,
858            source_span: SourceSpan::default(),
859            type_annotation: None,
860        }
861    }
862
863    pub fn list_comprehension(
864        variable_id: VariableId,
865        iterable_expr: Expr,
866        yield_expr: Expr,
867    ) -> Self {
868        Expr::list_comprehension_typed(
869            variable_id,
870            iterable_expr,
871            yield_expr,
872            InferredType::list(InferredType::unknown()),
873        )
874    }
875
876    pub fn bind_global_variable_types(&mut self, type_spec: &Vec<GlobalVariableTypeSpec>) {
877        type_inference::bind_global_variable_types(self, type_spec)
878    }
879
880    pub fn bind_instance_types(&mut self) {
881        type_inference::bind_instance_types(self)
882    }
883
884    pub fn literal(value: impl AsRef<str>) -> Self {
885        let default_type = DefaultType::String;
886
887        Expr::Literal {
888            value: value.as_ref().to_string(),
889            inferred_type: InferredType::from(&default_type),
890            source_span: SourceSpan::default(),
891            type_annotation: None,
892        }
893    }
894
895    pub fn empty_expr() -> Self {
896        Expr::literal("")
897    }
898
899    pub fn expr_block(expressions: Vec<Expr>) -> Self {
900        let inferred_type = expressions
901            .last()
902            .map_or(InferredType::unknown(), |e| e.inferred_type());
903
904        Expr::ExprBlock {
905            exprs: expressions,
906            inferred_type,
907            source_span: SourceSpan::default(),
908            type_annotation: None,
909        }
910    }
911
912    #[allow(clippy::should_implement_trait)]
913    pub fn not(expr: Expr) -> Self {
914        Expr::Not {
915            expr: Box::new(expr),
916            inferred_type: InferredType::bool(),
917            source_span: SourceSpan::default(),
918            type_annotation: None,
919        }
920    }
921
922    pub fn ok(expr: Expr, type_annotation: Option<TypeName>) -> Self {
923        let inferred_type = expr.inferred_type();
924
925        Expr::Result {
926            expr: Ok(Box::new(expr)),
927            type_annotation,
928            inferred_type: InferredType::result(Some(inferred_type), Some(InferredType::unknown())),
929            source_span: SourceSpan::default(),
930        }
931    }
932
933    pub fn option(expr: Option<Expr>) -> Self {
934        let inferred_type = match &expr {
935            Some(expr) => expr.inferred_type(),
936            None => InferredType::unknown(),
937        };
938
939        Expr::Option {
940            expr: expr.map(Box::new),
941            type_annotation: None,
942            inferred_type: InferredType::option(inferred_type),
943            source_span: SourceSpan::default(),
944        }
945    }
946
947    pub fn or(left: Expr, right: Expr) -> Self {
948        Expr::Or {
949            lhs: Box::new(left),
950            rhs: Box::new(right),
951            inferred_type: InferredType::bool(),
952            source_span: SourceSpan::default(),
953            type_annotation: None,
954        }
955    }
956
957    pub fn pattern_match(expr: Expr, match_arms: Vec<MatchArm>) -> Self {
958        Expr::PatternMatch {
959            predicate: Box::new(expr),
960            match_arms,
961            inferred_type: InferredType::unknown(),
962            source_span: SourceSpan::default(),
963            type_annotation: None,
964        }
965    }
966
967    pub fn record(expressions: Vec<(String, Expr)>) -> Self {
968        let inferred_type = InferredType::record(
969            expressions
970                .iter()
971                .map(|(field_name, expr)| (field_name.to_string(), expr.inferred_type()))
972                .collect(),
973        );
974
975        Expr::Record {
976            exprs: expressions
977                .into_iter()
978                .map(|(field_name, expr)| (field_name, Box::new(expr)))
979                .collect(),
980            inferred_type,
981            source_span: SourceSpan::default(),
982            type_annotation: None,
983        }
984    }
985
986    pub fn select_field(
987        expr: Expr,
988        field: impl AsRef<str>,
989        type_annotation: Option<TypeName>,
990    ) -> Self {
991        Expr::SelectField {
992            expr: Box::new(expr),
993            field: field.as_ref().to_string(),
994            type_annotation,
995            inferred_type: InferredType::unknown(),
996            source_span: SourceSpan::default(),
997        }
998    }
999
1000    pub fn select_index(expr: Expr, index: Expr) -> Self {
1001        Expr::SelectIndex {
1002            expr: Box::new(expr),
1003            index: Box::new(index),
1004            type_annotation: None,
1005            inferred_type: InferredType::unknown(),
1006            source_span: SourceSpan::default(),
1007        }
1008    }
1009
1010    pub fn get_tag(expr: Expr) -> Self {
1011        Expr::GetTag {
1012            expr: Box::new(expr),
1013            inferred_type: InferredType::unknown(),
1014            source_span: SourceSpan::default(),
1015            type_annotation: None,
1016        }
1017    }
1018
1019    pub fn tuple(expressions: Vec<Expr>) -> Self {
1020        let inferred_type = InferredType::tuple(
1021            expressions
1022                .iter()
1023                .map(|expr| expr.inferred_type())
1024                .collect(),
1025        );
1026
1027        Expr::Tuple {
1028            exprs: expressions,
1029            inferred_type,
1030            source_span: SourceSpan::default(),
1031            type_annotation: None,
1032        }
1033    }
1034
1035    pub fn sequence(expressions: Vec<Expr>, type_annotation: Option<TypeName>) -> Self {
1036        let inferred_type = InferredType::list(
1037            expressions
1038                .first()
1039                .map_or(InferredType::unknown(), |x| x.inferred_type()),
1040        );
1041
1042        Expr::Sequence {
1043            exprs: expressions,
1044            type_annotation,
1045            inferred_type,
1046            source_span: SourceSpan::default(),
1047        }
1048    }
1049
1050    pub fn inferred_type_mut(&mut self) -> &mut InferredType {
1051        match self {
1052            Expr::Let { inferred_type, .. }
1053            | Expr::SelectField { inferred_type, .. }
1054            | Expr::SelectIndex { inferred_type, .. }
1055            | Expr::Sequence { inferred_type, .. }
1056            | Expr::Record { inferred_type, .. }
1057            | Expr::Tuple { inferred_type, .. }
1058            | Expr::Literal { inferred_type, .. }
1059            | Expr::Number { inferred_type, .. }
1060            | Expr::Flags { inferred_type, .. }
1061            | Expr::Identifier { inferred_type, .. }
1062            | Expr::Boolean { inferred_type, .. }
1063            | Expr::Concat { inferred_type, .. }
1064            | Expr::ExprBlock { inferred_type, .. }
1065            | Expr::Not { inferred_type, .. }
1066            | Expr::GreaterThan { inferred_type, .. }
1067            | Expr::GreaterThanOrEqualTo { inferred_type, .. }
1068            | Expr::LessThanOrEqualTo { inferred_type, .. }
1069            | Expr::EqualTo { inferred_type, .. }
1070            | Expr::Plus { inferred_type, .. }
1071            | Expr::Minus { inferred_type, .. }
1072            | Expr::Divide { inferred_type, .. }
1073            | Expr::Multiply { inferred_type, .. }
1074            | Expr::LessThan { inferred_type, .. }
1075            | Expr::Cond { inferred_type, .. }
1076            | Expr::PatternMatch { inferred_type, .. }
1077            | Expr::Option { inferred_type, .. }
1078            | Expr::Result { inferred_type, .. }
1079            | Expr::Unwrap { inferred_type, .. }
1080            | Expr::Throw { inferred_type, .. }
1081            | Expr::GetTag { inferred_type, .. }
1082            | Expr::And { inferred_type, .. }
1083            | Expr::Or { inferred_type, .. }
1084            | Expr::ListComprehension { inferred_type, .. }
1085            | Expr::ListReduce { inferred_type, .. }
1086            | Expr::Call { inferred_type, .. }
1087            | Expr::Range { inferred_type, .. }
1088            | Expr::InvokeMethodLazy { inferred_type, .. }
1089            | Expr::Length { inferred_type, .. }
1090            | Expr::GenerateWorkerName { inferred_type, .. } => &mut *inferred_type,
1091        }
1092    }
1093
1094    pub fn inferred_type(&self) -> InferredType {
1095        match self {
1096            Expr::Let { inferred_type, .. }
1097            | Expr::SelectField { inferred_type, .. }
1098            | Expr::SelectIndex { inferred_type, .. }
1099            | Expr::Sequence { inferred_type, .. }
1100            | Expr::Record { inferred_type, .. }
1101            | Expr::Tuple { inferred_type, .. }
1102            | Expr::Literal { inferred_type, .. }
1103            | Expr::Number { inferred_type, .. }
1104            | Expr::Flags { inferred_type, .. }
1105            | Expr::Identifier { inferred_type, .. }
1106            | Expr::Boolean { inferred_type, .. }
1107            | Expr::Concat { inferred_type, .. }
1108            | Expr::ExprBlock { inferred_type, .. }
1109            | Expr::Not { inferred_type, .. }
1110            | Expr::GreaterThan { inferred_type, .. }
1111            | Expr::GreaterThanOrEqualTo { inferred_type, .. }
1112            | Expr::LessThanOrEqualTo { inferred_type, .. }
1113            | Expr::EqualTo { inferred_type, .. }
1114            | Expr::Plus { inferred_type, .. }
1115            | Expr::Minus { inferred_type, .. }
1116            | Expr::Divide { inferred_type, .. }
1117            | Expr::Multiply { inferred_type, .. }
1118            | Expr::LessThan { inferred_type, .. }
1119            | Expr::Cond { inferred_type, .. }
1120            | Expr::PatternMatch { inferred_type, .. }
1121            | Expr::Option { inferred_type, .. }
1122            | Expr::Result { inferred_type, .. }
1123            | Expr::Unwrap { inferred_type, .. }
1124            | Expr::Throw { inferred_type, .. }
1125            | Expr::GetTag { inferred_type, .. }
1126            | Expr::And { inferred_type, .. }
1127            | Expr::Or { inferred_type, .. }
1128            | Expr::ListComprehension { inferred_type, .. }
1129            | Expr::ListReduce { inferred_type, .. }
1130            | Expr::Call { inferred_type, .. }
1131            | Expr::Range { inferred_type, .. }
1132            | Expr::InvokeMethodLazy { inferred_type, .. }
1133            | Expr::Length { inferred_type, .. }
1134            | Expr::GenerateWorkerName { inferred_type, .. } => inferred_type.clone(),
1135        }
1136    }
1137
1138    pub fn infer_types(
1139        &mut self,
1140        component_dependency: &ComponentDependencies,
1141        type_spec: &Vec<GlobalVariableTypeSpec>,
1142    ) -> Result<(), RibTypeErrorInternal> {
1143        self.infer_types_initial_phase(component_dependency, type_spec)?;
1144        self.bind_instance_types();
1145        // Identifying the first fix point with method calls to infer all
1146        // worker function invocations as this forms the foundation for the rest of the
1147        // compilation. This is compiler doing its best to infer all the calls such
1148        // as worker invokes or instance calls etc.
1149        self.resolve_method_calls()?;
1150        type_inference::type_inference_fix_point(Self::resolve_method_calls, self)?;
1151        self.infer_function_call_types(component_dependency)?;
1152        type_inference::type_inference_fix_point(Self::inference_scan, self)?;
1153        self.check_types(component_dependency)?;
1154        self.unify_types()?;
1155        Ok(())
1156    }
1157
1158    pub fn infer_types_initial_phase(
1159        &mut self,
1160        component_dependency: &ComponentDependencies,
1161        type_spec: &Vec<GlobalVariableTypeSpec>,
1162    ) -> Result<(), RibTypeErrorInternal> {
1163        self.set_origin();
1164        self.bind_global_variable_types(type_spec);
1165        self.bind_type_annotations();
1166        self.bind_variables_of_list_comprehension();
1167        self.bind_variables_of_list_reduce();
1168        self.bind_variables_of_pattern_match();
1169        self.bind_variables_of_let_assignment();
1170        self.identify_instance_creation(component_dependency)?;
1171        self.ensure_stateful_instance();
1172        self.infer_variants(component_dependency);
1173        self.infer_enums(component_dependency);
1174        Ok(())
1175    }
1176
1177    pub fn resolve_method_calls(&mut self) -> Result<(), RibTypeErrorInternal> {
1178        self.bind_instance_types();
1179        self.infer_worker_function_invokes()?;
1180        Ok(())
1181    }
1182
1183    pub fn set_origin(&mut self) {
1184        let mut visitor = ExprVisitor::bottom_up(self);
1185
1186        while let Some(expr) = visitor.pop_front() {
1187            let source_location = expr.source_span();
1188            let origin = TypeOrigin::OriginatedAt(source_location.clone());
1189            let inferred_type = expr.inferred_type();
1190            let origin = inferred_type.add_origin(origin);
1191            expr.with_inferred_type_mut(origin);
1192        }
1193    }
1194
1195    // An inference is a single cycle of to-and-fro scanning of Rib expression, that it takes part in fix point of inference.
1196    // Not all phases of compilation will be part of this scan.
1197    // Example: function call argument inference based on the worker function hardly needs to be part of the scan.
1198    pub fn inference_scan(&mut self) -> Result<(), RibTypeErrorInternal> {
1199        self.infer_all_identifiers();
1200        self.push_types_down()?;
1201        self.infer_all_identifiers();
1202        self.pull_types_up()?;
1203        self.infer_global_inputs();
1204        Ok(())
1205    }
1206
1207    pub fn infer_worker_function_invokes(&mut self) -> Result<(), RibTypeErrorInternal> {
1208        type_inference::infer_worker_function_invokes(self)
1209    }
1210
1211    // Make sure the bindings in the arm pattern of a pattern match are given variable-ids.
1212    // The same variable-ids will be tagged to the corresponding identifiers in the arm resolution
1213    // to avoid conflicts.
1214    pub fn bind_variables_of_pattern_match(&mut self) {
1215        type_inference::bind_variables_of_pattern_match(self);
1216    }
1217
1218    // Make sure the variable assignment (let binding) are given variable ids,
1219    // which will be tagged to the corresponding identifiers to avoid conflicts.
1220    // This is done only for local variables and not global variables
1221    pub fn bind_variables_of_let_assignment(&mut self) {
1222        type_inference::bind_variables_of_let_assignment(self);
1223    }
1224
1225    pub fn bind_variables_of_list_comprehension(&mut self) {
1226        type_inference::bind_variables_of_list_comprehension(self);
1227    }
1228
1229    pub fn bind_variables_of_list_reduce(&mut self) {
1230        type_inference::bind_variables_of_list_reduce(self);
1231    }
1232
1233    pub fn identify_instance_creation(
1234        &mut self,
1235        component_dependency: &ComponentDependencies,
1236    ) -> Result<(), RibTypeErrorInternal> {
1237        type_inference::identify_instance_creation(self, component_dependency)
1238    }
1239
1240    pub fn ensure_stateful_instance(&mut self) {
1241        type_inference::ensure_stateful_instance(self)
1242    }
1243
1244    pub fn infer_function_call_types(
1245        &mut self,
1246        component_dependency: &ComponentDependencies,
1247    ) -> Result<(), RibTypeErrorInternal> {
1248        type_inference::infer_function_call_types(self, component_dependency)?;
1249        Ok(())
1250    }
1251
1252    pub fn push_types_down(&mut self) -> Result<(), RibTypeErrorInternal> {
1253        type_inference::push_types_down(self)
1254    }
1255
1256    pub fn infer_all_identifiers(&mut self) {
1257        type_inference::infer_all_identifiers(self)
1258    }
1259
1260    pub fn pull_types_up(&mut self) -> Result<(), RibTypeErrorInternal> {
1261        type_inference::type_pull_up(self)
1262    }
1263
1264    pub fn infer_global_inputs(&mut self) {
1265        type_inference::infer_global_inputs(self);
1266    }
1267
1268    pub fn bind_type_annotations(&mut self) {
1269        type_inference::bind_type_annotations(self);
1270    }
1271
1272    pub fn check_types(
1273        &mut self,
1274        component_dependency: &ComponentDependencies,
1275    ) -> Result<(), RibTypeErrorInternal> {
1276        type_checker::type_check(self, component_dependency)
1277    }
1278
1279    pub fn unify_types(&mut self) -> Result<(), RibTypeErrorInternal> {
1280        type_inference::unify_types(self)?;
1281        Ok(())
1282    }
1283
1284    pub fn merge_inferred_type(&self, new_inferred_type: InferredType) -> Expr {
1285        let mut expr_copied = self.clone();
1286        expr_copied.add_infer_type_mut(new_inferred_type);
1287        expr_copied
1288    }
1289
1290    pub fn add_infer_type_mut(&mut self, new_inferred_type: InferredType) {
1291        match self {
1292            Expr::Identifier { inferred_type, .. }
1293            | Expr::Let { inferred_type, .. }
1294            | Expr::SelectField { inferred_type, .. }
1295            | Expr::SelectIndex { inferred_type, .. }
1296            | Expr::Sequence { inferred_type, .. }
1297            | Expr::Record { inferred_type, .. }
1298            | Expr::Tuple { inferred_type, .. }
1299            | Expr::Literal { inferred_type, .. }
1300            | Expr::Number { inferred_type, .. }
1301            | Expr::Flags { inferred_type, .. }
1302            | Expr::Boolean { inferred_type, .. }
1303            | Expr::Concat { inferred_type, .. }
1304            | Expr::ExprBlock { inferred_type, .. }
1305            | Expr::Not { inferred_type, .. }
1306            | Expr::GreaterThan { inferred_type, .. }
1307            | Expr::GreaterThanOrEqualTo { inferred_type, .. }
1308            | Expr::LessThanOrEqualTo { inferred_type, .. }
1309            | Expr::EqualTo { inferred_type, .. }
1310            | Expr::Plus { inferred_type, .. }
1311            | Expr::Minus { inferred_type, .. }
1312            | Expr::Divide { inferred_type, .. }
1313            | Expr::Multiply { inferred_type, .. }
1314            | Expr::LessThan { inferred_type, .. }
1315            | Expr::Cond { inferred_type, .. }
1316            | Expr::PatternMatch { inferred_type, .. }
1317            | Expr::Option { inferred_type, .. }
1318            | Expr::Result { inferred_type, .. }
1319            | Expr::Unwrap { inferred_type, .. }
1320            | Expr::Throw { inferred_type, .. }
1321            | Expr::GetTag { inferred_type, .. }
1322            | Expr::And { inferred_type, .. }
1323            | Expr::Or { inferred_type, .. }
1324            | Expr::ListComprehension { inferred_type, .. }
1325            | Expr::ListReduce { inferred_type, .. }
1326            | Expr::InvokeMethodLazy { inferred_type, .. }
1327            | Expr::Range { inferred_type, .. }
1328            | Expr::Length { inferred_type, .. }
1329            | Expr::GenerateWorkerName { inferred_type, .. }
1330            | Expr::Call { inferred_type, .. } => {
1331                if !new_inferred_type.is_unknown() {
1332                    *inferred_type = inferred_type.merge(new_inferred_type);
1333                }
1334            }
1335        }
1336    }
1337
1338    pub fn reset_type(&mut self) {
1339        type_inference::reset_type_info(self);
1340    }
1341
1342    pub fn source_span(&self) -> SourceSpan {
1343        match self {
1344            Expr::Identifier { source_span, .. }
1345            | Expr::Let { source_span, .. }
1346            | Expr::SelectField { source_span, .. }
1347            | Expr::SelectIndex { source_span, .. }
1348            | Expr::Sequence { source_span, .. }
1349            | Expr::Record { source_span, .. }
1350            | Expr::Tuple { source_span, .. }
1351            | Expr::Literal { source_span, .. }
1352            | Expr::Number { source_span, .. }
1353            | Expr::Flags { source_span, .. }
1354            | Expr::Boolean { source_span, .. }
1355            | Expr::Concat { source_span, .. }
1356            | Expr::ExprBlock { source_span, .. }
1357            | Expr::Not { source_span, .. }
1358            | Expr::GreaterThan { source_span, .. }
1359            | Expr::GreaterThanOrEqualTo { source_span, .. }
1360            | Expr::LessThanOrEqualTo { source_span, .. }
1361            | Expr::EqualTo { source_span, .. }
1362            | Expr::LessThan { source_span, .. }
1363            | Expr::Plus { source_span, .. }
1364            | Expr::Minus { source_span, .. }
1365            | Expr::Divide { source_span, .. }
1366            | Expr::Multiply { source_span, .. }
1367            | Expr::Cond { source_span, .. }
1368            | Expr::PatternMatch { source_span, .. }
1369            | Expr::Option { source_span, .. }
1370            | Expr::Result { source_span, .. }
1371            | Expr::Unwrap { source_span, .. }
1372            | Expr::Throw { source_span, .. }
1373            | Expr::And { source_span, .. }
1374            | Expr::Or { source_span, .. }
1375            | Expr::GetTag { source_span, .. }
1376            | Expr::ListComprehension { source_span, .. }
1377            | Expr::ListReduce { source_span, .. }
1378            | Expr::InvokeMethodLazy { source_span, .. }
1379            | Expr::Range { source_span, .. }
1380            | Expr::Length { source_span, .. }
1381            | Expr::Call { source_span, .. }
1382            | Expr::GenerateWorkerName { source_span, .. } => source_span.clone(),
1383        }
1384    }
1385
1386    pub fn type_annotation(&self) -> &Option<TypeName> {
1387        match self {
1388            Expr::Identifier {
1389                type_annotation, ..
1390            }
1391            | Expr::Let {
1392                type_annotation, ..
1393            }
1394            | Expr::SelectField {
1395                type_annotation, ..
1396            }
1397            | Expr::SelectIndex {
1398                type_annotation, ..
1399            }
1400            | Expr::Sequence {
1401                type_annotation, ..
1402            }
1403            | Expr::Record {
1404                type_annotation, ..
1405            }
1406            | Expr::Tuple {
1407                type_annotation, ..
1408            }
1409            | Expr::Literal {
1410                type_annotation, ..
1411            }
1412            | Expr::Number {
1413                type_annotation, ..
1414            }
1415            | Expr::Flags {
1416                type_annotation, ..
1417            }
1418            | Expr::Boolean {
1419                type_annotation, ..
1420            }
1421            | Expr::Concat {
1422                type_annotation, ..
1423            }
1424            | Expr::ExprBlock {
1425                type_annotation, ..
1426            }
1427            | Expr::Not {
1428                type_annotation, ..
1429            }
1430            | Expr::GreaterThan {
1431                type_annotation, ..
1432            }
1433            | Expr::GreaterThanOrEqualTo {
1434                type_annotation, ..
1435            }
1436            | Expr::LessThanOrEqualTo {
1437                type_annotation, ..
1438            }
1439            | Expr::EqualTo {
1440                type_annotation, ..
1441            }
1442            | Expr::LessThan {
1443                type_annotation, ..
1444            }
1445            | Expr::Plus {
1446                type_annotation, ..
1447            }
1448            | Expr::Minus {
1449                type_annotation, ..
1450            }
1451            | Expr::Divide {
1452                type_annotation, ..
1453            }
1454            | Expr::Multiply {
1455                type_annotation, ..
1456            }
1457            | Expr::Cond {
1458                type_annotation, ..
1459            }
1460            | Expr::PatternMatch {
1461                type_annotation, ..
1462            }
1463            | Expr::Option {
1464                type_annotation, ..
1465            }
1466            | Expr::Result {
1467                type_annotation, ..
1468            }
1469            | Expr::Unwrap {
1470                type_annotation, ..
1471            }
1472            | Expr::Throw {
1473                type_annotation, ..
1474            }
1475            | Expr::And {
1476                type_annotation, ..
1477            }
1478            | Expr::Or {
1479                type_annotation, ..
1480            }
1481            | Expr::GetTag {
1482                type_annotation, ..
1483            }
1484            | Expr::ListComprehension {
1485                type_annotation, ..
1486            }
1487            | Expr::ListReduce {
1488                type_annotation, ..
1489            }
1490            | Expr::InvokeMethodLazy {
1491                type_annotation, ..
1492            }
1493            | Expr::Range {
1494                type_annotation, ..
1495            }
1496            | Expr::Length {
1497                type_annotation, ..
1498            }
1499            | Expr::GenerateWorkerName {
1500                type_annotation, ..
1501            }
1502            | Expr::Call {
1503                type_annotation, ..
1504            } => type_annotation,
1505        }
1506    }
1507
1508    pub fn with_type_annotation_opt(&self, type_annotation: Option<TypeName>) -> Expr {
1509        if let Some(type_annotation) = type_annotation {
1510            self.with_type_annotation(type_annotation)
1511        } else {
1512            self.clone()
1513        }
1514    }
1515
1516    pub fn with_type_annotation(&self, type_annotation: TypeName) -> Expr {
1517        let mut expr_copied = self.clone();
1518        expr_copied.with_type_annotation_mut(type_annotation);
1519        expr_copied
1520    }
1521
1522    pub fn with_type_annotation_mut(&mut self, type_annotation: TypeName) {
1523        let new_type_annotation = type_annotation;
1524
1525        match self {
1526            Expr::Identifier {
1527                type_annotation, ..
1528            }
1529            | Expr::Let {
1530                type_annotation, ..
1531            }
1532            | Expr::SelectField {
1533                type_annotation, ..
1534            }
1535            | Expr::SelectIndex {
1536                type_annotation, ..
1537            }
1538            | Expr::Sequence {
1539                type_annotation, ..
1540            }
1541            | Expr::Record {
1542                type_annotation, ..
1543            }
1544            | Expr::Tuple {
1545                type_annotation, ..
1546            }
1547            | Expr::Literal {
1548                type_annotation, ..
1549            }
1550            | Expr::Number {
1551                type_annotation, ..
1552            }
1553            | Expr::Flags {
1554                type_annotation, ..
1555            }
1556            | Expr::Boolean {
1557                type_annotation, ..
1558            }
1559            | Expr::Concat {
1560                type_annotation, ..
1561            }
1562            | Expr::ExprBlock {
1563                type_annotation, ..
1564            }
1565            | Expr::Not {
1566                type_annotation, ..
1567            }
1568            | Expr::GreaterThan {
1569                type_annotation, ..
1570            }
1571            | Expr::GreaterThanOrEqualTo {
1572                type_annotation, ..
1573            }
1574            | Expr::LessThanOrEqualTo {
1575                type_annotation, ..
1576            }
1577            | Expr::EqualTo {
1578                type_annotation, ..
1579            }
1580            | Expr::LessThan {
1581                type_annotation, ..
1582            }
1583            | Expr::Plus {
1584                type_annotation, ..
1585            }
1586            | Expr::Minus {
1587                type_annotation, ..
1588            }
1589            | Expr::Divide {
1590                type_annotation, ..
1591            }
1592            | Expr::Multiply {
1593                type_annotation, ..
1594            }
1595            | Expr::Cond {
1596                type_annotation, ..
1597            }
1598            | Expr::PatternMatch {
1599                type_annotation, ..
1600            }
1601            | Expr::Option {
1602                type_annotation, ..
1603            }
1604            | Expr::Result {
1605                type_annotation, ..
1606            }
1607            | Expr::Unwrap {
1608                type_annotation, ..
1609            }
1610            | Expr::Throw {
1611                type_annotation, ..
1612            }
1613            | Expr::And {
1614                type_annotation, ..
1615            }
1616            | Expr::Or {
1617                type_annotation, ..
1618            }
1619            | Expr::GetTag {
1620                type_annotation, ..
1621            }
1622            | Expr::Range {
1623                type_annotation, ..
1624            }
1625            | Expr::ListComprehension {
1626                type_annotation, ..
1627            }
1628            | Expr::ListReduce {
1629                type_annotation, ..
1630            }
1631            | Expr::InvokeMethodLazy {
1632                type_annotation, ..
1633            }
1634            | Expr::Length {
1635                type_annotation, ..
1636            }
1637            | Expr::GenerateWorkerName {
1638                type_annotation, ..
1639            }
1640            | Expr::Call {
1641                type_annotation, ..
1642            } => {
1643                *type_annotation = Some(new_type_annotation);
1644            }
1645        }
1646    }
1647
1648    pub fn with_source_span(&self, new_source_span: SourceSpan) -> Expr {
1649        let mut expr_copied = self.clone();
1650        expr_copied.with_source_span_mut(new_source_span);
1651        expr_copied
1652    }
1653
1654    pub fn with_source_span_mut(&mut self, new_source_span: SourceSpan) {
1655        match self {
1656            Expr::Identifier { source_span, .. }
1657            | Expr::Let { source_span, .. }
1658            | Expr::SelectField { source_span, .. }
1659            | Expr::SelectIndex { source_span, .. }
1660            | Expr::Sequence { source_span, .. }
1661            | Expr::Number { source_span, .. }
1662            | Expr::Record { source_span, .. }
1663            | Expr::Tuple { source_span, .. }
1664            | Expr::Literal { source_span, .. }
1665            | Expr::Flags { source_span, .. }
1666            | Expr::Boolean { source_span, .. }
1667            | Expr::Concat { source_span, .. }
1668            | Expr::ExprBlock { source_span, .. }
1669            | Expr::Not { source_span, .. }
1670            | Expr::GreaterThan { source_span, .. }
1671            | Expr::GreaterThanOrEqualTo { source_span, .. }
1672            | Expr::LessThanOrEqualTo { source_span, .. }
1673            | Expr::EqualTo { source_span, .. }
1674            | Expr::LessThan { source_span, .. }
1675            | Expr::Plus { source_span, .. }
1676            | Expr::Minus { source_span, .. }
1677            | Expr::Divide { source_span, .. }
1678            | Expr::Multiply { source_span, .. }
1679            | Expr::Cond { source_span, .. }
1680            | Expr::PatternMatch { source_span, .. }
1681            | Expr::Option { source_span, .. }
1682            | Expr::Result { source_span, .. }
1683            | Expr::Unwrap { source_span, .. }
1684            | Expr::Throw { source_span, .. }
1685            | Expr::And { source_span, .. }
1686            | Expr::Or { source_span, .. }
1687            | Expr::GetTag { source_span, .. }
1688            | Expr::Range { source_span, .. }
1689            | Expr::ListComprehension { source_span, .. }
1690            | Expr::ListReduce { source_span, .. }
1691            | Expr::InvokeMethodLazy { source_span, .. }
1692            | Expr::Length { source_span, .. }
1693            | Expr::GenerateWorkerName { source_span, .. }
1694            | Expr::Call { source_span, .. } => {
1695                *source_span = new_source_span;
1696            }
1697        }
1698    }
1699
1700    pub fn with_inferred_type(&self, new_inferred_type: InferredType) -> Expr {
1701        let mut expr_copied = self.clone();
1702        expr_copied.with_inferred_type_mut(new_inferred_type);
1703        expr_copied
1704    }
1705
1706    // `with_inferred_type` overrides the existing inferred_type and returns a new expr
1707    // This is different to `merge_inferred_type` where it tries to combine the new inferred type with the existing one.
1708    pub fn with_inferred_type_mut(&mut self, new_inferred_type: InferredType) {
1709        match self {
1710            Expr::Identifier { inferred_type, .. }
1711            | Expr::Let { inferred_type, .. }
1712            | Expr::SelectField { inferred_type, .. }
1713            | Expr::SelectIndex { inferred_type, .. }
1714            | Expr::Sequence { inferred_type, .. }
1715            | Expr::Record { inferred_type, .. }
1716            | Expr::Tuple { inferred_type, .. }
1717            | Expr::Literal { inferred_type, .. }
1718            | Expr::Number { inferred_type, .. }
1719            | Expr::Flags { inferred_type, .. }
1720            | Expr::Boolean { inferred_type, .. }
1721            | Expr::Concat { inferred_type, .. }
1722            | Expr::ExprBlock { inferred_type, .. }
1723            | Expr::Not { inferred_type, .. }
1724            | Expr::GreaterThan { inferred_type, .. }
1725            | Expr::GreaterThanOrEqualTo { inferred_type, .. }
1726            | Expr::LessThanOrEqualTo { inferred_type, .. }
1727            | Expr::EqualTo { inferred_type, .. }
1728            | Expr::LessThan { inferred_type, .. }
1729            | Expr::Plus { inferred_type, .. }
1730            | Expr::Minus { inferred_type, .. }
1731            | Expr::Divide { inferred_type, .. }
1732            | Expr::Multiply { inferred_type, .. }
1733            | Expr::Cond { inferred_type, .. }
1734            | Expr::PatternMatch { inferred_type, .. }
1735            | Expr::Option { inferred_type, .. }
1736            | Expr::Result { inferred_type, .. }
1737            | Expr::Unwrap { inferred_type, .. }
1738            | Expr::Throw { inferred_type, .. }
1739            | Expr::And { inferred_type, .. }
1740            | Expr::Or { inferred_type, .. }
1741            | Expr::GetTag { inferred_type, .. }
1742            | Expr::ListComprehension { inferred_type, .. }
1743            | Expr::ListReduce { inferred_type, .. }
1744            | Expr::InvokeMethodLazy { inferred_type, .. }
1745            | Expr::Range { inferred_type, .. }
1746            | Expr::Length { inferred_type, .. }
1747            | Expr::GenerateWorkerName { inferred_type, .. }
1748            | Expr::Call { inferred_type, .. } => {
1749                *inferred_type = new_inferred_type;
1750            }
1751        }
1752    }
1753
1754    pub fn infer_enums(&mut self, component_dependency: &ComponentDependencies) {
1755        type_inference::infer_enums(self, component_dependency);
1756    }
1757
1758    pub fn infer_variants(&mut self, component_dependency: &ComponentDependencies) {
1759        type_inference::infer_variants(self, component_dependency);
1760    }
1761
1762    pub fn visit_expr_nodes_lazy<'a>(&'a mut self, queue: &mut VecDeque<&'a mut Expr>) {
1763        type_inference::visit_expr_nodes_lazy(self, queue);
1764    }
1765
1766    pub fn number_inferred(
1767        big_decimal: BigDecimal,
1768        type_annotation: Option<TypeName>,
1769        inferred_type: InferredType,
1770    ) -> Expr {
1771        Expr::Number {
1772            number: Number { value: big_decimal },
1773            type_annotation,
1774            inferred_type,
1775            source_span: SourceSpan::default(),
1776        }
1777    }
1778
1779    pub fn number(big_decimal: BigDecimal) -> Expr {
1780        let default_type = DefaultType::from(&big_decimal);
1781        let inferred_type = InferredType::from(&default_type);
1782
1783        Expr::number_inferred(big_decimal, None, inferred_type)
1784    }
1785}
1786
1787#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord)]
1788pub enum Range {
1789    Range { from: Box<Expr>, to: Box<Expr> },
1790    RangeInclusive { from: Box<Expr>, to: Box<Expr> },
1791    RangeFrom { from: Box<Expr> },
1792}
1793
1794impl Range {
1795    pub fn from(&self) -> Option<&Expr> {
1796        match self {
1797            Range::Range { from, .. } => Some(from),
1798            Range::RangeInclusive { from, .. } => Some(from),
1799            Range::RangeFrom { from } => Some(from),
1800        }
1801    }
1802
1803    pub fn to(&self) -> Option<&Expr> {
1804        match self {
1805            Range::Range { to, .. } => Some(to),
1806            Range::RangeInclusive { to, .. } => Some(to),
1807            Range::RangeFrom { .. } => None,
1808        }
1809    }
1810
1811    pub fn inclusive(&self) -> bool {
1812        matches!(self, Range::RangeInclusive { .. })
1813    }
1814
1815    pub fn get_exprs_mut(&mut self) -> Vec<&mut Box<Expr>> {
1816        match self {
1817            Range::Range { from, to } => vec![from, to],
1818            Range::RangeInclusive { from, to } => vec![from, to],
1819            Range::RangeFrom { from } => vec![from],
1820        }
1821    }
1822
1823    pub fn get_exprs(&self) -> Vec<&Expr> {
1824        match self {
1825            Range::Range { from, to } => vec![from.as_ref(), to.as_ref()],
1826            Range::RangeInclusive { from, to } => vec![from.as_ref(), to.as_ref()],
1827            Range::RangeFrom { from } => vec![from.as_ref()],
1828        }
1829    }
1830}
1831
1832#[derive(Debug, Hash, Clone, PartialEq, Ord, PartialOrd)]
1833pub struct Number {
1834    pub value: BigDecimal,
1835}
1836
1837impl Eq for Number {}
1838
1839impl Number {
1840    pub fn to_val(&self, analysed_type: &AnalysedType) -> Option<ValueAndType> {
1841        match analysed_type {
1842            AnalysedType::F64(_) => self.value.to_f64().map(|v| v.into_value_and_type()),
1843            AnalysedType::U64(_) => self.value.to_u64().map(|v| v.into_value_and_type()),
1844            AnalysedType::F32(_) => self.value.to_f32().map(|v| v.into_value_and_type()),
1845            AnalysedType::U32(_) => self.value.to_u32().map(|v| v.into_value_and_type()),
1846            AnalysedType::S32(_) => self.value.to_i32().map(|v| v.into_value_and_type()),
1847            AnalysedType::S64(_) => self.value.to_i64().map(|v| v.into_value_and_type()),
1848            AnalysedType::U8(_) => self.value.to_u8().map(|v| v.into_value_and_type()),
1849            AnalysedType::S8(_) => self.value.to_i8().map(|v| v.into_value_and_type()),
1850            AnalysedType::U16(_) => self.value.to_u16().map(|v| v.into_value_and_type()),
1851            AnalysedType::S16(_) => self.value.to_i16().map(|v| v.into_value_and_type()),
1852            _ => None,
1853        }
1854    }
1855}
1856
1857impl Display for Number {
1858    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1859        write!(f, "{}", self.value)
1860    }
1861}
1862
1863#[derive(Debug, Hash, Clone, PartialEq, Eq, Ord, PartialOrd)]
1864pub struct MatchArm {
1865    pub arm_pattern: ArmPattern,
1866    pub arm_resolution_expr: Box<Expr>,
1867}
1868
1869impl MatchArm {
1870    pub fn new(arm_pattern: ArmPattern, arm_resolution: Expr) -> MatchArm {
1871        MatchArm {
1872            arm_pattern,
1873            arm_resolution_expr: Box::new(arm_resolution),
1874        }
1875    }
1876}
1877#[derive(Debug, Hash, Clone, PartialEq, Eq, Ord, PartialOrd)]
1878pub enum ArmPattern {
1879    WildCard,
1880    As(String, Box<ArmPattern>),
1881    Constructor(String, Vec<ArmPattern>),
1882    TupleConstructor(Vec<ArmPattern>),
1883    RecordConstructor(Vec<(String, ArmPattern)>),
1884    ListConstructor(Vec<ArmPattern>),
1885    Literal(Box<Expr>),
1886}
1887
1888impl ArmPattern {
1889    pub fn is_wildcard(&self) -> bool {
1890        matches!(self, ArmPattern::WildCard)
1891    }
1892
1893    pub fn is_literal_identifier(&self) -> bool {
1894        matches!(self, ArmPattern::Literal(expr) if expr.is_identifier())
1895    }
1896
1897    pub fn constructor(name: &str, patterns: Vec<ArmPattern>) -> ArmPattern {
1898        ArmPattern::Constructor(name.to_string(), patterns)
1899    }
1900
1901    pub fn literal(expr: Expr) -> ArmPattern {
1902        ArmPattern::Literal(Box::new(expr))
1903    }
1904
1905    pub fn get_expr_literals_mut(&mut self) -> Vec<&mut Box<Expr>> {
1906        match self {
1907            ArmPattern::Literal(expr) => vec![expr],
1908            ArmPattern::As(_, pattern) => pattern.get_expr_literals_mut(),
1909            ArmPattern::Constructor(_, patterns) => {
1910                let mut result = vec![];
1911                for pattern in patterns {
1912                    result.extend(pattern.get_expr_literals_mut());
1913                }
1914                result
1915            }
1916            ArmPattern::TupleConstructor(patterns) => {
1917                let mut result = vec![];
1918                for pattern in patterns {
1919                    result.extend(pattern.get_expr_literals_mut());
1920                }
1921                result
1922            }
1923            ArmPattern::RecordConstructor(patterns) => {
1924                let mut result = vec![];
1925                for (_, pattern) in patterns {
1926                    result.extend(pattern.get_expr_literals_mut());
1927                }
1928                result
1929            }
1930            ArmPattern::ListConstructor(patterns) => {
1931                let mut result = vec![];
1932                for pattern in patterns {
1933                    result.extend(pattern.get_expr_literals_mut());
1934                }
1935                result
1936            }
1937            ArmPattern::WildCard => vec![],
1938        }
1939    }
1940
1941    pub fn get_expr_literals(&self) -> Vec<&Expr> {
1942        match self {
1943            ArmPattern::Literal(expr) => vec![expr.as_ref()],
1944            ArmPattern::As(_, pattern) => pattern.get_expr_literals(),
1945            ArmPattern::Constructor(_, patterns) => {
1946                let mut result = vec![];
1947                for pattern in patterns {
1948                    result.extend(pattern.get_expr_literals());
1949                }
1950                result
1951            }
1952            ArmPattern::TupleConstructor(patterns) => {
1953                let mut result = vec![];
1954                for pattern in patterns {
1955                    result.extend(pattern.get_expr_literals());
1956                }
1957                result
1958            }
1959            ArmPattern::RecordConstructor(patterns) => {
1960                let mut result = vec![];
1961                for (_, pattern) in patterns {
1962                    result.extend(pattern.get_expr_literals());
1963                }
1964                result
1965            }
1966            ArmPattern::ListConstructor(patterns) => {
1967                let mut result = vec![];
1968                for pattern in patterns {
1969                    result.extend(pattern.get_expr_literals());
1970                }
1971                result
1972            }
1973            ArmPattern::WildCard => vec![],
1974        }
1975    }
1976    // Helper to construct ok(v). Cannot be used if there is nested constructors such as ok(some(v)))
1977    pub fn ok(binding_variable: &str) -> ArmPattern {
1978        ArmPattern::Literal(Box::new(Expr::Result {
1979            expr: Ok(Box::new(Expr::Identifier {
1980                variable_id: VariableId::global(binding_variable.to_string()),
1981                type_annotation: None,
1982                inferred_type: InferredType::unknown(),
1983                source_span: SourceSpan::default(),
1984            })),
1985            type_annotation: None,
1986            inferred_type: InferredType::result(
1987                Some(InferredType::unknown()),
1988                Some(InferredType::unknown()),
1989            ),
1990            source_span: SourceSpan::default(),
1991        }))
1992    }
1993
1994    // Helper to construct err(v). Cannot be used if there is nested constructors such as err(some(v)))
1995    pub fn err(binding_variable: &str) -> ArmPattern {
1996        ArmPattern::Literal(Box::new(Expr::Result {
1997            expr: Err(Box::new(Expr::Identifier {
1998                variable_id: VariableId::global(binding_variable.to_string()),
1999                type_annotation: None,
2000                inferred_type: InferredType::unknown(),
2001                source_span: SourceSpan::default(),
2002            })),
2003            type_annotation: None,
2004            inferred_type: InferredType::result(
2005                Some(InferredType::unknown()),
2006                Some(InferredType::unknown()),
2007            ),
2008            source_span: SourceSpan::default(),
2009        }))
2010    }
2011
2012    // Helper to construct some(v). Cannot be used if there is nested constructors such as some(ok(v)))
2013    pub fn some(binding_variable: &str) -> ArmPattern {
2014        ArmPattern::Literal(Box::new(Expr::Option {
2015            expr: Some(Box::new(Expr::Identifier {
2016                variable_id: VariableId::local_with_no_id(binding_variable),
2017                type_annotation: None,
2018                inferred_type: InferredType::unknown(),
2019                source_span: SourceSpan::default(),
2020            })),
2021            type_annotation: None,
2022            inferred_type: InferredType::unknown(),
2023            source_span: SourceSpan::default(),
2024        }))
2025    }
2026
2027    pub fn none() -> ArmPattern {
2028        ArmPattern::Literal(Box::new(Expr::Option {
2029            expr: None,
2030            type_annotation: None,
2031            inferred_type: InferredType::unknown(),
2032            source_span: SourceSpan::default(),
2033        }))
2034    }
2035
2036    pub fn identifier(binding_variable: &str) -> ArmPattern {
2037        ArmPattern::Literal(Box::new(Expr::Identifier {
2038            variable_id: VariableId::global(binding_variable.to_string()),
2039            type_annotation: None,
2040            inferred_type: InferredType::unknown(),
2041            source_span: SourceSpan::default(),
2042        }))
2043    }
2044    pub fn custom_constructor(name: &str, args: Vec<ArmPattern>) -> ArmPattern {
2045        ArmPattern::Constructor(name.to_string(), args)
2046    }
2047}
2048
2049#[cfg(feature = "protobuf")]
2050impl TryFrom<golem_api_grpc::proto::golem::rib::Expr> for Expr {
2051    type Error = String;
2052
2053    fn try_from(value: golem_api_grpc::proto::golem::rib::Expr) -> Result<Self, Self::Error> {
2054        let expr = value.expr.ok_or("Missing expr")?;
2055
2056        let expr = match expr {
2057            golem_api_grpc::proto::golem::rib::expr::Expr::Let(expr) => {
2058                let name = expr.name;
2059                let type_annotation = expr.type_name.map(TypeName::try_from).transpose()?;
2060                let expr_: golem_api_grpc::proto::golem::rib::Expr =
2061                    *expr.expr.ok_or("Missing expr")?;
2062                let expr: Expr = expr_.try_into()?;
2063                Expr::let_binding(name, expr, type_annotation)
2064            }
2065
2066            golem_api_grpc::proto::golem::rib::expr::Expr::SelectIndexV1(expr) => {
2067                let selection = *expr.expr.ok_or("Missing expr")?;
2068                let field = *expr.index.ok_or("Missing index")?;
2069                let type_annotation = expr.type_name.map(TypeName::try_from).transpose()?;
2070
2071                Expr::select_index(selection.try_into()?, field.try_into()?)
2072                    .with_type_annotation_opt(type_annotation)
2073            }
2074
2075            golem_api_grpc::proto::golem::rib::expr::Expr::Length(expr) => {
2076                let expr = expr.expr.ok_or("Missing expr")?;
2077                Expr::Length {
2078                    expr: Box::new((*expr).try_into()?),
2079                    type_annotation: None,
2080                    inferred_type: InferredType::unknown(),
2081                    source_span: SourceSpan::default(),
2082                }
2083            }
2084
2085            golem_api_grpc::proto::golem::rib::expr::Expr::Range(range) => {
2086                let range_expr = range.range_expr.ok_or("Missing range expr")?;
2087
2088                match range_expr {
2089                    RangeExpr::RangeFrom(range_from) => {
2090                        let from = range_from.from.ok_or("Missing from expr")?;
2091                        Expr::range_from((*from).try_into()?)
2092                    }
2093                    RangeExpr::Range(range) => {
2094                        let from = range.from.ok_or("Missing from expr")?;
2095                        let to = range.to.ok_or("Missing to expr")?;
2096                        Expr::range((*from).try_into()?, (*to).try_into()?)
2097                    }
2098                    RangeExpr::RangeInclusive(range_inclusive) => {
2099                        let from = range_inclusive.from.ok_or("Missing from expr")?;
2100                        let to = range_inclusive.to.ok_or("Missing to expr")?;
2101                        Expr::range_inclusive((*from).try_into()?, (*to).try_into()?)
2102                    }
2103                }
2104            }
2105
2106            golem_api_grpc::proto::golem::rib::expr::Expr::Not(expr) => {
2107                let expr = expr.expr.ok_or("Missing expr")?;
2108                Expr::not((*expr).try_into()?)
2109            }
2110
2111            golem_api_grpc::proto::golem::rib::expr::Expr::GreaterThan(expr) => {
2112                let left = expr.left.ok_or("Missing left expr")?;
2113                let right = expr.right.ok_or("Missing right expr")?;
2114                Expr::greater_than((*left).try_into()?, (*right).try_into()?)
2115            }
2116
2117            golem_api_grpc::proto::golem::rib::expr::Expr::GreaterThanOrEqual(expr) => {
2118                let left = expr.left.ok_or("Missing left expr")?;
2119                let right = expr.right.ok_or("Missing right expr")?;
2120                Expr::greater_than_or_equal_to((*left).try_into()?, (*right).try_into()?)
2121            }
2122
2123            golem_api_grpc::proto::golem::rib::expr::Expr::LessThan(expr) => {
2124                let left = expr.left.ok_or("Missing left expr")?;
2125                let right = expr.right.ok_or("Missing right expr")?;
2126                Expr::less_than((*left).try_into()?, (*right).try_into()?)
2127            }
2128
2129            golem_api_grpc::proto::golem::rib::expr::Expr::LessThanOrEqual(expr) => {
2130                let left = expr.left.ok_or("Missing left expr")?;
2131                let right = expr.right.ok_or("Missing right expr")?;
2132                Expr::less_than_or_equal_to((*left).try_into()?, (*right).try_into()?)
2133            }
2134
2135            golem_api_grpc::proto::golem::rib::expr::Expr::EqualTo(expr) => {
2136                let left = expr.left.ok_or("Missing left expr")?;
2137                let right = expr.right.ok_or("Missing right expr")?;
2138                Expr::equal_to((*left).try_into()?, (*right).try_into()?)
2139            }
2140
2141            golem_api_grpc::proto::golem::rib::expr::Expr::Add(expr) => {
2142                let left = expr.left.ok_or("Missing left expr")?;
2143                let right = expr.right.ok_or("Missing right expr")?;
2144                Expr::plus((*left).try_into()?, (*right).try_into()?)
2145            }
2146
2147            golem_api_grpc::proto::golem::rib::expr::Expr::Subtract(expr) => {
2148                let left = expr.left.ok_or("Missing left expr")?;
2149                let right = expr.right.ok_or("Missing right expr")?;
2150                Expr::plus((*left).try_into()?, (*right).try_into()?)
2151            }
2152
2153            golem_api_grpc::proto::golem::rib::expr::Expr::Divide(expr) => {
2154                let left = expr.left.ok_or("Missing left expr")?;
2155                let right = expr.right.ok_or("Missing right expr")?;
2156                Expr::plus((*left).try_into()?, (*right).try_into()?)
2157            }
2158
2159            golem_api_grpc::proto::golem::rib::expr::Expr::Multiply(expr) => {
2160                let left = expr.left.ok_or("Missing left expr")?;
2161                let right = expr.right.ok_or("Missing right expr")?;
2162                Expr::plus((*left).try_into()?, (*right).try_into()?)
2163            }
2164
2165            golem_api_grpc::proto::golem::rib::expr::Expr::Cond(expr) => {
2166                let left = expr.left.ok_or("Missing left expr")?;
2167                let cond = expr.cond.ok_or("Missing cond expr")?;
2168                let right = expr.right.ok_or("Missing right expr")?;
2169                Expr::cond(
2170                    (*left).try_into()?,
2171                    (*cond).try_into()?,
2172                    (*right).try_into()?,
2173                )
2174            }
2175
2176            golem_api_grpc::proto::golem::rib::expr::Expr::Concat(
2177                golem_api_grpc::proto::golem::rib::ConcatExpr { exprs },
2178            ) => {
2179                let exprs: Vec<Expr> = exprs
2180                    .into_iter()
2181                    .map(|expr| expr.try_into())
2182                    .collect::<Result<Vec<_>, _>>()?;
2183                Expr::concat(exprs)
2184            }
2185
2186            golem_api_grpc::proto::golem::rib::expr::Expr::Multiple(
2187                golem_api_grpc::proto::golem::rib::MultipleExpr { exprs },
2188            ) => {
2189                let exprs: Vec<Expr> = exprs
2190                    .into_iter()
2191                    .map(|expr| expr.try_into())
2192                    .collect::<Result<Vec<_>, _>>()?;
2193                Expr::expr_block(exprs)
2194            }
2195
2196            golem_api_grpc::proto::golem::rib::expr::Expr::Sequence(
2197                golem_api_grpc::proto::golem::rib::SequenceExpr { exprs, type_name },
2198            ) => {
2199                let type_annotation = type_name.map(TypeName::try_from).transpose()?;
2200
2201                let exprs: Vec<Expr> = exprs
2202                    .into_iter()
2203                    .map(|expr| expr.try_into())
2204                    .collect::<Result<Vec<_>, _>>()?;
2205                Expr::sequence(exprs, type_annotation)
2206            }
2207
2208            golem_api_grpc::proto::golem::rib::expr::Expr::Tuple(
2209                golem_api_grpc::proto::golem::rib::TupleExpr { exprs },
2210            ) => {
2211                let exprs: Vec<Expr> = exprs
2212                    .into_iter()
2213                    .map(|expr| expr.try_into())
2214                    .collect::<Result<Vec<_>, _>>()?;
2215                Expr::tuple(exprs)
2216            }
2217
2218            golem_api_grpc::proto::golem::rib::expr::Expr::Record(
2219                golem_api_grpc::proto::golem::rib::RecordExpr { fields },
2220            ) => {
2221                let mut values: Vec<(String, Expr)> = vec![];
2222                for record in fields.into_iter() {
2223                    let name = record.name;
2224                    let expr = record.expr.ok_or("Missing expr")?;
2225                    values.push((name, expr.try_into()?));
2226                }
2227                Expr::record(values)
2228            }
2229
2230            golem_api_grpc::proto::golem::rib::expr::Expr::Flags(
2231                golem_api_grpc::proto::golem::rib::FlagsExpr { values },
2232            ) => Expr::flags(values),
2233
2234            golem_api_grpc::proto::golem::rib::expr::Expr::Literal(
2235                golem_api_grpc::proto::golem::rib::LiteralExpr { value },
2236            ) => Expr::literal(value),
2237
2238            golem_api_grpc::proto::golem::rib::expr::Expr::Identifier(
2239                golem_api_grpc::proto::golem::rib::IdentifierExpr { name, type_name },
2240            ) => {
2241                let type_name = type_name.map(TypeName::try_from).transpose()?;
2242
2243                Expr::identifier_global(name.as_str(), type_name)
2244            }
2245
2246            golem_api_grpc::proto::golem::rib::expr::Expr::Boolean(
2247                golem_api_grpc::proto::golem::rib::BooleanExpr { value },
2248            ) => Expr::boolean(value),
2249
2250            golem_api_grpc::proto::golem::rib::expr::Expr::Throw(
2251                golem_api_grpc::proto::golem::rib::ThrowExpr { message },
2252            ) => Expr::throw(message),
2253
2254            golem_api_grpc::proto::golem::rib::expr::Expr::GenerateWorkerName(
2255                golem_api_grpc::proto::golem::rib::GenerateWorkerNameExpr {},
2256            ) => Expr::generate_worker_name(None),
2257
2258            golem_api_grpc::proto::golem::rib::expr::Expr::And(expr) => {
2259                let left = expr.left.ok_or("Missing left expr")?;
2260                let right = expr.right.ok_or("Missing right expr")?;
2261                Expr::and((*left).try_into()?, (*right).try_into()?)
2262            }
2263
2264            golem_api_grpc::proto::golem::rib::expr::Expr::Or(expr) => {
2265                let left = expr.left.ok_or("Missing left expr")?;
2266                let right = expr.right.ok_or("Missing right expr")?;
2267                Expr::or((*left).try_into()?, (*right).try_into()?)
2268            }
2269
2270            golem_api_grpc::proto::golem::rib::expr::Expr::Tag(expr) => {
2271                let expr = expr.expr.ok_or("Missing expr in tag")?;
2272                Expr::get_tag((*expr).try_into()?)
2273            }
2274
2275            golem_api_grpc::proto::golem::rib::expr::Expr::Unwrap(expr) => {
2276                let expr = expr.expr.ok_or("Missing expr")?;
2277                let expr: Expr = (*expr).try_into()?;
2278                expr.unwrap()
2279            }
2280
2281            golem_api_grpc::proto::golem::rib::expr::Expr::Number(number) => {
2282                // Backward compatibility
2283                let type_name = number.type_name.map(TypeName::try_from).transpose()?;
2284                let big_decimal = if let Some(number) = number.number {
2285                    BigDecimal::from_str(&number).map_err(|e| e.to_string())?
2286                } else if let Some(float) = number.float {
2287                    BigDecimal::from_f64(float).ok_or("Invalid float")?
2288                } else {
2289                    return Err("Missing number".to_string());
2290                };
2291
2292                Expr::number(big_decimal).with_type_annotation_opt(type_name)
2293            }
2294            golem_api_grpc::proto::golem::rib::expr::Expr::SelectField(expr) => {
2295                let expr = *expr;
2296                let field = expr.field;
2297                let type_name = expr.type_name.map(TypeName::try_from).transpose()?;
2298                let expr = *expr.expr.ok_or(
2299                    "Mi\
2300                ssing expr",
2301                )?;
2302
2303                Expr::select_field(expr.try_into()?, field.as_str(), type_name)
2304            }
2305            golem_api_grpc::proto::golem::rib::expr::Expr::SelectIndex(expr) => {
2306                let expr = *expr;
2307                let type_name = expr.type_name.map(TypeName::try_from).transpose()?;
2308                let index = expr.index as usize;
2309                let expr = *expr.expr.ok_or("Missing expr")?;
2310
2311                let index_expr =
2312                    Expr::number(BigDecimal::from_usize(index).ok_or("Invalid index")?);
2313
2314                Expr::select_index(expr.try_into()?, index_expr).with_type_annotation_opt(type_name)
2315            }
2316            golem_api_grpc::proto::golem::rib::expr::Expr::Option(expr) => {
2317                let type_name = expr.type_name;
2318                let type_name = type_name.map(TypeName::try_from).transpose()?;
2319
2320                match expr.expr {
2321                    Some(expr) => {
2322                        Expr::option(Some((*expr).try_into()?)).with_type_annotation_opt(type_name)
2323                    }
2324                    None => Expr::option(None).with_type_annotation_opt(type_name),
2325                }
2326            }
2327            golem_api_grpc::proto::golem::rib::expr::Expr::Result(expr) => {
2328                let type_name = expr.type_name;
2329                let type_name = type_name.map(TypeName::try_from).transpose()?;
2330                let result = expr.result.ok_or("Missing result")?;
2331                match result {
2332                    golem_api_grpc::proto::golem::rib::result_expr::Result::Ok(expr) => {
2333                        Expr::ok((*expr).try_into()?, type_name)
2334                    }
2335                    golem_api_grpc::proto::golem::rib::result_expr::Result::Err(expr) => {
2336                        Expr::err((*expr).try_into()?, type_name)
2337                    }
2338                }
2339            }
2340            golem_api_grpc::proto::golem::rib::expr::Expr::PatternMatch(expr) => {
2341                let patterns: Vec<MatchArm> = expr
2342                    .patterns
2343                    .into_iter()
2344                    .map(|expr| expr.try_into())
2345                    .collect::<Result<Vec<_>, _>>()?;
2346                let expr = expr.expr.ok_or("Missing expr")?;
2347                Expr::pattern_match((*expr).try_into()?, patterns)
2348            }
2349            golem_api_grpc::proto::golem::rib::expr::Expr::ListComprehension(
2350                list_comprehension,
2351            ) => {
2352                let iterable_expr = list_comprehension.iterable_expr.ok_or("Missing expr")?;
2353                let iterable_expr = (*iterable_expr).try_into()?;
2354                let yield_expr = list_comprehension.yield_expr.ok_or("Missing list")?;
2355                let yield_expr = (*yield_expr).try_into()?;
2356                let variable_id =
2357                    VariableId::list_comprehension_identifier(list_comprehension.iterated_variable);
2358                Expr::list_comprehension(variable_id, iterable_expr, yield_expr)
2359            }
2360            golem_api_grpc::proto::golem::rib::expr::Expr::ListReduce(list_reduce) => {
2361                let init_value_expr = list_reduce.init_value_expr.ok_or("Missing initial expr")?;
2362                let init_value_expr = (*init_value_expr).try_into()?;
2363                let iterable_expr = list_reduce.iterable_expr.ok_or("Missing expr")?;
2364                let iterable_expr = (*iterable_expr).try_into()?;
2365                let yield_expr = list_reduce.yield_expr.ok_or("Missing list")?;
2366                let yield_expr = (*yield_expr).try_into()?;
2367                let iterated_variable_id =
2368                    VariableId::list_comprehension_identifier(list_reduce.iterated_variable);
2369                let reduce_variable_id =
2370                    VariableId::list_reduce_identifier(list_reduce.reduce_variable);
2371                Expr::list_reduce(
2372                    reduce_variable_id,
2373                    iterated_variable_id,
2374                    iterable_expr,
2375                    init_value_expr,
2376                    yield_expr,
2377                )
2378            }
2379            golem_api_grpc::proto::golem::rib::expr::Expr::Call(expr) => {
2380                let params: Vec<Expr> = expr
2381                    .params
2382                    .into_iter()
2383                    .map(|expr| expr.try_into())
2384                    .collect::<Result<Vec<_>, _>>()?;
2385                // This is not required and kept for backward compatibility
2386                let legacy_invocation_name = expr.name;
2387                let call_type = expr.call_type;
2388                let generic_type_parameter = expr
2389                    .generic_type_parameter
2390                    .map(|tp| GenericTypeParameter { value: tp });
2391
2392                match (legacy_invocation_name, call_type) {
2393                    (Some(legacy), None) => {
2394                        let name = legacy.name.ok_or("Missing function call name")?;
2395                        match name {
2396                            golem_api_grpc::proto::golem::rib::invocation_name::Name::Parsed(name) => {
2397                                // Reading the previous parsed-function-name in persistent store as a dynamic-parsed-function-name
2398                                Expr::call_worker_function(DynamicParsedFunctionName::parse(
2399                                    ParsedFunctionName::try_from(name)?.to_string()
2400                                )?, generic_type_parameter, None, params, None)
2401                            }
2402                            golem_api_grpc::proto::golem::rib::invocation_name::Name::VariantConstructor(
2403                                name,
2404                            ) => Expr::call_worker_function(DynamicParsedFunctionName::parse(name)?, generic_type_parameter, None, params, None),
2405                            golem_api_grpc::proto::golem::rib::invocation_name::Name::EnumConstructor(
2406                                name,
2407                            ) => Expr::call_worker_function(DynamicParsedFunctionName::parse(name)?, generic_type_parameter, None, params, None),
2408                        }
2409                    }
2410                    (_, Some(call_type)) => {
2411                        let name = call_type.name.ok_or("Missing function call name")?;
2412                        match name {
2413                            golem_api_grpc::proto::golem::rib::call_type::Name::Parsed(name) => {
2414                                Expr::call_worker_function(name.try_into()?, generic_type_parameter, None, params, None)
2415                            }
2416                            golem_api_grpc::proto::golem::rib::call_type::Name::VariantConstructor(
2417                                name,
2418                            ) => Expr::call_worker_function(DynamicParsedFunctionName::parse(name)?, generic_type_parameter, None, params, None),
2419                            golem_api_grpc::proto::golem::rib::call_type::Name::EnumConstructor(
2420                                name,
2421                            ) => Expr::call_worker_function(DynamicParsedFunctionName::parse(name)?, generic_type_parameter, None, params, None),
2422                            golem_api_grpc::proto::golem::rib::call_type::Name::InstanceCreation(instance_creation) => {
2423                                let instance_creation_type = InstanceCreationType::try_from(*instance_creation)?;
2424                                let call_type = CallType::InstanceCreation(instance_creation_type);
2425                                Expr::Call {
2426                                    call_type,
2427                                    generic_type_parameter,
2428                                    args: vec![],
2429                                    inferred_type: InferredType::unknown(),
2430                                    source_span: SourceSpan::default(),
2431                                    type_annotation: None, // TODO
2432                                }
2433                            }
2434                        }
2435                    }
2436                    (_, _) => Err("Missing both call type (and legacy invocation type)")?,
2437                }
2438            }
2439            golem_api_grpc::proto::golem::rib::expr::Expr::LazyInvokeMethod(lazy_invoke) => {
2440                let lhs_proto = lazy_invoke.lhs.ok_or("Missing lhs")?;
2441                let lhs = Box::new((*lhs_proto).try_into()?);
2442                let method = lazy_invoke.method;
2443                let generic_type_parameter = lazy_invoke.generic_type_parameter;
2444                let args: Vec<Expr> = lazy_invoke
2445                    .args
2446                    .into_iter()
2447                    .map(Expr::try_from)
2448                    .collect::<Result<Vec<_>, _>>()?;
2449
2450                Expr::InvokeMethodLazy {
2451                    lhs,
2452                    method,
2453                    generic_type_parameter: generic_type_parameter
2454                        .map(|value| GenericTypeParameter { value }),
2455                    args,
2456                    inferred_type: InferredType::unknown(),
2457                    source_span: SourceSpan::default(),
2458                    type_annotation: None, //TODO
2459                }
2460            }
2461        };
2462        Ok(expr)
2463    }
2464}
2465
2466impl Display for Expr {
2467    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2468        write!(f, "{}", text::to_string(self).unwrap())
2469    }
2470}
2471
2472impl Display for ArmPattern {
2473    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2474        write!(f, "{}", text::to_string_arm_pattern(self).unwrap())
2475    }
2476}
2477
2478impl<'de> Deserialize<'de> for Expr {
2479    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2480    where
2481        D: serde::Deserializer<'de>,
2482    {
2483        let value = Value::deserialize(deserializer)?;
2484        match value {
2485            Value::String(expr_string) => match from_string(expr_string.as_str()) {
2486                Ok(expr) => Ok(expr),
2487                Err(message) => Err(serde::de::Error::custom(message.to_string())),
2488            },
2489
2490            e => Err(serde::de::Error::custom(format!(
2491                "Failed to deserialize expression {e}"
2492            ))),
2493        }
2494    }
2495}
2496
2497impl Serialize for Expr {
2498    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
2499    where
2500        S: Serializer,
2501    {
2502        match text::to_string(self) {
2503            Ok(value) => Value::serialize(&Value::String(value), serializer),
2504            Err(error) => Err(serde::ser::Error::custom(error.to_string())),
2505        }
2506    }
2507}
2508
2509#[cfg(feature = "protobuf")]
2510mod protobuf {
2511    use crate::{ArmPattern, Expr, MatchArm, Range};
2512    use golem_api_grpc::proto::golem::rib::range_expr::RangeExpr;
2513
2514    // It is to be noted that when we change `Expr` tree solely for the purpose of
2515    // updating type inference, we don't need to change the proto version
2516    // of Expr. A proto version of Expr changes only when Rib adds/updates the grammar itself.
2517    // This makes it easy to keep backward compatibility at the persistence level
2518    // (if persistence using grpc encode)
2519    //
2520    // Reason: A proto version of Expr doesn't take into the account the type inferred
2521    // for each expr, or encode any behaviour that's the result of a type inference
2522    // Example: in a type inference, a variable-id of expr which is tagged as `global` becomes
2523    // `VariableId::Local(Identifier)` after a particular type inference phase, however, when encoding
2524    // we don't need to consider this `Identifier` and is kept as global (i.e, the raw form) in Expr.
2525    // This is because we never (want to) encode an Expr which is a result of `infer_types` function.
2526    //
2527    // Summary: We encode Expr only prior to compilation. After compilation, we encode only the RibByteCode.
2528    // If we ever want to encode Expr after type-inference phase, it implies, we need to encode `InferredExpr`
2529    // rather than `Expr` and this will ensure, users when retrieving back the `Expr` will never have
2530    // noise regarding types and variable-ids, and will always stay one to one in round trip
2531    impl From<Expr> for golem_api_grpc::proto::golem::rib::Expr {
2532        fn from(value: Expr) -> Self {
2533            let expr = match value {
2534                Expr::GenerateWorkerName { .. } => Some(
2535                    golem_api_grpc::proto::golem::rib::expr::Expr::GenerateWorkerName(
2536                        golem_api_grpc::proto::golem::rib::GenerateWorkerNameExpr {},
2537                    ),
2538                ),
2539                Expr::Let {
2540                    variable_id,
2541                    type_annotation,
2542                    expr,
2543                    ..
2544                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Let(
2545                    Box::new(golem_api_grpc::proto::golem::rib::LetExpr {
2546                        name: variable_id.name().to_string(),
2547                        expr: Some(Box::new((*expr).into())),
2548                        type_name: type_annotation.map(|t| t.into()),
2549                    }),
2550                )),
2551
2552                Expr::Length { expr, .. } => {
2553                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Length(
2554                        Box::new(golem_api_grpc::proto::golem::rib::LengthExpr {
2555                            expr: Some(Box::new((*expr).into())),
2556                        }),
2557                    ))
2558                }
2559
2560                Expr::SelectField {
2561                    expr,
2562                    field,
2563                    type_annotation,
2564                    ..
2565                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::SelectField(
2566                    Box::new(golem_api_grpc::proto::golem::rib::SelectFieldExpr {
2567                        expr: Some(Box::new((*expr).into())),
2568                        field,
2569                        type_name: type_annotation.map(|t| t.into()),
2570                    }),
2571                )),
2572
2573                Expr::Range { range, .. } => match range {
2574                    Range::RangeFrom { from } => {
2575                        Some(golem_api_grpc::proto::golem::rib::expr::Expr::Range(
2576                            Box::new(golem_api_grpc::proto::golem::rib::RangeExpr {
2577                                range_expr: Some(RangeExpr::RangeFrom(Box::new(
2578                                    golem_api_grpc::proto::golem::rib::RangeFrom {
2579                                        from: Some(Box::new((*from).into())),
2580                                    },
2581                                ))),
2582                            }),
2583                        ))
2584                    }
2585                    Range::Range { from, to } => {
2586                        Some(golem_api_grpc::proto::golem::rib::expr::Expr::Range(
2587                            Box::new(golem_api_grpc::proto::golem::rib::RangeExpr {
2588                                range_expr: Some(RangeExpr::Range(Box::new(
2589                                    golem_api_grpc::proto::golem::rib::Range {
2590                                        from: Some(Box::new((*from).into())),
2591                                        to: Some(Box::new((*to).into())),
2592                                    },
2593                                ))),
2594                            }),
2595                        ))
2596                    }
2597                    Range::RangeInclusive { from, to } => {
2598                        Some(golem_api_grpc::proto::golem::rib::expr::Expr::Range(
2599                            Box::new(golem_api_grpc::proto::golem::rib::RangeExpr {
2600                                range_expr: Some(RangeExpr::RangeInclusive(Box::new(
2601                                    golem_api_grpc::proto::golem::rib::RangeInclusive {
2602                                        from: Some(Box::new((*from).into())),
2603                                        to: Some(Box::new((*to).into())),
2604                                    },
2605                                ))),
2606                            }),
2607                        ))
2608                    }
2609                },
2610
2611                Expr::SelectIndex {
2612                    expr,
2613                    index,
2614                    type_annotation,
2615                    ..
2616                } => Some(
2617                    golem_api_grpc::proto::golem::rib::expr::Expr::SelectIndexV1(Box::new(
2618                        golem_api_grpc::proto::golem::rib::SelectIndexExprV1 {
2619                            expr: Some(Box::new((*expr).into())),
2620                            index: Some(Box::new((*index).into())),
2621                            type_name: type_annotation.map(|t| t.into()),
2622                        },
2623                    )),
2624                ),
2625
2626                Expr::Sequence {
2627                    exprs: expressions,
2628                    type_annotation,
2629                    ..
2630                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Sequence(
2631                    golem_api_grpc::proto::golem::rib::SequenceExpr {
2632                        exprs: expressions.into_iter().map(|expr| expr.into()).collect(),
2633                        type_name: type_annotation.map(|t| t.into()),
2634                    },
2635                )),
2636                Expr::Record { exprs: fields, .. } => {
2637                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Record(
2638                        golem_api_grpc::proto::golem::rib::RecordExpr {
2639                            fields: fields
2640                                .into_iter()
2641                                .map(|(name, expr)| {
2642                                    golem_api_grpc::proto::golem::rib::RecordFieldExpr {
2643                                        name,
2644                                        expr: Some((*expr).into()),
2645                                    }
2646                                })
2647                                .collect(),
2648                        },
2649                    ))
2650                }
2651                Expr::Tuple {
2652                    exprs: expressions, ..
2653                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Tuple(
2654                    golem_api_grpc::proto::golem::rib::TupleExpr {
2655                        exprs: expressions.into_iter().map(|expr| expr.into()).collect(),
2656                    },
2657                )),
2658                Expr::Literal { value, .. } => {
2659                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Literal(
2660                        golem_api_grpc::proto::golem::rib::LiteralExpr { value },
2661                    ))
2662                }
2663                Expr::Number {
2664                    number,
2665                    type_annotation,
2666                    ..
2667                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Number(
2668                    golem_api_grpc::proto::golem::rib::NumberExpr {
2669                        number: Some(number.value.to_string()),
2670                        float: None,
2671                        type_name: type_annotation.map(|t| t.into()),
2672                    },
2673                )),
2674                Expr::Flags { flags, .. } => {
2675                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Flags(
2676                        golem_api_grpc::proto::golem::rib::FlagsExpr { values: flags },
2677                    ))
2678                }
2679                Expr::Identifier {
2680                    variable_id,
2681                    type_annotation,
2682                    ..
2683                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Identifier(
2684                    golem_api_grpc::proto::golem::rib::IdentifierExpr {
2685                        name: variable_id.name(),
2686                        type_name: type_annotation.map(|t| t.into()),
2687                    },
2688                )),
2689                Expr::Boolean { value, .. } => {
2690                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Boolean(
2691                        golem_api_grpc::proto::golem::rib::BooleanExpr { value },
2692                    ))
2693                }
2694                Expr::Concat {
2695                    exprs: expressions, ..
2696                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Concat(
2697                    golem_api_grpc::proto::golem::rib::ConcatExpr {
2698                        exprs: expressions.into_iter().map(|expr| expr.into()).collect(),
2699                    },
2700                )),
2701                Expr::ExprBlock {
2702                    exprs: expressions, ..
2703                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Multiple(
2704                    golem_api_grpc::proto::golem::rib::MultipleExpr {
2705                        exprs: expressions.into_iter().map(|expr| expr.into()).collect(),
2706                    },
2707                )),
2708                Expr::Not { expr, .. } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Not(
2709                    Box::new(golem_api_grpc::proto::golem::rib::NotExpr {
2710                        expr: Some(Box::new((*expr).into())),
2711                    }),
2712                )),
2713                Expr::GreaterThan {
2714                    lhs: left,
2715                    rhs: right,
2716                    ..
2717                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::GreaterThan(
2718                    Box::new(golem_api_grpc::proto::golem::rib::GreaterThanExpr {
2719                        left: Some(Box::new((*left).into())),
2720                        right: Some(Box::new((*right).into())),
2721                    }),
2722                )),
2723                Expr::GreaterThanOrEqualTo { lhs, rhs, .. } => Some(
2724                    golem_api_grpc::proto::golem::rib::expr::Expr::GreaterThanOrEqual(Box::new(
2725                        golem_api_grpc::proto::golem::rib::GreaterThanOrEqualToExpr {
2726                            left: Some(Box::new((*lhs).into())),
2727                            right: Some(Box::new((*rhs).into())),
2728                        },
2729                    )),
2730                ),
2731                Expr::LessThan {
2732                    lhs: left,
2733                    rhs: right,
2734                    ..
2735                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::LessThan(
2736                    Box::new(golem_api_grpc::proto::golem::rib::LessThanExpr {
2737                        left: Some(Box::new((*left).into())),
2738                        right: Some(Box::new((*right).into())),
2739                    }),
2740                )),
2741                Expr::Plus {
2742                    lhs: left,
2743                    rhs: right,
2744                    ..
2745                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Add(
2746                    Box::new(golem_api_grpc::proto::golem::rib::AddExpr {
2747                        left: Some(Box::new((*left).into())),
2748                        right: Some(Box::new((*right).into())),
2749                    }),
2750                )),
2751                Expr::Minus {
2752                    lhs: left,
2753                    rhs: right,
2754                    ..
2755                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Subtract(
2756                    Box::new(golem_api_grpc::proto::golem::rib::SubtractExpr {
2757                        left: Some(Box::new((*left).into())),
2758                        right: Some(Box::new((*right).into())),
2759                    }),
2760                )),
2761                Expr::Divide { lhs, rhs, .. } => {
2762                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Divide(
2763                        Box::new(golem_api_grpc::proto::golem::rib::DivideExpr {
2764                            left: Some(Box::new((*lhs).into())),
2765                            right: Some(Box::new((*rhs).into())),
2766                        }),
2767                    ))
2768                }
2769                Expr::Multiply { lhs, rhs, .. } => {
2770                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Multiply(
2771                        Box::new(golem_api_grpc::proto::golem::rib::MultiplyExpr {
2772                            left: Some(Box::new((*lhs).into())),
2773                            right: Some(Box::new((*rhs).into())),
2774                        }),
2775                    ))
2776                }
2777                Expr::LessThanOrEqualTo { lhs, rhs, .. } => Some(
2778                    golem_api_grpc::proto::golem::rib::expr::Expr::LessThanOrEqual(Box::new(
2779                        golem_api_grpc::proto::golem::rib::LessThanOrEqualToExpr {
2780                            left: Some(Box::new((*lhs).into())),
2781                            right: Some(Box::new((*rhs).into())),
2782                        },
2783                    )),
2784                ),
2785                Expr::EqualTo { lhs, rhs, .. } => {
2786                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::EqualTo(
2787                        Box::new(golem_api_grpc::proto::golem::rib::EqualToExpr {
2788                            left: Some(Box::new((*lhs).into())),
2789                            right: Some(Box::new((*rhs).into())),
2790                        }),
2791                    ))
2792                }
2793                // Note: We were storing and retrieving (proto) condition expressions such that
2794                // `cond` was written `lhs` and vice versa.
2795                // This is probably difficult to fix to keep backward compatibility
2796                // The issue is only with the protobuf types and the roundtrip tests were/are working since
2797                // the read handles this (i.e, reading cond as lhs)
2798                Expr::Cond {
2799                    cond: lhs,
2800                    lhs: cond,
2801                    rhs,
2802                    ..
2803                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Cond(
2804                    Box::new(golem_api_grpc::proto::golem::rib::CondExpr {
2805                        left: Some(Box::new((*lhs).into())),
2806                        cond: Some(Box::new((*cond).into())),
2807                        right: Some(Box::new((*rhs).into())),
2808                    }),
2809                )),
2810                Expr::PatternMatch {
2811                    predicate,
2812                    match_arms,
2813                    ..
2814                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::PatternMatch(
2815                    Box::new(golem_api_grpc::proto::golem::rib::PatternMatchExpr {
2816                        expr: Some(Box::new((*predicate).into())),
2817                        patterns: match_arms.into_iter().map(|a| a.into()).collect(),
2818                    }),
2819                )),
2820                Expr::Option {
2821                    expr,
2822                    type_annotation,
2823                    ..
2824                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Option(
2825                    Box::new(golem_api_grpc::proto::golem::rib::OptionExpr {
2826                        expr: expr.map(|expr| Box::new((*expr).into())),
2827                        type_name: type_annotation.map(|t| t.into()),
2828                    }),
2829                )),
2830                Expr::Result {
2831                    expr,
2832                    type_annotation,
2833                    ..
2834                } => {
2835                    let type_name = type_annotation.map(|t| t.into());
2836
2837                    let result = match expr {
2838                        Ok(expr) => golem_api_grpc::proto::golem::rib::result_expr::Result::Ok(
2839                            Box::new((*expr).into()),
2840                        ),
2841                        Err(expr) => golem_api_grpc::proto::golem::rib::result_expr::Result::Err(
2842                            Box::new((*expr).into()),
2843                        ),
2844                    };
2845
2846                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Result(
2847                        Box::new(golem_api_grpc::proto::golem::rib::ResultExpr {
2848                            result: Some(result),
2849                            type_name,
2850                        }),
2851                    ))
2852                }
2853                Expr::Call {
2854                    call_type,
2855                    generic_type_parameter,
2856                    args,
2857                    ..
2858                } => {
2859                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Call(
2860                        Box::new(golem_api_grpc::proto::golem::rib::CallExpr {
2861                            name: None, // Kept for backward compatibility
2862                            params: args.into_iter().map(|expr| expr.into()).collect(),
2863                            generic_type_parameter: generic_type_parameter.map(|t| t.value),
2864                            call_type: Some(Box::new(
2865                                golem_api_grpc::proto::golem::rib::CallType::from(call_type),
2866                            )),
2867                        }),
2868                    ))
2869                }
2870                Expr::Unwrap { expr, .. } => {
2871                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Unwrap(
2872                        Box::new(golem_api_grpc::proto::golem::rib::UnwrapExpr {
2873                            expr: Some(Box::new((*expr).into())),
2874                        }),
2875                    ))
2876                }
2877                Expr::Throw { message, .. } => {
2878                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Throw(
2879                        golem_api_grpc::proto::golem::rib::ThrowExpr { message },
2880                    ))
2881                }
2882                Expr::GetTag { expr, .. } => {
2883                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Tag(
2884                        Box::new(golem_api_grpc::proto::golem::rib::GetTagExpr {
2885                            expr: Some(Box::new((*expr).into())),
2886                        }),
2887                    ))
2888                }
2889                Expr::And { lhs, rhs, .. } => {
2890                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::And(
2891                        Box::new(golem_api_grpc::proto::golem::rib::AndExpr {
2892                            left: Some(Box::new((*lhs).into())),
2893                            right: Some(Box::new((*rhs).into())),
2894                        }),
2895                    ))
2896                }
2897
2898                Expr::Or { lhs, rhs, .. } => {
2899                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Or(Box::new(
2900                        golem_api_grpc::proto::golem::rib::OrExpr {
2901                            left: Some(Box::new((*lhs).into())),
2902                            right: Some(Box::new((*rhs).into())),
2903                        },
2904                    )))
2905                }
2906                Expr::ListComprehension {
2907                    iterated_variable,
2908                    iterable_expr,
2909                    yield_expr,
2910                    ..
2911                } => Some(
2912                    golem_api_grpc::proto::golem::rib::expr::Expr::ListComprehension(Box::new(
2913                        golem_api_grpc::proto::golem::rib::ListComprehensionExpr {
2914                            iterated_variable: iterated_variable.name(),
2915                            iterable_expr: Some(Box::new((*iterable_expr).into())),
2916                            yield_expr: Some(Box::new((*yield_expr).into())),
2917                        },
2918                    )),
2919                ),
2920
2921                Expr::ListReduce {
2922                    reduce_variable,
2923                    iterated_variable,
2924                    iterable_expr,
2925                    yield_expr,
2926                    init_value_expr,
2927                    ..
2928                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::ListReduce(
2929                    Box::new(golem_api_grpc::proto::golem::rib::ListReduceExpr {
2930                        reduce_variable: reduce_variable.name(),
2931                        iterated_variable: iterated_variable.name(),
2932                        iterable_expr: Some(Box::new((*iterable_expr).into())),
2933                        init_value_expr: Some(Box::new((*init_value_expr).into())),
2934                        yield_expr: Some(Box::new((*yield_expr).into())),
2935                    }),
2936                )),
2937                Expr::InvokeMethodLazy {
2938                    lhs,
2939                    method,
2940                    generic_type_parameter,
2941                    args,
2942                    ..
2943                } => Some(
2944                    golem_api_grpc::proto::golem::rib::expr::Expr::LazyInvokeMethod(Box::new(
2945                        golem_api_grpc::proto::golem::rib::LazyInvokeMethodExpr {
2946                            lhs: Some(Box::new((*lhs).into())),
2947                            method,
2948                            generic_type_parameter: generic_type_parameter.map(|t| t.value),
2949                            args: args.into_iter().map(|expr| expr.into()).collect(),
2950                        },
2951                    )),
2952                ),
2953            };
2954
2955            golem_api_grpc::proto::golem::rib::Expr { expr }
2956        }
2957    }
2958
2959    impl TryFrom<golem_api_grpc::proto::golem::rib::ArmPattern> for ArmPattern {
2960        type Error = String;
2961
2962        fn try_from(
2963            value: golem_api_grpc::proto::golem::rib::ArmPattern,
2964        ) -> Result<Self, Self::Error> {
2965            let pattern = value.pattern.ok_or("Missing pattern")?;
2966            match pattern {
2967                golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::WildCard(_) => {
2968                    Ok(ArmPattern::WildCard)
2969                }
2970                golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::As(asp) => {
2971                    let name = asp.name;
2972                    let pattern = asp.pattern.ok_or("Missing pattern")?;
2973                    Ok(ArmPattern::As(name, Box::new((*pattern).try_into()?)))
2974                }
2975                golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::Constructor(
2976                    golem_api_grpc::proto::golem::rib::ConstructorArmPattern { name, patterns },
2977                ) => {
2978                    let patterns = patterns
2979                        .into_iter()
2980                        .map(ArmPattern::try_from)
2981                        .collect::<Result<Vec<_>, _>>()?;
2982                    Ok(ArmPattern::Constructor(name, patterns))
2983                }
2984                golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::TupleConstructor(
2985                    golem_api_grpc::proto::golem::rib::TupleConstructorArmPattern { patterns },
2986                ) => {
2987                    let patterns = patterns
2988                        .into_iter()
2989                        .map(ArmPattern::try_from)
2990                        .collect::<Result<Vec<_>, _>>()?;
2991                    Ok(ArmPattern::TupleConstructor(patterns))
2992                }
2993                golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::Literal(
2994                    golem_api_grpc::proto::golem::rib::LiteralArmPattern { expr },
2995                ) => {
2996                    let inner = expr.ok_or("Missing expr")?;
2997                    Ok(ArmPattern::Literal(Box::new(inner.try_into()?)))
2998                }
2999                golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::RecordConstructor(
3000                    golem_api_grpc::proto::golem::rib::RecordConstructorArmPattern { fields },
3001                ) => {
3002                    let fields = fields
3003                        .into_iter()
3004                        .map(|field| {
3005                            let name = field.name;
3006                            let proto_pattern = field.pattern.ok_or("Missing pattern")?;
3007                            let arm_pattern = ArmPattern::try_from(proto_pattern)?;
3008                            Ok((name, arm_pattern))
3009                        })
3010                        .collect::<Result<Vec<_>, String>>()?;
3011                    Ok(ArmPattern::RecordConstructor(fields))
3012                }
3013                golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::ListConstructor(
3014                    golem_api_grpc::proto::golem::rib::ListConstructorArmPattern { patterns },
3015                ) => {
3016                    let patterns = patterns
3017                        .into_iter()
3018                        .map(ArmPattern::try_from)
3019                        .collect::<Result<Vec<_>, _>>()?;
3020                    Ok(ArmPattern::ListConstructor(patterns))
3021                }
3022            }
3023        }
3024    }
3025
3026    impl From<ArmPattern> for golem_api_grpc::proto::golem::rib::ArmPattern {
3027        fn from(value: ArmPattern) -> Self {
3028            match value {
3029                ArmPattern::WildCard => golem_api_grpc::proto::golem::rib::ArmPattern {
3030                    pattern: Some(
3031                        golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::WildCard(
3032                            golem_api_grpc::proto::golem::rib::WildCardArmPattern {},
3033                        ),
3034                    ),
3035                },
3036                ArmPattern::As(name, pattern) => golem_api_grpc::proto::golem::rib::ArmPattern {
3037                    pattern: Some(golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::As(
3038                        Box::new(golem_api_grpc::proto::golem::rib::AsArmPattern {
3039                            name,
3040                            pattern: Some(Box::new((*pattern).into())),
3041                        }),
3042                    )),
3043                },
3044                ArmPattern::Constructor(name, patterns) => {
3045                    golem_api_grpc::proto::golem::rib::ArmPattern {
3046                        pattern: Some(
3047                            golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::Constructor(
3048                                golem_api_grpc::proto::golem::rib::ConstructorArmPattern {
3049                                    name,
3050                                    patterns: patterns
3051                                        .into_iter()
3052                                        .map(golem_api_grpc::proto::golem::rib::ArmPattern::from)
3053                                        .collect(),
3054                                },
3055                            ),
3056                        ),
3057                    }
3058                }
3059                ArmPattern::Literal(expr) => golem_api_grpc::proto::golem::rib::ArmPattern {
3060                    pattern: Some(
3061                        golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::Literal(
3062                            golem_api_grpc::proto::golem::rib::LiteralArmPattern {
3063                                expr: Some((*expr).into()),
3064                            },
3065                        ),
3066                    ),
3067                },
3068
3069                ArmPattern::TupleConstructor(patterns) => {
3070                    golem_api_grpc::proto::golem::rib::ArmPattern {
3071                        pattern: Some(
3072                            golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::TupleConstructor(
3073                                golem_api_grpc::proto::golem::rib::TupleConstructorArmPattern {
3074                                    patterns: patterns
3075                                        .into_iter()
3076                                        .map(golem_api_grpc::proto::golem::rib::ArmPattern::from)
3077                                        .collect(),
3078                                },
3079                            ),
3080                        ),
3081                    }
3082                }
3083
3084                ArmPattern::RecordConstructor(fields) => {
3085                    golem_api_grpc::proto::golem::rib::ArmPattern {
3086                        pattern: Some(
3087                            golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::RecordConstructor(
3088                                golem_api_grpc::proto::golem::rib::RecordConstructorArmPattern {
3089                                    fields: fields
3090                                        .into_iter()
3091                                        .map(|(name, pattern)| {
3092                                            golem_api_grpc::proto::golem::rib::RecordFieldArmPattern {
3093                                                name,
3094                                                pattern: Some(pattern.into()),
3095                                            }
3096                                        })
3097                                        .collect(),
3098                                },
3099                            ),
3100                        ),
3101                    }
3102                }
3103
3104                ArmPattern::ListConstructor(patterns) => {
3105                    golem_api_grpc::proto::golem::rib::ArmPattern {
3106                        pattern: Some(
3107                            golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::ListConstructor(
3108                                golem_api_grpc::proto::golem::rib::ListConstructorArmPattern {
3109                                    patterns: patterns
3110                                        .into_iter()
3111                                        .map(golem_api_grpc::proto::golem::rib::ArmPattern::from)
3112                                        .collect(),
3113                                },
3114                            ),
3115                        ),
3116                    }
3117                }
3118            }
3119        }
3120    }
3121
3122    impl TryFrom<golem_api_grpc::proto::golem::rib::MatchArm> for MatchArm {
3123        type Error = String;
3124
3125        fn try_from(
3126            value: golem_api_grpc::proto::golem::rib::MatchArm,
3127        ) -> Result<Self, Self::Error> {
3128            let pattern = value.pattern.ok_or("Missing pattern")?;
3129            let expr = value.expr.ok_or("Missing expr")?;
3130            Ok(MatchArm::new(pattern.try_into()?, expr.try_into()?))
3131        }
3132    }
3133
3134    impl From<MatchArm> for golem_api_grpc::proto::golem::rib::MatchArm {
3135        fn from(value: MatchArm) -> Self {
3136            let MatchArm {
3137                arm_pattern,
3138                arm_resolution_expr,
3139            } = value;
3140            golem_api_grpc::proto::golem::rib::MatchArm {
3141                pattern: Some(arm_pattern.into()),
3142                expr: Some((*arm_resolution_expr).into()),
3143            }
3144        }
3145    }
3146}
3147
3148fn find_expr(expr: &mut Expr, source_span: &SourceSpan) -> Option<Expr> {
3149    let mut expr = expr.clone();
3150
3151    let mut visitor = ExprVisitor::bottom_up(&mut expr);
3152
3153    while let Some(current) = visitor.pop_back() {
3154        let span = current.source_span();
3155
3156        if source_span.eq(&span) {
3157            return Some(current.clone());
3158        }
3159    }
3160
3161    None
3162}