feat: ref

This commit is contained in:
2025-05-11 00:32:44 +08:00
parent 561b9bf36a
commit f52687bc1e
5 changed files with 62 additions and 55 deletions

View File

@@ -17,7 +17,7 @@ pub struct AttrSet {
}
impl AttrSet {
pub fn empty() -> AttrSet {
pub fn empty() -> Self {
AttrSet {
data: HashTrieMapSync::new_sync(),
}

View File

@@ -1,3 +1,5 @@
use std::cell::OnceCell;
use ecow::EcoString;
use itertools::Itertools;
use rpds::HashTrieMap;
@@ -40,19 +42,19 @@ impl From<ir::Param> for Param {
#[derive(Debug, Clone)]
pub struct Func {
pub env: Option<CapturedEnv>,
pub env: OnceCell<CapturedEnv>,
pub param: Param,
pub opcodes: OpCodes,
}
impl Func {
pub fn call(self, vm: &VM, arg: Value) -> Result<Value> {
pub fn call(&self, vm: &VM, arg: Value) -> Result<Value> {
use Param::*;
let env = self.env.unwrap().released();
let env = self.env.get().unwrap().clone().released();
match self.param {
Ident(ident) => env.enter(HashTrieMap::new_sync().insert(ident.into(), arg)),
match &self.param {
Ident(ident) => env.enter(HashTrieMap::new_sync().insert(ident.clone().into(), arg)),
Formals {
formals,
ellipsis,
@@ -73,18 +75,18 @@ impl Func {
for (formal, default) in formals {
let arg = arg
.select(formal.clone().into())
.or_else(|| default.map(|idx| Value::Thunk(vm.get_thunk(idx))))
.or_else(|| default.map(Value::ThunkRef))
.unwrap();
new.insert_mut(formal.into(), arg);
new.insert_mut(formal.clone().into(), arg);
}
if let Some(alias) = alias {
new.insert_mut(alias.into(), Value::AttrSet(arg));
new.insert_mut(alias.clone().into(), Value::AttrSet(arg));
}
env.enter(new);
}
}
vm.eval(self.opcodes, env)
vm.eval(self.opcodes.clone(), env)
}
}

View File

@@ -101,48 +101,52 @@ impl PartialEq for Thunk {
pub enum Value {
Const(Const),
Thunk(Thunk),
ThunkRef(usize),
AttrSet(AttrSet),
RecAttrSet(RecAttrSet),
List(List),
Catchable(c::Catchable),
PrimOp(PrimOp),
PartialPrimOp(PartialPrimOp),
Func(Func),
Func(usize),
}
#[derive(Debug, IsVariant, Unwrap, Clone, PartialEq)]
pub enum ValueAsRef<'a> {
Const(&'a Const),
Thunk(&'a Thunk),
AttrSet(&'a AttrSet),
RecAttrSet(&'a RecAttrSet),
List(&'a List),
Catchable(&'a c::Catchable),
PrimOp(&'a PrimOp),
PartialPrimOp(&'a PartialPrimOp),
Func(&'a Func),
pub enum ValueAsRef<'v> {
Const(&'v Const),
Thunk(&'v Thunk),
ThunkRef(&'v usize),
AttrSet(&'v AttrSet),
RecAttrSet(&'v RecAttrSet),
List(&'v List),
Catchable(&'v c::Catchable),
PrimOp(&'v PrimOp),
PartialPrimOp(&'v PartialPrimOp),
Func(&'v usize),
}
#[derive(Debug, IsVariant, Unwrap, PartialEq)]
pub enum ValueAsMut<'a> {
Const(&'a mut Const),
Thunk(&'a mut Thunk),
AttrSet(&'a mut AttrSet),
RecAttrSet(&'a mut RecAttrSet),
List(&'a mut List),
Catchable(&'a mut c::Catchable),
PrimOp(&'a mut PrimOp),
PartialPrimOp(&'a mut PartialPrimOp),
Func(&'a mut Func),
pub enum ValueAsMut<'v> {
Const(&'v mut Const),
Thunk(&'v Thunk),
ThunkRef(&'v usize),
AttrSet(&'v mut AttrSet),
RecAttrSet(&'v mut RecAttrSet),
List(&'v mut List),
Catchable(&'v mut c::Catchable),
PrimOp(&'v mut PrimOp),
PartialPrimOp(&'v mut PartialPrimOp),
Func(&'v usize),
}
impl Value {
pub fn as_ref(&self) -> ValueAsRef<'_> {
pub fn as_ref(&self) -> ValueAsRef {
use Value::*;
use ValueAsRef as R;
match self {
Const(x) => R::Const(x),
Thunk(x) => R::Thunk(x),
ThunkRef(x) => R::ThunkRef(x),
AttrSet(x) => R::AttrSet(x),
RecAttrSet(x) => R::RecAttrSet(x),
List(x) => R::List(x),
@@ -153,12 +157,13 @@ impl Value {
}
}
pub fn as_mut(&mut self) -> ValueAsMut<'_> {
pub fn as_mut(&mut self) -> ValueAsMut {
use Value::*;
use ValueAsMut as M;
match self {
Const(x) => M::Const(x),
Thunk(x) => M::Thunk(x),
ThunkRef(x) => M::ThunkRef(x),
AttrSet(x) => M::AttrSet(x),
RecAttrSet(x) => M::RecAttrSet(x),
List(x) => M::List(x),
@@ -177,6 +182,7 @@ impl Value {
match self {
Const(_) => todo!(),
Thunk(_) => "thunk",
ThunkRef(_) => "thunk",
AttrSet(_) => "set",
RecAttrSet(_) => "set",
List(_) => "list",
@@ -210,7 +216,7 @@ impl Value {
PartialPrimOp(func) => {
return Ok(func.call(vm, [arg].into_iter().chain(iter).collect()));
}
Func(func) => func.call(vm, arg)?,
Func(func) => vm.get_func(func).call(vm, arg)?,
_ => todo!(),
}
}
@@ -361,22 +367,19 @@ impl Value {
}
pub fn select(&mut self, sym: Symbol) -> &mut Self {
if let Value::AttrSet(attrs) = self {
let val = attrs.select(sym.clone()).unwrap_or_else(|| {
let val = match self {
Value::AttrSet(attrs) => attrs.select(sym.clone()).unwrap_or_else(|| {
Value::Catchable(c::Catchable::new(Some(format!("{sym:?} not found"))))
});
*self = val;
} else if let Value::RecAttrSet(attrs) = self {
let val = attrs.select(sym.clone()).unwrap_or_else(|| {
}),
Value::RecAttrSet(attrs) => attrs.select(sym.clone()).unwrap_or_else(|| {
Value::Catchable(c::Catchable::new(Some(format!("{sym:?} not found"))))
});
*self = val;
} else {
*self = Value::Catchable(Catchable::new(Some(format!(
}),
_ => Value::Catchable(Catchable::new(Some(format!(
"cannot select from {:?}",
self.typename()
))))
}
)))),
};
*self = val;
self
}
@@ -426,7 +429,7 @@ impl Value {
match self {
Value::Thunk(thunk) => {
let mut value = thunk.force(vm)?;
value.force_deep(vm)?;
let _ = value.force_deep(vm)?;
*self = value;
}
Value::List(list) => list.force_deep(vm)?,
@@ -447,6 +450,7 @@ impl ToPublic for Value {
Value::Catchable(catchable) => p::Value::Catchable(catchable),
Value::Const(cnst) => p::Value::Const(cnst.into()),
Value::Thunk(_) => p::Value::Thunk,
Value::ThunkRef(_) => p::Value::Thunk,
Value::PrimOp(primop) => p::Value::PrimOp(primop.name),
Value::PartialPrimOp(primop) => p::Value::PartialPrimOp(primop.name),
Value::Func(_) => p::Value::Func,