///|
/// Compile a jq filter through released public AST adaptations for string
/// slicing and stable grouping of complete key streams.
fn parse_filter(source : String) -> @ast.Expr raise {
lower(@moonjq.parse(source).expr)
}
///|
fn lower(expr : @ast.Expr) -> @ast.Expr {
match expr {
Slice(start, end) => {
let string_type : @ast.Expr = Operation(
Type,
Equal,
Literal(String("string")),
)
let sequence_type : @ast.Expr = Operation(
Operation(Type, Equal, Literal(String("array"))),
Or,
Operation(Type, Equal, Literal(String("null"))),
)
IfThenElse(
string_type,
Pipe(Explode, Pipe(Slice(start, end), Implode)),
IfThenElse(sequence_type, expr, Explode),
)
}
Pipe(a, b) => Pipe(lower(a), lower(b))
Comma(a, b) => Comma(lower(a), lower(b))
Optional(a) => Optional(lower(a))
ArrayConstruct(a) => ArrayConstruct(a.map(lower))
ObjectConstruct(fields) =>
ObjectConstruct(fields.map(pair => (lower(pair.0), pair.1.map(lower))))
Operation(a, op, b) => Operation(lower(a), op, lower(b))
Map(a) => Map(lower(a))
Select(a) => Select(lower(a))
SortBy(a) => lower_sorting(lower(a))
UniqueBy(a) => UniqueBy(lower(a))
GroupBy(a) => lower_grouping(lower(a))
MinBy(a) => MinBy(lower(a))
MaxBy(a) => MaxBy(lower(a))
Contains(a) => Contains(lower(a))
Inside(a) => Inside(lower(a))
In(a) => In(lower(a))
WithEntries(a) => WithEntries(lower(a))
MapValues(a) => MapValues(lower(a))
RangeFromTo(a, b) => RangeFromTo(lower(a), lower(b))
RangeWithStep(a, b, c) => RangeWithStep(lower(a), lower(b), lower(c))
FirstGen(a) => FirstGen(lower(a))
LastGen(a) => LastGen(lower(a))
Repeat(a) => Repeat(lower(a))
IndicesOf(a) => IndicesOf(lower(a))
IndexOf(a) => IndexOf(lower(a))
AnyGen(a, b) => AnyGen(lower(a), lower(b))
AllGen(a, b) => AllGen(lower(a), lower(b))
IfThenElse(a, b, c) => IfThenElse(lower(a), lower(b), lower(c))
TryCatch(a, b) => TryCatch(lower(a), b.map(lower))
As(a, name, b) => As(lower(a), name, lower(b))
Reduce(a, name, b, c) => Reduce(lower(a), name, lower(b), lower(c))
Foreach(a, name, b, c, d) =>
Foreach(lower(a), name, lower(b), lower(c), d.map(lower))
RecurseWith(a, b) => RecurseWith(lower(a), lower(b))
Walk(a) => Walk(lower(a))
// Assignment/path operands describe locations, not value evaluation.
Update(path, value) => Update(path, lower(value))
Assign(path, value) => Assign(path, lower(value))
AddAssign(path, value) => AddAssign(path, lower(value))
SubAssign(path, value) => SubAssign(path, lower(value))
MulAssign(path, value) => MulAssign(path, lower(value))
DivAssign(path, value) => DivAssign(path, lower(value))
ModAssign(path, value) => ModAssign(path, lower(value))
AltAssign(path, value) => AltAssign(path, lower(value))
Alternative(a, b) => Alternative(lower(a), lower(b))
StringInterpolation(parts) =>
StringInterpolation(parts.map(pair => (pair.0, pair.1.map(lower))))
FunctionDef(name, parameters, body) =>
FunctionDef(name, parameters, lower(body))
FunctionCall(name, args) => FunctionCall(name, args.map(lower))
RIndex(a) => RIndex(lower(a))
PathsWithFilter(a) => PathsWithFilter(lower(a))
GetPath(a) => GetPath(lower(a))
SetPath(a, b) => SetPath(lower(a), lower(b))
DelPaths(a) => DelPaths(lower(a))
Limit(n, a) => Limit(n, lower(a))
Until(a, b) => Until(lower(a), lower(b))
While(a, b) => While(lower(a), lower(b))
Pow(a) => Pow(lower(a))
_ => expr
}
}