feat: ref
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
use std::cell::OnceCell;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::builtins::env;
|
||||
@@ -19,17 +20,30 @@ mod stack;
|
||||
mod test;
|
||||
|
||||
pub fn run(prog: Program) -> Result<p::Value> {
|
||||
let vm = VM::new(prog.thunks, prog.funcs);
|
||||
Ok(vm.eval(prog.top_level, env())?.to_public(&vm))
|
||||
let vm = VM::new(
|
||||
prog.thunks,
|
||||
prog.funcs
|
||||
.into_iter()
|
||||
.map(|f| Func {
|
||||
env: OnceCell::new(),
|
||||
param: f.param,
|
||||
opcodes: f.opcodes,
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
let env = env();
|
||||
let temp = vm.eval(prog.top_level, env)?;
|
||||
let temp = temp.to_public(&vm);
|
||||
Ok(temp)
|
||||
}
|
||||
|
||||
pub struct VM {
|
||||
thunks: Box<[Thunk]>,
|
||||
funcs: Box<[Func]>,
|
||||
pub struct VM<'vm> {
|
||||
thunks: Box<[Thunk<'vm>]>,
|
||||
funcs: Box<[Func<'vm>]>,
|
||||
}
|
||||
|
||||
impl VM {
|
||||
fn new(thunks: Box<[OpCodes]>, funcs: Box<[Func]>) -> Self {
|
||||
impl<'vm> VM<'vm> {
|
||||
fn new(thunks: Box<[OpCodes]>, funcs: Box<[Func<'vm>]>) -> Self {
|
||||
let thunks = thunks
|
||||
.into_iter()
|
||||
.map(|opcodes| Thunk::new(opcodes))
|
||||
@@ -37,15 +51,15 @@ impl VM {
|
||||
VM { thunks, funcs }
|
||||
}
|
||||
|
||||
pub fn get_thunk(&self, idx: usize) -> &Thunk {
|
||||
&self.thunks[idx]
|
||||
pub fn get_thunk(&self, idx: usize) -> &'vm Thunk<'vm> {
|
||||
unsafe { &*(&self.thunks[idx] as *const _) }
|
||||
}
|
||||
|
||||
pub fn get_func(&self, idx: usize) -> &Func {
|
||||
&self.funcs[idx]
|
||||
pub fn get_func(&self, idx: usize) -> &'vm Func<'vm> {
|
||||
unsafe { &*(&self.funcs[idx] as *const _) }
|
||||
}
|
||||
|
||||
pub fn eval(&self, opcodes: OpCodes, env: Arc<Env>) -> Result<Value> {
|
||||
pub fn eval(&self, opcodes: OpCodes, env: Arc<Env<'vm>>) -> Result<Value<'vm>> {
|
||||
let mut stack = Stack::<STACK_SIZE>::new();
|
||||
let mut iter = opcodes.into_iter();
|
||||
while let Some(opcode) = iter.next() {
|
||||
@@ -61,12 +75,13 @@ impl VM {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn single_op<const CAP: usize>(
|
||||
fn single_op<'s, const CAP: usize>(
|
||||
&self,
|
||||
opcode: OpCode,
|
||||
stack: &mut Stack<CAP>,
|
||||
env: Arc<Env>,
|
||||
) -> Result<usize> {
|
||||
stack: &'s mut Stack<'vm, CAP>,
|
||||
env: Arc<Env<'vm>>,
|
||||
) -> Result<usize>
|
||||
{
|
||||
match opcode {
|
||||
OpCode::Illegal => panic!("illegal opcode"),
|
||||
OpCode::Const { value } => stack.push(Value::Const(value))?,
|
||||
@@ -101,8 +116,9 @@ impl VM {
|
||||
stack.push(func.call(self, args)?)?;
|
||||
}
|
||||
OpCode::Func { idx } => {
|
||||
self.get_func(idx).env.get_or_init(|| env.captured());
|
||||
stack.push(Value::Func(idx))?;
|
||||
let func = self.get_func(idx);
|
||||
func.env.get_or_init(|| env.captured());
|
||||
stack.push(Value::Func(func))?;
|
||||
}
|
||||
OpCode::UnOp { op } => {
|
||||
use UnOp::*;
|
||||
|
||||
Reference in New Issue
Block a user