From c5f95f4d87552a7d2a99d3076414b4f81df601af Mon Sep 17 00:00:00 2001 From: Alek Ratzloff Date: Fri, 4 Oct 2024 10:50:40 -0700 Subject: [PATCH] Add Vm::exit_module This does all of the routines necessary for exiting a module's execution. Signed-off-by: Alek Ratzloff --- src/main.rs | 5 +++- src/obj/module.rs | 40 ---------------------------- src/vm.rs | 66 ++++++++++++++++++++++++++++++----------------- 3 files changed, 46 insertions(+), 65 deletions(-) diff --git a/src/main.rs b/src/main.rs index 9ae7898..50ea670 100644 --- a/src/main.rs +++ b/src/main.rs @@ -47,8 +47,11 @@ fn main() -> Result<(), Box> { } // run + let module = upcast_obj(module); 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(); Ok(()) diff --git a/src/obj/module.rs b/src/obj/module.rs index 65f8acc..54a5f2f 100644 --- a/src/obj/module.rs +++ b/src/obj/module.rs @@ -81,43 +81,3 @@ impl Object for Module { //////////////////////////////////////////////////////////////////////////////// // 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!(), - } - } -} -*/ diff --git a/src/vm.rs b/src/vm.rs index 7e6a66b..c8dfff7 100644 --- a/src/vm.rs +++ b/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| { 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. /// /// 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 => { - let globals = self.globals.pop().unwrap(); - - let old_frame = self.pop_frame(); - self.stack - .resize_with(old_frame.stack_base, || unreachable!()); + self.exit_module(); // halt execution if there aren't any globals left if self.globals.is_empty() { 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); } } }