refactor: function

This commit is contained in:
2025-05-10 20:01:56 +08:00
parent fa3193ea50
commit 046b03c60e
8 changed files with 293 additions and 277 deletions

View File

@@ -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")

View File

@@ -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() {