pub mod frame; pub mod op; use crate::{ mem::gc::Gc, obj::prelude::*, vm::{frame::Frame, op::Op}, }; use std::rc::Rc; pub struct State { gc: G, frames: Vec, } impl State { pub fn new(gc: G) -> Self { State { gc, frames: Default::default(), } } pub fn frames(&self) -> &Vec { &self.frames } pub fn frames_mut(&mut self) -> &mut Vec { &mut self.frames } pub fn frame(&self) -> &Frame { self.frames.last().unwrap() } pub fn frame_mut(&mut self) -> &mut Frame { self.frames.last_mut().unwrap() } pub fn push_stack(&mut self, value: DynRef) { self.frame_mut().push(value); } pub fn pop_stack(&mut self) -> Option { self.frame_mut().pop() } pub fn ip(&self) -> usize { self.frame().ip() } pub fn set_ip(&mut self, ip: usize) { self.frame_mut().set_ip(ip); } pub fn get_local(&self, name: NameId) -> Option { self.frame().get_local(name) } pub fn set_local(&mut self, name: NameId, obj_ref: DynRef) -> Option { self.frame_mut().set_local(name, obj_ref) } pub fn ops(&self) -> &Rc> { self.frame().ops() } pub fn resume(&mut self) { while !self.frames().is_empty() { self.resume_fun(); let _frame = self.frames_mut().pop().unwrap(); // Push return value? } } pub fn resume_fun(&mut self) { while self.ip() < self.ops().len() { self.step(); } } pub fn step(&mut self) { let mut next_ip = self.ip() + 1; match self.ops()[self.ip()] { Op::Push(name) => { // TODO - local not found let obj_ref = self.get_local(name).expect("TODO - local not found"); self.push_stack(obj_ref); } Op::Pop(name) => { // stack should not underflow let obj_ref = self.pop_stack().expect("misaligned stack for pop"); if let Some(name) = name { self.set_local(name, obj_ref); } } Op::GetAttr(sym) => { let top = self.pop_stack().expect("misaligned stack for getattrs"); let obj_ref = { let top_ref = top.borrow(); let attrs = top_ref.attrs(); let attrs_ref = attrs.borrow(); // TODO - local not found attrs_ref.get(sym).expect("TODO - local not found") }; self.push_stack(obj_ref); } Op::Call(argc) => { let fun = self .pop_stack() .expect("misaligned stack for function call"); let mut argv = Vec::with_capacity(argc); for _ in 0..argc { let arg = self.pop_stack().expect("misaligned stack for argv"); argv.push(arg); } // reverse since arguments are pushed in order of being passed argv.reverse(); // TODO // move ops pointer to the stack frame if let Some(_fun) = fun.borrow().as_any().downcast_ref::() { self.set_ip(next_ip); next_ip = 0; todo!("New stack frame"); } else if let Some(_fun) = fun.borrow().as_any().downcast_ref::() { todo!(); } else { todo!("TODO - not a function"); } } } self.set_ip(next_ip); } }