diff --git a/golem-api-grpc/proto/golem/rib/expr.proto b/golem-api-grpc/proto/golem/rib/expr.proto
index a821089344..5b874dd4dd 100644
--- a/golem-api-grpc/proto/golem/rib/expr.proto
+++ b/golem-api-grpc/proto/golem/rib/expr.proto
@@ -35,6 +35,7 @@ message Expr {
     GetTagExpr tag = 26;
     UnwrapExpr unwrap = 27;
     ThrowExpr throw = 28;
+    OrExpr or = 29;
   }
 }
 
@@ -126,6 +127,11 @@ message AndExpr {
   Expr right = 2;
 }
 
+message OrExpr {
+  Expr left = 1;
+  Expr right = 2;
+}
+
 message GreaterThanOrEqualToExpr {
   Expr left = 1;
   Expr right = 2;
diff --git a/golem-api-grpc/proto/golem/rib/ir.proto b/golem-api-grpc/proto/golem/rib/ir.proto
index f5f0d7f5a7..228d904aec 100644
--- a/golem-api-grpc/proto/golem/rib/ir.proto
+++ b/golem-api-grpc/proto/golem/rib/ir.proto
@@ -42,6 +42,7 @@ message RibIR {
         EnumConstructionInstruction enum_construction = 30;
         And and = 31;
         CreateFunctionNameInstruction create_function_name = 32;
+        Or or = 33;
     }
 }
 
@@ -114,6 +115,7 @@ message LessThanOrEqualTo {}
 message GetTag {}
 message Negate {}
 message And {}
+message Or {}
 
 message FunctionReferenceType {
   oneof type {
diff --git a/golem-rib/src/compiler/byte_code.rs b/golem-rib/src/compiler/byte_code.rs
index 71e6ed9907..b8ef1ac436 100644
--- a/golem-rib/src/compiler/byte_code.rs
+++ b/golem-rib/src/compiler/byte_code.rs
@@ -151,10 +151,42 @@ mod internal {
                 instructions.push(RibIR::LessThanOrEqualTo);
             }
             Expr::And(lhs, rhs, _) => {
-                stack.push(ExprState::from_expr(rhs.deref()));
-                stack.push(ExprState::from_expr(lhs.deref()));
-                instructions.push(RibIR::And);
+                // This optimization isn't optional, it's required for the correct functioning of the interpreter
+                let optimised_expr = Expr::cond(
+                    Expr::EqualTo(
+                        lhs.clone(),
+                        Box::new(Expr::Boolean(true, InferredType::Bool)),
+                        InferredType::Bool,
+                    ),
+                    Expr::EqualTo(
+                        rhs.clone(),
+                        Box::new(Expr::Boolean(true, InferredType::Bool)),
+                        InferredType::Bool,
+                    ),
+                    Expr::Boolean(false, InferredType::Bool),
+                );
+
+                stack.push(ExprState::from_expr(&optimised_expr));
             }
+
+            Expr::Or(lhs, rhs, _) => {
+                let optimised_expr = Expr::cond(
+                    Expr::EqualTo(
+                        lhs.clone(),
+                        Box::new(Expr::Boolean(true, InferredType::Bool)),
+                        InferredType::Bool,
+                    ),
+                    Expr::Boolean(true, InferredType::Bool),
+                    Expr::EqualTo(
+                        rhs.clone(),
+                        Box::new(Expr::Boolean(true, InferredType::Bool)),
+                        InferredType::Bool,
+                    ),
+                );
+
+                stack.push(ExprState::from_expr(&optimised_expr));
+            }
+
             Expr::Record(fields, inferred_type) => {
                 // Push field instructions in reverse order
                 for (field_name, field_expr) in fields.iter().rev() {
diff --git a/golem-rib/src/compiler/desugar.rs b/golem-rib/src/compiler/desugar.rs
index cab54a5921..1af693e664 100644
--- a/golem-rib/src/compiler/desugar.rs
+++ b/golem-rib/src/compiler/desugar.rs
@@ -31,6 +31,7 @@ pub fn desugar_pattern_match(
 }
 
 mod internal {
+    use crate::call_type::CallType;
     use crate::{ArmPattern, Expr, InferredType, MatchArm, VariableId};
 
     pub(crate) fn build_expr_from(if_branches: Vec<IfThenBranch>) -> Option<Expr> {
@@ -89,13 +90,9 @@ mod internal {
         // some(some(x)) => "hello"
         // }
         match arm_pattern {
-            ArmPattern::Literal(arm_pattern_expr) => handle_literal(
-                arm_pattern_expr,
-                pred_expr,
-                resolution,
-                tag,
-                inferred_type_of_pred,
-            ),
+            ArmPattern::Literal(arm_pattern_expr) => {
+                handle_literal(arm_pattern_expr, pred_expr, resolution, tag)
+            }
 
             ArmPattern::Constructor(constructor_name, arm_patterns) => hande_constructor(
                 pred_expr,
@@ -103,6 +100,7 @@ mod internal {
                 arm_patterns,
                 resolution,
                 inferred_type_of_pred,
+                tag,
             ),
 
             ArmPattern::TupleConstructor(arm_patterns) => hande_constructor(
@@ -111,6 +109,7 @@ mod internal {
                 arm_patterns,
                 resolution,
                 inferred_type_of_pred,
+                tag,
             ),
 
             ArmPattern::ListConstructor(arm_patterns) => hande_constructor(
@@ -119,14 +118,18 @@ mod internal {
                 arm_patterns,
                 resolution,
                 inferred_type_of_pred,
+                tag,
             ),
 
-            ArmPattern::RecordConstructor(field_arm_pattern_collection) => handle_record(
-                pred_expr,
-                field_arm_pattern_collection,
-                resolution,
-                inferred_type_of_pred,
-            ),
+            ArmPattern::RecordConstructor(field_arm_pattern_collection) => {
+                handle_record_constructor(
+                    pred_expr,
+                    field_arm_pattern_collection,
+                    resolution,
+                    inferred_type_of_pred,
+                    tag,
+                )
+            }
 
             ArmPattern::As(name, inner_pattern) => handle_as_pattern(
                 name,
@@ -152,80 +155,8 @@ mod internal {
         pred_expr: &Expr,
         resolution: &Expr,
         tag: Option<Expr>,
-        pred_expr_inferred_type: InferredType,
     ) -> Option<IfThenBranch> {
         match arm_pattern_expr {
-            Expr::Option(Some(inner_pattern), _) => {
-                let unwrapped_inferred_type = match pred_expr_inferred_type {
-                    InferredType::Option(inner) => *inner,
-                    _ => InferredType::Unknown,
-                };
-
-                get_conditions(
-                    &MatchArm::new(
-                        ArmPattern::Literal(inner_pattern.clone()),
-                        resolution.clone(),
-                    ),
-                    &pred_expr.unwrap(),
-                    Some(Expr::equal_to(
-                        Expr::tag(pred_expr.clone()),
-                        Expr::literal("some"),
-                    )),
-                    unwrapped_inferred_type,
-                )
-            }
-
-            Expr::Option(None, _) => {
-                let branch = IfThenBranch {
-                    condition: Expr::equal_to(Expr::tag(pred_expr.clone()), Expr::literal("none")),
-                    body: resolution.clone(),
-                };
-                Some(branch)
-            }
-
-            Expr::Result(Ok(inner_pattern), _) => {
-                let unwrapped_inferred_type = match pred_expr_inferred_type {
-                    InferredType::Result { ok, .. } => {
-                        ok.unwrap_or(Box::new(InferredType::Unknown))
-                    }
-                    _ => Box::new(InferredType::Unknown),
-                };
-
-                get_conditions(
-                    &MatchArm::new(
-                        ArmPattern::Literal(inner_pattern.clone()),
-                        resolution.clone(),
-                    ),
-                    &pred_expr.unwrap(),
-                    Some(Expr::equal_to(
-                        Expr::tag(pred_expr.clone()),
-                        Expr::literal("ok"),
-                    )),
-                    *unwrapped_inferred_type,
-                )
-            }
-            Expr::Result(Err(inner_pattern), _) => {
-                let unwrapped_inferred_type = match pred_expr_inferred_type {
-                    InferredType::Result { error, .. } => {
-                        error.unwrap_or(Box::new(InferredType::Unknown))
-                    }
-                    _ => Box::new(InferredType::Unknown),
-                };
-
-                get_conditions(
-                    &MatchArm::new(
-                        ArmPattern::Literal(inner_pattern.clone()),
-                        resolution.clone(),
-                    ),
-                    &pred_expr.unwrap(),
-                    Some(Expr::equal_to(
-                        Expr::tag(pred_expr.clone()),
-                        Expr::literal("err"),
-                    )),
-                    *unwrapped_inferred_type,
-                )
-            }
-
             Expr::Identifier(identifier, inferred_type) => {
                 let assign_var = Expr::Let(
                     identifier.clone(),
@@ -235,6 +166,7 @@ mod internal {
                 );
 
                 let block = Expr::multiple(vec![assign_var, resolution.clone()]);
+
                 let branch = IfThenBranch {
                     condition: tag.unwrap_or(Expr::boolean(true)),
                     body: block,
@@ -242,22 +174,40 @@ mod internal {
                 Some(branch)
             }
 
+            Expr::Call(CallType::EnumConstructor(name), _, _) => {
+                let cond = if let Some(t) = tag {
+                    Expr::and(
+                        t,
+                        Expr::equal_to(Expr::get_tag(pred_expr.clone()), Expr::literal(name)),
+                    )
+                } else {
+                    Expr::equal_to(Expr::get_tag(pred_expr.clone()), Expr::literal(name))
+                };
+
+                let branch = IfThenBranch {
+                    condition: cond,
+                    body: resolution.clone(),
+                };
+                Some(branch)
+            }
+
             _ => {
-                // use tag lookup
                 let branch = IfThenBranch {
                     condition: Expr::equal_to(pred_expr.clone(), arm_pattern_expr.clone()),
                     body: resolution.clone(),
                 };
+
                 Some(branch)
             }
         }
     }
 
-    fn handle_record(
+    fn handle_record_constructor(
         pred_expr: &Expr,
         bind_patterns: &[(String, ArmPattern)],
         resolution: &Expr,
         pred_expr_inferred_type: InferredType,
+        tag: Option<Expr>,
     ) -> Option<IfThenBranch> {
         match pred_expr_inferred_type {
             InferredType::Record(field_and_types) => {
@@ -301,7 +251,13 @@ mod internal {
                 let and_cond = Expr::and_combine(conditions);
 
                 and_cond.map(|c| IfThenBranch {
-                    condition: c,
+                    condition: {
+                        if let Some(t) = tag {
+                            Expr::and(t, c)
+                        } else {
+                            c
+                        }
+                    },
                     body: Expr::multiple(resolution_body),
                 })
             }
@@ -316,6 +272,7 @@ mod internal {
         bind_patterns: &[ArmPattern],
         resolution: &Expr,
         pred_expr_inferred_type: InferredType,
+        tag: Option<Expr>,
     ) -> Option<IfThenBranch> {
         match pred_expr_inferred_type {
             InferredType::Variant(variant) => {
@@ -326,53 +283,96 @@ mod internal {
                     .find(|(case_name, _)| case_name == constructor_name);
                 let inner_variant_arg_type = inner_type.and_then(|(_, typ)| typ.clone());
 
+                let cond = if let Some(t) = tag {
+                    Expr::and(
+                        t,
+                        Expr::equal_to(
+                            Expr::get_tag(pred_expr.clone()),
+                            Expr::literal(constructor_name),
+                        ),
+                    )
+                } else {
+                    Expr::equal_to(
+                        Expr::get_tag(pred_expr.clone()),
+                        Expr::literal(constructor_name),
+                    )
+                };
                 match (arg_pattern_opt, inner_variant_arg_type) {
                     (None, None) => None,
                     (Some(pattern), Some(inferred_type)) => get_conditions(
                         &MatchArm::new(pattern.clone(), resolution.clone()),
                         &pred_expr.unwrap(),
-                        Some(Expr::equal_to(
-                            Expr::tag(pred_expr.clone()),
-                            Expr::literal(constructor_name),
-                        )),
+                        Some(cond),
                         inferred_type,
                     ),
-                    _ => None, // Probably fail here
+                    _ => None,
                 }
             }
-            InferredType::Option(inner) => match bind_patterns.first() {
-                Some(pattern) => get_conditions(
-                    &MatchArm::new(pattern.clone(), resolution.clone()),
-                    &pred_expr.unwrap(),
-                    Some(Expr::equal_to(
-                        Expr::tag(pred_expr.clone()),
-                        Expr::literal(constructor_name),
-                    )),
-                    *inner,
-                ),
-                _ => Some(IfThenBranch {
-                    condition: Expr::equal_to(
-                        Expr::tag(pred_expr.clone()),
+
+            InferredType::Option(inner) if constructor_name == "some" => {
+                let cond = if let Some(t) = tag {
+                    Expr::and(
+                        t,
+                        Expr::equal_to(
+                            Expr::get_tag(pred_expr.clone()),
+                            Expr::literal(constructor_name),
+                        ),
+                    )
+                } else {
+                    Expr::equal_to(
+                        Expr::get_tag(pred_expr.clone()),
                         Expr::literal(constructor_name),
+                    )
+                };
+
+                match bind_patterns.first() {
+                    Some(pattern) => get_conditions(
+                        &MatchArm::new(pattern.clone(), resolution.clone()),
+                        &pred_expr.unwrap(),
+                        Some(cond),
+                        *inner,
                     ),
-                    body: resolution.clone(),
-                }),
-            },
+                    _ => None,
+                }
+            }
+
+            InferredType::Option(_) if constructor_name == "none" => Some(IfThenBranch {
+                condition: Expr::equal_to(
+                    Expr::get_tag(pred_expr.clone()),
+                    Expr::literal(constructor_name),
+                ),
+                body: resolution.clone(),
+            }),
+
             InferredType::Result { ok, error } => {
                 let inner_variant_arg_type = if constructor_name == "ok" {
                     ok.as_deref()
-                } else {
+                } else if constructor_name == "err" {
                     error.as_deref()
+                } else {
+                    return None;
+                };
+
+                let cond = if let Some(t) = tag {
+                    Expr::and(
+                        t,
+                        Expr::equal_to(
+                            Expr::get_tag(pred_expr.clone()),
+                            Expr::literal(constructor_name),
+                        ),
+                    )
+                } else {
+                    Expr::equal_to(
+                        Expr::get_tag(pred_expr.clone()),
+                        Expr::literal(constructor_name),
+                    )
                 };
 
                 match bind_patterns.first() {
                     Some(pattern) => get_conditions(
                         &MatchArm::new(pattern.clone(), resolution.clone()),
                         &pred_expr.unwrap(),
-                        Some(Expr::equal_to(
-                            Expr::tag(pred_expr.clone()),
-                            Expr::literal(constructor_name),
-                        )),
+                        Some(cond),
                         inner_variant_arg_type
                             .unwrap_or(&InferredType::Unknown)
                             .clone(),
@@ -419,7 +419,13 @@ mod internal {
                 let and_cond = Expr::and_combine(conditions);
 
                 and_cond.map(|c| IfThenBranch {
-                    condition: c,
+                    condition: {
+                        if let Some(t) = tag {
+                            Expr::and(t, c)
+                        } else {
+                            c
+                        }
+                    },
                     body: Expr::multiple(resolution_body),
                 })
             }
@@ -461,7 +467,13 @@ mod internal {
                 let and_cond = Expr::and_combine(conditions);
 
                 and_cond.map(|c| IfThenBranch {
-                    condition: c,
+                    condition: {
+                        if let Some(t) = tag {
+                            Expr::and(t, c)
+                        } else {
+                            c
+                        }
+                    },
                     body: Expr::multiple(resolution_body),
                 })
             }
diff --git a/golem-rib/src/compiler/ir.rs b/golem-rib/src/compiler/ir.rs
index 2d7722e30b..25a375a48b 100644
--- a/golem-rib/src/compiler/ir.rs
+++ b/golem-rib/src/compiler/ir.rs
@@ -17,7 +17,7 @@ use bincode::{Decode, Encode};
 use golem_api_grpc::proto::golem::rib::rib_ir::Instruction;
 use golem_api_grpc::proto::golem::rib::{
     And, CallInstruction, ConcatInstruction, CreateFunctionNameInstruction, EqualTo, GetTag,
-    GreaterThan, GreaterThanOrEqualTo, JumpInstruction, LessThan, LessThanOrEqualTo, Negate,
+    GreaterThan, GreaterThanOrEqualTo, JumpInstruction, LessThan, LessThanOrEqualTo, Negate, Or,
     PushListInstruction, PushNoneInstruction, PushTupleInstruction, RibIr as ProtoRibIR,
 };
 use golem_wasm_ast::analysis::{AnalysedType, TypeStr};
@@ -44,6 +44,7 @@ pub enum RibIR {
     EqualTo,
     GreaterThan,
     And,
+    Or,
     LessThan,
     GreaterThanOrEqualTo,
     LessThanOrEqualTo,
@@ -318,6 +319,7 @@ impl TryFrom<ProtoRibIR> for RibIR {
             Instruction::GreaterThanOrEqualTo(_) => Ok(RibIR::GreaterThanOrEqualTo),
             Instruction::LessThanOrEqualTo(_) => Ok(RibIR::LessThanOrEqualTo),
             Instruction::And(_) => Ok(RibIR::And),
+            Instruction::Or(_) => Ok(RibIR::Or),
             Instruction::JumpIfFalse(value) => Ok(RibIR::JumpIfFalse(InstructionId::from(
                 value.instruction_id as usize,
             ))),
@@ -424,6 +426,7 @@ impl From<RibIR> for ProtoRibIR {
                 })
             }
             RibIR::And => Instruction::And(And {}),
+            RibIR::Or => Instruction::Or(Or {}),
             RibIR::AssignVar(value) => Instruction::AssignVar(value.into()),
             RibIR::LoadVar(value) => Instruction::LoadVar(value.into()),
             RibIR::CreateAndPushRecord(value) => Instruction::CreateAndPushRecord((&value).into()),
diff --git a/golem-rib/src/expr.rs b/golem-rib/src/expr.rs
index 787e5e127d..781a9f6851 100644
--- a/golem-rib/src/expr.rs
+++ b/golem-rib/src/expr.rs
@@ -50,6 +50,7 @@ pub enum Expr {
     Not(Box<Expr>, InferredType),
     GreaterThan(Box<Expr>, Box<Expr>, InferredType),
     And(Box<Expr>, Box<Expr>, InferredType),
+    Or(Box<Expr>, Box<Expr>, InferredType),
     GreaterThanOrEqualTo(Box<Expr>, Box<Expr>, InferredType),
     LessThanOrEqualTo(Box<Expr>, Box<Expr>, InferredType),
     EqualTo(Box<Expr>, Box<Expr>, InferredType),
@@ -325,6 +326,10 @@ impl Expr {
         )
     }
 
+    pub fn or(left: Expr, right: Expr) -> Self {
+        Expr::Or(Box::new(left), Box::new(right), InferredType::Bool)
+    }
+
     pub fn pattern_match(expr: Expr, match_arms: Vec<MatchArm>) -> Self {
         Expr::PatternMatch(Box::new(expr), match_arms, InferredType::Unknown)
     }
@@ -358,7 +363,7 @@ impl Expr {
         Expr::SelectIndex(Box::new(expr), index, InferredType::Unknown)
     }
 
-    pub fn tag(expr: Expr) -> Self {
+    pub fn get_tag(expr: Expr) -> Self {
         Expr::GetTag(Box::new(expr), InferredType::Unknown)
     }
 
@@ -412,6 +417,7 @@ impl Expr {
             | Expr::Throw(_, inferred_type)
             | Expr::GetTag(_, inferred_type)
             | Expr::And(_, _, inferred_type)
+            | Expr::Or(_, _, inferred_type)
             | Expr::Call(_, _, inferred_type) => inferred_type.clone(),
         }
     }
@@ -420,11 +426,7 @@ impl Expr {
         &mut self,
         function_type_registry: &FunctionTypeRegistry,
     ) -> Result<(), Vec<String>> {
-        self.bind_types();
-        self.name_binding_pattern_match_variables();
-        self.name_binding_local_variables();
-        self.infer_variants(function_type_registry);
-        self.infer_enums(function_type_registry);
+        self.infer_types_initial_phase(function_type_registry)?;
         self.infer_call_arguments_type(function_type_registry)
             .map_err(|x| vec![x])?;
         type_inference::type_inference_fix_point(Self::inference_scan, self)
@@ -433,29 +435,47 @@ impl Expr {
         Ok(())
     }
 
+    pub fn infer_types_initial_phase(
+        &mut self,
+        function_type_registry: &FunctionTypeRegistry,
+    ) -> Result<(), Vec<String>> {
+        self.bind_types();
+        self.name_binding_pattern_match_variables();
+        self.name_binding_local_variables();
+        self.infer_variants(function_type_registry);
+        self.infer_enums(function_type_registry);
+
+        Ok(())
+    }
+
     // An inference scan is a single cycle of to-and-fro scanning of Rib expression
     // to infer the types
     pub fn inference_scan(&mut self) -> Result<(), String> {
         self.infer_all_identifiers()?;
         self.push_types_down()?;
         self.infer_all_identifiers()?;
-        self.pull_types_up()?;
+        let expr = self.pull_types_up()?;
+        *self = expr;
         self.unify_types().unwrap_or(());
         self.infer_global_inputs();
 
         Ok(())
     }
 
+    // Make sure the bindings in the arm pattern of a pattern match are given variable-ids.
+    // The same variable-ids will be tagged to the corresponding identifiers in the arm resolution
+    // to avoid conflicts.
     pub fn name_binding_pattern_match_variables(&mut self) {
         type_inference::name_binding_pattern_matches(self);
     }
-    // We make sure the let bindings name are properly
-    // bound to the named identifiers.
+
+    // Make sure the variable assignment (let binding) are given variable ids,
+    // which will be tagged to the corresponding identifiers to avoid conflicts.
+    // This is done only for local variables and not global variables
     pub fn name_binding_local_variables(&mut self) {
         type_inference::name_binding_local_variables(self);
     }
 
-    // At this point we simply update the types to the parameter type expressions and the call expression itself.
     pub fn infer_call_arguments_type(
         &mut self,
         function_type_registry: &FunctionTypeRegistry,
@@ -471,8 +491,8 @@ impl Expr {
         type_inference::infer_all_identifiers(self)
     }
 
-    pub fn pull_types_up(&mut self) -> Result<(), String> {
-        type_inference::pull_types_up(self)
+    pub fn pull_types_up(&self) -> Result<Expr, String> {
+        type_inference::type_pull_up(self)
     }
 
     pub fn infer_global_inputs(&mut self) {
@@ -526,6 +546,7 @@ impl Expr {
             | Expr::Throw(_, inferred_type)
             | Expr::GetTag(_, inferred_type)
             | Expr::And(_, _, inferred_type)
+            | Expr::Or(_, _, inferred_type)
             | Expr::Call(_, _, inferred_type) => {
                 if new_inferred_type != InferredType::Unknown {
                     *inferred_type = inferred_type.merge(new_inferred_type);
@@ -566,6 +587,7 @@ impl Expr {
             | Expr::Unwrap(_, inferred_type)
             | Expr::Throw(_, inferred_type)
             | Expr::And(_, _, inferred_type)
+            | Expr::Or(_, _, inferred_type)
             | Expr::GetTag(_, inferred_type)
             | Expr::Call(_, _, inferred_type) => {
                 if new_inferred_type != InferredType::Unknown {
@@ -692,6 +714,14 @@ pub enum ArmPattern {
 }
 
 impl ArmPattern {
+    pub fn constructor(name: &str, patterns: Vec<ArmPattern>) -> ArmPattern {
+        ArmPattern::Constructor(name.to_string(), patterns)
+    }
+
+    pub fn literal(expr: Expr) -> ArmPattern {
+        ArmPattern::Literal(Box::new(expr))
+    }
+
     pub fn get_expr_literals_mut(&mut self) -> Vec<&mut Box<Expr>> {
         match self {
             ArmPattern::Literal(expr) => vec![expr],
@@ -961,9 +991,15 @@ impl TryFrom<golem_api_grpc::proto::golem::rib::Expr> for Expr {
                 Expr::and((*left).try_into()?, (*right).try_into()?)
             }
 
+            golem_api_grpc::proto::golem::rib::expr::Expr::Or(expr) => {
+                let left = expr.left.ok_or("Missing left expr")?;
+                let right = expr.right.ok_or("Missing right expr")?;
+                Expr::or((*left).try_into()?, (*right).try_into()?)
+            }
+
             golem_api_grpc::proto::golem::rib::expr::Expr::Tag(expr) => {
                 let expr = expr.expr.ok_or("Missing expr in tag")?;
-                Expr::tag((*expr).try_into()?)
+                Expr::get_tag((*expr).try_into()?)
             }
 
             golem_api_grpc::proto::golem::rib::expr::Expr::Unwrap(expr) => {
@@ -1273,6 +1309,13 @@ impl From<Expr> for golem_api_grpc::proto::golem::rib::Expr {
                     right: Some(Box::new((*right).into())),
                 }),
             )),
+
+            Expr::Or(left, right, _) => Some(golem_api_grpc::proto::golem::rib::expr::Expr::Or(
+                Box::new(golem_api_grpc::proto::golem::rib::OrExpr {
+                    left: Some(Box::new((*left).into())),
+                    right: Some(Box::new((*right).into())),
+                }),
+            )),
         };
 
         golem_api_grpc::proto::golem::rib::Expr { expr }
@@ -1546,13 +1589,14 @@ mod tests {
                     Expr::identifier("foo"),
                     vec![
                         MatchArm::new(
-                            ArmPattern::Literal(Box::new(Expr::option(Some(Expr::identifier(
-                                "x",
-                            ))))),
+                            ArmPattern::constructor(
+                                "some",
+                                vec![ArmPattern::Literal(Box::new(Expr::identifier("x")))],
+                            ),
                             Expr::identifier("x"),
                         ),
                         MatchArm::new(
-                            ArmPattern::Literal(Box::new(Expr::option(None))),
+                            ArmPattern::constructor("none", vec![]),
                             Expr::boolean(false),
                         ),
                     ],
@@ -1564,11 +1608,17 @@ mod tests {
                     Expr::identifier("bar"),
                     vec![
                         MatchArm::new(
-                            ArmPattern::Literal(Box::new(Expr::ok(Expr::identifier("x")))),
+                            ArmPattern::constructor(
+                                "ok",
+                                vec![ArmPattern::Literal(Box::new(Expr::identifier("x")))],
+                            ),
                             Expr::identifier("x"),
                         ),
                         MatchArm::new(
-                            ArmPattern::Literal(Box::new(Expr::err(Expr::identifier("msg")))),
+                            ArmPattern::constructor(
+                                "err",
+                                vec![ArmPattern::Literal(Box::new(Expr::identifier("msg")))],
+                            ),
                             Expr::boolean(false),
                         ),
                     ],
diff --git a/golem-rib/src/function_name.rs b/golem-rib/src/function_name.rs
index 2586d7a6a8..db59c5d1fe 100644
--- a/golem-rib/src/function_name.rs
+++ b/golem-rib/src/function_name.rs
@@ -896,6 +896,14 @@ pub struct ParsedFunctionName {
     pub function: ParsedFunctionReference,
 }
 
+// DynamicParsedFunctionName is different from ParsedFunctionName.
+// In `DynamicParsedFunctionName` the resource parameters are `Expr` (Rib) while they are `String`
+// in `ParsedFunctionName`.
+// `Expr` implies the real values are yet to be computed, while `String`
+// in ParsedFunctionName is a textual representation of the "real" values.
+// `Examples`:
+// `DynamicParsedFunctionName` : ns:name/interface.{resource1(identifier1, { field-a: some(identifier2) }).new}
+// `ParsedFunctionName` : ns:name/interface.{resource1("foo", { field-a: some("bar") }).new}
 #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)]
 pub struct DynamicParsedFunctionName {
     pub site: ParsedFunctionSite,
diff --git a/golem-rib/src/interpreter/literal.rs b/golem-rib/src/interpreter/literal.rs
index 4ee09c8062..5a787e9be5 100644
--- a/golem-rib/src/interpreter/literal.rs
+++ b/golem-rib/src/interpreter/literal.rs
@@ -25,6 +25,9 @@ impl GetLiteralValue for TypeAnnotatedValue {
     fn get_literal(&self) -> Option<LiteralValue> {
         match self {
             TypeAnnotatedValue::Str(value) => Some(LiteralValue::String(value.clone())),
+            TypeAnnotatedValue::Char(code_point) => char::from_u32(*code_point as u32)
+                .map(|c| c.to_string())
+                .map(LiteralValue::String),
             TypeAnnotatedValue::Bool(value) => Some(LiteralValue::Bool(*value)),
             TypeAnnotatedValue::Enum(value) => {
                 // An enum can be turned into a simple literal and can be part of string concatenations
diff --git a/golem-rib/src/interpreter/rib_interpreter.rs b/golem-rib/src/interpreter/rib_interpreter.rs
index 087984dcc2..01e784fc5d 100644
--- a/golem-rib/src/interpreter/rib_interpreter.rs
+++ b/golem-rib/src/interpreter/rib_interpreter.rs
@@ -202,6 +202,10 @@ impl Interpreter {
                 RibIR::And => {
                     internal::run_and_instruction(&mut self.stack)?;
                 }
+
+                RibIR::Or => {
+                    internal::run_or_instruction(&mut self.stack)?;
+                }
             }
         }
 
@@ -365,7 +369,6 @@ mod internal {
                     .pop_n(list_size)
                     .ok_or(format!("Expected {} value on the stack", list_size))?;
 
-                dbg!(last_list.clone());
                 let type_annotated_values = last_list
                     .iter()
                     .map(|interpreter_result| {
@@ -403,12 +406,12 @@ mod internal {
     pub(crate) fn run_and_instruction(
         interpreter_stack: &mut InterpreterStack,
     ) -> Result<(), String> {
-        let left = interpreter_stack.pop().ok_or(
-            "Empty stack and failed to get a value to do the comparison operation".to_string(),
-        )?;
-        let right = interpreter_stack.pop().ok_or(
-            "Failed to get a value from the stack to do the comparison operation".to_string(),
-        )?;
+        let left = interpreter_stack
+            .pop()
+            .ok_or("Internal Error: Failed to get LHS &&".to_string())?;
+        let right = interpreter_stack
+            .pop()
+            .ok_or("Internal Error: Failed to get RHS of &&".to_string())?;
 
         let result = left.compare(&right, |a, b| match (a.get_bool(), b.get_bool()) {
             (Some(a), Some(b)) => a && b,
@@ -420,6 +423,26 @@ mod internal {
         Ok(())
     }
 
+    pub(crate) fn run_or_instruction(
+        interpreter_stack: &mut InterpreterStack,
+    ) -> Result<(), String> {
+        let left = interpreter_stack
+            .pop()
+            .ok_or("Internal Error: Failed to get LHS &&".to_string())?;
+        let right = interpreter_stack
+            .pop()
+            .ok_or("Internal Error: Failed to get RHS of &&".to_string())?;
+
+        let result = left.compare(&right, |a, b| match (a.get_bool(), b.get_bool()) {
+            (Some(a), Some(b)) => a || b,
+            _ => false,
+        })?;
+
+        interpreter_stack.push(result);
+
+        Ok(())
+    }
+
     pub(crate) fn run_compare_instruction(
         interpreter_stack: &mut InterpreterStack,
         compare_fn: fn(LiteralValue, LiteralValue) -> bool,
@@ -837,8 +860,9 @@ mod internal {
             .ok_or("Failed to get a value from the stack to unwrap".to_string())?;
 
         let unwrapped_value = value
+            .clone()
             .unwrap()
-            .ok_or("Failed to unwrap the value".to_string())?;
+            .ok_or(format!("Failed to unwrap the value {:?}", value))?;
 
         interpreter_stack.push_val(unwrapped_value);
         Ok(())
@@ -864,6 +888,7 @@ mod internal {
                 },
                 None => "err".to_string(),
             },
+            TypeAnnotatedValue::Enum(enum_) => enum_.value,
             _ => "untagged".to_string(),
         };
 
@@ -1282,12 +1307,11 @@ mod interpreter_tests {
             let mut interpreter = Interpreter::default();
 
             let expr = r#"
-           let x = some(some(1u64));
+           let x: option<option<u64>> = none;
 
            match x {
-              some(x) => match x {
-                some(x) => x
-              }
+              some(some(x)) => x,
+              none => 0u64
            }
         "#;
 
@@ -1296,7 +1320,7 @@ mod interpreter_tests {
             let compiled = compiler::compile(&expr, &vec![]).unwrap();
             let result = interpreter.run(compiled.byte_code).await.unwrap();
 
-            assert_eq!(result.get_val().unwrap(), TypeAnnotatedValue::U64(1));
+            assert_eq!(result.get_val().unwrap(), TypeAnnotatedValue::U64(0));
         }
 
         #[tokio::test]
@@ -1515,7 +1539,6 @@ mod interpreter_tests {
         "#;
 
             let expr = Expr::from_text(expr).unwrap();
-            dbg!(expr.clone());
             let compiled = compiler::compile(&expr, &analysed_exports).unwrap();
             let result = interpreter.run(compiled.byte_code).await.unwrap();
 
diff --git a/golem-rib/src/interpreter/tests/mod.rs b/golem-rib/src/interpreter/tests/mod.rs
index 16374df421..391e48e2f7 100644
--- a/golem-rib/src/interpreter/tests/mod.rs
+++ b/golem-rib/src/interpreter/tests/mod.rs
@@ -1,7 +1,10 @@
 #[cfg(test)]
 mod comprehensive_test {
     use crate::{compiler, Expr};
-    use golem_wasm_ast::analysis::{AnalysedType, NameTypePair, TypeRecord, TypeStr, TypeU64};
+    use golem_wasm_ast::analysis::{
+        AnalysedType, NameTypePair, TypeBool, TypeF32, TypeF64, TypeRecord, TypeS16, TypeS32,
+        TypeStr, TypeU64, TypeU8,
+    };
     use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue;
 
     #[tokio::test]
@@ -22,21 +25,37 @@ mod comprehensive_test {
 
               let number_response = function-number-response(str1);
 
-              let option_str_response = function-option-str-response(str2);
+              let some_str_response = function-some-str-response(str2);
 
-              let option_number_response = function-option-number-response(str1);
+              let none_str_response = function-none-str-response(str2);
 
-              let option_option_response = function-option-option-response(str1);
+              let some_number_response = function-some-number-response(str1);
 
-              let option_variant_response = function-option-variant-response(str1);
+              let none_number_response = function-none-number-response(str1);
 
-              let option_enum_response = function-option-enum-response(str1);
+              let some_option_response = function-some-option-response(str1);
 
-              let option_tuple_response = function-option-tuple-response(str1);
+              let none_option_response = function-none-option-response(str1);
 
-              let option_record_response = function-option-record-response(str1);
+              let some_variant_response = function-some-variant-response(str1);
 
-              let option_list_response = function-option-list-response(str1);
+              let none_variant_response = function-none-variant-response(str1);
+
+              let some_enum_response = function-some-enum-response(str1);
+
+              let none_enum_response = function-none-enum-response(str1);
+
+              let some_tuple_response = function-some-tuple-response(str1);
+
+              let none_tuple_response = function-none-tuple-response(str1);
+
+              let some_record_response = function-some-record-response(str1);
+
+              let none_record_response = function-none-record-response(str1);
+
+              let some_list_response = function-some-list-response(str1);
+
+              let none_list_response = function-none-list-response(str1);
 
               let list_number_response = function-list-number-response(str1);
 
@@ -54,21 +73,37 @@ mod comprehensive_test {
 
               let list_record_response = function-list-record-response(str1);
 
-              let result_of_str_response = function-result-str-response(str1);
+              let ok_of_str_response = function-ok-str-response(str1);
+
+              let err_of_str_response = function-err-str-response(str1);
+
+              let ok_of_number_response = function-ok-number-response(str1);
+
+              let err_of_number_response = function-err-number-response(str1);
 
-              let result_of_number_response = function-result-number-response(str1);
+              let ok_of_variant_response = function-ok-variant-response(str1);
 
-              let result_of_variant_response = function-result-variant-response(str1);
+              let err_of_variant_response = function-err-variant-response(str1);
 
-              let result_of_enum_response = function-result-enum-response(str1);
+              let ok_of_enum_response = function-ok-enum-response(str1);
 
-              let result_of_tuple_response = function-result-tuple-response(str1);
+              let err_of_enum_response = function-err-enum-response(str1);
 
-              let result_of_flag_response = function-result-flag-response(str1);
+              let ok_of_tuple_response = function-ok-tuple-response(str1);
 
-              let result_of_record_response = function-result-record-response(str1);
+              let err_of_tuple_response = function-err-tuple-response(str1);
 
-              let result_of_list_response = function-result-list-response(str1);
+              let ok_of_flag_response = function-ok-flag-response(str1);
+
+              let err_of_flag_response = function-err-flag-response(str1);
+
+              let ok_of_record_response = function-ok-record-response(str1);
+
+              let err_of_record_response = function-err-record-response(str1);
+
+              let ok_of_list_response = function-ok-list-response(str1);
+
+              let err_of_list_response = function-err-list-response(str1);
 
               let tuple_response = function-tuple-response(str1);
 
@@ -82,44 +117,87 @@ mod comprehensive_test {
 
               let number_response_processed = if number_response == 42u64 then "foo" else "bar";
 
-              let option_str_response_processed = match option_str_response {
+              let some_str_response_processed = match some_str_response {
                 some(text) => text,
                 none => "not found"
               };
 
-              let option_number_response_processed = match option_number_response {
+              let none_str_response_processed = match none_str_response {
+                some(text) => text,
+                none => "not found"
+              };
+
+
+              let some_number_response_processed = match some_number_response {
                 some(number) => number,
                 none => 0
               };
 
-              let option_option_response_processed = match option_option_response {
+               let none_number_response_processed = match none_number_response {
+                some(number) => number,
+                none => 0
+              };
+
+              let some_option_response_processed = match some_option_response {
                  some(some(x)) => x,
                  none => "not found"
               };
 
-              let option_variant_response_processed = match option_variant_response {
+              let none_option_response_processed = match none_option_response {
+                 some(some(x)) => x,
+                 none => "not found"
+              };
+
+              let some_variant_response_processed = match some_variant_response {
+                 some(case-str(_)) => "found",
+                 _ => "not found"
+              };
+
+               let none_variant_response_processed = match none_variant_response {
                  some(case-str(_)) => "found",
                  _ => "not found"
               };
 
-              let option_enum_response_processed = match option_enum_response {
+              let some_enum_response_processed = match some_enum_response {
                  some(enum-a) => "a",
                  some(enum-b) => "b",
                  _ => "not found"
               };
 
-              let option_tuple_response_processed = match option_tuple_response {
+              let none_enum_response_processed = match none_enum_response {
+                 some(enum-a) => "a",
+                 some(enum-b) => "b",
+                 _ => "not found"
+              };
+
+              let some_tuple_response_processed = match some_tuple_response {
                     some((text, _, _, _, _, _, _, _, _, _, _, _)) => text,
                      _ => "not found"
                 };
 
-              let option_record_response_processed = match option_record_response {
-                  some({data-body: {list-of-str : _}}) => "found list",
+               let none_tuple_response_processed = match none_tuple_response {
+                    some((text, _, _, _, _, _, _, _, _, _, _, _)) => text,
+                     _ => "not found"
+                };
+
+
+              let some_record_response_processed = match some_record_response {
+                  some({data-body: {list-of-str : mylist}}) => mylist[0],
                    _ => "not found"
               };
 
-              let option_list_response_processed = match option_list_response {
-                    some([_]) => "found list",
+              let none_record_response_processed = match none_record_response {
+                  some({data-body: {list-of-str : mylist}}) => mylist[0],
+                   _ => "not found"
+              };
+
+              let some_list_response_processed = match some_list_response {
+                    some([foo]) => foo,
+                     _ => "not found"
+                };
+
+               let none_list_response_processed = match none_list_response {
+                    some([foo]) => foo,
                      _ => "not found"
                 };
 
@@ -157,56 +235,162 @@ mod comprehensive_test {
                 _ => "not found"
               };
 
-              let list_tuple_response_processed = match list_tuple_response {
+              let list_tuple_response_processed1 = match list_tuple_response {
                 [(text, _, _, _, _, _, _, _, _, _, _, _)] => text,
                 _ => "not found"
               };
 
+
+              let list_tuple_response_processed2 = match list_tuple_response {
+                [(_, number, _, _, _, _, _, _, _, _, _, _)] => number,
+                _ => 0
+              };
+
+              let list_tuple_response_processed3 = match list_tuple_response {
+                [(_, _, number, _, _, _, _, _, _, _, _, _)] => number,
+                _ => 0
+              };
+
+              let list_tuple_response_processed4 = match list_tuple_response {
+                [(_, _, _, number, _, _, _, _, _, _, _, _)] => number,
+                _ => 0
+              };
+
+              let list_tuple_response_processed5 = match list_tuple_response {
+                [(_, _, _, _, number, _, _, _, _, _, _, _)] => number,
+                _ => 0
+              };
+
+              let list_tuple_response_processed6 = match list_tuple_response {
+                [(_, _, _, _, _, boolean, _, _, _, _, _, _)] => boolean,
+                _ => false
+              };
+
+              let list_tuple_response_processed7 = match list_tuple_response {
+                [(_, _, _, _, _, _, char, _, _, _, _, _)] => "${char}",
+                _ => "not found"
+              };
+
+              let list_tuple_response_processed8 = match list_tuple_response {
+                [(_, _, _, _, _, _, _, some(number), _, _, _, _)] => number,
+                _ => 0
+              };
+
+              let list_tuple_response_processed9 = match list_tuple_response {
+                [(_, _, _, _, _, _, _, _, ok(number), _, _, _)] => number,
+                _ => 0
+              };
+
+              let list_tuple_response_processed10 = match list_tuple_response {
+                [(_, _, _, _, _, _, _, _, _, [boolean], _, _)] => boolean,
+                _ => false
+              };
+
+              let list_tuple_response_processed11 = match list_tuple_response {
+                [(_, _, _, _, _, _, _, _, _, _, case-hello(number), _)] => number,
+                _ => 0
+              };
+
+              let list_tuple_response_processed12 = match list_tuple_response {
+                [(_, _, _, _, _, _, _, _, _, _, _, {field-one: boolean, field-two: text})] => "${boolean}-${text}",
+                _ => "not found"
+              };
+
+
               let list_record_response_processed = match list_record_response {
                 [{data-body: {list-of-str : [text]}}] => text,
                 _ => "not found"
               };
 
-              let result_of_str_response_processed = match result_of_str_response {
+              let ok_of_str_response_processed = match ok_of_str_response {
                 ok(text) => text,
-                err(msg) => "not found"
+                err(msg) => msg
               };
 
-              let result_of_number_response_processed = match result_of_number_response {
+              let err_of_str_response_processed = match err_of_str_response {
+                ok(text) => text,
+                err(msg) => msg
+              };
+
+              let ok_of_number_response_processed = match ok_of_number_response {
                 ok(number) => number,
-                err(msg) => 0
+                err(number) => number
               };
 
-              let result_of_variant_response_processed = match result_of_variant_response {
-                ok(case-str(_)) => "found",
-                err(msg) => "not found"
+              let err_of_number_response_processed = match err_of_number_response {
+                  ok(number) => number,
+                  err(number) => number
+               };
+
+              let ok_of_variant_response_processed = match ok_of_variant_response {
+                ok(case-str(a)) => a,
+                err(case-str(b)) => b
               };
 
-              let result_of_enum_response_processed = match result_of_enum_response {
+                let err_of_variant_response_processed = match err_of_variant_response {
+                    ok(case-str(a)) => a,
+                    err(case-str(b)) => b
+                };
+
+              let ok_of_enum_response_processed = match ok_of_enum_response {
                 ok(enum-a) => "a",
                 ok(enum-b) => "b",
                 ok(enum-c) => "c",
                 err(msg) => "not found"
               };
 
-              let result_of_tuple_response_processed = match result_of_tuple_response {
+                let err_of_enum_response_processed = match err_of_enum_response {
+                    ok(enum-a) => "a",
+                    ok(enum-b) => "b",
+                    ok(enum-c) => "c",
+                    err(enum-a) => "error-a",
+                    err(enum-b) => "error-b",
+                    err(enum-c) => "error-c"
+                };
+
+              let ok_of_tuple_response_processed = match ok_of_tuple_response {
                 ok((text, _, _, _, _, _, _, _, _, _, _, _)) => text,
                 err(msg) => "not found"
               };
 
-              let result_of_flag_response_processed = match result_of_flag_response {
+               let err_of_tuple_response_processed = match err_of_tuple_response {
+                ok((text, _, _, _, _, _, _, _, _, _, _, _)) => text,
+                err((text, _, _, _, _, _, _, _, _, _, _, _)) => text
+              };
+
+
+              let ok_of_flag_response_processed = match ok_of_flag_response {
                 ok({featurex, featurey, featurez}) => "found all flags",
                 ok({featurex}) => "found x",
                 ok({featurey}) => "found x",
                 ok({featurex, featurey}) => "found x and y",
-                _ => "not found"
+                err({featurex, featurey, featurez}) => "found all flags",
+                err({featurex}) => "found x",
+                err({featurey}) => "found x",
+                err({featurex, featurey}) => "found x and y"
+               };
+
+                let err_of_flag_response_processed = match err_of_flag_response {
+                ok({featurex, featurey, featurez}) => "found all flags",
+                ok({featurex}) => "found x",
+                ok({featurey}) => "found x",
+                ok({featurex, featurey}) => "found x and y",
+                err({featurex, featurey, featurez}) => "found all flags",
+                err({featurex}) => "found x",
+                err({featurey}) => "found x",
+                err({featurex, featurey}) => "found x and y"
                };
 
-              let result_of_record_response_processed = match result_of_record_response {
-                 ok({data-body: {list-of-str : _}}) => "found list",
+              let ok_of_record_response_processed = match ok_of_record_response {
+                 ok({data-body: {list-of-str : mylist}}) => mylist[0],
                  err(msg) => "not found"
                };
 
+               let err_of_record_response_processed = match err_of_record_response {
+                 ok({data-body: {list-of-str : mylist}}) => mylist[0],
+                 err({data-body: {list-of-str : mylist}}) => mylist[0]
+               };
+
                let tuple_response_processed = match tuple_response {
                  (_, _, _, _, _, _, _, _, _, _, case-hello(a), _) => "${a}"
                };
@@ -224,29 +408,54 @@ mod comprehensive_test {
                };
 
               {
-                 a : option_str_response_processed,
-                 b: option_number_response_processed,
-                 c: option_option_response_processed,
-                 d: option_variant_response_processed,
-                 e: option_enum_response_processed,
-                 f: option_tuple_response_processed,
-                 g: option_record_response_processed,
-                 h: option_list_response_processed,
+                 a : some_str_response_processed,
+                 aa: list_tuple_response_processed2,
+                 ab: list_tuple_response_processed3,
+                 ac: list_tuple_response_processed4,
+                 ad: list_tuple_response_processed5,
+                 ae: list_tuple_response_processed6,
+                 af: list_tuple_response_processed7,
+                 ag: list_tuple_response_processed8,
+                 ah: list_tuple_response_processed9,
+                 ai: list_tuple_response_processed10,
+                 aj: list_tuple_response_processed11,
+                 ak: list_tuple_response_processed12,
+                 b: some_number_response_processed,
+                 bb: none_number_response_processed,
+                 c: some_option_response_processed,
+                 cc: none_option_response_processed,
+                 d: some_variant_response_processed,
+                 dd: none_variant_response_processed,
+                 e: some_enum_response_processed,
+                 ee: none_enum_response_processed,
+                 f: some_tuple_response_processed,
+                 ff: none_tuple_response_processed,
+                 g: some_record_response_processed,
+                 gg: none_record_response_processed,
+                 h: some_list_response_processed,
+                 hh: none_list_response_processed,
                  i: list_number_response_processed,
                  j: list_str_response_processed,
                  k: list_option_response_processed,
                  l: list_list_response_processed,
                  m: list_variant_response_processed,
                  n: list_enum_response_processed,
-                 o: list_tuple_response_processed,
+                 o: list_tuple_response_processed1,
                  p: list_record_response_processed,
-                 q: result_of_str_response_processed,
-                 r: result_of_number_response_processed,
-                 s: result_of_variant_response_processed,
-                 t: result_of_enum_response_processed,
-                 u: result_of_tuple_response_processed,
-                 v: result_of_flag_response_processed,
-                 w: result_of_record_response_processed,
+                 q: ok_of_str_response_processed,
+                 qq: err_of_str_response_processed,
+                 r: ok_of_number_response_processed,
+                 rr: err_of_number_response_processed,
+                 s: ok_of_variant_response_processed,
+                 ss: err_of_variant_response_processed,
+                 t: ok_of_enum_response_processed,
+                 tt: err_of_enum_response_processed,
+                 u: ok_of_tuple_response_processed,
+                 uu: err_of_tuple_response_processed,
+                 v: ok_of_flag_response_processed,
+                 vv: err_of_flag_response_processed,
+                 w: ok_of_record_response_processed,
+                 ww: err_of_record_response_processed,
                  x: tuple_response_processed,
                  y: enum_response_processed,
                  z: variant_response_processed
@@ -262,11 +471,77 @@ mod comprehensive_test {
         let mut rib_executor = mock_interpreter::interpreter();
         let result = rib_executor.run(compiled_expr).await.unwrap();
 
-        assert_eq!(result.get_val().unwrap(), expected_type_annotated_value());
+        let actual_as_text =
+            test_utils::convert_type_annotated_value_to_str(&result.get_val().unwrap());
+
+        let expected_as_text =
+            test_utils::convert_type_annotated_value_to_str(&expected_type_annotated_value());
+
+        assert_eq!(
+            result.get_val().unwrap(),
+            expected_type_annotated_value(),
+            "Assertion failed! \n\n Actual value as string  : {} \n\n Expected value as string: {}\n",
+            actual_as_text,
+            expected_as_text
+        );
     }
 
     fn expected_type_annotated_value() -> TypeAnnotatedValue {
-        let wasm_wave_str = "{a: \"foo\", b: 42, c: \"foo\", d: \"found\", e: \"a\", f: \"foo\", g: \"found list\", h: \"found list\", i: \"greater\", j: \"foo\", k: \"foo\", l: \"foo\", m: \"foo\", n: \"a\", o: \"foo\", p: \"foo\", q: \"foo\", r: 42, s: \"found\", t: \"a\", u: \"foo\", v: \"found x\", w: \"found list\", x: \"42\", y: \"a\", z: \"foo\"}";
+        let wasm_wave_str = r#"
+          {
+            a: "foo",
+            b: 42,
+            bb: 0,
+            c: "foo",
+            cc: "not found",
+            d: "found",
+            dd: "not found",
+            e: "a",
+            ee: "not found",
+            f: "foo",
+            ff: "not found",
+            g: "foo",
+            gg: "not found",
+            h: "foo",
+            hh: "not found",
+            i: "greater",
+            j: "foo",
+            k: "foo",
+            l: "foo",
+            m: "foo",
+            n: "a",
+            o: "foo",
+            p: "foo",
+            q: "foo",
+            qq: "foo",
+            r: 42,
+            rr: 42,
+            s: "foo",
+            ss: "foo",
+            t: "a",
+            tt: "error-a",
+            u: "foo",
+            uu: "foo",
+            v: "found x",
+            vv: "found x",
+            w: "foo",
+            ww: "foo",
+            x: "42",
+            y: "a",
+            z: "foo",
+            aa: 42,
+            ab: 42,
+            ac: 42,
+            ad: 42,
+            ae: true,
+            af: "a",
+            ag: 42,
+            ah: 42,
+            ai: true,
+            aj: 42,
+            ak: "true-foo"
+          }
+        "#;
 
         test_utils::get_type_annotated_value(&expected_analysed_type(), wasm_wave_str)
     }
@@ -278,34 +553,106 @@ mod comprehensive_test {
                     name: "a".to_string(),
                     typ: AnalysedType::Str(TypeStr),
                 },
+                NameTypePair {
+                    name: "aa".to_string(),
+                    typ: AnalysedType::U64(TypeU64),
+                },
+                NameTypePair {
+                    name: "ab".to_string(),
+                    typ: AnalysedType::S32(TypeS32),
+                },
+                NameTypePair {
+                    name: "ac".to_string(),
+                    typ: AnalysedType::F32(TypeF32),
+                },
+                NameTypePair {
+                    name: "ad".to_string(),
+                    typ: AnalysedType::F64(TypeF64),
+                },
+                NameTypePair {
+                    name: "ae".to_string(),
+                    typ: AnalysedType::Bool(TypeBool),
+                },
+                NameTypePair {
+                    name: "af".to_string(),
+                    typ: AnalysedType::Str(TypeStr),
+                },
+                NameTypePair {
+                    name: "ag".to_string(),
+                    typ: AnalysedType::S16(TypeS16),
+                },
+                NameTypePair {
+                    name: "ah".to_string(),
+                    typ: AnalysedType::U8(TypeU8),
+                },
+                NameTypePair {
+                    name: "ai".to_string(),
+                    typ: AnalysedType::Bool(TypeBool),
+                },
+                NameTypePair {
+                    name: "aj".to_string(),
+                    typ: AnalysedType::F64(TypeF64),
+                },
+                NameTypePair {
+                    name: "ak".to_string(),
+                    typ: AnalysedType::Str(TypeStr),
+                },
                 NameTypePair {
                     name: "b".to_string(),
                     typ: AnalysedType::U64(TypeU64),
                 },
+                NameTypePair {
+                    name: "bb".to_string(),
+                    typ: AnalysedType::U64(TypeU64),
+                },
                 NameTypePair {
                     name: "c".to_string(),
                     typ: AnalysedType::Str(TypeStr),
                 },
+                NameTypePair {
+                    name: "cc".to_string(),
+                    typ: AnalysedType::Str(TypeStr),
+                },
                 NameTypePair {
                     name: "d".to_string(),
                     typ: AnalysedType::Str(TypeStr),
                 },
+                NameTypePair {
+                    name: "dd".to_string(),
+                    typ: AnalysedType::Str(TypeStr),
+                },
                 NameTypePair {
                     name: "e".to_string(),
                     typ: AnalysedType::Str(TypeStr),
                 },
+                NameTypePair {
+                    name: "ee".to_string(),
+                    typ: AnalysedType::Str(TypeStr),
+                },
                 NameTypePair {
                     name: "f".to_string(),
                     typ: AnalysedType::Str(TypeStr),
                 },
+                NameTypePair {
+                    name: "ff".to_string(),
+                    typ: AnalysedType::Str(TypeStr),
+                },
                 NameTypePair {
                     name: "g".to_string(),
                     typ: AnalysedType::Str(TypeStr),
                 },
+                NameTypePair {
+                    name: "gg".to_string(),
+                    typ: AnalysedType::Str(TypeStr),
+                },
                 NameTypePair {
                     name: "h".to_string(),
                     typ: AnalysedType::Str(TypeStr),
                 },
+                NameTypePair {
+                    name: "hh".to_string(),
+                    typ: AnalysedType::Str(TypeStr),
+                },
                 NameTypePair {
                     name: "i".to_string(),
                     typ: AnalysedType::Str(TypeStr),
@@ -342,30 +689,58 @@ mod comprehensive_test {
                     name: "q".to_string(),
                     typ: AnalysedType::Str(TypeStr),
                 },
+                NameTypePair {
+                    name: "qq".to_string(),
+                    typ: AnalysedType::Str(TypeStr),
+                },
                 NameTypePair {
                     name: "r".to_string(),
                     typ: AnalysedType::U64(TypeU64),
                 },
+                NameTypePair {
+                    name: "rr".to_string(),
+                    typ: AnalysedType::U64(TypeU64),
+                },
                 NameTypePair {
                     name: "s".to_string(),
                     typ: AnalysedType::Str(TypeStr),
                 },
+                NameTypePair {
+                    name: "ss".to_string(),
+                    typ: AnalysedType::Str(TypeStr),
+                },
                 NameTypePair {
                     name: "t".to_string(),
                     typ: AnalysedType::Str(TypeStr),
                 },
+                NameTypePair {
+                    name: "tt".to_string(),
+                    typ: AnalysedType::Str(TypeStr),
+                },
                 NameTypePair {
                     name: "u".to_string(),
                     typ: AnalysedType::Str(TypeStr),
                 },
+                NameTypePair {
+                    name: "uu".to_string(),
+                    typ: AnalysedType::Str(TypeStr),
+                },
                 NameTypePair {
                     name: "v".to_string(),
                     typ: AnalysedType::Str(TypeStr),
                 },
+                NameTypePair {
+                    name: "vv".to_string(),
+                    typ: AnalysedType::Str(TypeStr),
+                },
                 NameTypePair {
                     name: "w".to_string(),
                     typ: AnalysedType::Str(TypeStr),
                 },
+                NameTypePair {
+                    name: "ww".to_string(),
+                    typ: AnalysedType::Str(TypeStr),
+                },
                 NameTypePair {
                     name: "x".to_string(),
                     typ: AnalysedType::Str(TypeStr),
@@ -393,14 +768,22 @@ mod comprehensive_test {
             exports.extend(function_metadata::function_no_arg_unit());
             exports.extend(function_metadata::function_str_response());
             exports.extend(function_metadata::function_number_response());
-            exports.extend(function_metadata::function_option_of_str_response());
-            exports.extend(function_metadata::function_option_of_number_response());
-            exports.extend(function_metadata::function_option_of_option_response());
-            exports.extend(function_metadata::function_option_of_variant_response());
-            exports.extend(function_metadata::function_option_of_enum_response());
-            exports.extend(function_metadata::function_option_of_tuple_response());
-            exports.extend(function_metadata::function_option_of_record_response());
-            exports.extend(function_metadata::function_option_of_list_response());
+            exports.extend(function_metadata::function_some_of_str_response());
+            exports.extend(function_metadata::function_none_of_str_response());
+            exports.extend(function_metadata::function_some_of_number_response());
+            exports.extend(function_metadata::function_none_of_number_response());
+            exports.extend(function_metadata::function_some_of_option_response());
+            exports.extend(function_metadata::function_none_of_option_response());
+            exports.extend(function_metadata::function_some_of_variant_response());
+            exports.extend(function_metadata::function_none_of_variant_response());
+            exports.extend(function_metadata::function_some_of_enum_response());
+            exports.extend(function_metadata::function_none_of_enum_response());
+            exports.extend(function_metadata::function_some_of_tuple_response());
+            exports.extend(function_metadata::function_none_of_tuple_response());
+            exports.extend(function_metadata::function_some_of_record_response());
+            exports.extend(function_metadata::function_none_of_record_response());
+            exports.extend(function_metadata::function_some_of_list_response());
+            exports.extend(function_metadata::function_none_of_list_response());
             exports.extend(function_metadata::function_list_of_number_response());
             exports.extend(function_metadata::function_list_of_str_response());
             exports.extend(function_metadata::function_list_of_option_response());
@@ -409,15 +792,24 @@ mod comprehensive_test {
             exports.extend(function_metadata::function_list_of_enum_response());
             exports.extend(function_metadata::function_list_of_tuple_response());
             exports.extend(function_metadata::function_list_of_record_response());
-            exports.extend(function_metadata::function_result_of_str_response());
-            exports.extend(function_metadata::function_result_of_number_response());
-            exports.extend(function_metadata::function_result_of_option_response());
-            exports.extend(function_metadata::function_result_of_variant_response());
-            exports.extend(function_metadata::function_result_of_enum_response());
-            exports.extend(function_metadata::function_result_of_tuple_response());
-            exports.extend(function_metadata::function_result_of_flag_response());
-            exports.extend(function_metadata::function_result_of_record_response());
-            exports.extend(function_metadata::function_result_of_list_response());
+            exports.extend(function_metadata::function_ok_of_str_response());
+            exports.extend(function_metadata::function_err_of_str_response());
+            exports.extend(function_metadata::function_ok_of_number_response());
+            exports.extend(function_metadata::function_err_of_number_response());
+            exports.extend(function_metadata::function_ok_of_option_response());
+            exports.extend(function_metadata::function_err_of_option_response());
+            exports.extend(function_metadata::function_ok_of_variant_response());
+            exports.extend(function_metadata::function_err_of_variant_response());
+            exports.extend(function_metadata::function_ok_of_enum_response());
+            exports.extend(function_metadata::function_err_of_enum_response());
+            exports.extend(function_metadata::function_ok_of_tuple_response());
+            exports.extend(function_metadata::function_err_of_tuple_response());
+            exports.extend(function_metadata::function_ok_of_flag_response());
+            exports.extend(function_metadata::function_err_of_flag_response());
+            exports.extend(function_metadata::function_ok_of_record_response());
+            exports.extend(function_metadata::function_err_of_record_response());
+            exports.extend(function_metadata::function_ok_of_list_response());
+            exports.extend(function_metadata::function_err_of_list_response());
             exports.extend(function_metadata::function_tuple_response());
             exports.extend(function_metadata::function_enum_response());
             exports.extend(function_metadata::function_flag_response());
@@ -469,65 +861,129 @@ mod comprehensive_test {
             )
         }
 
-        pub(crate) fn function_option_of_str_response() -> Vec<AnalysedExport> {
+        pub(crate) fn function_some_of_str_response() -> Vec<AnalysedExport> {
             test_utils::get_function_component_metadata(
-                "function-option-str-response",
+                "function-some-str-response",
                 vec![data_types::str_type()],
                 Some(data_types::option_of_str_type()),
             )
         }
 
-        pub(crate) fn function_option_of_number_response() -> Vec<AnalysedExport> {
+        pub(crate) fn function_none_of_str_response() -> Vec<AnalysedExport> {
             test_utils::get_function_component_metadata(
-                "function-option-number-response",
+                "function-none-str-response",
+                vec![data_types::str_type()],
+                Some(data_types::option_of_str_type()),
+            )
+        }
+
+        pub(crate) fn function_some_of_number_response() -> Vec<AnalysedExport> {
+            test_utils::get_function_component_metadata(
+                "function-some-number-response",
+                vec![data_types::str_type()],
+                Some(data_types::option_of_number_type()),
+            )
+        }
+
+        pub(crate) fn function_none_of_number_response() -> Vec<AnalysedExport> {
+            test_utils::get_function_component_metadata(
+                "function-none-number-response",
                 vec![data_types::str_type()],
                 Some(data_types::option_of_number_type()),
             )
         }
 
-        pub(crate) fn function_option_of_option_response() -> Vec<AnalysedExport> {
+        pub(crate) fn function_some_of_option_response() -> Vec<AnalysedExport> {
             test_utils::get_function_component_metadata(
-                "function-option-option-response",
+                "function-some-option-response",
                 vec![data_types::str_type()],
                 Some(data_types::option_of_option_type()),
             )
         }
 
-        pub(crate) fn function_option_of_variant_response() -> Vec<AnalysedExport> {
+        pub(crate) fn function_none_of_option_response() -> Vec<AnalysedExport> {
             test_utils::get_function_component_metadata(
-                "function-option-variant-response",
+                "function-none-option-response",
+                vec![data_types::str_type()],
+                Some(data_types::option_of_option_type()),
+            )
+        }
+
+        pub(crate) fn function_some_of_variant_response() -> Vec<AnalysedExport> {
+            test_utils::get_function_component_metadata(
+                "function-some-variant-response",
                 vec![data_types::str_type()],
                 Some(data_types::option_of_variant_type()),
             )
         }
 
-        pub(crate) fn function_option_of_enum_response() -> Vec<AnalysedExport> {
+        pub(crate) fn function_none_of_variant_response() -> Vec<AnalysedExport> {
             test_utils::get_function_component_metadata(
-                "function-option-enum-response",
+                "function-none-variant-response",
+                vec![data_types::str_type()],
+                Some(data_types::option_of_variant_type()),
+            )
+        }
+
+        pub(crate) fn function_some_of_enum_response() -> Vec<AnalysedExport> {
+            test_utils::get_function_component_metadata(
+                "function-some-enum-response",
                 vec![data_types::str_type()],
                 Some(data_types::option_of_enum_type()),
             )
         }
 
-        pub(crate) fn function_option_of_tuple_response() -> Vec<AnalysedExport> {
+        pub(crate) fn function_none_of_enum_response() -> Vec<AnalysedExport> {
             test_utils::get_function_component_metadata(
-                "function-option-tuple-response",
+                "function-none-enum-response",
+                vec![data_types::str_type()],
+                Some(data_types::option_of_enum_type()),
+            )
+        }
+
+        pub(crate) fn function_some_of_tuple_response() -> Vec<AnalysedExport> {
+            test_utils::get_function_component_metadata(
+                "function-some-tuple-response",
                 vec![data_types::str_type()],
                 Some(data_types::option_of_tuple()),
             )
         }
 
-        pub(crate) fn function_option_of_record_response() -> Vec<AnalysedExport> {
+        pub(crate) fn function_none_of_tuple_response() -> Vec<AnalysedExport> {
             test_utils::get_function_component_metadata(
-                "function-option-record-response",
+                "function-none-tuple-response",
+                vec![data_types::str_type()],
+                Some(data_types::option_of_tuple()),
+            )
+        }
+
+        pub(crate) fn function_some_of_record_response() -> Vec<AnalysedExport> {
+            test_utils::get_function_component_metadata(
+                "function-some-record-response",
+                vec![data_types::str_type()],
+                Some(data_types::option_of_record_type()),
+            )
+        }
+
+        pub(crate) fn function_none_of_record_response() -> Vec<AnalysedExport> {
+            test_utils::get_function_component_metadata(
+                "function-none-record-response",
                 vec![data_types::str_type()],
                 Some(data_types::option_of_record_type()),
             )
         }
 
-        pub(crate) fn function_option_of_list_response() -> Vec<AnalysedExport> {
+        pub(crate) fn function_some_of_list_response() -> Vec<AnalysedExport> {
             test_utils::get_function_component_metadata(
-                "function-option-list-response",
+                "function-some-list-response",
+                vec![data_types::str_type()],
+                Some(data_types::option_of_list()),
+            )
+        }
+
+        pub(crate) fn function_none_of_list_response() -> Vec<AnalysedExport> {
+            test_utils::get_function_component_metadata(
+                "function-none-list-response",
                 vec![data_types::str_type()],
                 Some(data_types::option_of_list()),
             )
@@ -597,73 +1053,145 @@ mod comprehensive_test {
             )
         }
 
-        pub(crate) fn function_result_of_str_response() -> Vec<AnalysedExport> {
+        pub(crate) fn function_ok_of_str_response() -> Vec<AnalysedExport> {
+            test_utils::get_function_component_metadata(
+                "function-ok-str-response",
+                vec![data_types::str_type()],
+                Some(data_types::result_of_str_type()),
+            )
+        }
+
+        pub(crate) fn function_err_of_str_response() -> Vec<AnalysedExport> {
             test_utils::get_function_component_metadata(
-                "function-result-str-response",
+                "function-err-str-response",
                 vec![data_types::str_type()],
                 Some(data_types::result_of_str_type()),
             )
         }
 
-        pub(crate) fn function_result_of_number_response() -> Vec<AnalysedExport> {
+        pub(crate) fn function_ok_of_number_response() -> Vec<AnalysedExport> {
             test_utils::get_function_component_metadata(
-                "function-result-number-response",
+                "function-ok-number-response",
                 vec![data_types::str_type()],
                 Some(data_types::result_of_number_type()),
             )
         }
 
-        pub(crate) fn function_result_of_option_response() -> Vec<AnalysedExport> {
+        pub(crate) fn function_err_of_number_response() -> Vec<AnalysedExport> {
+            test_utils::get_function_component_metadata(
+                "function-err-number-response",
+                vec![data_types::str_type()],
+                Some(data_types::result_of_number_type()),
+            )
+        }
+
+        pub(crate) fn function_ok_of_option_response() -> Vec<AnalysedExport> {
+            test_utils::get_function_component_metadata(
+                "function-ok-option-response",
+                vec![data_types::str_type()],
+                Some(data_types::result_of_option_type()),
+            )
+        }
+
+        pub(crate) fn function_err_of_option_response() -> Vec<AnalysedExport> {
             test_utils::get_function_component_metadata(
-                "function-result-option-response",
+                "function-err-option-response",
                 vec![data_types::str_type()],
                 Some(data_types::result_of_option_type()),
             )
         }
 
-        pub(crate) fn function_result_of_variant_response() -> Vec<AnalysedExport> {
+        pub(crate) fn function_ok_of_variant_response() -> Vec<AnalysedExport> {
             test_utils::get_function_component_metadata(
-                "function-result-variant-response",
+                "function-ok-variant-response",
                 vec![data_types::str_type()],
                 Some(data_types::result_of_variant_type()),
             )
         }
 
-        pub(crate) fn function_result_of_enum_response() -> Vec<AnalysedExport> {
+        pub(crate) fn function_err_of_variant_response() -> Vec<AnalysedExport> {
             test_utils::get_function_component_metadata(
-                "function-result-enum-response",
+                "function-err-variant-response",
+                vec![data_types::str_type()],
+                Some(data_types::result_of_variant_type()),
+            )
+        }
+
+        pub(crate) fn function_ok_of_enum_response() -> Vec<AnalysedExport> {
+            test_utils::get_function_component_metadata(
+                "function-ok-enum-response",
                 vec![data_types::str_type()],
                 Some(data_types::result_of_enum_type()),
             )
         }
 
-        pub(crate) fn function_result_of_tuple_response() -> Vec<AnalysedExport> {
+        pub(crate) fn function_err_of_enum_response() -> Vec<AnalysedExport> {
             test_utils::get_function_component_metadata(
-                "function-result-tuple-response",
+                "function-err-enum-response",
+                vec![data_types::str_type()],
+                Some(data_types::result_of_enum_type()),
+            )
+        }
+
+        pub(crate) fn function_ok_of_tuple_response() -> Vec<AnalysedExport> {
+            test_utils::get_function_component_metadata(
+                "function-ok-tuple-response",
+                vec![data_types::str_type()],
+                Some(data_types::result_of_tuple_type()),
+            )
+        }
+
+        pub(crate) fn function_err_of_tuple_response() -> Vec<AnalysedExport> {
+            test_utils::get_function_component_metadata(
+                "function-err-tuple-response",
                 vec![data_types::str_type()],
                 Some(data_types::result_of_tuple_type()),
             )
         }
 
-        pub(crate) fn function_result_of_flag_response() -> Vec<AnalysedExport> {
+        pub(crate) fn function_ok_of_flag_response() -> Vec<AnalysedExport> {
+            test_utils::get_function_component_metadata(
+                "function-ok-flag-response",
+                vec![data_types::str_type()],
+                Some(data_types::result_of_flag_type()),
+            )
+        }
+
+        pub(crate) fn function_err_of_flag_response() -> Vec<AnalysedExport> {
             test_utils::get_function_component_metadata(
-                "function-result-flag-response",
+                "function-err-flag-response",
                 vec![data_types::str_type()],
                 Some(data_types::result_of_flag_type()),
             )
         }
 
-        pub(crate) fn function_result_of_record_response() -> Vec<AnalysedExport> {
+        pub(crate) fn function_ok_of_record_response() -> Vec<AnalysedExport> {
+            test_utils::get_function_component_metadata(
+                "function-ok-record-response",
+                vec![data_types::str_type()],
+                Some(data_types::result_of_record_type()),
+            )
+        }
+
+        pub(crate) fn function_err_of_record_response() -> Vec<AnalysedExport> {
             test_utils::get_function_component_metadata(
-                "function-result-record-response",
+                "function-err-record-response",
                 vec![data_types::str_type()],
                 Some(data_types::result_of_record_type()),
             )
         }
 
-        pub(crate) fn function_result_of_list_response() -> Vec<AnalysedExport> {
+        pub(crate) fn function_ok_of_list_response() -> Vec<AnalysedExport> {
             test_utils::get_function_component_metadata(
-                "function-result-list-response",
+                "function-ok-list-response",
+                vec![data_types::str_type()],
+                Some(data_types::result_of_list_type()),
+            )
+        }
+
+        pub(crate) fn function_err_of_list_response() -> Vec<AnalysedExport> {
+            test_utils::get_function_component_metadata(
+                "function-err-list-response",
                 vec![data_types::str_type()],
                 Some(data_types::result_of_list_type()),
             )
@@ -1192,33 +1720,59 @@ mod comprehensive_test {
         use crate::interpreter::tests::comprehensive_test::{data_types, test_utils};
         use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue;
 
-        pub(crate) fn result_of_str() -> TypeAnnotatedValue {
+        pub(crate) fn ok_of_str() -> TypeAnnotatedValue {
             test_utils::get_type_annotated_value(&data_types::result_of_str_type(), "ok(\"foo\")")
         }
 
-        pub(crate) fn result_of_number() -> TypeAnnotatedValue {
+        pub(crate) fn err_of_str() -> TypeAnnotatedValue {
+            test_utils::get_type_annotated_value(&data_types::result_of_str_type(), "err(\"foo\")")
+        }
+
+        pub(crate) fn ok_of_number() -> TypeAnnotatedValue {
             test_utils::get_type_annotated_value(&data_types::result_of_number_type(), "ok(42)")
         }
 
-        pub(crate) fn result_of_option() -> TypeAnnotatedValue {
+        pub(crate) fn err_of_number() -> TypeAnnotatedValue {
+            test_utils::get_type_annotated_value(&data_types::result_of_number_type(), "err(42)")
+        }
+
+        pub(crate) fn ok_of_option() -> TypeAnnotatedValue {
             test_utils::get_type_annotated_value(
                 &data_types::result_of_option_type(),
                 "ok(some(\"foo\"))",
             )
         }
 
-        pub(crate) fn result_of_variant() -> TypeAnnotatedValue {
+        pub(crate) fn err_of_option() -> TypeAnnotatedValue {
+            test_utils::get_type_annotated_value(
+                &data_types::result_of_option_type(),
+                "err(some(\"foo\"))",
+            )
+        }
+
+        pub(crate) fn ok_of_variant() -> TypeAnnotatedValue {
             test_utils::get_type_annotated_value(
                 &data_types::result_of_variant_type(),
                 "ok(case-str(\"foo\"))",
             )
         }
 
-        pub(crate) fn result_of_enum() -> TypeAnnotatedValue {
+        pub(crate) fn err_of_variant() -> TypeAnnotatedValue {
+            test_utils::get_type_annotated_value(
+                &data_types::result_of_variant_type(),
+                "err(case-str(\"foo\"))",
+            )
+        }
+
+        pub(crate) fn ok_of_enum() -> TypeAnnotatedValue {
             test_utils::get_type_annotated_value(&data_types::result_of_enum_type(), "ok(enum-a)")
         }
 
-        pub(crate) fn result_of_tuple() -> TypeAnnotatedValue {
+        pub(crate) fn err_of_enum() -> TypeAnnotatedValue {
+            test_utils::get_type_annotated_value(&data_types::result_of_enum_type(), "err(enum-a)")
+        }
+
+        pub(crate) fn ok_of_tuple() -> TypeAnnotatedValue {
             let tuple_str = test_utils::convert_type_annotated_value_to_str(&tuple());
             let wave_str = format!("ok({})", tuple_str);
             test_utils::get_type_annotated_value(
@@ -1227,14 +1781,30 @@ mod comprehensive_test {
             )
         }
 
-        pub(crate) fn result_of_flag() -> TypeAnnotatedValue {
+        pub(crate) fn err_of_tuple() -> TypeAnnotatedValue {
+            let tuple_str = test_utils::convert_type_annotated_value_to_str(&tuple());
+            let wave_str = format!("err({})", tuple_str);
+            test_utils::get_type_annotated_value(
+                &data_types::result_of_tuple_type(),
+                wave_str.as_str(),
+            )
+        }
+
+        pub(crate) fn ok_of_flag() -> TypeAnnotatedValue {
             test_utils::get_type_annotated_value(
                 &data_types::result_of_flag_type(),
                 "ok({featurex})",
             )
         }
 
-        pub(crate) fn result_of_record() -> TypeAnnotatedValue {
+        pub(crate) fn err_of_flag() -> TypeAnnotatedValue {
+            test_utils::get_type_annotated_value(
+                &data_types::result_of_flag_type(),
+                "err({featurex})",
+            )
+        }
+
+        pub(crate) fn ok_of_record() -> TypeAnnotatedValue {
             let record_str = test_utils::convert_type_annotated_value_to_str(&record());
             let wave_str = format!("ok({})", &record_str);
             test_utils::get_type_annotated_value(
@@ -1243,13 +1813,29 @@ mod comprehensive_test {
             )
         }
 
-        pub(crate) fn result_of_list() -> TypeAnnotatedValue {
+        pub(crate) fn err_of_record() -> TypeAnnotatedValue {
+            let record_str = test_utils::convert_type_annotated_value_to_str(&record());
+            let wave_str = format!("err({})", &record_str);
+            test_utils::get_type_annotated_value(
+                &data_types::result_of_record_type(),
+                wave_str.as_str(),
+            )
+        }
+
+        pub(crate) fn ok_of_list() -> TypeAnnotatedValue {
             test_utils::get_type_annotated_value(
                 &data_types::result_of_list_type(),
                 "ok([\"foo\"])",
             )
         }
 
+        pub(crate) fn err_of_list() -> TypeAnnotatedValue {
+            test_utils::get_type_annotated_value(
+                &data_types::result_of_list_type(),
+                "err([\"foo\"])",
+            )
+        }
+
         pub(crate) fn list_of_number() -> TypeAnnotatedValue {
             test_utils::get_type_annotated_value(&data_types::list_of_number_type_type(), "[42]")
         }
@@ -1295,39 +1881,63 @@ mod comprehensive_test {
             )
         }
 
-        pub(crate) fn option_of_number() -> TypeAnnotatedValue {
+        pub(crate) fn some_of_number() -> TypeAnnotatedValue {
             test_utils::get_type_annotated_value(&data_types::option_of_number_type(), "some(42)")
         }
 
-        pub(crate) fn option_of_str() -> TypeAnnotatedValue {
+        pub(crate) fn none_of_number() -> TypeAnnotatedValue {
+            test_utils::get_type_annotated_value(&data_types::option_of_number_type(), "none")
+        }
+
+        pub(crate) fn some_of_str() -> TypeAnnotatedValue {
             test_utils::get_type_annotated_value(&data_types::option_of_str_type(), "some(\"foo\")")
         }
 
-        pub(crate) fn option_of_option() -> TypeAnnotatedValue {
+        pub(crate) fn none_of_str() -> TypeAnnotatedValue {
+            test_utils::get_type_annotated_value(&data_types::option_of_str_type(), "none")
+        }
+
+        pub(crate) fn some_of_some() -> TypeAnnotatedValue {
             test_utils::get_type_annotated_value(
                 &data_types::option_of_option_type(),
                 "some(some(\"foo\"))",
             )
         }
 
-        pub(crate) fn option_of_variant() -> TypeAnnotatedValue {
+        pub(crate) fn none_of_some() -> TypeAnnotatedValue {
+            test_utils::get_type_annotated_value(&data_types::option_of_option_type(), "none")
+        }
+
+        pub(crate) fn some_of_variant() -> TypeAnnotatedValue {
             test_utils::get_type_annotated_value(
                 &data_types::option_of_variant_type(),
                 "some(case-str(\"foo\"))",
             )
         }
 
-        pub(crate) fn option_of_enum() -> TypeAnnotatedValue {
+        pub(crate) fn none_of_variant() -> TypeAnnotatedValue {
+            test_utils::get_type_annotated_value(&data_types::option_of_variant_type(), "none")
+        }
+
+        pub(crate) fn some_of_enum() -> TypeAnnotatedValue {
             test_utils::get_type_annotated_value(&data_types::option_of_enum_type(), "some(enum-a)")
         }
 
-        pub(crate) fn option_of_tuple() -> TypeAnnotatedValue {
+        pub(crate) fn none_of_enum() -> TypeAnnotatedValue {
+            test_utils::get_type_annotated_value(&data_types::option_of_enum_type(), "none")
+        }
+
+        pub(crate) fn some_of_tuple() -> TypeAnnotatedValue {
             let tuple_str = test_utils::convert_type_annotated_value_to_str(&tuple());
             let wave_str = format!("some({})", tuple_str);
             test_utils::get_type_annotated_value(&data_types::option_of_tuple(), wave_str.as_str())
         }
 
-        pub(crate) fn option_of_record() -> TypeAnnotatedValue {
+        pub(crate) fn none_of_tuple() -> TypeAnnotatedValue {
+            test_utils::get_type_annotated_value(&data_types::option_of_tuple(), "none")
+        }
+
+        pub(crate) fn some_of_record() -> TypeAnnotatedValue {
             let record_str = test_utils::convert_type_annotated_value_to_str(&record());
             let wave_str = format!("some({})", &record_str);
             test_utils::get_type_annotated_value(
@@ -1336,10 +1946,18 @@ mod comprehensive_test {
             )
         }
 
-        pub(crate) fn option_of_list() -> TypeAnnotatedValue {
+        pub(crate) fn none_of_record() -> TypeAnnotatedValue {
+            test_utils::get_type_annotated_value(&data_types::option_of_record_type(), "none")
+        }
+
+        pub(crate) fn some_of_list() -> TypeAnnotatedValue {
             test_utils::get_type_annotated_value(&data_types::option_of_list(), "some([\"foo\"])")
         }
 
+        pub(crate) fn none_of_list() -> TypeAnnotatedValue {
+            test_utils::get_type_annotated_value(&data_types::option_of_list(), "none")
+        }
+
         pub(crate) fn tuple() -> TypeAnnotatedValue {
             test_utils::get_type_annotated_value(
                 &data_types::tuple_type(),
@@ -1456,37 +2074,63 @@ mod comprehensive_test {
                 ("function-no-arg-unit", None),
                 ("function-str-response", Some(mock_data::str_data())),
                 ("function-number-response", Some(mock_data::number_data())),
+                ("function-some-str-response", Some(mock_data::some_of_str())),
+                ("function-none-str-response", Some(mock_data::none_of_str())),
+                (
+                    "function-some-number-response",
+                    Some(mock_data::some_of_number()),
+                ),
+                (
+                    "function-none-number-response",
+                    Some(mock_data::none_of_number()),
+                ),
+                (
+                    "function-some-option-response",
+                    Some(mock_data::some_of_some()),
+                ),
+                (
+                    "function-none-option-response",
+                    Some(mock_data::none_of_some()),
+                ),
+                (
+                    "function-some-variant-response",
+                    Some(mock_data::some_of_variant()),
+                ),
+                (
+                    "function-none-variant-response",
+                    Some(mock_data::none_of_variant()),
+                ),
                 (
-                    "function-option-str-response",
-                    Some(mock_data::option_of_str()),
+                    "function-some-enum-response",
+                    Some(mock_data::some_of_enum()),
                 ),
                 (
-                    "function-option-number-response",
-                    Some(mock_data::option_of_number()),
+                    "function-none-enum-response",
+                    Some(mock_data::none_of_enum()),
                 ),
                 (
-                    "function-option-option-response",
-                    Some(mock_data::option_of_option()),
+                    "function-some-tuple-response",
+                    Some(mock_data::some_of_tuple()),
                 ),
                 (
-                    "function-option-variant-response",
-                    Some(mock_data::option_of_variant()),
+                    "function-none-tuple-response",
+                    Some(mock_data::none_of_tuple()),
                 ),
                 (
-                    "function-option-enum-response",
-                    Some(mock_data::option_of_enum()),
+                    "function-some-record-response",
+                    Some(mock_data::some_of_record()),
                 ),
                 (
-                    "function-option-tuple-response",
-                    Some(mock_data::option_of_tuple()),
+                    "function-none-record-response",
+                    Some(mock_data::none_of_record()),
                 ),
                 (
-                    "function-option-record-response",
-                    Some(mock_data::option_of_record()),
+                    "function-some-list-response",
+                    Some(mock_data::some_of_list()),
                 ),
                 (
-                    "function-option-list-response",
-                    Some(mock_data::option_of_list()),
+                    "function-none-list-response",
+                    Some(mock_data::none_of_list()),
                 ),
                 (
                     "function-list-number-response",
@@ -1517,42 +2161,51 @@ mod comprehensive_test {
                     "function-list-record-response",
                     Some(mock_data::list_of_record()),
                 ),
+                ("function-ok-str-response", Some(mock_data::ok_of_str())),
+                ("function-err-str-response", Some(mock_data::err_of_str())),
                 (
-                    "function-result-str-response",
-                    Some(mock_data::result_of_str()),
+                    "function-ok-number-response",
+                    Some(mock_data::ok_of_number()),
                 ),
                 (
-                    "function-result-number-response",
-                    Some(mock_data::result_of_number()),
+                    "function-err-number-response",
+                    Some(mock_data::err_of_number()),
                 ),
                 (
-                    "function-result-option-response",
-                    Some(mock_data::result_of_option()),
+                    "function-ok-option-response",
+                    Some(mock_data::ok_of_option()),
                 ),
                 (
-                    "function-result-variant-response",
-                    Some(mock_data::result_of_variant()),
+                    "function-err-option-response",
+                    Some(mock_data::err_of_option()),
                 ),
                 (
-                    "function-result-enum-response",
-                    Some(mock_data::result_of_enum()),
+                    "function-ok-variant-response",
+                    Some(mock_data::ok_of_variant()),
                 ),
                 (
-                    "function-result-tuple-response",
-                    Some(mock_data::result_of_tuple()),
+                    "function-err-variant-response",
+                    Some(mock_data::err_of_variant()),
                 ),
+                ("function-ok-enum-response", Some(mock_data::ok_of_enum())),
+                ("function-err-enum-response", Some(mock_data::err_of_enum())),
+                ("function-ok-tuple-response", Some(mock_data::ok_of_tuple())),
                 (
-                    "function-result-flag-response",
-                    Some(mock_data::result_of_flag()),
+                    "function-err-tuple-response",
+                    Some(mock_data::err_of_tuple()),
                 ),
+                ("function-ok-flag-response", Some(mock_data::ok_of_flag())),
+                ("function-err-flag-response", Some(mock_data::err_of_flag())),
                 (
-                    "function-result-record-response",
-                    Some(mock_data::result_of_record()),
+                    "function-ok-record-response",
+                    Some(mock_data::ok_of_record()),
                 ),
                 (
-                    "function-result-list-response",
-                    Some(mock_data::result_of_list()),
+                    "function-err-record-response",
+                    Some(mock_data::err_of_record()),
                 ),
+                ("function-ok-list-response", Some(mock_data::ok_of_list())),
+                ("function-err-list-response", Some(mock_data::err_of_list())),
                 ("function-tuple-response", Some(mock_data::tuple())),
                 ("function-enum-response", Some(mock_data::enum_data())),
                 ("function-flag-response", Some(mock_data::flag())),
diff --git a/golem-rib/src/parser/binary_comparison.rs b/golem-rib/src/parser/binary_comparison.rs
index aa51c1173f..1908ebc386 100644
--- a/golem-rib/src/parser/binary_comparison.rs
+++ b/golem-rib/src/parser/binary_comparison.rs
@@ -29,6 +29,8 @@ where
         attempt(string("==")),
         string("<"),
         string(">"),
+        string("&&"),
+        string("||"),
     ))
     .and_then(|str| match str {
         ">" => Ok(BinaryOp::GreaterThan),
@@ -36,6 +38,8 @@ where
         "==" => Ok(BinaryOp::EqualTo),
         ">=" => Ok(BinaryOp::GreaterThanOrEqualTo),
         "<=" => Ok(BinaryOp::LessThanOrEqualTo),
+        "&&" => Ok(BinaryOp::And),
+        "||" => Ok(BinaryOp::Or),
         _ => Err(RibParseError::Message(
             "Invalid binary operator".to_string(),
         )),
@@ -48,6 +52,8 @@ pub enum BinaryOp {
     LessThanOrEqualTo,
     GreaterThanOrEqualTo,
     EqualTo,
+    And,
+    Or,
 }
 
 #[cfg(test)]
diff --git a/golem-rib/src/parser/multi_line_code_block.rs b/golem-rib/src/parser/multi_line_code_block.rs
index 11cf775271..4fd4652dd6 100644
--- a/golem-rib/src/parser/multi_line_code_block.rs
+++ b/golem-rib/src/parser/multi_line_code_block.rs
@@ -150,7 +150,10 @@ mod tests {
         let expected = Expr::pattern_match(
             Expr::identifier("foo"),
             vec![MatchArm::new(
-                ArmPattern::Literal(Box::new(Expr::option(Some(Expr::identifier("x"))))),
+                ArmPattern::Constructor(
+                    "some".to_string(),
+                    vec![ArmPattern::Literal(Box::new(Expr::identifier("x")))],
+                ),
                 Expr::multiple(vec![
                     Expr::let_binding("x", Expr::number(1f64)),
                     Expr::let_binding("y", Expr::number(2f64)),
@@ -190,7 +193,10 @@ mod tests {
             Expr::pattern_match(
                 Expr::identifier("foo"),
                 vec![MatchArm::new(
-                    ArmPattern::Literal(Box::new(Expr::option(Some(Expr::identifier("x"))))),
+                    ArmPattern::Constructor(
+                        "some".to_string(),
+                        vec![ArmPattern::Literal(Box::new(Expr::identifier("x")))],
+                    ),
                     Expr::multiple(vec![
                         Expr::let_binding("x", Expr::number(1f64)),
                         Expr::let_binding("y", Expr::number(2f64)),
diff --git a/golem-rib/src/parser/pattern_match.rs b/golem-rib/src/parser/pattern_match.rs
index 7225d36857..2ca00dcaca 100644
--- a/golem-rib/src/parser/pattern_match.rs
+++ b/golem-rib/src/parser/pattern_match.rs
@@ -128,9 +128,8 @@ mod internal {
 
     use crate::expr::ArmPattern;
     use crate::parser::errors::RibParseError;
-    use crate::parser::optional::option;
     use crate::parser::pattern_match::arm_pattern::*;
-    use crate::parser::result::result;
+
     use crate::parser::rib_expr::rib_expr;
 
     pub(crate) fn arm_pattern_constructor<Input>() -> impl Parser<Input, Output = ArmPattern>
@@ -141,9 +140,7 @@ mod internal {
         >,
     {
         choice((
-            attempt(option().map(|expr| ArmPattern::Literal(Box::new(expr)))),
-            attempt(result().map(|expr| ArmPattern::Literal(Box::new(expr)))),
-            attempt(custom_arm_pattern_constructor()),
+            attempt(arm_pattern_constructor_with_name()),
             attempt(tuple_arm_pattern_constructor()),
             attempt(list_arm_pattern_constructor()),
             attempt(record_arm_pattern_constructor()),
@@ -172,20 +169,32 @@ mod internal {
             .message("Unable to parse alias name")
     }
 
-    fn custom_arm_pattern_constructor<Input>() -> impl Parser<Input, Output = ArmPattern>
+    fn arm_pattern_constructor_with_name<Input>() -> impl Parser<Input, Output = ArmPattern>
     where
         Input: combine::Stream<Token = char>,
         RibParseError: Into<
             <Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError,
         >,
     {
-        (
+        let custom = (
             constructor_type_name().skip(spaces()),
             string("(").skip(spaces()),
             sep_by(arm_pattern().skip(spaces()), char_(',').skip(spaces())),
             string(")").skip(spaces()),
         )
-            .map(|(name, _, patterns, _)| ArmPattern::Constructor(name, patterns))
+            .map(|(name, _, patterns, _)| ArmPattern::Constructor(name, patterns));
+
+        attempt(none_constructor()).or(custom)
+    }
+
+    fn none_constructor<Input>() -> impl Parser<Input, Output = ArmPattern>
+    where
+        Input: combine::Stream<Token = char>,
+        RibParseError: Into<
+            <Input::Error as ParseError<Input::Token, Input::Range, Input::Position>>::StreamError,
+        >,
+    {
+        string("none").map(|_| ArmPattern::constructor("none", vec![]))
     }
 
     fn tuple_arm_pattern_constructor<Input>() -> impl Parser<Input, Output = ArmPattern>
@@ -410,22 +419,29 @@ mod tests {
                     vec![
                         MatchArm::new(ArmPattern::WildCard, Expr::identifier("bar")),
                         MatchArm::new(
-                            ArmPattern::Literal(Box::new(Expr::ok(Expr::identifier("x")))),
-                            Expr::identifier("x")
+                            ArmPattern::constructor(
+                                "ok",
+                                vec![ArmPattern::Literal(Box::new(Expr::identifier("x")))],
+                            ),
+                            Expr::identifier("x"),
                         ),
                         MatchArm::new(
-                            ArmPattern::Literal(Box::new(Expr::err(Expr::identifier("x")))),
-                            Expr::identifier("x")
+                            ArmPattern::constructor(
+                                "err",
+                                vec![ArmPattern::Literal(Box::new(Expr::identifier("x")))],
+                            ),
+                            Expr::identifier("x"),
                         ),
                         MatchArm::new(
-                            ArmPattern::Literal(Box::new(Expr::option(None))),
-                            Expr::identifier("foo")
+                            ArmPattern::constructor("none", vec![]),
+                            Expr::identifier("foo"),
                         ),
                         MatchArm::new(
-                            ArmPattern::Literal(Box::new(Expr::option(Some(Expr::identifier(
-                                "x"
-                            ))))),
-                            Expr::identifier("x")
+                            ArmPattern::constructor(
+                                "some",
+                                vec![ArmPattern::Literal(Box::new(Expr::identifier("x")))],
+                            ),
+                            Expr::identifier("x"),
                         ),
                     ]
                 ),
diff --git a/golem-rib/src/parser/rib_expr.rs b/golem-rib/src/parser/rib_expr.rs
index d627ed6871..d1d0f92754 100644
--- a/golem-rib/src/parser/rib_expr.rs
+++ b/golem-rib/src/parser/rib_expr.rs
@@ -70,6 +70,8 @@ where
                     BinaryOp::LessThanOrEqualTo => Expr::less_than_or_equal_to(acc, next),
                     BinaryOp::GreaterThanOrEqualTo => Expr::greater_than_or_equal_to(acc, next),
                     BinaryOp::EqualTo => Expr::equal_to(acc, next),
+                    BinaryOp::And => Expr::and(acc, next),
+                    BinaryOp::Or => Expr::or(acc, next),
                 })
             }),
         )
diff --git a/golem-rib/src/parser/select_field.rs b/golem-rib/src/parser/select_field.rs
index b62674568e..37452184fd 100644
--- a/golem-rib/src/parser/select_field.rs
+++ b/golem-rib/src/parser/select_field.rs
@@ -261,26 +261,33 @@ mod tests {
                     vec![
                         MatchArm::new(ArmPattern::WildCard, Expr::identifier("bar")),
                         MatchArm::new(
-                            ArmPattern::Literal(Box::new(Expr::ok(Expr::identifier("x")))),
-                            Expr::identifier("x")
+                            ArmPattern::constructor(
+                                "ok",
+                                vec![ArmPattern::Literal(Box::new(Expr::identifier("x")))]
+                            ),
+                            Expr::identifier("x"),
                         ),
                         MatchArm::new(
-                            ArmPattern::Literal(Box::new(Expr::err(Expr::identifier("x")))),
-                            Expr::identifier("x")
+                            ArmPattern::constructor(
+                                "err",
+                                vec![ArmPattern::Literal(Box::new(Expr::identifier("x")))]
+                            ),
+                            Expr::identifier("x"),
                         ),
                         MatchArm::new(
-                            ArmPattern::Literal(Box::new(Expr::option(None))),
-                            Expr::identifier("foo")
+                            ArmPattern::constructor("none", vec![]),
+                            Expr::identifier("foo"),
                         ),
                         MatchArm::new(
-                            ArmPattern::Literal(Box::new(Expr::option(Some(Expr::identifier(
-                                "x"
-                            ))))),
-                            Expr::identifier("x")
+                            ArmPattern::constructor(
+                                "some",
+                                vec![ArmPattern::Literal(Box::new(Expr::identifier("x")))]
+                            ),
+                            Expr::identifier("x"),
                         ),
                         MatchArm::new(
                             ArmPattern::Literal(Box::new(Expr::identifier("foo"))),
-                            Expr::select_field(Expr::identifier("foo"), "bar")
+                            Expr::select_field(Expr::identifier("foo"), "bar"),
                         ),
                     ]
                 ),
diff --git a/golem-rib/src/text/mod.rs b/golem-rib/src/text/mod.rs
index 62ff7320fd..97aa262c48 100644
--- a/golem-rib/src/text/mod.rs
+++ b/golem-rib/src/text/mod.rs
@@ -337,8 +337,20 @@ mod record_tests {
                 Expr::pattern_match(
                     Expr::identifier("request"),
                     vec![
-                        MatchArm::new(ArmPattern::ok("foo"), Expr::literal("success")),
-                        MatchArm::new(ArmPattern::err("msg"), Expr::literal("failure")),
+                        MatchArm::new(
+                            ArmPattern::constructor(
+                                "ok",
+                                vec![ArmPattern::literal(Expr::identifier("foo"))],
+                            ),
+                            Expr::literal("success"),
+                        ),
+                        MatchArm::new(
+                            ArmPattern::constructor(
+                                "err",
+                                vec![ArmPattern::literal(Expr::identifier("msg"))],
+                            ),
+                            Expr::literal("failure"),
+                        ),
                     ],
                 ),
             ),
@@ -347,14 +359,35 @@ mod record_tests {
                 Expr::pattern_match(
                     Expr::identifier("request"),
                     vec![
-                        MatchArm::new(ArmPattern::ok("foo"), Expr::literal("success")),
                         MatchArm::new(
-                            ArmPattern::err("msg"),
+                            ArmPattern::constructor(
+                                "ok",
+                                vec![ArmPattern::literal(Expr::identifier("foo"))],
+                            ), // Use Constructor for ok
+                            Expr::literal("success"),
+                        ),
+                        MatchArm::new(
+                            ArmPattern::constructor(
+                                "err",
+                                vec![ArmPattern::literal(Expr::identifier("msg"))],
+                            ),
                             Expr::pattern_match(
                                 Expr::identifier("request"),
                                 vec![
-                                    MatchArm::new(ArmPattern::ok("foo"), Expr::literal("success")),
-                                    MatchArm::new(ArmPattern::err("msg"), Expr::literal("failure")),
+                                    MatchArm::new(
+                                        ArmPattern::constructor(
+                                            "ok",
+                                            vec![ArmPattern::literal(Expr::identifier("foo"))],
+                                        ),
+                                        Expr::literal("success"),
+                                    ),
+                                    MatchArm::new(
+                                        ArmPattern::constructor(
+                                            "err",
+                                            vec![ArmPattern::literal(Expr::identifier("msg"))],
+                                        ),
+                                        Expr::literal("failure"),
+                                    ),
                                 ],
                             ),
                         ),
@@ -362,6 +395,7 @@ mod record_tests {
                 ),
             ),
         ]);
+
         let expr_str = to_string(&input_expr).unwrap();
         let expected_record_str = r#"{a: match request {  ok(foo) => "success", err(msg) => "failure" } , b: match request {  ok(foo) => "success", err(msg) => match request {  ok(foo) => "success", err(msg) => "failure" }  } }"#.to_string();
         let output_expr = from_string(expr_str.as_str()).unwrap();
@@ -595,27 +629,61 @@ mod sequence_tests {
             Expr::pattern_match(
                 Expr::identifier("request"),
                 vec![
-                    MatchArm::new(ArmPattern::ok("foo"), Expr::literal("success")),
-                    MatchArm::new(ArmPattern::err("msg"), Expr::literal("failure")),
+                    MatchArm::new(
+                        ArmPattern::Constructor(
+                            "ok".to_string(),
+                            vec![ArmPattern::literal(Expr::identifier("foo"))],
+                        ),
+                        Expr::literal("success"),
+                    ),
+                    MatchArm::new(
+                        ArmPattern::Constructor(
+                            "err".to_string(),
+                            vec![ArmPattern::literal(Expr::identifier("msg"))],
+                        ),
+                        Expr::literal("failure"),
+                    ),
                 ],
             ),
             Expr::pattern_match(
                 Expr::identifier("request"),
                 vec![
-                    MatchArm::new(ArmPattern::ok("foo"), Expr::literal("success")),
                     MatchArm::new(
-                        ArmPattern::err("msg"),
+                        ArmPattern::Constructor(
+                            "ok".to_string(),
+                            vec![ArmPattern::literal(Expr::identifier("foo"))],
+                        ),
+                        Expr::literal("success"),
+                    ),
+                    MatchArm::new(
+                        ArmPattern::Constructor(
+                            "err".to_string(),
+                            vec![ArmPattern::literal(Expr::identifier("msg"))],
+                        ),
                         Expr::pattern_match(
                             Expr::identifier("request"),
                             vec![
-                                MatchArm::new(ArmPattern::ok("foo"), Expr::literal("success")),
-                                MatchArm::new(ArmPattern::err("msg"), Expr::literal("failure")),
+                                MatchArm::new(
+                                    ArmPattern::Constructor(
+                                        "ok".to_string(),
+                                        vec![ArmPattern::literal(Expr::identifier("foo"))],
+                                    ), // Use Constructor for ok
+                                    Expr::literal("success"),
+                                ),
+                                MatchArm::new(
+                                    ArmPattern::Constructor(
+                                        "err".to_string(),
+                                        vec![ArmPattern::literal(Expr::identifier("msg"))],
+                                    ),
+                                    Expr::literal("failure"),
+                                ),
                             ],
                         ),
                     ),
                 ],
             ),
         ]);
+
         let expr_str = to_string(&input_expr).unwrap();
         let expected_str = r#"[match request {  ok(foo) => "success", err(msg) => "failure" } , match request {  ok(foo) => "success", err(msg) => match request {  ok(foo) => "success", err(msg) => "failure" }  } ]"#.to_string();
         let output_expr = from_string(expr_str.as_str()).unwrap();
@@ -1159,8 +1227,20 @@ mod match_tests {
         let mut input_expr = Expr::pattern_match(
             Expr::identifier("request"),
             vec![
-                MatchArm::new(ArmPattern::ok("foo"), Expr::literal("success")),
-                MatchArm::new(ArmPattern::err("msg"), Expr::literal("failure")),
+                MatchArm::new(
+                    ArmPattern::constructor(
+                        "ok",
+                        vec![ArmPattern::literal(Expr::identifier("foo"))],
+                    ),
+                    Expr::literal("success"),
+                ),
+                MatchArm::new(
+                    ArmPattern::constructor(
+                        "err",
+                        vec![ArmPattern::literal(Expr::identifier("msg"))],
+                    ),
+                    Expr::literal("failure"),
+                ),
             ],
         );
 
@@ -1180,10 +1260,19 @@ mod match_tests {
             Expr::identifier("request"),
             vec![
                 MatchArm::new(
-                    ArmPattern::ok("foo"),
+                    ArmPattern::constructor(
+                        "ok",
+                        vec![ArmPattern::literal(Expr::identifier("foo"))],
+                    ),
                     Expr::flags(vec!["flag1".to_string(), "flag2".to_string()]),
                 ),
-                MatchArm::new(ArmPattern::err("msg"), Expr::literal("failure")),
+                MatchArm::new(
+                    ArmPattern::constructor(
+                        "err",
+                        vec![ArmPattern::literal(Expr::identifier("msg"))],
+                    ),
+                    Expr::literal("failure"),
+                ),
             ],
         );
 
@@ -1200,13 +1289,22 @@ mod match_tests {
             Expr::identifier("request"),
             vec![
                 MatchArm::new(
-                    ArmPattern::ok("foo"),
+                    ArmPattern::constructor(
+                        "ok",
+                        vec![ArmPattern::literal(Expr::identifier("foo"))],
+                    ),
                     Expr::tuple(vec![
                         Expr::identifier("request"),
                         Expr::identifier("request"),
                     ]),
                 ),
-                MatchArm::new(ArmPattern::err("msg"), Expr::literal("failure")),
+                MatchArm::new(
+                    ArmPattern::constructor(
+                        "err",
+                        vec![ArmPattern::literal(Expr::identifier("msg"))],
+                    ),
+                    Expr::literal("failure"),
+                ),
             ],
         );
 
@@ -1224,13 +1322,22 @@ mod match_tests {
             Expr::identifier("request"),
             vec![
                 MatchArm::new(
-                    ArmPattern::ok("foo"),
+                    ArmPattern::constructor(
+                        "ok",
+                        vec![ArmPattern::literal(Expr::identifier("foo"))],
+                    ),
                     Expr::sequence(vec![
                         Expr::identifier("request"),
                         Expr::identifier("request"),
                     ]),
                 ),
-                MatchArm::new(ArmPattern::err("msg"), Expr::literal("failure")),
+                MatchArm::new(
+                    ArmPattern::constructor(
+                        "err",
+                        vec![ArmPattern::literal(Expr::identifier("msg"))],
+                    ),
+                    Expr::literal("failure"),
+                ),
             ],
         );
 
@@ -1248,10 +1355,19 @@ mod match_tests {
             Expr::identifier("request"),
             vec![
                 MatchArm::new(
-                    ArmPattern::ok("foo"),
+                    ArmPattern::constructor(
+                        "ok",
+                        vec![ArmPattern::literal(Expr::identifier("foo"))],
+                    ),
                     Expr::record(vec![("field".to_string(), Expr::identifier("request"))]),
                 ),
-                MatchArm::new(ArmPattern::err("msg"), Expr::literal("failure")),
+                MatchArm::new(
+                    ArmPattern::constructor(
+                        "err",
+                        vec![ArmPattern::literal(Expr::identifier("msg"))],
+                    ),
+                    Expr::literal("failure"),
+                ),
             ],
         );
 
@@ -1268,12 +1384,18 @@ mod match_tests {
             Expr::identifier("request"),
             vec![
                 MatchArm::new(
-                    ArmPattern::ok("foo"),
-                    Expr::greater_than(Expr::number(1f64), Expr::number(2f64)),
+                    ArmPattern::constructor(
+                        "ok",
+                        vec![ArmPattern::literal(Expr::identifier("foo"))],
+                    ),
+                    Expr::greater_than(Expr::number(1.0), Expr::number(2.0)),
                 ),
                 MatchArm::new(
-                    ArmPattern::err("msg"),
-                    Expr::less_than(Expr::number(1f64), Expr::number(2f64)),
+                    ArmPattern::constructor(
+                        "err",
+                        vec![ArmPattern::literal(Expr::identifier("msg"))],
+                    ),
+                    Expr::less_than(Expr::number(1.0), Expr::number(2.0)),
                 ),
             ],
         );
@@ -1290,7 +1412,10 @@ mod match_tests {
             Expr::identifier("request"),
             vec![
                 MatchArm::new(
-                    ArmPattern::ok("foo"),
+                    ArmPattern::constructor(
+                        "ok",
+                        vec![ArmPattern::literal(Expr::identifier("foo"))],
+                    ),
                     Expr::cond(
                         Expr::equal_to(
                             Expr::select_field(Expr::identifier("request"), "foo"),
@@ -1300,7 +1425,13 @@ mod match_tests {
                         Expr::literal("failed"),
                     ),
                 ),
-                MatchArm::new(ArmPattern::err("msg"), Expr::literal("failure")),
+                MatchArm::new(
+                    ArmPattern::constructor(
+                        "err",
+                        vec![ArmPattern::literal(Expr::identifier("msg"))],
+                    ),
+                    Expr::literal("failure"),
+                ),
             ],
         );
 
diff --git a/golem-rib/src/text/writer.rs b/golem-rib/src/text/writer.rs
index ebe7015854..7013eaddc9 100644
--- a/golem-rib/src/text/writer.rs
+++ b/golem-rib/src/text/writer.rs
@@ -276,6 +276,11 @@ impl<W: Write> Writer<W> {
                 self.write_str(" && ")?;
                 self.write_expr(right)
             }
+            Expr::Or(left, right, _) => {
+                self.write_expr(left)?;
+                self.write_str(" || ")?;
+                self.write_expr(right)
+            }
         }
     }
 
diff --git a/golem-rib/src/type_inference/expr_visitor.rs b/golem-rib/src/type_inference/expr_visitor.rs
index 0f7ea5d142..722cdb0426 100644
--- a/golem-rib/src/type_inference/expr_visitor.rs
+++ b/golem-rib/src/type_inference/expr_visitor.rs
@@ -63,6 +63,16 @@ pub fn visit_children_bottom_up_mut<'a>(expr: &'a mut Expr, queue: &mut VecDeque
             queue.push_back(&mut *expr1);
             queue.push_back(&mut *expr2)
         }
+
+        Expr::Or(expr1, expr2, _) => {
+            queue.push_back(&mut *expr1);
+            queue.push_back(&mut *expr2)
+        }
+
+        Expr::GetTag(exr, _) => {
+            queue.push_back(&mut *exr);
+        }
+
         Expr::Literal(_, _) => {}
         Expr::Number(_, _, _) => {}
         Expr::Flags(_, _) => {}
@@ -70,7 +80,6 @@ pub fn visit_children_bottom_up_mut<'a>(expr: &'a mut Expr, queue: &mut VecDeque
         Expr::Boolean(_, _) => {}
         Expr::Option(None, _) => {}
         Expr::Throw(_, _) => {}
-        Expr::GetTag(_, _) => {}
     }
 }
 
@@ -134,6 +143,14 @@ pub fn visit_children_bottom_up<'a>(expr: &'a Expr, queue: &mut VecDeque<&'a Exp
             queue.push_back(expr1);
             queue.push_back(expr2);
         }
+        Expr::Or(expr1, expr2, _) => {
+            queue.push_back(expr1);
+            queue.push_back(expr2);
+        }
+        Expr::GetTag(expr, _) => {
+            queue.push_back(expr);
+        }
+
         Expr::Literal(_, _) => {}
         Expr::Number(_, _, _) => {}
         Expr::Flags(_, _) => {}
@@ -141,7 +158,6 @@ pub fn visit_children_bottom_up<'a>(expr: &'a Expr, queue: &mut VecDeque<&'a Exp
         Expr::Boolean(_, _) => {}
         Expr::Option(None, _) => {}
         Expr::Throw(_, _) => {}
-        Expr::GetTag(_, _) => {}
     }
 }
 
@@ -206,6 +222,10 @@ pub fn visit_children_mut_top_down<'a>(expr: &'a mut Expr, queue: &mut VecDeque<
             queue.push_front(&mut *expr1);
             queue.push_front(&mut *expr2)
         }
+        Expr::Or(expr1, expr2, _) => {
+            queue.push_front(&mut *expr1);
+            queue.push_front(&mut *expr2)
+        }
         Expr::PatternMatch(expr, arms, _) => {
             queue.push_front(&mut *expr);
             for arm in arms {
@@ -228,6 +248,10 @@ pub fn visit_children_mut_top_down<'a>(expr: &'a mut Expr, queue: &mut VecDeque<
                 queue.push_front(expr);
             }
         }
+        Expr::GetTag(expr, _) => {
+            queue.push_front(&mut *expr);
+        }
+
         Expr::Unwrap(expr, _) => queue.push_front(&mut *expr),
         Expr::Literal(_, _) => {}
         Expr::Number(_, _, _) => {}
@@ -236,7 +260,6 @@ pub fn visit_children_mut_top_down<'a>(expr: &'a mut Expr, queue: &mut VecDeque<
         Expr::Boolean(_, _) => {}
         Expr::Option(None, _) => {}
         Expr::Throw(_, _) => {}
-        Expr::GetTag(_, _) => {}
     }
 }
 
diff --git a/golem-rib/src/type_inference/mod.rs b/golem-rib/src/type_inference/mod.rs
index 36ad439377..c7449a8bd1 100644
--- a/golem-rib/src/type_inference/mod.rs
+++ b/golem-rib/src/type_inference/mod.rs
@@ -984,23 +984,23 @@ mod type_inference_tests {
                         )),
                         vec![
                             MatchArm::new(
-                                ArmPattern::Literal(Box::new(Expr::Option(
-                                    Some(Box::new(Expr::Identifier(
+                                ArmPattern::constructor(
+                                    "some",
+                                    vec![ArmPattern::literal(Expr::Identifier(
                                         VariableId::match_identifier("z".to_string(), 1),
                                         InferredType::U64,
-                                    ))),
-                                    InferredType::Option(Box::new(InferredType::U64)),
-                                ))),
+                                    ))],
+                                ),
                                 Expr::Identifier(VariableId::local("y", 0), InferredType::U64),
                             ),
                             MatchArm::new(
-                                ArmPattern::Literal(Box::new(Expr::Option(
-                                    Some(Box::new(Expr::Identifier(
+                                ArmPattern::constructor(
+                                    "some",
+                                    vec![ArmPattern::literal(Expr::Identifier(
                                         VariableId::match_identifier("z".to_string(), 2),
                                         InferredType::U64,
-                                    ))),
-                                    InferredType::Option(Box::new(InferredType::U64)),
-                                ))),
+                                    ))],
+                                ),
                                 Expr::Identifier(
                                     VariableId::match_identifier("z".to_string(), 2),
                                     InferredType::U64,
@@ -1187,13 +1187,13 @@ mod type_inference_tests {
                         )),
                         vec![
                             MatchArm::new(
-                                ArmPattern::Literal(Box::new(Expr::Option(
-                                    Some(Box::new(Expr::Identifier(
+                                ArmPattern::Constructor(
+                                    "some".to_string(),
+                                    vec![ArmPattern::Literal(Box::new(Expr::Identifier(
                                         VariableId::match_identifier("x".to_string(), 1),
                                         InferredType::U64,
-                                    ))),
-                                    InferredType::Option(Box::new(InferredType::U64)),
-                                ))),
+                                    )))],
+                                ),
                                 Expr::Option(
                                     Some(Box::new(Expr::Option(
                                         Some(Box::new(Expr::Identifier(
@@ -1208,10 +1208,7 @@ mod type_inference_tests {
                                 ),
                             ),
                             MatchArm::new(
-                                ArmPattern::Literal(Box::new(Expr::Option(
-                                    None,
-                                    InferredType::Option(Box::new(InferredType::U64)),
-                                ))),
+                                ArmPattern::constructor("none", vec![]),
                                 Expr::Option(
                                     Some(Box::new(Expr::Option(
                                         Some(Box::new(Expr::Identifier(
@@ -1273,19 +1270,16 @@ mod type_inference_tests {
                             )]))),
                         )),
                         vec![MatchArm::new(
-                            ArmPattern::Literal(Box::new(Expr::Option(
-                                Some(Box::new(Expr::Identifier(
+                            ArmPattern::Constructor(
+                                "some".to_string(),
+                                vec![ArmPattern::Literal(Box::new(Expr::Identifier(
                                     VariableId::match_identifier("x".to_string(), 1),
                                     InferredType::Record(vec![(
                                         "foo".to_string(),
                                         InferredType::Str,
                                     )]),
-                                ))),
-                                InferredType::Option(Box::new(InferredType::Record(vec![(
-                                    "foo".to_string(),
-                                    InferredType::Str,
-                                )]))),
-                            ))),
+                                )))],
+                            ),
                             Expr::Identifier(
                                 VariableId::match_identifier("x".to_string(), 1),
                                 InferredType::Record(vec![("foo".to_string(), InferredType::Str)]),
@@ -1336,19 +1330,16 @@ mod type_inference_tests {
                             )]))),
                         )),
                         vec![MatchArm::new(
-                            ArmPattern::Literal(Box::new(Expr::Option(
-                                Some(Box::new(Expr::Identifier(
+                            ArmPattern::constructor(
+                                "some",
+                                vec![ArmPattern::literal(Expr::Identifier(
                                     VariableId::match_identifier("x".to_string(), 1),
                                     InferredType::Record(vec![(
                                         "foo".to_string(),
                                         InferredType::Str,
                                     )]),
-                                ))),
-                                InferredType::Option(Box::new(InferredType::Record(vec![(
-                                    "foo".to_string(),
-                                    InferredType::Str,
-                                )]))),
-                            ))),
+                                ))],
+                            ),
                             Expr::SelectField(
                                 Box::new(Expr::Identifier(
                                     VariableId::match_identifier("x".to_string(), 1),
@@ -1425,19 +1416,16 @@ mod type_inference_tests {
                             )]))),
                         )),
                         vec![MatchArm::new(
-                            ArmPattern::Literal(Box::new(Expr::Option(
-                                Some(Box::new(Expr::Identifier(
+                            ArmPattern::Constructor(
+                                "some".to_string(),
+                                vec![ArmPattern::Literal(Box::new(Expr::Identifier(
                                     VariableId::match_identifier("x".to_string(), 1),
                                     InferredType::Record(vec![(
                                         "foo".to_string(),
                                         InferredType::Str,
                                     )]),
-                                ))),
-                                InferredType::Option(Box::new(InferredType::Record(vec![(
-                                    "foo".to_string(),
-                                    InferredType::Str,
-                                )]))),
-                            ))),
+                                )))],
+                            ),
                             Expr::SelectField(
                                 Box::new(Expr::Identifier(
                                     VariableId::match_identifier("x".to_string(), 1),
@@ -1463,15 +1451,13 @@ mod type_inference_tests {
                             )))),
                         )),
                         vec![MatchArm::new(
-                            ArmPattern::Literal(Box::new(Expr::Option(
-                                Some(Box::new(Expr::Identifier(
+                            ArmPattern::Constructor(
+                                "some".to_string(),
+                                vec![ArmPattern::Literal(Box::new(Expr::Identifier(
                                     VariableId::match_identifier("y".to_string(), 2),
                                     InferredType::List(Box::new(InferredType::U64)),
-                                ))),
-                                InferredType::Option(Box::new(InferredType::List(Box::new(
-                                    InferredType::U64,
-                                )))),
-                            ))),
+                                )))],
+                            ),
                             Expr::SelectIndex(
                                 Box::new(Expr::Identifier(
                                     VariableId::match_identifier("y".to_string(), 2),
@@ -2589,27 +2575,20 @@ mod type_inference_tests {
                         )),
                         vec![
                             MatchArm {
-                                arm_pattern: ArmPattern::Literal(Box::new(Expr::Option(
-                                    Some(Box::new(Expr::Identifier(
+                                arm_pattern: ArmPattern::constructor(
+                                    "some",
+                                    vec![ArmPattern::literal(Expr::Identifier(
                                         VariableId::MatchIdentifier(MatchIdentifier::new(
                                             "value".to_string(),
                                             1,
                                         )),
                                         InferredType::Option(Box::new(InferredType::Str)),
-                                    ))),
-                                    InferredType::Option(Box::new(InferredType::Option(Box::new(
-                                        InferredType::Str,
-                                    )))),
-                                ))),
+                                    ))],
+                                ),
                                 arm_resolution_expr: Box::new(Expr::literal("personal-id")),
                             },
                             MatchArm {
-                                arm_pattern: ArmPattern::Literal(Box::new(Expr::Option(
-                                    None,
-                                    InferredType::Option(Box::new(InferredType::Option(Box::new(
-                                        InferredType::Str,
-                                    )))),
-                                ))),
+                                arm_pattern: ArmPattern::constructor("none", vec![]),
                                 arm_resolution_expr: Box::new(Expr::SelectIndex(
                                     Box::new(Expr::SelectField(
                                         Box::new(Expr::SelectField(
diff --git a/golem-rib/src/type_inference/pattern_match_binding.rs b/golem-rib/src/type_inference/pattern_match_binding.rs
index e4eea777fa..ef249ddde0 100644
--- a/golem-rib/src/type_inference/pattern_match_binding.rs
+++ b/golem-rib/src/type_inference/pattern_match_binding.rs
@@ -260,19 +260,25 @@ mod pattern_match_bindings {
 
         pub(crate) fn expected_match(index: usize) -> Expr {
             Expr::PatternMatch(
-                Box::new(Expr::option(Some(Expr::identifier("x")))), // x is still global
+                Box::new(Expr::Option(
+                    Some(Box::new(Expr::Identifier(
+                        VariableId::Global("x".to_string()),
+                        InferredType::Unknown,
+                    ))),
+                    InferredType::Option(Box::new(InferredType::Unknown)),
+                )),
                 vec![
                     MatchArm {
-                        arm_pattern: ArmPattern::Literal(Box::new(Expr::Option(
-                            Some(Box::new(Expr::Identifier(
+                        arm_pattern: ArmPattern::constructor(
+                            "some",
+                            vec![ArmPattern::literal(Expr::Identifier(
                                 VariableId::MatchIdentifier(MatchIdentifier::new(
                                     "x".to_string(),
                                     index,
                                 )),
                                 InferredType::Unknown,
-                            ))),
-                            InferredType::Option(Box::new(InferredType::Unknown)),
-                        ))),
+                            ))],
+                        ),
                         arm_resolution_expr: Box::new(Expr::Identifier(
                             VariableId::MatchIdentifier(MatchIdentifier::new(
                                 "x".to_string(),
@@ -282,7 +288,7 @@ mod pattern_match_bindings {
                         )),
                     },
                     MatchArm {
-                        arm_pattern: ArmPattern::Literal(Box::new(Expr::option(None))),
+                        arm_pattern: ArmPattern::constructor("none", vec![]),
                         arm_resolution_expr: Box::new(Expr::number(0f64)),
                     },
                 ],
@@ -300,20 +306,20 @@ mod pattern_match_bindings {
                 Box::new(Expr::option(Some(Expr::identifier("x")))), // x is still global
                 vec![
                     MatchArm {
-                        arm_pattern: ArmPattern::Literal(Box::new(Expr::Option(
-                            Some(Box::new(Expr::Identifier(
+                        arm_pattern: ArmPattern::constructor(
+                            "some",
+                            vec![ArmPattern::literal(Expr::Identifier(
                                 VariableId::MatchIdentifier(MatchIdentifier::new(
                                     "x".to_string(),
                                     index,
                                 )),
                                 InferredType::Unknown,
-                            ))),
-                            InferredType::Option(Box::new(InferredType::Unknown)),
-                        ))),
+                            ))],
+                        ),
                         arm_resolution_expr: Box::new(block),
                     },
                     MatchArm {
-                        arm_pattern: ArmPattern::Literal(Box::new(Expr::option(None))),
+                        arm_pattern: ArmPattern::constructor("none", vec![]),
                         arm_resolution_expr: Box::new(Expr::number(0f64)),
                     },
                 ],
@@ -340,10 +346,16 @@ mod pattern_match_bindings {
                 )),
                 vec![
                     MatchArm {
-                        arm_pattern: ArmPattern::Literal(Box::new(Expr::ok(Expr::Identifier(
-                            VariableId::MatchIdentifier(MatchIdentifier::new("x".to_string(), 1)),
-                            InferredType::Unknown,
-                        )))),
+                        arm_pattern: ArmPattern::constructor(
+                            "ok",
+                            vec![ArmPattern::literal(Expr::Identifier(
+                                VariableId::MatchIdentifier(MatchIdentifier::new(
+                                    "x".to_string(),
+                                    1,
+                                )),
+                                InferredType::Unknown,
+                            ))],
+                        ),
                         arm_resolution_expr: Box::new(Expr::PatternMatch(
                             Box::new(Expr::Identifier(
                                 VariableId::MatchIdentifier(MatchIdentifier::new(
@@ -354,15 +366,16 @@ mod pattern_match_bindings {
                             )),
                             vec![
                                 MatchArm {
-                                    arm_pattern: ArmPattern::Literal(Box::new(Expr::option(Some(
-                                        Expr::Identifier(
+                                    arm_pattern: ArmPattern::constructor(
+                                        "some",
+                                        vec![ArmPattern::literal(Expr::Identifier(
                                             VariableId::MatchIdentifier(MatchIdentifier::new(
                                                 "x".to_string(),
                                                 2,
                                             )),
                                             InferredType::Unknown,
-                                        ),
-                                    )))),
+                                        ))],
+                                    ),
                                     arm_resolution_expr: Box::new(Expr::Identifier(
                                         VariableId::MatchIdentifier(MatchIdentifier::new(
                                             "x".to_string(),
@@ -372,7 +385,7 @@ mod pattern_match_bindings {
                                     )),
                                 },
                                 MatchArm {
-                                    arm_pattern: ArmPattern::Literal(Box::new(Expr::option(None))),
+                                    arm_pattern: ArmPattern::constructor("none", vec![]),
                                     arm_resolution_expr: Box::new(Expr::number(0f64)),
                                 },
                             ],
@@ -380,10 +393,16 @@ mod pattern_match_bindings {
                         )),
                     },
                     MatchArm {
-                        arm_pattern: ArmPattern::Literal(Box::new(Expr::err(Expr::Identifier(
-                            VariableId::MatchIdentifier(MatchIdentifier::new("x".to_string(), 4)), // 4 because none is an arm where we allotted the arm index to be 3
-                            InferredType::Unknown,
-                        )))),
+                        arm_pattern: ArmPattern::constructor(
+                            "err",
+                            vec![ArmPattern::literal(Expr::Identifier(
+                                VariableId::MatchIdentifier(MatchIdentifier::new(
+                                    "x".to_string(),
+                                    4,
+                                )),
+                                InferredType::Unknown,
+                            ))],
+                        ),
                         arm_resolution_expr: Box::new(Expr::number(0f64)),
                     },
                 ],
diff --git a/golem-rib/src/type_inference/type_binding.rs b/golem-rib/src/type_inference/type_binding.rs
index 45aa848180..bbaf35fc4f 100644
--- a/golem-rib/src/type_inference/type_binding.rs
+++ b/golem-rib/src/type_inference/type_binding.rs
@@ -71,6 +71,7 @@ mod internal {
             | Expr::Throw(_, inferred_type)
             | Expr::GetTag(_, inferred_type)
             | Expr::And(_, _, inferred_type)
+            | Expr::Or(_, _, inferred_type)
             | Expr::Call(_, _, inferred_type) => {
                 *inferred_type = new_type;
             }
diff --git a/golem-rib/src/type_inference/type_pull_up.rs b/golem-rib/src/type_inference/type_pull_up.rs
index 0f5663fba3..ad1f8b0c4b 100644
--- a/golem-rib/src/type_inference/type_pull_up.rs
+++ b/golem-rib/src/type_inference/type_pull_up.rs
@@ -13,187 +13,708 @@
 // limitations under the License.
 
 use crate::{Expr, InferredType};
+use std::collections::VecDeque;
 
-// TODO; This is recursion because we bumped into Rust borrowing issues with the following logic,
-// which may require changing Expr data structure with RefCells.
-// Logic that we need:
-//   * Fill up a queue with the root node being first
-//  [select_field(select_field(a, b), c), select_field(a, b), identifier(a)]
-//  Pop from back and push to the front of a stack of the current expression's inferred type, and keep assigning in between
-// Example:
-//  * Pop back to get identifier(a)
-//  * Try to pop_front inferred_type_stack, and its None. Push front the identifier(a)'s inferred_type:  Record(b -> Record(c -> u64))
-//  * Pop back from stack to get select_field(a, b)
-//  * Try to pop_front inferred_type_stack, and its Record(b -> Record(c -> u64)). Get the type of b and assign itself and push_front to stack.
-//  * Pop back from stack to get select_field(select_field(a, b), c)
-//  * Try to pop_front inferred_type_stack, and its  Record(c -> u64). Get the type of c and assign itself and push to stack.
-pub fn pull_types_up(expr: &mut Expr) -> Result<(), String> {
-    match expr {
-        Expr::Tuple(exprs, inferred_type) => {
-            let mut types = vec![];
-            for expr in exprs {
-                expr.pull_types_up()?;
-                types.push(expr.inferred_type());
-            }
-            let tuple_type = InferredType::Tuple(types);
-            *inferred_type = inferred_type.merge(tuple_type)
-        }
-        Expr::Sequence(exprs, inferred_type) => {
-            let mut types = vec![];
-            for expr in exprs {
-                expr.pull_types_up()?;
-                types.push(expr.inferred_type());
+pub fn type_pull_up(expr: &Expr) -> Result<Expr, String> {
+    let mut expr_queue = VecDeque::new();
+    internal::make_expr_nodes_queue(expr, &mut expr_queue);
+
+    let mut inferred_type_stack = VecDeque::new();
+
+    while let Some(expr) = expr_queue.pop_back() {
+        match expr {
+            Expr::Tuple(tuple_elems, current_inferred_type) => {
+                internal::handle_tuple(
+                    tuple_elems,
+                    current_inferred_type,
+                    &mut inferred_type_stack,
+                );
             }
-            if let Some(new_inferred_type) = types.first() {
-                let sequence_type = InferredType::List(Box::new(new_inferred_type.clone()));
-                *inferred_type = inferred_type.merge(sequence_type)
+
+            expr @ Expr::Identifier(_, _) => {
+                inferred_type_stack.push_front(expr.clone());
             }
-        }
-        Expr::Record(exprs, inferred_type) => {
-            let mut types = vec![];
-            for (field_name, expr) in exprs {
-                expr.pull_types_up()?;
-                types.push((field_name.clone(), expr.inferred_type()));
-            }
-            let record_type = InferredType::Record(types);
-            *inferred_type = inferred_type.merge(record_type);
-        }
-        Expr::Option(Some(expr), inferred_type) => {
-            expr.pull_types_up()?;
-            let option_type = InferredType::Option(Box::new(expr.inferred_type()));
-            *inferred_type = inferred_type.merge(option_type)
-        }
-        Expr::Result(Ok(expr), inferred_type) => {
-            expr.pull_types_up()?;
-            let result_type = InferredType::Result {
-                ok: Some(Box::new(expr.inferred_type())),
-                error: None,
-            };
-            *inferred_type = inferred_type.merge(result_type)
-        }
-        Expr::Result(Err(expr), inferred_type) => {
-            expr.pull_types_up()?;
-            let result_type = InferredType::Result {
-                ok: None,
-                error: Some(Box::new(expr.inferred_type())),
-            };
-            *inferred_type = inferred_type.merge(result_type)
-        }
 
-        Expr::Cond(_, then_, else_, inferred_type) => {
-            then_.pull_types_up()?;
-            else_.pull_types_up()?;
-            let then_type = then_.inferred_type();
-            let else_type = else_.inferred_type();
+            expr @ Expr::Flags(_, _) => {
+                inferred_type_stack.push_front(expr.clone());
+            }
 
-            if then_type == else_type {
-                *inferred_type = inferred_type.merge(then_type);
-            } else if let Some(cond_then_else_type) =
-                InferredType::all_of(vec![then_type, else_type])
-            {
-                *inferred_type = inferred_type.merge(cond_then_else_type);
+            Expr::SelectField(expr, field, current_inferred_type) => {
+                internal::handle_select_field(
+                    expr,
+                    field,
+                    current_inferred_type,
+                    &mut inferred_type_stack,
+                )?;
             }
-        }
 
-        // When it comes to pattern match, the only way to resolve the type of the pattern match
-        // from children (pulling types up) is from the match_arms
-        Expr::PatternMatch(predicate, match_arms, inferred_type) => {
-            predicate.pull_types_up()?;
-            let mut possible_inference_types = vec![];
+            Expr::SelectIndex(expr, index, current_inferred_type) => {
+                internal::handle_select_index(
+                    expr,
+                    index,
+                    current_inferred_type,
+                    &mut inferred_type_stack,
+                )?;
+            }
 
-            for match_arm in match_arms {
-                internal::pull_up_types_of_arm_pattern(&mut match_arm.arm_pattern)?;
+            Expr::Result(Ok(_), current_inferred_type) => {
+                internal::handle_result_ok(expr, current_inferred_type, &mut inferred_type_stack);
+            }
 
-                match_arm.arm_resolution_expr.pull_types_up()?;
-                possible_inference_types.push(match_arm.arm_resolution_expr.inferred_type())
+            Expr::Result(Err(_), current_inferred_type) => {
+                internal::handle_result_error(
+                    expr,
+                    current_inferred_type,
+                    &mut inferred_type_stack,
+                );
             }
 
-            if !possible_inference_types.is_empty() {
-                let first_type = possible_inference_types[0].clone();
-                if possible_inference_types.iter().all(|t| t == &first_type) {
-                    *inferred_type = inferred_type.merge(first_type);
-                } else if let Some(all_of) = InferredType::all_of(possible_inference_types) {
-                    *inferred_type = inferred_type.merge(all_of);
-                }
+            Expr::Option(Some(expr), current_inferred_type) => {
+                internal::handle_option_some(expr, current_inferred_type, &mut inferred_type_stack);
             }
-        }
-        Expr::Let(_, _, expr, _) => expr.pull_types_up()?,
-        Expr::SelectField(expr, field, inferred_type) => {
-            expr.pull_types_up()?;
-            let expr_type = expr.inferred_type();
-            let field_type = internal::get_inferred_type_of_selected_field(field, &expr_type)?;
-            *inferred_type = inferred_type.merge(field_type);
-        }
 
-        Expr::SelectIndex(expr, index, inferred_type) => {
-            expr.pull_types_up()?;
-            let expr_type = expr.inferred_type();
-            let list_type = internal::get_inferred_type_of_selected_index(*index, &expr_type)?;
-            *inferred_type = inferred_type.merge(list_type);
-        }
-        Expr::Literal(_, _) => {}
-        Expr::Number(_, _, _) => {}
-        Expr::Flags(_, _) => {}
-        Expr::Identifier(_, _) => {}
-        Expr::Boolean(_, _) => {}
-        Expr::Concat(exprs, _) => {
-            for expr in exprs {
-                expr.pull_types_up()?
+            Expr::Option(None, current_inferred_type) => {
+                inferred_type_stack.push_front(Expr::Option(None, current_inferred_type.clone()));
             }
-        }
-        Expr::Multiple(exprs, inferred_type) => {
-            let length = &exprs.len();
-            for (index, expr) in exprs.iter_mut().enumerate() {
-                expr.pull_types_up()?;
 
-                if index == length - 1 {
-                    *inferred_type = inferred_type.merge(expr.inferred_type());
-                }
+            Expr::Cond(pred, then, else_, current_inferred_type) => {
+                internal::handle_if_else(
+                    pred,
+                    then,
+                    else_,
+                    current_inferred_type,
+                    &mut inferred_type_stack,
+                );
+            }
+
+            Expr::PatternMatch(predicate, match_arms, current_inferred_type) => {
+                internal::handle_pattern_match(
+                    predicate,
+                    match_arms,
+                    current_inferred_type,
+                    &mut inferred_type_stack,
+                );
+            }
+
+            Expr::Concat(exprs, _) => {
+                internal::handle_concat(exprs, &mut inferred_type_stack);
+            }
+
+            Expr::Multiple(exprs, current_inferred_type) => {
+                internal::handle_multiple(exprs, current_inferred_type, &mut inferred_type_stack);
+            }
+
+            Expr::Not(_, current_inferred_type) => {
+                internal::handle_not(expr, current_inferred_type, &mut inferred_type_stack);
+            }
+
+            Expr::GreaterThan(left, right, current_inferred_type) => {
+                internal::handle_binary(
+                    left,
+                    right,
+                    current_inferred_type,
+                    &mut inferred_type_stack,
+                    Expr::GreaterThan,
+                );
+            }
+
+            Expr::GreaterThanOrEqualTo(left, right, current_inferred_type) => {
+                internal::handle_binary(
+                    left,
+                    right,
+                    current_inferred_type,
+                    &mut inferred_type_stack,
+                    Expr::GreaterThanOrEqualTo,
+                );
+            }
+
+            Expr::LessThanOrEqualTo(left, right, current_inferred_type) => {
+                internal::handle_binary(
+                    left,
+                    right,
+                    current_inferred_type,
+                    &mut inferred_type_stack,
+                    Expr::LessThanOrEqualTo,
+                );
+            }
+
+            Expr::EqualTo(left, right, current_inferred_type) => {
+                internal::handle_binary(
+                    left,
+                    right,
+                    current_inferred_type,
+                    &mut inferred_type_stack,
+                    Expr::EqualTo,
+                );
+            }
+
+            Expr::LessThan(left, right, current_inferred_type) => {
+                internal::handle_binary(
+                    left,
+                    right,
+                    current_inferred_type,
+                    &mut inferred_type_stack,
+                    Expr::LessThan,
+                );
+            }
+
+            Expr::Let(variable_id, typ, expr, inferred_type) => {
+                internal::handle_let(
+                    variable_id,
+                    expr,
+                    typ,
+                    inferred_type,
+                    &mut inferred_type_stack,
+                );
+            }
+            Expr::Sequence(exprs, current_inferred_type) => {
+                internal::handle_sequence(exprs, current_inferred_type, &mut inferred_type_stack);
+            }
+            Expr::Record(expr, inferred_type) => {
+                internal::handle_record(expr, inferred_type, &mut inferred_type_stack);
+            }
+            Expr::Literal(_, _) => {
+                inferred_type_stack.push_front(expr.clone());
+            }
+            Expr::Number(_, _, _) => {
+                inferred_type_stack.push_front(expr.clone());
+            }
+            Expr::Boolean(_, _) => {
+                inferred_type_stack.push_front(expr.clone());
+            }
+            Expr::And(left, right, _) => {
+                internal::handle_binary(
+                    left,
+                    right,
+                    &InferredType::Bool,
+                    &mut inferred_type_stack,
+                    Expr::And,
+                );
+            }
+
+            Expr::Or(left, right, _) => {
+                internal::handle_binary(
+                    left,
+                    right,
+                    &InferredType::Bool,
+                    &mut inferred_type_stack,
+                    Expr::Or,
+                );
+            }
+
+            Expr::Call(call_type, exprs, inferred_type) => {
+                internal::handle_call(call_type, exprs, inferred_type, &mut inferred_type_stack);
+            }
+
+            Expr::Unwrap(expr, inferred_type) => {
+                internal::handle_unwrap(expr, inferred_type, &mut inferred_type_stack);
+            }
+
+            Expr::Throw(_, _) => {
+                inferred_type_stack.push_front(expr.clone());
+            }
+
+            Expr::GetTag(_, inferred_type) => {
+                internal::handle_get_tag(expr, inferred_type, &mut inferred_type_stack);
             }
         }
-        Expr::Not(expr, _) => expr.pull_types_up()?,
-        Expr::GreaterThan(left, right, _) => {
-            left.pull_types_up()?;
-            right.pull_types_up()?;
+    }
+
+    inferred_type_stack
+        .pop_front()
+        .ok_or("Failed type inference during pull up".to_string())
+}
+
+mod internal {
+    use crate::call_type::CallType;
+
+    use crate::type_refinement::precise_types::{ListType, RecordType};
+    use crate::type_refinement::TypeRefinement;
+    use crate::{Expr, InferredType, MatchArm, VariableId};
+    use std::collections::VecDeque;
+    use std::ops::Deref;
+
+    pub(crate) fn make_expr_nodes_queue<'a>(expr: &'a Expr, expr_queue: &mut VecDeque<&'a Expr>) {
+        let mut stack = VecDeque::new();
+
+        stack.push_back(expr);
+
+        while let Some(current_expr) = stack.pop_back() {
+            expr_queue.push_back(current_expr);
+
+            current_expr.visit_children_bottom_up(&mut stack)
+        }
+    }
+
+    pub(crate) fn handle_tuple(
+        tuple_elems: &[Expr],
+        current_tuple_type: &InferredType,
+        inferred_type_stack: &mut VecDeque<Expr>,
+    ) {
+        let mut new_tuple_elems = vec![];
+
+        for current_tuple_elem in tuple_elems.iter().rev() {
+            let pulled_up_type = inferred_type_stack.pop_front();
+            let new_tuple_elem = pulled_up_type.unwrap_or(current_tuple_elem.clone());
+            new_tuple_elems.push(new_tuple_elem);
         }
-        Expr::GreaterThanOrEqualTo(left, right, _) => {
-            left.pull_types_up()?;
-            right.pull_types_up()?;
+
+        new_tuple_elems.reverse();
+
+        let new_tuple_type =
+            InferredType::Tuple(new_tuple_elems.iter().map(|x| x.inferred_type()).collect());
+
+        let merged_tuple_type = current_tuple_type.merge(new_tuple_type);
+        let new_tuple = Expr::Tuple(new_tuple_elems, merged_tuple_type);
+        inferred_type_stack.push_front(new_tuple);
+    }
+
+    pub(crate) fn handle_select_field(
+        original_selection_expr: &Expr,
+        field: &str,
+        current_field_type: &InferredType,
+        inferred_type_stack: &mut VecDeque<Expr>,
+    ) -> Result<(), String> {
+        let expr = inferred_type_stack
+            .pop_front()
+            .unwrap_or(original_selection_expr.clone());
+        let select_from_expr_type = expr.inferred_type();
+        let selection_field_type =
+            get_inferred_type_of_selected_field(field, &select_from_expr_type)?;
+
+        let new_select_field = Expr::SelectField(
+            Box::new(expr.clone()),
+            field.to_string(),
+            current_field_type.merge(selection_field_type),
+        );
+
+        inferred_type_stack.push_front(new_select_field);
+
+        Ok(())
+    }
+
+    pub fn handle_select_index(
+        original_selection_expr: &Expr,
+        index: &usize,
+        current_index_type: &InferredType,
+        inferred_type_stack: &mut VecDeque<Expr>,
+    ) -> Result<(), String> {
+        let expr = inferred_type_stack
+            .pop_front()
+            .unwrap_or(original_selection_expr.clone());
+        let inferred_type_of_selection_expr = expr.inferred_type();
+        let list_type =
+            get_inferred_type_of_selection_index(*index, &inferred_type_of_selection_expr)?;
+        let new_select_index = Expr::SelectIndex(
+            Box::new(expr.clone()),
+            *index,
+            current_index_type.merge(list_type),
+        );
+        inferred_type_stack.push_front(new_select_index);
+
+        Ok(())
+    }
+
+    pub(crate) fn handle_result_ok(
+        original_ok_expr: &Expr,
+        current_ok_type: &InferredType,
+        inferred_type_stack: &mut VecDeque<Expr>,
+    ) {
+        let ok_expr = inferred_type_stack
+            .pop_front()
+            .unwrap_or(original_ok_expr.clone());
+        let inferred_type_of_ok_expr = ok_expr.inferred_type();
+        let result_type = InferredType::Result {
+            ok: Some(Box::new(inferred_type_of_ok_expr)),
+            error: None,
+        };
+        let new_result = Expr::Result(
+            Ok(Box::new(ok_expr.clone())),
+            current_ok_type.merge(result_type),
+        );
+        inferred_type_stack.push_front(new_result);
+    }
+
+    pub(crate) fn handle_result_error(
+        original_error_expr: &Expr,
+        current_error_type: &InferredType,
+        inferred_type_stack: &mut VecDeque<Expr>,
+    ) {
+        let expr = inferred_type_stack
+            .pop_front()
+            .unwrap_or(original_error_expr.clone());
+        let inferred_type_of_error_expr = expr.inferred_type();
+        let result_type = InferredType::Result {
+            ok: None,
+            error: Some(Box::new(inferred_type_of_error_expr)),
+        };
+        let new_result = Expr::Result(
+            Err(Box::new(expr.clone())),
+            current_error_type.merge(result_type),
+        );
+        inferred_type_stack.push_front(new_result);
+    }
+
+    pub(crate) fn handle_option_some(
+        original_some_expr: &Expr,
+        current_some_type: &InferredType,
+        inferred_type_stack: &mut VecDeque<Expr>,
+    ) {
+        let expr = inferred_type_stack
+            .pop_front()
+            .unwrap_or(original_some_expr.clone());
+        let inferred_type_of_some_expr = expr.inferred_type();
+        let option_type = InferredType::Option(Box::new(inferred_type_of_some_expr));
+        let new_option = Expr::Option(
+            Some(Box::new(expr.clone())),
+            current_some_type.merge(option_type),
+        );
+        inferred_type_stack.push_front(new_option);
+    }
+
+    pub(crate) fn handle_if_else(
+        original_predicate: &Expr,
+        original_then_expr: &Expr,
+        original_else_expr: &Expr,
+        current_inferred_type: &InferredType,
+        inferred_type_stack: &mut VecDeque<Expr>,
+    ) {
+        let else_expr = inferred_type_stack
+            .pop_front()
+            .unwrap_or(original_else_expr.clone());
+        let then_expr = inferred_type_stack
+            .pop_front()
+            .unwrap_or(original_then_expr.clone());
+        let cond_expr = inferred_type_stack
+            .pop_front()
+            .unwrap_or(original_predicate.clone());
+        let inferred_type_of_then_expr = then_expr.inferred_type();
+        let inferred_type_of_else_expr = else_expr.inferred_type();
+
+        let new_type = current_inferred_type
+            .merge(inferred_type_of_then_expr.merge(inferred_type_of_else_expr));
+
+        let new_expr = Expr::Cond(
+            Box::new(cond_expr),
+            Box::new(then_expr.clone()),
+            Box::new(else_expr.clone()),
+            new_type,
+        );
+
+        inferred_type_stack.push_front(new_expr);
+    }
+
+    pub fn handle_pattern_match(
+        predicate: &Expr,
+        current_match_arms: &[MatchArm],
+        current_inferred_type: &InferredType,
+        inferred_type_stack: &mut VecDeque<Expr>,
+    ) {
+        let mut new_resolutions = vec![];
+        let mut new_arm_patterns = vec![];
+        for un_inferred_match_arm in current_match_arms.iter().rev() {
+            let arm_resolution = inferred_type_stack
+                .pop_front()
+                .unwrap_or(un_inferred_match_arm.arm_resolution_expr.deref().clone());
+
+            let mut arm_pattern = un_inferred_match_arm.arm_pattern.clone();
+            let mut current_arm_pattern_exprs = arm_pattern.get_expr_literals_mut();
+
+            let mut new_arm_pattern_exprs = vec![];
+
+            for _ in &current_arm_pattern_exprs {
+                let arm_expr = inferred_type_stack.pop_front();
+                new_arm_pattern_exprs.push(arm_expr)
+            }
+            new_arm_pattern_exprs.reverse();
+
+            current_arm_pattern_exprs
+                .iter_mut()
+                .zip(new_arm_pattern_exprs.iter())
+                .for_each(|(arm_expr, new_expr_opt)| {
+                    if let Some(new_expr) = new_expr_opt {
+                        **arm_expr = Box::new(new_expr.clone());
+                    }
+                });
+
+            new_resolutions.push(arm_resolution);
+            new_arm_patterns.push(arm_pattern);
         }
-        Expr::LessThanOrEqualTo(left, right, _) => {
-            left.pull_types_up()?;
-            right.pull_types_up()?;
+
+        let inferred_types = new_resolutions
+            .iter()
+            .map(|expr| expr.inferred_type())
+            .collect::<Vec<_>>();
+
+        let new_inferred_type = InferredType::all_of(inferred_types);
+
+        let mut new_match_arms = new_arm_patterns
+            .iter()
+            .zip(new_resolutions.iter())
+            .map(|(arm_pattern, arm_resolution)| crate::MatchArm {
+                arm_pattern: arm_pattern.clone(),
+                arm_resolution_expr: Box::new(arm_resolution.clone()),
+            })
+            .collect::<Vec<_>>();
+
+        new_match_arms.reverse();
+
+        let new_type = if let Some(new_inferred_type) = new_inferred_type {
+            current_inferred_type.merge(new_inferred_type)
+        } else {
+            current_inferred_type.clone()
+        };
+
+        let pred = inferred_type_stack.pop_front().unwrap_or(predicate.clone());
+
+        let new_expr = Expr::PatternMatch(Box::new(pred.clone()), new_match_arms, new_type);
+
+        inferred_type_stack.push_front(new_expr);
+    }
+
+    pub(crate) fn handle_concat(exprs: &Vec<Expr>, inferred_type_stack: &mut VecDeque<Expr>) {
+        let mut new_exprs = vec![];
+        for expr in exprs {
+            let expr = inferred_type_stack.pop_front().unwrap_or(expr.clone());
+            new_exprs.push(expr);
         }
-        Expr::EqualTo(left, right, _) => {
-            left.pull_types_up()?;
-            right.pull_types_up()?;
+
+        new_exprs.reverse();
+
+        let new_concat = Expr::Concat(new_exprs, InferredType::Str);
+        inferred_type_stack.push_front(new_concat);
+    }
+
+    pub(crate) fn handle_multiple(
+        current_expr_list: &Vec<Expr>,
+        current_inferred_type: &InferredType,
+        inferred_type_stack: &mut VecDeque<Expr>,
+    ) {
+        let mut new_exprs = vec![];
+        for _ in current_expr_list {
+            let expr = inferred_type_stack.pop_front();
+            if let Some(expr) = expr {
+                new_exprs.push(expr);
+            } else {
+                break;
+            }
         }
-        Expr::LessThan(left, right, _) => {
-            left.pull_types_up()?;
-            right.pull_types_up()?;
+
+        new_exprs.reverse();
+
+        let new_inferred_type = if let Some(last_expr) = new_exprs.last() {
+            last_expr.inferred_type()
+        } else {
+            InferredType::Unknown
+        };
+
+        let new_multiple =
+            Expr::Multiple(new_exprs, current_inferred_type.merge(new_inferred_type));
+        inferred_type_stack.push_front(new_multiple);
+    }
+
+    pub(crate) fn handle_not(
+        original_not_expr: &Expr,
+        current_not_type: &InferredType,
+        inferred_type_stack: &mut VecDeque<Expr>,
+    ) {
+        let expr = inferred_type_stack
+            .pop_front()
+            .unwrap_or(original_not_expr.clone());
+        let new_not = Expr::Not(Box::new(expr), current_not_type.clone());
+        inferred_type_stack.push_front(new_not);
+    }
+
+    pub(crate) fn handle_binary<F>(
+        original_left_expr: &Expr,
+        original_right_expr: &Expr,
+        current_inferred_type: &InferredType,
+        inferred_type_stack: &mut VecDeque<Expr>,
+        f: F,
+    ) where
+        F: Fn(Box<Expr>, Box<Expr>, InferredType) -> Expr,
+    {
+        let right_expr = inferred_type_stack
+            .pop_front()
+            .unwrap_or(original_right_expr.clone());
+        let left_expr = inferred_type_stack
+            .pop_front()
+            .unwrap_or(original_left_expr.clone());
+        let new_binary = f(
+            Box::new(left_expr),
+            Box::new(right_expr),
+            current_inferred_type.clone(),
+        );
+        inferred_type_stack.push_front(new_binary);
+    }
+
+    pub(crate) fn handle_call(
+        call_type: &CallType,
+        arguments: &[Expr],
+        inferred_type: &InferredType,
+        inferred_type_stack: &mut VecDeque<Expr>,
+    ) {
+        let mut new_arg_exprs = vec![];
+
+        for expr in arguments.iter().rev() {
+            let expr = inferred_type_stack.pop_front().unwrap_or(expr.clone());
+            new_arg_exprs.push(expr);
         }
-        Expr::Call(_, exprs, _) => {
-            for expr in exprs {
-                expr.pull_types_up()?
+
+        new_arg_exprs.reverse();
+
+        match call_type {
+            CallType::Function(fun_name) => {
+                let mut function_name = fun_name.clone();
+
+                let resource_params = function_name.function.raw_resource_params_mut();
+
+                if let Some(resource_params) = resource_params {
+                    let mut new_resource_params = vec![];
+                    for expr in resource_params.iter().rev() {
+                        let expr = inferred_type_stack.pop_front().unwrap_or(expr.clone());
+                        new_resource_params.push(expr);
+                    }
+
+                    new_resource_params.reverse();
+
+                    resource_params
+                        .iter_mut()
+                        .zip(new_resource_params.iter())
+                        .for_each(|(param, new_expr)| {
+                            *param = new_expr.clone();
+                        });
+                }
+
+                let new_call = Expr::Call(
+                    CallType::Function(function_name),
+                    new_arg_exprs,
+                    inferred_type.clone(),
+                );
+                inferred_type_stack.push_front(new_call);
+            }
+
+            CallType::VariantConstructor(str) => {
+                let new_call = Expr::Call(
+                    CallType::VariantConstructor(str.clone()),
+                    new_arg_exprs,
+                    inferred_type.clone(),
+                );
+                inferred_type_stack.push_front(new_call);
+            }
+
+            CallType::EnumConstructor(str) => {
+                let new_call = Expr::Call(
+                    CallType::EnumConstructor(str.clone()),
+                    new_arg_exprs,
+                    inferred_type.clone(),
+                );
+                inferred_type_stack.push_front(new_call);
             }
         }
-        Expr::Unwrap(expr, _) => expr.pull_types_up()?,
-        Expr::And(left, right, _) => {
-            left.pull_types_up()?;
-            right.pull_types_up()?;
+    }
+
+    pub(crate) fn handle_unwrap(
+        expr: &Expr,
+        current_inferred_type: &InferredType,
+        inferred_type_stack: &mut VecDeque<Expr>,
+    ) {
+        let expr = inferred_type_stack.pop_front().unwrap_or(expr.clone());
+        let new_unwrap = Expr::Unwrap(
+            Box::new(expr.clone()),
+            current_inferred_type.merge(expr.inferred_type()),
+        );
+        inferred_type_stack.push_front(new_unwrap);
+    }
+
+    pub(crate) fn handle_get_tag(
+        expr: &Expr,
+        current_inferred_type: &InferredType,
+        inferred_type_stack: &mut VecDeque<Expr>,
+    ) {
+        let expr = inferred_type_stack.pop_front().unwrap_or(expr.clone());
+        let new_get_tag = Expr::GetTag(
+            Box::new(expr.clone()),
+            current_inferred_type.merge(expr.inferred_type()),
+        );
+        inferred_type_stack.push_front(new_get_tag);
+    }
+
+    pub(crate) fn handle_let(
+        original_variable_id: &VariableId,
+        original_expr: &Expr,
+        optional_type: &Option<crate::parser::type_name::TypeName>,
+        current_inferred_type: &InferredType,
+        inferred_type_stack: &mut VecDeque<Expr>,
+    ) {
+        let expr = inferred_type_stack
+            .pop_front()
+            .unwrap_or(original_expr.clone());
+        let new_let = Expr::Let(
+            original_variable_id.clone(),
+            optional_type.clone(),
+            Box::new(expr),
+            current_inferred_type.clone(),
+        );
+        inferred_type_stack.push_front(new_let);
+    }
+
+    pub(crate) fn handle_sequence(
+        current_expr_list: &[Expr],
+        current_inferred_type: &InferredType,
+        inferred_type_stack: &mut VecDeque<Expr>,
+    ) {
+        let mut new_exprs = vec![];
+
+        for expr in current_expr_list.iter().rev() {
+            let expr = inferred_type_stack.pop_front().unwrap_or(expr.clone());
+            new_exprs.push(expr);
         }
-        Expr::Throw(_, _) => {}
-        Expr::GetTag(expr, _) => expr.pull_types_up()?,
-        Expr::Option(None, _) => {}
+
+        new_exprs.reverse();
+
+        let new_sequence = {
+            if let Some(first_expr) = new_exprs.clone().first() {
+                Expr::Sequence(
+                    new_exprs,
+                    current_inferred_type
+                        .clone()
+                        .merge(InferredType::List(Box::new(first_expr.inferred_type()))),
+                )
+            } else {
+                Expr::Sequence(new_exprs, current_inferred_type.clone())
+            }
+        };
+
+        inferred_type_stack.push_front(new_sequence);
     }
 
-    Ok(())
-}
+    pub(crate) fn handle_record(
+        current_expr_list: &[(String, Box<Expr>)],
+        current_inferred_type: &InferredType,
+        inferred_type_stack: &mut VecDeque<Expr>,
+    ) {
+        let mut ordered_types = vec![];
+        let mut new_exprs = vec![];
 
-mod internal {
-    use crate::type_refinement::precise_types::{ListType, RecordType};
-    use crate::type_refinement::TypeRefinement;
-    use crate::{ArmPattern, InferredType};
+        for (field, expr) in current_expr_list.iter().rev() {
+            let expr: Expr = inferred_type_stack
+                .pop_front()
+                .unwrap_or(expr.deref().clone());
+            ordered_types.push((field.clone(), expr.inferred_type()));
+            new_exprs.push((field.clone(), Box::new(expr.clone())));
+        }
+
+        new_exprs.reverse();
+        ordered_types.reverse();
+
+        let new_record_type = InferredType::Record(ordered_types);
+
+        let merged_record_type = current_inferred_type.merge(new_record_type);
+
+        let new_record = Expr::Record(new_exprs.to_vec(), merged_record_type);
+        inferred_type_stack.push_front(new_record);
+    }
 
     pub(crate) fn get_inferred_type_of_selected_field(
         select_field: &str,
@@ -207,7 +728,7 @@ mod internal {
         Ok(refined_record.inner_type_by_field(select_field))
     }
 
-    pub(crate) fn get_inferred_type_of_selected_index(
+    pub(crate) fn get_inferred_type_of_selection_index(
         selected_index: usize,
         select_from_type: &InferredType,
     ) -> Result<InferredType, String> {
@@ -218,57 +739,25 @@ mod internal {
 
         Ok(refined_list.inner_type())
     }
-
-    pub(crate) fn pull_up_types_of_arm_pattern(arm_pattern: &mut ArmPattern) -> Result<(), String> {
-        match arm_pattern {
-            ArmPattern::WildCard => {}
-            ArmPattern::As(_, arms_patterns) => {
-                pull_up_types_of_arm_pattern(arms_patterns)?;
-            }
-            ArmPattern::Constructor(_, arm_patterns) => {
-                for arm_pattern in arm_patterns {
-                    pull_up_types_of_arm_pattern(arm_pattern)?;
-                }
-            }
-            ArmPattern::TupleConstructor(arm_patterns) => {
-                for arm_pattern in arm_patterns {
-                    pull_up_types_of_arm_pattern(arm_pattern)?;
-                }
-            }
-
-            ArmPattern::ListConstructor(arm_patterns) => {
-                for arm_pattern in arm_patterns {
-                    pull_up_types_of_arm_pattern(arm_pattern)?;
-                }
-            }
-
-            ArmPattern::RecordConstructor(fields) => {
-                for (_, arm_pattern) in fields {
-                    pull_up_types_of_arm_pattern(arm_pattern)?;
-                }
-            }
-
-            ArmPattern::Literal(expr) => {
-                expr.pull_types_up()?;
-            }
-        }
-
-        Ok(())
-    }
 }
 
 #[cfg(test)]
 mod type_pull_up_tests {
+    use crate::call_type::CallType;
     use crate::function_name::DynamicParsedFunctionName;
-    use crate::{ArmPattern, Expr, InferredType, Number};
+    use crate::DynamicParsedFunctionReference::IndexedResourceMethod;
+    use crate::ParsedFunctionSite::PackagedInterface;
+    use crate::{
+        ArmPattern, Expr, FunctionTypeRegistry, InferredType, MatchArm, Number, VariableId,
+    };
 
     #[test]
     pub fn test_pull_up_identifier() {
         let expr = "foo";
         let mut expr = Expr::from_text(expr).unwrap();
         expr.add_infer_type_mut(InferredType::Str);
-        expr.pull_types_up().unwrap();
-        assert_eq!(expr.inferred_type(), InferredType::Str);
+        let new_expr = expr.pull_types_up().unwrap();
+        assert_eq!(new_expr.inferred_type(), InferredType::Str);
     }
 
     #[test]
@@ -279,144 +768,274 @@ mod type_pull_up_tests {
                 InferredType::Record(vec![("bar".to_string(), InferredType::U64)]),
             )]));
         let select_expr = Expr::select_field(record_identifier, "foo");
-        let mut expr = Expr::select_field(select_expr, "bar");
-        expr.pull_types_up().unwrap();
-        assert_eq!(expr.inferred_type(), InferredType::U64);
+        let expr = Expr::select_field(select_expr, "bar");
+        let new_expr = expr.pull_types_up().unwrap();
+        assert_eq!(new_expr.inferred_type(), InferredType::U64);
     }
 
     #[test]
     pub fn test_pull_up_for_select_index() {
-        let expr =
+        let identifier =
             Expr::identifier("foo").add_infer_type(InferredType::List(Box::new(InferredType::U64)));
-        let mut expr = Expr::select_index(expr, 0);
-        expr.pull_types_up().unwrap();
-        assert_eq!(expr.inferred_type(), InferredType::U64);
+        let expr = Expr::select_index(identifier.clone(), 0);
+        let new_expr = expr.pull_types_up().unwrap();
+        let expected = Expr::select_index(identifier, 0).add_infer_type(InferredType::U64);
+        assert_eq!(new_expr, expected);
     }
 
     #[test]
     pub fn test_pull_up_for_sequence() {
-        let mut expr = Expr::Sequence(
-            vec![
-                Expr::Number(Number { value: 1f64 }, None, InferredType::U64),
-                Expr::Number(Number { value: 1f64 }, None, InferredType::U32),
-            ],
-            InferredType::Unknown,
-        );
-        expr.pull_types_up().unwrap();
+        let elems = vec![
+            Expr::Number(Number { value: 1f64 }, None, InferredType::U64),
+            Expr::Number(Number { value: 2f64 }, None, InferredType::U64),
+        ];
+
+        let expr = Expr::Sequence(elems.clone(), InferredType::Unknown);
+        let new_expr = expr.pull_types_up().unwrap();
+
         assert_eq!(
-            expr.inferred_type(),
-            InferredType::List(Box::new(InferredType::U64))
+            new_expr,
+            Expr::Sequence(elems, InferredType::List(Box::new(InferredType::U64)))
         );
     }
 
     #[test]
     pub fn test_pull_up_for_tuple() {
-        let mut expr = Expr::tuple(vec![
+        let expr = Expr::tuple(vec![
             Expr::literal("foo"),
             Expr::Number(Number { value: 1f64 }, None, InferredType::U64),
         ]);
-        expr.pull_types_up().unwrap();
+        let new_expr = expr.pull_types_up().unwrap();
         assert_eq!(
-            expr.inferred_type(),
+            new_expr.inferred_type(),
             InferredType::Tuple(vec![InferredType::Str, InferredType::U64])
         );
     }
 
     #[test]
     pub fn test_pull_up_for_record() {
-        let mut expr = Expr::Record(
-            vec![
-                (
-                    "foo".to_string(),
-                    Box::new(Expr::Number(
-                        Number { value: 1f64 },
-                        None,
-                        InferredType::U64,
-                    )),
-                ),
-                (
-                    "bar".to_string(),
-                    Box::new(Expr::Number(
-                        Number { value: 1f64 },
-                        None,
-                        InferredType::U64,
-                    )),
-                ),
-            ],
+        let elems = vec![
+            (
+                "foo".to_string(),
+                Box::new(Expr::Number(
+                    Number { value: 1f64 },
+                    None,
+                    InferredType::U64,
+                )),
+            ),
+            (
+                "bar".to_string(),
+                Box::new(Expr::Number(
+                    Number { value: 2f64 },
+                    None,
+                    InferredType::U32,
+                )),
+            ),
+        ];
+        let expr = Expr::Record(
+            elems.clone(),
             InferredType::Record(vec![
                 ("foo".to_string(), InferredType::Unknown),
                 ("bar".to_string(), InferredType::Unknown),
             ]),
         );
-        expr.pull_types_up().unwrap();
+        let new_expr = expr.pull_types_up().unwrap();
 
         assert_eq!(
-            expr.inferred_type(),
-            InferredType::AllOf(vec![
-                InferredType::Record(vec![
-                    ("foo".to_string(), InferredType::U64),
-                    ("bar".to_string(), InferredType::U64)
-                ]),
-                InferredType::Record(vec![
-                    ("foo".to_string(), InferredType::Unknown),
-                    ("bar".to_string(), InferredType::Unknown)
+            new_expr,
+            Expr::Record(
+                elems,
+                InferredType::AllOf(vec![
+                    InferredType::Record(vec![
+                        ("foo".to_string(), InferredType::U64),
+                        ("bar".to_string(), InferredType::U32)
+                    ]),
+                    InferredType::Record(vec![
+                        ("foo".to_string(), InferredType::Unknown),
+                        ("bar".to_string(), InferredType::Unknown)
+                    ])
                 ])
-            ])
+            )
         );
     }
 
     #[test]
     pub fn test_pull_up_for_concat() {
-        let mut expr = Expr::concat(vec![Expr::number(1f64), Expr::number(2f64)]);
-        expr.pull_types_up().unwrap();
-        assert_eq!(expr.inferred_type(), InferredType::Str);
+        let expr = Expr::concat(vec![Expr::literal("foo"), Expr::literal("bar")]);
+        let new_expr = expr.pull_types_up().unwrap();
+        let expected = Expr::Concat(
+            vec![Expr::literal("foo"), Expr::literal("bar")],
+            InferredType::Str,
+        );
+        assert_eq!(new_expr, expected);
     }
 
     #[test]
     pub fn test_pull_up_for_not() {
-        let mut expr = Expr::not(Expr::boolean(true));
-        expr.pull_types_up().unwrap();
-        assert_eq!(expr.inferred_type(), InferredType::Bool);
+        let expr = Expr::not(Expr::boolean(true));
+        let new_expr = expr.pull_types_up().unwrap();
+        assert_eq!(new_expr.inferred_type(), InferredType::Bool);
+    }
+
+    #[test]
+    pub fn test_pull_up_if_else() {
+        let inner1 =
+            Expr::identifier("foo").add_infer_type(InferredType::List(Box::new(InferredType::U64)));
+
+        let select_index1 = Expr::select_index(inner1.clone(), 0);
+        let select_index2 = Expr::select_index(inner1, 1);
+
+        let inner2 =
+            Expr::identifier("bar").add_infer_type(InferredType::List(Box::new(InferredType::U64)));
+
+        let select_index3 = Expr::select_index(inner2.clone(), 0);
+        let select_index4 = Expr::select_index(inner2, 1);
+
+        let expr = Expr::cond(
+            Expr::greater_than(select_index1.clone(), select_index2.clone()),
+            select_index3.clone(),
+            select_index4.clone(),
+        );
+
+        let new_expr = expr.pull_types_up().unwrap();
+        let expected = Expr::Cond(
+            Box::new(Expr::GreaterThan(
+                Box::new(Expr::SelectIndex(
+                    Box::new(Expr::Identifier(
+                        VariableId::global("foo".to_string()),
+                        InferredType::List(Box::new(InferredType::U64)),
+                    )),
+                    0,
+                    InferredType::U64,
+                )),
+                Box::new(Expr::SelectIndex(
+                    Box::new(Expr::Identifier(
+                        VariableId::global("foo".to_string()),
+                        InferredType::List(Box::new(InferredType::U64)),
+                    )),
+                    1,
+                    InferredType::U64,
+                )),
+                InferredType::Bool,
+            )),
+            Box::new(Expr::SelectIndex(
+                Box::new(Expr::Identifier(
+                    VariableId::global("bar".to_string()),
+                    InferredType::List(Box::new(InferredType::U64)),
+                )),
+                0,
+                InferredType::U64,
+            )),
+            Box::new(Expr::SelectIndex(
+                Box::new(Expr::Identifier(
+                    VariableId::global("bar".to_string()),
+                    InferredType::List(Box::new(InferredType::U64)),
+                )),
+                1,
+                InferredType::U64,
+            )),
+            InferredType::U64,
+        );
+        assert_eq!(new_expr, expected);
     }
 
     #[test]
     pub fn test_pull_up_for_greater_than() {
-        let mut expr = Expr::greater_than(Expr::number(1f64), Expr::number(2f64));
-        expr.pull_types_up().unwrap();
-        assert_eq!(expr.inferred_type(), InferredType::Bool);
+        let inner = Expr::identifier("foo").add_infer_type(InferredType::Record(vec![
+            ("bar".to_string(), InferredType::Str),
+            ("baz".to_string(), InferredType::U64),
+        ]));
+
+        let select_field1 = Expr::select_field(inner.clone(), "bar");
+        let select_field2 = Expr::select_field(inner, "baz");
+        let expr = Expr::greater_than(select_field1.clone(), select_field2.clone());
+
+        let new_expr = expr.pull_types_up().unwrap();
+
+        let expected = Expr::greater_than(
+            select_field1.add_infer_type(InferredType::Str),
+            select_field2.add_infer_type(InferredType::U64),
+        )
+        .add_infer_type(InferredType::Bool);
+        assert_eq!(new_expr, expected);
     }
 
     #[test]
     pub fn test_pull_up_for_greater_than_or_equal_to() {
-        let mut expr = Expr::greater_than_or_equal_to(Expr::number(1f64), Expr::number(2f64));
-        expr.pull_types_up().unwrap();
-        assert_eq!(expr.inferred_type(), InferredType::Bool);
+        let inner =
+            Expr::identifier("foo").add_infer_type(InferredType::List(Box::new(InferredType::U64)));
+
+        let select_index1 = Expr::select_index(inner.clone(), 0);
+        let select_index2 = Expr::select_index(inner, 1);
+        let expr = Expr::greater_than_or_equal_to(select_index1.clone(), select_index2.clone());
+
+        let new_expr = expr.pull_types_up().unwrap();
+
+        let expected = Expr::greater_than_or_equal_to(
+            select_index1.add_infer_type(InferredType::U64),
+            select_index2.add_infer_type(InferredType::U64),
+        )
+        .add_infer_type(InferredType::Bool);
+        assert_eq!(new_expr, expected);
     }
 
     #[test]
     pub fn test_pull_up_for_less_than_or_equal_to() {
-        let mut expr = Expr::less_than_or_equal_to(Expr::number(1f64), Expr::number(2f64));
-        expr.pull_types_up().unwrap();
-        assert_eq!(expr.inferred_type(), InferredType::Bool);
+        let record_type = InferredType::Record(vec![
+            ("bar".to_string(), InferredType::Str),
+            ("baz".to_string(), InferredType::U64),
+        ]);
+
+        let inner = Expr::identifier("foo")
+            .add_infer_type(InferredType::List(Box::new(record_type.clone())));
+
+        let select_field_from_first =
+            Expr::select_field(Expr::select_index(inner.clone(), 0), "bar");
+        let select_field_from_second =
+            Expr::select_field(Expr::select_index(inner.clone(), 1), "baz");
+        let expr = Expr::less_than_or_equal_to(
+            select_field_from_first.clone(),
+            select_field_from_second.clone(),
+        );
+
+        let new_expr = expr.pull_types_up().unwrap();
+
+        let new_select_field_from_first = Expr::select_field(
+            Expr::select_index(inner.clone(), 0).add_infer_type(record_type.clone()),
+            "bar",
+        )
+        .add_infer_type(InferredType::Str);
+
+        let new_select_field_from_second = Expr::select_field(
+            Expr::select_index(inner.clone(), 1).add_infer_type(record_type),
+            "baz",
+        )
+        .add_infer_type(InferredType::U64);
+
+        let expected =
+            Expr::less_than_or_equal_to(new_select_field_from_first, new_select_field_from_second)
+                .add_infer_type(InferredType::Bool);
+
+        assert_eq!(new_expr, expected);
     }
 
     #[test]
     pub fn test_pull_up_for_equal_to() {
-        let mut expr = Expr::equal_to(Expr::number(1f64), Expr::number(2f64));
-        expr.pull_types_up().unwrap();
-        assert_eq!(expr.inferred_type(), InferredType::Bool);
+        let expr = Expr::equal_to(Expr::number(1f64), Expr::number(2f64));
+        let new_expr = expr.pull_types_up().unwrap();
+        assert_eq!(new_expr.inferred_type(), InferredType::Bool);
     }
 
     #[test]
     pub fn test_pull_up_for_less_than() {
-        let mut expr = Expr::less_than(Expr::number(1f64), Expr::number(2f64));
-        expr.pull_types_up().unwrap();
-        assert_eq!(expr.inferred_type(), InferredType::Bool);
+        let expr = Expr::less_than(Expr::number(1f64), Expr::number(2f64));
+        let new_expr = expr.pull_types_up().unwrap();
+        assert_eq!(new_expr.inferred_type(), InferredType::Bool);
     }
 
     #[test]
     pub fn test_pull_up_for_call() {
-        let mut expr = Expr::call(
+        let expr = Expr::call(
             DynamicParsedFunctionName::parse("global_fn").unwrap(),
             vec![Expr::number(1f64)],
         );
@@ -424,52 +1043,229 @@ mod type_pull_up_tests {
         assert_eq!(expr.inferred_type(), InferredType::Unknown);
     }
 
+    #[test]
+    pub fn test_pull_up_for_dynamic_call() {
+        let rib = r#"
+           let input = { foo: "afs", bar: "al" };
+           golem:it/api.{cart(input.foo).checkout}()
+        "#;
+
+        let mut expr = Expr::from_text(rib).unwrap();
+        let function_registry = FunctionTypeRegistry::empty();
+        expr.infer_types_initial_phase(&function_registry).unwrap();
+        expr.infer_all_identifiers().unwrap();
+        let new_expr = expr.pull_types_up().unwrap();
+
+        let expected = Expr::Multiple(
+            vec![
+                Expr::Let(
+                    VariableId::local("input", 0),
+                    None,
+                    Box::new(Expr::Record(
+                        vec![
+                            (
+                                "foo".to_string(),
+                                Box::new(Expr::Literal("afs".to_string(), InferredType::Str)),
+                            ),
+                            (
+                                "bar".to_string(),
+                                Box::new(Expr::Literal("al".to_string(), InferredType::Str)),
+                            ),
+                        ],
+                        InferredType::Record(vec![
+                            ("foo".to_string(), InferredType::Str),
+                            ("bar".to_string(), InferredType::Str),
+                        ]),
+                    )),
+                    InferredType::Unknown,
+                ),
+                Expr::Call(
+                    CallType::Function(DynamicParsedFunctionName {
+                        site: PackagedInterface {
+                            namespace: "golem".to_string(),
+                            package: "it".to_string(),
+                            interface: "api".to_string(),
+                            version: None,
+                        },
+                        function: IndexedResourceMethod {
+                            resource: "cart".to_string(),
+                            resource_params: vec![Expr::SelectField(
+                                Box::new(Expr::Identifier(
+                                    VariableId::local("input", 0),
+                                    InferredType::Record(vec![
+                                        ("foo".to_string(), InferredType::Str),
+                                        ("bar".to_string(), InferredType::Str),
+                                    ]),
+                                )),
+                                "foo".to_string(),
+                                InferredType::Str,
+                            )],
+                            method: "checkout".to_string(),
+                        },
+                    }),
+                    vec![],
+                    InferredType::Unknown,
+                ),
+            ],
+            InferredType::Unknown,
+        );
+
+        assert_eq!(new_expr, expected);
+    }
+
     #[test]
     pub fn test_pull_up_for_unwrap() {
-        let mut expr = Expr::option(Some(Expr::number(1f64))).unwrap();
-        expr.pull_types_up().unwrap();
-        assert_eq!(expr.inferred_type(), InferredType::Unknown);
+        let mut number = Expr::number(1f64);
+        number.override_type_type_mut(InferredType::F64);
+        let expr = Expr::option(Some(number)).unwrap();
+        let expr = expr.pull_types_up().unwrap();
+        assert_eq!(
+            expr.inferred_type(),
+            InferredType::Option(Box::new(InferredType::F64))
+        );
     }
 
     #[test]
     pub fn test_pull_up_for_tag() {
-        let mut expr = Expr::tag(Expr::number(1f64));
-        expr.pull_types_up().unwrap();
-        assert_eq!(expr.inferred_type(), InferredType::Unknown);
+        let mut number = Expr::number(1f64);
+        number.override_type_type_mut(InferredType::F64);
+        let expr = Expr::get_tag(Expr::option(Some(number)));
+        let expr = expr.pull_types_up().unwrap();
+        assert_eq!(
+            expr.inferred_type(),
+            InferredType::Option(Box::new(InferredType::F64))
+        );
     }
 
     #[test]
     pub fn test_pull_up_for_pattern_match() {
-        let mut expr = Expr::pattern_match(
-            Expr::number(1f64),
+        let expr = Expr::pattern_match(
+            Expr::select_field(
+                Expr::identifier("foo").add_infer_type(InferredType::Record(vec![(
+                    "bar".to_string(),
+                    InferredType::Str,
+                )])),
+                "bar",
+            ),
             vec![
-                crate::MatchArm {
-                    arm_pattern: ArmPattern::Literal(Box::new(Expr::Number(
-                        Number { value: 1f64 },
-                        None,
-                        InferredType::U64,
-                    ))),
-                    arm_resolution_expr: Box::new(Expr::Number(
-                        Number { value: 1f64 },
-                        None,
-                        InferredType::U64,
+                MatchArm {
+                    arm_pattern: ArmPattern::Constructor(
+                        "cons1".to_string(),
+                        vec![ArmPattern::Literal(Box::new(Expr::SelectField(
+                            Box::new(Expr::identifier("foo").add_infer_type(InferredType::Record(
+                                vec![("bar".to_string(), InferredType::Str)],
+                            ))),
+                            "bar".to_string(),
+                            InferredType::Unknown,
+                        )))],
+                    ),
+                    arm_resolution_expr: Box::new(Expr::SelectField(
+                        Box::new(Expr::identifier("baz").add_infer_type(InferredType::Record(
+                            vec![("qux".to_string(), InferredType::Str)],
+                        ))),
+                        "qux".to_string(),
+                        InferredType::Unknown,
                     )),
                 },
-                crate::MatchArm {
-                    arm_pattern: ArmPattern::Literal(Box::new(Expr::Number(
-                        Number { value: 2f64 },
-                        None,
-                        InferredType::U64,
-                    ))),
-                    arm_resolution_expr: Box::new(Expr::Number(
-                        Number { value: 2f64 },
-                        None,
-                        InferredType::U64,
+                MatchArm {
+                    arm_pattern: ArmPattern::Constructor(
+                        "cons2".to_string(),
+                        vec![ArmPattern::Literal(Box::new(Expr::SelectField(
+                            Box::new(Expr::identifier("quux").add_infer_type(
+                                InferredType::Record(vec![(
+                                    "corge".to_string(),
+                                    InferredType::Str,
+                                )]),
+                            )),
+                            "corge".to_string(),
+                            InferredType::Unknown,
+                        )))],
+                    ),
+                    arm_resolution_expr: Box::new(Expr::SelectField(
+                        Box::new(
+                            Expr::identifier("grault").add_infer_type(InferredType::Record(vec![
+                                ("garply".to_string(), InferredType::Str),
+                            ])),
+                        ),
+                        "garply".to_string(),
+                        InferredType::Unknown,
                     )),
                 },
             ],
         );
-        expr.pull_types_up().unwrap();
-        assert_eq!(expr.inferred_type(), InferredType::U64);
+        let new_expr = expr.pull_types_up().unwrap();
+        let expected = internal::expected_pattern_match();
+        assert_eq!(new_expr, expected);
+    }
+
+    mod internal {
+        use crate::{ArmPattern, Expr, InferredType, MatchArm, VariableId};
+
+        pub(crate) fn expected_pattern_match() -> Expr {
+            Expr::PatternMatch(
+                Box::new(Expr::SelectField(
+                    Box::new(Expr::Identifier(
+                        VariableId::global("foo".to_string()),
+                        InferredType::Record(vec![("bar".to_string(), InferredType::Str)]),
+                    )),
+                    "bar".to_string(),
+                    InferredType::Str,
+                )),
+                vec![
+                    MatchArm {
+                        arm_pattern: ArmPattern::Constructor(
+                            "cons1".to_string(),
+                            vec![ArmPattern::Literal(Box::new(Expr::SelectField(
+                                Box::new(Expr::Identifier(
+                                    VariableId::global("foo".to_string()),
+                                    InferredType::Record(vec![(
+                                        "bar".to_string(),
+                                        InferredType::Str,
+                                    )]),
+                                )),
+                                "bar".to_string(),
+                                InferredType::Str,
+                            )))],
+                        ),
+                        arm_resolution_expr: Box::new(Expr::SelectField(
+                            Box::new(Expr::Identifier(
+                                VariableId::global("baz".to_string()),
+                                InferredType::Record(vec![("qux".to_string(), InferredType::Str)]),
+                            )),
+                            "qux".to_string(),
+                            InferredType::Str,
+                        )),
+                    },
+                    MatchArm {
+                        arm_pattern: ArmPattern::Constructor(
+                            "cons2".to_string(),
+                            vec![ArmPattern::Literal(Box::new(Expr::SelectField(
+                                Box::new(Expr::Identifier(
+                                    VariableId::global("quux".to_string()),
+                                    InferredType::Record(vec![(
+                                        "corge".to_string(),
+                                        InferredType::Str,
+                                    )]),
+                                )),
+                                "corge".to_string(),
+                                InferredType::Str,
+                            )))],
+                        ),
+                        arm_resolution_expr: Box::new(Expr::SelectField(
+                            Box::new(Expr::Identifier(
+                                VariableId::global("grault".to_string()),
+                                InferredType::Record(vec![(
+                                    "garply".to_string(),
+                                    InferredType::Str,
+                                )]),
+                            )),
+                            "garply".to_string(),
+                            InferredType::Str,
+                        )),
+                    },
+                ],
+                InferredType::Str,
+            )
+        }
     }
 }
diff --git a/golem-rib/src/type_inference/type_unification.rs b/golem-rib/src/type_inference/type_unification.rs
index b0912564c0..76d30bc64e 100644
--- a/golem-rib/src/type_inference/type_unification.rs
+++ b/golem-rib/src/type_inference/type_unification.rs
@@ -268,10 +268,6 @@ pub fn unify_types(expr: &mut Expr) -> Result<(), Vec<String>> {
                 match unified_inferred_type {
                     Ok(unified_type) => *inferred_type = unified_type,
                     Err(e) => {
-                        errors.push(format!(
-                            "Unable to resolve the type of code block {}",
-                            expr_str
-                        ));
                         errors.extend(e);
                     }
                 }
@@ -334,6 +330,11 @@ pub fn unify_types(expr: &mut Expr) -> Result<(), Vec<String>> {
                 queue.push(left);
                 queue.push(right);
             }
+            Expr::Or(left, right, _) => {
+                queue.push(left);
+                queue.push(right);
+            }
+
             Expr::GreaterThanOrEqualTo(left, right, _) => {
                 queue.push(left);
                 queue.push(right);
diff --git a/golem-worker-service-base/src/api_definition/http/http_api_definition.rs b/golem-worker-service-base/src/api_definition/http/http_api_definition.rs
index b374f005cc..f163b087bc 100644
--- a/golem-worker-service-base/src/api_definition/http/http_api_definition.rs
+++ b/golem-worker-service-base/src/api_definition/http/http_api_definition.rs
@@ -682,7 +682,6 @@ mod tests {
             let yaml = get_api_spec(path_pattern, worker_id, response_mapping);
             let original: HttpApiDefinition = serde_yaml::from_value(yaml.clone()).unwrap();
 
-            dbg!(original.clone());
             let proto: grpc_apidefinition::ApiDefinition = original.clone().try_into().unwrap();
             let decoded: HttpApiDefinition = proto.try_into().unwrap();
             assert_eq!(original, decoded);