fix: PartialFunc

This commit is contained in:
2025-06-22 01:19:16 +08:00
parent 75e8705098
commit 20b5516101
13 changed files with 207 additions and 219 deletions

View File

@@ -12,5 +12,5 @@ use super::Value;
pub struct PartialFunc {
pub idx: usize,
pub args: Vec<Value>,
pub cache: HashMap<usize, Value>
pub cache: HashMap<usize, Value>,
}

View File

@@ -11,7 +11,7 @@ use super::common::*;
use super::public as p;
use crate::engine::Engine;
use crate::env::{Env, VmEnvWeak};
use crate::env::Env;
use crate::error::*;
mod attrset;
@@ -38,7 +38,7 @@ pub enum Value {
PrimOp(Rc<PrimOp>),
PartialPrimOp(Rc<PartialPrimOp>),
Func(usize),
PartialFunc(Rc<PartialFunc>)
PartialFunc(Rc<PartialFunc>),
}
impl Hash for Value {
@@ -166,21 +166,30 @@ impl Value {
PrimOp(func) => func.call(args, engine),
PartialPrimOp(func) => func.call(args, engine),
PartialFunc(func) => {
let self::PartialFunc { idx, args: old_args, cache } = Rc::make_mut(func);
let self::PartialFunc {
idx,
args: old_args,
cache,
} = Rc::make_mut(func);
let idx = *idx;
let len = args.len() + old_args.len();
env.reserve_args(len);
env.enter_args(std::mem::take(old_args));
let mut args = args.into_iter().peekable();
env.enter_arg(args.next().unwrap());
let (ret, cache) = env.enter_cache_level(|env| {
let (ret, cache) = env.with_cache(std::mem::take(cache), |env| {
engine.eval_func_deps(idx, env)?;
let mut ret = engine.eval_thunk(idx, env)?;
while args.peek().is_some() {
match ret {
Value::Func(func) => {
env.enter_arg(args.next().unwrap());
engine.eval_func_deps(idx, env)?;
ret = engine.eval_thunk(func, env)?;
}
Value::PartialFunc(_) => {
todo!()
}
Value::PrimOp(primop) => {
ret = primop.call(args.collect(), engine)?;
break;
@@ -207,15 +216,21 @@ impl Value {
let len = args.len();
let mut args = args.into_iter().peekable();
env.reserve_args(len);
let (ret, cache) = env.enter_cache_level(|env| {
env.enter_arg(args.next().unwrap());
let (ret, cache) = env.with_new_cache(|env| {
engine.eval_func_deps(idx, env)?;
let mut ret = engine.eval_thunk(idx, env)?;
env.enter_arg(args.next().unwrap());
ret.force(engine, env)?;
while args.peek().is_some() {
match ret {
Value::Func(func) => {
env.enter_arg(args.next().unwrap());
engine.eval_func_deps(idx, env)?;
ret = engine.eval_thunk(func, env)?;
}
Value::PartialFunc(mut func) => {
todo!()
}
Value::PrimOp(primop) => {
ret = primop.call(args.collect(), engine)?;
break;
@@ -481,7 +496,8 @@ impl Value {
pub fn force(&mut self, engine: &mut Engine, env: &mut Env) -> Result<&mut Self> {
if let &mut Value::Thunk(idx) = self {
*self = env.lookup_cache(idx, |env| engine.eval_thunk(idx, env))?
// *self = env.lookup_cache(idx, |env| engine.eval_thunk(idx, env))?
*self = env.lookup_cache(idx, |_| unreachable!())?
}
Ok(self)
}