From 7cbb082dc4ff008fd15f7af7cd320320f8b3cd7d Mon Sep 17 00:00:00 2001 From: imxyy_soope_ Date: Sun, 11 May 2025 10:19:55 +0800 Subject: [PATCH] feat: ref --- src/builtins/mod.rs | 2 +- src/bytecode.rs | 8 ++- src/compile.rs | 4 -- src/ty/internal/attrset.rs | 50 +++++++-------- src/ty/internal/func.rs | 12 ++-- src/ty/internal/list.rs | 16 ++--- src/ty/internal/mod.rs | 128 ++++++++++++++++++------------------- src/ty/internal/primop.rs | 22 +++---- src/vm/env.rs | 32 +++++----- src/vm/mod.rs | 52 +++++++++------ src/vm/stack.rs | 18 +++--- src/vm/test.rs | 1 - 12 files changed, 180 insertions(+), 165 deletions(-) diff --git a/src/builtins/mod.rs b/src/builtins/mod.rs index e3ec9cf..8dd1c1b 100644 --- a/src/builtins/mod.rs +++ b/src/builtins/mod.rs @@ -5,7 +5,7 @@ use crate::ty::common::Symbol; use crate::ty::internal::{_Thunk, Const, PrimOp, RecAttrSet, Thunk, Value}; use crate::vm::Env; -pub fn env() -> Arc { +pub fn env<'vm>() -> Arc> { let env = Arc::new(Env::empty()); env.insert(Symbol::from("true"), Value::Const(Const::Bool(true))); env.insert(Symbol::from("false"), Value::Const(Const::Bool(false))); diff --git a/src/bytecode.rs b/src/bytecode.rs index 69cdd66..0c8c89d 100644 --- a/src/bytecode.rs +++ b/src/bytecode.rs @@ -1,6 +1,6 @@ use ecow::EcoString; -use crate::ty::internal::{Const, Func}; +use crate::ty::internal::{Const, Param}; type Slice = Box<[T]>; @@ -94,6 +94,12 @@ pub enum UnOp { Not, } +#[derive(Debug)] +pub struct Func { + pub param: Param, + pub opcodes: OpCodes, +} + #[derive(Debug)] pub struct Program { pub top_level: OpCodes, diff --git a/src/compile.rs b/src/compile.rs index b4b06cf..7eec459 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -1,9 +1,6 @@ -use std::cell::OnceCell; - use crate::bytecode::*; use crate::ir; use crate::ty::internal::Const; -use crate::ty::internal::Func; pub struct Compiler { opcodes: Vec, @@ -21,7 +18,6 @@ pub fn compile(downgraded: ir::Downgraded) -> Program { .funcs .into_iter() .map(|func| Func { - env: OnceCell::new(), param: func.param.into(), opcodes: Compiler::new().compile(*func.body), }) diff --git a/src/ty/internal/attrset.rs b/src/ty/internal/attrset.rs index 3d1b586..14b1d97 100644 --- a/src/ty/internal/attrset.rs +++ b/src/ty/internal/attrset.rs @@ -12,29 +12,29 @@ use super::super::public as p; use super::{ToPublic, Value}; #[derive(Debug, Constructor, Clone, PartialEq)] -pub struct AttrSet { - data: HashTrieMapSync, +pub struct AttrSet<'vm> { + data: HashTrieMapSync>, } -impl AttrSet { +impl<'vm> AttrSet<'vm> { pub fn empty() -> Self { AttrSet { data: HashTrieMapSync::new_sync(), } } - pub fn push_attr_force(&mut self, sym: Symbol, val: Value) { + pub fn push_attr_force(&mut self, sym: Symbol, val: Value<'vm>) { self.data.insert_mut(sym, val); } - pub fn push_attr(&mut self, sym: Symbol, val: Value) { + pub fn push_attr(&mut self, sym: Symbol, val: Value<'vm>) { if self.data.get_mut(&sym).is_some() { todo!() } self.data.insert_mut(sym, val); } - pub fn select(&self, sym: Symbol) -> Option { + pub fn select(&self, sym: Symbol) -> Option> { self.data.get(&sym).cloned() } @@ -42,29 +42,29 @@ impl AttrSet { self.data.get(&sym).is_some() } - pub fn update(mut self, other: AttrSet) -> AttrSet { + pub fn update(mut self, other: AttrSet<'vm>) -> AttrSet<'vm> { for (k, v) in other.data.iter() { self.push_attr_force(k.clone(), v.clone()) } self } - pub fn update_rec(mut self, other: RecAttrSet) -> AttrSet { + pub fn update_rec(mut self, other: RecAttrSet<'vm>) -> AttrSet<'vm> { for (k, v) in other.data.borrow().iter() { self.push_attr_force(k.clone(), v.clone()) } self } - pub fn into_inner(self) -> HashTrieMapSync { + pub fn into_inner(self) -> HashTrieMapSync> { self.data } - pub fn as_inner(&self) -> &HashTrieMapSync { + pub fn as_inner(&self) -> &HashTrieMapSync> { &self.data } - pub fn force_deep(&mut self, vm: &VM) -> Result<()> { + pub fn force_deep(&mut self, vm: &VM<'vm>) -> Result<()> { let mut map: Vec<_> = self .data .into_iter() @@ -79,7 +79,7 @@ impl AttrSet { } } -impl ToPublic for AttrSet { +impl ToPublic for AttrSet<'_> { fn to_public(self, vm: &VM) -> p::Value { p::Value::AttrSet(p::AttrSet::new( self.data @@ -91,29 +91,29 @@ impl ToPublic for AttrSet { } #[derive(Debug, Constructor, Clone, PartialEq)] -pub struct RecAttrSet { - data: Arc>>, +pub struct RecAttrSet<'vm> { + data: Arc>>>, } -impl RecAttrSet { - pub fn empty() -> RecAttrSet { +impl<'vm> RecAttrSet<'vm> { + pub fn empty() -> Self { RecAttrSet { data: Arc::default(), } } - pub fn push_attr_force(&mut self, sym: Symbol, val: Value) { + pub fn push_attr_force(&mut self, sym: Symbol, val: Value<'vm>) { self.data.borrow_mut().insert_mut(sym, val); } - pub fn push_attr(&mut self, sym: Symbol, val: Value) { + pub fn push_attr(&mut self, sym: Symbol, val: Value<'vm>) { if self.data.borrow().get(&sym).is_some() { todo!() } self.data.borrow_mut().insert_mut(sym, val); } - pub fn select(&self, sym: Symbol) -> Option { + pub fn select(&self, sym: Symbol) -> Option> { self.data.borrow().get(&sym).cloned() } @@ -121,14 +121,14 @@ impl RecAttrSet { self.data.borrow().get(&sym).is_some() } - pub fn update(mut self, other: RecAttrSet) -> RecAttrSet { + pub fn update(mut self, other: RecAttrSet<'vm>) -> RecAttrSet<'vm> { for (k, v) in other.data.borrow().iter() { self.push_attr_force(k.clone(), v.clone()) } self } - pub fn update_normal(self, other: AttrSet) -> AttrSet { + pub fn update_normal(self, other: AttrSet<'vm>) -> AttrSet<'vm> { let map = self .data .borrow() @@ -142,15 +142,15 @@ impl RecAttrSet { new } - pub fn into_inner(self) -> HashTrieMapSync { + pub fn into_inner(self) -> HashTrieMapSync> { self.data.borrow().clone() } - pub fn from_inner(data: Arc>>) -> Self { + pub fn from_inner(data: Arc>>>) -> Self { RecAttrSet { data } } - pub fn force_deep(&mut self, vm: &VM) -> Result<()> { + pub fn force_deep(&mut self, vm: &VM<'vm>) -> Result<()> { let mut map: Vec<_> = self .data .borrow() @@ -166,7 +166,7 @@ impl RecAttrSet { } } -impl ToPublic for RecAttrSet { +impl ToPublic for RecAttrSet<'_> { fn to_public(self, vm: &VM) -> p::Value { p::Value::AttrSet(p::AttrSet::new( self.data diff --git a/src/ty/internal/func.rs b/src/ty/internal/func.rs index 9c20b8c..332626b 100644 --- a/src/ty/internal/func.rs +++ b/src/ty/internal/func.rs @@ -41,14 +41,14 @@ impl From for Param { } #[derive(Debug, Clone)] -pub struct Func { - pub env: OnceCell, +pub struct Func<'vm> { + pub env: OnceCell>, pub param: Param, pub opcodes: OpCodes, } -impl Func { - pub fn call(&self, vm: &VM, arg: Value) -> Result { +impl<'vm> Func<'vm> { + pub fn call(&'vm self, vm: &VM<'vm>, arg: Value<'vm>) -> Result> { use Param::*; let env = self.env.get().unwrap().clone().released(); @@ -75,7 +75,7 @@ impl Func { for (formal, default) in formals { let arg = arg .select(formal.clone().into()) - .or_else(|| default.map(Value::ThunkRef)) + .or_else(|| default.map(|idx| Value::ThunkRef(vm.get_thunk(idx)))) .unwrap(); new.insert_mut(formal.clone().into(), arg); } @@ -90,7 +90,7 @@ impl Func { } } -impl PartialEq for Func { +impl PartialEq for Func<'_> { fn eq(&self, _: &Self) -> bool { false } diff --git a/src/ty/internal/list.rs b/src/ty/internal/list.rs index 671c7ee..47ab8d2 100644 --- a/src/ty/internal/list.rs +++ b/src/ty/internal/list.rs @@ -8,29 +8,29 @@ use crate::vm::VM; use super::{ToPublic, Value}; #[derive(Debug, Constructor, Clone, PartialEq)] -pub struct List { - data: VectorSync, +pub struct List<'vm> { + data: VectorSync>, } -impl List { - pub fn empty() -> List { +impl<'vm> List<'vm> { + pub fn empty() -> Self { List { data: VectorSync::new_sync(), } } - pub fn push(&mut self, elem: Value) { + pub fn push(&mut self, elem: Value<'vm>) { self.data.push_back_mut(elem); } - pub fn concat(mut self, other: List) -> List { + pub fn concat(mut self, other: List<'vm>) -> List<'vm> { for elem in other.data.iter() { self.data.push_back_mut(elem.clone()); } self } - pub fn force_deep(&mut self, vm: &VM) -> Result<()> { + pub fn force_deep(&mut self, vm: &VM<'vm>) -> Result<()> { let mut vec: Vec<_> = self.data.iter().cloned().collect(); vec.iter_mut() .map(|v| v.force_deep(vm).map(|_| ())) @@ -41,7 +41,7 @@ impl List { } } -impl ToPublic for List { +impl ToPublic for List<'_> { fn to_public(self, vm: &VM) -> p::Value { p::Value::List(p::List::new( self.data diff --git a/src/ty/internal/mod.rs b/src/ty/internal/mod.rs index c08f064..4215402 100644 --- a/src/ty/internal/mod.rs +++ b/src/ty/internal/mod.rs @@ -30,20 +30,20 @@ pub trait ToPublic { } #[derive(Debug, Clone)] -pub struct Thunk { - pub thunk: RefCell<_Thunk>, - pub env: RefCell>>, +pub struct Thunk<'vm> { + pub thunk: RefCell<_Thunk<'vm>>, + pub env: RefCell>>>, } #[derive(Debug, IsVariant, Unwrap, Clone)] -pub enum _Thunk { +pub enum _Thunk<'vm> { Code(OpCodes), - SuspendedFrom(*const Thunk), - Value(Box), + SuspendedFrom(*const Thunk<'vm>), + Value(Box>), } -impl Thunk { - pub fn new(opcodes: OpCodes) -> Thunk { +impl<'vm> Thunk<'vm> { + pub fn new(opcodes: OpCodes) -> Self { Thunk { thunk: RefCell::new(_Thunk::Code(opcodes)), env: RefCell::new(None), @@ -54,11 +54,11 @@ impl Thunk { self.thunk.borrow().clone().unwrap_code() } - pub fn capture(&self, env: Arc) { + pub fn capture(&self, env: Arc>) { *self.env.borrow_mut() = Some(env); } - pub fn force(&self, vm: &VM) -> Result { + pub fn force(&self, vm: &VM<'vm>) -> Result> { match &*self.thunk.borrow() { _Thunk::Value(value) => return Ok(value.as_ref().clone()), _Thunk::SuspendedFrom(from) => { @@ -82,7 +82,7 @@ impl Thunk { Ok(value) } - pub fn value(&self) -> Option { + pub fn value(&'vm self) -> Option> { match &*self.thunk.borrow() { _Thunk::Value(value) => Some(value.as_ref().clone()), _ => None, @@ -90,62 +90,60 @@ impl Thunk { } } -impl PartialEq for Thunk { +impl PartialEq for Thunk<'_> { fn eq(&self, _: &Self) -> bool { false } } #[derive(Debug, IsVariant, Unwrap, Clone, PartialEq)] -pub enum Value { +pub enum Value<'vm> { Const(Const), - Thunk(Thunk), - ThunkRef(usize), - AttrSet(AttrSet), - RecAttrSet(RecAttrSet), - List(List), + Thunk(Thunk<'vm>), + ThunkRef(&'vm Thunk<'vm>), + AttrSet(AttrSet<'vm>), + RecAttrSet(RecAttrSet<'vm>), + List(List<'vm>), Catchable(c::Catchable), - PrimOp(PrimOp), - PartialPrimOp(PartialPrimOp), - Func(usize), + PrimOp(PrimOp<'vm>), + PartialPrimOp(PartialPrimOp<'vm>), + Func(&'vm Func<'vm>), } #[derive(Debug, IsVariant, Unwrap, Clone, PartialEq)] -pub enum ValueAsRef<'v> { +pub enum ValueAsRef<'v, 'vm: 'v> { Const(&'v Const), - Thunk(&'v Thunk), - ThunkRef(&'v usize), - AttrSet(&'v AttrSet), - RecAttrSet(&'v RecAttrSet), - List(&'v List), + Thunk(&'v Thunk<'vm>), + AttrSet(&'v AttrSet<'vm>), + RecAttrSet(&'v RecAttrSet<'vm>), + List(&'v List<'vm>), Catchable(&'v c::Catchable), - PrimOp(&'v PrimOp), - PartialPrimOp(&'v PartialPrimOp), - Func(&'v usize), + PrimOp(&'v PrimOp<'vm>), + PartialPrimOp(&'v PartialPrimOp<'vm>), + Func(&'vm Func<'vm>), } #[derive(Debug, IsVariant, Unwrap, PartialEq)] -pub enum ValueAsMut<'v> { +pub enum ValueAsMut<'v, 'vm: 'v> { Const(&'v mut Const), - Thunk(&'v Thunk), - ThunkRef(&'v usize), - AttrSet(&'v mut AttrSet), - RecAttrSet(&'v mut RecAttrSet), - List(&'v mut List), + Thunk(&'v Thunk<'vm>), + AttrSet(&'v mut AttrSet<'vm>), + RecAttrSet(&'v mut RecAttrSet<'vm>), + List(&'v mut List<'vm>), Catchable(&'v mut c::Catchable), - PrimOp(&'v mut PrimOp), - PartialPrimOp(&'v mut PartialPrimOp), - Func(&'v usize), + PrimOp(&'v mut PrimOp<'vm>), + PartialPrimOp(&'v mut PartialPrimOp<'vm>), + Func(&'vm Func<'vm>), } -impl Value { - pub fn as_ref(&self) -> ValueAsRef { +impl<'v, 'vm: 'v> Value<'vm> { + pub fn as_ref(&'vm self) -> ValueAsRef<'v, 'vm> { use Value::*; use ValueAsRef as R; match self { Const(x) => R::Const(x), Thunk(x) => R::Thunk(x), - ThunkRef(x) => R::ThunkRef(x), + ThunkRef(x) => R::Thunk(x), AttrSet(x) => R::AttrSet(x), RecAttrSet(x) => R::RecAttrSet(x), List(x) => R::List(x), @@ -156,13 +154,13 @@ impl Value { } } - pub fn as_mut(&mut self) -> ValueAsMut { + pub fn as_mut(&'vm mut self) -> ValueAsMut<'v, 'vm> { use Value::*; use ValueAsMut as M; match self { Const(x) => M::Const(x), Thunk(x) => M::Thunk(x), - ThunkRef(x) => M::ThunkRef(x), + ThunkRef(x) => M::Thunk(x), AttrSet(x) => M::AttrSet(x), RecAttrSet(x) => M::RecAttrSet(x), List(x) => M::List(x), @@ -175,7 +173,7 @@ impl Value { } use Value::Const as VmConst; -impl Value { +impl<'vm> Value<'vm> { pub fn typename(&self) -> &'static str { use Value::*; match self { @@ -200,7 +198,7 @@ impl Value { } } - pub fn call(self, vm: &VM, args: Vec) -> Result { + pub fn call(self, vm: &VM<'vm>, args: Vec>) -> Result> { use Value::*; Ok(match self { PrimOp(func) => func.call(vm, args), @@ -215,7 +213,7 @@ impl Value { PartialPrimOp(func) => { return Ok(func.call(vm, [arg].into_iter().chain(iter).collect())); } - Func(func) => vm.get_func(func).call(vm, arg)?, + Func(func) => func.call(vm, arg)?, _ => todo!(), } } @@ -226,7 +224,7 @@ impl Value { }) } - pub fn not(self) -> Value { + pub fn not(self) -> Value<'vm> { use Const::*; match self { VmConst(Bool(bool)) => VmConst(Bool(!bool)), @@ -235,7 +233,7 @@ impl Value { } } - pub fn and(self, other: Value) -> Value { + pub fn and(self, other: Value<'vm>) -> Value<'vm> { use Const::*; match (self, other) { (VmConst(Bool(a)), VmConst(Bool(b))) => VmConst(Bool(a && b)), @@ -244,7 +242,7 @@ impl Value { } } - pub fn or(self, other: Value) -> Value { + pub fn or(self, other: Value<'vm>) -> Value<'vm> { use Const::*; match (self, other) { (VmConst(Bool(a)), VmConst(Bool(b))) => VmConst(Bool(a || b)), @@ -253,7 +251,7 @@ impl Value { } } - pub fn eq(self, other: Value) -> Value { + pub fn eq(self, other: Value<'vm>) -> Value<'vm> { use Const::Bool; match (self, other) { (x @ Value::Catchable(_), _) | (_, x @ Value::Catchable(_)) => x, @@ -261,7 +259,7 @@ impl Value { } } - pub fn lt(self, other: Value) -> Value { + pub fn lt(self, other: Value<'vm>) -> Value<'vm> { use Const::*; VmConst(Bool(match (self, other) { (VmConst(Int(a)), VmConst(Int(b))) => a < b, @@ -274,7 +272,7 @@ impl Value { })) } - pub fn neg(self) -> Value { + pub fn neg(self) -> Value<'vm> { use Const::*; match self { VmConst(Int(int)) => VmConst(Int(-int)), @@ -284,7 +282,7 @@ impl Value { } } - pub fn add(self, other: Value) -> Value { + pub fn add(self, other: Value<'vm>) -> Value<'vm> { use Const::*; match (self, other) { (VmConst(Int(a)), VmConst(Int(b))) => VmConst(Int(a + b)), @@ -301,7 +299,7 @@ impl Value { } } - pub fn mul(self, other: Value) -> Value { + pub fn mul(self, other: Value<'vm>) -> Value<'vm> { use Const::*; match (self, other) { (VmConst(Int(a)), VmConst(Int(b))) => VmConst(Int(a * b)), @@ -313,7 +311,7 @@ impl Value { } } - pub fn div(self, other: Value) -> Value { + pub fn div(self, other: Value<'vm>) -> Value<'vm> { use Const::*; match (self, other) { (_, VmConst(Int(0))) => todo!(), @@ -327,7 +325,7 @@ impl Value { } } - pub fn concat_string(&mut self, mut other: Value) -> &mut Self { + pub fn concat_string(&mut self, mut other: Value<'vm>) -> &mut Self { match (self.coerce_to_string(), other.coerce_to_string()) { (VmConst(Const::String(a)), VmConst(Const::String(b))) => a.push_str(b.as_str()), (_, Value::Catchable(_)) => *self = other, @@ -337,7 +335,7 @@ impl Value { self } - pub fn push(&mut self, elem: Value) -> &mut Self { + pub fn push(&mut self, elem: Value<'vm>) -> &mut Self { if let Value::List(list) = self { list.push(elem); } else if let Value::Catchable(_) = self { @@ -349,7 +347,7 @@ impl Value { self } - pub fn concat(self, other: Value) -> Value { + pub fn concat(self, other: Value<'vm>) -> Value<'vm> { match (self, other) { (Value::List(a), Value::List(b)) => Value::List(a.concat(b)), (x @ Value::Catchable(_), _) | (_, x @ Value::Catchable(_)) => x, @@ -357,7 +355,7 @@ impl Value { } } - pub fn push_attr(&mut self, sym: Symbol, val: Value) -> &mut Self { + pub fn push_attr(&mut self, sym: Symbol, val: Value<'vm>) -> &mut Self { if let Value::AttrSet(attrs) = self { attrs.push_attr(sym, val) } else if let Value::RecAttrSet(attrs) = self { @@ -371,7 +369,7 @@ impl Value { self } - pub fn update(self, other: Value) -> Value { + pub fn update(self, other: Value<'vm>) -> Value<'vm> { match (self, other) { (Value::AttrSet(a), Value::AttrSet(b)) => Value::AttrSet(a.update(b)), (Value::RecAttrSet(a), Value::AttrSet(b)) => Value::AttrSet(a.update_normal(b)), @@ -399,7 +397,7 @@ impl Value { Ok(self) } - pub fn select_with_default(&mut self, sym: Symbol, default: Value) -> Result<&mut Self> { + pub fn select_with_default(&mut self, sym: Symbol, default: Value<'vm>) -> Result<&mut Self> { let val = match self { Value::AttrSet(attrs) => attrs.select(sym.clone()).unwrap_or(default), Value::RecAttrSet(attrs) => attrs.select(sym.clone()).unwrap_or(default), @@ -438,7 +436,7 @@ impl Value { self } - pub fn force(&mut self, vm: &VM) -> Result<&mut Self> { + pub fn force(&mut self, vm: &VM<'vm>) -> Result<&mut Self> { if let Value::Thunk(thunk) = self { let value = thunk.force(vm)?; *self = value @@ -446,7 +444,7 @@ impl Value { Ok(self) } - pub fn force_deep(&mut self, vm: &VM) -> Result<&mut Self> { + pub fn force_deep(&mut self, vm: &VM<'vm>) -> Result<&mut Self> { match self { Value::Thunk(thunk) => { let mut value = thunk.force(vm)?; @@ -462,7 +460,7 @@ impl Value { } } -impl ToPublic for Value { +impl ToPublic for Value<'_> { fn to_public(self, vm: &VM) -> p::Value { match self { Value::AttrSet(attrs) => attrs.to_public(vm), diff --git a/src/ty/internal/primop.rs b/src/ty/internal/primop.rs index ee45473..d48943a 100644 --- a/src/ty/internal/primop.rs +++ b/src/ty/internal/primop.rs @@ -5,20 +5,20 @@ use crate::vm::VM; use super::Value; #[derive(Debug, Clone, Constructor)] -pub struct PrimOp { +pub struct PrimOp<'vm> { pub name: &'static str, arity: u8, - func: fn(&VM, Vec) -> Value, + func: fn(&VM<'vm>, Vec>) -> Value<'vm>, } -impl PartialEq for PrimOp { +impl PartialEq for PrimOp<'_> { fn eq(&self, _: &Self) -> bool { false } } -impl PrimOp { - pub fn call(self, vm: &VM, args: Vec) -> Value { +impl<'vm> PrimOp<'vm> { + pub fn call(self, vm: &VM<'vm>, args: Vec>) -> Value<'vm> { if (args.len() as u8) < self.arity { Value::PartialPrimOp(PartialPrimOp { name: self.name, @@ -35,21 +35,21 @@ impl PrimOp { } #[derive(Debug, Clone)] -pub struct PartialPrimOp { +pub struct PartialPrimOp<'vm> { pub name: &'static str, arity: u8, - args: Vec, - func: fn(&VM, Vec) -> Value, + args: Vec>, + func: fn(&VM<'vm>, Vec>) -> Value<'vm>, } -impl PartialEq for PartialPrimOp { +impl PartialEq for PartialPrimOp<'_> { fn eq(&self, _: &Self) -> bool { false } } -impl PartialPrimOp { - pub fn call(mut self, vm: &VM, args: Vec) -> Value { +impl<'vm> PartialPrimOp<'vm> { + pub fn call(mut self, vm: &VM<'vm>, args: Vec>) -> Value<'vm> { let len = args.len() as u8; self.args.extend(args); if len < self.arity { diff --git a/src/vm/env.rs b/src/vm/env.rs index c252be1..219b980 100644 --- a/src/vm/env.rs +++ b/src/vm/env.rs @@ -7,12 +7,12 @@ use crate::ty::common::Symbol; use crate::ty::internal::Value; #[derive(Debug, Default)] -pub struct Env { - last: RefCell>>, - map: Arc>>, +pub struct Env<'vm> { + last: RefCell>>>, + map: Arc>>>, } -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, +pub struct CapturedEnv<'vm> { + env: Arc>, } -impl Env { - pub fn empty() -> Env { +impl<'vm> Env<'vm> { + pub fn empty() -> Self { Env::default() } - pub fn lookup(&self, symbol: Symbol) -> Option { + pub fn lookup(&self, symbol: Symbol) -> Option> { 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) { + pub fn enter(&self, new: HashTrieMapSync>) { 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>> { + pub fn enter_rec(&self) -> Arc>>> { 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) -> CapturedEnv { + pub fn captured(self: Arc) -> CapturedEnv<'vm> { CapturedEnv { env: self } } } -impl CapturedEnv { - pub fn lookup(&self, symbol: Symbol) -> Option { +impl<'vm> CapturedEnv<'vm> { + pub fn lookup(&self, symbol: Symbol) -> Option> { self.env.lookup(symbol) } - pub fn released(self) -> Arc { + pub fn released(self) -> Arc> { Arc::new(self.env.as_ref().clone()) } } diff --git a/src/vm/mod.rs b/src/vm/mod.rs index 83a5c7f..a58b05f 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -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 { - 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) -> Result { + pub fn eval(&self, opcodes: OpCodes, env: Arc>) -> Result> { let mut stack = Stack::::new(); let mut iter = opcodes.into_iter(); while let Some(opcode) = iter.next() { @@ -61,12 +75,13 @@ impl VM { } #[inline] - fn single_op( + fn single_op<'s, const CAP: usize>( &self, opcode: OpCode, - stack: &mut Stack, - env: Arc, - ) -> Result { + stack: &'s mut Stack<'vm, CAP>, + env: Arc>, + ) -> Result + { 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::*; diff --git a/src/vm/stack.rs b/src/vm/stack.rs index 5887cdf..9056e46 100644 --- a/src/vm/stack.rs +++ b/src/vm/stack.rs @@ -6,8 +6,8 @@ use crate::ty::internal::Value; pub const STACK_SIZE: usize = 8 * 1024 / size_of::(); -pub struct Stack { - items: Box<[MaybeUninit; CAP]>, +pub struct Stack<'vm, const CAP: usize> { + items: Box<[MaybeUninit>; CAP]>, top: usize, } @@ -17,7 +17,7 @@ macro_rules! into { }; } -impl Stack { +impl<'vm, const CAP: usize> Stack<'vm, CAP> { pub fn new() -> Self { Stack { items: (0..CAP) @@ -29,7 +29,7 @@ impl Stack { } } - 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 Stack { 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 Stack { } } -impl Deref for Stack { - 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 Drop for Stack { +impl Drop for Stack<'_, CAP> { fn drop(&mut self) { self.items.as_mut_slice()[0..self.top] .iter_mut() diff --git a/src/vm/test.rs b/src/vm/test.rs index cbcd51c..5913ee2 100644 --- a/src/vm/test.rs +++ b/src/vm/test.rs @@ -204,7 +204,6 @@ fn test_fib() { } #[bench] -#[ignore] fn bench_fib(b: &mut Bencher) { b.iter(|| { black_box(test_expr(