From ae173d4fded75fd73801318b43bb9e756c5bca1a Mon Sep 17 00:00:00 2001 From: Kavi Gupta Date: Fri, 25 Jul 2025 16:54:20 -0400 Subject: [PATCH 01/20] extract a zipper adt --- src/compression.rs | 32 ++++++++++++++++---------------- src/lib.rs | 2 ++ src/util.rs | 2 +- src/zipper.rs | 3 +++ 4 files changed, 22 insertions(+), 17 deletions(-) create mode 100644 src/zipper.rs diff --git a/src/compression.rs b/src/compression.rs index 3ca8adae..d2ba14f9 100644 --- a/src/compression.rs +++ b/src/compression.rs @@ -312,7 +312,7 @@ impl Hash for Pattern { } /// only used during tracking - gets the zippers to args of a pattern -fn zids_of_ivar_of_expr(expr: &ExprOwned, zid_of_zip: &FxHashMap,ZId>) -> Option>> { +fn zids_of_ivar_of_expr(expr: &ExprOwned, zid_of_zip: &FxHashMap) -> Option>> { // quickly determine arity let mut arity = 0; @@ -324,10 +324,10 @@ fn zids_of_ivar_of_expr(expr: &ExprOwned, zid_of_zip: &FxHashMap,ZId> } } - let mut curr_zip: Vec = vec![]; + let mut curr_zip: Zipper = vec![]; let mut zids_of_ivar = vec![vec![]; arity as usize]; - fn helper(expr: Expr, curr_zip: &mut Vec, zids_of_ivar: &mut Vec>, zid_of_zip: &FxHashMap,ZId>) -> Result<(), ()> { + fn helper(expr: Expr, curr_zip: &mut Zipper, zids_of_ivar: &mut Vec>, zid_of_zip: &FxHashMap) -> Result<(), ()> { match expr.node() { Node::Prim(_) => {}, Node::Var(_, _) => {}, @@ -508,13 +508,13 @@ impl Pattern { fn to_expr(&self, shared: &SharedData) -> ExprOwned { let mut set = ExprSet::empty(Order::ChildFirst, false, false); - let mut curr_zip: Vec = vec![]; + let mut curr_zip: Zipper = vec![]; // map zids to zips with a bool thats true if this is a hole and false if its a future ivar - let zips: Vec<(Vec,Node)> = self.holes.iter().map(|zid| (shared.zip_of_zid[*zid].clone(), Node::Prim(HOLE_SYM.clone()))) + let zips: Vec<(Zipper,Node)> = self.holes.iter().map(|zid| (shared.zip_of_zid[*zid].clone(), Node::Prim(HOLE_SYM.clone()))) .chain(self.pattern_args.iterate_arguments() .map(|labelled_zid| (shared.zip_of_zid[labelled_zid.zid].clone(), Node::IVar(labelled_zid.ivar as i32)))).collect(); - fn helper(set: &mut ExprSet, curr_node: Idx, curr_zip: &mut Vec, zips: &[(Vec,Node)], shared: &SharedData) -> Idx { + fn helper(set: &mut ExprSet, curr_node: Idx, curr_zip: &mut Zipper, zips: &[(Zipper,Node)], shared: &SharedData) -> Idx { if let Some((_,e)) = zips.iter().find(|(zip,_)| zip == curr_zip) { return set.add(e.clone()); // current zip matches a hole } @@ -626,8 +626,8 @@ pub struct SharedData { pub corpus_span: Span, pub roots: Vec, pub zids_of_node: FxHashMap>, - pub zip_of_zid: Vec>, - pub zid_of_zip: FxHashMap, ZId>, + pub zip_of_zid: Vec, + pub zid_of_zip: FxHashMap, pub extensions_of_zid: Vec, pub set: ExprSet, pub num_paths_to_node: Vec, @@ -1185,10 +1185,10 @@ fn get_zippers( analyzed_cost: &AnalyzedExpr, set: &mut ExprSet, analyzed_free_vars: &mut AnalyzedExpr, -) -> (FxHashMap, ZId>, Vec>, Vec>, FxHashMap>, Vec) { +) -> (FxHashMap, Vec, Vec>, FxHashMap>, Vec) { - let mut zid_of_zip: FxHashMap, ZId> = Default::default(); - let mut zip_of_zid: Vec> = Default::default(); + let mut zid_of_zip: FxHashMap = Default::default(); + let mut zip_of_zid: Vec = Default::default(); let mut arg_of_zid_node: Vec> = Default::default(); let mut zids_of_node: FxHashMap> = Default::default(); @@ -1613,7 +1613,7 @@ pub fn inverse_delta(cost_once: Cost, usages: Cost, arg_uses: usize, cost_fn: &E // (not used in popl code - experimental; always exists at the first return statement unless --inv-arg-cap is turned on) #[allow(clippy::too_many_arguments)] -pub fn inverse_argument_capture(finished: &mut FinishedPattern, cfg: &CompressionStepConfig, zip_of_zid: &[Vec], arg_of_zid_node: &[FxHashMap], extensions_of_zid: &[ZIdExtension], set: &ExprSet, analyzed_ivars: &AnalyzedExpr, cost_fn: &ExprCost) { +pub fn inverse_argument_capture(finished: &mut FinishedPattern, cfg: &CompressionStepConfig, zip_of_zid: &[Zipper], arg_of_zid_node: &[FxHashMap], extensions_of_zid: &[ZIdExtension], set: &ExprSet, analyzed_ivars: &AnalyzedExpr, cost_fn: &ExprCost) { if !cfg.inv_arg_cap || cfg.no_other_util { return } @@ -1665,19 +1665,19 @@ fn possible_to_uninline(counts: FxHashMap)>, finished_usa } /// not used in popl code - experimental -fn use_counts(pattern: &Pattern, zip_of_zid: &[Vec], arg_of_zid_node: &[FxHashMap], extensions_of_zid: &[ZIdExtension], set: &ExprSet, analyzed_ivars: &AnalyzedExpr) -> FxHashMap)> { - let mut curr_zip: Vec = vec![]; +fn use_counts(pattern: &Pattern, zip_of_zid: &[Zipper], arg_of_zid_node: &[FxHashMap], extensions_of_zid: &[ZIdExtension], set: &ExprSet, analyzed_ivars: &AnalyzedExpr) -> FxHashMap)> { + let mut curr_zip: Zipper = vec![]; let curr_zid: ZId = EMPTY_ZID; let zids = &pattern.pattern_args.iterate_arguments().cloned().collect::>(); // map zids to zips with a bool thats true if this is a hole and false if its a future ivar - let zips: Vec> = zids.iter() + let zips: Vec = zids.iter() .map(|labelled_zid| zip_of_zid[labelled_zid.zid].clone()).collect(); let mut counts: FxHashMap)> = Default::default(); #[allow(clippy::too_many_arguments)] - fn helper(curr_node: Idx, match_loc: Idx, curr_zip: &mut Vec, curr_zid: ZId, zips: &[Vec], zids: &[LabelledZId], arg_of_zid_node: &[FxHashMap], extensions_of_zid: &[ZIdExtension], set: &ExprSet, counts: &mut FxHashMap)>, analyzed_ivars: &AnalyzedExpr) { + fn helper(curr_node: Idx, match_loc: Idx, curr_zip: &mut Zipper, curr_zid: ZId, zips: &[Zipper], zids: &[LabelledZId], arg_of_zid_node: &[FxHashMap], extensions_of_zid: &[ZIdExtension], set: &ExprSet, counts: &mut FxHashMap)>, analyzed_ivars: &AnalyzedExpr) { if zids.iter().any(|labelled| labelled.zid == curr_zid){ return // current zip matches an arg } diff --git a/src/lib.rs b/src/lib.rs index ea13bbd9..d01b7dab 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,6 +9,7 @@ pub mod expansion; pub mod pattern_args; pub mod symvar; pub mod test_utils; +pub mod zipper; pub use { compression::*, @@ -22,6 +23,7 @@ pub use { pattern_args::*, symvar::*, test_utils::*, + zipper::*, }; pub use colorful::{Color,Colorful,RGB}; diff --git a/src/util.rs b/src/util.rs index adabf32b..0920b82e 100644 --- a/src/util.rs +++ b/src/util.rs @@ -122,7 +122,7 @@ pub fn num_paths_to_node(roots: &[Idx], corpus_span: &Span, set: &ExprSet) -> (V } -pub fn zipper_replace(mut expr: ExprOwned, zipper: &[ZNode], new: Node) -> ExprOwned { +pub fn zipper_replace(mut expr: ExprOwned, zipper: &Zipper, new: Node) -> ExprOwned { let idx = expr.immut().zip(zipper).idx; *expr.as_mut().get_node_mut(idx) = new; expr diff --git a/src/zipper.rs b/src/zipper.rs new file mode 100644 index 00000000..25814282 --- /dev/null +++ b/src/zipper.rs @@ -0,0 +1,3 @@ +pub use lambdas::{ZNode, ZId, LabelledZId}; + +pub type Zipper = Vec; \ No newline at end of file From fe35e598e1b5183ecfecd14ae12e89f69cb6eeab Mon Sep 17 00:00:00 2001 From: Kavi Gupta Date: Mon, 28 Jul 2025 16:26:01 -0400 Subject: [PATCH 02/20] extract zipper adt functions --- src/compression.rs | 66 +++++++++++++++++++++++----------------------- src/expansion.rs | 4 +-- src/rewriting.rs | 2 +- src/util.rs | 2 +- src/zipper.rs | 51 ++++++++++++++++++++++++++++++++++- 5 files changed, 87 insertions(+), 38 deletions(-) diff --git a/src/compression.rs b/src/compression.rs index d2ba14f9..4bc8aada 100644 --- a/src/compression.rs +++ b/src/compression.rs @@ -6,7 +6,7 @@ use core::panic; use std::convert::TryInto; use std::fmt::{self, Formatter, Display}; use std::hash::{Hash, Hasher}; -use itertools::Itertools; +use itertools::{Itertools, Zip}; use serde_json::json; use clap::{Parser}; use serde::Serialize; @@ -324,7 +324,7 @@ fn zids_of_ivar_of_expr(expr: &ExprOwned, zid_of_zip: &FxHashMap) -> } } - let mut curr_zip: Zipper = vec![]; + let mut curr_zip: Zipper = Zipper::new(); let mut zids_of_ivar = vec![vec![]; arity as usize]; fn helper(expr: Expr, curr_zip: &mut Zipper, zids_of_ivar: &mut Vec>, zid_of_zip: &FxHashMap) -> Result<(), ()> { @@ -335,17 +335,17 @@ fn zids_of_ivar_of_expr(expr: &ExprOwned, zid_of_zip: &FxHashMap) -> zids_of_ivar[*i as usize].push(zid_of_zip.get(curr_zip).cloned().ok_or(())?); }, Node::Lam(b, _) => { - curr_zip.push(ZNode::Body); + curr_zip.add_to_end(ZNode::Body); helper(expr.get(*b), curr_zip, zids_of_ivar, zid_of_zip)?; - curr_zip.pop(); + curr_zip.remove_from_end(); } Node::App(f,x) => { - curr_zip.push(ZNode::Func); + curr_zip.add_to_end(ZNode::Func); helper(expr.get(*f), curr_zip, zids_of_ivar, zid_of_zip)?; - curr_zip.pop(); - curr_zip.push(ZNode::Arg); + curr_zip.remove_from_end(); + curr_zip.add_to_end(ZNode::Arg); helper(expr.get(*x), curr_zip, zids_of_ivar, zid_of_zip)?; - curr_zip.pop(); + curr_zip.remove_from_end(); } } Ok(()) @@ -508,7 +508,7 @@ impl Pattern { fn to_expr(&self, shared: &SharedData) -> ExprOwned { let mut set = ExprSet::empty(Order::ChildFirst, false, false); - let mut curr_zip: Zipper = vec![]; + let mut curr_zip: Zipper = Zipper::new(); // map zids to zips with a bool thats true if this is a hole and false if its a future ivar let zips: Vec<(Zipper,Node)> = self.holes.iter().map(|zid| (shared.zip_of_zid[*zid].clone(), Node::Prim(HOLE_SYM.clone()))) .chain(self.pattern_args.iterate_arguments() @@ -523,18 +523,18 @@ impl Pattern { Node::Prim(p) => set.add(Node::Prim(p.clone())), Node::Var(v, tag) => set.add(Node::Var(*v, *tag)), Node::Lam(b, tag) => { - curr_zip.push(ZNode::Body); + curr_zip.add_to_end(ZNode::Body); let b_idx = helper(set, *b, curr_zip, zips, shared); - curr_zip.pop(); + curr_zip.remove_from_end(); set.add(Node::Lam(b_idx, *tag)) } Node::App(f,x) => { - curr_zip.push(ZNode::Func); + curr_zip.add_to_end(ZNode::Func); let f_idx = helper(set, *f, curr_zip, zips, shared); - curr_zip.pop(); - curr_zip.push(ZNode::Arg); + curr_zip.remove_from_end(); + curr_zip.add_to_end(ZNode::Arg); let x_idx = helper(set, *x, curr_zip, zips, shared); - curr_zip.pop(); + curr_zip.remove_from_end(); set.add(Node::App(f_idx,x_idx)) } _ => unreachable!(), @@ -550,7 +550,7 @@ impl Pattern { let mut expr = self.to_expr(shared); let expands_to = format!("{}",tracked_expands_to(self, hole_zid, shared)).magenta().bold().to_string(); let replace_sentinel = Node::Prim("".into()); - let idx = expr.immut().zip(&shared.zip_of_zid[hole_zid]).idx; + let idx = expr.immut().zip(&shared.zip_of_zid[hole_zid][..]).idx; expr.set[idx] = replace_sentinel; expr.to_string().replace("", &expands_to) } @@ -971,7 +971,7 @@ fn stitch_search( // Pruning (FREE VARS): if an invention has free variables in the body then it's not a real function and we can discard it // Here we just check if our expansion just yielded a variable, and if that is bound based on how many lambdas there are above it. - if expands_to.free_variable(shared.zip_of_zid[hole_zid].iter().filter(|znode|**znode == ZNode::Body).count()) { + if expands_to.free_variable(shared.zip_of_zid[hole_zid].depth_root_to_arg()) { if !shared.cfg.no_stats { shared.stats.lock().deref_mut().free_vars_fired += 1; }; if tracked && !shared.cfg.quiet { println!("{} pruned by free var in body when expanding {} to {}", "[TRACK]".red().bold(), original_pattern.to_expr(&shared), original_pattern.show_track_expansion(hole_zid, &shared)) } continue 'expansion; // free var @@ -1192,8 +1192,8 @@ fn get_zippers( let mut arg_of_zid_node: Vec> = Default::default(); let mut zids_of_node: FxHashMap> = Default::default(); - zid_of_zip.insert(vec![], EMPTY_ZID); - zip_of_zid.push(vec![]); + zid_of_zip.insert(Zipper::new(), EMPTY_ZID); + zip_of_zid.push(Zipper::new()); arg_of_zid_node.push(FxHashMap::default()); // loop over all nodes in all programs in bottom up order @@ -1218,7 +1218,7 @@ fn get_zippers( for f_zid in zids_of_node[&f].iter() { // clone and extend zip to get new zid for this node let mut zip = zip_of_zid[*f_zid].clone(); - zip.insert(0,ZNode::Func); + zip.add_to_front(ZNode::Func); let zid = zid_of_zip.entry(zip.clone()).or_insert_with(|| { let zid = zip_of_zid.len(); zip_of_zid.push(zip); @@ -1236,7 +1236,7 @@ fn get_zippers( for x_zid in zids_of_node[&x].iter() { // clone and extend zip to get new zid for this node let mut zip = zip_of_zid[*x_zid].clone(); - zip.insert(0,ZNode::Arg); + zip.add_to_front(ZNode::Arg); let zid = zid_of_zip.entry(zip.clone()).or_insert_with(|| { let zid = zip_of_zid.len(); zip_of_zid.push(zip); @@ -1256,7 +1256,7 @@ fn get_zippers( // clone and extend zip to get new zid for this node let mut zip = zip_of_zid[*b_zid].clone(); - zip.insert(0,ZNode::Body); + zip.add_to_front(ZNode::Body); let zid = zid_of_zip.entry(zip.clone()).or_insert_with(|| { let zid = zip_of_zid.len(); zip_of_zid.push(zip.clone()); @@ -1275,7 +1275,7 @@ fn get_zippers( // by inserting an IVar to indicate this // how many lambdas are along this zipper? (including most recent one) - let depth_root_to_arg = zip.iter().filter(|x| **x == ZNode::Body).count() as i32; + let depth_root_to_arg = zip.depth_root_to_arg() as i32; // find all pointers to $0 (this is the `init_depth` parameter) and replace then with #(num_lams - 1) that is // point past all lambdas except the newly added one. For example if there were no lambdas other than the @@ -1294,11 +1294,11 @@ fn get_zippers( let extensions_of_zid = zip_of_zid.iter().map(|zip| { let mut zip_body = zip.clone(); - zip_body.push(ZNode::Body); + zip_body.add_to_end(ZNode::Body); let mut zip_arg = zip.clone(); - zip_arg.push(ZNode::Arg); + zip_arg.add_to_end(ZNode::Arg); let mut zip_func = zip.clone(); - zip_func.push(ZNode::Func); + zip_func.add_to_end(ZNode::Func); ZIdExtension { body: zid_of_zip.get(&zip_body).copied(), arg: zid_of_zip.get(&zip_arg).copied(), @@ -1666,7 +1666,7 @@ fn possible_to_uninline(counts: FxHashMap)>, finished_usa /// not used in popl code - experimental fn use_counts(pattern: &Pattern, zip_of_zid: &[Zipper], arg_of_zid_node: &[FxHashMap], extensions_of_zid: &[ZIdExtension], set: &ExprSet, analyzed_ivars: &AnalyzedExpr) -> FxHashMap)> { - let mut curr_zip: Zipper = vec![]; + let mut curr_zip: Zipper = Zipper::new(); let curr_zid: ZId = EMPTY_ZID; let zids = &pattern.pattern_args.iterate_arguments().cloned().collect::>(); @@ -1695,20 +1695,20 @@ fn use_counts(pattern: &Pattern, zip_of_zid: &[Zipper], arg_of_zid_node: &[FxHas Node::Prim(_) => {}, Node::Var(_, _) => {}, Node::Lam(b, _) => { - curr_zip.push(ZNode::Body); + curr_zip.add_to_end(ZNode::Body); let new_zid = extensions_of_zid[curr_zid].body.unwrap(); helper(*b, match_loc, curr_zip, new_zid, zips, zids, arg_of_zid_node, extensions_of_zid, set, counts, analyzed_ivars); - curr_zip.pop(); + curr_zip.remove_from_end(); } Node::App(f,x) => { - curr_zip.push(ZNode::Func); + curr_zip.add_to_end(ZNode::Func); let new_zid = extensions_of_zid[curr_zid].func.unwrap(); helper(*f, match_loc, curr_zip, new_zid, zips, zids, arg_of_zid_node, extensions_of_zid, set, counts, analyzed_ivars); - curr_zip.pop(); - curr_zip.push(ZNode::Arg); + curr_zip.remove_from_end(); + curr_zip.add_to_end(ZNode::Arg); let new_zid = extensions_of_zid[curr_zid].arg.unwrap(); helper(*x, match_loc, curr_zip, new_zid, zips, zids, arg_of_zid_node, extensions_of_zid, set, counts, analyzed_ivars); - curr_zip.pop(); + curr_zip.remove_from_end(); } _ => unreachable!(), } diff --git a/src/expansion.rs b/src/expansion.rs index af3a2f7b..597616c1 100644 --- a/src/expansion.rs +++ b/src/expansion.rs @@ -134,7 +134,7 @@ impl std::fmt::Display for ExpandsTo { pub fn tracked_expands_to(pattern: &Pattern, hole_zid: ZId, shared: &SharedData) -> ExpandsTo { // apply the hole zipper to the original expr being tracked to get the subtree // this will expand into, then get the ExpandsTo of that - let idx = shared.tracking.as_ref().unwrap().expr.immut().zip(&shared.zip_of_zid[hole_zid]).idx; + let idx = shared.tracking.as_ref().unwrap().expr.immut().zip(&shared.zip_of_zid[hole_zid][..]).idx; match expands_to_of_node(&shared.tracking.as_ref().unwrap().expr.set[idx]) { ExpandsTo(ExpandsToInner::IVar(i, VariableType::Metavar)) => { ExpandsTo(ExpandsToInner::IVar(pattern.pattern_args.find_variable(shared, i as usize) as i32, VariableType::Metavar)) @@ -176,7 +176,7 @@ pub fn get_ivars_expansions(original_pattern: &Pattern, arg_of_loc: &FxHashMap 0 { let analyzed_free_vars = &mut AnalyzedExpr::new(FreeVarAnalysis); diff --git a/src/util.rs b/src/util.rs index 0920b82e..7accad49 100644 --- a/src/util.rs +++ b/src/util.rs @@ -123,7 +123,7 @@ pub fn num_paths_to_node(roots: &[Idx], corpus_span: &Span, set: &ExprSet) -> (V pub fn zipper_replace(mut expr: ExprOwned, zipper: &Zipper, new: Node) -> ExprOwned { - let idx = expr.immut().zip(zipper).idx; + let idx = expr.immut().zip(&zipper[..]).idx; *expr.as_mut().get_node_mut(idx) = new; expr } \ No newline at end of file diff --git a/src/zipper.rs b/src/zipper.rs index 25814282..9b87ded0 100644 --- a/src/zipper.rs +++ b/src/zipper.rs @@ -1,3 +1,52 @@ pub use lambdas::{ZNode, ZId, LabelledZId}; -pub type Zipper = Vec; \ No newline at end of file +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct Zipper(Vec); + +// impl Slice for Zipper + +impl std::ops::Index for Zipper +where + Idx: std::slice::SliceIndex<[ZNode]>, +{ + type Output = Idx::Output; + + fn index(&self, index: Idx) -> &Self::Output { + &self.0[index] + } +} + +impl Zipper { + + pub fn new() -> Self { + Zipper(Vec::new()) + } + + pub fn ends_with_func(&self) -> bool { + matches!(self.0.last(), Some(ZNode::Func)) + } + + pub fn function_arity(&self) -> usize { + self.0.iter().rev().take_while(|znode| **znode == ZNode::Func).count() + } + + pub fn depth_root_to_arg(&self) -> usize { + self.0.iter().filter(|x| **x == ZNode::Body).count() + } + + pub fn starts_with(&self, other: &Zipper) -> bool { + self.0.starts_with(&other.0) + } + + pub fn add_to_front(&mut self, node: ZNode) { + self.0.insert(0, node); + } + + pub fn add_to_end(&mut self, node: ZNode) { + self.0.push(node); + } + + pub fn remove_from_end(&mut self) { + self.0.pop(); + } +} \ No newline at end of file From 83d97cc266378f4c691a080ba9d6b10d63568fa0 Mon Sep 17 00:00:00 2001 From: Kavi Gupta Date: Mon, 28 Jul 2025 16:27:57 -0400 Subject: [PATCH 03/20] fix lint --- src/compression.rs | 12 ++++++------ src/expansion.rs | 2 +- src/zipper.rs | 6 +----- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/compression.rs b/src/compression.rs index 4bc8aada..e000a7f6 100644 --- a/src/compression.rs +++ b/src/compression.rs @@ -6,7 +6,7 @@ use core::panic; use std::convert::TryInto; use std::fmt::{self, Formatter, Display}; use std::hash::{Hash, Hasher}; -use itertools::{Itertools, Zip}; +use itertools::{Itertools}; use serde_json::json; use clap::{Parser}; use serde::Serialize; @@ -324,7 +324,7 @@ fn zids_of_ivar_of_expr(expr: &ExprOwned, zid_of_zip: &FxHashMap) -> } } - let mut curr_zip: Zipper = Zipper::new(); + let mut curr_zip: Zipper = Zipper::default(); let mut zids_of_ivar = vec![vec![]; arity as usize]; fn helper(expr: Expr, curr_zip: &mut Zipper, zids_of_ivar: &mut Vec>, zid_of_zip: &FxHashMap) -> Result<(), ()> { @@ -508,7 +508,7 @@ impl Pattern { fn to_expr(&self, shared: &SharedData) -> ExprOwned { let mut set = ExprSet::empty(Order::ChildFirst, false, false); - let mut curr_zip: Zipper = Zipper::new(); + let mut curr_zip: Zipper = Zipper::default(); // map zids to zips with a bool thats true if this is a hole and false if its a future ivar let zips: Vec<(Zipper,Node)> = self.holes.iter().map(|zid| (shared.zip_of_zid[*zid].clone(), Node::Prim(HOLE_SYM.clone()))) .chain(self.pattern_args.iterate_arguments() @@ -1192,8 +1192,8 @@ fn get_zippers( let mut arg_of_zid_node: Vec> = Default::default(); let mut zids_of_node: FxHashMap> = Default::default(); - zid_of_zip.insert(Zipper::new(), EMPTY_ZID); - zip_of_zid.push(Zipper::new()); + zid_of_zip.insert(Zipper::default(), EMPTY_ZID); + zip_of_zid.push(Zipper::default()); arg_of_zid_node.push(FxHashMap::default()); // loop over all nodes in all programs in bottom up order @@ -1666,7 +1666,7 @@ fn possible_to_uninline(counts: FxHashMap)>, finished_usa /// not used in popl code - experimental fn use_counts(pattern: &Pattern, zip_of_zid: &[Zipper], arg_of_zid_node: &[FxHashMap], extensions_of_zid: &[ZIdExtension], set: &ExprSet, analyzed_ivars: &AnalyzedExpr) -> FxHashMap)> { - let mut curr_zip: Zipper = Zipper::new(); + let mut curr_zip: Zipper = Zipper::default(); let curr_zid: ZId = EMPTY_ZID; let zids = &pattern.pattern_args.iterate_arguments().cloned().collect::>(); diff --git a/src/expansion.rs b/src/expansion.rs index 597616c1..3f55a440 100644 --- a/src/expansion.rs +++ b/src/expansion.rs @@ -1,7 +1,7 @@ use std::{fmt::{self, Formatter}, sync::Arc}; use itertools::Itertools; -use lambdas::{Idx, Node, Symbol, Tag, ZId, ZNode}; +use lambdas::{Idx, Node, Symbol, Tag, ZId}; use rustc_hash::{FxHashMap, FxHashSet}; use crate::{invalid_metavar_location, Arg, Cost, LocationsForReusableArgs, Pattern, PatternArgs, SharedData, SymvarInfo, VariableType, ZIdExtension}; diff --git a/src/zipper.rs b/src/zipper.rs index 9b87ded0..c5127d93 100644 --- a/src/zipper.rs +++ b/src/zipper.rs @@ -1,6 +1,6 @@ pub use lambdas::{ZNode, ZId, LabelledZId}; -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, Default)] pub struct Zipper(Vec); // impl Slice for Zipper @@ -17,10 +17,6 @@ where } impl Zipper { - - pub fn new() -> Self { - Zipper(Vec::new()) - } pub fn ends_with_func(&self) -> bool { matches!(self.0.last(), Some(ZNode::Func)) From 61bddf8ce1709fc0b1f2bd9a6b224055e92d4154 Mon Sep 17 00:00:00 2001 From: Kavi Gupta Date: Mon, 28 Jul 2025 16:40:07 -0400 Subject: [PATCH 04/20] comment --- src/zipper.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/zipper.rs b/src/zipper.rs index c5127d93..8d906f36 100644 --- a/src/zipper.rs +++ b/src/zipper.rs @@ -3,8 +3,6 @@ pub use lambdas::{ZNode, ZId, LabelledZId}; #[derive(Clone, Debug, PartialEq, Eq, Hash, Default)] pub struct Zipper(Vec); -// impl Slice for Zipper - impl std::ops::Index for Zipper where Idx: std::slice::SliceIndex<[ZNode]>, From bc707c7bcccc6a12eb05818af94bdb61f7999ab2 Mon Sep 17 00:00:00 2001 From: Kavi Gupta Date: Mon, 28 Jul 2025 16:54:32 -0400 Subject: [PATCH 05/20] range full --- src/zipper.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/zipper.rs b/src/zipper.rs index 8d906f36..e4e46e4d 100644 --- a/src/zipper.rs +++ b/src/zipper.rs @@ -1,15 +1,16 @@ +use std::ops::{self, RangeFull}; + pub use lambdas::{ZNode, ZId, LabelledZId}; #[derive(Clone, Debug, PartialEq, Eq, Hash, Default)] pub struct Zipper(Vec); -impl std::ops::Index for Zipper +impl ops::Index for Zipper where - Idx: std::slice::SliceIndex<[ZNode]>, { - type Output = Idx::Output; + type Output = [ZNode]; - fn index(&self, index: Idx) -> &Self::Output { + fn index(&self, index: RangeFull) -> &Self::Output { &self.0[index] } } From 1cc79bcc92360fba44eb2cec15f644381e95cd07 Mon Sep 17 00:00:00 2001 From: Kavi Gupta Date: Mon, 28 Jul 2025 17:13:41 -0400 Subject: [PATCH 06/20] iterator instead of zip --- Cargo.toml | 4 ++-- src/compression.rs | 2 +- src/expansion.rs | 2 +- src/util.rs | 2 +- src/zipper.rs | 15 ++++----------- 5 files changed, 9 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 96387271..3124be84 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,12 +20,12 @@ parking_lot = "0.12.0" colorful = "0.2.1" rustc-hash = "1.1.0" # lambdas = "0.2.0" -lambdas = { git = "https://github.com/mlb2251/lambdas", rev = "550ade8"} +# lambdas = { git = "https://github.com/mlb2251/lambdas", rev = "550ade8"} test-case = "3.3.1" # [patch.crates-io] -# lambdas = { path = "../lambdas"} +lambdas = { path = "../lambdas"} # enable for flamegraphs diff --git a/src/compression.rs b/src/compression.rs index e000a7f6..12596269 100644 --- a/src/compression.rs +++ b/src/compression.rs @@ -550,7 +550,7 @@ impl Pattern { let mut expr = self.to_expr(shared); let expands_to = format!("{}",tracked_expands_to(self, hole_zid, shared)).magenta().bold().to_string(); let replace_sentinel = Node::Prim("".into()); - let idx = expr.immut().zip(&shared.zip_of_zid[hole_zid][..]).idx; + let idx = expr.immut().zip_iter(shared.zip_of_zid[hole_zid].iter()).idx; expr.set[idx] = replace_sentinel; expr.to_string().replace("", &expands_to) } diff --git a/src/expansion.rs b/src/expansion.rs index 3f55a440..851009f7 100644 --- a/src/expansion.rs +++ b/src/expansion.rs @@ -134,7 +134,7 @@ impl std::fmt::Display for ExpandsTo { pub fn tracked_expands_to(pattern: &Pattern, hole_zid: ZId, shared: &SharedData) -> ExpandsTo { // apply the hole zipper to the original expr being tracked to get the subtree // this will expand into, then get the ExpandsTo of that - let idx = shared.tracking.as_ref().unwrap().expr.immut().zip(&shared.zip_of_zid[hole_zid][..]).idx; + let idx = shared.tracking.as_ref().unwrap().expr.immut().zip_iter(shared.zip_of_zid[hole_zid].iter()).idx; match expands_to_of_node(&shared.tracking.as_ref().unwrap().expr.set[idx]) { ExpandsTo(ExpandsToInner::IVar(i, VariableType::Metavar)) => { ExpandsTo(ExpandsToInner::IVar(pattern.pattern_args.find_variable(shared, i as usize) as i32, VariableType::Metavar)) diff --git a/src/util.rs b/src/util.rs index 7accad49..1d986673 100644 --- a/src/util.rs +++ b/src/util.rs @@ -123,7 +123,7 @@ pub fn num_paths_to_node(roots: &[Idx], corpus_span: &Span, set: &ExprSet) -> (V pub fn zipper_replace(mut expr: ExprOwned, zipper: &Zipper, new: Node) -> ExprOwned { - let idx = expr.immut().zip(&zipper[..]).idx; + let idx = expr.immut().zip_iter(zipper.iter()).idx; *expr.as_mut().get_node_mut(idx) = new; expr } \ No newline at end of file diff --git a/src/zipper.rs b/src/zipper.rs index e4e46e4d..888b6592 100644 --- a/src/zipper.rs +++ b/src/zipper.rs @@ -1,21 +1,14 @@ -use std::ops::{self, RangeFull}; - pub use lambdas::{ZNode, ZId, LabelledZId}; #[derive(Clone, Debug, PartialEq, Eq, Hash, Default)] pub struct Zipper(Vec); -impl ops::Index for Zipper -where -{ - type Output = [ZNode]; - - fn index(&self, index: RangeFull) -> &Self::Output { - &self.0[index] - } -} impl Zipper { + + pub fn iter(&self) -> impl Iterator { + self.0.iter() + } pub fn ends_with_func(&self) -> bool { matches!(self.0.last(), Some(ZNode::Func)) From ca180b7a7ddb65628c2845e6667e57e6f1910d20 Mon Sep 17 00:00:00 2001 From: Kavi Gupta Date: Mon, 28 Jul 2025 17:20:42 -0400 Subject: [PATCH 07/20] use zip iter version --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 96387271..e32b91f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ parking_lot = "0.12.0" colorful = "0.2.1" rustc-hash = "1.1.0" # lambdas = "0.2.0" -lambdas = { git = "https://github.com/mlb2251/lambdas", rev = "550ade8"} +lambdas = { git = "https://github.com/mlb2251/lambdas", rev = "bcb969f"} test-case = "3.3.1" From acf0c6ef7fc8a43ab24cdf207d834716ff972403 Mon Sep 17 00:00:00 2001 From: Kavi Gupta Date: Mon, 28 Jul 2025 17:36:41 -0400 Subject: [PATCH 08/20] update commit hash --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e32b91f9..4791ec06 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ parking_lot = "0.12.0" colorful = "0.2.1" rustc-hash = "1.1.0" # lambdas = "0.2.0" -lambdas = { git = "https://github.com/mlb2251/lambdas", rev = "bcb969f"} +lambdas = { git = "https://github.com/mlb2251/lambdas", rev = "2c9bfd0"} test-case = "3.3.1" From eb69b51a5decd15204bf24786bc52caa971754bf Mon Sep 17 00:00:00 2001 From: Kavi Gupta Date: Mon, 28 Jul 2025 17:38:01 -0400 Subject: [PATCH 09/20] update --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index ac7c8f0d..4791ec06 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ test-case = "3.3.1" # [patch.crates-io] -lambdas = { path = "../lambdas"} +# lambdas = { path = "../lambdas"} # enable for flamegraphs From dd0adfd14d7e1d1ee585323680f26e8727b7f0ca Mon Sep 17 00:00:00 2001 From: Kavi Gupta Date: Mon, 28 Jul 2025 17:41:56 -0400 Subject: [PATCH 10/20] reverse --- src/zipper.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/zipper.rs b/src/zipper.rs index 888b6592..2ae5fee0 100644 --- a/src/zipper.rs +++ b/src/zipper.rs @@ -7,15 +7,15 @@ pub struct Zipper(Vec); impl Zipper { pub fn iter(&self) -> impl Iterator { - self.0.iter() + self.0.iter().rev() } pub fn ends_with_func(&self) -> bool { - matches!(self.0.last(), Some(ZNode::Func)) + matches!(self.0.first(), Some(ZNode::Func)) } pub fn function_arity(&self) -> usize { - self.0.iter().rev().take_while(|znode| **znode == ZNode::Func).count() + self.0.iter().take_while(|znode| **znode == ZNode::Func).count() } pub fn depth_root_to_arg(&self) -> usize { @@ -23,18 +23,18 @@ impl Zipper { } pub fn starts_with(&self, other: &Zipper) -> bool { - self.0.starts_with(&other.0) + self.0.ends_with(&other.0) } pub fn add_to_front(&mut self, node: ZNode) { - self.0.insert(0, node); + self.0.push(node); } pub fn add_to_end(&mut self, node: ZNode) { - self.0.push(node); + self.0.insert(0, node) } pub fn remove_from_end(&mut self) { - self.0.pop(); + self.0.remove(0); } } \ No newline at end of file From 6d479366df31e437c6a84aeb4c2f7cd90e5c775e Mon Sep 17 00:00:00 2001 From: Kavi Gupta Date: Tue, 29 Jul 2025 11:16:58 -0700 Subject: [PATCH 11/20] Revert "reverse" This reverts commit dd0adfd14d7e1d1ee585323680f26e8727b7f0ca. --- src/zipper.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/zipper.rs b/src/zipper.rs index 2ae5fee0..888b6592 100644 --- a/src/zipper.rs +++ b/src/zipper.rs @@ -7,15 +7,15 @@ pub struct Zipper(Vec); impl Zipper { pub fn iter(&self) -> impl Iterator { - self.0.iter().rev() + self.0.iter() } pub fn ends_with_func(&self) -> bool { - matches!(self.0.first(), Some(ZNode::Func)) + matches!(self.0.last(), Some(ZNode::Func)) } pub fn function_arity(&self) -> usize { - self.0.iter().take_while(|znode| **znode == ZNode::Func).count() + self.0.iter().rev().take_while(|znode| **znode == ZNode::Func).count() } pub fn depth_root_to_arg(&self) -> usize { @@ -23,18 +23,18 @@ impl Zipper { } pub fn starts_with(&self, other: &Zipper) -> bool { - self.0.ends_with(&other.0) + self.0.starts_with(&other.0) } pub fn add_to_front(&mut self, node: ZNode) { - self.0.push(node); + self.0.insert(0, node); } pub fn add_to_end(&mut self, node: ZNode) { - self.0.insert(0, node) + self.0.push(node); } pub fn remove_from_end(&mut self) { - self.0.remove(0); + self.0.pop(); } } \ No newline at end of file From 275fcbcfaf7ac192016ba740252f18cdd1334878 Mon Sep 17 00:00:00 2001 From: Kavi Gupta Date: Tue, 29 Jul 2025 11:22:30 -0700 Subject: [PATCH 12/20] inline --- src/zipper.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/zipper.rs b/src/zipper.rs index 888b6592..c96516c6 100644 --- a/src/zipper.rs +++ b/src/zipper.rs @@ -6,34 +6,42 @@ pub struct Zipper(Vec); impl Zipper { + #[inline] pub fn iter(&self) -> impl Iterator { self.0.iter() } + #[inline] pub fn ends_with_func(&self) -> bool { matches!(self.0.last(), Some(ZNode::Func)) } + #[inline] pub fn function_arity(&self) -> usize { self.0.iter().rev().take_while(|znode| **znode == ZNode::Func).count() } + #[inline] pub fn depth_root_to_arg(&self) -> usize { self.0.iter().filter(|x| **x == ZNode::Body).count() } + #[inline] pub fn starts_with(&self, other: &Zipper) -> bool { self.0.starts_with(&other.0) } + #[inline] pub fn add_to_front(&mut self, node: ZNode) { self.0.insert(0, node); } + #[inline] pub fn add_to_end(&mut self, node: ZNode) { self.0.push(node); } + #[inline] pub fn remove_from_end(&mut self) { self.0.pop(); } From 51676ed3167ba8063fecc5dc33b853f32c572b47 Mon Sep 17 00:00:00 2001 From: Kavi Gupta Date: Tue, 29 Jul 2025 11:23:23 -0700 Subject: [PATCH 13/20] undo --- src/compression.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compression.rs b/src/compression.rs index 12596269..02caaa29 100644 --- a/src/compression.rs +++ b/src/compression.rs @@ -6,7 +6,7 @@ use core::panic; use std::convert::TryInto; use std::fmt::{self, Formatter, Display}; use std::hash::{Hash, Hasher}; -use itertools::{Itertools}; +use itertools::Itertools; use serde_json::json; use clap::{Parser}; use serde::Serialize; From 80996e259577fdf9701963706a784756ff70c57e Mon Sep 17 00:00:00 2001 From: Kavi Gupta Date: Tue, 29 Jul 2025 11:27:46 -0700 Subject: [PATCH 14/20] undo the ADT part --- src/compression.rs | 54 +++++++++++++++++++++++----------------------- src/expansion.rs | 6 +++--- src/rewriting.rs | 2 +- src/util.rs | 2 +- src/zipper.rs | 2 +- 5 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/compression.rs b/src/compression.rs index 02caaa29..5296346c 100644 --- a/src/compression.rs +++ b/src/compression.rs @@ -335,17 +335,17 @@ fn zids_of_ivar_of_expr(expr: &ExprOwned, zid_of_zip: &FxHashMap) -> zids_of_ivar[*i as usize].push(zid_of_zip.get(curr_zip).cloned().ok_or(())?); }, Node::Lam(b, _) => { - curr_zip.add_to_end(ZNode::Body); + curr_zip.0.push(ZNode::Body); helper(expr.get(*b), curr_zip, zids_of_ivar, zid_of_zip)?; - curr_zip.remove_from_end(); + curr_zip.0.pop(); } Node::App(f,x) => { - curr_zip.add_to_end(ZNode::Func); + curr_zip.0.push(ZNode::Func); helper(expr.get(*f), curr_zip, zids_of_ivar, zid_of_zip)?; - curr_zip.remove_from_end(); - curr_zip.add_to_end(ZNode::Arg); + curr_zip.0.pop(); + curr_zip.0.push(ZNode::Arg); helper(expr.get(*x), curr_zip, zids_of_ivar, zid_of_zip)?; - curr_zip.remove_from_end(); + curr_zip.0.pop(); } } Ok(()) @@ -523,18 +523,18 @@ impl Pattern { Node::Prim(p) => set.add(Node::Prim(p.clone())), Node::Var(v, tag) => set.add(Node::Var(*v, *tag)), Node::Lam(b, tag) => { - curr_zip.add_to_end(ZNode::Body); + curr_zip.0.push(ZNode::Body); let b_idx = helper(set, *b, curr_zip, zips, shared); - curr_zip.remove_from_end(); + curr_zip.0.pop(); set.add(Node::Lam(b_idx, *tag)) } Node::App(f,x) => { - curr_zip.add_to_end(ZNode::Func); + curr_zip.0.push(ZNode::Func); let f_idx = helper(set, *f, curr_zip, zips, shared); - curr_zip.remove_from_end(); - curr_zip.add_to_end(ZNode::Arg); + curr_zip.0.pop(); + curr_zip.0.push(ZNode::Arg); let x_idx = helper(set, *x, curr_zip, zips, shared); - curr_zip.remove_from_end(); + curr_zip.0.pop(); set.add(Node::App(f_idx,x_idx)) } _ => unreachable!(), @@ -550,7 +550,7 @@ impl Pattern { let mut expr = self.to_expr(shared); let expands_to = format!("{}",tracked_expands_to(self, hole_zid, shared)).magenta().bold().to_string(); let replace_sentinel = Node::Prim("".into()); - let idx = expr.immut().zip_iter(shared.zip_of_zid[hole_zid].iter()).idx; + let idx = expr.immut().zip(&shared.zip_of_zid[hole_zid].0).idx; expr.set[idx] = replace_sentinel; expr.to_string().replace("", &expands_to) } @@ -971,7 +971,7 @@ fn stitch_search( // Pruning (FREE VARS): if an invention has free variables in the body then it's not a real function and we can discard it // Here we just check if our expansion just yielded a variable, and if that is bound based on how many lambdas there are above it. - if expands_to.free_variable(shared.zip_of_zid[hole_zid].depth_root_to_arg()) { + if expands_to.free_variable(shared.zip_of_zid[hole_zid].0.iter().filter(|znode|**znode == ZNode::Body).count()) { if !shared.cfg.no_stats { shared.stats.lock().deref_mut().free_vars_fired += 1; }; if tracked && !shared.cfg.quiet { println!("{} pruned by free var in body when expanding {} to {}", "[TRACK]".red().bold(), original_pattern.to_expr(&shared), original_pattern.show_track_expansion(hole_zid, &shared)) } continue 'expansion; // free var @@ -1218,7 +1218,7 @@ fn get_zippers( for f_zid in zids_of_node[&f].iter() { // clone and extend zip to get new zid for this node let mut zip = zip_of_zid[*f_zid].clone(); - zip.add_to_front(ZNode::Func); + zip.0.insert(0,ZNode::Func); let zid = zid_of_zip.entry(zip.clone()).or_insert_with(|| { let zid = zip_of_zid.len(); zip_of_zid.push(zip); @@ -1236,7 +1236,7 @@ fn get_zippers( for x_zid in zids_of_node[&x].iter() { // clone and extend zip to get new zid for this node let mut zip = zip_of_zid[*x_zid].clone(); - zip.add_to_front(ZNode::Arg); + zip.0.insert(0,ZNode::Arg); let zid = zid_of_zip.entry(zip.clone()).or_insert_with(|| { let zid = zip_of_zid.len(); zip_of_zid.push(zip); @@ -1256,7 +1256,7 @@ fn get_zippers( // clone and extend zip to get new zid for this node let mut zip = zip_of_zid[*b_zid].clone(); - zip.add_to_front(ZNode::Body); + zip.0.insert(0,ZNode::Body); let zid = zid_of_zip.entry(zip.clone()).or_insert_with(|| { let zid = zip_of_zid.len(); zip_of_zid.push(zip.clone()); @@ -1275,7 +1275,7 @@ fn get_zippers( // by inserting an IVar to indicate this // how many lambdas are along this zipper? (including most recent one) - let depth_root_to_arg = zip.depth_root_to_arg() as i32; + let depth_root_to_arg = zip.0.iter().filter(|x| **x == ZNode::Body).count() as i32; // find all pointers to $0 (this is the `init_depth` parameter) and replace then with #(num_lams - 1) that is // point past all lambdas except the newly added one. For example if there were no lambdas other than the @@ -1294,11 +1294,11 @@ fn get_zippers( let extensions_of_zid = zip_of_zid.iter().map(|zip| { let mut zip_body = zip.clone(); - zip_body.add_to_end(ZNode::Body); + zip_body.0.push(ZNode::Body); let mut zip_arg = zip.clone(); - zip_arg.add_to_end(ZNode::Arg); + zip_arg.0.push(ZNode::Arg); let mut zip_func = zip.clone(); - zip_func.add_to_end(ZNode::Func); + zip_func.0.push(ZNode::Func); ZIdExtension { body: zid_of_zip.get(&zip_body).copied(), arg: zid_of_zip.get(&zip_arg).copied(), @@ -1695,20 +1695,20 @@ fn use_counts(pattern: &Pattern, zip_of_zid: &[Zipper], arg_of_zid_node: &[FxHas Node::Prim(_) => {}, Node::Var(_, _) => {}, Node::Lam(b, _) => { - curr_zip.add_to_end(ZNode::Body); + curr_zip.0.push(ZNode::Body); let new_zid = extensions_of_zid[curr_zid].body.unwrap(); helper(*b, match_loc, curr_zip, new_zid, zips, zids, arg_of_zid_node, extensions_of_zid, set, counts, analyzed_ivars); - curr_zip.remove_from_end(); + curr_zip.0.pop(); } Node::App(f,x) => { - curr_zip.add_to_end(ZNode::Func); + curr_zip.0.push(ZNode::Func); let new_zid = extensions_of_zid[curr_zid].func.unwrap(); helper(*f, match_loc, curr_zip, new_zid, zips, zids, arg_of_zid_node, extensions_of_zid, set, counts, analyzed_ivars); - curr_zip.remove_from_end(); - curr_zip.add_to_end(ZNode::Arg); + curr_zip.0.pop(); + curr_zip.0.push(ZNode::Arg); let new_zid = extensions_of_zid[curr_zid].arg.unwrap(); helper(*x, match_loc, curr_zip, new_zid, zips, zids, arg_of_zid_node, extensions_of_zid, set, counts, analyzed_ivars); - curr_zip.remove_from_end(); + curr_zip.0.pop(); } _ => unreachable!(), } diff --git a/src/expansion.rs b/src/expansion.rs index 851009f7..372a77b7 100644 --- a/src/expansion.rs +++ b/src/expansion.rs @@ -1,7 +1,7 @@ use std::{fmt::{self, Formatter}, sync::Arc}; use itertools::Itertools; -use lambdas::{Idx, Node, Symbol, Tag, ZId}; +use lambdas::{Idx, Node, Symbol, Tag, ZId, ZNode}; use rustc_hash::{FxHashMap, FxHashSet}; use crate::{invalid_metavar_location, Arg, Cost, LocationsForReusableArgs, Pattern, PatternArgs, SharedData, SymvarInfo, VariableType, ZIdExtension}; @@ -134,7 +134,7 @@ impl std::fmt::Display for ExpandsTo { pub fn tracked_expands_to(pattern: &Pattern, hole_zid: ZId, shared: &SharedData) -> ExpandsTo { // apply the hole zipper to the original expr being tracked to get the subtree // this will expand into, then get the ExpandsTo of that - let idx = shared.tracking.as_ref().unwrap().expr.immut().zip_iter(shared.zip_of_zid[hole_zid].iter()).idx; + let idx = shared.tracking.as_ref().unwrap().expr.immut().zip(&shared.zip_of_zid[hole_zid].0).idx; match expands_to_of_node(&shared.tracking.as_ref().unwrap().expr.set[idx]) { ExpandsTo(ExpandsToInner::IVar(i, VariableType::Metavar)) => { ExpandsTo(ExpandsToInner::IVar(pattern.pattern_args.find_variable(shared, i as usize) as i32, VariableType::Metavar)) @@ -176,7 +176,7 @@ pub fn get_ivars_expansions(original_pattern: &Pattern, arg_of_loc: &FxHashMap 0 { let analyzed_free_vars = &mut AnalyzedExpr::new(FreeVarAnalysis); diff --git a/src/util.rs b/src/util.rs index 1d986673..b52c5ef4 100644 --- a/src/util.rs +++ b/src/util.rs @@ -123,7 +123,7 @@ pub fn num_paths_to_node(roots: &[Idx], corpus_span: &Span, set: &ExprSet) -> (V pub fn zipper_replace(mut expr: ExprOwned, zipper: &Zipper, new: Node) -> ExprOwned { - let idx = expr.immut().zip_iter(zipper.iter()).idx; + let idx = expr.immut().zip_iter(zipper.0.iter()).idx; *expr.as_mut().get_node_mut(idx) = new; expr } \ No newline at end of file diff --git a/src/zipper.rs b/src/zipper.rs index c96516c6..5a4934d3 100644 --- a/src/zipper.rs +++ b/src/zipper.rs @@ -1,7 +1,7 @@ pub use lambdas::{ZNode, ZId, LabelledZId}; #[derive(Clone, Debug, PartialEq, Eq, Hash, Default)] -pub struct Zipper(Vec); +pub struct Zipper(pub Vec); impl Zipper { From 1a038c651d4de62c07b2629b850120a5c93ff53d Mon Sep 17 00:00:00 2001 From: Kavi Gupta Date: Tue, 29 Jul 2025 11:37:23 -0700 Subject: [PATCH 15/20] redo some ADT --- src/compression.rs | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/compression.rs b/src/compression.rs index 5296346c..8aeb3283 100644 --- a/src/compression.rs +++ b/src/compression.rs @@ -335,17 +335,17 @@ fn zids_of_ivar_of_expr(expr: &ExprOwned, zid_of_zip: &FxHashMap) -> zids_of_ivar[*i as usize].push(zid_of_zip.get(curr_zip).cloned().ok_or(())?); }, Node::Lam(b, _) => { - curr_zip.0.push(ZNode::Body); + curr_zip.add_to_end(ZNode::Body); helper(expr.get(*b), curr_zip, zids_of_ivar, zid_of_zip)?; - curr_zip.0.pop(); + curr_zip.remove_from_end(); } Node::App(f,x) => { - curr_zip.0.push(ZNode::Func); + curr_zip.add_to_end(ZNode::Func); helper(expr.get(*f), curr_zip, zids_of_ivar, zid_of_zip)?; - curr_zip.0.pop(); - curr_zip.0.push(ZNode::Arg); + curr_zip.remove_from_end(); + curr_zip.add_to_end(ZNode::Arg); helper(expr.get(*x), curr_zip, zids_of_ivar, zid_of_zip)?; - curr_zip.0.pop(); + curr_zip.remove_from_end(); } } Ok(()) @@ -523,18 +523,18 @@ impl Pattern { Node::Prim(p) => set.add(Node::Prim(p.clone())), Node::Var(v, tag) => set.add(Node::Var(*v, *tag)), Node::Lam(b, tag) => { - curr_zip.0.push(ZNode::Body); + curr_zip.add_to_end(ZNode::Body); let b_idx = helper(set, *b, curr_zip, zips, shared); - curr_zip.0.pop(); + curr_zip.remove_from_end(); set.add(Node::Lam(b_idx, *tag)) } Node::App(f,x) => { - curr_zip.0.push(ZNode::Func); + curr_zip.add_to_end(ZNode::Func); let f_idx = helper(set, *f, curr_zip, zips, shared); - curr_zip.0.pop(); - curr_zip.0.push(ZNode::Arg); + curr_zip.remove_from_end(); + curr_zip.add_to_end(ZNode::Arg); let x_idx = helper(set, *x, curr_zip, zips, shared); - curr_zip.0.pop(); + curr_zip.remove_from_end(); set.add(Node::App(f_idx,x_idx)) } _ => unreachable!(), @@ -1218,7 +1218,7 @@ fn get_zippers( for f_zid in zids_of_node[&f].iter() { // clone and extend zip to get new zid for this node let mut zip = zip_of_zid[*f_zid].clone(); - zip.0.insert(0,ZNode::Func); + zip.add_to_front(ZNode::Func); let zid = zid_of_zip.entry(zip.clone()).or_insert_with(|| { let zid = zip_of_zid.len(); zip_of_zid.push(zip); @@ -1236,7 +1236,7 @@ fn get_zippers( for x_zid in zids_of_node[&x].iter() { // clone and extend zip to get new zid for this node let mut zip = zip_of_zid[*x_zid].clone(); - zip.0.insert(0,ZNode::Arg); + zip.add_to_front(ZNode::Arg); let zid = zid_of_zip.entry(zip.clone()).or_insert_with(|| { let zid = zip_of_zid.len(); zip_of_zid.push(zip); @@ -1256,7 +1256,7 @@ fn get_zippers( // clone and extend zip to get new zid for this node let mut zip = zip_of_zid[*b_zid].clone(); - zip.0.insert(0,ZNode::Body); + zip.add_to_front(ZNode::Body); let zid = zid_of_zip.entry(zip.clone()).or_insert_with(|| { let zid = zip_of_zid.len(); zip_of_zid.push(zip.clone()); @@ -1695,20 +1695,20 @@ fn use_counts(pattern: &Pattern, zip_of_zid: &[Zipper], arg_of_zid_node: &[FxHas Node::Prim(_) => {}, Node::Var(_, _) => {}, Node::Lam(b, _) => { - curr_zip.0.push(ZNode::Body); + curr_zip.add_to_end(ZNode::Body); let new_zid = extensions_of_zid[curr_zid].body.unwrap(); helper(*b, match_loc, curr_zip, new_zid, zips, zids, arg_of_zid_node, extensions_of_zid, set, counts, analyzed_ivars); - curr_zip.0.pop(); + curr_zip.remove_from_end(); } Node::App(f,x) => { - curr_zip.0.push(ZNode::Func); + curr_zip.add_to_end(ZNode::Func); let new_zid = extensions_of_zid[curr_zid].func.unwrap(); helper(*f, match_loc, curr_zip, new_zid, zips, zids, arg_of_zid_node, extensions_of_zid, set, counts, analyzed_ivars); - curr_zip.0.pop(); - curr_zip.0.push(ZNode::Arg); + curr_zip.remove_from_end(); + curr_zip.add_to_end(ZNode::Arg); let new_zid = extensions_of_zid[curr_zid].arg.unwrap(); helper(*x, match_loc, curr_zip, new_zid, zips, zids, arg_of_zid_node, extensions_of_zid, set, counts, analyzed_ivars); - curr_zip.0.pop(); + curr_zip.remove_from_end(); } _ => unreachable!(), } From 840f7bcb20af8ac99549e0da7b0ca1ccc0301781 Mon Sep 17 00:00:00 2001 From: Kavi Gupta Date: Tue, 29 Jul 2025 11:45:43 -0700 Subject: [PATCH 16/20] inline always --- src/zipper.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/zipper.rs b/src/zipper.rs index 5a4934d3..2051a644 100644 --- a/src/zipper.rs +++ b/src/zipper.rs @@ -6,42 +6,42 @@ pub struct Zipper(pub Vec); impl Zipper { - #[inline] + #[inline(always)] pub fn iter(&self) -> impl Iterator { self.0.iter() } - #[inline] + #[inline(always)] pub fn ends_with_func(&self) -> bool { matches!(self.0.last(), Some(ZNode::Func)) } - #[inline] + #[inline(always)] pub fn function_arity(&self) -> usize { self.0.iter().rev().take_while(|znode| **znode == ZNode::Func).count() } - #[inline] + #[inline(always)] pub fn depth_root_to_arg(&self) -> usize { self.0.iter().filter(|x| **x == ZNode::Body).count() } - #[inline] + #[inline(always)] pub fn starts_with(&self, other: &Zipper) -> bool { self.0.starts_with(&other.0) } - #[inline] + #[inline(always)] pub fn add_to_front(&mut self, node: ZNode) { self.0.insert(0, node); } - #[inline] + #[inline(always)] pub fn add_to_end(&mut self, node: ZNode) { self.0.push(node); } - #[inline] + #[inline(always)] pub fn remove_from_end(&mut self) { self.0.pop(); } From b75c653038c7c35ece57cd231145fc08f9e06b8d Mon Sep 17 00:00:00 2001 From: Kavi Gupta Date: Tue, 29 Jul 2025 11:56:27 -0700 Subject: [PATCH 17/20] one more adt --- src/compression.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compression.rs b/src/compression.rs index 8aeb3283..411010b8 100644 --- a/src/compression.rs +++ b/src/compression.rs @@ -1294,11 +1294,11 @@ fn get_zippers( let extensions_of_zid = zip_of_zid.iter().map(|zip| { let mut zip_body = zip.clone(); - zip_body.0.push(ZNode::Body); + zip_body.add_to_end(ZNode::Body); let mut zip_arg = zip.clone(); - zip_arg.0.push(ZNode::Arg); + zip_arg.add_to_end(ZNode::Arg); let mut zip_func = zip.clone(); - zip_func.0.push(ZNode::Func); + zip_func.add_to_end(ZNode::Func); ZIdExtension { body: zid_of_zip.get(&zip_body).copied(), arg: zid_of_zip.get(&zip_arg).copied(), From 9abf319bf725f573fc91dfb398b22352becd6682 Mon Sep 17 00:00:00 2001 From: Kavi Gupta Date: Tue, 29 Jul 2025 12:11:07 -0700 Subject: [PATCH 18/20] more adt --- src/compression.rs | 4 ++-- src/expansion.rs | 4 ++-- src/rewriting.rs | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/compression.rs b/src/compression.rs index 411010b8..07d3c642 100644 --- a/src/compression.rs +++ b/src/compression.rs @@ -971,7 +971,7 @@ fn stitch_search( // Pruning (FREE VARS): if an invention has free variables in the body then it's not a real function and we can discard it // Here we just check if our expansion just yielded a variable, and if that is bound based on how many lambdas there are above it. - if expands_to.free_variable(shared.zip_of_zid[hole_zid].0.iter().filter(|znode|**znode == ZNode::Body).count()) { + if expands_to.free_variable(shared.zip_of_zid[hole_zid].depth_root_to_arg()) { if !shared.cfg.no_stats { shared.stats.lock().deref_mut().free_vars_fired += 1; }; if tracked && !shared.cfg.quiet { println!("{} pruned by free var in body when expanding {} to {}", "[TRACK]".red().bold(), original_pattern.to_expr(&shared), original_pattern.show_track_expansion(hole_zid, &shared)) } continue 'expansion; // free var @@ -1275,7 +1275,7 @@ fn get_zippers( // by inserting an IVar to indicate this // how many lambdas are along this zipper? (including most recent one) - let depth_root_to_arg = zip.0.iter().filter(|x| **x == ZNode::Body).count() as i32; + let depth_root_to_arg = zip.depth_root_to_arg() as i32; // find all pointers to $0 (this is the `init_depth` parameter) and replace then with #(num_lams - 1) that is // point past all lambdas except the newly added one. For example if there were no lambdas other than the diff --git a/src/expansion.rs b/src/expansion.rs index 372a77b7..ddd30737 100644 --- a/src/expansion.rs +++ b/src/expansion.rs @@ -1,7 +1,7 @@ use std::{fmt::{self, Formatter}, sync::Arc}; use itertools::Itertools; -use lambdas::{Idx, Node, Symbol, Tag, ZId, ZNode}; +use lambdas::{Idx, Node, Symbol, Tag, ZId}; use rustc_hash::{FxHashMap, FxHashSet}; use crate::{invalid_metavar_location, Arg, Cost, LocationsForReusableArgs, Pattern, PatternArgs, SharedData, SymvarInfo, VariableType, ZIdExtension}; @@ -176,7 +176,7 @@ pub fn get_ivars_expansions(original_pattern: &Pattern, arg_of_loc: &FxHashMap 0 { let analyzed_free_vars = &mut AnalyzedExpr::new(FreeVarAnalysis); From fbc80640d9967e4acecb4515fd60ec2c7a1302e0 Mon Sep 17 00:00:00 2001 From: Kavi Gupta Date: Tue, 29 Jul 2025 12:18:54 -0700 Subject: [PATCH 19/20] zip --- src/compression.rs | 2 +- src/expansion.rs | 2 +- src/util.rs | 2 +- src/zipper.rs | 9 ++++++++- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/compression.rs b/src/compression.rs index 07d3c642..3625ee8e 100644 --- a/src/compression.rs +++ b/src/compression.rs @@ -550,7 +550,7 @@ impl Pattern { let mut expr = self.to_expr(shared); let expands_to = format!("{}",tracked_expands_to(self, hole_zid, shared)).magenta().bold().to_string(); let replace_sentinel = Node::Prim("".into()); - let idx = expr.immut().zip(&shared.zip_of_zid[hole_zid].0).idx; + let idx = shared.zip_of_zid[hole_zid].zip(&expr); expr.set[idx] = replace_sentinel; expr.to_string().replace("", &expands_to) } diff --git a/src/expansion.rs b/src/expansion.rs index ddd30737..3c853f3d 100644 --- a/src/expansion.rs +++ b/src/expansion.rs @@ -134,7 +134,7 @@ impl std::fmt::Display for ExpandsTo { pub fn tracked_expands_to(pattern: &Pattern, hole_zid: ZId, shared: &SharedData) -> ExpandsTo { // apply the hole zipper to the original expr being tracked to get the subtree // this will expand into, then get the ExpandsTo of that - let idx = shared.tracking.as_ref().unwrap().expr.immut().zip(&shared.zip_of_zid[hole_zid].0).idx; + let idx = shared.zip_of_zid[hole_zid].zip(&shared.tracking.as_ref().unwrap().expr); match expands_to_of_node(&shared.tracking.as_ref().unwrap().expr.set[idx]) { ExpandsTo(ExpandsToInner::IVar(i, VariableType::Metavar)) => { ExpandsTo(ExpandsToInner::IVar(pattern.pattern_args.find_variable(shared, i as usize) as i32, VariableType::Metavar)) diff --git a/src/util.rs b/src/util.rs index b52c5ef4..fb330a3f 100644 --- a/src/util.rs +++ b/src/util.rs @@ -123,7 +123,7 @@ pub fn num_paths_to_node(roots: &[Idx], corpus_span: &Span, set: &ExprSet) -> (V pub fn zipper_replace(mut expr: ExprOwned, zipper: &Zipper, new: Node) -> ExprOwned { - let idx = expr.immut().zip_iter(zipper.0.iter()).idx; + let idx = zipper.zip(&expr); *expr.as_mut().get_node_mut(idx) = new; expr } \ No newline at end of file diff --git a/src/zipper.rs b/src/zipper.rs index 2051a644..1dc65b44 100644 --- a/src/zipper.rs +++ b/src/zipper.rs @@ -1,7 +1,8 @@ +use lambdas::ExprOwned; pub use lambdas::{ZNode, ZId, LabelledZId}; #[derive(Clone, Debug, PartialEq, Eq, Hash, Default)] -pub struct Zipper(pub Vec); +pub struct Zipper(Vec); impl Zipper { @@ -45,4 +46,10 @@ impl Zipper { pub fn remove_from_end(&mut self) { self.0.pop(); } + + #[inline(always)] + pub fn zip(&self, expr: &ExprOwned) -> ZId { + expr.immut().zip(&self.0).idx + } + } \ No newline at end of file From d16ec656074f8e647efa2ef74ecfaddb84124f61 Mon Sep 17 00:00:00 2001 From: Kavi Gupta Date: Tue, 29 Jul 2025 12:22:48 -0700 Subject: [PATCH 20/20] clean up --- src/zipper.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/zipper.rs b/src/zipper.rs index 1dc65b44..1dc5d0e4 100644 --- a/src/zipper.rs +++ b/src/zipper.rs @@ -7,11 +7,6 @@ pub struct Zipper(Vec); impl Zipper { - #[inline(always)] - pub fn iter(&self) -> impl Iterator { - self.0.iter() - } - #[inline(always)] pub fn ends_with_func(&self) -> bool { matches!(self.0.last(), Some(ZNode::Func))