diff --git a/.vscode/launch.json b/.vscode/launch.json index c67b7f8..ccb8606 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -7,12 +7,12 @@ { "type": "lldb", "request": "launch", - "name": "Debug executable 'value_script'", + "name": "Debug executable 'vstc'", "cargo": { "args": [ "build", - "--bin=vstc", - "--package=value_script" + "-p", + "vstc" ], "filter": { "name": "vstc", @@ -42,4 +42,4 @@ "cwd": "${workspaceFolder}" } ] -} \ No newline at end of file +} diff --git a/valuescript_vm/src/bytecode_decoder.rs b/valuescript_vm/src/bytecode_decoder.rs index 1ae1459..b15d756 100644 --- a/valuescript_vm/src/bytecode_decoder.rs +++ b/valuescript_vm/src/bytecode_decoder.rs @@ -95,60 +95,70 @@ impl BytecodeDecoder { return BytecodeType::from_byte(self.peek_byte()); } - pub fn decode_val(&mut self, registers: &Vec) -> Val { + pub fn decode_vallish<'a>(&mut self, registers: &'a Vec) -> Vallish<'a> { + use Vallish::*; + return match self.decode_type() { BytecodeType::End => panic!("Cannot decode end"), - BytecodeType::Void => Val::Void, - BytecodeType::Undefined => Val::Undefined, - BytecodeType::Null => Val::Null, - BytecodeType::False => Val::Bool(false), - BytecodeType::True => Val::Bool(true), - BytecodeType::SignedByte => (self.decode_signed_byte() as f64).to_val(), - BytecodeType::Number => self.decode_number().to_val(), - BytecodeType::String => self.decode_string().to_val(), - BytecodeType::Array => self.decode_vec_val(registers).to_val(), + BytecodeType::Void => Own(Val::Void), + BytecodeType::Undefined => Own(Val::Undefined), + BytecodeType::Null => Own(Val::Null), + BytecodeType::False => Own(Val::Bool(false)), + BytecodeType::True => Own(Val::Bool(true)), + BytecodeType::SignedByte => Own((self.decode_signed_byte() as f64).to_val()), + BytecodeType::Number => Own(self.decode_number().to_val()), + BytecodeType::String => Own(self.decode_string().to_val()), + BytecodeType::Array => Own(self.decode_vec_val(registers).to_val()), BytecodeType::Object => { let mut string_map: BTreeMap = BTreeMap::new(); let mut symbol_map: BTreeMap = BTreeMap::new(); while self.peek_type() != BytecodeType::End { - let key = self.decode_val(registers); + let key = self.decode_vallish(registers); let value = self.decode_val(registers); - match key { + match key.get_ref() { Val::String(string) => string_map.insert(string.to_string(), value), - Val::Symbol(symbol) => symbol_map.insert(symbol, value), + Val::Symbol(symbol) => symbol_map.insert(symbol.clone(), value), key => string_map.insert(key.to_string(), value), }; } self.decode_type(); // End (TODO: assert) - VsObject { - string_map, - symbol_map, - prototype: None, - } - .to_val() + Own( + VsObject { + string_map, + symbol_map, + prototype: None, + } + .to_val(), + ) } - BytecodeType::Function => self.decode_function(false), - BytecodeType::Pointer => self.decode_pointer(registers), - BytecodeType::Register => match registers[self.decode_register_index().unwrap()].clone() { - Val::Void => Val::Undefined, - val => val, + BytecodeType::Function => Own(self.decode_function(false)), + BytecodeType::Pointer => Own(self.decode_pointer(registers)), + BytecodeType::Register => match registers[self.decode_register_index().unwrap()] { + Val::Void => Own(Val::Undefined), + ref val => Ref(val), }, - BytecodeType::Builtin => BUILTIN_VALS[self.decode_varsize_uint()](), - BytecodeType::Class => VsClass { - constructor: self.decode_val(registers), - instance_prototype: self.decode_val(registers), - } - .to_val(), - BytecodeType::BigInt => self.decode_bigint().to_val(), - BytecodeType::GeneratorFunction => self.decode_function(true), + BytecodeType::Builtin => Own(BUILTIN_VALS[self.decode_varsize_uint()]()), + BytecodeType::Class => Own( + VsClass { + constructor: self.decode_val(registers), + instance_prototype: self.decode_val(registers), + } + .to_val(), + ), + BytecodeType::BigInt => Own(self.decode_bigint().to_val()), + BytecodeType::GeneratorFunction => Own(self.decode_function(true)), BytecodeType::Unrecognized => panic!("Unrecognized bytecode type at {}", self.pos - 1), }; } + pub fn decode_val(&mut self, registers: &Vec) -> Val { + return self.decode_vallish(registers).get_val(); + } + pub fn decode_vec_val(&mut self, registers: &Vec) -> Vec { let mut vals: Vec = Vec::new(); @@ -298,3 +308,24 @@ impl BytecodeDecoder { return InstructionByte::from_byte(self.decode_byte()); } } + +pub enum Vallish<'a> { + Own(Val), + Ref(&'a Val), +} + +impl<'a> Vallish<'a> { + pub fn get_val(self) -> Val { + match self { + Vallish::Own(val) => val, + Vallish::Ref(val) => val.clone(), + } + } + + pub fn get_ref(&self) -> &Val { + match self { + Vallish::Own(val) => val, + Vallish::Ref(val) => val, + } + } +} diff --git a/valuescript_vm/src/bytecode_stack_frame.rs b/valuescript_vm/src/bytecode_stack_frame.rs index f1104df..c15c1a3 100644 --- a/valuescript_vm/src/bytecode_stack_frame.rs +++ b/valuescript_vm/src/bytecode_stack_frame.rs @@ -32,13 +32,13 @@ pub struct CatchSetting { } impl BytecodeStackFrame { - pub fn apply_unary_op(&mut self, op: fn(input: Val) -> Val) { - let input = self.decoder.decode_val(&self.registers); + pub fn apply_unary_op(&mut self, op: fn(input: &Val) -> Val) { + let input = self.decoder.decode_vallish(&self.registers); let register_index = self.decoder.decode_register_index(); if register_index.is_some() { - self.registers[register_index.unwrap()] = op(input); + self.registers[register_index.unwrap()] = op(input.get_ref()); } } diff --git a/valuescript_vm/src/operations.rs b/valuescript_vm/src/operations.rs index aaeda5f..3e78af4 100644 --- a/valuescript_vm/src/operations.rs +++ b/valuescript_vm/src/operations.rs @@ -43,7 +43,7 @@ pub fn op_plus(left: Val, right: Val) -> Result { return Ok(Val::Number(left_prim.to_number() + right_prim.to_number())); } -pub fn op_unary_plus(input: Val) -> Val { +pub fn op_unary_plus(input: &Val) -> Val { match input.as_bigint_data() { Some(bigint) => Val::BigInt(bigint), _ => Val::Number(input.to_number()), @@ -60,7 +60,7 @@ pub fn op_minus(left: Val, right: Val) -> Result { } } -pub fn op_unary_minus(input: Val) -> Val { +pub fn op_unary_minus(input: &Val) -> Val { match input.as_bigint_data() { Some(bigint) => Val::BigInt(-bigint), _ => Val::Number(-input.to_number()), @@ -170,7 +170,7 @@ pub fn op_or(left: Val, right: Val) -> Result { Ok(if left.is_truthy() { left } else { right }) } -pub fn op_not(input: Val) -> Val { +pub fn op_not(input: &Val) -> Val { return Val::Bool(!input.is_truthy()); } @@ -282,7 +282,7 @@ pub fn op_bit_or(left: Val, right: Val) -> Result { } } -pub fn op_bit_not(input: Val) -> Val { +pub fn op_bit_not(input: &Val) -> Val { match input.as_bigint_data() { Some(bigint) => Val::BigInt(!bigint), None => { @@ -341,7 +341,7 @@ pub fn op_right_shift_unsigned(left: Val, right: Val) -> Result { } } -pub fn op_typeof(input: Val) -> Val { +pub fn op_typeof(input: &Val) -> Val { use VsType::*; match input.typeof_() {