use super::*; use super::super::utils::*; impl MirInterpreter { pub(super) fn handle_const(&mut self, dst: ValueId, value: &ConstValue) -> Result<(), VMError> { let v = match value { ConstValue::Integer(i) => VMValue::Integer(*i), ConstValue::Float(f) => VMValue::Float(*f), ConstValue::Bool(b) => VMValue::Bool(*b), ConstValue::String(s) => VMValue::String(s.clone()), ConstValue::Null | ConstValue::Void => VMValue::Void, }; self.regs.insert(dst, v); Ok(()) } pub(super) fn handle_binop( &mut self, dst: ValueId, op: BinaryOp, lhs: ValueId, rhs: ValueId, ) -> Result<(), VMError> { let a = self.reg_load(lhs)?; let b = self.reg_load(rhs)?; // Operator Box (Add) — observe always; adopt gated if let BinaryOp::Add = op { let in_guard = self .cur_fn .as_deref() .map(|n| n.starts_with("AddOperator.apply/")) .unwrap_or(false); if let Some(op_fn) = self.functions.get("AddOperator.apply/2").cloned() { if !in_guard { if crate::config::env::operator_box_add_adopt() { let out = self.exec_function_inner(&op_fn, Some(&[a.clone(), b.clone()]))?; self.regs.insert(dst, out); return Ok(()); } else { let _ = self.exec_function_inner(&op_fn, Some(&[a.clone(), b.clone()])); } } } } let v = self.eval_binop(op, a, b)?; self.regs.insert(dst, v); Ok(()) } pub(super) fn handle_unary_op( &mut self, dst: ValueId, op: crate::mir::UnaryOp, operand: ValueId, ) -> Result<(), VMError> { let x = self.reg_load(operand)?; let v = match op { crate::mir::UnaryOp::Neg => match x { VMValue::Integer(i) => VMValue::Integer(-i), VMValue::Float(f) => VMValue::Float(-f), _ => { return Err(VMError::TypeError(format!( "neg expects number, got {:?}", x ))) } }, crate::mir::UnaryOp::Not => VMValue::Bool(!to_bool_vm(&x).map_err(VMError::TypeError)?), crate::mir::UnaryOp::BitNot => match x { VMValue::Integer(i) => VMValue::Integer(!i), _ => { return Err(VMError::TypeError(format!( "bitnot expects integer, got {:?}", x ))) } }, }; self.regs.insert(dst, v); Ok(()) } pub(super) fn handle_compare( &mut self, dst: ValueId, op: CompareOp, lhs: ValueId, rhs: ValueId, ) -> Result<(), VMError> { let a = self.reg_load(lhs)?; let b = self.reg_load(rhs)?; // Operator Box (Compare) — observe always; adopt gated if let Some(op_fn) = self.functions.get("CompareOperator.apply/3").cloned() { let in_guard = self .cur_fn .as_deref() .map(|n| n.starts_with("CompareOperator.apply/")) .unwrap_or(false); let opname = match op { CompareOp::Eq => "Eq", CompareOp::Ne => "Ne", CompareOp::Lt => "Lt", CompareOp::Le => "Le", CompareOp::Gt => "Gt", CompareOp::Ge => "Ge", }; if !in_guard { if crate::config::env::operator_box_compare_adopt() { let out = self.exec_function_inner( &op_fn, Some(&[VMValue::String(opname.to_string()), a.clone(), b.clone()]), )?; let res = match out { VMValue::Bool(b) => b, _ => self.eval_cmp(op, a.clone(), b.clone())?, }; self.regs.insert(dst, VMValue::Bool(res)); return Ok(()); } else { let _ = self.exec_function_inner( &op_fn, Some(&[VMValue::String(opname.to_string()), a.clone(), b.clone()]), ); } } } let res = self.eval_cmp(op, a, b)?; self.regs.insert(dst, VMValue::Bool(res)); Ok(()) } pub(super) fn handle_copy(&mut self, dst: ValueId, src: ValueId) -> Result<(), VMError> { let v = self.reg_load(src)?; self.regs.insert(dst, v); Ok(()) } }