70 lines
1.6 KiB
Rust
70 lines
1.6 KiB
Rust
|
|
use crate::object::*;
|
||
|
|
use crate::vm::error::*;
|
||
|
|
use std::cell::RefCell;
|
||
|
|
use std::rc::Rc;
|
||
|
|
|
||
|
|
#[derive(Default)]
|
||
|
|
pub struct MachineBuilder {
|
||
|
|
max_stack_size: Option<usize>,
|
||
|
|
max_arena_objects: Option<usize>,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl MachineBuilder {
|
||
|
|
pub fn max_stack_size(mut self, max_stack_size: Option<usize>) -> Self {
|
||
|
|
self.max_stack_size = max_stack_size;
|
||
|
|
self
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn max_arena_objects(mut self, max_arena_objects: Option<usize>) -> 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<Value>,
|
||
|
|
max_stack_size: Option<usize>,
|
||
|
|
arena: Rc<RefCell<Arena>>,
|
||
|
|
}
|
||
|
|
|
||
|
|
impl Machine {
|
||
|
|
pub fn new(max_stack_size: Option<usize>, arena: Arena) -> Self {
|
||
|
|
Machine {
|
||
|
|
stack: Default::default(),
|
||
|
|
max_stack_size,
|
||
|
|
arena: Rc::new(RefCell::new(arena)),
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn max_stack_size(&self) -> Option<usize> {
|
||
|
|
self.max_stack_size
|
||
|
|
}
|
||
|
|
|
||
|
|
pub fn stack(&self) -> &Vec<Value> {
|
||
|
|
&self.stack
|
||
|
|
}
|
||
|
|
pub fn stack_mut(&mut self) -> &mut Vec<Value> {
|
||
|
|
&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<Value> {
|
||
|
|
self.stack_mut().pop()
|
||
|
|
}
|
||
|
|
}
|