Skip to content

Commit 31c1117

Browse files
authored
Simplify object construction. (#163)
1 parent 03cbbcc commit 31c1117

File tree

2 files changed

+63
-78
lines changed

2 files changed

+63
-78
lines changed

jaq-interpret/src/filter.rs

+7-29
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ pub(crate) enum Ast {
6262
Float(f64),
6363
Str(String),
6464
Array(Id),
65-
Object(Box<[(Id, Id)]>),
65+
ObjEmpty,
66+
ObjSingle(Id, Id),
6667

6768
Try(Id, Id),
6869
Neg(Id),
@@ -142,25 +143,6 @@ fn run_cvs<'a>(f: Ref<'a>, cvs: Results<'a, Cv<'a>, Error>) -> impl Iterator<Ite
142143
cvs.flat_map(move |cv| then(cv, |cv| f.run(cv)))
143144
}
144145

145-
type ObjVec = Vec<(ValR, ValR)>;
146-
fn obj_cart<'a, I>(mut args: I, cv: Cv<'a>, prev: ObjVec) -> BoxIter<'a, ObjVec>
147-
where
148-
I: Iterator<Item = (Ref<'a>, Ref<'a>)> + Clone + 'a,
149-
{
150-
if let Some((l, r)) = args.next() {
151-
let iter = l.run(cv.clone());
152-
flat_map_with(iter, (args, cv, prev), move |l, (args, cv, prev)| {
153-
let iter = r.run(cv.clone());
154-
flat_map_with(iter, (l, args, cv, prev), |r, (l, args, cv, mut prev)| {
155-
prev.push((l, r));
156-
obj_cart(args, cv, prev)
157-
})
158-
})
159-
} else {
160-
box_once(prev)
161-
}
162-
}
163-
164146
fn reduce<'a, T: Clone + 'a, F>(xs: Results<'a, T, Error>, init: Val, f: F) -> ValRs
165147
where
166148
F: Fn(T, Val) -> ValRs<'a> + 'a,
@@ -240,14 +222,10 @@ impl<'a> FilterT<'a> for Ref<'a> {
240222
Ast::Array(f) => Box::new(once_with(move || {
241223
w(f).run(cv).collect::<Result<_, _>>().map(Val::arr)
242224
})),
243-
Ast::Object(o) if o.is_empty() => box_once(Ok(Val::Obj(Default::default()))),
244-
Ast::Object(o) => Box::new(
245-
obj_cart(o.iter().map(move |(k, v)| (w(k), w(v))), cv, Vec::new()).map(|kvs| {
246-
kvs.into_iter()
247-
.map(|(k, v)| Ok((k?.to_str()?, v?)))
248-
.collect::<Result<_, _>>()
249-
.map(Val::obj)
250-
}),
225+
Ast::ObjEmpty => box_once(Ok(Val::Obj(Default::default()))),
226+
Ast::ObjSingle(k, v) => Box::new(
227+
Self::cartesian(w(k), w(v), cv)
228+
.map(|(k, v)| Ok(Val::obj([(k?.to_str()?, v?)].into_iter().collect()))),
251229
),
252230
Ast::Try(f, c) => Box::new(w(f).run((cv.0.clone(), cv.1)).flat_map(move |y| {
253231
y.map_or_else(
@@ -364,7 +342,7 @@ impl<'a> FilterT<'a> for Ref<'a> {
364342
match &self.1[self.0 .0] {
365343
Ast::ToString => err,
366344
Ast::Int(_) | Ast::Float(_) | Ast::Str(_) => err,
367-
Ast::Array(_) | Ast::Object(_) => err,
345+
Ast::Array(_) | Ast::ObjEmpty | Ast::ObjSingle(..) => err,
368346
Ast::Neg(_) | Ast::Logic(..) | Ast::Math(..) | Ast::Ord(..) => err,
369347
Ast::Update(..) | Ast::UpdateMath(..) | Ast::Assign(..) => err,
370348

jaq-interpret/src/lir.rs

+56-49
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,9 @@ fn recurse(typ: CallTyp) -> Filter {
6666
impl Ctx {
6767
/// `{}[]` returns zero values.
6868
fn empty(&mut self) -> Filter {
69-
// `{}`
70-
let obj = Filter::Object(Default::default());
7169
// `[]`
7270
let path = (path::Part::Range(None, None), path::Opt::Essential);
73-
Filter::Path(self.id_of_ast(obj), Path(Vec::from([path])))
71+
Filter::Path(self.id_of_ast(Filter::ObjEmpty), Path(Vec::from([path])))
7472
}
7573

7674
/// `..`, also known as `recurse/0`, is defined as `., (.[]? | ..)`
@@ -128,31 +126,52 @@ impl Ctx {
128126
AbsId(len)
129127
}
130128

129+
fn get(&mut self, f: Spanned<mir::Filter>) -> AbsId {
130+
let f = self.filter(f);
131+
self.id_of_ast(f)
132+
}
133+
134+
fn add(&mut self, l: Filter, r: Filter) -> Filter {
135+
Filter::Math(self.id_of_ast(l), MathOp::Add, self.id_of_ast(r))
136+
}
137+
138+
fn of_str(&mut self, s: Str<Spanned<mir::Filter>>) -> Filter {
139+
let fmt = s.fmt.map_or(TOSTRING, |fmt| self.get(*fmt));
140+
use jaq_syn::string::Part;
141+
let iter = s.parts.into_iter().map(|part| match part {
142+
Part::Str(s) => Filter::Str(s),
143+
Part::Fun(f) => Filter::Pipe(self.get(f), false, fmt),
144+
});
145+
let mut iter = iter.collect::<Vec<_>>().into_iter().rev();
146+
let last = iter.next().unwrap_or_else(|| Filter::Str("".into()));
147+
iter.fold(last, |acc, x| self.add(x, acc))
148+
}
149+
150+
fn of_key_val(&mut self, kv: KeyVal<Spanned<mir::Filter>>) -> Filter {
151+
match kv {
152+
KeyVal::Filter(k, v) => Filter::ObjSingle(self.get(k), self.get(v)),
153+
KeyVal::Str(k, v) => {
154+
let k = self.of_str(k);
155+
let k = self.id_of_ast(k);
156+
let v = match v {
157+
None => {
158+
self.id_of_ast(Filter::Path(IDENTITY, Path::from(path::Part::Index(k))))
159+
}
160+
Some(v) => self.get(v),
161+
};
162+
Filter::ObjSingle(k, v)
163+
}
164+
}
165+
}
166+
131167
/// Convert a MIR filter to a LIR filter.
132168
fn filter(&mut self, f: Spanned<mir::Filter>) -> Filter {
133-
let get = |f, ctx: &mut Self| {
134-
let f = ctx.filter(f);
135-
ctx.id_of_ast(f)
136-
};
137-
let of_str = |s: Str<_>, ctx: &mut Self| {
138-
let fmt = s.fmt.map_or(TOSTRING, |fmt| get(*fmt, ctx));
139-
use jaq_syn::string::Part;
140-
let iter = s.parts.into_iter().map(|part| match part {
141-
Part::Str(s) => Filter::Str(s),
142-
Part::Fun(f) => Filter::Pipe(get(f, ctx), false, fmt),
143-
});
144-
let mut iter = iter.collect::<Vec<_>>().into_iter().rev();
145-
let last = iter.next();
146-
iter.fold(last.unwrap_or_else(|| Filter::Str("".into())), |acc, x| {
147-
Filter::Math(ctx.id_of_ast(x), MathOp::Add, ctx.id_of_ast(acc))
148-
})
149-
};
150169
use mir::Filter as Expr;
151170

152171
match f.0 {
153172
Expr::Var(v) => Filter::Var(v),
154173
Expr::Call(call, args) => {
155-
let args: Vec<_> = args.into_iter().map(|a| get(a, self)).collect();
174+
let args: Vec<_> = args.into_iter().map(|a| self.get(a)).collect();
156175
match call {
157176
mir::Call::Arg(a) if args.is_empty() => Filter::Var(a),
158177
mir::Call::Arg(_) => panic!("higher-order argument encountered"),
@@ -180,38 +199,26 @@ impl Ctx {
180199
}
181200

182201
Expr::Fold(typ, Fold { xs, init, f, .. }) => {
183-
Filter::Fold(typ, get(*xs, self), get(*init, self), get(*f, self))
202+
Filter::Fold(typ, self.get(*xs), self.get(*init), self.get(*f))
184203
}
185204

186205
Expr::Id => Filter::Id,
187206
Expr::Num(hir::Num::Float(f)) => Filter::Float(f),
188207
Expr::Num(hir::Num::Int(i)) => Filter::Int(i),
189-
Expr::Str(s) => of_str(*s, self),
190-
Expr::Array(a) => Filter::Array(a.map_or(EMPTY, |a| get(*a, self))),
208+
Expr::Str(s) => self.of_str(*s),
209+
Expr::Array(a) => Filter::Array(a.map_or(EMPTY, |a| self.get(*a))),
191210
Expr::Object(o) => {
192-
let kvs = o.into_iter().map(|kv| match kv {
193-
KeyVal::Filter(k, v) => (get(k, self), get(v, self)),
194-
KeyVal::Str(k, v) => {
195-
let k = of_str(k, self);
196-
let k = self.id_of_ast(k);
197-
let v = match v {
198-
None => self.id_of_ast(Filter::Path(
199-
IDENTITY,
200-
Path::from(path::Part::Index(k)),
201-
)),
202-
Some(v) => get(v, self),
203-
};
204-
(k, v)
205-
}
206-
});
207-
Filter::Object(kvs.collect())
211+
let kvs = o.into_iter().map(|kv| self.of_key_val(kv));
212+
let mut kvs = kvs.collect::<Vec<_>>().into_iter().rev();
213+
let last = kvs.next().unwrap_or(Filter::ObjEmpty);
214+
kvs.fold(last, |acc, x| self.add(x, acc))
208215
}
209-
Expr::Try(f) => Filter::Try(get(*f, self), EMPTY),
210-
Expr::Neg(f) => Filter::Neg(get(*f, self)),
216+
Expr::Try(f) => Filter::Try(self.get(*f), EMPTY),
217+
Expr::Neg(f) => Filter::Neg(self.get(*f)),
211218
Expr::Recurse => recurse(CallTyp::Catch),
212219

213220
Expr::Binary(l, op, r) => {
214-
let (l, r) = (get(*l, self), get(*r, self));
221+
let (l, r) = (self.get(*l), self.get(*r));
215222
match op {
216223
BinaryOp::Pipe(bind) => Filter::Pipe(l, bind.is_some(), r),
217224
BinaryOp::Comma => Filter::Comma(l, r),
@@ -229,20 +236,20 @@ impl Ctx {
229236
Expr::Ite(if_thens, else_) => {
230237
let else_ = else_.map_or(Filter::Id, |else_| self.filter(*else_));
231238
if_thens.into_iter().rev().fold(else_, |acc, (if_, then_)| {
232-
Filter::Ite(get(if_, self), get(then_, self), self.id_of_ast(acc))
239+
Filter::Ite(self.get(if_), self.get(then_), self.id_of_ast(acc))
233240
})
234241
}
235242
Expr::TryCatch(try_, catch_) => {
236-
Filter::Try(get(*try_, self), catch_.map_or(EMPTY, |c| get(*c, self)))
243+
Filter::Try(self.get(*try_), catch_.map_or(EMPTY, |c| self.get(*c)))
237244
}
238245
Expr::Path(f, path) => {
239-
let f = get(*f, self);
246+
let f = self.get(*f);
240247
use jaq_syn::path::Part;
241248
let path = path.into_iter().map(|(p, opt)| match p {
242-
Part::Index(i) => (path::Part::Index(get(i, self)), opt),
249+
Part::Index(i) => (path::Part::Index(self.get(i)), opt),
243250
Part::Range(lower, upper) => {
244-
let lower = lower.map(|f| get(f, self));
245-
let upper = upper.map(|f| get(f, self));
251+
let lower = lower.map(|f| self.get(f));
252+
let upper = upper.map(|f| self.get(f));
246253
(path::Part::Range(lower, upper), opt)
247254
}
248255
});

0 commit comments

Comments
 (0)