feat: at least it compiles, right?

This commit is contained in:
2025-06-12 20:12:31 +08:00
parent 7293cb9f75
commit 49255948ff
22 changed files with 383 additions and 251 deletions

View File

@@ -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) {

View File

@@ -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 }
}
}

View File

@@ -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 {

View File

@@ -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 {
}
}
}

View File

@@ -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;