use crate::object::*; use crate::vm::error::*; use std::cell::RefCell; use std::rc::Rc; #[derive(Default)] pub struct MachineBuilder { max_stack_size: Option, max_arena_objects: Option, } impl MachineBuilder { pub fn max_stack_size(mut self, max_stack_size: Option) -> Self { self.max_stack_size = max_stack_size; self } pub fn max_arena_objects(mut self, max_arena_objects: Option) -> Self { self.max_arena_objects = max_arena_objects; self } pub fn finish(self) -> Machine { Machine::new(self.max_stack_size, Arena::new(self.max_arena_objects)) } } /// The current state of a VM. #[derive(Debug)] pub struct Machine { stack: Vec, max_stack_size: Option, arena: Rc>, } impl Machine { pub fn new(max_stack_size: Option, arena: Arena) -> Self { Machine { stack: Default::default(), max_stack_size, arena: Rc::new(RefCell::new(arena)), } } pub fn max_stack_size(&self) -> Option { self.max_stack_size } pub fn stack(&self) -> &Vec { &self.stack } pub fn stack_mut(&mut self) -> &mut Vec { &mut self.stack } pub fn stack_push(&mut self, value: Value) -> Result<()> { if let Some(max) = self.max_stack_size() { if self.stack.len() >= max { return Err(RuntimeError::StackOverflow); } } self.stack_mut().push(value); Ok(()) } pub fn stack_pop(&mut self) -> Option { self.stack_mut().pop() } }