diff --git a/crates/oxide_vm/src/coercion.rs b/crates/oxide_vm/src/coercion.rs index d267562b..e07b811c 100644 --- a/crates/oxide_vm/src/coercion.rs +++ b/crates/oxide_vm/src/coercion.rs @@ -11,7 +11,7 @@ pub fn to_primitive(val: JsValue) -> JsValue { val } -pub fn to_number(val: JsValue) -> f64 { +pub fn to_number(val: JsValue, string_forge: &StringForge) -> f64 { if val.is_int() { return val.as_int() as f64; } @@ -27,6 +27,12 @@ pub fn to_number(val: JsValue) -> f64 { if val.is_undefined() { return f64::NAN; } + if val.is_string() { + let s = string_forge + .lookup(val.as_string_index()) + .unwrap_or_default(); + return s.parse::().unwrap_or(f64::NAN); + } if val.is_object() { panic_to_object(); } @@ -98,7 +104,7 @@ pub fn to_boolean(val: JsValue) -> bool { false } -pub fn abstract_eq(lhs: JsValue, rhs: JsValue) -> bool { +pub fn abstract_eq(lhs: JsValue, rhs: JsValue, string_forge: &StringForge) -> bool { if lhs.is_null() && rhs.is_undefined() { return true; } @@ -124,16 +130,16 @@ pub fn abstract_eq(lhs: JsValue, rhs: JsValue) -> bool { return true; } if (lhs.is_int() || lhs.is_double()) && (rhs.is_int() || rhs.is_double()) { - return strict_double_eq(to_number(lhs), to_number(rhs)); + return strict_double_eq(to_number(lhs, string_forge), to_number(rhs, string_forge)); } if (lhs.is_int() || lhs.is_double()) && rhs.is_bool() { - return to_number(lhs) == to_number(rhs); + return to_number(lhs, string_forge) == to_number(rhs, string_forge); } if lhs.is_bool() && (rhs.is_int() || rhs.is_double()) { - return to_number(lhs) == to_number(rhs); + return to_number(lhs, string_forge) == to_number(rhs, string_forge); } if lhs.is_bool() || rhs.is_bool() { - return to_number(lhs) == to_number(rhs); + return to_number(lhs, string_forge) == to_number(rhs, string_forge); } if lhs.is_null() || rhs.is_null() { return false; @@ -186,8 +192,8 @@ pub fn relational_compare(string_forge: &StringForge, lhs: JsValue, rhs: JsValue .unwrap_or_default(); return Some(ls < rs); } - let l = to_number(lhs); - let r = to_number(rhs); + let l = to_number(lhs, string_forge); + let r = to_number(rhs, string_forge); if l.is_nan() || r.is_nan() { return None; } diff --git a/crates/oxide_vm/src/vm.rs b/crates/oxide_vm/src/vm.rs index 37546fe1..2d3fd2a9 100644 --- a/crates/oxide_vm/src/vm.rs +++ b/crates/oxide_vm/src/vm.rs @@ -164,48 +164,56 @@ impl Vm { let concat = format!("{ls}{rs}"); self.regs[rd] = self.intern(&concat); } else { - let ln = coercion::to_number(lhs); - let rn = coercion::to_number(rhs); + let ln = coercion::to_number(lhs, self.kernel.string_forge().as_ref()); + let rn = coercion::to_number(rhs, self.kernel.string_forge().as_ref()); self.regs[rd] = JsValue::float(ln + rn); } } OpCode::SUB => { - let l = coercion::to_number(self.regs[a]); - let r = coercion::to_number(self.regs[b]); + let l = coercion::to_number(self.regs[a], self.kernel.string_forge().as_ref()); + let r = coercion::to_number(self.regs[b], self.kernel.string_forge().as_ref()); self.regs[rd] = JsValue::float(l - r); } OpCode::MUL => { - let l = coercion::to_number(self.regs[a]); - let r = coercion::to_number(self.regs[b]); + let l = coercion::to_number(self.regs[a], self.kernel.string_forge().as_ref()); + let r = coercion::to_number(self.regs[b], self.kernel.string_forge().as_ref()); self.regs[rd] = JsValue::float(l * r); } OpCode::DIV => { - let l = coercion::to_number(self.regs[a]); - let r = coercion::to_number(self.regs[b]); + let l = coercion::to_number(self.regs[a], self.kernel.string_forge().as_ref()); + let r = coercion::to_number(self.regs[b], self.kernel.string_forge().as_ref()); self.regs[rd] = JsValue::float(l / r); } OpCode::MOD => { - let l = coercion::to_number(self.regs[a]); - let r = coercion::to_number(self.regs[b]); + let l = coercion::to_number(self.regs[a], self.kernel.string_forge().as_ref()); + let r = coercion::to_number(self.regs[b], self.kernel.string_forge().as_ref()); self.regs[rd] = JsValue::float(l % r); } OpCode::NEG => { - let v = coercion::to_number(self.regs[a]); + let v = coercion::to_number(self.regs[a], self.kernel.string_forge().as_ref()); self.regs[rd] = JsValue::float(-v); } OpCode::EQ => { - let eq = coercion::abstract_eq(self.regs[a], self.regs[b]); + let eq = coercion::abstract_eq( + self.regs[a], + self.regs[b], + self.kernel.string_forge().as_ref(), + ); self.regs[rd] = JsValue::bool(eq); } OpCode::NEQ => { - let ne = !coercion::abstract_eq(self.regs[a], self.regs[b]); + let ne = !coercion::abstract_eq( + self.regs[a], + self.regs[b], + self.kernel.string_forge().as_ref(), + ); self.regs[rd] = JsValue::bool(ne); }