From 357984c2191c78733b5bdae336c04eb6b2cb62a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20F=C3=A4rber?= <01mf02@gmail.com> Date: Fri, 27 Oct 2023 12:13:01 +0200 Subject: [PATCH] Generate objects lazily. --- Cargo.lock | 1 - jaq-interpret/Cargo.toml | 1 - jaq-interpret/src/filter.rs | 42 +++++++++++++++++++++++++++---------- jaq-interpret/src/lib.rs | 3 ++- jaq-interpret/src/lir.rs | 2 -- jaq-interpret/src/path.rs | 4 ++-- 6 files changed, 35 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1fdcbb03e..1d7626f87 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -298,7 +298,6 @@ dependencies = [ "dyn-clone", "hifijson", "indexmap", - "itertools", "jaq-parse", "jaq-syn", "once_cell", diff --git a/jaq-interpret/Cargo.toml b/jaq-interpret/Cargo.toml index 8247e3c4b..b503716e0 100644 --- a/jaq-interpret/Cargo.toml +++ b/jaq-interpret/Cargo.toml @@ -21,7 +21,6 @@ ahash = "0.7.6" dyn-clone = "1.0" hifijson = { version = "0.2.0", optional = true } indexmap = "2.0" -itertools = "0.10.3" once_cell = "1.16.0" serde_json = { version = "1.0.81", optional = true } diff --git a/jaq-interpret/src/filter.rs b/jaq-interpret/src/filter.rs index 757e26143..2b865a105 100644 --- a/jaq-interpret/src/filter.rs +++ b/jaq-interpret/src/filter.rs @@ -1,4 +1,4 @@ -use crate::box_iter::{box_once, flat_map_with, map_with}; +use crate::box_iter::{box_once, flat_map_with, map_with, BoxIter}; use crate::results::{fold, recurse, then, Results}; use crate::val::{Val, ValR, ValRs}; use crate::{rc_lazy_list, Bind, Ctx, Error}; @@ -120,6 +120,30 @@ where } } +type ObjVec = Vec<(ValR, ValR)>; +fn obj_cart<'a, I>(mut args: I, cv: Cv<'a>, prev: ObjVec) -> BoxIter<'a, ObjVec> +where + I: Iterator, Ref<'a>)> + Clone + 'a, +{ + match args.next() { + Some((l, r)) => flat_map_with( + l.run(cv.clone()), + (args, cv, prev), + move |l, (args, cv, prev)| { + flat_map_with( + r.run(cv.clone()), + (l, args, cv, prev), + |r, (l, args, cv, mut prev)| { + prev.push((l, r)); + obj_cart(args, cv, prev) + }, + ) + }, + ), + None => box_once(prev), + } +} + fn reduce<'a, T: Clone + 'a, F>(xs: Results<'a, T, Error>, init: Val, f: F) -> ValRs where F: Fn(T, Val) -> ValRs<'a> + 'a, @@ -188,7 +212,6 @@ impl<'a> FilterT<'a> for &'a Owned { impl<'a> FilterT<'a> for Ref<'a> { fn run(self, cv: Cv<'a>) -> ValRs<'a> { use core::iter::once; - use itertools::Itertools; // wrap a filter AST with the filter definitions let w = move |id: &Id| Ref(*id, self.1); match &self.1[self.0 .0] { @@ -200,15 +223,12 @@ impl<'a> FilterT<'a> for Ref<'a> { Ast::Array(f) => box_once(w(f).run(cv).collect::>().map(Val::arr)), Ast::Object(o) if o.is_empty() => box_once(Ok(Val::Obj(Default::default()))), Ast::Object(o) => Box::new( - o.iter() - .map(|(k, v)| Self::cartesian(w(k), w(v), cv.clone()).collect::>()) - .multi_cartesian_product() - .map(|kvs| { - kvs.into_iter() - .map(|(k, v)| Ok((k?.to_str()?, v?))) - .collect::>() - .map(Val::obj) - }), + obj_cart(o.iter().map(move |(k, v)| (w(k), w(v))), cv, Vec::new()).map(|kvs| { + kvs.into_iter() + .map(|(k, v)| Ok((k?.to_str()?, v?))) + .collect::>() + .map(Val::obj) + }), ), Ast::Try(f, c) => Box::new(w(f).run((cv.0.clone(), cv.1)).flat_map(move |y| { y.map_or_else( diff --git a/jaq-interpret/src/lib.rs b/jaq-interpret/src/lib.rs index 05235a477..63209b534 100644 --- a/jaq-interpret/src/lib.rs +++ b/jaq-interpret/src/lib.rs @@ -191,6 +191,7 @@ impl ParseCtx { let inputs = RcIter::new(core::iter::empty()); let out = f.run((Ctx::new([], &inputs), x)); - itertools::assert_equal(out, ys); + + assert!(out.eq(ys)) } } diff --git a/jaq-interpret/src/lir.rs b/jaq-interpret/src/lir.rs index c6d40034a..f2dab0f3b 100644 --- a/jaq-interpret/src/lir.rs +++ b/jaq-interpret/src/lir.rs @@ -31,8 +31,6 @@ pub fn root_def(def: mir::Def) -> filter::Owned { filter::Owned::new(id, ctx.defs) } -// TODO: remove itertools dependency - impl Ctx { fn init_constants(&mut self) { for (f, id) in [(Filter::Id, IDENTITY), (Filter::ToString, TOSTRING)] { diff --git a/jaq-interpret/src/path.rs b/jaq-interpret/src/path.rs index 4885ff2a0..efd83817f 100644 --- a/jaq-interpret/src/path.rs +++ b/jaq-interpret/src/path.rs @@ -202,8 +202,8 @@ fn prod<'a, T: 'a + Clone>( l: impl Iterator + 'a, r: impl Iterator + 'a, ) -> impl Iterator + 'a { - use itertools::Itertools; - l.cartesian_product(r.collect::>()) + let r: Vec<_> = r.collect(); + l.flat_map(move |l| r.clone().into_iter().map(move |r| (l.clone(), r))) } fn skip_take(from: usize, until: usize) -> (usize, usize) {