From c12a27a1ffee601c4ff44b7dd5657733de1784d6 Mon Sep 17 00:00:00 2001 From: Andrew Morris Date: Tue, 30 May 2023 12:28:08 +1000 Subject: [PATCH] Implement cat as stack frame --- .../src/array_higher_functions/array_sort.rs | 2 +- valuescript_vm/src/bytecode_decoder.rs | 24 +++---- valuescript_vm/src/bytecode_stack_frame.rs | 34 ++++------ valuescript_vm/src/cat_stack_frame.rs | 65 +++++++++++++++++++ valuescript_vm/src/lib.rs | 1 + valuescript_vm/src/vs_value.rs | 6 ++ 6 files changed, 98 insertions(+), 34 deletions(-) create mode 100644 valuescript_vm/src/cat_stack_frame.rs diff --git a/valuescript_vm/src/array_higher_functions/array_sort.rs b/valuescript_vm/src/array_higher_functions/array_sort.rs index afbef0b..c17f39b 100644 --- a/valuescript_vm/src/array_higher_functions/array_sort.rs +++ b/valuescript_vm/src/array_higher_functions/array_sort.rs @@ -316,6 +316,6 @@ impl StackFrameTrait for SortFrame { } fn catch_exception(&mut self, _exception: Val) -> bool { - return false; + false } } diff --git a/valuescript_vm/src/bytecode_decoder.rs b/valuescript_vm/src/bytecode_decoder.rs index 208b435..40253bc 100644 --- a/valuescript_vm/src/bytecode_decoder.rs +++ b/valuescript_vm/src/bytecode_decoder.rs @@ -102,17 +102,7 @@ impl BytecodeDecoder { 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 => { - let mut vals: Vec = Vec::new(); - - while self.peek_type() != BytecodeType::End { - vals.push(self.decode_val(registers)); - } - - self.decode_type(); // End (TODO: assert) - - vals.to_val() - } + BytecodeType::Array => self.decode_vec_val(registers).to_val(), BytecodeType::Object => { let mut string_map: BTreeMap = BTreeMap::new(); let mut symbol_map: BTreeMap = BTreeMap::new(); @@ -154,6 +144,18 @@ impl BytecodeDecoder { }; } + pub fn decode_vec_val(&mut self, registers: &Vec) -> Vec { + let mut vals: Vec = Vec::new(); + + while self.peek_type() != BytecodeType::End { + vals.push(self.decode_val(registers)); + } + + self.decode_type(); // End (TODO: assert) + + vals + } + pub fn decode_signed_byte(&mut self) -> i8 { let res = self.bytecode[self.pos] as i8; self.pos += 1; diff --git a/valuescript_vm/src/bytecode_stack_frame.rs b/valuescript_vm/src/bytecode_stack_frame.rs index 26372d6..abddfac 100644 --- a/valuescript_vm/src/bytecode_stack_frame.rs +++ b/valuescript_vm/src/bytecode_stack_frame.rs @@ -3,6 +3,7 @@ use valuescript_common::InstructionByte; use crate::builtins::type_error_builtin::ToTypeError; use crate::bytecode_decoder::BytecodeDecoder; use crate::bytecode_decoder::BytecodeType; +use crate::cat_stack_frame::CatStackFrame; use crate::native_function::ThisWrapper; use crate::operations; use crate::stack_frame::FrameStepOk; @@ -521,31 +522,20 @@ impl StackFrameTrait for BytecodeStackFrame { } Cat => { - let mut vals = Vec::::new(); + assert!( + self.decoder.decode_type() == BytecodeType::Array, + "TODO: cat non-inline arrays" + ); - let bytecode_type = self.decoder.decode_type(); + let cat_frame = CatStackFrame { + args: self.decoder.decode_vec_val(&self.registers), + i: 0, + res: vec![], + }; - if bytecode_type != BytecodeType::Array { - panic!("Not implemented: cat instruction not using inline array"); - } + self.return_target = self.decoder.decode_register_index(); - while self.decoder.peek_type() != BytecodeType::End { - let iterable = self.decoder.decode_val(&self.registers); - - match iterable { - Val::Array(array_data) => { - for item in &array_data.elements { - vals.push(item.clone()); - } - } - _ => todo!("Cat: Non-array iterable"), - } - } - - // TODO: Just skip the byte in release builds? - assert!(self.decoder.decode_type() == BytecodeType::End); - - self.registers[self.decoder.decode_register_index().unwrap()] = vals.to_val(); + return Ok(FrameStepOk::Push(Box::new(cat_frame))); } }; diff --git a/valuescript_vm/src/cat_stack_frame.rs b/valuescript_vm/src/cat_stack_frame.rs new file mode 100644 index 0000000..58e58f7 --- /dev/null +++ b/valuescript_vm/src/cat_stack_frame.rs @@ -0,0 +1,65 @@ +use std::{mem::take, rc::Rc}; + +use crate::{ + builtins::error_builtin::ToError, + stack_frame::{CallResult, FrameStepOk, FrameStepResult, StackFrameTrait}, + vs_value::{ToVal, Val}, +}; + +#[derive(Debug)] +pub struct CatStackFrame { + pub args: Vec, + pub i: usize, + pub res: Vec, +} + +impl StackFrameTrait for CatStackFrame { + fn write_this(&mut self, _const: bool, _this: Val) -> Result<(), Val> { + Ok(()) + } + + fn write_param(&mut self, param: Val) { + self.args.push(param); + } + + fn step(&mut self) -> FrameStepResult { + let arg = match self.args.get_mut(self.i) { + None => { + return Ok(FrameStepOk::Pop(CallResult { + return_: take(&mut self.res).to_val(), + this: Val::Undefined, + })); + } + Some(arg) => take(arg), + }; + + self.i += 1; + + if let Val::Array(mut arg) = arg { + match Rc::get_mut(&mut arg) { + Some(arg) => self.res.append(&mut arg.elements), + None => { + for item in &arg.elements { + self.res.push(item.clone()); + } + } + } + + return Ok(FrameStepOk::Continue); + } + + Err("TODO: Cat: Non-array iterables".to_error()) + } + + fn apply_call_result(&mut self, _call_result: CallResult) { + panic!("Not expected (yet)"); + } + + fn get_call_result(&mut self) -> CallResult { + panic!("Not appropriate for CatStackFrame"); + } + + fn catch_exception(&mut self, _exception: Val) -> bool { + false + } +} diff --git a/valuescript_vm/src/lib.rs b/valuescript_vm/src/lib.rs index 8e980a5..5c6b351 100644 --- a/valuescript_vm/src/lib.rs +++ b/valuescript_vm/src/lib.rs @@ -4,6 +4,7 @@ mod builtins; mod bytecode; mod bytecode_decoder; mod bytecode_stack_frame; +mod cat_stack_frame; mod first_stack_frame; mod helpers; mod iteration; diff --git a/valuescript_vm/src/vs_value.rs b/valuescript_vm/src/vs_value.rs index 869f6b5..60f694c 100644 --- a/valuescript_vm/src/vs_value.rs +++ b/valuescript_vm/src/vs_value.rs @@ -34,6 +34,12 @@ pub enum Val { Dynamic(Rc), } +impl Default for Val { + fn default() -> Self { + Val::Void + } +} + #[derive(PartialEq, Debug)] pub enum VsType { Undefined,