Implement stack unwinding

This commit is contained in:
Andrew Morris
2023-03-23 09:57:40 +11:00
parent 337c5c5296
commit 0daaf0f650
8 changed files with 49 additions and 1 deletions

View File

@@ -137,4 +137,8 @@ impl StackFrameTrait for ArrayMappingFrame {
fn get_call_result(&mut self) -> CallResult {
panic!("Not appropriate for MapFrame")
}
fn catch_exception(&mut self, _exception: Val) -> bool {
return false;
}
}

View File

@@ -105,4 +105,8 @@ impl StackFrameTrait for ReduceFrame {
fn get_call_result(&mut self) -> CallResult {
panic!("Not appropriate for ReduceFrame")
}
fn catch_exception(&mut self, _exception: Val) -> bool {
return false;
}
}

View File

@@ -119,4 +119,8 @@ impl StackFrameTrait for ReduceRightFrame {
fn get_call_result(&mut self) -> CallResult {
panic!("Not appropriate for ReduceRightFrame")
}
fn catch_exception(&mut self, _exception: Val) -> bool {
return false;
}
}

View File

@@ -304,4 +304,8 @@ impl StackFrameTrait for SortFrame {
fn get_call_result(&mut self) -> CallResult {
panic!("Not appropriate for SortFrame")
}
fn catch_exception(&mut self, _exception: Val) -> bool {
return false;
}
}

View File

@@ -445,6 +445,10 @@ impl StackFrameTrait for BytecodeStackFrame {
fn get_call_result(&mut self) -> CallResult {
panic!("Not appropriate for BytecodeStackFrame")
}
fn catch_exception(&mut self, _exception: Val) -> bool {
return false; // TODO
}
}
enum ThisArg {

View File

@@ -36,4 +36,8 @@ impl StackFrameTrait for FirstStackFrame {
fn get_call_result(&mut self) -> CallResult {
return self.call_result.clone();
}
fn catch_exception(&mut self, _exception: Val) -> bool {
panic!("Not appropriate for FirstStackFrame");
}
}

View File

@@ -22,4 +22,5 @@ pub trait StackFrameTrait {
fn step(&mut self) -> FrameStepResult;
fn apply_call_result(&mut self, call_result: CallResult);
fn get_call_result(&mut self) -> CallResult;
fn catch_exception(&mut self, exception: Val) -> bool;
}

View File

@@ -50,7 +50,12 @@ impl VirtualMachine {
}
pub fn step(&mut self) -> Result<(), Val> {
match self.frame.step()? {
let step_ok = match self.frame.step() {
Ok(step_ok) => step_ok,
Err(e) => return self.handle_exception(e),
};
match step_ok {
FrameStepOk::Continue => {}
FrameStepOk::Pop(call_result) => {
self.pop();
@@ -74,4 +79,22 @@ impl VirtualMachine {
let mut old_frame = self.stack.pop().unwrap();
std::mem::swap(&mut self.frame, &mut old_frame);
}
pub fn handle_exception(&mut self, exception: Val) -> Result<(), Val> {
while !self.stack.is_empty() {
let handled = self.frame.catch_exception(exception.clone());
if handled {
return Ok(());
}
if self.stack.is_empty() {
return Err(exception);
}
self.pop();
}
Err(exception)
}
}