use super::*; impl MirInterpreter { pub(super) fn reg_load(&self, id: ValueId) -> Result { self.regs .get(&id) .cloned() .ok_or_else(|| VMError::InvalidValue(format!("use of undefined value {:?}", id))) } pub(super) fn eval_binop( &self, op: BinaryOp, a: VMValue, b: VMValue, ) -> Result { use BinaryOp::*; use VMValue::*; Ok(match (op, a, b) { (Add, Integer(x), Integer(y)) => Integer(x + y), (Add, String(s), Integer(y)) => String(format!("{}{}", s, y)), (Add, String(s), Float(y)) => String(format!("{}{}", s, y)), (Add, String(s), Bool(y)) => String(format!("{}{}", s, y)), (Add, String(s), String(t)) => String(format!("{}{}", s, t)), (Add, Integer(x), String(t)) => String(format!("{}{}", x, t)), (Add, Float(x), String(t)) => String(format!("{}{}", x, t)), (Add, Bool(x), String(t)) => String(format!("{}{}", x, t)), (Sub, Integer(x), Integer(y)) => Integer(x - y), (Mul, Integer(x), Integer(y)) => Integer(x * y), (Div, Integer(_), Integer(0)) => return Err(VMError::DivisionByZero), (Div, Integer(x), Integer(y)) => Integer(x / y), (Mod, Integer(_), Integer(0)) => return Err(VMError::DivisionByZero), (Mod, Integer(x), Integer(y)) => Integer(x % y), (Add, Float(x), Float(y)) => Float(x + y), (Sub, Float(x), Float(y)) => Float(x - y), (Mul, Float(x), Float(y)) => Float(x * y), (Div, Float(_), Float(y)) if y == 0.0 => return Err(VMError::DivisionByZero), (Div, Float(x), Float(y)) => Float(x / y), (Mod, Float(x), Float(y)) => Float(x % y), (BitAnd, Integer(x), Integer(y)) => Integer(x & y), (BitOr, Integer(x), Integer(y)) => Integer(x | y), (BitXor, Integer(x), Integer(y)) => Integer(x ^ y), (Shl, Integer(x), Integer(y)) => Integer(x.wrapping_shl(y as u32)), (Shr, Integer(x), Integer(y)) => Integer(x.wrapping_shr(y as u32)), (opk, va, vb) => { return Err(VMError::TypeError(format!( "unsupported binop {:?} on {:?} and {:?}", opk, va, vb ))) } }) } pub(super) fn eval_cmp(&self, op: CompareOp, a: VMValue, b: VMValue) -> Result { use CompareOp::*; use VMValue::*; Ok(match (op, &a, &b) { (Eq, _, _) => eq_vm(&a, &b), (Ne, _, _) => !eq_vm(&a, &b), (Lt, Integer(x), Integer(y)) => x < y, (Le, Integer(x), Integer(y)) => x <= y, (Gt, Integer(x), Integer(y)) => x > y, (Ge, Integer(x), Integer(y)) => x >= y, (Lt, Float(x), Float(y)) => x < y, (Le, Float(x), Float(y)) => x <= y, (Gt, Float(x), Float(y)) => x > y, (Ge, Float(x), Float(y)) => x >= y, (opk, va, vb) => { return Err(VMError::TypeError(format!( "unsupported compare {:?} on {:?} and {:?}", opk, va, vb ))) } }) } }