diff --git a/src/ty/internal/attrset.rs b/src/ty/internal/attrset.rs index beacfb6..e491250 100644 --- a/src/ty/internal/attrset.rs +++ b/src/ty/internal/attrset.rs @@ -45,7 +45,18 @@ impl<'vm> AttrSet<'vm> { self.data = self .data .into_iter() - .map(|(k, v)| (k.clone(), match v.clone() { x @ Value::ThunkRef(thunk) => { thunk.capture(env.clone()); x }, x => x })) + .map(|(k, v)| { + ( + k.clone(), + match v.clone() { + x @ Value::ThunkRef(thunk) => { + thunk.capture(env.clone()); + x + } + x => x, + }, + ) + }) .collect(); } @@ -99,7 +110,7 @@ impl ToPublic for AttrSet<'_> { #[derive(Debug, Constructor, Clone, PartialEq)] pub struct RecAttrSet<'vm> { - data: Rc> + data: Rc>, } impl<'vm> RecAttrSet<'vm> { @@ -178,7 +189,8 @@ impl<'vm> RecAttrSet<'vm> { impl ToPublic for RecAttrSet<'_> { fn to_public(self, vm: &VM) -> p::Value { p::Value::AttrSet(p::AttrSet::new( - self.data.map + self.data + .map .borrow() .iter() .map(|(sym, value)| (sym.clone(), value.clone().to_public(vm))) diff --git a/src/ty/internal/mod.rs b/src/ty/internal/mod.rs index 8bb79bf..6046921 100644 --- a/src/ty/internal/mod.rs +++ b/src/ty/internal/mod.rs @@ -25,77 +25,6 @@ pub use func::*; pub use list::List; pub use primop::*; -pub trait ToPublic { - fn to_public(self, vm: &VM) -> p::Value; -} - -#[derive(Debug, Clone)] -pub struct Thunk<'vm> { - pub thunk: RefCell<_Thunk<'vm>>, - pub env: RefCell>>>, -} - -#[derive(Debug, IsVariant, Unwrap, Clone)] -pub enum _Thunk<'vm> { - Code(OpCodes), - SuspendedFrom(*const Thunk<'vm>), - Value(Box>), -} - -impl<'vm> Thunk<'vm> { - pub fn new(opcodes: OpCodes) -> Self { - Thunk { - thunk: RefCell::new(_Thunk::Code(opcodes)), - env: RefCell::new(None), - } - } - - pub fn unwrap_code(&self) -> OpCodes { - self.thunk.borrow().clone().unwrap_code() - } - - pub fn capture(&self, env: Rc>) { - *self.env.borrow_mut() = Some(env); - } - - pub fn force(&self, vm: &VM<'vm>) -> Result> { - match &*self.thunk.borrow() { - _Thunk::Value(value) => return Ok(value.as_ref().clone()), - _Thunk::SuspendedFrom(from) => { - return Err(Error::EvalError(format!( - "thunk {:p} already suspended from {from:p} (infinite recursion encountered)", - self as *const Thunk - ))); - } - _Thunk::Code(_) => (), - } - let opcodes = std::mem::replace( - &mut *self.thunk.borrow_mut(), - _Thunk::SuspendedFrom(self as *const Thunk), - ) - .unwrap_code(); - let value = vm.eval(opcodes, self.env.borrow().clone().unwrap())?; - let _ = std::mem::replace( - &mut *self.thunk.borrow_mut(), - _Thunk::Value(value.clone().into()), - ); - Ok(value) - } - - pub fn value(&'vm self) -> Option> { - match &*self.thunk.borrow() { - _Thunk::Value(value) => Some(value.as_ref().clone()), - _ => None, - } - } -} - -impl PartialEq for Thunk<'_> { - fn eq(&self, _: &Self) -> bool { - false - } -} - #[derive(Debug, IsVariant, Unwrap, Clone, PartialEq)] pub enum Value<'vm> { Const(Const), @@ -484,3 +413,74 @@ impl ToPublic for Value<'_> { } } } + +pub trait ToPublic { + fn to_public(self, vm: &VM) -> p::Value; +} + +#[derive(Debug, Clone)] +pub struct Thunk<'vm> { + pub thunk: RefCell<_Thunk<'vm>>, + pub env: RefCell>>>, +} + +#[derive(Debug, IsVariant, Unwrap, Clone)] +pub enum _Thunk<'vm> { + Code(OpCodes), + SuspendedFrom(*const Thunk<'vm>), + Value(Box>), +} + +impl<'vm> Thunk<'vm> { + pub fn new(opcodes: OpCodes) -> Self { + Thunk { + thunk: RefCell::new(_Thunk::Code(opcodes)), + env: RefCell::new(None), + } + } + + pub fn unwrap_code(&self) -> OpCodes { + self.thunk.borrow().clone().unwrap_code() + } + + pub fn capture(&self, env: Rc>) { + *self.env.borrow_mut() = Some(env); + } + + pub fn force(&self, vm: &VM<'vm>) -> Result> { + match &*self.thunk.borrow() { + _Thunk::Value(value) => return Ok(value.as_ref().clone()), + _Thunk::SuspendedFrom(from) => { + return Err(Error::EvalError(format!( + "thunk {:p} already suspended from {from:p} (infinite recursion encountered)", + self as *const Thunk + ))); + } + _Thunk::Code(_) => (), + } + let opcodes = std::mem::replace( + &mut *self.thunk.borrow_mut(), + _Thunk::SuspendedFrom(self as *const Thunk), + ) + .unwrap_code(); + let value = vm.eval(opcodes, self.env.borrow().clone().unwrap())?; + let _ = std::mem::replace( + &mut *self.thunk.borrow_mut(), + _Thunk::Value(value.clone().into()), + ); + Ok(value) + } + + pub fn value(&'vm self) -> Option> { + match &*self.thunk.borrow() { + _Thunk::Value(value) => Some(value.as_ref().clone()), + _ => None, + } + } +} + +impl PartialEq for Thunk<'_> { + fn eq(&self, _: &Self) -> bool { + false + } +} diff --git a/src/vm/mod.rs b/src/vm/mod.rs index bb0be16..b029b22 100644 --- a/src/vm/mod.rs +++ b/src/vm/mod.rs @@ -86,8 +86,7 @@ impl<'vm> VM<'vm> { opcode: OpCode, stack: &'s mut Stack<'vm, CAP>, env: &Rc>, - ) -> Result - { + ) -> Result { match opcode { OpCode::Illegal => panic!("illegal opcode"), OpCode::Const { value } => stack.push(Value::Const(value))?, @@ -170,8 +169,12 @@ impl<'vm> VM<'vm> { } OpCode::FinalizeRec => { env.enter(stack.tos()?.clone().unwrap_attr_set().into_inner()); - stack.tos_mut()?.as_mut().unwrap_attr_set().capture(env.clone()); - }, + stack + .tos_mut()? + .as_mut() + .unwrap_attr_set() + .capture(env.clone()); + } OpCode::PushStaticAttr { name } => { let val = stack.pop(); stack.tos_mut()?.push_attr(Symbol::new(name.clone()), val);