Codebase list gojq-upstream / run/df2a107e-8e70-46b9-935b-2069922d4135/main
Debianized package Debian Janitor 1 year, 5 months ago
25 changed file(s) with 311 addition(s) and 977 deletion(s). Raw diff Collapse all Expand all
+0
-2
.gitattributes less more
0 **/testdata/** binary
1 /builtin.go eol=lf
+0
-55
.github/workflows/ci.yaml less more
0 name: CI
1
2 on:
3 push:
4 branches:
5 - main
6 pull_request:
7
8 jobs:
9 test:
10 name: Test
11 runs-on: ${{ matrix.os }}
12 strategy:
13 matrix:
14 os: [ubuntu-latest, macos-latest, windows-latest]
15 go: [1.19.x, 1.18.x, 1.17.x]
16 steps:
17 - name: Checkout code
18 uses: actions/checkout@v3
19 - name: Setup Go
20 uses: actions/setup-go@v3
21 with:
22 go-version: ${{ matrix.go }}
23 - name: Test
24 run: make test
25 - name: Test with GOARCH=386
26 run: env GOARCH=386 go test -v ./...
27 if: matrix.os != 'macos-latest'
28 - name: Lint
29 run: make lint
30 - name: Check tools
31 run: make check-tools
32 - name: Check go generate
33 run: go generate && ! git diff | grep ^
34 shell: bash
35 - name: Check command examples in README.md
36 run: |
37 ./gojq -Rnr 'reduce inputs as $x (
38 {};
39 if $x|test("^ [$] .*gojq|^```")
40 then
41 if .command
42 then .results += [{command: .command, output: .output}] | del(.command,.output)
43 end | if $x|test("gojq") then .command = $x[3:] end
44 elif .command then .output += ($x + "\n" | sub(" +#.*"; ""))
45 end
46 ) | .results[] |
47 "if got=$(diff <(printf %s \(.output | @sh)) \\
48 <(\(.command | gsub("gojq"; "./gojq")) 2>&1)); then
49 echo ok: \(.command | @sh)
50 else
51 echo ng: \(.command | @sh); echo \"$got\"; exit 1
52 fi"
53 ' README.md | bash
54 shell: bash
+0
-78
.github/workflows/release.yaml less more
0 name: Release
1
2 on:
3 push:
4 tags:
5 - 'v*'
6
7 jobs:
8
9 release:
10 name: Release
11 runs-on: ubuntu-latest
12 steps:
13
14 - name: Checkout code
15 uses: actions/checkout@v3
16
17 - name: Setup Go
18 uses: actions/setup-go@v3
19 with:
20 go-version: 1.x
21
22 - name: Cross build
23 run: make cross
24
25 - name: Create Release
26 id: create_release
27 uses: actions/create-release@v1
28 env:
29 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30 with:
31 tag_name: ${{ github.ref }}
32 release_name: Release ${{ github.ref }}
33
34 - name: Upload
35 run: make upload
36 env:
37 GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
38
39 - name: Docker metadata
40 uses: docker/metadata-action@v4
41 id: metadata
42 with:
43 images: |
44 ${{ github.repository }}
45 ghcr.io/${{ github.repository }}
46 tags: |
47 type=semver,pattern={{version}}
48 type=semver,pattern={{major}}.{{minor}}
49 type=semver,pattern={{major}}
50
51 - name: Set up QEMU
52 uses: docker/setup-qemu-action@v2
53
54 - name: Set up Docker Buildx
55 uses: docker/setup-buildx-action@v2
56
57 - name: Login to Docker Hub
58 uses: docker/login-action@v2
59 with:
60 username: ${{ secrets.DOCKER_USERNAME }}
61 password: ${{ secrets.DOCKER_PASSWORD }}
62
63 - name: Login to GitHub Container Registry
64 uses: docker/login-action@v2
65 with:
66 registry: ghcr.io
67 username: ${{ github.repository_owner }}
68 password: ${{ secrets.GITHUB_TOKEN }}
69
70 - name: Build and release Docker image
71 uses: docker/build-push-action@v3
72 with:
73 context: .
74 push: true
75 platforms: linux/amd64, linux/arm64
76 tags: ${{ steps.metadata.outputs.tags }}
77 labels: ${{ steps.metadata.outputs.labels }}
+0
-8
.gitignore less more
0 /gojq
1 /goxz
2 /CREDITS
3 /._*
4 /y.output
5 *.exe
6 *.test
7 *.out
3232
3333 .PHONY: install
3434 install:
35 go install -ldflags=$(BUILD_LDFLAGS) ./cmd/$(BIN)
35 go install -ldflags=$(BUILD_LDFLAGS) ./...
3636
3737 .PHONY: install-dev
3838 install-dev: parser.go builtin.go
39 go install -ldflags=$(BUILD_LDFLAGS) ./cmd/$(BIN)
39 go install -ldflags=$(BUILD_LDFLAGS) ./...
4040
4141 .PHONY: install-debug
4242 install-debug: parser.go builtin.go
43 go install -tags gojq_debug -ldflags=$(BUILD_LDFLAGS) ./cmd/$(BIN)
43 go install -tags gojq_debug -ldflags=$(BUILD_LDFLAGS) ./...
4444
4545 .PHONY: show-version
4646 show-version: $(GOBIN)/gobump
7777 - gojq does not keep the order of object keys. I understand this might cause problems for some scripts but basically, we should not rely on the order of object keys. Due to this limitation, gojq does not have `keys_unsorted` function and `--sort-keys` (`-S`) option. I would implement when ordered map is implemented in the standard library of Go but I'm less motivated.
7878 - gojq supports arbitrary-precision integer calculation while jq does not; jq loses the precision of large integers when calculation is involved. Note that even with gojq, all mathematical functions, including `floor` and `round`, convert integers to floating-point numbers; only addition, subtraction, multiplication, modulo, and division operators (when divisible) keep the integer precision. To calculate floor division of integers without losing the precision, use `def idivide($n): (. - . % $n) / $n;`. To round down floating-point numbers to integers, use `def ifloor: floor | tostring | tonumber;`, but note that this function does not work with large floating-point numbers and also loses the precision of large integers.
7979 - gojq fixes various bugs of jq. gojq correctly deletes elements of arrays by `|= empty` ([jq#2051](https://github.com/stedolan/jq/issues/2051)). gojq fixes `try`/`catch` handling ([jq#1859](https://github.com/stedolan/jq/issues/1859), [jq#1885](https://github.com/stedolan/jq/issues/1885), [jq#2140](https://github.com/stedolan/jq/issues/2140)). gojq fixes `nth/2` to output nothing when the count is equal to or larger than the stream size ([jq#1867](https://github.com/stedolan/jq/issues/1867)). gojq consistently counts by characters (not by bytes) in `index`, `rindex`, and `indices` functions; `"12345" | .[index("3"):]` results in `"345"` ([jq#1430](https://github.com/stedolan/jq/issues/1430), [jq#1624](https://github.com/stedolan/jq/issues/1624)). gojq handles overlapping occurrence differently in `rindex` and `indices`; `"ababa" | [rindex("aba"), indices("aba")]` results in `[2,[0,2]]` ([jq#2433](https://github.com/stedolan/jq/issues/2433)). gojq supports string indexing; `"abcde"[2]` ([jq#1520](https://github.com/stedolan/jq/issues/1520)). gojq accepts indexing query `.e0` ([jq#1526](https://github.com/stedolan/jq/issues/1526), [jq#1651](https://github.com/stedolan/jq/issues/1651)), and allows `gsub` to handle patterns including `"^"` ([jq#2148](https://github.com/stedolan/jq/issues/2148)). gojq improves variable lexer to allow using keywords for variable names, especially in binding patterns, also disallows spaces after `$` ([jq#526](https://github.com/stedolan/jq/issues/526)). gojq fixes handling files with no newline characters at the end ([jq#2374](https://github.com/stedolan/jq/issues/2374)).
80 - gojq truncates down floating-point numbers on indexing (`[0] | .[0.5]` results in `0` not `null`), and slicing (`[0,1,2] | .[0.5:1.5]` results in `[0]` not `[0,1]`). gojq parses unary operators with higher precedence than variable binding (`[-1 as $x | 1,$x]` results in `[1,-1]` not `[-1,-1]`). gojq implements `@uri` to escape all the reserved characters defined in RFC 3986, Sec. 2.2 ([jq#1506](https://github.com/stedolan/jq/issues/1506)), and fixes `@base64d` to allow binary string as the decoded string ([jq#1931](https://github.com/stedolan/jq/issues/1931)). gojq improves time formatting and parsing; deals with `%f` in `strftime` and `strptime` ([jq#1409](https://github.com/stedolan/jq/issues/1409)), parses timezone offsets with `fromdate` and `fromdateiso8601` ([jq#1053](https://github.com/stedolan/jq/issues/1053)), supports timezone name/offset with `%Z`/`%z` in `strptime` ([jq#929](https://github.com/stedolan/jq/issues/929), [jq#2195](https://github.com/stedolan/jq/issues/2195)), and looks up correct timezone during daylight saving time on formatting with `%Z` ([jq#1912](https://github.com/stedolan/jq/issues/1912)). gojq supports nanoseconds in date and time functions.
81 - gojq does not support some functions intentionally; `get_jq_origin`, `get_prog_origin`, `get_search_list` (unstable, not listed in jq document), `input_line_number`, `$__loc__` (performance issue), `recurse_down` (deprecated in jq). gojq does not support some flags; `--ascii-output, -a` (performance issue), `--seq` (not used commonly), `--sort-keys, -S` (sorts by default because `map[string]interface{}` does not keep the order), `--unbuffered` (unbuffered by default). gojq does not parse JSON extensions supported by jq; `NaN`, `Infinity`, and `[000]`. gojq normalizes floating-point numbers to fit to double-precision floating-point numbers. gojq does not support some regular expression flags (regular expression engine differences). gojq does not support BOM (`encoding/json` does not support this). gojq disallows using keywords for function names (`def true: .; true` is a confusing query), and module name prefixes in function declarations (using module prefixes like `def m::f: .;` is undocumented).
80 - gojq implements `@uri` to escape all the reserved characters defined in RFC 3986, Sec. 2.2 ([jq#1506](https://github.com/stedolan/jq/issues/1506)), and fixes `@base64d` to allow binary string as the decoded string ([jq#1931](https://github.com/stedolan/jq/issues/1931)). gojq improves time formatting and parsing; deals with `%f` in `strftime` and `strptime` ([jq#1409](https://github.com/stedolan/jq/issues/1409)), parses timezone offsets with `fromdate` and `fromdateiso8601` ([jq#1053](https://github.com/stedolan/jq/issues/1053)), supports timezone name/offset with `%Z`/`%z` in `strptime` ([jq#929](https://github.com/stedolan/jq/issues/929), [jq#2195](https://github.com/stedolan/jq/issues/2195)), and looks up correct timezone during daylight saving time on formatting with `%Z` ([jq#1912](https://github.com/stedolan/jq/issues/1912)). gojq supports nanoseconds in date and time functions.
81 - gojq does not support some functions intentionally; `get_jq_origin`, `get_prog_origin`, `get_search_list` (unstable, not listed in jq document), `input_line_number`, `$__loc__` (performance issue), `recurse_down` (deprecated in jq). gojq does not support some flags; `--ascii-output, -a` (performance issue), `--seq` (not used commonly), `--sort-keys, -S` (sorts by default because `map[string]interface{}` does not keep the order), `--unbuffered` (unbuffered by default). gojq does not parse JSON extensions supported by jq; `NaN`, `Infinity`, and `[000]`. gojq normalizes floating-point numbers to fit to double-precision floating-point numbers. gojq does not support some regular expression flags (regular expression engine differences). gojq does not support BOM (`encoding/json` does not support this). gojq disallows using keywords for function names (declaration of `def true: .;` is a confusing query).
8282 - gojq supports reading from YAML input (`--yaml-input`) while jq does not. gojq also supports YAML output (`--yaml-output`).
8383
8484 ### Color configuration
4545 fd.Minify()
4646 fds[fd.Name] = append(fds[fd.Name], fd)
4747 }
48 fds["_assign"] = nil
49 fds["_modify"] = nil
5048 t, err := astgen.Build(fds)
5149 if err != nil {
5250 return err
66 "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: "."}}}}}}},
77 "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"}}}}}}},
88 "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"}}}}},
9 "_assign": []*FuncDef{},
10 "_modify": []*FuncDef{},
9 "_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"}}}}}}}}}},
10 "_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{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}, &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}, Op: OpAdd, 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"}}}}}}}}}}}}}}}}}}}},
1111 "all": []*FuncDef{&FuncDef{Name: "all", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "all", Args: []*Query{&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{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "y"}, Op: OpPipe, Right: &Query{Func: "not"}}}}}}}}}}}}},
1212 "any": []*FuncDef{&FuncDef{Name: "any", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "any", Args: []*Query{&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{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Func: "y"}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "not"}}}},
1313 "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"}}}}}}}}}},
14 "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"}}}}},
15 "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"}}}}},
1416 "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"}}}}}}}}}},
1517 "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{Func: "_capture"}}}},
1618 "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: TermTypeArray, Array: &Array{Query: &Query{Func: "$x"}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}, IsSlice: true}}}, Op: OpPipe, Right: &Query{Func: "combinations"}}}}}}}}}}}}}}, &FuncDef{Name: "combinations", Args: []string{"n"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "limit", Args: []*Query{&Query{Func: "n"}, &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "repeat", Args: []*Query{&Query{Func: "."}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "combinations"}}}},
1921 "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"}}}}}}}}},
2022 "fromdate": []*FuncDef{&FuncDef{Name: "fromdate", Body: &Query{Func: "fromdateiso8601"}}},
2123 "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"}}}},
22 "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"}}}}, 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"}}}}}}}}}}}}}},
24 "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"}}}}}}}}}}}}}},
2325 "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"}}}}}}}}}}}}}},
2426 "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"}}}}}}}}}},
2527 "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"}}}}}}}}}}}}},
3234 "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"}}}}}},
3335 "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"}}}}}}},
3436 "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"}}}},
35 "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{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_match", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "$flags"}, &Query{Func: "false"}}}, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}},
37 "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}}}}}}},
3638 "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"}}}}}}}}}}}}}},
3739 "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"}}}}}}}}}}}}}},
3840 "normals": []*FuncDef{&FuncDef{Name: "normals", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Func: "isnormal"}}}}}}},
4648 "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"}}},
4749 "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"}}},
4850 "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"}}}}}}}}}}}},
49 "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{Func: "$flags"}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "g"}}}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "captures"}}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{}}}}, Then: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "string"}}}, Else: &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"}}}}}}}}}}}}}},
51 "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{Func: "$flags"}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "g"}}}}}}}}, 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"}}}}}}}}},
5052 "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"}}}}}},
5153 "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"}}}}}}}}}}}}}},
52 "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{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "split", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "$flags"}}}, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}},
54 "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}}}}}}},
5355 "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"}}}}}}}}}},
54 "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: "$str"}}, 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: OpEq, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{}}}}, Then: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$str"}, SuffixList: []*Suffix{&Suffix{Index: &Index{End: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "offset"}}}, IsSlice: true}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "string"}}}}, Else: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "matches"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeUnary, Unary: &Unary{Op: OpSub, Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}, &Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$r"}}, Body: &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: TermTypeQuery, Query: &Query{Left: &Query{Func: "$r"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "_capture"}, Op: OpPipe, Right: &Query{Func: "str"}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$str"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &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"}}}}}}, End: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "offset"}}}, IsSlice: true}}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "string"}}}}}}}}}, &ObjectKeyVal{Key: "offset", Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$r"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Name: "offset"}}}}}}}}, &ObjectKeyVal{Key: "matches", Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "matches"}, SuffixList: []*Suffix{&Suffix{Index: &Index{End: &Query{Term: &Term{Type: TermTypeUnary, Unary: &Unary{Op: OpSub, Term: &Term{Type: TermTypeNumber, Number: "1"}}}}, IsSlice: true}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "_sub"}}}}}}}}}}}}, 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: "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"}}}}}}}}},
56 "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: "$str"}}, 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: TermTypeIndex, Index: &Index{Name: "matches"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeUnary, Unary: &Unary{Op: OpSub, Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}, &Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$r"}}, Body: &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: TermTypeQuery, Query: &Query{Left: &Query{Func: "$r"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "_capture"}, Op: OpPipe, Right: &Query{Func: "str"}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$str"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &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"}}}}}}, End: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "offset"}}}, IsSlice: true}}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "string"}}}}}}}}}, &ObjectKeyVal{Key: "offset", Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$r"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Name: "offset"}}}}}}}}, &ObjectKeyVal{Key: "matches", Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "matches"}, SuffixList: []*Suffix{&Suffix{Index: &Index{End: &Query{Term: &Term{Type: TermTypeUnary, Unary: &Unary{Op: OpSub, Term: &Term{Type: TermTypeNumber, Number: "1"}}}}, IsSlice: true}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "_sub"}}}}}}}, Else: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$str"}, SuffixList: []*Suffix{&Suffix{Index: &Index{End: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "offset"}}}, IsSlice: true}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "string"}}}}}}}}}, 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: "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"}}}}}}}}},
5557 "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"}}}}}}},
5658 "todate": []*FuncDef{&FuncDef{Name: "todate", Body: &Query{Func: "todateiso8601"}}},
5759 "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"}}}}}}}}},
6062 "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"}}}}}}}}}}}}}},
6163 "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"}}},
6264 "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"}}}}}}}},
63 "walk": []*FuncDef{&FuncDef{Name: "walk", Args: []string{"f"}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: "_walk", Body: &Query{Left: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "array"}}}}, Then: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Func: "_walk"}}}}}, Elif: []*IfElif{&IfElif{Cond: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "object"}}}}, Then: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map_values", Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "last", Args: []*Query{&Query{Func: "_walk"}}}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "f"}}}}, Func: "_walk"}}},
65 "walk": []*FuncDef{&FuncDef{Name: "walk", Args: []string{"f"}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: "_walk", Body: &Query{Left: &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: TermTypeFunc, Func: &Func{Name: "map_values", Args: []*Query{&Query{Func: "_walk"}}}}}}}}, Op: OpPipe, Right: &Query{Func: "f"}}}}, Func: "_walk"}}},
6466 "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"}}},
6567 "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"}}}}},
6668 }
3939 def leaf_paths: paths(scalars);
4040
4141 def inside(xs): . as $x | xs | contains($x);
42 def combinations:
43 if length == 0 then
44 []
45 else
46 .[0][] as $x | [$x] + (.[1:] | combinations)
47 end;
42 def combinations: if length == 0 then [] else .[0][] as $x | [$x] + (.[1:] | combinations) end;
4843 def combinations(n): [limit(n; repeat(.))] | combinations;
44 def ascii_downcase:
45 explode | map(if 65 <= . and . <= 90 then . + 32 end) | implode;
46 def ascii_upcase:
47 explode | map(if 97 <= . and . <= 122 then . - 32 end) | implode;
4948 def walk(f):
50 def _walk:
51 if type == "array" then
52 map(_walk)
53 elif type == "object" then
54 map_values(last(_walk))
55 end | f;
49 def _walk: if type | . == "array" or . == "object" then map_values(_walk) end | f;
5650 _walk;
5751
5852 def first: .[0];
6862 def any(g; y): isempty(g | select(y)) | not;
6963 def limit($n; g):
7064 if $n > 0 then
71 label $out |
72 foreach g as $item (
73 $n;
74 . - 1;
75 $item, if . <= 0 then break $out else empty end
76 )
65 label $out
66 | foreach g as $item
67 ($n; . - 1; $item, if . <= 0 then break $out else empty end)
7768 elif $n == 0 then
7869 empty
7970 else
8475 if $n < 0 then
8576 error("nth doesn't support negative indices")
8677 else
87 label $out |
88 foreach g as $item (
89 $n + 1;
90 . - 1;
91 if . <= 0 then $item, break $out else empty end
92 )
78 label $out
79 | foreach g as $item
80 ($n + 1; . - 1; if . <= 0 then $item, break $out else empty end)
9381 end;
9482
9583 def truncate_stream(f):
96 . as $n | null | f |
97 if .[0] | length > $n then .[0] |= .[$n:] else empty end;
84 . as $n | null | f | if .[0] | length > $n then .[0] |= .[$n:] else empty end;
9885 def fromstream(f):
99 { x: null, e: false } as $init |
100 foreach f as $i (
101 $init;
102 if .e then $init end |
103 if $i | length == 2 then
104 setpath(["e"]; $i[0] | length == 0) |
105 setpath(["x"] + $i[0]; $i[1])
106 else
107 setpath(["e"]; $i[0] | length == 1)
108 end;
109 if .e then .x else empty end
110 );
86 { x: null, e: false } as $init
87 | foreach f as $i
88 ( $init;
89 if .e then $init else . end
90 | if $i | length == 2
91 then setpath(["e"]; $i[0] | length==0) | setpath(["x"] + $i[0]; $i[1])
92 else setpath(["e"]; $i[0] | length==1) end;
93 if .e then .x else empty end);
11194 def tostream:
112 path(def r: (.[]? | r), .; r) as $p |
113 getpath($p) |
114 reduce path(.[]?) as $q ([$p, .]; [$p + $q]);
95 path(def r: (.[]? | r), .; r) as $p
96 | getpath($p)
97 | reduce path(.[]?) as $q ([$p, .]; [$p + $q]);
11598
99 def _assign(ps; $v):
100 reduce path(ps) as $p (.; setpath($p; $v));
101 def _modify(ps; f):
102 reduce path(ps) as $p
103 ([., []]; label $out | (([0] + $p) as $q | setpath($q; getpath($q) | f) | ., break $out), setpath([1]; .[1] + [$p]))
104 | . as $x | $x[0] | delpaths($x[1]);
116105 def map_values(f): .[] |= f;
117106 def del(f): delpaths([path(f)]);
118107 def paths: path(..) | select(. != []);
124113 def todate: todateiso8601;
125114
126115 def match($re): match($re; null);
127 def match($re; $flags): _match($re; $flags; false)[];
116 def match($re; $flags): _match($re; $flags; false) | .[];
128117 def test($re): test($re; null);
129118 def test($re; $flags): _match($re; $flags; true);
130119 def capture($re): capture($re; null);
131120 def capture($re; $flags): match($re; $flags) | _capture;
132121 def scan($re): scan($re; null);
133122 def scan($re; $flags):
134 match($re; $flags + "g") |
135 if .captures == [] then
136 .string
137 else
138 [.captures[].string]
139 end;
123 match($re; $flags + "g")
124 | if .captures|length > 0 then [.captures[].string] else .string end;
140125 def splits($re): splits($re; null);
141 def splits($re; $flags): split($re; $flags)[];
126 def splits($re; $flags): split($re; $flags) | .[];
142127 def sub($re; str): sub($re; str; null);
143128 def sub($re; str; $flags):
144 . as $str |
145 def _sub:
146 if .matches == [] then
147 $str[:.offset] + .string
148 else
149 .matches[-1] as $r |
150 {
151 string: (($r | _capture | str) + $str[$r.offset+$r.length:.offset] + .string),
152 offset: $r.offset,
153 matches: .matches[:-1],
154 } |
155 _sub
156 end;
129 . as $str
130 | def _sub:
131 if .matches|length > 0
132 then
133 .matches[-1] as $r
134 | {
135 string: (($r | _capture | str) + $str[$r.offset+$r.length:.offset] + .string),
136 offset: $r.offset,
137 matches: .matches[:-1],
138 }
139 | _sub
140 else
141 $str[:.offset] + .string
142 end;
157143 { string: "", matches: [match($re; $flags)] } | _sub;
158144 def gsub($re; str): sub($re; str; "g");
159145 def gsub($re; str; $flags): sub($re; str; $flags + "g");
165151 if . == "break" then empty else error end;
166152
167153 def INDEX(stream; idx_expr):
168 reduce stream as $row ({}; .[$row | idx_expr | tostring] = $row);
169 def INDEX(idx_expr):
170 INDEX(.[]; idx_expr);
154 reduce stream as $row ({}; .[$row|idx_expr|tostring] = $row);
155 def INDEX(idx_expr): INDEX(.[]; idx_expr);
171156 def JOIN($idx; idx_expr):
172157 [.[] | [., $idx[idx_expr]]];
173158 def JOIN($idx; stream; idx_expr):
2424 return &encoder{w: new(bytes.Buffer), tab: tab, indent: indent}
2525 }
2626
27 func (e *encoder) flush() error {
28 _, err := e.out.Write(e.w.Bytes())
27 func (e *encoder) marshal(v interface{}, w io.Writer) error {
28 e.out = w
29 e.encode(v)
30 _, err := w.Write(e.w.Bytes())
2931 e.w.Reset()
3032 return err
3133 }
3234
33 func (e *encoder) marshal(v interface{}, w io.Writer) error {
34 e.out = w
35 err := e.encode(v)
36 if ferr := e.flush(); ferr != nil && err == nil {
37 err = ferr
38 }
39 return err
40 }
41
42 func (e *encoder) encode(v interface{}) error {
35 func (e *encoder) encode(v interface{}) {
4336 switch v := v.(type) {
4437 case nil:
4538 e.write([]byte("null"), nullColor)
5851 case string:
5952 e.encodeString(v, stringColor)
6053 case []interface{}:
61 if err := e.encodeArray(v); err != nil {
62 return err
63 }
54 e.encodeArray(v)
6455 case map[string]interface{}:
65 if err := e.encodeMap(v); err != nil {
66 return err
67 }
56 e.encodeMap(v)
6857 default:
6958 panic(fmt.Sprintf("invalid type: %[1]T (%[1]v)", v))
7059 }
7160 if e.w.Len() > 8*1024 {
72 return e.flush()
73 }
74 return nil
61 e.out.Write(e.w.Bytes())
62 e.w.Reset()
63 }
7564 }
7665
7766 // ref: floatEncoder in encoding/json
162151 }
163152 }
164153
165 func (e *encoder) encodeArray(vs []interface{}) error {
154 func (e *encoder) encodeArray(vs []interface{}) {
166155 e.writeByte('[', arrayColor)
167156 e.depth += e.indent
168157 for i, v := range vs {
172161 if e.indent != 0 {
173162 e.writeIndent()
174163 }
175 if err := e.encode(v); err != nil {
176 return err
177 }
164 e.encode(v)
178165 }
179166 e.depth -= e.indent
180167 if len(vs) > 0 && e.indent != 0 {
181168 e.writeIndent()
182169 }
183170 e.writeByte(']', arrayColor)
184 return nil
185 }
186
187 func (e *encoder) encodeMap(vs map[string]interface{}) error {
171 }
172
173 func (e *encoder) encodeMap(vs map[string]interface{}) {
188174 e.writeByte('{', objectColor)
189175 e.depth += e.indent
190176 type keyVal struct {
212198 if e.indent != 0 {
213199 e.w.WriteByte(' ')
214200 }
215 if err := e.encode(kv.val); err != nil {
216 return err
217 }
201 e.encode(kv.val)
218202 }
219203 e.depth -= e.indent
220204 if len(vs) > 0 && e.indent != 0 {
221205 e.writeIndent()
222206 }
223207 e.writeByte('}', objectColor)
224 return nil
225208 }
226209
227210 func (e *encoder) writeIndent() {
228211 e.w.WriteByte('\n')
229212 if n := e.depth; n > 0 {
230213 if e.tab {
231 e.writeIndentInternal(n, "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t")
214 const tabs = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"
215 for n > len(tabs) {
216 e.w.Write([]byte(tabs))
217 n -= len(tabs)
218 }
219 e.w.Write([]byte(tabs)[:n])
232220 } else {
233 e.writeIndentInternal(n, " ")
234 }
235 }
236 }
237
238 func (e *encoder) writeIndentInternal(n int, spaces string) {
239 if l := len(spaces); n <= l {
240 e.w.WriteString(spaces[:n])
241 } else {
242 e.w.WriteString(spaces)
243 for n -= l; n > 0; n, l = n-l, l*2 {
244 if n < l {
245 l = n
246 }
247 e.w.Write(e.w.Bytes()[e.w.Len()-l:])
221 const spaces = " "
222 for n > len(spaces) {
223 e.w.Write([]byte(spaces))
224 n -= len(spaces)
225 }
226 e.w.Write([]byte(spaces)[:n])
248227 }
249228 }
250229 }
836836 [-1,-2,-3,-4722366482869645213696]
837837 [1,2,3,4722366482869645213696]
838838
839 - name: unary operator against string
839 - name: unary operators against string
840840 args:
841841 - '(-.)'
842842 input: '"abcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcde"'
843843 error: |
844844 cannot negate: string ("abcdeabcdeabcdeabcdeabcd ...")
845
846 - name: unary operator with variable binding
847 args:
848 - '-1 as $x | 1, $x'
849 input: 'null'
850 expected: |
851 1
852 -1
853845
854846 - name: object construction
855847 args:
19271919 "endswith cannot be applied to: object ({})"
19281920 "endswith cannot be applied to: number (10)"
19291921
1930 - name: combinations/0 function
1931 args:
1932 - -c
1933 - '[combinations]'
1934 input: '[] [[0]] [[1, 2, 3], [4, 5, 6]]'
1935 expected: |
1936 [[]]
1937 [[0]]
1938 [[1,4],[1,5],[1,6],[2,4],[2,5],[2,6],[3,4],[3,5],[3,6]]
1939
1940 - name: combinations/1 function
1941 args:
1942 - -c
1943 - '[combinations(3)]'
1944 input: '[] [0] [1, 2]'
1945 expected: |
1946 []
1947 [[0,0,0]]
1948 [[1,1,1],[1,1,2],[1,2,1],[1,2,2],[2,1,1],[2,1,2],[2,2,1],[2,2,2]]
1949
19501922 - name: ltrimstr function
19511923 args:
19521924 - 'map(ltrimstr("foo")), ("x"|ltrimstr(0, null, {}))'
19891961 "x"
19901962 "x"
19911963
1992 - name: explode function
1993 args:
1994 - -c
1995 - 'explode'
1996 input: |
1997 ""
1998 "foo bar"
1999 "12345"
2000 "\n\t"
1964 - name: combinations/0 function
1965 args:
1966 - -c
1967 - '[combinations]'
1968 input: '[] [[0]] [[1, 2, 3], [4, 5, 6]]'
1969 expected: |
1970 [[]]
1971 [[0]]
1972 [[1,4],[1,5],[1,6],[2,4],[2,5],[2,6],[3,4],[3,5],[3,6]]
1973
1974 - name: combinations/1 function
1975 args:
1976 - -c
1977 - '[combinations(3)]'
1978 input: '[] [0] [1, 2]'
20011979 expected: |
20021980 []
2003 [102,111,111,32,98,97,114]
2004 [65297,65298,65299,65300,65301]
2005 [10,9]
2006
2007 - name: implode function
2008 args:
2009 - 'implode'
2010 input: |
2011 []
2012 [102,111,111,32,98,97,114]
2013 [65297,65298,65299,65300,65301]
2014 [10,9]
2015 expected: |
2016 ""
2017 "foo bar"
2018 "12345"
2019 "\n\t"
2020
2021 - name: implode function error
2022 args:
2023 - 'try implode catch .'
2024 input: |
2025 [0]
2026 [-1]
2027 [1114112]
2028 [[]]
2029 [{}]
2030 expected: |
2031 "\u0000"
2032 "implode cannot be applied to: array ([-1])"
2033 "implode cannot be applied to: array ([1114112])"
2034 "implode cannot be applied to: array ([[]])"
2035 "implode cannot be applied to: array ([{}])"
2036
2037 - name: split/1 function
2038 args:
2039 - 'split(", ","") | join("/")'
2040 input: |
2041 "a,b, c, d, e,f"
2042 ", a,b, c, d, e,f, "
2043 expected: |
2044 "a,b/c/d/e,f"
2045 "a/,/b/,/ /c/,/ /d/,/ /e/,/f"
2046 "/a,b/c/d/e,f/"
2047 ",/ /a/,/b/,/ /c/,/ /d/,/ /e/,/f/,/ "
1981 [[0,0,0]]
1982 [[1,1,1],[1,1,2],[1,2,1],[1,2,2],[2,1,1],[2,1,2],[2,2,1],[2,2,2]]
20481983
20491984 - name: join function
20501985 args:
21082043 - name: ascii_downcase function
21092044 args:
21102045 - 'ascii_downcase'
2111 input: '"@ABC XYZ[] `abc xyz{} Αα"'
2112 expected: |
2113 "@abc xyz[] `abc xyz{} Αα"
2046 input: '"@ABC XYZ[] `abc xyz{} ☆"'
2047 expected: |
2048 "@abc xyz[] `abc xyz{} ☆"
21142049
21152050 - name: ascii_upcase function
21162051 args:
21172052 - 'ascii_upcase'
2118 input: '"@ABC XYZ[] `abc xyz{} Αα"'
2119 expected: |
2120 "@ABC XYZ[] `ABC XYZ{} Αα"
2053 input: '"@ABC XYZ[] `abc xyz{} ☆"'
2054 expected: |
2055 "@ABC XYZ[] `ABC XYZ{} ☆"
21212056
21222057 - name: walk function
21232058 args:
21312066 2
21322067 ["aa",{"b":[]},"aa",{"b":[]}]
21332068 {"c":[null,true,false,null,true,false]}
2134
2135 - name: walk function with multiple values
2136 args:
2137 - -c
2138 - 'walk(.,0)'
2139 input: '[1,2,3] {"x":1,"y":2,"z":3}'
2140 expected: |
2141 [1,0,2,0,3,0]
2142 0
2143 {"x":0,"y":0,"z":0}
2144 0
21452069
21462070 - name: transpose function
21472071 args:
28822806 expected: |
28832807 [5,5,false,3,3,[null,false],null,false]
28842808
2809 - name: explode function
2810 args:
2811 - -c
2812 - 'explode'
2813 input: |
2814 ""
2815 "foo bar"
2816 "12345"
2817 "\n\t"
2818 expected: |
2819 []
2820 [102,111,111,32,98,97,114]
2821 [65297,65298,65299,65300,65301]
2822 [10,9]
2823
2824 - name: implode function
2825 args:
2826 - 'implode'
2827 input: |
2828 []
2829 [102,111,111,32,98,97,114]
2830 [65297,65298,65299,65300,65301]
2831 [10,9]
2832 expected: |
2833 ""
2834 "foo bar"
2835 "12345"
2836 "\n\t"
2837
2838 - name: implode function error
2839 args:
2840 - 'try implode catch .'
2841 input: |
2842 [0]
2843 [-1]
2844 [1114112]
2845 [[]]
2846 [{}]
2847 expected: |
2848 "\u0000"
2849 "implode cannot be applied to: array ([-1])"
2850 "implode cannot be applied to: array ([1114112])"
2851 "implode cannot be applied to: array ([[]])"
2852 "implode cannot be applied to: array ([{}])"
2853
2854 - name: split/1 function
2855 args:
2856 - 'split(", ","") | join("/")'
2857 input: |
2858 "a,b, c, d, e,f"
2859 ", a,b, c, d, e,f, "
2860 expected: |
2861 "a,b/c/d/e,f"
2862 "a/,/b/,/ /c/,/ /d/,/ /e/,/f"
2863 "/a,b/c/d/e,f/"
2864 ",/ /a/,/b/,/ /c/,/ /d/,/ /e/,/f/,/ "
2865
28852866 - name: condition
28862867 args:
28872868 - 'if . then . else [.] end'
31833164 1
31843165 3
31853166 6
3186
3187 - name: label and break in try catch syntax
3188 args:
3189 - 'label $x | (label $y | try break $y catch .), .'
3190 input: '10'
3191 expected: |
3192 10
31933167
31943168 - name: label and break in function argument
31953169 args:
42604234 expected: |
42614235 [1,2,4,5]
42624236
4263 - name: delpaths function with overlapping paths
4237 - name: delpaths function with overlapped paths
42644238 args:
42654239 - -c
42664240 - 'delpaths([["x"],["x",0,"y"]], [["x",0],["x",0,"y"]], [["x"],["x",{"start":0}]])'
43614335 expected: |
43624336 [0,3,5,6,9]
43634337
4364 - name: del function against large array with select
4365 args:
4366 - '[range(.)] | (5,7) as $x | del(.[] | select(. % $x == 0)) | add'
4367 input: '50000'
4368 expected: |
4369 1000000000
4370 1071421429
4371
4372 - name: del function against large array with slicing
4373 args:
4374 - '[range(.)] | del(.[range(length) | {start:.,end:(.+1)}])'
4375 input: '50000'
4376 expected: |
4377 []
4378
43794338 - name: assignment operator against object
43804339 args:
43814340 - -c
43914350 input: '[0,1,2]'
43924351 expected: |
43934352 [3,1,3]
4394
4395 - name: assignment operator against number
4396 args:
4397 - '. = 1'
4398 input: '0'
4399 expected: |
4400 1
4401
4402 - name: assignment operator against number error
4403 args:
4404 - '.foo = 1'
4405 input: '0'
4406 error: |
4407 expected an object but got: number (0)
4408
4409 - name: assignment operator against object with multiple paths
4410 args:
4411 - -c
4412 - '(.foo,.bar,.baz) = 1'
4413 input: 'null'
4414 expected: |
4415 {"bar":1,"baz":1,"foo":1}
44164353
44174354 - name: assignment operator against array with slicing
44184355 args:
44854422 expected: |
44864423 {"foo":[{"bar":1},{"bar":1}]}
44874424
4488 - name: assignment operator with overlapping paths
4489 args:
4490 - -c
4491 - '[(.x,.x.y,.x.y.z) = {}, (.x.y.z,.x.y,.x) = {}]'
4492 input: 'null'
4493 expected: |
4494 [{"x":{"y":{"z":{}}}},{"x":{}}]
4495
44964425 - name: assignment operator query
44974426 args:
44984427 - -c
45014430 expected: |
45024431 {"bar":42,"foo":42}
45034432
4504 - name: assignment operator query with multiple paths
4505 args:
4506 - -c
4507 - '(.foo,.bar,.baz) = .bar + 1'
4508 input: '{"bar":42}'
4509 expected: |
4510 {"bar":43,"baz":43,"foo":43}
4511
4512 - name: assignment operator array index negative error
4513 args:
4514 - '.[-1,0] = 1'
4515 input: '[]'
4516 error: |
4517 setpath cannot be applied to: number (-1)
4518
45194433 - name: assignment operator array index limit error
45204434 args:
45214435 - '.[200000000] = 1'
45474461 expected: |
45484462 [{"k":"a","v":1},{"k":"b","v":0},{"k":"c","v":3}]
45494463
4550 - name: assignment operator with fork
4551 args:
4552 - -c
4553 - '[range(3)] | .[] = 0 | [.[] = 1, .[] = 2]'
4554 input: 'null'
4555 expected: |
4556 [[1,1,1],[2,2,2]]
4557
4558 - name: assignment operator against large array
4559 args:
4560 - '[range(.)] | .[] = 1 | add'
4561 input: '50000'
4562 expected: |
4563 50000
4564
4565 - name: assignment operator against large array with select
4566 args:
4567 - '[range(.)] | (.[] | select(. % 2 > 0)) = 1 | add'
4568 input: '50000'
4569 expected: |
4570 625000000
4571
4572 - name: assignment operator against large array with range
4573 args:
4574 - '[range(.)] | .[range(length)] = 1 | add'
4575 input: '50000'
4576 expected: |
4577 50000
4578
4579 - name: assignment operator against large array with slicing
4580 args:
4581 - '[range(.)] | .[range(length) | {start:.,end:(.+1)}] = [1] | add'
4582 input: '50000'
4583 expected: |
4584 50000
4585
4586 - name: assignment operator against large object
4587 args:
4588 - '[{key:range(.)|tostring}] | from_entries | .[] = 1 | add'
4589 input: '50000'
4590 expected: |
4591 50000
4592
4593 - name: assignment operator constructing large array
4594 args:
4595 - '.[range(50000)] = 1 | add'
4596 input: 'null'
4597 expected: |
4598 50000
4599
4600 - name: update-assignment operator
4464 - name: modify operator
46014465 args:
46024466 - -c
46034467 - '.foo |= .+1'
46054469 expected: |
46064470 {"foo":2}
46074471
4608 - name: update-assignment operator deeply
4472 - name: modify operator deeply
46094473 args:
46104474 - -c
46114475 - '.[0].a |= {"old":., "new":(.+1)}'
46134477 expected: |
46144478 [{"a":{"new":2,"old":1},"b":2}]
46154479
4616 - name: update-assignment operator in function
4480 - name: modify operator in function
46174481 args:
46184482 - -c
46194483 - 'def inc(x): x |= .+1; inc(.[].a)'
46214485 expected: |
46224486 [{"a":2,"b":2},{"a":3,"b":4},{"a":8,"b":8}]
46234487
4624 - name: update-assignment operator with empty
4488 - name: modify operator with empty
46254489 args:
46264490 - -c
46274491 - '.foo |= empty'
46294493 expected: |
46304494 {"bar":48}
46314495
4632 - name: update-assignment operator with repeat
4633 args:
4634 - -c
4635 - '.foo |= repeat(.)'
4636 input: '{"foo": 42, "bar": 48}'
4637 expected: |
4638 {"bar":48,"foo":42}
4639
4640 - name: update-assignment operator with same paths
4641 args:
4642 - -c
4643 - '(.foo,.foo,.foo) |= .+1'
4644 input: '{"foo": 0}'
4645 expected: |
4646 {"foo":3}
4647
4648 - name: update-assignment operator against array with empty function
4496 - name: modify operator on array with empty function
46494497 args:
46504498 - -c
46514499 - '(.[] | select(. % 2 > 0)) |= empty'
46534501 expected: |
46544502 [2,4]
46554503
4656 - name: update-assignment operator against array with conditional empty function
4504 - name: modify operator on array with conditional empty function
46574505 args:
46584506 - -c
46594507 - '[range(.)] | .[] |= if . % 2 == 0 then empty else [., -.] end'
46614509 expected: |
46624510 [[1,-1],[3,-3],[5,-5],[7,-7],[9,-9]]
46634511
4664 - name: update-assignment operator with fork
4665 args:
4666 - -c
4667 - '[range(3)] | .[] |= 0 | [.[] |= 1, .[] |= 2]'
4668 input: 'null'
4669 expected: |
4670 [[1,1,1],[2,2,2]]
4671
4672 - name: update-assignment operator against large array
4673 args:
4674 - '[range(.)] | .[] |= . * 2 | add'
4675 input: '50000'
4676 expected: |
4677 2499950000
4678
4679 - name: update-assignment operator against large array with select
4680 args:
4681 - '[range(.)] | (.[] | select(. % 2 > 0)) |= (. * 2) | add'
4682 input: '50000'
4683 expected: |
4684 1874975000
4685
4686 - name: update-assignment operator against large object
4687 args:
4688 - '[range(.) | {key:tostring,value:.}] | from_entries | .[] |= . * 2 | add'
4689 input: '50000'
4690 expected: |
4691 2499950000
4692
4693 - name: update-assignment operator against array with overlapping paths
4694 args:
4695 - -c
4696 - '(.[1:3][],.[2:4][],.[2]) |= .+1'
4697 input: '[1,2,3,4,5]'
4698 expected: |
4699 [1,3,6,5,5]
4700
4701 - name: update-assignment operator with optional operator
4512 - name: modify operator with optional operator
47024513 args:
47034514 - -c
47044515 - '.foo |= .?'
47064517 expected: |
47074518 {"foo":42}
47084519
4709 - name: update-assignment operator with infinite range
4710 args:
4711 - -c
4712 - '[range(.)] | .[] |= range(infinite)'
4713 input: '5'
4714 expected: |
4715 [0,0,0,0,0]
4716
4717 - name: update-assignment operator with try catch
4520 - name: modify operator with try catch
47184521 args:
47194522 - -c
47204523 - '. |= try . catch .'
47224525 expected: |
47234526 1
47244527
4725 - name: update-assignment operator with alternative operator
4528 - name: modify operator with alternative operator
47264529 args:
47274530 - -c
47284531 - '.foo |= (fromjson? // "x")'
48914694 expected: |
48924695 [0,"id"]
48934696
4894 - name: path function with getpath
4895 args:
4896 - -c
4897 - '[path(getpath([[0]] | .[0],.[]))]'
4898 input: 'null'
4899 expected: |
4900 [[0],[0]]
4901
49024697 - name: path function against nan
49034698 args:
49044699 - -c
49744769 [
49754770 "y"
49764771 ]
4977
4978 - name: path function with assignment operator
4979 args:
4980 - 'path(. = .x)'
4981 input: 'null'
4982 expected: |
4983 []
49844772
49854773 - name: path function with error function
49864774 args:
58625650 args:
58635651 - '@csv'
58645652 input: |
5865 [1, "foo", null, "foo,\n\"bar\"\tbaz\u0000\\0"]
5866 expected: |
5867 "1,\"foo\",,\"foo,\n\"\"bar\"\"\tbaz\\0\\0\""
5653 [1, "foo", null, "foo,\n\"bar\"\tbaz"]
5654 expected: |
5655 "1,\"foo\",,\"foo,\n\"\"bar\"\"\tbaz\""
58685656
58695657 - name: format strings @csv with string interpolation
58705658 args:
58935681 args:
58945682 - '@tsv'
58955683 input: |
5896 [1, "foo", null, "foo,\n\"bar\"\tbaz\u0000\\0"]
5897 expected: |
5898 "1\tfoo\t\tfoo,\\n\"bar\"\\tbaz\\0\\\\0"
5684 [1, "foo", null, "foo,\n\"bar\"\tba\\z"]
5685 expected: |
5686 "1\tfoo\t\tfoo,\\n\"bar\"\\tba\\\\z"
58995687
59005688 - name: format strings @tsv with string interpolation
59015689 args:
59265714 input: |
59275715 null
59285716 true
5929 [1, "f'o'o\u0000\\0", null, false]
5717 [1, "f'o'o", null, false]
59305718 expected: |
59315719 "null"
59325720 "true"
5933 "1 'f'\\''o'\\''o\\0\\0' null false"
5721 "1 'f'\\''o'\\''o' null false"
59345722
59355723 - name: format strings @sh error
59365724 args:
0 // gojq - Go implementation of jq
10 package main
21
32 import (
276276 }
277277 }
278278 return nil
279 }
280
281 func (c *compiler) appendBuiltin(name string, argcnt int) func() {
282 setjump := c.lazy(func() *code {
283 return &code{op: opjump, v: len(c.codes)}
284 })
285 c.appendCodeInfo(name)
286 c.builtinScope.funcs = append(
287 c.builtinScope.funcs,
288 &funcinfo{name, len(c.codes), argcnt},
289 )
290 return func() {
291 setjump()
292 c.appendCodeInfo("end of " + name)
293 }
294279 }
295280
296281 func (c *compiler) newScope() *scopeinfo {
788773 func (c *compiler) compileLabel(e *Label) error {
789774 c.appendCodeInfo(e)
790775 v := c.pushVariable("$%" + e.Ident[1:])
791 c.append(&code{op: opforklabel, v: v})
776 defer c.lazy(func() *code {
777 return &code{op: opforklabel, v: v}
778 })()
792779 return c.compileQuery(e.Body)
793780 }
794781
799786 }
800787 c.append(&code{op: oppop})
801788 c.append(&code{op: opload, v: v})
802 c.append(&code{op: opcall, v: [3]interface{}{funcBreak(label), 0, "_break"}})
789 c.append(&code{op: opcall, v: [3]interface{}{
790 func(v interface{}, _ []interface{}) interface{} {
791 return &breakError{label, v}
792 },
793 0,
794 "_break",
795 }})
803796 return nil
804 }
805
806 func funcBreak(label string) func(interface{}, []interface{}) interface{} {
807 return func(v interface{}, _ []interface{}) interface{} {
808 return &breakError{label, v}
809 }
810797 }
811798
812799 func (c *compiler) compileTerm(e *Term) error {
941928 break
942929 }
943930 }
944 if len(fds) == 0 {
945 switch e.Name {
946 case "_assign":
947 c.compileAssign()
948 case "_modify":
949 c.compileModify()
950 }
951 }
952931 if f := c.lookupBuiltin(e.Name, len(e.Args)); f != nil {
953932 return c.compileCallPc(f, e.Args)
954933 }
970949 [3]interface{}{c.funcBuiltins, 0, e.Name},
971950 e.Args,
972951 true,
973 -1,
952 false,
974953 )
975954 case "input":
976955 if c.inputIter == nil {
980959 [3]interface{}{c.funcInput, 0, e.Name},
981960 e.Args,
982961 true,
983 -1,
962 false,
984963 )
985964 case "modulemeta":
986965 return c.compileCallInternal(
987966 [3]interface{}{c.funcModulemeta, 0, e.Name},
988967 e.Args,
989968 true,
990 -1,
969 false,
991970 )
992971 default:
993972 return c.compileCall(e.Name, e.Args)
998977 [3]interface{}{fn.callback, len(e.Args), e.Name},
999978 e.Args,
1000979 true,
1001 -1,
980 false,
1002981 ); err != nil {
1003982 return err
1004983 }
1008987 return nil
1009988 }
1010989 return &funcNotFoundError{e}
1011 }
1012
1013 // Appends the compiled code for the assignment operator (`=`) to maximize
1014 // performance. Originally the operator was implemented as follows.
1015 //
1016 // def _assign(p; $x): reduce path(p) as $p (.; setpath($p; $x));
1017 //
1018 // To overcome the difficulty of reducing allocations on `setpath`, we use the
1019 // `allocator` type and track the allocated addresses during the reduction.
1020 func (c *compiler) compileAssign() {
1021 defer c.appendBuiltin("_assign", 2)()
1022 scope := c.newScope()
1023 v, p := [2]int{scope.id, 0}, [2]int{scope.id, 1}
1024 x, a := [2]int{scope.id, 2}, [2]int{scope.id, 3}
1025 c.appends(
1026 &code{op: opscope, v: [3]int{scope.id, 4, 2}},
1027 &code{op: opstore, v: v}, // def _assign(p; $x):
1028 &code{op: opstore, v: p},
1029 &code{op: opstore, v: x},
1030 &code{op: opload, v: v},
1031 &code{op: opexpbegin},
1032 &code{op: opload, v: x},
1033 &code{op: opcallpc},
1034 &code{op: opstore, v: x},
1035 &code{op: opexpend},
1036 &code{op: oppush, v: nil},
1037 &code{op: opcall, v: [3]interface{}{funcAllocator, 0, "_allocator"}},
1038 &code{op: opstore, v: a},
1039 &code{op: opload, v: v},
1040 &code{op: opfork, v: len(c.codes) + 28}, // reduce [L1]
1041 &code{op: oppathbegin}, // path(p)
1042 &code{op: opload, v: p},
1043 &code{op: opcallpc},
1044 &code{op: opload, v: v},
1045 &code{op: oppathend},
1046 &code{op: opstore, v: p}, // as $p (.;
1047 &code{op: opload, v: a}, // setpath($p; $x)
1048 &code{op: opload, v: x},
1049 &code{op: opload, v: p},
1050 &code{op: opload, v: v},
1051 &code{op: opcall, v: [3]interface{}{funcSetpathWithAllocator, 3, "_setpath"}},
1052 &code{op: opstore, v: v},
1053 &code{op: opbacktrack}, // );
1054 &code{op: oppop}, // [L1]
1055 &code{op: opload, v: v},
1056 &code{op: opret},
1057 )
1058 }
1059
1060 // Appends the compiled code for the update-assignment operator (`|=`) to
1061 // maximize performance. We use the `allocator` type, just like `_assign/2`.
1062 func (c *compiler) compileModify() {
1063 defer c.appendBuiltin("_modify", 2)()
1064 scope := c.newScope()
1065 v, p := [2]int{scope.id, 0}, [2]int{scope.id, 1}
1066 f, d := [2]int{scope.id, 2}, [2]int{scope.id, 3}
1067 a, l := [2]int{scope.id, 4}, [2]int{scope.id, 5}
1068 c.appends(
1069 &code{op: opscope, v: [3]int{scope.id, 6, 2}},
1070 &code{op: opstore, v: v}, // def _modify(p; f):
1071 &code{op: opstore, v: p},
1072 &code{op: opstore, v: f},
1073 &code{op: oppush, v: []interface{}{}},
1074 &code{op: opstore, v: d},
1075 &code{op: oppush, v: nil},
1076 &code{op: opcall, v: [3]interface{}{funcAllocator, 0, "_allocator"}},
1077 &code{op: opstore, v: a},
1078 &code{op: opload, v: v},
1079 &code{op: opfork, v: len(c.codes) + 39}, // reduce [L1]
1080 &code{op: oppathbegin}, // path(p)
1081 &code{op: opload, v: p},
1082 &code{op: opcallpc},
1083 &code{op: opload, v: v},
1084 &code{op: oppathend},
1085 &code{op: opstore, v: p}, // as $p (.;
1086 &code{op: opforklabel, v: l}, // label $l |
1087 &code{op: opload, v: v}, //
1088 &code{op: opfork, v: len(c.codes) + 36}, // [L2]
1089 &code{op: oppop}, // (getpath($p) |
1090 &code{op: opload, v: a},
1091 &code{op: opload, v: p},
1092 &code{op: opload, v: v},
1093 &code{op: opcall, v: [3]interface{}{internalFuncs["getpath"].callback, 1, "getpath"}},
1094 &code{op: opload, v: f}, // f)
1095 &code{op: opcallpc},
1096 &code{op: opload, v: p}, // setpath($p; ...)
1097 &code{op: opload, v: v},
1098 &code{op: opcall, v: [3]interface{}{funcSetpathWithAllocator, 3, "_setpath"}},
1099 &code{op: opstore, v: v},
1100 &code{op: opload, v: v}, // ., break $l
1101 &code{op: opfork, v: len(c.codes) + 34}, // [L4]
1102 &code{op: opjump, v: len(c.codes) + 38}, // [L3]
1103 &code{op: opload, v: l}, // [L4]
1104 &code{op: opcall, v: [3]interface{}{funcBreak(""), 0, "_break"}},
1105 &code{op: opload, v: p}, // append $p to $d [L2]
1106 &code{op: opappend, v: d}, //
1107 &code{op: opbacktrack}, // ) | [L3]
1108 &code{op: oppop}, // delpaths($d); [L1]
1109 &code{op: opload, v: a},
1110 &code{op: opload, v: d},
1111 &code{op: opload, v: v},
1112 &code{op: opcall, v: [3]interface{}{funcDelpathsWithAllocator, 2, "_delpaths"}},
1113 &code{op: opret},
1114 )
1115990 }
1116991
1117992 func (c *compiler) funcBuiltins(interface{}, []interface{}) interface{} {
14711346
14721347 func (c *compiler) compileCall(name string, args []*Query) error {
14731348 fn := internalFuncs[name]
1474 var indexing int
1475 switch name {
1476 case "_index", "_slice":
1477 indexing = 1
1478 case "getpath":
1479 indexing = 0
1480 default:
1481 indexing = -1
1482 }
14831349 if err := c.compileCallInternal(
14841350 [3]interface{}{fn.callback, len(args), name},
14851351 args,
14861352 true,
1487 indexing,
1353 name == "_index" || name == "_slice",
14881354 ); err != nil {
14891355 return err
14901356 }
14951361 }
14961362
14971363 func (c *compiler) compileCallPc(fn *funcinfo, args []*Query) error {
1498 return c.compileCallInternal(fn.pc, args, false, -1)
1364 return c.compileCallInternal(fn.pc, args, false, false)
14991365 }
15001366
15011367 func (c *compiler) compileCallInternal(
1502 fn interface{}, args []*Query, internal bool, indexing int,
1503 ) error {
1368 fn interface{}, args []*Query, internal, indexing bool) error {
15041369 if len(args) == 0 {
15051370 c.append(&code{op: opcall, v: fn})
15061371 return nil
15071372 }
15081373 v := c.newVariable()
15091374 c.append(&code{op: opstore, v: v})
1510 if indexing >= 0 {
1375 if indexing {
15111376 c.append(&code{op: opexpbegin})
15121377 }
15131378 for i := len(args) - 1; i >= 0; i-- {
15461411 } else {
15471412 c.append(&code{op: oppushpc, v: pc})
15481413 }
1549 if i == indexing {
1414 if indexing && i == 1 {
15501415 if c.codes[len(c.codes)-2].op == opexpbegin {
15511416 c.codes[len(c.codes)-2] = c.codes[len(c.codes)-1]
15521417 c.codes = c.codes[:len(c.codes)-1]
15551420 }
15561421 }
15571422 }
1558 if indexing > 0 {
1423 if indexing {
15591424 c.append(&code{op: oppush, v: nil})
15601425 } else {
15611426 c.append(&code{op: opload, v: v})
15661431
15671432 func (c *compiler) append(code *code) {
15681433 c.codes = append(c.codes, code)
1569 }
1570
1571 func (c *compiler) appends(codes ...*code) {
1572 c.codes = append(c.codes, codes...)
15731434 }
15741435
15751436 func (c *compiler) lazy(f func() *code) func() {
0 golang-githubitchyny-gojq (0.12.9-1) UNRELEASED; urgency=low
1
2 * Initial release.
3 * Debianized package
4
5 -- Debian Janitor <janitor@jelmer.uk> Thu, 01 Dec 2022 11:36:30 +0000
0 Rules-Requires-Root: no
1 Standards-Version: 4.6.1.0
2 XS-Go-Import-Path: github.com/itchyny/gojq
3 Homepage: https://github.com/itchyny/gojq
4 Section: devel
5 Source: golang-githubitchyny-gojq
6 Build-Depends: debhelper-compat (= 13),
7 dh-sequence-golang,
8 golang-github-google-go-cmp-dev,
9 golang-github-itchyny-timefmt-go-dev,
10 golang-github-mattn-go-isatty-dev,
11 golang-github-mattn-go-runewidth-dev,
12 golang-github-rivo-uniseg-dev,
13 golang-go (>= 2:1.17~),
14 golang-golang-x-sys-dev,
15 golang-gopkg-yaml.v3-dev
16 Testsuite: autopkgtest-pkg-go
17 Priority: optional
18 Maintainer: Debian Janitor <janitor@jelmer.uk>
19
20 Package: golang-githubitchyny-gojq-dev
21 Architecture: all
22 Multi-Arch: foreign
23 Depends: ${misc:Depends}
24 Section: golang
0 Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
1 Upstream-Name: github.com/itchyny/gojq
2
3 Files: *
4 Copyright: Unknown
5 License: Expat
6 Comment: No explicit license found, using license(s) from:
7 LICENSE
8
9 Files: debian/*
10 Copyright: Unknown
11 License: Expat
12 Comment: No explicit license found, using license(s) from:
13 LICENSE
14
15 License: Expat
16 Comment: Add the corresponding license text here
0 #!/usr/bin/make -f
1
2 %:
3 dh $@ --buildsystem=golang
0 3.0 (quilt)
0 ---
1 Bug-Database: https://github.com/itchyny/gojq/issues
2 Bug-Submit: https://github.com/itchyny/gojq/issues/new
3 Repository: https://github.com/itchyny/gojq.git
4 Repository-Browse: https://github.com/itchyny/gojq
0 version=4
1 opts=filenamemangle=s/.*\/v(\d\S+)\.tar\.gz/gojq-$1\.tar\.gz/ https://github.com/itchyny/gojq/tags .*\/v(\d\S+)\.tar\.gz
203203 return fmt.Sprintf("[%d,%d,%d]", v[0], v[1], v[2])
204204 case [3]interface{}:
205205 return fmt.Sprintf("[%v,%v,%v]", v[0], v[1], v[2])
206 case allocator:
207 return fmt.Sprintf("%v", v)
208206 default:
209207 return Preview(v)
210208 }
8888 switch er := err.(type) {
8989 case *tryEndError:
9090 err = er.err
91 break loop
92 case *breakError:
9391 break loop
9492 case ValueError:
9593 if er, ok := er.(*exitCodeError); ok && er.halt {
307305 return xs[i].path.(string) < xs[j].path.(string)
308306 })
309307 case Iter:
308 if !env.paths.empty() && env.expdepth == 0 {
309 err = &invalidPathIterError{v}
310 break loop
311 }
310312 if w, ok := v.Next(); ok {
311313 env.push(v)
312314 env.pushfork(pc)
77 "math"
88 "math/big"
99 "net/url"
10 "reflect"
1110 "regexp"
1211 "sort"
1312 "strconv"
7069 "explode": argFunc0(funcExplode),
7170 "implode": argFunc0(funcImplode),
7271 "split": {argcount1 | argcount2, false, funcSplit},
73 "ascii_downcase": argFunc0(funcASCIIDowncase),
74 "ascii_upcase": argFunc0(funcASCIIUpcase),
7572 "tojson": argFunc0(funcToJSON),
7673 "fromjson": argFunc0(funcFromJSON),
7774 "format": argFunc1(funcFormat),
749746 return xs
750747 }
751748
752 func funcASCIIDowncase(v interface{}) interface{} {
753 s, ok := v.(string)
754 if !ok {
755 return &funcTypeError{"ascii_downcase", v}
756 }
757 return strings.Map(func(r rune) rune {
758 if 'A' <= r && r <= 'Z' {
759 return r + ('a' - 'A')
760 }
761 return r
762 }, s)
763 }
764
765 func funcASCIIUpcase(v interface{}) interface{} {
766 s, ok := v.(string)
767 if !ok {
768 return &funcTypeError{"ascii_upcase", v}
769 }
770 return strings.Map(func(r rune) rune {
771 if 'a' <= r && r <= 'z' {
772 return r - ('a' - 'A')
773 }
774 return r
775 }, s)
776 }
777
778749 func funcToJSON(v interface{}) interface{} {
779750 return jsonMarshal(v)
780751 }
835806 }
836807 }
837808
838 var csvEscaper = strings.NewReplacer(
839 `"`, `""`,
840 "\x00", `\0`,
841 )
842
843809 func funcToCSV(v interface{}) interface{} {
844810 return formatJoin("csv", v, ",", func(s string) string {
845 return `"` + csvEscaper.Replace(s) + `"`
811 return `"` + strings.ReplaceAll(s, `"`, `""`) + `"`
846812 })
847813 }
848814
851817 "\r", `\r`,
852818 "\n", `\n`,
853819 "\\", `\\`,
854 "\x00", `\0`,
855820 )
856821
857822 func funcToTSV(v interface{}) interface{} {
858823 return formatJoin("tsv", v, "\t", tsvEscaper.Replace)
859824 }
860
861 var shEscaper = strings.NewReplacer(
862 "'", `'\''`,
863 "\x00", `\0`,
864 )
865825
866826 func funcToSh(v interface{}) interface{} {
867827 if _, ok := v.([]interface{}); !ok {
868828 v = []interface{}{v}
869829 }
870830 return formatJoin("sh", v, " ", func(s string) string {
871 return "'" + shEscaper.Replace(s) + "'"
831 return "'" + strings.ReplaceAll(s, "'", `'\''`) + "'"
872832 })
873833 }
874834
14141374 return ok && !math.IsNaN(x) && !math.IsInf(x, 0) && x != 0.0
14151375 }
14161376
1417 // An `allocator` creates new maps and slices, stores the allocated addresses.
1418 // This allocator is used to reduce allocations on assignment operator (`=`),
1419 // update-assignment operator (`|=`), and the `map_values`, `del`, `delpaths`
1420 // functions.
1421 type allocator map[uintptr]struct{}
1422
1423 func funcAllocator(interface{}, []interface{}) interface{} {
1424 return allocator{}
1425 }
1426
1427 func (a allocator) allocated(v interface{}) bool {
1428 _, ok := a[reflect.ValueOf(v).Pointer()]
1429 return ok
1430 }
1431
1432 func (a allocator) makeObject(l int) map[string]interface{} {
1433 v := make(map[string]interface{}, l)
1434 if a != nil {
1435 a[reflect.ValueOf(v).Pointer()] = struct{}{}
1436 }
1437 return v
1438 }
1439
1440 func (a allocator) makeArray(l, c int) []interface{} {
1441 if c < l {
1442 c = l
1443 }
1444 v := make([]interface{}, l, c)
1445 if a != nil {
1446 a[reflect.ValueOf(v).Pointer()] = struct{}{}
1447 }
1448 return v
1449 }
1450
14511377 func funcSetpath(v, p, n interface{}) interface{} {
1452 // There is no need to use an allocator on a single update.
1453 return setpath(v, p, n, nil)
1454 }
1455
1456 // Used in compiler#compileAssign and compiler#compileModify.
1457 func funcSetpathWithAllocator(v interface{}, args []interface{}) interface{} {
1458 return setpath(v, args[0], args[1], args[2].(allocator))
1459 }
1460
1461 func setpath(v, p, n interface{}, a allocator) interface{} {
14621378 path, ok := p.([]interface{})
14631379 if !ok {
14641380 return &funcTypeError{"setpath", p}
14651381 }
14661382 var err error
1467 if v, err = update(v, path, n, a); err != nil {
1383 if v, err = update(v, path, n); err != nil {
14681384 if err, ok := err.(*funcTypeError); ok {
14691385 err.name = "setpath"
14701386 }
14741390 }
14751391
14761392 func funcDelpaths(v, p interface{}) interface{} {
1477 return delpaths(v, p, allocator{})
1478 }
1479
1480 // Used in compiler#compileAssign and compiler#compileModify.
1481 func funcDelpathsWithAllocator(v interface{}, args []interface{}) interface{} {
1482 return delpaths(v, args[0], args[1].(allocator))
1483 }
1484
1485 func delpaths(v, p interface{}, a allocator) interface{} {
14861393 paths, ok := p.([]interface{})
14871394 if !ok {
14881395 return &funcTypeError{"delpaths", p}
1489 }
1490 if len(paths) == 0 {
1491 return v
14921396 }
14931397 // Fills the paths with an empty value and then delete them. We cannot delete
14941398 // in each loop because array indices should not change. For example,
15001404 if !ok {
15011405 return &funcTypeError{"delpaths", p}
15021406 }
1503 if v, err = update(v, path, empty, a); err != nil {
1407 if v, err = update(v, path, empty); err != nil {
15041408 return err
15051409 }
15061410 }
15071411 return deleteEmpty(v)
15081412 }
15091413
1510 func update(v interface{}, path []interface{}, n interface{}, a allocator) (interface{}, error) {
1414 func update(v interface{}, path []interface{}, n interface{}) (interface{}, error) {
15111415 if len(path) == 0 {
15121416 return n, nil
15131417 }
15151419 case string:
15161420 switch v := v.(type) {
15171421 case nil:
1518 return updateObject(nil, p, path[1:], n, a)
1422 return updateObject(nil, p, path[1:], n)
15191423 case map[string]interface{}:
1520 return updateObject(v, p, path[1:], n, a)
1424 return updateObject(v, p, path[1:], n)
15211425 case struct{}:
15221426 return v, nil
15231427 default:
15271431 i, _ := toInt(p)
15281432 switch v := v.(type) {
15291433 case nil:
1530 return updateArrayIndex(nil, i, path[1:], n, a)
1434 return updateArrayIndex(nil, i, path[1:], n)
15311435 case []interface{}:
1532 return updateArrayIndex(v, i, path[1:], n, a)
1436 return updateArrayIndex(v, i, path[1:], n)
15331437 case struct{}:
15341438 return v, nil
15351439 default:
15381442 case map[string]interface{}:
15391443 switch v := v.(type) {
15401444 case nil:
1541 return updateArraySlice(nil, p, path[1:], n, a)
1445 return updateArraySlice(nil, p, path[1:], n)
15421446 case []interface{}:
1543 return updateArraySlice(v, p, path[1:], n, a)
1447 return updateArraySlice(v, p, path[1:], n)
15441448 case struct{}:
15451449 return v, nil
15461450 default:
15561460 }
15571461 }
15581462
1559 func updateObject(v map[string]interface{}, k string, path []interface{}, n interface{}, a allocator) (interface{}, error) {
1463 func updateObject(v map[string]interface{}, k string, path []interface{}, n interface{}) (interface{}, error) {
15601464 x, ok := v[k]
15611465 if !ok && n == struct{}{} {
15621466 return v, nil
15631467 }
1564 u, err := update(x, path, n, a)
1468 u, err := update(x, path, n)
15651469 if err != nil {
15661470 return nil, err
15671471 }
1568 if a.allocated(v) {
1569 v[k] = u
1570 return v, nil
1571 }
1572 w := a.makeObject(len(v) + 1)
1472 w := make(map[string]interface{}, len(v)+1)
15731473 for k, v := range v {
15741474 w[k] = v
15751475 }
15771477 return w, nil
15781478 }
15791479
1580 func updateArrayIndex(v []interface{}, i int, path []interface{}, n interface{}, a allocator) (interface{}, error) {
1480 func updateArrayIndex(v []interface{}, i int, path []interface{}, n interface{}) (interface{}, error) {
15811481 var x interface{}
15821482 if j := clampIndex(i, -1, len(v)); j < 0 {
15831483 if n == struct{}{} {
15951495 return nil, &arrayIndexTooLargeError{i}
15961496 }
15971497 }
1598 u, err := update(x, path, n, a)
1498 u, err := update(x, path, n)
15991499 if err != nil {
16001500 return nil, err
16011501 }
1602 l, c := len(v), cap(v)
1603 if a.allocated(v) {
1604 if i < c {
1605 if i >= l {
1606 v = v[:i+1]
1607 }
1608 v[i] = u
1609 return v, nil
1610 }
1611 c *= 2
1612 }
1502 l := len(v)
16131503 if i >= l {
16141504 l = i + 1
16151505 }
1616 w := a.makeArray(l, c)
1506 w := make([]interface{}, l)
16171507 copy(w, v)
16181508 w[i] = u
16191509 return w, nil
16201510 }
16211511
1622 func updateArraySlice(v []interface{}, m map[string]interface{}, path []interface{}, n interface{}, a allocator) (interface{}, error) {
1512 func updateArraySlice(v []interface{}, m map[string]interface{}, path []interface{}, n interface{}) (interface{}, error) {
16231513 s, ok := m["start"]
16241514 if !ok {
16251515 return nil, &expectedStartEndError{m}
16401530 if start == end && n == struct{}{} {
16411531 return v, nil
16421532 }
1643 u, err := update(v[start:end], path, n, a)
1533 u, err := update(v[start:end], path, n)
16441534 if err != nil {
16451535 return nil, err
16461536 }
16471537 switch u := u.(type) {
16481538 case []interface{}:
1649 var w []interface{}
1650 if len(u) == end-start && a.allocated(v) {
1651 w = v
1652 } else {
1653 w = a.makeArray(len(v)-(end-start)+len(u), 0)
1654 copy(w, v[:start])
1655 copy(w[start+len(u):], v[end:])
1656 }
1539 w := make([]interface{}, len(v)-(end-start)+len(u))
1540 copy(w, v[:start])
16571541 copy(w[start:], u)
1542 copy(w[start+len(u):], v[end:])
16581543 return w, nil
16591544 case struct{}:
1660 var w []interface{}
1661 if a.allocated(v) {
1662 w = v
1663 } else {
1664 w = a.makeArray(len(v), 0)
1665 copy(w, v)
1666 }
1545 w := make([]interface{}, len(v))
1546 copy(w, v)
16671547 for i := start; i < end; i++ {
16681548 w[i] = u
16691549 }
8787 type moduleLoaderJSON struct{}
8888
8989 func (*moduleLoaderJSON) LoadJSON(name string) (interface{}, error) {
90 if name == "module1" {
90 switch name {
91 case "module1":
9192 return []interface{}{1.0, 42, json.Number("123")}, nil
9293 }
9394 return nil, fmt.Errorf("module not found: %q", name)
670671 }
671672 }
672673
673 func TestWithIterFunctionPathIndexing(t *testing.T) {
674 func TestWithIterFunctionPath(t *testing.T) {
674675 query, err := gojq.Parse(".[f] = 1")
675676 if err != nil {
676677 t.Fatal(err)
695696 }
696697 }
697698
698 func TestWithIterFunctionPathInputValue(t *testing.T) {
699 query, err := gojq.Parse("{x: 0} | (f|.x) = 1")
700 if err != nil {
701 t.Fatal(err)
702 }
703 code, err := gojq.Compile(query,
704 gojq.WithIterFunction("f", 0, 0, func(v interface{}, _ []interface{}) gojq.Iter {
705 return gojq.NewIter(v, v, v)
706 }),
707 )
708 if err != nil {
709 t.Fatal(err)
710 }
711 iter := code.Run(nil)
712 for {
713 v, ok := iter.Next()
714 if !ok {
715 break
716 }
717 if expected := map[string]interface{}{"x": 1}; !reflect.DeepEqual(v, expected) {
718 t.Errorf("expected: %v, got: %v", expected, v)
719 }
720 }
721 }
722
723 func TestWithIterFunctionPathEmpty(t *testing.T) {
699 func TestWithIterFunctionPathError(t *testing.T) {
724700 query, err := gojq.Parse("{x: 0} | (f|.x) = 1")
725701 if err != nil {
726702 t.Fatal(err)
727703 }
728704 code, err := gojq.Compile(query,
729705 gojq.WithIterFunction("f", 0, 0, func(interface{}, []interface{}) gojq.Iter {
730 return gojq.NewIter()
731 }),
732 )
733 if err != nil {
734 t.Fatal(err)
735 }
736 iter := code.Run(nil)
737 for {
738 v, ok := iter.Next()
739 if !ok {
740 break
741 }
742 if expected := map[string]interface{}{"x": 0}; !reflect.DeepEqual(v, expected) {
743 t.Errorf("expected: %v, got: %v", expected, v)
744 }
745 }
746 }
747
748 func TestWithIterFunctionInvalidPathError(t *testing.T) {
749 query, err := gojq.Parse("{x: 0} | (f|.x) = 1")
750 if err != nil {
751 t.Fatal(err)
752 }
753 code, err := gojq.Compile(query,
754 gojq.WithIterFunction("f", 0, 0, func(interface{}, []interface{}) gojq.Iter {
755 return gojq.NewIter(map[string]interface{}{"x": 1})
706 return gojq.NewIter(map[string]interface{}{"x": 0})
756707 }),
757708 )
758709 if err != nil {
764715 t.Fatal("should emit an error but got no output")
765716 }
766717 if err, ok := v.(error); ok {
767 if expected := `invalid path against: object ({"x":1})`; err.Error() != expected {
768 t.Errorf("expected: %v, got: %v", expected, err)
769 }
770 } else {
771 t.Errorf("should emit an error but got: %v", v)
772 }
773 }
774
775 func TestWithIterFunctionPathError(t *testing.T) {
776 query, err := gojq.Parse("{x: 0} | (f|.x) = 1")
777 if err != nil {
778 t.Fatal(err)
779 }
780 code, err := gojq.Compile(query,
781 gojq.WithIterFunction("f", 0, 0, func(interface{}, []interface{}) gojq.Iter {
782 return gojq.NewIter(errors.New("error"))
783 }),
784 )
785 if err != nil {
786 t.Fatal(err)
787 }
788 iter := code.Run(nil)
789 v, ok := iter.Next()
790 if !ok {
791 t.Fatal("should emit an error but got no output")
792 }
793 if err, ok := v.(error); ok {
794 if expected := "error"; err.Error() != expected {
718 if expected := "invalid path on iterating against: gojq.Iter"; err.Error() != expected {
795719 t.Errorf("expected: %v, got: %v", expected, err)
796720 }
797721 } else {
823747 type moduleLoader2 struct{}
824748
825749 func (*moduleLoader2) LoadModule(name string) (*gojq.Query, error) {
826 if name == "module1" {
750 switch name {
751 case "module1":
827752 return gojq.Parse(`
828753 def g: def h: f * 3; h * 4;
829754 `)
33 package gojq
44
55 import __yyfmt__ "fmt"
6
7 //line parser.go.y:2
68
79 // Parse a query string, and returns the query struct.
810 //
1012 // which reports the invalid token and the byte offset in the query string. The
1113 // token is empty if the error occurred after scanning the entire query string.
1214 // The byte offset is the scanned bytes when the error occurred.
13 //
14 //line parser.go.y:2
1515 func Parse(src string) (*Query, error) {
1616 l := newLexer(src)
1717 if yyParse(l) > 0 {