From 205f5efa027bd2285d5596aa6e444f48ae7e5afc Mon Sep 17 00:00:00 2001 From: Andrew Morris Date: Thu, 25 May 2023 13:45:38 +1000 Subject: [PATCH] Add Symbol builtin --- inputs/passing/basicSymbol.ts | 7 ++ valuescript_common/src/builtins.rs | 3 + valuescript_vm/src/builtins/mod.rs | 2 + valuescript_vm/src/builtins/symbol_builtin.rs | 84 +++++++++++++++++++ valuescript_vm/src/bytecode_decoder.rs | 20 +++-- valuescript_vm/src/operations.rs | 12 ++- 6 files changed, 118 insertions(+), 10 deletions(-) create mode 100644 inputs/passing/basicSymbol.ts create mode 100644 valuescript_vm/src/builtins/symbol_builtin.rs diff --git a/inputs/passing/basicSymbol.ts b/inputs/passing/basicSymbol.ts new file mode 100644 index 0000000..80feff7 --- /dev/null +++ b/inputs/passing/basicSymbol.ts @@ -0,0 +1,7 @@ +// test_output! [Symbol.iterator,{},3] + +export default function main() { + const x = { [Symbol.iterator]: 3 }; + + return [Symbol.iterator, x, x[Symbol.iterator]]; +} diff --git a/valuescript_common/src/builtins.rs b/valuescript_common/src/builtins.rs index a1c4452..92cec2b 100644 --- a/valuescript_common/src/builtins.rs +++ b/valuescript_common/src/builtins.rs @@ -25,6 +25,8 @@ pub enum BuiltinName { Error, TypeError, RangeError, + + Symbol, } pub const BUILTIN_NAMES: [&str; BuiltinName::COUNT] = [ @@ -41,6 +43,7 @@ pub const BUILTIN_NAMES: [&str; BuiltinName::COUNT] = [ "Error", "TypeError", "RangeError", + "Symbol", ]; pub const BUILTIN_COUNT: usize = BuiltinName::COUNT; diff --git a/valuescript_vm/src/builtins/mod.rs b/valuescript_vm/src/builtins/mod.rs index 985cd4c..ee35aae 100644 --- a/valuescript_vm/src/builtins/mod.rs +++ b/valuescript_vm/src/builtins/mod.rs @@ -6,6 +6,7 @@ mod math_builtin; mod number_builtin; pub mod range_error_builtin; mod string_builtin; +mod symbol_builtin; pub mod type_error_builtin; use valuescript_common::BUILTIN_COUNT; @@ -26,4 +27,5 @@ pub static BUILTIN_VALS: [&'static (dyn ValTrait + Sync); BUILTIN_COUNT] = [ &error_builtin::ERROR_BUILTIN, &type_error_builtin::TYPE_ERROR_BUILTIN, &range_error_builtin::RANGE_ERROR_BUILTIN, + &symbol_builtin::SYMBOL_BUILTIN, ]; diff --git a/valuescript_vm/src/builtins/symbol_builtin.rs b/valuescript_vm/src/builtins/symbol_builtin.rs new file mode 100644 index 0000000..531d4f9 --- /dev/null +++ b/valuescript_vm/src/builtins/symbol_builtin.rs @@ -0,0 +1,84 @@ +use std::rc::Rc; + +use num_bigint::BigInt; + +use crate::{ + builtins::type_error_builtin::to_type_error, + native_function::ThisWrapper, + type_error, + vs_array::VsArray, + vs_class::VsClass, + vs_object::VsObject, + vs_symbol::VsSymbol, + vs_value::{LoadFunctionResult, Val, VsType}, + ValTrait, +}; + +pub struct SymbolBuiltin {} + +pub static SYMBOL_BUILTIN: SymbolBuiltin = SymbolBuiltin {}; + +impl ValTrait for SymbolBuiltin { + fn typeof_(&self) -> VsType { + VsType::Object + } + fn val_to_string(&self) -> String { + "[object Symbol]".to_string() + } + fn to_number(&self) -> f64 { + core::f64::NAN + } + fn to_index(&self) -> Option { + None + } + fn is_primitive(&self) -> bool { + false + } + fn to_primitive(&self) -> Val { + Val::String(Rc::new("[object Symbol]".to_string())) + } + fn is_truthy(&self) -> bool { + true + } + fn is_nullish(&self) -> bool { + false + } + fn bind(&self, _params: Vec) -> Option { + None + } + fn as_bigint_data(&self) -> Option { + None + } + fn as_array_data(&self) -> Option> { + None + } + fn as_object_data(&self) -> Option> { + None + } + fn as_class_data(&self) -> Option> { + None + } + + fn load_function(&self) -> LoadFunctionResult { + LoadFunctionResult::NotAFunction + } + + fn sub(&self, key: Val) -> Result { + Ok(match key.val_to_string().as_str() { + "iterator" => Val::Symbol(VsSymbol::ITERATOR), + _ => Val::Undefined, + }) + } + + fn submov(&mut self, _key: Val, _value: Val) -> Result<(), Val> { + type_error!("Cannot assign to subscript of Symbol builtin") + } + + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "\x1b[36m[Symbol]\x1b[39m") + } + + fn codify(&self) -> String { + "Symbol".into() + } +} diff --git a/valuescript_vm/src/bytecode_decoder.rs b/valuescript_vm/src/bytecode_decoder.rs index dc208cc..9c763c7 100644 --- a/valuescript_vm/src/bytecode_decoder.rs +++ b/valuescript_vm/src/bytecode_decoder.rs @@ -11,6 +11,7 @@ use crate::vs_class::VsClass; use crate::vs_function::VsFunction; use crate::vs_object::VsObject; use crate::vs_pointer::VsPointer; +use crate::vs_symbol::VsSymbol; use crate::vs_value::Val; use crate::vs_value::ValTrait; @@ -114,20 +115,25 @@ impl BytecodeDecoder { Val::Array(Rc::new(VsArray::from(vals))) } BytecodeType::Object => { - let mut obj: BTreeMap = BTreeMap::new(); + let mut string_map: BTreeMap = BTreeMap::new(); + let mut symbol_map: BTreeMap = BTreeMap::new(); while self.peek_type() != BytecodeType::End { - obj.insert( - self.decode_val(registers).val_to_string(), - self.decode_val(registers), - ); + let key = self.decode_val(registers); + let value = self.decode_val(registers); + + match key { + Val::String(string) => string_map.insert(string.to_string(), value), + Val::Symbol(symbol) => symbol_map.insert(symbol, value), + key => string_map.insert(key.val_to_string(), value), + }; } self.decode_type(); // End (TODO: assert) Val::Object(Rc::new(VsObject { - string_map: obj, - symbol_map: Default::default(), + string_map, + symbol_map, prototype: None, })) } diff --git a/valuescript_vm/src/operations.rs b/valuescript_vm/src/operations.rs index f6e790d..ab8a4a5 100644 --- a/valuescript_vm/src/operations.rs +++ b/valuescript_vm/src/operations.rs @@ -471,9 +471,15 @@ pub fn op_submov(target: &mut Val, subscript: Val, value: Val) -> Result<(), Val Ok(()) } Val::Object(object_data) => { - Rc::make_mut(object_data) - .string_map - .insert(subscript.val_to_string(), value); + let object_data_mut = Rc::make_mut(object_data); + + match subscript { + Val::String(string) => object_data_mut.string_map.insert(string.to_string(), value), + Val::Symbol(symbol) => object_data_mut.symbol_map.insert(symbol, value), + _ => object_data_mut + .string_map + .insert(subscript.val_to_string(), value), + }; Ok(()) }