diff --git a/Cargo.lock b/Cargo.lock index 047f162..019d1af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -328,6 +328,7 @@ dependencies = [ "rnix", "rustyline", "thiserror 2.0.12", + "tracing", ] [[package]] @@ -336,6 +337,12 @@ 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" @@ -554,6 +561,37 @@ 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 988e521..27e9e58 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ 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/env.rs b/src/env.rs index 9ed9920..ca15f63 100644 --- a/src/env.rs +++ b/src/env.rs @@ -4,7 +4,7 @@ use std::rc::{Rc, Weak}; use ecow::EcoString; use hashbrown::HashMap; -use crate::error::{Error, Result}; +use crate::error::Result; use crate::stack::Stack; use crate::ty::internal::Value; @@ -48,15 +48,14 @@ impl Env { } } - pub fn enter_cache_level(&mut self, f: impl FnOnce(&mut Self) -> T) -> T { + pub fn enter_cache_level(&mut self, f: impl FnOnce(&mut Self) -> T) -> (T, HashMap) { self.cache.push(HashMap::new()); let ret = f(self); - self.cache.pop(); - ret + (ret, self.cache.pop().unwrap()) } - pub fn pop_cache_level(&mut self) { - self.cache.pop(); + pub fn pop_cache_level(&mut self) -> HashMap { + self.cache.pop().unwrap() } pub fn insert_cache(&mut self, idx: usize, val: Value) { diff --git a/src/ir/ctx.rs b/src/ir/ctx.rs index 3794ba3..e90ed79 100644 --- a/src/ir/ctx.rs +++ b/src/ir/ctx.rs @@ -1,3 +1,4 @@ +use tracing::{event, span, Level}; use derive_more::Unwrap; use ecow::EcoString; use hashbrown::{HashMap, HashSet}; @@ -170,14 +171,14 @@ impl DowngradeContext { pub fn new_dep(&mut self, this: Index, dep: Dep) -> Result<()> { #[cfg(debug_assertions)] - println!("{this:?} => {dep:?}"); + event!(Level::DEBUG, "{this:?} => {dep:?}"); match this { Index::Thunk(idx) => { - if dep == Dep::Thunk(idx) && !matches!(self.thunks[idx].0, Ir::List(_)) { + /* if dep == Dep::Thunk(idx) && !matches!(self.thunks[idx].0, Ir::List(_)) { return Err(Error::DowngradeError( "infinite recursion encountered".into(), )); - } + } */ self.thunk_deps[idx].insert(dep.unwrap_thunk()) } Index::Func(idx) => self.func_deps[idx].insert(dep), diff --git a/src/ty/internal/func.rs b/src/ty/internal/func.rs index 360f8d5..bc05761 100644 --- a/src/ty/internal/func.rs +++ b/src/ty/internal/func.rs @@ -1,21 +1,16 @@ use std::rc::Rc; +use derive_more::Constructor; +use hashbrown::HashMap; + use crate::env::Env; - use crate::ir; -pub struct Func<'gc> { - pub func: &'gc ir::Func, - pub env: Rc, -} -impl<'gc> Func<'gc> { - pub fn new(func: &'gc ir::Func, env: Rc) -> Self { - Self { func, env } - } -} +use super::Value; -impl PartialEq for Func<'_> { - fn eq(&self, _: &Self) -> bool { - false - } +#[derive(Debug, Clone, Constructor)] +pub struct PartialFunc { + pub idx: usize, + pub args: Vec, + pub cache: HashMap } diff --git a/src/ty/internal/mod.rs b/src/ty/internal/mod.rs index 3351830..1e7974b 100644 --- a/src/ty/internal/mod.rs +++ b/src/ty/internal/mod.rs @@ -3,6 +3,7 @@ use std::rc::Rc; use derive_more::{IsVariant, Unwrap}; use ecow::EcoString; +use func::PartialFunc; use hashbrown::HashSet; use replace_with::replace_with_or_abort; @@ -37,7 +38,7 @@ pub enum Value { PrimOp(Rc), PartialPrimOp(Rc), Func(usize), - PartialFunc(usize, Vec), + PartialFunc(Rc) } impl Hash for Value { @@ -97,7 +98,7 @@ pub enum ValueAsRef<'v> { PrimOp(&'v PrimOp), PartialPrimOp(&'v PartialPrimOp), Func(usize), - PartialFunc(usize, &'v Vec), + PartialFunc(&'v PartialFunc), } impl Value { @@ -117,7 +118,7 @@ impl Value { PrimOp(x) => R::PrimOp(x), PartialPrimOp(x) => R::PartialPrimOp(x), Func(x) => R::Func(*x), - PartialFunc(x, args) => R::PartialFunc(*x, args), + PartialFunc(x) => R::PartialFunc(x), } } } @@ -164,14 +165,15 @@ impl Value { *self = match self { PrimOp(func) => func.call(args, engine), PartialPrimOp(func) => func.call(args, engine), - PartialFunc(idx, old) => { + PartialFunc(func) => { + let self::PartialFunc { idx, args: old_args, cache } = Rc::make_mut(func); let idx = *idx; - let len = args.len() + old.len(); + let len = args.len() + old_args.len(); env.reserve_args(len); - env.enter_args(std::mem::take(old)); - env.enter_cache_level(|env| { - let mut args = args.into_iter().peekable(); - env.enter_arg(args.next().unwrap()); + 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 mut ret = engine.eval_thunk(idx, env)?; while args.peek().is_some() { match ret { @@ -190,22 +192,24 @@ impl Value { _ => todo!(), } } - let args = env.pop_args(len); - if let Value::Func(idx) = ret { - ret = Value::PartialFunc(idx, args) - } else if let Value::PartialFunc(_, old) = &mut ret { - old.extend(args); - } ret.ok() - }) + }); + let mut ret = ret?; + let args = env.pop_args(len); + if let Value::Func(idx) = ret { + ret = PartialFunc(self::PartialFunc::new(idx, args, cache).into()); + } else if let Value::PartialFunc(func) = &mut ret { + Rc::make_mut(func).args.extend(args); + } + ret.ok() } &mut Func(idx) => { let len = args.len(); let mut args = args.into_iter().peekable(); env.reserve_args(len); - env.enter_cache_level(|env| { - env.enter_arg(args.next().unwrap()); + let (ret, cache) = env.enter_cache_level(|env| { let mut ret = engine.eval_thunk(idx, env)?; + env.enter_arg(args.next().unwrap()); while args.peek().is_some() { match ret { Value::Func(func) => { @@ -223,14 +227,16 @@ impl Value { _ => todo!(), } } - let args = env.pop_args(len); - if let Value::Func(idx) = ret { - ret = Value::PartialFunc(idx, args) - } else if let Value::PartialFunc(_, old) = &mut ret { - old.extend(args); - } ret.ok() - }) + }); + let mut ret = ret?; + let args = env.pop_args(len); + if let Value::Func(idx) = ret { + ret = Value::PartialFunc(self::PartialFunc::new(idx, args, cache).into()) + } else if let Value::PartialFunc(func) = &mut ret { + Rc::make_mut(func).args.extend(args); + } + ret.ok() } Catchable(_) => return Ok(()), other => todo!("{}", other.typename()),