feat: ref
This commit is contained in:
@@ -7,12 +7,12 @@ use crate::ty::common::Symbol;
|
||||
use crate::ty::internal::Value;
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct Env {
|
||||
last: RefCell<Option<Arc<Env>>>,
|
||||
map: Arc<RefCell<HashTrieMapSync<Symbol, Value>>>,
|
||||
pub struct Env<'vm> {
|
||||
last: RefCell<Option<Arc<Env<'vm>>>>,
|
||||
map: Arc<RefCell<HashTrieMapSync<Symbol, Value<'vm>>>>,
|
||||
}
|
||||
|
||||
impl Clone for Env {
|
||||
impl Clone for Env<'_> {
|
||||
fn clone(&self) -> Self {
|
||||
Env {
|
||||
last: RefCell::new(
|
||||
@@ -27,24 +27,24 @@ impl Clone for Env {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct CapturedEnv {
|
||||
env: Arc<Env>,
|
||||
pub struct CapturedEnv<'vm> {
|
||||
env: Arc<Env<'vm>>,
|
||||
}
|
||||
|
||||
impl Env {
|
||||
pub fn empty() -> Env {
|
||||
impl<'vm> Env<'vm> {
|
||||
pub fn empty() -> Self {
|
||||
Env::default()
|
||||
}
|
||||
|
||||
pub fn lookup(&self, symbol: Symbol) -> Option<Value> {
|
||||
pub fn lookup(&self, symbol: Symbol) -> Option<Value<'vm>> {
|
||||
self.map.borrow().get(&symbol).cloned()
|
||||
}
|
||||
|
||||
pub fn insert(&self, symbol: Symbol, value: Value) {
|
||||
pub fn insert(&self, symbol: Symbol, value: Value<'vm>) {
|
||||
self.map.borrow_mut().insert_mut(symbol, value);
|
||||
}
|
||||
|
||||
pub fn enter(&self, new: HashTrieMapSync<Symbol, Value>) {
|
||||
pub fn enter(&self, new: HashTrieMapSync<Symbol, Value<'vm>>) {
|
||||
let mut map = self.map.borrow().clone();
|
||||
for (k, v) in new.iter() {
|
||||
map.insert_mut(k.clone(), v.clone());
|
||||
@@ -57,7 +57,7 @@ impl Env {
|
||||
*self.map.borrow_mut() = map;
|
||||
}
|
||||
|
||||
pub fn enter_rec(&self) -> Arc<RefCell<HashTrieMapSync<Symbol, Value>>> {
|
||||
pub fn enter_rec(&self) -> Arc<RefCell<HashTrieMapSync<Symbol, Value<'vm>>>> {
|
||||
let last = Env {
|
||||
last: self.last.clone(),
|
||||
map: self.map.clone(),
|
||||
@@ -73,17 +73,17 @@ impl Env {
|
||||
*self.map.borrow_mut() = map;
|
||||
}
|
||||
|
||||
pub fn captured(self: Arc<Self>) -> CapturedEnv {
|
||||
pub fn captured(self: Arc<Self>) -> CapturedEnv<'vm> {
|
||||
CapturedEnv { env: self }
|
||||
}
|
||||
}
|
||||
|
||||
impl CapturedEnv {
|
||||
pub fn lookup(&self, symbol: Symbol) -> Option<Value> {
|
||||
impl<'vm> CapturedEnv<'vm> {
|
||||
pub fn lookup(&self, symbol: Symbol) -> Option<Value<'vm>> {
|
||||
self.env.lookup(symbol)
|
||||
}
|
||||
|
||||
pub fn released(self) -> Arc<Env> {
|
||||
pub fn released(self) -> Arc<Env<'vm>> {
|
||||
Arc::new(self.env.as_ref().clone())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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::*;
|
||||
|
||||
@@ -6,8 +6,8 @@ use crate::ty::internal::Value;
|
||||
|
||||
pub const STACK_SIZE: usize = 8 * 1024 / size_of::<Value>();
|
||||
|
||||
pub struct Stack<const CAP: usize> {
|
||||
items: Box<[MaybeUninit<Value>; CAP]>,
|
||||
pub struct Stack<'vm, const CAP: usize> {
|
||||
items: Box<[MaybeUninit<Value<'vm>>; CAP]>,
|
||||
top: usize,
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ macro_rules! into {
|
||||
};
|
||||
}
|
||||
|
||||
impl<const CAP: usize> Stack<CAP> {
|
||||
impl<'vm, const CAP: usize> Stack<'vm, CAP> {
|
||||
pub fn new() -> Self {
|
||||
Stack {
|
||||
items: (0..CAP)
|
||||
@@ -29,7 +29,7 @@ impl<const CAP: usize> Stack<CAP> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn push(&mut self, item: Value) -> Result<()> {
|
||||
pub fn push(&mut self, item: Value<'vm>) -> Result<()> {
|
||||
self.items
|
||||
.get_mut(self.top)
|
||||
.map_or_else(
|
||||
@@ -41,14 +41,14 @@ impl<const CAP: usize> Stack<CAP> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn pop(&mut self) -> Value {
|
||||
pub fn pop(&mut self) -> Value<'vm> {
|
||||
self.top -= 1;
|
||||
let item = self.items.get_mut(self.top).unwrap();
|
||||
|
||||
unsafe { replace(item, MaybeUninit::uninit()).assume_init() }
|
||||
}
|
||||
|
||||
pub fn tos_mut(&mut self) -> Result<&mut Value> {
|
||||
pub fn tos_mut(&mut self) -> Result<&mut Value<'vm>> {
|
||||
if self.top == 0 {
|
||||
panic!("stack empty")
|
||||
} else {
|
||||
@@ -57,14 +57,14 @@ impl<const CAP: usize> Stack<CAP> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<const CAP: usize> Deref for Stack<CAP> {
|
||||
type Target = [Value];
|
||||
impl<'vm, const CAP: usize> Deref for Stack<'vm, CAP> {
|
||||
type Target = [Value<'vm>];
|
||||
fn deref(&self) -> &Self::Target {
|
||||
into!(&self.items[0..self.top])
|
||||
}
|
||||
}
|
||||
|
||||
impl<const CAP: usize> Drop for Stack<CAP> {
|
||||
impl<const CAP: usize> Drop for Stack<'_, CAP> {
|
||||
fn drop(&mut self) {
|
||||
self.items.as_mut_slice()[0..self.top]
|
||||
.iter_mut()
|
||||
|
||||
@@ -204,7 +204,6 @@ fn test_fib() {
|
||||
}
|
||||
|
||||
#[bench]
|
||||
#[ignore]
|
||||
fn bench_fib(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
black_box(test_expr(
|
||||
|
||||
Reference in New Issue
Block a user