Create a RunState to indicate whether the current interpreter is recoverable
This commit is contained in:
parent
02cb00f14b
commit
fa556a2af1
10
src/lib.rs
10
src/lib.rs
|
@ -221,6 +221,16 @@ pub enum TrapKind {
|
||||||
Host(Box<host::HostError>),
|
Host(Box<host::HostError>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TrapKind {
|
||||||
|
/// Whether this trap is specified by the host.
|
||||||
|
pub fn is_host(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
&TrapKind::Host(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Internal interpreter error.
|
/// Internal interpreter error.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
|
|
|
@ -45,12 +45,24 @@ enum RunResult {
|
||||||
NestedCall(FuncRef),
|
NestedCall(FuncRef),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Function execution state, related to pause and resume.
|
||||||
|
enum RunState {
|
||||||
|
/// The interpreter has been created, but has not been executed.
|
||||||
|
Initialized,
|
||||||
|
/// The interpreter has started execution, and cannot be called again if it exits normally, or no Host traps happened.
|
||||||
|
Started,
|
||||||
|
/// The interpreter has been executed, and returned a Host trap. It can resume execution by providing back a return
|
||||||
|
/// value.
|
||||||
|
Resumable(Option<ValueType>),
|
||||||
|
}
|
||||||
|
|
||||||
/// Function interpreter.
|
/// Function interpreter.
|
||||||
pub struct Interpreter<'a, E: Externals + 'a> {
|
pub struct Interpreter<'a, E: Externals + 'a> {
|
||||||
externals: &'a mut E,
|
externals: &'a mut E,
|
||||||
value_stack: ValueStack,
|
value_stack: ValueStack,
|
||||||
call_stack: Vec<FunctionContext>,
|
call_stack: Vec<FunctionContext>,
|
||||||
return_type: Option<ValueType>,
|
return_type: Option<ValueType>,
|
||||||
|
state: RunState,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, E: Externals> Interpreter<'a, E> {
|
impl<'a, E: Externals> Interpreter<'a, E> {
|
||||||
|
@ -77,10 +89,12 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
||||||
value_stack,
|
value_stack,
|
||||||
call_stack,
|
call_stack,
|
||||||
return_type,
|
return_type,
|
||||||
|
state: RunState::Initialized,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn start_execution(&mut self) -> Result<Option<RuntimeValue>, Trap> {
|
pub fn start_execution(&mut self) -> Result<Option<RuntimeValue>, Trap> {
|
||||||
|
self.state = RunState::Started;
|
||||||
self.run_interpreter_loop()?;
|
self.run_interpreter_loop()?;
|
||||||
|
|
||||||
let opt_return_value = self.return_type.map(|_vt| {
|
let opt_return_value = self.return_type.map(|_vt| {
|
||||||
|
@ -137,7 +151,15 @@ impl<'a, E: Externals> Interpreter<'a, E> {
|
||||||
},
|
},
|
||||||
FuncInstanceInternal::Host { ref signature, .. } => {
|
FuncInstanceInternal::Host { ref signature, .. } => {
|
||||||
let args = prepare_function_args(signature, &mut self.value_stack);
|
let args = prepare_function_args(signature, &mut self.value_stack);
|
||||||
let return_val = FuncInstance::invoke(&nested_func, &args, self.externals)?;
|
let return_val = match FuncInstance::invoke(&nested_func, &args, self.externals) {
|
||||||
|
Ok(val) => val,
|
||||||
|
Err(trap) => {
|
||||||
|
if trap.kind().is_host() {
|
||||||
|
self.state = RunState::Resumable(nested_func.signature().return_type());
|
||||||
|
}
|
||||||
|
return Err(trap);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
// Check if `return_val` matches the signature.
|
// Check if `return_val` matches the signature.
|
||||||
let value_ty = return_val.as_ref().map(|val| val.value_type());
|
let value_ty = return_val.as_ref().map(|val| val.value_type());
|
||||||
|
|
Loading…
Reference in New Issue