Set up frame steps for exceptions

This commit is contained in:
Andrew Morris
2023-03-21 09:51:25 +11:00
parent eaf6280c71
commit 11b547db15
11 changed files with 233 additions and 169 deletions

View File

@@ -1,8 +1,9 @@
use std::rc::Rc;
use super::super::vs_value::{Val, ValTrait, LoadFunctionResult};
use super::super::vs_array::VsArray;
use super::super::stack_frame::{StackFrameTrait, FrameStepResult, CallResult};
use crate::stack_frame::FrameStepResult;
use crate::stack_frame::{CallResult, FrameStepOk, StackFrameTrait};
use crate::vs_array::VsArray;
use crate::vs_value::{LoadFunctionResult, Val, ValTrait};
pub trait ArrayMappingState {
fn process(&mut self, i: usize, element: &Val, mapped: Val) -> Option<Val>;
@@ -42,9 +43,13 @@ impl StackFrameTrait for ArrayMappingFrame {
fn write_param(&mut self, param: Val) {
match self.param_i {
0 => { self.mapper = param; }
1 => { self.this_arg = param; }
_ => {},
0 => {
self.mapper = param;
}
1 => {
self.this_arg = param;
}
_ => {}
};
self.param_i += 1;
@@ -57,10 +62,10 @@ impl StackFrameTrait for ArrayMappingFrame {
};
for early_exit in &self.early_exit {
return FrameStepResult::Pop(CallResult {
return Ok(FrameStepOk::Pop(CallResult {
return_: early_exit.clone(),
this: Val::Array(array_data.clone()),
})
}));
}
let array_i = self.array_i;
@@ -69,12 +74,12 @@ impl StackFrameTrait for ArrayMappingFrame {
match array_data.elements.get(array_i) {
Some(el) => match el {
Val::Void => {
return FrameStepResult::Continue;
},
return Ok(FrameStepOk::Continue);
}
_ => match self.mapper.load_function() {
LoadFunctionResult::NotAFunction =>
LoadFunctionResult::NotAFunction => {
std::panic!("Not implemented: exception: map fn is not a function")
,
}
LoadFunctionResult::NativeFunction(native_fn) => {
return match self.state.process(
array_i,
@@ -88,28 +93,28 @@ impl StackFrameTrait for ArrayMappingFrame {
],
),
) {
None => FrameStepResult::Continue,
Some(val) => FrameStepResult::Pop(CallResult {
None => Ok(FrameStepOk::Continue),
Some(val) => Ok(FrameStepOk::Pop(CallResult {
return_: val,
this: Val::Array(array_data.clone()),
}),
})),
};
},
}
LoadFunctionResult::StackFrame(mut new_frame) => {
new_frame.write_this(self.this_arg.clone());
new_frame.write_param(el.clone());
new_frame.write_param(Val::Number(array_i as f64));
new_frame.write_param(Val::Array(array_data.clone()));
return FrameStepResult::Push(new_frame);
},
return Ok(FrameStepOk::Push(new_frame));
}
},
},
None => {
return FrameStepResult::Pop(CallResult {
return Ok(FrameStepOk::Pop(CallResult {
return_: self.state.finish(),
this: Val::Array(array_data.clone()),
});
},
}));
}
};
}

View File

@@ -1,18 +1,20 @@
use std::rc::Rc;
use super::super::vs_value::{Val, ValTrait, LoadFunctionResult};
use super::super::vs_array::VsArray;
use super::super::native_frame_function::NativeFrameFunction;
use super::super::stack_frame::{StackFrameTrait, FrameStepResult, CallResult};
use crate::native_frame_function::NativeFrameFunction;
use crate::stack_frame::{CallResult, FrameStepOk, FrameStepResult, StackFrameTrait};
use crate::vs_array::VsArray;
use crate::vs_value::{LoadFunctionResult, Val, ValTrait};
pub static REDUCE: NativeFrameFunction = NativeFrameFunction {
make_frame: || Box::new(ReduceFrame {
this: None,
array_i: 0,
reducer: Val::Void,
param_i: 0,
value: None,
}),
make_frame: || {
Box::new(ReduceFrame {
this: None,
array_i: 0,
reducer: Val::Void,
param_i: 0,
value: None,
})
},
};
struct ReduceFrame {
@@ -31,9 +33,13 @@ impl StackFrameTrait for ReduceFrame {
fn write_param(&mut self, param: Val) {
match self.param_i {
0 => { self.reducer = param; }
1 => { self.value = Some(param); }
_ => {},
0 => {
self.reducer = param;
}
1 => {
self.value = Some(param);
}
_ => {}
};
self.param_i += 1;
@@ -51,17 +57,17 @@ impl StackFrameTrait for ReduceFrame {
match array_data.elements.get(array_i) {
Some(el) => match el {
Val::Void => {
return FrameStepResult::Continue;
},
return Ok(FrameStepOk::Continue);
}
_ => match &self.value {
None => {
self.value = Some(el.clone());
return FrameStepResult::Continue;
},
return Ok(FrameStepOk::Continue);
}
Some(value) => match self.reducer.load_function() {
LoadFunctionResult::NotAFunction =>
LoadFunctionResult::NotAFunction => {
std::panic!("Not implemented: exception: reduce fn is not a function")
,
}
LoadFunctionResult::NativeFunction(native_fn) => {
self.value = Some(native_fn(
&mut Val::Undefined,
@@ -72,29 +78,29 @@ impl StackFrameTrait for ReduceFrame {
Val::Array(array_data.clone()),
],
));
return FrameStepResult::Continue;
},
return Ok(FrameStepOk::Continue);
}
LoadFunctionResult::StackFrame(mut new_frame) => {
new_frame.write_param(value.clone());
new_frame.write_param(el.clone());
new_frame.write_param(Val::Number(array_i as f64));
new_frame.write_param(Val::Array(array_data.clone()));
return FrameStepResult::Push(new_frame);
},
return Ok(FrameStepOk::Push(new_frame));
}
},
},
},
None => match &self.value {
None => {
std::panic!("Not implemented: exception: reduce of empty array with no initial value");
},
}
Some(value) => {
return FrameStepResult::Pop(CallResult {
return Ok(FrameStepOk::Pop(CallResult {
return_: value.clone(),
this: Val::Array(array_data.clone()),
});
},
}));
}
},
};
}

View File

@@ -1,18 +1,20 @@
use std::rc::Rc;
use super::super::vs_value::{Val, ValTrait, LoadFunctionResult};
use super::super::vs_array::VsArray;
use super::super::native_frame_function::NativeFrameFunction;
use super::super::stack_frame::{StackFrameTrait, FrameStepResult, CallResult};
use crate::native_frame_function::NativeFrameFunction;
use crate::stack_frame::{CallResult, FrameStepOk, FrameStepResult, StackFrameTrait};
use crate::vs_array::VsArray;
use crate::vs_value::{LoadFunctionResult, Val, ValTrait};
pub static REDUCE_RIGHT: NativeFrameFunction = NativeFrameFunction {
make_frame: || Box::new(ReduceRightFrame {
this: None,
array_i: 0,
reducer: Val::Void,
param_i: 0,
value: None,
}),
make_frame: || {
Box::new(ReduceRightFrame {
this: None,
array_i: 0,
reducer: Val::Void,
param_i: 0,
value: None,
})
},
};
struct ReduceRightFrame {
@@ -29,18 +31,20 @@ impl StackFrameTrait for ReduceRightFrame {
self.this = this.as_array_data();
match &self.this {
None => {},
Some(ad) => {
self.array_i = ad.elements.len()
},
None => {}
Some(ad) => self.array_i = ad.elements.len(),
};
}
fn write_param(&mut self, param: Val) {
match self.param_i {
0 => { self.reducer = param; }
1 => { self.value = Some(param); }
_ => {},
0 => {
self.reducer = param;
}
1 => {
self.value = Some(param);
}
_ => {}
};
self.param_i += 1;
@@ -55,14 +59,16 @@ impl StackFrameTrait for ReduceRightFrame {
if self.array_i == 0 {
match &self.value {
None => {
std::panic!("Not implemented: exception: reduceRight of empty array with no initial value");
},
std::panic!(
"Not implemented: exception: reduceRight of empty array with no initial value"
);
}
Some(value) => {
return FrameStepResult::Pop(CallResult {
return Ok(FrameStepOk::Pop(CallResult {
return_: value.clone(),
this: Val::Array(array_data.clone()),
});
},
}));
}
}
}
@@ -73,17 +79,17 @@ impl StackFrameTrait for ReduceRightFrame {
match el {
Val::Void => {
return FrameStepResult::Continue;
},
return Ok(FrameStepOk::Continue);
}
_ => match &self.value {
None => {
self.value = Some(el.clone());
return FrameStepResult::Continue;
},
return Ok(FrameStepOk::Continue);
}
Some(value) => match self.reducer.load_function() {
LoadFunctionResult::NotAFunction =>
LoadFunctionResult::NotAFunction => {
std::panic!("Not implemented: exception: reduceRight fn is not a function")
,
}
LoadFunctionResult::NativeFunction(native_fn) => {
self.value = Some(native_fn(
&mut Val::Undefined,
@@ -94,16 +100,16 @@ impl StackFrameTrait for ReduceRightFrame {
Val::Array(array_data.clone()),
],
));
return FrameStepResult::Continue;
},
return Ok(FrameStepOk::Continue);
}
LoadFunctionResult::StackFrame(mut new_frame) => {
new_frame.write_param(value.clone());
new_frame.write_param(el.clone());
new_frame.write_param(Val::Number(array_i as f64));
new_frame.write_param(Val::Array(array_data.clone()));
return FrameStepResult::Push(new_frame);
},
return Ok(FrameStepOk::Push(new_frame));
}
},
},
};

View File

@@ -1,18 +1,23 @@
use std::rc::Rc;
use super::super::vs_value::{Val, ValTrait, LoadFunctionResult};
use super::super::vs_array::VsArray;
use super::super::native_frame_function::NativeFrameFunction;
use super::super::stack_frame::{StackFrameTrait, FrameStepResult, CallResult};
use crate::native_frame_function::NativeFrameFunction;
use crate::stack_frame::FrameStepResult;
use crate::stack_frame::{CallResult, FrameStepOk, StackFrameTrait};
use crate::vs_array::VsArray;
use crate::vs_value::{LoadFunctionResult, Val, ValTrait};
pub static SORT: NativeFrameFunction = NativeFrameFunction {
make_frame: || Box::new(SortFrame {
this: None,
comparator: Val::Void,
param_i: 0,
tree: SortTreeNode { data: SortTreeNodeData::Sorted(vec![]) },
started: false,
}),
make_frame: || {
Box::new(SortFrame {
this: None,
comparator: Val::Void,
param_i: 0,
tree: SortTreeNode {
data: SortTreeNodeData::Sorted(vec![]),
},
started: false,
})
},
};
struct SortFrame {
@@ -46,14 +51,16 @@ impl SortTreeNode {
if len <= 1 {
let mut sorted = vec![];
for i in vals.start..vals.end {
sorted.push(vals.vec[i].clone());
}
return SortTreeNode { data: SortTreeNodeData::Sorted(sorted) };
return SortTreeNode {
data: SortTreeNodeData::Sorted(sorted),
};
}
if len == 2 {
return SortTreeNode {
data: SortTreeNodeData::Sorting(
@@ -69,9 +76,9 @@ impl SortTreeNode {
),
};
}
let mid = vals.start + (vals.end - vals.start) / 2;
return SortTreeNode {
data: SortTreeNodeData::Branch(
Box::new(SortTreeNode::new(VecSlice {
@@ -91,9 +98,10 @@ impl SortTreeNode {
fn get_compare_elements(&self) -> Option<(Val, Val)> {
match &self.data {
SortTreeNodeData::Branch(left, right) => {
return left.get_compare_elements()
return left
.get_compare_elements()
.or_else(|| right.get_compare_elements());
},
}
SortTreeNodeData::Sorting(_vals, left, right) => {
let lval_opt = left.vec.get(left.pos);
let rval_opt = right.vec.get(right.pos);
@@ -101,15 +109,15 @@ impl SortTreeNode {
match (lval_opt, rval_opt) {
(Some(lval), Some(rval)) => {
return Some((lval.clone(), rval.clone()));
},
}
_ => {
std::panic!("Failed to get compare elements from sorting state");
},
}
}
},
}
SortTreeNodeData::Sorted(_) => {
return None;
},
}
};
}
@@ -119,10 +127,10 @@ impl SortTreeNode {
match &mut left.data {
SortTreeNodeData::Branch(_, _) | SortTreeNodeData::Sorting(_, _, _) => {
left.apply_outcome(should_swap);
},
}
SortTreeNodeData::Sorted(left_vals) => {
right.apply_outcome(should_swap);
match &mut right.data {
SortTreeNodeData::Sorted(right_vals) => {
let mut owned_left_vals = vec![];
@@ -132,19 +140,25 @@ impl SortTreeNode {
self.data = SortTreeNodeData::Sorting(
vec![],
VecPos { vec: owned_left_vals, pos: 0 },
VecPos { vec: owned_right_vals, pos: 0 },
VecPos {
vec: owned_left_vals,
pos: 0,
},
VecPos {
vec: owned_right_vals,
pos: 0,
},
);
},
_ => {},
}
_ => {}
};
}
};
},
}
SortTreeNodeData::Sorted(_) => {
std::panic!("Failed to apply outcome");
},
}
SortTreeNodeData::Sorting(vals, left, right) => {
let lval_opt = left.vec.get(left.pos);
@@ -155,11 +169,11 @@ impl SortTreeNode {
false => {
vals.push(lval.clone());
left.pos += 1;
},
}
true => {
vals.push(rval.clone());
right.pos += 1;
},
}
},
_ => std::panic!("Failed to apply outcome"),
};
@@ -178,7 +192,7 @@ impl SortTreeNode {
self.data = SortTreeNodeData::Sorted(owned_vals);
}
},
}
};
}
}
@@ -196,8 +210,10 @@ impl StackFrameTrait for SortFrame {
fn write_param(&mut self, param: Val) {
match self.param_i {
0 => { self.comparator = param; },
_ => {},
0 => {
self.comparator = param;
}
_ => {}
};
self.param_i += 1;
@@ -214,15 +230,15 @@ impl StackFrameTrait for SortFrame {
Val::Void => {
let array_data_mut = Rc::make_mut(array_data);
array_data_mut.elements.sort_by(|a, b|
a.val_to_string().cmp(&b.val_to_string())
);
array_data_mut
.elements
.sort_by(|a, b| a.val_to_string().cmp(&b.val_to_string()));
return FrameStepResult::Pop(CallResult {
return Ok(FrameStepOk::Pop(CallResult {
return_: Val::Array(array_data.clone()),
this: Val::Array(array_data.clone()),
});
},
}));
}
_ => {
self.tree = SortTreeNode::new(VecSlice {
vec: &array_data.elements,
@@ -231,7 +247,7 @@ impl StackFrameTrait for SortFrame {
});
self.started = true;
},
}
};
}
@@ -242,17 +258,17 @@ impl StackFrameTrait for SortFrame {
std::mem::swap(&mut owned_vals, vals);
let res = Val::Array(Rc::new(VsArray::from(owned_vals)));
return FrameStepResult::Pop(CallResult {
return Ok(FrameStepOk::Pop(CallResult {
return_: res.clone(),
this: res,
});
},
}));
}
_ => std::panic!("This shouldn't happen"),
},
Some((left, right)) => match self.comparator.load_function() {
LoadFunctionResult::NotAFunction => {
std::panic!("Not implemented: exception: comparator is not a function");
},
}
LoadFunctionResult::NativeFunction(native_fn) => {
let res = native_fn(&mut Val::Undefined, vec![left, right]).to_number();
@@ -262,13 +278,13 @@ impl StackFrameTrait for SortFrame {
};
self.tree.apply_outcome(should_swap);
return FrameStepResult::Continue;
},
return Ok(FrameStepOk::Continue);
}
LoadFunctionResult::StackFrame(mut new_frame) => {
new_frame.write_param(left);
new_frame.write_param(right);
return FrameStepResult::Push(new_frame);
},
return Ok(FrameStepOk::Push(new_frame));
}
},
};
}

View File

@@ -1,12 +1,14 @@
use std::rc::Rc;
use super::bytecode_decoder::BytecodeDecoder;
use super::bytecode_decoder::BytecodeType;
use super::instruction::Instruction;
use super::operations;
use super::stack_frame::{CallResult, FrameStepResult, StackFrame, StackFrameTrait};
use super::vs_object::VsObject;
use super::vs_value::{LoadFunctionResult, Val, ValTrait};
use crate::bytecode_decoder::BytecodeDecoder;
use crate::bytecode_decoder::BytecodeType;
use crate::instruction::Instruction;
use crate::operations;
use crate::stack_frame::FrameStepOk;
use crate::stack_frame::FrameStepResult;
use crate::stack_frame::{CallResult, StackFrame, StackFrameTrait};
use crate::vs_object::VsObject;
use crate::vs_value::{LoadFunctionResult, Val, ValTrait};
pub struct BytecodeStackFrame {
pub decoder: BytecodeDecoder,
@@ -90,10 +92,10 @@ impl StackFrameTrait for BytecodeStackFrame {
match self.decoder.decode_instruction() {
End => {
return FrameStepResult::Pop(CallResult {
return Ok(FrameStepOk::Pop(CallResult {
return_: self.registers[0].clone(),
this: self.registers[1].clone(),
});
}));
}
Mov => {
@@ -168,7 +170,7 @@ impl StackFrameTrait for BytecodeStackFrame {
self.return_target = self.decoder.decode_register_index();
self.this_target = None;
return FrameStepResult::Push(new_frame);
return Ok(FrameStepOk::Push(new_frame));
}
LoadFunctionResult::NativeFunction(native_fn) => {
let res = native_fn(&mut Val::Undefined, self.decode_parameters());
@@ -208,7 +210,7 @@ impl StackFrameTrait for BytecodeStackFrame {
self.return_target = self.decoder.decode_register_index();
return FrameStepResult::Push(new_frame);
return Ok(FrameStepOk::Push(new_frame));
}
LoadFunctionResult::NativeFunction(_native_fn) => {
std::panic!("Not implemented");
@@ -294,7 +296,7 @@ impl StackFrameTrait for BytecodeStackFrame {
ThisArg::Val(_) => None,
};
return FrameStepResult::Push(new_frame);
return Ok(FrameStepOk::Push(new_frame));
}
LoadFunctionResult::NativeFunction(native_fn) => {
let params = self.decode_parameters();
@@ -369,7 +371,7 @@ impl StackFrameTrait for BytecodeStackFrame {
self.return_target = None;
self.this_target = self.decoder.decode_register_index();
return FrameStepResult::Push(new_frame);
return Ok(FrameStepOk::Push(new_frame));
}
LoadFunctionResult::NativeFunction(native_fn) => {
native_fn(&mut instance, self.decode_parameters());
@@ -386,7 +388,7 @@ impl StackFrameTrait for BytecodeStackFrame {
}
};
return FrameStepResult::Continue;
return Ok(FrameStepOk::Continue);
}
fn apply_call_result(&mut self, call_result: CallResult) {

View File

@@ -8,12 +8,14 @@ pub struct CallResult {
pub this: Val,
}
pub enum FrameStepResult {
pub enum FrameStepOk {
Continue,
Pop(CallResult),
Push(StackFrame),
}
pub type FrameStepResult = Result<FrameStepOk, Val>;
pub trait StackFrameTrait {
fn write_this(&mut self, this: Val);
fn write_param(&mut self, param: Val);

View File

@@ -1,9 +1,10 @@
use std::rc::Rc;
use super::bytecode_decoder::BytecodeDecoder;
use super::first_stack_frame::FirstStackFrame;
use super::stack_frame::{FrameStepResult, StackFrame};
use super::vs_value::{LoadFunctionResult, Val, ValTrait};
use crate::bytecode_decoder::BytecodeDecoder;
use crate::first_stack_frame::FirstStackFrame;
use crate::stack_frame::FrameStepOk;
use crate::stack_frame::StackFrame;
use crate::vs_value::{LoadFunctionResult, Val, ValTrait};
pub struct VirtualMachine {
pub frame: StackFrame,
@@ -11,7 +12,7 @@ pub struct VirtualMachine {
}
impl VirtualMachine {
pub fn run(&mut self, bytecode: &Rc<Vec<u8>>, params: &[String]) -> Val {
pub fn run(&mut self, bytecode: &Rc<Vec<u8>>, params: &[String]) -> Result<Val, Val> {
let mut bd = BytecodeDecoder {
data: bytecode.clone(),
pos: 0,
@@ -31,10 +32,10 @@ impl VirtualMachine {
self.push(frame);
while self.stack.len() > 0 {
self.step();
self.step()?;
}
return self.frame.get_call_result().return_;
return Ok(self.frame.get_call_result().return_);
}
pub fn new() -> VirtualMachine {
@@ -48,17 +49,19 @@ impl VirtualMachine {
};
}
pub fn step(&mut self) {
match self.frame.step() {
FrameStepResult::Continue => {}
FrameStepResult::Pop(call_result) => {
pub fn step(&mut self) -> Result<(), Val> {
match self.frame.step()? {
FrameStepOk::Continue => {}
FrameStepOk::Pop(call_result) => {
self.pop();
self.frame.apply_call_result(call_result);
}
FrameStepResult::Push(new_frame) => {
FrameStepOk::Push(new_frame) => {
self.push(new_frame);
}
};
}
Ok(())
}
pub fn push(&mut self, mut frame: StackFrame) {