///|
fn optimize(filter : Filter) -> Filter {
match filter {
Pipe(left, right) => {
let l = optimize(left)
let r = optimize(right)
match (l, r) {
(Identity, r) => r
(l, Identity) => l
_ => Pipe(l, r)
}
}
Comma(left, right) => Comma(optimize(left), optimize(right))
Paren(inner) => optimize(inner)
ArrayConstruct(Some(inner)) => ArrayConstruct(Some(optimize(inner)))
ObjectConstruct(fields) => {
let opt_fields : Array[(ObjKey, Filter)] = []
for i = 0; i < fields.length(); i = i + 1 {
let (key, value) = fields[i]
let opt_key = match key {
ExprKey(expr) => ExprKey(optimize(expr))
_ => key
}
opt_fields.push((opt_key, optimize(value)))
}
ObjectConstruct(opt_fields)
}
Try(inner) => Try(optimize(inner))
TryCatch(inner, handler) => TryCatch(optimize(inner), optimize(handler))
IfThenElse(cond, then_b, else_b) =>
IfThenElse(optimize(cond), optimize(then_b), optimize(else_b))
Binding(pat, expr, body) => Binding(pat, optimize(expr), optimize(body))
Reduce(iter, pat, init, update) =>
Reduce(optimize(iter), pat, optimize(init), optimize(update))
FuncDef(name, params, body, rest) =>
FuncDef(name, params, optimize(body), optimize(rest))
FuncCall(name, args) => {
let opt_args : Array[Filter] = []
for i = 0; i < args.length(); i = i + 1 {
opt_args.push(optimize(args[i]))
}
FuncCall(name, opt_args)
}
Neg(inner) => Neg(optimize(inner))
Arith(op, left, right) => Arith(op, optimize(left), optimize(right))
Compare(op, left, right) => Compare(op, optimize(left), optimize(right))
LogicAnd(left, right) => LogicAnd(optimize(left), optimize(right))
LogicOr(left, right) => LogicOr(optimize(left), optimize(right))
DynIndex(expr) => DynIndex(optimize(expr))
PostfixDynIndex(base, idx) => PostfixDynIndex(optimize(base), optimize(idx))
DynSlice(base, start, end) =>
DynSlice(optimize(base), start.map(optimize), end.map(optimize))
Alternative(left, right) => Alternative(optimize(left), optimize(right))
Foreach(iter, pat, init, update, extract) =>
Foreach(
optimize(iter),
pat,
optimize(init),
optimize(update),
extract.map(optimize),
)
StringInterp(parts) => {
let opt_parts : Array[(String, Filter?)] = []
for part in parts {
let (lit, filter_opt) = part
opt_parts.push(
(
lit,
match filter_opt {
Some(f) => Some(optimize(f))
None => None
},
),
)
}
StringInterp(opt_parts)
}
Assign(path_expr, value_expr) =>
Assign(optimize(path_expr), optimize(value_expr))
Update(path_expr, update_filter) =>
Update(optimize(path_expr), optimize(update_filter))
UpdateAlt(path_expr, value_expr) =>
UpdateAlt(optimize(path_expr), optimize(value_expr))
Label(name, body) => Label(name, optimize(body))
Break(_) => filter
BindingAlt(patterns, expr, body) =>
BindingAlt(patterns, optimize(expr), optimize(body))
_ => filter
}
}