Add Vm::exit_module
This does all of the routines necessary for exiting a module's execution. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -47,8 +47,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// run
|
// run
|
||||||
|
let module = upcast_obj(module);
|
||||||
let mut vm = vm::Vm::new(&constants);
|
let mut vm = vm::Vm::new(&constants);
|
||||||
vm.enter_module(upcast_obj(module));
|
// VM needs the module to be on top of the stack when it executes
|
||||||
|
vm.push(module.clone());
|
||||||
|
vm.enter_module(module);
|
||||||
vm.run();
|
vm.run();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -81,43 +81,3 @@ impl Object for Module {
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Module method implementations
|
// Module method implementations
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
/*
|
|
||||||
impl Module {
|
|
||||||
pub(crate) fn execute(vm: &mut Vm, state: FunctionState) -> FunctionResult {
|
|
||||||
match state {
|
|
||||||
FunctionState::Begin => {
|
|
||||||
let this = vm.frame_stack()[0].clone();
|
|
||||||
let value = with_obj_downcast(this.clone(), |module: &Module| {
|
|
||||||
module.evaluated_value.clone()
|
|
||||||
});
|
|
||||||
|
|
||||||
// don't evaluate this twice
|
|
||||||
if let Some(value) = value {
|
|
||||||
return FunctionResult::ReturnPush(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
vm.enter_module(this.clone());
|
|
||||||
FunctionResult::Yield(0)
|
|
||||||
}
|
|
||||||
FunctionState::Resume(0) => {
|
|
||||||
let this = vm.frame_stack()[0].clone();
|
|
||||||
let obj = with_obj_downcast(this.clone(), |module: &Module| {
|
|
||||||
assert_eq!(module.globals().len(), vm.globals().len());
|
|
||||||
let obj = Obj::create();
|
|
||||||
module
|
|
||||||
.globals()
|
|
||||||
.iter()
|
|
||||||
.zip(vm.globals())
|
|
||||||
.for_each(|(name, value)| {
|
|
||||||
obj.borrow_mut().set_attr(name, value.clone());
|
|
||||||
});
|
|
||||||
obj
|
|
||||||
});
|
|
||||||
FunctionResult::ReturnPush(obj)
|
|
||||||
}
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|||||||
66
src/vm.rs
66
src/vm.rs
@@ -198,7 +198,17 @@ impl<'c> Vm<'c> {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pub fn enter_module(&mut self, module_ptr: ObjP) {
|
/// Performs module entrance routines.
|
||||||
|
///
|
||||||
|
/// This **will not** check if the module has already been evaluated - this is up to the caller
|
||||||
|
/// to do so.
|
||||||
|
///
|
||||||
|
/// This function will set the VM up for execution of a new module by:
|
||||||
|
///
|
||||||
|
/// 1. Create a new globals stack for the new module to use, and populate it with all of the
|
||||||
|
/// globals that are used in the module.
|
||||||
|
/// 2. Create and push a new module stack frame.
|
||||||
|
pub(crate) fn enter_module(&mut self, module_ptr: ObjP) {
|
||||||
with_obj_downcast(module_ptr.clone(), |module: &Module| {
|
with_obj_downcast(module_ptr.clone(), |module: &Module| {
|
||||||
let mut globals: Vec<_> = module.globals().iter().map(|_| Nil::create()).collect();
|
let mut globals: Vec<_> = module.globals().iter().map(|_| Nil::create()).collect();
|
||||||
|
|
||||||
@@ -227,6 +237,36 @@ impl<'c> Vm<'c> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Performs module exit routines.
|
||||||
|
///
|
||||||
|
/// This expects that the module object that was executed is still on top of the stack. This
|
||||||
|
/// will be popped, and the object represented by this module will be pushed to the stack.
|
||||||
|
fn exit_module(&mut self) {
|
||||||
|
let globals = self.globals.pop().expect("no globals");
|
||||||
|
let old_frame = self.pop_frame();
|
||||||
|
self.stack
|
||||||
|
.resize_with(old_frame.stack_base, || unreachable!());
|
||||||
|
|
||||||
|
let module = self.pop();
|
||||||
|
|
||||||
|
// create the object and assign it as the module's evaluated value
|
||||||
|
let obj = with_obj_downcast_mut(module, |module: &mut Module| {
|
||||||
|
assert_eq!(module.globals().len(), globals.len());
|
||||||
|
let obj = Obj::create();
|
||||||
|
module
|
||||||
|
.globals()
|
||||||
|
.iter()
|
||||||
|
.zip(globals)
|
||||||
|
.for_each(|(name, value)| {
|
||||||
|
obj.borrow_mut().set_attr(name, value.clone());
|
||||||
|
});
|
||||||
|
module.set_evaluated_value(Some(obj.clone()));
|
||||||
|
obj
|
||||||
|
});
|
||||||
|
|
||||||
|
self.push(obj);
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the current instruction and advance the IP.
|
/// Get the current instruction and advance the IP.
|
||||||
///
|
///
|
||||||
/// This may actually end up calling a function on top of the stack, if it's a builtin function.
|
/// This may actually end up calling a function on top of the stack, if it's a builtin function.
|
||||||
@@ -447,34 +487,12 @@ impl<'c> Vm<'c> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Op::ExitModule => {
|
Op::ExitModule => {
|
||||||
let globals = self.globals.pop().unwrap();
|
self.exit_module();
|
||||||
|
|
||||||
let old_frame = self.pop_frame();
|
|
||||||
self.stack
|
|
||||||
.resize_with(old_frame.stack_base, || unreachable!());
|
|
||||||
|
|
||||||
// halt execution if there aren't any globals left
|
// halt execution if there aren't any globals left
|
||||||
if self.globals.is_empty() {
|
if self.globals.is_empty() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let module = self.pop();
|
|
||||||
// create the object and assign it as the module's evaluated value
|
|
||||||
let obj = with_obj_downcast_mut(module, |module: &mut Module| {
|
|
||||||
assert_eq!(module.globals().len(), globals.len());
|
|
||||||
let obj = Obj::create();
|
|
||||||
module
|
|
||||||
.globals()
|
|
||||||
.iter()
|
|
||||||
.zip(globals)
|
|
||||||
.for_each(|(name, value)| {
|
|
||||||
obj.borrow_mut().set_attr(name, value.clone());
|
|
||||||
});
|
|
||||||
module.set_evaluated_value(Some(obj.clone()));
|
|
||||||
obj
|
|
||||||
});
|
|
||||||
|
|
||||||
self.push(obj);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user