Repository: microsoft/qsharp
Pull request #1508 (2024-05-10 21:39:51)

MathJax kata preview fixes
This fixes an issue with `\braket` where it was doubling up the entries. The preview today shows:

<img width="782" alt="image" src="https://github.com/microsoft/qsharp/assets/993909/4adcfbd9-6660-42f6-8943-623d7e0d488a">

The fix was to replace physics with braket package. (Not sure why, will log a MathJax bug for that also).

The below two items I was playing with a week ago, but including here:

- Made the page render one kata at a time, and supports linking to a kata via the URL and forward/back navigation between katas without a page reload. (As on slow machines putting every kata on the one page was too slow)
- Converted to Preact to match the rest of our code, instead of manipulating DOM elements directly.


Patch:
diff --git a/compiler/qsc_eval/src/state.rs b/compiler/qsc_eval/src/state.rs
index 6befc095..6e69c071 100644
--- a/compiler/qsc_eval/src/state.rs
+++ b/compiler/qsc_eval/src/state.rs
@@ -342,12 +342,12 @@ fn get_terms_for_state(state: &Vec<(BigUint, Complex64)>) -> Vec<Term> {
 }
 
 /// Get the state represented as a formula in the LaTeX format if possible.
-/// Empty string is returned if the resulting formula is not nice, i.e.
+/// `None` is returned if the resulting formula is not nice, i.e.
 /// if the formula consists of more than 16 terms or if more than two coefficients are not recognized.
 #[must_use]
-pub fn get_latex(state: &Vec<(BigUint, Complex64)>, qubit_count: usize) -> String {
+pub fn get_latex(state: &Vec<(BigUint, Complex64)>, qubit_count: usize) -> Option<String> {
     if state.len() > 16 {
-        return String::new();
+        return None;
     }
 
     let terms: Vec<Term> = get_terms_for_state(state);
@@ -361,7 +361,7 @@ pub fn get_latex(state: &Vec<(BigUint, Complex64)>, qubit_count: usize) -> Strin
                 bad_term_count += 1;
             };
             if bad_term_count > 2 {
-                return String::new();
+                return None;
             }
         }
     }
@@ -378,7 +378,7 @@ pub fn get_latex(state: &Vec<(BigUint, Complex64)>, qubit_count: usize) -> Strin
     latex.push('$');
     latex.shrink_to_fit();
 
-    latex
+    Some(latex)
 }
 
 /// Write latex for one term of quantum state.
diff --git a/compiler/qsc_partial_eval/src/evaluation_context.rs b/compiler/qsc_partial_eval/src/evaluation_context.rs
index 38f67105..15aaf722 100644
--- a/compiler/qsc_partial_eval/src/evaluation_context.rs
+++ b/compiler/qsc_partial_eval/src/evaluation_context.rs
@@ -8,7 +8,7 @@ use qsc_eval::{
 };
 use qsc_fir::fir::{LocalItemId, LocalVarId, PackageId};
 use qsc_rca::{RuntimeKind, ValueKind};
-use qsc_rir::rir::BlockId;
+use qsc_rir::rir::{BlockId, Literal, VariableId};
 use rustc_hash::FxHashMap;
 use std::collections::hash_map::Entry;
 
@@ -96,8 +96,12 @@ pub struct Scope {
     pub args_value_kind: Vec<ValueKind>,
     /// The classical environment of the callable, which holds values corresponding to local variables.
     pub env: Env,
+    // Consider optimizing `hybrid_vars` and `mutable_vars` by removing them and enlightening the evaluator on how to
+    // properly handle `Value::Var`, which could be either `static` or `dynamic`.
     /// Map that holds the values of local variables.
-    pub hybrid_vars: FxHashMap<LocalVarId, Value>,
+    hybrid_vars: FxHashMap<LocalVarId, Value>,
+    /// Maps variable IDs to mutable variables, which contain their current kind.
+    mutable_vars: FxHashMap<VariableId, MutableVar>,
     /// Number of currently active blocks (starting from where this scope was created).
     active_block_count: usize,
 }
@@ -157,9 +161,20 @@ impl Scope {
             env,
             active_block_count: 1,
             hybrid_vars,
+            mutable_vars: FxHashMap::default(),
         }
     }
 
+    /// Gets a mutable variable.
+    pub fn find_mutable_var(&self, var_id: VariableId) -> Option<&MutableVar> {
+        self.mutable_vars.get(&var_id)
+    }
+
+    /// Gets a mutable mutable variable.
+    pub fn find_mutable_var_mut(&mut self, var_id: VariableId) -> Option<&mut MutableVar> {
+        self.mutable_vars.get_mut(&var_id)
+    }
+
     /// Gets the value of a hybrid local variable.
     pub fn get_classical_local_value(&self, local_var_id: LocalVarId) -> &Value {
         &self
@@ -176,6 +191,19 @@ impl Scope {
             .expect("local hybrid variable value does not exist")
     }
 
+    // Inserts a value in the hybrid vars map.
+    pub fn insert_hybrid_local_value(&mut self, local_var_id: LocalVarId, value: Value) {
+        self.hybrid_vars.insert(local_var_id, value);
+    }
+
+    // Insert a variable into the mutable variables map.
+    pub fn insert_mutable_var(&mut self, var_id: VariableId, mutable_var: MutableVar) {
+        let Entry::Vacant(vacant) = self.mutable_vars.entry(var_id) else {
+            panic!("mutable variable should not already exist");
+        };
+        vacant.insert(mutable_var);
+    }
+
     /// Determines whether we are currently evaluating a branch within the scope.
     pub fn is_currently_evaluating_branch(&self) -> bool {
         self.active_block_count > 1
@@ -289,3 +317,13 @@ fn map_eval_value_to_value_kind(value: &Value) -> ValueKind {
         | Value::String(_) => ValueKind::Element(RuntimeKind::Static),
     }
 }
+
+pub struct MutableVar {
+    pub id: LocalVarId,
+    pub kind: MutableKind,
+}
+
+pub enum MutableKind {
+    Static(Literal),
+    Dynamic,
+}
diff --git a/compiler/qsc_partial_eval/src/lib.rs b/compiler/qsc_partial_eval/src/lib.rs
index 608e50c2..3abf992a 100644
--- a/compiler/qsc_partial_eval/src/lib.rs
+++ b/compiler/qsc_partial_eval/src/lib.rs
@@ -9,7 +9,8 @@ mod evaluation_context;
 mod management;
 
 use evaluation_context::{
-    Arg, BlockNode, BranchControlFlow, EvalControlFlow, EvaluationContext, Scope,
+    Arg, BlockNode, BranchControlFlow, EvalControlFlow, EvaluationContext, MutableKind, MutableVar,
+    Scope,
 };
 use management::{QuantumIntrinsicsChecker, ResourceManager};
 use miette::Diagnostic;
@@ -182,15 +183,11 @@ impl<'a> PartialEvaluator<'a> {
         }
 
         // Always bind the value to the hybrid map but do it differently depending of the value type.
-        let maybe_var_type = try_get_eval_var_type(&value);
-        if let Some(var_type) = maybe_var_type {
-            // Get a variable to store into.
-            let value_operand = map_eval_value_to_rir_operand(&value);
-            let eval_var = self.get_or_create_variable(ident.id, var_type);
-            let rir_var = map_eval_var_to_rir_var(eval_var);
-            // Insert a store instruction.
-            let store_ins = Instruction::Store(value_operand, rir_var);
-            self.get_current_rir_block_mut().0.push(store_ins);
+        if let Some((var_id, mutable_var)) = self.try_create_mutable_variable(ident.id, &value) {
+            // Keep track of whether the mutable variable is static or dynamic.
+            self.eval_context
+                .get_current_scope_mut()
+                .insert_mutable_var(var_id, mutable_var);
         } else {
             self.bind_value_in_hybrid_map(ident, value);
         }
@@ -211,8 +208,7 @@ impl<'a> PartialEvaluator<'a> {
         // Insert the value into the hybrid vars map.
         self.eval_context
             .get_current_scope_mut()
-            .hybrid_vars
-            .insert(ident.id, value);
+            .insert_hybrid_local_value(ident.id, value);
     }
 
     fn create_intrinsic_callable(
@@ -287,8 +283,8 @@ impl<'a> PartialEvaluator<'a> {
         &mut self,
         bin_op: BinOp,
         lhs_value: Value,
-        lhs_span: Span,
         rhs_expr_id: ExprId,
+        lhs_span: Span,         // For diagnostic purposes only.
         bin_op_expr_span: Span, // For diagnostic purposes only.
     ) -> Result<EvalControlFlow, Error> {
         // Evaluate the binary operation differently depending on the LHS value variant.
@@ -299,26 +295,31 @@ impl<'a> PartialEvaluator<'a> {
                 rhs_expr_id,
                 bin_op_expr_span,
             ),
-            Value::Result(_lhs_result) => Err(Error::Unimplemented(
-                "result binary operation".to_string(),
-                lhs_span,
-            )),
-            Value::Bool(_lhs_bool) => Err(Error::Unimplemented(
-                "bool binary operation".to_string(),
-                lhs_span,
-            )),
-            Value::Int(_lhs_int) => Err(Error::Unimplemented(
-                "int binary operation".to_string(),
-                lhs_span,
-            )),
+            Value::Result(lhs_result) => self.eval_bin_op_with_lhs_result_operand(
+                bin_op,
+                lhs_result,
+                rhs_expr_id,
+                bin_op_expr_span,
+            ),
+            Value::Bool(lhs_bool) => {
+                self.eval_bin_op_with_lhs_classical_bool_operand(bin_op, lhs_bool, rhs_expr_id)
+            }
+            Value::Int(lhs_int) => {
+                let lhs_operand = Operand::Literal(Literal::Integer(lhs_int));
+                self.eval_bin_op_with_lhs_integer_operand(
+                    bin_op,
+                    lhs_operand,
+                    rhs_expr_id,
+                    bin_op_expr_span,
+                )
+            }
             Value::Double(_lhs_double) => Err(Error::Unimplemented(
                 "double binary operation".to_string(),
                 lhs_span,
             )),
-            Value::Var(_lhs_eval_var) => Err(Error::Unimplemented(
-                "binary operation with dynamic LHS".to_string(),
-                lhs_span,
-            )),
+            Value::Var(lhs_eval_var) => {
+                self.eval_bin_op_with_lhs_var(bin_op, lhs_eval_var, rhs_expr_id, bin_op_expr_span)
+            }
             _ => Err(Error::Unexpected(
                 format!("unsupported LHS value: {lhs_value}"),
                 lhs_span,
@@ -367,6 +368,234 @@ impl<'a> PartialEvaluator<'a> {
         Ok(EvalControlFlow::Continue(array_value))
     }
 
+    fn eval_bin_op_with_lhs_result_operand(
+        &mut self,
+        bin_op: BinOp,
+        lhs_result: val::Result,
+        rhs_expr_id: ExprId,
+        bin_op_expr_span: Span, // For diagnostic purposes only.
+    ) -> Result<EvalControlFlow, Error> {
+        let rhs_control_flow = self.try_eval_expr(rhs_expr_id)?;
+        let EvalControlFlow::Continue(rhs_value) = rhs_control_flow else {
+            let rhs_expr = self.get_expr(rhs_expr_id);
+            return Err(Error::Unexpected(
+                "embedded return in RHS expression".to_string(),
+                rhs_expr.span,
+            ));
+        };
+        let Value::Result(rhs_result) = rhs_value else {
+            panic!("expected result value from RHS expression");
+        };
+
+        // Get the operands to use when generating the binary operation instruction.
+        let lhs_operand = self.eval_result_as_bool_operand(lhs_result);
+        let rhs_operand = self.eval_result_as_bool_operand(rhs_result);
+
+        // Create a variable to store the result of the expression.
+        let variable_id = self.resource_manager.next_var();
+        let rir_variable = rir::Variable {
+            variable_id,
+            ty: rir::Ty::Boolean, // Binary operations between results are always Boolean.
+        };
+
+        // Create the binary operation instruction and add it to the current block.
+        let condition_code = match bin_op {
+            BinOp::Eq => ConditionCode::Eq,
+            BinOp::Neq => ConditionCode::Ne,
+            _ => {
+                return Err(Error::Unexpected(
+                    format!("invalid binary operator for Result operands: {bin_op:?})"),
+                    bin_op_expr_span,
+                ))
+            }
+        };
+
+        let instruction = match (bin_op, lhs_operand, rhs_operand) {
+            (BinOp::Eq, Operand::Literal(Literal::Bool(true)), operand)
+            | (BinOp::Eq, operand, Operand::Literal(Literal::Bool(true)))
+            | (BinOp::Neq, Operand::Literal(Literal::Bool(false)), operand)
+            | (BinOp::Neq, operand, Operand::Literal(Literal::Bool(false))) => {
+                // One of the operands is a literal so we just need a store instruction.
+                Instruction::Store(operand, rir_variable)
+            }
+            // Both operators are non-literals so we need the comparison instruction.
+            _ => Instruction::Icmp(condition_code, lhs_operand, rhs_operand, rir_variable),
+        };
+        self.get_current_rir_block_mut().0.push(instruction);
+
+        // Return the variable as a value.
+        let value = Value::Var(map_rir_var_to_eval_var(rir_variable));
+        Ok(EvalControlFlow::Continue(value))
+    }
+
+    fn eval_bin_op_with_lhs_classical_bool_operand(
+        &mut self,
+        bin_op: BinOp,
+        lhs_bool: bool,
+        rhs_expr_id: ExprId,
+    ) -> Result<EvalControlFlow, Error> {
+        let value = match (bin_op, lhs_bool) {
+            // Handle short-circuiting for logical AND and logical OR.
+            (BinOp::AndL, false) => Value::Bool(false),
+            (BinOp::OrL, true) => Value::Bool(true),
+            // Cases for which just returning the RHS value is sufficient.
+            (BinOp::AndL | BinOp::Eq, true) | (BinOp::OrL | BinOp::Neq, false) => {
+                // Try to evaluate the RHS expression to get its value.
+                let rhs_control_flow = self.try_eval_expr(rhs_expr_id)?;
+                let EvalControlFlow::Continue(rhs_value) = rhs_control_flow else {
+                    let rhs_expr = self.get_expr(rhs_expr_id);
+                    return Err(Error::Unexpected(
+                        "embedded return in RHS expression".to_string(),
+                        rhs_expr.span,
+                    ));
+                };
+                rhs_value
+            }
+            // The other possible cases.
+            (BinOp::Eq | BinOp::Neq, _) => {
+                // Try to evaluate the RHS expression to get its value.
+                let rhs_control_flow = self.try_eval_expr(rhs_expr_id)?;
+                let EvalControlFlow::Continue(rhs_value) = rhs_control_flow else {
+                    let rhs_expr = self.get_expr(rhs_expr_id);
+                    return Err(Error::Unexpected(
+                        "embedded return in RHS expression".to_string(),
+                        rhs_expr.span,
+                    ));
+                };
+
+                // Create the operands.
+                let lhs_operand = Operand::Literal(Literal::Bool(lhs_bool));
+                let rhs_operand = map_eval_value_to_rir_operand(&rhs_value);
+
+                // If both operands are literals, evaluate the binary operation and return its value.
+                if let (Operand::Literal(lhs_literal), Operand::Literal(rhs_literal)) =
+                    (lhs_operand, rhs_operand)
+                {
+                    let value = eval_bin_op_with_bool_literals(bin_op, lhs_literal, rhs_literal);
+                    return Ok(EvalControlFlow::Continue(value));
+                }
+
+                // Generate the specific instruction depending on the operand.
+                let bin_op_variable_id = self.resource_manager.next_var();
+                let bin_op_rir_variable = rir::Variable {
+                    variable_id: bin_op_variable_id,
+                    ty: rir::Ty::Boolean,
+                };
+                let bin_op_ins = match bin_op {
+                    BinOp::AndL => {
+                        Instruction::LogicalAnd(lhs_operand, rhs_operand, bin_op_rir_variable)
+                    }
+                    BinOp::OrL => {
+                        Instruction::LogicalOr(lhs_operand, rhs_operand, bin_op_rir_variable)
+                    }
+                    BinOp::Eq => Instruction::Icmp(
+                        ConditionCode::Eq,
+                        lhs_operand,
+                        rhs_operand,
+                        bin_op_rir_variable,
+                    ),
+                    BinOp::Neq => Instruction::Icmp(
+                        ConditionCode::Ne,
+                        lhs_operand,
+                        rhs_operand,
+                        bin_op_rir_variable,
+                    ),
+                    _ => panic!("unsupported binary operation for bools: {bin_op:?}"),
+                };
+                self.get_current_rir_block_mut().0.push(bin_op_ins);
+                Value::Var(map_rir_var_to_eval_var(bin_op_rir_variable))
+            }
+            _ => panic!("unsupported binary operation for bools: {bin_op:?}"),
+        };
+        Ok(EvalControlFlow::Continue(value))
+    }
+
+    fn eval_bin_op_with_lhs_integer_operand(
+        &mut self,
+        bin_op: BinOp,
+        lhs_operand: Operand,
+        rhs_expr_id: ExprId,
+        bin_op_expr_span: Span, // For diagnostic purposes only.
+    ) -> Result<EvalControlFlow, Error> {
+        assert!(
+            matches!(lhs_operand.get_type(), rir::Ty::Integer),
+            "LHS is expected to be of integer type"
+        );
+
+        // Try to evaluate the RHS expression to get its value and construct its operand.
+        let rhs_control_flow = self.try_eval_expr(rhs_expr_id)?;
+        let EvalControlFlow::Continue(rhs_value) = rhs_control_flow else {
+            let rhs_expr = self.get_expr(rhs_expr_id);
+            return Err(Error::Unexpected(
+                "embedded return in RHS expression".to_string(),
+                rhs_expr.span,
+            ));
+        };
+        let rhs_operand = map_eval_value_to_rir_operand(&rhs_value);
+        assert!(
+            matches!(rhs_operand.get_type(), rir::Ty::Integer),
+            "LHS value is expected to be of integer type"
+        );
+
+        // If both operands are literals, evaluate the binary operation and return its value.
+        if let (Operand::Literal(lhs_literal), Operand::Literal(rhs_literal)) =
+            (lhs_operand, rhs_operand)
+        {
+            let value = eval_bin_op_with_integer_literals(
+                bin_op,
+                lhs_literal,
+                rhs_literal,
+                bin_op_expr_span,
+            )?;
+            return Ok(EvalControlFlow::Continue(value));
+        }
+
+        // Create the variable ID, create the instruction and insert it.
+        let bin_op_variable_id = self.resource_manager.next_var();
+        let (bin_op_rir_variable, bin_op_rir_ins) =
+            create_instruction_for_binary_operation_with_integer_operands(
+                bin_op,
+                lhs_operand,
+                rhs_operand,
+                bin_op_variable_id,
+                bin_op_expr_span,
+            )?;
+
+        // Insert the instruction.
+        self.get_current_rir_block_mut().0.push(bin_op_rir_ins);
+        let value = Value::Var(map_rir_var_to_eval_var(bin_op_rir_variable));
+        Ok(EvalControlFlow::Continue(value))
+    }
+
+    fn eval_bin_op_with_lhs_var(
+        &mut self,
+        bin_op: BinOp,
+        lhs_eval_var: Var,
+        rhs_expr_id: ExprId,
+        bin_op_expr_span: Span, // For diagnostic purposes only.
+    ) -> Result<EvalControlFlow, Error> {
+        match lhs_eval_var.ty {
+            VarTy::Boolean => Err(Error::Unimplemented(
+                "bool binary operation with dynamic LHS".to_string(),
+                bin_op_expr_span,
+            )),
+            VarTy::Integer => {
+                let lhs_rir_var = map_eval_var_to_rir_var(lhs_eval_var);
+                let lhs_operand = Operand::Variable(lhs_rir_var);
+                self.eval_bin_op_with_lhs_integer_operand(
+                    bin_op,
+                    lhs_operand,
+                    rhs_expr_id,
+                    bin_op_expr_span,
+                )
+            }
+            VarTy::Double => Err(Error::Unimplemented(
+                "double binary operation with dynamic LHS".to_string(),
+                bin_op_expr_span,
+            )),
+        }
+    }
+
     fn eval_classical_expr(&mut self, expr_id: ExprId) -> Result<EvalControlFlow, Error> {
         let current_package_id = self.get_current_package_id();
         let store_expr_id = StoreExprId::from((current_package_id, expr_id));
@@ -445,7 +674,7 @@ impl<'a> PartialEvaluator<'a> {
                 self.eval_expr_assign_op(*bin_op, *lhs_expr_id, *rhs_expr_id, expr.span)
             }
             ExprKind::BinOp(bin_op, lhs_expr_id, rhs_expr_id) => {
-                self.eval_expr_bin_op(expr_id, *bin_op, *lhs_expr_id, *rhs_expr_id)
+                self.eval_expr_bin_op(*bin_op, *lhs_expr_id, *rhs_expr_id, expr.span)
             }
             ExprKind::Block(block_id) => self.try_eval_block(*block_id),
             ExprKind::Call(callee_expr_id, args_expr_id) => {
@@ -628,12 +857,12 @@ impl<'a> PartialEvaluator<'a> {
         let bin_op_control_flow = self.eval_bin_op(
             bin_op,
             lhs_value,
-            lhs_expr.span,
             rhs_expr_id,
+            lhs_expr.span,
             bin_op_expr_span,
         )?;
         let EvalControlFlow::Continue(bin_op_value) = bin_op_control_flow else {
-            panic!("evaluating a binary operation is expected to return an error or a continue, never a return");
+            panic!("evaluating a binary operation is expected to result in an error or a continue, but never in a return");
         };
         self.update_bindings(lhs_expr_id, bin_op_value)?;
         Ok(EvalControlFlow::Continue(Value::unit()))
@@ -642,71 +871,31 @@ impl<'a> PartialEvaluator<'a> {
     #[allow(clippy::similar_names)]
     fn eval_expr_bin_op(
         &mut self,
-        bin_op_expr_id: ExprId,
         bin_op: BinOp,
         lhs_expr_id: ExprId,
         rhs_expr_id: ExprId,
+        bin_op_expr_span: Span, // For diagnostic purposes only.
     ) -> Result<EvalControlFlow, Error> {
-        // Try to evaluate both the LHS and RHS expressions to get their value, short-circuiting execution if any of the
-        // expressions is a return.
+        // Try to evaluate the LHS expression and get its value, short-circuiting execution if it is a return.
         let lhs_control_flow = self.try_eval_expr(lhs_expr_id)?;
-        if lhs_control_flow.is_return() {
+        let EvalControlFlow::Continue(lhs_value) = lhs_control_flow else {
             let lhs_expr = self.get_expr(lhs_expr_id);
             return Err(Error::Unexpected(
                 "embedded return in binary operation".to_string(),
                 lhs_expr.span,
             ));
-        }
-        let rhs_control_flow = self.try_eval_expr(rhs_expr_id)?;
-        if rhs_control_flow.is_return() {
-            let rhs_expr = self.get_expr(rhs_expr_id);
-            return Err(Error::Unexpected(
-                "embedded return in binary operation".to_string(),
-                rhs_expr.span,
-            ));
-        }
-
-        // Get the operands to use when generating the binary operation instruction depending on the type of the
-        // expression's value.
-        let lhs_value = lhs_control_flow.into_value();
-        let lhs_operand = if let Value::Result(result) = lhs_value {
-            self.eval_result_as_bool_operand(result)
-        } else {
-            map_eval_value_to_rir_operand(&lhs_value)
-        };
-        let rhs_value = rhs_control_flow.into_value();
-        let rhs_operand = if let Value::Result(result) = rhs_value {
-            self.eval_result_as_bool_operand(result)
-        } else {
-            map_eval_value_to_rir_operand(&rhs_value)
         };
 
-        // Create a variable to store the result of the expression.
-        let bin_op_expr = self.get_expr(bin_op_expr_id);
-        let variable_id = self.resource_manager.next_var();
-        let variable_ty = map_fir_type_to_rir_type(&bin_op_expr.ty);
-        let variable = rir::Variable {
-            variable_id,
-            ty: variable_ty,
-        };
-
-        // Create the binary operation instruction and add it to the current block.
-        let instruction = match bin_op {
-            BinOp::Eq => Instruction::Icmp(ConditionCode::Eq, lhs_operand, rhs_operand, variable),
-            BinOp::Neq => Instruction::Icmp(ConditionCode::Ne, lhs_operand, rhs_operand, variable),
-            _ => {
-                return Err(Error::Unimplemented(
-                    format!("BinOp Expr ({bin_op:?})"),
-                    bin_op_expr.span,
-                ))
-            }
-        };
-        let current_block = self.get_current_rir_block_mut();
-        current_block.0.push(instruction);
-
-        // Return the variable as a value.
-        let value = Value::Var(map_rir_var_to_eval_var(variable));
-        Ok(EvalControlFlow::Continue(value))
+        // Now that we have a LHS value, evaluate the binary operation, which will properly consider short-circuiting
+        // logic in the case of Boolean operations.
+        let lhs_expr = self.get_expr(lhs_expr_id);
+        self.eval_bin_op(
+            bin_op,
+            lhs_value,
+            rhs_expr_id,
+            lhs_expr.span,
+            bin_op_expr_span,
+        )
     }
 
     fn eval_expr_call(
@@ -1206,11 +1395,29 @@ impl<'a> PartialEvaluator<'a> {
                 },
                 FunctorApp::default(),
             ),
-            Res::Local(local_var_id) => self
-                .eval_context
-                .get_current_scope()
-                .get_hybrid_local_value(*local_var_id)
-                .clone(),
+            Res::Local(local_var_id) => {
+                let bound_value = self
+                    .eval_context
+                    .get_current_scope()
+                    .get_hybrid_local_value(*local_var_id);
+
+                // Check whether the bound value is a mutable variable, and if so, return its value directly rather than
+                // the variable if it is static at this moment.
+                if let Value::Var(var) = bound_value {
+                    let current_scope = self.eval_context.get_current_scope();
+                    if let Some(MutableVar {
+                        kind: MutableKind::Static(literal),
+                        ..
+                    }) = current_scope.find_mutable_var(var.id.into())
+                    {
+                        map_rir_literal_to_eval_value(*literal)
+                    } else {
+                        bound_value.clone()
+                    }
+                } else {
+                    bound_value.clone()
+                }
+            }
         }
     }
 
@@ -1356,20 +1563,40 @@ impl<'a> PartialEvaluator<'a> {
         expr_generator_set.generate_application_compute_kind(&callable_scope.args_value_kind)
     }
 
-    fn get_or_create_variable(&mut self, local_var_id: LocalVarId, var_ty: VarTy) -> Var {
-        let current_scope = self.eval_context.get_current_scope_mut();
-        let entry = current_scope.hybrid_vars.entry(local_var_id);
-        let local_var_value = entry.or_insert(Value::Var({
-            let var_id = self.resource_manager.next_var();
-            Var {
-                id: var_id.into(),
-                ty: var_ty,
-            }
-        }));
-        let Value::Var(var) = local_var_value else {
-            panic!("value must be a variable");
+    fn try_create_mutable_variable(
+        &mut self,
+        local_var_id: LocalVarId,
+        value: &Value,
+    ) -> Option<(rir::VariableId, MutableVar)> {
+        // Check if we can create a mutable variable for this value.
+        let var_ty = try_get_eval_var_type(value)?;
+
+        // Create an evaluator variable and insert it.
+        let var_id = self.resource_manager.next_var();
+        let eval_var = Var {
+            id: var_id.into(),
+            ty: var_ty,
         };
-        *var
+        self.eval_context
+            .get_current_scope_mut()
+            .insert_hybrid_local_value(local_var_id, Value::Var(eval_var));
+
+        // Insert a store instruction.
+        let value_operand = map_eval_value_to_rir_operand(value);
+        let rir_var = map_eval_var_to_rir_var(eval_var);
+        let store_ins = Instruction::Store(value_operand, rir_var);
+        self.get_current_rir_block_mut().0.push(store_ins);
+
+        // Create a mutable variable.
+        let mutable_kind = match value_operand {
+            Operand::Literal(literal) => MutableKind::Static(literal),
+            Operand::Variable(_) => MutableKind::Dynamic,
+        };
+        let mutable_var = MutableVar {
+            id: local_var_id,
+            kind: mutable_kind,
+        };
+        Some((var_id, mutable_var))
     }
 
     fn get_or_insert_callable(&mut self, callable: Callable) -> CallableId {
@@ -1650,6 +1877,16 @@ impl<'a> PartialEvaluator<'a> {
             let rir_var = map_eval_var_to_rir_var(*var);
             let store_ins = Instruction::Store(rhs_operand, rir_var);
             self.get_current_rir_block_mut().0.push(store_ins);
+
+            // If this is a mutable variable, make sure to update whether it is static or dynamic.
+            let current_scope = self.eval_context.get_current_scope_mut();
+            if matches!(rhs_operand, Operand::Variable(_))
+                || current_scope.is_currently_evaluating_branch()
+            {
+                if let Some(mutable_var) = current_scope.find_mutable_var_mut(rir_var.variable_id) {
+                    mutable_var.kind = MutableKind::Dynamic;
+                }
+            }
         } else {
             // Verify that we are not updating a value that does not have a backing variable from a dynamic branch
             // because it is unsupported.
@@ -1912,6 +2149,229 @@ impl<'a> PartialEvaluator<'a> {
     }
 }
 
+#[allow(clippy::too_many_lines)]
+fn create_instruction_for_binary_operation_with_integer_operands(
+    bin_op: BinOp,
+    lhs_operand: Operand,
+    rhs_operand: Operand,
+    bin_op_variable_id: rir::VariableId,
+    bin_op_expr_span: Span, // For diagnostic purposes only.
+) -> Result<(rir::Variable, Instruction), Error> {
+    let (rir_variable, rir_ins) = match bin_op {
+        BinOp::Add => {
+            let bin_op_rir_variable = rir::Variable::new_integer(bin_op_variable_id);
+            let bin_op_rir_ins = Instruction::Add(lhs_operand, rhs_operand, bin_op_rir_variable);
+            (bin_op_rir_variable, bin_op_rir_ins)
+        }
+        BinOp::Sub => {
+            let bin_op_rir_variable = rir::Variable::new_integer(bin_op_variable_id);
+            let bin_op_rir_ins = Instruction::Sub(lhs_operand, rhs_operand, bin_op_rir_variable);
+            (bin_op_rir_variable, bin_op_rir_ins)
+        }
+        BinOp::Mul => {
+            let bin_op_rir_variable = rir::Variable::new_integer(bin_op_variable_id);
+            let bin_op_rir_ins = Instruction::Mul(lhs_operand, rhs_operand, bin_op_rir_variable);
+            (bin_op_rir_variable, bin_op_rir_ins)
+        }
+        BinOp::Div => {
+            // Validate that the RHS is not a zero.
+            if let Operand::Literal(Literal::Integer(0)) = rhs_operand {
+                let error =
+                    Error::EvaluationFailed("division by zero".to_string(), bin_op_expr_span);
+                return Err(error);
+            }
+            let bin_op_rir_variable = rir::Variable::new_integer(bin_op_variable_id);
+            let bin_op_rir_ins = Instruction::Sdiv(lhs_operand, rhs_operand, bin_op_rir_variable);
+            (bin_op_rir_variable, bin_op_rir_ins)
+        }
+        BinOp::Mod => {
+            let bin_op_rir_variable = rir::Variable::new_integer(bin_op_variable_id);
+            let bin_op_rir_ins = Instruction::Srem(lhs_operand, rhs_operand, bin_op_rir_variable);
+            (bin_op_rir_variable, bin_op_rir_ins)
+        }
+        BinOp::Exp => {
+            let error = Error::Unimplemented(
+                "exponentiation for integer operands".to_string(),
+                bin_op_expr_span,
+            );
+            return Err(error);
+        }
+        BinOp::AndB => {
+            let bin_op_rir_variable = rir::Variable::new_integer(bin_op_variable_id);
+            let bin_op_rir_ins =
+                Instruction::BitwiseAnd(lhs_operand, rhs_operand, bin_op_rir_variable);
+            (bin_op_rir_variable, bin_op_rir_ins)
+        }
+        BinOp::OrB => {
+            let bin_op_rir_variable = rir::Variable::new_integer(bin_op_variable_id);
+            let bin_op_rir_ins =
+                Instruction::BitwiseOr(lhs_operand, rhs_operand, bin_op_rir_variable);
+            (bin_op_rir_variable, bin_op_rir_ins)
+        }
+        BinOp::XorB => {
+            let bin_op_rir_variable = rir::Variable::new_integer(bin_op_variable_id);
+            let bin_op_rir_ins =
+                Instruction::BitwiseXor(lhs_operand, rhs_operand, bin_op_rir_variable);
+            (bin_op_rir_variable, bin_op_rir_ins)
+        }
+        BinOp::Shl => {
+            let bin_op_rir_variable = rir::Variable::new_integer(bin_op_variable_id);
+            let bin_op_rir_ins = Instruction::Shl(lhs_operand, rhs_operand, bin_op_rir_variable);
+            (bin_op_rir_variable, bin_op_rir_ins)
+        }
+        BinOp::Shr => {
+            let bin_op_rir_variable = rir::Variable::new_integer(bin_op_variable_id);
+            let bin_op_rir_ins = Instruction::Ashr(lhs_operand, rhs_operand, bin_op_rir_variable);
+            (bin_op_rir_variable, bin_op_rir_ins)
+        }
+        BinOp::Eq => {
+            let bin_op_rir_variable = rir::Variable::new_boolean(bin_op_variable_id);
+            let bin_op_rir_ins = Instruction::Icmp(
+                ConditionCode::Eq,
+                lhs_operand,
+                rhs_operand,
+                bin_op_rir_variable,
+            );
+            (bin_op_rir_variable, bin_op_rir_ins)
+        }
+        BinOp::Neq => {
+            let bin_op_rir_variable = rir::Variable::new_boolean(bin_op_variable_id);
+            let bin_op_rir_ins = Instruction::Icmp(
+                ConditionCode::Ne,
+                lhs_operand,
+                rhs_operand,
+                bin_op_rir_variable,
+            );
+            (bin_op_rir_variable, bin_op_rir_ins)
+        }
+        BinOp::Gt => {
+            let bin_op_rir_variable = rir::Variable::new_boolean(bin_op_variable_id);
+            let bin_op_rir_ins = Instruction::Icmp(
+                ConditionCode::Sgt,
+                lhs_operand,
+                rhs_operand,
+                bin_op_rir_variable,
+            );
+            (bin_op_rir_variable, bin_op_rir_ins)
+        }
+        BinOp::Gte => {
+            let bin_op_rir_variable = rir::Variable::new_boolean(bin_op_variable_id);
+            let bin_op_rir_ins = Instruction::Icmp(
+                ConditionCode::Sge,
+                lhs_operand,
+                rhs_operand,
+                bin_op_rir_variable,
+            );
+            (bin_op_rir_variable, bin_op_rir_ins)
+        }
+        BinOp::Lt => {
+            let bin_op_rir_variable = rir::Variable::new_boolean(bin_op_variable_id);
+            let bin_op_rir_ins = Instruction::Icmp(
+                ConditionCode::Slt,
+                lhs_operand,
+                rhs_operand,
+                bin_op_rir_variable,
+            );
+            (bin_op_rir_variable, bin_op_rir_ins)
+        }
+        BinOp::Lte => {
+            let bin_op_rir_variable = rir::Variable::new_boolean(bin_op_variable_id);
+            let bin_op_rir_ins = Instruction::Icmp(
+                ConditionCode::Sle,
+                lhs_operand,
+                rhs_operand,
+                bin_op_rir_variable,
+            );
+            (bin_op_rir_variable, bin_op_rir_ins)
+        }
+        _ => panic!("unsupported binary operation for integers: {bin_op:?}"),
+    };
+    Ok((rir_variable, rir_ins))
+}
+
+fn eval_bin_op_with_bool_literals(
+    bin_op: BinOp,
+    lhs_literal: Literal,
+    rhs_literal: Literal,
+) -> Value {
+    let (Literal::Bool(lhs_bool), Literal::Bool(rhs_bool)) = (lhs_literal, rhs_literal) else {
+        panic!("at least one literal is not bool: {lhs_literal}, {rhs_literal}");
+    };
+
+    let bin_op_result = match bin_op {
+        BinOp::Eq => lhs_bool == rhs_bool,
+        BinOp::Neq => lhs_bool != rhs_bool,
+        BinOp::AndL => lhs_bool && rhs_bool,
+        BinOp::OrL => lhs_bool || rhs_bool,
+        _ => panic!("invalid bool operator: {bin_op:?}"),
+    };
+    Value::Bool(bin_op_result)
+}
+
+fn eval_bin_op_with_integer_literals(
+    bin_op: BinOp,
+    lhs_literal: Literal,
+    rhs_literal: Literal,
+    bin_op_expr_span: Span, // For diagnostic purposes only
+) -> Result<Value, Error> {
+    fn eval_integer_div(lhs_int: i64, rhs_int: i64, span: Span) -> Result<Value, Error> {
+        match (lhs_int, rhs_int) {
+            (_, 0) => Err(Error::EvaluationFailed(
+                "division by zero".to_string(),
+                span,
+            )),
+            (lhs, rhs) => Ok(Value::Int(lhs / rhs)),
+        }
+    }
+
+    fn eval_integer_mod(lhs_int: i64, rhs_int: i64, span: Span) -> Result<Value, Error> {
+        match (lhs_int, rhs_int) {
+            (_, 0) => Err(Error::EvaluationFailed(
+                "division by zero".to_string(),
+                span,
+            )),
+            (lhs, rhs) => Ok(Value::Int(lhs % rhs)),
+        }
+    }
+
+    fn eval_integer_exp(lhs_int: i64, rhs_int: i64, span: Span) -> Result<Value, Error> {
+        let Ok(rhs_int_as_u32) = u32::try_from(rhs_int) else {
+            return Err(Error::EvaluationFailed(
+                "invalid exponent".to_string(),
+                span,
+            ));
+        };
+
+        Ok(Value::Int(lhs_int.pow(rhs_int_as_u32)))
+    }
+
+    // Validate that both literals are integers.
+    let (Literal::Integer(lhs_int), Literal::Integer(rhs_int)) = (lhs_literal, rhs_literal) else {
+        panic!("at least one literal is not an integer: {lhs_literal}, {rhs_literal}");
+    };
+
+    match bin_op {
+        BinOp::Eq => Ok(Value::Bool(lhs_int == rhs_int)),
+        BinOp::Neq => Ok(Value::Bool(lhs_int != rhs_int)),
+        BinOp::Gt => Ok(Value::Bool(lhs_int > rhs_int)),
+        BinOp::Gte => Ok(Value::Bool(lhs_int >= rhs_int)),
+        BinOp::Lt => Ok(Value::Bool(lhs_int < rhs_int)),
+        BinOp::Lte => Ok(Value::Bool(lhs_int <= rhs_int)),
+        BinOp::Add => Ok(Value::Int(lhs_int + rhs_int)),
+        BinOp::Sub => Ok(Value::Int(lhs_int - rhs_int)),
+        BinOp::Mul => Ok(Value::Int(lhs_int * rhs_int)),
+        BinOp::Div => eval_integer_div(lhs_int, rhs_int, bin_op_expr_span),
+        BinOp::Mod => eval_integer_mod(lhs_int, rhs_int, bin_op_expr_span),
+        BinOp::Exp => eval_integer_exp(lhs_int, rhs_int, bin_op_expr_span),
+        BinOp::AndB => Ok(Value::Int(lhs_int & rhs_int)),
+        BinOp::OrB => Ok(Value::Int(lhs_int | rhs_int)),
+        BinOp::XorB => Ok(Value::Int(lhs_int ^ rhs_int)),
+        BinOp::Shl => Ok(Value::Int(lhs_int << rhs_int)),
+        BinOp::Shr => Ok(Value::Int(lhs_int >> rhs_int)),
+        _ => panic!("invalid integer operator: {bin_op:?}"),
+    }
+}
+
 fn get_spec_decl(spec_impl: &SpecImpl, functor_app: FunctorApp) -> &SpecDecl {
     if !functor_app.adjoint && functor_app.controlled == 0 {
         &spec_impl.body
@@ -1990,6 +2450,15 @@ fn map_fir_type_to_rir_type(ty: &Ty) -> rir::Ty {
     }
 }
 
+fn map_rir_literal_to_eval_value(literal: rir::Literal) -> Value {
+    match literal {
+        rir::Literal::Bool(b) => Value::Bool(b),
+        rir::Literal::Double(d) => Value::Double(d),
+        rir::Literal::Integer(i) => Value::Int(i),
+        _ => panic!("{literal:?} RIR literal cannot be mapped to evaluator value"),
+    }
+}
+
 fn map_rir_var_to_eval_var(var: rir::Variable) -> Var {
     Var {
         id: var.variable_id.into(),
diff --git a/compiler/qsc_rca/src/core.rs b/compiler/qsc_rca/src/core.rs
index 77fe6710..5da592bf 100644
--- a/compiler/qsc_rca/src/core.rs
+++ b/compiler/qsc_rca/src/core.rs
@@ -1404,17 +1404,22 @@ impl<'a> Analyzer<'a> {
                     panic!("expected a local variable");
                 };
 
-                // The updated compute kind is based on the compute kind of the value expression.
+                // The updated compute kind is the aggregation of the compute kind of the local variable and the
+                // assigned value.
+                // Start by initializing the updated compute kind with the compute kind of the local variable.
                 let application_instance = self.get_current_application_instance();
-                let value_expr_compute_kind =
-                    *application_instance.get_expr_compute_kind(value_expr_id);
-
-                // Since the local variable compute kind is what will be updated, the value kind must match the local
-                // variable's type. In some cases, there might be some loss of granularity on the value kind (e.g.
-                // assigning an array to a UDT variable field since we do not track individual UDT fields).
                 let local_var_compute_kind = application_instance
                     .locals_map
                     .get_local_compute_kind(*local_var_id);
+                let mut updated_compute_kind = local_var_compute_kind.compute_kind;
+
+                // Since the local variable compute kind is what will be updated, the value kind must match the local
+                // variable's type. That is why before aggregating the compute kind of the assigned value we need to get
+                // a default value kind of the matching type.
+                // In some cases, there might be some loss of granularity on the value kind (e.g. assigning an array to
+                // a UDT variable field since we do not track individual UDT fields).
+                let value_expr_compute_kind =
+                    *application_instance.get_expr_compute_kind(value_expr_id);
                 let mut value_kind =
                     ValueKind::new_static_from_type(&local_var_compute_kind.local.ty);
                 if let ComputeKind::Quantum(value_expr_quantum_properties) = value_expr_compute_kind
@@ -1423,8 +1428,6 @@ impl<'a> Analyzer<'a> {
                         .value_kind
                         .project_onto_variant(&mut value_kind);
                 }
-
-                let mut updated_compute_kind = ComputeKind::Classical;
                 updated_compute_kind = updated_compute_kind
                     .aggregate_runtime_features(value_expr_compute_kind, value_kind);
 
diff --git a/compiler/qsc_rir/src/passes/ssa_transform.rs b/compiler/qsc_rir/src/passes/ssa_transform.rs
index c41414cc..0239459b 100644
--- a/compiler/qsc_rir/src/passes/ssa_transform.rs
+++ b/compiler/qsc_rir/src/passes/ssa_transform.rs
@@ -48,7 +48,15 @@ pub fn transform_to_ssa(program: &mut Program, preds: &IndexMap<BlockId, Vec<Blo
             .expect("block should have at least one predecessor");
 
         // The block is only a candidate for phi nodes if it has multiple predecessors.
-        if !rest_preds.is_empty() {
+        if rest_preds.is_empty() {
+            // If the block has only one predecessor, track any updates to the variable map from that
+            // predecessor to ensure any phi values that may have been added or inherited in the predecessor
+            // are propagated to this block.
+            let pred_var_map = block_var_map
+                .get(*first_pred)
+                .expect("block should have variable map");
+            pred_var_map.clone_into(&mut var_map_updates);
+        } else {
             // Check each variable in the first predecessor's variable map, and if any other
             // predecessor has a different value for the variable, a phi node is needed.
             for (var_id, operand) in block_var_map
@@ -99,16 +107,16 @@ pub fn transform_to_ssa(program: &mut Program, preds: &IndexMap<BlockId, Vec<Blo
                     next_var_id = next_var_id.successor();
                 }
             }
+        }
 
-            // Now that the block has finished processing, apply any updates to the block and
-            // merge those updates into the stored variable map to propagate to successors.
-            map_variable_use_in_block(block, &mut var_map_updates);
-            for (var_id, operand) in var_map_updates {
-                let var_map = block_var_map
-                    .get_mut(block_id)
-                    .expect("block should have variable map");
-                var_map.entry(var_id).or_insert(operand);
-            }
+        // Now that the block has finished processing, apply any updates to the block and
+        // merge those updates into the stored variable map to propagate to successors.
+        map_variable_use_in_block(block, &mut var_map_updates);
+        for (var_id, operand) in var_map_updates {
+            let var_map = block_var_map
+                .get_mut(block_id)
+                .expect("block should have variable map");
+            var_map.entry(var_id).or_insert(operand);
         }
     }
 }
diff --git a/compiler/qsc_rir/src/rir.rs b/compiler/qsc_rir/src/rir.rs
index 6415350d..e283e73d 100644
--- a/compiler/qsc_rir/src/rir.rs
+++ b/compiler/qsc_rir/src/rir.rs
@@ -456,6 +456,32 @@ impl Display for Variable {
     }
 }
 
+impl Variable {
+    #[must_use]
+    pub fn new_boolean(id: VariableId) -> Self {
+        Self {
+            variable_id: id,
+            ty: Ty::Boolean,
+        }
+    }
+
+    #[must_use]
+    pub fn new_integer(id: VariableId) -> Self {
+        Self {
+            variable_id: id,
+            ty: Ty::Integer,
+        }
+    }
+
+    #[must_use]
+    pub fn new_double(id: VariableId) -> Self {
+        Self {
+            variable_id: id,
+            ty: Ty::Double,
+        }
+    }
+}
+
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub enum Ty {
     Qubit,
diff --git a/library/std/arrays.qs b/library/std/arrays.qs
index f5fe2449..9c680f8f 100644
--- a/library/std/arrays.qs
+++ b/library/std/arrays.qs
@@ -1054,7 +1054,7 @@ namespace Microsoft.Quantum.Arrays {
     /// let naturals = SequenceI(1, _); // function to create sequence from 1 to `to`
     /// ```
     function SequenceI(from : Int, to : Int) : Int[] {
-        Fact(to >= from, $"`to` must be larger than `from`.");
+        Fact(to >= from, "`to` must be larger than `from`.");
         mutable array = [];
         for index in from..to {
             set array += [index];
diff --git a/library/std/convert.qs b/library/std/convert.qs
index db5c8627..d3425ce7 100644
--- a/library/std/convert.qs
+++ b/library/std/convert.qs
@@ -107,7 +107,7 @@ namespace Microsoft.Quantum.Convert {
             set result += [(runningValue &&& 1) != 0];
             set runningValue >>>= 1;
         }
-        Fact(runningValue == 0, $"`number`={number} is too large to fit into {bits} bits.");
+        Fact(runningValue == 0, "`number` is too large to fit into array of length `bits`.");
 
         result
     }
diff --git a/npm/qsharp/src/compiler/common.ts b/npm/qsharp/src/compiler/common.ts
index bcfb0332..1656e5f3 100644
--- a/npm/qsharp/src/compiler/common.ts
+++ b/npm/qsharp/src/compiler/common.ts
@@ -16,7 +16,7 @@ export type Result =
 interface DumpMsg {
   type: "DumpMachine";
   state: Dump;
-  stateLatex: string;
+  stateLatex: string | null;
 }
 
 interface MessageMsg {
diff --git a/npm/qsharp/src/compiler/events.ts b/npm/qsharp/src/compiler/events.ts
index fa3ada9b..20c21e23 100644
--- a/npm/qsharp/src/compiler/events.ts
+++ b/npm/qsharp/src/compiler/events.ts
@@ -8,7 +8,7 @@ import { IServiceEventTarget } from "../workers/common.js";
 // Create strongly typed compiler events
 export type QscEventData =
   | { type: "Message"; detail: string }
-  | { type: "DumpMachine"; detail: { state: Dump; stateLatex: string } }
+  | { type: "DumpMachine"; detail: { state: Dump; stateLatex: string | null } }
   | { type: "Result"; detail: Result };
 
 export type QscEvents = Event & QscEventData;
@@ -93,7 +93,7 @@ export class QscEventTarget implements IQscEventTarget {
     this.queueUiRefresh();
   }
 
-  private onDumpMachine(detail: { state: Dump; stateLatex: string }) {
+  private onDumpMachine(detail: { state: Dump; stateLatex: string | null }) {
     this.ensureActiveShot();
 
     const shotIdx = this.results.length - 1;
diff --git a/pip/qsharp/_native.pyi b/pip/qsharp/_native.pyi
index 6d2b6ef9..d4381ac7 100644
--- a/pip/qsharp/_native.pyi
+++ b/pip/qsharp/_native.pyi
@@ -184,6 +184,7 @@ class Output:
     def __repr__(self) -> str: ...
     def __str__(self) -> str: ...
     def _repr_html_(self) -> str: ...
+    def _repr_latex_(self) -> Optional[str]: ...
     def state_dump(self) -> Optional[StateDumpData]: ...
 
 class StateDumpData:
@@ -204,6 +205,7 @@ class StateDumpData:
     def __repr__(self) -> str: ...
     def __str__(self) -> str: ...
     def _repr_html_(self) -> str: ...
+    def _repr_latex_(self) -> Optional[str]: ...
 
 class Circuit:
     def json(self) -> str: ...
diff --git a/pip/qsharp/_qsharp.py b/pip/qsharp/_qsharp.py
index 94c5402e..9fe3ec26 100644
--- a/pip/qsharp/_qsharp.py
+++ b/pip/qsharp/_qsharp.py
@@ -343,6 +343,9 @@ class StateDump:
     def _repr_html_(self) -> str:
         return self.__data._repr_html_()
 
+    def _repr_latex_(self) -> Optional[str]:
+        return self.__data._repr_latex_()
+
     def check_eq(
         self, state: Union[Dict[int, complex], List[complex]], tolerance: float = 1e-10
     ) -> bool:
diff --git a/pip/src/displayable_output.rs b/pip/src/displayable_output.rs
index 9d5fa103..8edadc75 100644
--- a/pip/src/displayable_output.rs
+++ b/pip/src/displayable_output.rs
@@ -6,7 +6,7 @@ mod tests;
 
 use num_bigint::BigUint;
 use num_complex::{Complex64, ComplexFloat};
-use qsc::{fmt_basis_state_label, fmt_complex, format_state_id, get_phase};
+use qsc::{fmt_basis_state_label, fmt_complex, format_state_id, get_latex, get_phase};
 use std::fmt::Write;
 
 #[derive(Clone)]
@@ -51,6 +51,10 @@ impl DisplayableState {
                 })
         )
     }
+
+    pub fn to_latex(&self) -> Option<String> {
+        get_latex(&self.0, self.1)
+    }
 }
 
 pub enum DisplayableOutput {
diff --git a/pip/src/interpreter.rs b/pip/src/interpreter.rs
index 0d42ad77..cb0d61d6 100644
--- a/pip/src/interpreter.rs
+++ b/pip/src/interpreter.rs
@@ -358,6 +358,13 @@ impl Output {
         }
     }
 
+    fn _repr_latex_(&self) -> Option<String> {
+        match &self.0 {
+            DisplayableOutput::State(state) => state.to_latex(),
+            DisplayableOutput::Message(_) => None,
+        }
+    }
+
     fn state_dump(&self) -> Option<StateDumpData> {
         match &self.0 {
             DisplayableOutput::State(state) => Some(StateDumpData(state.clone())),
@@ -416,6 +423,10 @@ impl StateDumpData {
     fn _repr_html_(&self) -> String {
         self.0.to_html()
     }
+
+    fn _repr_latex_(&self) -> Option<String> {
+        self.0.to_latex()
+    }
 }
 
 #[pyclass(unsendable)]
diff --git a/playground/README.md b/playground/README.md
index 62d0a869..6906315c 100644
--- a/playground/README.md
+++ b/playground/README.md
@@ -5,14 +5,14 @@ This is a simple web site built using the Monaco editor and the qsharp npm packa
 ## Building the Playground Locally
 
 1. Build the entire repo by running `./build.py` in the root directory.
-   If you only want to build the functionality necessary to run the playground, you can use `python .\build.py --wasm --npm --play`.
+   If you only want to build the functionality necessary to run the playground, you can use `python ./build.py --wasm --npm --play`.
 2. Then make `./playground` your current directory and run `npm start` to start the web server.
 3. Copy the URL that will be printed to console and open it in a browser to use the playground.
 
 ## Building the Playground Locally in Watch Mode
 
 1. Build the entire repo by running `./build.py` in the root directory.
-   If you only want to build the functionality necessary to run the playground, you can use `python .\build.py --wasm --npm --play`.
+   If you only want to build the functionality necessary to run the playground, you can use `python ./build.py --wasm --npm --play`.
 2. Run `node watch.mjs` at the root of the repo.
 3. Copy the URL that will be printed to the console and open it in a browser to use the playground.
 
diff --git a/playground/build.js b/playground/build.js
index 4329e570..086939ba 100644
--- a/playground/build.js
+++ b/playground/build.js
@@ -35,7 +35,7 @@ const buildOptions = {
     join(thisDir, "src/main.tsx"),
     join(thisDir, "src/compiler-worker.ts"),
     join(thisDir, "src/language-service-worker.ts"),
-    join(thisDir, "src/kataViewer.ts"),
+    join(thisDir, "src/kataViewer.tsx"),
   ],
   outdir,
   bundle: true,
diff --git a/playground/public/katas.html b/playground/public/katas.html
index 2b0a3f88..650ee6d9 100644
--- a/playground/public/katas.html
+++ b/playground/public/katas.html
@@ -4,9 +4,18 @@
     <meta charset="UTF-8" />
     <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     <title>Katas MathJax review</title>
+    <link
+      rel="stylesheet"
+      href="https://cdn.jsdelivr.net/npm/github-markdown-css@5.5.1/github-markdown-light.css"
+    />
+    <link
+      rel="stylesheet"
+      href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/styles/default.min.css"
+    />
     <style>
       body {
         font-family: system-ui, "Segoe UI", sans-serif;
+        margin: 0;
       }
       table {
         border-spacing: 0;
@@ -21,22 +30,42 @@
         border: 0.5px solid gray;
         padding: 8px;
       }
+      .nav {
+        /* background: lightblue; */
+        width: 320px;
+        height: 100vh;
+        padding-top: 16px;
+        position: fixed;
+        overflow-y: auto;
+        background-color: #eee;
+      }
+      .content {
+        margin-left: 330px;
+        padding: 16px;
+        width: calc(100% - 362px);
+        /* height: 100vh; */
+        overflow-y: auto;
+        /* background: lightcyan; */
+      }
+      .nav-item {
+        font-size: 1.1em;
+        padding: 8px;
+        color: #444;
+      }
+      .nav-item:hover {
+        background-color: #ddd;
+      }
+      .nav-selected {
+        font-weight: 600;
+        background-color: #ccc;
+      }
     </style>
-    <link
-      rel="stylesheet"
-      href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/default.min.css"
-    />
   </head>
   <body>
-    <div id="errors"></div>
-    <h1>Azure Quantum Katas</h1>
-    <p>
-      This is a very basic rendering of the Azure Quantum Katas using MathJax
-      for content review purposes
-    </p>
-    <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js"></script>
-    <script src="https://unpkg.com/highlightjs-qsharp/dist/qsharp.min.js"></script>
+    <div id="app"></div>
     <script src="libs/kataViewer.js"></script>
-    <script src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
+    <script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/highlight.min.js"></script>
+    <script src="https://cdn.jsdelivr.net/npm/highlightjs-qsharp@1.0.2/dist/qsharp.min.js"></script>
+    <script src="https://cdn.jsdelivr.net/npm/mathjax@3.2.2/es5/tex-mml-chtml.js"></script>
   </body>
 </html>
diff --git a/playground/src/kataViewer.ts b/playground/src/kataViewer.ts
deleted file mode 100644
index 8cefcb6b..00000000
--- a/playground/src/kataViewer.ts
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright (c) Microsoft Corporation.
-// Licensed under the MIT License.
-
-import { ExplainedSolutionItem, Kata, getAllKatas } from "qsharp-lang";
-
-(window as any).MathJax = {
-  loader: { load: ["[tex]/physics", "[tex]/color"] },
-  tex: {
-    packages: { "[+]": ["physics", "color"] },
-    inlineMath: [
-      ["$", "$"],
-      ["\\(", "\\)"],
-    ],
-    formatError: (jax: any, err: any) => {
-      console.log("LaTeX processing error occurred. ", err, jax);
-      const errorNode = document.createElement("div");
-      errorNode.innerText = `LaTeX processing error: ${err.message}.\nLaTeX: ${jax.latex}\n\n`;
-      errorNode.style.fontSize = "20px";
-      errorNode.style.color = "red";
-      document.querySelector("#errors")?.appendChild(errorNode);
-      window.scroll(0, 0);
-      jax.formatError(err);
-    },
-  },
-  startup: {
-    pageReady: async () => {
-      await onload();
-      return (window as any).MathJax.startup.defaultPageReady();
-    },
-  },
-};
-
-async function onload() {
-  const katas = await getAllKatas();
-
-  const indexDiv = document.createElement("div");
-  document.body.appendChild(indexDiv);
-  const indexKatas = document.createElement("ul");
-  indexDiv.appendChild(indexKatas);
-
-  katas.forEach((kata) => {
-    const kataLi = document.createElement("li");
-    kataLi.innerHTML = `<a href="#kata-${kata.id}">${kata.title}</a>`;
-    indexKatas.appendChild(kataLi);
-
-    document.body.appendChild(getKataDiv(kata, indexKatas));
-  });
-  document.querySelectorAll("details").forEach((item) => (item.open = true));
-  document
-    .querySelectorAll("code")
-    .forEach((item) => (item.className = "qsharp"));
-  (window as any).hljs.highlightAll();
-}
-
-function getKataDiv(kata: Kata, index: HTMLElement) {
-  const kataDiv = document.createElement("div");
-  const kataHeader = document.createElement("h1");
-  kataHeader.innerText = kata.title;
-  kataHeader.id = `kata-${kata.id}`;
-  kataDiv.appendChild(kataHeader);
-
-  const sectionIndex = document.createElement("ul");
-  index.appendChild(sectionIndex);
-
-  kata.sections.forEach((section) => {
-    const sectionDiv = document.createElement("div");
-    const sectionHeader = document.createElement("h2");
-    sectionHeader.innerText = section.title;
-    const sectionId = `section-${section.id}`;
-    sectionHeader.id = sectionId;
-    sectionDiv.appendChild(sectionHeader);
-
-    const sectionLi = document.createElement("li");
-    sectionLi.innerHTML = `<a href="#${sectionId}">${section.title}</a>`;
-    sectionIndex.appendChild(sectionLi);
-
-    if (section.type === "lesson") {
-      section.items.forEach((item) => {
-        switch (item.type) {
-          case "text-content": {
-            const content = document.createElement("div");
-            content.innerHTML = item.asHtml;
-            sectionDiv.appendChild(content);
-            break;
-          }
-          case "question": {
-            const questionHeader = document.createElement("h3");
-            questionHeader.innerHTML = `Question`;
-            sectionDiv.appendChild(questionHeader);
-            const questionBody = document.createElement("div");
-            questionBody.innerHTML = item.description.asHtml;
-            sectionDiv.appendChild(questionBody);
-            const answerHeader = document.createElement("h3");
-            answerHeader.innerHTML = `Answer`;
-            sectionDiv.appendChild(answerHeader);
-            item.answer.items.forEach((item) => addContent(item, sectionDiv));
-            break;
-          }
-          case "example": {
-            const code = document.createElement("pre");
-            code.innerHTML = `<code>${item.code}</code>`;
-            sectionDiv.appendChild(code);
-            break;
-          }
-        }
-      });
-    } else {
-      // Exercise
-      const exerciseHeader = document.createElement("h3");
-      exerciseHeader.innerHTML = `Exercise: <u>${section.title}</u>`;
-      sectionDiv.appendChild(exerciseHeader);
-      const exerciseDesc = document.createElement("div");
-      exerciseDesc.innerHTML = section.description.asHtml;
-      sectionDiv.appendChild(exerciseDesc);
-
-      const codeDiv = document.createElement("pre");
-      codeDiv.innerHTML = `<code>${section.placeholderCode}</code>`;
-      sectionDiv.appendChild(codeDiv);
-
-      const solutionHeader = document.createElement("h4");
-      solutionHeader.innerHTML = `Solution`;
-      sectionDiv.appendChild(solutionHeader);
-
-      section.explainedSolution.items.forEach((item) =>
-        addContent(item, sectionDiv),
-      );
-    }
-    kataDiv.appendChild(sectionDiv);
-  });
-  return kataDiv;
-}
-
-function addContent(item: ExplainedSolutionItem, sectionDiv: HTMLDivElement) {
-  if (item.type === "text-content") {
-    const contentDiv = document.createElement("div");
-    contentDiv.innerHTML = item.asHtml;
-    sectionDiv.appendChild(contentDiv);
-  } else {
-    // example or solution
-    const codeDiv = document.createElement("pre");
-    codeDiv.innerHTML = `<code>${item.code}</code>`;
-    sectionDiv.appendChild(codeDiv);
-  }
-}
diff --git a/playground/src/kataViewer.tsx b/playground/src/kataViewer.tsx
new file mode 100644
index 00000000..00b65b87
--- /dev/null
+++ b/playground/src/kataViewer.tsx
@@ -0,0 +1,206 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+// import "preact/debug"; // Include this line only when debugging rendering
+
+import { render } from "preact";
+import { useEffect } from "preact/hooks";
+
+import {
+  Exercise,
+  ExplainedSolutionItem,
+  Kata,
+  Lesson,
+  getAllKatas,
+} from "qsharp-lang";
+
+declare global {
+  // The below are added by the MathJax and Highlight.js scripts
+  interface Window {
+    MathJax: any;
+    hljs: any;
+  }
+}
+
+window.MathJax = {
+  loader: {
+    load: ["[tex]/color", "[tex]/braket"],
+  },
+  tex: {
+    packages: { "[+]": ["color", "braket"] },
+    inlineMath: [
+      ["$", "$"],
+      ["\\(", "\\)"],
+    ],
+    formatError: (jax: any, err: any) => {
+      console.log("LaTeX processing error occurred. ", err, jax);
+      const errorNode = document.createElement("div");
+      errorNode.innerText = `LaTeX processing error: ${err.message}.\nLaTeX: ${jax.latex}\n\n`;
+      errorNode.style.fontSize = "20px";
+      errorNode.style.color = "red";
+      document.querySelector("#errors")?.appendChild(errorNode);
+      window.scroll(0, 0);
+      jax.formatError(err);
+    },
+  },
+  startup: {
+    pageReady: async () => {
+      await onload();
+      return window.MathJax.startup.defaultPageReady();
+    },
+  },
+};
+
+function Nav(props: {
+  katas: Kata[];
+  onnav: (index: number) => void;
+  selected: number;
+}) {
+  return (
+    <div class="nav">
+      {props.katas.map((kata, idx) => (
+        <>
+          <div
+            className={
+              idx === props.selected ? "nav-item nav-selected" : "nav-item"
+            }
+            onClick={() => props.onnav(idx)}
+          >
+            {kata.title}
+          </div>
+        </>
+      ))}
+    </div>
+  );
+}
+
+function KataEl(props: { kata: Kata }) {
+  useEffect(() => {
+    window.hljs.highlightAll();
+    window.MathJax.texReset();
+    window.MathJax.typesetClear();
+    window.MathJax.typesetPromise([".content"]);
+  }, [props.kata.id]);
+  window.scrollTo(0, 0);
+  return (
+    <div class="content" key={props.kata.id}>
+      <div id="errors"></div>
+      <h1>{props.kata.title}</h1>
+      {props.kata.sections.map((section) =>
+        section.type === "lesson" ? (
+          <LessonEl lesson={section} />
+        ) : (
+          <ExerciseEl exercise={section} />
+        ),
+      )}
+    </div>
+  );
+}
+
+function LessonEl(props: { lesson: Lesson }) {
+  const item = props.lesson;
+  return (
+    <>
+      <h2>{item.title}</h2>
+      {item.items.map((item) => {
+        switch (item.type) {
+          case "text-content":
+            return (
+              <div dangerouslySetInnerHTML={{ __html: item.asHtml }}></div>
+            );
+          case "question":
+            return (
+              <>
+                <h3>Question</h3>
+                <div
+                  dangerouslySetInnerHTML={{ __html: item.description.asHtml }}
+                />
+                <h3>Answer</h3>
+                {item.answer.items.map((answer) => (
+                  <ExplainedSolution item={answer} />
+                ))}
+              </>
+            );
+          case "example":
+            return (
+              <pre>
+                <code>{item.code}</code>
+              </pre>
+            );
+        }
+      })}
+    </>
+  );
+}
+
+function ExerciseEl(props: { exercise: Exercise }) {
+  const item = props.exercise;
+  return (
+    <>
+      <h2>{"Exercise: " + item.title}</h2>
+      <div dangerouslySetInnerHTML={{ __html: item.description.asHtml }} />
+      <pre>
+        <code>{item.placeholderCode}</code>
+      </pre>
+      <h4>Solution</h4>
+      {item.explainedSolution.items.map((item) => (
+        <ExplainedSolution item={item} />
+      ))}
+    </>
+  );
+}
+
+function ExplainedSolution(props: { item: ExplainedSolutionItem }) {
+  const item = props.item;
+  return (
+    <div>
+      {item.type === "text-content" ? (
+        <div dangerouslySetInnerHTML={{ __html: item.asHtml }}></div>
+      ) : (
+        <pre>
+          <code>{item.code}</code>
+        </pre>
+      )}
+    </div>
+  );
+}
+
+async function onload() {
+  const katas = await getAllKatas();
+  const app = document.querySelector("#app") as HTMLDivElement;
+
+  function onRender(index: number) {
+    render(
+      <>
+        <Nav katas={katas} onnav={onNav} selected={index} />
+        <KataEl kata={katas[index]} />
+      </>,
+      app,
+    );
+  }
+
+  // Update the history and URL fragment if the user navigates katas
+  function onNav(index: number) {
+    history.pushState(null, "", "#" + katas[index].id);
+    onRender(index);
+  }
+
+  // Handle back/forward navigation
+  window.addEventListener("popstate", () => {
+    loadFromUrl();
+  });
+
+  function loadFromUrl() {
+    let kataIndex = 0;
+    if (window.location.hash) {
+      const kataId = window.location.hash.slice(1);
+      kataIndex = katas.findIndex((kata) => kata.id === kataId);
+    }
+    if (kataIndex < 0) kataIndex = 0;
+
+    onRender(kataIndex);
+  }
+
+  // Do initial load
+  loadFromUrl();
+}
diff --git a/playground/src/state.tsx b/playground/src/state.tsx
index 285ffb90..c45a255d 100644
--- a/playground/src/state.tsx
+++ b/playground/src/state.tsx
@@ -17,7 +17,7 @@ function formatComplex(real: number, imag: number) {
   return `${r}${i}`;
 }
 
-export function StateTable(props: { dump: Dump; latexDump: string }) {
+export function StateTable(props: { dump: Dump; latexDump: string | null }) {
   return (
     <div>
       <table class="state-table">
@@ -55,7 +55,7 @@ export function StateTable(props: { dump: Dump; latexDump: string }) {
           })}
         </tbody>
       </table>
-      <Markdown markdown={props.latexDump} />
+      <Markdown markdown={props.latexDump ?? ""} />
       <br></br>
     </div>
   );
diff --git a/samples/language/Array.qs b/samples/language/Array.qs
index 8c032222..b46aed19 100644
--- a/samples/language/Array.qs
+++ b/samples/language/Array.qs
@@ -23,16 +23,25 @@ namespace MyQuantumApp {
 
         // A basic Int Array literal
         let intArray : Int[] = [1, 2, 3, 4];
+        Message($"Integer Array : {intArray} of length {Length(intArray)}");
+
         // A basic String Array literal
         let stringArray = ["a", "string", "array"];
+        Message($"{stringArray}");
 
         // A new array expression creating the array `[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]`
-        let repeatedArray = Repeated(0, 10);
+        let repeatedArray = [0, size = 10];
+        Message($"{repeatedArray}");
+        let repeatedArray = Repeated(0, 10);  // contains [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
+        Message($"{repeatedArray}");
 
         // Arrays can be sliced with ranges.
         let slice = intArray[1..2..4];  // contains [2,4]
+        Message($"{slice}");
         let slice = intArray[2..-1..0]; // contains [3,2,1]
+        Message($"{slice}");
         let slice = intArray[...]; // contains [1, 2, 3, 4];
+        Message($"{slice}");
 
         return intArray;
     }
diff --git a/watch.mjs b/watch.mjs
index 95ae0ed8..27b37ebc 100644
--- a/watch.mjs
+++ b/watch.mjs
@@ -9,17 +9,16 @@ Always use ./build.py to ensure that all projects are built correctly before che
 Also run ./build.py to do any initial repo setup (npm install, copying 3rd party libs, etc.)
 
 Once running, any changes to the source code for Rust directories listed, or for
-the npm, vscode, or playground projects, should automatically recompile. Just
+the npm, vscode, docs, katas, samples or playground projects, should automatically recompile. Just
 reload the playground page or reload the VS Code window to see the changes.
 
 Notes:
 
-- This builds the wasm module, npm package, VS Code extension, and runs the playground.
+- This builds the wasm module, npm package, VS Code extension, docs, katas, samples and runs the playground.
 - It does NOT build Python packages or native binaries (currently).
-- It does NOT watch for docs, katas, or samples changes (currently).
 - It does NOT build the Node.js wasm package (or run any of the node unit tests).
 - It builds debug binaries (whereas ./build.py builds for release).
-- Future updates could include watching for katas changes, and supporting '--release'
+- Future updates could include supporting '--release'
 
 */
 


Test patch:
diff --git a/compiler/qsc/src/interpret/tests.rs b/compiler/qsc/src/interpret/tests.rs
index 796083a8..893a9927 100644
--- a/compiler/qsc/src/interpret/tests.rs
+++ b/compiler/qsc/src/interpret/tests.rs
@@ -830,13 +830,12 @@ mod given_interpreter {
                 block_0:
                   call void @__quantum__qis__mresetz__body(%Qubit* inttoptr (i64 0 to %Qubit*), %Result* inttoptr (i64 0 to %Result*))
                   %var_0 = call i1 @__quantum__qis__read_result__body(%Result* inttoptr (i64 0 to %Result*))
-                  %var_1 = icmp eq i1 %var_0, true
                   %var_2 = call i1 @__quantum__qis__read_result__body(%Result* inttoptr (i64 0 to %Result*))
                   %var_3 = icmp eq i1 %var_2, false
                   call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
                   call void @__quantum__rt__result_record_output(%Result* inttoptr (i64 0 to %Result*), i8* null)
                   call void @__quantum__rt__tuple_record_output(i64 2, i8* null)
-                  call void @__quantum__rt__bool_record_output(i1 %var_1, i8* null)
+                  call void @__quantum__rt__bool_record_output(i1 %var_0, i8* null)
                   call void @__quantum__rt__bool_record_output(i1 %var_3, i8* null)
                   ret void
                 }
diff --git a/compiler/qsc_eval/src/state/tests.rs b/compiler/qsc_eval/src/state/tests.rs
index 199f22d1..1f742f74 100644
--- a/compiler/qsc_eval/src/state/tests.rs
+++ b/compiler/qsc_eval/src/state/tests.rs
@@ -458,330 +458,136 @@ fn assert_latex_for_algebraic(
     let number = AlgebraicNumber::new(&RationalNumber::new(numerator, denominator), root);
     let mut latex = String::with_capacity(50);
     write_latex_for_algebraic_number(&mut latex, &number, render_one);
-    expected.assert_debug_eq(&latex);
+    expected.assert_eq(&latex);
 }
 
 #[test]
 fn check_get_latex_for_algebraic() {
-    assert_latex_for_algebraic(
-        &expect!([r#"
-            "\\frac{5 \\sqrt{2}}{3}"
-        "#]),
-        5,
-        3,
-        2,
-        false,
-    );
-    assert_latex_for_algebraic(
-        &expect!([r#"
-            "\\frac{5 \\sqrt{2}}{3}"
-        "#]),
-        -5,
-        3,
-        2,
-        false,
-    );
-    assert_latex_for_algebraic(
-        &expect!([r#"
-            "\\frac{\\sqrt{2}}{3}"
-        "#]),
-        1,
-        3,
-        2,
-        false,
-    );
-    assert_latex_for_algebraic(
-        &expect!([r#"
-            "5 \\sqrt{2}"
-        "#]),
-        5,
-        1,
-        2,
-        false,
-    );
-    assert_latex_for_algebraic(
-        &expect!([r#"
-            "\\frac{5}{3}"
-        "#]),
-        5,
-        3,
-        1,
-        false,
-    );
-    assert_latex_for_algebraic(
-        &expect!([r#"
-            "\\sqrt{2}"
-        "#]),
-        1,
-        1,
-        2,
-        false,
-    );
-    assert_latex_for_algebraic(
-        &expect!([r#"
-            "5"
-        "#]),
-        5,
-        1,
-        1,
-        false,
-    );
-    assert_latex_for_algebraic(
-        &expect!([r#"
-            "\\frac{1}{3}"
-        "#]),
-        1,
-        3,
-        1,
-        false,
-    );
-    assert_latex_for_algebraic(
-        &expect!([r#"
-            ""
-        "#]),
-        1,
-        1,
-        1,
-        false,
-    );
-    assert_latex_for_algebraic(
-        &expect!([r#"
-            "1"
-        "#]),
-        1,
-        1,
-        1,
-        true,
-    );
+    assert_latex_for_algebraic(&expect!([r"\frac{5 \sqrt{2}}{3}"]), 5, 3, 2, false);
+    assert_latex_for_algebraic(&expect!([r"\frac{5 \sqrt{2}}{3}"]), -5, 3, 2, false);
+    assert_latex_for_algebraic(&expect!([r"\frac{\sqrt{2}}{3}"]), 1, 3, 2, false);
+    assert_latex_for_algebraic(&expect!([r"5 \sqrt{2}"]), 5, 1, 2, false);
+    assert_latex_for_algebraic(&expect!([r"\frac{5}{3}"]), 5, 3, 1, false);
+    assert_latex_for_algebraic(&expect!([r"\sqrt{2}"]), 1, 1, 2, false);
+    assert_latex_for_algebraic(&expect!("5"), 5, 1, 1, false);
+    assert_latex_for_algebraic(&expect!([r"\frac{1}{3}"]), 1, 3, 1, false);
+    assert_latex_for_algebraic(&expect!(""), 1, 1, 1, false);
+    assert_latex_for_algebraic(&expect!("1"), 1, 1, 1, true);
 }
 
 fn assert_latex_for_decimal(expected: &Expect, number: f64, render_one: bool) {
     let number = DecimalNumber::new(number);
     let mut latex = String::with_capacity(50);
     write_latex_for_decimal_number(&mut latex, &number, render_one);
-    expected.assert_debug_eq(&latex);
+    expected.assert_eq(&latex);
 }
 
 #[test]
 fn check_get_latex_for_decimal() {
-    assert_latex_for_decimal(
-        &expect!([r#"
-            "0.25"
-        "#]),
-        0.25,
-        false,
-    );
-    assert_latex_for_decimal(
-        &expect!([r#"
-            "0.25"
-        "#]),
-        -0.25,
-        false,
-    );
-    assert_latex_for_decimal(
-        &expect!([r#"
-            ""
-        "#]),
-        -1.0,
-        false,
-    );
-    assert_latex_for_decimal(
-        &expect!([r#"
-            ""
-        "#]),
-        1.0,
-        false,
-    );
-    assert_latex_for_decimal(
-        &expect!([r#"
-            "1"
-        "#]),
-        1.0,
-        true,
-    );
+    assert_latex_for_decimal(&expect!("0.25"), 0.25, false);
+    assert_latex_for_decimal(&expect!("0.25"), -0.25, false);
+    assert_latex_for_decimal(&expect!(""), -1.0, false);
+    assert_latex_for_decimal(&expect!(""), 1.0, false);
+    assert_latex_for_decimal(&expect!("1"), 1.0, true);
 }
 
 fn assert_latex_for_real(expected: &Expect, x: f64, render_one: bool) {
     let number = RealNumber::recognize(x);
     let mut latex = String::with_capacity(50);
     write_latex_for_real_number(&mut latex, &number, render_one);
-    expected.assert_debug_eq(&latex);
+    expected.assert_eq(&latex);
 }
 
 #[test]
 fn check_get_latex_for_real() {
-    assert_latex_for_real(
-        &expect!([r#"
-        "\\frac{1}{4}"
-    "#]),
-        1.0 / 4.0,
-        false,
-    );
-    assert_latex_for_real(
-        &expect!([r#"
-        "\\frac{1}{4}"
-    "#]),
-        -1.0 / 4.0,
-        false,
-    );
-    assert_latex_for_real(
-        &expect!([r#"
-            ""
-        "#]),
-        1.0,
-        false,
-    );
-    assert_latex_for_real(
-        &expect!([r#"
-            "1"
-        "#]),
-        1.0,
-        true,
-    );
-    assert_latex_for_real(
-        &expect!([r#"
-            "0"
-        "#]),
-        0.0,
-        false,
-    );
-    assert_latex_for_real(
-        &expect!([r#"
-            "0.0003"
-        "#]),
-        1.0 / 4000.0,
-        false,
-    );
+    assert_latex_for_real(&expect!([r"\frac{1}{4}"]), 1.0 / 4.0, false);
+    assert_latex_for_real(&expect!([r"\frac{1}{4}"]), -1.0 / 4.0, false);
+    assert_latex_for_real(&expect!(""), 1.0, false);
+    assert_latex_for_real(&expect!("1"), 1.0, true);
+    assert_latex_for_real(&expect!("0"), 0.0, false);
+    assert_latex_for_real(&expect!("0.0003"), 1.0 / 4000.0, false);
 }
 
 fn assert_latex_for_cartesian(expected: &Expect, re: f64, im: f64, render_plus: bool) {
     let number = CartesianForm::recognize(re, im);
     let mut latex = String::with_capacity(50);
     write_latex_for_cartesian_form(&mut latex, &number, render_plus);
-    expected.assert_debug_eq(&latex);
+    expected.assert_eq(&latex);
 }
 
 #[test]
 fn check_get_latex_for_cartesian() {
     assert_latex_for_cartesian(
-        &expect!([r#"
-            "\\left( \\frac{1}{2}+\\frac{1}{2}i \\right)"
-        "#]),
+        &expect!([r"\left( \frac{1}{2}+\frac{1}{2}i \right)"]),
         0.5,
         0.5,
         false,
     );
     assert_latex_for_cartesian(
-        &expect!([r#"
-            "-\\left( \\frac{1}{2}-\\frac{1}{2}i \\right)"
-        "#]),
+        &expect!([r"-\left( \frac{1}{2}-\frac{1}{2}i \right)"]),
         -0.5,
         0.5,
         false,
     );
     assert_latex_for_cartesian(
-        &expect!([r#"
-            "\\left( \\frac{1}{2}-\\frac{1}{2}i \\right)"
-        "#]),
+        &expect!([r"\left( \frac{1}{2}-\frac{1}{2}i \right)"]),
         0.5,
         -0.5,
         false,
     );
     assert_latex_for_cartesian(
-        &expect!([r#"
-            "-\\left( \\frac{1}{2}+\\frac{1}{2}i \\right)"
-        "#]),
-        -0.5,
+        &expect!([r"-\left( \frac{1}{2}+\frac{1}{2}i \right)"]),
         -0.5,
-        false,
-    );
-    assert_latex_for_cartesian(
-        &expect!([r#"
-            "-\\frac{1}{2}i"
-        "#]),
-        0.0,
-        -0.5,
-        false,
-    );
-    assert_latex_for_cartesian(
-        &expect!([r#"
-            "-\\frac{1}{2}"
-        "#]),
         -0.5,
-        0.0,
         false,
     );
-    assert_latex_for_cartesian(
-        &expect!([r#"
-            ""
-        "#]),
-        1.0,
-        0.0,
-        false,
-    );
-    assert_latex_for_cartesian(
-        &expect!([r#"
-            "+"
-        "#]),
-        1.0,
-        0.0,
-        true,
-    );
+    assert_latex_for_cartesian(&expect!([r"-\frac{1}{2}i"]), 0.0, -0.5, false);
+    assert_latex_for_cartesian(&expect!([r"-\frac{1}{2}"]), -0.5, 0.0, false);
+    assert_latex_for_cartesian(&expect!(""), 1.0, 0.0, false);
+    assert_latex_for_cartesian(&expect!("+"), 1.0, 0.0, true);
 }
 
 fn assert_latex_for_polar(expected: &Expect, re: f64, im: f64, render_plus: bool) {
     let number = PolarForm::recognize(re, im).expect("Polar form not recognized.");
     let mut latex = String::with_capacity(50);
     write_latex_for_polar_form(&mut latex, &number, render_plus);
-    expected.assert_debug_eq(&latex);
+    expected.assert_eq(&latex);
 }
 
 #[test]
 fn check_get_latex_for_polar() {
     assert_latex_for_polar(
-        &expect!([r#"
-            "+\\frac{1}{2} e^{ i \\pi / 3}"
-        "#]),
+        &expect!([r"+\frac{1}{2} e^{ i \pi / 3}"]),
         1.0 / 2.0 * (PI / 3.0).cos(),
         1.0 / 2.0 * (PI / 3.0).sin(),
         true,
     );
     assert_latex_for_polar(
-        &expect!([r#"
-            "+ e^{ i \\pi / 3}"
-        "#]),
+        &expect!([r"+ e^{ i \pi / 3}"]),
         (PI / 3.0).cos(),
         (PI / 3.0).sin(),
         true,
     );
     assert_latex_for_polar(
-        &expect!([r#"
-            "+\\frac{1}{2} e^{- i \\pi / 3}"
-        "#]),
+        &expect!([r"+\frac{1}{2} e^{- i \pi / 3}"]),
         1.0 / 2.0 * (-PI / 3.0).cos(),
         1.0 / 2.0 * (-PI / 3.0).sin(),
         true,
     );
     assert_latex_for_polar(
-        &expect!([r#"
-            "+\\frac{1}{2} e^{2 i \\pi / 3}"
-        "#]),
+        &expect!([r"+\frac{1}{2} e^{2 i \pi / 3}"]),
         1.0 / 2.0 * (2.0 * PI / 3.0).cos(),
         1.0 / 2.0 * (2.0 * PI / 3.0).sin(),
         true,
     );
     assert_latex_for_polar(
-        &expect!([r#"
-            "+\\frac{1}{2} e^{-2 i \\pi / 3}"
-        "#]),
+        &expect!([r"+\frac{1}{2} e^{-2 i \pi / 3}"]),
         1.0 / 2.0 * (-2.0 * PI / 3.0).cos(),
         1.0 / 2.0 * (-2.0 * PI / 3.0).sin(),
         true,
     );
     assert_latex_for_polar(
-        &expect!([r#"
-            "\\frac{1}{2} e^{-2 i \\pi / 3}"
-        "#]),
+        &expect!([r"\frac{1}{2} e^{-2 i \pi / 3}"]),
         1.0 / 2.0 * (-2.0 * PI / 3.0).cos(),
         1.0 / 2.0 * (-2.0 * PI / 3.0).sin(),
         false,
@@ -795,47 +601,37 @@ fn assert_latex_for_term(expected: &Expect, re: f64, im: f64, render_plus: bool)
     };
     let mut latex = String::with_capacity(50);
     write_latex_for_term(&mut latex, &t, render_plus);
-    expected.assert_debug_eq(&latex);
+    expected.assert_eq(&latex);
 }
 
 #[test]
 fn check_get_latex_for_term() {
     assert_latex_for_term(
-        &expect!([r#"
-            "+\\frac{1}{2} e^{ i \\pi / 3}"
-        "#]),
+        &expect!([r"+\frac{1}{2} e^{ i \pi / 3}"]),
         1.0 / 2.0 * (PI / 3.0).cos(),
         1.0 / 2.0 * (PI / 3.0).sin(),
         true,
     );
     assert_latex_for_term(
-        &expect!([r#"
-            "+\\left( \\frac{1}{2}+\\frac{1}{2}i \\right)"
-        "#]),
+        &expect!([r"+\left( \frac{1}{2}+\frac{1}{2}i \right)"]),
         1.0 / 2.0,
         1.0 / 2.0,
         true,
     );
     assert_latex_for_term(
-        &expect!([r#"
-            "\\left( \\frac{1}{2}+\\frac{1}{2}i \\right)"
-        "#]),
+        &expect!([r"\left( \frac{1}{2}+\frac{1}{2}i \right)"]),
         1.0 / 2.0,
         1.0 / 2.0,
         false,
     );
     assert_latex_for_term(
-        &expect!([r#"
-            "-\\left( \\frac{1}{2}-\\frac{1}{2}i \\right)"
-        "#]),
+        &expect!([r"-\left( \frac{1}{2}-\frac{1}{2}i \right)"]),
         -1.0 / 2.0,
         1.0 / 2.0,
         true,
     );
     assert_latex_for_term(
-        &expect!([r#"
-            "-\\left( \\frac{1}{2}-\\frac{1}{2}i \\right)"
-        "#]),
+        &expect!([r"-\left( \frac{1}{2}-\frac{1}{2}i \right)"]),
         -1.0 / 2.0,
         1.0 / 2.0,
         false,
@@ -844,47 +640,36 @@ fn check_get_latex_for_term() {
 
 #[test]
 fn check_get_latex() {
-    expect!([r#"
-        "$|\\psi\\rangle = \\left( \\frac{1}{2}+\\frac{1}{2}i \\right)|00\\rangle$"
-    "#])
-    .assert_debug_eq(&get_latex(
-        &vec![(0_u8.into(), Complex64::new(0.5, 0.5))],
-        2,
-    ));
-    expect!([r#"
-        "$|\\psi\\rangle = -|00\\rangle$"
-    "#])
-    .assert_debug_eq(&get_latex(
-        &vec![(0_u8.into(), Complex64::new(-1.0, 0.0))],
-        2,
-    ));
-    expect!([r#"
-        "$|\\psi\\rangle = -i|00\\rangle$"
-    "#])
-    .assert_debug_eq(&get_latex(
-        &vec![(0_u8.into(), Complex64::new(0.0, -1.0))],
-        2,
-    ));
-    expect!([r#"
-        "$|\\psi\\rangle =  e^{-2 i \\pi / 3}|00\\rangle$"
-    "#])
-    .assert_debug_eq(&get_latex(
-        &vec![(
-            0_u8.into(),
-            Complex64::new((-2.0 * PI / 3.0).cos(), (-2.0 * PI / 3.0).sin()),
-        )],
-        2,
-    ));
-    expect!([r#"
-        "$|\\psi\\rangle = \\left( 1+\\frac{\\sqrt{2}}{2}i \\right)|00\\rangle+\\left( 1+\\frac{\\sqrt{2}}{2}i \\right)|10\\rangle$"
-    "#])
-    .assert_debug_eq(&get_latex(
+    expect!([r"$|\psi\rangle = \left( \frac{1}{2}+\frac{1}{2}i \right)|00\rangle$"]).assert_eq(
+        &get_latex(&vec![(0_u8.into(), Complex64::new(0.5, 0.5))], 2)
+            .expect("expected valid latex"),
+    );
+    expect!([r"$|\psi\rangle = -|00\rangle$"]).assert_eq(
+        &get_latex(&vec![(0_u8.into(), Complex64::new(-1.0, 0.0))], 2)
+            .expect("expected valid latex"),
+    );
+    expect!([r"$|\psi\rangle = -i|00\rangle$"]).assert_eq(
+        &get_latex(&vec![(0_u8.into(), Complex64::new(0.0, -1.0))], 2)
+            .expect("expected valid latex"),
+    );
+    expect!([r"$|\psi\rangle =  e^{-2 i \pi / 3}|00\rangle$"]).assert_eq(
+        &get_latex(
+            &vec![(
+                0_u8.into(),
+                Complex64::new((-2.0 * PI / 3.0).cos(), (-2.0 * PI / 3.0).sin()),
+            )],
+            2,
+        )
+        .expect("expected valid latex"),
+    );
+    expect!([r"$|\psi\rangle = \left( 1+\frac{\sqrt{2}}{2}i \right)|00\rangle+\left( 1+\frac{\sqrt{2}}{2}i \right)|10\rangle$"])
+    .assert_eq(&get_latex(
         &vec![
             (0_u8.into(), Complex64::new(1.0, 1.0 / 2.0_f64.sqrt())),
             (2_u8.into(), Complex64::new(1.0, 1.0 / 2.0_f64.sqrt())),
         ],
         2,
-    ));
+    ).expect("expected valid latex"));
 }
 
 #[test]
@@ -903,20 +688,18 @@ fn check_get_latex_perf() {
         ),
     ];
 
-    expect!([r#"
-        "$|\\psi\\rangle = \\frac{1}{2}|00\\rangle+\\frac{1}{2} e^{ i \\pi / 4}|01\\rangle+\\frac{1}{2}i|10\\rangle+\\frac{1}{2} e^{3 i \\pi / 4}|11\\rangle$"
-    "#])
-    .assert_debug_eq(&get_latex(
+    expect!([r"$|\psi\rangle = \frac{1}{2}|00\rangle+\frac{1}{2} e^{ i \pi / 4}|01\rangle+\frac{1}{2}i|10\rangle+\frac{1}{2} e^{3 i \pi / 4}|11\rangle$"])
+    .assert_eq(&get_latex(
         &state,
         2,
-    ));
+    ).expect("expected valid latex"));
 
     print!("Start...");
     let start = Instant::now();
     let mut l: usize = 0;
     for _ in 0..1_000 {
         let s = get_latex(&state, 2);
-        l += s.len();
+        l += s.map_or(0, |s| s.len());
     }
     println!(
         "Done. {} bytes in {:?}.",
diff --git a/compiler/qsc_partial_eval/tests/arrays.rs b/compiler/qsc_partial_eval/tests/arrays.rs
index f34bd59c..17ce85f8 100644
--- a/compiler/qsc_partial_eval/tests/arrays.rs
+++ b/compiler/qsc_partial_eval/tests/arrays.rs
@@ -141,7 +141,7 @@ fn array_with_hybrid_content() {
             Block:
                 Call id(1), args( Qubit(0), Result(0), )
                 Variable(0, Boolean) = Call id(2), args( Result(0), )
-                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(true)
+                Variable(1, Boolean) = Store Variable(0, Boolean)
                 Call id(3), args( Integer(2), Pointer, )
                 Call id(4), args( Bool(true), Pointer, )
                 Call id(4), args( Variable(1, Boolean), Pointer, )
@@ -215,231 +215,6 @@ fn array_repeat_with_dynamic_content() {
     );
 }
 
-#[test]
-fn array_of_results_replace_element_at_index_with_dynamic_content() {
-    let program = get_rir_program(indoc! {r#"
-        namespace Test {
-            @EntryPoint()
-            operation Main() : Result[] {
-                use (q0, q1) = (Qubit(), Qubit());
-                mutable arr = [MResetZ(q0), Zero];
-                set arr w/= 1 <- MResetZ(q1);
-                arr
-            }
-        }
-    "#});
-    let measurement_callable_id = CallableId(1);
-    assert_callable(
-        &program,
-        measurement_callable_id,
-        &expect![[r#"
-            Callable:
-                name: __quantum__qis__mresetz__body
-                call_type: Measurement
-                input_type:
-                    [0]: Qubit
-                    [1]: Result
-                output_type: <VOID>
-                body: <NONE>"#]],
-    );
-    let array_output_recording_callable_id = CallableId(2);
-    assert_callable(
-        &program,
-        array_output_recording_callable_id,
-        &expect![[r#"
-            Callable:
-                name: __quantum__rt__array_record_output
-                call_type: OutputRecording
-                input_type:
-                    [0]: Integer
-                    [1]: Pointer
-                output_type: <VOID>
-                body: <NONE>"#]],
-    );
-    let result_output_recording_callable_id = CallableId(3);
-    assert_callable(
-        &program,
-        result_output_recording_callable_id,
-        &expect![[r#"
-            Callable:
-                name: __quantum__rt__result_record_output
-                call_type: OutputRecording
-                input_type:
-                    [0]: Result
-                    [1]: Pointer
-                output_type: <VOID>
-                body: <NONE>"#]],
-    );
-    assert_block_instructions(
-        &program,
-        BlockId(0),
-        &expect![[r#"
-            Block:
-                Call id(1), args( Qubit(0), Result(0), )
-                Call id(1), args( Qubit(1), Result(1), )
-                Call id(2), args( Integer(2), Pointer, )
-                Call id(3), args( Result(0), Pointer, )
-                Call id(3), args( Result(1), Pointer, )
-                Return"#]],
-    );
-}
-
-#[test]
-fn array_of_bools_replace_element_at_index_with_dynamic_content() {
-    let program = get_rir_program(indoc! {r#"
-        namespace Test {
-            @EntryPoint()
-            operation Main() : Bool[] {
-                use (q0, q1) = (Qubit(), Qubit());
-                mutable arr = [MResetZ(q0) == Zero, true];
-                set arr w/= 1 <- MResetZ(q1) == One;
-                arr
-            }
-        }
-    "#});
-    let measurement_callable_id = CallableId(1);
-    assert_callable(
-        &program,
-        measurement_callable_id,
-        &expect![[r#"
-            Callable:
-                name: __quantum__qis__mresetz__body
-                call_type: Measurement
-                input_type:
-                    [0]: Qubit
-                    [1]: Result
-                output_type: <VOID>
-                body: <NONE>"#]],
-    );
-    let readout_callable_id = CallableId(2);
-    assert_callable(
-        &program,
-        readout_callable_id,
-        &expect![[r#"
-            Callable:
-                name: __quantum__qis__read_result__body
-                call_type: Readout
-                input_type:
-                    [0]: Result
-                output_type: Boolean
-                body: <NONE>"#]],
-    );
-    let array_output_recording_callable_id = CallableId(3);
-    assert_callable(
-        &program,
-        array_output_recording_callable_id,
-        &expect![[r#"
-            Callable:
-                name: __quantum__rt__array_record_output
-                call_type: OutputRecording
-                input_type:
-                    [0]: Integer
-                    [1]: Pointer
-                output_type: <VOID>
-                body: <NONE>"#]],
-    );
-    let bool_output_recording_callable_id = CallableId(4);
-    assert_callable(
-        &program,
-        bool_output_recording_callable_id,
-        &expect![[r#"
-            Callable:
-                name: __quantum__rt__bool_record_output
-                call_type: OutputRecording
-                input_type:
-                    [0]: Boolean
-                    [1]: Pointer
-                output_type: <VOID>
-                body: <NONE>"#]],
-    );
-    assert_block_instructions(
-        &program,
-        BlockId(0),
-        &expect![[r#"
-            Block:
-                Call id(1), args( Qubit(0), Result(0), )
-                Variable(0, Boolean) = Call id(2), args( Result(0), )
-                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
-                Call id(1), args( Qubit(1), Result(1), )
-                Variable(2, Boolean) = Call id(2), args( Result(1), )
-                Variable(3, Boolean) = Icmp Eq, Variable(2, Boolean), Bool(true)
-                Call id(3), args( Integer(2), Pointer, )
-                Call id(4), args( Variable(1, Boolean), Pointer, )
-                Call id(4), args( Variable(3, Boolean), Pointer, )
-                Return"#]],
-    );
-}
-
-#[test]
-fn empty_array_of_results_in_place_concatenation() {
-    let program = get_rir_program(indoc! {r#"
-        namespace Test {
-            @EntryPoint()
-            operation Main() : Result[] {
-                use (q0, q1) = (Qubit(), Qubit());
-                mutable results = [];
-                set results += [MResetZ(q0)];
-                set results += [MResetZ(q1)];
-                results
-            }
-        }
-    "#});
-    let measurement_callable_id = CallableId(1);
-    assert_callable(
-        &program,
-        measurement_callable_id,
-        &expect![[r#"
-            Callable:
-                name: __quantum__qis__mresetz__body
-                call_type: Measurement
-                input_type:
-                    [0]: Qubit
-                    [1]: Result
-                output_type: <VOID>
-                body: <NONE>"#]],
-    );
-    let array_output_recording_callable_id = CallableId(2);
-    assert_callable(
-        &program,
-        array_output_recording_callable_id,
-        &expect![[r#"
-            Callable:
-                name: __quantum__rt__array_record_output
-                call_type: OutputRecording
-                input_type:
-                    [0]: Integer
-                    [1]: Pointer
-                output_type: <VOID>
-                body: <NONE>"#]],
-    );
-    let result_output_recording_callable_id = CallableId(3);
-    assert_callable(
-        &program,
-        result_output_recording_callable_id,
-        &expect![[r#"
-            Callable:
-                name: __quantum__rt__result_record_output
-                call_type: OutputRecording
-                input_type:
-                    [0]: Result
-                    [1]: Pointer
-                output_type: <VOID>
-                body: <NONE>"#]],
-    );
-    assert_block_instructions(
-        &program,
-        BlockId(0),
-        &expect![[r#"
-            Block:
-                Call id(1), args( Qubit(0), Result(0), )
-                Call id(1), args( Qubit(1), Result(1), )
-                Call id(2), args( Integer(2), Pointer, )
-                Call id(3), args( Result(0), Pointer, )
-                Call id(3), args( Result(1), Pointer, )
-                Return"#]],
-    );
-}
-
 #[test]
 fn result_at_index_in_array() {
     let program = get_rir_program(indoc! {r#"
@@ -491,72 +266,3 @@ fn result_at_index_in_array() {
                 Return"#]],
     );
 }
-
-#[test]
-fn non_empty_array_of_results_in_place_concatenation() {
-    let program = get_rir_program(indoc! {r#"
-        namespace Test {
-            @EntryPoint()
-            operation Main() : Result[] {
-                use (q0, q1) = (Qubit(), Qubit());
-                mutable results = [MResetZ(q0)];
-                set results += [MResetZ(q1)];
-                results
-            }
-        }
-    "#});
-    let measurement_callable_id = CallableId(1);
-    assert_callable(
-        &program,
-        measurement_callable_id,
-        &expect![[r#"
-            Callable:
-                name: __quantum__qis__mresetz__body
-                call_type: Measurement
-                input_type:
-                    [0]: Qubit
-                    [1]: Result
-                output_type: <VOID>
-                body: <NONE>"#]],
-    );
-    let array_output_recording_callable_id = CallableId(2);
-    assert_callable(
-        &program,
-        array_output_recording_callable_id,
-        &expect![[r#"
-            Callable:
-                name: __quantum__rt__array_record_output
-                call_type: OutputRecording
-                input_type:
-                    [0]: Integer
-                    [1]: Pointer
-                output_type: <VOID>
-                body: <NONE>"#]],
-    );
-    let result_output_recording_callable_id = CallableId(3);
-    assert_callable(
-        &program,
-        result_output_recording_callable_id,
-        &expect![[r#"
-            Callable:
-                name: __quantum__rt__result_record_output
-                call_type: OutputRecording
-                input_type:
-                    [0]: Result
-                    [1]: Pointer
-                output_type: <VOID>
-                body: <NONE>"#]],
-    );
-    assert_block_instructions(
-        &program,
-        BlockId(0),
-        &expect![[r#"
-            Block:
-                Call id(1), args( Qubit(0), Result(0), )
-                Call id(1), args( Qubit(1), Result(1), )
-                Call id(2), args( Integer(2), Pointer, )
-                Call id(3), args( Result(0), Pointer, )
-                Call id(3), args( Result(1), Pointer, )
-                Return"#]],
-    );
-}
diff --git a/compiler/qsc_partial_eval/tests/assigns.rs b/compiler/qsc_partial_eval/tests/assigns.rs
index 05c46381..6821eb8d 100644
--- a/compiler/qsc_partial_eval/tests/assigns.rs
+++ b/compiler/qsc_partial_eval/tests/assigns.rs
@@ -191,7 +191,7 @@ fn assigning_dynamic_bool_updates_value_and_adds_store_instructions() {
                 Variable(0, Boolean) = Store Bool(false)
                 Call id(1), args( Qubit(0), Result(0), )
                 Variable(1, Boolean) = Call id(2), args( Result(0), )
-                Variable(2, Boolean) = Icmp Eq, Variable(1, Boolean), Bool(true)
+                Variable(2, Boolean) = Store Variable(1, Boolean)
                 Variable(0, Boolean) = Store Variable(2, Boolean)
                 Call id(3), args( Variable(0, Boolean), Pointer, )
                 Return"#]],
@@ -299,7 +299,7 @@ fn assigning_dynamic_int_updates_value_and_adds_store_instructions() {
                 Variable(0, Integer) = Store Integer(0)
                 Call id(1), args( Qubit(0), Result(0), )
                 Variable(1, Boolean) = Call id(2), args( Result(0), )
-                Variable(2, Boolean) = Icmp Eq, Variable(1, Boolean), Bool(true)
+                Variable(2, Boolean) = Store Variable(1, Boolean)
                 Branch Variable(2, Boolean), 2, 3
             Block 1:Block:
                 Variable(0, Integer) = Store Variable(3, Integer)
@@ -378,7 +378,7 @@ fn assigning_classical_bool_within_dynamic_if_expression_adds_store_instruction(
                 Variable(0, Boolean) = Store Bool(false)
                 Call id(1), args( Qubit(0), Result(0), )
                 Variable(1, Boolean) = Call id(2), args( Result(0), )
-                Variable(2, Boolean) = Icmp Eq, Variable(1, Boolean), Bool(true)
+                Variable(2, Boolean) = Store Variable(1, Boolean)
                 Branch Variable(2, Boolean), 2, 1
             Block 1:Block:
                 Call id(3), args( Variable(0, Boolean), Pointer, )
@@ -491,3 +491,1538 @@ fn assigning_result_literal_within_dynamic_if_expression_produces_error() {
         ]],
     );
 }
+
+#[test]
+fn array_of_results_replace_element_at_index_with_dynamic_content() {
+    let program = get_rir_program(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result[] {
+                use (q0, q1) = (Qubit(), Qubit());
+                mutable arr = [MResetZ(q0), Zero];
+                set arr w/= 1 <- MResetZ(q1);
+                arr
+            }
+        }
+    "#});
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let array_output_recording_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        array_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__array_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let result_output_recording_callable_id = CallableId(3);
+    assert_callable(
+        &program,
+        result_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__result_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Result
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Call id(1), args( Qubit(1), Result(1), )
+                Call id(2), args( Integer(2), Pointer, )
+                Call id(3), args( Result(0), Pointer, )
+                Call id(3), args( Result(1), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn array_of_bools_replace_element_at_index_with_dynamic_content() {
+    let program = get_rir_program(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool[] {
+                use (q0, q1) = (Qubit(), Qubit());
+                mutable arr = [MResetZ(q0) == Zero, true];
+                set arr w/= 1 <- MResetZ(q1) == One;
+                arr
+            }
+        }
+    "#});
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__read_result__body
+                call_type: Readout
+                input_type:
+                    [0]: Result
+                output_type: Boolean
+                body: <NONE>"#]],
+    );
+    let array_output_recording_callable_id = CallableId(3);
+    assert_callable(
+        &program,
+        array_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__array_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let bool_output_recording_callable_id = CallableId(4);
+    assert_callable(
+        &program,
+        bool_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__bool_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Boolean
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+                Call id(1), args( Qubit(1), Result(1), )
+                Variable(2, Boolean) = Call id(2), args( Result(1), )
+                Variable(3, Boolean) = Store Variable(2, Boolean)
+                Call id(3), args( Integer(2), Pointer, )
+                Call id(4), args( Variable(1, Boolean), Pointer, )
+                Call id(4), args( Variable(3, Boolean), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn empty_array_of_results_in_place_concatenation() {
+    let program = get_rir_program(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result[] {
+                use (q0, q1) = (Qubit(), Qubit());
+                mutable results = [];
+                set results += [MResetZ(q0)];
+                set results += [MResetZ(q1)];
+                results
+            }
+        }
+    "#});
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let array_output_recording_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        array_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__array_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let result_output_recording_callable_id = CallableId(3);
+    assert_callable(
+        &program,
+        result_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__result_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Result
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Call id(1), args( Qubit(1), Result(1), )
+                Call id(2), args( Integer(2), Pointer, )
+                Call id(3), args( Result(0), Pointer, )
+                Call id(3), args( Result(1), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn non_empty_array_of_results_in_place_concatenation() {
+    let program = get_rir_program(indoc! {r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Result[] {
+                use (q0, q1) = (Qubit(), Qubit());
+                mutable results = [MResetZ(q0)];
+                set results += [MResetZ(q1)];
+                results
+            }
+        }
+    "#});
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let array_output_recording_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        array_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__array_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let result_output_recording_callable_id = CallableId(3);
+    assert_callable(
+        &program,
+        result_output_recording_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__result_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Result
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Call id(1), args( Qubit(1), Result(1), )
+                Call id(2), args( Integer(2), Pointer, )
+                Call id(3), args( Result(0), Pointer, )
+                Call id(3), args( Result(1), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn logical_and_assign_with_lhs_classical_true_is_optimized_as_store() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                let a = MResetZ(q) == One;
+                mutable b = true;
+                set b and= a;
+                b
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__rt__bool_record_output
+            call_type: OutputRecording
+            input_type:
+                [0]: Boolean
+                [1]: Pointer
+            output_type: <VOID>
+            body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Store Variable(0, Boolean)
+                Variable(2, Boolean) = Store Bool(true)
+                Variable(2, Boolean) = Store Variable(1, Boolean)
+                Call id(3), args( Variable(2, Boolean), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn logical_and_assign_with_lhs_classical_false_short_circuits_evaluation() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                let a = MResetZ(q) == One;
+                mutable b = false;
+                set b and= a;
+                b
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__rt__bool_record_output
+            call_type: OutputRecording
+            input_type:
+                [0]: Boolean
+                [1]: Pointer
+            output_type: <VOID>
+            body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Store Variable(0, Boolean)
+                Variable(2, Boolean) = Store Bool(false)
+                Variable(2, Boolean) = Store Bool(false)
+                Call id(3), args( Bool(false), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn logical_and_assign_with_dynamic_lhs_and_dynamic_rhs_raises_error() {
+    let error = get_partial_evaluation_error(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                mutable b = MResetZ(q) == Zero;
+                set b and= MResetZ(q) == One;
+                b
+            }
+        }
+        "#,
+    });
+    // This error message will no longer happen once Boolean operations with a dynamic LHS are supported.
+    assert_error(
+        &error,
+        &expect![[
+            r#"Unimplemented("bool binary operation with dynamic LHS", Span { lo: 139, hi: 167 })"#
+        ]],
+    );
+}
+
+#[test]
+fn logical_or_assign_with_lhs_classical_true_short_circuits_evaluation() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                let a = MResetZ(q) == One;
+                mutable b = true;
+                set b or= a;
+                b
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__rt__bool_record_output
+            call_type: OutputRecording
+            input_type:
+                [0]: Boolean
+                [1]: Pointer
+            output_type: <VOID>
+            body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Store Variable(0, Boolean)
+                Variable(2, Boolean) = Store Bool(true)
+                Variable(2, Boolean) = Store Bool(true)
+                Call id(3), args( Bool(true), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn logical_or_assign_with_lhs_classical_false_is_optimized_as_store() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                let a = MResetZ(q) == One;
+                mutable b = false;
+                set b or= a;
+                b
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__rt__bool_record_output
+            call_type: OutputRecording
+            input_type:
+                [0]: Boolean
+                [1]: Pointer
+            output_type: <VOID>
+            body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Store Variable(0, Boolean)
+                Variable(2, Boolean) = Store Bool(false)
+                Variable(2, Boolean) = Store Variable(1, Boolean)
+                Call id(3), args( Variable(2, Boolean), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn logical_or_assign_with_dynamic_lhs_and_dynamic_rhs_raises_error() {
+    let error = get_partial_evaluation_error(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                mutable b = MResetZ(q) == Zero;
+                set b or= MResetZ(q) == One;
+                b
+            }
+        }
+        "#,
+    });
+    // This error message will no longer happen once Boolean operations with a dynamic LHS are supported.
+    assert_error(
+        &error,
+        &expect![[
+            r#"Unimplemented("bool binary operation with dynamic LHS", Span { lo: 139, hi: 166 })"#
+        ]],
+    );
+}
+
+#[test]
+fn integer_assign_add_with_lhs_classical_integer_and_rhs_dynamic_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                mutable i = 0;
+                set i += MResetZ(q) == Zero ? 0 | 1;
+                i
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__integer_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Variable(0, Integer) = Store Integer(0)
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(1, Boolean) = Call id(2), args( Result(0), )
+                Variable(2, Boolean) = Icmp Eq, Variable(1, Boolean), Bool(false)
+                Branch Variable(2, Boolean), 2, 3
+            Block 1:Block:
+                Variable(4, Integer) = Add Integer(0), Variable(3, Integer)
+                Variable(0, Integer) = Store Variable(4, Integer)
+                Call id(3), args( Variable(0, Integer), Pointer, )
+                Return
+            Block 2:Block:
+                Variable(3, Integer) = Store Integer(0)
+                Jump(1)
+            Block 3:Block:
+                Variable(3, Integer) = Store Integer(1)
+                Jump(1)"#]],
+    );
+}
+
+#[test]
+fn integer_assign_sub_with_lhs_dynamic_integer_and_rhs_classical_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                mutable i = MResetZ(q) == Zero ? 0 | 1;
+                set i -= 1;
+                i
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__integer_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+        Blocks:
+        Block 0:Block:
+            Call id(1), args( Qubit(0), Result(0), )
+            Variable(0, Boolean) = Call id(2), args( Result(0), )
+            Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+            Branch Variable(1, Boolean), 2, 3
+        Block 1:Block:
+            Variable(3, Integer) = Store Variable(2, Integer)
+            Variable(4, Integer) = Sub Variable(3, Integer), Integer(1)
+            Variable(3, Integer) = Store Variable(4, Integer)
+            Call id(3), args( Variable(3, Integer), Pointer, )
+            Return
+        Block 2:Block:
+            Variable(2, Integer) = Store Integer(0)
+            Jump(1)
+        Block 3:Block:
+            Variable(2, Integer) = Store Integer(1)
+            Jump(1)"#]],
+    );
+}
+
+#[test]
+fn integer_assign_mul_with_lhs_dynamic_integer_and_rhs_dynamic_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                mutable i = MResetZ(q) == Zero ? 0 | 1;
+                set i *= MResetZ(q) == Zero ? 1 | 0;
+                i
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__integer_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+        Blocks:
+        Block 0:Block:
+            Call id(1), args( Qubit(0), Result(0), )
+            Variable(0, Boolean) = Call id(2), args( Result(0), )
+            Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+            Branch Variable(1, Boolean), 2, 3
+        Block 1:Block:
+            Variable(3, Integer) = Store Variable(2, Integer)
+            Call id(1), args( Qubit(0), Result(1), )
+            Variable(4, Boolean) = Call id(2), args( Result(1), )
+            Variable(5, Boolean) = Icmp Eq, Variable(4, Boolean), Bool(false)
+            Branch Variable(5, Boolean), 5, 6
+        Block 2:Block:
+            Variable(2, Integer) = Store Integer(0)
+            Jump(1)
+        Block 3:Block:
+            Variable(2, Integer) = Store Integer(1)
+            Jump(1)
+        Block 4:Block:
+            Variable(7, Integer) = Mul Variable(3, Integer), Variable(6, Integer)
+            Variable(3, Integer) = Store Variable(7, Integer)
+            Call id(3), args( Variable(3, Integer), Pointer, )
+            Return
+        Block 5:Block:
+            Variable(6, Integer) = Store Integer(1)
+            Jump(4)
+        Block 6:Block:
+            Variable(6, Integer) = Store Integer(0)
+            Jump(4)"#]],
+    );
+}
+
+#[test]
+fn integer_assign_div_with_lhs_classical_integer_and_rhs_dynamic_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                mutable i = 0;
+                set i /= MResetZ(q) == Zero ? 0 | 1;
+                i
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__integer_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Variable(0, Integer) = Store Integer(0)
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(1, Boolean) = Call id(2), args( Result(0), )
+                Variable(2, Boolean) = Icmp Eq, Variable(1, Boolean), Bool(false)
+                Branch Variable(2, Boolean), 2, 3
+            Block 1:Block:
+                Variable(4, Integer) = Sdiv Integer(0), Variable(3, Integer)
+                Variable(0, Integer) = Store Variable(4, Integer)
+                Call id(3), args( Variable(0, Integer), Pointer, )
+                Return
+            Block 2:Block:
+                Variable(3, Integer) = Store Integer(0)
+                Jump(1)
+            Block 3:Block:
+                Variable(3, Integer) = Store Integer(1)
+                Jump(1)"#]],
+    );
+}
+
+#[test]
+fn integer_assign_mod_with_lhs_dynamic_integer_and_rhs_classical_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                mutable i = MResetZ(q) == Zero ? 0 | 1;
+                set i %= 1;
+                i
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__integer_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+        Blocks:
+        Block 0:Block:
+            Call id(1), args( Qubit(0), Result(0), )
+            Variable(0, Boolean) = Call id(2), args( Result(0), )
+            Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+            Branch Variable(1, Boolean), 2, 3
+        Block 1:Block:
+            Variable(3, Integer) = Store Variable(2, Integer)
+            Variable(4, Integer) = Srem Variable(3, Integer), Integer(1)
+            Variable(3, Integer) = Store Variable(4, Integer)
+            Call id(3), args( Variable(3, Integer), Pointer, )
+            Return
+        Block 2:Block:
+            Variable(2, Integer) = Store Integer(0)
+            Jump(1)
+        Block 3:Block:
+            Variable(2, Integer) = Store Integer(1)
+            Jump(1)"#]],
+    );
+}
+
+#[test]
+fn integer_assign_exp_with_lhs_classical_integer_and_rhs_dynamic_integer() {
+    let error = get_partial_evaluation_error(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                mutable i = 0;
+                set i ^= MResetZ(q) == Zero ? 0 | 1;
+                i
+            }
+        }
+        "#,
+    });
+    // When this binary operation is supported, this error should be different.
+    assert_error(
+        &error,
+        &expect![[
+            r#"Unimplemented("exponentiation for integer operands", Span { lo: 121, hi: 156 })"#
+        ]],
+    );
+}
+
+#[test]
+fn integer_assign_exp_with_lhs_dynamic_integer_and_rhs_classical_integer() {
+    let error = get_partial_evaluation_error(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                mutable i = MResetZ(q) == Zero ? 0 | 1;
+                set i ^= 3;
+                i
+            }
+        }
+        "#,
+    });
+    // When this binary operation is supported, this program should not yield an error.
+    assert_error(
+        &error,
+        &expect![[
+            r#"Unimplemented("exponentiation for integer operands", Span { lo: 146, hi: 156 })"#
+        ]],
+    );
+}
+
+#[test]
+fn integer_assign_exp_with_lhs_dynamic_integer_and_rhs_dynamic_integer() {
+    let error = get_partial_evaluation_error(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                mutable i = MResetZ(q) == Zero ? 0 | 1;
+                set i ^= MResetZ(q) == Zero ? 1 | 0;
+                i
+            }
+        }
+        "#,
+    });
+    // When this binary operation is supported, this error should be different.
+    assert_error(
+        &error,
+        &expect![[
+            r#"Unimplemented("exponentiation for integer operands", Span { lo: 146, hi: 181 })"#
+        ]],
+    );
+}
+
+#[test]
+fn integer_assign_bitwise_and_with_lhs_dynamic_integer_and_rhs_dynamic_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                mutable i = MResetZ(q) == Zero ? 0 | 1;
+                set i &&&= MResetZ(q) == Zero ? 1 | 0;
+                i
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__integer_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Variable(3, Integer) = Store Variable(2, Integer)
+                Call id(1), args( Qubit(0), Result(1), )
+                Variable(4, Boolean) = Call id(2), args( Result(1), )
+                Variable(5, Boolean) = Icmp Eq, Variable(4, Boolean), Bool(false)
+                Branch Variable(5, Boolean), 5, 6
+            Block 2:Block:
+                Variable(2, Integer) = Store Integer(0)
+                Jump(1)
+            Block 3:Block:
+                Variable(2, Integer) = Store Integer(1)
+                Jump(1)
+            Block 4:Block:
+                Variable(7, Integer) = BitwiseAnd Variable(3, Integer), Variable(6, Integer)
+                Variable(3, Integer) = Store Variable(7, Integer)
+                Call id(3), args( Variable(3, Integer), Pointer, )
+                Return
+            Block 5:Block:
+                Variable(6, Integer) = Store Integer(1)
+                Jump(4)
+            Block 6:Block:
+                Variable(6, Integer) = Store Integer(0)
+                Jump(4)"#]],
+    );
+}
+
+#[test]
+fn integer_assign_bitwise_or_with_lhs_classical_integer_and_rhs_dynamic_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                mutable i = 0;
+                set i |||= MResetZ(q) == Zero ? 0 | 1;
+                i
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__integer_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Variable(0, Integer) = Store Integer(0)
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(1, Boolean) = Call id(2), args( Result(0), )
+                Variable(2, Boolean) = Icmp Eq, Variable(1, Boolean), Bool(false)
+                Branch Variable(2, Boolean), 2, 3
+            Block 1:Block:
+                Variable(4, Integer) = BitwiseOr Integer(0), Variable(3, Integer)
+                Variable(0, Integer) = Store Variable(4, Integer)
+                Call id(3), args( Variable(0, Integer), Pointer, )
+                Return
+            Block 2:Block:
+                Variable(3, Integer) = Store Integer(0)
+                Jump(1)
+            Block 3:Block:
+                Variable(3, Integer) = Store Integer(1)
+                Jump(1)"#]],
+    );
+}
+
+#[test]
+fn integer_bitwise_xor_with_lhs_dynamic_integer_and_rhs_classical_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                mutable i = MResetZ(q) == Zero ? 0 | 1;
+                set i ^^^= 1;
+                i
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__integer_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+        Blocks:
+        Block 0:Block:
+            Call id(1), args( Qubit(0), Result(0), )
+            Variable(0, Boolean) = Call id(2), args( Result(0), )
+            Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+            Branch Variable(1, Boolean), 2, 3
+        Block 1:Block:
+            Variable(3, Integer) = Store Variable(2, Integer)
+            Variable(4, Integer) = BitwiseXor Variable(3, Integer), Integer(1)
+            Variable(3, Integer) = Store Variable(4, Integer)
+            Call id(3), args( Variable(3, Integer), Pointer, )
+            Return
+        Block 2:Block:
+            Variable(2, Integer) = Store Integer(0)
+            Jump(1)
+        Block 3:Block:
+            Variable(2, Integer) = Store Integer(1)
+            Jump(1)"#]],
+    );
+}
+
+#[test]
+fn integer_assign_bitwise_left_shift_with_lhs_dynamic_integer_and_rhs_dynamic_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                mutable i = MResetZ(q) == Zero ? 0 | 1;
+                set i <<<= MResetZ(q) == Zero ? 1 | 0;
+                i
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__integer_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Variable(3, Integer) = Store Variable(2, Integer)
+                Call id(1), args( Qubit(0), Result(1), )
+                Variable(4, Boolean) = Call id(2), args( Result(1), )
+                Variable(5, Boolean) = Icmp Eq, Variable(4, Boolean), Bool(false)
+                Branch Variable(5, Boolean), 5, 6
+            Block 2:Block:
+                Variable(2, Integer) = Store Integer(0)
+                Jump(1)
+            Block 3:Block:
+                Variable(2, Integer) = Store Integer(1)
+                Jump(1)
+            Block 4:Block:
+                Variable(7, Integer) = Shl Variable(3, Integer), Variable(6, Integer)
+                Variable(3, Integer) = Store Variable(7, Integer)
+                Call id(3), args( Variable(3, Integer), Pointer, )
+                Return
+            Block 5:Block:
+                Variable(6, Integer) = Store Integer(1)
+                Jump(4)
+            Block 6:Block:
+                Variable(6, Integer) = Store Integer(0)
+                Jump(4)"#]],
+    );
+}
+
+#[test]
+fn integer_assign_bitwise_right_shift_with_lhs_classical_integer_and_rhs_dynamic_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                mutable i = 0;
+                set i >>>= MResetZ(q) == Zero ? 0 | 1;
+                i
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__integer_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Variable(0, Integer) = Store Integer(0)
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(1, Boolean) = Call id(2), args( Result(0), )
+                Variable(2, Boolean) = Icmp Eq, Variable(1, Boolean), Bool(false)
+                Branch Variable(2, Boolean), 2, 3
+            Block 1:Block:
+                Variable(4, Integer) = Ashr Integer(0), Variable(3, Integer)
+                Variable(0, Integer) = Store Variable(4, Integer)
+                Call id(3), args( Variable(0, Integer), Pointer, )
+                Return
+            Block 2:Block:
+                Variable(3, Integer) = Store Integer(0)
+                Jump(1)
+            Block 3:Block:
+                Variable(3, Integer) = Store Integer(1)
+                Jump(1)"#]],
+    );
+}
diff --git a/compiler/qsc_partial_eval/tests/bindings.rs b/compiler/qsc_partial_eval/tests/bindings.rs
index 6aaa29eb..ccfa7a76 100644
--- a/compiler/qsc_partial_eval/tests/bindings.rs
+++ b/compiler/qsc_partial_eval/tests/bindings.rs
@@ -176,7 +176,7 @@ fn immutable_bool_binding_does_not_generate_store_instruction() {
             Block:
                 Call id(1), args( Qubit(0), Result(0), )
                 Variable(0, Boolean) = Call id(2), args( Result(0), )
-                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(true)
+                Variable(1, Boolean) = Store Variable(0, Boolean)
                 Call id(3), args( Variable(1, Boolean), Pointer, )
                 Return"#]],
     );
@@ -242,7 +242,7 @@ fn mutable_bool_binding_generates_store_instruction() {
             Block:
                 Call id(1), args( Qubit(0), Result(0), )
                 Variable(0, Boolean) = Call id(2), args( Result(0), )
-                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(true)
+                Variable(1, Boolean) = Store Variable(0, Boolean)
                 Variable(2, Boolean) = Store Variable(1, Boolean)
                 Call id(3), args( Variable(2, Boolean), Pointer, )
                 Return"#]],
@@ -309,7 +309,7 @@ fn immutable_int_binding_does_not_generate_store_instruction() {
             Block 0:Block:
                 Call id(1), args( Qubit(0), Result(0), )
                 Variable(0, Boolean) = Call id(2), args( Result(0), )
-                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(true)
+                Variable(1, Boolean) = Store Variable(0, Boolean)
                 Branch Variable(1, Boolean), 2, 3
             Block 1:Block:
                 Call id(3), args( Variable(2, Integer), Pointer, )
@@ -383,7 +383,7 @@ fn mutable_int_binding_does_generate_store_instruction() {
             Block 0:Block:
                 Call id(1), args( Qubit(0), Result(0), )
                 Variable(0, Boolean) = Call id(2), args( Result(0), )
-                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(true)
+                Variable(1, Boolean) = Store Variable(0, Boolean)
                 Branch Variable(1, Boolean), 2, 3
             Block 1:Block:
                 Variable(3, Integer) = Store Variable(2, Integer)
diff --git a/compiler/qsc_partial_eval/tests/branching.rs b/compiler/qsc_partial_eval/tests/branching.rs
index 4c1c4076..197ca747 100644
--- a/compiler/qsc_partial_eval/tests/branching.rs
+++ b/compiler/qsc_partial_eval/tests/branching.rs
@@ -369,21 +369,21 @@ fn if_else_expression_with_dynamic_condition() {
     assert_blocks(
         &program,
         &expect![[r#"
-        Blocks:
-        Block 0:Block:
-            Call id(1), args( Qubit(0), Result(0), )
-            Variable(0, Boolean) = Call id(2), args( Result(0), )
-            Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(true)
-            Branch Variable(1, Boolean), 2, 3
-        Block 1:Block:
-            Call id(5), args( Integer(0), Pointer, )
-            Return
-        Block 2:Block:
-            Call id(3), args( Qubit(0), )
-            Jump(1)
-        Block 3:Block:
-            Call id(4), args( Qubit(0), )
-            Jump(1)"#]],
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Store Variable(0, Boolean)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Call id(5), args( Integer(0), Pointer, )
+                Return
+            Block 2:Block:
+                Call id(3), args( Qubit(0), )
+                Jump(1)
+            Block 3:Block:
+                Call id(4), args( Qubit(0), )
+                Jump(1)"#]],
     );
 }
 
@@ -483,31 +483,31 @@ fn if_elif_else_expression_with_dynamic_condition() {
     assert_blocks(
         &program,
         &expect![[r#"
-        Blocks:
-        Block 0:Block:
-            Call id(1), args( Qubit(0), Result(0), )
-            Call id(1), args( Qubit(1), Result(1), )
-            Variable(0, Boolean) = Call id(2), args( Result(0), )
-            Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(true)
-            Branch Variable(1, Boolean), 2, 3
-        Block 1:Block:
-            Call id(6), args( Integer(0), Pointer, )
-            Return
-        Block 2:Block:
-            Call id(3), args( Qubit(2), )
-            Jump(1)
-        Block 3:Block:
-            Variable(2, Boolean) = Call id(2), args( Result(1), )
-            Variable(3, Boolean) = Icmp Eq, Variable(2, Boolean), Bool(true)
-            Branch Variable(3, Boolean), 5, 6
-        Block 4:Block:
-            Jump(1)
-        Block 5:Block:
-            Call id(4), args( Qubit(2), )
-            Jump(4)
-        Block 6:Block:
-            Call id(5), args( Qubit(2), )
-            Jump(4)"#]],
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Call id(1), args( Qubit(1), Result(1), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Store Variable(0, Boolean)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Call id(6), args( Integer(0), Pointer, )
+                Return
+            Block 2:Block:
+                Call id(3), args( Qubit(2), )
+                Jump(1)
+            Block 3:Block:
+                Variable(2, Boolean) = Call id(2), args( Result(1), )
+                Variable(3, Boolean) = Store Variable(2, Boolean)
+                Branch Variable(3, Boolean), 5, 6
+            Block 4:Block:
+                Jump(1)
+            Block 5:Block:
+                Call id(4), args( Qubit(2), )
+                Jump(4)
+            Block 6:Block:
+                Call id(5), args( Qubit(2), )
+                Jump(4)"#]],
     );
 }
 
@@ -738,21 +738,21 @@ fn if_else_expression_with_dynamic_condition_and_nested_if_expression_with_true_
     assert_blocks(
         &program,
         &expect![[r#"
-        Blocks:
-        Block 0:Block:
-            Call id(1), args( Qubit(0), Result(0), )
-            Variable(0, Boolean) = Call id(2), args( Result(0), )
-            Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(true)
-            Branch Variable(1, Boolean), 2, 3
-        Block 1:Block:
-            Call id(5), args( Integer(0), Pointer, )
-            Return
-        Block 2:Block:
-            Call id(3), args( Qubit(0), )
-            Jump(1)
-        Block 3:Block:
-            Call id(4), args( Qubit(0), )
-            Jump(1)"#]],
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Store Variable(0, Boolean)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Call id(5), args( Integer(0), Pointer, )
+                Return
+            Block 2:Block:
+                Call id(3), args( Qubit(0), )
+                Jump(1)
+            Block 3:Block:
+                Call id(4), args( Qubit(0), )
+                Jump(1)"#]],
     );
 }
 
@@ -824,20 +824,20 @@ fn if_else_expression_with_dynamic_condition_and_nested_if_expression_with_false
     assert_blocks(
         &program,
         &expect![[r#"
-        Blocks:
-        Block 0:Block:
-            Call id(1), args( Qubit(0), Result(0), )
-            Variable(0, Boolean) = Call id(2), args( Result(0), )
-            Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(true)
-            Branch Variable(1, Boolean), 2, 3
-        Block 1:Block:
-            Call id(4), args( Integer(0), Pointer, )
-            Return
-        Block 2:Block:
-            Call id(3), args( Qubit(0), )
-            Jump(1)
-        Block 3:Block:
-            Jump(1)"#]],
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Store Variable(0, Boolean)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Call id(4), args( Integer(0), Pointer, )
+                Return
+            Block 2:Block:
+                Call id(3), args( Qubit(0), )
+                Jump(1)
+            Block 3:Block:
+                Jump(1)"#]],
     );
 }
 
@@ -907,25 +907,25 @@ fn if_expression_with_dynamic_condition_and_nested_if_expression_with_dynamic_co
     assert_blocks(
         &program,
         &expect![[r#"
-        Blocks:
-        Block 0:Block:
-            Call id(1), args( Qubit(0), Result(0), )
-            Call id(1), args( Qubit(1), Result(1), )
-            Variable(0, Boolean) = Call id(2), args( Result(0), )
-            Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
-            Branch Variable(1, Boolean), 2, 1
-        Block 1:Block:
-            Call id(4), args( Integer(0), Pointer, )
-            Return
-        Block 2:Block:
-            Variable(2, Boolean) = Call id(2), args( Result(1), )
-            Variable(3, Boolean) = Icmp Eq, Variable(2, Boolean), Bool(true)
-            Branch Variable(3, Boolean), 4, 3
-        Block 3:Block:
-            Jump(1)
-        Block 4:Block:
-            Call id(3), args( Qubit(2), )
-            Jump(3)"#]],
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Call id(1), args( Qubit(1), Result(1), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+                Branch Variable(1, Boolean), 2, 1
+            Block 1:Block:
+                Call id(4), args( Integer(0), Pointer, )
+                Return
+            Block 2:Block:
+                Variable(2, Boolean) = Call id(2), args( Result(1), )
+                Variable(3, Boolean) = Store Variable(2, Boolean)
+                Branch Variable(3, Boolean), 4, 3
+            Block 3:Block:
+                Jump(1)
+            Block 4:Block:
+                Call id(3), args( Qubit(2), )
+                Jump(3)"#]],
     );
 }
 
@@ -1046,40 +1046,40 @@ fn doubly_nested_if_else_expressions_with_dynamic_conditions() {
     assert_blocks(
         &program,
         &expect![[r#"
-        Blocks:
-        Block 0:Block:
-            Call id(1), args( Qubit(0), Result(0), )
-            Call id(1), args( Qubit(1), Result(1), )
-            Variable(0, Boolean) = Call id(2), args( Result(0), )
-            Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
-            Branch Variable(1, Boolean), 2, 6
-        Block 1:Block:
-            Call id(7), args( Integer(0), Pointer, )
-            Return
-        Block 2:Block:
-            Variable(2, Boolean) = Call id(2), args( Result(1), )
-            Variable(3, Boolean) = Icmp Eq, Variable(2, Boolean), Bool(false)
-            Branch Variable(3, Boolean), 4, 5
-        Block 3:Block:
-            Jump(1)
-        Block 4:Block:
-            Call id(3), args( Qubit(2), )
-            Jump(3)
-        Block 5:Block:
-            Call id(4), args( Qubit(2), )
-            Jump(3)
-        Block 6:Block:
-            Variable(4, Boolean) = Call id(2), args( Result(1), )
-            Variable(5, Boolean) = Icmp Eq, Variable(4, Boolean), Bool(true)
-            Branch Variable(5, Boolean), 8, 9
-        Block 7:Block:
-            Jump(1)
-        Block 8:Block:
-            Call id(5), args( Qubit(2), )
-            Jump(7)
-        Block 9:Block:
-            Call id(6), args( Qubit(2), )
-            Jump(7)"#]],
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Call id(1), args( Qubit(1), Result(1), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+                Branch Variable(1, Boolean), 2, 6
+            Block 1:Block:
+                Call id(7), args( Integer(0), Pointer, )
+                Return
+            Block 2:Block:
+                Variable(2, Boolean) = Call id(2), args( Result(1), )
+                Variable(3, Boolean) = Icmp Eq, Variable(2, Boolean), Bool(false)
+                Branch Variable(3, Boolean), 4, 5
+            Block 3:Block:
+                Jump(1)
+            Block 4:Block:
+                Call id(3), args( Qubit(2), )
+                Jump(3)
+            Block 5:Block:
+                Call id(4), args( Qubit(2), )
+                Jump(3)
+            Block 6:Block:
+                Variable(4, Boolean) = Call id(2), args( Result(1), )
+                Variable(5, Boolean) = Store Variable(4, Boolean)
+                Branch Variable(5, Boolean), 8, 9
+            Block 7:Block:
+                Jump(1)
+            Block 8:Block:
+                Call id(5), args( Qubit(2), )
+                Jump(7)
+            Block 9:Block:
+                Call id(6), args( Qubit(2), )
+                Jump(7)"#]],
     );
 }
 
@@ -1271,21 +1271,21 @@ fn if_else_expression_with_dynamic_condition_and_subsequent_call_to_operation()
     assert_blocks(
         &program,
         &expect![[r#"
-        Blocks:
-        Block 0:Block:
-            Call id(1), args( Qubit(0), Result(0), )
-            Variable(0, Boolean) = Call id(2), args( Result(0), )
-            Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(true)
-            Branch Variable(1, Boolean), 2, 3
-        Block 1:Block:
-            Call id(5), args( Qubit(0), )
-            Call id(6), args( Integer(0), Pointer, )
-            Return
-        Block 2:Block:
-            Call id(3), args( Qubit(0), )
-            Jump(1)
-        Block 3:Block:
-            Call id(4), args( Qubit(0), )
-            Jump(1)"#]],
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Store Variable(0, Boolean)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Call id(5), args( Qubit(0), )
+                Call id(6), args( Integer(0), Pointer, )
+                Return
+            Block 2:Block:
+                Call id(3), args( Qubit(0), )
+                Jump(1)
+            Block 3:Block:
+                Call id(4), args( Qubit(0), )
+                Jump(1)"#]],
     );
 }
diff --git a/compiler/qsc_partial_eval/tests/calls.rs b/compiler/qsc_partial_eval/tests/calls.rs
index 2c859068..1872be61 100644
--- a/compiler/qsc_partial_eval/tests/calls.rs
+++ b/compiler/qsc_partial_eval/tests/calls.rs
@@ -373,21 +373,21 @@ fn calls_to_unitary_that_conditionally_calls_intrinsic_with_dynamic_bool() {
     assert_blocks(
         &program,
         &expect![[r#"
-        Blocks:
-        Block 0:Block:
-            Call id(1), args( Qubit(0), Result(0), )
-            Variable(0, Boolean) = Call id(2), args( Result(0), )
-            Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(true)
-            Branch Variable(1, Boolean), 2, 3
-        Block 1:Block:
-            Call id(5), args( Integer(0), Pointer, )
-            Return
-        Block 2:Block:
-            Call id(3), args( Qubit(1), )
-            Jump(1)
-        Block 3:Block:
-            Call id(4), args( Qubit(1), )
-            Jump(1)"#]],
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Store Variable(0, Boolean)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Call id(5), args( Integer(0), Pointer, )
+                Return
+            Block 2:Block:
+                Call id(3), args( Qubit(1), )
+                Jump(1)
+            Block 3:Block:
+                Call id(4), args( Qubit(1), )
+                Jump(1)"#]],
     );
 }
 
@@ -695,7 +695,7 @@ fn call_to_boolean_function_using_dynamic_result_as_argument_generates_branches(
             Block 0:Block:
                 Call id(1), args( Qubit(0), Result(0), )
                 Variable(0, Boolean) = Call id(2), args( Result(0), )
-                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(true)
+                Variable(1, Boolean) = Store Variable(0, Boolean)
                 Branch Variable(1, Boolean), 2, 1
             Block 1:Block:
                 Call id(4), args( Integer(0), Pointer, )
diff --git a/compiler/qsc_partial_eval/tests/misc.rs b/compiler/qsc_partial_eval/tests/misc.rs
index 35a515e1..6288af3d 100644
--- a/compiler/qsc_partial_eval/tests/misc.rs
+++ b/compiler/qsc_partial_eval/tests/misc.rs
@@ -8,7 +8,7 @@ pub mod test_utils;
 use expect_test::expect;
 use indoc::indoc;
 use qsc_rir::rir::{BlockId, CallableId};
-use test_utils::{assert_block_instructions, assert_callable, get_rir_program};
+use test_utils::{assert_block_instructions, assert_blocks, assert_callable, get_rir_program};
 
 #[test]
 fn unitary_call_within_an_if_with_classical_condition_within_a_for_loop() {
@@ -176,3 +176,166 @@ fn unitary_call_within_an_if_with_classical_condition_within_a_repeat_until_loop
                 Return"#]],
     );
 }
+
+#[test]
+fn boolean_assign_and_update_with_classical_value_within_an_if_with_dynamic_condition() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use qubit = Qubit();
+                mutable b = true;
+                if MResetZ(qubit) == One {
+                    set b and= false;
+                }
+                return b;
+            }
+        }
+        "#,
+    });
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Variable(0, Boolean) = Store Bool(true)
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(1, Boolean) = Call id(2), args( Result(0), )
+                Variable(2, Boolean) = Store Variable(1, Boolean)
+                Branch Variable(2, Boolean), 2, 1
+            Block 1:Block:
+                Call id(3), args( Variable(0, Boolean), Pointer, )
+                Return
+            Block 2:Block:
+                Variable(0, Boolean) = Store Bool(false)
+                Jump(1)"#]],
+    );
+}
+
+#[test]
+fn integer_assign_and_update_with_classical_value_within_an_if_with_dynamic_condition() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use qubit = Qubit();
+                mutable i = 1;
+                if MResetZ(qubit) == One {
+                    set i |||= 1 <<< 2;
+                }
+                return i;
+            }
+        }
+        "#,
+    });
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Variable(0, Integer) = Store Integer(1)
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(1, Boolean) = Call id(2), args( Result(0), )
+                Variable(2, Boolean) = Store Variable(1, Boolean)
+                Branch Variable(2, Boolean), 2, 1
+            Block 1:Block:
+                Call id(3), args( Variable(0, Integer), Pointer, )
+                Return
+            Block 2:Block:
+                Variable(0, Integer) = Store Integer(5)
+                Jump(1)"#]],
+    );
+}
+
+#[test]
+fn integer_assign_with_hybrid_value_within_an_if_with_dynamic_condition() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use qubit = Qubit();
+                mutable i = 0;
+                for idxBit in 0..1{
+                    if (MResetZ(qubit) == One) {
+                        set i |||= 1 <<< idxBit;
+                    }
+                }
+                return i;
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__integer_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+        Blocks:
+        Block 0:Block:
+            Variable(0, Integer) = Store Integer(0)
+            Variable(1, Integer) = Store Integer(0)
+            Call id(1), args( Qubit(0), Result(0), )
+            Variable(2, Boolean) = Call id(2), args( Result(0), )
+            Variable(3, Boolean) = Store Variable(2, Boolean)
+            Branch Variable(3, Boolean), 2, 1
+        Block 1:Block:
+            Variable(1, Integer) = Store Integer(1)
+            Call id(1), args( Qubit(0), Result(1), )
+            Variable(4, Boolean) = Call id(2), args( Result(1), )
+            Variable(5, Boolean) = Store Variable(4, Boolean)
+            Branch Variable(5, Boolean), 4, 3
+        Block 2:Block:
+            Variable(0, Integer) = Store Integer(1)
+            Jump(1)
+        Block 3:Block:
+            Variable(1, Integer) = Store Integer(2)
+            Call id(3), args( Variable(0, Integer), Pointer, )
+            Return
+        Block 4:Block:
+            Variable(6, Integer) = BitwiseOr Variable(0, Integer), Integer(2)
+            Variable(0, Integer) = Store Variable(6, Integer)
+            Jump(3)"#]],
+    );
+}
diff --git a/compiler/qsc_partial_eval/tests/operators.rs b/compiler/qsc_partial_eval/tests/operators.rs
index b8781eff..86907b61 100644
--- a/compiler/qsc_partial_eval/tests/operators.rs
+++ b/compiler/qsc_partial_eval/tests/operators.rs
@@ -8,7 +8,10 @@ pub mod test_utils;
 use expect_test::expect;
 use indoc::indoc;
 use qsc_rir::rir::{BlockId, CallableId};
-use test_utils::{assert_block_instructions, assert_blocks, assert_callable, get_rir_program};
+use test_utils::{
+    assert_block_instructions, assert_blocks, assert_callable, assert_error,
+    get_partial_evaluation_error, get_rir_program,
+};
 
 #[test]
 fn leading_positive_unary_operator_does_not_generate_rir_instruction() {
@@ -300,3 +303,2171 @@ fn logical_not_unary_operator_generates_logical_not_rir_instruction() {
                 Return"#]],
     );
 }
+
+#[test]
+fn comparing_measurement_results_for_equality_adds_read_result_and_comparison_instructions() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use (q0, q1) = (Qubit(), Qubit());
+                let r0 = MResetZ(q0);
+                let r1 = MResetZ(q1);
+                r0 == r1
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let bool_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        bool_record_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__rt__bool_record_output
+            call_type: OutputRecording
+            input_type:
+                [0]: Boolean
+                [1]: Pointer
+            output_type: <VOID>
+            body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Call id(1), args( Qubit(1), Result(1), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Call id(2), args( Result(1), )
+                Variable(2, Boolean) = Icmp Eq, Variable(0, Boolean), Variable(1, Boolean)
+                Call id(3), args( Variable(2, Boolean), Pointer, )
+                Return"#]],
+    );
+    assert_eq!(program.num_qubits, 2);
+    assert_eq!(program.num_results, 2);
+}
+
+#[test]
+fn comparing_measurement_results_for_inequality_adds_read_result_and_comparison_instructions() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use (q0, q1) = (Qubit(), Qubit());
+                let r0 = MResetZ(q0);
+                let r1 = MResetZ(q1);
+                r0 != r1
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__mresetz__body
+            call_type: Measurement
+            input_type:
+                [0]: Qubit
+                [1]: Result
+            output_type: <VOID>
+            body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let bool_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        bool_record_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__rt__bool_record_output
+            call_type: OutputRecording
+            input_type:
+                [0]: Boolean
+                [1]: Pointer
+            output_type: <VOID>
+            body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Call id(1), args( Qubit(1), Result(1), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Call id(2), args( Result(1), )
+                Variable(2, Boolean) = Icmp Ne, Variable(0, Boolean), Variable(1, Boolean)
+                Call id(3), args( Variable(2, Boolean), Pointer, )
+                Return"#]],
+    );
+    assert_eq!(program.num_qubits, 2);
+    assert_eq!(program.num_results, 2);
+}
+
+#[test]
+fn comparing_measurement_result_against_result_literal_for_equality_adds_read_result_and_comparison_instructions(
+) {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                let r = MResetZ(q);
+                r == Zero
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__mresetz__body
+            call_type: Measurement
+            input_type:
+                [0]: Qubit
+                [1]: Result
+            output_type: <VOID>
+            body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let bool_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        bool_record_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__rt__bool_record_output
+            call_type: OutputRecording
+            input_type:
+                [0]: Boolean
+                [1]: Pointer
+            output_type: <VOID>
+            body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+                Call id(3), args( Variable(1, Boolean), Pointer, )
+                Return"#]],
+    );
+    assert_eq!(program.num_qubits, 1);
+    assert_eq!(program.num_results, 1);
+}
+
+#[test]
+fn comparing_measurement_result_against_result_literal_for_inequality_adds_read_result_and_comparison_instructions(
+) {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                let r = MResetZ(q);
+                r != One
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__mresetz__body
+            call_type: Measurement
+            input_type:
+                [0]: Qubit
+                [1]: Result
+            output_type: <VOID>
+            body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let bool_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        bool_record_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__rt__bool_record_output
+            call_type: OutputRecording
+            input_type:
+                [0]: Boolean
+                [1]: Pointer
+            output_type: <VOID>
+            body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Icmp Ne, Variable(0, Boolean), Bool(true)
+                Call id(3), args( Variable(1, Boolean), Pointer, )
+                Return"#]],
+    );
+    assert_eq!(program.num_qubits, 1);
+    assert_eq!(program.num_results, 1);
+}
+
+#[test]
+fn comparing_lhs_classical_boolean_against_rhs_dynamic_boolean_for_equality() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                let b = MResetZ(q) == One;
+                false == b
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__rt__bool_record_output
+            call_type: OutputRecording
+            input_type:
+                [0]: Boolean
+                [1]: Pointer
+            output_type: <VOID>
+            body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Store Variable(0, Boolean)
+                Variable(2, Boolean) = Icmp Eq, Bool(false), Variable(1, Boolean)
+                Call id(3), args( Variable(2, Boolean), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn comparing_lhs_dynamic_boolean_against_rhs_dynamic_boolean_for_equality_raises_error() {
+    let error = get_partial_evaluation_error(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                (MResetZ(q) == Zero) == (MResetZ(q) == One)
+            }
+        }
+        "#,
+    });
+    // This error message will no longer happen once Boolean operations with a dynamic LHS are supported.
+    assert_error(
+        &error,
+        &expect![[
+            r#"Unimplemented("bool binary operation with dynamic LHS", Span { lo: 99, hi: 142 })"#
+        ]],
+    );
+}
+
+#[test]
+fn comparing_lhs_classical_boolean_against_rhs_dynamic_boolean_for_inequality() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                let b = MResetZ(q) == One;
+                true != b
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__rt__bool_record_output
+            call_type: OutputRecording
+            input_type:
+                [0]: Boolean
+                [1]: Pointer
+            output_type: <VOID>
+            body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Store Variable(0, Boolean)
+                Variable(2, Boolean) = Icmp Ne, Bool(true), Variable(1, Boolean)
+                Call id(3), args( Variable(2, Boolean), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn comparing_lhs_dynamic_boolean_against_rhs_dynamic_boolean_for_inequality_raises_error() {
+    let error = get_partial_evaluation_error(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                (MResetZ(q) == Zero) != (MResetZ(q) == One)
+            }
+        }
+        "#,
+    });
+    // This error message will no longer happen once Boolean operations with a dynamic LHS are supported.
+    assert_error(
+        &error,
+        &expect![[
+            r#"Unimplemented("bool binary operation with dynamic LHS", Span { lo: 99, hi: 142 })"#
+        ]],
+    );
+}
+
+#[test]
+fn logical_and_with_lhs_classical_true_is_optimized_as_store() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                let b = MResetZ(q) == One;
+                true and b
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__rt__bool_record_output
+            call_type: OutputRecording
+            input_type:
+                [0]: Boolean
+                [1]: Pointer
+            output_type: <VOID>
+            body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Store Variable(0, Boolean)
+                Call id(3), args( Variable(1, Boolean), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn logical_and_with_lhs_classical_false_short_circuits_evaluation() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                let b = MResetZ(q) == One;
+                false and (true == b)
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__rt__bool_record_output
+            call_type: OutputRecording
+            input_type:
+                [0]: Boolean
+                [1]: Pointer
+            output_type: <VOID>
+            body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Store Variable(0, Boolean)
+                Call id(3), args( Bool(false), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn logical_and_with_dynamic_lhs_and_dynamic_rhs_raises_error() {
+    let error = get_partial_evaluation_error(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                (MResetZ(q) == Zero) and (MResetZ(q) == One)
+            }
+        }
+        "#,
+    });
+    // This error message will no longer happen once Boolean operations with a dynamic LHS are supported.
+    assert_error(
+        &error,
+        &expect![[
+            r#"Unimplemented("bool binary operation with dynamic LHS", Span { lo: 99, hi: 143 })"#
+        ]],
+    );
+}
+
+#[test]
+fn logical_or_with_lhs_classical_true_short_circuits_evaluation() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                let b = MResetZ(q) == One;
+                true or (false != b)
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__rt__bool_record_output
+            call_type: OutputRecording
+            input_type:
+                [0]: Boolean
+                [1]: Pointer
+            output_type: <VOID>
+            body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Store Variable(0, Boolean)
+                Call id(3), args( Bool(true), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn logical_or_with_lhs_classical_false_is_optimized_as_store() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                let b = MResetZ(q) == One;
+                false or b
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__rt__bool_record_output
+            call_type: OutputRecording
+            input_type:
+                [0]: Boolean
+                [1]: Pointer
+            output_type: <VOID>
+            body: <NONE>"#]],
+    );
+    assert_block_instructions(
+        &program,
+        BlockId(0),
+        &expect![[r#"
+            Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Store Variable(0, Boolean)
+                Call id(3), args( Variable(1, Boolean), Pointer, )
+                Return"#]],
+    );
+}
+
+#[test]
+fn logical_or_with_dynamic_lhs_and_dynamic_rhs_raises_error() {
+    let error = get_partial_evaluation_error(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                (MResetZ(q) == Zero) or (MResetZ(q) == One)
+            }
+        }
+        "#,
+    });
+    // This error message will no longer happen once Boolean operations with a dynamic LHS are supported.
+    assert_error(
+        &error,
+        &expect![[
+            r#"Unimplemented("bool binary operation with dynamic LHS", Span { lo: 99, hi: 142 })"#
+        ]],
+    );
+}
+
+#[test]
+fn integer_add_with_lhs_classical_integer_and_rhs_dynamic_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                let i = MResetZ(q) == Zero ? 0 | 1;
+                1 + i
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__integer_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Variable(3, Integer) = Add Integer(1), Variable(2, Integer)
+                Call id(3), args( Variable(3, Integer), Pointer, )
+                Return
+            Block 2:Block:
+                Variable(2, Integer) = Store Integer(0)
+                Jump(1)
+            Block 3:Block:
+                Variable(2, Integer) = Store Integer(1)
+                Jump(1)"#]],
+    );
+}
+
+#[test]
+fn integer_sub_with_lhs_dynamic_integer_and_rhs_classical_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                let i = MResetZ(q) == Zero ? 0 | 1;
+                i - 1
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__integer_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Variable(3, Integer) = Sub Variable(2, Integer), Integer(1)
+                Call id(3), args( Variable(3, Integer), Pointer, )
+                Return
+            Block 2:Block:
+                Variable(2, Integer) = Store Integer(0)
+                Jump(1)
+            Block 3:Block:
+                Variable(2, Integer) = Store Integer(1)
+                Jump(1)"#]],
+    );
+}
+
+#[test]
+fn integer_mul_with_lhs_dynamic_integer_and_rhs_dynamic_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                let a = MResetZ(q) == Zero ? 0 | 1;
+                let b = MResetZ(q) == Zero ? 1 | 0;
+                a * b
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__integer_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Call id(1), args( Qubit(0), Result(1), )
+                Variable(3, Boolean) = Call id(2), args( Result(1), )
+                Variable(4, Boolean) = Icmp Eq, Variable(3, Boolean), Bool(false)
+                Branch Variable(4, Boolean), 5, 6
+            Block 2:Block:
+                Variable(2, Integer) = Store Integer(0)
+                Jump(1)
+            Block 3:Block:
+                Variable(2, Integer) = Store Integer(1)
+                Jump(1)
+            Block 4:Block:
+                Variable(6, Integer) = Mul Variable(2, Integer), Variable(5, Integer)
+                Call id(3), args( Variable(6, Integer), Pointer, )
+                Return
+            Block 5:Block:
+                Variable(5, Integer) = Store Integer(1)
+                Jump(4)
+            Block 6:Block:
+                Variable(5, Integer) = Store Integer(0)
+                Jump(4)"#]],
+    );
+}
+
+#[test]
+fn integer_div_with_lhs_classical_integer_and_rhs_dynamic_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                let i = MResetZ(q) == Zero ? 0 | 1;
+                1 / i
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__integer_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Variable(3, Integer) = Sdiv Integer(1), Variable(2, Integer)
+                Call id(3), args( Variable(3, Integer), Pointer, )
+                Return
+            Block 2:Block:
+                Variable(2, Integer) = Store Integer(0)
+                Jump(1)
+            Block 3:Block:
+                Variable(2, Integer) = Store Integer(1)
+                Jump(1)"#]],
+    );
+}
+
+#[test]
+fn integer_div_with_lhs_dynamic_integer_and_rhs_zero_raises_error() {
+    let error = get_partial_evaluation_error(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                let i = MResetZ(q) == Zero ? 0 | 1;
+                i / 0
+            }
+        }
+        "#,
+    });
+    assert_error(
+        &error,
+        &expect![[r#"EvaluationFailed("division by zero", Span { lo: 142, hi: 147 })"#]],
+    );
+}
+
+#[test]
+fn integer_mod_with_lhs_dynamic_integer_and_rhs_classical_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                let i = MResetZ(q) == Zero ? 0 | 1;
+                i % 1
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__integer_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Variable(3, Integer) = Srem Variable(2, Integer), Integer(1)
+                Call id(3), args( Variable(3, Integer), Pointer, )
+                Return
+            Block 2:Block:
+                Variable(2, Integer) = Store Integer(0)
+                Jump(1)
+            Block 3:Block:
+                Variable(2, Integer) = Store Integer(1)
+                Jump(1)"#]],
+    );
+}
+
+#[test]
+fn integer_exponentiation_with_lhs_classical_integer_and_rhs_dynamic_integer() {
+    let error = get_partial_evaluation_error(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                let i = MResetZ(q) == Zero ? 0 | 1;
+                2 ^ i
+            }
+        }
+        "#,
+    });
+    // When this binary operation is supported, this error should be different.
+    assert_error(
+        &error,
+        &expect![[
+            r#"Unimplemented("exponentiation for integer operands", Span { lo: 142, hi: 147 })"#
+        ]],
+    );
+}
+
+#[test]
+fn integer_exponentiation_with_lhs_dynamic_integer_and_rhs_classical_integer() {
+    let error = get_partial_evaluation_error(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                let i = MResetZ(q) == Zero ? 0 | 1;
+                i ^ 3
+            }
+        }
+        "#,
+    });
+    // When this binary operation is supported, this program should not yield an error.
+    assert_error(
+        &error,
+        &expect![[
+            r#"Unimplemented("exponentiation for integer operands", Span { lo: 142, hi: 147 })"#
+        ]],
+    );
+}
+
+#[test]
+fn integer_exponentiation_with_lhs_dynamic_integer_and_rhs_dynamic_integer() {
+    let error = get_partial_evaluation_error(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                let a = MResetZ(q) == Zero ? 0 | 1;
+                let b = MResetZ(q) == Zero ? 1 | 0;
+                a ^ b
+            }
+        }
+        "#,
+    });
+    // When this binary operation is supported, this error should be different.
+    assert_error(
+        &error,
+        &expect![[
+            r#"Unimplemented("exponentiation for integer operands", Span { lo: 186, hi: 191 })"#
+        ]],
+    );
+}
+
+#[test]
+fn integer_bitwise_and_with_lhs_dynamic_integer_and_rhs_dynamic_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                let a = MResetZ(q) == Zero ? 0 | 1;
+                let b = MResetZ(q) == Zero ? 1 | 0;
+                a &&& b
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__integer_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Call id(1), args( Qubit(0), Result(1), )
+                Variable(3, Boolean) = Call id(2), args( Result(1), )
+                Variable(4, Boolean) = Icmp Eq, Variable(3, Boolean), Bool(false)
+                Branch Variable(4, Boolean), 5, 6
+            Block 2:Block:
+                Variable(2, Integer) = Store Integer(0)
+                Jump(1)
+            Block 3:Block:
+                Variable(2, Integer) = Store Integer(1)
+                Jump(1)
+            Block 4:Block:
+                Variable(6, Integer) = BitwiseAnd Variable(2, Integer), Variable(5, Integer)
+                Call id(3), args( Variable(6, Integer), Pointer, )
+                Return
+            Block 5:Block:
+                Variable(5, Integer) = Store Integer(1)
+                Jump(4)
+            Block 6:Block:
+                Variable(5, Integer) = Store Integer(0)
+                Jump(4)"#]],
+    );
+}
+
+#[test]
+fn integer_bitwise_or_with_lhs_classical_integer_and_rhs_dynamic_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                let i = MResetZ(q) == Zero ? 0 | 1;
+                1 ||| i
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__integer_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Variable(3, Integer) = BitwiseOr Integer(1), Variable(2, Integer)
+                Call id(3), args( Variable(3, Integer), Pointer, )
+                Return
+            Block 2:Block:
+                Variable(2, Integer) = Store Integer(0)
+                Jump(1)
+            Block 3:Block:
+                Variable(2, Integer) = Store Integer(1)
+                Jump(1)"#]],
+    );
+}
+
+#[test]
+fn integer_bitwise_xor_with_lhs_dynamic_integer_and_rhs_classical_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                let i = MResetZ(q) == Zero ? 0 | 1;
+                i ^^^ 1
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__integer_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Variable(3, Integer) = BitwiseXor Variable(2, Integer), Integer(1)
+                Call id(3), args( Variable(3, Integer), Pointer, )
+                Return
+            Block 2:Block:
+                Variable(2, Integer) = Store Integer(0)
+                Jump(1)
+            Block 3:Block:
+                Variable(2, Integer) = Store Integer(1)
+                Jump(1)"#]],
+    );
+}
+
+#[test]
+fn integer_bitwise_left_shif_with_lhs_dynamic_integer_and_rhs_dynamic_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                let a = MResetZ(q) == Zero ? 0 | 1;
+                let b = MResetZ(q) == Zero ? 1 | 0;
+                a <<< b
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__integer_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Call id(1), args( Qubit(0), Result(1), )
+                Variable(3, Boolean) = Call id(2), args( Result(1), )
+                Variable(4, Boolean) = Icmp Eq, Variable(3, Boolean), Bool(false)
+                Branch Variable(4, Boolean), 5, 6
+            Block 2:Block:
+                Variable(2, Integer) = Store Integer(0)
+                Jump(1)
+            Block 3:Block:
+                Variable(2, Integer) = Store Integer(1)
+                Jump(1)
+            Block 4:Block:
+                Variable(6, Integer) = Shl Variable(2, Integer), Variable(5, Integer)
+                Call id(3), args( Variable(6, Integer), Pointer, )
+                Return
+            Block 5:Block:
+                Variable(5, Integer) = Store Integer(1)
+                Jump(4)
+            Block 6:Block:
+                Variable(5, Integer) = Store Integer(0)
+                Jump(4)"#]],
+    );
+}
+
+#[test]
+fn integer_bitwise_right_shift_with_lhs_classical_integer_and_rhs_dynamic_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Int {
+                use q = Qubit();
+                let i = MResetZ(q) == Zero ? 0 | 1;
+                1 >>> i
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__integer_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Integer
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Variable(3, Integer) = Ashr Integer(1), Variable(2, Integer)
+                Call id(3), args( Variable(3, Integer), Pointer, )
+                Return
+            Block 2:Block:
+                Variable(2, Integer) = Store Integer(0)
+                Jump(1)
+            Block 3:Block:
+                Variable(2, Integer) = Store Integer(1)
+                Jump(1)"#]],
+    );
+}
+
+#[test]
+fn integer_equality_comparison_with_lhs_dynamic_integer_and_rhs_classical_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                let i = MResetZ(q) == Zero ? 0 | 1;
+                i == 1
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__bool_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Boolean
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Variable(3, Boolean) = Icmp Eq, Variable(2, Integer), Integer(1)
+                Call id(3), args( Variable(3, Boolean), Pointer, )
+                Return
+            Block 2:Block:
+                Variable(2, Integer) = Store Integer(0)
+                Jump(1)
+            Block 3:Block:
+                Variable(2, Integer) = Store Integer(1)
+                Jump(1)"#]],
+    );
+}
+
+#[test]
+fn integer_inequality_comparison_with_lhs_dynamic_integer_and_rhs_dynamic_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                let a = MResetZ(q) == Zero ? 0 | 1;
+                let b = MResetZ(q) == Zero ? 1 | 0;
+                a != b
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__bool_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Boolean
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Call id(1), args( Qubit(0), Result(1), )
+                Variable(3, Boolean) = Call id(2), args( Result(1), )
+                Variable(4, Boolean) = Icmp Eq, Variable(3, Boolean), Bool(false)
+                Branch Variable(4, Boolean), 5, 6
+            Block 2:Block:
+                Variable(2, Integer) = Store Integer(0)
+                Jump(1)
+            Block 3:Block:
+                Variable(2, Integer) = Store Integer(1)
+                Jump(1)
+            Block 4:Block:
+                Variable(6, Boolean) = Icmp Ne, Variable(2, Integer), Variable(5, Integer)
+                Call id(3), args( Variable(6, Boolean), Pointer, )
+                Return
+            Block 5:Block:
+                Variable(5, Integer) = Store Integer(1)
+                Jump(4)
+            Block 6:Block:
+                Variable(5, Integer) = Store Integer(0)
+                Jump(4)"#]],
+    );
+}
+
+#[test]
+fn integer_greater_than_comparison_with_lhs_classical_integer_and_rhs_dynamic_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                let i = MResetZ(q) == Zero ? 0 | 1;
+                1 > i
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__bool_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Boolean
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Variable(3, Boolean) = Icmp Sgt, Integer(1), Variable(2, Integer)
+                Call id(3), args( Variable(3, Boolean), Pointer, )
+                Return
+            Block 2:Block:
+                Variable(2, Integer) = Store Integer(0)
+                Jump(1)
+            Block 3:Block:
+                Variable(2, Integer) = Store Integer(1)
+                Jump(1)"#]],
+    );
+}
+
+#[test]
+fn integer_greater_or_equal_than_comparison_with_lhs_dynamic_integer_and_rhs_classical_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                let i = MResetZ(q) == Zero ? 0 | 1;
+                i >= 1
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__bool_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Boolean
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Variable(3, Boolean) = Icmp Sge, Variable(2, Integer), Integer(1)
+                Call id(3), args( Variable(3, Boolean), Pointer, )
+                Return
+            Block 2:Block:
+                Variable(2, Integer) = Store Integer(0)
+                Jump(1)
+            Block 3:Block:
+                Variable(2, Integer) = Store Integer(1)
+                Jump(1)"#]],
+    );
+}
+
+#[test]
+fn integer_less_than_comparison_with_lhs_dynamic_integer_and_rhs_dynamic_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                let a = MResetZ(q) == Zero ? 0 | 1;
+                let b = MResetZ(q) == Zero ? 1 | 0;
+                a < b
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__bool_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Boolean
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Call id(1), args( Qubit(0), Result(1), )
+                Variable(3, Boolean) = Call id(2), args( Result(1), )
+                Variable(4, Boolean) = Icmp Eq, Variable(3, Boolean), Bool(false)
+                Branch Variable(4, Boolean), 5, 6
+            Block 2:Block:
+                Variable(2, Integer) = Store Integer(0)
+                Jump(1)
+            Block 3:Block:
+                Variable(2, Integer) = Store Integer(1)
+                Jump(1)
+            Block 4:Block:
+                Variable(6, Boolean) = Icmp Slt, Variable(2, Integer), Variable(5, Integer)
+                Call id(3), args( Variable(6, Boolean), Pointer, )
+                Return
+            Block 5:Block:
+                Variable(5, Integer) = Store Integer(1)
+                Jump(4)
+            Block 6:Block:
+                Variable(5, Integer) = Store Integer(0)
+                Jump(4)"#]],
+    );
+}
+
+#[test]
+fn integer_less_or_equal_than_comparison_with_lhs_classical_integer_and_rhs_dynamic_integer() {
+    let program = get_rir_program(indoc! {
+        r#"
+        namespace Test {
+            @EntryPoint()
+            operation Main() : Bool {
+                use q = Qubit();
+                let i = MResetZ(q) == Zero ? 0 | 1;
+                1 <= i
+            }
+        }
+        "#,
+    });
+    let measurement_callable_id = CallableId(1);
+    assert_callable(
+        &program,
+        measurement_callable_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__qis__mresetz__body
+                call_type: Measurement
+                input_type:
+                    [0]: Qubit
+                    [1]: Result
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    let readout_callable_id = CallableId(2);
+    assert_callable(
+        &program,
+        readout_callable_id,
+        &expect![[r#"
+        Callable:
+            name: __quantum__qis__read_result__body
+            call_type: Readout
+            input_type:
+                [0]: Result
+            output_type: Boolean
+            body: <NONE>"#]],
+    );
+    let output_record_id = CallableId(3);
+    assert_callable(
+        &program,
+        output_record_id,
+        &expect![[r#"
+            Callable:
+                name: __quantum__rt__bool_record_output
+                call_type: OutputRecording
+                input_type:
+                    [0]: Boolean
+                    [1]: Pointer
+                output_type: <VOID>
+                body: <NONE>"#]],
+    );
+    assert_blocks(
+        &program,
+        &expect![[r#"
+            Blocks:
+            Block 0:Block:
+                Call id(1), args( Qubit(0), Result(0), )
+                Variable(0, Boolean) = Call id(2), args( Result(0), )
+                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
+                Branch Variable(1, Boolean), 2, 3
+            Block 1:Block:
+                Variable(3, Boolean) = Icmp Sle, Integer(1), Variable(2, Integer)
+                Call id(3), args( Variable(3, Boolean), Pointer, )
+                Return
+            Block 2:Block:
+                Variable(2, Integer) = Store Integer(0)
+                Jump(1)
+            Block 3:Block:
+                Variable(2, Integer) = Store Integer(1)
+                Jump(1)"#]],
+    );
+}
diff --git a/compiler/qsc_partial_eval/tests/output_recording.rs b/compiler/qsc_partial_eval/tests/output_recording.rs
index 8f499934..4b5fd288 100644
--- a/compiler/qsc_partial_eval/tests/output_recording.rs
+++ b/compiler/qsc_partial_eval/tests/output_recording.rs
@@ -159,7 +159,7 @@ fn output_recording_for_nested_tuples() {
                     Variable(0, Boolean) = Call id(2), args( Result(0), )
                     Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
                     Variable(2, Boolean) = Call id(2), args( Result(0), )
-                    Variable(3, Boolean) = Icmp Eq, Variable(2, Boolean), Bool(true)
+                    Variable(3, Boolean) = Store Variable(2, Boolean)
                     Call id(3), args( Integer(3), Pointer, )
                     Call id(4), args( Result(0), Pointer, )
                     Call id(3), args( Integer(2), Pointer, )
@@ -255,7 +255,7 @@ fn output_recording_for_tuple_of_arrays() {
                     Variable(0, Boolean) = Call id(2), args( Result(0), )
                     Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
                     Variable(2, Boolean) = Call id(2), args( Result(0), )
-                    Variable(3, Boolean) = Icmp Eq, Variable(2, Boolean), Bool(true)
+                    Variable(3, Boolean) = Store Variable(2, Boolean)
                     Call id(3), args( Integer(2), Pointer, )
                     Call id(4), args( Result(0), Pointer, )
                     Call id(5), args( Integer(2), Pointer, )
@@ -347,7 +347,7 @@ fn output_recording_for_array_of_tuples() {
                     Variable(0, Boolean) = Call id(2), args( Result(0), )
                     Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(false)
                     Variable(2, Boolean) = Call id(2), args( Result(0), )
-                    Variable(3, Boolean) = Icmp Eq, Variable(2, Boolean), Bool(true)
+                    Variable(3, Boolean) = Store Variable(2, Boolean)
                     Call id(3), args( Integer(2), Pointer, )
                     Call id(4), args( Integer(2), Pointer, )
                     Call id(5), args( Result(0), Pointer, )
diff --git a/compiler/qsc_partial_eval/tests/results.rs b/compiler/qsc_partial_eval/tests/results.rs
index 8c15c6e7..97110b2b 100644
--- a/compiler/qsc_partial_eval/tests/results.rs
+++ b/compiler/qsc_partial_eval/tests/results.rs
@@ -340,291 +340,3 @@ fn result_ids_are_correct_for_measuring_multiple_qubits() {
     assert_eq!(program.num_qubits, 3);
     assert_eq!(program.num_results, 3);
 }
-
-#[test]
-fn comparing_measurement_results_for_equality_adds_read_result_and_comparison_instructions() {
-    let program = get_rir_program(indoc! {
-        r#"
-        namespace Test {
-            @EntryPoint()
-            operation Main() : Bool {
-                use (q0, q1) = (Qubit(), Qubit());
-                let r0 = QIR.Intrinsic.__quantum__qis__m__body(q0);
-                let r1 = QIR.Intrinsic.__quantum__qis__m__body(q1);
-                r0 == r1
-            }
-        }
-        "#,
-    });
-    let measurement_callable_id = CallableId(1);
-    assert_callable(
-        &program,
-        measurement_callable_id,
-        &expect![[r#"
-        Callable:
-            name: __quantum__qis__mz__body
-            call_type: Measurement
-            input_type:
-                [0]: Qubit
-                [1]: Result
-            output_type: <VOID>
-            body: <NONE>"#]],
-    );
-    let readout_callable_id = CallableId(2);
-    assert_callable(
-        &program,
-        readout_callable_id,
-        &expect![[r#"
-        Callable:
-            name: __quantum__qis__read_result__body
-            call_type: Readout
-            input_type:
-                [0]: Result
-            output_type: Boolean
-            body: <NONE>"#]],
-    );
-    let bool_record_id = CallableId(3);
-    assert_callable(
-        &program,
-        bool_record_id,
-        &expect![[r#"
-        Callable:
-            name: __quantum__rt__bool_record_output
-            call_type: OutputRecording
-            input_type:
-                [0]: Boolean
-                [1]: Pointer
-            output_type: <VOID>
-            body: <NONE>"#]],
-    );
-    assert_block_instructions(
-        &program,
-        BlockId(0),
-        &expect![[r#"
-            Block:
-                Call id(1), args( Qubit(0), Result(0), )
-                Call id(1), args( Qubit(1), Result(1), )
-                Variable(0, Boolean) = Call id(2), args( Result(0), )
-                Variable(1, Boolean) = Call id(2), args( Result(1), )
-                Variable(2, Boolean) = Icmp Eq, Variable(0, Boolean), Variable(1, Boolean)
-                Call id(3), args( Variable(2, Boolean), Pointer, )
-                Return"#]],
-    );
-    assert_eq!(program.num_qubits, 2);
-    assert_eq!(program.num_results, 2);
-}
-
-#[test]
-fn comparing_measurement_results_for_inequality_adds_read_result_and_comparison_instructions() {
-    let program = get_rir_program(indoc! {
-        r#"
-        namespace Test {
-            @EntryPoint()
-            operation Main() : Bool {
-                use (q0, q1) = (Qubit(), Qubit());
-                let r0 = QIR.Intrinsic.__quantum__qis__m__body(q0);
-                let r1 = QIR.Intrinsic.__quantum__qis__m__body(q1);
-                r0 != r1
-            }
-        }
-        "#,
-    });
-    let measurement_callable_id = CallableId(1);
-    assert_callable(
-        &program,
-        measurement_callable_id,
-        &expect![[r#"
-        Callable:
-            name: __quantum__qis__mz__body
-            call_type: Measurement
-            input_type:
-                [0]: Qubit
-                [1]: Result
-            output_type: <VOID>
-            body: <NONE>"#]],
-    );
-    let readout_callable_id = CallableId(2);
-    assert_callable(
-        &program,
-        readout_callable_id,
-        &expect![[r#"
-        Callable:
-            name: __quantum__qis__read_result__body
-            call_type: Readout
-            input_type:
-                [0]: Result
-            output_type: Boolean
-            body: <NONE>"#]],
-    );
-    let bool_record_id = CallableId(3);
-    assert_callable(
-        &program,
-        bool_record_id,
-        &expect![[r#"
-        Callable:
-            name: __quantum__rt__bool_record_output
-            call_type: OutputRecording
-            input_type:
-                [0]: Boolean
-                [1]: Pointer
-            output_type: <VOID>
-            body: <NONE>"#]],
-    );
-    assert_block_instructions(
-        &program,
-        BlockId(0),
-        &expect![[r#"
-            Block:
-                Call id(1), args( Qubit(0), Result(0), )
-                Call id(1), args( Qubit(1), Result(1), )
-                Variable(0, Boolean) = Call id(2), args( Result(0), )
-                Variable(1, Boolean) = Call id(2), args( Result(1), )
-                Variable(2, Boolean) = Icmp Ne, Variable(0, Boolean), Variable(1, Boolean)
-                Call id(3), args( Variable(2, Boolean), Pointer, )
-                Return"#]],
-    );
-    assert_eq!(program.num_qubits, 2);
-    assert_eq!(program.num_results, 2);
-}
-
-#[test]
-fn comparing_measurement_result_against_result_literal_for_equality_adds_read_result_and_comparison_instructions(
-) {
-    let program = get_rir_program(indoc! {
-        r#"
-        namespace Test {
-            @EntryPoint()
-            operation Main() : Bool {
-                use q = Qubit();
-                let r = QIR.Intrinsic.__quantum__qis__m__body(q);
-                r == One
-            }
-        }
-        "#,
-    });
-    let measurement_callable_id = CallableId(1);
-    assert_callable(
-        &program,
-        measurement_callable_id,
-        &expect![[r#"
-        Callable:
-            name: __quantum__qis__mz__body
-            call_type: Measurement
-            input_type:
-                [0]: Qubit
-                [1]: Result
-            output_type: <VOID>
-            body: <NONE>"#]],
-    );
-    let readout_callable_id = CallableId(2);
-    assert_callable(
-        &program,
-        readout_callable_id,
-        &expect![[r#"
-        Callable:
-            name: __quantum__qis__read_result__body
-            call_type: Readout
-            input_type:
-                [0]: Result
-            output_type: Boolean
-            body: <NONE>"#]],
-    );
-    let bool_record_id = CallableId(3);
-    assert_callable(
-        &program,
-        bool_record_id,
-        &expect![[r#"
-        Callable:
-            name: __quantum__rt__bool_record_output
-            call_type: OutputRecording
-            input_type:
-                [0]: Boolean
-                [1]: Pointer
-            output_type: <VOID>
-            body: <NONE>"#]],
-    );
-    assert_block_instructions(
-        &program,
-        BlockId(0),
-        &expect![[r#"
-            Block:
-                Call id(1), args( Qubit(0), Result(0), )
-                Variable(0, Boolean) = Call id(2), args( Result(0), )
-                Variable(1, Boolean) = Icmp Eq, Variable(0, Boolean), Bool(true)
-                Call id(3), args( Variable(1, Boolean), Pointer, )
-                Return"#]],
-    );
-    assert_eq!(program.num_qubits, 1);
-    assert_eq!(program.num_results, 1);
-}
-
-#[test]
-fn comparing_measurement_result_against_result_literal_for_inequality_adds_read_result_and_comparison_instructions(
-) {
-    let program = get_rir_program(indoc! {
-        r#"
-        namespace Test {
-            @EntryPoint()
-            operation Main() : Bool {
-                use q = Qubit();
-                let r = QIR.Intrinsic.__quantum__qis__m__body(q);
-                r != Zero
-            }
-        }
-        "#,
-    });
-    let measurement_callable_id = CallableId(1);
-    assert_callable(
-        &program,
-        measurement_callable_id,
-        &expect![[r#"
-        Callable:
-            name: __quantum__qis__mz__body
-            call_type: Measurement
-            input_type:
-                [0]: Qubit
-                [1]: Result
-            output_type: <VOID>
-            body: <NONE>"#]],
-    );
-    let readout_callable_id = CallableId(2);
-    assert_callable(
-        &program,
-        readout_callable_id,
-        &expect![[r#"
-        Callable:
-            name: __quantum__qis__read_result__body
-            call_type: Readout
-            input_type:
-                [0]: Result
-            output_type: Boolean
-            body: <NONE>"#]],
-    );
-    let bool_record_id = CallableId(3);
-    assert_callable(
-        &program,
-        bool_record_id,
-        &expect![[r#"
-        Callable:
-            name: __quantum__rt__bool_record_output
-            call_type: OutputRecording
-            input_type:
-                [0]: Boolean
-                [1]: Pointer
-            output_type: <VOID>
-            body: <NONE>"#]],
-    );
-    assert_block_instructions(
-        &program,
-        BlockId(0),
-        &expect![[r#"
-            Block:
-                Call id(1), args( Qubit(0), Result(0), )
-                Variable(0, Boolean) = Call id(2), args( Result(0), )
-                Variable(1, Boolean) = Icmp Ne, Variable(0, Boolean), Bool(false)
-                Call id(3), args( Variable(1, Boolean), Pointer, )
-                Return"#]],
-    );
-    assert_eq!(program.num_qubits, 1);
-    assert_eq!(program.num_results, 1);
-}
diff --git a/compiler/qsc_partial_eval/tests/returns.rs b/compiler/qsc_partial_eval/tests/returns.rs
index a03ddc77..41996118 100644
--- a/compiler/qsc_partial_eval/tests/returns.rs
+++ b/compiler/qsc_partial_eval/tests/returns.rs
@@ -930,10 +930,9 @@ fn explicit_return_embedded_in_assign_op_expr_yields_error() {
         }
     }
     "#});
-    // The type of error will change once this kind of hybrid expression is supported.
     assert_error(
         &error,
-        &expect![[r#"Unimplemented("int binary operation", Span { lo: 166, hi: 167 })"#]],
+        &expect![[r#"Unexpected("embedded return in RHS expression", Span { lo: 171, hi: 183 })"#]],
     );
 }
 
@@ -951,9 +950,7 @@ fn explicit_return_embedded_in_bin_op_expr_yields_error() {
     "#});
     assert_error(
         &error,
-        &expect![[
-            r#"Unexpected("embedded return in binary operation", Span { lo: 151, hi: 163 })"#
-        ]],
+        &expect![[r#"Unexpected("embedded return in RHS expression", Span { lo: 151, hi: 163 })"#]],
     );
 }
 
diff --git a/compiler/qsc_rca/tests/assigns.rs b/compiler/qsc_rca/tests/assigns.rs
index 98f4bdf3..cc02a254 100644
--- a/compiler/qsc_rca/tests/assigns.rs
+++ b/compiler/qsc_rca/tests/assigns.rs
@@ -276,3 +276,101 @@ fn check_rca_for_assign_dynamic_call_result_to_tuple_of_vars() {
                 dynamic_param_applications: <empty>"#]],
     );
 }
+
+#[test]
+fn check_rca_for_mutable_classical_integer_assigned_updated_with_classical_integer() {
+    let mut compilation_context = CompilationContext::default();
+    compilation_context.update(
+        r#"
+        open Microsoft.Quantum.Convert;
+        open Microsoft.Quantum.Measurement;
+        use register = Qubit[8];
+        let results = MeasureEachZ(register);
+        mutable i = 0;
+        set i += 1;
+        i"#,
+    );
+    let package_store_compute_properties = compilation_context.get_compute_properties();
+    check_last_statement_compute_properties(
+        package_store_compute_properties,
+        &expect![[r#"
+            ApplicationsGeneratorSet:
+                inherent: Classical
+                dynamic_param_applications: <empty>"#]],
+    );
+}
+
+#[test]
+fn check_rca_for_mutable_classical_integer_assigned_updated_with_dynamic_integer() {
+    let mut compilation_context = CompilationContext::default();
+    compilation_context.update(
+        r#"
+        open Microsoft.Quantum.Convert;
+        open Microsoft.Quantum.Measurement;
+        use register = Qubit[8];
+        let results = MeasureEachZ(register);
+        mutable i = 0;
+        set i += ResultArrayAsInt(results);
+        i"#,
+    );
+    let package_store_compute_properties = compilation_context.get_compute_properties();
+    check_last_statement_compute_properties(
+        package_store_compute_properties,
+        &expect![[r#"
+            ApplicationsGeneratorSet:
+                inherent: Quantum: QuantumProperties:
+                    runtime_features: RuntimeFeatureFlags(UseOfDynamicBool | UseOfDynamicInt)
+                    value_kind: Element(Dynamic)
+                dynamic_param_applications: <empty>"#]],
+    );
+}
+
+#[test]
+fn check_rca_for_mutable_dynamic_integer_assigned_updated_with_classical_integer() {
+    let mut compilation_context = CompilationContext::default();
+    compilation_context.update(
+        r#"
+        open Microsoft.Quantum.Convert;
+        open Microsoft.Quantum.Measurement;
+        use register = Qubit[8];
+        let results = MeasureEachZ(register);
+        mutable i = ResultArrayAsInt(results);
+        set i += 1;
+        i"#,
+    );
+    let package_store_compute_properties = compilation_context.get_compute_properties();
+    check_last_statement_compute_properties(
+        package_store_compute_properties,
+        &expect![[r#"
+            ApplicationsGeneratorSet:
+                inherent: Quantum: QuantumProperties:
+                    runtime_features: RuntimeFeatureFlags(UseOfDynamicBool | UseOfDynamicInt)
+                    value_kind: Element(Dynamic)
+                dynamic_param_applications: <empty>"#]],
+    );
+}
+
+#[test]
+fn check_rca_for_mutable_dynamic_integer_assigned_updated_with_dynamic_integer() {
+    let mut compilation_context = CompilationContext::default();
+    compilation_context.update(
+        r#"
+        open Microsoft.Quantum.Convert;
+        open Microsoft.Quantum.Measurement;
+        use register = Qubit[8];
+        let results = MeasureEachZ(register);
+        mutable i = ResultArrayAsInt(results);
+        set i += ResultArrayAsInt(results);
+        i"#,
+    );
+    let package_store_compute_properties = compilation_context.get_compute_properties();
+    check_last_statement_compute_properties(
+        package_store_compute_properties,
+        &expect![[r#"
+            ApplicationsGeneratorSet:
+                inherent: Quantum: QuantumProperties:
+                    runtime_features: RuntimeFeatureFlags(UseOfDynamicBool | UseOfDynamicInt)
+                    value_kind: Element(Dynamic)
+                dynamic_param_applications: <empty>"#]],
+    );
+}
diff --git a/compiler/qsc_rir/src/passes/ssa_transform/tests.rs b/compiler/qsc_rir/src/passes/ssa_transform/tests.rs
index d5f54232..8c5c8ae8 100644
--- a/compiler/qsc_rir/src/passes/ssa_transform/tests.rs
+++ b/compiler/qsc_rir/src/passes/ssa_transform/tests.rs
@@ -2055,3 +2055,169 @@ fn ssa_transform_inerts_phi_nodes_for_early_return_graph_pattern() {
             num_qubits: 0
             num_results: 0"#]].assert_eq(&program.to_string());
 }
+
+#[test]
+fn ssa_transform_propagates_updates_from_multiple_predecessors_to_later_single_successors() {
+    let mut program = new_program();
+    program.callables.insert(
+        CallableId(1),
+        Callable {
+            name: "dynamic_bool".to_string(),
+            input_type: Vec::new(),
+            output_type: Some(Ty::Boolean),
+            body: None,
+            call_type: CallableType::Regular,
+        },
+    );
+
+    // Create a program that has a middle block with multiple predecessors and does not update a value from
+    // the dominating entry block (in this case, the bool value for the first branch).
+    // All successors of the middle block should have the same value for this variable, even if it isn't used,
+    // avoiding a panic in the SSA transformation if the value is not propagated through the variable
+    // maps used for updates.
+    program.blocks.insert(
+        BlockId(0),
+        Block(vec![
+            Instruction::Call(
+                CallableId(1),
+                Vec::new(),
+                Some(Variable {
+                    variable_id: VariableId(0),
+                    ty: Ty::Boolean,
+                }),
+            ),
+            Instruction::Store(
+                Operand::Variable(Variable {
+                    variable_id: VariableId(0),
+                    ty: Ty::Boolean,
+                }),
+                Variable {
+                    variable_id: VariableId(1),
+                    ty: Ty::Boolean,
+                },
+            ),
+            Instruction::Branch(
+                Variable {
+                    variable_id: VariableId(1),
+                    ty: Ty::Boolean,
+                },
+                BlockId(1),
+                BlockId(2),
+            ),
+        ]),
+    );
+    program
+        .blocks
+        .insert(BlockId(1), Block(vec![Instruction::Jump(BlockId(2))]));
+    program.blocks.insert(
+        BlockId(2),
+        Block(vec![
+            Instruction::Call(
+                CallableId(1),
+                Vec::new(),
+                Some(Variable {
+                    variable_id: VariableId(2),
+                    ty: Ty::Boolean,
+                }),
+            ),
+            Instruction::Store(
+                Operand::Variable(Variable {
+                    variable_id: VariableId(2),
+                    ty: Ty::Boolean,
+                }),
+                Variable {
+                    variable_id: VariableId(3),
+                    ty: Ty::Boolean,
+                },
+            ),
+            Instruction::Branch(
+                Variable {
+                    variable_id: VariableId(3),
+                    ty: Ty::Boolean,
+                },
+                BlockId(3),
+                BlockId(4),
+            ),
+        ]),
+    );
+    program
+        .blocks
+        .insert(BlockId(3), Block(vec![Instruction::Jump(BlockId(4))]));
+    program
+        .blocks
+        .insert(BlockId(4), Block(vec![Instruction::Return]));
+
+    // Before
+    expect![[r#"
+        Program:
+            entry: 0
+            callables:
+                Callable 0: Callable:
+                    name: main
+                    call_type: Regular
+                    input_type: <VOID>
+                    output_type: <VOID>
+                    body: 0
+                Callable 1: Callable:
+                    name: dynamic_bool
+                    call_type: Regular
+                    input_type: <VOID>
+                    output_type: Boolean
+                    body: <NONE>
+            blocks:
+                Block 0: Block:
+                    Variable(0, Boolean) = Call id(1), args( )
+                    Variable(1, Boolean) = Store Variable(0, Boolean)
+                    Branch Variable(1, Boolean), 1, 2
+                Block 1: Block:
+                    Jump(2)
+                Block 2: Block:
+                    Variable(2, Boolean) = Call id(1), args( )
+                    Variable(3, Boolean) = Store Variable(2, Boolean)
+                    Branch Variable(3, Boolean), 3, 4
+                Block 3: Block:
+                    Jump(4)
+                Block 4: Block:
+                    Return
+            config: Config:
+                capabilities: Base
+            num_qubits: 0
+            num_results: 0"#]]
+    .assert_eq(&program.to_string());
+
+    // After
+    transform_program(&mut program);
+    expect![[r#"
+        Program:
+            entry: 0
+            callables:
+                Callable 0: Callable:
+                    name: main
+                    call_type: Regular
+                    input_type: <VOID>
+                    output_type: <VOID>
+                    body: 0
+                Callable 1: Callable:
+                    name: dynamic_bool
+                    call_type: Regular
+                    input_type: <VOID>
+                    output_type: Boolean
+                    body: <NONE>
+            blocks:
+                Block 0: Block:
+                    Variable(0, Boolean) = Call id(1), args( )
+                    Branch Variable(0, Boolean), 1, 2
+                Block 1: Block:
+                    Jump(2)
+                Block 2: Block:
+                    Variable(2, Boolean) = Call id(1), args( )
+                    Branch Variable(2, Boolean), 3, 4
+                Block 3: Block:
+                    Jump(4)
+                Block 4: Block:
+                    Return
+            config: Config:
+                capabilities: TargetCapabilityFlags(Adaptive | IntegerComputations | FloatingPointComputations | BackwardsBranching | HigherLevelConstructs | QubitReset)
+            num_qubits: 0
+            num_results: 0"#]].assert_eq(&program.to_string());
+}