rib/
expr.rs

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