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    CustomInstanceSpec, DynamicParsedFunctionName, ExprVisitor, GlobalVariableTypeSpec,
25    InferredType, 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        global_variable_type_spec: &Vec<GlobalVariableTypeSpec>,
1142        custom_instance_spec: &[CustomInstanceSpec],
1143    ) -> Result<(), RibTypeErrorInternal> {
1144        self.infer_types_initial_phase(
1145            component_dependency,
1146            global_variable_type_spec,
1147            custom_instance_spec,
1148        )?;
1149        self.bind_instance_types();
1150        // Identifying the first fix point with method calls to infer all
1151        // worker function invocations as this forms the foundation for the rest of the
1152        // compilation. This is compiler doing its best to infer all the calls such
1153        // as worker invokes or instance calls etc.
1154        type_inference::type_inference_fix_point(Self::resolve_method_calls, self)?;
1155        self.infer_function_call_types(component_dependency, custom_instance_spec)?;
1156        type_inference::type_inference_fix_point(
1157            |x| Self::inference_scan(x, component_dependency, custom_instance_spec),
1158            self,
1159        )?;
1160        self.check_types(component_dependency)?;
1161        self.unify_types()?;
1162        Ok(())
1163    }
1164
1165    pub fn infer_types_initial_phase(
1166        &mut self,
1167        component_dependency: &ComponentDependencies,
1168        global_variable_type_spec: &Vec<GlobalVariableTypeSpec>,
1169        custom_instance_spec: &[CustomInstanceSpec],
1170    ) -> Result<(), RibTypeErrorInternal> {
1171        self.set_origin();
1172        self.bind_global_variable_types(global_variable_type_spec);
1173        self.bind_type_annotations();
1174        self.bind_variables_of_list_comprehension();
1175        self.bind_variables_of_list_reduce();
1176        self.bind_variables_of_pattern_match();
1177        self.bind_variables_of_let_assignment();
1178        self.identify_instance_creation(component_dependency, custom_instance_spec)?;
1179        self.ensure_stateful_instance();
1180        self.infer_variants(component_dependency);
1181        self.infer_enums(component_dependency);
1182        Ok(())
1183    }
1184
1185    pub fn resolve_method_calls(&mut self) -> Result<(), RibTypeErrorInternal> {
1186        self.bind_instance_types();
1187        self.infer_worker_function_invokes()?;
1188        Ok(())
1189    }
1190
1191    pub fn set_origin(&mut self) {
1192        let mut visitor = ExprVisitor::bottom_up(self);
1193
1194        while let Some(expr) = visitor.pop_front() {
1195            let source_location = expr.source_span();
1196            let origin = TypeOrigin::OriginatedAt(source_location.clone());
1197            let inferred_type = expr.inferred_type();
1198            let origin = inferred_type.add_origin(origin);
1199            expr.with_inferred_type_mut(origin);
1200        }
1201    }
1202
1203    // An inference is a single cycle of to-and-fro scanning of Rib expression, that it takes part in fix point of inference.
1204    // Not all phases of compilation will be part of this scan.
1205    // Example: function call argument inference based on the worker function hardly needs to be part of the scan.
1206    pub fn inference_scan(
1207        &mut self,
1208        component_dependencies: &ComponentDependencies,
1209        custom_instance_spec: &[CustomInstanceSpec],
1210    ) -> Result<(), RibTypeErrorInternal> {
1211        self.infer_all_identifiers();
1212        self.push_types_down()?;
1213        self.infer_all_identifiers();
1214        self.pull_types_up(component_dependencies)?;
1215        self.infer_global_inputs();
1216        self.infer_function_call_types(component_dependencies, custom_instance_spec)?;
1217        Ok(())
1218    }
1219
1220    pub fn infer_worker_function_invokes(&mut self) -> Result<(), RibTypeErrorInternal> {
1221        type_inference::infer_worker_function_invokes(self)
1222    }
1223
1224    // Make sure the bindings in the arm pattern of a pattern match are given variable-ids.
1225    // The same variable-ids will be tagged to the corresponding identifiers in the arm resolution
1226    // to avoid conflicts.
1227    pub fn bind_variables_of_pattern_match(&mut self) {
1228        type_inference::bind_variables_of_pattern_match(self);
1229    }
1230
1231    // Make sure the variable assignment (let binding) are given variable ids,
1232    // which will be tagged to the corresponding identifiers to avoid conflicts.
1233    // This is done only for local variables and not global variables
1234    pub fn bind_variables_of_let_assignment(&mut self) {
1235        type_inference::bind_variables_of_let_assignment(self);
1236    }
1237
1238    pub fn bind_variables_of_list_comprehension(&mut self) {
1239        type_inference::bind_variables_of_list_comprehension(self);
1240    }
1241
1242    pub fn bind_variables_of_list_reduce(&mut self) {
1243        type_inference::bind_variables_of_list_reduce(self);
1244    }
1245
1246    pub fn identify_instance_creation(
1247        &mut self,
1248        component_dependency: &ComponentDependencies,
1249        custom_instance_spec: &[CustomInstanceSpec],
1250    ) -> Result<(), RibTypeErrorInternal> {
1251        type_inference::identify_instance_creation(self, component_dependency, custom_instance_spec)
1252    }
1253
1254    pub fn ensure_stateful_instance(&mut self) {
1255        type_inference::ensure_stateful_instance(self)
1256    }
1257
1258    pub fn infer_function_call_types(
1259        &mut self,
1260        component_dependency: &ComponentDependencies,
1261        custom_instance_spec: &[CustomInstanceSpec],
1262    ) -> Result<(), RibTypeErrorInternal> {
1263        type_inference::infer_function_call_types(
1264            self,
1265            component_dependency,
1266            custom_instance_spec,
1267        )?;
1268        Ok(())
1269    }
1270
1271    pub fn push_types_down(&mut self) -> Result<(), RibTypeErrorInternal> {
1272        type_inference::push_types_down(self)
1273    }
1274
1275    pub fn infer_all_identifiers(&mut self) {
1276        type_inference::infer_all_identifiers(self)
1277    }
1278
1279    pub fn pull_types_up(
1280        &mut self,
1281        component_dependencies: &ComponentDependencies,
1282    ) -> Result<(), RibTypeErrorInternal> {
1283        type_inference::type_pull_up(self, component_dependencies)
1284    }
1285
1286    pub fn infer_global_inputs(&mut self) {
1287        type_inference::infer_global_inputs(self);
1288    }
1289
1290    pub fn bind_type_annotations(&mut self) {
1291        type_inference::bind_type_annotations(self);
1292    }
1293
1294    pub fn check_types(
1295        &mut self,
1296        component_dependency: &ComponentDependencies,
1297    ) -> Result<(), RibTypeErrorInternal> {
1298        type_checker::type_check(self, component_dependency)
1299    }
1300
1301    pub fn unify_types(&mut self) -> Result<(), RibTypeErrorInternal> {
1302        type_inference::unify_types(self)?;
1303        Ok(())
1304    }
1305
1306    pub fn merge_inferred_type(&self, new_inferred_type: InferredType) -> Expr {
1307        let mut expr_copied = self.clone();
1308        expr_copied.add_infer_type_mut(new_inferred_type);
1309        expr_copied
1310    }
1311
1312    pub fn add_infer_type_mut(&mut self, new_inferred_type: InferredType) {
1313        match self {
1314            Expr::Identifier { inferred_type, .. }
1315            | Expr::Let { inferred_type, .. }
1316            | Expr::SelectField { inferred_type, .. }
1317            | Expr::SelectIndex { inferred_type, .. }
1318            | Expr::Sequence { inferred_type, .. }
1319            | Expr::Record { inferred_type, .. }
1320            | Expr::Tuple { inferred_type, .. }
1321            | Expr::Literal { inferred_type, .. }
1322            | Expr::Number { inferred_type, .. }
1323            | Expr::Flags { inferred_type, .. }
1324            | Expr::Boolean { inferred_type, .. }
1325            | Expr::Concat { inferred_type, .. }
1326            | Expr::ExprBlock { inferred_type, .. }
1327            | Expr::Not { inferred_type, .. }
1328            | Expr::GreaterThan { inferred_type, .. }
1329            | Expr::GreaterThanOrEqualTo { inferred_type, .. }
1330            | Expr::LessThanOrEqualTo { inferred_type, .. }
1331            | Expr::EqualTo { inferred_type, .. }
1332            | Expr::Plus { inferred_type, .. }
1333            | Expr::Minus { inferred_type, .. }
1334            | Expr::Divide { inferred_type, .. }
1335            | Expr::Multiply { inferred_type, .. }
1336            | Expr::LessThan { inferred_type, .. }
1337            | Expr::Cond { inferred_type, .. }
1338            | Expr::PatternMatch { inferred_type, .. }
1339            | Expr::Option { inferred_type, .. }
1340            | Expr::Result { inferred_type, .. }
1341            | Expr::Unwrap { inferred_type, .. }
1342            | Expr::Throw { inferred_type, .. }
1343            | Expr::GetTag { inferred_type, .. }
1344            | Expr::And { inferred_type, .. }
1345            | Expr::Or { inferred_type, .. }
1346            | Expr::ListComprehension { inferred_type, .. }
1347            | Expr::ListReduce { inferred_type, .. }
1348            | Expr::InvokeMethodLazy { inferred_type, .. }
1349            | Expr::Range { inferred_type, .. }
1350            | Expr::Length { inferred_type, .. }
1351            | Expr::GenerateWorkerName { inferred_type, .. }
1352            | Expr::Call { inferred_type, .. } => {
1353                if !new_inferred_type.is_unknown() {
1354                    *inferred_type = inferred_type.merge(new_inferred_type);
1355                }
1356            }
1357        }
1358    }
1359
1360    pub fn reset_type(&mut self) {
1361        type_inference::reset_type_info(self);
1362    }
1363
1364    pub fn source_span(&self) -> SourceSpan {
1365        match self {
1366            Expr::Identifier { source_span, .. }
1367            | Expr::Let { source_span, .. }
1368            | Expr::SelectField { source_span, .. }
1369            | Expr::SelectIndex { source_span, .. }
1370            | Expr::Sequence { source_span, .. }
1371            | Expr::Record { source_span, .. }
1372            | Expr::Tuple { source_span, .. }
1373            | Expr::Literal { source_span, .. }
1374            | Expr::Number { source_span, .. }
1375            | Expr::Flags { source_span, .. }
1376            | Expr::Boolean { source_span, .. }
1377            | Expr::Concat { source_span, .. }
1378            | Expr::ExprBlock { source_span, .. }
1379            | Expr::Not { source_span, .. }
1380            | Expr::GreaterThan { source_span, .. }
1381            | Expr::GreaterThanOrEqualTo { source_span, .. }
1382            | Expr::LessThanOrEqualTo { source_span, .. }
1383            | Expr::EqualTo { source_span, .. }
1384            | Expr::LessThan { source_span, .. }
1385            | Expr::Plus { source_span, .. }
1386            | Expr::Minus { source_span, .. }
1387            | Expr::Divide { source_span, .. }
1388            | Expr::Multiply { source_span, .. }
1389            | Expr::Cond { source_span, .. }
1390            | Expr::PatternMatch { source_span, .. }
1391            | Expr::Option { source_span, .. }
1392            | Expr::Result { source_span, .. }
1393            | Expr::Unwrap { source_span, .. }
1394            | Expr::Throw { source_span, .. }
1395            | Expr::And { source_span, .. }
1396            | Expr::Or { source_span, .. }
1397            | Expr::GetTag { source_span, .. }
1398            | Expr::ListComprehension { source_span, .. }
1399            | Expr::ListReduce { source_span, .. }
1400            | Expr::InvokeMethodLazy { source_span, .. }
1401            | Expr::Range { source_span, .. }
1402            | Expr::Length { source_span, .. }
1403            | Expr::Call { source_span, .. }
1404            | Expr::GenerateWorkerName { source_span, .. } => source_span.clone(),
1405        }
1406    }
1407
1408    pub fn type_annotation(&self) -> &Option<TypeName> {
1409        match self {
1410            Expr::Identifier {
1411                type_annotation, ..
1412            }
1413            | Expr::Let {
1414                type_annotation, ..
1415            }
1416            | Expr::SelectField {
1417                type_annotation, ..
1418            }
1419            | Expr::SelectIndex {
1420                type_annotation, ..
1421            }
1422            | Expr::Sequence {
1423                type_annotation, ..
1424            }
1425            | Expr::Record {
1426                type_annotation, ..
1427            }
1428            | Expr::Tuple {
1429                type_annotation, ..
1430            }
1431            | Expr::Literal {
1432                type_annotation, ..
1433            }
1434            | Expr::Number {
1435                type_annotation, ..
1436            }
1437            | Expr::Flags {
1438                type_annotation, ..
1439            }
1440            | Expr::Boolean {
1441                type_annotation, ..
1442            }
1443            | Expr::Concat {
1444                type_annotation, ..
1445            }
1446            | Expr::ExprBlock {
1447                type_annotation, ..
1448            }
1449            | Expr::Not {
1450                type_annotation, ..
1451            }
1452            | Expr::GreaterThan {
1453                type_annotation, ..
1454            }
1455            | Expr::GreaterThanOrEqualTo {
1456                type_annotation, ..
1457            }
1458            | Expr::LessThanOrEqualTo {
1459                type_annotation, ..
1460            }
1461            | Expr::EqualTo {
1462                type_annotation, ..
1463            }
1464            | Expr::LessThan {
1465                type_annotation, ..
1466            }
1467            | Expr::Plus {
1468                type_annotation, ..
1469            }
1470            | Expr::Minus {
1471                type_annotation, ..
1472            }
1473            | Expr::Divide {
1474                type_annotation, ..
1475            }
1476            | Expr::Multiply {
1477                type_annotation, ..
1478            }
1479            | Expr::Cond {
1480                type_annotation, ..
1481            }
1482            | Expr::PatternMatch {
1483                type_annotation, ..
1484            }
1485            | Expr::Option {
1486                type_annotation, ..
1487            }
1488            | Expr::Result {
1489                type_annotation, ..
1490            }
1491            | Expr::Unwrap {
1492                type_annotation, ..
1493            }
1494            | Expr::Throw {
1495                type_annotation, ..
1496            }
1497            | Expr::And {
1498                type_annotation, ..
1499            }
1500            | Expr::Or {
1501                type_annotation, ..
1502            }
1503            | Expr::GetTag {
1504                type_annotation, ..
1505            }
1506            | Expr::ListComprehension {
1507                type_annotation, ..
1508            }
1509            | Expr::ListReduce {
1510                type_annotation, ..
1511            }
1512            | Expr::InvokeMethodLazy {
1513                type_annotation, ..
1514            }
1515            | Expr::Range {
1516                type_annotation, ..
1517            }
1518            | Expr::Length {
1519                type_annotation, ..
1520            }
1521            | Expr::GenerateWorkerName {
1522                type_annotation, ..
1523            }
1524            | Expr::Call {
1525                type_annotation, ..
1526            } => type_annotation,
1527        }
1528    }
1529
1530    pub fn with_type_annotation_opt(&self, type_annotation: Option<TypeName>) -> Expr {
1531        if let Some(type_annotation) = type_annotation {
1532            self.with_type_annotation(type_annotation)
1533        } else {
1534            self.clone()
1535        }
1536    }
1537
1538    pub fn with_type_annotation(&self, type_annotation: TypeName) -> Expr {
1539        let mut expr_copied = self.clone();
1540        expr_copied.with_type_annotation_mut(type_annotation);
1541        expr_copied
1542    }
1543
1544    pub fn with_type_annotation_mut(&mut self, type_annotation: TypeName) {
1545        let new_type_annotation = type_annotation;
1546
1547        match self {
1548            Expr::Identifier {
1549                type_annotation, ..
1550            }
1551            | Expr::Let {
1552                type_annotation, ..
1553            }
1554            | Expr::SelectField {
1555                type_annotation, ..
1556            }
1557            | Expr::SelectIndex {
1558                type_annotation, ..
1559            }
1560            | Expr::Sequence {
1561                type_annotation, ..
1562            }
1563            | Expr::Record {
1564                type_annotation, ..
1565            }
1566            | Expr::Tuple {
1567                type_annotation, ..
1568            }
1569            | Expr::Literal {
1570                type_annotation, ..
1571            }
1572            | Expr::Number {
1573                type_annotation, ..
1574            }
1575            | Expr::Flags {
1576                type_annotation, ..
1577            }
1578            | Expr::Boolean {
1579                type_annotation, ..
1580            }
1581            | Expr::Concat {
1582                type_annotation, ..
1583            }
1584            | Expr::ExprBlock {
1585                type_annotation, ..
1586            }
1587            | Expr::Not {
1588                type_annotation, ..
1589            }
1590            | Expr::GreaterThan {
1591                type_annotation, ..
1592            }
1593            | Expr::GreaterThanOrEqualTo {
1594                type_annotation, ..
1595            }
1596            | Expr::LessThanOrEqualTo {
1597                type_annotation, ..
1598            }
1599            | Expr::EqualTo {
1600                type_annotation, ..
1601            }
1602            | Expr::LessThan {
1603                type_annotation, ..
1604            }
1605            | Expr::Plus {
1606                type_annotation, ..
1607            }
1608            | Expr::Minus {
1609                type_annotation, ..
1610            }
1611            | Expr::Divide {
1612                type_annotation, ..
1613            }
1614            | Expr::Multiply {
1615                type_annotation, ..
1616            }
1617            | Expr::Cond {
1618                type_annotation, ..
1619            }
1620            | Expr::PatternMatch {
1621                type_annotation, ..
1622            }
1623            | Expr::Option {
1624                type_annotation, ..
1625            }
1626            | Expr::Result {
1627                type_annotation, ..
1628            }
1629            | Expr::Unwrap {
1630                type_annotation, ..
1631            }
1632            | Expr::Throw {
1633                type_annotation, ..
1634            }
1635            | Expr::And {
1636                type_annotation, ..
1637            }
1638            | Expr::Or {
1639                type_annotation, ..
1640            }
1641            | Expr::GetTag {
1642                type_annotation, ..
1643            }
1644            | Expr::Range {
1645                type_annotation, ..
1646            }
1647            | Expr::ListComprehension {
1648                type_annotation, ..
1649            }
1650            | Expr::ListReduce {
1651                type_annotation, ..
1652            }
1653            | Expr::InvokeMethodLazy {
1654                type_annotation, ..
1655            }
1656            | Expr::Length {
1657                type_annotation, ..
1658            }
1659            | Expr::GenerateWorkerName {
1660                type_annotation, ..
1661            }
1662            | Expr::Call {
1663                type_annotation, ..
1664            } => {
1665                *type_annotation = Some(new_type_annotation);
1666            }
1667        }
1668    }
1669
1670    pub fn with_source_span(&self, new_source_span: SourceSpan) -> Expr {
1671        let mut expr_copied = self.clone();
1672        expr_copied.with_source_span_mut(new_source_span);
1673        expr_copied
1674    }
1675
1676    pub fn with_source_span_mut(&mut self, new_source_span: SourceSpan) {
1677        match self {
1678            Expr::Identifier { source_span, .. }
1679            | Expr::Let { source_span, .. }
1680            | Expr::SelectField { source_span, .. }
1681            | Expr::SelectIndex { source_span, .. }
1682            | Expr::Sequence { source_span, .. }
1683            | Expr::Number { source_span, .. }
1684            | Expr::Record { source_span, .. }
1685            | Expr::Tuple { source_span, .. }
1686            | Expr::Literal { source_span, .. }
1687            | Expr::Flags { source_span, .. }
1688            | Expr::Boolean { source_span, .. }
1689            | Expr::Concat { source_span, .. }
1690            | Expr::ExprBlock { source_span, .. }
1691            | Expr::Not { source_span, .. }
1692            | Expr::GreaterThan { source_span, .. }
1693            | Expr::GreaterThanOrEqualTo { source_span, .. }
1694            | Expr::LessThanOrEqualTo { source_span, .. }
1695            | Expr::EqualTo { source_span, .. }
1696            | Expr::LessThan { source_span, .. }
1697            | Expr::Plus { source_span, .. }
1698            | Expr::Minus { source_span, .. }
1699            | Expr::Divide { source_span, .. }
1700            | Expr::Multiply { source_span, .. }
1701            | Expr::Cond { source_span, .. }
1702            | Expr::PatternMatch { source_span, .. }
1703            | Expr::Option { source_span, .. }
1704            | Expr::Result { source_span, .. }
1705            | Expr::Unwrap { source_span, .. }
1706            | Expr::Throw { source_span, .. }
1707            | Expr::And { source_span, .. }
1708            | Expr::Or { source_span, .. }
1709            | Expr::GetTag { source_span, .. }
1710            | Expr::Range { source_span, .. }
1711            | Expr::ListComprehension { source_span, .. }
1712            | Expr::ListReduce { source_span, .. }
1713            | Expr::InvokeMethodLazy { source_span, .. }
1714            | Expr::Length { source_span, .. }
1715            | Expr::GenerateWorkerName { source_span, .. }
1716            | Expr::Call { source_span, .. } => {
1717                *source_span = new_source_span;
1718            }
1719        }
1720    }
1721
1722    pub fn with_inferred_type(&self, new_inferred_type: InferredType) -> Expr {
1723        let mut expr_copied = self.clone();
1724        expr_copied.with_inferred_type_mut(new_inferred_type);
1725        expr_copied
1726    }
1727
1728    // `with_inferred_type` overrides the existing inferred_type and returns a new expr
1729    // This is different to `merge_inferred_type` where it tries to combine the new inferred type with the existing one.
1730    pub fn with_inferred_type_mut(&mut self, new_inferred_type: InferredType) {
1731        match self {
1732            Expr::Identifier { inferred_type, .. }
1733            | Expr::Let { inferred_type, .. }
1734            | Expr::SelectField { inferred_type, .. }
1735            | Expr::SelectIndex { inferred_type, .. }
1736            | Expr::Sequence { inferred_type, .. }
1737            | Expr::Record { inferred_type, .. }
1738            | Expr::Tuple { inferred_type, .. }
1739            | Expr::Literal { inferred_type, .. }
1740            | Expr::Number { inferred_type, .. }
1741            | Expr::Flags { inferred_type, .. }
1742            | Expr::Boolean { inferred_type, .. }
1743            | Expr::Concat { inferred_type, .. }
1744            | Expr::ExprBlock { inferred_type, .. }
1745            | Expr::Not { inferred_type, .. }
1746            | Expr::GreaterThan { inferred_type, .. }
1747            | Expr::GreaterThanOrEqualTo { inferred_type, .. }
1748            | Expr::LessThanOrEqualTo { inferred_type, .. }
1749            | Expr::EqualTo { inferred_type, .. }
1750            | Expr::LessThan { inferred_type, .. }
1751            | Expr::Plus { inferred_type, .. }
1752            | Expr::Minus { inferred_type, .. }
1753            | Expr::Divide { inferred_type, .. }
1754            | Expr::Multiply { inferred_type, .. }
1755            | Expr::Cond { inferred_type, .. }
1756            | Expr::PatternMatch { inferred_type, .. }
1757            | Expr::Option { inferred_type, .. }
1758            | Expr::Result { inferred_type, .. }
1759            | Expr::Unwrap { inferred_type, .. }
1760            | Expr::Throw { inferred_type, .. }
1761            | Expr::And { inferred_type, .. }
1762            | Expr::Or { inferred_type, .. }
1763            | Expr::GetTag { inferred_type, .. }
1764            | Expr::ListComprehension { inferred_type, .. }
1765            | Expr::ListReduce { inferred_type, .. }
1766            | Expr::InvokeMethodLazy { inferred_type, .. }
1767            | Expr::Range { inferred_type, .. }
1768            | Expr::Length { inferred_type, .. }
1769            | Expr::GenerateWorkerName { inferred_type, .. }
1770            | Expr::Call { inferred_type, .. } => {
1771                *inferred_type = new_inferred_type;
1772            }
1773        }
1774    }
1775
1776    pub fn infer_enums(&mut self, component_dependency: &ComponentDependencies) {
1777        type_inference::infer_enums(self, component_dependency);
1778    }
1779
1780    pub fn infer_variants(&mut self, component_dependency: &ComponentDependencies) {
1781        type_inference::infer_variants(self, component_dependency);
1782    }
1783
1784    pub fn visit_expr_nodes_lazy<'a>(&'a mut self, queue: &mut VecDeque<&'a mut Expr>) {
1785        type_inference::visit_expr_nodes_lazy(self, queue);
1786    }
1787
1788    pub fn number_inferred(
1789        big_decimal: BigDecimal,
1790        type_annotation: Option<TypeName>,
1791        inferred_type: InferredType,
1792    ) -> Expr {
1793        Expr::Number {
1794            number: Number { value: big_decimal },
1795            type_annotation,
1796            inferred_type,
1797            source_span: SourceSpan::default(),
1798        }
1799    }
1800
1801    pub fn number(big_decimal: BigDecimal) -> Expr {
1802        let default_type = DefaultType::from(&big_decimal);
1803        let inferred_type = InferredType::from(&default_type);
1804
1805        Expr::number_inferred(big_decimal, None, inferred_type)
1806    }
1807}
1808
1809#[derive(Debug, Hash, Clone, PartialEq, Eq, PartialOrd, Ord)]
1810pub enum Range {
1811    Range { from: Box<Expr>, to: Box<Expr> },
1812    RangeInclusive { from: Box<Expr>, to: Box<Expr> },
1813    RangeFrom { from: Box<Expr> },
1814}
1815
1816impl Range {
1817    pub fn from(&self) -> Option<&Expr> {
1818        match self {
1819            Range::Range { from, .. } => Some(from),
1820            Range::RangeInclusive { from, .. } => Some(from),
1821            Range::RangeFrom { from } => Some(from),
1822        }
1823    }
1824
1825    pub fn to(&self) -> Option<&Expr> {
1826        match self {
1827            Range::Range { to, .. } => Some(to),
1828            Range::RangeInclusive { to, .. } => Some(to),
1829            Range::RangeFrom { .. } => None,
1830        }
1831    }
1832
1833    pub fn inclusive(&self) -> bool {
1834        matches!(self, Range::RangeInclusive { .. })
1835    }
1836
1837    pub fn get_exprs_mut(&mut self) -> Vec<&mut Box<Expr>> {
1838        match self {
1839            Range::Range { from, to } => vec![from, to],
1840            Range::RangeInclusive { from, to } => vec![from, to],
1841            Range::RangeFrom { from } => vec![from],
1842        }
1843    }
1844
1845    pub fn get_exprs(&self) -> Vec<&Expr> {
1846        match self {
1847            Range::Range { from, to } => vec![from.as_ref(), to.as_ref()],
1848            Range::RangeInclusive { from, to } => vec![from.as_ref(), to.as_ref()],
1849            Range::RangeFrom { from } => vec![from.as_ref()],
1850        }
1851    }
1852}
1853
1854#[derive(Debug, Hash, Clone, PartialEq, Ord, PartialOrd)]
1855pub struct Number {
1856    pub value: BigDecimal,
1857}
1858
1859impl Eq for Number {}
1860
1861impl Number {
1862    pub fn to_val(&self, analysed_type: &AnalysedType) -> Option<ValueAndType> {
1863        match analysed_type {
1864            AnalysedType::F64(_) => self.value.to_f64().map(|v| v.into_value_and_type()),
1865            AnalysedType::U64(_) => self.value.to_u64().map(|v| v.into_value_and_type()),
1866            AnalysedType::F32(_) => self.value.to_f32().map(|v| v.into_value_and_type()),
1867            AnalysedType::U32(_) => self.value.to_u32().map(|v| v.into_value_and_type()),
1868            AnalysedType::S32(_) => self.value.to_i32().map(|v| v.into_value_and_type()),
1869            AnalysedType::S64(_) => self.value.to_i64().map(|v| v.into_value_and_type()),
1870            AnalysedType::U8(_) => self.value.to_u8().map(|v| v.into_value_and_type()),
1871            AnalysedType::S8(_) => self.value.to_i8().map(|v| v.into_value_and_type()),
1872            AnalysedType::U16(_) => self.value.to_u16().map(|v| v.into_value_and_type()),
1873            AnalysedType::S16(_) => self.value.to_i16().map(|v| v.into_value_and_type()),
1874            _ => None,
1875        }
1876    }
1877}
1878
1879impl Display for Number {
1880    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1881        write!(f, "{}", self.value)
1882    }
1883}
1884
1885#[derive(Debug, Hash, Clone, PartialEq, Eq, Ord, PartialOrd)]
1886pub struct MatchArm {
1887    pub arm_pattern: ArmPattern,
1888    pub arm_resolution_expr: Box<Expr>,
1889}
1890
1891impl MatchArm {
1892    pub fn new(arm_pattern: ArmPattern, arm_resolution: Expr) -> MatchArm {
1893        MatchArm {
1894            arm_pattern,
1895            arm_resolution_expr: Box::new(arm_resolution),
1896        }
1897    }
1898}
1899#[derive(Debug, Hash, Clone, PartialEq, Eq, Ord, PartialOrd)]
1900pub enum ArmPattern {
1901    WildCard,
1902    As(String, Box<ArmPattern>),
1903    Constructor(String, Vec<ArmPattern>),
1904    TupleConstructor(Vec<ArmPattern>),
1905    RecordConstructor(Vec<(String, ArmPattern)>),
1906    ListConstructor(Vec<ArmPattern>),
1907    Literal(Box<Expr>),
1908}
1909
1910impl ArmPattern {
1911    pub fn is_wildcard(&self) -> bool {
1912        matches!(self, ArmPattern::WildCard)
1913    }
1914
1915    pub fn is_literal_identifier(&self) -> bool {
1916        matches!(self, ArmPattern::Literal(expr) if expr.is_identifier())
1917    }
1918
1919    pub fn constructor(name: &str, patterns: Vec<ArmPattern>) -> ArmPattern {
1920        ArmPattern::Constructor(name.to_string(), patterns)
1921    }
1922
1923    pub fn literal(expr: Expr) -> ArmPattern {
1924        ArmPattern::Literal(Box::new(expr))
1925    }
1926
1927    pub fn get_expr_literals_mut(&mut self) -> Vec<&mut Box<Expr>> {
1928        match self {
1929            ArmPattern::Literal(expr) => vec![expr],
1930            ArmPattern::As(_, pattern) => pattern.get_expr_literals_mut(),
1931            ArmPattern::Constructor(_, patterns) => {
1932                let mut result = vec![];
1933                for pattern in patterns {
1934                    result.extend(pattern.get_expr_literals_mut());
1935                }
1936                result
1937            }
1938            ArmPattern::TupleConstructor(patterns) => {
1939                let mut result = vec![];
1940                for pattern in patterns {
1941                    result.extend(pattern.get_expr_literals_mut());
1942                }
1943                result
1944            }
1945            ArmPattern::RecordConstructor(patterns) => {
1946                let mut result = vec![];
1947                for (_, pattern) in patterns {
1948                    result.extend(pattern.get_expr_literals_mut());
1949                }
1950                result
1951            }
1952            ArmPattern::ListConstructor(patterns) => {
1953                let mut result = vec![];
1954                for pattern in patterns {
1955                    result.extend(pattern.get_expr_literals_mut());
1956                }
1957                result
1958            }
1959            ArmPattern::WildCard => vec![],
1960        }
1961    }
1962
1963    pub fn get_expr_literals(&self) -> Vec<&Expr> {
1964        match self {
1965            ArmPattern::Literal(expr) => vec![expr.as_ref()],
1966            ArmPattern::As(_, pattern) => pattern.get_expr_literals(),
1967            ArmPattern::Constructor(_, patterns) => {
1968                let mut result = vec![];
1969                for pattern in patterns {
1970                    result.extend(pattern.get_expr_literals());
1971                }
1972                result
1973            }
1974            ArmPattern::TupleConstructor(patterns) => {
1975                let mut result = vec![];
1976                for pattern in patterns {
1977                    result.extend(pattern.get_expr_literals());
1978                }
1979                result
1980            }
1981            ArmPattern::RecordConstructor(patterns) => {
1982                let mut result = vec![];
1983                for (_, pattern) in patterns {
1984                    result.extend(pattern.get_expr_literals());
1985                }
1986                result
1987            }
1988            ArmPattern::ListConstructor(patterns) => {
1989                let mut result = vec![];
1990                for pattern in patterns {
1991                    result.extend(pattern.get_expr_literals());
1992                }
1993                result
1994            }
1995            ArmPattern::WildCard => vec![],
1996        }
1997    }
1998    // Helper to construct ok(v). Cannot be used if there is nested constructors such as ok(some(v)))
1999    pub fn ok(binding_variable: &str) -> ArmPattern {
2000        ArmPattern::Literal(Box::new(Expr::Result {
2001            expr: Ok(Box::new(Expr::Identifier {
2002                variable_id: VariableId::global(binding_variable.to_string()),
2003                type_annotation: None,
2004                inferred_type: InferredType::unknown(),
2005                source_span: SourceSpan::default(),
2006            })),
2007            type_annotation: None,
2008            inferred_type: InferredType::result(
2009                Some(InferredType::unknown()),
2010                Some(InferredType::unknown()),
2011            ),
2012            source_span: SourceSpan::default(),
2013        }))
2014    }
2015
2016    // Helper to construct err(v). Cannot be used if there is nested constructors such as err(some(v)))
2017    pub fn err(binding_variable: &str) -> ArmPattern {
2018        ArmPattern::Literal(Box::new(Expr::Result {
2019            expr: Err(Box::new(Expr::Identifier {
2020                variable_id: VariableId::global(binding_variable.to_string()),
2021                type_annotation: None,
2022                inferred_type: InferredType::unknown(),
2023                source_span: SourceSpan::default(),
2024            })),
2025            type_annotation: None,
2026            inferred_type: InferredType::result(
2027                Some(InferredType::unknown()),
2028                Some(InferredType::unknown()),
2029            ),
2030            source_span: SourceSpan::default(),
2031        }))
2032    }
2033
2034    // Helper to construct some(v). Cannot be used if there is nested constructors such as some(ok(v)))
2035    pub fn some(binding_variable: &str) -> ArmPattern {
2036        ArmPattern::Literal(Box::new(Expr::Option {
2037            expr: Some(Box::new(Expr::Identifier {
2038                variable_id: VariableId::local_with_no_id(binding_variable),
2039                type_annotation: None,
2040                inferred_type: InferredType::unknown(),
2041                source_span: SourceSpan::default(),
2042            })),
2043            type_annotation: None,
2044            inferred_type: InferredType::unknown(),
2045            source_span: SourceSpan::default(),
2046        }))
2047    }
2048
2049    pub fn none() -> ArmPattern {
2050        ArmPattern::Literal(Box::new(Expr::Option {
2051            expr: None,
2052            type_annotation: None,
2053            inferred_type: InferredType::unknown(),
2054            source_span: SourceSpan::default(),
2055        }))
2056    }
2057
2058    pub fn identifier(binding_variable: &str) -> ArmPattern {
2059        ArmPattern::Literal(Box::new(Expr::Identifier {
2060            variable_id: VariableId::global(binding_variable.to_string()),
2061            type_annotation: None,
2062            inferred_type: InferredType::unknown(),
2063            source_span: SourceSpan::default(),
2064        }))
2065    }
2066    pub fn custom_constructor(name: &str, args: Vec<ArmPattern>) -> ArmPattern {
2067        ArmPattern::Constructor(name.to_string(), args)
2068    }
2069}
2070
2071#[cfg(feature = "protobuf")]
2072impl TryFrom<golem_api_grpc::proto::golem::rib::Expr> for Expr {
2073    type Error = String;
2074
2075    fn try_from(value: golem_api_grpc::proto::golem::rib::Expr) -> Result<Self, Self::Error> {
2076        let expr = value.expr.ok_or("Missing expr")?;
2077
2078        let expr = match expr {
2079            golem_api_grpc::proto::golem::rib::expr::Expr::Let(expr) => {
2080                let name = expr.name;
2081                let type_annotation = expr.type_name.map(TypeName::try_from).transpose()?;
2082                let expr_: golem_api_grpc::proto::golem::rib::Expr =
2083                    *expr.expr.ok_or("Missing expr")?;
2084                let expr: Expr = expr_.try_into()?;
2085                Expr::let_binding(name, expr, type_annotation)
2086            }
2087
2088            golem_api_grpc::proto::golem::rib::expr::Expr::SelectIndexV1(expr) => {
2089                let selection = *expr.expr.ok_or("Missing expr")?;
2090                let field = *expr.index.ok_or("Missing index")?;
2091                let type_annotation = expr.type_name.map(TypeName::try_from).transpose()?;
2092
2093                Expr::select_index(selection.try_into()?, field.try_into()?)
2094                    .with_type_annotation_opt(type_annotation)
2095            }
2096
2097            golem_api_grpc::proto::golem::rib::expr::Expr::Length(expr) => {
2098                let expr = expr.expr.ok_or("Missing expr")?;
2099                Expr::Length {
2100                    expr: Box::new((*expr).try_into()?),
2101                    type_annotation: None,
2102                    inferred_type: InferredType::unknown(),
2103                    source_span: SourceSpan::default(),
2104                }
2105            }
2106
2107            golem_api_grpc::proto::golem::rib::expr::Expr::Range(range) => {
2108                let range_expr = range.range_expr.ok_or("Missing range expr")?;
2109
2110                match range_expr {
2111                    RangeExpr::RangeFrom(range_from) => {
2112                        let from = range_from.from.ok_or("Missing from expr")?;
2113                        Expr::range_from((*from).try_into()?)
2114                    }
2115                    RangeExpr::Range(range) => {
2116                        let from = range.from.ok_or("Missing from expr")?;
2117                        let to = range.to.ok_or("Missing to expr")?;
2118                        Expr::range((*from).try_into()?, (*to).try_into()?)
2119                    }
2120                    RangeExpr::RangeInclusive(range_inclusive) => {
2121                        let from = range_inclusive.from.ok_or("Missing from expr")?;
2122                        let to = range_inclusive.to.ok_or("Missing to expr")?;
2123                        Expr::range_inclusive((*from).try_into()?, (*to).try_into()?)
2124                    }
2125                }
2126            }
2127
2128            golem_api_grpc::proto::golem::rib::expr::Expr::Not(expr) => {
2129                let expr = expr.expr.ok_or("Missing expr")?;
2130                Expr::not((*expr).try_into()?)
2131            }
2132
2133            golem_api_grpc::proto::golem::rib::expr::Expr::GreaterThan(expr) => {
2134                let left = expr.left.ok_or("Missing left expr")?;
2135                let right = expr.right.ok_or("Missing right expr")?;
2136                Expr::greater_than((*left).try_into()?, (*right).try_into()?)
2137            }
2138
2139            golem_api_grpc::proto::golem::rib::expr::Expr::GreaterThanOrEqual(expr) => {
2140                let left = expr.left.ok_or("Missing left expr")?;
2141                let right = expr.right.ok_or("Missing right expr")?;
2142                Expr::greater_than_or_equal_to((*left).try_into()?, (*right).try_into()?)
2143            }
2144
2145            golem_api_grpc::proto::golem::rib::expr::Expr::LessThan(expr) => {
2146                let left = expr.left.ok_or("Missing left expr")?;
2147                let right = expr.right.ok_or("Missing right expr")?;
2148                Expr::less_than((*left).try_into()?, (*right).try_into()?)
2149            }
2150
2151            golem_api_grpc::proto::golem::rib::expr::Expr::LessThanOrEqual(expr) => {
2152                let left = expr.left.ok_or("Missing left expr")?;
2153                let right = expr.right.ok_or("Missing right expr")?;
2154                Expr::less_than_or_equal_to((*left).try_into()?, (*right).try_into()?)
2155            }
2156
2157            golem_api_grpc::proto::golem::rib::expr::Expr::EqualTo(expr) => {
2158                let left = expr.left.ok_or("Missing left expr")?;
2159                let right = expr.right.ok_or("Missing right expr")?;
2160                Expr::equal_to((*left).try_into()?, (*right).try_into()?)
2161            }
2162
2163            golem_api_grpc::proto::golem::rib::expr::Expr::Add(expr) => {
2164                let left = expr.left.ok_or("Missing left expr")?;
2165                let right = expr.right.ok_or("Missing right expr")?;
2166                Expr::plus((*left).try_into()?, (*right).try_into()?)
2167            }
2168
2169            golem_api_grpc::proto::golem::rib::expr::Expr::Subtract(expr) => {
2170                let left = expr.left.ok_or("Missing left expr")?;
2171                let right = expr.right.ok_or("Missing right expr")?;
2172                Expr::plus((*left).try_into()?, (*right).try_into()?)
2173            }
2174
2175            golem_api_grpc::proto::golem::rib::expr::Expr::Divide(expr) => {
2176                let left = expr.left.ok_or("Missing left expr")?;
2177                let right = expr.right.ok_or("Missing right expr")?;
2178                Expr::plus((*left).try_into()?, (*right).try_into()?)
2179            }
2180
2181            golem_api_grpc::proto::golem::rib::expr::Expr::Multiply(expr) => {
2182                let left = expr.left.ok_or("Missing left expr")?;
2183                let right = expr.right.ok_or("Missing right expr")?;
2184                Expr::plus((*left).try_into()?, (*right).try_into()?)
2185            }
2186
2187            golem_api_grpc::proto::golem::rib::expr::Expr::Cond(expr) => {
2188                let left = expr.left.ok_or("Missing left expr")?;
2189                let cond = expr.cond.ok_or("Missing cond expr")?;
2190                let right = expr.right.ok_or("Missing right expr")?;
2191                Expr::cond(
2192                    (*left).try_into()?,
2193                    (*cond).try_into()?,
2194                    (*right).try_into()?,
2195                )
2196            }
2197
2198            golem_api_grpc::proto::golem::rib::expr::Expr::Concat(
2199                golem_api_grpc::proto::golem::rib::ConcatExpr { exprs },
2200            ) => {
2201                let exprs: Vec<Expr> = exprs
2202                    .into_iter()
2203                    .map(|expr| expr.try_into())
2204                    .collect::<Result<Vec<_>, _>>()?;
2205                Expr::concat(exprs)
2206            }
2207
2208            golem_api_grpc::proto::golem::rib::expr::Expr::Multiple(
2209                golem_api_grpc::proto::golem::rib::MultipleExpr { exprs },
2210            ) => {
2211                let exprs: Vec<Expr> = exprs
2212                    .into_iter()
2213                    .map(|expr| expr.try_into())
2214                    .collect::<Result<Vec<_>, _>>()?;
2215                Expr::expr_block(exprs)
2216            }
2217
2218            golem_api_grpc::proto::golem::rib::expr::Expr::Sequence(
2219                golem_api_grpc::proto::golem::rib::SequenceExpr { exprs, type_name },
2220            ) => {
2221                let type_annotation = type_name.map(TypeName::try_from).transpose()?;
2222
2223                let exprs: Vec<Expr> = exprs
2224                    .into_iter()
2225                    .map(|expr| expr.try_into())
2226                    .collect::<Result<Vec<_>, _>>()?;
2227                Expr::sequence(exprs, type_annotation)
2228            }
2229
2230            golem_api_grpc::proto::golem::rib::expr::Expr::Tuple(
2231                golem_api_grpc::proto::golem::rib::TupleExpr { exprs },
2232            ) => {
2233                let exprs: Vec<Expr> = exprs
2234                    .into_iter()
2235                    .map(|expr| expr.try_into())
2236                    .collect::<Result<Vec<_>, _>>()?;
2237                Expr::tuple(exprs)
2238            }
2239
2240            golem_api_grpc::proto::golem::rib::expr::Expr::Record(
2241                golem_api_grpc::proto::golem::rib::RecordExpr { fields },
2242            ) => {
2243                let mut values: Vec<(String, Expr)> = vec![];
2244                for record in fields.into_iter() {
2245                    let name = record.name;
2246                    let expr = record.expr.ok_or("Missing expr")?;
2247                    values.push((name, expr.try_into()?));
2248                }
2249                Expr::record(values)
2250            }
2251
2252            golem_api_grpc::proto::golem::rib::expr::Expr::Flags(
2253                golem_api_grpc::proto::golem::rib::FlagsExpr { values },
2254            ) => Expr::flags(values),
2255
2256            golem_api_grpc::proto::golem::rib::expr::Expr::Literal(
2257                golem_api_grpc::proto::golem::rib::LiteralExpr { value },
2258            ) => Expr::literal(value),
2259
2260            golem_api_grpc::proto::golem::rib::expr::Expr::Identifier(
2261                golem_api_grpc::proto::golem::rib::IdentifierExpr { name, type_name },
2262            ) => {
2263                let type_name = type_name.map(TypeName::try_from).transpose()?;
2264
2265                Expr::identifier_global(name.as_str(), type_name)
2266            }
2267
2268            golem_api_grpc::proto::golem::rib::expr::Expr::Boolean(
2269                golem_api_grpc::proto::golem::rib::BooleanExpr { value },
2270            ) => Expr::boolean(value),
2271
2272            golem_api_grpc::proto::golem::rib::expr::Expr::Throw(
2273                golem_api_grpc::proto::golem::rib::ThrowExpr { message },
2274            ) => Expr::throw(message),
2275
2276            golem_api_grpc::proto::golem::rib::expr::Expr::GenerateWorkerName(
2277                golem_api_grpc::proto::golem::rib::GenerateWorkerNameExpr {},
2278            ) => Expr::generate_worker_name(None),
2279
2280            golem_api_grpc::proto::golem::rib::expr::Expr::And(expr) => {
2281                let left = expr.left.ok_or("Missing left expr")?;
2282                let right = expr.right.ok_or("Missing right expr")?;
2283                Expr::and((*left).try_into()?, (*right).try_into()?)
2284            }
2285
2286            golem_api_grpc::proto::golem::rib::expr::Expr::Or(expr) => {
2287                let left = expr.left.ok_or("Missing left expr")?;
2288                let right = expr.right.ok_or("Missing right expr")?;
2289                Expr::or((*left).try_into()?, (*right).try_into()?)
2290            }
2291
2292            golem_api_grpc::proto::golem::rib::expr::Expr::Tag(expr) => {
2293                let expr = expr.expr.ok_or("Missing expr in tag")?;
2294                Expr::get_tag((*expr).try_into()?)
2295            }
2296
2297            golem_api_grpc::proto::golem::rib::expr::Expr::Unwrap(expr) => {
2298                let expr = expr.expr.ok_or("Missing expr")?;
2299                let expr: Expr = (*expr).try_into()?;
2300                expr.unwrap()
2301            }
2302
2303            golem_api_grpc::proto::golem::rib::expr::Expr::Number(number) => {
2304                // Backward compatibility
2305                let type_name = number.type_name.map(TypeName::try_from).transpose()?;
2306                let big_decimal = if let Some(number) = number.number {
2307                    BigDecimal::from_str(&number).map_err(|e| e.to_string())?
2308                } else if let Some(float) = number.float {
2309                    BigDecimal::from_f64(float).ok_or("Invalid float")?
2310                } else {
2311                    return Err("Missing number".to_string());
2312                };
2313
2314                Expr::number(big_decimal).with_type_annotation_opt(type_name)
2315            }
2316            golem_api_grpc::proto::golem::rib::expr::Expr::SelectField(expr) => {
2317                let expr = *expr;
2318                let field = expr.field;
2319                let type_name = expr.type_name.map(TypeName::try_from).transpose()?;
2320                let expr = *expr.expr.ok_or(
2321                    "Mi\
2322                ssing expr",
2323                )?;
2324
2325                Expr::select_field(expr.try_into()?, field.as_str(), type_name)
2326            }
2327            golem_api_grpc::proto::golem::rib::expr::Expr::SelectIndex(expr) => {
2328                let expr = *expr;
2329                let type_name = expr.type_name.map(TypeName::try_from).transpose()?;
2330                let index = expr.index as usize;
2331                let expr = *expr.expr.ok_or("Missing expr")?;
2332
2333                let index_expr =
2334                    Expr::number(BigDecimal::from_usize(index).ok_or("Invalid index")?);
2335
2336                Expr::select_index(expr.try_into()?, index_expr).with_type_annotation_opt(type_name)
2337            }
2338            golem_api_grpc::proto::golem::rib::expr::Expr::Option(expr) => {
2339                let type_name = expr.type_name;
2340                let type_name = type_name.map(TypeName::try_from).transpose()?;
2341
2342                match expr.expr {
2343                    Some(expr) => {
2344                        Expr::option(Some((*expr).try_into()?)).with_type_annotation_opt(type_name)
2345                    }
2346                    None => Expr::option(None).with_type_annotation_opt(type_name),
2347                }
2348            }
2349            golem_api_grpc::proto::golem::rib::expr::Expr::Result(expr) => {
2350                let type_name = expr.type_name;
2351                let type_name = type_name.map(TypeName::try_from).transpose()?;
2352                let result = expr.result.ok_or("Missing result")?;
2353                match result {
2354                    golem_api_grpc::proto::golem::rib::result_expr::Result::Ok(expr) => {
2355                        Expr::ok((*expr).try_into()?, type_name)
2356                    }
2357                    golem_api_grpc::proto::golem::rib::result_expr::Result::Err(expr) => {
2358                        Expr::err((*expr).try_into()?, type_name)
2359                    }
2360                }
2361            }
2362            golem_api_grpc::proto::golem::rib::expr::Expr::PatternMatch(expr) => {
2363                let patterns: Vec<MatchArm> = expr
2364                    .patterns
2365                    .into_iter()
2366                    .map(|expr| expr.try_into())
2367                    .collect::<Result<Vec<_>, _>>()?;
2368                let expr = expr.expr.ok_or("Missing expr")?;
2369                Expr::pattern_match((*expr).try_into()?, patterns)
2370            }
2371            golem_api_grpc::proto::golem::rib::expr::Expr::ListComprehension(
2372                list_comprehension,
2373            ) => {
2374                let iterable_expr = list_comprehension.iterable_expr.ok_or("Missing expr")?;
2375                let iterable_expr = (*iterable_expr).try_into()?;
2376                let yield_expr = list_comprehension.yield_expr.ok_or("Missing list")?;
2377                let yield_expr = (*yield_expr).try_into()?;
2378                let variable_id =
2379                    VariableId::list_comprehension_identifier(list_comprehension.iterated_variable);
2380                Expr::list_comprehension(variable_id, iterable_expr, yield_expr)
2381            }
2382            golem_api_grpc::proto::golem::rib::expr::Expr::ListReduce(list_reduce) => {
2383                let init_value_expr = list_reduce.init_value_expr.ok_or("Missing initial expr")?;
2384                let init_value_expr = (*init_value_expr).try_into()?;
2385                let iterable_expr = list_reduce.iterable_expr.ok_or("Missing expr")?;
2386                let iterable_expr = (*iterable_expr).try_into()?;
2387                let yield_expr = list_reduce.yield_expr.ok_or("Missing list")?;
2388                let yield_expr = (*yield_expr).try_into()?;
2389                let iterated_variable_id =
2390                    VariableId::list_comprehension_identifier(list_reduce.iterated_variable);
2391                let reduce_variable_id =
2392                    VariableId::list_reduce_identifier(list_reduce.reduce_variable);
2393                Expr::list_reduce(
2394                    reduce_variable_id,
2395                    iterated_variable_id,
2396                    iterable_expr,
2397                    init_value_expr,
2398                    yield_expr,
2399                )
2400            }
2401            golem_api_grpc::proto::golem::rib::expr::Expr::Call(expr) => {
2402                let params: Vec<Expr> = expr
2403                    .params
2404                    .into_iter()
2405                    .map(|expr| expr.try_into())
2406                    .collect::<Result<Vec<_>, _>>()?;
2407                // This is not required and kept for backward compatibility
2408                let legacy_invocation_name = expr.name;
2409                let call_type = expr.call_type;
2410                let generic_type_parameter = expr
2411                    .generic_type_parameter
2412                    .map(|tp| GenericTypeParameter { value: tp });
2413
2414                match (legacy_invocation_name, call_type) {
2415                    (Some(legacy), None) => {
2416                        let name = legacy.name.ok_or("Missing function call name")?;
2417                        match name {
2418                            golem_api_grpc::proto::golem::rib::invocation_name::Name::Parsed(name) => {
2419                                // Reading the previous parsed-function-name in persistent store as a dynamic-parsed-function-name
2420                                Expr::call_worker_function(DynamicParsedFunctionName::parse(
2421                                    ParsedFunctionName::try_from(name)?.to_string()
2422                                )?, generic_type_parameter, None, params, None)
2423                            }
2424                            golem_api_grpc::proto::golem::rib::invocation_name::Name::VariantConstructor(
2425                                name,
2426                            ) => Expr::call_worker_function(DynamicParsedFunctionName::parse(name)?, generic_type_parameter, None, params, None),
2427                            golem_api_grpc::proto::golem::rib::invocation_name::Name::EnumConstructor(
2428                                name,
2429                            ) => Expr::call_worker_function(DynamicParsedFunctionName::parse(name)?, generic_type_parameter, None, params, None),
2430                        }
2431                    }
2432                    (_, Some(call_type)) => {
2433                        let name = call_type.name.ok_or("Missing function call name")?;
2434                        match name {
2435                            golem_api_grpc::proto::golem::rib::call_type::Name::Parsed(name) => {
2436                                Expr::call_worker_function(name.try_into()?, generic_type_parameter, None, params, None)
2437                            }
2438                            golem_api_grpc::proto::golem::rib::call_type::Name::VariantConstructor(
2439                                name,
2440                            ) => Expr::call_worker_function(DynamicParsedFunctionName::parse(name)?, generic_type_parameter, None, params, None),
2441                            golem_api_grpc::proto::golem::rib::call_type::Name::EnumConstructor(
2442                                name,
2443                            ) => Expr::call_worker_function(DynamicParsedFunctionName::parse(name)?, generic_type_parameter, None, params, None),
2444                            golem_api_grpc::proto::golem::rib::call_type::Name::InstanceCreation(instance_creation) => {
2445                                let instance_creation_type = InstanceCreationType::try_from(*instance_creation)?;
2446                                let call_type = CallType::InstanceCreation(instance_creation_type);
2447                                Expr::Call {
2448                                    call_type,
2449                                    generic_type_parameter,
2450                                    args: vec![],
2451                                    inferred_type: InferredType::unknown(),
2452                                    source_span: SourceSpan::default(),
2453                                    type_annotation: None, // TODO
2454                                }
2455                            }
2456                        }
2457                    }
2458                    (_, _) => Err("Missing both call type (and legacy invocation type)")?,
2459                }
2460            }
2461            golem_api_grpc::proto::golem::rib::expr::Expr::LazyInvokeMethod(lazy_invoke) => {
2462                let lhs_proto = lazy_invoke.lhs.ok_or("Missing lhs")?;
2463                let lhs = Box::new((*lhs_proto).try_into()?);
2464                let method = lazy_invoke.method;
2465                let generic_type_parameter = lazy_invoke.generic_type_parameter;
2466                let args: Vec<Expr> = lazy_invoke
2467                    .args
2468                    .into_iter()
2469                    .map(Expr::try_from)
2470                    .collect::<Result<Vec<_>, _>>()?;
2471
2472                Expr::InvokeMethodLazy {
2473                    lhs,
2474                    method,
2475                    generic_type_parameter: generic_type_parameter
2476                        .map(|value| GenericTypeParameter { value }),
2477                    args,
2478                    inferred_type: InferredType::unknown(),
2479                    source_span: SourceSpan::default(),
2480                    type_annotation: None, //TODO
2481                }
2482            }
2483        };
2484        Ok(expr)
2485    }
2486}
2487
2488impl Display for Expr {
2489    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2490        write!(f, "{}", text::to_string(self).unwrap())
2491    }
2492}
2493
2494impl Display for ArmPattern {
2495    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2496        write!(f, "{}", text::to_string_arm_pattern(self).unwrap())
2497    }
2498}
2499
2500impl<'de> Deserialize<'de> for Expr {
2501    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
2502    where
2503        D: serde::Deserializer<'de>,
2504    {
2505        let value = Value::deserialize(deserializer)?;
2506        match value {
2507            Value::String(expr_string) => match from_string(expr_string.as_str()) {
2508                Ok(expr) => Ok(expr),
2509                Err(message) => Err(serde::de::Error::custom(message.to_string())),
2510            },
2511
2512            e => Err(serde::de::Error::custom(format!(
2513                "Failed to deserialize expression {e}"
2514            ))),
2515        }
2516    }
2517}
2518
2519impl Serialize for Expr {
2520    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
2521    where
2522        S: Serializer,
2523    {
2524        match text::to_string(self) {
2525            Ok(value) => Value::serialize(&Value::String(value), serializer),
2526            Err(error) => Err(serde::ser::Error::custom(error.to_string())),
2527        }
2528    }
2529}
2530
2531#[cfg(feature = "protobuf")]
2532mod protobuf {
2533    use crate::{ArmPattern, Expr, MatchArm, Range};
2534    use golem_api_grpc::proto::golem::rib::range_expr::RangeExpr;
2535
2536    // It is to be noted that when we change `Expr` tree solely for the purpose of
2537    // updating type inference, we don't need to change the proto version
2538    // of Expr. A proto version of Expr changes only when Rib adds/updates the grammar itself.
2539    // This makes it easy to keep backward compatibility at the persistence level
2540    // (if persistence using grpc encode)
2541    //
2542    // Reason: A proto version of Expr doesn't take into the account the type inferred
2543    // for each expr, or encode any behaviour that's the result of a type inference
2544    // Example: in a type inference, a variable-id of expr which is tagged as `global` becomes
2545    // `VariableId::Local(Identifier)` after a particular type inference phase, however, when encoding
2546    // we don't need to consider this `Identifier` and is kept as global (i.e, the raw form) in Expr.
2547    // This is because we never (want to) encode an Expr which is a result of `infer_types` function.
2548    //
2549    // Summary: We encode Expr only prior to compilation. After compilation, we encode only the RibByteCode.
2550    // If we ever want to encode Expr after type-inference phase, it implies, we need to encode `InferredExpr`
2551    // rather than `Expr` and this will ensure, users when retrieving back the `Expr` will never have
2552    // noise regarding types and variable-ids, and will always stay one to one in round trip
2553    impl From<Expr> for golem_api_grpc::proto::golem::rib::Expr {
2554        fn from(value: Expr) -> Self {
2555            let expr = match value {
2556                Expr::GenerateWorkerName { .. } => Some(
2557                    golem_api_grpc::proto::golem::rib::expr::Expr::GenerateWorkerName(
2558                        golem_api_grpc::proto::golem::rib::GenerateWorkerNameExpr {},
2559                    ),
2560                ),
2561                Expr::Let {
2562                    variable_id,
2563                    type_annotation,
2564                    expr,
2565                    ..
2566                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Let(
2567                    Box::new(golem_api_grpc::proto::golem::rib::LetExpr {
2568                        name: variable_id.name().to_string(),
2569                        expr: Some(Box::new((*expr).into())),
2570                        type_name: type_annotation.map(|t| t.into()),
2571                    }),
2572                )),
2573
2574                Expr::Length { expr, .. } => {
2575                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Length(
2576                        Box::new(golem_api_grpc::proto::golem::rib::LengthExpr {
2577                            expr: Some(Box::new((*expr).into())),
2578                        }),
2579                    ))
2580                }
2581
2582                Expr::SelectField {
2583                    expr,
2584                    field,
2585                    type_annotation,
2586                    ..
2587                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::SelectField(
2588                    Box::new(golem_api_grpc::proto::golem::rib::SelectFieldExpr {
2589                        expr: Some(Box::new((*expr).into())),
2590                        field,
2591                        type_name: type_annotation.map(|t| t.into()),
2592                    }),
2593                )),
2594
2595                Expr::Range { range, .. } => match range {
2596                    Range::RangeFrom { from } => {
2597                        Some(golem_api_grpc::proto::golem::rib::expr::Expr::Range(
2598                            Box::new(golem_api_grpc::proto::golem::rib::RangeExpr {
2599                                range_expr: Some(RangeExpr::RangeFrom(Box::new(
2600                                    golem_api_grpc::proto::golem::rib::RangeFrom {
2601                                        from: Some(Box::new((*from).into())),
2602                                    },
2603                                ))),
2604                            }),
2605                        ))
2606                    }
2607                    Range::Range { from, to } => {
2608                        Some(golem_api_grpc::proto::golem::rib::expr::Expr::Range(
2609                            Box::new(golem_api_grpc::proto::golem::rib::RangeExpr {
2610                                range_expr: Some(RangeExpr::Range(Box::new(
2611                                    golem_api_grpc::proto::golem::rib::Range {
2612                                        from: Some(Box::new((*from).into())),
2613                                        to: Some(Box::new((*to).into())),
2614                                    },
2615                                ))),
2616                            }),
2617                        ))
2618                    }
2619                    Range::RangeInclusive { from, to } => {
2620                        Some(golem_api_grpc::proto::golem::rib::expr::Expr::Range(
2621                            Box::new(golem_api_grpc::proto::golem::rib::RangeExpr {
2622                                range_expr: Some(RangeExpr::RangeInclusive(Box::new(
2623                                    golem_api_grpc::proto::golem::rib::RangeInclusive {
2624                                        from: Some(Box::new((*from).into())),
2625                                        to: Some(Box::new((*to).into())),
2626                                    },
2627                                ))),
2628                            }),
2629                        ))
2630                    }
2631                },
2632
2633                Expr::SelectIndex {
2634                    expr,
2635                    index,
2636                    type_annotation,
2637                    ..
2638                } => Some(
2639                    golem_api_grpc::proto::golem::rib::expr::Expr::SelectIndexV1(Box::new(
2640                        golem_api_grpc::proto::golem::rib::SelectIndexExprV1 {
2641                            expr: Some(Box::new((*expr).into())),
2642                            index: Some(Box::new((*index).into())),
2643                            type_name: type_annotation.map(|t| t.into()),
2644                        },
2645                    )),
2646                ),
2647
2648                Expr::Sequence {
2649                    exprs: expressions,
2650                    type_annotation,
2651                    ..
2652                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Sequence(
2653                    golem_api_grpc::proto::golem::rib::SequenceExpr {
2654                        exprs: expressions.into_iter().map(|expr| expr.into()).collect(),
2655                        type_name: type_annotation.map(|t| t.into()),
2656                    },
2657                )),
2658                Expr::Record { exprs: fields, .. } => {
2659                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Record(
2660                        golem_api_grpc::proto::golem::rib::RecordExpr {
2661                            fields: fields
2662                                .into_iter()
2663                                .map(|(name, expr)| {
2664                                    golem_api_grpc::proto::golem::rib::RecordFieldExpr {
2665                                        name,
2666                                        expr: Some((*expr).into()),
2667                                    }
2668                                })
2669                                .collect(),
2670                        },
2671                    ))
2672                }
2673                Expr::Tuple {
2674                    exprs: expressions, ..
2675                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Tuple(
2676                    golem_api_grpc::proto::golem::rib::TupleExpr {
2677                        exprs: expressions.into_iter().map(|expr| expr.into()).collect(),
2678                    },
2679                )),
2680                Expr::Literal { value, .. } => {
2681                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Literal(
2682                        golem_api_grpc::proto::golem::rib::LiteralExpr { value },
2683                    ))
2684                }
2685                Expr::Number {
2686                    number,
2687                    type_annotation,
2688                    ..
2689                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Number(
2690                    golem_api_grpc::proto::golem::rib::NumberExpr {
2691                        number: Some(number.value.to_string()),
2692                        float: None,
2693                        type_name: type_annotation.map(|t| t.into()),
2694                    },
2695                )),
2696                Expr::Flags { flags, .. } => {
2697                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Flags(
2698                        golem_api_grpc::proto::golem::rib::FlagsExpr { values: flags },
2699                    ))
2700                }
2701                Expr::Identifier {
2702                    variable_id,
2703                    type_annotation,
2704                    ..
2705                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Identifier(
2706                    golem_api_grpc::proto::golem::rib::IdentifierExpr {
2707                        name: variable_id.name(),
2708                        type_name: type_annotation.map(|t| t.into()),
2709                    },
2710                )),
2711                Expr::Boolean { value, .. } => {
2712                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Boolean(
2713                        golem_api_grpc::proto::golem::rib::BooleanExpr { value },
2714                    ))
2715                }
2716                Expr::Concat {
2717                    exprs: expressions, ..
2718                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Concat(
2719                    golem_api_grpc::proto::golem::rib::ConcatExpr {
2720                        exprs: expressions.into_iter().map(|expr| expr.into()).collect(),
2721                    },
2722                )),
2723                Expr::ExprBlock {
2724                    exprs: expressions, ..
2725                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Multiple(
2726                    golem_api_grpc::proto::golem::rib::MultipleExpr {
2727                        exprs: expressions.into_iter().map(|expr| expr.into()).collect(),
2728                    },
2729                )),
2730                Expr::Not { expr, .. } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Not(
2731                    Box::new(golem_api_grpc::proto::golem::rib::NotExpr {
2732                        expr: Some(Box::new((*expr).into())),
2733                    }),
2734                )),
2735                Expr::GreaterThan {
2736                    lhs: left,
2737                    rhs: right,
2738                    ..
2739                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::GreaterThan(
2740                    Box::new(golem_api_grpc::proto::golem::rib::GreaterThanExpr {
2741                        left: Some(Box::new((*left).into())),
2742                        right: Some(Box::new((*right).into())),
2743                    }),
2744                )),
2745                Expr::GreaterThanOrEqualTo { lhs, rhs, .. } => Some(
2746                    golem_api_grpc::proto::golem::rib::expr::Expr::GreaterThanOrEqual(Box::new(
2747                        golem_api_grpc::proto::golem::rib::GreaterThanOrEqualToExpr {
2748                            left: Some(Box::new((*lhs).into())),
2749                            right: Some(Box::new((*rhs).into())),
2750                        },
2751                    )),
2752                ),
2753                Expr::LessThan {
2754                    lhs: left,
2755                    rhs: right,
2756                    ..
2757                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::LessThan(
2758                    Box::new(golem_api_grpc::proto::golem::rib::LessThanExpr {
2759                        left: Some(Box::new((*left).into())),
2760                        right: Some(Box::new((*right).into())),
2761                    }),
2762                )),
2763                Expr::Plus {
2764                    lhs: left,
2765                    rhs: right,
2766                    ..
2767                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Add(
2768                    Box::new(golem_api_grpc::proto::golem::rib::AddExpr {
2769                        left: Some(Box::new((*left).into())),
2770                        right: Some(Box::new((*right).into())),
2771                    }),
2772                )),
2773                Expr::Minus {
2774                    lhs: left,
2775                    rhs: right,
2776                    ..
2777                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Subtract(
2778                    Box::new(golem_api_grpc::proto::golem::rib::SubtractExpr {
2779                        left: Some(Box::new((*left).into())),
2780                        right: Some(Box::new((*right).into())),
2781                    }),
2782                )),
2783                Expr::Divide { lhs, rhs, .. } => {
2784                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Divide(
2785                        Box::new(golem_api_grpc::proto::golem::rib::DivideExpr {
2786                            left: Some(Box::new((*lhs).into())),
2787                            right: Some(Box::new((*rhs).into())),
2788                        }),
2789                    ))
2790                }
2791                Expr::Multiply { lhs, rhs, .. } => {
2792                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Multiply(
2793                        Box::new(golem_api_grpc::proto::golem::rib::MultiplyExpr {
2794                            left: Some(Box::new((*lhs).into())),
2795                            right: Some(Box::new((*rhs).into())),
2796                        }),
2797                    ))
2798                }
2799                Expr::LessThanOrEqualTo { lhs, rhs, .. } => Some(
2800                    golem_api_grpc::proto::golem::rib::expr::Expr::LessThanOrEqual(Box::new(
2801                        golem_api_grpc::proto::golem::rib::LessThanOrEqualToExpr {
2802                            left: Some(Box::new((*lhs).into())),
2803                            right: Some(Box::new((*rhs).into())),
2804                        },
2805                    )),
2806                ),
2807                Expr::EqualTo { lhs, rhs, .. } => {
2808                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::EqualTo(
2809                        Box::new(golem_api_grpc::proto::golem::rib::EqualToExpr {
2810                            left: Some(Box::new((*lhs).into())),
2811                            right: Some(Box::new((*rhs).into())),
2812                        }),
2813                    ))
2814                }
2815                // Note: We were storing and retrieving (proto) condition expressions such that
2816                // `cond` was written `lhs` and vice versa.
2817                // This is probably difficult to fix to keep backward compatibility
2818                // The issue is only with the protobuf types and the roundtrip tests were/are working since
2819                // the read handles this (i.e, reading cond as lhs)
2820                Expr::Cond {
2821                    cond: lhs,
2822                    lhs: cond,
2823                    rhs,
2824                    ..
2825                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Cond(
2826                    Box::new(golem_api_grpc::proto::golem::rib::CondExpr {
2827                        left: Some(Box::new((*lhs).into())),
2828                        cond: Some(Box::new((*cond).into())),
2829                        right: Some(Box::new((*rhs).into())),
2830                    }),
2831                )),
2832                Expr::PatternMatch {
2833                    predicate,
2834                    match_arms,
2835                    ..
2836                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::PatternMatch(
2837                    Box::new(golem_api_grpc::proto::golem::rib::PatternMatchExpr {
2838                        expr: Some(Box::new((*predicate).into())),
2839                        patterns: match_arms.into_iter().map(|a| a.into()).collect(),
2840                    }),
2841                )),
2842                Expr::Option {
2843                    expr,
2844                    type_annotation,
2845                    ..
2846                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Option(
2847                    Box::new(golem_api_grpc::proto::golem::rib::OptionExpr {
2848                        expr: expr.map(|expr| Box::new((*expr).into())),
2849                        type_name: type_annotation.map(|t| t.into()),
2850                    }),
2851                )),
2852                Expr::Result {
2853                    expr,
2854                    type_annotation,
2855                    ..
2856                } => {
2857                    let type_name = type_annotation.map(|t| t.into());
2858
2859                    let result = match expr {
2860                        Ok(expr) => golem_api_grpc::proto::golem::rib::result_expr::Result::Ok(
2861                            Box::new((*expr).into()),
2862                        ),
2863                        Err(expr) => golem_api_grpc::proto::golem::rib::result_expr::Result::Err(
2864                            Box::new((*expr).into()),
2865                        ),
2866                    };
2867
2868                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Result(
2869                        Box::new(golem_api_grpc::proto::golem::rib::ResultExpr {
2870                            result: Some(result),
2871                            type_name,
2872                        }),
2873                    ))
2874                }
2875                Expr::Call {
2876                    call_type,
2877                    generic_type_parameter,
2878                    args,
2879                    ..
2880                } => {
2881                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Call(
2882                        Box::new(golem_api_grpc::proto::golem::rib::CallExpr {
2883                            name: None, // Kept for backward compatibility
2884                            params: args.into_iter().map(|expr| expr.into()).collect(),
2885                            generic_type_parameter: generic_type_parameter.map(|t| t.value),
2886                            call_type: Some(Box::new(
2887                                golem_api_grpc::proto::golem::rib::CallType::from(call_type),
2888                            )),
2889                        }),
2890                    ))
2891                }
2892                Expr::Unwrap { expr, .. } => {
2893                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Unwrap(
2894                        Box::new(golem_api_grpc::proto::golem::rib::UnwrapExpr {
2895                            expr: Some(Box::new((*expr).into())),
2896                        }),
2897                    ))
2898                }
2899                Expr::Throw { message, .. } => {
2900                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Throw(
2901                        golem_api_grpc::proto::golem::rib::ThrowExpr { message },
2902                    ))
2903                }
2904                Expr::GetTag { expr, .. } => {
2905                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Tag(
2906                        Box::new(golem_api_grpc::proto::golem::rib::GetTagExpr {
2907                            expr: Some(Box::new((*expr).into())),
2908                        }),
2909                    ))
2910                }
2911                Expr::And { lhs, rhs, .. } => {
2912                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::And(
2913                        Box::new(golem_api_grpc::proto::golem::rib::AndExpr {
2914                            left: Some(Box::new((*lhs).into())),
2915                            right: Some(Box::new((*rhs).into())),
2916                        }),
2917                    ))
2918                }
2919
2920                Expr::Or { lhs, rhs, .. } => {
2921                    Some(golem_api_grpc::proto::golem::rib::expr::Expr::Or(Box::new(
2922                        golem_api_grpc::proto::golem::rib::OrExpr {
2923                            left: Some(Box::new((*lhs).into())),
2924                            right: Some(Box::new((*rhs).into())),
2925                        },
2926                    )))
2927                }
2928                Expr::ListComprehension {
2929                    iterated_variable,
2930                    iterable_expr,
2931                    yield_expr,
2932                    ..
2933                } => Some(
2934                    golem_api_grpc::proto::golem::rib::expr::Expr::ListComprehension(Box::new(
2935                        golem_api_grpc::proto::golem::rib::ListComprehensionExpr {
2936                            iterated_variable: iterated_variable.name(),
2937                            iterable_expr: Some(Box::new((*iterable_expr).into())),
2938                            yield_expr: Some(Box::new((*yield_expr).into())),
2939                        },
2940                    )),
2941                ),
2942
2943                Expr::ListReduce {
2944                    reduce_variable,
2945                    iterated_variable,
2946                    iterable_expr,
2947                    yield_expr,
2948                    init_value_expr,
2949                    ..
2950                } => Some(golem_api_grpc::proto::golem::rib::expr::Expr::ListReduce(
2951                    Box::new(golem_api_grpc::proto::golem::rib::ListReduceExpr {
2952                        reduce_variable: reduce_variable.name(),
2953                        iterated_variable: iterated_variable.name(),
2954                        iterable_expr: Some(Box::new((*iterable_expr).into())),
2955                        init_value_expr: Some(Box::new((*init_value_expr).into())),
2956                        yield_expr: Some(Box::new((*yield_expr).into())),
2957                    }),
2958                )),
2959                Expr::InvokeMethodLazy {
2960                    lhs,
2961                    method,
2962                    generic_type_parameter,
2963                    args,
2964                    ..
2965                } => Some(
2966                    golem_api_grpc::proto::golem::rib::expr::Expr::LazyInvokeMethod(Box::new(
2967                        golem_api_grpc::proto::golem::rib::LazyInvokeMethodExpr {
2968                            lhs: Some(Box::new((*lhs).into())),
2969                            method,
2970                            generic_type_parameter: generic_type_parameter.map(|t| t.value),
2971                            args: args.into_iter().map(|expr| expr.into()).collect(),
2972                        },
2973                    )),
2974                ),
2975            };
2976
2977            golem_api_grpc::proto::golem::rib::Expr { expr }
2978        }
2979    }
2980
2981    impl TryFrom<golem_api_grpc::proto::golem::rib::ArmPattern> for ArmPattern {
2982        type Error = String;
2983
2984        fn try_from(
2985            value: golem_api_grpc::proto::golem::rib::ArmPattern,
2986        ) -> Result<Self, Self::Error> {
2987            let pattern = value.pattern.ok_or("Missing pattern")?;
2988            match pattern {
2989                golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::WildCard(_) => {
2990                    Ok(ArmPattern::WildCard)
2991                }
2992                golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::As(asp) => {
2993                    let name = asp.name;
2994                    let pattern = asp.pattern.ok_or("Missing pattern")?;
2995                    Ok(ArmPattern::As(name, Box::new((*pattern).try_into()?)))
2996                }
2997                golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::Constructor(
2998                    golem_api_grpc::proto::golem::rib::ConstructorArmPattern { name, patterns },
2999                ) => {
3000                    let patterns = patterns
3001                        .into_iter()
3002                        .map(ArmPattern::try_from)
3003                        .collect::<Result<Vec<_>, _>>()?;
3004                    Ok(ArmPattern::Constructor(name, patterns))
3005                }
3006                golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::TupleConstructor(
3007                    golem_api_grpc::proto::golem::rib::TupleConstructorArmPattern { patterns },
3008                ) => {
3009                    let patterns = patterns
3010                        .into_iter()
3011                        .map(ArmPattern::try_from)
3012                        .collect::<Result<Vec<_>, _>>()?;
3013                    Ok(ArmPattern::TupleConstructor(patterns))
3014                }
3015                golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::Literal(
3016                    golem_api_grpc::proto::golem::rib::LiteralArmPattern { expr },
3017                ) => {
3018                    let inner = expr.ok_or("Missing expr")?;
3019                    Ok(ArmPattern::Literal(Box::new(inner.try_into()?)))
3020                }
3021                golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::RecordConstructor(
3022                    golem_api_grpc::proto::golem::rib::RecordConstructorArmPattern { fields },
3023                ) => {
3024                    let fields = fields
3025                        .into_iter()
3026                        .map(|field| {
3027                            let name = field.name;
3028                            let proto_pattern = field.pattern.ok_or("Missing pattern")?;
3029                            let arm_pattern = ArmPattern::try_from(proto_pattern)?;
3030                            Ok((name, arm_pattern))
3031                        })
3032                        .collect::<Result<Vec<_>, String>>()?;
3033                    Ok(ArmPattern::RecordConstructor(fields))
3034                }
3035                golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::ListConstructor(
3036                    golem_api_grpc::proto::golem::rib::ListConstructorArmPattern { patterns },
3037                ) => {
3038                    let patterns = patterns
3039                        .into_iter()
3040                        .map(ArmPattern::try_from)
3041                        .collect::<Result<Vec<_>, _>>()?;
3042                    Ok(ArmPattern::ListConstructor(patterns))
3043                }
3044            }
3045        }
3046    }
3047
3048    impl From<ArmPattern> for golem_api_grpc::proto::golem::rib::ArmPattern {
3049        fn from(value: ArmPattern) -> Self {
3050            match value {
3051                ArmPattern::WildCard => golem_api_grpc::proto::golem::rib::ArmPattern {
3052                    pattern: Some(
3053                        golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::WildCard(
3054                            golem_api_grpc::proto::golem::rib::WildCardArmPattern {},
3055                        ),
3056                    ),
3057                },
3058                ArmPattern::As(name, pattern) => golem_api_grpc::proto::golem::rib::ArmPattern {
3059                    pattern: Some(golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::As(
3060                        Box::new(golem_api_grpc::proto::golem::rib::AsArmPattern {
3061                            name,
3062                            pattern: Some(Box::new((*pattern).into())),
3063                        }),
3064                    )),
3065                },
3066                ArmPattern::Constructor(name, patterns) => {
3067                    golem_api_grpc::proto::golem::rib::ArmPattern {
3068                        pattern: Some(
3069                            golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::Constructor(
3070                                golem_api_grpc::proto::golem::rib::ConstructorArmPattern {
3071                                    name,
3072                                    patterns: patterns
3073                                        .into_iter()
3074                                        .map(golem_api_grpc::proto::golem::rib::ArmPattern::from)
3075                                        .collect(),
3076                                },
3077                            ),
3078                        ),
3079                    }
3080                }
3081                ArmPattern::Literal(expr) => golem_api_grpc::proto::golem::rib::ArmPattern {
3082                    pattern: Some(
3083                        golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::Literal(
3084                            golem_api_grpc::proto::golem::rib::LiteralArmPattern {
3085                                expr: Some((*expr).into()),
3086                            },
3087                        ),
3088                    ),
3089                },
3090
3091                ArmPattern::TupleConstructor(patterns) => {
3092                    golem_api_grpc::proto::golem::rib::ArmPattern {
3093                        pattern: Some(
3094                            golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::TupleConstructor(
3095                                golem_api_grpc::proto::golem::rib::TupleConstructorArmPattern {
3096                                    patterns: patterns
3097                                        .into_iter()
3098                                        .map(golem_api_grpc::proto::golem::rib::ArmPattern::from)
3099                                        .collect(),
3100                                },
3101                            ),
3102                        ),
3103                    }
3104                }
3105
3106                ArmPattern::RecordConstructor(fields) => {
3107                    golem_api_grpc::proto::golem::rib::ArmPattern {
3108                        pattern: Some(
3109                            golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::RecordConstructor(
3110                                golem_api_grpc::proto::golem::rib::RecordConstructorArmPattern {
3111                                    fields: fields
3112                                        .into_iter()
3113                                        .map(|(name, pattern)| {
3114                                            golem_api_grpc::proto::golem::rib::RecordFieldArmPattern {
3115                                                name,
3116                                                pattern: Some(pattern.into()),
3117                                            }
3118                                        })
3119                                        .collect(),
3120                                },
3121                            ),
3122                        ),
3123                    }
3124                }
3125
3126                ArmPattern::ListConstructor(patterns) => {
3127                    golem_api_grpc::proto::golem::rib::ArmPattern {
3128                        pattern: Some(
3129                            golem_api_grpc::proto::golem::rib::arm_pattern::Pattern::ListConstructor(
3130                                golem_api_grpc::proto::golem::rib::ListConstructorArmPattern {
3131                                    patterns: patterns
3132                                        .into_iter()
3133                                        .map(golem_api_grpc::proto::golem::rib::ArmPattern::from)
3134                                        .collect(),
3135                                },
3136                            ),
3137                        ),
3138                    }
3139                }
3140            }
3141        }
3142    }
3143
3144    impl TryFrom<golem_api_grpc::proto::golem::rib::MatchArm> for MatchArm {
3145        type Error = String;
3146
3147        fn try_from(
3148            value: golem_api_grpc::proto::golem::rib::MatchArm,
3149        ) -> Result<Self, Self::Error> {
3150            let pattern = value.pattern.ok_or("Missing pattern")?;
3151            let expr = value.expr.ok_or("Missing expr")?;
3152            Ok(MatchArm::new(pattern.try_into()?, expr.try_into()?))
3153        }
3154    }
3155
3156    impl From<MatchArm> for golem_api_grpc::proto::golem::rib::MatchArm {
3157        fn from(value: MatchArm) -> Self {
3158            let MatchArm {
3159                arm_pattern,
3160                arm_resolution_expr,
3161            } = value;
3162            golem_api_grpc::proto::golem::rib::MatchArm {
3163                pattern: Some(arm_pattern.into()),
3164                expr: Some((*arm_resolution_expr).into()),
3165            }
3166        }
3167    }
3168}
3169
3170fn find_expr(expr: &mut Expr, source_span: &SourceSpan) -> Option<Expr> {
3171    let mut expr = expr.clone();
3172
3173    let mut visitor = ExprVisitor::bottom_up(&mut expr);
3174
3175    while let Some(current) = visitor.pop_back() {
3176        let span = current.source_span();
3177
3178        if source_span.eq(&span) {
3179            return Some(current.clone());
3180        }
3181    }
3182
3183    None
3184}