refactor: function
This commit is contained in:
@@ -32,7 +32,7 @@ impl<const CAP: usize> Stack<CAP> {
|
||||
pub fn push(&mut self, item: Value) -> Result<()> {
|
||||
self.items
|
||||
.get_mut(self.top)
|
||||
.map_or(Err(Error::EvalError("stack overflow".to_string())), |ok| {
|
||||
.map_or_else(|| Err(Error::EvalError("stack overflow".to_string())), |ok| {
|
||||
Ok(ok)
|
||||
})?
|
||||
.write(item);
|
||||
@@ -47,14 +47,6 @@ impl<const CAP: usize> Stack<CAP> {
|
||||
unsafe { replace(item, MaybeUninit::uninit()).assume_init() }
|
||||
}
|
||||
|
||||
pub fn tos(&self) -> Result<&Value> {
|
||||
if self.top == 0 {
|
||||
panic!("stack empty")
|
||||
} else {
|
||||
Ok(into!(&self.items[self.top - 1]))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tos_mut(&mut self) -> Result<&mut Value> {
|
||||
if self.top == 0 {
|
||||
panic!("stack empty")
|
||||
|
||||
49
src/vm/vm.rs
49
src/vm/vm.rs
@@ -1,7 +1,7 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::builtins::env;
|
||||
use crate::bytecode::{self, BinOp, OpCode, OpCodes, Program, Thunks, UnOp};
|
||||
use crate::bytecode::{self, BinOp, Funcs, OpCode, OpCodes, Program, Thunks, UnOp};
|
||||
use crate::error::*;
|
||||
use crate::ty::common::Symbol;
|
||||
use crate::ty::internal::*;
|
||||
@@ -11,27 +11,32 @@ use super::env::Env;
|
||||
use super::stack::{STACK_SIZE, Stack};
|
||||
|
||||
pub fn run(prog: Program) -> Result<p::Value> {
|
||||
let vm = VM::new(prog.thunks);
|
||||
let vm = VM::new(prog.thunks, prog.funcs);
|
||||
Ok(vm.eval(prog.top_level, env())?.to_public(&vm))
|
||||
}
|
||||
|
||||
pub struct VM {
|
||||
thunks: Box<[Thunk]>,
|
||||
funcs: Funcs,
|
||||
}
|
||||
|
||||
impl VM {
|
||||
fn new(thunks: Thunks) -> Self {
|
||||
fn new(thunks: Thunks, funcs: Funcs) -> Self {
|
||||
let thunks = thunks
|
||||
.into_iter()
|
||||
.map(|bytecode::Thunk { opcodes }| Thunk::new(opcodes))
|
||||
.collect();
|
||||
VM { thunks }
|
||||
VM { thunks, funcs }
|
||||
}
|
||||
|
||||
pub fn get_thunk(&self, idx: usize) -> Thunk {
|
||||
self.thunks[idx].clone()
|
||||
}
|
||||
|
||||
pub fn get_func(&self, idx: usize) -> Func {
|
||||
self.funcs[idx].clone()
|
||||
}
|
||||
|
||||
pub fn eval(&self, opcodes: OpCodes, env: Arc<Env>) -> Result<Value> {
|
||||
let mut stack = Stack::<STACK_SIZE>::new();
|
||||
let mut iter = opcodes.into_iter();
|
||||
@@ -88,37 +93,9 @@ impl VM {
|
||||
stack.push(func.call(self, args)?)?;
|
||||
}
|
||||
OpCode::Func { idx } => {
|
||||
stack.push(Value::Func(Func::new(
|
||||
env.captured(),
|
||||
self.thunks[idx].unwrap_code(),
|
||||
)))?;
|
||||
}
|
||||
OpCode::PushIdentParam { sym } => {
|
||||
stack
|
||||
.tos_mut()?
|
||||
.as_mut()
|
||||
.unwrap_func()
|
||||
.push_ident_param(sym);
|
||||
}
|
||||
OpCode::PushFormalParam { sym } => {
|
||||
stack
|
||||
.tos_mut()?
|
||||
.as_mut()
|
||||
.unwrap_func()
|
||||
.push_formal_param(sym);
|
||||
}
|
||||
OpCode::PushDefaultParam { idx } => {
|
||||
stack
|
||||
.tos_mut()?
|
||||
.as_mut()
|
||||
.unwrap_func()
|
||||
.push_default_param(self.get_thunk(idx));
|
||||
}
|
||||
OpCode::SetEllipsis => {
|
||||
stack.tos_mut()?.as_mut().unwrap_func().set_ellipsis();
|
||||
}
|
||||
OpCode::SetAlias { sym } => {
|
||||
stack.tos_mut()?.as_mut().unwrap_func().set_alias(sym);
|
||||
let mut func = self.get_func(idx);
|
||||
func.env = Some(env.captured());
|
||||
stack.push(Value::Func(func))?;
|
||||
}
|
||||
OpCode::UnOp { op } => {
|
||||
use UnOp::*;
|
||||
@@ -216,7 +193,7 @@ impl VM {
|
||||
OpCode::LookUp { sym } => {
|
||||
stack.push(
|
||||
env.lookup(Symbol::new(sym.clone()))
|
||||
.ok_or(Error::EvalError(format!(r#""{sym}" not found"#)))?,
|
||||
.ok_or_else(|| Error::EvalError(format!(r#""{sym}" not found"#)))?,
|
||||
)?;
|
||||
}
|
||||
OpCode::EnterEnv => match stack.pop() {
|
||||
|
||||
Reference in New Issue
Block a user