From 9dffad1517883b7f3f12017bded1f82d886b47e3 Mon Sep 17 00:00:00 2001 From: Mattias Wadman Date: Sat, 21 Aug 2021 21:19:38 +0200 Subject: [PATCH] Add token position and query json marshal support --- _tools/gen_builtin.go | 4 +- builtin.go | 154 +++++++++++------------ compiler.go | 148 +++++++++++----------- error.go | 2 +- func.go | 2 +- lexer.go | 29 +++-- module_loader.go | 4 +- operator.go | 81 +++++++++++- parser.go | 8 +- parser.go.y | 8 +- query.go | 284 +++++++++++++++++++++--------------------- query_test.go | 12 +- term_type.go | 91 +++++++++++++- 13 files changed, 506 insertions(+), 321 deletions(-) diff --git a/_tools/gen_builtin.go b/_tools/gen_builtin.go index ebd61d22..e0965286 100644 --- a/_tools/gen_builtin.go +++ b/_tools/gen_builtin.go @@ -44,12 +44,12 @@ func run(input, output string) error { return err } for _, fd := range q.FuncDefs { - name := fd.Name + name := fd.Name.Str if name[0] == '_' { name = name[1:] } fd.Minify() - qs[name] = append(qs[fd.Name], fd) + qs[name] = append(qs[fd.Name.Str], fd) } t, err := astgen.Build(qs) if err != nil { diff --git a/builtin.go b/builtin.go index 7be5777e..172c222e 100644 --- a/builtin.go +++ b/builtin.go @@ -4,82 +4,82 @@ package gojq func init() { builtinFuncDefs = map[string][]*FuncDef{ - "IN": []*FuncDef{&FuncDef{Name: "IN", Args: []string{"s"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "any", Args: []*Query{&Query{Left: &Query{Func: "s"}, Op: OpEq, Right: &Query{Func: "."}}, &Query{Func: "."}}}}}}, &FuncDef{Name: "IN", Args: []string{"src", "s"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "any", Args: []*Query{&Query{Left: &Query{Func: "src"}, Op: OpEq, Right: &Query{Func: "s"}}, &Query{Func: "."}}}}}}}, - "INDEX": []*FuncDef{&FuncDef{Name: "INDEX", Args: []string{"stream", "idx_expr"}, Body: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "stream"}}, Pattern: &Pattern{Name: "$row"}, Start: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{}}}, Update: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Left: &Query{Func: "$row"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "idx_expr"}, Op: OpPipe, Right: &Query{Func: "tostring"}}}}}}, Op: OpAssign, Right: &Query{Func: "$row"}}}}}}, &FuncDef{Name: "INDEX", Args: []string{"idx_expr"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "INDEX", Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, &Query{Func: "idx_expr"}}}}}}}, - "JOIN": []*FuncDef{&FuncDef{Name: "JOIN", Args: []string{"$idx", "idx_expr"}, Body: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$idx"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Func: "idx_expr"}}}}}}}}}}}}}}}, &FuncDef{Name: "JOIN", Args: []string{"$idx", "stream", "idx_expr"}, Body: &Query{Left: &Query{Func: "stream"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$idx"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Func: "idx_expr"}}}}}}}}}}}}, &FuncDef{Name: "JOIN", Args: []string{"$idx", "stream", "idx_expr", "join_expr"}, Body: &Query{Left: &Query{Func: "stream"}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$idx"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Func: "idx_expr"}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "join_expr"}}}}}, - "all": []*FuncDef{&FuncDef{Name: "all", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "all", Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, &Query{Func: "."}}}}}}, &FuncDef{Name: "all", Args: []string{"y"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "all", Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, &Query{Func: "y"}}}}}}, &FuncDef{Name: "all", Args: []string{"g", "y"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "isempty", Args: []*Query{&Query{Left: &Query{Func: "g"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "y"}, Op: OpAnd, Right: &Query{Func: "empty"}}}}}}}}}, - "any": []*FuncDef{&FuncDef{Name: "any", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "any", Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, &Query{Func: "."}}}}}}, &FuncDef{Name: "any", Args: []string{"y"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "any", Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, &Query{Func: "y"}}}}}}, &FuncDef{Name: "any", Args: []string{"g", "y"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "isempty", Args: []*Query{&Query{Left: &Query{Func: "g"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "y"}, Op: OpOr, Right: &Query{Func: "empty"}}}}}}}, Op: OpPipe, Right: &Query{Func: "not"}}}}, - "arrays": []*FuncDef{&FuncDef{Name: "arrays", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "array"}}}}}}}}}}, - "ascii_downcase": []*FuncDef{&FuncDef{Name: "ascii_downcase", Body: &Query{Left: &Query{Func: "explode"}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Left: &Query{Term: &Term{Type: TermTypeNumber, Number: "65"}}, Op: OpLe, Right: &Query{Func: "."}}, Op: OpAnd, Right: &Query{Left: &Query{Func: "."}, Op: OpLe, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "90"}}}}, Then: &Query{Left: &Query{Func: "."}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "32"}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "implode"}}}}}, - "ascii_upcase": []*FuncDef{&FuncDef{Name: "ascii_upcase", Body: &Query{Left: &Query{Func: "explode"}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Left: &Query{Term: &Term{Type: TermTypeNumber, Number: "97"}}, Op: OpLe, Right: &Query{Func: "."}}, Op: OpAnd, Right: &Query{Left: &Query{Func: "."}, Op: OpLe, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "122"}}}}, Then: &Query{Left: &Query{Func: "."}, Op: OpSub, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "32"}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "implode"}}}}}, - "assign": []*FuncDef{&FuncDef{Name: "_assign", Args: []string{"ps", "$v"}, Body: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "path", Args: []*Query{&Query{Func: "ps"}}}}, Pattern: &Pattern{Name: "$p"}, Start: &Query{Func: "."}, Update: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{&Query{Func: "$p"}, &Query{Func: "$v"}}}}}}}}}}, - "booleans": []*FuncDef{&FuncDef{Name: "booleans", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "boolean"}}}}}}}}}}, - "capture": []*FuncDef{&FuncDef{Name: "capture", Args: []string{"$re"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "capture", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "null"}}}}}}, &FuncDef{Name: "capture", Args: []string{"$re", "$flags"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "match", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "$flags"}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "captures"}, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "name"}}}, Op: OpNe, Right: &Query{Func: "null"}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{KeyQuery: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "name"}}}, Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "string"}}}}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: "add"}, Op: OpAlt, Right: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{}}}}}}}}, - "combinations": []*FuncDef{&FuncDef{Name: "combinations", Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "length"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{}}}, Else: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}, IsSlice: true}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "combinations"}, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$y"}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "$x"}}}}, Op: OpAdd, Right: &Query{Func: "$y"}}}}}}}}}}}}}}}}}, &FuncDef{Name: "combinations", Args: []string{"n"}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$dot"}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "range", Args: []*Query{&Query{Func: "n"}}}}}, Op: OpPipe, Right: &Query{Func: "$dot"}}}}}, Op: OpPipe, Right: &Query{Func: "combinations"}}}}}}}}}, - "del": []*FuncDef{&FuncDef{Name: "del", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "delpaths", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "path", Args: []*Query{&Query{Func: "f"}}}}}}}}}}}}}}, - "endswith": []*FuncDef{&FuncDef{Name: "endswith", Args: []string{"$x"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "string"}}}}, Then: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "string"}}}}}, Then: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeUnary, Unary: &Unary{Op: OpSub, Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Func: "length"}}}}}}, IsSlice: true}}}, Op: OpEq, Right: &Query{Func: "$x"}}, Else: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_type_error", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "endswith"}}}}}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_type_error", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "endswith"}}}}}}}}}}}}, - "finites": []*FuncDef{&FuncDef{Name: "finites", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Func: "isfinite"}}}}}}}, - "first": []*FuncDef{&FuncDef{Name: "first", Body: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}, &FuncDef{Name: "first", Args: []string{"g"}, Body: &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{Ident: "$out", Body: &Query{Left: &Query{Func: "g"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeBreak, Break: "$out"}}}}}}}}}, - "flatten": []*FuncDef{&FuncDef{Name: "_flatten", Args: []string{"$x"}, Body: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}, Pattern: &Pattern{Name: "$i"}, Start: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{}}}, Update: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$i"}, Op: OpPipe, Right: &Query{Left: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "array"}}}}, Op: OpAnd, Right: &Query{Left: &Query{Func: "$x"}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}, Then: &Query{Left: &Query{Func: "."}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "$i"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_flatten", Args: []*Query{&Query{Left: &Query{Func: "$x"}, Op: OpSub, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}}}}}, Else: &Query{Left: &Query{Func: "."}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "$i"}}}}}}}}}}}}, &FuncDef{Name: "flatten", Args: []string{"$x"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$x"}, Op: OpLt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "error", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "flatten depth must not be negative"}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_flatten", Args: []*Query{&Query{Func: "$x"}}}}}}}}}, &FuncDef{Name: "flatten", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_flatten", Args: []*Query{&Query{Term: &Term{Type: TermTypeUnary, Unary: &Unary{Op: OpSub, Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}}}}, - "from_entries": []*FuncDef{&FuncDef{Name: "from_entries", Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{KeyQuery: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "key"}}}, Op: OpAlt, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "Key"}}}, Op: OpAlt, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "name"}}}, Op: OpAlt, Right: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "Name"}}}}}}, Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "has", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "value"}}}}}}}, Then: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "value"}}}, Else: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "Value"}}}}}}}}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: "add"}, Op: OpAlt, Right: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{}}}}}}}, - "fromdate": []*FuncDef{&FuncDef{Name: "fromdate", Body: &Query{Func: "fromdateiso8601"}}}, - "fromdateiso8601": []*FuncDef{&FuncDef{Name: "fromdateiso8601", Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "strptime", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "%Y-%m-%dT%H:%M:%S%z"}}}}}}}, Op: OpPipe, Right: &Query{Func: "mktime"}}}}, - "fromstream": []*FuncDef{&FuncDef{Name: "fromstream", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{Key: "x", Val: &ObjectVal{Queries: []*Query{&Query{Func: "null"}}}}, &ObjectKeyVal{Key: "e", Val: &ObjectVal{Queries: []*Query{&Query{Func: "false"}}}}}}, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$init"}}, Body: &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "f"}}, Pattern: &Pattern{Name: "$i"}, Start: &Query{Func: "$init"}, Update: &Query{Left: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "e"}}}, Then: &Query{Func: "$init"}, Else: &Query{Func: "."}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$i"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "length"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "2"}}}}, Then: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "e"}}}}}}, &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$i"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: "length"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{&Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "x"}}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$i"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}}, &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$i"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "e"}}}}}}, &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$i"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: "length"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}}}}}}, Extract: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "e"}}}, Then: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "x"}}}, Else: &Query{Func: "empty"}}}}}}}}}}}}}}, - "group_by": []*FuncDef{&FuncDef{Name: "group_by", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_group_by", Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "f"}}}}}}}}}}}}}}, - "gsub": []*FuncDef{&FuncDef{Name: "gsub", Args: []string{"$re", "str"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "sub", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "str"}, &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "g"}}}}}}}}, &FuncDef{Name: "gsub", Args: []string{"$re", "str", "$flags"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "sub", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "str"}, &Query{Left: &Query{Func: "$flags"}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "g"}}}}}}}}}}, - "in": []*FuncDef{&FuncDef{Name: "in", Args: []string{"xs"}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{Left: &Query{Func: "xs"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "has", Args: []*Query{&Query{Func: "$x"}}}}}}}}}}}}}, - "index": []*FuncDef{&FuncDef{Name: "index", Args: []string{"$x"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_lindex", Args: []*Query{&Query{Func: "$x"}}}}}}}, - "indices": []*FuncDef{&FuncDef{Name: "indices", Args: []string{"$x"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_indices", Args: []*Query{&Query{Func: "$x"}}}}}}}, - "inputs": []*FuncDef{&FuncDef{Name: "inputs", Body: &Query{Term: &Term{Type: TermTypeTry, Try: &Try{Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "repeat", Args: []*Query{&Query{Func: "input"}}}}}, Catch: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "break"}}}}, Then: &Query{Func: "empty"}, Else: &Query{Func: "error"}}}}}}}}}, - "inside": []*FuncDef{&FuncDef{Name: "inside", Args: []string{"xs"}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{Left: &Query{Func: "xs"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "contains", Args: []*Query{&Query{Func: "$x"}}}}}}}}}}}}}, - "isempty": []*FuncDef{&FuncDef{Name: "isempty", Args: []string{"g"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "first", Args: []*Query{&Query{Left: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "g"}, Op: OpPipe, Right: &Query{Func: "false"}}}}, Op: OpComma, Right: &Query{Func: "true"}}}}}}}}, - "iterables": []*FuncDef{&FuncDef{Name: "iterables", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "type"}, Op: OpPipe, Right: &Query{Left: &Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "array"}}}}, Op: OpOr, Right: &Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "object"}}}}}}}}}}}}, - "join": []*FuncDef{&FuncDef{Name: "join", Args: []string{"$x"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}, Pattern: &Pattern{Name: "$i"}, Start: &Query{Func: "null"}, Update: &Query{Left: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Func: "null"}}, Then: &Query{Term: &Term{Type: TermTypeString, Str: &String{}}}, Else: &Query{Left: &Query{Func: "."}, Op: OpAdd, Right: &Query{Func: "$x"}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "$i"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "type"}, Op: OpPipe, Right: &Query{Left: &Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "boolean"}}}}, Op: OpOr, Right: &Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "number"}}}}}}, Then: &Query{Func: "tostring"}, Else: &Query{Left: &Query{Func: "."}, Op: OpAlt, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{}}}}}}}}}}}}}}, Op: OpAlt, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{}}}}}}, - "last": []*FuncDef{&FuncDef{Name: "last", Body: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeUnary, Unary: &Unary{Op: OpSub, Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}}, &FuncDef{Name: "last", Args: []string{"g"}, Body: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "g"}}, Pattern: &Pattern{Name: "$item"}, Start: &Query{Func: "null"}, Update: &Query{Func: "$item"}}}}}}, - "leaf_paths": []*FuncDef{&FuncDef{Name: "leaf_paths", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "paths", Args: []*Query{&Query{Func: "scalars"}}}}}}}, - "limit": []*FuncDef{&FuncDef{Name: "limit", Args: []string{"$n", "g"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$n"}, Op: OpGt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{Ident: "$out", Body: &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "g"}}, Pattern: &Pattern{Name: "$item"}, Start: &Query{Func: "$n"}, Update: &Query{Left: &Query{Func: "."}, Op: OpSub, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}, Extract: &Query{Left: &Query{Func: "$item"}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "."}, Op: OpLe, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Term: &Term{Type: TermTypeBreak, Break: "$out"}}, Else: &Query{Func: "empty"}}}}}}}}}}}, Elif: []*IfElif{&IfElif{Cond: &Query{Left: &Query{Func: "$n"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Func: "empty"}}}, Else: &Query{Func: "g"}}}}}}, - "ltrimstr": []*FuncDef{&FuncDef{Name: "ltrimstr", Args: []string{"$x"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Left: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "string"}}}}, Op: OpAnd, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "string"}}}}}}}}, Op: OpAnd, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "startswith", Args: []*Query{&Query{Func: "$x"}}}}}}, Then: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Func: "length"}}, IsSlice: true}}}}}}}}, - "map": []*FuncDef{&FuncDef{Name: "map", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, Op: OpPipe, Right: &Query{Func: "f"}}}}}}}, - "map_values": []*FuncDef{&FuncDef{Name: "map_values", Args: []string{"f"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, Op: OpModify, Right: &Query{Func: "f"}}}}, - "match": []*FuncDef{&FuncDef{Name: "match", Args: []string{"$re"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "match", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "null"}}}}}}, &FuncDef{Name: "match", Args: []string{"$re", "$flags"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_match", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "$flags"}, &Query{Func: "false"}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}, - "max": []*FuncDef{&FuncDef{Name: "max", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "max_by", Args: []*Query{&Query{Func: "."}}}}}}}, - "max_by": []*FuncDef{&FuncDef{Name: "max_by", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_max_by", Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "f"}}}}}}}}}}}}}}, - "min": []*FuncDef{&FuncDef{Name: "min", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "min_by", Args: []*Query{&Query{Func: "."}}}}}}}, - "min_by": []*FuncDef{&FuncDef{Name: "min_by", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_min_by", Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "f"}}}}}}}}}}}}}}, - "modify": []*FuncDef{&FuncDef{Name: "_modify", Args: []string{"ps", "f"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "path", Args: []*Query{&Query{Func: "ps"}}}}, Pattern: &Pattern{Name: "$p"}, Start: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{}}}}}}}, Update: &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{Ident: "$out", Body: &Query{Left: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}, Op: OpAdd, Right: &Query{Func: "$p"}}, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$q"}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{&Query{Func: "$q"}, &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "getpath", Args: []*Query{&Query{Func: "$q"}}}}}, Op: OpPipe, Right: &Query{Func: "f"}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeBreak, Break: "$out"}}}}}}}}}}}, Op: OpComma, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}, Op: OpUpdateAdd, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "$p"}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$x"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "delpaths", Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$x"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}}}}}}}}}}}}}}, - "normals": []*FuncDef{&FuncDef{Name: "normals", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Func: "isnormal"}}}}}}}, - "not": []*FuncDef{&FuncDef{Name: "not", Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Func: "."}, Then: &Query{Func: "false"}, Else: &Query{Func: "true"}}}}}}, - "nth": []*FuncDef{&FuncDef{Name: "nth", Args: []string{"$n"}, Body: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Func: "$n"}}}}}, &FuncDef{Name: "nth", Args: []string{"$n", "g"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$n"}, Op: OpLt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "error", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "nth doesn't support negative indices"}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{Ident: "$out", Body: &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "g"}}, Pattern: &Pattern{Name: "$item"}, Start: &Query{Func: "$n"}, Update: &Query{Left: &Query{Func: "."}, Op: OpSub, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}, Extract: &Query{Left: &Query{Left: &Query{Left: &Query{Func: "."}, Op: OpLt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Op: OpOr, Right: &Query{Func: "empty"}}, Op: OpPipe, Right: &Query{Left: &Query{Func: "$item"}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeBreak, Break: "$out"}}}}}}}}}}}}}}}, - "nulls": []*FuncDef{&FuncDef{Name: "nulls", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Func: "null"}}}}}}}}, - "numbers": []*FuncDef{&FuncDef{Name: "numbers", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "number"}}}}}}}}}}, - "objects": []*FuncDef{&FuncDef{Name: "objects", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "object"}}}}}}}}}}, - "paths": []*FuncDef{&FuncDef{Name: "paths", Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "path", Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "recurse", Args: []*Query{&Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "type"}, Op: OpPipe, Right: &Query{Left: &Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "array"}}}}, Op: OpOr, Right: &Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "object"}}}}}}, Then: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, Else: &Query{Func: "empty"}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "length"}, Op: OpGt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}}}, &FuncDef{Name: "paths", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{Left: &Query{Func: "paths"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$p"}}, Body: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "getpath", Args: []*Query{&Query{Func: "$p"}}}}}, Op: OpPipe, Right: &Query{Func: "f"}}}}}}}}}}}}}}}}}}}}, - "range": []*FuncDef{&FuncDef{Name: "range", Args: []string{"$x"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "range", Args: []*Query{&Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}, &Query{Func: "$x"}}}}}}, &FuncDef{Name: "range", Args: []string{"$start", "$end"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$start"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "type"}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "number"}}}}}, Then: &Query{Left: &Query{Func: "$start"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_type_error", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "range"}}}}}}}}, Elif: []*IfElif{&IfElif{Cond: &Query{Left: &Query{Func: "$end"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "type"}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "number"}}}}}, Then: &Query{Left: &Query{Func: "$end"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_type_error", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "range"}}}}}}}}}}, Else: &Query{Left: &Query{Func: "$start"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "while", Args: []*Query{&Query{Left: &Query{Func: "."}, Op: OpLt, Right: &Query{Func: "$end"}}, &Query{Left: &Query{Func: "."}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}}}}}}, &FuncDef{Name: "range", Args: []string{"$start", "$end", "$step"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$start"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "type"}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "number"}}}}}, Then: &Query{Left: &Query{Func: "$start"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_type_error", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "range"}}}}}}}}, Elif: []*IfElif{&IfElif{Cond: &Query{Left: &Query{Func: "$end"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "type"}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "number"}}}}}, Then: &Query{Left: &Query{Func: "$end"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_type_error", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "range"}}}}}}}}}, &IfElif{Cond: &Query{Left: &Query{Func: "$step"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "type"}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "number"}}}}}, Then: &Query{Left: &Query{Func: "$step"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_type_error", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "range"}}}}}}}}}, &IfElif{Cond: &Query{Left: &Query{Func: "$step"}, Op: OpGt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Left: &Query{Func: "$start"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "while", Args: []*Query{&Query{Left: &Query{Func: "."}, Op: OpLt, Right: &Query{Func: "$end"}}, &Query{Left: &Query{Func: "."}, Op: OpAdd, Right: &Query{Func: "$step"}}}}}}}}, &IfElif{Cond: &Query{Left: &Query{Func: "$step"}, Op: OpLt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Left: &Query{Func: "$start"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "while", Args: []*Query{&Query{Left: &Query{Func: "."}, Op: OpGt, Right: &Query{Func: "$end"}}, &Query{Left: &Query{Func: "."}, Op: OpAdd, Right: &Query{Func: "$step"}}}}}}}}}, Else: &Query{Func: "empty"}}}}}}, - "recurse": []*FuncDef{&FuncDef{Name: "recurse", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "recurse", Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Optional: true}}}}}}}}}, &FuncDef{Name: "recurse", Args: []string{"f"}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: "r", Body: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "f"}, Op: OpPipe, Right: &Query{Func: "r"}}}}}}}, Func: "r"}}, &FuncDef{Name: "recurse", Args: []string{"f", "cond"}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: "r", Body: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "f"}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Func: "cond"}}}}}, Op: OpPipe, Right: &Query{Func: "r"}}}}}}}}, Func: "r"}}}, - "repeat": []*FuncDef{&FuncDef{Name: "repeat", Args: []string{"f"}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: "_repeat", Body: &Query{Left: &Query{Func: "f"}, Op: OpComma, Right: &Query{Func: "_repeat"}}}}, Func: "_repeat"}}}, - "rindex": []*FuncDef{&FuncDef{Name: "rindex", Args: []string{"$x"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_rindex", Args: []*Query{&Query{Func: "$x"}}}}}}}, - "rtrimstr": []*FuncDef{&FuncDef{Name: "rtrimstr", Args: []string{"$x"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Left: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "string"}}}}, Op: OpAnd, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "string"}}}}}}}}, Op: OpAnd, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "endswith", Args: []*Query{&Query{Func: "$x"}}}}}}, Then: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{End: &Query{Term: &Term{Type: TermTypeUnary, Unary: &Unary{Op: OpSub, Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Func: "length"}}}}}}}}}}}}}}, - "scalars": []*FuncDef{&FuncDef{Name: "scalars", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "type"}, Op: OpPipe, Right: &Query{Left: &Query{Left: &Query{Func: "."}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "array"}}}}, Op: OpAnd, Right: &Query{Left: &Query{Func: "."}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "object"}}}}}}}}}}}}, - "scan": []*FuncDef{&FuncDef{Name: "scan", Args: []string{"$re"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "scan", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "null"}}}}}}, &FuncDef{Name: "scan", Args: []string{"$re", "$flags"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "match", Args: []*Query{&Query{Func: "$re"}, &Query{Left: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "g"}}}, Op: OpAdd, Right: &Query{Func: "$flags"}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "captures"}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: "length"}, Op: OpGt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}, Then: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "captures"}, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Index: &Index{Name: "string"}}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "string"}}}}}}}}}, - "select": []*FuncDef{&FuncDef{Name: "select", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Func: "f"}, Then: &Query{Func: "."}, Else: &Query{Func: "empty"}}}}}}, - "sort": []*FuncDef{&FuncDef{Name: "sort", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "sort_by", Args: []*Query{&Query{Func: "."}}}}}}}, - "sort_by": []*FuncDef{&FuncDef{Name: "sort_by", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_sort_by", Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "f"}}}}}}}}}}}}}}, - "splits": []*FuncDef{&FuncDef{Name: "splits", Args: []string{"$re"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "splits", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "null"}}}}}}, &FuncDef{Name: "splits", Args: []string{"$re", "$flags"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "split", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "$flags"}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}, - "startswith": []*FuncDef{&FuncDef{Name: "startswith", Args: []string{"$x"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "string"}}}}, Then: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "string"}}}}}, Then: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{End: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Func: "length"}}}}}, Op: OpEq, Right: &Query{Func: "$x"}}, Else: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_type_error", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "startswith"}}}}}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_type_error", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "startswith"}}}}}}}}}}}}, - "strings": []*FuncDef{&FuncDef{Name: "strings", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "string"}}}}}}}}}}, - "sub": []*FuncDef{&FuncDef{Name: "sub", Args: []string{"$re", "str"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "sub", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "str"}, &Query{Func: "null"}}}}}}, &FuncDef{Name: "sub", Args: []string{"$re", "str", "$flags"}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$in"}}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: "sub", Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "matches"}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: "length"}, Op: OpGt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}, Then: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "matches"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}, &Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$r"}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$r"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Name: "captures"}}, &Suffix{Iter: true}}}}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "name"}}}, Op: OpNe, Right: &Query{Func: "null"}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{KeyQuery: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "name"}}}, Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "string"}}}}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Left: &Query{Func: "add"}, Op: OpAlt, Right: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{}}}}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{Key: "string", Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$x"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Name: "string"}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$in"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$x"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Name: "offset"}}}}}, IsSlice: true, End: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$r"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Name: "offset"}}}}}}}}}}}, Op: OpAdd, Right: &Query{Func: "str"}}}}}}}, &ObjectKeyVal{Key: "offset", Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$r"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Name: "offset"}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$r"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Name: "length"}}}}}}}}}}}, &ObjectKeyVal{Key: "matches", Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$x"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Name: "matches"}}, &Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}, IsSlice: true}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "sub"}}}}}}}}}}}}}}, Else: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "string"}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$in"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "offset"}}}, IsSlice: true}}}}}}}}}}}, Left: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{Key: "string", Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{}}}}}}, &ObjectKeyVal{Key: "offset", Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}, &ObjectKeyVal{Key: "matches", Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "match", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "$flags"}}}}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "sub"}}}}}}}}}, - "test": []*FuncDef{&FuncDef{Name: "test", Args: []string{"$re"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "test", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "null"}}}}}}, &FuncDef{Name: "test", Args: []string{"$re", "$flags"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_match", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "$flags"}, &Query{Func: "true"}}}}}}}, - "to_entries": []*FuncDef{&FuncDef{Name: "to_entries", Body: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "keys"}, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$k"}}, Body: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{Key: "key", Val: &ObjectVal{Queries: []*Query{&Query{Func: "$k"}}}}, &ObjectKeyVal{Key: "value", Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Func: "$k"}}}}}}}}}}}}}}}}}}}}}, - "todate": []*FuncDef{&FuncDef{Name: "todate", Body: &Query{Func: "todateiso8601"}}}, - "todateiso8601": []*FuncDef{&FuncDef{Name: "todateiso8601", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "strftime", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "%Y-%m-%dT%H:%M:%SZ"}}}}}}}}}, - "tostream": []*FuncDef{&FuncDef{Name: "tostream", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "path", Args: []*Query{&Query{FuncDefs: []*FuncDef{&FuncDef{Name: "r", Body: &Query{Left: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Optional: true}}}}, Op: OpPipe, Right: &Query{Func: "r"}}}}, Op: OpComma, Right: &Query{Func: "."}}}}, Func: "r"}}}, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$p"}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "getpath", Args: []*Query{&Query{Func: "$p"}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "path", Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Optional: true}}}}}}}, Pattern: &Pattern{Name: "$q"}, Start: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: "$p"}, Op: OpComma, Right: &Query{Func: "."}}}}}, Update: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: "$p"}, Op: OpAdd, Right: &Query{Func: "$q"}}}}}}}}}}}}}}}}, - "truncate_stream": []*FuncDef{&FuncDef{Name: "truncate_stream", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$n"}}, Body: &Query{Left: &Query{Func: "null"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "f"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$input"}}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}, Op: OpPipe, Right: &Query{Func: "length"}}}}, Op: OpGt, Right: &Query{Func: "$n"}}, Then: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}, &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$input"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}, &Suffix{Index: &Index{Start: &Query{Func: "$n"}, IsSlice: true}}}}}}}}}, Else: &Query{Func: "empty"}}}}}}}}}}}}}}}}}}, - "unique": []*FuncDef{&FuncDef{Name: "unique", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "unique_by", Args: []*Query{&Query{Func: "."}}}}}}}, - "unique_by": []*FuncDef{&FuncDef{Name: "unique_by", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_unique_by", Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "f"}}}}}}}}}}}}}}, - "until": []*FuncDef{&FuncDef{Name: "until", Args: []string{"cond", "next"}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: "_until", Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Func: "cond"}, Then: &Query{Func: "."}, Else: &Query{Left: &Query{Func: "next"}, Op: OpPipe, Right: &Query{Func: "_until"}}}}}}}, Func: "_until"}}}, - "values": []*FuncDef{&FuncDef{Name: "values", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "."}, Op: OpNe, Right: &Query{Func: "null"}}}}}}}}, - "walk": []*FuncDef{&FuncDef{Name: "walk", Args: []string{"f"}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: "w", Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "object"}}}}, Then: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$in"}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "keys"}, SuffixList: []*Suffix{&Suffix{Iter: true}}}, Pattern: &Pattern{Name: "$key"}, Start: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{}}}, Update: &Query{Left: &Query{Func: "."}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{KeyQuery: &Query{Func: "$key"}, Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$in"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Func: "$key"}}}}}}, &Query{Func: "w"}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "f"}}}}}}}, Elif: []*IfElif{&IfElif{Cond: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "array"}}}}, Then: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Func: "w"}}}}}, Op: OpPipe, Right: &Query{Func: "f"}}}}, Else: &Query{Func: "f"}}}}}}, Func: "w"}}}, - "while": []*FuncDef{&FuncDef{Name: "while", Args: []string{"cond", "update"}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: "_while", Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Func: "cond"}, Then: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "update"}, Op: OpPipe, Right: &Query{Func: "_while"}}}}}, Else: &Query{Func: "empty"}}}}}}, Func: "_while"}}}, - "with_entries": []*FuncDef{&FuncDef{Name: "with_entries", Args: []string{"f"}, Body: &Query{Left: &Query{Func: "to_entries"}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Func: "f"}}}}}, Op: OpPipe, Right: &Query{Func: "from_entries"}}}}}, + "IN": []*FuncDef{&FuncDef{Name: &Token{Str: "IN", Start: 7701, Stop: 7702}, Args: []*Token{&Token{Str: "s", Start: 7704, Stop: 7704}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "any", Start: 7708, Stop: 7710}, Args: []*Query{&Query{Left: &Query{Func: &Token{Str: "s"}}, Op: OpEq, Right: &Query{Func: &Token{Str: "."}}}, &Query{Func: &Token{Str: "."}}}}}}}, &FuncDef{Name: &Token{Str: "IN", Start: 7728, Stop: 7729}, Args: []*Token{&Token{Str: "src", Start: 7731, Stop: 7733}, &Token{Str: "s", Start: 7736, Stop: 7736}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "any", Start: 7740, Stop: 7742}, Args: []*Query{&Query{Left: &Query{Func: &Token{Str: "src"}}, Op: OpEq, Right: &Query{Func: &Token{Str: "s"}}}, &Query{Func: &Token{Str: "."}}}}}}}}, + "INDEX": []*FuncDef{&FuncDef{Name: &Token{Str: "INDEX", Start: 7353, Stop: 7357}, Args: []*Token{&Token{Str: "stream", Start: 7359, Stop: 7364}, &Token{Str: "idx_expr", Start: 7367, Stop: 7374}}, Body: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "stream", Start: 7387, Stop: 7392}}}, Pattern: &Pattern{Name: &Token{Str: "$row", Start: 7397, Stop: 7400}}, Start: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{}}}, Update: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Left: &Query{Func: &Token{Str: "$row"}}, Op: OpPipe, Right: &Query{Left: &Query{Func: &Token{Str: "idx_expr"}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "tostring"}}}}}}}, Op: OpAssign, Right: &Query{Func: &Token{Str: "$row"}}}}}}}, &FuncDef{Name: &Token{Str: "INDEX", Start: 7446, Stop: 7450}, Args: []*Token{&Token{Str: "idx_expr", Start: 7452, Stop: 7459}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "INDEX", Start: 7463, Stop: 7467}, Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, &Query{Func: &Token{Str: "idx_expr"}}}}}}}}, + "JOIN": []*FuncDef{&FuncDef{Name: &Token{Str: "JOIN", Start: 7489, Stop: 7492}, Args: []*Token{&Token{Str: "$idx", Start: 7494, Stop: 7497}, &Token{Str: "idx_expr", Start: 7500, Stop: 7507}}, Body: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "$idx", Start: 7524, Stop: 7527}}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Func: &Token{Str: "idx_expr"}}}}}}}}}}}}}}}}, &FuncDef{Name: &Token{Str: "JOIN", Start: 7546, Stop: 7549}, Args: []*Token{&Token{Str: "$idx", Start: 7551, Stop: 7554}, &Token{Str: "stream", Start: 7557, Stop: 7562}, &Token{Str: "idx_expr", Start: 7565, Stop: 7572}}, Body: &Query{Left: &Query{Func: &Token{Str: "stream"}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "$idx", Start: 7591, Stop: 7594}}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Func: &Token{Str: "idx_expr"}}}}}}}}}}}}}, &FuncDef{Name: &Token{Str: "JOIN", Start: 7612, Stop: 7615}, Args: []*Token{&Token{Str: "$idx", Start: 7617, Stop: 7620}, &Token{Str: "stream", Start: 7623, Stop: 7628}, &Token{Str: "idx_expr", Start: 7631, Stop: 7638}, &Token{Str: "join_expr", Start: 7641, Stop: 7649}}, Body: &Query{Left: &Query{Func: &Token{Str: "stream"}}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "$idx", Start: 7668, Stop: 7671}}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Func: &Token{Str: "idx_expr"}}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "join_expr"}}}}}}, + "all": []*FuncDef{&FuncDef{Name: &Token{Str: "all", Start: 4100, Stop: 4102}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "all", Start: 4105, Stop: 4107}, Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, &Query{Func: &Token{Str: "."}}}}}}}, &FuncDef{Name: &Token{Str: "all", Start: 4122, Stop: 4124}, Args: []*Token{&Token{Str: "y", Start: 4126, Stop: 4126}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "all", Start: 4130, Stop: 4132}, Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, &Query{Func: &Token{Str: "y"}}}}}}}, &FuncDef{Name: &Token{Str: "all", Start: 4147, Stop: 4149}, Args: []*Token{&Token{Str: "g", Start: 4151, Stop: 4151}, &Token{Str: "y", Start: 4154, Stop: 4154}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "isempty", Start: 4158, Stop: 4164}, Args: []*Query{&Query{Left: &Query{Func: &Token{Str: "g"}}, Op: OpPipe, Right: &Query{Left: &Query{Func: &Token{Str: "y"}}, Op: OpAnd, Right: &Query{Func: &Token{Str: "empty"}}}}}}}}}}, + "any": []*FuncDef{&FuncDef{Name: &Token{Str: "any", Start: 4186, Stop: 4188}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "any", Start: 4191, Stop: 4193}, Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, &Query{Func: &Token{Str: "."}}}}}}}, &FuncDef{Name: &Token{Str: "any", Start: 4208, Stop: 4210}, Args: []*Token{&Token{Str: "y", Start: 4212, Stop: 4212}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "any", Start: 4216, Stop: 4218}, Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, &Query{Func: &Token{Str: "y"}}}}}}}, &FuncDef{Name: &Token{Str: "any", Start: 4233, Stop: 4235}, Args: []*Token{&Token{Str: "g", Start: 4237, Stop: 4237}, &Token{Str: "y", Start: 4240, Stop: 4240}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "isempty", Start: 4244, Stop: 4250}, Args: []*Query{&Query{Left: &Query{Func: &Token{Str: "g"}}, Op: OpPipe, Right: &Query{Left: &Query{Func: &Token{Str: "y"}}, Op: OpOr, Right: &Query{Func: &Token{Str: "empty"}}}}}}}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "not"}}}}}, + "arrays": []*FuncDef{&FuncDef{Name: &Token{Str: "arrays", Start: 1938, Stop: 1943}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "select", Start: 1946, Stop: 1951}, Args: []*Query{&Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "array", Start: 1961, Stop: 1967}}}}}}}}}}}, + "ascii_downcase": []*FuncDef{&FuncDef{Name: &Token{Str: "ascii_downcase", Start: 3552, Stop: 3565}, Body: &Query{Left: &Query{Func: &Token{Str: "explode"}}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "map", Start: 3580, Stop: 3582}, Args: []*Query{&Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Left: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "65", Start: 3587, Stop: 3588}}}, Op: OpLe, Right: &Query{Func: &Token{Str: "."}}}, Op: OpAnd, Right: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpLe, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "90", Start: 3604, Stop: 3605}}}}}, Then: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "32", Start: 3616, Stop: 3617}}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "implode"}}}}}}, + "ascii_upcase": []*FuncDef{&FuncDef{Name: &Token{Str: "ascii_upcase", Start: 3639, Stop: 3650}, Body: &Query{Left: &Query{Func: &Token{Str: "explode"}}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "map", Start: 3665, Stop: 3667}, Args: []*Query{&Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Left: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "97", Start: 3672, Stop: 3673}}}, Op: OpLe, Right: &Query{Func: &Token{Str: "."}}}, Op: OpAnd, Right: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpLe, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "122", Start: 3689, Stop: 3691}}}}}, Then: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpSub, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "32", Start: 3702, Stop: 3703}}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "implode"}}}}}}, + "assign": []*FuncDef{&FuncDef{Name: &Token{Str: "_assign", Start: 5276, Stop: 5282}, Args: []*Token{&Token{Str: "ps", Start: 5284, Stop: 5285}, &Token{Str: "$v", Start: 5288, Stop: 5289}}, Body: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "path", Start: 5302, Stop: 5305}, Args: []*Query{&Query{Func: &Token{Str: "ps"}}}}}, Pattern: &Pattern{Name: &Token{Str: "$p", Start: 5314, Stop: 5315}}, Start: &Query{Func: &Token{Str: "."}}, Update: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "setpath", Start: 5321, Stop: 5327}, Args: []*Query{&Query{Func: &Token{Str: "$p"}}, &Query{Func: &Token{Str: "$v"}}}}}}}}}}}, + "booleans": []*FuncDef{&FuncDef{Name: &Token{Str: "booleans", Start: 2075, Stop: 2082}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "select", Start: 2085, Stop: 2090}, Args: []*Query{&Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "boolean", Start: 2100, Stop: 2108}}}}}}}}}}}, + "capture": []*FuncDef{&FuncDef{Name: &Token{Str: "capture", Start: 6140, Stop: 6146}, Args: []*Token{&Token{Str: "$re", Start: 6148, Stop: 6150}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "capture", Start: 6154, Stop: 6160}, Args: []*Query{&Query{Func: &Token{Str: "$re"}}, &Query{Func: &Token{Str: "null"}}}}}}}, &FuncDef{Name: &Token{Str: "capture", Start: 6178, Stop: 6184}, Args: []*Token{&Token{Str: "$re", Start: 6186, Stop: 6188}, &Token{Str: "$flags", Start: 6191, Stop: 6196}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "match", Start: 6202, Stop: 6206}, Args: []*Query{&Query{Func: &Token{Str: "$re"}}, &Query{Func: &Token{Str: "$flags"}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: &Token{Str: "captures", Start: 6228, Stop: 6236}}, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "select", Start: 6242, Stop: 6247}, Args: []*Query{&Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: &Token{Str: "name", Start: 6249, Stop: 6253}}}}, Op: OpNe, Right: &Query{Func: &Token{Str: "null"}}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{KeyQuery: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: &Token{Str: "name", Start: 6269, Stop: 6273}}}}, Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: &Token{Str: "string", Start: 6277, Stop: 6283}}}}}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: &Token{Str: "add"}}, Op: OpAlt, Right: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{}}}}}}}}, + "combinations": []*FuncDef{&FuncDef{Name: &Token{Str: "combinations", Start: 3188, Stop: 3199}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: &Token{Str: "length"}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 3217, Stop: 3217}}}}, Then: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{}}}, Else: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 3244, Stop: 3244}}}}, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: &Token{Str: "$x", Start: 3252, Stop: 3253}}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "1", Start: 3259, Stop: 3259}}}, IsSlice: true}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "combinations", Start: 3265, Stop: 3276}}, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: &Token{Str: "$y", Start: 3281, Stop: 3282}}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: &Token{Str: "$x"}}}}}, Op: OpAdd, Right: &Query{Func: &Token{Str: "$y"}}}}}}}}}}}}}}}}}}, &FuncDef{Name: &Token{Str: "combinations", Start: 3307, Stop: 3318}, Args: []*Token{&Token{Str: "n", Start: 3320, Stop: 3320}}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: &Token{Str: "$dot", Start: 3331, Stop: 3334}}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "range", Start: 3339, Stop: 3343}, Args: []*Query{&Query{Func: &Token{Str: "n"}}}}}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "$dot"}}}}}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "combinations"}}}}}}}}}}, + "del": []*FuncDef{&FuncDef{Name: &Token{Str: "del", Start: 5567, Stop: 5569}, Args: []*Token{&Token{Str: "f", Start: 5571, Stop: 5571}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "delpaths", Start: 5575, Stop: 5582}, Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "path", Start: 5585, Stop: 5588}, Args: []*Query{&Query{Func: &Token{Str: "f"}}}}}}}}}}}}}}}, + "endswith": []*FuncDef{&FuncDef{Name: &Token{Str: "endswith", Start: 2748, Stop: 2755}, Args: []*Token{&Token{Str: "$x", Start: 2757, Stop: 2758}}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "string", Start: 2775, Stop: 2782}}}}}, Then: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: &Token{Str: "$x"}}, Op: OpPipe, Right: &Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "string", Start: 2807, Stop: 2814}}}}}}, Then: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeUnary, Unary: &Unary{Op: OpSub, Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: &Token{Str: "$x"}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "length"}}}}}}}, IsSlice: true}}}, Op: OpEq, Right: &Query{Func: &Token{Str: "$x"}}}, Else: &Query{Left: &Query{Func: &Token{Str: "$x"}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "_type_error", Start: 2873, Stop: 2883}, Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "endswith", Start: 2885, Stop: 2894}}}}}}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "_type_error", Start: 2916, Stop: 2926}, Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "endswith", Start: 2928, Stop: 2937}}}}}}}}}}}}}, + "finites": []*FuncDef{&FuncDef{Name: &Token{Str: "finites", Start: 2155, Stop: 2161}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "select", Start: 2164, Stop: 2169}, Args: []*Query{&Query{Func: &Token{Str: "isfinite"}}}}}}}}, + "first": []*FuncDef{&FuncDef{Name: &Token{Str: "first", Start: 3934, Stop: 3938}, Body: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 3943, Stop: 3943}}}}}}}, &FuncDef{Name: &Token{Str: "first", Start: 3951, Stop: 3955}, Args: []*Token{&Token{Str: "g", Start: 3957, Stop: 3957}}, Body: &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{Ident: &Token{Str: "$out", Start: 3967, Stop: 3970}, Body: &Query{Left: &Query{Func: &Token{Str: "g"}}, Op: OpPipe, Right: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeBreak, Break: &Token{Str: "$out", Start: 3987, Stop: 3990}}}}}}}}}}, + "flatten": []*FuncDef{&FuncDef{Name: &Token{Str: "_flatten", Start: 1377, Stop: 1384}, Args: []*Token{&Token{Str: "$x", Start: 1386, Stop: 1387}}, Body: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}, Pattern: &Pattern{Name: &Token{Str: "$i", Start: 1407, Stop: 1408}}, Start: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{}}}, Update: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: &Token{Str: "$i"}}, Op: OpPipe, Right: &Query{Left: &Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "array", Start: 1442, Stop: 1448}}}}}, Op: OpAnd, Right: &Query{Left: &Query{Func: &Token{Str: "$x"}}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 1460, Stop: 1460}}}}}}, Then: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: &Token{Str: "$i"}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "_flatten", Start: 1483, Stop: 1490}, Args: []*Query{&Query{Left: &Query{Func: &Token{Str: "$x"}}, Op: OpSub, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "1", Start: 1495, Stop: 1495}}}}}}}}}}}}, Else: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: &Token{Str: "$i"}}}}}}}}}}}}}, &FuncDef{Name: &Token{Str: "flatten", Start: 1535, Stop: 1541}, Args: []*Token{&Token{Str: "$x", Start: 1543, Stop: 1544}}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: &Token{Str: "$x"}}, Op: OpLt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 1558, Stop: 1558}}}}, Then: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "error", Start: 1567, Stop: 1571}, Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "flatten depth must not be negative", Start: 1573, Stop: 1608}}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "_flatten", Start: 1618, Stop: 1625}, Args: []*Query{&Query{Func: &Token{Str: "$x"}}}}}}}}}}, &FuncDef{Name: &Token{Str: "flatten", Start: 1640, Stop: 1646}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "_flatten", Start: 1649, Stop: 1656}, Args: []*Query{&Query{Term: &Term{Type: TermTypeUnary, Unary: &Unary{Op: OpSub, Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "1", Start: 1659, Stop: 1659}}}}}}}}}}}, + "from_entries": []*FuncDef{&FuncDef{Name: &Token{Str: "from_entries", Start: 162, Stop: 173}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "map", Start: 178, Stop: 180}, Args: []*Query{&Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{KeyQuery: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: &Token{Str: "key", Start: 185, Stop: 188}}}}, Op: OpAlt, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: &Token{Str: "Key", Start: 193, Stop: 196}}}}, Op: OpAlt, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: &Token{Str: "name", Start: 201, Stop: 205}}}}, Op: OpAlt, Right: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: &Token{Str: "Name", Start: 210, Stop: 214}}}}}}}, Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "has", Start: 222, Stop: 224}, Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "value", Start: 226, Stop: 232}}}}}}}}, Then: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: &Token{Str: "value", Start: 240, Stop: 245}}}}, Else: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: &Token{Str: "Value", Start: 252, Stop: 257}}}}}}}}}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: &Token{Str: "add"}}, Op: OpAlt, Right: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{}}}}}}}, + "fromdate": []*FuncDef{&FuncDef{Name: &Token{Str: "fromdate", Start: 5907, Stop: 5914}, Body: &Query{Func: &Token{Str: "fromdateiso8601"}}}}, + "fromdateiso8601": []*FuncDef{&FuncDef{Name: &Token{Str: "fromdateiso8601", Start: 5793, Stop: 5807}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "strptime", Start: 5810, Stop: 5817}, Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "%Y-%m-%dT%H:%M:%S%z", Start: 5819, Stop: 5839}}}}}}}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "mktime"}}}}}, + "fromstream": []*FuncDef{&FuncDef{Name: &Token{Str: "fromstream", Start: 4824, Stop: 4833}, Args: []*Token{&Token{Str: "f", Start: 4835, Stop: 4835}}, Body: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{Key: &Token{Str: "x", Start: 4843, Stop: 4843}, Val: &ObjectVal{Queries: []*Query{&Query{Func: &Token{Str: "null"}}}}}, &ObjectKeyVal{Key: &Token{Str: "e", Start: 4852, Stop: 4852}, Val: &ObjectVal{Queries: []*Query{&Query{Func: &Token{Str: "false"}}}}}}}, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: &Token{Str: "$init", Start: 4866, Stop: 4870}}}, Body: &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "f", Start: 4886, Stop: 4886}}}, Pattern: &Pattern{Name: &Token{Str: "$i", Start: 4891, Stop: 4892}}, Start: &Query{Func: &Token{Str: "$init"}}, Update: &Query{Left: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: &Token{Str: "e", Start: 4920, Stop: 4921}}}}, Then: &Query{Func: &Token{Str: "$init"}}, Else: &Query{Func: &Token{Str: "."}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: &Token{Str: "$i"}}, Op: OpPipe, Right: &Query{Left: &Query{Func: &Token{Str: "length"}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "2", Start: 4973, Stop: 4973}}}}}, Then: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "setpath", Start: 4990, Stop: 4996}, Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "e", Start: 4999, Stop: 5001}}}}}}}, &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "$i", Start: 5005, Stop: 5006}}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 5008, Stop: 5008}}}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: &Token{Str: "length"}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 5021, Stop: 5021}}}}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "setpath", Start: 5026, Stop: 5032}, Args: []*Query{&Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "x", Start: 5035, Stop: 5037}}}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "$i", Start: 5042, Stop: 5043}}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 5045, Stop: 5045}}}}}}}}}, &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "$i", Start: 5049, Stop: 5050}}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "1", Start: 5052, Stop: 5052}}}}}}}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "setpath", Start: 5071, Stop: 5077}, Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "e", Start: 5080, Stop: 5082}}}}}}}, &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "$i", Start: 5086, Stop: 5087}}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 5089, Stop: 5089}}}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: &Token{Str: "length"}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "1", Start: 5102, Stop: 5102}}}}}}}}}}}}}, Extract: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: &Token{Str: "e", Start: 5121, Stop: 5122}}}}, Then: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: &Token{Str: "x", Start: 5129, Stop: 5130}}}}, Else: &Query{Func: &Token{Str: "empty"}}}}}}}}}}}}}}}, + "group_by": []*FuncDef{&FuncDef{Name: &Token{Str: "group_by", Start: 1833, Stop: 1840}, Args: []*Token{&Token{Str: "f", Start: 1842, Stop: 1842}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "_group_by", Start: 1846, Stop: 1854}, Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "map", Start: 1856, Stop: 1858}, Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: &Token{Str: "f"}}}}}}}}}}}}}}}, + "gsub": []*FuncDef{&FuncDef{Name: &Token{Str: "gsub", Start: 7163, Stop: 7166}, Args: []*Token{&Token{Str: "$re", Start: 7168, Stop: 7170}, &Token{Str: "str", Start: 7173, Stop: 7175}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "sub", Start: 7179, Stop: 7181}, Args: []*Query{&Query{Func: &Token{Str: "$re"}}, &Query{Func: &Token{Str: "str"}}, &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "g", Start: 7193, Stop: 7195}}}}}}}}}, &FuncDef{Name: &Token{Str: "gsub", Start: 7203, Stop: 7206}, Args: []*Token{&Token{Str: "$re", Start: 7208, Stop: 7210}, &Token{Str: "str", Start: 7213, Stop: 7215}, &Token{Str: "$flags", Start: 7218, Stop: 7223}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "sub", Start: 7227, Stop: 7229}, Args: []*Query{&Query{Func: &Token{Str: "$re"}}, &Query{Func: &Token{Str: "str"}}, &Query{Left: &Query{Func: &Token{Str: "$flags"}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "g", Start: 7250, Stop: 7252}}}}}}}}}}}, + "in": []*FuncDef{&FuncDef{Name: &Token{Str: "in", Start: 45, Stop: 46}, Args: []*Token{&Token{Str: "xs", Start: 48, Stop: 49}}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: &Token{Str: "$x", Start: 58, Stop: 59}}}, Body: &Query{Left: &Query{Func: &Token{Str: "xs"}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "has", Start: 68, Stop: 70}, Args: []*Query{&Query{Func: &Token{Str: "$x"}}}}}}}}}}}}}}, + "index": []*FuncDef{&FuncDef{Name: &Token{Str: "index", Start: 2441, Stop: 2445}, Args: []*Token{&Token{Str: "$x", Start: 2447, Stop: 2448}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "_lindex", Start: 2452, Stop: 2458}, Args: []*Query{&Query{Func: &Token{Str: "$x"}}}}}}}}, + "indices": []*FuncDef{&FuncDef{Name: &Token{Str: "indices", Start: 2410, Stop: 2416}, Args: []*Token{&Token{Str: "$x", Start: 2418, Stop: 2419}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "_indices", Start: 2423, Stop: 2430}, Args: []*Query{&Query{Func: &Token{Str: "$x"}}}}}}}}, + "inputs": []*FuncDef{&FuncDef{Name: &Token{Str: "inputs", Start: 7261, Stop: 7266}, Body: &Query{Term: &Term{Type: TermTypeTry, Try: &Try{Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "repeat", Start: 7279, Stop: 7284}, Args: []*Query{&Query{Func: &Token{Str: "input"}}}}}}, Catch: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "break", Start: 7313, Stop: 7319}}}}}, Then: &Query{Func: &Token{Str: "empty"}}, Else: &Query{Func: &Token{Str: "error"}}}}}}}}}}, + "inside": []*FuncDef{&FuncDef{Name: &Token{Str: "inside", Start: 2498, Stop: 2503}, Args: []*Token{&Token{Str: "xs", Start: 2505, Stop: 2506}}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: &Token{Str: "$x", Start: 2515, Stop: 2516}}}, Body: &Query{Left: &Query{Func: &Token{Str: "xs"}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "contains", Start: 2525, Stop: 2532}, Args: []*Query{&Query{Func: &Token{Str: "$x"}}}}}}}}}}}}}}, + "isempty": []*FuncDef{&FuncDef{Name: &Token{Str: "isempty", Start: 4060, Stop: 4066}, Args: []*Token{&Token{Str: "g", Start: 4068, Stop: 4068}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "first", Start: 4072, Stop: 4076}, Args: []*Query{&Query{Left: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: &Token{Str: "g"}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "false"}}}}}, Op: OpComma, Right: &Query{Func: &Token{Str: "true"}}}}}}}}}, + "iterables": []*FuncDef{&FuncDef{Name: &Token{Str: "iterables", Start: 2014, Stop: 2022}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "select", Start: 2025, Stop: 2030}, Args: []*Query{&Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpPipe, Right: &Query{Left: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "array", Start: 2044, Stop: 2050}}}}}, Op: OpOr, Right: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "object", Start: 2060, Stop: 2067}}}}}}}}}}}}}, + "join": []*FuncDef{&FuncDef{Name: &Token{Str: "join", Start: 3376, Stop: 3379}, Args: []*Token{&Token{Str: "$x", Start: 3381, Stop: 3382}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}, Pattern: &Pattern{Name: &Token{Str: "$i", Start: 3400, Stop: 3401}}, Start: &Query{Func: &Token{Str: "null"}}, Update: &Query{Left: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpEq, Right: &Query{Func: &Token{Str: "null"}}}, Then: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Start: 3432, Stop: 3433}}}}, Else: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpAdd, Right: &Query{Func: &Token{Str: "$x"}}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: &Token{Str: "$i"}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpPipe, Right: &Query{Left: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "boolean", Start: 3478, Stop: 3486}}}}}, Op: OpOr, Right: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "number", Start: 3496, Stop: 3503}}}}}}}, Then: &Query{Func: &Token{Str: "tostring"}}, Else: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpAlt, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Start: 3529, Stop: 3530}}}}}}}}}}}}}}}, Op: OpAlt, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Start: 3544, Stop: 3545}}}}}}}, + "last": []*FuncDef{&FuncDef{Name: &Token{Str: "last", Start: 3997, Stop: 4000}, Body: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeUnary, Unary: &Unary{Op: OpSub, Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "1", Start: 4006, Stop: 4006}}}}}}}}}, &FuncDef{Name: &Token{Str: "last", Start: 4014, Stop: 4017}, Args: []*Token{&Token{Str: "g", Start: 4019, Stop: 4019}}, Body: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "g", Start: 4030, Stop: 4030}}}, Pattern: &Pattern{Name: &Token{Str: "$item", Start: 4035, Stop: 4039}}, Start: &Query{Func: &Token{Str: "null"}}, Update: &Query{Func: &Token{Str: "$item"}}}}}}}, + "leaf_paths": []*FuncDef{&FuncDef{Name: &Token{Str: "leaf_paths", Start: 2377, Stop: 2386}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "paths", Start: 2389, Stop: 2393}, Args: []*Query{&Query{Func: &Token{Str: "scalars"}}}}}}}}, + "limit": []*FuncDef{&FuncDef{Name: &Token{Str: "limit", Start: 4277, Stop: 4281}, Args: []*Token{&Token{Str: "$n", Start: 4283, Stop: 4284}, &Token{Str: "g", Start: 4287, Stop: 4287}}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: &Token{Str: "$n"}}, Op: OpGt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 4301, Stop: 4301}}}}, Then: &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{Ident: &Token{Str: "$out", Start: 4318, Stop: 4321}, Body: &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "g", Start: 4339, Stop: 4339}}}, Pattern: &Pattern{Name: &Token{Str: "$item", Start: 4344, Stop: 4348}}, Start: &Query{Func: &Token{Str: "$n"}}, Update: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpSub, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "1", Start: 4365, Stop: 4365}}}}, Extract: &Query{Left: &Query{Func: &Token{Str: "$item"}}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpLe, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 4383, Stop: 4383}}}}, Then: &Query{Term: &Term{Type: TermTypeBreak, Break: &Token{Str: "$out", Start: 4396, Stop: 4399}}}, Else: &Query{Func: &Token{Str: "empty"}}}}}}}}}}}}, Elif: []*IfElif{&IfElif{Cond: &Query{Left: &Query{Func: &Token{Str: "$n"}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 4430, Stop: 4430}}}}, Then: &Query{Func: &Token{Str: "empty"}}}}, Else: &Query{Func: &Token{Str: "g"}}}}}}}, + "ltrimstr": []*FuncDef{&FuncDef{Name: &Token{Str: "ltrimstr", Start: 2951, Stop: 2958}, Args: []*Token{&Token{Str: "$x", Start: 2960, Stop: 2961}}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Left: &Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "string", Start: 2978, Stop: 2985}}}}}, Op: OpAnd, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: &Token{Str: "$x"}}, Op: OpPipe, Right: &Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "string", Start: 3003, Stop: 3010}}}}}}}}}, Op: OpAnd, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "startswith", Start: 3017, Stop: 3026}, Args: []*Query{&Query{Func: &Token{Str: "$x"}}}}}}}, Then: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Left: &Query{Func: &Token{Str: "$x"}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "length"}}}, IsSlice: true}}}}}}}}, + "map": []*FuncDef{&FuncDef{Name: &Token{Str: "map", Start: 81, Stop: 83}, Args: []*Token{&Token{Str: "f", Start: 85, Stop: 85}}, Body: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "f"}}}}}}}}, + "map_values": []*FuncDef{&FuncDef{Name: &Token{Str: "map_values", Start: 5538, Stop: 5547}, Args: []*Token{&Token{Str: "f", Start: 5549, Stop: 5549}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, Op: OpModify, Right: &Query{Func: &Token{Str: "f"}}}}}, + "match": []*FuncDef{&FuncDef{Name: &Token{Str: "match", Start: 5966, Stop: 5970}, Args: []*Token{&Token{Str: "$re", Start: 5972, Stop: 5974}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "match", Start: 5978, Stop: 5982}, Args: []*Query{&Query{Func: &Token{Str: "$re"}}, &Query{Func: &Token{Str: "null"}}}}}}}, &FuncDef{Name: &Token{Str: "match", Start: 6000, Stop: 6004}, Args: []*Token{&Token{Str: "$re", Start: 6006, Stop: 6008}, &Token{Str: "$flags", Start: 6011, Stop: 6016}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "_match", Start: 6020, Stop: 6025}, Args: []*Query{&Query{Func: &Token{Str: "$re"}}, &Query{Func: &Token{Str: "$flags"}}, &Query{Func: &Token{Str: "false"}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}, + "max": []*FuncDef{&FuncDef{Name: &Token{Str: "max", Start: 1721, Stop: 1723}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "max_by", Start: 1726, Stop: 1731}, Args: []*Query{&Query{Func: &Token{Str: "."}}}}}}}}, + "max_by": []*FuncDef{&FuncDef{Name: &Token{Str: "max_by", Start: 1741, Stop: 1746}, Args: []*Token{&Token{Str: "f", Start: 1748, Stop: 1748}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "_max_by", Start: 1752, Stop: 1758}, Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "map", Start: 1760, Stop: 1762}, Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: &Token{Str: "f"}}}}}}}}}}}}}}}, + "min": []*FuncDef{&FuncDef{Name: &Token{Str: "min", Start: 1667, Stop: 1669}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "min_by", Start: 1672, Stop: 1677}, Args: []*Query{&Query{Func: &Token{Str: "."}}}}}}}}, + "min_by": []*FuncDef{&FuncDef{Name: &Token{Str: "min_by", Start: 1687, Stop: 1692}, Args: []*Token{&Token{Str: "f", Start: 1694, Stop: 1694}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "_min_by", Start: 1698, Stop: 1704}, Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "map", Start: 1706, Stop: 1708}, Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: &Token{Str: "f"}}}}}}}}}}}}}}}, + "modify": []*FuncDef{&FuncDef{Name: &Token{Str: "_modify", Start: 5343, Stop: 5349}, Args: []*Token{&Token{Str: "ps", Start: 5351, Stop: 5352}, &Token{Str: "f", Start: 5355, Stop: 5355}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "path", Start: 5368, Stop: 5371}, Args: []*Query{&Query{Func: &Token{Str: "ps"}}}}}, Pattern: &Pattern{Name: &Token{Str: "$p", Start: 5380, Stop: 5381}}, Start: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{}}}}}}}, Update: &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{Ident: &Token{Str: "$out", Start: 5403, Stop: 5406}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 5413, Stop: 5413}}}}}}, Op: OpAdd, Right: &Query{Func: &Token{Str: "$p"}}}, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: &Token{Str: "$q", Start: 5425, Stop: 5426}}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "setpath", Start: 5430, Stop: 5436}, Args: []*Query{&Query{Func: &Token{Str: "$q"}}, &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "getpath", Start: 5442, Stop: 5448}, Args: []*Query{&Query{Func: &Token{Str: "$q"}}}}}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "f"}}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeBreak, Break: &Token{Str: "$out", Start: 5470, Stop: 5473}}}}}}}}}}}}, Op: OpComma, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "1", Start: 5479, Stop: 5479}}}}}}, Op: OpUpdateAdd, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: &Token{Str: "$p"}}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: &Token{Str: "$x", Start: 5504, Stop: 5505}}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "$x", Start: 5509, Stop: 5510}}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 5512, Stop: 5512}}}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "delpaths", Start: 5517, Stop: 5524}, Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "$x", Start: 5526, Stop: 5527}}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "1", Start: 5529, Stop: 5529}}}}}}}}}}}}}}}}}}}}}, + "normals": []*FuncDef{&FuncDef{Name: &Token{Str: "normals", Start: 2186, Stop: 2192}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "select", Start: 2195, Stop: 2200}, Args: []*Query{&Query{Func: &Token{Str: "isnormal"}}}}}}}}, + "not": []*FuncDef{&FuncDef{Name: &Token{Str: "not", Start: 5, Stop: 7}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Func: &Token{Str: "."}}, Then: &Query{Func: &Token{Str: "false"}}, Else: &Query{Func: &Token{Str: "true"}}}}}}}, + "nth": []*FuncDef{&FuncDef{Name: &Token{Str: "nth", Start: 4471, Stop: 4473}, Args: []*Token{&Token{Str: "$n", Start: 4475, Stop: 4476}}, Body: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Func: &Token{Str: "$n"}}}}}}, &FuncDef{Name: &Token{Str: "nth", Start: 4491, Stop: 4493}, Args: []*Token{&Token{Str: "$n", Start: 4495, Stop: 4496}, &Token{Str: "g", Start: 4499, Stop: 4499}}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: &Token{Str: "$n"}}, Op: OpLt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 4513, Stop: 4513}}}}, Then: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "error", Start: 4524, Stop: 4528}, Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "nth doesn't support negative indices", Start: 4530, Stop: 4567}}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{Ident: &Token{Str: "$out", Start: 4587, Stop: 4590}, Body: &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "g", Start: 4608, Stop: 4608}}}, Pattern: &Pattern{Name: &Token{Str: "$item", Start: 4613, Stop: 4617}}, Start: &Query{Func: &Token{Str: "$n"}}, Update: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpSub, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "1", Start: 4634, Stop: 4634}}}}, Extract: &Query{Left: &Query{Left: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpLt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 4641, Stop: 4641}}}}, Op: OpOr, Right: &Query{Func: &Token{Str: "empty"}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: &Token{Str: "$item"}}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeBreak, Break: &Token{Str: "$out", Start: 4667, Stop: 4670}}}}}}}}}}}}}}}}, + "nulls": []*FuncDef{&FuncDef{Name: &Token{Str: "nulls", Start: 2256, Stop: 2260}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "select", Start: 2263, Stop: 2268}, Args: []*Query{&Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpEq, Right: &Query{Func: &Token{Str: "null"}}}}}}}}}, + "numbers": []*FuncDef{&FuncDef{Name: &Token{Str: "numbers", Start: 2116, Stop: 2122}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "select", Start: 2125, Stop: 2130}, Args: []*Query{&Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "number", Start: 2140, Stop: 2147}}}}}}}}}}}, + "objects": []*FuncDef{&FuncDef{Name: &Token{Str: "objects", Start: 1975, Stop: 1981}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "select", Start: 1984, Stop: 1989}, Args: []*Query{&Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "object", Start: 1999, Stop: 2006}}}}}}}}}}}, + "paths": []*FuncDef{&FuncDef{Name: &Token{Str: "paths", Start: 5600, Stop: 5604}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "path", Start: 5609, Stop: 5612}, Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "recurse", Start: 5614, Stop: 5620}, Args: []*Query{&Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpPipe, Right: &Query{Left: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "array", Start: 5637, Stop: 5643}}}}}, Op: OpOr, Right: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "object", Start: 5653, Stop: 5660}}}}}}}, Then: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, Else: &Query{Func: &Token{Str: "empty"}}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "select", Start: 5694, Stop: 5699}, Args: []*Query{&Query{Left: &Query{Func: &Token{Str: "length"}}, Op: OpGt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 5710, Stop: 5710}}}}}}}}}}, &FuncDef{Name: &Token{Str: "paths", Start: 5718, Stop: 5722}, Args: []*Token{&Token{Str: "f", Start: 5724, Stop: 5724}}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: &Token{Str: "$x", Start: 5735, Stop: 5736}}}, Body: &Query{Left: &Query{Func: &Token{Str: "paths"}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "select", Start: 5748, Stop: 5753}, Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: &Token{Str: "$p", Start: 5760, Stop: 5761}}}, Body: &Query{Left: &Query{Func: &Token{Str: "$x"}}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "getpath", Start: 5770, Stop: 5776}, Args: []*Query{&Query{Func: &Token{Str: "$p"}}}}}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "f"}}}}}}}}}}}}}}}}}}}}}, + "range": []*FuncDef{&FuncDef{Name: &Token{Str: "range", Start: 752, Stop: 756}, Args: []*Token{&Token{Str: "$x", Start: 758, Stop: 759}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "range", Start: 763, Stop: 767}, Args: []*Query{&Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 769, Stop: 769}}}, &Query{Func: &Token{Str: "$x"}}}}}}}, &FuncDef{Name: &Token{Str: "range", Start: 781, Stop: 785}, Args: []*Token{&Token{Str: "$start", Start: 787, Stop: 792}, &Token{Str: "$end", Start: 795, Stop: 798}}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: &Token{Str: "$start"}}, Op: OpPipe, Right: &Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "number", Start: 824, Stop: 831}}}}}}, Then: &Query{Left: &Query{Func: &Token{Str: "$start"}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "_type_error", Start: 851, Stop: 861}, Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "range", Start: 863, Stop: 869}}}}}}}}}, Elif: []*IfElif{&IfElif{Cond: &Query{Left: &Query{Func: &Token{Str: "$end"}}, Op: OpPipe, Right: &Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "number", Start: 894, Stop: 901}}}}}}, Then: &Query{Left: &Query{Func: &Token{Str: "$end"}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "_type_error", Start: 919, Stop: 929}, Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "range", Start: 931, Stop: 937}}}}}}}}}}}, Else: &Query{Left: &Query{Func: &Token{Str: "$start"}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "while", Start: 960, Stop: 964}, Args: []*Query{&Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpLt, Right: &Query{Func: &Token{Str: "$end"}}}, &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "1", Start: 980, Stop: 980}}}}}}}}}}}}}, &FuncDef{Name: &Token{Str: "range", Start: 994, Stop: 998}, Args: []*Token{&Token{Str: "$start", Start: 1000, Stop: 1005}, &Token{Str: "$end", Start: 1008, Stop: 1011}, &Token{Str: "$step", Start: 1014, Stop: 1018}}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: &Token{Str: "$start"}}, Op: OpPipe, Right: &Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "number", Start: 1044, Stop: 1051}}}}}}, Then: &Query{Left: &Query{Func: &Token{Str: "$start"}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "_type_error", Start: 1071, Stop: 1081}, Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "range", Start: 1083, Stop: 1089}}}}}}}}}, Elif: []*IfElif{&IfElif{Cond: &Query{Left: &Query{Func: &Token{Str: "$end"}}, Op: OpPipe, Right: &Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "number", Start: 1114, Stop: 1121}}}}}}, Then: &Query{Left: &Query{Func: &Token{Str: "$end"}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "_type_error", Start: 1139, Stop: 1149}, Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "range", Start: 1151, Stop: 1157}}}}}}}}}}, &IfElif{Cond: &Query{Left: &Query{Func: &Token{Str: "$step"}}, Op: OpPipe, Right: &Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "number", Start: 1183, Stop: 1190}}}}}}, Then: &Query{Left: &Query{Func: &Token{Str: "$step"}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "_type_error", Start: 1209, Stop: 1219}, Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "range", Start: 1221, Stop: 1227}}}}}}}}}}, &IfElif{Cond: &Query{Left: &Query{Func: &Token{Str: "$step"}}, Op: OpGt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 1245, Stop: 1245}}}}, Then: &Query{Left: &Query{Func: &Token{Str: "$start"}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "while", Start: 1265, Stop: 1269}, Args: []*Query{&Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpLt, Right: &Query{Func: &Token{Str: "$end"}}}, &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpAdd, Right: &Query{Func: &Token{Str: "$step"}}}}}}}}}, &IfElif{Cond: &Query{Left: &Query{Func: &Token{Str: "$step"}}, Op: OpLt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 1307, Stop: 1307}}}}, Then: &Query{Left: &Query{Func: &Token{Str: "$start"}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "while", Start: 1327, Stop: 1331}, Args: []*Query{&Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpGt, Right: &Query{Func: &Token{Str: "$end"}}}, &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpAdd, Right: &Query{Func: &Token{Str: "$step"}}}}}}}}}}, Else: &Query{Func: &Token{Str: "empty"}}}}}}}, + "recurse": []*FuncDef{&FuncDef{Name: &Token{Str: "recurse", Start: 388, Stop: 394}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "recurse", Start: 397, Stop: 403}, Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Optional: true}}}}}}}}}, &FuncDef{Name: &Token{Str: "recurse", Start: 416, Stop: 422}, Args: []*Token{&Token{Str: "f", Start: 424, Stop: 424}}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: &Token{Str: "r", Start: 432, Stop: 432}, Body: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: &Token{Str: "f"}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "r"}}}}}}}}, Func: &Token{Str: "r"}}}, &FuncDef{Name: &Token{Str: "recurse", Start: 454, Stop: 460}, Args: []*Token{&Token{Str: "f", Start: 462, Stop: 462}, &Token{Str: "cond", Start: 465, Stop: 468}}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: &Token{Str: "r", Start: 476, Stop: 476}, Body: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: &Token{Str: "f"}}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "select", Start: 487, Stop: 492}, Args: []*Query{&Query{Func: &Token{Str: "cond"}}}}}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "r"}}}}}}}}}, Func: &Token{Str: "r"}}}}, + "repeat": []*FuncDef{&FuncDef{Name: &Token{Str: "repeat", Start: 699, Stop: 704}, Args: []*Token{&Token{Str: "f", Start: 706, Stop: 706}}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: &Token{Str: "_repeat", Start: 716, Stop: 722}, Body: &Query{Left: &Query{Func: &Token{Str: "f"}}, Op: OpComma, Right: &Query{Func: &Token{Str: "_repeat"}}}}}, Func: &Token{Str: "_repeat"}}}}, + "rindex": []*FuncDef{&FuncDef{Name: &Token{Str: "rindex", Start: 2469, Stop: 2474}, Args: []*Token{&Token{Str: "$x", Start: 2476, Stop: 2477}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "_rindex", Start: 2481, Stop: 2487}, Args: []*Query{&Query{Func: &Token{Str: "$x"}}}}}}}}, + "rtrimstr": []*FuncDef{&FuncDef{Name: &Token{Str: "rtrimstr", Start: 3068, Stop: 3075}, Args: []*Token{&Token{Str: "$x", Start: 3077, Stop: 3078}}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Left: &Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "string", Start: 3095, Stop: 3102}}}}}, Op: OpAnd, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: &Token{Str: "$x"}}, Op: OpPipe, Right: &Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "string", Start: 3120, Stop: 3127}}}}}}}}}, Op: OpAnd, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "endswith", Start: 3134, Stop: 3141}, Args: []*Query{&Query{Func: &Token{Str: "$x"}}}}}}}, Then: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{End: &Query{Term: &Term{Type: TermTypeUnary, Unary: &Unary{Op: OpSub, Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: &Token{Str: "$x"}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "length"}}}}}}}}}}}}}}}, + "scalars": []*FuncDef{&FuncDef{Name: &Token{Str: "scalars", Start: 2317, Stop: 2323}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "select", Start: 2326, Stop: 2331}, Args: []*Query{&Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpPipe, Right: &Query{Left: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "array", Start: 2345, Stop: 2351}}}}}, Op: OpAnd, Right: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "object", Start: 2362, Stop: 2369}}}}}}}}}}}}}, + "scan": []*FuncDef{&FuncDef{Name: &Token{Str: "scan", Start: 6309, Stop: 6312}, Args: []*Token{&Token{Str: "$re", Start: 6314, Stop: 6316}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "scan", Start: 6320, Stop: 6323}, Args: []*Query{&Query{Func: &Token{Str: "$re"}}, &Query{Func: &Token{Str: "null"}}}}}}}, &FuncDef{Name: &Token{Str: "scan", Start: 6341, Stop: 6344}, Args: []*Token{&Token{Str: "$re", Start: 6346, Stop: 6348}, &Token{Str: "$flags", Start: 6351, Stop: 6356}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "match", Start: 6362, Stop: 6366}, Args: []*Query{&Query{Func: &Token{Str: "$re"}}, &Query{Left: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "g", Start: 6373, Stop: 6375}}}}, Op: OpAdd, Right: &Query{Func: &Token{Str: "$flags"}}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: &Token{Str: "captures", Start: 6396, Stop: 6404}}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: &Token{Str: "length"}}, Op: OpGt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 6415, Stop: 6415}}}}}, Then: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: &Token{Str: "captures", Start: 6423, Stop: 6431}}, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Index: &Index{Name: &Token{Str: "string", Start: 6434, Stop: 6440}}}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: &Token{Str: "string", Start: 6448, Stop: 6454}}}}}}}}}}, + "select": []*FuncDef{&FuncDef{Name: &Token{Str: "select", Start: 345, Stop: 350}, Args: []*Token{&Token{Str: "f", Start: 352, Stop: 352}}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Func: &Token{Str: "f"}}, Then: &Query{Func: &Token{Str: "."}}, Else: &Query{Func: &Token{Str: "empty"}}}}}}}, + "sort": []*FuncDef{&FuncDef{Name: &Token{Str: "sort", Start: 1775, Stop: 1778}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "sort_by", Start: 1781, Stop: 1787}, Args: []*Query{&Query{Func: &Token{Str: "."}}}}}}}}, + "sort_by": []*FuncDef{&FuncDef{Name: &Token{Str: "sort_by", Start: 1797, Stop: 1803}, Args: []*Token{&Token{Str: "f", Start: 1805, Stop: 1805}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "_sort_by", Start: 1809, Stop: 1816}, Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "map", Start: 1818, Stop: 1820}, Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: &Token{Str: "f"}}}}}}}}}}}}}}}, + "splits": []*FuncDef{&FuncDef{Name: &Token{Str: "splits", Start: 6465, Stop: 6470}, Args: []*Token{&Token{Str: "$re", Start: 6472, Stop: 6474}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "splits", Start: 6478, Stop: 6483}, Args: []*Query{&Query{Func: &Token{Str: "$re"}}, &Query{Func: &Token{Str: "null"}}}}}}}, &FuncDef{Name: &Token{Str: "splits", Start: 6501, Stop: 6506}, Args: []*Token{&Token{Str: "$re", Start: 6508, Stop: 6510}, &Token{Str: "$flags", Start: 6513, Stop: 6518}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "split", Start: 6522, Stop: 6526}, Args: []*Query{&Query{Func: &Token{Str: "$re"}}, &Query{Func: &Token{Str: "$flags"}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}, + "startswith": []*FuncDef{&FuncDef{Name: &Token{Str: "startswith", Start: 2543, Stop: 2552}, Args: []*Token{&Token{Str: "$x", Start: 2554, Stop: 2555}}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "string", Start: 2572, Stop: 2579}}}}}, Then: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: &Token{Str: "$x"}}, Op: OpPipe, Right: &Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "string", Start: 2604, Stop: 2611}}}}}}, Then: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{End: &Query{Left: &Query{Func: &Token{Str: "$x"}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "length"}}}}}}, Op: OpEq, Right: &Query{Func: &Token{Str: "$x"}}}, Else: &Query{Left: &Query{Func: &Token{Str: "$x"}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "_type_error", Start: 2666, Stop: 2676}, Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "startswith", Start: 2678, Stop: 2689}}}}}}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "_type_error", Start: 2711, Stop: 2721}, Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "startswith", Start: 2723, Stop: 2734}}}}}}}}}}}}}, + "strings": []*FuncDef{&FuncDef{Name: &Token{Str: "strings", Start: 2217, Stop: 2223}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "select", Start: 2226, Stop: 2231}, Args: []*Query{&Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "string", Start: 2241, Stop: 2248}}}}}}}}}}}, + "sub": []*FuncDef{&FuncDef{Name: &Token{Str: "sub", Start: 6552, Stop: 6554}, Args: []*Token{&Token{Str: "$re", Start: 6556, Stop: 6558}, &Token{Str: "str", Start: 6561, Stop: 6563}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "sub", Start: 6567, Stop: 6569}, Args: []*Query{&Query{Func: &Token{Str: "$re"}}, &Query{Func: &Token{Str: "str"}}, &Query{Func: &Token{Str: "null"}}}}}}}, &FuncDef{Name: &Token{Str: "sub", Start: 6592, Stop: 6594}, Args: []*Token{&Token{Str: "$re", Start: 6596, Stop: 6598}, &Token{Str: "str", Start: 6601, Stop: 6603}, &Token{Str: "$flags", Start: 6606, Stop: 6611}}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: &Token{Str: "$in", Start: 6622, Stop: 6624}}}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: &Token{Str: "sub", Start: 6636, Stop: 6638}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: &Token{Str: "matches", Start: 6652, Stop: 6659}}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: &Token{Str: "length"}}, Op: OpGt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 6670, Stop: 6670}}}}}, Then: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: &Token{Str: "$x", Start: 6700, Stop: 6701}}}, Body: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: &Token{Str: "matches", Start: 6705, Stop: 6712}}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 6714, Stop: 6714}}}}}, &Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: &Token{Str: "$r", Start: 6720, Stop: 6721}}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "$r", Start: 6738, Stop: 6739}}, SuffixList: []*Suffix{&Suffix{Index: &Index{Name: &Token{Str: "captures", Start: 6740, Stop: 6748}}}, &Suffix{Iter: true}}}}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "select", Start: 6754, Stop: 6759}, Args: []*Query{&Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: &Token{Str: "name", Start: 6761, Stop: 6765}}}}, Op: OpNe, Right: &Query{Func: &Token{Str: "null"}}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{KeyQuery: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: &Token{Str: "name", Start: 6781, Stop: 6785}}}}, Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: &Token{Str: "string", Start: 6789, Stop: 6795}}}}}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Left: &Query{Func: &Token{Str: "add"}}, Op: OpAlt, Right: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{}}}}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{Key: &Token{Str: "string", Start: 6856, Stop: 6861}, Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "$x", Start: 6865, Stop: 6866}}, SuffixList: []*Suffix{&Suffix{Index: &Index{Name: &Token{Str: "string", Start: 6867, Stop: 6873}}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "$in", Start: 6877, Stop: 6879}}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "$x", Start: 6881, Stop: 6882}}, SuffixList: []*Suffix{&Suffix{Index: &Index{Name: &Token{Str: "offset", Start: 6883, Stop: 6889}}}}}}, IsSlice: true, End: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "$r", Start: 6891, Stop: 6892}}, SuffixList: []*Suffix{&Suffix{Index: &Index{Name: &Token{Str: "offset", Start: 6893, Stop: 6899}}}}}}}}}}}}, Op: OpAdd, Right: &Query{Func: &Token{Str: "str"}}}}}}}}, &ObjectKeyVal{Key: &Token{Str: "offset", Start: 6926, Stop: 6931}, Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "$r", Start: 6935, Stop: 6936}}, SuffixList: []*Suffix{&Suffix{Index: &Index{Name: &Token{Str: "offset", Start: 6937, Stop: 6943}}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "$r", Start: 6947, Stop: 6948}}, SuffixList: []*Suffix{&Suffix{Index: &Index{Name: &Token{Str: "length", Start: 6949, Stop: 6955}}}}}}}}}}}}, &ObjectKeyVal{Key: &Token{Str: "matches", Start: 6975, Stop: 6981}, Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "$x", Start: 6984, Stop: 6985}}, SuffixList: []*Suffix{&Suffix{Index: &Index{Name: &Token{Str: "matches", Start: 6986, Stop: 6993}}}, &Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "1", Start: 6995, Stop: 6995}}}, IsSlice: true}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "sub"}}}}}}}}}}}}}}}, Else: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: &Token{Str: "string", Start: 7056, Stop: 7062}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "$in", Start: 7066, Stop: 7068}}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: &Token{Str: "offset", Start: 7070, Stop: 7076}}}}, IsSlice: true}}}}}}}}}}}, Left: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{Key: &Token{Str: "string", Start: 7097, Stop: 7102}, Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Start: 7105, Stop: 7106}}}}}}}, &ObjectKeyVal{Key: &Token{Str: "offset", Start: 7109, Stop: 7114}, Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 7117, Stop: 7117}}}}}}, &ObjectKeyVal{Key: &Token{Str: "matches", Start: 7120, Stop: 7126}, Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "match", Start: 7130, Stop: 7134}, Args: []*Query{&Query{Func: &Token{Str: "$re"}}, &Query{Func: &Token{Str: "$flags"}}}}}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "sub"}}}}}}}}}}, + "test": []*FuncDef{&FuncDef{Name: &Token{Str: "test", Start: 6058, Stop: 6061}, Args: []*Token{&Token{Str: "$re", Start: 6063, Stop: 6065}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "test", Start: 6069, Stop: 6072}, Args: []*Query{&Query{Func: &Token{Str: "$re"}}, &Query{Func: &Token{Str: "null"}}}}}}}, &FuncDef{Name: &Token{Str: "test", Start: 6090, Stop: 6093}, Args: []*Token{&Token{Str: "$re", Start: 6095, Stop: 6097}, &Token{Str: "$flags", Start: 6100, Stop: 6105}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "_match", Start: 6109, Stop: 6114}, Args: []*Query{&Query{Func: &Token{Str: "$re"}}, &Query{Func: &Token{Str: "$flags"}}, &Query{Func: &Token{Str: "true"}}}}}}}}, + "to_entries": []*FuncDef{&FuncDef{Name: &Token{Str: "to_entries", Start: 104, Stop: 113}, Body: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "keys", Start: 117, Stop: 120}}, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: &Token{Str: "$k", Start: 127, Stop: 128}}}, Body: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{Key: &Token{Str: "key", Start: 133, Stop: 135}, Val: &ObjectVal{Queries: []*Query{&Query{Func: &Token{Str: "$k"}}}}}, &ObjectKeyVal{Key: &Token{Str: "value", Start: 142, Stop: 146}, Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Func: &Token{Str: "$k"}}}}}}}}}}}}}}}}}}}}}}, + "todate": []*FuncDef{&FuncDef{Name: &Token{Str: "todate", Start: 5938, Stop: 5943}, Body: &Query{Func: &Token{Str: "todateiso8601"}}}}, + "todateiso8601": []*FuncDef{&FuncDef{Name: &Token{Str: "todateiso8601", Start: 5856, Stop: 5868}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "strftime", Start: 5871, Stop: 5878}, Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "%Y-%m-%dT%H:%M:%SZ", Start: 5880, Stop: 5899}}}}}}}}}}, + "tostream": []*FuncDef{&FuncDef{Name: &Token{Str: "tostream", Start: 5153, Stop: 5160}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "path", Start: 5165, Stop: 5168}, Args: []*Query{&Query{FuncDefs: []*FuncDef{&FuncDef{Name: &Token{Str: "r", Start: 5174, Stop: 5174}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Optional: true}}}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "r"}}}}}, Op: OpComma, Right: &Query{Func: &Token{Str: "."}}}}}, Func: &Token{Str: "r"}}}}, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: &Token{Str: "$p", Start: 5198, Stop: 5199}}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "getpath", Start: 5207, Stop: 5213}, Args: []*Query{&Query{Func: &Token{Str: "$p"}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "path", Start: 5232, Stop: 5235}, Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Optional: true}}}}}}}, Pattern: &Pattern{Name: &Token{Str: "$q", Start: 5246, Stop: 5247}}, Start: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: &Token{Str: "$p"}}, Op: OpComma, Right: &Query{Func: &Token{Str: "."}}}}}}, Update: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: &Token{Str: "$p"}}, Op: OpAdd, Right: &Query{Func: &Token{Str: "$q"}}}}}}}}}}}}}}}}}, + "truncate_stream": []*FuncDef{&FuncDef{Name: &Token{Str: "truncate_stream", Start: 4685, Stop: 4699}, Args: []*Token{&Token{Str: "f", Start: 4701, Stop: 4701}}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: &Token{Str: "$n", Start: 4712, Stop: 4713}}}, Body: &Query{Left: &Query{Func: &Token{Str: "null"}}, Op: OpPipe, Right: &Query{Left: &Query{Func: &Token{Str: "f"}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: &Token{Str: "$input", Start: 4733, Stop: 4738}}}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 4752, Stop: 4752}}}}}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "length"}}}}}, Op: OpGt, Right: &Query{Func: &Token{Str: "$n"}}}, Then: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "setpath", Start: 4775, Stop: 4781}, Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 4784, Stop: 4784}}}}}}, &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "$input", Start: 4788, Stop: 4793}}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: &Token{Str: "0", Start: 4795, Stop: 4795}}}}}, &Suffix{Index: &Index{Start: &Query{Func: &Token{Str: "$n"}}, IsSlice: true}}}}}}}}}, Else: &Query{Func: &Token{Str: "empty"}}}}}}}}}}}}}}}}}}}, + "unique": []*FuncDef{&FuncDef{Name: &Token{Str: "unique", Start: 1871, Stop: 1876}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "unique_by", Start: 1879, Stop: 1887}, Args: []*Query{&Query{Func: &Token{Str: "."}}}}}}}}, + "unique_by": []*FuncDef{&FuncDef{Name: &Token{Str: "unique_by", Start: 1897, Stop: 1905}, Args: []*Token{&Token{Str: "f", Start: 1907, Stop: 1907}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "_unique_by", Start: 1911, Stop: 1920}, Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "map", Start: 1922, Stop: 1924}, Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: &Token{Str: "f"}}}}}}}}}}}}}}}, + "until": []*FuncDef{&FuncDef{Name: &Token{Str: "until", Start: 613, Stop: 617}, Args: []*Token{&Token{Str: "cond", Start: 619, Stop: 622}, &Token{Str: "next", Start: 625, Stop: 628}}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: &Token{Str: "_until", Start: 638, Stop: 643}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Func: &Token{Str: "cond"}}, Then: &Query{Func: &Token{Str: "."}}, Else: &Query{Left: &Query{Func: &Token{Str: "next"}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "_until"}}}}}}}}, Func: &Token{Str: "_until"}}}}, + "values": []*FuncDef{&FuncDef{Name: &Token{Str: "values", Start: 2286, Stop: 2291}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "select", Start: 2294, Stop: 2299}, Args: []*Query{&Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpNe, Right: &Query{Func: &Token{Str: "null"}}}}}}}}}, + "walk": []*FuncDef{&FuncDef{Name: &Token{Str: "walk", Start: 3725, Stop: 3728}, Args: []*Token{&Token{Str: "f", Start: 3730, Stop: 3730}}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: &Token{Str: "w", Start: 3740, Stop: 3740}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "object", Start: 3758, Stop: 3765}}}}}, Then: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: &Token{Str: "$in", Start: 3783, Stop: 3785}}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "keys", Start: 3796, Stop: 3799}}, SuffixList: []*Suffix{&Suffix{Iter: true}}}, Pattern: &Pattern{Name: &Token{Str: "$key", Start: 3806, Stop: 3809}}, Start: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{}}}, Update: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{KeyQuery: &Query{Func: &Token{Str: "$key"}}, Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "$in", Start: 3830, Stop: 3832}}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Func: &Token{Str: "$key"}}}}}}}, &Query{Func: &Token{Str: "w"}}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "f"}}}}}}}}, Elif: []*IfElif{&IfElif{Cond: &Query{Left: &Query{Func: &Token{Str: "type"}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: "array", Start: 3868, Stop: 3874}}}}}, Then: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "map", Start: 3887, Stop: 3889}, Args: []*Query{&Query{Func: &Token{Str: "w"}}}}}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "f"}}}}}, Else: &Query{Func: &Token{Str: "f"}}}}}}}, Func: &Token{Str: "w"}}}}, + "while": []*FuncDef{&FuncDef{Name: &Token{Str: "while", Start: 514, Stop: 518}, Args: []*Token{&Token{Str: "cond", Start: 520, Stop: 523}, &Token{Str: "update", Start: 526, Stop: 531}}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: &Token{Str: "_while", Start: 541, Stop: 546}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Func: &Token{Str: "cond"}}, Then: &Query{Left: &Query{Func: &Token{Str: "."}}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: &Token{Str: "update"}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "_while"}}}}}}, Else: &Query{Func: &Token{Str: "empty"}}}}}}}, Func: &Token{Str: "_while"}}}}, + "with_entries": []*FuncDef{&FuncDef{Name: &Token{Str: "with_entries", Start: 288, Stop: 299}, Args: []*Token{&Token{Str: "f", Start: 301, Stop: 301}}, Body: &Query{Left: &Query{Func: &Token{Str: "to_entries"}}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: &Token{Str: "map", Start: 318, Stop: 320}, Args: []*Query{&Query{Func: &Token{Str: "f"}}}}}}, Op: OpPipe, Right: &Query{Func: &Token{Str: "from_entries"}}}}}}, } } diff --git a/compiler.go b/compiler.go index 460c514f..e1e9a40e 100644 --- a/compiler.go +++ b/compiler.go @@ -148,10 +148,10 @@ func (c *compiler) compile(q *Query) error { func (c *compiler) compileImport(i *Import) error { var path, alias string var err error - if i.ImportPath != "" { - path, alias = i.ImportPath, i.ImportAlias + if i.ImportPath != nil { + path, alias = i.ImportPath.Str, i.ImportAlias.Str } else { - path = i.IncludePath + path = i.IncludePath.Str } if c.moduleLoader == nil { return fmt.Errorf("cannot load module: %q", path) @@ -301,7 +301,7 @@ func (c *compiler) compileFuncDef(e *FuncDef, builtin bool) error { if builtin { scope = c.scopes[0] for i := len(scope.funcs) - 1; i >= 0; i-- { - if f := scope.funcs[i]; f.name == e.Name && f.argcnt == len(e.Args) { + if f := scope.funcs[i]; f.name == e.Name.Str && f.argcnt == len(e.Args) { return nil } } @@ -311,10 +311,10 @@ func (c *compiler) compileFuncDef(e *FuncDef, builtin bool) error { defer c.lazy(func() *code { return &code{op: opjump, v: c.pc()} })() - c.appendCodeInfo(e.Name) - defer c.appendCodeInfo("end of " + e.Name) + c.appendCodeInfo(e.Name.Str) + defer c.appendCodeInfo("end of " + e.Name.Str) pc := c.pc() - scope.funcs = append(scope.funcs, &funcinfo{e.Name, pc, len(e.Args)}) + scope.funcs = append(scope.funcs, &funcinfo{e.Name.Str, pc, len(e.Args)}) defer func(l int, variables []string) { c.scopes, c.variables = c.scopes[:l], variables }(len(c.scopes), c.variables) @@ -333,14 +333,14 @@ func (c *compiler) compileFuncDef(e *FuncDef, builtin bool) error { v := c.newVariable() c.append(&code{op: opstore, v: v}) for _, arg := range e.Args { - if arg[0] == '$' { - c.appendCodeInfo(arg[1:]) - w := c.createVariable(arg[1:]) + if arg.Str[0] == '$' { + c.appendCodeInfo(arg.Str[1:]) + w := c.createVariable(arg.Str[1:]) c.append(&code{op: opstore, v: w}) - vis = append(vis, varIndex{arg, w}) + vis = append(vis, varIndex{arg.Str, w}) } else { c.appendCodeInfo(arg) - c.append(&code{op: opstore, v: c.createVariable(arg)}) + c.append(&code{op: opstore, v: c.createVariable(arg.Str)}) } } for _, w := range vis { @@ -361,8 +361,8 @@ func (c *compiler) compileQuery(e *Query) error { return err } } - if e.Func != "" { - switch e.Func { + if e.Func != nil { + switch e.Func.Str { case ".": return c.compileTerm(&Term{Type: TermTypeIdentity}) case "..": @@ -486,7 +486,7 @@ func (c *compiler) compileQueryUpdate(l, r *Query, op Operator) error { case OpModify: return c.compileFunc( &Func{ - Name: op.getFunc(), + Name: &Token{Str: op.getFunc()}, // TODO: should not use token? Args: []*Query{l, r}, }, ) @@ -499,16 +499,16 @@ func (c *compiler) compileQueryUpdate(l, r *Query, op Operator) error { c.append(&code{op: opstore, v: c.pushVariable(name)}) return c.compileFunc( &Func{ - Name: "_modify", + Name: &Token{Str: "_modify"}, // TODO: should not use token? Args: []*Query{ l, {Term: &Term{ Type: TermTypeFunc, Func: &Func{ - Name: op.getFunc(), + Name: &Token{Str: op.getFunc()}, Args: []*Query{ {Term: &Term{Type: TermTypeIdentity}}, - {Func: name}, + {Func: &Token{Str: name}}, }, }, }}, @@ -559,8 +559,8 @@ func (c *compiler) compileBind(b *Bind) error { func (c *compiler) compilePattern(p *Pattern) ([][2]int, error) { c.appendCodeInfo(p) - if p.Name != "" { - v := c.pushVariable(p.Name) + if p.Name != nil { + v := c.pushVariable(p.Name.Str) c.append(&code{op: opstore, v: v}) return [][2]int{v}, nil } else if len(p.Array) > 0 { @@ -586,11 +586,11 @@ func (c *compiler) compilePattern(p *Pattern) ([][2]int, error) { c.append(&code{op: opstore, v: v}) for _, kv := range p.Object { var key, name string - if kv.KeyOnly != "" { - key, name = kv.KeyOnly[1:], kv.KeyOnly + if kv.KeyOnly != nil { + key, name = kv.KeyOnly.Str[1:], kv.KeyOnly.Str c.append(&code{op: oppush, v: key}) - } else if kv.Key != "" { - key = kv.Key + } else if kv.Key != nil { + key = kv.Key.Str if key != "" && key[0] == '$' { key, name = key[1:], key } @@ -614,7 +614,7 @@ func (c *compiler) compilePattern(p *Pattern) ([][2]int, error) { if kv.Val != nil { c.append(&code{op: opdup}) } - ns, err := c.compilePattern(&Pattern{Name: name}) + ns, err := c.compilePattern(&Pattern{Name: &Token{Str: name}}) if err != nil { return nil, err } @@ -772,7 +772,7 @@ func (c *compiler) compileForeach(e *Foreach) error { func (c *compiler) compileLabel(e *Label) error { c.appendCodeInfo(e) - v := c.pushVariable("$%" + e.Ident[1:]) + v := c.pushVariable("$%" + e.Ident.Str[1:]) defer c.lazy(func() *code { return &code{op: opforklabel, v: v} })() @@ -807,7 +807,7 @@ func (c *compiler) compileTerm(e *Term) error { case TermTypeIdentity: return nil case TermTypeRecurse: - return c.compileFunc(&Func{Name: "recurse"}) + return c.compileFunc(&Func{Name: &Token{Str: "recurse"}}) case TermTypeNull: c.append(&code{op: opconst, v: nil}) return nil @@ -826,7 +826,7 @@ func (c *compiler) compileTerm(e *Term) error { case TermTypeArray: return c.compileArray(e.Array) case TermTypeNumber: - v := normalizeNumbers(json.Number(e.Number)) + v := normalizeNumbers(json.Number(e.Number.Str)) if err, ok := v.(error); ok { return err } @@ -835,7 +835,7 @@ func (c *compiler) compileTerm(e *Term) error { case TermTypeUnary: return c.compileUnary(e.Unary) case TermTypeFormat: - return c.compileFormat(e.Format, e.Str) + return c.compileFormat(e.Format.Str, e.Str) case TermTypeString: return c.compileString(e.Str, nil) case TermTypeIf: @@ -849,7 +849,7 @@ func (c *compiler) compileTerm(e *Term) error { case TermTypeLabel: return c.compileLabel(e.Label) case TermTypeBreak: - return c.compileBreak(e.Break) + return c.compileBreak(e.Break.Str) case TermTypeQuery: defer c.newScopeDepth()() return c.compileQuery(e.Query) @@ -860,8 +860,8 @@ func (c *compiler) compileTerm(e *Term) error { func (c *compiler) compileIndex(e *Term, x *Index) error { c.appendCodeInfo(x) - if x.Name != "" { - return c.compileCall("_index", []*Query{{Term: e}, {Term: &Term{Type: TermTypeString, Str: &String{Str: x.Name}}}}) + if x.Name != nil { + return c.compileCall("_index", []*Query{{Term: e}, {Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: x.Name.Str}}}}}) } if x.Str != nil { return c.compileCall("_index", []*Query{{Term: e}, {Term: &Term{Type: TermTypeString, Str: x.Str}}}) @@ -879,7 +879,7 @@ func (c *compiler) compileIndex(e *Term, x *Index) error { } func (c *compiler) compileFunc(e *Func) error { - name := e.Name + name := e.Name.Str if len(e.Args) == 0 { if f, v := c.lookupFuncOrVariable(name); f != nil { return c.compileCallPc(f, e.Args) @@ -929,26 +929,26 @@ func (c *compiler) compileFunc(e *Func) error { } s := c.scopes[0] for i := len(s.funcs) - 1; i >= 0; i-- { - if f := s.funcs[i]; f.name == e.Name && f.argcnt == len(e.Args) { + if f := s.funcs[i]; f.name == e.Name.Str && f.argcnt == len(e.Args) { return c.compileCallPc(f, e.Args) } } } - if fn, ok := internalFuncs[e.Name]; ok && fn.accept(len(e.Args)) { - switch e.Name { + if fn, ok := internalFuncs[e.Name.Str]; ok && fn.accept(len(e.Args)) { + switch e.Name.Str { case "empty": c.append(&code{op: opbacktrack}) return nil case "path": c.append(&code{op: oppathbegin}) - if err := c.compileCall(e.Name, e.Args); err != nil { + if err := c.compileCall(e.Name.Str, e.Args); err != nil { return err } c.codes[len(c.codes)-1] = &code{op: oppathend} return nil case "builtins": return c.compileCallInternal( - [3]interface{}{c.funcBuiltins, 0, e.Name}, + [3]interface{}{c.funcBuiltins, 0, e.Name.Str}, e.Args, true, false, @@ -958,25 +958,25 @@ func (c *compiler) compileFunc(e *Func) error { return &inputNotAllowedError{} } return c.compileCallInternal( - [3]interface{}{c.funcInput, 0, e.Name}, + [3]interface{}{c.funcInput, 0, e.Name.Str}, e.Args, true, false, ) case "modulemeta": return c.compileCallInternal( - [3]interface{}{c.funcModulemeta, 0, e.Name}, + [3]interface{}{c.funcModulemeta, 0, e.Name.Str}, e.Args, true, false, ) default: - return c.compileCall(e.Name, e.Args) + return c.compileCall(e.Name.Str, e.Args) } } - if fn, ok := c.customFuncs[e.Name]; ok && fn.accept(len(e.Args)) { + if fn, ok := c.customFuncs[e.Name.Str]; ok && fn.accept(len(e.Args)) { if err := c.compileCallInternal( - [3]interface{}{fn.callback, len(e.Args), e.Name}, + [3]interface{}{fn.callback, len(e.Args), e.Name.Str}, e.Args, true, false, @@ -999,8 +999,8 @@ func (c *compiler) funcBuiltins(interface{}, []interface{}) interface{} { var xs []*funcNameArity for _, fds := range builtinFuncDefs { for _, fd := range fds { - if fd.Name[0] != '_' { - xs = append(xs, &funcNameArity{fd.Name, len(fd.Args)}) + if fd.Name.Str[0] != '_' { + xs = append(xs, &funcNameArity{fd.Name.Str, len(fd.Args)}) } } } @@ -1081,18 +1081,22 @@ func (c *compiler) funcModulemeta(v interface{}, _ []interface{}) interface{} { } } } - if i.ImportPath == "" { - v["relpath"] = i.IncludePath - } else { - v["relpath"] = i.ImportPath + if i.ImportPath != nil { + v["relpath"] = i.ImportPath.Str + } else if i.IncludePath != nil { + v["relpath"] = i.IncludePath.Str } if err != nil { return err } - if i.ImportAlias != "" { - v["as"] = strings.TrimPrefix(i.ImportAlias, "$") + var as string + if i.ImportAlias != nil { + as = i.ImportAlias.Str + } + if as != "" { + v["as"] = strings.TrimPrefix(as, "$") } - v["is_data"] = strings.HasPrefix(i.ImportAlias, "$") + v["is_data"] = strings.HasPrefix(as, "$") deps = append(deps, v) } meta["deps"] = deps @@ -1137,13 +1141,13 @@ func (c *compiler) compileObject(e *Object) error { } func (c *compiler) compileObjectKeyVal(v [2]int, kv *ObjectKeyVal) error { - if kv.KeyOnly != "" { - if kv.KeyOnly[0] == '$' { - c.append(&code{op: oppush, v: kv.KeyOnly[1:]}) + if kv.KeyOnly != nil { + if kv.KeyOnly.Str[0] == '$' { + c.append(&code{op: oppush, v: kv.KeyOnly.Str[1:]}) c.append(&code{op: opload, v: v}) return c.compileFunc(&Func{Name: kv.KeyOnly}) } - c.append(&code{op: oppush, v: kv.KeyOnly}) + c.append(&code{op: oppush, v: kv.KeyOnly.Str}) c.append(&code{op: opload, v: v}) return c.compileIndex(&Term{Type: TermTypeIdentity}, &Index{Name: kv.KeyOnly}) } else if kv.KeyOnlyString != nil { @@ -1170,13 +1174,13 @@ func (c *compiler) compileObjectKeyVal(v [2]int, kv *ObjectKeyVal) error { if err := c.compileString(kv.KeyString, nil); err != nil { return err } - } else if kv.Key[0] == '$' { + } else if kv.Key.Str[0] == '$' { c.append(&code{op: opload, v: v}) if err := c.compileFunc(&Func{Name: kv.Key}); err != nil { return err } } else { - c.append(&code{op: oppush, v: kv.Key}) + c.append(&code{op: oppush, v: kv.Key.Str}) } c.append(&code{op: opload, v: v}) return c.compileObjectVal(kv.Val) @@ -1259,8 +1263,8 @@ func (c *compiler) compileFormat(fmt string, str *String) error { f := formatToFunc(fmt) if f == nil { f = &Func{ - Name: "format", - Args: []*Query{{Term: &Term{Type: TermTypeString, Str: &String{Str: fmt[1:]}}}}, + Name: &Token{Str: "format"}, + Args: []*Query{{Term: &Term{Type: TermTypeString, Str: &String{Str: &Token{Str: fmt[1:]}}}}}, } } if str == nil { @@ -1272,23 +1276,23 @@ func (c *compiler) compileFormat(fmt string, str *String) error { func formatToFunc(fmt string) *Func { switch fmt { case "@text": - return &Func{Name: "tostring"} + return &Func{Name: &Token{Str: "tostring"}} case "@json": - return &Func{Name: "tojson"} + return &Func{Name: &Token{Str: "tojson"}} case "@html": - return &Func{Name: "_tohtml"} + return &Func{Name: &Token{Str: "_tohtml"}} case "@uri": - return &Func{Name: "_touri"} + return &Func{Name: &Token{Str: "_touri"}} case "@csv": - return &Func{Name: "_tocsv"} + return &Func{Name: &Token{Str: "_tocsv"}} case "@tsv": - return &Func{Name: "_totsv"} + return &Func{Name: &Token{Str: "_totsv"}} case "@sh": - return &Func{Name: "_tosh"} + return &Func{Name: &Token{Str: "_tosh"}} case "@base64": - return &Func{Name: "_tobase64"} + return &Func{Name: &Token{Str: "_tobase64"}} case "@base64d": - return &Func{Name: "_tobase64d"} + return &Func{Name: &Token{Str: "_tobase64d"}} default: return nil } @@ -1296,11 +1300,11 @@ func formatToFunc(fmt string) *Func { func (c *compiler) compileString(s *String, f *Func) error { if s.Queries == nil { - c.append(&code{op: opconst, v: s.Str}) + c.append(&code{op: opconst, v: s.Str.Str}) return nil } if f == nil { - f = &Func{Name: "tostring"} + f = &Func{Name: &Token{Str: "tostring"}} } var q *Query for _, e := range s.Queries { @@ -1376,7 +1380,7 @@ func (c *compiler) compileCallInternal( for i := len(args) - 1; i >= 0; i-- { pc := c.pc() + 1 // skip opjump (ref: compileFuncDef) name := "lambda:" + strconv.Itoa(pc) - if err := c.compileFuncDef(&FuncDef{Name: name, Body: args[i]}, false); err != nil { + if err := c.compileFuncDef(&FuncDef{Name: &Token{Str: name}, Body: args[i]}, false); err != nil { return err } if internal { diff --git a/error.go b/error.go index 01d04791..8ddb2dba 100644 --- a/error.go +++ b/error.go @@ -100,7 +100,7 @@ type funcNotFoundError struct { } func (err *funcNotFoundError) Error() string { - return "function not defined: " + err.f.Name + "/" + strconv.Itoa(len(err.f.Args)) + return "function not defined: " + err.f.Name.Str + "/" + strconv.Itoa(len(err.f.Args)) } type funcTypeError struct { diff --git a/func.go b/func.go index 838ced8b..9972585f 100644 --- a/func.go +++ b/func.go @@ -587,7 +587,7 @@ func funcFormat(v, x interface{}) interface{} { if f == nil { return &formatNotFoundError{fmt} } - return internalFuncs[f.Name].callback(v, nil) + return internalFuncs[f.Name.Str].callback(v, nil) default: return &funcTypeError{"format", x} } diff --git a/lexer.go b/lexer.go index d36a6838..c60690f3 100644 --- a/lexer.go +++ b/lexer.go @@ -16,6 +16,12 @@ type lexer struct { err error } +type Token struct { + Str string `json:"str,omitempty"` + Start int `json:"start,omitempty"` + Stop int `json:"stop,omitempty"` +} + func newLexer(src string) *lexer { return &lexer{source: src} } @@ -47,17 +53,22 @@ var keywords = map[string]int{ } func (l *lexer) Lex(lval *yySymType) (tokenType int) { - defer func() { l.tokenType = tokenType }() + lval.token = &Token{} + defer func() { + l.tokenType = tokenType + lval.token.Stop = l.offset + }() if len(l.source) == l.offset { l.token = "" return eof } if l.inString { tok, str := l.scanString(l.offset) - lval.token = str + lval.token.Str = str return tok } ch, iseof := l.next() + lval.token.Start = l.offset - 1 if iseof { l.token = "" return eof @@ -67,7 +78,7 @@ func (l *lexer) Lex(lval *yySymType) (tokenType int) { i := l.offset - 1 j, isModule := l.scanIdentOrModule() l.token = l.source[i:j] - lval.token = l.token + lval.token.Str = l.token if isModule { return tokModuleIdent } @@ -83,7 +94,7 @@ func (l *lexer) Lex(lval *yySymType) (tokenType int) { return tokInvalid } l.token = l.source[i:j] - lval.token = l.token + lval.token.Str = l.token return tokNumber } switch ch { @@ -96,7 +107,7 @@ func (l *lexer) Lex(lval *yySymType) (tokenType int) { return tokRecurse case isIdent(ch, false): l.token = l.source[l.offset-1 : l.scanIdent()] - lval.token = l.token[1:] + lval.token.Str = l.token[1:] return tokIndex case isNumber(ch): i := l.offset - 1 @@ -106,7 +117,7 @@ func (l *lexer) Lex(lval *yySymType) (tokenType int) { return tokInvalid } l.token = l.source[i:j] - lval.token = l.token + lval.token.Str = l.token return tokNumber default: return '.' @@ -116,7 +127,7 @@ func (l *lexer) Lex(lval *yySymType) (tokenType int) { i := l.offset - 1 j, isModule := l.scanIdentOrModule() l.token = l.source[i:j] - lval.token = l.token + lval.token.Str = l.token if isModule { return tokModuleVariable } @@ -226,12 +237,12 @@ func (l *lexer) Lex(lval *yySymType) (tokenType int) { case '@': if isIdent(l.peek(), true) { l.token = l.source[l.offset-1 : l.scanIdent()] - lval.token = l.token + lval.token.Str = l.token return tokFormat } case '"': tok, str := l.scanString(l.offset - 1) - lval.token = str + lval.token.Str = str return tok default: if ch >= utf8.RuneSelf { diff --git a/module_loader.go b/module_loader.go index fe26aa99..5a69a7b9 100644 --- a/module_loader.go +++ b/module_loader.go @@ -128,8 +128,8 @@ func parseModule(path, cnt string) (*Query, error) { i.Meta.KeyVals = append( i.Meta.KeyVals, &ConstObjectKeyVal{ - Key: "$$path", - Val: &ConstTerm{Str: path}, + Key: &Token{Str: "$$path"}, + Val: &ConstTerm{Str: &Token{Str: path}}, }, ) } diff --git a/operator.go b/operator.go index 48fb976e..f3705114 100644 --- a/operator.go +++ b/operator.go @@ -1,6 +1,8 @@ package gojq import ( + "encoding/json" + "fmt" "math" "math/big" "reflect" @@ -38,6 +40,62 @@ const ( OpUpdateAlt ) +// OperatorFromString convert string to Operator or zero if not possible +func OperatorFromString(s string) Operator { + switch s { + case "|": + return OpPipe + case ",": + return OpComma + case "+": + return OpAdd + case "-": + return OpSub + case "*": + return OpMul + case "/": + return OpDiv + case "%": + return OpMod + case "==": + return OpEq + case "!=": + return OpNe + case ">": + return OpGt + case "<": + return OpLt + case ">=": + return OpGe + case "<=": + return OpLe + case "and": + return OpAnd + case "or": + return OpOr + case "//": + return OpAlt + case "=": + return OpAssign + case "|=": + return OpModify + case "+=": + return OpUpdateAdd + case "-=": + return OpUpdateSub + case "*=": + return OpUpdateMul + case "/=": + return OpUpdateDiv + case "%=": + return OpUpdateMod + case "//=": + return OpUpdateAlt + default: + return 0 + } +} + // String implements Stringer. func (op Operator) String() string { switch op { @@ -90,7 +148,7 @@ func (op Operator) String() string { case OpUpdateAlt: return "//=" default: - panic(op) + return "" } } @@ -208,6 +266,27 @@ func (op Operator) getFunc() string { } } +func (op Operator) MarshalJSON() ([]byte, error) { + if op == 0 { + return json.Marshal(nil) + } + return json.Marshal(op.String()) +} + +func (op *Operator) UnmarshalJSON(text []byte) error { + var s string + err := json.Unmarshal(text, &s) + if s == "" || err != nil { + *op = 0 + return nil + } + *op = OperatorFromString(s) + if *op == 0 { + return fmt.Errorf("unknown operator %v", s) + } + return nil +} + func binopTypeSwitch( l, r interface{}, callbackInts func(_, _ int) interface{}, diff --git a/parser.go b/parser.go index 0d67af3a..764890c3 100644 --- a/parser.go +++ b/parser.go @@ -20,7 +20,7 @@ func Parse(src string) (*Query, error) { type yySymType struct { yys int value interface{} - token string + token *Token operator Operator } @@ -876,19 +876,19 @@ yydefault: yyDollar = yyS[yypt-8 : yypt+1] //line parser.go.y:122 { - yyVAL.value = &FuncDef{yyDollar[2].token, yyDollar[4].value.([]string), yyDollar[7].value.(*Query)} + yyVAL.value = &FuncDef{yyDollar[2].token, yyDollar[4].value.([]*Token), yyDollar[7].value.(*Query)} } case 16: yyDollar = yyS[yypt-1 : yypt+1] //line parser.go.y:128 { - yyVAL.value = []string{yyDollar[1].token} + yyVAL.value = []*Token{yyDollar[1].token} } case 17: yyDollar = yyS[yypt-3 : yypt+1] //line parser.go.y:132 { - yyVAL.value = append(yyDollar[1].value.([]string), yyDollar[3].token) + yyVAL.value = append(yyDollar[1].value.([]*Token), yyDollar[3].token) } case 18: yyDollar = yyS[yypt-1 : yypt+1] diff --git a/parser.go.y b/parser.go.y index e4c8ddb3..819924a3 100644 --- a/parser.go.y +++ b/parser.go.y @@ -13,7 +13,7 @@ func Parse(src string) (*Query, error) { %union { value interface{} - token string + token *Token operator Operator } @@ -120,17 +120,17 @@ funcdef } | tokDef tokIdent '(' funcdefargs ')' ':' query ';' { - $$ = &FuncDef{$2, $4.([]string), $7.(*Query)} + $$ = &FuncDef{$2, $4.([]*Token), $7.(*Query)} } funcdefargs : tokIdentVariable { - $$ = []string{$1} + $$ = []*Token{$1} } | funcdefargs ';' tokIdentVariable { - $$ = append($1.([]string), $3) + $$ = append($1.([]*Token), $3) } tokIdentVariable diff --git a/query.go b/query.go index 01765232..1a16db14 100644 --- a/query.go +++ b/query.go @@ -9,14 +9,14 @@ import ( // Query represents the abstract syntax tree of a jq query. type Query struct { - Meta *ConstObject - Imports []*Import - FuncDefs []*FuncDef - Term *Term - Left *Query - Op Operator - Right *Query - Func string + Meta *ConstObject `json:"meta,omitempty"` + Imports []*Import `json:"imports,omitempty"` + FuncDefs []*FuncDef `json:"func_defs,omitempty"` + Term *Term `json:"term,omitempty"` + Left *Query `json:"left,omitempty"` + Op Operator `json:"op,omitempty"` + Right *Query `json:"right,omitempty"` + Func *Token `json:"func,omitempty"` } // Run the query. @@ -59,8 +59,8 @@ func (e *Query) writeTo(s *strings.Builder) { if len(e.FuncDefs) > 0 { s.WriteByte(' ') } - if e.Func != "" { - s.WriteString(e.Func) + if e.Func != nil { + s.WriteString(e.Func.Str) } else if e.Term != nil { e.Term.writeTo(s) } else if e.Right != nil { @@ -83,7 +83,7 @@ func (e *Query) minify() { if e.Term != nil { if name := e.Term.toFunc(); name != "" { e.Term = nil - e.Func = name + e.Func = &Token{Str: name} } else { e.Term.minify() } @@ -102,10 +102,10 @@ func (e *Query) toIndices() []interface{} { // Import ... type Import struct { - ImportPath string - ImportAlias string - IncludePath string - Meta *ConstObject + ImportPath *Token `json:"import_path,omitempty"` + ImportAlias *Token `json:"import_alias,omitempty"` + IncludePath *Token `json:"include_path,omitempty"` + Meta *ConstObject `json:"meta,omitempty"` } func (e *Import) String() string { @@ -115,14 +115,14 @@ func (e *Import) String() string { } func (e *Import) writeTo(s *strings.Builder) { - if e.ImportPath != "" { + if e.ImportPath != nil { s.WriteString("import ") - s.WriteString(strconv.Quote(e.ImportPath)) + s.WriteString(strconv.Quote(e.ImportPath.Str)) s.WriteString(" as ") - s.WriteString(e.ImportAlias) + s.WriteString(e.ImportAlias.Str) } else { s.WriteString("include ") - s.WriteString(strconv.Quote(e.IncludePath)) + s.WriteString(strconv.Quote(e.IncludePath.Str)) } if e.Meta != nil { s.WriteByte(' ') @@ -133,9 +133,9 @@ func (e *Import) writeTo(s *strings.Builder) { // FuncDef ... type FuncDef struct { - Name string - Args []string - Body *Query + Name *Token `json:"name,omitempty"` + Args []*Token `json:"args,omitempty"` + Body *Query `json:"body,omitempty"` } func (e *FuncDef) String() string { @@ -146,14 +146,14 @@ func (e *FuncDef) String() string { func (e *FuncDef) writeTo(s *strings.Builder) { s.WriteString("def ") - s.WriteString(e.Name) + s.WriteString(e.Name.Str) if len(e.Args) > 0 { s.WriteByte('(') for i, e := range e.Args { if i > 0 { s.WriteString("; ") } - s.WriteString(e) + s.WriteString(e.Str) } s.WriteByte(')') } @@ -169,23 +169,23 @@ func (e *FuncDef) Minify() { // Term ... type Term struct { - Type TermType - Index *Index - Func *Func - Object *Object - Array *Array - Number string - Unary *Unary - Format string - Str *String - If *If - Try *Try - Reduce *Reduce - Foreach *Foreach - Label *Label - Break string - Query *Query - SuffixList []*Suffix + Type TermType `json:"type,omitempty"` + Index *Index `json:"index,omitempty"` + Func *Func `json:"func,omitempty"` + Object *Object `json:"object,omitempty"` + Array *Array `json:"array,omitempty"` + Number *Token `json:"number,omitempty"` + Unary *Unary `json:"unary,omitempty"` + Format *Token `json:"format,omitempty"` + Str *String `json:"str,omitempty"` + If *If `json:"if,omitempty"` + Try *Try `json:"try,omitempty"` + Reduce *Reduce `json:"reduce,omitempty"` + Foreach *Foreach `json:"foreach,omitempty"` + Label *Label `json:"label,omitempty"` + Break *Token `json:"break,omitempty"` + Query *Query `json:"query,omitempty"` + SuffixList []*Suffix `json:"suffix_list,omitempty"` } func (e *Term) String() string { @@ -215,11 +215,11 @@ func (e *Term) writeTo(s *strings.Builder) { case TermTypeArray: e.Array.writeTo(s) case TermTypeNumber: - s.WriteString(e.Number) + s.WriteString(e.Number.Str) case TermTypeUnary: e.Unary.writeTo(s) case TermTypeFormat: - s.WriteString(e.Format) + s.WriteString(e.Format.Str) if e.Str != nil { s.WriteByte(' ') e.Str.writeTo(s) @@ -238,7 +238,7 @@ func (e *Term) writeTo(s *strings.Builder) { e.Label.writeTo(s) case TermTypeBreak: s.WriteString("break ") - s.WriteString(e.Break) + s.WriteString(e.Break.Str) case TermTypeQuery: s.WriteByte('(') e.Query.writeTo(s) @@ -331,8 +331,8 @@ func (e *Term) toIndices() []interface{} { // Unary ... type Unary struct { - Op Operator - Term *Term + Op Operator `json:"op,omitempty"` + Term *Term `json:"term,omitempty"` } func (e *Unary) String() string { @@ -352,9 +352,9 @@ func (e *Unary) minify() { // Pattern ... type Pattern struct { - Name string - Array []*Pattern - Object []*PatternObject + Name *Token `json:"name,omitempty"` + Array []*Pattern `json:"array,omitempty"` + Object []*PatternObject `json:"object,omitempty"` } func (e *Pattern) String() string { @@ -364,8 +364,8 @@ func (e *Pattern) String() string { } func (e *Pattern) writeTo(s *strings.Builder) { - if e.Name != "" { - s.WriteString(e.Name) + if e.Name != nil { + s.WriteString(e.Name.Str) } else if len(e.Array) > 0 { s.WriteByte('[') for i, e := range e.Array { @@ -389,11 +389,11 @@ func (e *Pattern) writeTo(s *strings.Builder) { // PatternObject ... type PatternObject struct { - Key string - KeyString *String - KeyQuery *Query - Val *Pattern - KeyOnly string + Key *Token `json:"key,omitempty"` + KeyString *String `json:"key_string,omitempty"` + KeyQuery *Query `json:"key_query,omitempty"` + Val *Pattern `json:"val,omitempty"` + KeyOnly *Token `json:"key_only,omitempty"` } func (e *PatternObject) String() string { @@ -403,8 +403,8 @@ func (e *PatternObject) String() string { } func (e *PatternObject) writeTo(s *strings.Builder) { - if e.Key != "" { - s.WriteString(e.Key) + if e.Key != nil { + s.WriteString(e.Key.Str) } else if e.KeyString != nil { e.KeyString.writeTo(s) } else if e.KeyQuery != nil { @@ -416,18 +416,18 @@ func (e *PatternObject) writeTo(s *strings.Builder) { s.WriteString(": ") e.Val.writeTo(s) } - if e.KeyOnly != "" { - s.WriteString(e.KeyOnly) + if e.KeyOnly != nil { + s.WriteString(e.KeyOnly.Str) } } // Index ... type Index struct { - Name string - Str *String - Start *Query - IsSlice bool - End *Query + Name *Token `json:"name,omitempty"` + Str *String `json:"str,omitempty"` + Start *Query `json:"start,omitempty"` + IsSlice bool `json:"is_slice,omitempty"` + End *Query `json:"end,omitempty"` } func (e *Index) String() string { @@ -448,8 +448,8 @@ func (e *Index) writeTo(s *strings.Builder) { } func (e *Index) writeSuffixTo(s *strings.Builder) { - if e.Name != "" { - s.WriteString(e.Name) + if e.Name != nil { + s.WriteString(e.Name.Str) } else { if e.Str != nil { e.Str.writeTo(s) @@ -485,16 +485,16 @@ func (e *Index) minify() { } func (e *Index) toIndices() []interface{} { - if e.Name == "" { + if e.Name == nil { return nil } - return []interface{}{e.Name} + return []interface{}{e.Name.Str} } // Func ... type Func struct { - Name string - Args []*Query + Name *Token `json:"name,omitempty"` + Args []*Query `json:"args,omitempty"` } func (e *Func) String() string { @@ -504,7 +504,7 @@ func (e *Func) String() string { } func (e *Func) writeTo(s *strings.Builder) { - s.WriteString(e.Name) + s.WriteString(e.Name.Str) if len(e.Args) > 0 { s.WriteByte('(') for i, e := range e.Args { @@ -527,13 +527,13 @@ func (e *Func) toFunc() string { if len(e.Args) != 0 { return "" } - return e.Name + return e.Name.Str } // String ... type String struct { - Str string - Queries []*Query + Str *Token `json:"str,omitempty"` + Queries []*Query `json:"queries,omitempty"` } func (e *String) String() string { @@ -544,7 +544,7 @@ func (e *String) String() string { func (e *String) writeTo(s *strings.Builder) { if e.Queries == nil { - s.WriteString(strconv.Quote(e.Str)) + s.WriteString(strconv.Quote(e.Str.Str)) return } s.WriteByte('"') @@ -568,7 +568,7 @@ func (e *String) minify() { // Object ... type Object struct { - KeyVals []*ObjectKeyVal + KeyVals []*ObjectKeyVal `json:"key_vals,omitempty"` } func (e *Object) String() string { @@ -600,12 +600,12 @@ func (e *Object) minify() { // ObjectKeyVal ... type ObjectKeyVal struct { - Key string - KeyString *String - KeyQuery *Query - Val *ObjectVal - KeyOnly string - KeyOnlyString *String + Key *Token `json:"key,omitempty"` + KeyString *String `json:"key_string,omitempty"` + KeyQuery *Query `json:"key_query,omitempty"` + Val *ObjectVal `json:"val,omitempty"` + KeyOnly *Token `json:"key_only,omitempty"` + KeyOnlyString *String `json:"key_only_string,omitempty"` } func (e *ObjectKeyVal) String() string { @@ -615,8 +615,8 @@ func (e *ObjectKeyVal) String() string { } func (e *ObjectKeyVal) writeTo(s *strings.Builder) { - if e.Key != "" { - s.WriteString(e.Key) + if e.Key != nil { + s.WriteString(e.Key.Str) } else if e.KeyString != nil { e.KeyString.writeTo(s) } else if e.KeyQuery != nil { @@ -628,8 +628,8 @@ func (e *ObjectKeyVal) writeTo(s *strings.Builder) { s.WriteString(": ") e.Val.writeTo(s) } - if e.KeyOnly != "" { - s.WriteString(e.KeyOnly) + if e.KeyOnly != nil { + s.WriteString(e.KeyOnly.Str) } else if e.KeyOnlyString != nil { e.KeyOnlyString.writeTo(s) } @@ -651,7 +651,7 @@ func (e *ObjectKeyVal) minify() { // ObjectVal ... type ObjectVal struct { - Queries []*Query + Queries []*Query `json:"queries,omitempty"` } func (e *ObjectVal) String() string { @@ -677,7 +677,7 @@ func (e *ObjectVal) minify() { // Array ... type Array struct { - Query *Query + Query *Query `json:"query,omitempty"` } func (e *Array) String() string { @@ -702,10 +702,10 @@ func (e *Array) minify() { // Suffix ... type Suffix struct { - Index *Index - Iter bool - Optional bool - Bind *Bind + Index *Index `json:"index,omitempty"` + Iter bool `json:"iter,omitempty"` + Optional bool `json:"optional,omitempty"` + Bind *Bind `json:"bind,omitempty"` } func (e *Suffix) String() string { @@ -716,7 +716,7 @@ func (e *Suffix) String() string { func (e *Suffix) writeTo(s *strings.Builder) { if e.Index != nil { - if e.Index.Name != "" || e.Index.Str != nil { + if e.Index.Name != nil || e.Index.Str != nil { e.Index.writeTo(s) } else { e.Index.writeSuffixTo(s) @@ -757,8 +757,8 @@ func (e *Suffix) toIndices() []interface{} { // Bind ... type Bind struct { - Patterns []*Pattern - Body *Query + Patterns []*Pattern `json:"patterns,omitempty"` + Body *Query `json:"body,omitempty"` } func (e *Bind) String() string { @@ -789,10 +789,10 @@ func (e *Bind) minify() { // If ... type If struct { - Cond *Query - Then *Query - Elif []*IfElif - Else *Query + Cond *Query `json:"cond,omitempty"` + Then *Query `json:"then,omitempty"` + Elif []*IfElif `json:"elif,omitempty"` + Else *Query `json:"else,omitempty"` } func (e *If) String() string { @@ -830,8 +830,8 @@ func (e *If) minify() { // IfElif ... type IfElif struct { - Cond *Query - Then *Query + Cond *Query `json:"cond,omitempty"` + Then *Query `json:"then,omitempty"` } func (e *IfElif) String() string { @@ -854,8 +854,8 @@ func (e *IfElif) minify() { // Try ... type Try struct { - Body *Query - Catch *Query + Body *Query `json:"body,omitempty"` + Catch *Query `json:"catch,omitempty"` } func (e *Try) String() string { @@ -882,10 +882,10 @@ func (e *Try) minify() { // Reduce ... type Reduce struct { - Term *Term - Pattern *Pattern - Start *Query - Update *Query + Term *Term `json:"term,omitempty"` + Pattern *Pattern `json:"pattern,omitempty"` + Start *Query `json:"start,omitempty"` + Update *Query `json:"update,omitempty"` } func (e *Reduce) String() string { @@ -914,11 +914,11 @@ func (e *Reduce) minify() { // Foreach ... type Foreach struct { - Term *Term - Pattern *Pattern - Start *Query - Update *Query - Extract *Query + Term *Term `json:"term,omitempty"` + Pattern *Pattern `json:"pattern,omitempty"` + Start *Query `json:"start,omitempty"` + Update *Query `json:"update,omitempty"` + Extract *Query `json:"extract,omitempty"` } func (e *Foreach) String() string { @@ -954,8 +954,8 @@ func (e *Foreach) minify() { // Label ... type Label struct { - Ident string - Body *Query + Ident *Token `json:"ident,omitempty"` + Body *Query `json:"body,omitempty"` } func (e *Label) String() string { @@ -966,7 +966,7 @@ func (e *Label) String() string { func (e *Label) writeTo(s *strings.Builder) { s.WriteString("label ") - s.WriteString(e.Ident) + s.WriteString(e.Ident.Str) s.WriteString(" | ") e.Body.writeTo(s) } @@ -977,13 +977,13 @@ func (e *Label) minify() { // ConstTerm ... type ConstTerm struct { - Object *ConstObject - Array *ConstArray - Number string - Str string - Null bool - True bool - False bool + Object *ConstObject `json:"object,omitempty"` + Array *ConstArray `json:"array,omitempty"` + Number *Token `json:"number,omitempty"` + Str *Token `json:"str,omitempty"` + Null bool `json:"null,omitempty"` + True bool `json:"true,omitempty"` + False bool `json:"false,omitempty"` } func (e *ConstTerm) String() string { @@ -997,10 +997,10 @@ func (e *ConstTerm) writeTo(s *strings.Builder) { e.Object.writeTo(s) } else if e.Array != nil { e.Array.writeTo(s) - } else if e.Number != "" { - s.WriteString(e.Number) - } else if e.Str != "" { - s.WriteString(strconv.Quote(e.Str)) + } else if e.Number != nil { + s.WriteString(e.Number.Str) + } else if e.Str != nil { + s.WriteString(strconv.Quote(e.Str.Str)) } else if e.Null { s.WriteString("null") } else if e.True { @@ -1015,8 +1015,8 @@ func (e *ConstTerm) toValue() interface{} { return e.Object.ToValue() } else if e.Array != nil { return e.Array.toValue() - } else if e.Number != "" { - return normalizeNumbers(json.Number(e.Number)) + } else if e.Number != nil { + return normalizeNumbers(json.Number(e.Number.Str)) } else if e.Null { return nil } else if e.True { @@ -1024,13 +1024,13 @@ func (e *ConstTerm) toValue() interface{} { } else if e.False { return false } else { - return e.Str + return e.Str.Str } } // ConstObject ... type ConstObject struct { - KeyVals []*ConstObjectKeyVal + KeyVals []*ConstObjectKeyVal `json:"keyvals,omitempty"` } func (e *ConstObject) String() string { @@ -1061,9 +1061,11 @@ func (e *ConstObject) ToValue() map[string]interface{} { } v := make(map[string]interface{}, len(e.KeyVals)) for _, e := range e.KeyVals { - key := e.Key - if key == "" { - key = e.KeyString + var key string + if e.Key != nil { + key = e.Key.Str + } else if e.KeyString != nil { + key = e.KeyString.Str } v[key] = e.Val.toValue() } @@ -1072,9 +1074,9 @@ func (e *ConstObject) ToValue() map[string]interface{} { // ConstObjectKeyVal ... type ConstObjectKeyVal struct { - Key string - KeyString string - Val *ConstTerm + Key *Token `json:"key,omitempty"` + KeyString *Token `json:"key_string,omitempty"` + Val *ConstTerm `json:"val,omitempty"` } func (e *ConstObjectKeyVal) String() string { @@ -1084,10 +1086,10 @@ func (e *ConstObjectKeyVal) String() string { } func (e *ConstObjectKeyVal) writeTo(s *strings.Builder) { - if e.Key != "" { - s.WriteString(e.Key) + if e.Key != nil { + s.WriteString(e.Key.Str) } else { - s.WriteString(e.KeyString) + s.WriteString(e.KeyString.Str) } s.WriteString(": ") e.Val.writeTo(s) @@ -1095,7 +1097,7 @@ func (e *ConstObjectKeyVal) writeTo(s *strings.Builder) { // ConstArray ... type ConstArray struct { - Elems []*ConstTerm + Elems []*ConstTerm `json:"elems,omitempty"` } func (e *ConstArray) String() string { diff --git a/query_test.go b/query_test.go index 2489ae9f..1a91d4f3 100644 --- a/query_test.go +++ b/query_test.go @@ -216,12 +216,18 @@ func TestQueryString(t *testing.T) { if err != nil { t.Fatal(err) } - r, err := gojq.Parse(q.String()) + // done in three steps to normalize string format so that token positions + // can be compared properly + q2, err := gojq.Parse(q.String()) if err != nil { t.Fatal(err) } - if !reflect.DeepEqual(q, r) { - t.Errorf("\n%v\n%v", q, r) + q3, err := gojq.Parse(q2.String()) + if err != nil { + t.Fatal(err) + } + if !reflect.DeepEqual(q2, q3) { + t.Errorf("\n%v\n%v", q2, q3) } } diff --git a/term_type.go b/term_type.go index 1670948c..49d80459 100644 --- a/term_type.go +++ b/term_type.go @@ -1,5 +1,10 @@ package gojq +import ( + "encoding/json" + "fmt" +) + // TermType represents the type of Term. type TermType int @@ -27,9 +32,56 @@ const ( TermTypeQuery ) -// GoString implements GoStringer. -func (termType TermType) GoString() (str string) { - defer func() { str = "gojq." + str }() +// TermTypeFromString convert string to TermType or zero if not possible +func TermTypeFromString(s string) TermType { + switch s { + case "TermTypeIdentity": + return TermTypeIdentity + case "TermTypeRecurse": + return TermTypeRecurse + case "TermTypeNull": + return TermTypeNull + case "TermTypeTrue": + return TermTypeTrue + case "TermTypeFalse": + return TermTypeFalse + case "TermTypeIndex": + return TermTypeIndex + case "TermTypeFunc": + return TermTypeFunc + case "TermTypeObject": + return TermTypeObject + case "TermTypeArray": + return TermTypeArray + case "TermTypeNumber": + return TermTypeNumber + case "TermTypeUnary": + return TermTypeUnary + case "TermTypeFormat": + return TermTypeFormat + case "TermTypeString": + return TermTypeString + case "TermTypeIf": + return TermTypeIf + case "TermTypeTry": + return TermTypeTry + case "TermTypeReduce": + return TermTypeReduce + case "TermTypeForeach": + return TermTypeForeach + case "TermTypeLabel": + return TermTypeLabel + case "TermTypeBreak": + return TermTypeBreak + case "TermTypeQuery": + return TermTypeQuery + default: + return 0 + } +} + +// String implements Stringer. +func (termType TermType) String() string { switch termType { case TermTypeIdentity: return "TermTypeIdentity" @@ -72,6 +124,37 @@ func (termType TermType) GoString() (str string) { case TermTypeQuery: return "TermTypeQuery" default: - panic(termType) + return "" + } +} + +// GoString implements GoStringer. +func (termType TermType) GoString() string { + if s := termType.String(); s != "" { + return "gojq." + s + } + panic(termType) +} + +func (termType TermType) MarshalJSON() ([]byte, error) { + if termType == 0 { + return json.Marshal(nil) + } + if s := termType.String(); s != "" { + return json.Marshal(s) + } + return nil, fmt.Errorf("unknown term %v", termType) +} + +func (termType *TermType) UnmarshalJSON(text []byte) error { + var s string + err := json.Unmarshal(text, &s) + if err != nil { + return err + } + *termType = TermTypeFromString(s) + if *termType == 0 { + return fmt.Errorf("unknown term %v", s) } + return nil }