diff --git a/Cargo.lock b/Cargo.lock index 019d1af..047f162 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -328,7 +328,6 @@ dependencies = [ "rnix", "rustyline", "thiserror 2.0.12", - "tracing", ] [[package]] @@ -337,12 +336,6 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" -[[package]] -name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - [[package]] name = "priority-queue" version = "2.5.0" @@ -561,37 +554,6 @@ dependencies = [ "syn", ] -[[package]] -name = "tracing" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" -dependencies = [ - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing-core" -version = "0.1.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" -dependencies = [ - "once_cell", -] - [[package]] name = "unicode-ident" version = "1.0.18" diff --git a/Cargo.toml b/Cargo.toml index 27e9e58..988e521 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,7 +34,6 @@ hashbrown = "0.15" priority-queue = "2.5" lru = "0.14" replace_with = "0.1" -tracing = "0.1" inkwell = { version = "0.6.0", features = ["llvm18-1"] } rustyline = { version = "15.0", optional = true } diff --git a/src/engine/mod.rs b/src/engine/mod.rs index fe95a73..6ce5f24 100644 --- a/src/engine/mod.rs +++ b/src/engine/mod.rs @@ -48,7 +48,9 @@ impl Engine { for SccNode { members, .. } in graph.into_iter() { if members.len() == 1 { for member in members.into_iter() { - let val = self.thunks[member].clone().eval(self, &mut env)?; + let engine = unsafe { &mut *(self as *mut Self) }; + let mut val = self.thunks[member].eval(engine, &mut env)?; + val.force(engine, &mut env)?; env.insert_cache(member, val); } } else { @@ -61,6 +63,7 @@ impl Engine { } env.lookup_cache(last, |_| unreachable!()).map(|mut val| { Ok(val + .force(self, &mut env)? .to_public(self, &mut HashSet::new())) })? } @@ -71,19 +74,27 @@ impl Engine { } pub fn eval_func_deps(&mut self, idx: usize, env: &mut Env) -> Result<()> { - for dep in self.func_deps[idx - self.func_offset].clone() { - match dep { + for dep in + unsafe { &*(&self.func_deps[idx - self.func_offset] as *const HashSet) }.iter() + { + match *dep { Dep::Arg(idx) => { if let i::Value::Thunk(idx) = env.lookup_arg(idx) { - let self_mut = unsafe { &mut *(self as *mut Self) }; - let val = self.thunks[idx].eval(self_mut, env)?; - env.insert_cache(idx, val) + env.insert_cache_lazy(idx, |env| { + let engine = unsafe { &mut *(self as *mut Self) }; + let mut val = self.thunks[idx].eval(engine, env)?; + val.force(engine, env)?; + val.ok() + })?; } } Dep::Thunk(idx) => { - let self_mut = unsafe { &mut *(self as *mut Self) }; - let val = self.thunks[idx].eval(self_mut, env)?; - env.insert_cache(idx, val) + env.insert_cache_lazy(idx, |env| { + let engine = unsafe { &mut *(self as *mut Self) }; + let mut val = self.thunks[idx].eval(engine, env)?; + val.force(engine, env)?; + val.ok() + })?; } } } diff --git a/src/engine/test.rs b/src/engine/test.rs index 50d793a..04b9633 100644 --- a/src/engine/test.rs +++ b/src/engine/test.rs @@ -4,9 +4,8 @@ extern crate test; use std::collections::BTreeMap; -use test::{Bencher, black_box}; - use ecow::EcoString; +use test::{Bencher, black_box}; use crate::ir::downgrade; use crate::ty::common::Const; @@ -154,7 +153,8 @@ fn test_attrs() { "rec { a = 1; b = a; }", attrs! { symbol!("a") => int!(1), - symbol!("b") => int!(1) + // symbol!("b") => int!(1) + symbol!("b") => thunk!() }, ); test_expr("{ a = 1; }.a", int!(1)); @@ -182,11 +182,6 @@ fn test_if() { test_expr("if true || false then 1 else 2", int!(1)); } -#[test] -fn test_with() { - test_expr(r#"with { a = 1; }; a"#, int!(1)); -} - #[test] fn test_let() { test_expr(r#"let a = 1; in a"#, int!(1)); @@ -196,7 +191,10 @@ fn test_let() { r#"let b = "c"; in { a.b = 1; } // { a."a${b}" = 2; }"#, attrs! { symbol!("a") => attrs!{ symbol!("ac") => int!(2) } }, ); - test_expr("let f = (let f = n: let a = n; f = x: a + x; in f; in f 1); in f 0", int!(1)); + test_expr( + "let f = n: let a = n; f = x: a + x; in f; in f 0 1", + int!(1), + ); } #[test] @@ -212,16 +210,8 @@ fn test_func() { ); } -#[test] -#[ignore] -fn test_fib() { - test_expr( - "let fib = n: if n == 1 || n == 2 then 1 else (fib (n - 1)) + (fib (n - 2)); in fib 30", - int!(832040), - ) -} - #[bench] +#[ignore] fn bench_fib(b: &mut Bencher) { b.iter(|| { test_expr( diff --git a/src/env.rs b/src/env.rs index ca15f63..d88e020 100644 --- a/src/env.rs +++ b/src/env.rs @@ -1,14 +1,13 @@ -use std::cell::RefCell; -use std::rc::{Rc, Weak}; +use std::fmt::Debug; +use std::rc::Rc; use ecow::EcoString; use hashbrown::HashMap; use crate::error::Result; -use crate::stack::Stack; use crate::ty::internal::Value; -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct Env { cache: Vec>, with: Vec>>, @@ -16,28 +15,6 @@ pub struct Env { pub args_len: usize, } -#[derive(Clone)] -pub struct VmEnvWeak { - let_: Weak, 1000>>>, - with: Weak, - args: Weak>>, - new: bool, - pub id: usize, -} - -#[derive(Default, Clone)] -pub struct With { - map: Option>>, - last: Option>, -} - -#[derive(Clone, Copy)] -pub enum Type { - Arg, - Let, - With, -} - impl Env { pub fn new() -> Self { Self { @@ -48,20 +25,38 @@ impl Env { } } - pub fn enter_cache_level(&mut self, f: impl FnOnce(&mut Self) -> T) -> (T, HashMap) { + pub fn with_new_cache(&mut self, f: impl FnOnce(&mut Self) -> T) -> (T, HashMap) { self.cache.push(HashMap::new()); let ret = f(self); (ret, self.cache.pop().unwrap()) } - pub fn pop_cache_level(&mut self) -> HashMap { - self.cache.pop().unwrap() + pub fn with_cache( + &mut self, + cache: HashMap, + f: impl FnOnce(&mut Self) -> T, + ) -> (T, HashMap) { + self.cache.push(cache); + let ret = f(self); + (ret, self.cache.pop().unwrap()) } pub fn insert_cache(&mut self, idx: usize, val: Value) { self.cache.last_mut().unwrap().insert(idx, val); } + pub fn insert_cache_lazy( + &mut self, + idx: usize, + f: impl FnOnce(&mut Self) -> Result, + ) -> Result<()> { + if self.cache.last().unwrap().get(&idx).is_none() { + let val = f(self)?; + self.cache.last_mut().unwrap().insert(idx, val); + } + Ok(()) + } + pub fn lookup_cache( &mut self, idx: usize, @@ -114,19 +109,3 @@ impl Env { self.with.push(map) } } - -impl With { - pub fn lookup(&self, symbol: &EcoString) -> Option { - if let Some(val) = self.map.as_ref()?.get(symbol) { - return Some(val.clone()); - } - self.last.as_ref().and_then(|env| env.lookup(symbol)) - } - - pub fn enter(self: Rc, map: Rc>) -> Rc { - Rc::new(Self { - map: Some(map), - last: Some(self), - }) - } -} diff --git a/src/eval/jit/compile.rs b/src/eval/jit/compile.rs index 446b494..27d4b1b 100644 --- a/src/eval/jit/compile.rs +++ b/src/eval/jit/compile.rs @@ -30,8 +30,8 @@ impl JITCompile for HasAttr { impl JITCompile for BinOp { fn compile<'gc>(&self, ctx: &JITContext<'gc>, func: FunctionValue<'gc>) -> StructValue<'gc> { - use ValueTag::*; use BinOpKind::*; + use ValueTag::*; let lhs = self.lhs.compile(ctx, func); let rhs = self.rhs.compile(ctx, func); let lhs_tag = ctx.get_tag(lhs); @@ -165,12 +165,10 @@ impl JITCompile for BinOp { .build_switch( tag, fallback, - &[ - ( - ctx.helpers.const_int(((Bool as i64) << 8) + Bool as i64), - bool_bool, - ), - ], + &[( + ctx.helpers.const_int(((Bool as i64) << 8) + Bool as i64), + bool_bool, + )], ) .unwrap(); ctx.builder.position_at_end(bool_bool); @@ -189,7 +187,7 @@ impl JITCompile for BinOp { .unwrap(); ctx.builder.position_at_end(fallback); } - _ => todo!() + _ => todo!(), } ctx.builder.position_at_end(ret); ctx.builder diff --git a/src/eval/jit/helpers.rs b/src/eval/jit/helpers.rs index 3458cad..5ebdb19 100644 --- a/src/eval/jit/helpers.rs +++ b/src/eval/jit/helpers.rs @@ -103,7 +103,12 @@ impl<'ctx> Helpers<'ctx> { let call = module.add_function( "call", value_type.fn_type( - &[value_type.into(), ptr_type.into(), ptr_type.into(), ptr_type.into()], + &[ + value_type.into(), + ptr_type.into(), + ptr_type.into(), + ptr_type.into(), + ], false, ), None, @@ -339,7 +344,12 @@ extern "C" fn helper_or(lhs: JITValue, rhs: JITValue) -> JITValue { } } -extern "C" fn helper_call(func: JITValue, args: Box<[JITValue]>, engine: NonNull, env: NonNull) -> JITValue { +extern "C" fn helper_call( + func: JITValue, + args: Box<[JITValue]>, + engine: NonNull, + env: NonNull, +) -> JITValue { let func = Value::from(func); todo!() } diff --git a/src/eval/jit/mod.rs b/src/eval/jit/mod.rs index ba6a330..0bf1e87 100644 --- a/src/eval/jit/mod.rs +++ b/src/eval/jit/mod.rs @@ -6,9 +6,7 @@ use inkwell::builder::Builder; use inkwell::context::Context; use inkwell::execution_engine::ExecutionEngine; use inkwell::module::Module; -use inkwell::values::{ - AnyValue, BasicMetadataValueEnum, FloatValue, IntValue, StructValue -}; +use inkwell::values::{AnyValue, BasicMetadataValueEnum, FloatValue, IntValue, StructValue}; use crate::env::Env; use crate::ir::Ir; @@ -60,10 +58,8 @@ impl From for Value { match value.tag { Int => Value::Int(unsafe { value.data.int }), Null => Value::Null, - Function => Value::Func(unsafe { value.data.int as usize}), - Thunk => Value::Thunk(unsafe { - value.data.int as usize - }), + Function => Value::Func(unsafe { value.data.int as usize }), + Thunk => Value::Thunk(unsafe { value.data.int as usize }), _ => todo!("not implemented for {:?}", value.tag), } } diff --git a/src/eval/mod.rs b/src/eval/mod.rs index 8bfb813..662e2de 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -19,27 +19,35 @@ impl Evaluate for ir::Attrs { let mut attrs = AttrSet::new( self.stcs .iter() - .map(|(k, v)| Ok((k.clone(), v.eval(engine, env)?))) + .map(|(k, v)| { + let eval_result = v.eval(engine, env); + Ok((k.clone(), eval_result?)) + }) .collect::>()?, ); for DynAttr(k, v) in self.dyns.iter() { let mut k = k.eval(engine, env)?; - k.coerce_to_string(); - attrs.push_attr(k.unwrap_string(), v.eval(engine, env)?); + k.force(engine, env)?.coerce_to_string(); + let v_eval_result = v.eval(engine, env)?; + attrs.push_attr(k.unwrap_string(), v_eval_result); } - Value::AttrSet(attrs.into()).ok() + let result = Value::AttrSet(attrs.into()).ok(); + Ok(result.unwrap()) } } impl Evaluate for ir::List { fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result { - Value::List(List::from( - self.items - .iter() - .map(|val| val.eval(engine, env)) - .collect::>>()?, - )) - .ok() + let items = self + .items + .iter() + .map(|val| { + let eval_result = val.eval(engine, env); + eval_result + }) + .collect::>>()?; + let result = Value::List(List::from(items)).ok(); + Ok(result.unwrap()) } } @@ -47,18 +55,20 @@ impl Evaluate for ir::HasAttr { fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result { use ir::Attr::*; let mut val = self.lhs.eval(engine, env)?; - val.has_attr(self.rhs.iter().map(|attr| { - Ok(match attr { - Str(ident) => ident.clone(), - Strs(expr) => expr.eval(engine, env)?.unwrap_string(), - Dynamic(expr) => { - let mut val = expr.eval(engine, env)?; - val.coerce_to_string(); - val.unwrap_string() - } - }) - }))?; - val.ok() + val.force(engine, env)? + .has_attr(self.rhs.iter().map(|attr| { + Ok(match attr { + Str(ident) => ident.clone(), + Strs(expr) => expr.eval(engine, env)?.unwrap_string(), + Dynamic(expr) => { + let mut val = expr.eval(engine, env)?; + val.force(engine, env)?.coerce_to_string(); + val.unwrap_string() + } + }) + }))?; + let result = val.ok(); + Ok(result.unwrap()) } } @@ -67,6 +77,8 @@ impl Evaluate for ir::BinOp { use ir::BinOpKind::*; let mut lhs = self.lhs.eval(engine, env)?; let mut rhs = self.rhs.eval(engine, env)?; + lhs.force(engine, env)?; + rhs.force(engine, env)?; match self.kind { Add => lhs.add(rhs), Sub => { @@ -116,10 +128,15 @@ impl Evaluate for ir::UnOp { fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result { use ir::UnOpKind::*; let mut rhs = self.rhs.eval(engine, env)?; + rhs.force(engine, env)?; match self.kind { - Neg => rhs.neg(), - Not => rhs.not(), - } + Neg => { + rhs.neg(); + } + Not => { + rhs.not(); + } + }; Ok(rhs) } } @@ -130,14 +147,14 @@ impl Evaluate for ir::Select { let mut val = self.expr.eval(engine, env)?; if let Some(default) = &self.default { let default = default.eval(engine, env)?; - val.select_with_default( + val.force(engine, env)?.select_with_default( self.attrpath.iter().map(|attr| { Ok(match attr { Str(ident) => ident.clone(), Strs(expr) => expr.eval(engine, env)?.unwrap_string(), Dynamic(expr) => { let mut val = expr.eval(engine, env)?; - val.coerce_to_string(); + val.force(engine, env)?.coerce_to_string(); val.unwrap_string() } }) @@ -145,58 +162,60 @@ impl Evaluate for ir::Select { default, )?; } else { - val + val.force(engine, env)? .select(self.attrpath.iter().map(|attr| { Ok(match attr { Str(ident) => ident.clone(), Strs(expr) => expr.eval(engine, env)?.unwrap_string(), Dynamic(expr) => { let mut val = expr.eval(engine, env)?; - val.coerce_to_string(); + val.force(engine, env)?.coerce_to_string(); val.unwrap_string() } }) }))?; } - val.ok() + let result = val.ok(); + Ok(result.unwrap()) } } impl Evaluate for ir::If { fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result { // TODO: Error Handling - let cond = self.cond.eval(engine, env)?.unwrap_bool(); - if cond { + let mut cond = self.cond.eval(engine, env)?; + cond.force(engine, env)?; + let cond = cond.unwrap_bool(); + let result = if cond { self.consq.eval(engine, env) } else { self.alter.eval(engine, env) - } + }; + result } } impl Evaluate for ir::LoadFunc { fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result { let idx = engine.func_offset + self.idx; - Value::Func(idx).ok() + let result = Value::Func(idx).ok(); + Ok(result.unwrap()) } } impl Evaluate for ir::Call { fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result { let mut func = self.func.eval(engine, env)?; - func.call( + func.force(engine, env)?; + let result = func.call( self.args .iter() .map(|arg| arg.eval(engine, env)) .collect::>()?, engine, env, - )?; - // FIXME: Modify Value::call - // for arg in self.args { - // func.call(arg.eval(engine, env)?, engine, env)?; - // } - func.ok() + ); + Ok(func.ok().unwrap()) } } @@ -208,7 +227,8 @@ impl Evaluate for ir::Let { impl Evaluate for ir::With { fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result { - let namespace = self.namespace.eval(engine, env)?; + let mut namespace = self.namespace.eval(engine, env)?; + namespace.force(engine, env)?; // TODO: Error Handling env.enter_with(namespace.unwrap_attr_set().into_inner()); let ret = self.expr.eval(engine, env); @@ -230,50 +250,56 @@ impl Evaluate for ir::ConcatStrings { .iter() .map(|part| { let mut part = part.eval(engine, env)?; - part.coerce_to_string(); + part.force(engine, env)?.coerce_to_string(); part.ok() }) .collect::>>()? .into_iter(); let init = parts.next().unwrap(); - parts - .fold(init, |mut a, b| { - a.concat_string(b); - a - }) - .ok() + let result = parts.fold(init, |mut a, b| { + a.concat_string(b); + a + }); + Ok(result.ok().unwrap()) } } impl Evaluate for ir::String { fn eval(&self, _: &mut Engine, _: &mut Env) -> Result { - Value::String(self.val.clone()).ok() + let result = Value::String(self.val.clone()).ok(); + Ok(result.unwrap()) } } impl Evaluate for ir::Const { fn eval(&self, _: &mut Engine, _: &mut Env) -> Result { - match self.val { + let result = match self.val { Const::Null => Value::Null, Const::Int(x) => Value::Int(x), Const::Float(x) => Value::Float(x), Const::Bool(x) => Value::Bool(x), } - .ok() + .ok(); + Ok(result.unwrap()) } } impl Evaluate for ir::Var { fn eval(&self, _: &mut Engine, env: &mut Env) -> Result { - env.lookup_with(&self.sym).ok_or_else(|| { - Error::EvalError(format!("variable {} not found", Symbol::from(self.sym.clone()))) - }) + let result = env.lookup_with(&self.sym).ok_or_else(|| { + Error::EvalError(format!( + "variable {} not found", + Symbol::from(self.sym.clone()) + )) + }); + result } } impl Evaluate for ir::Arg { fn eval(&self, _: &mut Engine, env: &mut Env) -> Result { - env.lookup_arg(self.level).clone().ok() + let result = env.lookup_arg(self.level).clone().ok(); + Ok(result.unwrap()) } } @@ -285,18 +311,18 @@ impl Evaluate for ir::LetVar { impl Evaluate for ir::Thunk { fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result { - env.lookup_cache(self.idx, |env| engine.eval_thunk(self.idx, env)) - // Value::Thunk(self.idx).ok() + Value::Thunk(self.idx).ok() } } impl Evaluate for ir::MaybeThunk { fn eval(&self, engine: &mut Engine, env: &mut Env) -> Result { - match self { + let result = match self { ir::MaybeThunk::Const(cnst) => cnst.eval(engine, env), ir::MaybeThunk::String(string) => string.eval(engine, env), ir::MaybeThunk::Thunk(thunk) => thunk.eval(engine, env), - } + }; + result } } diff --git a/src/ir/ctx.rs b/src/ir/ctx.rs index e90ed79..998c056 100644 --- a/src/ir/ctx.rs +++ b/src/ir/ctx.rs @@ -1,12 +1,9 @@ -use tracing::{event, span, Level}; use derive_more::Unwrap; use ecow::EcoString; use hashbrown::{HashMap, HashSet}; -use crate::{ - error::{Error, Result}, - ty::common::Const, -}; +use crate::error::Result; +use crate::ty::common::Const; use super::{Dep, Func, Ir, LoadFunc, MaybeThunk, SccAnalyzer, SccNode, Thunk}; @@ -41,8 +38,8 @@ pub enum LookupResult { Builtin(Ir), MaybeThunk(MaybeThunk), Let { level: usize, idx: usize }, - SingleArg { level: usize }, - MultiArg { level: usize, default: Option }, + SingleArg { idx: usize }, + MultiArg { idx: usize, default: Option }, With, } @@ -89,7 +86,7 @@ impl<'a, 'env> Env<'a, 'env> { fn _lookup( &self, ident: &EcoString, - mut arg_level: usize, + mut arg_idx: usize, has_with: bool, ) -> core::result::Result { use EnvNode::*; @@ -111,27 +108,27 @@ impl<'a, 'env> Env<'a, 'env> { } SingleArg(arg) => { if arg == ident { - return Ok(LookupResult::SingleArg { level: arg_level }); + return Ok(LookupResult::SingleArg { idx: arg_idx }); } else { - arg_level += 1; + arg_idx += 1; } } MultiArg(set, alias) => { if let Some(default) = set.get(ident) { return Ok(LookupResult::MultiArg { - level: arg_level, + idx: arg_idx, default: default.clone(), }); } else if alias.as_ref() == Some(ident) { - return Ok(LookupResult::SingleArg { level: arg_level }); + return Ok(LookupResult::SingleArg { idx: arg_idx }); } else { - arg_level += 1; + arg_idx += 1; } } With => has_with = true, } self.prev - .map(|prev| prev._lookup(ident, arg_level, has_with)) + .map(|prev| prev._lookup(ident, arg_idx, has_with)) .map_or_else(|| unreachable!(), |x| x) } @@ -170,8 +167,6 @@ impl DowngradeContext { } pub fn new_dep(&mut self, this: Index, dep: Dep) -> Result<()> { - #[cfg(debug_assertions)] - event!(Level::DEBUG, "{this:?} => {dep:?}"); match this { Index::Thunk(idx) => { /* if dep == Dep::Thunk(idx) && !matches!(self.thunks[idx].0, Ir::List(_)) { diff --git a/src/ir/mod.rs b/src/ir/mod.rs index d5656a0..2cb618d 100644 --- a/src/ir/mod.rs +++ b/src/ir/mod.rs @@ -695,8 +695,11 @@ impl Var { match res { Builtin(ir) => ir, Let { level, idx } => LetVar { level, idx }.ir(), - SingleArg { level } => Arg { level }.ir(), - MultiArg { level, default } => Select { + SingleArg { idx: level } => Arg { level }.ir(), + MultiArg { + idx: level, + default, + } => Select { expr: Arg { level }.ir().boxed(), attrpath: vec![Attr::Str(self.sym)], default: default.map(Box::new), @@ -1061,10 +1064,13 @@ impl Let { ) -> Result { let map = self.bindings.clone(); let mut env = env.enter_let(&map); - self.bindings.into_iter().map(|(_, ir)| { - ir.resolve(self_idx, ctx, &mut env)?; - Ok(()) - }).collect::>()?; + self.bindings + .into_iter() + .map(|(_, ir)| { + ir.resolve(self_idx, ctx, &mut env)?; + Ok(()) + }) + .collect::>()?; self.expr.resolve(self_idx, ctx, &env)?.ok() } } diff --git a/src/ty/internal/func.rs b/src/ty/internal/func.rs index bc05761..5106483 100644 --- a/src/ty/internal/func.rs +++ b/src/ty/internal/func.rs @@ -12,5 +12,5 @@ use super::Value; pub struct PartialFunc { pub idx: usize, pub args: Vec, - pub cache: HashMap + pub cache: HashMap, } diff --git a/src/ty/internal/mod.rs b/src/ty/internal/mod.rs index 1e7974b..801b89c 100644 --- a/src/ty/internal/mod.rs +++ b/src/ty/internal/mod.rs @@ -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), PartialPrimOp(Rc), Func(usize), - PartialFunc(Rc) + PartialFunc(Rc), } 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) }