feat: at least it compiles, right?
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
use std::ops::Deref;
|
||||
use std::rc::Rc;
|
||||
|
||||
use ecow::EcoString;
|
||||
use derive_more::Constructor;
|
||||
use ecow::EcoString;
|
||||
use hashbrown::{HashMap, HashSet};
|
||||
use itertools::Itertools;
|
||||
|
||||
@@ -50,30 +50,39 @@ impl AttrSet {
|
||||
self.data.insert(sym, val);
|
||||
}
|
||||
|
||||
pub fn select(&self, mut path: impl DoubleEndedIterator<Item = Result<EcoString>>) -> Result<Value> {
|
||||
// .ok_or_else(|| Error::EvalError())),
|
||||
pub fn select(
|
||||
&self,
|
||||
mut path: impl DoubleEndedIterator<Item = Result<EcoString>>,
|
||||
) -> Result<Value> {
|
||||
// .ok_or_else(|| Error::EvalError())),
|
||||
let mut data = &self.data;
|
||||
let last = path.nth_back(0).unwrap();
|
||||
for item in path {
|
||||
let item = item?;
|
||||
let Some(Value::AttrSet(attrs)) = data.get(&item) else {
|
||||
return Err(Error::EvalError(format!("{} not found", Symbol::from(item))))
|
||||
let Some(Value::AttrSet(attrs)) = data.get(&item) else {
|
||||
return Err(Error::EvalError(format!(
|
||||
"{} not found",
|
||||
Symbol::from(item)
|
||||
)));
|
||||
};
|
||||
data = attrs.as_inner();
|
||||
}
|
||||
let last = last?;
|
||||
data.get(&last).cloned().ok_or_else(|| Error::EvalError(format!("{} not found", Symbol::from(last))))
|
||||
data.get(&last)
|
||||
.cloned()
|
||||
.ok_or_else(|| Error::EvalError(format!("{} not found", Symbol::from(last))))
|
||||
}
|
||||
|
||||
pub fn has_attr(&self, path: impl IntoIterator<Item = Result<EcoString>>) -> Result<bool> {
|
||||
pub fn has_attr(&self, mut path: impl DoubleEndedIterator<Item = Result<EcoString>>) -> Result<bool> {
|
||||
let mut data = &self.data;
|
||||
let last = path.nth_back(0).unwrap();
|
||||
for item in path {
|
||||
let Some(Value::AttrSet(attrs)) = data.get(&item?) else {
|
||||
return Ok(false)
|
||||
let Some(Value::AttrSet(attrs)) = data.get(&item?) else {
|
||||
return Ok(false);
|
||||
};
|
||||
data = attrs.as_inner();
|
||||
}
|
||||
Ok(true)
|
||||
Ok(data.get(&last?).is_some())
|
||||
}
|
||||
|
||||
pub fn update(&mut self, other: &AttrSet) {
|
||||
|
||||
@@ -10,10 +10,7 @@ pub struct Func<'gc> {
|
||||
|
||||
impl<'gc> Func<'gc> {
|
||||
pub fn new(func: &'gc ir::Func, env: Rc<VmEnv>) -> Self {
|
||||
Self {
|
||||
func,
|
||||
env,
|
||||
}
|
||||
Self { func, env }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,9 +4,9 @@ use std::rc::Weak;
|
||||
use ecow::EcoVec;
|
||||
use hashbrown::HashSet;
|
||||
|
||||
use crate::engine::Engine;
|
||||
use crate::env::VmEnv;
|
||||
use crate::ty::public as p;
|
||||
use crate::engine::Engine;
|
||||
|
||||
use super::Value;
|
||||
|
||||
@@ -36,7 +36,9 @@ impl Deref for List {
|
||||
|
||||
impl List {
|
||||
pub fn new() -> Self {
|
||||
List { data: EcoVec::new() }
|
||||
List {
|
||||
data: EcoVec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_capacity(cap: usize) -> Self {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use std::cell::RefCell;
|
||||
use std::hash::Hash;
|
||||
use std::rc::{Rc, Weak};
|
||||
use std::sync::RwLock;
|
||||
use std::rc::Rc;
|
||||
|
||||
use derive_more::{IsVariant, Unwrap};
|
||||
use ecow::EcoString;
|
||||
@@ -9,11 +8,11 @@ use hashbrown::HashSet;
|
||||
use replace_with::replace_with_or_abort;
|
||||
|
||||
use super::common::*;
|
||||
use super::public::{self as p, Symbol};
|
||||
use super::public as p;
|
||||
|
||||
use crate::env::VmEnv;
|
||||
use crate::error::*;
|
||||
use crate::engine::Engine;
|
||||
use crate::env::{VmEnv, VmEnvWeak};
|
||||
use crate::error::*;
|
||||
|
||||
mod attrset;
|
||||
mod func;
|
||||
@@ -27,30 +26,14 @@ pub use primop::*;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum EnvRef {
|
||||
Strong(Rc<VmEnv>),
|
||||
Weak(Weak<VmEnv>)
|
||||
Strong(VmEnv),
|
||||
Weak(VmEnvWeak),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ThunkRef {
|
||||
pub idx: usize,
|
||||
pub env: Option<EnvRef>
|
||||
}
|
||||
|
||||
pub enum Thunk {
|
||||
Expr(ThunkRef),
|
||||
Suspended,
|
||||
Value(Value)
|
||||
}
|
||||
|
||||
impl Thunk {
|
||||
pub fn new(idx: usize) -> Self {
|
||||
Thunk::Expr(ThunkRef::new(idx))
|
||||
}
|
||||
|
||||
pub fn force(&mut self, engine: &Engine) -> Result<Value> {
|
||||
todo!()
|
||||
}
|
||||
pub env: Option<EnvRef>,
|
||||
}
|
||||
|
||||
impl ThunkRef {
|
||||
@@ -61,12 +44,19 @@ impl ThunkRef {
|
||||
pub fn capture(&mut self, env: EnvRef) {
|
||||
let _ = self.env.insert(env);
|
||||
}
|
||||
|
||||
pub fn upgrade(&mut self) {
|
||||
replace_with_or_abort(&mut self.env, |env| {
|
||||
env.map(|env| EnvRef::Strong(env.upgraded()))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl EnvRef {
|
||||
pub fn upgrade(&mut self) {
|
||||
if let EnvRef::Weak(weak) = &*self {
|
||||
*self = EnvRef::Strong(weak.upgrade().unwrap())
|
||||
pub fn upgraded(self) -> VmEnv {
|
||||
match self {
|
||||
EnvRef::Weak(weak) => weak.upgrade(),
|
||||
EnvRef::Strong(strong) => strong,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -78,13 +68,13 @@ pub enum Value {
|
||||
Bool(bool),
|
||||
String(EcoString),
|
||||
Null,
|
||||
Thunk(Rc<RwLock<Thunk>>),
|
||||
Thunk(ThunkRef),
|
||||
AttrSet(Rc<AttrSet>),
|
||||
List(List),
|
||||
Catchable(EcoString),
|
||||
PrimOp(Rc<PrimOp>),
|
||||
PartialPrimOp(Rc<PartialPrimOp>),
|
||||
Func(Rc<RwLock<ThunkRef>>),
|
||||
Func(ThunkRef),
|
||||
}
|
||||
|
||||
impl Hash for Value {
|
||||
@@ -137,13 +127,13 @@ pub enum ValueAsRef<'v> {
|
||||
Bool(bool),
|
||||
String(&'v EcoString),
|
||||
Null,
|
||||
Thunk(&'v RwLock<Thunk>),
|
||||
Thunk(&'v ThunkRef),
|
||||
AttrSet(&'v AttrSet),
|
||||
List(&'v List),
|
||||
Catchable(&'v str),
|
||||
PrimOp(&'v PrimOp),
|
||||
PartialPrimOp(&'v PartialPrimOp),
|
||||
Func(&'v RwLock<ThunkRef>),
|
||||
Func(&'v ThunkRef),
|
||||
}
|
||||
|
||||
impl Value {
|
||||
@@ -197,7 +187,7 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn call(&mut self, arg: Self, engine: &Engine) -> Result<()> {
|
||||
pub fn call(&mut self, arg: Self, engine: &mut Engine) -> Result<()> {
|
||||
use Value::*;
|
||||
if matches!(arg, Value::Catchable(_)) {
|
||||
*self = arg;
|
||||
@@ -206,6 +196,13 @@ impl Value {
|
||||
*self = match self {
|
||||
PrimOp(func) => func.call(arg, engine),
|
||||
PartialPrimOp(func) => func.call(arg, engine),
|
||||
Func(func) => {
|
||||
let mut env = func.env.take().unwrap().upgraded().clone();
|
||||
env.enter_arg(arg);
|
||||
let val = engine.eval_thunk(func.idx, &mut env);
|
||||
env.pop_arg();
|
||||
val
|
||||
}
|
||||
Catchable(_) => return Ok(()),
|
||||
_ => todo!(),
|
||||
}?;
|
||||
@@ -389,10 +386,12 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn select(&mut self, path: impl DoubleEndedIterator<Item = Result<EcoString>>) -> Result<&mut Self> {
|
||||
pub fn select(
|
||||
&mut self,
|
||||
path: impl DoubleEndedIterator<Item = Result<EcoString>>,
|
||||
) -> Result<&mut Self> {
|
||||
let val = match self {
|
||||
Value::AttrSet(attrs) => attrs
|
||||
.select(path),
|
||||
Value::AttrSet(attrs) => attrs.select(path),
|
||||
Value::Catchable(_) => return Ok(self),
|
||||
_ => Err(Error::EvalError(format!(
|
||||
"cannot select from {:?}",
|
||||
@@ -403,7 +402,11 @@ impl Value {
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn select_with_default(&mut self, path: impl DoubleEndedIterator<Item = Result<EcoString>>, default: Self) -> Result<&mut Self> {
|
||||
pub fn select_with_default(
|
||||
&mut self,
|
||||
path: impl DoubleEndedIterator<Item = Result<EcoString>>,
|
||||
default: Self,
|
||||
) -> Result<&mut Self> {
|
||||
let val = match self {
|
||||
Value::AttrSet(attrs) => attrs.select(path).unwrap_or(default),
|
||||
Value::Catchable(_) => return Ok(self),
|
||||
@@ -418,7 +421,7 @@ impl Value {
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn has_attr(&mut self, path: impl IntoIterator<Item = Result<EcoString>>) -> Result<()> {
|
||||
pub fn has_attr(&mut self, path: impl DoubleEndedIterator<Item = Result<EcoString>>) -> Result<()> {
|
||||
if let Value::AttrSet(attrs) = self {
|
||||
let val = Value::Bool(attrs.has_attr(path)?);
|
||||
*self = val;
|
||||
@@ -438,13 +441,16 @@ impl Value {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn force(&mut self, engine: &Engine) -> Result<&mut Self> {
|
||||
if let Value::Thunk(thunk) = &*self {
|
||||
let val = {
|
||||
let mut thunk = thunk.write().unwrap();
|
||||
thunk.force(engine)
|
||||
}?;
|
||||
*self = val;
|
||||
pub fn force(&mut self, engine: &mut Engine) -> Result<&mut Self> {
|
||||
if let Value::Thunk(thunk) = self {
|
||||
unsafe {
|
||||
let old = std::ptr::read(thunk);
|
||||
let mut env = old.env.unwrap().upgraded();
|
||||
std::ptr::write(
|
||||
self,
|
||||
engine.eval_thunk(old.idx, &mut env)?,
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
@@ -477,4 +483,3 @@ impl Value {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ use std::rc::Rc;
|
||||
|
||||
use derive_more::Constructor;
|
||||
|
||||
use crate::error::Result;
|
||||
use crate::engine::Engine;
|
||||
use crate::error::Result;
|
||||
|
||||
use super::Value;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user