From 9c21f0ee9c64f8cd844bc45ff352b68a6e9fa485 Mon Sep 17 00:00:00 2001 From: Andrew Morris Date: Thu, 27 Jul 2023 11:42:49 +1000 Subject: [PATCH] Implement instanceof --- inputs/failing/instanceof.ts | 17 +++++++++++++++++ valuescript_vm/src/operations.rs | 25 +++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 inputs/failing/instanceof.ts diff --git a/inputs/failing/instanceof.ts b/inputs/failing/instanceof.ts new file mode 100644 index 0000000..60047f4 --- /dev/null +++ b/inputs/failing/instanceof.ts @@ -0,0 +1,17 @@ +//! test_output([true,false,true]) + +export default () => { + return [ + new X() instanceof X, + new X() instanceof Y, + new Error("") instanceof Error, + ]; +}; + +class X { + x() {} +} + +class Y { + y() {} +} diff --git a/valuescript_vm/src/operations.rs b/valuescript_vm/src/operations.rs index 4564aa9..2741d49 100644 --- a/valuescript_vm/src/operations.rs +++ b/valuescript_vm/src/operations.rs @@ -318,6 +318,10 @@ pub fn op_triple_eq_impl(left: &Val, right: &Val) -> Result { left.hash == right.hash } + #[allow(clippy::vtable_address_comparisons)] // TODO: Is this ok? + (Val::Static(left), Val::Static(right)) => std::ptr::eq(&**left, &**right), + #[allow(clippy::vtable_address_comparisons)] // TODO: Is this ok? + (Val::Dynamic(left), Val::Dynamic(right)) => std::ptr::eq(&**left, &**right), (Val::Static(..) | Val::Dynamic(..) | Val::CopyCounter(..), _) | (_, Val::Static(..) | Val::Dynamic(..) | Val::CopyCounter(..)) => { if left.typeof_() != right.typeof_() { @@ -551,8 +555,25 @@ pub fn op_typeof(input: &Val) -> Val { .to_val() } -pub fn op_instance_of(_left: &Val, _right: &Val) -> Result { - Err("TODO: op_instance_of".to_internal_error()) +pub fn op_instance_of(left: &Val, right: &Val) -> Result { + let class_data = match right.as_class_data() { + Some(class_data) => class_data, + None => return Err("Right-hand side of `instanceof` is not a class".to_type_error()), + }; + + let left_prototype = match left { + Val::Object(obj) => match &obj.prototype { + Some(proto) => proto, + None => return Ok(false.to_val()), + }, + Val::Null => return Ok(false.to_val()), + _ => match left.typeof_() { + VsType::Object => return Err("TODO: instanceof indirection".to_internal_error()), + _ => return Ok(false.to_val()), + }, + }; + + Ok(op_triple_eq_impl(left_prototype, &class_data.prototype)?.to_val()) } pub fn op_in(left: &Val, right: &Val) -> Result {