diff --git a/go.mod b/go.mod index a5ab456b..957c60e8 100644 --- a/go.mod +++ b/go.mod @@ -5,22 +5,29 @@ go 1.12 require ( github.com/Eun/go-convert v0.0.0-20200421145326-bef6c56666ee github.com/Eun/go-doppelgangerreader v0.0.0-20190911075941-30f1527f16b2 - github.com/Eun/yaegi-template v1.5.5 + github.com/Eun/yaegi-template v1.5.10 github.com/aaw/maybe_tls v0.0.0-20160803104303-89c499bcc6aa + github.com/alecthomas/participle v0.4.2-0.20191220090139-9fbceec1d131 // indirect github.com/araddon/dateparse v0.0.0-20200409225146-d820a6159ab1 // indirect - github.com/dave/jennifer v1.4.0 + github.com/dave/jennifer v1.4.1 + github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 // indirect github.com/google/go-cmp v0.4.0 - github.com/gookit/color v1.2.3 - github.com/itchyny/gojq v0.10.1 + github.com/gookit/color v1.3.2 + github.com/itchyny/gojq v0.11.2 + github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 // indirect github.com/json-iterator/go v1.1.10 github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 // indirect github.com/k0kubun/pp v3.0.1+incompatible + github.com/lestrrat-go/strftime v1.0.1 // indirect github.com/lunixbochs/vtclean v1.0.0 github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.1 // indirect github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect + github.com/pbnjay/strptime v0.0.0-20140226051138-5c05b0d668c9 // indirect + github.com/pkg/errors v0.9.1 // indirect github.com/stretchr/testify v1.6.1 - github.com/tidwall/pretty v1.0.1 + github.com/tebeka/strftime v0.1.3 // indirect + github.com/tidwall/pretty v1.0.2 golang.org/x/tools v0.0.0-20201026223136-e84cfc6dd5ca golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect diff --git a/go.sum b/go.sum index 3608d64a..5f848331 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ github.com/Eun/go-doppelgangerreader v0.0.0-20190911075941-30f1527f16b2 h1:RfkLL github.com/Eun/go-doppelgangerreader v0.0.0-20190911075941-30f1527f16b2/go.mod h1:+o+i8cYK1XYOQo4ocUKNV4R9D5Y7MIAPJk2l5SEh93M= github.com/Eun/yaegi-template v1.5.5 h1:WF1wPpaBWpoX+YKHnzssgBwO9ipMI7A97iLzpSIEoX0= github.com/Eun/yaegi-template v1.5.5/go.mod h1:r9lupbIpc5/CJ7JgrjD6EFw8243cFtRsN06B+6v5hcg= +github.com/Eun/yaegi-template v1.5.10 h1:QF8IUEdFkAOOe58M6Wc+ihUfdJ92BdA1+CrCV4edyV8= +github.com/Eun/yaegi-template v1.5.10/go.mod h1:fiXVM1ETDu6jJBPgDjPbJEDX0S6TH7AyrLkX70Opyok= github.com/aaw/maybe_tls v0.0.0-20160803104303-89c499bcc6aa h1:6yJyU8MlPBB2enGJdPciPlr8P+PC0nhCFHnSHYMirZI= github.com/aaw/maybe_tls v0.0.0-20160803104303-89c499bcc6aa/go.mod h1:I0wzMZvViQzmJjxK+AtfFAnqDCkQV/+r17PO1CCSYnU= github.com/alecthomas/go-thrift v0.0.0-20170109061633-7914173639b2/go.mod h1:CxCgO+NdpMdi9SsTlGbc0W+/UNxO3I0AabOEJZ3w61w= @@ -18,6 +20,8 @@ github.com/araddon/dateparse v0.0.0-20200409225146-d820a6159ab1 h1:TEBmxO80TM04L github.com/araddon/dateparse v0.0.0-20200409225146-d820a6159ab1/go.mod h1:SLqhdZcd+dF3TEVL2RMoob5bBP5R1P1qkox+HtCBgGI= github.com/dave/jennifer v1.4.0 h1:tNJFJmLDVTLu+v05mVZ88RINa3vQqnyyWkTKWYz0CwE= github.com/dave/jennifer v1.4.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= +github.com/dave/jennifer v1.4.1 h1:XyqG6cn5RQsTj3qlWQTKlRGAyrTcsk1kUmWdZBzRjDw= +github.com/dave/jennifer v1.4.1/go.mod h1:7jEdnm+qBcxl8PC0zyp7vxcpSRnzXSt9r39tpTVGlwA= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -26,15 +30,25 @@ github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239/go.mod h1:Gdwt2ce0 github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.3 h1:x95R7cp+rSeeqAMI2knLtQ0DKlaBhv2NrtrOvafPHRo= +github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/gookit/color v1.2.3 h1:2Si0/JAEE2+1hkNYuTszu54Ti9wfp+M4JNNrknf9/D0= github.com/gookit/color v1.2.3/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg= +github.com/gookit/color v1.3.2 h1:WO8+16ZZtx+HlOb6cueziUAF8VtALZKRr/jOvuDk0X0= +github.com/gookit/color v1.3.2/go.mod h1:R3ogXq2B9rTbXoSHJ1HyUVAZ3poOJHpd9nQmyGZsfvQ= github.com/hokaccha/go-prettyjson v0.0.0-20190818114111-108c894c2c0e/go.mod h1:pFlLw2CfqZiIBOx6BuCeRLCrfxBJipTY0nIOF/VbGcI= github.com/itchyny/astgen-go v0.0.0-20200116103543-aaa595cf980e h1:PupVBrJNomt2fTXto19vW8Jh1ftn1oKxgtjSzSuLBZI= github.com/itchyny/astgen-go v0.0.0-20200116103543-aaa595cf980e/go.mod h1:9Gyr9nZoENI+woes+xm+BFhmvYmAp6bPtXD866pQH9g= +github.com/itchyny/astgen-go v0.0.0-20200815150004-12a293722290 h1:9ZAJ5+eh9dfcPsJ1CXoiE16JzsBmJm1e124eUkXAyc0= +github.com/itchyny/astgen-go v0.0.0-20200815150004-12a293722290/go.mod h1:296z3W7Xsrp2mlIY88ruDKscuvrkL6zXCNRtaYVshzw= github.com/itchyny/go-flags v1.5.0/go.mod h1:lenkYuCobuxLBAd/HGFE4LRoW8D3B6iXRQfWYJ+MNbA= github.com/itchyny/gojq v0.10.1 h1:52TnrHnzmenfqUtJ52OfjG16uDoFSu1xYmfVQ5kRMuQ= github.com/itchyny/gojq v0.10.1/go.mod h1:dJzXXNL1A+1rjDF8tDTzW5vOe4i9iIkKSH21HxV76Sw= +github.com/itchyny/gojq v0.11.2 h1:lKhMKfH7fTKMWj2Zr8az/9TliCn0TTXVc/BXfQ8Jhfc= +github.com/itchyny/gojq v0.11.2/go.mod h1:XtmtF1PxeDpwLC1jyz/xAmV78ANlP0S9LVEPsKweK0A= +github.com/itchyny/timefmt-go v0.1.1 h1:rLpnm9xxb39PEEVzO0n4IRp0q6/RmBc7Dy/rE4HrA0U= +github.com/itchyny/timefmt-go v0.1.1/go.mod h1:0osSSCQSASBJMsIZnhAaF1C2fCBTJZXrnj37mG8/c+A= github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 h1:IPJ3dvxmJ4uczJe5YQdrYB16oTJlGSC/OyZDqUk9xX4= github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869/go.mod h1:cJ6Cj7dQo+O6GJNiMx+Pa94qKj+TG8ONdKHgMNIyyag= github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= @@ -55,6 +69,8 @@ github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw= +github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= @@ -89,8 +105,12 @@ github.com/tebeka/strftime v0.1.3 h1:5HQXOqWKYRFfNyBMNVc9z5+QzuBtIXy03psIhtdJYto github.com/tebeka/strftime v0.1.3/go.mod h1:7wJm3dZlpr4l/oVK0t1HYIc4rMzQ2XJlOMIUJUJH6XQ= github.com/tidwall/pretty v1.0.1 h1:WE4RBSZ1x6McVVC8S/Md+Qse8YUv6HRObAx6ke00NY8= github.com/tidwall/pretty v1.0.1/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tidwall/pretty v1.0.2 h1:Z7S3cePv9Jwm1KwS0513MRaoUe3S01WPbLNV40pwWZU= +github.com/tidwall/pretty v1.0.2/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/traefik/yaegi v0.9.4 h1:ZyxSsvpzZTTTbvE2ODjRkOvq6kYT3dIZDqUfCZJYDtw= github.com/traefik/yaegi v0.9.4/go.mod h1:FAYnRlZyuVlEkvnkHq3bvJ1lW5be6XuwgLdkYgYG6Lk= +github.com/traefik/yaegi v0.9.7 h1:CbeKjEhy3DoSC8xC4TQF2Mhmd7u3Cjqluz1//x6Vtcs= +github.com/traefik/yaegi v0.9.7/go.mod h1:FAYnRlZyuVlEkvnkHq3bvJ1lW5be6XuwgLdkYgYG6Lk= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= diff --git a/readme_gen_test.go b/readme_gen_test.go index 2657436d..cd7a81e4 100644 --- a/readme_gen_test.go +++ b/readme_gen_test.go @@ -4,6 +4,7 @@ package hit_test import ( "encoding/base64" + "errors" "fmt" "testing" @@ -69,16 +70,19 @@ func TestReadmeCodePart5(t *testing.T) { func TestReadmeCodePart6(t *testing.T) { MustDo( Get("https://httpbin.org/get"), - Send().Custom(func(hit Hit) { + Send().Custom(func(hit Hit) error { hit.Request().Body().SetStringf("Hello %s", "World") + return nil }), - Expect().Custom(func(hit Hit) { + Expect().Custom(func(hit Hit) error { if len(hit.Response().Body().MustString()) <= 0 { - t.FailNow() + return errors.New("expected the body to be not empty") } + return nil }), - Custom(AfterExpectStep, func(Hit) { + Custom(AfterExpectStep, func(Hit) error { fmt.Println("everything done") + return nil }), ) } diff --git a/vendor/github.com/Eun/yaegi-template/codebuffer/live_iterator.go b/vendor/github.com/Eun/yaegi-template/codebuffer/live_iterator.go index 429ead0f..261bb325 100644 --- a/vendor/github.com/Eun/yaegi-template/codebuffer/live_iterator.go +++ b/vendor/github.com/Eun/yaegi-template/codebuffer/live_iterator.go @@ -125,7 +125,9 @@ func (i *liveIterator) readTextBlock() (*Part, bool, error) { if err := writeSeqBuffer(); err != nil { return nil, true, err } - return constructTextPart(contentBuffer.Bytes(), i.stripLeadingWhiteSpaces), true, nil + stripLeadingWhiteSpaces := i.stripLeadingWhiteSpaces + i.stripLeadingWhiteSpaces = false // reset strip leading whitespaces + return constructTextPart(contentBuffer.Bytes(), stripLeadingWhiteSpaces), true, nil } if r == i.startSequence[pos] { //nolint:nestif @@ -154,7 +156,9 @@ func (i *liveIterator) readTextBlock() (*Part, bool, error) { } i.inCodeBlock = true - return constructTextPart(content, i.stripLeadingWhiteSpaces), false, nil + stripLeadingWhiteSpaces := i.stripLeadingWhiteSpaces + i.stripLeadingWhiteSpaces = false // reset strip leading whitespaces + return constructTextPart(content, stripLeadingWhiteSpaces), false, nil } if err := writeSeqBuffer(); err != nil { return nil, true, err diff --git a/vendor/github.com/alecthomas/participle/.golangci.yml b/vendor/github.com/alecthomas/participle/.golangci.yml deleted file mode 100644 index d4230d51..00000000 --- a/vendor/github.com/alecthomas/participle/.golangci.yml +++ /dev/null @@ -1,47 +0,0 @@ -run: - tests: true - skip-dirs: - - _examples - -output: - print-issued-lines: false - -linters: - enable-all: true - disable: - - maligned - - megacheck - - lll - - gocyclo - - gochecknoglobals - - wsl - - whitespace - - godox - - funlen - -linters-settings: - govet: - check-shadowing: true - gocyclo: - min-complexity: 10 - dupl: - threshold: 100 - goconst: - min-len: 8 - min-occurrences: 3 - -issues: - max-per-linter: 0 - max-same: 0 - exclude-use-default: false - exclude: - # Captured by errcheck. - - '^(G104|G204):' - # Very commonly not checked. - - 'Error return value of .(.*\.Help|.*\.MarkFlagRequired|(os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*printf?|os\.(Un)?Setenv). is not checked' - - 'exported method `(.*\.MarshalJSON|.*\.UnmarshalJSON|.*\.EntityURN|.*\.GoString|.*\.Pos)` should have comment or be unexported' - - 'composite literal uses unkeyed fields' - - 'declaration of "err" shadows declaration' - - 'bad syntax for struct tag key' - - 'bad syntax for struct tag pair' - - '^ST1012' diff --git a/vendor/github.com/alecthomas/participle/COPYING b/vendor/github.com/alecthomas/participle/COPYING deleted file mode 100644 index 92dc39f7..00000000 --- a/vendor/github.com/alecthomas/participle/COPYING +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (C) 2017 Alec Thomas - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/github.com/alecthomas/participle/README.md b/vendor/github.com/alecthomas/participle/README.md deleted file mode 100644 index 7920039a..00000000 --- a/vendor/github.com/alecthomas/participle/README.md +++ /dev/null @@ -1,371 +0,0 @@ -# A dead simple parser package for Go - -[![Godoc](https://godoc.org/github.com/alecthomas/participle?status.svg)](http://godoc.org/github.com/alecthomas/participle) [![CircleCI](https://img.shields.io/circleci/project/github/alecthomas/participle.svg)](https://circleci.com/gh/alecthomas/participle) - [![Go Report Card](https://goreportcard.com/badge/github.com/alecthomas/participle)](https://goreportcard.com/report/github.com/alecthomas/participle) [![Slack chat](https://img.shields.io/static/v1?logo=slack&style=flat&label=slack&color=green&message=gophers)](https://gophers.slack.com/messages/CN9DS8YF3) - - - -1. [Introduction](#introduction) -2. [Limitations](#limitations) -3. [Tutorial](#tutorial) -4. [Overview](#overview) -5. [Annotation syntax](#annotation-syntax) -6. [Capturing](#capturing) -7. [Streaming](#streaming) -8. [Lexing](#lexing) -9. [Options](#options) -10. [Examples](#examples) -11. [Performance](#performance) -12. [Concurrency](#concurrency) -13. [Error reporting](#error-reporting) - - - - -## Introduction - -The goal of this package is to provide a simple, idiomatic and elegant way of -defining parsers in Go. - -Participle's method of defining grammars should be familiar to any Go -programmer who has used the `encoding/json` package: struct field tags define -what and how input is mapped to those same fields. This is not unusual for Go -encoders, but is unusual for a parser. - - -## Limitations - -Participle parsers are LL(k). Among other things, this means that they do not support left recursion. - -The default value of K is 1 but this can be controlled with `participle.UseLookahead(k)`. - -Left recursion must be eliminated by restructuring your grammar. - - -## Tutorial - -A [tutorial](TUTORIAL.md) is available, walking through the creation of an .ini parser. - - -## Overview - -A grammar is an annotated Go structure used to both define the parser grammar, -and be the AST output by the parser. As an example, following is the final INI -parser from the tutorial. - - ```go - type INI struct { - Properties []*Property `{ @@ }` - Sections []*Section `{ @@ }` - } - - type Section struct { - Identifier string `"[" @Ident "]"` - Properties []*Property `{ @@ }` - } - - type Property struct { - Key string `@Ident "="` - Value *Value `@@` - } - - type Value struct { - String *string ` @String` - Number *float64 `| @Float` - } - ``` - -> **Note:** Participle also supports named struct tags (eg. Hello string `parser:"@Ident"`). - -A parser is constructed from a grammar and a lexer: - -```go -parser, err := participle.Build(&INI{}) -``` - -Once constructed, the parser is applied to input to produce an AST: - -```go -ast := &INI{} -err := parser.ParseString("size = 10", ast) -// ast == &INI{ -// Properties: []*Property{ -// {Key: "size", Value: &Value{Number: &10}}, -// }, -// } -``` - - -## Annotation syntax - -- `@` Capture expression into the field. -- `@@` Recursively capture using the fields own type. -- `` Match named lexer token. -- `( ... )` Group. -- `"..."` Match the literal (note that the lexer must emit tokens matching this literal exactly). -- `"...":` Match the literal, specifying the exact lexer token type to match. -- ` ...` Match expressions. -- ` | ` Match one of the alternatives. - -The following modifiers can be used after any expression: - -- `*` Expression can match zero or more times. -- `+` Expression must match one or more times. -- `?` Expression can match zero or once. -- `!` Require a non-empty match (this is useful with a sequence of optional matches eg. `("a"? "b"? "c"?)!`). - -Supported but deprecated: -- `{ ... }` Match 0 or more times (**DEPRECATED** - prefer `( ... )*`). -- `[ ... ]` Optional (**DEPRECATED** - prefer `( ... )?`). - -Notes: - -- Each struct is a single production, with each field applied in sequence. -- `@` is the mechanism for capturing matches into the field. -- if a struct field is not keyed with "parser", the entire struct tag - will be used as the grammar fragment. This allows the grammar syntax to remain - clear and simple to maintain. - - -## Capturing - -Prefixing any expression in the grammar with `@` will capture matching values -for that expression into the corresponding field. - -For example: - -```go -// The grammar definition. -type Grammar struct { - Hello string `@Ident` -} - -// The source text to parse. -source := "world" - -// After parsing, the resulting AST. -result == &Grammar{ - Hello: "world", -} -``` - -For slice and string fields, each instance of `@` will accumulate into the -field (including repeated patterns). Accumulation into other types is not -supported. - -A successful capture match into a boolean field will set the field to true. - -For integer and floating point types, a successful capture will be parsed -with `strconv.ParseInt()` and `strconv.ParseBool()` respectively. - -Custom control of how values are captured into fields can be achieved by a -field type implementing the `Capture` interface (`Capture(values []string) -error`). - - -## Streaming - -Participle supports streaming parsing. Simply pass a channel of your grammar into -`Parse*()`. The grammar will be repeatedly parsed and sent to the channel. Note that -the `Parse*()` call will not return until parsing completes, so it should generally be -started in a goroutine. - -```go -type token struct { - Str string ` @Ident` - Num int `| @Int` -} - -parser, err := participle.Build(&token{}) - -tokens := make(chan *token, 128) -err := parser.ParseString(`hello 10 11 12 world`, tokens) -for token := range tokens { - fmt.Printf("%#v\n", token) -} -``` - - -## Lexing - -Participle operates on tokens and thus relies on a lexer to convert character -streams to tokens. - -Four lexers are provided, varying in speed and flexibility. Configure your parser with a lexer -via `participle.Lexer()`. - -The best combination of speed, flexibility and usability is `lexer/regex.New()`. - -Ordered by speed they are: - -1. `lexer.DefaultDefinition` is based on the - [text/scanner](https://golang.org/pkg/text/scanner/) package and only allows - tokens provided by that package. This is the default lexer. -2. `lexer.Regexp()` (legacy) maps regular expression named subgroups to lexer symbols. -3. `lexer/regex.New()` is a more readable regex lexer, with each rule in the form ` = `. -4. `lexer/ebnf.New()` is a lexer based on the Go EBNF package. It has a large potential for optimisation - through code generation, but that is not implemented yet. - -To use your own Lexer you will need to implement two interfaces: -[Definition](https://godoc.org/github.com/alecthomas/participle/lexer#Definition) -and [Lexer](https://godoc.org/github.com/alecthomas/participle/lexer#Lexer). - - -## Options - -The Parser's behaviour can be configured via [Options](https://godoc.org/github.com/alecthomas/participle#Option). - - -## Examples - -There are several [examples](https://github.com/alecthomas/participle/tree/master/_examples) included: - -Example | Description ---------|--------------- -[BASIC](https://github.com/alecthomas/participle/tree/master/_examples/basic) | A lexer, parser and interpreter for a [rudimentary dialect](https://caml.inria.fr/pub/docs/oreilly-book/html/book-ora058.html) of BASIC. -[EBNF](https://github.com/alecthomas/participle/tree/master/_examples/ebnf) | Parser for the form of EBNF used by Go. -[Expr](https://github.com/alecthomas/participle/tree/master/_examples/expr) | A basic mathematical expression parser and evaluator. -[GraphQL](https://github.com/alecthomas/participle/tree/master/_examples/graphql) | Lexer+parser for GraphQL schemas -[HCL](https://github.com/alecthomas/participle/tree/master/_examples/hcl) | A parser for the [HashiCorp Configuration Language](https://github.com/hashicorp/hcl). -[INI](https://github.com/alecthomas/participle/tree/master/_examples/ini) | An INI file parser. -[Protobuf](https://github.com/alecthomas/participle/tree/master/_examples/protobuf) | A full [Protobuf](https://developers.google.com/protocol-buffers/) version 2 and 3 parser. -[SQL](https://github.com/alecthomas/participle/tree/master/_examples/sql) | A *very* rudimentary SQL SELECT parser. -[Thrift](https://github.com/alecthomas/participle/tree/master/_examples/thrift) | A full [Thrift](https://thrift.apache.org/docs/idl) parser. -[TOML](https://github.com/alecthomas/participle/blob/master/_examples/toml/main.go) | A [TOML](https://github.com/toml-lang/toml) parser. - -Included below is a full GraphQL lexer and parser: - -```go -package main - -import ( - "os" - - "github.com/alecthomas/kong" - "github.com/alecthomas/repr" - - "github.com/alecthomas/participle" - "github.com/alecthomas/participle/lexer" - "github.com/alecthomas/participle/lexer/ebnf" -) - -type File struct { - Entries []*Entry `@@*` -} - -type Entry struct { - Type *Type ` @@` - Schema *Schema `| @@` - Enum *Enum `| @@` - Scalar string `| "scalar" @Ident` -} - -type Enum struct { - Name string `"enum" @Ident` - Cases []string `"{" @Ident* "}"` -} - -type Schema struct { - Fields []*Field `"schema" "{" @@* "}"` -} - -type Type struct { - Name string `"type" @Ident` - Implements string `("implements" @Ident)?` - Fields []*Field `"{" @@* "}"` -} - -type Field struct { - Name string `@Ident` - Arguments []*Argument `("(" (@@ ("," @@)*)? ")")?` - Type *TypeRef `":" @@` - Annotation string `("@" @Ident)?` -} - -type Argument struct { - Name string `@Ident` - Type *TypeRef `":" @@` - Default *Value `("=" @@)?` -} - -type TypeRef struct { - Array *TypeRef `( "[" @@ "]"` - Type string ` | @Ident )` - NonNullable bool `@"!"?` -} - -type Value struct { - Symbol string `@Ident` -} - -var ( - graphQLLexer = lexer.Must(ebnf.New(` - Comment = ("#" | "//") { "\u0000"…"\uffff"-"\n" } . - Ident = (alpha | "_") { "_" | alpha | digit } . - Number = ("." | digit) {"." | digit} . - Whitespace = " " | "\t" | "\n" | "\r" . - Punct = "!"…"/" | ":"…"@" | "["…`+"\"`\""+` | "{"…"~" . - - alpha = "a"…"z" | "A"…"Z" . - digit = "0"…"9" . -`)) - - parser = participle.MustBuild(&File{}, - participle.Lexer(graphQLLexer), - participle.Elide("Comment", "Whitespace"), - ) - - cli struct { - Files []string `arg:"" type:"existingfile" required:"" help:"GraphQL schema files to parse."` - } -) - -func main() { - ctx := kong.Parse(&cli) - for _, file := range cli.Files { - ast := &File{} - r, err := os.Open(file) - ctx.FatalIfErrorf(err) - err = parser.Parse(r, ast) - r.Close() - repr.Println(ast) - ctx.FatalIfErrorf(err) - } -} - -``` - - -## Performance - -One of the included examples is a complete Thrift parser -(shell-style comments are not supported). This gives -a convenient baseline for comparing to the PEG based -[pigeon](https://github.com/PuerkitoBio/pigeon), which is the parser used by -[go-thrift](https://github.com/samuel/go-thrift). Additionally, the pigeon -parser is utilising a generated parser, while the participle parser is built at -run time. - -You can run the benchmarks yourself, but here's the output on my machine: - - BenchmarkParticipleThrift-4 10000 221818 ns/op 48880 B/op 1240 allocs/op - BenchmarkGoThriftParser-4 2000 804709 ns/op 170301 B/op 3086 allocs/op - -On a real life codebase of 47K lines of Thrift, Participle takes 200ms and go- -thrift takes 630ms, which aligns quite closely with the benchmarks. - - -## Concurrency - -A compiled `Parser` instance can be used concurrently. A `LexerDefinition` can be used concurrently. A `Lexer` instance cannot be used concurrently. - - -## Error reporting - -There are a few areas where Participle can provide useful feedback to users of your parser. - -1. Errors returned by [Parser.Parse()](https://godoc.org/github.com/alecthomas/participle#Parser.Parse) will be of type [Error](https://godoc.org/github.com/alecthomas/participle#Error). This will contain positional information where available. If the source `io.Reader` includes a `Name() string` method (as `os.File` does), the filename will be included. -2. Participle will make a best effort to return as much of the AST up to the error location as possible. -3. Any node in the AST containing a field `Pos lexer.Position` will be automatically populated with the starting location of the first matching token. - -These related pieces of information can be combined to provide fairly comprehensive error reporting. diff --git a/vendor/github.com/alecthomas/participle/TUTORIAL.md b/vendor/github.com/alecthomas/participle/TUTORIAL.md deleted file mode 100644 index b2059507..00000000 --- a/vendor/github.com/alecthomas/participle/TUTORIAL.md +++ /dev/null @@ -1,255 +0,0 @@ -# Participle parser tutorial - - - -1. [Introduction](#introduction) -1. [The complete grammar](#the-complete-grammar) -1. [Root of the .ini AST \(structure, fields\)](#root-of-the-ini-ast-structure-fields) -1. [.ini properties \(named tokens, capturing, literals\)](#ini-properties-named-tokens-capturing-literals) -1. [.ini property values \(alternates, recursive structs, sequences\)](#ini-property-values-alternates-recursive-structs-sequences) -1. [Complete, but limited, .ini grammar \(top-level properties only\)](#complete-but-limited-ini-grammar-top-level-properties-only) -1. [Extending our grammar to support sections](#extending-our-grammar-to-support-sections) -1. [\(Optional\) Source positional information](#optional-source-positional-information) -1. [Parsing using our grammar](#parsing-using-our-grammar) - - - -## Introduction - -Writing a parser in Participle typically involves starting from the "root" of -the AST, annotating fields with the grammar, then recursively expanding until -it is complete. The AST is expressed via Go data types and the grammar is -expressed through struct field tags, as a form of EBNF. - -The parser we're going to create for this tutorial parses .ini files -like this: - -```ini -age = 21 -name = "Bob Smith" - -[address] -city = "Beverly Hills" -postal_code = 90210 -``` - -## The complete grammar - -I think it's useful to see the complete grammar first, to see what we're -working towards. Read on below for details. - - ```go - type INI struct { - Properties []*Property `@@*` - Sections []*Section `@@*` - } - - type Section struct { - Identifier string `"[" @Ident "]"` - Properties []*Property `@@*` - } - - type Property struct { - Key string `@Ident "="` - Value *Value `@@` - } - - type Value struct { - String *string ` @String` - Number *float64 `| @Float` - } - ``` - -## Root of the .ini AST (structure, fields) - -The first step is to create a root struct for our grammar. In the case of our -.ini parser, this struct will contain a sequence of properties: - -```go -type INI struct { - Properties []*Property -} - -type Property struct { -} -``` - -## .ini properties (named tokens, capturing, literals) - -Each property in an .ini file has an identifier key: - -```go -type Property struct { - Key string -} -``` - -The default lexer tokenises Go source code, and includes an `Ident` token type -that matches identifiers. To match this token we simply use the token type -name: - -```go -type Property struct { - Key string `Ident` -} -``` - -This will *match* identifiers, but not *capture* them into the `Key` field. To -capture input tokens into AST fields, prefix any grammar node with `@`: - -```go -type Property struct { - Key string `@Ident` -} -``` - -In .ini files, each key is separated from its value with a literal `=`. To -match a literal, enclose the literal in double quotes: - -```go -type Property struct { - Key string `@Ident "="` -} -``` - -> Note: literals in the grammar must match tokens from the lexer *exactly*. In -> this example if the lexer does not output `=` as a distinct token the -> grammar will not match. - -## .ini property values (alternates, recursive structs, sequences) - -For the purposes of our example we are only going to support quoted string -and numeric property values. As each value can be *either* a string or a float -we'll need something akin to a sum type. Go's type system cannot express this -directly, so we'll use the common approach of making each element a pointer. -The selected "case" will *not* be nil. - -```go -type Value struct { - String *string - Number *float64 -} -``` - -> Note: Participle will hydrate pointers as necessary. - -To express matching a set of alternatives we use the `|` operator: - -```go -type Value struct { - String *string ` @String` - Number *float64 `| @Float` -} -``` - -> Note: the grammar can cross fields. - -Next, we'll match values and capture them into the `Property`. To recursively -capture structs use `@@` (capture self): - -```go -type Property struct { - Key string `@Ident "="` - Value *Value `@@` -} -``` - -Now that we can parse a `Property` we need to go back to the root of the -grammar. We want to parse 0 or more properties. To do this, we use `*`. -Participle will accumulate each match into the slice until matching fails, -then move to the next node in the grammar. - -```go -type INI struct { - Properties []*Property `@@*` -} -``` - -> Note: tokens can also be accumulated into strings, appending each match. - -## Complete, but limited, .ini grammar (top-level properties only) - -We now have a functional, but limited, .ini parser! - -```go -type INI struct { - Properties []*Property `@@*` -} - -type Property struct { - Key string `@Ident "="` - Value *Value `@@` -} - -type Value struct { - String *string ` @String` - Number *float64 `| @Float` -} -``` - -## Extending our grammar to support sections - -Adding support for sections is simply a matter of utilising the constructs -we've just learnt. A section consists of a header identifier, and a sequence -of properties: - -```go -type Section struct { - Identifier string `"[" @Ident "]"` - Properties []*Property `@@*` -} -``` - -Simple! - -Now we just add a sequence of `Section`s to our root node: - -```go -type INI struct { - Properties []*Property `@@*` - Sections []*Section `@@*` -} -``` - -And we're done! - -## (Optional) Source positional information - -If a grammar node includes a field with the name `Pos` and type `lexer.Position`, it will be automatically populated by positional information. eg. - -```go -type Value struct { - Pos lexer.Position - String *string ` @String` - Number *float64 `| @Float` -} -``` - -This is useful for error reporting. - -## Parsing using our grammar - -To parse with this grammar we first construct the parser (we'll use the -default lexer for now): - -```go -parser, err := participle.Build(&INI{}) -``` - -Then create a root node and parse into it with `parser.Parse{,String,Bytes}()`: - -```go -ini := &INI{} -err = parser.ParseString(` -age = 21 -name = "Bob Smith" - -[address] -city = "Beverly Hills" -postal_code = 90210 -`, ini) -``` - -You can find the full example [here](_examples/ini/main.go), alongside -other examples including an SQL `SELECT` parser and a full -[Thrift](https://thrift.apache.org/) parser. diff --git a/vendor/github.com/alecthomas/participle/api.go b/vendor/github.com/alecthomas/participle/api.go deleted file mode 100644 index bb803595..00000000 --- a/vendor/github.com/alecthomas/participle/api.go +++ /dev/null @@ -1,19 +0,0 @@ -package participle - -import ( - "github.com/alecthomas/participle/lexer" -) - -// Capture can be implemented by fields in order to transform captured tokens into field values. -type Capture interface { - Capture(values []string) error -} - -// The Parseable interface can be implemented by any element in the grammar to provide custom parsing. -type Parseable interface { - // Parse into the receiver. - // - // Should return NextMatch if no tokens matched and parsing should continue. - // Nil should be returned if parsing was successful. - Parse(lex *lexer.PeekingLexer) error -} diff --git a/vendor/github.com/alecthomas/participle/context.go b/vendor/github.com/alecthomas/participle/context.go deleted file mode 100644 index 9d40fb33..00000000 --- a/vendor/github.com/alecthomas/participle/context.go +++ /dev/null @@ -1,91 +0,0 @@ -package participle - -import ( - "reflect" - - "github.com/alecthomas/participle/lexer" -) - -type contextFieldSet struct { - pos lexer.Position - strct reflect.Value - field structLexerField - fieldValue []reflect.Value -} - -// Context for a single parse. -type parseContext struct { - *lexer.PeekingLexer - deepestError error - deepestErrorDepth int - lookahead int - caseInsensitive map[rune]bool - apply []*contextFieldSet - allowTrailing bool -} - -func newParseContext(lex *lexer.PeekingLexer, lookahead int, caseInsensitive map[rune]bool) *parseContext { - return &parseContext{ - PeekingLexer: lex, - caseInsensitive: caseInsensitive, - lookahead: lookahead, - } -} - -func (p *parseContext) DeepestError(err error) error { - if p.PeekingLexer.Cursor() >= p.deepestErrorDepth { - return err - } - if p.deepestError != nil { - return p.deepestError - } - return err -} - -// Defer adds a function to be applied once a branch has been picked. -func (p *parseContext) Defer(pos lexer.Position, strct reflect.Value, field structLexerField, fieldValue []reflect.Value) { - p.apply = append(p.apply, &contextFieldSet{pos, strct, field, fieldValue}) -} - -// Apply deferred functions. -func (p *parseContext) Apply() error { - for _, apply := range p.apply { - if err := setField(apply.pos, apply.strct, apply.field, apply.fieldValue); err != nil { - return err - } - } - p.apply = nil - return nil -} - -// Branch accepts the branch as the correct branch. -func (p *parseContext) Accept(branch *parseContext) { - p.apply = append(p.apply, branch.apply...) - p.PeekingLexer = branch.PeekingLexer -} - -// Branch starts a new lookahead branch. -func (p *parseContext) Branch() *parseContext { - branch := &parseContext{} - *branch = *p - branch.apply = nil - branch.PeekingLexer = p.PeekingLexer.Clone() - return branch -} - -// Stop returns true if parsing should terminate after the given "branch" failed to match. -// -// Additionally, "err" should be the branch error, if any. This will be tracked to -// aid in error reporting under the assumption that the deepest occurring error is more -// useful than errors further up. -func (p *parseContext) Stop(err error, branch *parseContext) bool { - if branch.PeekingLexer.Cursor() >= p.deepestErrorDepth { - p.deepestError = err - p.deepestErrorDepth = branch.PeekingLexer.Cursor() - } - if branch.PeekingLexer.Cursor() > p.PeekingLexer.Cursor()+p.lookahead { - p.Accept(branch) - return true - } - return false -} diff --git a/vendor/github.com/alecthomas/participle/doc.go b/vendor/github.com/alecthomas/participle/doc.go deleted file mode 100644 index 4e0b73cb..00000000 --- a/vendor/github.com/alecthomas/participle/doc.go +++ /dev/null @@ -1,73 +0,0 @@ -// Package participle constructs parsers from definitions in struct tags and parses directly into -// those structs. The approach is philosophically similar to how other marshallers work in Go, -// "unmarshalling" an instance of a grammar into a struct. -// -// The supported annotation syntax is: -// -// - `@` Capture expression into the field. -// - `@@` Recursively capture using the fields own type. -// - `` Match named lexer token. -// - `( ... )` Group. -// - `"..."` Match the literal (note that the lexer must emit tokens matching this literal exactly). -// - `"...":` Match the literal, specifying the exact lexer token type to match. -// - ` ...` Match expressions. -// - ` | ` Match one of the alternatives. -// -// The following modifiers can be used after any expression: -// -// - `*` Expression can match zero or more times. -// - `+` Expression must match one or more times. -// - `?` Expression can match zero or once. -// - `!` Require a non-empty match (this is useful with a sequence of optional matches eg. `("a"? "b"? "c"?)!`). -// -// Supported but deprecated: -// -// - `{ ... }` Match 0 or more times (**DEPRECATED** - prefer `( ... )*`). -// - `[ ... ]` Optional (**DEPRECATED** - prefer `( ... )?`). -// -// Here's an example of an EBNF grammar. -// -// type Group struct { -// Expression *Expression `"(" @@ ")"` -// } -// -// type Option struct { -// Expression *Expression `"[" @@ "]"` -// } -// -// type Repetition struct { -// Expression *Expression `"{" @@ "}"` -// } -// -// type Literal struct { -// Start string `@String` // lexer.Lexer token "String" -// End string `("…" @String)?` -// } -// -// type Term struct { -// Name string ` @Ident` -// Literal *Literal `| @@` -// Group *Group `| @@` -// Option *Option `| @@` -// Repetition *Repetition `| @@` -// } -// -// type Sequence struct { -// Terms []*Term `@@+` -// } -// -// type Expression struct { -// Alternatives []*Sequence `@@ ("|" @@)*` -// } -// -// type Expressions []*Expression -// -// type Production struct { -// Name string `@Ident "="` -// Expressions Expressions `@@+ "."` -// } -// -// type EBNF struct { -// Productions []*Production `@@*` -// } -package participle diff --git a/vendor/github.com/alecthomas/participle/error.go b/vendor/github.com/alecthomas/participle/error.go deleted file mode 100644 index e8617c4e..00000000 --- a/vendor/github.com/alecthomas/participle/error.go +++ /dev/null @@ -1,58 +0,0 @@ -package participle - -import ( - "fmt" - - "github.com/alecthomas/participle/lexer" -) - -// Error represents an error while parsing. -// -// The error will contain positional information if available. -type Error interface { - error - // Unadorned message. - Message() string - // Position error occurred. - Position() lexer.Position -} - -// UnexpectedTokenError is returned by Parse when an unexpected token is encountered. -// -// This is useful for composing parsers in order to detect when a sub-parser has terminated. -type UnexpectedTokenError struct{ lexer.Token } - -func (u UnexpectedTokenError) Error() string { - return lexer.FormatError(u.Pos, u.Message()) -} - -func (u UnexpectedTokenError) Message() string { // nolint: golint - return fmt.Sprintf("unexpected token %q", u.Value) -} -func (u UnexpectedTokenError) Position() lexer.Position { return u.Pos } // nolint: golint - -type parseError struct { - Message string - Pos lexer.Position -} - -func (p *parseError) Position() lexer.Position { return p.Pos } - -// AnnotateError wraps an existing error with a position. -// -// If the existing error is a lexer.Error or participle.Error it will be returned unmodified. -func AnnotateError(pos lexer.Position, err error) error { - if perr, ok := err.(Error); ok { - return perr - } - return &parseError{Message: err.Error(), Pos: pos} -} - -// Errorf creats a new Error at the given position. -func Errorf(pos lexer.Position, format string, args ...interface{}) error { - return &parseError{Message: fmt.Sprintf(format, args...), Pos: pos} -} - -func (p *parseError) Error() string { - return lexer.FormatError(p.Pos, p.Message) -} diff --git a/vendor/github.com/alecthomas/participle/go.mod b/vendor/github.com/alecthomas/participle/go.mod deleted file mode 100644 index 08326040..00000000 --- a/vendor/github.com/alecthomas/participle/go.mod +++ /dev/null @@ -1,13 +0,0 @@ -module github.com/alecthomas/participle - -require ( - github.com/alecthomas/go-thrift v0.0.0-20170109061633-7914173639b2 - github.com/alecthomas/kong v0.2.1 - github.com/alecthomas/repr v0.0.0-20181024024818-d37bc2a10ba1 - github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect - github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect - github.com/stretchr/testify v1.4.0 - gopkg.in/alecthomas/kingpin.v2 v2.2.6 -) - -go 1.13 diff --git a/vendor/github.com/alecthomas/participle/go.sum b/vendor/github.com/alecthomas/participle/go.sum deleted file mode 100644 index dec2a15a..00000000 --- a/vendor/github.com/alecthomas/participle/go.sum +++ /dev/null @@ -1,28 +0,0 @@ -github.com/alecthomas/go-thrift v0.0.0-20170109061633-7914173639b2 h1:gKv6LPDhF/G3cNribA+kZtNPiPpKabZGLhcJuEtp3ig= -github.com/alecthomas/go-thrift v0.0.0-20170109061633-7914173639b2/go.mod h1:CxCgO+NdpMdi9SsTlGbc0W+/UNxO3I0AabOEJZ3w61w= -github.com/alecthomas/kong v0.2.1 h1:V1tLBhyQBC4rsbXbcOvm3GBaytJSwRNX69fp1WJxbqQ= -github.com/alecthomas/kong v0.2.1/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI= -github.com/alecthomas/repr v0.0.0-20181024024818-d37bc2a10ba1 h1:GDQdwm/gAcJcLAKQQZGOJ4knlw+7rfEQQcmwTbt4p5E= -github.com/alecthomas/repr v0.0.0-20181024024818-d37bc2a10ba1/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/alecthomas/participle/grammar.go b/vendor/github.com/alecthomas/participle/grammar.go deleted file mode 100644 index 3a3b42a4..00000000 --- a/vendor/github.com/alecthomas/participle/grammar.go +++ /dev/null @@ -1,326 +0,0 @@ -package participle - -import ( - "fmt" - "reflect" - "text/scanner" - - "github.com/alecthomas/participle/lexer" -) - -type generatorContext struct { - lexer.Definition - typeNodes map[reflect.Type]node - symbolsToIDs map[rune]string -} - -func newGeneratorContext(lex lexer.Definition) *generatorContext { - return &generatorContext{ - Definition: lex, - typeNodes: map[reflect.Type]node{}, - symbolsToIDs: lexer.SymbolsByRune(lex), - } -} - -// Takes a type and builds a tree of nodes out of it. -func (g *generatorContext) parseType(t reflect.Type) (_ node, returnedError error) { - t = indirectType(t) - if n, ok := g.typeNodes[t]; ok { - return n, nil - } - if t.Implements(parseableType) { - return &parseable{t.Elem()}, nil - } - if reflect.PtrTo(t).Implements(parseableType) { - return &parseable{t}, nil - } - switch t.Kind() { - case reflect.Slice, reflect.Ptr: - t = indirectType(t.Elem()) - if t.Kind() != reflect.Struct { - return nil, fmt.Errorf("expected a struct but got %T", t) - } - fallthrough - - case reflect.Struct: - slexer, err := lexStruct(t) - if err != nil { - return nil, err - } - out := &strct{typ: t} - g.typeNodes[t] = out // Ensure we avoid infinite recursion. - if slexer.NumField() == 0 { - return nil, fmt.Errorf("can not parse into empty struct %s", t) - } - defer decorate(&returnedError, func() string { return slexer.Field().Name }) - e, err := g.parseDisjunction(slexer) - if err != nil { - return nil, err - } - if e == nil { - return nil, fmt.Errorf("no grammar found in %s", t) - } - if token, _ := slexer.Peek(); !token.EOF() { - return nil, fmt.Errorf("unexpected input %q", token.Value) - } - out.expr = e - return out, nil - } - return nil, fmt.Errorf("%s should be a struct or should implement the Parseable interface", t) -} - -func (g *generatorContext) parseDisjunction(slexer *structLexer) (node, error) { - out := &disjunction{} - for { - n, err := g.parseSequence(slexer) - if err != nil { - return nil, err - } - if n == nil { - return nil, fmt.Errorf("alternative expression %d cannot be empty", len(out.nodes)+1) - } - out.nodes = append(out.nodes, n) - if token, _ := slexer.Peek(); token.Type != '|' { - break - } - _, err = slexer.Next() // | - if err != nil { - return nil, err - } - } - if len(out.nodes) == 1 { - return out.nodes[0], nil - } - return out, nil -} - -func (g *generatorContext) parseSequence(slexer *structLexer) (node, error) { - head := &sequence{} - cursor := head -loop: - for { - if token, err := slexer.Peek(); err != nil { - return nil, err - } else if token.Type == lexer.EOF { - break loop - } - term, err := g.parseTerm(slexer) - if err != nil { - return nil, err - } - if term == nil { - break loop - } - if cursor.node == nil { - cursor.head = true - cursor.node = term - } else { - cursor.next = &sequence{node: term} - cursor = cursor.next - } - } - if head.node == nil { - return nil, nil - } - if head.next == nil { - return head.node, nil - } - return head, nil -} - -func (g *generatorContext) parseTermNoModifiers(slexer *structLexer) (node, error) { - t, err := slexer.Peek() - if err != nil { - return nil, err - } - var out node - switch t.Type { - case '@': - out, err = g.parseCapture(slexer) - case scanner.String, scanner.RawString, scanner.Char: - out, err = g.parseLiteral(slexer) - case '[': - return g.parseOptional(slexer) - case '{': - return g.parseRepetition(slexer) - case '(': - out, err = g.parseGroup(slexer) - case scanner.Ident: - out, err = g.parseReference(slexer) - case lexer.EOF: - _, _ = slexer.Next() - return nil, nil - default: - return nil, nil - } - return out, err -} - -func (g *generatorContext) parseTerm(slexer *structLexer) (node, error) { - out, err := g.parseTermNoModifiers(slexer) - if err != nil { - return nil, err - } - return g.parseModifier(slexer, out) -} - -// Parse modifiers: ?, *, + and/or ! -func (g *generatorContext) parseModifier(slexer *structLexer, expr node) (node, error) { - out := &group{expr: expr} - t, err := slexer.Peek() - if err != nil { - return nil, err - } - switch t.Type { - case '!': - out.mode = groupMatchNonEmpty - case '+': - out.mode = groupMatchOneOrMore - case '*': - out.mode = groupMatchZeroOrMore - case '?': - out.mode = groupMatchZeroOrOne - default: - return expr, nil - } - _, _ = slexer.Next() - return out, nil -} - -// @ captures into the current field. -func (g *generatorContext) parseCapture(slexer *structLexer) (node, error) { - _, _ = slexer.Next() - token, err := slexer.Peek() - if err != nil { - return nil, err - } - field := slexer.Field() - if token.Type == '@' { - _, _ = slexer.Next() - n, err := g.parseType(field.Type) - if err != nil { - return nil, err - } - return &capture{field, n}, nil - } - if indirectType(field.Type).Kind() == reflect.Struct && !field.Type.Implements(captureType) { - return nil, fmt.Errorf("structs can only be parsed with @@ or by implementing the Capture interface") - } - n, err := g.parseTermNoModifiers(slexer) - if err != nil { - return nil, err - } - return &capture{field, n}, nil -} - -// A reference in the form refers to a named token from the lexer. -func (g *generatorContext) parseReference(slexer *structLexer) (node, error) { // nolint: interfacer - token, err := slexer.Next() - if err != nil { - return nil, err - } - if token.Type != scanner.Ident { - return nil, fmt.Errorf("expected identifier but got %q", token) - } - typ, ok := g.Symbols()[token.Value] - if !ok { - return nil, fmt.Errorf("unknown token type %q", token) - } - return &reference{typ: typ, identifier: token.Value}, nil -} - -// [ ] optionally matches . -func (g *generatorContext) parseOptional(slexer *structLexer) (node, error) { - _, _ = slexer.Next() // [ - disj, err := g.parseDisjunction(slexer) - if err != nil { - return nil, err - } - n := &group{expr: disj, mode: groupMatchZeroOrOne} - next, err := slexer.Next() - if err != nil { - return nil, err - } - if next.Type != ']' { - return nil, fmt.Errorf("expected ] but got %q", next) - } - return n, nil -} - -// { } matches 0 or more repititions of -func (g *generatorContext) parseRepetition(slexer *structLexer) (node, error) { - _, _ = slexer.Next() // { - disj, err := g.parseDisjunction(slexer) - if err != nil { - return nil, err - } - n := &group{expr: disj, mode: groupMatchZeroOrMore} - next, err := slexer.Next() - if err != nil { - return nil, err - } - if next.Type != '}' { - return nil, fmt.Errorf("expected } but got %q", next) - } - return n, nil -} - -// ( ) groups a sub-expression -func (g *generatorContext) parseGroup(slexer *structLexer) (node, error) { - _, _ = slexer.Next() // ( - disj, err := g.parseDisjunction(slexer) - if err != nil { - return nil, err - } - next, err := slexer.Next() // ) - if err != nil { - return nil, err - } - if next.Type != ')' { - return nil, fmt.Errorf("expected ) but got %q", next) - } - return &group{expr: disj}, nil -} - -// A literal string. -// -// Note that for this to match, the tokeniser must be able to produce this string. For example, -// if the tokeniser only produces individual characters but the literal is "hello", or vice versa. -func (g *generatorContext) parseLiteral(lex *structLexer) (node, error) { // nolint: interfacer - token, err := lex.Next() - if err != nil { - return nil, err - } - if token.Type != scanner.String && token.Type != scanner.RawString && token.Type != scanner.Char { - return nil, fmt.Errorf("expected quoted string but got %q", token) - } - s := token.Value - t := rune(-1) - token, err = lex.Peek() - if err != nil { - return nil, err - } - if token.Value == ":" && (token.Type == scanner.Char || token.Type == ':') { - _, _ = lex.Next() - token, err = lex.Next() - if err != nil { - return nil, err - } - if token.Type != scanner.Ident { - return nil, fmt.Errorf("expected identifier for literal type constraint but got %q", token) - } - var ok bool - t, ok = g.Symbols()[token.Value] - if !ok { - return nil, fmt.Errorf("unknown token type %q in literal type constraint", token) - } - } - return &literal{s: s, t: t, tt: g.symbolsToIDs[t]}, nil -} - -func indirectType(t reflect.Type) reflect.Type { - if t.Kind() == reflect.Ptr || t.Kind() == reflect.Slice { - return indirectType(t.Elem()) - } - return t -} diff --git a/vendor/github.com/alecthomas/participle/lexer/doc.go b/vendor/github.com/alecthomas/participle/lexer/doc.go deleted file mode 100644 index d0fc0108..00000000 --- a/vendor/github.com/alecthomas/participle/lexer/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -// Package lexer defines interfaces and implementations used by Participle to perform lexing. -// -// The primary interfaces are Definition and Lexer. There are three implementations of these -// interfaces: -// -// TextScannerLexer is based on text/scanner. This is the fastest, but least flexible, in that -// tokens are restricted to those supported by that package. It can scan about 5M tokens/second on a -// late 2013 15" MacBook Pro. -// -// The second lexer is constructed via the Regexp() function, mapping regexp capture groups -// to tokens. The complete input source is read into memory, so it is unsuitable for large inputs. -// -// The final lexer provided accepts a lexical grammar in EBNF. Each capitalised production is a -// lexical token supported by the resulting Lexer. This is very flexible, but a bit slower, scanning -// around 730K tokens/second on the same machine, though it is currently completely unoptimised. -// This could/should be converted to a table-based lexer. -// -// Lexer implementations must use Panic/Panicf to report errors. -package lexer diff --git a/vendor/github.com/alecthomas/participle/lexer/errors.go b/vendor/github.com/alecthomas/participle/lexer/errors.go deleted file mode 100644 index bf2965fb..00000000 --- a/vendor/github.com/alecthomas/participle/lexer/errors.go +++ /dev/null @@ -1,42 +0,0 @@ -package lexer - -import "fmt" - -// Error represents an error while parsing. -type Error struct { - Msg string - Pos Position -} - -// Errorf creats a new Error at the given position. -func Errorf(pos Position, format string, args ...interface{}) *Error { - return &Error{ - Msg: fmt.Sprintf(format, args...), - Pos: pos, - } -} - -func (e *Error) Message() string { return e.Msg } // nolint: golint -func (e *Error) Position() Position { return e.Pos } // nolint: golint - -// Error complies with the error interface and reports the position of an error. -func (e *Error) Error() string { - return FormatError(e.Pos, e.Msg) -} - -// FormatError formats an error in the form "[:][::] " -func FormatError(pos Position, message string) string { - msg := "" - if pos.Filename != "" { - msg += pos.Filename + ":" - } - if pos.Line != 0 || pos.Column != 0 { - msg += fmt.Sprintf("%d:%d:", pos.Line, pos.Column) - } - if msg != "" { - msg += " " + message - } else { - msg = message - } - return msg -} diff --git a/vendor/github.com/alecthomas/participle/lexer/lexer.go b/vendor/github.com/alecthomas/participle/lexer/lexer.go deleted file mode 100644 index 874c58d0..00000000 --- a/vendor/github.com/alecthomas/participle/lexer/lexer.go +++ /dev/null @@ -1,146 +0,0 @@ -package lexer - -import ( - "fmt" - "io" -) - -const ( - // EOF represents an end of file. - EOF rune = -(iota + 1) -) - -// EOFToken creates a new EOF token at the given position. -func EOFToken(pos Position) Token { - return Token{Type: EOF, Pos: pos} -} - -// Definition provides the parser with metadata for a lexer. -type Definition interface { - // Lex an io.Reader. - Lex(io.Reader) (Lexer, error) - // Symbols returns a map of symbolic names to the corresponding pseudo-runes for those symbols. - // This is the same approach as used by text/scanner. For example, "EOF" might have the rune - // value of -1, "Ident" might be -2, and so on. - Symbols() map[string]rune -} - -// A Lexer returns tokens from a source. -type Lexer interface { - // Next consumes and returns the next token. - Next() (Token, error) -} - -// SymbolsByRune returns a map of lexer symbol names keyed by rune. -func SymbolsByRune(def Definition) map[rune]string { - out := map[rune]string{} - for s, r := range def.Symbols() { - out[r] = s - } - return out -} - -// NameOfReader attempts to retrieve the filename of a reader. -func NameOfReader(r interface{}) string { - if nr, ok := r.(interface{ Name() string }); ok { - return nr.Name() - } - return "" -} - -// Must takes the result of a Definition constructor call and returns the definition, but panics if -// it errors -// -// eg. -// -// lex = lexer.Must(lexer.Build(`Symbol = "symbol" .`)) -func Must(def Definition, err error) Definition { - if err != nil { - panic(err) - } - return def -} - -// ConsumeAll reads all tokens from a Lexer. -func ConsumeAll(lexer Lexer) ([]Token, error) { - tokens := []Token{} - for { - token, err := lexer.Next() - if err != nil { - return nil, err - } - tokens = append(tokens, token) - if token.Type == EOF { - return tokens, nil - } - } -} - -// Position of a token. -type Position struct { - Filename string - Offset int - Line int - Column int -} - -func (p Position) GoString() string { - return fmt.Sprintf("Position{Filename: %q, Offset: %d, Line: %d, Column: %d}", - p.Filename, p.Offset, p.Line, p.Column) -} - -func (p Position) String() string { - filename := p.Filename - if filename == "" { - return fmt.Sprintf("%d:%d", p.Line, p.Column) - } - return fmt.Sprintf("%s:%d:%d", filename, p.Line, p.Column) -} - -// A Token returned by a Lexer. -type Token struct { - // Type of token. This is the value keyed by symbol as returned by Definition.Symbols(). - Type rune - Value string - Pos Position -} - -// RuneToken represents a rune as a Token. -func RuneToken(r rune) Token { - return Token{Type: r, Value: string(r)} -} - -// EOF returns true if this Token is an EOF token. -func (t Token) EOF() bool { - return t.Type == EOF -} - -func (t Token) String() string { - if t.EOF() { - return "" - } - return t.Value -} - -func (t Token) GoString() string { - if t.Pos == (Position{}) { - return fmt.Sprintf("Token{%d, %q}", t.Type, t.Value) - } - return fmt.Sprintf("Token@%s{%d, %q}", t.Pos.String(), t.Type, t.Value) -} - -// MakeSymbolTable builds a lookup table for checking token ID existence. -// -// For each symbolic name in "types", the returned map will contain the corresponding token ID as a key. -func MakeSymbolTable(def Definition, types ...string) (map[rune]bool, error) { - symbols := def.Symbols() - table := map[rune]bool{} - for _, symbol := range types { - rn, ok := symbols[symbol] - if !ok { - return nil, fmt.Errorf("lexer does not support symbol %q", symbol) - } - table[rn] = true - } - return table, nil -} diff --git a/vendor/github.com/alecthomas/participle/lexer/peek.go b/vendor/github.com/alecthomas/participle/lexer/peek.go deleted file mode 100644 index 8788f502..00000000 --- a/vendor/github.com/alecthomas/participle/lexer/peek.go +++ /dev/null @@ -1,56 +0,0 @@ -package lexer - -// PeekingLexer supports arbitrary lookahead as well as cloning. -type PeekingLexer struct { - cursor int - eof Token - tokens []Token -} - -// Upgrade a Lexer to a PeekingLexer with arbitrary lookahead. -func Upgrade(lex Lexer) (*PeekingLexer, error) { - r := &PeekingLexer{} - for { - t, err := lex.Next() - if err != nil { - return nil, err - } - if t.EOF() { - r.eof = t - break - } - r.tokens = append(r.tokens, t) - } - return r, nil -} - -// Cursor position in tokens. -func (p *PeekingLexer) Cursor() int { - return p.cursor -} - -// Next consumes and returns the next token. -func (p *PeekingLexer) Next() (Token, error) { - if p.cursor >= len(p.tokens) { - return p.eof, nil - } - p.cursor++ - return p.tokens[p.cursor-1], nil -} - -// Peek ahead at the n+1 token. ie. Peek(0) will peek at the next token. -func (p *PeekingLexer) Peek(n int) (Token, error) { - i := p.cursor + n - if i >= len(p.tokens) { - return p.eof, nil - } - return p.tokens[i], nil -} - -// Clone creates a clone of this PeekingLexer at its current token. -// -// The parent and clone are completely independent. -func (p *PeekingLexer) Clone() *PeekingLexer { - clone := *p - return &clone -} diff --git a/vendor/github.com/alecthomas/participle/lexer/regexp.go b/vendor/github.com/alecthomas/participle/lexer/regexp.go deleted file mode 100644 index ea56fe93..00000000 --- a/vendor/github.com/alecthomas/participle/lexer/regexp.go +++ /dev/null @@ -1,112 +0,0 @@ -package lexer - -import ( - "bytes" - "io" - "io/ioutil" - "regexp" - "unicode/utf8" -) - -var eolBytes = []byte("\n") - -type regexpDefinition struct { - re *regexp.Regexp - symbols map[string]rune -} - -// Regexp creates a lexer definition from a regular expression. -// -// Each named sub-expression in the regular expression matches a token. Anonymous sub-expressions -// will be matched and discarded. -// -// eg. -// -// def, err := Regexp(`(?P[a-z]+)|(\s+)|(?P\d+)`) -func Regexp(pattern string) (Definition, error) { - re, err := regexp.Compile(pattern) - if err != nil { - return nil, err - } - symbols := map[string]rune{ - "EOF": EOF, - } - for i, sym := range re.SubexpNames()[1:] { - if sym != "" { - symbols[sym] = EOF - 1 - rune(i) - } - } - return ®expDefinition{re: re, symbols: symbols}, nil -} - -func (d *regexpDefinition) Lex(r io.Reader) (Lexer, error) { - b, err := ioutil.ReadAll(r) - if err != nil { - return nil, err - } - return ®expLexer{ - pos: Position{ - Filename: NameOfReader(r), - Line: 1, - Column: 1, - }, - b: b, - re: d.re, - names: d.re.SubexpNames(), - }, nil -} - -func (d *regexpDefinition) Symbols() map[string]rune { - return d.symbols -} - -type regexpLexer struct { - pos Position - b []byte - re *regexp.Regexp - names []string -} - -func (r *regexpLexer) Next() (Token, error) { -nextToken: - for len(r.b) != 0 { - matches := r.re.FindSubmatchIndex(r.b) - if matches == nil || matches[0] != 0 { - rn, _ := utf8.DecodeRune(r.b) - return Token{}, Errorf(r.pos, "invalid token %q", rn) - } - match := r.b[:matches[1]] - token := Token{ - Pos: r.pos, - Value: string(match), - } - - // Update lexer state. - r.pos.Offset += matches[1] - lines := bytes.Count(match, eolBytes) - r.pos.Line += lines - // Update column. - if lines == 0 { - r.pos.Column += utf8.RuneCount(match) - } else { - r.pos.Column = utf8.RuneCount(match[bytes.LastIndex(match, eolBytes):]) - } - // Move slice along. - r.b = r.b[matches[1]:] - - // Finally, assign token type. If it is not a named group, we continue to the next token. - for i := 2; i < len(matches); i += 2 { - if matches[i] != -1 { - if r.names[i/2] == "" { - continue nextToken - } - token.Type = EOF - rune(i/2) - break - } - } - - return token, nil - } - - return EOFToken(r.pos), nil -} diff --git a/vendor/github.com/alecthomas/participle/lexer/text_scanner.go b/vendor/github.com/alecthomas/participle/lexer/text_scanner.go deleted file mode 100644 index 15a856dd..00000000 --- a/vendor/github.com/alecthomas/participle/lexer/text_scanner.go +++ /dev/null @@ -1,126 +0,0 @@ -package lexer - -import ( - "bytes" - "fmt" - "io" - "strconv" - "strings" - "text/scanner" - "unicode/utf8" -) - -// TextScannerLexer is a lexer that uses the text/scanner module. -var ( - TextScannerLexer Definition = &defaultDefinition{} - - // DefaultDefinition defines properties for the default lexer. - DefaultDefinition = TextScannerLexer -) - -type defaultDefinition struct{} - -func (d *defaultDefinition) Lex(r io.Reader) (Lexer, error) { - return Lex(r), nil -} - -func (d *defaultDefinition) Symbols() map[string]rune { - return map[string]rune{ - "EOF": scanner.EOF, - "Char": scanner.Char, - "Ident": scanner.Ident, - "Int": scanner.Int, - "Float": scanner.Float, - "String": scanner.String, - "RawString": scanner.RawString, - "Comment": scanner.Comment, - } -} - -// textScannerLexer is a Lexer based on text/scanner.Scanner -type textScannerLexer struct { - scanner *scanner.Scanner - filename string - err error -} - -// Lex an io.Reader with text/scanner.Scanner. -// -// This provides very fast lexing of source code compatible with Go tokens. -// -// Note that this differs from text/scanner.Scanner in that string tokens will be unquoted. -func Lex(r io.Reader) Lexer { - s := &scanner.Scanner{} - s.Init(r) - lexer := lexWithScanner(r, s) - lexer.scanner.Error = func(s *scanner.Scanner, msg string) { - // This is to support single quoted strings. Hacky. - if !strings.HasSuffix(msg, "char literal") { - lexer.err = Errorf(Position(lexer.scanner.Pos()), msg) - } - } - return lexer -} - -// LexWithScanner creates a Lexer from a user-provided scanner.Scanner. -// -// Useful if you need to customise the Scanner. -func LexWithScanner(r io.Reader, scan *scanner.Scanner) Lexer { - return lexWithScanner(r, scan) -} - -func lexWithScanner(r io.Reader, scan *scanner.Scanner) *textScannerLexer { - lexer := &textScannerLexer{ - filename: NameOfReader(r), - scanner: scan, - } - return lexer -} - -// LexBytes returns a new default lexer over bytes. -func LexBytes(b []byte) Lexer { - return Lex(bytes.NewReader(b)) -} - -// LexString returns a new default lexer over a string. -func LexString(s string) Lexer { - return Lex(strings.NewReader(s)) -} - -func (t *textScannerLexer) Next() (Token, error) { - typ := t.scanner.Scan() - text := t.scanner.TokenText() - pos := Position(t.scanner.Position) - pos.Filename = t.filename - if t.err != nil { - return Token{}, t.err - } - return textScannerTransform(Token{ - Type: typ, - Value: text, - Pos: pos, - }) -} - -func textScannerTransform(token Token) (Token, error) { - // Unquote strings. - switch token.Type { - case scanner.Char: - // FIXME(alec): This is pretty hacky...we convert a single quoted char into a double - // quoted string in order to support single quoted strings. - token.Value = fmt.Sprintf("\"%s\"", token.Value[1:len(token.Value)-1]) - fallthrough - case scanner.String: - s, err := strconv.Unquote(token.Value) - if err != nil { - return Token{}, Errorf(token.Pos, "%s: %q", err.Error(), token.Value) - } - token.Value = s - if token.Type == scanner.Char && utf8.RuneCountInString(s) > 1 { - token.Type = scanner.String - } - case scanner.RawString: - token.Value = token.Value[1 : len(token.Value)-1] - } - return token, nil -} diff --git a/vendor/github.com/alecthomas/participle/map.go b/vendor/github.com/alecthomas/participle/map.go deleted file mode 100644 index 99e80c77..00000000 --- a/vendor/github.com/alecthomas/participle/map.go +++ /dev/null @@ -1,118 +0,0 @@ -package participle - -import ( - "errors" - "io" - "strconv" - "strings" - - "github.com/alecthomas/participle/lexer" -) - -type mapperByToken struct { - symbols []string - mapper Mapper -} - -// DropToken can be returned by a Mapper to remove a token from the stream. -var DropToken = errors.New("drop token") // nolint: golint - -// Mapper function for mutating tokens before being applied to the AST. -// -// If the Mapper func returns an error of DropToken, the token will be removed from the stream. -type Mapper func(token lexer.Token) (lexer.Token, error) - -// Map is an Option that configures the Parser to apply a mapping function to each Token from the lexer. -// -// This can be useful to eg. upper-case all tokens of a certain type, or dequote strings. -// -// "symbols" specifies the token symbols that the Mapper will be applied to. If empty, all tokens will be mapped. -func Map(mapper Mapper, symbols ...string) Option { - return func(p *Parser) error { - p.mappers = append(p.mappers, mapperByToken{ - mapper: mapper, - symbols: symbols, - }) - return nil - } -} - -// Unquote applies strconv.Unquote() to tokens of the given types. -// -// Tokens of type "String" will be unquoted if no other types are provided. -func Unquote(types ...string) Option { - if len(types) == 0 { - types = []string{"String"} - } - return Map(func(t lexer.Token) (lexer.Token, error) { - value, err := unquote(t.Value) - if err != nil { - return t, lexer.Errorf(t.Pos, "invalid quoted string %q: %s", t.Value, err.Error()) - } - t.Value = value - return t, nil - }, types...) -} - -func unquote(s string) (string, error) { - quote := s[0] - s = s[1 : len(s)-1] - out := "" - for s != "" { - value, _, tail, err := strconv.UnquoteChar(s, quote) - if err != nil { - return "", err - } - s = tail - out += string(value) - } - return out, nil -} - -// Upper is an Option that upper-cases all tokens of the given type. Useful for case normalisation. -func Upper(types ...string) Option { - return Map(func(token lexer.Token) (lexer.Token, error) { - token.Value = strings.ToUpper(token.Value) - return token, nil - }, types...) -} - -// Elide drops tokens of the specified types. -func Elide(types ...string) Option { - return Map(func(token lexer.Token) (lexer.Token, error) { - return lexer.Token{}, DropToken - }, types...) -} - -// Apply a Mapping to all tokens coming out of a Lexer. -type mappingLexerDef struct { - lexer.Definition - mapper Mapper -} - -func (m *mappingLexerDef) Lex(r io.Reader) (lexer.Lexer, error) { - lexer, err := m.Definition.Lex(r) - if err != nil { - return nil, err - } - return &mappingLexer{lexer, m.mapper}, nil -} - -type mappingLexer struct { - lexer.Lexer - mapper Mapper -} - -func (m *mappingLexer) Next() (lexer.Token, error) { - for { - t, err := m.Lexer.Next() - if err != nil { - return t, err - } - t, err = m.mapper(t) - if err == DropToken { - continue - } - return t, err - } -} diff --git a/vendor/github.com/alecthomas/participle/nodes.go b/vendor/github.com/alecthomas/participle/nodes.go deleted file mode 100644 index 2e84bcdf..00000000 --- a/vendor/github.com/alecthomas/participle/nodes.go +++ /dev/null @@ -1,575 +0,0 @@ -package participle - -import ( - "errors" - "fmt" - "reflect" - "strconv" - "strings" - - "github.com/alecthomas/participle/lexer" -) - -var ( - // MaxIterations limits the number of elements capturable by {}. - MaxIterations = 1000000 - - positionType = reflect.TypeOf(lexer.Position{}) - captureType = reflect.TypeOf((*Capture)(nil)).Elem() - parseableType = reflect.TypeOf((*Parseable)(nil)).Elem() - - // NextMatch should be returned by Parseable.Parse() method implementations to indicate - // that the node did not match and that other matches should be attempted, if appropriate. - NextMatch = errors.New("no match") // nolint: golint -) - -// A node in the grammar. -type node interface { - // Parse from scanner into value. - // - // Returned slice will be nil if the node does not match. - Parse(ctx *parseContext, parent reflect.Value) ([]reflect.Value, error) - - // Return a decent string representation of the Node. - String() string -} - -func decorate(err *error, name func() string) { - if *err == nil { - return - } - switch realError := (*err).(type) { - case *lexer.Error: - *err = &parseError{Message: name() + ": " + realError.Msg, Pos: realError.Pos} - case *parseError: - *err = &parseError{Message: name() + ": " + realError.Message, Pos: realError.Pos} - default: - *err = &parseError{Message: fmt.Sprintf("%s: %s", name(), realError)} - } -} - -// A node that proxies to an implementation that implements the Parseable interface. -type parseable struct { - t reflect.Type -} - -func (p *parseable) String() string { return stringer(p) } - -func (p *parseable) Parse(ctx *parseContext, parent reflect.Value) (out []reflect.Value, err error) { - rv := reflect.New(p.t) - v := rv.Interface().(Parseable) - err = v.Parse(ctx.PeekingLexer) - if err != nil { - if err == NextMatch { - return nil, nil - } - return nil, err - } - return []reflect.Value{rv.Elem()}, nil -} - -type strct struct { - typ reflect.Type - expr node -} - -func (s *strct) String() string { return stringer(s) } - -func (s *strct) maybeInjectPos(pos lexer.Position, v reflect.Value) { - if f := v.FieldByName("Pos"); f.IsValid() && f.Type() == positionType { - f.Set(reflect.ValueOf(pos)) - } -} - -func (s *strct) Parse(ctx *parseContext, parent reflect.Value) (out []reflect.Value, err error) { - sv := reflect.New(s.typ).Elem() - t, err := ctx.Peek(0) - if err != nil { - return nil, err - } - s.maybeInjectPos(t.Pos, sv) - if out, err = s.expr.Parse(ctx, sv); err != nil { - _ = ctx.Apply() - return []reflect.Value{sv}, err - } else if out == nil { - return nil, nil - } - return []reflect.Value{sv}, ctx.Apply() -} - -type groupMatchMode int - -const ( - groupMatchOnce groupMatchMode = iota - groupMatchZeroOrOne = iota - groupMatchZeroOrMore = iota - groupMatchOneOrMore = iota - groupMatchNonEmpty = iota -) - -// ( ) - match once -// ( )* - match zero or more times -// ( )+ - match one or more times -// ( )? - match zero or once -// ( )! - must be a non-empty match -// -// The additional modifier "!" forces the content of the group to be non-empty if it does match. -type group struct { - expr node - mode groupMatchMode -} - -func (g *group) String() string { return stringer(g) } -func (g *group) Parse(ctx *parseContext, parent reflect.Value) (out []reflect.Value, err error) { - // Configure min/max matches. - min := 1 - max := 1 - switch g.mode { - case groupMatchNonEmpty: - out, err = g.expr.Parse(ctx, parent) - if err != nil { - return out, err - } - if len(out) == 0 { - t, _ := ctx.Peek(0) - return out, lexer.Errorf(t.Pos, "sub-expression %s cannot be empty", g) - } - return out, nil - case groupMatchOnce: - return g.expr.Parse(ctx, parent) - case groupMatchZeroOrOne: - min = 0 - case groupMatchZeroOrMore: - min = 0 - max = MaxIterations - case groupMatchOneOrMore: - min = 1 - max = MaxIterations - } - matches := 0 - for ; matches < max; matches++ { - branch := ctx.Branch() - v, err := g.expr.Parse(branch, parent) - out = append(out, v...) - if err != nil { - // Optional part failed to match. - if ctx.Stop(err, branch) { - return out, err - } - break - } else { - ctx.Accept(branch) - } - if v == nil { - break - } - } - // fmt.Printf("%d < %d < %d: out == nil? %v\n", min, matches, max, out == nil) - t, _ := ctx.Peek(0) - if matches >= MaxIterations { - panic(lexer.Errorf(t.Pos, "too many iterations of %s (> %d)", g, MaxIterations)) - } - if matches < min { - return out, lexer.Errorf(t.Pos, "sub-expression %s must match at least once", g) - } - // The idea here is that something like "a"? is a successful match and that parsing should proceed. - if min == 0 && out == nil { - out = []reflect.Value{} - } - return out, nil -} - -// {"|" } -type disjunction struct { - nodes []node -} - -func (d *disjunction) String() string { return stringer(d) } - -func (d *disjunction) Parse(ctx *parseContext, parent reflect.Value) (out []reflect.Value, err error) { - var ( - deepestError = 0 - firstError error - firstValues []reflect.Value - ) - for _, a := range d.nodes { - branch := ctx.Branch() - if value, err := a.Parse(branch, parent); err != nil { - // If this branch progressed too far and still didn't match, error out. - if ctx.Stop(err, branch) { - return value, err - } - // Show the closest error returned. The idea here is that the further the parser progresses - // without error, the more difficult it is to trace the error back to its root. - if branch.Cursor() >= deepestError { - firstError = err - firstValues = value - deepestError = branch.Cursor() - } - } else if value != nil { - ctx.Accept(branch) - return value, nil - } - } - if firstError != nil { - return firstValues, firstError - } - return nil, nil -} - -// ... -type sequence struct { - head bool - node node - next *sequence -} - -func (s *sequence) String() string { return stringer(s) } - -func (s *sequence) Parse(ctx *parseContext, parent reflect.Value) (out []reflect.Value, err error) { - for n := s; n != nil; n = n.next { - child, err := n.node.Parse(ctx, parent) - out = append(out, child...) - if err != nil { - return out, err - } - if child == nil { - // Early exit if first value doesn't match, otherwise all values must match. - if n == s { - return nil, nil - } - token, err := ctx.Peek(0) - if err != nil { - return nil, err - } - return out, lexer.Errorf(token.Pos, "unexpected %q (expected %s)", token, n) - } - } - return out, nil -} - -// @ -type capture struct { - field structLexerField - node node -} - -func (c *capture) String() string { return stringer(c) } - -func (c *capture) Parse(ctx *parseContext, parent reflect.Value) (out []reflect.Value, err error) { - token, err := ctx.Peek(0) - if err != nil { - return nil, err - } - pos := token.Pos - v, err := c.node.Parse(ctx, parent) - if err != nil { - if v != nil { - ctx.Defer(pos, parent, c.field, v) - } - return []reflect.Value{parent}, err - } - if v == nil { - return nil, nil - } - ctx.Defer(pos, parent, c.field, v) - return []reflect.Value{parent}, nil -} - -// - named lexer token reference -type reference struct { - typ rune - identifier string // Used for informational purposes. -} - -func (r *reference) String() string { return stringer(r) } - -func (r *reference) Parse(ctx *parseContext, parent reflect.Value) (out []reflect.Value, err error) { - token, err := ctx.Peek(0) - if err != nil { - return nil, err - } - if token.Type != r.typ { - return nil, nil - } - _, _ = ctx.Next() - return []reflect.Value{reflect.ValueOf(token.Value)}, nil -} - -// [ ] -type optional struct { - node node -} - -func (o *optional) String() string { return stringer(o) } - -func (o *optional) Parse(ctx *parseContext, parent reflect.Value) (out []reflect.Value, err error) { - branch := ctx.Branch() - out, err = o.node.Parse(branch, parent) - if err != nil { - // Optional part failed to match. - if ctx.Stop(err, branch) { - return out, err - } - } else { - ctx.Accept(branch) - } - if out == nil { - out = []reflect.Value{} - } - return out, nil -} - -// { } -type repetition struct { - node node -} - -func (r *repetition) String() string { return stringer(r) } - -// Parse a repetition. Once a repetition is encountered it will always match, so grammars -// should ensure that branches are differentiated prior to the repetition. -func (r *repetition) Parse(ctx *parseContext, parent reflect.Value) (out []reflect.Value, err error) { - i := 0 - for ; i < MaxIterations; i++ { - branch := ctx.Branch() - v, err := r.node.Parse(branch, parent) - out = append(out, v...) - if err != nil { - // Optional part failed to match. - if ctx.Stop(err, branch) { - return out, err - } - break - } else { - ctx.Accept(branch) - } - if v == nil { - break - } - } - if i >= MaxIterations { - t, _ := ctx.Peek(0) - panic(lexer.Errorf(t.Pos, "too many iterations of %s (> %d)", r, MaxIterations)) - } - if out == nil { - out = []reflect.Value{} - } - return out, nil -} - -// Match a token literal exactly "..."[:]. -type literal struct { - s string - t rune - tt string // Used for display purposes - symbolic name of t. -} - -func (l *literal) String() string { return stringer(l) } - -func (l *literal) Parse(ctx *parseContext, parent reflect.Value) (out []reflect.Value, err error) { - token, err := ctx.Peek(0) - if err != nil { - return nil, err - } - equal := false // nolint: ineffassign - if ctx.caseInsensitive[token.Type] { - equal = strings.EqualFold(token.Value, l.s) - } else { - equal = token.Value == l.s - } - if equal && (l.t == -1 || l.t == token.Type) { - next, err := ctx.Next() - if err != nil { - return nil, err - } - return []reflect.Value{reflect.ValueOf(next.Value)}, nil - } - return nil, nil -} - -// Attempt to transform values to given type. -// -// This will dereference pointers, and attempt to parse strings into integer values, floats, etc. -func conform(t reflect.Type, values []reflect.Value) (out []reflect.Value, err error) { - for _, v := range values { - for t != v.Type() && t.Kind() == reflect.Ptr && v.Kind() != reflect.Ptr { - // This can occur during partial failure. - if !v.CanAddr() { - return - } - v = v.Addr() - } - - // Already of the right kind, don't bother converting. - if v.Kind() == t.Kind() { - if v.Type() != t { - v = v.Convert(t) - } - out = append(out, v) - continue - } - - kind := t.Kind() - switch kind { - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - n, err := strconv.ParseInt(v.String(), 0, sizeOfKind(kind)) - if err != nil { - return nil, fmt.Errorf("invalid integer %q: %s", v.String(), err) - } - v = reflect.New(t).Elem() - v.SetInt(n) - - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - n, err := strconv.ParseUint(v.String(), 0, sizeOfKind(kind)) - if err != nil { - return nil, fmt.Errorf("invalid integer %q: %s", v.String(), err) - } - v = reflect.New(t).Elem() - v.SetUint(n) - - case reflect.Bool: - v = reflect.ValueOf(true) - - case reflect.Float32, reflect.Float64: - n, err := strconv.ParseFloat(v.String(), sizeOfKind(kind)) - if err != nil { - return nil, fmt.Errorf("invalid integer %q: %s", v.String(), err) - } - v = reflect.New(t).Elem() - v.SetFloat(n) - } - - out = append(out, v) - } - return out, nil -} - -func sizeOfKind(kind reflect.Kind) int { - switch kind { - case reflect.Int8, reflect.Uint8: - return 8 - case reflect.Int16, reflect.Uint16: - return 16 - case reflect.Int32, reflect.Uint32, reflect.Float32: - return 32 - case reflect.Int64, reflect.Uint64, reflect.Float64: - return 64 - case reflect.Int, reflect.Uint: - return strconv.IntSize - } - panic("unsupported kind " + kind.String()) -} - -// Set field. -// -// If field is a pointer the pointer will be set to the value. If field is a string, value will be -// appended. If field is a slice, value will be appended to slice. -// -// For all other types, an attempt will be made to convert the string to the corresponding -// type (int, float32, etc.). -func setField(pos lexer.Position, strct reflect.Value, field structLexerField, fieldValue []reflect.Value) (err error) { // nolint: gocognit - defer decorate(&err, func() string { return strct.Type().Name() + "." + field.Name }) - - f := strct.FieldByIndex(field.Index) - switch f.Kind() { - case reflect.Slice: - fieldValue, err = conform(f.Type().Elem(), fieldValue) - if err != nil { - return err - } - f.Set(reflect.Append(f, fieldValue...)) - return nil - - case reflect.Ptr: - if f.IsNil() { - fv := reflect.New(f.Type().Elem()).Elem() - f.Set(fv.Addr()) - f = fv - } else { - f = f.Elem() - } - } - - if f.Kind() == reflect.Struct { - if pf := f.FieldByName("Pos"); pf.IsValid() && pf.Type() == positionType { - pf.Set(reflect.ValueOf(pos)) - } - } - - if f.CanAddr() { - if d, ok := f.Addr().Interface().(Capture); ok { - ifv := []string{} - for _, v := range fieldValue { - ifv = append(ifv, v.Interface().(string)) - } - err := d.Capture(ifv) - if err != nil { - return err - } - return nil - } - } - - // Strings concatenate all captured tokens. - if f.Kind() == reflect.String { - fieldValue, err = conform(f.Type(), fieldValue) - if err != nil { - return err - } - for _, v := range fieldValue { - f.Set(reflect.ValueOf(f.String() + v.String()).Convert(f.Type())) - } - return nil - } - - // Coalesce multiple tokens into one. This allows eg. ["-", "10"] to be captured as separate tokens but - // parsed as a single string "-10". - if len(fieldValue) > 1 { - out := []string{} - for _, v := range fieldValue { - out = append(out, v.String()) - } - fieldValue = []reflect.Value{reflect.ValueOf(strings.Join(out, ""))} - } - - fieldValue, err = conform(f.Type(), fieldValue) - if err != nil { - return err - } - - fv := fieldValue[0] - - switch f.Kind() { - // Numeric types will increment if the token can not be coerced. - case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: - if fv.Type() != f.Type() { - f.SetInt(f.Int() + 1) - } else { - f.Set(fv) - } - case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: - if fv.Type() != f.Type() { - f.SetUint(f.Uint() + 1) - } else { - f.Set(fv) - } - - case reflect.Float32, reflect.Float64: - if fv.Type() != f.Type() { - f.SetFloat(f.Float() + 1) - } else { - f.Set(fv) - } - - case reflect.Bool, reflect.Struct: - if fv.Type() != f.Type() { - return fmt.Errorf("value %q is not correct type %s", fv, f.Type()) - } - f.Set(fv) - - default: - return fmt.Errorf("unsupported field type %s for field %s", f.Type(), field.Name) - } - return nil -} diff --git a/vendor/github.com/alecthomas/participle/options.go b/vendor/github.com/alecthomas/participle/options.go deleted file mode 100644 index 22f36b60..00000000 --- a/vendor/github.com/alecthomas/participle/options.go +++ /dev/null @@ -1,51 +0,0 @@ -package participle - -import ( - "github.com/alecthomas/participle/lexer" -) - -// An Option to modify the behaviour of the Parser. -type Option func(p *Parser) error - -// Lexer is an Option that sets the lexer to use with the given grammar. -func Lexer(def lexer.Definition) Option { - return func(p *Parser) error { - p.lex = def - return nil - } -} - -// UseLookahead allows branch lookahead up to "n" tokens. -// -// If parsing cannot be disambiguated before "n" tokens of lookahead, parsing will fail. -// -// Note that increasing lookahead has a minor performance impact, but also -// reduces the accuracy of error reporting. -func UseLookahead(n int) Option { - return func(p *Parser) error { - p.useLookahead = n - return nil - } -} - -// CaseInsensitive allows the specified token types to be matched case-insensitively. -func CaseInsensitive(tokens ...string) Option { - return func(p *Parser) error { - for _, token := range tokens { - p.caseInsensitive[token] = true - } - return nil - } -} - -// ParseOption modifies how an individual parse is applied. -type ParseOption func(p *parseContext) - -// AllowTrailing tokens without erroring. -// -// That is, do not error if a full parse completes but additional tokens remain. -func AllowTrailing(ok bool) ParseOption { - return func(p *parseContext) { - p.allowTrailing = ok - } -} diff --git a/vendor/github.com/alecthomas/participle/parser.go b/vendor/github.com/alecthomas/participle/parser.go deleted file mode 100644 index d2a030d7..00000000 --- a/vendor/github.com/alecthomas/participle/parser.go +++ /dev/null @@ -1,253 +0,0 @@ -package participle - -import ( - "bytes" - "fmt" - "io" - "reflect" - "strings" - - "github.com/alecthomas/participle/lexer" -) - -// A Parser for a particular grammar and lexer. -type Parser struct { - root node - lex lexer.Definition - typ reflect.Type - useLookahead int - caseInsensitive map[string]bool - mappers []mapperByToken -} - -// MustBuild calls Build(grammar, options...) and panics if an error occurs. -func MustBuild(grammar interface{}, options ...Option) *Parser { - parser, err := Build(grammar, options...) - if err != nil { - panic(err) - } - return parser -} - -// Build constructs a parser for the given grammar. -// -// If "Lexer()" is not provided as an option, a default lexer based on text/scanner will be used. This scans typical Go- -// like tokens. -// -// See documentation for details -func Build(grammar interface{}, options ...Option) (parser *Parser, err error) { - // Configure Parser struct with defaults + options. - p := &Parser{ - lex: lexer.TextScannerLexer, - caseInsensitive: map[string]bool{}, - useLookahead: 1, - } - for _, option := range options { - if option == nil { - return nil, fmt.Errorf("nil Option passed, signature has changed; " + - "if you intended to provide a custom Lexer, try participle.Build(grammar, participle.Lexer(lexer))") - } - if err = option(p); err != nil { - return nil, err - } - } - - if len(p.mappers) > 0 { - mappers := map[rune][]Mapper{} - symbols := p.lex.Symbols() - for _, mapper := range p.mappers { - if len(mapper.symbols) == 0 { - mappers[lexer.EOF] = append(mappers[lexer.EOF], mapper.mapper) - } else { - for _, symbol := range mapper.symbols { - if rn, ok := symbols[symbol]; !ok { - return nil, fmt.Errorf("mapper %#v uses unknown token %q", mapper, symbol) - } else { // nolint: golint - mappers[rn] = append(mappers[rn], mapper.mapper) - } - } - } - } - p.lex = &mappingLexerDef{p.lex, func(t lexer.Token) (lexer.Token, error) { - combined := make([]Mapper, 0, len(mappers[t.Type])+len(mappers[lexer.EOF])) - combined = append(combined, mappers[lexer.EOF]...) - combined = append(combined, mappers[t.Type]...) - - var err error - for _, m := range combined { - t, err = m(t) - if err != nil { - return t, err - } - } - return t, nil - }} - } - - context := newGeneratorContext(p.lex) - v := reflect.ValueOf(grammar) - if v.Kind() == reflect.Interface { - v = v.Elem() - } - p.typ = v.Type() - p.root, err = context.parseType(p.typ) - if err != nil { - return nil, err - } - return p, nil -} - -// Lex uses the parser's lexer to tokenise input. -func (p *Parser) Lex(r io.Reader) ([]lexer.Token, error) { - lex, err := p.lex.Lex(r) - if err != nil { - return nil, err - } - tokens, err := lexer.ConsumeAll(lex) - return tokens, err -} - -// ParseFromLexer into grammar v which must be of the same type as the grammar passed to -// participle.Build(). -// -// This may return a participle.Error. -func (p *Parser) ParseFromLexer(lex *lexer.PeekingLexer, v interface{}, options ...ParseOption) error { - rv := reflect.ValueOf(v) - if rv.Kind() == reflect.Interface { - rv = rv.Elem() - } - var stream reflect.Value - if rv.Kind() == reflect.Chan { - stream = rv - rt := rv.Type().Elem() - rv = reflect.New(rt).Elem() - } - rt := rv.Type() - if rt != p.typ { - return fmt.Errorf("must parse into value of type %s not %T", p.typ, v) - } - if rt.Kind() != reflect.Ptr || rt.Elem().Kind() != reflect.Struct { - return fmt.Errorf("target must be a pointer to a struct, not %s", rt) - } - caseInsensitive := map[rune]bool{} - for sym, rn := range p.lex.Symbols() { - if p.caseInsensitive[sym] { - caseInsensitive[rn] = true - } - } - ctx := newParseContext(lex, p.useLookahead, caseInsensitive) - defer func() { *lex = *ctx.PeekingLexer }() - for _, option := range options { - option(ctx) - } - // If the grammar implements Parseable, use it. - if parseable, ok := v.(Parseable); ok { - return p.rootParseable(ctx, parseable) - } - if stream.IsValid() { - return p.parseStreaming(ctx, stream) - } - return p.parseOne(ctx, rv) -} - -// Parse from r into grammar v which must be of the same type as the grammar passed to -// participle.Build(). -// -// This may return a participle.Error. -func (p *Parser) Parse(r io.Reader, v interface{}, options ...ParseOption) (err error) { - lex, err := p.lex.Lex(r) - if err != nil { - return err - } - peeker, err := lexer.Upgrade(lex) - if err != nil { - return err - } - return p.ParseFromLexer(peeker, v, options...) -} - -func (p *Parser) parseStreaming(ctx *parseContext, rv reflect.Value) error { - t := rv.Type().Elem().Elem() - for { - if token, _ := ctx.Peek(0); token.EOF() { - rv.Close() - return nil - } - v := reflect.New(t) - if err := p.parseInto(ctx, v); err != nil { - return err - } - rv.Send(v) - } -} - -func (p *Parser) parseOne(ctx *parseContext, rv reflect.Value) error { - err := p.parseInto(ctx, rv) - if err != nil { - return err - } - token, err := ctx.Peek(0) - if err != nil { - return err - } else if !token.EOF() && !ctx.allowTrailing { - return ctx.DeepestError(UnexpectedTokenError{token}) - } - return nil -} - -func (p *Parser) parseInto(ctx *parseContext, rv reflect.Value) error { - if rv.IsNil() { - return fmt.Errorf("target must be a non-nil pointer to a struct, but is a nil %s", rv.Type()) - } - pv, err := p.root.Parse(ctx, rv.Elem()) - if len(pv) > 0 && pv[0].Type() == rv.Elem().Type() { - rv.Elem().Set(reflect.Indirect(pv[0])) - } - if err != nil { - return err - } - if pv == nil { - token, _ := ctx.Peek(0) - return ctx.DeepestError(UnexpectedTokenError{token}) - } - return nil -} - -func (p *Parser) rootParseable(ctx *parseContext, parseable Parseable) error { - peek, err := ctx.Peek(0) - if err != nil { - return err - } - err = parseable.Parse(ctx.PeekingLexer) - if err == NextMatch { - token, _ := ctx.Peek(0) - return ctx.DeepestError(UnexpectedTokenError{token}) - } - peek, err = ctx.Peek(0) - if err != nil { - return err - } - if !peek.EOF() && !ctx.allowTrailing { - return ctx.DeepestError(UnexpectedTokenError{peek}) - } - return nil -} - -// ParseString is a convenience around Parse(). -// -// This may return a participle.Error. -func (p *Parser) ParseString(s string, v interface{}, options ...ParseOption) error { - return p.Parse(strings.NewReader(s), v, options...) -} - -// ParseBytes is a convenience around Parse(). -// -// This may return a participle.Error. -func (p *Parser) ParseBytes(b []byte, v interface{}, options ...ParseOption) error { - return p.Parse(bytes.NewReader(b), v, options...) -} - -// String representation of the grammar. -func (p *Parser) String() string { - return stringern(p.root, 128) -} diff --git a/vendor/github.com/alecthomas/participle/stringer.go b/vendor/github.com/alecthomas/participle/stringer.go deleted file mode 100644 index 1998b72f..00000000 --- a/vendor/github.com/alecthomas/participle/stringer.go +++ /dev/null @@ -1,174 +0,0 @@ -package participle - -import ( - "bytes" - "fmt" - "strings" - - "github.com/alecthomas/participle/lexer" -) - -type stringerVisitor struct { - bytes.Buffer - seen map[node]bool -} - -func stringern(n node, depth int) string { - v := &stringerVisitor{seen: map[node]bool{}} - v.visit(n, depth) - return v.String() -} - -func stringer(n node) string { - return stringern(n, 1) -} - -func (s *stringerVisitor) visit(n node, depth int) { // nolint: gocognit - if s.seen[n] || depth <= 0 { - fmt.Fprintf(s, "...") - return - } - s.seen[n] = true - - switch n := n.(type) { - case *disjunction: - for i, c := range n.nodes { - if i > 0 { - fmt.Fprint(s, " | ") - } - s.visit(c, depth) - } - - case *strct: - s.visit(n.expr, depth) - - case *sequence: - c := n - for i := 0; c != nil && depth-i > 0; c, i = c.next, i+1 { - if c != n { - fmt.Fprint(s, " ") - } - s.visit(c.node, depth-i) - } - - case *parseable: - fmt.Fprintf(s, "<%s>", strings.ToLower(n.t.Name())) - - case *capture: - if _, ok := n.node.(*parseable); ok { - fmt.Fprintf(s, "<%s>", strings.ToLower(n.field.Name)) - } else { - if n.node == nil { - fmt.Fprintf(s, "<%s>", strings.ToLower(n.field.Name)) - } else { - s.visit(n.node, depth) - } - } - - case *reference: - fmt.Fprintf(s, "<%s>", strings.ToLower(n.identifier)) - - case *optional: - composite := compositeNode(map[node]bool{}, n) - if composite { - fmt.Fprint(s, "(") - } - s.visit(n.node, depth) - if composite { - fmt.Fprint(s, ")") - } - fmt.Fprint(s, "?") - - case *repetition: - composite := compositeNode(map[node]bool{}, n) - if composite { - fmt.Fprint(s, "(") - } - s.visit(n.node, depth) - if composite { - fmt.Fprint(s, ")") - } - fmt.Fprint(s, "*") - - case *literal: - fmt.Fprintf(s, "%q", n.s) - if n.t != lexer.EOF && n.s == "" { - fmt.Fprintf(s, ":%s", n.tt) - } - - case *group: - composite := n.mode != groupMatchOnce && compositeNode(map[node]bool{}, n) - - if composite { - fmt.Fprint(s, "(") - } - if child, ok := n.expr.(*group); ok && child.mode == groupMatchOnce { - s.visit(child.expr, depth) - } else if child, ok := n.expr.(*capture); ok { - if grandchild, ok := child.node.(*group); ok && grandchild.mode == groupMatchOnce { - s.visit(grandchild.expr, depth) - } else { - s.visit(n.expr, depth) - } - } else { - s.visit(n.expr, depth) - } - if composite { - fmt.Fprint(s, ")") - } - switch n.mode { - case groupMatchNonEmpty: - fmt.Fprintf(s, "!") - case groupMatchZeroOrOne: - fmt.Fprintf(s, "?") - case groupMatchZeroOrMore: - fmt.Fprintf(s, "*") - case groupMatchOneOrMore: - fmt.Fprintf(s, "+") - } - - default: - panic("unsupported") - } -} - -func compositeNode(seen map[node]bool, n node) bool { - if n == nil || seen[n] { - return false - } - seen[n] = true - - switch n := n.(type) { - case *sequence: - return n.next != nil - - case *disjunction: - for _, c := range n.nodes { - if compositeNode(seen, c) { - return true - } - } - return false - - case *reference, *literal, *parseable: - return false - - case *strct: - return compositeNode(seen, n.expr) - - case *capture: - return compositeNode(seen, n.node) - - case *optional: - return compositeNode(seen, n.node) - - case *repetition: - return compositeNode(seen, n.node) - - case *group: - return compositeNode(seen, n.expr) - - default: - panic("unsupported") - } -} diff --git a/vendor/github.com/alecthomas/participle/struct.go b/vendor/github.com/alecthomas/participle/struct.go deleted file mode 100644 index a11d18c1..00000000 --- a/vendor/github.com/alecthomas/participle/struct.go +++ /dev/null @@ -1,140 +0,0 @@ -package participle - -import ( - "fmt" - "reflect" - - "github.com/alecthomas/participle/lexer" -) - -// A structLexer lexes over the tags of struct fields while tracking the current field. -type structLexer struct { - s reflect.Type - field int - indexes [][]int - lexer *lexer.PeekingLexer -} - -func lexStruct(s reflect.Type) (*structLexer, error) { - indexes, err := collectFieldIndexes(s) - if err != nil { - return nil, err - } - slex := &structLexer{ - s: s, - indexes: indexes, - } - if len(slex.indexes) > 0 { - tag := fieldLexerTag(slex.Field().StructField) - slex.lexer, err = lexer.Upgrade(lexer.LexString(tag)) - if err != nil { - return nil, err - } - } - return slex, nil -} - -// NumField returns the number of fields in the struct associated with this structLexer. -func (s *structLexer) NumField() int { - return len(s.indexes) -} - -type structLexerField struct { - reflect.StructField - Index []int -} - -// Field returns the field associated with the current token. -func (s *structLexer) Field() structLexerField { - return s.GetField(s.field) -} - -func (s *structLexer) GetField(field int) structLexerField { - if field >= len(s.indexes) { - field = len(s.indexes) - 1 - } - return structLexerField{ - StructField: s.s.FieldByIndex(s.indexes[field]), - Index: s.indexes[field], - } -} - -func (s *structLexer) Peek() (lexer.Token, error) { - field := s.field - lex := s.lexer - for { - token, err := lex.Peek(0) - if err != nil { - return token, err - } - if !token.EOF() { - token.Pos.Line = field + 1 - return token, nil - } - field++ - if field >= s.NumField() { - return lexer.EOFToken(token.Pos), nil - } - tag := fieldLexerTag(s.GetField(field).StructField) - lex, err = lexer.Upgrade(lexer.LexString(tag)) - if err != nil { - return token, err - } - } -} - -func (s *structLexer) Next() (lexer.Token, error) { - token, err := s.lexer.Next() - if err != nil { - return token, err - } - if !token.EOF() { - token.Pos.Line = s.field + 1 - return token, nil - } - if s.field+1 >= s.NumField() { - return lexer.EOFToken(token.Pos), nil - } - s.field++ - tag := fieldLexerTag(s.Field().StructField) - s.lexer, err = lexer.Upgrade(lexer.LexString(tag)) - if err != nil { - return token, err - } - return s.Next() -} - -func fieldLexerTag(field reflect.StructField) string { - if tag, ok := field.Tag.Lookup("parser"); ok { - return tag - } - return string(field.Tag) -} - -// Recursively collect flattened indices for top-level fields and embedded fields. -func collectFieldIndexes(s reflect.Type) (out [][]int, err error) { - if s.Kind() != reflect.Struct { - return nil, fmt.Errorf("expected a struct but got %q", s) - } - defer decorate(&err, s.String) - for i := 0; i < s.NumField(); i++ { - f := s.Field(i) - switch { - case f.Anonymous: // nolint: gocritic - children, err := collectFieldIndexes(f.Type) - if err != nil { - return nil, err - } - for _, idx := range children { - out = append(out, append(f.Index, idx...)) - } - - case f.PkgPath != "": - continue - - case fieldLexerTag(f) != "": - out = append(out, f.Index) - } - } - return -} diff --git a/vendor/github.com/dave/jennifer/jen/file.go b/vendor/github.com/dave/jennifer/jen/file.go index ca57b640..c19f5165 100644 --- a/vendor/github.com/dave/jennifer/jen/file.go +++ b/vendor/github.com/dave/jennifer/jen/file.go @@ -5,6 +5,8 @@ import ( "fmt" "regexp" "strings" + "unicode" + "unicode/utf8" ) // NewFile Creates a new file, with the specified package name. @@ -240,5 +242,15 @@ func guessAlias(path string) string { importsRegex := regexp.MustCompile(`[^a-z0-9]`) alias = importsRegex.ReplaceAllString(alias, "") + // can't have a first digit, per Go identifier rules, so just skip them + for firstRune, runeLen := utf8.DecodeRuneInString(alias); unicode.IsDigit(firstRune); firstRune, runeLen = utf8.DecodeRuneInString(alias) { + alias = alias[runeLen:] + } + + // If path part was all digits, we may be left with an empty string. In this case use "pkg" as the alias. + if alias == "" { + alias = "pkg" + } + return alias } diff --git a/vendor/github.com/gookit/color/.travis.yml b/vendor/github.com/gookit/color/.travis.yml index b2df0025..386f6dbc 100644 --- a/vendor/github.com/gookit/color/.travis.yml +++ b/vendor/github.com/gookit/color/.travis.yml @@ -1,14 +1,21 @@ language: go +env: + GO111MODULE: on + go: - - '1.9' - - '1.10' +# - '1.9' +# - '1.10' - '1.11' - '1.12' + - '1.13' + - '1.14' + - '1.15' before_install: - go get github.com/mattn/goveralls - go get golang.org/x/tools/cmd/cover script: + # gofmt -w ./ # - go test -v -cover - $HOME/gopath/bin/goveralls -v -service=travis-ci diff --git a/vendor/github.com/gookit/color/README.md b/vendor/github.com/gookit/color/README.md index b22eecd7..d68432eb 100644 --- a/vendor/github.com/gookit/color/README.md +++ b/vendor/github.com/gookit/color/README.md @@ -1,5 +1,7 @@ # CLI Color +![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/gookit/color?style=flat-square) +[![Actions Status](https://github.com/gookit/color/workflows/action-tests/badge.svg)](https://github.com/gookit/color/actions) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/51b28c5f7ffe4cc2b0f12ecf25ed247f)](https://app.codacy.com/app/inhere/color) [![GoDoc](https://godoc.org/github.com/gookit/color?status.svg)](https://pkg.go.dev/github.com/gookit/color?tab=overview) [![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/gookit/color)](https://github.com/gookit/color) @@ -13,13 +15,18 @@ A command-line color library with true color support, universal API methods and Basic color preview: -![basic-color](_examples/images/basic-color.png) +![basic-color](_examples/images/basic-color2.png) + +Now, 256 colors and RGB colors have also been supported to work in Windows CMD and PowerShell: + +![color-on-cmd-pwsh](_examples/images/color-on-cmd-pwsh.jpg) ## Features - Simple to use, zero dependencies - - Supports rich color output: 16-color, 256-color, true color (24-bit) + - Supports rich color output: 16-color, 256-color, true color (24-bit, RGB) - 16-color output is the most commonly used and most widely supported, working on any Windows version + - Since `v1.2.4` **the 256-color, true color (24-bit) support windows CMD and PowerShell** - See [this gist](https://gist.github.com/XVilka/8346728) for information on true color support - Generic API methods: `Print`, `Printf`, `Println`, `Sprint`, `Sprintf` - Supports HTML tag-style color rendering, such as `message`. Support working on windows `cmd` `powerShell` @@ -31,20 +38,20 @@ Basic color preview: - [godoc for gopkg](https://pkg.go.dev/gopkg.in/gookit/color.v1) - [godoc for github](https://pkg.go.dev/github.com/gookit/color) -## Quick start +## Install ```bash -import "gopkg.in/gookit/color.v1" // is recommended -// or -import "github.com/gookit/color" +go get github.com/gookit/color ``` +## Quick start + ```go package main import ( "fmt" - + "github.com/gookit/color" ) @@ -152,6 +159,7 @@ Supported on any Windows version. - `color.Info` - `color.Note` + - `color.Warn` - `color.Light` - `color.Error` - `color.Danger` @@ -160,54 +168,86 @@ Supported on any Windows version. - `color.Success` - `color.Comment` - `color.Primary` - - `color.Warning` - `color.Question` - `color.Secondary` ### Basic Style +print message use defined style: + ```go -// print message color.Info.Println("Info message") -color.Success.Println("Success message") +color.Note.Println("Note message") +color.Notice.Println("Notice message") +color.Error.Println("Error message") +color.Danger.Println("Danger message") +color.Warn.Println("Warn message") +color.Debug.Println("Debug message") +color.Primary.Println("Primary message") +color.Question.Println("Question message") +color.Secondary.Println("Secondary message") ``` Run demo: `go run ./_examples/theme_basic.go` -![theme-basic](_examples/images/theme-basic.jpg) +![theme-basic](_examples/images/theme-basic.png) ### Tips Style ```go -color.Info.Tips("tips style message") -color.Warn.Tips("tips style message") +color.Info.Tips("Info tips message") +color.Note.Tips("Note tips message") +color.Notice.Tips("Notice tips message") +color.Error.Tips("Error tips message") +color.Danger.Tips("Danger tips message") +color.Warn.Tips("Warn tips message") +color.Debug.Tips("Debug tips message") +color.Primary.Tips("Primary tips message") +color.Question.Tips("Question tips message") +color.Secondary.Tips("Secondary tips message") ``` Run demo: `go run ./_examples/theme_tips.go` -![theme-tips](_examples/images/theme-tips.jpg) +![theme-tips](_examples/images/theme-tips.png) ### Prompt Style ```go -color.Info.Prompt("prompt style message") -color.Warn.Prompt("prompt style message") +color.Info.Prompt("Info prompt message") +color.Note.Prompt("Note prompt message") +color.Notice.Prompt("Notice prompt message") +color.Error.Prompt("Error prompt message") +color.Danger.Prompt("Danger prompt message") +color.Warn.Prompt("Warn prompt message") +color.Debug.Prompt("Debug prompt message") +color.Primary.Prompt("Primary prompt message") +color.Question.Prompt("Question prompt message") +color.Secondary.Prompt("Secondary prompt message") ``` Run demo: `go run ./_examples/theme_prompt.go` -![theme-prompt](_examples/images/theme-prompt.jpg) +![theme-prompt](_examples/images/theme-prompt.png) ### Block Style ```go -color.Info.Block("block style message") -color.Warn.Block("block style message") +color.Info.Block("Info block message") +color.Note.Block("Note block message") +color.Notice.Block("Notice block message") +color.Error.Block("Error block message") +color.Danger.Block("Danger block message") +color.Warn.Block("Warn block message") +color.Debug.Block("Debug block message") +color.Primary.Block("Primary block message") +color.Question.Block("Question block message") +color.Secondary.Block("Secondary block message") ``` Run demo: `go run ./_examples/theme_block.go` -![theme-block](_examples/images/theme-block.jpg) +![theme-block](_examples/images/theme-block.png) ## HTML-like tag usage @@ -235,10 +275,12 @@ color.Tag("info").Println("info style text") Run demo: `go run ./_examples/colortag.go` -![color-tags](_examples/images/color-tags.jpg) +![color-tags](_examples/images/color-tags.png) ## 256-color usage +> 256 colors support Windows CMD, PowerShell environment after `v1.2.4` + ### Set the foreground or background color - `color.C256(val uint8, isBg ...bool) Color256` @@ -267,10 +309,30 @@ s.Printf("format %s", "message") Run demo: `go run ./_examples/color256.go` -![color-tags](_examples/images/256-color.jpg) +![color-tags](_examples/images/color-256.png) ## Use RGB color +> RGB colors support Windows `CMD`, `PowerShell` environment after `v1.2.4` + +**Preview:** + +> Run demo: `Run demo: go run ./_examples/color_rgb.go` + +![color-rgb](_examples/images/color-rgb.png) + +example: + +```go +color.RGB(30, 144, 255).Println("message. use RGB number") + +color.HEX("#1976D2").Println("blue-darken") +color.HEX("#D50000", true).Println("red-accent. use HEX style") + +color.RGBStyleFromString("213,0,0").Println("red-accent. use RGB number") +color.HEXStyle("eee", "D50000").Println("deep-purple color") +``` + ### Set the foreground or background color - `color.RGB(r, g, b uint8, isBg ...bool) RGBColor` @@ -290,37 +352,50 @@ c.Printf("format %s", "message") - `color.HEX(hex string, isBg ...bool) RGBColor` ```go -c := HEX("ccc") // can also: "cccccc" "#cccccc" +c := color.HEX("ccc") // can also: "cccccc" "#cccccc" c.Println("message") c.Printf("format %s", "message") -c = HEX("aabbcc", true) // as bg color +c = color.HEX("aabbcc", true) // as bg color c.Println("message") c.Printf("format %s", "message") ``` -### Use a RGB color style +### Use an RGB color style Can be used to set the foreground and background colors at the same time. - - `color.NewRGBStyle(fg RGBColor, bg ...RGBColor) *RGBStyle` +- `color.NewRGBStyle(fg RGBColor, bg ...RGBColor) *RGBStyle` ```go -s := NewRGBStyle(RGB(20, 144, 234), RGB(234, 78, 23)) +s := color.NewRGBStyle(RGB(20, 144, 234), RGB(234, 78, 23)) s.Println("message") s.Printf("format %s", "message") ``` Create a style from an hexadecimal color string: - - `color.HEXStyle(fg string, bg ...string) *RGBStyle` +- `color.HEXStyle(fg string, bg ...string) *RGBStyle` ```go -s := HEXStyle("11aa23", "eee") +s := color.HEXStyle("11aa23", "eee") s.Println("message") s.Printf("format %s", "message") ``` +## Func refer + +there are some useful functions reference + +- `Disable()` disable color render +- `SetOutput(io.Writer)` custom set the colored text output writer +- `ForceOpenColor()` force open color render +- `ClearCode(str string) string` Use for clear color codes +- `ClearTag(s string) string` clear all color html-tag for a string +- `IsConsole(w io.Writer)` Determine whether w is one of stderr, stdout, stdin +- `HexToRgb(hex string) (rgb []int)` Convert hex color string to RGB numbers +- `RgbToHex(rgb []int) string` Convert RGB to hex code + ## Gookit packages - [gookit/ini](https://github.com/gookit/ini) Go config management, use INI files diff --git a/vendor/github.com/gookit/color/README.zh-CN.md b/vendor/github.com/gookit/color/README.zh-CN.md index ab98928a..9d2b998c 100644 --- a/vendor/github.com/gookit/color/README.zh-CN.md +++ b/vendor/github.com/gookit/color/README.zh-CN.md @@ -1,5 +1,7 @@ # CLI Color +![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/gookit/color?style=flat-square) +[![Actions Status](https://github.com/gookit/color/workflows/action-tests/badge.svg)](https://github.com/gookit/color/actions) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/51b28c5f7ffe4cc2b0f12ecf25ed247f)](https://app.codacy.com/app/inhere/color) [![GoDoc](https://godoc.org/github.com/gookit/color?status.svg)](https://pkg.go.dev/github.com/gookit/color?tab=overview) [![GitHub tag (latest SemVer)](https://img.shields.io/github/tag/gookit/color)](https://github.com/gookit/color) @@ -13,14 +15,19 @@ Golang下的命令行色彩使用库, 拥有丰富的色彩渲染输出,通用 基本颜色预览: -![basic-color](_examples/images/basic-color.png) +![basic-color](_examples/images/basic-color2.png) + +现在,256色和RGB色彩也已经支持windows CMD和PowerShell中工作: + +![color-on-cmd-pwsh](_examples/images/color-on-cmd-pwsh.jpg) ## 功能特色 - 使用简单方便,无其他依赖 - - 支持丰富的颜色输出, 16色(4bit),256色(8bit),RGB色彩(24bit) + - 支持丰富的颜色输出, 16色(4bit),256色(8bit),RGB色彩(24bit, RGB) - 16色(4bit)是最常用和支持最广的,支持Windows `cmd.exe` - - 另外两种支持 `linux` `mac` 和 Windows下的 `ConEmu` `git-bash` `mintty` 等部分终端 + - 自 `v1.2.4` 起 **256色(8bit),RGB色彩(24bit)均支持windows CMD和PowerShell终端** + - 请查看 [this gist](https://gist.github.com/XVilka/8346728) 了解支持RGB色彩的终端 - 通用的API方法:`Print` `Printf` `Println` `Sprint` `Sprintf` - 同时支持html标签式的颜色渲染. eg: `message` - 基础色彩: `Bold` `Black` `White` `Gray` `Red` `Green` `Yellow` `Blue` `Magenta` `Cyan` @@ -32,17 +39,15 @@ Golang下的命令行色彩使用库, 拥有丰富的色彩渲染输出,通用 - [godoc for gopkg](https://pkg.go.dev/gopkg.in/gookit/color.v1) - [godoc for github](https://pkg.go.dev/github.com/gookit/color) -## 快速开始 - -如下,引入当前包就可以快速的使用 +## 安装 ```bash -import "gopkg.in/gookit/color.v1" // 推荐 -// or -import "github.com/gookit/color" +go get github.com/gookit/color ``` -### 如何使用 +## 快速开始 + +如下,引入当前包就可以快速的使用 ```go package main @@ -178,7 +183,7 @@ color.Success.Println("Success message") Run demo: `go run ./_examples/theme_basic.go` -![theme-basic](_examples/images/theme-basic.jpg) +![theme-basic](_examples/images/theme-basic.png) ### 简约提示风格 @@ -189,7 +194,7 @@ color.Warn.Tips("tips style message") Run demo: `go run ./_examples/theme_tips.go` -![theme-tips](_examples/images/theme-tips.jpg) +![theme-tips](_examples/images/theme-tips.png) ### 着重提示风格 @@ -200,7 +205,7 @@ color.Warn.Prompt("prompt style message") Run demo: `go run ./_examples/theme_prompt.go` -![theme-prompt](_examples/images/theme-prompt.jpg) +![theme-prompt](_examples/images/theme-prompt.png) ### 强调提示风格 @@ -211,7 +216,7 @@ color.Warn.Block("prompt style message") Run demo: `go run ./_examples/theme_block.go` -![theme-block](_examples/images/theme-block.jpg) +![theme-block](_examples/images/theme-block.png) ### 使用颜色标签 @@ -243,10 +248,12 @@ color.Tag("info").Println("info style text") > 运行 demo: `go run ./_examples/colortag.go` -![color-tags](_examples/images/color-tags.jpg) +![color-tags](_examples/images/color-tags.png) ## 256色使用 +> 256色彩在 `v1.2.4` 后支持Windows CMD,PowerShell 环境 + ### 使用前景或后景色 - `color.C256(val uint8, isBg ...bool) Color256` @@ -275,10 +282,30 @@ s.Printf("format %s", "message") > 运行 demo: `go run ./_examples/color256.go` -![color-tags](_examples/images/256-color.jpg) +![color-tags](_examples/images/color-256.png) ## RGB色彩使用 +> RGB色彩在 `v1.2.4` 后支持 Windows `CMD`, `PowerShell` 环境 + +**效果预览:** + +> 运行 demo: `Run demo: go run ./_examples/color_rgb.go` + +![color-rgb](_examples/images/color-rgb.png) + +代码示例: + +```go +color.RGB(30, 144, 255).Println("message. use RGB number") + +color.HEX("#1976D2").Println("blue-darken") +color.HEX("#D50000", true).Println("red-accent. use HEX style") + +color.RGBStyleFromString("213,0,0").Println("red-accent. use RGB number") +color.HEXStyle("eee", "D50000").Println("deep-purple color") +``` + ### 使用前景或后景色 - `color.RGB(r, g, b uint8, isBg ...bool) RGBColor` @@ -296,11 +323,11 @@ c.Printf("format %s", "message") - `color.HEX(hex string, isBg ...bool) RGBColor` 从16进制颜色创建 ```go -c := HEX("ccc") // 也可以写为: "cccccc" "#cccccc" +c := color.HEX("ccc") // 也可以写为: "cccccc" "#cccccc" c.Println("message") c.Printf("format %s", "message") -c = HEX("aabbcc", true) // as bg color +c = color.HEX("aabbcc", true) // as bg color c.Println("message") c.Printf("format %s", "message") ``` @@ -312,19 +339,32 @@ c.Printf("format %s", "message") - `color.NewRGBStyle(fg RGBColor, bg ...RGBColor) *RGBStyle` ```go -s := NewRGBStyle(RGB(20, 144, 234), RGB(234, 78, 23)) +s := color.NewRGBStyle(RGB(20, 144, 234), RGB(234, 78, 23)) s.Println("message") s.Printf("format %s", "message") ``` - - `color.HEXStyle(fg string, bg ...string) *RGBStyle` 从16进制颜色创建 +- `color.HEXStyle(fg string, bg ...string) *RGBStyle` 从16进制颜色创建 ```go -s := HEXStyle("11aa23", "eee") +s := color.HEXStyle("11aa23", "eee") s.Println("message") s.Printf("format %s", "message") ``` +## 方法参考 + +一些有用的工具方法参考 + +- `Disable()` disable color render +- `SetOutput(io.Writer)` custom set the colored text output writer +- `ForceOpenColor()` force open color render +- `ClearCode(str string) string` Use for clear color codes +- `ClearTag(s string) string` clear all color html-tag for a string +- `IsConsole(w io.Writer)` Determine whether w is one of stderr, stdout, stdin +- `HexToRgb(hex string) (rgb []int)` Convert hex color string to RGB numbers +- `RgbToHex(rgb []int) string` Convert RGB to hex code + ## Gookit 工具包 - [gookit/ini](https://github.com/gookit/ini) INI配置读取管理,支持多文件加载,数据覆盖合并, 解析ENV变量, 解析变量引用 diff --git a/vendor/github.com/gookit/color/color.go b/vendor/github.com/gookit/color/color.go index f287a4d8..01518143 100644 --- a/vendor/github.com/gookit/color/color.go +++ b/vendor/github.com/gookit/color/color.go @@ -33,15 +33,19 @@ const ( FullColorTpl = "\x1b[%sm%s\x1b[0m" ) -// ResetSet 重置/正常 关闭所有属性。 +// ResetSet Close all properties. const ResetSet = "\x1b[0m" // CodeExpr regex to clear color codes eg "\033[1;36mText\x1b[0m" const CodeExpr = `\033\[[\d;?]+m` var ( - // Enable switch color display + // Enable switch color render and display Enable = true + // RenderTag render HTML tag on call color.Xprint, color.PrintX + RenderTag = true + // errors on windows render OR print to io.Writer + errors []error // output the default io.Writer message print output io.Writer = os.Stdout // mark current env, It's like in `cmd.exe` @@ -65,9 +69,9 @@ func Set(colors ...Color) (int, error) { } // on windows cmd.exe - if isLikeInCmd { - return winSet(colors...) - } + // if isLikeInCmd { + // return winSet(colors...) + // } return fmt.Printf(SettingTpl, colors2code(colors...)) } @@ -79,16 +83,23 @@ func Reset() (int, error) { } // on windows cmd.exe - if isLikeInCmd { - return winReset() - } + // if isLikeInCmd { + // return winReset() + // } return fmt.Print(ResetSet) } // Disable disable color output -func Disable() { +func Disable() bool { + oldVal := Enable Enable = false + return oldVal +} + +// NotRenderTag on call color.Xprint, color.PrintX +func NotRenderTag() { + RenderTag = false } // SetOutput set default colored text output @@ -101,6 +112,18 @@ func ResetOutput() { output = os.Stdout } +// ResetOptions reset all package option setting +func ResetOptions() { + RenderTag = true + Enable = true + output = os.Stdout +} + +// ForceColor force open color render +func ForceColor() bool { + return ForceOpenColor() +} + // ForceOpenColor force open color render func ForceOpenColor() bool { oldVal := isSupportColor @@ -109,6 +132,16 @@ func ForceOpenColor() bool { return oldVal } +// IsLikeInCmd check result +func IsLikeInCmd() bool { + return isLikeInCmd +} + +// GetErrors info +func GetErrors() []error { + return errors +} + /************************************************************* * render color code *************************************************************/ diff --git a/vendor/github.com/gookit/color/color_16.go b/vendor/github.com/gookit/color/color_16.go index 6a54ee18..9d425500 100644 --- a/vendor/github.com/gookit/color/color_16.go +++ b/vendor/github.com/gookit/color/color_16.go @@ -2,6 +2,7 @@ package color import ( "fmt" + "strconv" "strings" ) @@ -9,6 +10,33 @@ import ( // 3(2^3=8) OR 4(2^4=16) bite color. type Color uint8 +// Opts basic color options. code: 0 - 9 +type Opts []Color + +// Add option value +func (o *Opts) Add(ops ...Color) { + for _, op := range ops { + if uint8(op) < 10 { + *o = append(*o, op) + } + } +} + +// IsValid options +func (o Opts) IsValid() bool { + return len(o) > 0 +} + +// IsEmpty options +func (o Opts) IsEmpty() bool { + return len(o) == 0 +} + +// String options to string. eg: "1;3" +func (o Opts) String() string { + return colors2code(o...) +} + /************************************************************* * Basic 16 color definition *************************************************************/ @@ -57,7 +85,7 @@ const ( // Extra background color 100 - 107(非标准) const ( - BgDarkGray Color = iota + 99 + BgDarkGray Color = iota + 100 BgLightRed BgLightGreen BgLightYellow @@ -157,19 +185,19 @@ func (c Color) Sprintf(format string, args ...interface{}) string { // green := color.FgGreen.Print // green("message") func (c Color) Print(args ...interface{}) { - doPrint(c.Code(), []Color{c}, fmt.Sprint(args...)) + doPrintV2(c.Code(), fmt.Sprint(args...)) } // Printf format and print messages. // Usage: // color.Cyan.Printf("string %s", "arg0") func (c Color) Printf(format string, a ...interface{}) { - doPrint(c.Code(), []Color{c}, fmt.Sprintf(format, a...)) + doPrintV2(c.Code(), fmt.Sprintf(format, a...)) } // Println messages with new line func (c Color) Println(a ...interface{}) { - doPrintln(c.String(), []Color{c}, a) + doPrintlnV2(c.String(), a) } // Light current color. eg: 36(FgCyan) -> 96(FgLightCyan). @@ -202,12 +230,14 @@ func (c Color) Darken() Color { // Code convert to code string. eg "35" func (c Color) Code() string { - return fmt.Sprintf("%d", c) + // return fmt.Sprintf("%d", c) + return strconv.Itoa(int(c)) } // String convert to code string. eg "35" func (c Color) String() string { - return fmt.Sprintf("%d", c) + // return fmt.Sprintf("%d", c) + return strconv.Itoa(int(c)) } // IsValid color value diff --git a/vendor/github.com/gookit/color/color_256.go b/vendor/github.com/gookit/color/color_256.go index d5243594..ae37ba66 100644 --- a/vendor/github.com/gookit/color/color_256.go +++ b/vendor/github.com/gookit/color/color_256.go @@ -41,12 +41,15 @@ const ( // // 颜色值使用10进制和16进制都可 0x98 = 152 // -// 颜色有两位uint8组成, +// 颜色有两位uint8组成: // 0: color value // 1: color type, Fg=0 Bg=1 // >1: unset value +// example: // fg color: [152, 0] // bg color: [152, 1] +// +// NOTICE: now support 256 color on windows CMD, PowerShell type Color256 [2]uint8 // Bit8 create a color256 @@ -68,17 +71,17 @@ func C256(val uint8, isBg ...bool) Color256 { // Print print message func (c Color256) Print(a ...interface{}) { - fmt.Print(RenderCode(c.String(), a...)) + doPrintV2(c.String(), fmt.Sprint(a...)) } // Printf format and print message func (c Color256) Printf(format string, a ...interface{}) { - fmt.Print(RenderString(c.String(), fmt.Sprintf(format, a...))) + doPrintV2(c.String(), fmt.Sprintf(format, a...)) } // Println print message with newline func (c Color256) Println(a ...interface{}) { - fmt.Println(RenderString(c.String(), formatArgsForPrintln(a))) + doPrintlnV2(c.String(), a) } // Sprint returns rendered message @@ -125,9 +128,12 @@ func (c Color256) IsEmpty() bool { // 都是由两位uint8组成, 第一位是色彩值; // 第二位与Bit8Color不一样的是,在这里表示是否设置了值 0 未设置 ^0 已设置 type Style256 struct { - p *Printer + // p Printer + // Name of the style Name string + // color options of the style + opts Opts // fg and bg color fg, bg Color256 } @@ -152,9 +158,10 @@ func S256(fgAndBg ...uint8) *Style256 { } // Set fg and bg color value -func (s *Style256) Set(fgVal, bgVal uint8) *Style256 { +func (s *Style256) Set(fgVal, bgVal uint8, ops ...Color) *Style256 { s.fg = Color256{fgVal, 1} s.bg = Color256{bgVal, 1} + s.opts.Add(ops...) return s } @@ -170,19 +177,31 @@ func (s *Style256) SetFg(fgVal uint8) *Style256 { return s } -// Print print message +// SetOpts set options +func (s *Style256) SetOpts(opts Opts) *Style256 { + s.opts = opts + return s +} + +// AddOpts add options +func (s *Style256) AddOpts(opts ...Color) *Style256 { + s.opts.Add(opts...) + return s +} + +// Print message func (s *Style256) Print(a ...interface{}) { - fmt.Print(RenderCode(s.String(), a...)) + doPrintV2(s.String(), fmt.Sprint(a...)) } // Printf format and print message func (s *Style256) Printf(format string, a ...interface{}) { - fmt.Print(RenderString(s.String(), fmt.Sprintf(format, a...))) + doPrintV2(s.String(), fmt.Sprintf(format, a...)) } // Println print message with newline func (s *Style256) Println(a ...interface{}) { - fmt.Println(RenderString(s.String(), formatArgsForPrintln(a))) + doPrintlnV2(s.String(), a) } // Sprint returns rendered message @@ -211,5 +230,9 @@ func (s *Style256) String() string { ss = append(ss, fmt.Sprintf(TplBg256, s.bg[0])) } + if s.opts.IsValid() { + ss = append(ss, s.opts.String()) + } + return strings.Join(ss, ";") } diff --git a/vendor/github.com/gookit/color/color_rgb.go b/vendor/github.com/gookit/color/color_rgb.go index c38c86c2..a20b7256 100644 --- a/vendor/github.com/gookit/color/color_rgb.go +++ b/vendor/github.com/gookit/color/color_rgb.go @@ -12,8 +12,8 @@ import ( // R 00-FF G 00-FF B 00-FF (16进制) // // Format: -// ESC[ … 38;2;;; … m // 选择RGB前景色 -// ESC[ … 48;2;;; … m // 选择RGB背景色 +// ESC[ … 38;2;;; … m // Select RGB foreground color +// ESC[ … 48;2;;; … m // Choose RGB background color // // links: // https://zh.wikipedia.org/wiki/ANSI%E8%BD%AC%E4%B9%89%E5%BA%8F%E5%88%97#24位 @@ -44,9 +44,11 @@ const ( // // Usage: // // 0, 1, 2 is R,G,B. -// // 3th: Fg=0, Bg=1, >1: unset value +// // 3rd: Fg=0, Bg=1, >1: unset value // RGBColor{30,144,255, 0} // RGBColor{30,144,255, 1} +// +// NOTICE: now support RGB color on windows CMD, PowerShell type RGBColor [4]uint8 // create a empty RGBColor @@ -74,7 +76,7 @@ func RGB(r, g, b uint8, isBg ...bool) RGBColor { // c := HEX("0xaabbcc") // c.Print("message") func HEX(hex string, isBg ...bool) RGBColor { - if rgb := HexToRGB(hex); len(rgb) > 0 { + if rgb := HexToRgb(hex); len(rgb) > 0 { return RGB(uint8(rgb[0]), uint8(rgb[1]), uint8(rgb[2]), isBg...) } @@ -107,17 +109,17 @@ func RGBFromString(rgb string, isBg ...bool) RGBColor { // Print print message func (c RGBColor) Print(a ...interface{}) { - fmt.Print(RenderCode(c.String(), a...)) + doPrintV2(c.String(), fmt.Sprint(a...)) } // Printf format and print message func (c RGBColor) Printf(format string, a ...interface{}) { - fmt.Print(RenderString(c.String(), fmt.Sprintf(format, a...))) + doPrintV2(c.String(), fmt.Sprintf(format, a...)) } // Println print message with newline func (c RGBColor) Println(a ...interface{}) { - fmt.Println(RenderString(c.String(), formatArgsForPrintln(a))) + doPrintlnV2(c.String(), a) } // Sprint returns rendered message @@ -142,11 +144,11 @@ func (c RGBColor) Code() string { // String to color code string func (c RGBColor) String() string { - if c[3] == AsFg { // 0 is Fg + if c[3] == AsFg { return fmt.Sprintf(TplFgRGB, c[0], c[1], c[2]) } - if c[3] == AsBg { // 1 is Bg + if c[3] == AsBg { return fmt.Sprintf(TplBgRGB, c[0], c[1], c[2]) } @@ -157,50 +159,17 @@ func (c RGBColor) String() string { // IsEmpty value func (c RGBColor) IsEmpty() bool { - return c[3] > 1 + return c[3] > AsBg } -// HexToRGB hex color string to RGB numbers -// Usage: -// rgb := HexToRGB("ccc") // rgb: [204 204 204] -// rgb := HexToRGB("aabbcc") // rgb: [170 187 204] -// rgb := HexToRGB("#aabbcc") // rgb: [170 187 204] -// rgb := HexToRGB("0xad99c0") // rgb: [170 187 204] -func HexToRGB(hex string) (rgb []int) { - hex = strings.TrimSpace(hex) - if hex == "" { - return - } - - // like from css. eg "#ccc" "#ad99c0" - if hex[0] == '#' { - hex = hex[1:] - } - - hex = strings.ToLower(hex) - switch len(hex) { - case 3: // "ccc" - hex = string([]byte{hex[0], hex[0], hex[1], hex[1], hex[2], hex[2]}) - case 8: // "0xad99c0" - hex = strings.TrimPrefix(hex, "0x") - } - - // recheck - if len(hex) != 6 { - return - } - - // convert string to int64 - if i64, err := strconv.ParseInt(hex, 16, 32); err == nil { - color := int(i64) - // parse int - rgb = make([]int, 3) - rgb[0] = color >> 16 - rgb[1] = (color & 0x00FF00) >> 8 - rgb[2] = color & 0x0000FF - } +// IsValid value +// func (c RGBColor) IsValid() bool { +// return c[3] <= AsBg +// } - return +// C256 returns the closest approximate 256 (8 bit) color +func (c RGBColor) C256() Color256 { + return C256(rgb2short(c[0], c[1], c[2]), c[3] == AsBg) } /************************************************************* @@ -209,12 +178,16 @@ func HexToRGB(hex string) (rgb []int) { // RGBStyle definition. // -// 前/背景色 -// 都是由4位uint8组成, 前三位是色彩值; -// 最后一位与RGBColor不一样的是,在这里表示是否设置了值 1 表示已设置 ^1 未设置 +// Foreground/Background color +// All are composed of 4 digits uint8, the first three digits are the color value; +// The last bit is different from RGBColor, here it indicates whether the value is set. +// - 1 Has been set +// - ^1 Not set type RGBStyle struct { // Name of the style Name string + // color options of the style + opts Opts // fg and bg color fg, bg RGBColor } @@ -239,7 +212,11 @@ func HEXStyle(fg string, bg ...string) *RGBStyle { s.SetBg(HEX(bg[0])) } - return s.SetFg(HEX(fg)) + if len(fg) > 0 { + s.SetFg(HEX(fg)) + } + + return s } // RGBStyleFromString create a RGBStyle from color value string. @@ -256,37 +233,49 @@ func RGBStyleFromString(fg string, bg ...string) *RGBStyle { } // Set fg and bg color -func (s *RGBStyle) Set(fg, bg RGBColor) *RGBStyle { - return s.SetFg(fg).SetBg(bg) +func (s *RGBStyle) Set(fg, bg RGBColor, opts ...Color) *RGBStyle { + return s.SetFg(fg).SetBg(bg).SetOpts(opts) } // SetFg set fg color func (s *RGBStyle) SetFg(fg RGBColor) *RGBStyle { - fg[3] = 1 + fg[3] = 1 // add fixed value, mark is valid s.fg = fg return s } // SetBg set bg color func (s *RGBStyle) SetBg(bg RGBColor) *RGBStyle { - bg[3] = 1 + bg[3] = 1 // add fixed value, mark is valid s.bg = bg return s } +// SetOpts set options +func (s *RGBStyle) SetOpts(opts Opts) *RGBStyle { + s.opts = opts + return s +} + +// AddOpts add options +func (s *RGBStyle) AddOpts(opts ...Color) *RGBStyle { + s.opts.Add(opts...) + return s +} + // Print print message func (s *RGBStyle) Print(a ...interface{}) { - fmt.Print(RenderCode(s.String(), a...)) + doPrintV2(s.String(), fmt.Sprint(a...)) } // Printf format and print message func (s *RGBStyle) Printf(format string, a ...interface{}) { - fmt.Print(RenderString(s.String(), fmt.Sprintf(format, a...))) + doPrintV2(s.String(), fmt.Sprintf(format, a...)) } // Println print message with newline func (s *RGBStyle) Println(a ...interface{}) { - fmt.Println(RenderString(s.String(), formatArgsForPrintln(a))) + doPrintlnV2(s.String(), a) } // Sprint returns rendered message @@ -307,7 +296,8 @@ func (s *RGBStyle) Code() string { // String convert to color code string func (s *RGBStyle) String() string { var ss []string - if s.fg[3] == 1 { // last value ensure is enable. + // last value ensure is enable. + if s.fg[3] == 1 { ss = append(ss, fmt.Sprintf(TplFgRGB, s.fg[0], s.fg[1], s.fg[2])) } @@ -315,6 +305,10 @@ func (s *RGBStyle) String() string { ss = append(ss, fmt.Sprintf(TplBgRGB, s.bg[0], s.bg[1], s.bg[2])) } + if s.opts.IsValid() { + ss = append(ss, s.opts.String()) + } + return strings.Join(ss, ";") } @@ -322,8 +316,3 @@ func (s *RGBStyle) String() string { func (s *RGBStyle) IsEmpty() bool { return s.fg[3] != 1 && s.bg[3] != 1 } - -// RGBto256 value -// func RGBto256(r, g, b uint8) { -// -// } diff --git a/vendor/github.com/gookit/color/color_windows.go b/vendor/github.com/gookit/color/color_windows.go index eea94301..b5e0f480 100644 --- a/vendor/github.com/gookit/color/color_windows.go +++ b/vendor/github.com/gookit/color/color_windows.go @@ -13,73 +13,6 @@ import ( "unsafe" ) -// color on windows cmd -// you can see on windows by command: COLOR /? -// windows color build by: "Bg + Fg" OR only "Fg" -// Consists of any two of the following: -// the first is the background color, and the second is the foreground color -// 颜色属性由两个十六进制数字指定 -// - 第一个对应于背景,第二个对应于前景。 -// - 当只传入一个值时,则认为是前景色 -// 每个数字可以为以下任何值: -// more see: https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/cmd -const ( - // Foreground colors. - winFgBlack uint16 = 0x00 // 0 黑色 - winFgBlue uint16 = 0x01 // 1 蓝色 - winFgGreen uint16 = 0x02 // 2 绿色 - winFgAqua uint16 = 0x03 // 3 浅绿 skyblue - winFgRed uint16 = 0x04 // 4 红色 - winFgPink uint16 = 0x05 // 5 紫色/品红 - winFgYellow uint16 = 0x06 // 6 黄色 - winFgWhite uint16 = 0x07 // 7 白色 - winFgGray uint16 = 0x08 // 8 灰色 - - winFgLightBlue uint16 = 0x09 // 9 淡蓝色 - winFgLightGreen uint16 = 0x0a // 10 淡绿色 - winFgLightAqua uint16 = 0x0b // 11 淡浅绿色 - winFgLightRed uint16 = 0x0c // 12 淡红色 - winFgLightPink uint16 = 0x0d // 13 Purple 淡紫色, Pink 粉红 - winFgLightYellow uint16 = 0x0e // 14 淡黄色 - winFgLightWhite uint16 = 0x0f // 15 亮白色 - - // Background colors. - winBgBlack uint16 = 0x00 // 黑色 - winBgBlue uint16 = 0x10 // 蓝色 - winBgGreen uint16 = 0x20 // 绿色 - winBgAqua uint16 = 0x30 // 浅绿 skyblue - winBgRed uint16 = 0x40 // 红色 - winBgPink uint16 = 0x50 // 紫色 - winBgYellow uint16 = 0x60 // 黄色 - winBgWhite uint16 = 0x70 // 白色 - winBgGray uint16 = 0x80 // 128 灰色 - - winBgLightBlue uint16 = 0x90 // 淡蓝色 - winBgLightGreen uint16 = 0xa0 // 淡绿色 - winBgLightAqua uint16 = 0xb0 // 淡浅绿色 - winBgLightRed uint16 = 0xc0 // 淡红色 - winBgLightPink uint16 = 0xd0 // 淡紫色 - winBgLightYellow uint16 = 0xe0 // 淡黄色 - winBgLightWhite uint16 = 0xf0 // 240 亮白色 - - // bg black, fg white - winDefSetting = winBgBlack | winFgWhite - - // Option settings - // see https://docs.microsoft.com/en-us/windows/console/char-info-str - winFgIntensity uint16 = 0x0008 // 8 前景强度 - winBgIntensity uint16 = 0x0080 // 128 背景强度 - - WinOpLeading uint16 = 0x0100 // 前导字节 - WinOpTrailing uint16 = 0x0200 // 尾随字节 - WinOpHorizontal uint16 = 0x0400 // 顶部水平 - WinOpReverse uint16 = 0x4000 // 反转前景和背景 - WinOpUnderscore uint16 = 0x8000 // 32768 下划线 -) - -// color on windows -var winColorsMap map[Color]uint16 - // related docs // https://docs.microsoft.com/zh-cn/windows/console/console-virtual-terminal-sequences // https://docs.microsoft.com/zh-cn/windows/console/console-virtual-terminal-sequences#samples @@ -89,13 +22,6 @@ var ( procGetConsoleMode *syscall.LazyProc procSetConsoleMode *syscall.LazyProc - - procSetTextAttribute *syscall.LazyProc - procGetConsoleScreenBufferInfo *syscall.LazyProc - - // console screen buffer info - // eg {size:{x:215 y:3000} cursorPosition:{x:0 y:893} attributes:7 window:{left:0 top:882 right:214 bottom:893} maximumWindowSize:{x:215 y:170}} - defScreenInfo consoleScreenBufferInfo ) func init() { @@ -104,9 +30,15 @@ func init() { return } - // init simple color code info isLikeInCmd = true - initWinColorsMap() + if !Enable { + return + } + + // force open + isSupportColor = true + // init simple color code info + // initWinColorsMap() // load related windows dll // isMSys = utils.IsMSys() @@ -116,9 +48,17 @@ func init() { procGetConsoleMode = kernel32.NewProc("GetConsoleMode") procSetConsoleMode = kernel32.NewProc("SetConsoleMode") - procSetTextAttribute = kernel32.NewProc("SetConsoleTextAttribute") - // https://docs.microsoft.com/en-us/windows/console/getconsolescreenbufferinfo - procGetConsoleScreenBufferInfo = kernel32.NewProc("GetConsoleScreenBufferInfo") + outHandle, err := syscall.Open("CONOUT$", syscall.O_RDWR, 0) + if err != nil { + fmt.Println(53, err) + return + } + err = EnableVirtualTerminalProcessing(outHandle, true) + saveInternalError(err) + if err != nil { + fmt.Println(err) + // isSupportColor = false + } // fetch console screen buffer info // err := getConsoleScreenBufferInfo(uintptr(syscall.Stdout), &defScreenInfo) @@ -146,8 +86,10 @@ const ( func EnableVirtualTerminalProcessing(stream syscall.Handle, enable bool) error { var mode uint32 // Check if it is currently in the terminal - err := syscall.GetConsoleMode(syscall.Stdout, &mode) + // err := syscall.GetConsoleMode(syscall.Stdout, &mode) + err := syscall.GetConsoleMode(stream, &mode) if err != nil { + fmt.Println(92, err) return err } @@ -157,7 +99,7 @@ func EnableVirtualTerminalProcessing(stream syscall.Handle, enable bool) error { mode &^= EnableVirtualTerminalProcessingMode } - ret, _, err := procSetConsoleMode.Call(uintptr(unsafe.Pointer(stream)), uintptr(mode)) + ret, _, err := procSetConsoleMode.Call(uintptr(stream), uintptr(mode)) if ret == 0 { return err } @@ -191,157 +133,6 @@ func renderColorCodeOnCmd(fn func()) { * render simple color code on windows *************************************************************/ -// initWinColorsMap init colors to win-colors mapping -func initWinColorsMap() { - // init map - winColorsMap = map[Color]uint16{ - // Foreground colors - FgBlack: winFgBlack, - FgRed: winFgRed, - FgGreen: winFgGreen, - FgYellow: winFgYellow, - FgBlue: winFgBlue, - FgMagenta: winFgPink, // diff - FgCyan: winFgAqua, // diff - FgWhite: winFgWhite, - FgDefault: winFgWhite, - - // Extra Foreground colors - FgDarkGray: winFgGray, - FgLightRed: winFgLightBlue, - FgLightGreen: winFgLightGreen, - FgLightYellow: winFgLightYellow, - FgLightBlue: winFgLightRed, - FgLightMagenta: winFgLightPink, - FgLightCyan: winFgLightAqua, - FgLightWhite: winFgLightWhite, - - // Background colors - BgBlack: winBgBlack, - BgRed: winBgRed, - BgGreen: winBgGreen, - BgYellow: winBgYellow, - BgBlue: winBgBlue, - BgMagenta: winBgPink, // diff - BgCyan: winBgAqua, // diff - BgWhite: winBgWhite, - BgDefault: winBgBlack, - - // Extra Background colors - BgDarkGray: winBgGray, - BgLightRed: winBgLightBlue, - BgLightGreen: winBgLightGreen, - BgLightYellow: winBgLightYellow, - BgLightBlue: winBgLightRed, - BgLightMagenta: winBgLightPink, - BgLightCyan: winBgLightAqua, - BgLightWhite: winBgLightWhite, - - // Option settings(注释掉的,将在win cmd中忽略掉) - // OpReset: winDefSetting, // 重置所有设置 - OpBold: winFgIntensity, // 加粗 -> - // OpFuzzy: // 模糊(不是所有的终端仿真器都支持) - // OpItalic // 斜体(不是所有的终端仿真器都支持) - OpUnderscore: WinOpUnderscore, // 下划线 - // OpBlink // 闪烁 - // OpFastBlink // 快速闪烁(未广泛支持) - // OpReverse: WinOpReverse // 颠倒的 交换背景色与前景色 - // OpConcealed // 隐匿的 - // OpStrikethrough // 删除的,删除线(未广泛支持) - } -} - -// winPrint -func winPrint(str string, colors ...Color) { - _, _ = winInternalPrint(str, colorsToWinAttr(colors), false) -} - -// winPrintln -func winPrintln(str string, colors ...Color) { - _, _ = winInternalPrint(str, colorsToWinAttr(colors), true) -} - -// winInternalPrint -// winInternalPrint("hello [OK];", 2|8, true) //亮绿色 -func winInternalPrint(str string, attribute uint16, newline bool) (int, error) { - if !Enable { // not enable - if newline { - return fmt.Fprintln(output, str) - } - return fmt.Fprint(output, str) - } - - // fmt.Print("attribute val: ", attribute, "\n") - _, _ = setConsoleTextAttr(uintptr(syscall.Stdout), attribute) - if newline { - _, _ = fmt.Fprintln(output, str) - } else { - _, _ = fmt.Fprint(output, str) - } - - // handle, _, _ = procSetTextAttribute.Call(uintptr(syscall.Stdout), winDefSetting) - // closeHandle := kernel32.NewProc("CloseHandle") - // closeHandle.Call(handle) - - return winReset() -} - -// winSet set console color attributes -func winSet(colors ...Color) (int, error) { - // not enable - if !Enable { - return 0, nil - } - - return setConsoleTextAttr(uintptr(syscall.Stdout), colorsToWinAttr(colors)) -} - -// winReset reset color settings to default -func winReset() (int, error) { - // not enable - if !Enable { - return 0, nil - } - - return setConsoleTextAttr(uintptr(syscall.Stdout), winDefSetting) -} - -// colorsToWinAttr convert generic colors to win-colors attribute -func colorsToWinAttr(colors []Color) uint16 { - var setting uint16 - for _, c := range colors { - // check exists - if wc, ok := winColorsMap[c]; ok { - setting |= wc - } - } - - return setting -} - -// getWinColor convert Color to win-color value -func getWinColor(color Color) uint16 { - if wc, ok := winColorsMap[color]; ok { - return wc - } - - return 0 -} - -// setConsoleTextAttr -// ret != 0 is OK. -func setConsoleTextAttr(consoleOutput uintptr, winAttr uint16) (n int, err error) { - // err is type of syscall.Errno - ret, _, err := procSetTextAttribute.Call(consoleOutput, uintptr(winAttr)) - - // if success, err.Error() is equals "The operation completed successfully." - if err != nil && err.Error() == "The operation completed successfully." { - err = nil // set as nil - } - - return int(ret), err -} - // IsTty returns true if the given file descriptor is a terminal. func IsTty(fd uintptr) bool { var st uint32 @@ -359,62 +150,3 @@ func IsTerminal(fd int) bool { r, _, e := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(fd), uintptr(unsafe.Pointer(&st)), 0) return r != 0 && e == 0 } - -/************************************************************* - * some extra utils for windows - *************************************************************/ - -// from package: golang.org/x/sys/windows -type ( - short int16 - word uint16 - - // coord cursor position coordinates - coord struct { - x short - y short - } - - smallRect struct { - left short - top short - right short - bottom short - } - - // Used with GetConsoleScreenBuffer to retrieve information about a console - // screen buffer. See - // https://docs.microsoft.com/en-us/windows/console/console-screen-buffer-info-str - // for details. - consoleScreenBufferInfo struct { - size coord - cursorPosition coord - attributes word // is windows color setting - window smallRect - maximumWindowSize coord - } -) - -// GetSize returns the dimensions of the given terminal. -func getSize(fd int) (width, height int, err error) { - var info consoleScreenBufferInfo - if err := getConsoleScreenBufferInfo(uintptr(fd), &info); err != nil { - return 0, 0, err - } - - return int(info.size.x), int(info.size.y), nil -} - -// from package: golang.org/x/sys/windows -func getConsoleScreenBufferInfo(consoleOutput uintptr, info *consoleScreenBufferInfo) (err error) { - r1, _, e1 := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, consoleOutput, uintptr(unsafe.Pointer(info)), 0) - if r1 == 0 { - if e1 != 0 { - err = e1 - } else { - err = syscall.EINVAL - } - } - - return -} diff --git a/vendor/github.com/gookit/color/go.mod b/vendor/github.com/gookit/color/go.mod index fd738c79..f81dabde 100644 --- a/vendor/github.com/gookit/color/go.mod +++ b/vendor/github.com/gookit/color/go.mod @@ -1,5 +1,5 @@ module github.com/gookit/color -go 1.11 +go 1.12 require github.com/stretchr/testify v1.3.0 diff --git a/vendor/github.com/gookit/color/go.sum b/vendor/github.com/gookit/color/go.sum index 4347755a..8afa960a 100644 --- a/vendor/github.com/gookit/color/go.sum +++ b/vendor/github.com/gookit/color/go.sum @@ -1,7 +1,22 @@ github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-playground/assert v1.2.1 h1:ad06XqC+TOv0nJWnbULSlh3ehp5uLuQEojZY5Tq8RgI= +github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/gookit/color v1.2.9/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg= +github.com/gookit/goutil v0.3.5 h1:95hWrCXcz7wuwlvcHw7YyUbFH0fV15YM0WPioYMcZww= +github.com/gookit/goutil v0.3.5/go.mod h1:OHs5W5Xmfj4pCMXHnMxsDPrCc0SRbHLgJ2qs6wr5fxM= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= diff --git a/vendor/github.com/gookit/color/rgb_to_256.go b/vendor/github.com/gookit/color/rgb_to_256.go new file mode 100644 index 00000000..f29bf262 --- /dev/null +++ b/vendor/github.com/gookit/color/rgb_to_256.go @@ -0,0 +1,307 @@ +package color + +import ( + "fmt" + "math" +) + +// adapted from https://gist.github.com/MicahElliott/719710 + +var ( + lookupTable = map[string]uint8{ // color look-up table + // 8-bit, RGB hex + + // Primary 3-bit (8 colors). Unique representation! + "000000": 0, + "800000": 1, + "008000": 2, + "808000": 3, + "000080": 4, + "800080": 5, + "008080": 6, + "c0c0c0": 7, + + // Equivalent "bright" versions of original 8 colors. + "808080": 8, + "ff0000": 9, + "00ff00": 10, + "ffff00": 11, + "0000ff": 12, + "ff00ff": 13, + "00ffff": 14, + "ffffff": 15, + + // values commented out below are duplicates from the prior sections + + // Strictly ascending. + // "000000": 16, + "00005f": 17, + "000087": 18, + "0000af": 19, + "0000d7": 20, + // "0000ff": 21, + "005f00": 22, + "005f5f": 23, + "005f87": 24, + "005faf": 25, + "005fd7": 26, + "005fff": 27, + "008700": 28, + "00875f": 29, + "008787": 30, + "0087af": 31, + "0087d7": 32, + "0087ff": 33, + "00af00": 34, + "00af5f": 35, + "00af87": 36, + "00afaf": 37, + "00afd7": 38, + "00afff": 39, + "00d700": 40, + "00d75f": 41, + "00d787": 42, + "00d7af": 43, + "00d7d7": 44, + "00d7ff": 45, + // "00ff00": 46, + "00ff5f": 47, + "00ff87": 48, + "00ffaf": 49, + "00ffd7": 50, + // "00ffff": 51, + "5f0000": 52, + "5f005f": 53, + "5f0087": 54, + "5f00af": 55, + "5f00d7": 56, + "5f00ff": 57, + "5f5f00": 58, + "5f5f5f": 59, + "5f5f87": 60, + "5f5faf": 61, + "5f5fd7": 62, + "5f5fff": 63, + "5f8700": 64, + "5f875f": 65, + "5f8787": 66, + "5f87af": 67, + "5f87d7": 68, + "5f87ff": 69, + "5faf00": 70, + "5faf5f": 71, + "5faf87": 72, + "5fafaf": 73, + "5fafd7": 74, + "5fafff": 75, + "5fd700": 76, + "5fd75f": 77, + "5fd787": 78, + "5fd7af": 79, + "5fd7d7": 80, + "5fd7ff": 81, + "5fff00": 82, + "5fff5f": 83, + "5fff87": 84, + "5fffaf": 85, + "5fffd7": 86, + "5fffff": 87, + "870000": 88, + "87005f": 89, + "870087": 90, + "8700af": 91, + "8700d7": 92, + "8700ff": 93, + "875f00": 94, + "875f5f": 95, + "875f87": 96, + "875faf": 97, + "875fd7": 98, + "875fff": 99, + "878700": 100, + "87875f": 101, + "878787": 102, + "8787af": 103, + "8787d7": 104, + "8787ff": 105, + "87af00": 106, + "87af5f": 107, + "87af87": 108, + "87afaf": 109, + "87afd7": 110, + "87afff": 111, + "87d700": 112, + "87d75f": 113, + "87d787": 114, + "87d7af": 115, + "87d7d7": 116, + "87d7ff": 117, + "87ff00": 118, + "87ff5f": 119, + "87ff87": 120, + "87ffaf": 121, + "87ffd7": 122, + "87ffff": 123, + "af0000": 124, + "af005f": 125, + "af0087": 126, + "af00af": 127, + "af00d7": 128, + "af00ff": 129, + "af5f00": 130, + "af5f5f": 131, + "af5f87": 132, + "af5faf": 133, + "af5fd7": 134, + "af5fff": 135, + "af8700": 136, + "af875f": 137, + "af8787": 138, + "af87af": 139, + "af87d7": 140, + "af87ff": 141, + "afaf00": 142, + "afaf5f": 143, + "afaf87": 144, + "afafaf": 145, + "afafd7": 146, + "afafff": 147, + "afd700": 148, + "afd75f": 149, + "afd787": 150, + "afd7af": 151, + "afd7d7": 152, + "afd7ff": 153, + "afff00": 154, + "afff5f": 155, + "afff87": 156, + "afffaf": 157, + "afffd7": 158, + "afffff": 159, + "d70000": 160, + "d7005f": 161, + "d70087": 162, + "d700af": 163, + "d700d7": 164, + "d700ff": 165, + "d75f00": 166, + "d75f5f": 167, + "d75f87": 168, + "d75faf": 169, + "d75fd7": 170, + "d75fff": 171, + "d78700": 172, + "d7875f": 173, + "d78787": 174, + "d787af": 175, + "d787d7": 176, + "d787ff": 177, + "d7af00": 178, + "d7af5f": 179, + "d7af87": 180, + "d7afaf": 181, + "d7afd7": 182, + "d7afff": 183, + "d7d700": 184, + "d7d75f": 185, + "d7d787": 186, + "d7d7af": 187, + "d7d7d7": 188, + "d7d7ff": 189, + "d7ff00": 190, + "d7ff5f": 191, + "d7ff87": 192, + "d7ffaf": 193, + "d7ffd7": 194, + "d7ffff": 195, + // "ff0000": 196, + "ff005f": 197, + "ff0087": 198, + "ff00af": 199, + "ff00d7": 200, + // "ff00ff": 201, + "ff5f00": 202, + "ff5f5f": 203, + "ff5f87": 204, + "ff5faf": 205, + "ff5fd7": 206, + "ff5fff": 207, + "ff8700": 208, + "ff875f": 209, + "ff8787": 210, + "ff87af": 211, + "ff87d7": 212, + "ff87ff": 213, + "ffaf00": 214, + "ffaf5f": 215, + "ffaf87": 216, + "ffafaf": 217, + "ffafd7": 218, + "ffafff": 219, + "ffd700": 220, + "ffd75f": 221, + "ffd787": 222, + "ffd7af": 223, + "ffd7d7": 224, + "ffd7ff": 225, + // "ffff00": 226, + "ffff5f": 227, + "ffff87": 228, + "ffffaf": 229, + "ffffd7": 230, + // "ffffff": 231, + + // Gray-scale range. + "080808": 232, + "121212": 233, + "1c1c1c": 234, + "262626": 235, + "303030": 236, + "3a3a3a": 237, + "444444": 238, + "4e4e4e": 239, + "585858": 240, + "626262": 241, + "6c6c6c": 242, + "767676": 243, + // "808080": 244, + "8a8a8a": 245, + "949494": 246, + "9e9e9e": 247, + "a8a8a8": 248, + "b2b2b2": 249, + "bcbcbc": 250, + "c6c6c6": 251, + "d0d0d0": 252, + "dadada": 253, + "e4e4e4": 254, + "eeeeee": 255, + } + incs = []uint8{0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff} +) + +func rgb2short(r, g, b uint8) uint8 { + res := make([]uint8, 3) + for partI, part := range [3]uint8{r, g, b} { + i := 0 + for i < len(incs)-1 { + s, b := incs[i], incs[i+1] // smaller, bigger + if s <= part && part <= b { + s1 := math.Abs(float64(s) - float64(part)) + b1 := math.Abs(float64(b) - float64(part)) + var closest uint8 + if s1 < b1 { + closest = s + } else { + closest = b + } + res[partI] = closest + break + } + i++ + } + } + hex := fmt.Sprintf("%02x%02x%02x", res[0], res[1], res[2]) + equiv := lookupTable[hex] + return equiv +} diff --git a/vendor/github.com/gookit/color/style.go b/vendor/github.com/gookit/color/style.go index 412efb3b..f2e88121 100644 --- a/vendor/github.com/gookit/color/style.go +++ b/vendor/github.com/gookit/color/style.go @@ -59,17 +59,17 @@ func (s Style) Sprintf(format string, a ...interface{}) string { // Print render and Print text func (s Style) Print(a ...interface{}) { - doPrint(s.String(), s, fmt.Sprint(a...)) + doPrintV2(s.String(), fmt.Sprint(a...)) } // Printf render and print text func (s Style) Printf(format string, a ...interface{}) { - doPrint(s.Code(), s, fmt.Sprintf(format, a...)) + doPrintV2(s.Code(), fmt.Sprintf(format, a...)) } // Println render and print text line func (s Style) Println(a ...interface{}) { - doPrintln(s.String(), s, a) + doPrintlnV2(s.String(), a) } // Code convert to code string. returns like "32;45;3" @@ -157,7 +157,7 @@ var ( // Notice color style Notice = &Theme{"notice", Style{OpBold, FgCyan}} // Comment color style - Comment = &Theme{"comment", Style{OpReset, FgLightYellow}} + Comment = &Theme{"comment", Style{OpReset, FgYellow}} // Success color style Success = &Theme{"success", Style{OpBold, FgGreen}} // Primary color style @@ -249,3 +249,37 @@ func GetStyle(name string) Style { // empty style return New() } + +/************************************************************* + * quick use style print message + *************************************************************/ + +// Infof print message with Info style +func Infof(format string, a ...interface{}) { + Info.Printf(format, a...) +} + +// Infoln print message with Info style +func Infoln(a ...interface{}) { + Info.Println(a...) +} + +// Errorf print message with Error style +func Errorf(format string, a ...interface{}) { + Error.Printf(format, a...) +} + +// Errorln print message with Error style +func Errorln(a ...interface{}) { + Error.Println(a...) +} + +// Warnf print message with Warn style +func Warnf(format string, a ...interface{}) { + Warn.Printf(format, a...) +} + +// Warnln print message with Warn style +func Warnln(a ...interface{}) { + Warn.Println(a...) +} diff --git a/vendor/github.com/gookit/color/tag.go b/vendor/github.com/gookit/color/tag.go index 50daa404..5963b3b5 100644 --- a/vendor/github.com/gookit/color/tag.go +++ b/vendor/github.com/gookit/color/tag.go @@ -2,8 +2,6 @@ package color import ( "fmt" - "io" - "log" "regexp" "strings" ) @@ -108,115 +106,14 @@ var colorTags = map[string]string{ "reverse": "7", } -/************************************************************* - * print methods(will auto parse color tags) - *************************************************************/ - -// Print render color tag and print messages -func Print(a ...interface{}) { - Fprint(output, a...) -} - -// Printf format and print messages -func Printf(format string, a ...interface{}) { - Fprintf(output, format, a...) -} - -// Println messages with new line -func Println(a ...interface{}) { - Fprintln(output, a...) -} - -// Fprint print rendered messages to writer -// Notice: will ignore print error -func Fprint(w io.Writer, a ...interface{}) { - if isLikeInCmd { - renderColorCodeOnCmd(func() { - _, _ = fmt.Fprint(w, Render(a...)) - }) - } else { - _, _ = fmt.Fprint(w, Render(a...)) - } -} - -// Fprintf print format and rendered messages to writer. -// Notice: will ignore print error -func Fprintf(w io.Writer, format string, a ...interface{}) { - str := fmt.Sprintf(format, a...) - if isLikeInCmd { - renderColorCodeOnCmd(func() { - _, _ = fmt.Fprint(w, ReplaceTag(str)) - }) - } else { - _, _ = fmt.Fprint(w, ReplaceTag(str)) - } -} - -// Fprintln print rendered messages line to writer -// Notice: will ignore print error -func Fprintln(w io.Writer, a ...interface{}) { - str := formatArgsForPrintln(a) - if isLikeInCmd { - renderColorCodeOnCmd(func() { - _, _ = fmt.Fprintln(w, ReplaceTag(str)) - }) - } else { - _, _ = fmt.Fprintln(w, ReplaceTag(str)) - } -} - -// Lprint passes colored messages to a log.Logger for printing. -// Notice: should be goroutine safe -func Lprint(l *log.Logger, a ...interface{}) { - if isLikeInCmd { - renderColorCodeOnCmd(func() { - l.Print(Render(a...)) - }) - } else { - l.Print(Render(a...)) - } -} - -// Render parse color tags, return rendered string. -// Usage: -// text := Render("hello world!") -// fmt.Println(text) -func Render(a ...interface{}) string { - if len(a) == 0 { - return "" - } - - return ReplaceTag(fmt.Sprint(a...)) -} - -// Sprint parse color tags, return rendered string -func Sprint(args ...interface{}) string { - return Render(args...) -} - -// Sprintf format and return rendered string -func Sprintf(format string, a ...interface{}) string { - return ReplaceTag(fmt.Sprintf(format, a...)) -} - -// String alias of the ReplaceTag -func String(s string) string { - return ReplaceTag(s) -} - -// Text alias of the ReplaceTag -func Text(s string) string { - return ReplaceTag(s) -} - /************************************************************* * parse color tags *************************************************************/ // ReplaceTag parse string, replace color tag and return rendered string func ReplaceTag(str string) string { - // not contains color tag - if !strings.Contains(str, "") { + // disable handler TAG OR not contains color tag + if !RenderTag || !strings.Contains(str, "") { return str } diff --git a/vendor/github.com/gookit/color/utils.go b/vendor/github.com/gookit/color/utils.go index 1a28bea2..4b3a5fe6 100644 --- a/vendor/github.com/gookit/color/utils.go +++ b/vendor/github.com/gookit/color/utils.go @@ -3,8 +3,11 @@ package color import ( "fmt" "io" + "log" "os" + "strconv" "strings" + "syscall" ) // Support color: @@ -17,22 +20,26 @@ import ( // Don't support color: // "TERM=cygwin" var specialColorTerms = map[string]bool{ + "alacritty": true, "screen-256color": true, "tmux-256color": true, "rxvt-unicode-256color": true, } -// IsConsole 判断 w 是否为 stderr、stdout、stdin 三者之一 -func IsConsole(out io.Writer) bool { - o, ok := out.(*os.File) +// IsConsole Determine whether w is one of stderr, stdout, stdin +func IsConsole(w io.Writer) bool { + o, ok := w.(*os.File) if !ok { return false } - return o == os.Stdout || o == os.Stderr || o == os.Stdin + fd := o.Fd() + + // fix: cannot use 'o == os.Stdout' to compare + return fd == uintptr(syscall.Stdout) || fd == uintptr(syscall.Stdin) || fd == uintptr(syscall.Stderr) } -// IsMSys msys(MINGW64) 环境,不一定支持颜色 +// IsMSys msys(MINGW64) environment, does not necessarily support color func IsMSys() bool { // like "MSYSTEM=MINGW64" if len(os.Getenv("MSYSTEM")) > 0 { @@ -69,7 +76,8 @@ func IsSupportColor() bool { return true } - return false + // up: if support 256-color, can also support basic color. + return IsSupport256Color() } // IsSupport256Color render @@ -78,7 +86,13 @@ func IsSupport256Color() bool { // "TERM=screen-256color" // "TERM=tmux-256color" // "TERM=rxvt-unicode-256color" - return strings.Contains(os.Getenv("TERM"), "256color") + supported := strings.Contains(os.Getenv("TERM"), "256color") + if !supported { + // up: if support true-color, can also support 256-color. + supported = IsSupportTrueColor() + } + + return supported } // IsSupportTrueColor render. IsSupportRGBColor @@ -87,47 +101,224 @@ func IsSupportTrueColor() bool { return strings.Contains(os.Getenv("COLORTERM"), "truecolor") } +// Hex2rgb alias of the HexToRgb() +func Hex2rgb(hex string) []int { return HexToRgb(hex) } + +// HexToRGB alias of the HexToRgb() +func HexToRGB(hex string) []int { return HexToRgb(hex) } + +// HexToRgb convert hex color string to RGB numbers +// Usage: +// rgb := HexToRgb("ccc") // rgb: [204 204 204] +// rgb := HexToRgb("aabbcc") // rgb: [170 187 204] +// rgb := HexToRgb("#aabbcc") // rgb: [170 187 204] +// rgb := HexToRgb("0xad99c0") // rgb: [170 187 204] +func HexToRgb(hex string) (rgb []int) { + hex = strings.TrimSpace(hex) + if hex == "" { + return + } + + // like from css. eg "#ccc" "#ad99c0" + if hex[0] == '#' { + hex = hex[1:] + } + + hex = strings.ToLower(hex) + switch len(hex) { + case 3: // "ccc" + hex = string([]byte{hex[0], hex[0], hex[1], hex[1], hex[2], hex[2]}) + case 8: // "0xad99c0" + hex = strings.TrimPrefix(hex, "0x") + } + + // recheck + if len(hex) != 6 { + return + } + + // convert string to int64 + if i64, err := strconv.ParseInt(hex, 16, 32); err == nil { + color := int(i64) + // parse int + rgb = make([]int, 3) + rgb[0] = color >> 16 + rgb[1] = (color & 0x00FF00) >> 8 + rgb[2] = color & 0x0000FF + } + + return +} + +// Rgb2hex alias of the RgbToHex() +func Rgb2hex(rgb []int) string { return RgbToHex(rgb) } + +// RgbToHex convert RGB to hex code +// Usage: +// hex := RgbToHex([]int{170, 187, 204}) // hex: "aabbcc" +func RgbToHex(rgb []int) string { + hexNodes := make([]string, len(rgb)) + for _, v := range rgb { + hexNodes = append(hexNodes, strconv.FormatInt(int64(v), 16)) + } + + return strings.Join(hexNodes, "") +} + +/************************************************************* + * print methods(will auto parse color tags) + *************************************************************/ + +// Print render color tag and print messages +func Print(a ...interface{}) { + Fprint(output, a...) +} + +// Printf format and print messages +func Printf(format string, a ...interface{}) { + Fprintf(output, format, a...) +} + +// Println messages with new line +func Println(a ...interface{}) { + Fprintln(output, a...) +} + +// Fprint print rendered messages to writer +// Notice: will ignore print error +func Fprint(w io.Writer, a ...interface{}) { + _, err := fmt.Fprint(w, Render(a...)) + saveInternalError(err) + + // if isLikeInCmd { + // renderColorCodeOnCmd(func() { + // _, _ = fmt.Fprint(w, Render(a...)) + // }) + // } else { + // _, _ = fmt.Fprint(w, Render(a...)) + // } +} + +// Fprintf print format and rendered messages to writer. +// Notice: will ignore print error +func Fprintf(w io.Writer, format string, a ...interface{}) { + str := fmt.Sprintf(format, a...) + _, err := fmt.Fprint(w, ReplaceTag(str)) + saveInternalError(err) + + // if isLikeInCmd { + // renderColorCodeOnCmd(func() { + // _, _ = fmt.Fprint(w, ReplaceTag(str)) + // }) + // } else { + // _, _ = fmt.Fprint(w, ReplaceTag(str)) + // } +} + +// Fprintln print rendered messages line to writer +// Notice: will ignore print error +func Fprintln(w io.Writer, a ...interface{}) { + str := formatArgsForPrintln(a) + _, err := fmt.Fprintln(w, ReplaceTag(str)) + saveInternalError(err) + + // if isLikeInCmd { + // renderColorCodeOnCmd(func() { + // _, _ = fmt.Fprintln(w, ReplaceTag(str)) + // }) + // } else { + // _, _ = fmt.Fprintln(w, ReplaceTag(str)) + // } +} + +// Lprint passes colored messages to a log.Logger for printing. +// Notice: should be goroutine safe +func Lprint(l *log.Logger, a ...interface{}) { + l.Print(Render(a...)) + + // if isLikeInCmd { + // renderColorCodeOnCmd(func() { + // l.Print(Render(a...)) + // }) + // } else { + // l.Print(Render(a...)) + // } +} + +// Render parse color tags, return rendered string. +// Usage: +// text := Render("hello world!") +// fmt.Println(text) +func Render(a ...interface{}) string { + if len(a) == 0 { + return "" + } + + return ReplaceTag(fmt.Sprint(a...)) +} + +// Sprint parse color tags, return rendered string +func Sprint(args ...interface{}) string { + return Render(args...) +} + +// Sprintf format and return rendered string +func Sprintf(format string, a ...interface{}) string { + return ReplaceTag(fmt.Sprintf(format, a...)) +} + +// String alias of the ReplaceTag +func String(s string) string { + return ReplaceTag(s) +} + +// Text alias of the ReplaceTag +func Text(s string) string { + return ReplaceTag(s) +} + +/************************************************************* + * helper methods for print + *************************************************************/ + // its Win system. linux windows darwin // func isWindows() bool { // return runtime.GOOS == "windows" // } -func doPrint(code string, colors []Color, str string) { - if isLikeInCmd { - winPrint(str, colors...) - } else { - _, _ = fmt.Fprint(output, RenderString(code, str)) - } -} - -func doPrintln(code string, colors []Color, args []interface{}) { - str := formatArgsForPrintln(args) - if isLikeInCmd { - winPrintln(str, colors...) - } else { - _, _ = fmt.Fprintln(output, RenderString(code, str)) +func saveInternalError(err error) { + if err != nil { + errors = append(errors, err) } } +// new implementation, support render full color code on pwsh.exe, cmd.exe func doPrintV2(code, str string) { - if isLikeInCmd { - renderColorCodeOnCmd(func() { - _, _ = fmt.Fprint(output, RenderString(code, str)) - }) - } else { - _, _ = fmt.Fprint(output, RenderString(code, str)) - } + _, err := fmt.Fprint(output, RenderString(code, str)) + saveInternalError(err) + + // if isLikeInCmd { + // renderColorCodeOnCmd(func() { + // _, _ = fmt.Fprint(output, RenderString(code, str)) + // }) + // } else { + // _, _ = fmt.Fprint(output, RenderString(code, str)) + // } } +// new implementation, support render full color code on pwsh.exe, cmd.exe func doPrintlnV2(code string, args []interface{}) { str := formatArgsForPrintln(args) - if isLikeInCmd { - renderColorCodeOnCmd(func() { - _, _ = fmt.Fprintln(output, RenderString(code, str)) - }) - } else { - _, _ = fmt.Fprintln(output, RenderString(code, str)) - } + _, err := fmt.Fprintln(output, RenderString(code, str)) + saveInternalError(err) + + // if isLikeInCmd { + // renderColorCodeOnCmd(func() { + // _, _ = fmt.Fprintln(output, RenderString(code, str)) + // }) + // } else { + // _, _ = fmt.Fprintln(output, RenderString(code, str)) + // } } func stringToArr(str, sep string) (arr []string) { @@ -142,7 +333,6 @@ func stringToArr(str, sep string) (arr []string) { arr = append(arr, val) } } - return } diff --git a/vendor/github.com/itchyny/astgen-go/LICENSE b/vendor/github.com/itchyny/astgen-go/LICENSE index b973043c..fcccadc5 100644 --- a/vendor/github.com/itchyny/astgen-go/LICENSE +++ b/vendor/github.com/itchyny/astgen-go/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2019 itchyny +Copyright (c) 2019,2020 itchyny Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/github.com/itchyny/astgen-go/Makefile b/vendor/github.com/itchyny/astgen-go/Makefile index 0ff8dd92..bacef7bf 100644 --- a/vendor/github.com/itchyny/astgen-go/Makefile +++ b/vendor/github.com/itchyny/astgen-go/Makefile @@ -2,7 +2,7 @@ GOBIN ?= $(shell go env GOPATH)/bin export GO111MODULE=on .PHONY: all -all: clean test +all: test .PHONY: test test: diff --git a/vendor/github.com/itchyny/astgen-go/README.md b/vendor/github.com/itchyny/astgen-go/README.md index e8513b54..e103c604 100644 --- a/vendor/github.com/itchyny/astgen-go/README.md +++ b/vendor/github.com/itchyny/astgen-go/README.md @@ -1 +1,60 @@ -# astgen-go [![CI Status](https://github.com/itchyny/astgen-go/workflows/CI/badge.svg)](https://github.com/itchyny/astgen-go/actions) +# astgen-go +[![CI Status](https://github.com/itchyny/astgen-go/workflows/CI/badge.svg)](https://github.com/itchyny/astgen-go/actions) +[![Go Report Card](https://goreportcard.com/badge/github.com/itchyny/astgen-go)](https://goreportcard.com/report/github.com/itchyny/astgen-go) +[![MIT License](http://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/itchyny/astgen-go/blob/master/LICENSE) +[![pkg.go.dev](https://pkg.go.dev/badge/github.com/itchyny/astgen-go)](https://pkg.go.dev/github.com/itchyny/astgen-go) + +Build Go code from arbitrary value in Go. + +## Usage +```go +package main + +import ( + "go/printer" + "go/token" + "log" + "os" + + "github.com/itchyny/astgen-go" +) + +type X struct { + x int + y Y + z *Z +} + +type Y struct { + y int +} + +type Z struct { + s string + t map[string]int +} + +func main() { + x := &X{1, Y{2}, &Z{"hello", map[string]int{"x": 42}}} + t, err := astgen.Build(x) + if err != nil { + log.Fatal(err) + } + err = printer.Fprint(os.Stdout, token.NewFileSet(), t) + if err != nil { + log.Fatal(err) + } +} +``` +```go +&X{x: 1, y: Y{y: 2}, z: &Z{s: "hello", t: map[string]int{"x": 42}}} +``` + +## Bug Tracker +Report bug at [Issues・itchyny/astgen-go - GitHub](https://github.com/itchyny/astgen-go/issues). + +## Author +itchyny (https://github.com/itchyny) + +## License +This software is released under the MIT License, see LICENSE. diff --git a/vendor/github.com/itchyny/astgen-go/build.go b/vendor/github.com/itchyny/astgen-go/build.go index 2c8ca63f..dc0545d3 100644 --- a/vendor/github.com/itchyny/astgen-go/build.go +++ b/vendor/github.com/itchyny/astgen-go/build.go @@ -63,7 +63,7 @@ func (b *builder) build(v reflect.Value) (ast.Node, error) { } prevType = bv.typ params = append(params, &ast.Field{ - Names: []*ast.Ident{&ast.Ident{Name: bv.name}}, + Names: []*ast.Ident{{Name: bv.name}}, Type: bv.typ, }) } @@ -74,7 +74,7 @@ func (b *builder) build(v reflect.Value) (ast.Node, error) { Params: &ast.FieldList{List: params}, Results: &ast.FieldList{ List: []*ast.Field{ - &ast.Field{Type: t}, + {Type: t}, }, }, }, diff --git a/vendor/github.com/itchyny/astgen-go/go.mod b/vendor/github.com/itchyny/astgen-go/go.mod index b17c5763..9c0464b4 100644 --- a/vendor/github.com/itchyny/astgen-go/go.mod +++ b/vendor/github.com/itchyny/astgen-go/go.mod @@ -1,5 +1,3 @@ module github.com/itchyny/astgen-go -go 1.12 - -require github.com/stretchr/testify v1.3.0 +go 1.14 diff --git a/vendor/github.com/itchyny/astgen-go/go.sum b/vendor/github.com/itchyny/astgen-go/go.sum deleted file mode 100644 index 4347755a..00000000 --- a/vendor/github.com/itchyny/astgen-go/go.sum +++ /dev/null @@ -1,7 +0,0 @@ -github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= diff --git a/vendor/github.com/itchyny/astgen-go/type.go b/vendor/github.com/itchyny/astgen-go/type.go index efbfc34d..9de9c5eb 100644 --- a/vendor/github.com/itchyny/astgen-go/type.go +++ b/vendor/github.com/itchyny/astgen-go/type.go @@ -61,7 +61,7 @@ func buildType(t reflect.Type) (ast.Expr, error) { tag = &ast.BasicLit{Value: "`" + string(sf.Tag) + "`"} } fs = append(fs, &ast.Field{ - Names: []*ast.Ident{&ast.Ident{Name: sf.Name}}, + Names: []*ast.Ident{{Name: sf.Name}}, Type: t, Tag: tag, }) diff --git a/vendor/github.com/itchyny/gojq/.dockerignore b/vendor/github.com/itchyny/gojq/.dockerignore new file mode 100644 index 00000000..1187229a --- /dev/null +++ b/vendor/github.com/itchyny/gojq/.dockerignore @@ -0,0 +1,8 @@ +/goxz +/gojq +/._* +/y.output +*.exe +*.test +*.out +/.github/ diff --git a/vendor/github.com/itchyny/gojq/.gitignore b/vendor/github.com/itchyny/gojq/.gitignore index ed19b9f7..e350f930 100644 --- a/vendor/github.com/itchyny/gojq/.gitignore +++ b/vendor/github.com/itchyny/gojq/.gitignore @@ -1,3 +1,8 @@ -/goxz /gojq +/goxz +/CREDITS /._* +/y.output +*.exe +*.test +*.out diff --git a/vendor/github.com/itchyny/gojq/CHANGELOG.md b/vendor/github.com/itchyny/gojq/CHANGELOG.md index 8370df28..abb66c22 100644 --- a/vendor/github.com/itchyny/gojq/CHANGELOG.md +++ b/vendor/github.com/itchyny/gojq/CHANGELOG.md @@ -1,4 +1,44 @@ # Changelog +## [v0.11.2](https://github.com/itchyny/gojq/compare/v0.11.1..v0.11.2) (2020-10-01) +* fix build for 32bit architecture +* release to [GitHub Container Registry](https://github.com/users/itchyny/packages/container/package/gojq) + +## [v0.11.1](https://github.com/itchyny/gojq/compare/v0.11.0..v0.11.1) (2020-08-22) +* improve compatibility of `strftime`, `strptime` functions with jq +* fix YAML input with numbers in keys +* fix crash on multiplying a large number or `infinite` to a string +* fix crash on error while slicing a string (`""[:{}]`) +* fix crash on modulo by a number near 0.0 (`1 % 0.1`) +* include `CREDITS` file in artifacts + +## [v0.11.0](https://github.com/itchyny/gojq/compare/v0.10.4..v0.11.0) (2020-07-08) +* improve parsing performance significantly +* rewrite the parser from `participle` library to `goyacc` generated parser +* release to [itchyny/gojq - Docker Hub](https://hub.docker.com/r/itchyny/gojq) +* support string interpolation for object pattern key + +## [v0.10.4](https://github.com/itchyny/gojq/compare/v0.10.3..v0.10.4) (2020-06-30) +* implement variable in object key (`. as $x | { $x: 1 }`) +* fix modify operator (`|=`) with `try` `catch` expression +* fix optional operator (`?`) with alternative operator (`//`) in `map_values` function +* fix normalizing numeric types for library users +* export `gojq.NewModuleLoader` function for library users + +## [v0.10.3](https://github.com/itchyny/gojq/compare/v0.10.2..v0.10.3) (2020-06-06) +* implement `add`, `unique_by`, `max_by`, `min_by`, `reverse` by internal + functions for performance and reducing the binary size +* improve performance of `setpath`, `delpaths` functions +* fix assignment against nested slicing (`[1,2,3] | .[1:][:1] = [5]`) +* limit the array index of assignment operator +* optimize constant arrays and objects + +## [v0.10.2](https://github.com/itchyny/gojq/compare/v0.10.1..v0.10.2) (2020-05-24) +* implement `sort_by`, `group_by`, `bsearch` by internal functions for performance + and reducing the binary size +* fix object construction and constant object to allow trailing commas +* fix `tonumber` function to allow leading zeros +* minify the builtin functions to reduce the binary size + ## [v0.10.1](https://github.com/itchyny/gojq/compare/v0.10.0..v0.10.1) (2020-04-24) * fix array addition not to modify the left hand side @@ -92,7 +132,6 @@ * implement `setpath` function ## [v0.3.0](https://github.com/itchyny/gojq/compare/v0.2.0..v0.3.0) (2019-06-05) - * implement `reduce`, `foreach`, `label`, `break` syntax * improve binding variable syntax to bind to an object or an array * implement string interpolation @@ -121,7 +160,6 @@ * implement `-s` flag for reading all inputs into an array ## [v0.2.0](https://github.com/itchyny/gojq/compare/v0.1.0..v0.2.0) (2019-05-06) - * implement binding variable syntax (`... as $var`) * implement `try` `catch` syntax * implement alternative operator (`//`) @@ -133,7 +171,6 @@ * support indexing against strings ## [v0.1.0](https://github.com/itchyny/gojq/compare/v0.0.1..v0.1.0) (2019-05-02) - * implement binary operators (`+`, `-`, `*`, `/`, `%`, `==`, `!=`, `>`, `<`, `>=`, `<=`, `and`, `or`) * implement unary operators (`+`, `-`) @@ -153,5 +190,4 @@ * support json file name arguments ## [v0.0.1](https://github.com/itchyny/gojq/compare/0fa3241..v0.0.1) (2019-04-14) - * initial implementation diff --git a/vendor/github.com/itchyny/gojq/Dockerfile b/vendor/github.com/itchyny/gojq/Dockerfile new file mode 100644 index 00000000..97eeae60 --- /dev/null +++ b/vendor/github.com/itchyny/gojq/Dockerfile @@ -0,0 +1,12 @@ +FROM golang:1.14 as builder + +WORKDIR /app +COPY . . +ENV CGO_ENABLED 0 +RUN make build + +FROM alpine:3.12 + +COPY --from=builder /app/gojq /usr/local/bin/ +ENTRYPOINT ["/usr/local/bin/gojq"] +CMD ["--help"] diff --git a/vendor/github.com/itchyny/gojq/Makefile b/vendor/github.com/itchyny/gojq/Makefile index 6e7c4ec8..a19ace66 100644 --- a/vendor/github.com/itchyny/gojq/Makefile +++ b/vendor/github.com/itchyny/gojq/Makefile @@ -7,25 +7,40 @@ GOBIN ?= $(shell go env GOPATH)/bin export GO111MODULE=on .PHONY: all -all: clean build +all: build .PHONY: build -build: builtin.go string.go +build: + go build -ldflags=$(BUILD_LDFLAGS) -o $(BIN) ./cmd/$(BIN) + +.PHONY: build-dev +build-dev: parser.go builtin.go go build -ldflags=$(BUILD_LDFLAGS) -o $(BIN) ./cmd/$(BIN) .PHONY: build-debug -build-debug: builtin.go string.go +build-debug: parser.go builtin.go go build -tags debug -ldflags=$(BUILD_LDFLAGS) -o $(BIN) ./cmd/$(BIN) -builtin.go string.go: builtin.jq parser.go query.go operator.go _tools/* +builtin.go: builtin.jq parser.go.y parser.go query.go operator.go _tools/* GOOS= GOARCH= go generate +.SUFFIXES: +parser.go: parser.go.y lexer.go $(GOBIN)/goyacc + goyacc -o $@ $< + +$(GOBIN)/goyacc: + @cd && go get golang.org/x/tools/cmd/goyacc + .PHONY: install -install: builtin.go string.go +install: + go install -ldflags=$(BUILD_LDFLAGS) ./... + +.PHONY: install-dev +install-dev: parser.go builtin.go go install -ldflags=$(BUILD_LDFLAGS) ./... .PHONY: install-debug -install-debug: builtin.go string.go +install-debug: parser.go builtin.go go install -tags debug -ldflags=$(BUILD_LDFLAGS) ./... .PHONY: show-version @@ -36,18 +51,26 @@ $(GOBIN)/gobump: @cd && go get github.com/x-motemen/gobump/cmd/gobump .PHONY: cross -cross: $(GOBIN)/goxz +cross: $(GOBIN)/goxz CREDITS goxz -n $(BIN) -pv=v$(VERSION) -include _$(BIN) -build-ldflags=$(BUILD_LDFLAGS) ./cmd/$(BIN) $(GOBIN)/goxz: cd && go get github.com/Songmu/goxz/cmd/goxz +CREDITS: $(GOBIN)/gocredits go.sum + go mod tidy + gocredits -w . + +$(GOBIN)/gocredits: + cd && go get github.com/Songmu/gocredits/cmd/gocredits + .PHONY: test test: build go test -v ./... .PHONY: lint lint: $(GOBIN)/golint + go vet ./... golint -set_exit_status ./... $(GOBIN)/golint: @@ -66,7 +89,7 @@ check-tools: .PHONY: clean clean: - rm -rf $(BIN) goxz + rm -rf $(BIN) goxz CREDITS go clean .PHONY: bump diff --git a/vendor/github.com/itchyny/gojq/README.md b/vendor/github.com/itchyny/gojq/README.md index 5ab0c47f..fbe6368e 100644 --- a/vendor/github.com/itchyny/gojq/README.md +++ b/vendor/github.com/itchyny/gojq/README.md @@ -1,5 +1,13 @@ -# gojq [![CI Status](https://github.com/itchyny/gojq/workflows/CI/badge.svg)](https://github.com/itchyny/gojq/actions) -Pure Go implementation of [jq](https://github.com/stedolan/jq). +# gojq +[![CI Status](https://github.com/itchyny/gojq/workflows/CI/badge.svg)](https://github.com/itchyny/gojq/actions) +[![Go Report Card](https://goreportcard.com/badge/github.com/itchyny/gojq)](https://goreportcard.com/report/github.com/itchyny/gojq) +[![MIT License](http://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/itchyny/gojq/blob/master/LICENSE) +[![release](https://img.shields.io/github/release/itchyny/gojq/all.svg)](https://github.com/itchyny/gojq/releases) +[![pkg.go.dev](https://pkg.go.dev/badge/github.com/itchyny/gojq)](https://pkg.go.dev/github.com/itchyny/gojq) + +### Pure Go implementation of [jq](https://github.com/stedolan/jq) +This is an implementation of jq command written in Go language. +You can also embed gojq as a library to your Go products. ## Usage ```sh @@ -49,8 +57,13 @@ brew install itchyny/tap/gojq ``` ### Build from source -```bash -go get -u github.com/itchyny/gojq/cmd/gojq +```sh +go get github.com/itchyny/gojq/cmd/gojq +``` + +### Docker +```sh +docker run -i --rm itchyny/gojq ``` ## Difference to jq @@ -102,7 +115,7 @@ func main() { [`gojq.Compile`](https://pkg.go.dev/github.com/itchyny/gojq?tab=doc#Compile) allows to configure the following compiler options. -- [`gojq.WithModuleLoader`](https://pkg.go.dev/github.com/itchyny/gojq?tab=doc#WithModuleLoader) allows to load modules. By default, the module feature is disabled. +- [`gojq.WithModuleLoader`](https://pkg.go.dev/github.com/itchyny/gojq?tab=doc#WithModuleLoader) allows to load modules. By default, the module feature is disabled. If you want to load modules from the filesystem, use [`gojq.NewModuleLoader`](https://pkg.go.dev/github.com/itchyny/gojq?tab=doc#NewModuleLoader). - [`gojq.WithEnvironLoader`](https://pkg.go.dev/github.com/itchyny/gojq?tab=doc#WithEnvironLoader) allows to configure the environment variables referenced by `env` and `$ENV`. By default, OS environment variables are not accessible due to security reason. You can use `gojq.WithEnvironLoader(os.Environ)` if you want. - [`gojq.WithVariables`](https://pkg.go.dev/github.com/itchyny/gojq?tab=doc#WithVariables) allows to configure the variables which can be used in the query. Pass the values of the variables to [`code.Run`](https://pkg.go.dev/github.com/itchyny/gojq?tab=doc#Code.Run) in the same order. - [`gojq.WithInputIter`](https://pkg.go.dev/github.com/itchyny/gojq?tab=doc#WithInputIter) allows to use `input` and `inputs` functions. By default, these functions are disabled. diff --git a/vendor/github.com/itchyny/gojq/_gojq b/vendor/github.com/itchyny/gojq/_gojq index b4d3184c..ae4198b2 100644 --- a/vendor/github.com/itchyny/gojq/_gojq +++ b/vendor/github.com/itchyny/gojq/_gojq @@ -6,7 +6,7 @@ _gojq() '(-c --compact-output)'{-c,--compact-output}'[compact output]' \ '(-r --raw-output)'{-r,--raw-output}'[output raw strings]' \ '(-j --join-output)'{-j,--join-output}'[stop printing a newline after each output]' \ - '(-0 --nul-output)'{-0,--nul-output}'[print NUL after each ouput]' \ + '(-0 --nul-output)'{-0,--nul-output}'[print NUL after each output]' \ '(-C --color-output)'{-C,--color-output}'[colorize output even if piped]' \ '(-M --monochrome-output)'{-M,--monochrome-output}'[stop colorizing output]' \ '(--yaml-output)'--yaml-output'[output by YAML]' \ diff --git a/vendor/github.com/itchyny/gojq/builtin.go b/vendor/github.com/itchyny/gojq/builtin.go index 060fe021..bf82d464 100644 --- a/vendor/github.com/itchyny/gojq/builtin.go +++ b/vendor/github.com/itchyny/gojq/builtin.go @@ -4,86 +4,83 @@ package gojq func init() { builtinFuncDefs = map[string][]*FuncDef{ - "IN": []*FuncDef{&FuncDef{Name: "IN", Args: []string{"s"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "any", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "s"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "IN", Args: []string{"src", "s"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "any", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "src"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "s"}}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "INDEX": []*FuncDef{&FuncDef{Name: "INDEX", Args: []string{"stream", "idx_expr"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Reduce: &Reduce{Term: &Term{Func: &Func{Name: "stream"}}, Pattern: &Pattern{Name: "$row"}, Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Object: &Object{}}}}}}}}}}}}}}, Update: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$row"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "idx_expr"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "tostring"}}}}}}}}}}}}}}}}}}}}}, UpdateOp: OpAssign, Update: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$row"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "INDEX", Args: []string{"idx_expr"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "INDEX", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "idx_expr"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "JOIN": []*FuncDef{&FuncDef{Name: "JOIN", Args: []string{"$idx", "idx_expr"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}, &Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$idx"}, SuffixList: []*Suffix{&Suffix{SuffixIndex: &SuffixIndex{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "idx_expr"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "JOIN", Args: []string{"$idx", "stream", "idx_expr"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "stream"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}, &Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$idx"}, SuffixList: []*Suffix{&Suffix{SuffixIndex: &SuffixIndex{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "idx_expr"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "JOIN", Args: []string{"$idx", "stream", "idx_expr", "join_expr"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "stream"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}, &Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$idx"}, SuffixList: []*Suffix{&Suffix{SuffixIndex: &SuffixIndex{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "idx_expr"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "join_expr"}}}}}}}}}}}}}}}}, - "add": []*FuncDef{&FuncDef{Name: "add", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Reduce: &Reduce{Term: &Term{Identity: true, SuffixList: []*Suffix{&Suffix{Iter: true}}}, Pattern: &Pattern{Name: "$x"}, Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Null: true}}}}}}}}}}}}}, Update: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "all": []*FuncDef{&FuncDef{Name: "all", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "all", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "all", Args: []string{"y"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "all", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "y"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "all", Args: []string{"g", "y"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "isempty", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "g"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "y"}}}}}, Right: []AndExprRight{AndExprRight{Op: OpAnd, Right: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "empty"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "any": []*FuncDef{&FuncDef{Name: "any", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "any", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "any", Args: []string{"y"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "any", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "y"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "any", Args: []string{"g", "y"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "isempty", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "g"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "y"}}}}}}, Right: []LogicRight{LogicRight{Op: OpOr, Right: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "empty"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "not"}}}}}}}}}}}}}}}}, - "arrays": []*FuncDef{&FuncDef{Name: "arrays", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "select", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"array"`}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "ascii_downcase": []*FuncDef{&FuncDef{Name: "ascii_downcase", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "explode"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "map", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "65"}}}, Right: &CompareRight{Op: OpLe, Right: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}, Right: []AndExprRight{AndExprRight{Op: OpAnd, Right: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}, Right: &CompareRight{Op: OpLe, Right: &Arith{Left: &Factor{Left: &Term{Number: "90"}}}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Number: "32"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "implode"}}}}}}}}}}}}}}}}, - "ascii_upcase": []*FuncDef{&FuncDef{Name: "ascii_upcase", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "explode"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "map", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "97"}}}, Right: &CompareRight{Op: OpLe, Right: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}, Right: []AndExprRight{AndExprRight{Op: OpAnd, Right: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}, Right: &CompareRight{Op: OpLe, Right: &Arith{Left: &Factor{Left: &Term{Number: "122"}}}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}, Right: []ArithRight{ArithRight{Op: OpSub, Right: &Factor{Left: &Term{Number: "32"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "implode"}}}}}}}}}}}}}}}}, - "assign": []*FuncDef{&FuncDef{Name: "_assign", Args: []string{"ps", "$v"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Reduce: &Reduce{Term: &Term{Func: &Func{Name: "path", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "ps"}}}}}}}}}}}}}}}}}, Pattern: &Pattern{Name: "$p"}, Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}}}}}, Update: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "setpath", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$p"}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$v"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "booleans": []*FuncDef{&FuncDef{Name: "booleans", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "select", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"boolean"`}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "bsearch": []*FuncDef{&FuncDef{Name: "bsearch", Args: []string{"$target"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "length"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Unary: &Unary{Op: OpSub, Term: &Term{Number: "1"}}}}}}}}}}}}}}}, Elif: []IfElif{IfElif{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "length"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$target"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}, Elif: []IfElif{IfElif{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$target"}}}}, Right: &CompareRight{Op: OpLt, Right: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Unary: &Unary{Op: OpSub, Term: &Term{Number: "1"}}}}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Unary: &Unary{Op: OpSub, Term: &Term{Number: "2"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$in"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}, &Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "length"}}}, Right: []ArithRight{ArithRight{Op: OpSub, Right: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}, &Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Null: true}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "until", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}, Right: &CompareRight{Op: OpGt, Right: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "2"}}}}}}}}}}}}}}}}}, Right: &CompareRight{Op: OpNe, Right: &Arith{Left: &Factor{Left: &Term{Null: true}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}}}}}}}}, UpdateOp: OpAssign, Update: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Unary: &Unary{Op: OpSub, Term: &Term{Number: "1"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}}}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Right: []FactorRight{FactorRight{Op: OpDiv, Right: &Term{Number: "2"}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "floor"}}}}}}}}}}}}}}}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$mid"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$in"}, SuffixList: []*Suffix{&Suffix{SuffixIndex: &SuffixIndex{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$mid"}}}}}}}}}}}}}}}}}}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$monkey"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$monkey"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$target"}}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "2"}}}}}}}}}}}}}}}}}}}}, UpdateOp: OpAssign, Update: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$mid"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Elif: []IfElif{IfElif{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}}}}}}}}, UpdateOp: OpAssign, Update: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Unary: &Unary{Op: OpSub, Term: &Term{Number: "1"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, IfElif{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$monkey"}}}}, Right: &CompareRight{Op: OpLt, Right: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$target"}}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}, UpdateOp: OpAssign, Update: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$mid"}}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}}}}}}}}, UpdateOp: OpAssign, Update: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$mid"}}}, Right: []ArithRight{ArithRight{Op: OpSub, Right: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "2"}}}}}}}}}}}}}}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Null: true}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$in"}, SuffixList: []*Suffix{&Suffix{SuffixIndex: &SuffixIndex{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Right: &CompareRight{Op: OpLt, Right: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$target"}}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Unary: &Unary{Op: OpSub, Term: &Term{Number: "2"}}}}, Right: []ArithRight{ArithRight{Op: OpSub, Right: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Unary: &Unary{Op: OpSub, Term: &Term{Number: "1"}}}}, Right: []ArithRight{ArithRight{Op: OpSub, Right: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "2"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "capture": []*FuncDef{&FuncDef{Name: "capture", Args: []string{"$re"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "capture", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$re"}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Null: true}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "capture", Args: []string{"$re", "$flags"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "match", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$re"}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$flags"}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Name: ".captures"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "select", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Name: ".name"}}}}, Right: &CompareRight{Op: OpNe, Right: &Arith{Left: &Factor{Left: &Term{Null: true}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Object: &Object{KeyVals: []ObjectKeyVal{ObjectKeyVal{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Name: ".name"}}}}}}}}}}}}}}, Val: &ObjectVal{Alts: []*Alt{&Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Name: ".string"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "add"}}}}}}}}, Right: []AltRight{AltRight{Op: OpAlt, Right: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Object: &Object{}}}}}}}}}}}}}}}}}}, - "combinations": []*FuncDef{&FuncDef{Name: "combinations", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "length"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}, IsSlice: true}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "combinations"}}}}}}}}}}}}}}}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$y"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}}}}}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Func: &Func{Name: "$y"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "combinations", Args: []string{"n"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$dot"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "range", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "n"}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$dot"}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "combinations"}}}}}}}}}}}}}}}}}}}}}}}}, - "del": []*FuncDef{&FuncDef{Name: "del", Args: []string{"f"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "delpaths", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "path", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "endswith": []*FuncDef{&FuncDef{Name: "endswith", Args: []string{"$x"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"string"`}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"string"`}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Unary: &Unary{Op: OpSub, Term: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "length"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, IsSlice: true}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "_type_error", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Str: `"endswith"`}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "_type_error", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Str: `"endswith"`}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "finites": []*FuncDef{&FuncDef{Name: "finites", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "select", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "isfinite"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "first": []*FuncDef{&FuncDef{Name: "first", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "first", Args: []string{"g"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Label: &Label{Ident: "$out", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "g"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}, &Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Break: "$out"}}}}}}}}}}}}}}}}}}}}}}}, - "flatten": []*FuncDef{&FuncDef{Name: "_flatten", Args: []string{"$x"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Reduce: &Reduce{Term: &Term{Identity: true, SuffixList: []*Suffix{&Suffix{Iter: true}}}, Pattern: &Pattern{Name: "$i"}, Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{}}}}}}}}}}}}}}, Update: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$i"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"array"`}}}}}, Right: []AndExprRight{AndExprRight{Op: OpAnd, Right: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}, Right: &CompareRight{Op: OpNe, Right: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$i"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "_flatten", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}, Right: []ArithRight{ArithRight{Op: OpSub, Right: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$i"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "flatten", Args: []string{"$x"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}, Right: &CompareRight{Op: OpLt, Right: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "error", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Str: `"flatten depth must not be negative"`}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "_flatten", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "flatten", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "_flatten", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Unary: &Unary{Op: OpSub, Term: &Term{Number: "1"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "from_entries": []*FuncDef{&FuncDef{Name: "from_entries", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "map", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Object: &Object{KeyVals: []ObjectKeyVal{ObjectKeyVal{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Name: ".key"}}}}}}}}, Right: []AltRight{AltRight{Op: OpAlt, Right: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Name: ".Key"}}}}}}}}}, AltRight{Op: OpAlt, Right: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Name: ".name"}}}}}}}}}, AltRight{Op: OpAlt, Right: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Name: ".Name"}}}}}}}}}}}}}}}}, Val: &ObjectVal{Alts: []*Alt{&Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "has", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Str: `"value"`}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Name: ".value"}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Name: ".Value"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "add"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}, UpdateOp: OpUpdateAlt, Update: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Object: &Object{}}}}}}}}}}}}}}}}}}, - "fromdate": []*FuncDef{&FuncDef{Name: "fromdate", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "fromdateiso8601"}}}}}}}}}}}}}}}}, - "fromdateiso8601": []*FuncDef{&FuncDef{Name: "fromdateiso8601", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "strptime", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Str: `"%Y-%m-%dT%H:%M:%SZ"`}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "mktime"}}}}}}}}}}}}}}}}, - "fromstream": []*FuncDef{&FuncDef{Name: "fromstream", Args: []string{"f"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Object: &Object{KeyVals: []ObjectKeyVal{ObjectKeyVal{Key: "x", Val: &ObjectVal{Alts: []*Alt{&Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Null: true}}}}}}}}}}}, ObjectKeyVal{Key: "e", Val: &ObjectVal{Alts: []*Alt{&Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{False: true}}}}}}}}}}}}}}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$init"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Foreach: &Foreach{Term: &Term{Func: &Func{Name: "f"}}, Pattern: &Pattern{Name: "$i"}, Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$init"}}}}}}}}}}}}}}, Update: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Name: ".e"}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$init"}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$i"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "length"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Number: "2"}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "setpath", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Str: `"e"`}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$i"}, SuffixList: []*Suffix{&Suffix{SuffixIndex: &SuffixIndex{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "length"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "setpath", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Str: `"x"`}}}}}}}}}}}}}}}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Func: &Func{Name: "$i"}, SuffixList: []*Suffix{&Suffix{SuffixIndex: &SuffixIndex{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$i"}, SuffixList: []*Suffix{&Suffix{SuffixIndex: &SuffixIndex{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "setpath", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Str: `"e"`}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$i"}, SuffixList: []*Suffix{&Suffix{SuffixIndex: &SuffixIndex{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "length"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Extract: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Name: ".e"}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Name: ".x"}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "empty"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "group_by": []*FuncDef{&FuncDef{Name: "group_by", Args: []string{"f"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{FuncDefs: []*FuncDef{&FuncDef{Name: "_group_by", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "length"}}}}, Right: &CompareRight{Op: OpGt, Right: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}, IsSlice: true}}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$xs"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$fx"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}, &Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$xs"}, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "select", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$fx"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$xs"}, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "select", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}}}}}, Right: &CompareRight{Op: OpNe, Right: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$fx"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "_group_by"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "empty"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "sort_by", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "_group_by"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "gsub": []*FuncDef{&FuncDef{Name: "gsub", Args: []string{"$re", "str"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "sub", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$re"}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "str"}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Str: `"g"`}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "gsub", Args: []string{"$re", "str", "$flags"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "sub", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$re"}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "str"}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$flags"}}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Str: `"g"`}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "in": []*FuncDef{&FuncDef{Name: "in", Args: []string{"xs"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "xs"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "has", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "index": []*FuncDef{&FuncDef{Name: "index", Args: []string{"$x"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "indices", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "indices": []*FuncDef{&FuncDef{Name: "indices", Args: []string{"$x"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"array"`}}}}}, Right: []AndExprRight{AndExprRight{Op: OpAnd, Right: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}}}}}}}}}}}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"array"`}}}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Elif: []IfElif{IfElif{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"array"`}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, IfElif{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"string"`}}}}}, Right: []AndExprRight{AndExprRight{Op: OpAnd, Right: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}}}}}}}}}}}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"string"`}}}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "explode"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "explode"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "inputs": []*FuncDef{&FuncDef{Name: "inputs", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Try: &Try{Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "repeat", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "input"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Catch: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"break"`}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "empty"}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "error"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "inside": []*FuncDef{&FuncDef{Name: "inside", Args: []string{"xs"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "xs"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "contains", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "isempty": []*FuncDef{&FuncDef{Name: "isempty", Args: []string{"g"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "first", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "g"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{False: true}}}}}}}}}}}}}}}}}}}}}}, &Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{True: true}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "iterables": []*FuncDef{&FuncDef{Name: "iterables", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "select", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"array"`}}}}}}, Right: []LogicRight{LogicRight{Op: OpOr, Right: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"object"`}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "join": []*FuncDef{&FuncDef{Name: "join", Args: []string{"$x"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Reduce: &Reduce{Term: &Term{Identity: true, SuffixList: []*Suffix{&Suffix{Iter: true}}}, Pattern: &Pattern{Name: "$i"}, Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Null: true}}}}}}}}}}}}}, Update: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Null: true}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Str: `""`}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$i"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"boolean"`}}}}}}, Right: []LogicRight{LogicRight{Op: OpOr, Right: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"number"`}}}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "tostring"}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}, Right: []AltRight{AltRight{Op: OpAlt, Right: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Str: `""`}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Right: []AltRight{AltRight{Op: OpAlt, Right: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Str: `""`}}}}}}}}}}}}}}}}}, - "last": []*FuncDef{&FuncDef{Name: "last", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Unary: &Unary{Op: OpSub, Term: &Term{Number: "1"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "last", Args: []string{"g"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Reduce: &Reduce{Term: &Term{Func: &Func{Name: "g"}}, Pattern: &Pattern{Name: "$item"}, Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Null: true}}}}}}}}}}}}}, Update: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$item"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "leaf_paths": []*FuncDef{&FuncDef{Name: "leaf_paths", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "paths", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "scalars"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "limit": []*FuncDef{&FuncDef{Name: "limit", Args: []string{"$n", "g"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$n"}}}}, Right: &CompareRight{Op: OpGt, Right: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Label: &Label{Ident: "$out", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Foreach: &Foreach{Term: &Term{Func: &Func{Name: "g"}}, Pattern: &Pattern{Name: "$item"}, Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$n"}}}}}}}}}}}}}}, Update: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}, Right: []ArithRight{ArithRight{Op: OpSub, Right: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}}}, Extract: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$item"}}}}}}}}}}, &Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}, Right: &CompareRight{Op: OpLe, Right: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Break: "$out"}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "empty"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Elif: []IfElif{IfElif{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$n"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "empty"}}}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "g"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "ltrimstr": []*FuncDef{&FuncDef{Name: "ltrimstr", Args: []string{"$x"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"string"`}}}}}, Right: []AndExprRight{AndExprRight{Op: OpAnd, Right: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"string"`}}}}}}}}}}}}}}}}}}}, AndExprRight{Op: OpAnd, Right: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "startswith", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "length"}}}}}}}}}}}}}}, IsSlice: true}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "map": []*FuncDef{&FuncDef{Name: "map", Args: []string{"f"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "map_values": []*FuncDef{&FuncDef{Name: "map_values", Args: []string{"f"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}}, UpdateOp: OpModify, Update: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}}}}}, - "match": []*FuncDef{&FuncDef{Name: "match", Args: []string{"$re"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "match", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$re"}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Null: true}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "match", Args: []string{"$re", "$flags"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "_match_impl", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$re"}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$flags"}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{False: true}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}}}}}}}}}}}, - "max": []*FuncDef{&FuncDef{Name: "max", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "max_by", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "max_by": []*FuncDef{&FuncDef{Name: "max_by", Args: []string{"f"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Reduce: &Reduce{Term: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}, IsSlice: true}, SuffixList: []*Suffix{&Suffix{Iter: true}}}, Pattern: &Pattern{Name: "$x"}, Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}}}}}}}}, Update: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}}}}, Right: &CompareRight{Op: OpLe, Right: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "min": []*FuncDef{&FuncDef{Name: "min", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "min_by", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "min_by": []*FuncDef{&FuncDef{Name: "min_by", Args: []string{"f"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Reduce: &Reduce{Term: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}, IsSlice: true}, SuffixList: []*Suffix{&Suffix{Iter: true}}}, Pattern: &Pattern{Name: "$x"}, Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}}}}}}}}, Update: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}}}}, Right: &CompareRight{Op: OpGt, Right: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "modify": []*FuncDef{&FuncDef{Name: "_modify", Args: []string{"ps", "f"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Reduce: &Reduce{Term: &Term{Func: &Func{Name: "path", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "ps"}}}}}}}}}}}}}}}}}, Pattern: &Pattern{Name: "$p"}, Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}, &Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Update: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Label: &Label{Ident: "$out", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Func: &Func{Name: "$p"}}}}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$q"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "setpath", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$q"}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "getpath", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$q"}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}, &Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Break: "$out"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}}}}}}}}, UpdateOp: OpUpdateAdd, Update: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$p"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}, SuffixList: []*Suffix{&Suffix{SuffixIndex: &SuffixIndex{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "delpaths", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}, SuffixList: []*Suffix{&Suffix{SuffixIndex: &SuffixIndex{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "normals": []*FuncDef{&FuncDef{Name: "normals", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "select", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "isnormal"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "not": []*FuncDef{&FuncDef{Name: "not", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{False: true}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{True: true}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "nth": []*FuncDef{&FuncDef{Name: "nth", Args: []string{"$n"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$n"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "nth", Args: []string{"$n", "g"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$n"}}}}, Right: &CompareRight{Op: OpLt, Right: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "error", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Str: `"nth doesn't support negative indices"`}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Label: &Label{Ident: "$out", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Foreach: &Foreach{Term: &Term{Func: &Func{Name: "g"}}, Pattern: &Pattern{Name: "$item"}, Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$n"}}}}}}}}}}}}}}, Update: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}, Right: []ArithRight{ArithRight{Op: OpSub, Right: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}}}, Extract: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}, Right: &CompareRight{Op: OpLt, Right: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}, Right: []LogicRight{LogicRight{Op: OpOr, Right: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "empty"}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$item"}}}}}}}}}}, &Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Break: "$out"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "nulls": []*FuncDef{&FuncDef{Name: "nulls", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "select", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Null: true}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "numbers": []*FuncDef{&FuncDef{Name: "numbers", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "select", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"number"`}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "objects": []*FuncDef{&FuncDef{Name: "objects", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "select", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"object"`}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "paths": []*FuncDef{&FuncDef{Name: "paths", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "path", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "recurse", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"array"`}}}}}}, Right: []LogicRight{LogicRight{Op: OpOr, Right: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"object"`}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "empty"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "select", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "length"}}}}, Right: &CompareRight{Op: OpGt, Right: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "paths", Args: []string{"f"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "paths"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "select", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$p"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "getpath", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$p"}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "range": []*FuncDef{&FuncDef{Name: "range", Args: []string{"$x"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "range", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "range", Args: []string{"$start", "$end"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$start"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "while", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}, Right: &CompareRight{Op: OpLt, Right: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$end"}}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "range", Args: []string{"$start", "$end", "$step"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$step"}}}}, Right: &CompareRight{Op: OpGt, Right: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$start"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "while", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}, Right: &CompareRight{Op: OpLt, Right: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$end"}}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Func: &Func{Name: "$step"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Elif: []IfElif{IfElif{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$step"}}}}, Right: &CompareRight{Op: OpLt, Right: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$start"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "while", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}, Right: &CompareRight{Op: OpGt, Right: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$end"}}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Func: &Func{Name: "$step"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "empty"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "recurse": []*FuncDef{&FuncDef{Name: "recurse", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "recurse", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Optional: true}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "recurse", Args: []string{"f"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{FuncDefs: []*FuncDef{&FuncDef{Name: "r", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}, &Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "r"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "r"}}}}}}}}}}}}}}}, &FuncDef{Name: "recurse", Args: []string{"f", "cond"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{FuncDefs: []*FuncDef{&FuncDef{Name: "r", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}, &Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "select", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "cond"}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "r"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "r"}}}}}}}}}}}}}}}}, - "repeat": []*FuncDef{&FuncDef{Name: "repeat", Args: []string{"f"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{FuncDefs: []*FuncDef{&FuncDef{Name: "_repeat", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}, &Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "_repeat"}}}}}}}}}}}}}}}}, Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "_repeat"}}}}}}}}}}}}}}}}, - "reverse": []*FuncDef{&FuncDef{Name: "reverse", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "length"}}}, Right: []ArithRight{ArithRight{Op: OpSub, Right: &Factor{Left: &Term{Number: "1"}}}, ArithRight{Op: OpSub, Right: &Factor{Left: &Term{Func: &Func{Name: "range", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "length"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "rindex": []*FuncDef{&FuncDef{Name: "rindex", Args: []string{"$x"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "indices", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Unary: &Unary{Op: OpSub, Term: &Term{Number: "1"}}}}}}}}}}}}}}}, IsSlice: true}, SuffixList: []*Suffix{&Suffix{SuffixIndex: &SuffixIndex{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "rtrimstr": []*FuncDef{&FuncDef{Name: "rtrimstr", Args: []string{"$x"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"string"`}}}}}, Right: []AndExprRight{AndExprRight{Op: OpAnd, Right: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"string"`}}}}}}}}}}}}}}}}}}}, AndExprRight{Op: OpAnd, Right: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "endswith", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{End: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Unary: &Unary{Op: OpSub, Term: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "length"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "scalars": []*FuncDef{&FuncDef{Name: "scalars", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "select", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}, Right: &CompareRight{Op: OpNe, Right: &Arith{Left: &Factor{Left: &Term{Str: `"array"`}}}}}, Right: []AndExprRight{AndExprRight{Op: OpAnd, Right: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}, Right: &CompareRight{Op: OpNe, Right: &Arith{Left: &Factor{Left: &Term{Str: `"object"`}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "scan": []*FuncDef{&FuncDef{Name: "scan", Args: []string{"$re"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "scan", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$re"}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Null: true}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "scan", Args: []string{"$re", "$flags"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "match", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$re"}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Str: `"g"`}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Func: &Func{Name: "$flags"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Name: ".captures"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "length"}}}}, Right: &CompareRight{Op: OpGt, Right: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Name: ".captures"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Name: ".string"}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Name: ".string"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "select": []*FuncDef{&FuncDef{Name: "select", Args: []string{"f"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "empty"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "sort": []*FuncDef{&FuncDef{Name: "sort", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "sort_by", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "sort_by": []*FuncDef{&FuncDef{Name: "sort_by", Args: []string{"f"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{FuncDefs: []*FuncDef{&FuncDef{Name: "_sort_by", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "length"}}}}, Right: &CompareRight{Op: OpGt, Right: &Arith{Left: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}, IsSlice: true}}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$xs"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$fx"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$xs"}, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "select", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}}}}}, Right: &CompareRight{Op: OpLt, Right: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$fx"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "_sort_by"}}}}}}}}}}}}}}}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}}}}}}}, ArithRight{Right: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$xs"}, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "select", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}}}}}, Right: &CompareRight{Op: OpGe, Right: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$fx"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "_sort_by"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "_sort_by"}}}}}}}}}}}}}}}}, - "splits": []*FuncDef{&FuncDef{Name: "splits", Args: []string{"$re"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "splits", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$re"}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Null: true}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "splits", Args: []string{"$re", "$flags"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "split", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$re"}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$flags"}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}}}}}}}}}}}, - "startswith": []*FuncDef{&FuncDef{Name: "startswith", Args: []string{"$x"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"string"`}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"string"`}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{End: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "length"}}}}}}}}}}}}}}}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "_type_error", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Str: `"startswith"`}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "_type_error", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Str: `"startswith"`}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "strings": []*FuncDef{&FuncDef{Name: "strings", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "select", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"string"`}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "sub": []*FuncDef{&FuncDef{Name: "sub", Args: []string{"$re", "str"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "sub", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$re"}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "str"}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Null: true}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "sub", Args: []string{"$re", "str", "$flags"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$in"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Reduce: &Reduce{Term: &Term{Func: &Func{Name: "match", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$re"}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$flags"}}}}}}}}}}}}}}}}}, Pattern: &Pattern{Name: "$r"}, Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Str: `""`}}}}}}}}}, &Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}}}}}}}}, Update: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$r"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Name: ".captures"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "select", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Name: ".name"}}}}, Right: &CompareRight{Op: OpNe, Right: &Arith{Left: &Factor{Left: &Term{Null: true}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Object: &Object{KeyVals: []ObjectKeyVal{ObjectKeyVal{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Name: ".name"}}}}}}}}}}}}}}, Val: &ObjectVal{Alts: []*Alt{&Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Name: ".string"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "add"}}}}}}}}, Right: []AltRight{AltRight{Op: OpAlt, Right: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Object: &Object{}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}, SuffixList: []*Suffix{&Suffix{SuffixIndex: &SuffixIndex{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Func: &Func{Name: "$in"}, SuffixList: []*Suffix{&Suffix{SuffixIndex: &SuffixIndex{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$x"}, SuffixList: []*Suffix{&Suffix{SuffixIndex: &SuffixIndex{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, IsSlice: true, End: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$r"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Name: ".offset"}}}}}}}}}}}}}}}}}}}}}}, ArithRight{Right: &Factor{Left: &Term{Func: &Func{Name: "str"}}}}}}}}}}}}, &Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$r"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Name: ".offset"}}}}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Func: &Func{Name: "$r"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Name: ".length"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Func: &Func{Name: "$in"}, SuffixList: []*Suffix{&Suffix{SuffixIndex: &SuffixIndex{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "1"}}}}}}}}}}}}}}}}}}}}}}}}}}}, IsSlice: true}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "test": []*FuncDef{&FuncDef{Name: "test", Args: []string{"$re"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "test", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$re"}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Null: true}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &FuncDef{Name: "test", Args: []string{"$re", "$flags"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "_match_impl", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$re"}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$flags"}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{True: true}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "to_entries": []*FuncDef{&FuncDef{Name: "to_entries", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "keys"}, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$k"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Object: &Object{KeyVals: []ObjectKeyVal{ObjectKeyVal{Key: "key", Val: &ObjectVal{Alts: []*Alt{&Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$k"}}}}}}}}}}}}, ObjectKeyVal{Key: "value", Val: &ObjectVal{Alts: []*Alt{&Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$k"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "todate": []*FuncDef{&FuncDef{Name: "todate", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "todateiso8601"}}}}}}}}}}}}}}}}, - "todateiso8601": []*FuncDef{&FuncDef{Name: "todateiso8601", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "strftime", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Str: `"%Y-%m-%dT%H:%M:%SZ"`}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "tostream": []*FuncDef{&FuncDef{Name: "tostream", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "path", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{FuncDefs: []*FuncDef{&FuncDef{Name: "r", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Optional: true}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "r"}}}}}}}}}}}}}}}}}}}}}}}, &Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}}}}}}}, Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "r"}}}}}}}}}}}}}}}}}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$p"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "getpath", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$p"}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Reduce: &Reduce{Term: &Term{Func: &Func{Name: "path", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Optional: true}}}}}}}}}}}}}}}}}}, Pattern: &Pattern{Name: "$q"}, Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$p"}}}}}}}}}}, &Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}}}}}}}}}}}}}}}}}}}, Update: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$p"}}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Func: &Func{Name: "$q"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "transpose": []*FuncDef{&FuncDef{Name: "transpose", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Array: &Array{}}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$in"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "map", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "length"}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "max"}}}}}}}}}}}}}}}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$max"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "length"}}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$length"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Reduce: &Reduce{Term: &Term{Func: &Func{Name: "range", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$max"}}}}}}}}}}}}}}}}}, Pattern: &Pattern{Name: "$j"}, Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{}}}}}}}}}}}}}}, Update: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Reduce: &Reduce{Term: &Term{Func: &Func{Name: "range", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$length"}}}}}}}}}}}}}}}}}, Pattern: &Pattern{Name: "$i"}, Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{}}}}}}}}}}}}}}, Update: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$in"}, SuffixList: []*Suffix{&Suffix{SuffixIndex: &SuffixIndex{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$i"}}}}}}}}}}}}}}}}, &Suffix{SuffixIndex: &SuffixIndex{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$j"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "truncate_stream": []*FuncDef{&FuncDef{Name: "truncate_stream", Args: []string{"f"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$n"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Null: true}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$input"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "length"}}}}}}}}}}}}}}}}}, Right: &CompareRight{Op: OpGt, Right: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$n"}}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "setpath", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Array: &Array{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$input"}, SuffixList: []*Suffix{&Suffix{SuffixIndex: &SuffixIndex{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}, &Suffix{SuffixIndex: &SuffixIndex{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$n"}}}}}}}}}}}}}}, IsSlice: true}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "empty"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "unique": []*FuncDef{&FuncDef{Name: "unique", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "group_by", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "map", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "unique_by": []*FuncDef{&FuncDef{Name: "unique_by", Args: []string{"f"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "group_by", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "map", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Index: &Index{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Number: "0"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "until": []*FuncDef{&FuncDef{Name: "until", Args: []string{"cond", "next"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{FuncDefs: []*FuncDef{&FuncDef{Name: "_until", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "cond"}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "next"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "_until"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "_until"}}}}}}}}}}}}}}}}, - "values": []*FuncDef{&FuncDef{Name: "values", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "select", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}, Right: &CompareRight{Op: OpNe, Right: &Arith{Left: &Factor{Left: &Term{Null: true}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "walk": []*FuncDef{&FuncDef{Name: "walk", Args: []string{"f"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}, Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$in"}}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"object"`}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Reduce: &Reduce{Term: &Term{Func: &Func{Name: "keys"}, SuffixList: []*Suffix{&Suffix{Iter: true}}}, Pattern: &Pattern{Name: "$key"}, Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Object: &Object{}}}}}}}}}}}}}}, Update: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}, Right: []ArithRight{ArithRight{Right: &Factor{Left: &Term{Object: &Object{KeyVals: []ObjectKeyVal{ObjectKeyVal{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$key"}}}}}}}}}}}}}}, Val: &ObjectVal{Alts: []*Alt{&Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$in"}, SuffixList: []*Suffix{&Suffix{SuffixIndex: &SuffixIndex{Start: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "$key"}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "walk", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}, Elif: []IfElif{IfElif{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "type"}}}}, Right: &CompareRight{Op: OpEq, Right: &Arith{Left: &Factor{Left: &Term{Str: `"array"`}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "map", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "walk", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, - "while": []*FuncDef{&FuncDef{Name: "while", Args: []string{"cond", "update"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{FuncDefs: []*FuncDef{&FuncDef{Name: "_while", Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{If: &If{Cond: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "cond"}}}}}}}}}}}}}}, Then: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Identity: true}}}}}}}}}, &Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Query: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "update"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "_while"}}}}}}}}}}}}}}}}}}}}}}}}}}}, Else: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "empty"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "_while"}}}}}}}}}}}}}}}}, - "with_entries": []*FuncDef{&FuncDef{Name: "with_entries", Args: []string{"f"}, Body: &Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "to_entries"}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "map", Args: []*Query{&Query{Commas: []*Comma{&Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "f"}}}}}}}}}}}}}}}}}}}}}}}}}}}, &Comma{Filters: []*Filter{&Filter{Alt: &Alt{Left: &Expr{Logic: &Logic{Left: &AndExpr{Left: &Compare{Left: &Arith{Left: &Factor{Left: &Term{Func: &Func{Name: "from_entries"}}}}}}}}}}}}}}}}, + "IN": []*FuncDef{&FuncDef{Name: "IN", Args: []string{"s"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "any", Args: []*Query{&Query{Left: &Query{Func: "s"}, Op: OpEq, Right: &Query{Func: "."}}, &Query{Func: "."}}}}}}, &FuncDef{Name: "IN", Args: []string{"src", "s"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "any", Args: []*Query{&Query{Left: &Query{Func: "src"}, Op: OpEq, Right: &Query{Func: "s"}}, &Query{Func: "."}}}}}}}, + "INDEX": []*FuncDef{&FuncDef{Name: "INDEX", Args: []string{"stream", "idx_expr"}, Body: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "stream"}}, Pattern: &Pattern{Name: "$row"}, Start: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{}}}, Update: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Left: &Query{Func: "$row"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "idx_expr"}, Op: OpPipe, Right: &Query{Func: "tostring"}}}}}}, Op: OpAssign, Right: &Query{Func: "$row"}}}}}}, &FuncDef{Name: "INDEX", Args: []string{"idx_expr"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "INDEX", Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, &Query{Func: "idx_expr"}}}}}}}, + "JOIN": []*FuncDef{&FuncDef{Name: "JOIN", Args: []string{"$idx", "idx_expr"}, Body: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$idx"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Func: "idx_expr"}}}}}}}}}}}}}}}, &FuncDef{Name: "JOIN", Args: []string{"$idx", "stream", "idx_expr"}, Body: &Query{Left: &Query{Func: "stream"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$idx"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Func: "idx_expr"}}}}}}}}}}}}, &FuncDef{Name: "JOIN", Args: []string{"$idx", "stream", "idx_expr", "join_expr"}, Body: &Query{Left: &Query{Func: "stream"}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$idx"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Func: "idx_expr"}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "join_expr"}}}}}, + "all": []*FuncDef{&FuncDef{Name: "all", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "all", Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, &Query{Func: "."}}}}}}, &FuncDef{Name: "all", Args: []string{"y"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "all", Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, &Query{Func: "y"}}}}}}, &FuncDef{Name: "all", Args: []string{"g", "y"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "isempty", Args: []*Query{&Query{Left: &Query{Func: "g"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "y"}, Op: OpAnd, Right: &Query{Func: "empty"}}}}}}}}}, + "any": []*FuncDef{&FuncDef{Name: "any", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "any", Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, &Query{Func: "."}}}}}}, &FuncDef{Name: "any", Args: []string{"y"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "any", Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, &Query{Func: "y"}}}}}}, &FuncDef{Name: "any", Args: []string{"g", "y"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "isempty", Args: []*Query{&Query{Left: &Query{Func: "g"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "y"}, Op: OpOr, Right: &Query{Func: "empty"}}}}}}}, Op: OpPipe, Right: &Query{Func: "not"}}}}, + "arrays": []*FuncDef{&FuncDef{Name: "arrays", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "array"}}}}}}}}}}, + "ascii_downcase": []*FuncDef{&FuncDef{Name: "ascii_downcase", Body: &Query{Left: &Query{Func: "explode"}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Left: &Query{Term: &Term{Type: TermTypeNumber, Number: "65"}}, Op: OpLe, Right: &Query{Func: "."}}, Op: OpAnd, Right: &Query{Left: &Query{Func: "."}, Op: OpLe, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "90"}}}}, Then: &Query{Left: &Query{Func: "."}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "32"}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "implode"}}}}}, + "ascii_upcase": []*FuncDef{&FuncDef{Name: "ascii_upcase", Body: &Query{Left: &Query{Func: "explode"}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Left: &Query{Term: &Term{Type: TermTypeNumber, Number: "97"}}, Op: OpLe, Right: &Query{Func: "."}}, Op: OpAnd, Right: &Query{Left: &Query{Func: "."}, Op: OpLe, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "122"}}}}, Then: &Query{Left: &Query{Func: "."}, Op: OpSub, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "32"}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "implode"}}}}}, + "assign": []*FuncDef{&FuncDef{Name: "_assign", Args: []string{"ps", "$v"}, Body: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "path", Args: []*Query{&Query{Func: "ps"}}}}, Pattern: &Pattern{Name: "$p"}, Start: &Query{Func: "."}, Update: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{&Query{Func: "$p"}, &Query{Func: "$v"}}}}}}}}}}, + "booleans": []*FuncDef{&FuncDef{Name: "booleans", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "boolean"}}}}}}}}}}, + "capture": []*FuncDef{&FuncDef{Name: "capture", Args: []string{"$re"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "capture", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "null"}}}}}}, &FuncDef{Name: "capture", Args: []string{"$re", "$flags"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "match", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "$flags"}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "captures"}}}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "name"}}}, Op: OpNe, Right: &Query{Func: "null"}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{KeyQuery: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "name"}}}, Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "string"}}}}}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: "add"}, Op: OpAlt, Right: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{}}}}}}}}, + "combinations": []*FuncDef{&FuncDef{Name: "combinations", Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "length"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{}}}, Else: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{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"}}, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$y"}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "$x"}}}}, Op: OpAdd, Right: &Query{Func: "$y"}}}}}}}}}}}}}}}}, &FuncDef{Name: "combinations", Args: []string{"n"}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$dot"}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "range", Args: []*Query{&Query{Func: "n"}}}}}, Op: OpPipe, Right: &Query{Func: "$dot"}}}}}, Op: OpPipe, Right: &Query{Func: "combinations"}}}}}}}}}, + "del": []*FuncDef{&FuncDef{Name: "del", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "delpaths", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "path", Args: []*Query{&Query{Func: "f"}}}}}}}}}}}}}}, + "endswith": []*FuncDef{&FuncDef{Name: "endswith", Args: []string{"$x"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "string"}}}}, Then: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "string"}}}}}, Then: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeUnary, Unary: &Unary{Op: OpSub, Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Func: "length"}}}}}}, IsSlice: true}}}, Op: OpEq, Right: &Query{Func: "$x"}}, Else: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_type_error", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "endswith"}}}}}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_type_error", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "endswith"}}}}}}}}}}}}, + "finites": []*FuncDef{&FuncDef{Name: "finites", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Func: "isfinite"}}}}}}}, + "first": []*FuncDef{&FuncDef{Name: "first", Body: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}, &FuncDef{Name: "first", Args: []string{"g"}, Body: &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{Ident: "$out", Body: &Query{Left: &Query{Func: "g"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeBreak, Break: "$out"}}}}}}}}}, + "flatten": []*FuncDef{&FuncDef{Name: "_flatten", Args: []string{"$x"}, Body: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}, Pattern: &Pattern{Name: "$i"}, Start: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{}}}, Update: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$i"}, Op: OpPipe, Right: &Query{Left: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "array"}}}}, Op: OpAnd, Right: &Query{Left: &Query{Func: "$x"}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}, Then: &Query{Left: &Query{Func: "."}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "$i"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_flatten", Args: []*Query{&Query{Left: &Query{Func: "$x"}, Op: OpSub, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}}}}}, Else: &Query{Left: &Query{Func: "."}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "$i"}}}}}}}}}}}}, &FuncDef{Name: "flatten", Args: []string{"$x"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$x"}, Op: OpLt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "error", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "flatten depth must not be negative"}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_flatten", Args: []*Query{&Query{Func: "$x"}}}}}}}}}, &FuncDef{Name: "flatten", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_flatten", Args: []*Query{&Query{Term: &Term{Type: TermTypeUnary, Unary: &Unary{Op: OpSub, Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}}}}, + "from_entries": []*FuncDef{&FuncDef{Name: "from_entries", Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{KeyQuery: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "key"}}}, Op: OpAlt, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "Key"}}}, Op: OpAlt, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "name"}}}, Op: OpAlt, Right: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "Name"}}}}}}, Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "has", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "value"}}}}}}}, Then: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "value"}}}, Else: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "Value"}}}}}}}}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: "add"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "."}, Op: OpUpdateAlt, Right: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{}}}}}}}}, + "fromdate": []*FuncDef{&FuncDef{Name: "fromdate", Body: &Query{Func: "fromdateiso8601"}}}, + "fromdateiso8601": []*FuncDef{&FuncDef{Name: "fromdateiso8601", Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "strptime", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "%Y-%m-%dT%H:%M:%SZ"}}}}}}}, Op: OpPipe, Right: &Query{Func: "mktime"}}}}, + "fromstream": []*FuncDef{&FuncDef{Name: "fromstream", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{Key: "x", Val: &ObjectVal{Queries: []*Query{&Query{Func: "null"}}}}, &ObjectKeyVal{Key: "e", Val: &ObjectVal{Queries: []*Query{&Query{Func: "false"}}}}}}, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$init"}}, Body: &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "f"}}, Pattern: &Pattern{Name: "$i"}, Start: &Query{Func: "$init"}, Update: &Query{Left: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "e"}}}, Then: &Query{Func: "$init"}, Else: &Query{Func: "."}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$i"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "length"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "2"}}}}, Then: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "e"}}}}}}, &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$i"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: "length"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{&Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "x"}}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$i"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}}, &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$i"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "e"}}}}}}, &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$i"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: "length"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}}}}}}, Extract: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "e"}}}, Then: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "x"}}}, Else: &Query{Func: "empty"}}}}}}}}}}}}}}, + "group_by": []*FuncDef{&FuncDef{Name: "group_by", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_group_by", Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "f"}}}}}}}}}}}}}}, + "gsub": []*FuncDef{&FuncDef{Name: "gsub", Args: []string{"$re", "str"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "sub", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "str"}, &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "g"}}}}}}}}, &FuncDef{Name: "gsub", Args: []string{"$re", "str", "$flags"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "sub", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "str"}, &Query{Left: &Query{Func: "$flags"}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "g"}}}}}}}}}}, + "in": []*FuncDef{&FuncDef{Name: "in", Args: []string{"xs"}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{Left: &Query{Func: "xs"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "has", Args: []*Query{&Query{Func: "$x"}}}}}}}}}}}}}, + "index": []*FuncDef{&FuncDef{Name: "index", Args: []string{"$x"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "indices", Args: []*Query{&Query{Func: "$x"}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}}, + "indices": []*FuncDef{&FuncDef{Name: "indices", Args: []string{"$x"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "array"}}}}, Op: OpAnd, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Func: "type"}}}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "array"}}}}}, Then: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Func: "$x"}}}}, Elif: []*IfElif{&IfElif{Cond: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "array"}}}}, Then: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "$x"}}}}}}}}, &IfElif{Cond: &Query{Left: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "string"}}}}, Op: OpAnd, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Func: "type"}}}}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "string"}}}}}, Then: &Query{Left: &Query{Func: "explode"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Func: "explode"}}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Func: "$x"}}}}}}}}}, + "inputs": []*FuncDef{&FuncDef{Name: "inputs", Body: &Query{Term: &Term{Type: TermTypeTry, Try: &Try{Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "repeat", Args: []*Query{&Query{Func: "input"}}}}}, Catch: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "break"}}}}, Then: &Query{Func: "empty"}, Else: &Query{Func: "error"}}}}}}}}}, + "inside": []*FuncDef{&FuncDef{Name: "inside", Args: []string{"xs"}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{Left: &Query{Func: "xs"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "contains", Args: []*Query{&Query{Func: "$x"}}}}}}}}}}}}}, + "isempty": []*FuncDef{&FuncDef{Name: "isempty", Args: []string{"g"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "first", Args: []*Query{&Query{Left: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "g"}, Op: OpPipe, Right: &Query{Func: "false"}}}}, Op: OpComma, Right: &Query{Func: "true"}}}}}}}}, + "iterables": []*FuncDef{&FuncDef{Name: "iterables", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "type"}, Op: OpPipe, Right: &Query{Left: &Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "array"}}}}, Op: OpOr, Right: &Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "object"}}}}}}}}}}}}, + "join": []*FuncDef{&FuncDef{Name: "join", Args: []string{"$x"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}, Pattern: &Pattern{Name: "$i"}, Start: &Query{Func: "null"}, Update: &Query{Left: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Func: "null"}}, Then: &Query{Term: &Term{Type: TermTypeString, Str: &String{}}}, Else: &Query{Left: &Query{Func: "."}, Op: OpAdd, Right: &Query{Func: "$x"}}}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "$i"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "boolean"}}}}, Op: OpOr, Right: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "number"}}}}}, Then: &Query{Func: "tostring"}, Else: &Query{Left: &Query{Func: "."}, Op: OpAlt, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{}}}}}}}}}}}}}}, Op: OpAlt, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{}}}}}}, + "last": []*FuncDef{&FuncDef{Name: "last", Body: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeUnary, Unary: &Unary{Op: OpSub, Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}}, &FuncDef{Name: "last", Args: []string{"g"}, Body: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "g"}}, Pattern: &Pattern{Name: "$item"}, Start: &Query{Func: "null"}, Update: &Query{Func: "$item"}}}}}}, + "leaf_paths": []*FuncDef{&FuncDef{Name: "leaf_paths", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "paths", Args: []*Query{&Query{Func: "scalars"}}}}}}}, + "limit": []*FuncDef{&FuncDef{Name: "limit", Args: []string{"$n", "g"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$n"}, Op: OpGt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{Ident: "$out", Body: &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "g"}}, Pattern: &Pattern{Name: "$item"}, Start: &Query{Func: "$n"}, Update: &Query{Left: &Query{Func: "."}, Op: OpSub, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}, Extract: &Query{Left: &Query{Func: "$item"}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "."}, Op: OpLe, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Term: &Term{Type: TermTypeBreak, Break: "$out"}}, Else: &Query{Func: "empty"}}}}}}}}}}}, Elif: []*IfElif{&IfElif{Cond: &Query{Left: &Query{Func: "$n"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Func: "empty"}}}, Else: &Query{Func: "g"}}}}}}, + "ltrimstr": []*FuncDef{&FuncDef{Name: "ltrimstr", Args: []string{"$x"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Left: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "string"}}}}, Op: OpAnd, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "string"}}}}}}}}, Op: OpAnd, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "startswith", Args: []*Query{&Query{Func: "$x"}}}}}}, Then: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Func: "length"}}, IsSlice: true}}}}}}}}, + "map": []*FuncDef{&FuncDef{Name: "map", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, Op: OpPipe, Right: &Query{Func: "f"}}}}}}}, + "map_values": []*FuncDef{&FuncDef{Name: "map_values", Args: []string{"f"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, Op: OpModify, Right: &Query{Func: "f"}}}}, + "match": []*FuncDef{&FuncDef{Name: "match", Args: []string{"$re"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "match", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "null"}}}}}}, &FuncDef{Name: "match", Args: []string{"$re", "$flags"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_match", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "$flags"}, &Query{Func: "false"}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}, + "max": []*FuncDef{&FuncDef{Name: "max", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "max_by", Args: []*Query{&Query{Func: "."}}}}}}}, + "max_by": []*FuncDef{&FuncDef{Name: "max_by", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_max_by", Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "f"}}}}}}}}}}}}}}, + "min": []*FuncDef{&FuncDef{Name: "min", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "min_by", Args: []*Query{&Query{Func: "."}}}}}}}, + "min_by": []*FuncDef{&FuncDef{Name: "min_by", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_min_by", Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "f"}}}}}}}}}}}}}}, + "modify": []*FuncDef{&FuncDef{Name: "_modify", Args: []string{"ps", "f"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "path", Args: []*Query{&Query{Func: "ps"}}}}, Pattern: &Pattern{Name: "$p"}, Start: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{}}}}}}}, Update: &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{Ident: "$out", Body: &Query{Left: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}, Op: OpAdd, Right: &Query{Func: "$p"}}, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$q"}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{&Query{Func: "$q"}, &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "getpath", Args: []*Query{&Query{Func: "$q"}}}}}, Op: OpPipe, Right: &Query{Func: "f"}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeBreak, Break: "$out"}}}}}}}}}}}, Op: OpComma, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}, Op: OpUpdateAdd, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "$p"}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$x"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "delpaths", Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$x"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}}}}}}}}}}}}}}, + "normals": []*FuncDef{&FuncDef{Name: "normals", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Func: "isnormal"}}}}}}}, + "not": []*FuncDef{&FuncDef{Name: "not", Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Func: "."}, Then: &Query{Func: "false"}, Else: &Query{Func: "true"}}}}}}, + "nth": []*FuncDef{&FuncDef{Name: "nth", Args: []string{"$n"}, Body: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Func: "$n"}}}}}, &FuncDef{Name: "nth", Args: []string{"$n", "g"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$n"}, Op: OpLt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "error", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "nth doesn't support negative indices"}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{Ident: "$out", Body: &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "g"}}, Pattern: &Pattern{Name: "$item"}, Start: &Query{Func: "$n"}, Update: &Query{Left: &Query{Func: "."}, Op: OpSub, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}, Extract: &Query{Left: &Query{Left: &Query{Left: &Query{Func: "."}, Op: OpLt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Op: OpOr, Right: &Query{Func: "empty"}}, Op: OpPipe, Right: &Query{Left: &Query{Func: "$item"}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeBreak, Break: "$out"}}}}}}}}}}}}}}}, + "nulls": []*FuncDef{&FuncDef{Name: "nulls", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Func: "null"}}}}}}}}, + "numbers": []*FuncDef{&FuncDef{Name: "numbers", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "number"}}}}}}}}}}, + "objects": []*FuncDef{&FuncDef{Name: "objects", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "object"}}}}}}}}}}, + "paths": []*FuncDef{&FuncDef{Name: "paths", Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "path", Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "recurse", Args: []*Query{&Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "type"}, Op: OpPipe, Right: &Query{Left: &Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "array"}}}}, Op: OpOr, Right: &Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "object"}}}}}}}}, Then: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, Else: &Query{Func: "empty"}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "length"}, Op: OpGt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}}}, &FuncDef{Name: "paths", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{Left: &Query{Func: "paths"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$p"}}, Body: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "getpath", Args: []*Query{&Query{Func: "$p"}}}}}, Op: OpPipe, Right: &Query{Func: "f"}}}}}}}}}}}}}}}}}}}}, + "range": []*FuncDef{&FuncDef{Name: "range", Args: []string{"$x"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "range", Args: []*Query{&Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}, &Query{Func: "$x"}}}}}}, &FuncDef{Name: "range", Args: []string{"$start", "$end"}, Body: &Query{Left: &Query{Func: "$start"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "while", Args: []*Query{&Query{Left: &Query{Func: "."}, Op: OpLt, Right: &Query{Func: "$end"}}, &Query{Left: &Query{Func: "."}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}}}, &FuncDef{Name: "range", Args: []string{"$start", "$end", "$step"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$step"}, Op: OpGt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Left: &Query{Func: "$start"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "while", Args: []*Query{&Query{Left: &Query{Func: "."}, Op: OpLt, Right: &Query{Func: "$end"}}, &Query{Left: &Query{Func: "."}, Op: OpAdd, Right: &Query{Func: "$step"}}}}}}}, Elif: []*IfElif{&IfElif{Cond: &Query{Left: &Query{Func: "$step"}, Op: OpLt, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}, Then: &Query{Left: &Query{Func: "$start"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "while", Args: []*Query{&Query{Left: &Query{Func: "."}, Op: OpGt, Right: &Query{Func: "$end"}}, &Query{Left: &Query{Func: "."}, Op: OpAdd, Right: &Query{Func: "$step"}}}}}}}}}, Else: &Query{Func: "empty"}}}}}}, + "recurse": []*FuncDef{&FuncDef{Name: "recurse", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "recurse", Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Optional: true}}}}}}}}}, &FuncDef{Name: "recurse", Args: []string{"f"}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: "r", Body: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "f"}, Op: OpPipe, Right: &Query{Func: "r"}}}}}}}, Func: "r"}}, &FuncDef{Name: "recurse", Args: []string{"f", "cond"}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: "r", Body: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "f"}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Func: "cond"}}}}}, Op: OpPipe, Right: &Query{Func: "r"}}}}}}}}, Func: "r"}}}, + "repeat": []*FuncDef{&FuncDef{Name: "repeat", Args: []string{"f"}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: "_repeat", Body: &Query{Left: &Query{Func: "f"}, Op: OpComma, Right: &Query{Func: "_repeat"}}}}, Func: "_repeat"}}}, + "rindex": []*FuncDef{&FuncDef{Name: "rindex", Args: []string{"$x"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "indices", Args: []*Query{&Query{Func: "$x"}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeUnary, Unary: &Unary{Op: OpSub, Term: &Term{Type: TermTypeNumber, Number: "1"}}}}, IsSlice: true}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}}}}}, + "rtrimstr": []*FuncDef{&FuncDef{Name: "rtrimstr", Args: []string{"$x"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Left: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "string"}}}}, Op: OpAnd, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "string"}}}}}}}}, Op: OpAnd, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "endswith", Args: []*Query{&Query{Func: "$x"}}}}}}, Then: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{End: &Query{Term: &Term{Type: TermTypeUnary, Unary: &Unary{Op: OpSub, Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Func: "length"}}}}}}}}}}}}}}, + "scalars": []*FuncDef{&FuncDef{Name: "scalars", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "type"}, Op: OpPipe, Right: &Query{Left: &Query{Left: &Query{Func: "."}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "array"}}}}, Op: OpAnd, Right: &Query{Left: &Query{Func: "."}, Op: OpNe, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "object"}}}}}}}}}}}}, + "scan": []*FuncDef{&FuncDef{Name: "scan", Args: []string{"$re"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "scan", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "null"}}}}}}, &FuncDef{Name: "scan", Args: []string{"$re", "$flags"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "match", Args: []*Query{&Query{Func: "$re"}, &Query{Left: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "g"}}}, Op: OpAdd, Right: &Query{Func: "$flags"}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Term: &Term{Type: TermTypeQuery, Query: &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{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "captures"}}}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "string"}}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "string"}}}}}}}}}, + "select": []*FuncDef{&FuncDef{Name: "select", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Func: "f"}, Then: &Query{Func: "."}, Else: &Query{Func: "empty"}}}}}}, + "sort": []*FuncDef{&FuncDef{Name: "sort", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "sort_by", Args: []*Query{&Query{Func: "."}}}}}}}, + "sort_by": []*FuncDef{&FuncDef{Name: "sort_by", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_sort_by", Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "f"}}}}}}}}}}}}}}, + "splits": []*FuncDef{&FuncDef{Name: "splits", Args: []string{"$re"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "splits", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "null"}}}}}}, &FuncDef{Name: "splits", Args: []string{"$re", "$flags"}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "split", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "$flags"}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}}}}, + "startswith": []*FuncDef{&FuncDef{Name: "startswith", Args: []string{"$x"}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "string"}}}}, Then: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "string"}}}}}, Then: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{End: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Func: "length"}}}}}, Op: OpEq, Right: &Query{Func: "$x"}}, Else: &Query{Left: &Query{Func: "$x"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_type_error", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "startswith"}}}}}}}}}}}, Else: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_type_error", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "startswith"}}}}}}}}}}}}, + "strings": []*FuncDef{&FuncDef{Name: "strings", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "string"}}}}}}}}}}, + "sub": []*FuncDef{&FuncDef{Name: "sub", Args: []string{"$re", "str"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "sub", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "str"}, &Query{Func: "null"}}}}}}, &FuncDef{Name: "sub", Args: []string{"$re", "str", "$flags"}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$in"}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "match", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "$flags"}}}}, Pattern: &Pattern{Name: "$r"}, Start: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Term: &Term{Type: TermTypeString, Str: &String{}}}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}}, Update: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$x"}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: "$r"}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "captures"}}}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}}}}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "name"}}}, Op: OpNe, Right: &Query{Func: "null"}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{KeyQuery: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "name"}}}, Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Name: "string"}}}}}}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Left: &Query{Func: "add"}, Op: OpAlt, Right: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Left: &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: OpAdd, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$in"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$x"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}}}, IsSlice: true, End: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$r"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Name: "offset"}}}}}}}}}}}, Op: OpAdd, Right: &Query{Func: "str"}}, Op: OpComma, Right: &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"}}}}}}}}}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$in"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "1"}}}}}, IsSlice: true}}}}}}}}}}}}}}, + "test": []*FuncDef{&FuncDef{Name: "test", Args: []string{"$re"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "test", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "null"}}}}}}, &FuncDef{Name: "test", Args: []string{"$re", "$flags"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_match", Args: []*Query{&Query{Func: "$re"}, &Query{Func: "$flags"}, &Query{Func: "true"}}}}}}}, + "to_entries": []*FuncDef{&FuncDef{Name: "to_entries", Body: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "keys"}, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$k"}}, Body: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{Key: "key", Val: &ObjectVal{Queries: []*Query{&Query{Func: "$k"}}}}, &ObjectKeyVal{Key: "value", Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Func: "$k"}}}}}}}}}}}}}}}}}}}}}, + "todate": []*FuncDef{&FuncDef{Name: "todate", Body: &Query{Func: "todateiso8601"}}}, + "todateiso8601": []*FuncDef{&FuncDef{Name: "todateiso8601", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "strftime", Args: []*Query{&Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "%Y-%m-%dT%H:%M:%SZ"}}}}}}}}}, + "tostream": []*FuncDef{&FuncDef{Name: "tostream", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "path", Args: []*Query{&Query{FuncDefs: []*FuncDef{&FuncDef{Name: "r", Body: &Query{Left: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Optional: true}}}}, Op: OpPipe, Right: &Query{Func: "r"}}}}, Op: OpComma, Right: &Query{Func: "."}}}}, Func: "r"}}}, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$p"}}, Body: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "getpath", Args: []*Query{&Query{Func: "$p"}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "path", Args: []*Query{&Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Iter: true}, &Suffix{Optional: true}}}}}}}, Pattern: &Pattern{Name: "$q"}, Start: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: "$p"}, Op: OpComma, Right: &Query{Func: "."}}}}}, Update: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Left: &Query{Func: "$p"}, Op: OpAdd, Right: &Query{Func: "$q"}}}}}}}}}}}}}}}}, + "transpose": []*FuncDef{&FuncDef{Name: "transpose", Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "."}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{}}}}, Then: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{}}}, Else: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$in"}}, Body: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Func: "length"}}}}}, Op: OpPipe, Right: &Query{Func: "max"}}, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$max"}}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "length"}, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$length"}}, Body: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "range", Args: []*Query{&Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}, &Query{Func: "$max"}}}}, Pattern: &Pattern{Name: "$j"}, Start: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{}}}, Update: &Query{Left: &Query{Func: "."}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "range", Args: []*Query{&Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}, &Query{Func: "$length"}}}}, Pattern: &Pattern{Name: "$i"}, Start: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{}}}, Update: &Query{Left: &Query{Func: "."}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$in"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Func: "$i"}}}, &Suffix{Index: &Index{Start: &Query{Func: "$j"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}, + "truncate_stream": []*FuncDef{&FuncDef{Name: "truncate_stream", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$n"}}, Body: &Query{Left: &Query{Func: "null"}, Op: OpPipe, Right: &Query{Left: &Query{Func: "f"}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$input"}}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Term: &Term{Type: TermTypeIndex, Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}, Op: OpPipe, Right: &Query{Func: "length"}}}}, Op: OpGt, Right: &Query{Func: "$n"}}, Then: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "setpath", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}}, &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$input"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Term: &Term{Type: TermTypeNumber, Number: "0"}}}}, &Suffix{Index: &Index{Start: &Query{Func: "$n"}, IsSlice: true}}}}}}}}}, Else: &Query{Func: "empty"}}}}}}}}}}}}}}}}}}, + "unique": []*FuncDef{&FuncDef{Name: "unique", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "unique_by", Args: []*Query{&Query{Func: "."}}}}}}}, + "unique_by": []*FuncDef{&FuncDef{Name: "unique_by", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "_unique_by", Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeArray, Array: &Array{Query: &Query{Func: "f"}}}}}}}}}}}}}}, + "until": []*FuncDef{&FuncDef{Name: "until", Args: []string{"cond", "next"}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: "_until", Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Func: "cond"}, Then: &Query{Func: "."}, Else: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "next"}, Op: OpPipe, Right: &Query{Func: "_until"}}}}}}}}}, Func: "_until"}}}, + "values": []*FuncDef{&FuncDef{Name: "values", Body: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "select", Args: []*Query{&Query{Left: &Query{Func: "."}, Op: OpNe, Right: &Query{Func: "null"}}}}}}}}, + "walk": []*FuncDef{&FuncDef{Name: "walk", Args: []string{"f"}, Body: &Query{Term: &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{&Suffix{Bind: &Bind{Patterns: []*Pattern{&Pattern{Name: "$in"}}, Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "object"}}}}, Then: &Query{Left: &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "keys"}, SuffixList: []*Suffix{&Suffix{Iter: true}}}, Pattern: &Pattern{Name: "$key"}, Start: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{}}}, Update: &Query{Left: &Query{Func: "."}, Op: OpAdd, Right: &Query{Term: &Term{Type: TermTypeObject, Object: &Object{KeyVals: []*ObjectKeyVal{&ObjectKeyVal{KeyQuery: &Query{Func: "$key"}, Val: &ObjectVal{Queries: []*Query{&Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "$in"}, SuffixList: []*Suffix{&Suffix{Index: &Index{Start: &Query{Func: "$key"}}}}}}, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "walk", Args: []*Query{&Query{Func: "f"}}}}}}}}}}}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "f"}}, Elif: []*IfElif{&IfElif{Cond: &Query{Left: &Query{Func: "type"}, Op: OpEq, Right: &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: "array"}}}}, Then: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "walk", Args: []*Query{&Query{Func: "f"}}}}}}}}}, Op: OpPipe, Right: &Query{Func: "f"}}}}, Else: &Query{Func: "f"}}}}}}}}}}}, + "while": []*FuncDef{&FuncDef{Name: "while", Args: []string{"cond", "update"}, Body: &Query{FuncDefs: []*FuncDef{&FuncDef{Name: "_while", Body: &Query{Term: &Term{Type: TermTypeIf, If: &If{Cond: &Query{Func: "cond"}, Then: &Query{Left: &Query{Func: "."}, Op: OpComma, Right: &Query{Term: &Term{Type: TermTypeQuery, Query: &Query{Left: &Query{Func: "update"}, Op: OpPipe, Right: &Query{Func: "_while"}}}}}, Else: &Query{Func: "empty"}}}}}}, Func: "_while"}}}, + "with_entries": []*FuncDef{&FuncDef{Name: "with_entries", Args: []string{"f"}, Body: &Query{Left: &Query{Func: "to_entries"}, Op: OpPipe, Right: &Query{Left: &Query{Term: &Term{Type: TermTypeFunc, Func: &Func{Name: "map", Args: []*Query{&Query{Func: "f"}}}}}, Op: OpPipe, Right: &Query{Func: "from_entries"}}}}}, } } diff --git a/vendor/github.com/itchyny/gojq/builtin.jq b/vendor/github.com/itchyny/gojq/builtin.jq index e18c070f..22913ba5 100644 --- a/vendor/github.com/itchyny/gojq/builtin.jq +++ b/vendor/github.com/itchyny/gojq/builtin.jq @@ -1,7 +1,6 @@ def not: if . then false else true end; def in(xs): . as $x | xs | has($x); def map(f): [.[] | f]; -def add: reduce .[] as $x (null; . + $x); def to_entries: [keys[] as $k | {key: $k, value: .[$k]}]; def from_entries: map({ (.key // .Key // .name // .Name): (if has("value") then .value else .Value end) }) @@ -42,31 +41,14 @@ def flatten($x): else _flatten($x) end; def flatten: _flatten(-1); def min: min_by(.); -def min_by(f): reduce .[1:][] as $x (.[0]; if (.|f) > ($x|f) then $x end); +def min_by(f): _min_by(map([f])); def max: max_by(.); -def max_by(f): reduce .[1:][] as $x (.[0]; if (.|f) <= ($x|f) then $x end); +def max_by(f): _max_by(map([f])); def sort: sort_by(.); -def sort_by(f): - def _sort_by: - if length > 1 then - .[0] as $x | .[1:] as $xs | ($x|[f]) as $fx - | ([$xs[] | select([f] < $fx)] | _sort_by) - + [$x] - + ([$xs[] | select([f] >= $fx)] | _sort_by) - end; - _sort_by; -def group_by(f): - def _group_by: - if length > 0 then - .[0] as $x | .[1:] as $xs | ($x|[f]) as $fx - | [$x, $xs[] | select([f] == $fx)], - ([$xs[] | select([f] != $fx)] | _group_by) - else - empty - end; - sort_by(f) | [_group_by]; -def unique: group_by(.) | map(.[0]); -def unique_by(f): group_by(f) | map(.[0]); +def sort_by(f): _sort_by(map([f])); +def group_by(f): _group_by(map([f])); +def unique: unique_by(.); +def unique_by(f): _unique_by(map([f])); def arrays: select(type == "array"); def objects: select(type == "object"); @@ -81,7 +63,6 @@ def values: select(. != null); def scalars: select(type |. != "array" and . != "object"); def leaf_paths: paths(scalars); -def reverse: [.[length - 1 - range(0;length)]]; def indices($x): if type == "array" and ($x|type) == "array" then .[$x] elif type == "array" then .[[$x]] @@ -207,7 +188,7 @@ def _assign(ps; $v): reduce path(ps) as $p (.; setpath($p; $v)); def _modify(ps; f): reduce path(ps) as $p - ([., []]; label $out | ([0] + $p as $q | setpath($q; getpath($q) | f) | ., break $out), .[1] += [$p]) + ([., []]; label $out | (([0] + $p) as $q | setpath($q; getpath($q) | f) | ., break $out), .[1] += [$p]) | . as $x | $x[0] | delpaths($x[1]); def map_values(f): .[] |= f; def del(f): delpaths([path(f)]); @@ -217,43 +198,15 @@ def paths: def paths(f): . as $x | paths | select(. as $p | $x | getpath($p) | f); -def bsearch($target): - if length == 0 then - -1 - elif length == 1 then - if $target == .[0] then 0 elif $target < .[0] then -1 else -2 end - else . as $in - # state variable: [start, end, answer] - # where start and end are the upper and lower offsets to use. - | [0, length-1, null] - | until(.[0] > .[1]; - if .[2] != null then (.[1] = -1) # i.e. break - else - (((.[1] + .[0]) / 2) | floor) as $mid - | $in[$mid] as $monkey - | if $monkey == $target then (.[2] = $mid) # success - elif .[0] == .[1] then (.[1] = -1) # failure - elif $monkey < $target then (.[0] = ($mid + 1)) - else (.[1] = ($mid - 1)) - end - end) - | if .[2] == null then # compute the insertion point - if $in[.[0]] < $target then (-2 -.[0]) - else (-1 -.[0]) - end - else .[2] - end - end; - def fromdateiso8601: strptime("%Y-%m-%dT%H:%M:%SZ") | mktime; def todateiso8601: strftime("%Y-%m-%dT%H:%M:%SZ"); def fromdate: fromdateiso8601; def todate: todateiso8601; def match($re): match($re; null); -def match($re; $flags): _match_impl($re; $flags; false) | .[]; +def match($re; $flags): _match($re; $flags; false) | .[]; def test($re): test($re; null); -def test($re; $flags): _match_impl($re; $flags; true); +def test($re; $flags): _match($re; $flags; true); def capture($re): capture($re; null); def capture($re; $flags): match($re; $flags) diff --git a/vendor/github.com/itchyny/gojq/clone.go b/vendor/github.com/itchyny/gojq/clone.go deleted file mode 100644 index 25523395..00000000 --- a/vendor/github.com/itchyny/gojq/clone.go +++ /dev/null @@ -1,20 +0,0 @@ -package gojq - -func clone(v interface{}) interface{} { - switch v := v.(type) { - case map[string]interface{}: - u := make(map[string]interface{}, len(v)) - for k, v := range v { - u[k] = clone(v) - } - return u - case []interface{}: - u := make([]interface{}, len(v)) - for i, v := range v { - u[i] = clone(v) - } - return u - default: - return v - } -} diff --git a/vendor/github.com/itchyny/gojq/code.go b/vendor/github.com/itchyny/gojq/code.go index dc146d08..da430619 100644 --- a/vendor/github.com/itchyny/gojq/code.go +++ b/vendor/github.com/itchyny/gojq/code.go @@ -18,7 +18,8 @@ const ( opobject opappend opfork - opforkopt + opforktrybegin + opforktryend opforkalt opforklabel opbacktrack @@ -59,8 +60,10 @@ func (op opcode) String() string { return "append" case opfork: return "fork" - case opforkopt: - return "forkopt" + case opforktrybegin: + return "forktrybegin" + case opforktryend: + return "forktryend" case opforkalt: return "forkalt" case opforklabel: diff --git a/vendor/github.com/itchyny/gojq/compiler.go b/vendor/github.com/itchyny/gojq/compiler.go index d3b51efb..6d7116ca 100644 --- a/vendor/github.com/itchyny/gojq/compiler.go +++ b/vendor/github.com/itchyny/gojq/compiler.go @@ -7,9 +7,7 @@ import ( "fmt" "regexp" "sort" - "strconv" "strings" - "unicode/utf8" ) type compiler struct { @@ -42,7 +40,7 @@ func (c *Code) Run(v interface{}, values ...interface{}) Iter { // RunWithContext runs the code with context. func (c *Code) RunWithContext(ctx context.Context, v interface{}, values ...interface{}) Iter { if len(values) > len(c.variables) { - return unitIterator(errTooManyVariableValues) + return unitIterator(&tooManyVariableValuesError{}) } else if len(values) < len(c.variables) { return unitIterator(&expectedVariableError{c.variables[len(values)]}) } @@ -54,9 +52,9 @@ func (c *Code) RunWithContext(ctx context.Context, v interface{}, values ...inte // ModuleLoader is an interface for loading modules. type ModuleLoader interface { - LoadModule(string) (*Module, error) - // (optional) LoadModuleWithMeta(string, map[string]interface{}) (*Module, error) - // (optional) LoadInitModules() ([]*Module, error) + LoadModule(string) (*Query, error) + // (optional) LoadModuleWithMeta(string, map[string]interface{}) (*Query, error) + // (optional) LoadInitModules() ([]*Query, error) // (optional) LoadJSON(string) (interface{}, error) // (optional) LoadJSONWithMeta(string, map[string]interface{}) (interface{}, error) } @@ -99,20 +97,25 @@ func Compile(q *Query, options ...CompilerOption) (*Code, error) { })() if c.moduleLoader != nil { if moduleLoader, ok := c.moduleLoader.(interface { - LoadInitModules() ([]*Module, error) + LoadInitModules() ([]*Query, error) }); ok { - ms, err := moduleLoader.LoadInitModules() + qs, err := moduleLoader.LoadInitModules() if err != nil { return nil, err } - for _, m := range ms { - if err := c.compileModule(m, ""); err != nil { + for _, q := range qs { + if err := c.compileModule(q, ""); err != nil { return nil, err } } } } - return c.compile(q) + code, err := c.compile(q) + if err != nil { + return nil, err + } + c.optimizeJumps() + return code, nil } var varNameRe = regexp.MustCompile(`^\$[a-zA-Z_][a-zA-Z0-9_]*$`) @@ -134,7 +137,6 @@ func (c *compiler) compile(q *Query) (*Code, error) { return nil, err } c.append(&code{op: opret}) - c.optimizeJumps() return &Code{ variables: c.variables, codes: c.codes, @@ -144,17 +146,14 @@ func (c *compiler) compile(q *Query) (*Code, error) { func (c *compiler) compileImport(i *Import) error { var path, alias string + var err error if i.ImportPath != "" { path, alias = i.ImportPath, i.ImportAlias } else { path = i.IncludePath } if c.moduleLoader == nil { - return fmt.Errorf("cannot load module: %s", path) - } - path, err := strconv.Unquote(path) - if err != nil { - return err + return fmt.Errorf("cannot load module: %q", path) } if strings.HasPrefix(alias, "$") { var vals interface{} @@ -179,27 +178,28 @@ func (c *compiler) compileImport(i *Import) error { c.append(&code{op: opstore, v: c.pushVariable(alias + "::" + alias[1:])}) return nil } - var m *Module + var q *Query if moduleLoader, ok := c.moduleLoader.(interface { - LoadModuleWithMeta(string, map[string]interface{}) (*Module, error) + LoadModuleWithMeta(string, map[string]interface{}) (*Query, error) }); ok { - if m, err = moduleLoader.LoadModuleWithMeta(path, i.Meta.ToValue()); err != nil { + if q, err = moduleLoader.LoadModuleWithMeta(path, i.Meta.ToValue()); err != nil { return err } - } else if m, err = c.moduleLoader.LoadModule(path); err != nil { + } else if q, err = c.moduleLoader.LoadModule(path); err != nil { return err } c.appendCodeInfo("module " + path) defer c.appendCodeInfo("end of module " + path) - return c.compileModule(m, alias) + return c.compileModule(q, alias) } -func (c *compiler) compileModule(m *Module, alias string) error { +func (c *compiler) compileModule(q *Query, alias string) error { cc := &compiler{ moduleLoader: c.moduleLoader, environLoader: c.environLoader, variables: c.variables, inputIter: c.inputIter, - codeoffset: c.pc(), scopes: c.scopes, scopecnt: c.scopecnt} + codeoffset: c.pc(), scopes: c.scopes, scopecnt: c.scopecnt, + } defer cc.newScopeDepth()() - bs, err := cc.compileModuleInternal(m) + bs, err := cc.compileModuleInternal(q) if err != nil { return err } @@ -215,13 +215,13 @@ func (c *compiler) compileModule(m *Module, alias string) error { return nil } -func (c *compiler) compileModuleInternal(m *Module) (*Code, error) { - for _, i := range m.Imports { +func (c *compiler) compileModuleInternal(q *Query) (*Code, error) { + for _, i := range q.Imports { if err := c.compileImport(i); err != nil { return nil, err } } - for _, fd := range m.FuncDefs { + for _, fd := range q.FuncDefs { if err := c.compileFuncDef(fd, false); err != nil { return nil, err } @@ -283,7 +283,8 @@ func (c *compiler) compileFuncDef(e *FuncDef, builtin bool) error { c.funcs = append(c.funcs, &funcinfo{e.Name, pc, e.Args, argsorder}) cc := &compiler{ moduleLoader: c.moduleLoader, environLoader: c.environLoader, inputIter: c.inputIter, - codeoffset: pc, scopecnt: c.scopecnt, funcs: c.funcs} + codeoffset: pc, scopecnt: c.scopecnt, funcs: c.funcs, + } scope := cc.newScope() cc.scopes = append(c.scopes, scope) setscope := cc.lazy(func() *code { @@ -340,51 +341,96 @@ func getArgsOrder(args []string) []int { } func (c *compiler) compileQuery(e *Query) error { - for _, e := range e.Commas { - if err := c.compileComma(e); err != nil { + for _, fd := range e.FuncDefs { + if err := c.compileFuncDef(fd, false); err != nil { return err } } - return nil + if e.Func != "" { + switch e.Func { + case ".": + return c.compileTerm(&Term{Type: TermTypeIdentity}) + case "..": + return c.compileTerm(&Term{Type: TermTypeRecurse}) + case "null": + return c.compileTerm(&Term{Type: TermTypeNull}) + case "true": + return c.compileTerm(&Term{Type: TermTypeTrue}) + case "false": + return c.compileTerm(&Term{Type: TermTypeFalse}) + default: + return c.compileFunc(&Func{Name: e.Func}) + } + } else if e.Term != nil { + return c.compileTerm(e.Term) + } + switch e.Op { + case OpPipe: + if err := c.compileQuery(e.Left); err != nil { + return err + } + return c.compileQuery(e.Right) + case OpComma: + return c.compileComma(e.Left, e.Right) + case OpAlt: + return c.compileAlt(e.Left, e.Right) + case OpAssign, OpModify, OpUpdateAdd, OpUpdateSub, + OpUpdateMul, OpUpdateDiv, OpUpdateMod, OpUpdateAlt: + return c.compileQueryUpdate(e.Left, e.Right, e.Op) + case OpOr: + return c.compileIf( + &If{ + Cond: e.Left, + Then: &Query{Term: &Term{Type: TermTypeTrue}}, + Else: &Query{Term: &Term{Type: TermTypeIf, If: &If{ + Cond: e.Right, + Then: &Query{Term: &Term{Type: TermTypeTrue}}, + Else: &Query{Term: &Term{Type: TermTypeFalse}}, + }}}, + }, + ) + case OpAnd: + return c.compileIf( + &If{ + Cond: e.Left, + Then: &Query{Term: &Term{Type: TermTypeIf, If: &If{ + Cond: e.Right, + Then: &Query{Term: &Term{Type: TermTypeTrue}}, + Else: &Query{Term: &Term{Type: TermTypeFalse}}, + }}}, + Else: &Query{Term: &Term{Type: TermTypeFalse}}, + }, + ) + default: + return c.compileCall( + e.Op.getFunc(), + []*Query{e.Left, e.Right}, + ) + } } -func (c *compiler) compileComma(e *Comma) error { - if len(e.Filters) == 1 { - return c.compileFilter(e.Filters[0]) - } +func (c *compiler) compileComma(l, r *Query) error { setfork := c.lazy(func() *code { return &code{op: opfork, v: c.pc() + 1} }) - if err := c.compileComma(&Comma{Filters: e.Filters[:len(e.Filters)-1]}); err != nil { + if err := c.compileQuery(l); err != nil { return err } setfork() defer c.lazy(func() *code { return &code{op: opjump, v: c.pc()} })() - return c.compileFilter(e.Filters[len(e.Filters)-1]) -} - -func (c *compiler) compileFilter(e *Filter) error { - for _, fd := range e.FuncDefs { - if err := c.compileFuncDef(fd, false); err != nil { - return err - } - } - return c.compileAlt(e.Alt) + return c.compileQuery(r) } -func (c *compiler) compileAlt(e *Alt) error { - if len(e.Right) == 0 { - return c.compileExpr(e.Left) - } +func (c *compiler) compileAlt(l, r *Query) error { c.append(&code{op: oppush, v: false}) found := c.newVariable() c.append(&code{op: opstore, v: found}) setfork := c.lazy(func() *code { return &code{op: opfork, v: c.pc()} // opload found }) - if err := c.compileExpr(e.Left); err != nil { + if err := c.compileQuery(l); err != nil { return err } c.append(&code{op: opdup}) @@ -401,42 +447,19 @@ func (c *compiler) compileAlt(e *Alt) error { c.append(&code{op: opjumpifnot, v: c.pc() + 3}) c.append(&code{op: opbacktrack}) // if found, backtrack c.append(&code{op: oppop}) - return c.compileAlt(&Alt{e.Right[0].Right, e.Right[1:]}) -} - -func (c *compiler) compileExpr(e *Expr) (err error) { - if e.Update != nil { - return c.compileExprUpdate(e) - } else if e.Bind != nil { - c.append(&code{op: opdup}) - c.append(&code{op: opexpbegin}) - defer func() { - if err == nil { - err = c.compileBind(e.Bind) - } - }() - } - if e.Logic != nil { - return c.compileLogic(e.Logic) - } else if e.Label != nil { - return c.compileLabel(e.Label) - } else { - return fmt.Errorf("invalid expr: %s", e) - } + return c.compileQuery(r) } -func (c *compiler) compileExprUpdate(e *Expr) (err error) { - t := *e // clone without changing e - (&t).Update = nil - switch e.UpdateOp { +func (c *compiler) compileQueryUpdate(l, r *Query, op Operator) (err error) { + switch op { case OpAssign: // .foo.bar = f => setpath(["foo", "bar"]; f) - if xs := t.toIndices(); xs != nil { + if xs := l.toIndices(); xs != nil { // ref: compileCall v := c.newVariable() c.append(&code{op: opstore, v: v}) c.append(&code{op: opload, v: v}) - if err := c.compileAlt(e.Update); err != nil { + if err := c.compileQuery(r); err != nil { return err } c.append(&code{op: oppush, v: xs}) @@ -448,17 +471,14 @@ func (c *compiler) compileExprUpdate(e *Expr) (err error) { case OpModify: return c.compileFunc( &Func{ - Name: e.UpdateOp.getFunc(), - Args: []*Query{ - t.toQuery(), - e.Update.toQuery(), - }, + Name: op.getFunc(), + Args: []*Query{l, r}, }, ) default: name := "$%0" c.append(&code{op: opdup}) - if err := c.compileAlt(e.Update); err != nil { + if err := c.compileQuery(r); err != nil { return err } c.append(&code{op: opstore, v: c.pushVariable(name)}) @@ -466,14 +486,17 @@ func (c *compiler) compileExprUpdate(e *Expr) (err error) { &Func{ Name: "_modify", Args: []*Query{ - t.toQuery(), - (&Term{Func: &Func{ - Name: e.UpdateOp.getFunc(), - Args: []*Query{ - (&Term{Identity: true}).toQuery(), - (&Term{Func: &Func{Name: name}}).toQuery(), + l, + {Term: &Term{ + Type: TermTypeFunc, + Func: &Func{ + Name: op.getFunc(), + Args: []*Query{ + {Term: &Term{Type: TermTypeIdentity}}, + {Func: name}, + }, }, - }}).toQuery(), + }}, }, }, ) @@ -515,7 +538,7 @@ func (c *compiler) compileBind(b *Bind) error { c.codes[len(c.codes)-2] = c.codes[len(c.codes)-1] c.codes = c.codes[:len(c.codes)-1] } else { - c.append(&code{op: opexpend}) // ref: compileExpr + c.append(&code{op: opexpend}) // ref: compileQuery } return c.compileQuery(b.Body) } @@ -558,12 +581,14 @@ func (c *compiler) compilePattern(p *Pattern) ([][2]int, error) { key, name = key[1:], key } c.append(&code{op: oppush, v: key}) - } else if kv.KeyString != "" { - key = kv.KeyString[1 : len(kv.KeyString)-1] - c.append(&code{op: oppush, v: key}) - } else if kv.Query != nil { + } else if kv.KeyString != nil { + c.append(&code{op: opload, v: v}) + if err := c.compileString(kv.KeyString, nil); err != nil { + return nil, err + } + } else if kv.KeyQuery != nil { c.append(&code{op: opload, v: v}) - if err := c.compileQuery(kv.Query); err != nil { + if err := c.compileQuery(kv.KeyQuery); err != nil { return nil, err } } @@ -595,23 +620,6 @@ func (c *compiler) compilePattern(p *Pattern) ([][2]int, error) { } } -func (c *compiler) compileLogic(e *Logic) error { - if len(e.Right) == 0 { - return c.compileAndExpr(e.Left) - } - return c.compileIf( - &If{ - Cond: (&Logic{e.Left, e.Right[:len(e.Right)-1]}).toQuery(), - Then: (&Term{True: true}).toQuery(), - Else: (&Term{If: &If{ - Cond: e.Right[len(e.Right)-1].Right.toQuery(), - Then: (&Term{True: true}).toQuery(), - Else: (&Term{False: true}).toQuery(), - }}).toQuery(), - }, - ) -} - func (c *compiler) compileIf(e *If) error { c.appendCodeInfo(e) c.append(&code{op: opdup}) // duplicate the value for then or else clause @@ -646,21 +654,22 @@ func (c *compiler) compileIf(e *If) error { func (c *compiler) compileTry(e *Try) error { c.appendCodeInfo(e) - setforkopt := c.lazy(func() *code { - return &code{op: opforkopt, v: c.pc()} + setforktrybegin := c.lazy(func() *code { + return &code{op: opforktrybegin, v: c.pc()} }) f := c.newScopeDepth() if err := c.compileQuery(e.Body); err != nil { return err } f() + c.append(&code{op: opforktryend}) defer c.lazy(func() *code { return &code{op: opjump, v: c.pc()} })() - setforkopt() + setforktrybegin() if e.Catch != nil { defer c.newScopeDepth()() - return c.compileTerm(e.Catch) + return c.compileQuery(e.Catch) } c.append(&code{op: opbacktrack}) return nil @@ -739,61 +748,6 @@ func (c *compiler) compileLabel(e *Label) error { return c.compileQuery(e.Body) } -func (c *compiler) compileAndExpr(e *AndExpr) error { - if len(e.Right) == 0 { - return c.compileCompare(e.Left) - } - return c.compileIf( - &If{ - Cond: (&AndExpr{e.Left, e.Right[:len(e.Right)-1]}).toQuery(), - Then: (&Term{If: &If{ - Cond: e.Right[len(e.Right)-1].Right.toQuery(), - Then: (&Term{True: true}).toQuery(), - Else: (&Term{False: true}).toQuery(), - }}).toQuery(), - Else: (&Term{False: true}).toQuery(), - }, - ) -} - -func (c *compiler) compileCompare(e *Compare) error { - if e.Right == nil { - return c.compileArith(e.Left) - } - return c.compileCall( - e.Right.Op.getFunc(), - []*Query{e.Left.toQuery(), e.Right.Right.toQuery()}, - ) -} - -func (c *compiler) compileArith(e *Arith) error { - if len(e.Right) == 0 { - return c.compileFactor(e.Left) - } - r := e.Right[len(e.Right)-1] - return c.compileCall( - r.Op.getFunc(), - []*Query{ - (&Arith{e.Left, e.Right[:len(e.Right)-1]}).toQuery(), - r.Right.toQuery(), - }, - ) -} - -func (c *compiler) compileFactor(e *Factor) error { - if len(e.Right) == 0 { - return c.compileTerm(e.Left) - } - r := e.Right[len(e.Right)-1] - return c.compileCall( - r.Op.getFunc(), - []*Query{ - (&Factor{e.Left, e.Right[:len(e.Right)-1]}).toQuery(), - r.Right.toQuery(), - }, - ) -} - func (c *compiler) compileTerm(e *Term) (err error) { if len(e.SuffixList) > 0 { s := e.SuffixList[len(e.SuffixList)-1] @@ -801,58 +755,59 @@ func (c *compiler) compileTerm(e *Term) (err error) { (&t).SuffixList = t.SuffixList[:len(e.SuffixList)-1] return c.compileTermSuffix(&t, s) } - if e.Index != nil { - return c.compileIndex(&Term{Identity: true}, e.Index) - } else if e.Identity { + switch e.Type { + case TermTypeIdentity: return nil - } else if e.Recurse { + case TermTypeRecurse: return c.compileFunc(&Func{Name: "recurse"}) - } else if e.Null { + case TermTypeNull: c.append(&code{op: opconst, v: nil}) return nil - } else if e.True { + case TermTypeTrue: c.append(&code{op: opconst, v: true}) return nil - } else if e.False { + case TermTypeFalse: c.append(&code{op: opconst, v: false}) return nil - } else if e.Func != nil { + case TermTypeIndex: + return c.compileIndex(&Term{Type: TermTypeIdentity}, e.Index) + case TermTypeFunc: return c.compileFunc(e.Func) - } else if e.Object != nil { + case TermTypeObject: return c.compileObject(e.Object) - } else if e.Array != nil { + case TermTypeArray: return c.compileArray(e.Array) - } else if e.Number != "" { + case TermTypeNumber: v := normalizeNumbers(json.Number(e.Number)) if err, ok := v.(error); ok { return err } c.append(&code{op: opconst, v: v}) return nil - } else if e.Unary != nil { + case TermTypeUnary: return c.compileUnary(e.Unary) - } else if e.Format != "" { - return c.compileFormat(e.Format, e.FormatStr) - } else if e.Str != "" { - return c.compileString(e.Str) - } else if e.RawStr != "" { - c.append(&code{op: opconst, v: e.RawStr}) - return nil - } else if e.If != nil { + case TermTypeFormat: + return c.compileFormat(e.Format, e.Str) + case TermTypeString: + return c.compileString(e.Str, nil) + case TermTypeIf: return c.compileIf(e.If) - } else if e.Try != nil { + case TermTypeTry: return c.compileTry(e.Try) - } else if e.Reduce != nil { + case TermTypeReduce: return c.compileReduce(e.Reduce) - } else if e.Foreach != nil { + case TermTypeForeach: return c.compileForeach(e.Foreach) - } else if e.Break != "" { + case TermTypeLabel: + return c.compileLabel(e.Label) + case TermTypeBreak: c.append(&code{op: opconst, v: e.Break}) return c.compileCall("_break", nil) - } else if e.Query != nil { + case TermTypeQuery: + e.Query.minify() defer c.newScopeDepth()() return c.compileQuery(e.Query) - } else { + default: return fmt.Errorf("invalid term: %s", e) } } @@ -860,25 +815,21 @@ func (c *compiler) compileTerm(e *Term) (err error) { func (c *compiler) compileIndex(e *Term, x *Index) error { c.appendCodeInfo(x) if x.Name != "" { - return c.compileCall("_index", []*Query{e.toQuery(), (&Term{RawStr: x.Name[1:]}).toQuery()}) + return c.compileCall("_index", []*Query{{Term: e}, {Term: &Term{Type: TermTypeString, Str: &String{Str: x.Name}}}}) } - if x.Str != "" { - q, err := c.stringToQuery(x.Str, nil) - if err != nil { - return err - } - return c.compileCall("_index", []*Query{e.toQuery(), q}) + if x.Str != nil { + return c.compileCall("_index", []*Query{{Term: e}, {Term: &Term{Type: TermTypeString, Str: x.Str}}}) } if x.Start != nil { if x.IsSlice { if x.End != nil { - return c.compileCall("_slice", []*Query{e.toQuery(), x.End, x.Start}) + return c.compileCall("_slice", []*Query{{Term: e}, x.End, x.Start}) } - return c.compileCall("_slice", []*Query{e.toQuery(), (&Term{Null: true}).toQuery(), x.Start}) + return c.compileCall("_slice", []*Query{{Term: e}, {Term: &Term{Type: TermTypeNull}}, x.Start}) } - return c.compileCall("_index", []*Query{e.toQuery(), x.Start}) + return c.compileCall("_index", []*Query{{Term: e}, x.Start}) } - return c.compileCall("_slice", []*Query{e.toQuery(), x.End, (&Term{Null: true}).toQuery()}) + return c.compileCall("_slice", []*Query{{Term: e}, x.End, {Term: &Term{Type: TermTypeNull}}}) } func (c *compiler) compileFunc(e *Func) error { @@ -993,23 +944,23 @@ func (c *compiler) funcModulemeta(v interface{}, _ []interface{}) interface{} { if c.moduleLoader == nil { return fmt.Errorf("cannot load module: %q", s) } - var m *Module + var q *Query var err error if moduleLoader, ok := c.moduleLoader.(interface { - LoadModuleWithMeta(string, map[string]interface{}) (*Module, error) + LoadModuleWithMeta(string, map[string]interface{}) (*Query, error) }); ok { - if m, err = moduleLoader.LoadModuleWithMeta(s, nil); err != nil { + if q, err = moduleLoader.LoadModuleWithMeta(s, nil); err != nil { return err } - } else if m, err = c.moduleLoader.LoadModule(s); err != nil { + } else if q, err = c.moduleLoader.LoadModule(s); err != nil { return err } - meta := m.Meta.ToValue() + meta := q.Meta.ToValue() if meta == nil { meta = make(map[string]interface{}) } var deps []interface{} - for _, i := range m.Imports { + for _, i := range q.Imports { v := i.Meta.ToValue() if v == nil { v = make(map[string]interface{}) @@ -1022,9 +973,9 @@ func (c *compiler) funcModulemeta(v interface{}, _ []interface{}) interface{} { } } if i.ImportPath == "" { - v["relpath"], err = strconv.Unquote(i.IncludePath) + v["relpath"] = i.IncludePath } else { - v["relpath"], err = strconv.Unquote(i.ImportPath) + v["relpath"] = i.ImportPath } if err != nil { return err @@ -1048,28 +999,47 @@ func (c *compiler) compileObject(e *Object) error { defer c.newScopeDepth()() v := c.newVariable() c.append(&code{op: opstore, v: v}) + pc := len(c.codes) for _, kv := range e.KeyVals { if err := c.compileObjectKeyVal(v, kv); err != nil { return err } } c.append(&code{op: opobject, v: len(e.KeyVals)}) + // optimize constant objects + l := len(e.KeyVals) + if pc+l*3+1 != len(c.codes) { + return nil + } + for i := 0; i < l; i++ { + if c.codes[pc+i*3].op != oppush || + c.codes[pc+i*3+1].op != opload || + c.codes[pc+i*3+2].op != opconst { + return nil + } + } + w := make(map[string]interface{}, l) + for i := 0; i < l; i++ { + w[c.codes[pc+i*3].v.(string)] = c.codes[pc+i*3+2].v + } + c.codes[pc-1] = &code{op: opconst, v: w} + c.codes = c.codes[:pc] return nil } -func (c *compiler) compileObjectKeyVal(v [2]int, kv ObjectKeyVal) error { - if kv.KeyOnly != nil { - if (*kv.KeyOnly)[0] == '$' { - c.append(&code{op: oppush, v: (*kv.KeyOnly)[1:]}) +func (c *compiler) compileObjectKeyVal(v [2]int, kv *ObjectKeyVal) error { + if kv.KeyOnly != "" { + if kv.KeyOnly[0] == '$' { + c.append(&code{op: oppush, v: kv.KeyOnly[1:]}) c.append(&code{op: opload, v: v}) - return c.compileFunc(&Func{Name: *kv.KeyOnly}) + return c.compileFunc(&Func{Name: kv.KeyOnly}) } - c.append(&code{op: oppush, v: *kv.KeyOnly}) + c.append(&code{op: oppush, v: kv.KeyOnly}) c.append(&code{op: opload, v: v}) - return c.compileIndex(&Term{Identity: true}, &Index{Name: "." + *kv.KeyOnly}) - } else if kv.KeyOnlyString != "" { + return c.compileIndex(&Term{Type: TermTypeIdentity}, &Index{Name: kv.KeyOnly}) + } else if kv.KeyOnlyString != nil { c.append(&code{op: opload, v: v}) - if err := c.compileString(kv.KeyOnlyString); err != nil { + if err := c.compileString(kv.KeyOnlyString, nil); err != nil { return err } c.append(&code{op: opdup}) @@ -1079,16 +1049,21 @@ func (c *compiler) compileObjectKeyVal(v [2]int, kv ObjectKeyVal) error { c.append(&code{op: opcall, v: [3]interface{}{internalFuncs["_index"].callback, 2, "_index"}}) return nil } else { - if kv.Query != nil { + if kv.KeyQuery != nil { c.append(&code{op: opload, v: v}) f := c.newScopeDepth() - if err := c.compileQuery(kv.Query); err != nil { + if err := c.compileQuery(kv.KeyQuery); err != nil { return err } f() - } else if kv.KeyString != "" { + } else if kv.KeyString != nil { + c.append(&code{op: opload, v: v}) + if err := c.compileString(kv.KeyString, nil); err != nil { + return err + } + } else if kv.Key[0] == '$' { c.append(&code{op: opload, v: v}) - if err := c.compileString(kv.KeyString); err != nil { + if err := c.compileFunc(&Func{Name: kv.Key}); err != nil { return err } } else { @@ -1100,8 +1075,8 @@ func (c *compiler) compileObjectKeyVal(v [2]int, kv ObjectKeyVal) error { } func (c *compiler) compileObjectVal(e *ObjectVal) error { - for _, e := range e.Alts { - if err := c.compileAlt(e); err != nil { + for _, e := range e.Queries { + if err := c.compileQuery(e); err != nil { return err } } @@ -1117,9 +1092,13 @@ func (c *compiler) compileArray(e *Array) error { c.append(&code{op: oppush, v: []interface{}{}}) arr := c.newVariable() c.append(&code{op: opstore, v: arr}) - defer c.lazy(func() *code { - return &code{op: opfork, v: c.pc() - 2} - })() + pc := len(c.codes) + c.append(&code{op: opnop}) + defer func() { + if pc < len(c.codes) { + c.codes[pc] = &code{op: opfork, v: c.pc() - 2} + } + }() defer c.newScopeDepth()() if err := c.compileQuery(e.Query); err != nil { return err @@ -1128,6 +1107,27 @@ func (c *compiler) compileArray(e *Array) error { c.append(&code{op: opbacktrack}) c.append(&code{op: oppop}) c.append(&code{op: opload, v: arr}) + if e.Query.Op == OpPipe { + return nil + } + // optimize constant arrays + l := e.Query.countCommaQueries() + if 3*l != len(c.codes)-pc-3 { + return nil + } + for i := 0; i < l; i++ { + if (i > 0 && c.codes[pc+i].op != opfork) || + c.codes[pc+i*2+l].op != opconst || + (i < l-1 && c.codes[pc+i*2+l+1].op != opjump) { + return nil + } + } + v := make([]interface{}, l) + for i := 0; i < l; i++ { + v[i] = c.codes[pc+i*2+l].v + } + c.codes[pc-2] = &code{op: opconst, v: v} + c.codes = c.codes[:pc-1] return nil } @@ -1146,16 +1146,12 @@ func (c *compiler) compileUnary(e *Unary) error { } } -func (c *compiler) compileFormat(fmt, str string) error { +func (c *compiler) compileFormat(fmt string, str *String) error { if f := formatToFunc(fmt); f != nil { - if str == "" { + if str == nil { return c.compileFunc(f) } - q, err := c.stringToQuery(str, f) - if err != nil { - return err - } - return c.compileQuery(q) + return c.compileString(str, f) } return &formatNotFoundError{fmt} } @@ -1185,95 +1181,31 @@ func formatToFunc(fmt string) *Func { } } -func (c *compiler) compileString(s string) error { - if !strings.Contains(s, "\\(") { - s, err := strconv.Unquote(s) - if err == nil { - c.append(&code{op: opconst, v: s}) - return nil - } - } - q, err := c.stringToQuery(s, nil) - if err != nil { - return err +func (c *compiler) compileString(s *String, f *Func) error { + if s.Queries == nil { + c.append(&code{op: opconst, v: s.Str}) + return nil } - return c.compileQuery(q) -} - -func (c *compiler) stringToQuery(s string, f *Func) (*Query, error) { if f == nil { f = &Func{Name: "tostring"} } - // ref: strconv.Unquote - x := s[1 : len(s)-1] - var runeTmp [utf8.UTFMax]byte - buf := make([]byte, 0, 3*len(x)/2) - var xs []*Filter - var es []*Expr - var cnt int - for len(x) > 0 { - r, multibyte, ss, err := strconv.UnquoteChar(x, '"') - if err != nil { - if !strings.HasPrefix(x, "\\(") { - return nil, err - } - match := queryInStringPattern.FindString(x) - i := len([]byte(match)) - if i == 0 { - return nil, &stringLiteralError{s} - } - t := x[2 : i-1] - q, err := Parse(t) - if err != nil { - return nil, &stringQueryError{t, err} - } - x = x[i:] - if len(buf) > 0 { - xs = append(xs, (&Term{RawStr: string(buf)}).toFilter()) - buf = buf[:0] - } - q.Commas = append(q.Commas, (&Term{Func: f}).toQuery().Commas...) - name := fmt.Sprintf("$%%%d", cnt) - es = append(es, &Expr{ - Logic: (&Term{Query: q}).toLogic(), - Bind: &Bind{Patterns: []*Pattern{{Name: name}}}, - }) - xs = append(xs, (&Term{Func: &Func{Name: name}}).toFilter()) - cnt++ - continue - } - x = ss - if r < utf8.RuneSelf || !multibyte { - buf = append(buf, byte(r)) - } else { - n := utf8.EncodeRune(runeTmp[:], r) - buf = append(buf, runeTmp[:n]...) - } - } - if len(xs) == 0 { - return (&Term{RawStr: string(buf)}).toQuery(), nil + e := s.Queries[0] + if e.Term.Str == nil { + e = &Query{Left: e, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: f}}} } - if len(buf) > 0 { - xs = append(xs, (&Term{RawStr: string(buf)}).toFilter()) - } - q := (&Term{Array: &Array{&Query{Commas: []*Comma{{xs}}}}}).toQuery() - q.Commas = append(q.Commas, (&Term{ - Func: &Func{ - Name: "join", - Args: []*Query{(&Term{Str: `""`}).toQuery()}, - }}).toQuery().Commas...) - for _, e := range es { - e.Bind.Body, q = q, e.toQuery() + for i := 1; i < len(s.Queries); i++ { + x := s.Queries[i] + if x.Term.Str == nil { + x = &Query{Left: x, Op: OpPipe, Right: &Query{Term: &Term{Type: TermTypeFunc, Func: f}}} + } + e = &Query{Left: e, Op: OpAdd, Right: x} } - c.appendCodeInfo(q) - return q, nil + return c.compileQuery(e) } func (c *compiler) compileTermSuffix(e *Term, s *Suffix) error { if s.Index != nil { return c.compileIndex(e, s.Index) - } else if s.SuffixIndex != nil { - return c.compileIndex(e, s.SuffixIndex.toIndex()) } else if s.Iter { if err := c.compileTerm(e); err != nil { return err @@ -1291,7 +1223,14 @@ func (c *compiler) compileTermSuffix(e *Term, s *Suffix) error { return c.compileTermSuffix(u, s) } } - return c.compileTry(&Try{Body: e.toQuery()}) + return c.compileTry(&Try{Body: &Query{Term: e}}) + } else if s.Bind != nil { + c.append(&code{op: opdup}) + c.append(&code{op: opexpbegin}) + if err := c.compileTerm(e); err != nil { + return err + } + return c.compileBind(s.Bind) } else { return fmt.Errorf("invalid suffix: %s", s) } diff --git a/vendor/github.com/itchyny/gojq/debug.go b/vendor/github.com/itchyny/gojq/debug.go index e7463fde..eea1d1cc 100644 --- a/vendor/github.com/itchyny/gojq/debug.go +++ b/vendor/github.com/itchyny/gojq/debug.go @@ -136,9 +136,9 @@ func (env *env) debugState(pc int, backtrack bool) { func formatOp(c opcode, backtrack bool) string { if backtrack { - return c.String() + " " + strings.Repeat(" ", 10-len(c.String())) + return c.String() + " " + strings.Repeat(" ", 13-len(c.String())) } - return c.String() + strings.Repeat(" ", 22-len(c.String())) + return c.String() + strings.Repeat(" ", 25-len(c.String())) } func (env *env) debugForks(pc int, op string) { @@ -158,7 +158,7 @@ func (env *env) debugForks(pc int, op string) { buf.WriteByte('>') } } - fmt.Fprintf(debugOut, "\t-\t%s%s%d\t|\t%s\n", op, strings.Repeat(" ", 19), pc, buf.String()) + fmt.Fprintf(debugOut, "\t-\t%s%s%d\t|\t%s\n", op, strings.Repeat(" ", 22), pc, buf.String()) } func debugOperand(c *code) string { diff --git a/vendor/github.com/itchyny/gojq/env.go b/vendor/github.com/itchyny/gojq/env.go index ff0df2bc..4850b084 100644 --- a/vendor/github.com/itchyny/gojq/env.go +++ b/vendor/github.com/itchyny/gojq/env.go @@ -11,7 +11,7 @@ type env struct { codes []*code codeinfos []codeinfo forks []*fork - backtrack int + backtrack bool offset int expdepth int ctx context.Context diff --git a/vendor/github.com/itchyny/gojq/error.go b/vendor/github.com/itchyny/gojq/error.go index 6b2dacfe..13d49075 100644 --- a/vendor/github.com/itchyny/gojq/error.go +++ b/vendor/github.com/itchyny/gojq/error.go @@ -2,7 +2,6 @@ package gojq import ( "encoding/json" - "errors" "fmt" "math/big" "reflect" @@ -32,6 +31,14 @@ func (err *iteratorError) Error() string { return fmt.Sprintf("cannot iterate over: %s", typeErrorPreview(err.v)) } +type arrayIndexTooLargeError struct { + v interface{} +} + +func (err *arrayIndexTooLargeError) Error() string { + return fmt.Sprintf("array index too large: %s", previewValue(err.v)) +} + type objectKeyNotStringError struct { v interface{} } @@ -115,7 +122,7 @@ type hasKeyTypeError struct { } func (err *hasKeyTypeError) Error() string { - return fmt.Sprintf("cannot check wether %s has a key: %s", typeErrorPreview(err.l), typeErrorPreview(err.r)) + return fmt.Sprintf("cannot check whether %s has a key: %s", typeErrorPreview(err.l), typeErrorPreview(err.r)) } type unaryTypeError struct { @@ -177,7 +184,11 @@ func (err *formatShError) Error() string { return fmt.Sprintf("cannot escape for shell: %s", typeErrorPreview(err.v)) } -var errTooManyVariableValues = errors.New("too many variable values provided") +type tooManyVariableValuesError struct{} + +func (err *tooManyVariableValuesError) Error() string { + return "too many variable values provided" +} type expectedVariableError struct { n string @@ -219,17 +230,12 @@ func (err *stringLiteralError) Error() string { return fmt.Sprintf("expected a string but got: %s", err.s) } -type stringQueryError struct { - s string +type tryEndError struct { err error } -func (err *stringQueryError) Error() string { - return fmt.Sprintf("invalid query in string interpolation %s: %s", err.s, err.err) -} - -func (err *stringQueryError) QueryParseError() (string, string, string, error) { - return "query in string interpolation", "", err.s, err.err +func (err *tryEndError) Error() string { + return err.err.Error() } type invalidPathError struct { @@ -256,6 +262,32 @@ func (err *getpathError) Error() string { return fmt.Sprintf("cannot getpath with %s against: %s", previewValue(err.path), typeErrorPreview(err.v)) } +type queryParseError struct { + typ, fname, contents string + err error +} + +func (err *queryParseError) QueryParseError() (string, string, string, error) { + return err.typ, err.fname, err.contents, err.err +} + +func (err *queryParseError) Error() string { + return fmt.Sprintf("invalid %s: %s: %s", err.typ, err.fname, err.err) +} + +type jsonParseError struct { + fname, contents string + err error +} + +func (err *jsonParseError) JSONParseError() (string, string, error) { + return err.fname, err.contents, err.err +} + +func (err *jsonParseError) Error() string { + return fmt.Sprintf("invalid json: %s: %s", err.fname, err.err) +} + func typeErrorPreview(v interface{}) string { p := preview(v) if p != "" { diff --git a/vendor/github.com/itchyny/gojq/execute.go b/vendor/github.com/itchyny/gojq/execute.go index 9ff5508e..08d2d027 100644 --- a/vendor/github.com/itchyny/gojq/execute.go +++ b/vendor/github.com/itchyny/gojq/execute.go @@ -20,9 +20,8 @@ func (env *env) execute(bc *Code, v interface{}, vars ...interface{}) Iter { func (env *env) Next() (interface{}, bool) { var err error pc, callpc, index := env.pc, len(env.codes)-1, -1 - backtrack := env.backtrack > 0 - hasCtx := env.ctx != nil - defer func() { env.pc, env.backtrack = pc, pc }() + backtrack, hasCtx := env.backtrack, env.ctx != nil + defer func() { env.pc, env.backtrack = pc, true }() loop: for ; pc < len(env.codes); pc++ { env.debugState(pc, backtrack) @@ -78,31 +77,47 @@ loop: } else { env.pushfork(code.op, pc) } - case opforkopt: - fallthrough - case opforkalt: + case opforktrybegin: if backtrack { if err == nil { break loop } - if code.op == opforkopt { - if env.backtrack <= code.v.(int) { - env.pop() - if er, ok := err.(*exitCodeError); ok { - env.push(er.value) - if er.halt { - break loop - } - if er.value == nil { - backtrack, err = true, nil - break loop - } - } else { - env.push(err.Error()) - } - } else { + switch er := err.(type) { + case *tryEndError: + err = er.err + break loop + case *exitCodeError: + env.pop() + env.push(er.value) + if er.halt { + break loop + } + if er.value == nil { + err = nil break loop } + default: + env.pop() + env.push(err.Error()) + } + pc, backtrack, err = code.v.(int), false, nil + goto loop + } else { + env.pushfork(code.op, pc) + } + case opforktryend: + if backtrack { + if err != nil { + err = &tryEndError{err} + } + break loop + } else { + env.pushfork(code.op, pc) + } + case opforkalt: + if backtrack { + if err == nil { + break loop } pc, backtrack, err = code.v.(int), false, nil goto loop @@ -273,9 +288,6 @@ loop: } } if len(env.forks) > 0 { - if !backtrack { - env.backtrack = pc - } pc, backtrack = env.popfork().pc, true goto loop } diff --git a/vendor/github.com/itchyny/gojq/func.go b/vendor/github.com/itchyny/gojq/func.go index 09fe8f37..3f97e24a 100644 --- a/vendor/github.com/itchyny/gojq/func.go +++ b/vendor/github.com/itchyny/gojq/func.go @@ -10,11 +10,11 @@ import ( "net/url" "regexp" "sort" + "strconv" "strings" "time" - "github.com/lestrrat-go/strftime" - "github.com/pbnjay/strptime" + "github.com/itchyny/timefmt-go" ) //go:generate go run _tools/gen_builtin.go -i builtin.jq -o builtin.go @@ -51,9 +51,11 @@ func init() { "utf8bytelength": argFunc0(funcUtf8ByteLength), "keys": argFunc0(funcKeys), "has": argFunc1(funcHas), + "add": argFunc0(funcAdd), "tonumber": argFunc0(funcToNumber), "tostring": argFunc0(funcToString), "type": argFunc0(funcType), + "reverse": argFunc0(funcReverse), "contains": argFunc1(funcContains), "explode": argFunc0(funcExplode), "implode": argFunc0(funcImplode), @@ -85,6 +87,11 @@ func init() { "_less": argFunc2(funcOpLt), "_greatereq": argFunc2(funcOpGe), "_lesseq": argFunc2(funcOpLe), + "_min_by": argFunc1(funcMinBy), + "_max_by": argFunc1(funcMaxBy), + "_sort_by": argFunc1(funcSortBy), + "_group_by": argFunc1(funcGroupBy), + "_unique_by": argFunc1(funcUniqueBy), "sin": mathFunc("sin", math.Sin), "cos": mathFunc("cos", math.Cos), "tan": mathFunc("tan", math.Tan), @@ -155,6 +162,7 @@ func init() { "setpath": argFunc2(funcSetpath), "delpaths": argFunc1(funcDelpaths), "getpath": argFunc1(funcGetpath), + "bsearch": argFunc1(funcBsearch), "gmtime": argFunc0(funcGmtime), "localtime": argFunc0(funcLocaltime), "mktime": argFunc0(funcMktime), @@ -162,7 +170,7 @@ func init() { "strflocaltime": argFunc1(funcStrflocaltime), "strptime": argFunc1(funcStrptime), "now": argFunc0(funcNow), - "_match_impl": argFunc3(funcMatchImpl), + "_match": argFunc3(funcMatch), "error": {argcount0 | argcount1, funcError}, "halt": argFunc0(funcHalt), "halt_error": {argcount0 | argcount1, funcHaltError}, @@ -172,30 +180,34 @@ func init() { } func argFunc0(fn func(interface{}) interface{}) function { - return function{argcount0, func(v interface{}, _ []interface{}) interface{} { - return fn(v) - }, + return function{ + argcount0, func(v interface{}, _ []interface{}) interface{} { + return fn(v) + }, } } func argFunc1(fn func(interface{}, interface{}) interface{}) function { - return function{argcount1, func(v interface{}, args []interface{}) interface{} { - return fn(v, args[0]) - }, + return function{ + argcount1, func(v interface{}, args []interface{}) interface{} { + return fn(v, args[0]) + }, } } func argFunc2(fn func(interface{}, interface{}, interface{}) interface{}) function { - return function{argcount2, func(v interface{}, args []interface{}) interface{} { - return fn(v, args[0], args[1]) - }, + return function{ + argcount2, func(v interface{}, args []interface{}) interface{} { + return fn(v, args[0], args[1]) + }, } } func argFunc3(fn func(interface{}, interface{}, interface{}, interface{}) interface{}) function { - return function{argcount3, func(v interface{}, args []interface{}) interface{} { - return fn(v, args[0], args[1], args[2]) - }, + return function{ + argcount3, func(v interface{}, args []interface{}) interface{} { + return fn(v, args[0], args[1], args[2]) + }, } } @@ -320,16 +332,74 @@ func funcHas(v, x interface{}) interface{} { } } +func funcAdd(v interface{}) interface{} { + if vs, ok := v.(map[string]interface{}); ok { + xs := make([]string, len(vs)) + var i int + for k := range vs { + xs[i] = k + i++ + } + sort.Strings(xs) + us := make([]interface{}, len(vs)) + for i, x := range xs { + us[i] = vs[x] + } + v = us + } + vs, ok := v.([]interface{}) + if !ok { + return &funcTypeError{"add", v} + } + v = nil + for _, x := range vs { + switch y := x.(type) { + case map[string]interface{}: + switch w := v.(type) { + case nil: + m := make(map[string]interface{}) + for k, e := range y { + m[k] = e + } + v = m + continue + case map[string]interface{}: + for k, e := range y { + w[k] = e + } + continue + } + case []interface{}: + switch w := v.(type) { + case nil: + s := make([]interface{}, len(y)) + copy(s, y) + v = s + continue + case []interface{}: + v = append(w, y...) + continue + } + } + v = funcOpAdd(nil, v, x) + if err, ok := v.(error); ok { + return err + } + } + return v +} + +var numberPattern = regexp.MustCompile(`^[-+]?(?:(?:\d*\.)?\d+|\d+\.)(?:[eE][-+]?\d+)?$`) + func funcToNumber(v interface{}) interface{} { switch v := v.(type) { case int, float64, *big.Int: return v case string: - var x float64 - if err := json.Unmarshal([]byte(v), &x); err != nil { - return fmt.Errorf("%s: %q", err, v) + if !numberPattern.MatchString(v) { + return fmt.Errorf("invalid number: %q", v) } - return x + return normalizeNumbers(json.Number(v)) default: return &funcTypeError{"tonumber", v} } @@ -346,6 +416,18 @@ func funcType(v interface{}) interface{} { return typeof(v) } +func funcReverse(v interface{}) interface{} { + vs, ok := v.([]interface{}) + if !ok { + return &expectedArrayError{v} + } + ws := make([]interface{}, len(vs)) + for i, v := range vs { + ws[len(ws)-i-1] = v + } + return ws +} + func funcContains(v, x interface{}) interface{} { switch v := v.(type) { case nil: @@ -476,21 +558,26 @@ func implode(v []interface{}) interface{} { func funcToJSON(v interface{}) interface{} { s, err := encodeJSON(v) if err != nil { - s, err = encodeJSON(normalizeValues(v)) - if err != nil { - return err - } + return err } return s } func encodeJSON(v interface{}) (string, error) { + switch v := v.(type) { + case int: + return strconv.FormatInt(int64(v), 10), nil + case *big.Int: + return v.String(), nil + } buf := new(bytes.Buffer) enc := json.NewEncoder(buf) enc.SetEscapeHTML(false) - err := enc.Encode(v) - if err != nil { - return "", err + if err := enc.Encode(v); err != nil { + buf.Reset() + if err = enc.Encode(normalizeValues(v)); err != nil { + return "", err + } } s := buf.String() return s[:len(s)-1], nil // trim last newline character @@ -743,6 +830,7 @@ func funcSlice(_, v, end, start interface{}) (r interface{}) { r = implode([]interface{}{s}) case nil: r = "" + case error: default: panic(r) } @@ -820,8 +908,124 @@ func toIndex(a []interface{}, i int) int { } } -func funcBreak(x interface{}) interface{} { - return &breakError{x.(string)} +func funcBreak(v interface{}) interface{} { + if v, ok := v.(string); ok { + return &breakError{v} + } + return &funcTypeError{"_break", v} +} + +func funcMinBy(v, x interface{}) interface{} { + vs, ok := v.([]interface{}) + if !ok { + return &expectedArrayError{v} + } + xs, ok := x.([]interface{}) + if !ok { + return &expectedArrayError{x} + } + if len(vs) != len(xs) { + panic("length mismatch in min_by") + } + return funcMinMaxBy(vs, xs, true) +} + +func funcMaxBy(v, x interface{}) interface{} { + vs, ok := v.([]interface{}) + if !ok { + return &expectedArrayError{v} + } + xs, ok := x.([]interface{}) + if !ok { + return &expectedArrayError{x} + } + if len(vs) != len(xs) { + panic("length mismatch in max_by") + } + return funcMinMaxBy(vs, xs, false) +} + +func funcMinMaxBy(vs, xs []interface{}, isMin bool) interface{} { + if len(vs) == 0 { + return nil + } + i, j, x := 0, 0, xs[0] + for i++; i < len(xs); i++ { + if (compare(x, xs[i]) > 0) == isMin { + j, x = i, xs[i] + } + } + return vs[j] +} + +type sortItem struct { + value, key interface{} +} + +func funcSortBy(v, x interface{}) interface{} { + items, err := sortItems(v, x) + if err != nil { + return err + } + rs := make([]interface{}, len(items)) + for i, x := range items { + rs[i] = x.value + } + return rs +} + +func funcGroupBy(v, x interface{}) interface{} { + items, err := sortItems(v, x) + if err != nil { + return err + } + var rs []interface{} + var last interface{} + for i, r := range items { + if i == 0 || compare(last, r.key) != 0 { + rs, last = append(rs, []interface{}{r.value}), r.key + } else { + rs[len(rs)-1] = append(rs[len(rs)-1].([]interface{}), r.value) + } + } + return rs +} + +func funcUniqueBy(v, x interface{}) interface{} { + items, err := sortItems(v, x) + if err != nil { + return err + } + var rs []interface{} + var last interface{} + for i, r := range items { + if i == 0 || compare(last, r.key) != 0 { + rs, last = append(rs, r.value), r.key + } + } + return rs +} + +func sortItems(v, x interface{}) ([]*sortItem, error) { + vs, ok := v.([]interface{}) + if !ok { + return nil, &expectedArrayError{v} + } + xs, ok := x.([]interface{}) + if !ok { + return nil, &expectedArrayError{x} + } + if len(vs) != len(xs) { + panic("length mismatch") + } + items := make([]*sortItem, len(vs)) + for i, v := range vs { + items[i] = &sortItem{v, xs[i]} + } + sort.SliceStable(items, func(i, j int) bool { + return compare(items[i].key, items[j].key) < 0 + }) + return items, nil } func funcSignificand(v float64) float64 { @@ -928,9 +1132,18 @@ func funcIsnormal(v interface{}) interface{} { } func funcSetpath(v, p, w interface{}) interface{} { - return updatePaths("setpath", clone(v), p, func(interface{}) interface{} { - return w - }) + path, ok := p.([]interface{}) + if !ok { + return &funcTypeError{"setpath", p} + } + var err error + if v, err = updatePaths(v, path, w, false); err != nil { + if err, ok := err.(*funcTypeError); ok { + err.name = "setpath" + } + return err + } + return v } func funcDelpaths(v, p interface{}) interface{} { @@ -938,152 +1151,190 @@ func funcDelpaths(v, p interface{}) interface{} { if !ok { return &funcTypeError{"delpaths", p} } - for _, path := range paths { - v = updatePaths("delpaths", clone(v), path, func(interface{}) interface{} { - return struct{}{} - }) - if _, ok := v.(error); ok { - return v + // Fills the paths with an empty value and then delete them. We cannot delete + // in each loop because array indices should not change. For example, + // jq -n "[0, 1, 2, 3] | delpaths([[1], [2]])" #=> [0, 3]. + var empty struct{} + var err error + for _, p := range paths { + path, ok := p.([]interface{}) + if !ok { + return &funcTypeError{"delpaths", p} + } + if v, err = updatePaths(v, path, empty, true); err != nil { + return err } } return deleteEmpty(v) } -func updatePaths(name string, v, p interface{}, f func(interface{}) interface{}) interface{} { - keys, ok := p.([]interface{}) - if !ok { - return &funcTypeError{name, p} +func updatePaths(v interface{}, path []interface{}, w interface{}, delpaths bool) (interface{}, error) { + if len(path) == 0 { + return w, nil } - if len(keys) == 0 { - return f(v) - } - u := v - g := func(w interface{}) interface{} { v = w; return w } -loop: - for i, x := range keys { - switch x := x.(type) { - case string: - if u == nil { - if name == "delpaths" { - break loop - } - u = g(make(map[string]interface{})) + switch x := path[0].(type) { + case string: + if v == nil { + if delpaths { + return v, nil } - switch uu := u.(type) { - case map[string]interface{}: - if _, ok := uu[x]; !ok && name == "delpaths" { - break loop - } - if i < len(keys)-1 { - u = uu[x] - g = func(w interface{}) interface{} { uu[x] = w; return w } - } else { - uu[x] = f(uu[x]) - } - default: - return &expectedObjectError{u} + v = make(map[string]interface{}) + } + switch uu := v.(type) { + case map[string]interface{}: + if _, ok := uu[x]; !ok && delpaths { + return v, nil } - case int, float64, *big.Int: - if u == nil { - u = g([]interface{}{}) + u, err := updatePaths(uu[x], path[1:], w, delpaths) + if err != nil { + return nil, err + } + vs := make(map[string]interface{}, len(uu)) + for k, v := range uu { + vs[k] = v } + vs[x] = u + return vs, nil + default: + return nil, &expectedObjectError{v} + } + case int, float64, *big.Int: + if v == nil { + if delpaths { + return v, nil + } + v = []interface{}{} + } + switch uu := v.(type) { + case []interface{}: y, _ := toInt(x) - switch uu := u.(type) { - case []interface{}: - l := len(uu) - if y >= len(uu) && name == "setpath" { - l = y + 1 - } else if y < -len(uu) { - if name == "delpaths" { - break loop - } - return &funcTypeError{name, y} - } else if y < 0 { - y = len(uu) + y + l := len(uu) + var copied bool + if copied = y >= l; copied { + if delpaths { + return v, nil } + if y > 0x3ffffff { + return nil, &arrayIndexTooLargeError{y} + } + l = y + 1 ys := make([]interface{}, l) copy(ys, uu) uu = ys - g(uu) - if y >= len(uu) { - break loop - } - if i < len(keys)-1 { - u = uu[y] - g = func(w interface{}) interface{} { uu[y] = w; return w } - } else { - uu[y] = f(uu[y]) + } else if y < -l { + if delpaths { + return v, nil } - default: - return &expectedArrayError{u} + return nil, &funcTypeError{v: y} + } else if y < 0 { + y += l } - case map[string]interface{}: - if len(x) == 0 { - switch u.(type) { - case []interface{}: - return &arrayIndexNotNumberError{x} - default: - return &objectKeyNotStringError{x} - } + u, err := updatePaths(uu[y], path[1:], w, delpaths) + if err != nil { + return nil, err } - if u == nil { - u = g([]interface{}{}) + if copied { + uu[y] = u + return uu, nil } - switch uu := u.(type) { + vs := make([]interface{}, l) + copy(vs, uu) + vs[y] = u + return vs, nil + default: + return nil, &expectedArrayError{v} + } + case map[string]interface{}: + if len(x) == 0 { + switch v.(type) { case []interface{}: - var start, end int - if x, ok := toInt(x["start"]); ok { - x := toIndex(uu, x) - if x > len(uu) || x == -1 { - start = len(uu) - } else if x == -2 { - start = 0 - } else { - start = x - } - } - if x, ok := toInt(x["end"]); ok { - x := toIndex(uu, x) - if x < start { - end = start - } else { - end = x - } + return nil, &arrayIndexNotNumberError{x} + default: + return nil, &objectKeyNotStringError{x} + } + } + if v == nil { + v = []interface{}{} + } + switch uu := v.(type) { + case []interface{}: + var start, end int + if x, ok := toInt(x["start"]); ok { + x := toIndex(uu, x) + if x > len(uu) || x == -1 { + start = len(uu) + } else if x == -2 { + start = 0 } else { + start = x + } + } + if x, ok := toInt(x["end"]); ok { + x := toIndex(uu, x) + if x == -1 { end = len(uu) + } else if x < start { + end = start + } else { + end = x } - if i < len(keys)-1 { - u = uu[start] - g = func(w interface{}) interface{} { uu[start] = w; return w } - } else if name == "delpaths" { - for y := start; y < end; y++ { - uu[y] = f(nil) + } else { + end = len(uu) + } + if delpaths { + if start >= end { + return uu, nil + } + if len(path) > 1 { + u, err := updatePaths(uu[start:end], path[1:], w, delpaths) + if err != nil { + return nil, err } - } else { - switch v := f(nil).(type) { + switch us := u.(type) { case []interface{}: - vv := make([]interface{}, start+len(v)+len(uu)-end) - copy(vv, uu[:start]) - copy(vv[start:], v) - copy(vv[start+len(v):], uu[end:]) - g(vv) + vs := make([]interface{}, len(uu)) + copy(vs, uu) + copy(vs[start:end], us) + return vs, nil default: - return &expectedArrayError{v} + return nil, &expectedArrayError{u} } } - default: - return &expectedArrayError{u} + vs := make([]interface{}, len(uu)) + copy(vs, uu) + for y := start; y < end; y++ { + vs[y] = w + } + return vs, nil } - default: - switch u.(type) { + if len(path) > 1 { + u, err := updatePaths(uu[start:end], path[1:], w, delpaths) + if err != nil { + return nil, err + } + w = u + } + switch v := w.(type) { case []interface{}: - return &arrayIndexNotNumberError{x} + vs := make([]interface{}, start+len(v)+len(uu)-end) + copy(vs, uu[:start]) + copy(vs[start:], v) + copy(vs[start+len(v):], uu[end:]) + return vs, nil default: - return &objectKeyNotStringError{x} + return nil, &expectedArrayError{v} } + default: + return nil, &expectedArrayError{v} + } + default: + switch v.(type) { + case []interface{}: + return nil, &arrayIndexNotNumberError{x} + default: + return nil, &objectKeyNotStringError{x} } } - return v } func funcGetpath(v, p interface{}) interface{} { @@ -1108,6 +1359,20 @@ func funcGetpath(v, p interface{}) interface{} { return v } +func funcBsearch(v, t interface{}) interface{} { + vs, ok := v.([]interface{}) + if !ok { + return &funcTypeError{"bsearch", v} + } + i := sort.Search(len(vs), func(i int) bool { + return compare(vs[i], t) >= 0 + }) + if i < len(vs) && compare(vs[i], t) == 0 { + return i + } + return -i - 1 +} + func funcGmtime(v interface{}) interface{} { if v, ok := toFloat(v); ok { return epochToArray(v, time.UTC) @@ -1157,11 +1422,7 @@ func funcStrftime(v, x interface{}) interface{} { if err != nil { return err } - got, err := strftime.Format(format, t) - if err != nil { - return err - } - return got + return timefmt.Format(t, format) } return &funcTypeError{"strftime", x} } @@ -1178,11 +1439,7 @@ func funcStrflocaltime(v, x interface{}) interface{} { if err != nil { return err } - got, err := strftime.Format(format, t) - if err != nil { - return err - } - return got + return timefmt.Format(t, format) } return &funcTypeError{"strflocaltime", x} } @@ -1192,7 +1449,7 @@ func funcStrflocaltime(v, x interface{}) interface{} { func funcStrptime(v, x interface{}) interface{} { if v, ok := v.(string); ok { if format, ok := x.(string); ok { - t, err := strptime.Parse(v, format) + t, err := timefmt.Parse(v, format) if err != nil { return err } @@ -1252,7 +1509,7 @@ func funcNow(interface{}) interface{} { return float64(t.Unix()) + float64(t.Nanosecond())/1e9 } -func funcMatchImpl(v, re, fs, testing interface{}) interface{} { +func funcMatch(v, re, fs, testing interface{}) interface{} { var flags string if fs != nil { v, ok := fs.(string) @@ -1350,8 +1607,9 @@ func funcHalt(interface{}) interface{} { } func funcHaltError(v interface{}, args []interface{}) interface{} { - code, ok := 5, false + code := 5 if len(args) > 0 { + var ok bool if code, ok = toInt(args[0]); !ok { return &funcTypeError{"halt_error", args[0]} } @@ -1386,7 +1644,10 @@ func funcBuiltins(interface{}) interface{} { } func internalfuncTypeError(v, x interface{}) interface{} { - return &funcTypeError{x.(string), v} + if x, ok := x.(string); ok { + return &funcTypeError{x, v} + } + return &funcTypeError{"_type_error", v} } func toInt(x interface{}) (int, bool) { @@ -1397,7 +1658,9 @@ func toInt(x interface{}) (int, bool) { return int(x), true case *big.Int: if x.IsInt64() { - return int(x.Int64()), true + if i := x.Int64(); minInt <= i && i <= maxInt { + return int(i), true + } } if x.Sign() > 0 { return maxInt, true diff --git a/vendor/github.com/itchyny/gojq/go.mod b/vendor/github.com/itchyny/gojq/go.mod index 7890c1cd..68819556 100644 --- a/vendor/github.com/itchyny/gojq/go.mod +++ b/vendor/github.com/itchyny/gojq/go.mod @@ -3,21 +3,15 @@ module github.com/itchyny/gojq go 1.14 require ( - github.com/alecthomas/participle v0.4.2-0.20191220090139-9fbceec1d131 - github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 // indirect github.com/fatih/color v1.9.0 github.com/hokaccha/go-prettyjson v0.0.0-20190818114111-108c894c2c0e - github.com/itchyny/astgen-go v0.0.0-20200116103543-aaa595cf980e + github.com/itchyny/astgen-go v0.0.0-20200815150004-12a293722290 github.com/itchyny/go-flags v1.5.0 - github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 // indirect - github.com/lestrrat-go/strftime v1.0.1 - github.com/mattn/go-colorable v0.1.6 // indirect + github.com/itchyny/timefmt-go v0.1.1 + github.com/mattn/go-colorable v0.1.7 // indirect github.com/mattn/go-isatty v0.0.12 github.com/mattn/go-runewidth v0.0.9 - github.com/pbnjay/strptime v0.0.0-20140226051138-5c05b0d668c9 - github.com/pkg/errors v0.9.1 // indirect - github.com/stretchr/testify v1.5.0 - github.com/tebeka/strftime v0.1.3 // indirect - golang.org/x/sys v0.0.0-20200331124033-c3d80250170d // indirect - gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c + github.com/stretchr/testify v1.6.1 + golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f // indirect + gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 ) diff --git a/vendor/github.com/itchyny/gojq/go.sum b/vendor/github.com/itchyny/gojq/go.sum index 924a477b..ec1f068e 100644 --- a/vendor/github.com/itchyny/gojq/go.sum +++ b/vendor/github.com/itchyny/gojq/go.sum @@ -1,68 +1,38 @@ -github.com/alecthomas/go-thrift v0.0.0-20170109061633-7914173639b2/go.mod h1:CxCgO+NdpMdi9SsTlGbc0W+/UNxO3I0AabOEJZ3w61w= -github.com/alecthomas/kong v0.2.1/go.mod h1:+inYUSluD+p4L8KdviBSgzcqEjUQOfC5fQDRFuc36lI= -github.com/alecthomas/participle v0.4.2-0.20191220090139-9fbceec1d131 h1:iPgE4wTIM/fgSreWdpxnKXxaGOgGwfPqc2aVPq2BFSU= -github.com/alecthomas/participle v0.4.2-0.20191220090139-9fbceec1d131/go.mod h1:T8u4bQOSMwrkTWOSyt8/jSFPEnRtd0FKFMjVfYBlqPs= -github.com/alecthomas/repr v0.0.0-20181024024818-d37bc2a10ba1/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 h1:Ghm4eQYC0nEPnSJdVkTrXpu9KtoVCSo1hg7mtI7G9KU= -github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239/go.mod h1:Gdwt2ce0yfBxPvZrHkprdPPTTS3N5rwmLE8T22KBXlw= github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/hokaccha/go-prettyjson v0.0.0-20190818114111-108c894c2c0e h1:0aewS5NTyxftZHSnFaJmWE5oCCrj4DyEXkAiMa1iZJM= github.com/hokaccha/go-prettyjson v0.0.0-20190818114111-108c894c2c0e/go.mod h1:pFlLw2CfqZiIBOx6BuCeRLCrfxBJipTY0nIOF/VbGcI= -github.com/itchyny/astgen-go v0.0.0-20200116103543-aaa595cf980e h1:PupVBrJNomt2fTXto19vW8Jh1ftn1oKxgtjSzSuLBZI= -github.com/itchyny/astgen-go v0.0.0-20200116103543-aaa595cf980e/go.mod h1:9Gyr9nZoENI+woes+xm+BFhmvYmAp6bPtXD866pQH9g= +github.com/itchyny/astgen-go v0.0.0-20200815150004-12a293722290 h1:9ZAJ5+eh9dfcPsJ1CXoiE16JzsBmJm1e124eUkXAyc0= +github.com/itchyny/astgen-go v0.0.0-20200815150004-12a293722290/go.mod h1:296z3W7Xsrp2mlIY88ruDKscuvrkL6zXCNRtaYVshzw= github.com/itchyny/go-flags v1.5.0 h1:Z5q2ist2sfDjDlExVPBrMqlsEDxDR2h4zuOElB0OEYI= github.com/itchyny/go-flags v1.5.0/go.mod h1:lenkYuCobuxLBAd/HGFE4LRoW8D3B6iXRQfWYJ+MNbA= -github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 h1:IPJ3dvxmJ4uczJe5YQdrYB16oTJlGSC/OyZDqUk9xX4= -github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869/go.mod h1:cJ6Cj7dQo+O6GJNiMx+Pa94qKj+TG8ONdKHgMNIyyag= -github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8= -github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= -github.com/lestrrat-go/strftime v1.0.1 h1:o7qz5pmLzPDLyGW4lG6JvTKPUfTFXwe+vOamIYWtnVU= -github.com/lestrrat-go/strftime v1.0.1/go.mod h1:E1nN3pCbtMSu1yjSVeyuRFVm/U0xoR76fd03sz+Qz4g= -github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA= +github.com/itchyny/timefmt-go v0.1.1 h1:rLpnm9xxb39PEEVzO0n4IRp0q6/RmBc7Dy/rE4HrA0U= +github.com/itchyny/timefmt-go v0.1.1/go.mod h1:0osSSCQSASBJMsIZnhAaF1C2fCBTJZXrnj37mG8/c+A= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE= -github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.7 h1:bQGKb3vps/j0E9GfJQ03JyhRuxsvdAanXlT9BTw3mdw= +github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= -github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/pbnjay/strptime v0.0.0-20140226051138-5c05b0d668c9 h1:4lfz0keanz7/gAlvJ7lAe9zmE08HXxifBZJC0AdeGKo= -github.com/pbnjay/strptime v0.0.0-20140226051138-5c05b0d668c9/go.mod h1:6Hr+C/olSdkdL3z68MlyXWzwhvwmwN7KuUFXGb3PoOk= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.0 h1:DMOzIV76tmoDNE9pX6RSN0aDtCYeCg5VueieJaAo1uw= -github.com/stretchr/testify v1.5.0/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/tebeka/strftime v0.1.3 h1:5HQXOqWKYRFfNyBMNVc9z5+QzuBtIXy03psIhtdJYto= -github.com/tebeka/strftime v0.1.3/go.mod h1:7wJm3dZlpr4l/oVK0t1HYIc4rMzQ2XJlOMIUJUJH6XQ= +github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4 h1:sfkvUWPNGwSV+8/fNqctR5lS2AqCSqYwXdrjCxp/dXo= golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d h1:nc5K6ox/4lTFbMVSL9WRR81ixkcwXThoiF6yf+R9scA= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/vendor/github.com/itchyny/gojq/lexer.go b/vendor/github.com/itchyny/gojq/lexer.go new file mode 100644 index 00000000..e7eab898 --- /dev/null +++ b/vendor/github.com/itchyny/gojq/lexer.go @@ -0,0 +1,496 @@ +package gojq + +import ( + "fmt" + "strconv" + "strings" + "unicode/utf8" +) + +type lexer struct { + source []byte + offset int + result *Query + token string + tokenType int + inString bool + err error +} + +func newLexer(src string) *lexer { + return &lexer{source: []byte(src)} +} + +const eof = -1 + +var keywords = map[string]int{ + "or": tokOrOp, + "and": tokAndOp, + "module": tokModule, + "import": tokImport, + "include": tokInclude, + "def": tokDef, + "as": tokAs, + "label": tokLabel, + "break": tokBreak, + "null": tokNull, + "true": tokTrue, + "false": tokFalse, + "if": tokIf, + "then": tokThen, + "elif": tokElif, + "else": tokElse, + "end": tokEnd, + "try": tokTry, + "catch": tokCatch, + "reduce": tokReduce, + "foreach": tokForeach, +} + +func (l *lexer) Lex(lval *yySymType) (tokenType int) { + defer func() { l.tokenType = tokenType }() + if len(l.source) == l.offset { + l.token = "" + return eof + } + if l.inString { + tok, str := l.scanString(l.offset) + lval.token = str + return tok + } + ch, iseof := l.next() + if iseof { + l.token = "" + return eof + } + switch { + case isIdent(ch, false): + i := l.offset - 1 + j, isModule := l.scanIdentOrModule() + l.token = string(l.source[i:j]) + lval.token = l.token + if isModule { + return tokModuleIdent + } + if tok, ok := keywords[l.token]; ok { + return tok + } + return tokIdent + case isNumber(ch): + i := l.offset - 1 + j := l.scanNumber(numberStateLead) + if j < 0 { + l.token = string(l.source[i:-j]) + return tokInvalid + } + l.token = string(l.source[i:j]) + lval.token = l.token + return tokNumber + } + switch ch { + case '.': + ch := l.peek() + switch { + case ch == '.': + l.offset++ + l.token = ".." + return tokRecurse + case isIdent(ch, false): + l.token = string(l.source[l.offset-1 : l.scanIdent()]) + lval.token = l.token[1:] + return tokIndex + case isNumber(ch): + i := l.offset - 1 + j := l.scanNumber(numberStateFloat) + if j < 0 { + l.token = string(l.source[i:-j]) + return tokInvalid + } + l.token = string(l.source[i:j]) + lval.token = l.token + return tokNumber + default: + return '.' + } + case '$': + if isIdent(l.peek(), false) { + i := l.offset - 1 + j, isModule := l.scanIdentOrModule() + l.token = string(l.source[i:j]) + lval.token = l.token + if isModule { + return tokModuleVariable + } + return tokVariable + } + case '|': + if l.peek() == '=' { + l.offset++ + l.token = "|=" + lval.operator = OpModify + return tokUpdateOp + } + case '?': + if l.peek() == '/' { + l.offset++ + if l.peek() == '/' { + l.offset++ + l.token = "?//" + return tokDestAltOp + } + } + case '+': + if l.peek() == '=' { + l.offset++ + l.token = "+=" + lval.operator = OpUpdateAdd + return tokUpdateOp + } + case '-': + if l.peek() == '=' { + l.offset++ + l.token = "-=" + lval.operator = OpUpdateSub + return tokUpdateOp + } + case '*': + if l.peek() == '=' { + l.offset++ + l.token = "*=" + lval.operator = OpUpdateMul + return tokUpdateOp + } + case '/': + switch l.peek() { + case '=': + l.offset++ + l.token = "/=" + lval.operator = OpUpdateDiv + return tokUpdateOp + case '/': + l.offset++ + if l.peek() == '=' { + l.offset++ + l.token = "//=" + lval.operator = OpUpdateAlt + return tokUpdateOp + } + l.token = "//" + lval.operator = OpAlt + return tokAltOp + } + case '%': + if l.peek() == '=' { + l.offset++ + l.token = "%=" + lval.operator = OpUpdateMod + return tokUpdateOp + } + case '=': + if l.peek() == '=' { + l.offset++ + l.token = "==" + lval.operator = OpEq + return tokCompareOp + } + l.token = "=" + lval.operator = OpAssign + return tokUpdateOp + case '!': + if l.peek() == '=' { + l.offset++ + l.token = "!=" + lval.operator = OpNe + return tokCompareOp + } + case '>': + if l.peek() == '=' { + l.offset++ + l.token = ">=" + lval.operator = OpGe + return tokCompareOp + } + l.token = ">" + lval.operator = OpGt + return tokCompareOp + case '<': + if l.peek() == '=' { + l.offset++ + l.token = "<=" + lval.operator = OpLe + return tokCompareOp + } + l.token = "<" + lval.operator = OpLt + return tokCompareOp + case '@': + if isIdent(l.peek(), false) { + l.token = string(l.source[l.offset-1 : l.scanIdent()]) + lval.token = l.token + return tokFormat + } + case '"': + tok, str := l.scanString(l.offset - 1) + lval.token = str + return tok + default: + if ch >= utf8.RuneSelf { + r, _ := utf8.DecodeRune(l.source[l.offset-1:]) + l.token = string(r) + l.offset += len(l.token) + } + } + return int(ch) +} + +func (l *lexer) next() (byte, bool) { + for { + ch := l.source[l.offset] + l.offset++ + if ch == '#' { + if len(l.source) == l.offset { + return 0, true + } + for !isNewLine(l.source[l.offset]) { + l.offset++ + if len(l.source) == l.offset { + return 0, true + } + } + } else if !isWhite(ch) { + return ch, false + } else if len(l.source) == l.offset { + return 0, true + } + } +} + +func (l *lexer) peek() byte { + if len(l.source) == l.offset { + return 0 + } + return l.source[l.offset] +} + +func (l *lexer) scanIdent() int { + for isIdent(l.peek(), true) { + l.offset++ + } + return l.offset +} + +func (l *lexer) scanIdentOrModule() (int, bool) { + index := l.scanIdent() + var isModule bool + if l.peek() == ':' { + l.offset++ + if l.peek() == ':' { + l.offset++ + if isIdent(l.peek(), false) { + l.offset++ + index = l.scanIdent() + isModule = true + } else { + l.offset -= 2 + } + } else { + l.offset-- + } + } + return index, isModule +} + +const ( + numberStateLead = iota + numberStateFloat + numberStateExpLead + numberStateExp +) + +func (l *lexer) scanNumber(state int) int { + for { + switch state { + case numberStateLead, numberStateFloat: + if ch := l.peek(); isNumber(ch) { + l.offset++ + } else { + switch ch { + case '.': + if state != numberStateLead { + return l.offset + } + l.offset++ + state = numberStateFloat + case 'e', 'E': + l.offset++ + switch l.peek() { + case '-', '+': + l.offset++ + } + state = numberStateExpLead + default: + if isIdent(ch, false) { + l.offset++ + return -l.offset + } + return l.offset + } + } + case numberStateExpLead, numberStateExp: + if ch := l.peek(); !isNumber(ch) { + if isIdent(ch, false) { + l.offset++ + return -l.offset + } + if state == numberStateExpLead { + return -l.offset + } + return l.offset + } + l.offset++ + state = numberStateExp + default: + panic(state) + } + } +} + +func (l *lexer) scanString(start int) (int, string) { + var quote bool + for i, m := l.offset, len(l.source); i < m; i++ { + ch := l.source[i] + switch ch { + case '\\': + quote = !quote + case '"': + if !quote { + if !l.inString { + l.offset = i + 1 + l.token = string(l.source[start:l.offset]) + str, err := strconv.Unquote(l.token) + if err != nil { + return tokInvalid, "" + } + return tokString, str + } + if i > l.offset { + l.offset = i + l.token = string(l.source[start:l.offset]) + str, err := strconv.Unquote("\"" + l.token + "\"") + if err != nil { + return tokInvalid, "" + } + return tokString, str + } + l.inString = false + l.offset = i + 1 + return tokStringEnd, "" + } + quote = false + case '(': + if quote { + if l.inString { + if i > l.offset+1 { + l.offset = i - 1 + l.token = string(l.source[start:l.offset]) + str, err := strconv.Unquote("\"" + l.token + "\"") + if err != nil { + return tokInvalid, "" + } + return tokString, str + } + l.offset = i + 1 + l.inString = false + return tokStringQuery, "" + } + l.inString = true + return tokStringStart, "" + } + default: + if quote { + if !('a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || + '0' <= ch && ch <= '9' || ch == '\'' || ch == '"') { + l.offset = i + 1 + l.token = string(l.source[l.offset-2 : l.offset]) + return tokInvalid, "" + } + quote = false + } + } + } + l.offset = len(l.source) + l.token = string(l.source[start:l.offset]) + return tokInvalid, "" +} + +type parseError struct { + offset int + token string + tokenType int +} + +func (err *parseError) Error() string { + var message string + prefix := "unexpected" + switch { + case err.tokenType == eof: + message = "" + case err.tokenType == tokInvalid: + prefix = "invalid" + fallthrough + case err.tokenType >= utf8.RuneSelf: + if strings.HasPrefix(err.token, "\"") { + message = err.token + } else { + message = "\"" + err.token + "\"" + } + default: + message = strconv.Quote(string(rune(err.tokenType))) + } + return fmt.Sprintf("%s token %s", prefix, message) +} + +func (err *parseError) Token() (string, int) { + return err.token, err.offset +} + +func (l *lexer) Error(e string) { + offset, token := l.offset, l.token + switch { + case l.tokenType == eof: + offset++ + case l.tokenType >= utf8.RuneSelf: + offset -= len(token) - 1 + default: + token = fmt.Sprintf("%c", l.tokenType) + } + l.err = &parseError{offset, token, l.tokenType} +} + +func isWhite(ch byte) bool { + switch ch { + case '\t', '\n', '\r', ' ': + return true + default: + return false + } +} + +func isIdent(ch byte, tail bool) bool { + return 'a' <= ch && ch <= 'z' || + 'A' <= ch && ch <= 'Z' || ch == '_' || + tail && isNumber(ch) +} + +func isNumber(ch byte) bool { + return '0' <= ch && ch <= '9' +} + +func isNewLine(ch byte) bool { + switch ch { + case '\n', '\r': + return true + default: + return false + } +} diff --git a/vendor/github.com/itchyny/gojq/module_loader.go b/vendor/github.com/itchyny/gojq/module_loader.go new file mode 100644 index 00000000..9550bc9d --- /dev/null +++ b/vendor/github.com/itchyny/gojq/module_loader.go @@ -0,0 +1,154 @@ +package gojq + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "io/ioutil" + "os" + "path/filepath" +) + +type moduleLoader struct { + paths []string +} + +// NewModuleLoader creates a new ModuleLoader reading local modules in the paths. +func NewModuleLoader(paths []string) ModuleLoader { + return &moduleLoader{paths} +} + +func (l *moduleLoader) LoadInitModules() ([]*Query, error) { + var qs []*Query + for _, path := range l.paths { + if filepath.Base(path) != ".jq" { + continue + } + fi, err := os.Stat(path) + if err != nil { + if os.IsNotExist(err) { + continue + } + return nil, err + } + if fi.IsDir() { + continue + } + cnt, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + q, err := parseModule(path, string(cnt)) + if err != nil { + return nil, &queryParseError{"query in module", path, string(cnt), err} + } + qs = append(qs, q) + } + return qs, nil +} + +func (l *moduleLoader) LoadModule(string) (*Query, error) { + panic("LocalModuleLoader#LoadModule: unreachable") +} + +func (l *moduleLoader) LoadModuleWithMeta(name string, meta map[string]interface{}) (*Query, error) { + path, err := l.lookupModule(name, ".jq", meta) + if err != nil { + return nil, err + } + cnt, err := ioutil.ReadFile(path) + if err != nil { + return nil, err + } + q, err := parseModule(path, string(cnt)) + if err != nil { + return nil, &queryParseError{"query in module", path, string(cnt), err} + } + return q, nil +} + +func (l *moduleLoader) LoadJSONWithMeta(name string, meta map[string]interface{}) (interface{}, error) { + path, err := l.lookupModule(name, ".json", meta) + if err != nil { + return nil, err + } + f, err := os.Open(path) + if err != nil { + return nil, err + } + defer f.Close() + var vals []interface{} + var buf bytes.Buffer + dec := json.NewDecoder(io.TeeReader(f, &buf)) + for { + var val interface{} + if err := dec.Decode(&val); err != nil { + if err == io.EOF { + break + } + return nil, &jsonParseError{path, buf.String(), err} + } + vals = append(vals, val) + } + return vals, nil +} + +func (l *moduleLoader) lookupModule(name, extension string, meta map[string]interface{}) (string, error) { + paths := l.paths + if path := searchPath(meta); path != "" { + paths = append([]string{path}, paths...) + } + for _, base := range paths { + path := filepath.Clean(filepath.Join(base, name+extension)) + if _, err := os.Stat(path); err == nil { + return path, err + } + path = filepath.Clean(filepath.Join(base, name, filepath.Base(name)+extension)) + if _, err := os.Stat(path); err == nil { + return path, err + } + } + return "", fmt.Errorf("module not found: %q", name) +} + +// This is a dirty hack to implement the "search" field. +func parseModule(path, cnt string) (*Query, error) { + q, err := Parse(cnt) + if err != nil { + return nil, err + } + for _, i := range q.Imports { + if i.Meta == nil { + continue + } + i.Meta.KeyVals = append( + i.Meta.KeyVals, + &ConstObjectKeyVal{ + Key: "$$path", + Val: &ConstTerm{Str: path}, + }, + ) + } + return q, nil +} + +func searchPath(meta map[string]interface{}) string { + x, ok := meta["$$path"] + if !ok { + return "" + } + path, ok := x.(string) + if !ok { + return "" + } + x, ok = meta["search"] + if !ok { + return "" + } + s, ok := x.(string) + if !ok { + return "" + } + return filepath.Join(filepath.Dir(path), s) +} diff --git a/vendor/github.com/itchyny/gojq/normalize.go b/vendor/github.com/itchyny/gojq/normalize.go index da143ef2..d1bf86f6 100644 --- a/vendor/github.com/itchyny/gojq/normalize.go +++ b/vendor/github.com/itchyny/gojq/normalize.go @@ -4,14 +4,13 @@ import ( "encoding/json" "math" "math/big" - "reflect" "strings" ) func normalizeNumbers(v interface{}) interface{} { switch v := v.(type) { case json.Number: - if i, err := v.Int64(); err == nil { + if i, err := v.Int64(); err == nil && minInt <= i && i <= maxInt { return int(i) } if strings.ContainsAny(string(v), ".eE") { @@ -28,21 +27,53 @@ func normalizeNumbers(v interface{}) interface{} { return math.MaxFloat64 case *big.Int: if v.IsInt64() { - return int(v.Int64()) + if i := v.Int64(); minInt <= i && i <= maxInt { + return int(i) + } } return v + case int64: + if v > int64(maxInt) { + return new(big.Int).SetUint64(uint64(v)) + } + return int(v) + case int32: + return int(v) + case int16: + return int(v) + case int8: + return int(v) + case uint: + if v > uint(maxInt) { + return new(big.Int).SetUint64(uint64(v)) + } + return int(v) + case uint64: + if v > uint64(maxInt) { + return new(big.Int).SetUint64(v) + } + return int(v) + case uint32: + if v > uint32(maxHalfInt) { + return new(big.Int).SetUint64(uint64(v)) + } + return int(v) + case uint16: + return int(v) + case uint8: + return int(v) + case float32: + return float64(v) case map[string]interface{}: - u := make(map[string]interface{}, len(v)) - for k, v := range v { - u[k] = normalizeNumbers(v) + for k, x := range v { + v[k] = normalizeNumbers(x) } - return u + return v case []interface{}: - u := make([]interface{}, len(v)) - for i, v := range v { - u[i] = normalizeNumbers(v) + for i, x := range v { + v[i] = normalizeNumbers(x) } - return u + return v default: return v } @@ -75,33 +106,34 @@ func normalizeValues(v interface{}) interface{} { } } +// It's ok to delete destructively because this function is used right after +// updatePaths, where it shallow-copies maps or slices on updates. func deleteEmpty(v interface{}) interface{} { switch v := v.(type) { case struct{}: return nil case map[string]interface{}: - u := make(map[string]interface{}, len(v)) - for k, v := range v { - if v == struct{}{} { - continue + for k, w := range v { + if w == struct{}{} { + delete(v, k) + } else { + v[k] = deleteEmpty(w) } - u[k] = deleteEmpty(v) } - return u + return v case []interface{}: - u := make([]interface{}, 0, len(v)) - for _, v := range v { - if v == struct{}{} { - continue + var j int + for _, w := range v { + if w != struct{}{} { + v[j] = deleteEmpty(w) + j++ } - u = append(u, deleteEmpty(v)) } - return u + for i := j; i < len(v); i++ { + v[i] = nil + } + return v[:j] default: return v } } - -func deepEqual(x, y interface{}) bool { - return reflect.DeepEqual(normalizeNumbers(x), normalizeNumbers(y)) -} diff --git a/vendor/github.com/itchyny/gojq/operator.go b/vendor/github.com/itchyny/gojq/operator.go index 08d7be81..7d94365a 100644 --- a/vendor/github.com/itchyny/gojq/operator.go +++ b/vendor/github.com/itchyny/gojq/operator.go @@ -3,6 +3,7 @@ package gojq import ( "math" "math/big" + "reflect" "strings" ) @@ -11,7 +12,9 @@ type Operator int // Operators ... const ( - OpAdd Operator = iota + OpPipe Operator = iota + 1 + OpComma + OpAdd OpSub OpMul OpDiv @@ -35,44 +38,13 @@ const ( OpUpdateAlt ) -var operatorMap = map[string]Operator{ - "+": OpAdd, - "-": OpSub, - "*": OpMul, - "/": OpDiv, - "%": OpMod, - "==": OpEq, - "!=": OpNe, - ">": OpGt, - "<": OpLt, - ">=": OpGe, - "<=": OpLe, - "and": OpAnd, - "or": OpOr, - "//": OpAlt, - "=": OpAssign, - "|=": OpModify, - "+=": OpUpdateAdd, - "-=": OpUpdateSub, - "*=": OpUpdateMul, - "/=": OpUpdateDiv, - "%=": OpUpdateMod, - "//=": OpUpdateAlt, -} - -// Capture implements participle.Capture. -func (op *Operator) Capture(s []string) error { - var ok bool - *op, ok = operatorMap[s[0]] - if !ok { - panic("operator: " + s[0]) - } - return nil -} - // String implements Stringer. func (op Operator) String() string { switch op { + case OpPipe: + return "|" + case OpComma: + return "," case OpAdd: return "+" case OpSub: @@ -125,6 +97,10 @@ func (op Operator) String() string { // GoString implements GoStringer. func (op Operator) GoString() string { switch op { + case OpPipe: + return "OpPipe" + case OpComma: + return "OpComma" case OpAdd: return "OpAdd" case OpSub: @@ -176,6 +152,10 @@ func (op Operator) GoString() string { func (op Operator) getFunc() string { switch op { + case OpPipe: + panic("unreachable") + case OpComma: + panic("unreachable") case OpAdd: return "_add" case OpSub: @@ -369,7 +349,7 @@ func funcOpSub(_, l, r interface{}) interface{} { for _, v := range l { var found bool for _, w := range r { - if deepEqual(v, w) { + if reflect.DeepEqual(normalizeNumbers(v), normalizeNumbers(w)) { found = true break } @@ -395,7 +375,7 @@ func funcOpMul(_, l, r interface{}) interface{} { deepMergeObjects, func(l, r interface{}) interface{} { multiplyString := func(s string, cnt float64) interface{} { - if cnt <= 0.0 { + if cnt <= 0.0 || int(cnt) < 0 || int(cnt) > maxHalfInt/(16*(len(s)+1)) { return nil } if cnt < 1.0 { @@ -510,7 +490,7 @@ func funcOpMod(_, l, r interface{}) interface{} { return l % r }, func(l, r float64) interface{} { - if r == 0.0 { + if int(r) == 0 { return &zeroModuloError{l, r} } return int(l) % int(r) diff --git a/vendor/github.com/itchyny/gojq/option.go b/vendor/github.com/itchyny/gojq/option.go index 205aca57..d4ac541b 100644 --- a/vendor/github.com/itchyny/gojq/option.go +++ b/vendor/github.com/itchyny/gojq/option.go @@ -4,6 +4,7 @@ package gojq type CompilerOption func(*compiler) // WithModuleLoader is a compiler option for module loader. +// If you want to load modules from the filesystem, use NewModuleLoader. func WithModuleLoader(moduleLoader ModuleLoader) CompilerOption { return func(c *compiler) { c.moduleLoader = moduleLoader diff --git a/vendor/github.com/itchyny/gojq/parser.go b/vendor/github.com/itchyny/gojq/parser.go index fe507e4f..c98c5abb 100644 --- a/vendor/github.com/itchyny/gojq/parser.go +++ b/vendor/github.com/itchyny/gojq/parser.go @@ -1,56 +1,1691 @@ -package gojq +// Code generated by goyacc -o parser.go parser.go.y. DO NOT EDIT. -import ( - "strings" +//line parser.go.y:2 +package gojq - "github.com/alecthomas/participle" - "github.com/alecthomas/participle/lexer" -) +import __yyfmt__ "fmt" -//go:generate go run _tools/gen_string.go -o string.go -var parserOptions = []participle.Option{ - participle.Lexer(lexer.Must(lexer.Regexp(`(\s+|#[^\n]*)` + - `|(?P(import|include|null|true|false|if|then|elif|else|end|or|and|as|try|catch|reduce|foreach|label|break)\b)` + - `|(?P\$?[a-zA-Z_][a-zA-Z0-9_]*::[a-zA-Z_][a-zA-Z0-9_]*)` + - `|(?P[a-zA-Z_][a-zA-Z0-9_]*)` + - `|(?P\$[a-zA-Z_][a-zA-Z0-9_]*)` + - `|(?P\.[a-zA-Z_][a-zA-Z0-9_]*)` + - `|(?P(//=))` + - `|(?P(\.\.|\??//))` + - `|(?P([=!]=|[<>]=?))` + - `|(?P(=|[-|+*/%]=))` + - `|(?P((\d*\.)?\d+([eE]([-+]?\d+))?\b))` + - `|(?P` + stringPatternStr + `)` + - `|(?P@[a-zA-Z0-9_]+)` + - "|(?P[!-/:-@\\[-\\]^-`{-~])", - ))), -} - -var parser = participle.MustBuild(&Query{}, parserOptions...) +//line parser.go.y:2 // Parse parses a query. func Parse(src string) (*Query, error) { - var query Query - if err := parser.ParseString(src, &query); err != nil { - if strings.TrimSpace(src) != "" { - return nil, err + l := newLexer(src) + if yyParse(l) > 0 { + return nil, l.err + } + return l.result, nil +} + +//line parser.go.y:14 +type yySymType struct { + yys int + value interface{} + token string + operator Operator +} + +const tokAltOp = 57346 +const tokUpdateOp = 57347 +const tokDestAltOp = 57348 +const tokOrOp = 57349 +const tokAndOp = 57350 +const tokCompareOp = 57351 +const tokModule = 57352 +const tokImport = 57353 +const tokInclude = 57354 +const tokDef = 57355 +const tokAs = 57356 +const tokLabel = 57357 +const tokBreak = 57358 +const tokNull = 57359 +const tokTrue = 57360 +const tokFalse = 57361 +const tokIdent = 57362 +const tokVariable = 57363 +const tokModuleIdent = 57364 +const tokModuleVariable = 57365 +const tokIndex = 57366 +const tokNumber = 57367 +const tokFormat = 57368 +const tokInvalid = 57369 +const tokString = 57370 +const tokStringStart = 57371 +const tokStringQuery = 57372 +const tokStringEnd = 57373 +const tokIf = 57374 +const tokThen = 57375 +const tokElif = 57376 +const tokElse = 57377 +const tokEnd = 57378 +const tokTry = 57379 +const tokCatch = 57380 +const tokReduce = 57381 +const tokForeach = 57382 +const tokRecurse = 57383 +const tokFuncDefPost = 57384 +const tokTermPost = 57385 +const tokEmptyCatch = 57386 + +var yyToknames = [...]string{ + "$end", + "error", + "$unk", + "tokAltOp", + "tokUpdateOp", + "tokDestAltOp", + "tokOrOp", + "tokAndOp", + "tokCompareOp", + "tokModule", + "tokImport", + "tokInclude", + "tokDef", + "tokAs", + "tokLabel", + "tokBreak", + "tokNull", + "tokTrue", + "tokFalse", + "tokIdent", + "tokVariable", + "tokModuleIdent", + "tokModuleVariable", + "tokIndex", + "tokNumber", + "tokFormat", + "tokInvalid", + "tokString", + "tokStringStart", + "tokStringQuery", + "tokStringEnd", + "tokIf", + "tokThen", + "tokElif", + "tokElse", + "tokEnd", + "tokTry", + "tokCatch", + "tokReduce", + "tokForeach", + "tokRecurse", + "tokFuncDefPost", + "tokTermPost", + "tokEmptyCatch", + "'|'", + "','", + "'+'", + "'-'", + "'*'", + "'/'", + "'%'", + "'.'", + "'?'", + "'['", + "';'", + "':'", + "'('", + "')'", + "']'", + "'{'", + "'}'", +} + +var yyStatenames = [...]string{} + +const yyEofCode = 1 +const yyErrCode = 2 +const yyInitialStackSize = 16 + +//line parser.go.y:665 + +//line yacctab:1 +var yyExca = [...]int{ + -1, 1, + 1, -1, + -2, 0, + -1, 132, + 5, 0, + -2, 32, + -1, 135, + 9, 0, + -2, 35, + -1, 196, + 56, 113, + -2, 54, +} + +const yyPrivate = 57344 + +const yyLast = 1053 + +var yyAct = [...]int{ + 88, 234, 176, 111, 14, 171, 12, 122, 211, 31, + 177, 192, 109, 116, 9, 142, 48, 225, 97, 99, + 95, 96, 91, 143, 51, 162, 124, 10, 245, 223, + 233, 103, 224, 106, 157, 158, 232, 117, 107, 108, + 105, 244, 222, 238, 102, 112, 237, 77, 78, 104, + 79, 80, 81, 262, 257, 209, 144, 123, 208, 241, + 227, 226, 145, 165, 164, 128, 77, 78, 127, 79, + 80, 81, 84, 85, 86, 129, 75, 130, 131, 132, + 133, 134, 135, 136, 137, 138, 139, 140, 74, 76, + 82, 83, 84, 85, 86, 149, 75, 90, 126, 198, + 243, 174, 197, 147, 47, 160, 75, 74, 76, 82, + 83, 84, 85, 86, 166, 75, 146, 276, 240, 156, + 275, 42, 43, 152, 163, 93, 92, 94, 125, 255, + 185, 186, 265, 90, 46, 181, 182, 183, 45, 51, + 119, 188, 175, 179, 42, 43, 180, 94, 100, 193, + 169, 199, 170, 168, 202, 194, 203, 204, 205, 101, + 190, 93, 92, 94, 207, 172, 173, 200, 201, 212, + 212, 215, 184, 112, 213, 98, 210, 217, 10, 216, + 187, 13, 123, 181, 182, 183, 121, 219, 220, 13, + 3, 179, 11, 5, 180, 90, 228, 7, 8, 230, + 44, 28, 27, 218, 221, 178, 87, 49, 77, 78, + 239, 79, 80, 81, 110, 82, 83, 84, 85, 86, + 184, 75, 151, 93, 92, 94, 10, 154, 254, 193, + 80, 81, 90, 252, 253, 194, 256, 247, 159, 246, + 120, 191, 248, 249, 258, 212, 212, 189, 261, 259, + 260, 82, 83, 84, 85, 86, 266, 75, 268, 141, + 93, 92, 94, 206, 270, 271, 6, 4, 272, 82, + 83, 84, 85, 86, 277, 75, 2, 278, 269, 20, + 1, 19, 37, 24, 25, 26, 38, 40, 39, 41, + 23, 29, 30, 0, 42, 43, 0, 0, 17, 0, + 0, 0, 0, 18, 0, 15, 16, 22, 0, 89, + 0, 0, 0, 34, 33, 0, 0, 0, 21, 90, + 36, 0, 150, 32, 0, 148, 35, 20, 0, 19, + 37, 24, 25, 26, 38, 40, 39, 41, 23, 29, + 30, 0, 42, 43, 0, 0, 17, 93, 92, 94, + 0, 18, 0, 15, 16, 22, 0, 0, 0, 0, + 0, 34, 33, 0, 0, 0, 21, 0, 36, 0, + 0, 32, 0, 229, 35, 20, 0, 19, 37, 24, + 25, 26, 38, 40, 39, 41, 23, 29, 30, 0, + 42, 43, 0, 0, 17, 0, 0, 0, 0, 18, + 0, 15, 16, 22, 0, 0, 0, 0, 0, 34, + 33, 0, 0, 0, 21, 0, 36, 0, 0, 32, + 0, 118, 35, 20, 0, 19, 37, 24, 25, 26, + 38, 40, 39, 41, 23, 29, 30, 0, 42, 43, + 0, 0, 17, 0, 0, 0, 0, 18, 0, 15, + 16, 22, 0, 0, 0, 0, 0, 34, 33, 0, + 0, 0, 21, 0, 36, 0, 0, 32, 53, 54, + 35, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 114, 196, 0, 0, 0, 0, 0, 0, 42, + 43, 0, 0, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 53, 54, 0, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 114, 115, 0, 195, 0, + 0, 0, 0, 42, 43, 0, 0, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 37, 24, 25, 26, + 38, 40, 39, 41, 23, 29, 30, 0, 42, 43, + 77, 78, 113, 79, 80, 81, 0, 0, 0, 0, + 0, 22, 0, 0, 0, 0, 0, 34, 33, 79, + 80, 81, 21, 0, 36, 0, 0, 32, 77, 78, + 35, 79, 80, 81, 0, 0, 0, 0, 0, 0, + 0, 74, 76, 82, 83, 84, 85, 86, 0, 75, + 0, 0, 0, 77, 78, 251, 79, 80, 81, 82, + 83, 84, 85, 86, 0, 75, 0, 0, 0, 74, + 76, 82, 83, 84, 85, 86, 81, 75, 0, 0, + 0, 77, 78, 231, 79, 80, 81, 0, 0, 0, + 0, 0, 0, 0, 74, 76, 82, 83, 84, 85, + 86, 0, 75, 0, 0, 0, 77, 78, 167, 79, + 80, 81, 0, 0, 82, 83, 84, 85, 86, 0, + 75, 0, 74, 76, 82, 83, 84, 85, 86, 0, + 75, 0, 0, 77, 78, 279, 79, 80, 81, 0, + 0, 0, 0, 0, 0, 0, 0, 74, 76, 82, + 83, 84, 85, 86, 0, 75, 0, 0, 77, 78, + 274, 79, 80, 81, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 74, 76, 82, 83, 84, 85, + 86, 0, 75, 0, 0, 77, 78, 250, 79, 80, + 81, 0, 0, 0, 0, 0, 0, 0, 0, 74, + 76, 82, 83, 84, 85, 86, 0, 75, 0, 0, + 77, 78, 242, 79, 80, 81, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 74, 76, 82, 83, + 84, 85, 86, 0, 75, 0, 0, 77, 78, 214, + 79, 80, 81, 0, 0, 0, 0, 0, 0, 0, + 0, 74, 76, 82, 83, 84, 85, 86, 0, 75, + 0, 0, 77, 78, 161, 79, 80, 81, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 74, 76, + 82, 83, 84, 85, 86, 0, 75, 0, 273, 77, + 78, 0, 79, 80, 81, 0, 0, 0, 0, 0, + 0, 0, 0, 74, 76, 82, 83, 84, 85, 86, + 0, 75, 0, 264, 77, 78, 0, 79, 80, 81, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 74, 76, 82, 83, 84, 85, 86, 0, 75, 0, + 263, 77, 78, 0, 79, 80, 81, 0, 0, 0, + 0, 0, 0, 0, 0, 74, 76, 82, 83, 84, + 85, 86, 0, 75, 0, 236, 0, 0, 0, 77, + 78, 235, 79, 80, 81, 0, 0, 0, 0, 0, + 0, 0, 74, 76, 82, 83, 84, 85, 86, 0, + 75, 77, 78, 0, 79, 80, 81, 0, 267, 0, + 77, 78, 0, 79, 80, 81, 0, 0, 0, 0, + 74, 76, 82, 83, 84, 85, 86, 0, 75, 77, + 78, 0, 79, 80, 81, 155, 0, 0, 0, 153, + 0, 0, 74, 76, 82, 83, 84, 85, 86, 0, + 75, 74, 76, 82, 83, 84, 85, 86, 0, 75, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 74, 76, 82, 83, 84, 85, 86, 0, 75, 53, + 54, 0, 55, 56, 57, 58, 59, 60, 61, 62, + 63, 64, 50, 0, 0, 0, 0, 0, 0, 0, + 52, 0, 0, 0, 65, 66, 67, 68, 69, 70, + 71, 72, 73, +} + +var yyPact = [...]int{ + 180, -1000, 186, -33, -1000, 410, 186, 110, 106, 49, + 1012, -1000, 965, 410, 295, 520, 520, 410, 410, 127, + 139, 93, -1000, -1000, -1000, -1000, -1000, -8, -1000, -1000, + 116, -1000, 410, 520, 520, 495, 362, 119, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, 172, -33, -1000, -35, 82, + 42, 12, 9, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 410, -1000, 410, 410, 410, 410, + 410, 410, 410, 410, 410, 410, 410, -1000, 965, 2, + -1000, -1000, -1000, 93, 266, 208, 109, 946, 410, 937, + 74, -22, -1000, -1000, 410, -1000, 756, 171, 171, -36, + 78, 8, 7, 410, -1000, -1000, -1000, 599, -1000, -1000, + 122, 145, 46, -1000, -1000, 1012, 166, 166, 166, 965, + 204, 204, 562, 222, 617, 168, 23, 23, 53, 53, + 53, 135, -1000, -1000, 2, 461, -1000, -1000, -1000, 43, + 410, 2, 2, 410, -1000, 410, 410, 410, 145, 0, + 965, -1000, -1000, 495, 520, 520, 731, -1000, -1000, -1000, + 410, -33, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, 118, -1000, -1000, 410, 2, -17, + -1000, -29, -1000, 5, 4, 410, -1000, -1000, 314, 574, + -21, -27, 887, -1000, 965, 860, -12, -1000, -1000, 410, + -1000, -1000, 73, -1000, 3, 704, 45, -1000, -18, -1000, + 965, -1000, -1000, 2, -1000, 461, 2, 2, 679, -1000, + 546, -1000, 410, 410, 94, 410, -1000, -2, 145, 965, + 520, 520, -1000, -1000, -1000, 166, -1000, -1000, -1000, -1000, + -3, -1000, 835, 808, 96, 410, 915, 410, -1000, -1000, + -1000, -1000, 2, 410, 410, -1000, 965, 410, 783, -1000, + 652, 62, 887, -1000, -1000, -1000, 410, -1000, 627, -1000, +} + +var yyPgo = [...]int{ + 0, 280, 276, 267, 193, 266, 7, 192, 175, 263, + 0, 259, 15, 247, 241, 11, 4, 9, 240, 22, + 238, 1, 228, 227, 12, 214, 8, 2, 10, 16, + 207, 205, 203, 5, 202, 201, 13, 3, +} + +var yyR1 = [...]int{ + 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, + 6, 6, 7, 7, 8, 8, 9, 9, 33, 33, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 10, 10, 11, 11, 12, 12, 12, 13, 13, 14, + 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 17, 17, 18, 18, 18, 34, 34, 35, + 35, 19, 19, 19, 19, 19, 20, 20, 21, 21, + 22, 22, 23, 23, 24, 24, 24, 25, 25, 25, + 25, 25, 37, 37, 37, 26, 26, 27, 27, 27, + 27, 27, 27, 27, 28, 29, 29, 29, 30, 30, + 30, 31, 31, 32, 32, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, 36, 36, 36, 36, + 36, 36, 36, 36, 36, 36, +} + +var yyR2 = [...]int{ + 0, 2, 0, 3, 2, 2, 0, 2, 6, 4, + 0, 1, 0, 2, 5, 8, 1, 3, 1, 1, + 2, 3, 5, 9, 9, 11, 7, 3, 4, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 1, 1, 3, 1, 3, 3, 1, 3, 1, + 3, 3, 3, 5, 1, 1, 1, 1, 2, 2, + 1, 1, 1, 1, 4, 1, 1, 1, 2, 1, + 3, 2, 2, 3, 3, 2, 2, 2, 2, 2, + 3, 3, 1, 3, 0, 2, 4, 1, 1, 1, + 1, 2, 3, 4, 4, 5, 1, 3, 0, 5, + 0, 2, 0, 2, 0, 1, 3, 3, 3, 5, + 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, + 1, 1, 1, 1, 3, 0, 1, 3, 3, 3, + 3, 2, 3, 1, 3, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, +} + +var yyChk = [...]int{ + -1000, -1, -2, 10, -3, -4, -5, 11, 12, -28, + 60, -7, -10, -8, -16, 39, 40, 32, 37, 15, + 13, 52, 41, 24, 17, 18, 19, -34, -35, 25, + 26, -17, 57, 48, 47, 60, 54, 16, 20, 22, + 21, 23, 28, 29, -4, 28, 28, 55, -29, -30, + 20, -36, 28, 7, 8, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 45, 53, 46, 4, 5, 7, + 8, 9, 47, 48, 49, 50, 51, -7, -10, 14, + 24, -19, 53, 52, 54, -16, -16, -10, -8, -10, + 21, 20, -19, -17, 57, -17, -10, -16, -16, -24, + -25, -37, -17, 57, 20, 21, -36, -10, 59, 21, + -18, 14, -6, -28, 61, 46, 56, 56, 56, -10, + -10, -10, -10, -10, -10, -10, -10, -10, -10, -10, + -10, -11, -12, 21, 54, 60, -19, -17, 59, -10, + 56, 14, 14, 33, -23, 38, 45, 56, 57, -20, + -10, 58, 61, 46, 56, 56, -10, 59, 31, 28, + 30, -33, 20, 21, 55, -29, -27, -28, -31, 25, + 28, 17, 18, 19, 54, -27, -27, 45, 6, -13, + -12, -14, -15, -37, -17, 57, 21, 59, 56, -10, + -12, -12, -10, -10, -10, -10, -9, -33, 58, 55, + -24, -26, -16, -26, 58, -10, -6, 59, -32, -27, + -10, -12, 59, 46, 61, 46, 56, 56, -10, 59, + -10, 59, 57, 57, -21, 34, 55, 58, 55, -10, + 45, 56, 58, 55, 59, 46, -12, -15, -12, -12, + 58, 59, -10, -10, -22, 35, -10, 56, -33, -26, + -26, -27, 56, 55, 55, 36, -10, 33, -10, -12, + -10, -10, -10, 55, 58, 58, 55, -21, -10, 58, +} + +var yyDef = [...]int{ + 2, -2, 6, 0, 1, 12, 6, 0, 0, 0, + 125, 4, 5, 12, 41, 0, 0, 0, 0, 0, + 0, 55, 56, 57, 60, 61, 62, 63, 65, 66, + 67, 69, 0, 0, 0, 104, 0, 0, 87, 88, + 89, 90, 82, 84, 7, 0, 10, 3, 0, 126, + 0, 0, 0, 135, 136, 137, 138, 139, 140, 141, + 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, + 152, 153, 154, 155, 0, 29, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 13, 20, 0, + 77, 78, 79, 0, 0, 0, 0, 0, 0, 102, + 0, 0, 58, 59, 0, 68, 0, 71, 72, 0, + 105, 110, 111, 0, 112, 113, 114, 0, 75, 76, + 0, 0, 0, 11, 124, 125, 0, 0, 0, 21, + 30, 31, -2, 33, 34, -2, 36, 37, 38, 39, + 40, 0, 42, 44, 0, 0, 80, 81, 91, 0, + 0, 0, 0, 0, 27, 0, 0, 0, 0, 0, + 96, 70, 73, 104, 0, 0, 0, 74, 83, 85, + 0, 10, 18, 19, 9, 127, 128, 117, 118, 119, + 120, 121, 122, 123, 0, 129, 130, 0, 0, 0, + 47, 0, 49, 0, 0, 0, -2, 92, 0, 0, + 0, 0, 98, 103, 28, 0, 0, 16, 64, 0, + 106, 107, 115, 108, 0, 0, 0, 131, 0, 133, + 22, 43, 45, 0, 46, 0, 0, 0, 0, 93, + 0, 94, 0, 0, 100, 0, 14, 0, 0, 97, + 0, 0, 86, 8, 132, 0, 48, 50, 51, 52, + 0, 95, 0, 0, 0, 0, 0, 0, 17, 116, + 109, 134, 0, 0, 0, 26, 101, 0, 0, 53, + 0, 0, 98, 15, 23, 24, 0, 99, 0, 25, +} + +var yyTok1 = [...]int{ + 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 51, 3, 3, + 57, 58, 49, 47, 46, 48, 52, 50, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 56, 55, + 3, 3, 3, 53, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 54, 3, 59, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 60, 45, 61, +} + +var yyTok2 = [...]int{ + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, +} + +var yyTok3 = [...]int{ + 0, +} + +var yyErrorMessages = [...]struct { + state int + token int + msg string +}{} + +//line yaccpar:1 + +/* parser for yacc output */ + +var ( + yyDebug = 0 + yyErrorVerbose = false +) + +type yyLexer interface { + Lex(lval *yySymType) int + Error(s string) +} + +type yyParser interface { + Parse(yyLexer) int + Lookahead() int +} + +type yyParserImpl struct { + lval yySymType + stack [yyInitialStackSize]yySymType + char int +} + +func (p *yyParserImpl) Lookahead() int { + return p.char +} + +func yyNewParser() yyParser { + return &yyParserImpl{} +} + +const yyFlag = -1000 + +func yyTokname(c int) string { + if c >= 1 && c-1 < len(yyToknames) { + if yyToknames[c-1] != "" { + return yyToknames[c-1] } - if err = parser.ParseString(".", &query); err != nil { - return nil, err + } + return __yyfmt__.Sprintf("tok-%v", c) +} + +func yyStatname(s int) string { + if s >= 0 && s < len(yyStatenames) { + if yyStatenames[s] != "" { + return yyStatenames[s] } } - return &query, nil + return __yyfmt__.Sprintf("state-%v", s) } -var modulesParser = participle.MustBuild(&Module{}, parserOptions...) +func yyErrorMessage(state, lookAhead int) string { + const TOKSTART = 4 + + if !yyErrorVerbose { + return "syntax error" + } + + for _, e := range yyErrorMessages { + if e.state == state && e.token == lookAhead { + return "syntax error: " + e.msg + } + } + + res := "syntax error: unexpected " + yyTokname(lookAhead) + + // To match Bison, suggest at most four expected tokens. + expected := make([]int, 0, 4) + + // Look for shiftable tokens. + base := yyPact[state] + for tok := TOKSTART; tok-1 < len(yyToknames); tok++ { + if n := base + tok; n >= 0 && n < yyLast && yyChk[yyAct[n]] == tok { + if len(expected) == cap(expected) { + return res + } + expected = append(expected, tok) + } + } + + if yyDef[state] == -2 { + i := 0 + for yyExca[i] != -1 || yyExca[i+1] != state { + i += 2 + } + + // Look for tokens that we accept or reduce. + for i += 2; yyExca[i] >= 0; i += 2 { + tok := yyExca[i] + if tok < TOKSTART || yyExca[i+1] == 0 { + continue + } + if len(expected) == cap(expected) { + return res + } + expected = append(expected, tok) + } -// ParseModule parses a module. -func ParseModule(src string) (*Module, error) { - var module Module - if err := modulesParser.ParseString(src, &module); err != nil { - if strings.TrimSpace(src) != "" { - return nil, err + // If the default action is to accept or reduce, give up. + if yyExca[i+1] != 0 { + return res + } + } + + for i, tok := range expected { + if i == 0 { + res += ", expecting " + } else { + res += " or " + } + res += yyTokname(tok) + } + return res +} + +func yylex1(lex yyLexer, lval *yySymType) (char, token int) { + token = 0 + char = lex.Lex(lval) + if char <= 0 { + token = yyTok1[0] + goto out + } + if char < len(yyTok1) { + token = yyTok1[char] + goto out + } + if char >= yyPrivate { + if char < yyPrivate+len(yyTok2) { + token = yyTok2[char-yyPrivate] + goto out + } + } + for i := 0; i < len(yyTok3); i += 2 { + token = yyTok3[i+0] + if token == char { + token = yyTok3[i+1] + goto out + } + } + +out: + if token == 0 { + token = yyTok2[1] /* unknown char */ + } + if yyDebug >= 3 { + __yyfmt__.Printf("lex %s(%d)\n", yyTokname(token), uint(char)) + } + return char, token +} + +func yyParse(yylex yyLexer) int { + return yyNewParser().Parse(yylex) +} + +func (yyrcvr *yyParserImpl) Parse(yylex yyLexer) int { + var yyn int + var yyVAL yySymType + var yyDollar []yySymType + _ = yyDollar // silence set and not used + yyS := yyrcvr.stack[:] + + Nerrs := 0 /* number of errors */ + Errflag := 0 /* error recovery flag */ + yystate := 0 + yyrcvr.char = -1 + yytoken := -1 // yyrcvr.char translated into internal numbering + defer func() { + // Make sure we report no lookahead when not parsing. + yystate = -1 + yyrcvr.char = -1 + yytoken = -1 + }() + yyp := -1 + goto yystack + +ret0: + return 0 + +ret1: + return 1 + +yystack: + /* put a state and value onto the stack */ + if yyDebug >= 4 { + __yyfmt__.Printf("char %v in %v\n", yyTokname(yytoken), yyStatname(yystate)) + } + + yyp++ + if yyp >= len(yyS) { + nyys := make([]yySymType, len(yyS)*2) + copy(nyys, yyS) + yyS = nyys + } + yyS[yyp] = yyVAL + yyS[yyp].yys = yystate + +yynewstate: + yyn = yyPact[yystate] + if yyn <= yyFlag { + goto yydefault /* simple state */ + } + if yyrcvr.char < 0 { + yyrcvr.char, yytoken = yylex1(yylex, &yyrcvr.lval) + } + yyn += yytoken + if yyn < 0 || yyn >= yyLast { + goto yydefault + } + yyn = yyAct[yyn] + if yyChk[yyn] == yytoken { /* valid shift */ + yyrcvr.char = -1 + yytoken = -1 + yyVAL = yyrcvr.lval + yystate = yyn + if Errflag > 0 { + Errflag-- + } + goto yystack + } + +yydefault: + /* default state action */ + yyn = yyDef[yystate] + if yyn == -2 { + if yyrcvr.char < 0 { + yyrcvr.char, yytoken = yylex1(yylex, &yyrcvr.lval) + } + + /* look through exception table */ + xi := 0 + for { + if yyExca[xi+0] == -1 && yyExca[xi+1] == yystate { + break + } + xi += 2 + } + for xi += 2; ; xi += 2 { + yyn = yyExca[xi+0] + if yyn < 0 || yyn == yytoken { + break + } + } + yyn = yyExca[xi+1] + if yyn < 0 { + goto ret0 + } + } + if yyn == 0 { + /* error ... attempt to resume parsing */ + switch Errflag { + case 0: /* brand new error */ + yylex.Error(yyErrorMessage(yystate, yytoken)) + Nerrs++ + if yyDebug >= 1 { + __yyfmt__.Printf("%s", yyStatname(yystate)) + __yyfmt__.Printf(" saw %s\n", yyTokname(yytoken)) + } + fallthrough + + case 1, 2: /* incompletely recovered error ... try again */ + Errflag = 3 + + /* find a state where "error" is a legal shift action */ + for yyp >= 0 { + yyn = yyPact[yyS[yyp].yys] + yyErrCode + if yyn >= 0 && yyn < yyLast { + yystate = yyAct[yyn] /* simulate a shift of "error" */ + if yyChk[yystate] == yyErrCode { + goto yystack + } + } + + /* the current p has no shift on "error", pop stack */ + if yyDebug >= 2 { + __yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys) + } + yyp-- + } + /* there is no state on the stack with an error shift ... abort */ + goto ret1 + + case 3: /* no shift yet; clobber input char */ + if yyDebug >= 2 { + __yyfmt__.Printf("error recovery discards %s\n", yyTokname(yytoken)) + } + if yytoken == yyEofCode { + goto ret1 + } + yyrcvr.char = -1 + yytoken = -1 + goto yynewstate /* try again in the same state */ + } + } + + /* reduction by production yyn */ + if yyDebug >= 2 { + __yyfmt__.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate)) + } + + yynt := yyn + yypt := yyp + _ = yypt // guard against "declared and not used" + + yyp -= yyR2[yyn] + // yyp is now the index of $0. Perform the default action. Iff the + // reduced production is ε, $1 is possibly out of range. + if yyp+1 >= len(yyS) { + nyys := make([]yySymType, len(yyS)*2) + copy(nyys, yyS) + yyS = nyys + } + yyVAL = yyS[yyp+1] + + /* consult goto table to find next state */ + yyn = yyR1[yyn] + yyg := yyPgo[yyn] + yyj := yyg + yyS[yyp].yys + 1 + + if yyj >= yyLast { + yystate = yyAct[yyg] + } else { + yystate = yyAct[yyj] + if yyChk[yystate] != -yyn { + yystate = yyAct[yyg] + } + } + // dummy call; replaced with literal code + switch yynt { + + case 1: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:53 + { + if yyDollar[1].value != nil { + yyDollar[2].value.(*Query).Meta = yyDollar[1].value.(*ConstObject) + } + yylex.(*lexer).result = yyDollar[2].value.(*Query) + } + case 2: + yyDollar = yyS[yypt-0 : yypt+1] +//line parser.go.y:60 + { + yyVAL.value = nil + } + case 3: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:64 + { + yyVAL.value = yyDollar[2].value + } + case 4: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:70 + { + yyVAL.value = &Query{Imports: yyDollar[1].value.([]*Import), FuncDefs: yyDollar[2].value.([]*FuncDef), Term: &Term{Type: TermTypeIdentity}} + } + case 5: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:74 + { + if yyDollar[1].value != nil { + yyDollar[2].value.(*Query).Imports = yyDollar[1].value.([]*Import) + } + yyVAL.value = yyDollar[2].value + } + case 6: + yyDollar = yyS[yypt-0 : yypt+1] +//line parser.go.y:81 + { + yyVAL.value = []*Import(nil) + } + case 7: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:85 + { + yyVAL.value = prependImport(yyDollar[2].value.([]*Import), yyDollar[1].value.(*Import)) + } + case 8: + yyDollar = yyS[yypt-6 : yypt+1] +//line parser.go.y:91 + { + yyVAL.value = &Import{ImportPath: yyDollar[2].token, ImportAlias: yyDollar[4].token, Meta: yyDollar[5].value.(*ConstObject)} + } + case 9: + yyDollar = yyS[yypt-4 : yypt+1] +//line parser.go.y:95 + { + yyVAL.value = &Import{IncludePath: yyDollar[2].token, Meta: yyDollar[3].value.(*ConstObject)} + } + case 10: + yyDollar = yyS[yypt-0 : yypt+1] +//line parser.go.y:101 + { + yyVAL.value = (*ConstObject)(nil) + } + case 11: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:104 + { + } + case 12: + yyDollar = yyS[yypt-0 : yypt+1] +//line parser.go.y:108 + { + yyVAL.value = []*FuncDef(nil) + } + case 13: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:112 + { + yyVAL.value = prependFuncDef(yyDollar[2].value.([]*FuncDef), yyDollar[1].value.(*FuncDef)) + } + case 14: + yyDollar = yyS[yypt-5 : yypt+1] +//line parser.go.y:118 + { + yyVAL.value = &FuncDef{Name: yyDollar[2].token, Body: yyDollar[4].value.(*Query)} + } + case 15: + yyDollar = yyS[yypt-8 : yypt+1] +//line parser.go.y:122 + { + yyVAL.value = &FuncDef{yyDollar[2].token, yyDollar[4].value.([]string), yyDollar[7].value.(*Query)} + } + case 16: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:128 + { + yyVAL.value = []string{yyDollar[1].token} + } + case 17: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:132 + { + yyVAL.value = append(yyDollar[1].value.([]string), yyDollar[3].token) + } + case 18: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:137 + { + } + case 19: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:138 + { + } + case 20: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:142 + { + yyDollar[2].value.(*Query).FuncDefs = prependFuncDef(yyDollar[2].value.(*Query).FuncDefs, yyDollar[1].value.(*FuncDef)) + yyVAL.value = yyDollar[2].value + } + case 21: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:147 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: OpPipe, Right: yyDollar[3].value.(*Query)} + } + case 22: + yyDollar = yyS[yypt-5 : yypt+1] +//line parser.go.y:151 + { + yyDollar[1].value.(*Term).SuffixList = append(yyDollar[1].value.(*Term).SuffixList, &Suffix{Bind: &Bind{yyDollar[3].value.([]*Pattern), yyDollar[5].value.(*Query)}}) + yyVAL.value = &Query{Term: yyDollar[1].value.(*Term)} + } + case 23: + yyDollar = yyS[yypt-9 : yypt+1] +//line parser.go.y:156 + { + yyVAL.value = &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{yyDollar[2].value.(*Term), yyDollar[4].value.(*Pattern), yyDollar[6].value.(*Query), yyDollar[8].value.(*Query)}}} + } + case 24: + yyDollar = yyS[yypt-9 : yypt+1] +//line parser.go.y:160 + { + yyVAL.value = &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{yyDollar[2].value.(*Term), yyDollar[4].value.(*Pattern), yyDollar[6].value.(*Query), yyDollar[8].value.(*Query), nil}}} + } + case 25: + yyDollar = yyS[yypt-11 : yypt+1] +//line parser.go.y:164 + { + yyVAL.value = &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{yyDollar[2].value.(*Term), yyDollar[4].value.(*Pattern), yyDollar[6].value.(*Query), yyDollar[8].value.(*Query), yyDollar[10].value.(*Query)}}} + } + case 26: + yyDollar = yyS[yypt-7 : yypt+1] +//line parser.go.y:168 + { + yyVAL.value = &Query{Term: &Term{Type: TermTypeIf, If: &If{yyDollar[2].value.(*Query), yyDollar[4].value.(*Query), yyDollar[5].value.([]*IfElif), yyDollar[6].value.(*Query)}}} + } + case 27: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:172 + { + yyVAL.value = &Query{Term: &Term{Type: TermTypeTry, Try: &Try{yyDollar[2].value.(*Query), yyDollar[3].value.(*Query)}}} + } + case 28: + yyDollar = yyS[yypt-4 : yypt+1] +//line parser.go.y:176 + { + yyVAL.value = &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{yyDollar[2].token, yyDollar[4].value.(*Query)}}} + } + case 29: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:180 + { + if t := yyDollar[1].value.(*Query).Term; t != nil { + t.SuffixList = append(t.SuffixList, &Suffix{Optional: true}) + } else { + yyVAL.value = &Query{Term: &Term{Type: TermTypeQuery, Query: yyDollar[1].value.(*Query), SuffixList: []*Suffix{{Optional: true}}}} + } + } + case 30: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:188 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: OpComma, Right: yyDollar[3].value.(*Query)} + } + case 31: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:192 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: yyDollar[2].operator, Right: yyDollar[3].value.(*Query)} + } + case 32: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:196 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: yyDollar[2].operator, Right: yyDollar[3].value.(*Query)} + } + case 33: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:200 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: OpOr, Right: yyDollar[3].value.(*Query)} + } + case 34: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:204 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: OpAnd, Right: yyDollar[3].value.(*Query)} + } + case 35: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:208 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: yyDollar[2].operator, Right: yyDollar[3].value.(*Query)} + } + case 36: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:212 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: OpAdd, Right: yyDollar[3].value.(*Query)} + } + case 37: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:216 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: OpSub, Right: yyDollar[3].value.(*Query)} + } + case 38: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:220 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: OpMul, Right: yyDollar[3].value.(*Query)} + } + case 39: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:224 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: OpDiv, Right: yyDollar[3].value.(*Query)} + } + case 40: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:228 + { + yyVAL.value = &Query{Left: yyDollar[1].value.(*Query), Op: OpMod, Right: yyDollar[3].value.(*Query)} + } + case 41: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:232 + { + yyVAL.value = &Query{Term: yyDollar[1].value.(*Term)} + } + case 42: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:238 + { + yyVAL.value = []*Pattern{yyDollar[1].value.(*Pattern)} + } + case 43: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:242 + { + yyVAL.value = append(yyDollar[1].value.([]*Pattern), yyDollar[3].value.(*Pattern)) + } + case 44: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:248 + { + yyVAL.value = &Pattern{Name: yyDollar[1].token} + } + case 45: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:252 + { + yyVAL.value = &Pattern{Array: yyDollar[2].value.([]*Pattern)} + } + case 46: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:256 + { + yyVAL.value = &Pattern{Object: yyDollar[2].value.([]*PatternObject)} + } + case 47: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:262 + { + yyVAL.value = []*Pattern{yyDollar[1].value.(*Pattern)} + } + case 48: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:266 + { + yyVAL.value = append(yyDollar[1].value.([]*Pattern), yyDollar[3].value.(*Pattern)) + } + case 49: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:272 + { + yyVAL.value = []*PatternObject{yyDollar[1].value.(*PatternObject)} + } + case 50: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:276 + { + yyVAL.value = append(yyDollar[1].value.([]*PatternObject), yyDollar[3].value.(*PatternObject)) + } + case 51: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:282 + { + yyVAL.value = &PatternObject{Key: yyDollar[1].token, Val: yyDollar[3].value.(*Pattern)} + } + case 52: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:286 + { + yyVAL.value = &PatternObject{KeyString: yyDollar[1].value.(*String), Val: yyDollar[3].value.(*Pattern)} + } + case 53: + yyDollar = yyS[yypt-5 : yypt+1] +//line parser.go.y:290 + { + yyVAL.value = &PatternObject{KeyQuery: yyDollar[2].value.(*Query), Val: yyDollar[5].value.(*Pattern)} + } + case 54: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:294 + { + yyVAL.value = &PatternObject{KeyOnly: yyDollar[1].token} + } + case 55: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:300 + { + yyVAL.value = &Term{Type: TermTypeIdentity} + } + case 56: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:304 + { + yyVAL.value = &Term{Type: TermTypeRecurse} + } + case 57: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:308 + { + yyVAL.value = &Term{Type: TermTypeIndex, Index: &Index{Name: yyDollar[1].token}} + } + case 58: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:312 + { + if yyDollar[2].value.(*Suffix).Iter { + yyVAL.value = &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{yyDollar[2].value.(*Suffix)}} + } else { + yyVAL.value = &Term{Type: TermTypeIndex, Index: yyDollar[2].value.(*Suffix).Index} + } + } + case 59: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:320 + { + yyVAL.value = &Term{Type: TermTypeIndex, Index: &Index{Str: yyDollar[2].value.(*String)}} + } + case 60: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:324 + { + yyVAL.value = &Term{Type: TermTypeNull} + } + case 61: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:328 + { + yyVAL.value = &Term{Type: TermTypeTrue} + } + case 62: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:332 + { + yyVAL.value = &Term{Type: TermTypeFalse} + } + case 63: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:336 + { + yyVAL.value = &Term{Type: TermTypeFunc, Func: &Func{Name: yyDollar[1].token}} + } + case 64: + yyDollar = yyS[yypt-4 : yypt+1] +//line parser.go.y:340 + { + yyVAL.value = &Term{Type: TermTypeFunc, Func: &Func{Name: yyDollar[1].token, Args: yyDollar[3].value.([]*Query)}} + } + case 65: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:344 + { + yyVAL.value = &Term{Type: TermTypeFunc, Func: &Func{Name: yyDollar[1].token}} + } + case 66: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:348 + { + yyVAL.value = &Term{Type: TermTypeNumber, Number: yyDollar[1].token} + } + case 67: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:352 + { + yyVAL.value = &Term{Type: TermTypeFormat, Format: yyDollar[1].token} + } + case 68: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:356 + { + yyVAL.value = &Term{Type: TermTypeFormat, Format: yyDollar[1].token, Str: yyDollar[2].value.(*String)} + } + case 69: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:360 + { + yyVAL.value = &Term{Type: TermTypeString, Str: yyDollar[1].value.(*String)} + } + case 70: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:364 + { + yyVAL.value = &Term{Type: TermTypeQuery, Query: yyDollar[2].value.(*Query)} + } + case 71: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:368 + { + yyVAL.value = &Term{Type: TermTypeUnary, Unary: &Unary{OpSub, yyDollar[2].value.(*Term)}} + } + case 72: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:372 + { + yyVAL.value = &Term{Type: TermTypeUnary, Unary: &Unary{OpAdd, yyDollar[2].value.(*Term)}} + } + case 73: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:376 + { + yyVAL.value = &Term{Type: TermTypeObject, Object: &Object{yyDollar[2].value.([]*ObjectKeyVal)}} + } + case 74: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:380 + { + yyVAL.value = &Term{Type: TermTypeArray, Array: &Array{yyDollar[2].value.(*Query)}} + } + case 75: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:384 + { + yyVAL.value = &Term{Type: TermTypeArray, Array: &Array{}} + } + case 76: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:388 + { + yyVAL.value = &Term{Type: TermTypeBreak, Break: yyDollar[2].token} + } + case 77: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:392 + { + yyDollar[1].value.(*Term).SuffixList = append(yyDollar[1].value.(*Term).SuffixList, &Suffix{Index: &Index{Name: yyDollar[2].token}}) + } + case 78: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:396 + { + yyDollar[1].value.(*Term).SuffixList = append(yyDollar[1].value.(*Term).SuffixList, yyDollar[2].value.(*Suffix)) + } + case 79: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:400 + { + yyDollar[1].value.(*Term).SuffixList = append(yyDollar[1].value.(*Term).SuffixList, &Suffix{Optional: true}) + } + case 80: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:404 + { + yyDollar[1].value.(*Term).SuffixList = append(yyDollar[1].value.(*Term).SuffixList, yyDollar[3].value.(*Suffix)) + } + case 81: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:408 + { + yyDollar[1].value.(*Term).SuffixList = append(yyDollar[1].value.(*Term).SuffixList, &Suffix{Index: &Index{Str: yyDollar[3].value.(*String)}}) + } + case 82: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:414 + { + yyVAL.value = &String{Str: yyDollar[1].token} + } + case 83: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:418 + { + yyVAL.value = &String{Queries: yyDollar[2].value.([]*Query)} + } + case 84: + yyDollar = yyS[yypt-0 : yypt+1] +//line parser.go.y:424 + { + yyVAL.value = []*Query{} + } + case 85: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:428 + { + yyVAL.value = append(yyDollar[1].value.([]*Query), &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: yyDollar[2].token}}}) + } + case 86: + yyDollar = yyS[yypt-4 : yypt+1] +//line parser.go.y:432 + { + yylex.(*lexer).inString = true + yyVAL.value = append(yyDollar[1].value.([]*Query), &Query{Term: &Term{Type: TermTypeQuery, Query: yyDollar[3].value.(*Query)}}) + } + case 87: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:438 + { + } + case 88: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:439 + { + } + case 89: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:442 + { + } + case 90: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:443 + { + } + case 91: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:447 + { + yyVAL.value = &Suffix{Iter: true} + } + case 92: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:451 + { + yyVAL.value = &Suffix{Index: &Index{Start: yyDollar[2].value.(*Query)}} + } + case 93: + yyDollar = yyS[yypt-4 : yypt+1] +//line parser.go.y:455 + { + yyVAL.value = &Suffix{Index: &Index{Start: yyDollar[2].value.(*Query), IsSlice: true}} + } + case 94: + yyDollar = yyS[yypt-4 : yypt+1] +//line parser.go.y:459 + { + yyVAL.value = &Suffix{Index: &Index{End: yyDollar[3].value.(*Query)}} + } + case 95: + yyDollar = yyS[yypt-5 : yypt+1] +//line parser.go.y:463 + { + yyVAL.value = &Suffix{Index: &Index{Start: yyDollar[2].value.(*Query), IsSlice: true, End: yyDollar[4].value.(*Query)}} + } + case 96: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:469 + { + yyVAL.value = []*Query{yyDollar[1].value.(*Query)} + } + case 97: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:473 + { + yyVAL.value = append(yyDollar[1].value.([]*Query), yyDollar[3].value.(*Query)) + } + case 98: + yyDollar = yyS[yypt-0 : yypt+1] +//line parser.go.y:479 + { + yyVAL.value = []*IfElif(nil) + } + case 99: + yyDollar = yyS[yypt-5 : yypt+1] +//line parser.go.y:483 + { + yyVAL.value = prependIfElif(yyDollar[5].value.([]*IfElif), &IfElif{yyDollar[2].value.(*Query), yyDollar[4].value.(*Query)}) + } + case 100: + yyDollar = yyS[yypt-0 : yypt+1] +//line parser.go.y:489 + { + yyVAL.value = (*Query)(nil) + } + case 101: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:493 + { + yyVAL.value = yyDollar[2].value + } + case 102: + yyDollar = yyS[yypt-0 : yypt+1] +//line parser.go.y:499 + { + yyVAL.value = (*Query)(nil) + } + case 103: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:503 + { + yyVAL.value = yyDollar[2].value + } + case 104: + yyDollar = yyS[yypt-0 : yypt+1] +//line parser.go.y:509 + { + yyVAL.value = []*ObjectKeyVal(nil) + } + case 105: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:513 + { + yyVAL.value = []*ObjectKeyVal{yyDollar[1].value.(*ObjectKeyVal)} + } + case 106: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:517 + { + yyVAL.value = prependObjectKeyVal(yyDollar[3].value.([]*ObjectKeyVal), yyDollar[1].value.(*ObjectKeyVal)) + } + case 107: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:523 + { + yyVAL.value = &ObjectKeyVal{Key: yyDollar[1].token, Val: yyDollar[3].value.(*ObjectVal)} + } + case 108: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:527 + { + yyVAL.value = &ObjectKeyVal{KeyString: yyDollar[1].value.(*String), Val: yyDollar[3].value.(*ObjectVal)} + } + case 109: + yyDollar = yyS[yypt-5 : yypt+1] +//line parser.go.y:531 + { + yyVAL.value = &ObjectKeyVal{KeyQuery: yyDollar[2].value.(*Query), Val: yyDollar[5].value.(*ObjectVal)} + } + case 110: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:535 + { + yyVAL.value = &ObjectKeyVal{KeyOnly: yyDollar[1].token} + } + case 111: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:539 + { + yyVAL.value = &ObjectKeyVal{KeyOnlyString: yyDollar[1].value.(*String)} + } + case 112: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:544 + { + } + case 113: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:545 + { + } + case 114: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:546 + { + } + case 115: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:550 + { + yyVAL.value = &ObjectVal{[]*Query{{Term: yyDollar[1].value.(*Term)}}} + } + case 116: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:554 + { + yyVAL.value = &ObjectVal{prependQuery(yyDollar[3].value.(*ObjectVal).Queries, &Query{Term: yyDollar[1].value.(*Term)})} + } + case 117: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:560 + { + yyVAL.value = &ConstTerm{Object: yyDollar[1].value.(*ConstObject)} + } + case 118: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:564 + { + yyVAL.value = &ConstTerm{Array: yyDollar[1].value.(*ConstArray)} + } + case 119: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:568 + { + yyVAL.value = &ConstTerm{Number: yyDollar[1].token} + } + case 120: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:572 + { + yyVAL.value = &ConstTerm{Str: yyDollar[1].token} + } + case 121: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:576 + { + yyVAL.value = &ConstTerm{Null: true} + } + case 122: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:580 + { + yyVAL.value = &ConstTerm{True: true} + } + case 123: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:584 + { + yyVAL.value = &ConstTerm{False: true} + } + case 124: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:590 + { + yyVAL.value = &ConstObject{yyDollar[2].value.([]*ConstObjectKeyVal)} + } + case 125: + yyDollar = yyS[yypt-0 : yypt+1] +//line parser.go.y:596 + { + yyVAL.value = []*ConstObjectKeyVal(nil) + } + case 126: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:600 + { + yyVAL.value = []*ConstObjectKeyVal{yyDollar[1].value.(*ConstObjectKeyVal)} + } + case 127: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:604 + { + yyVAL.value = prependConstObjectKeyVal(yyDollar[3].value.([]*ConstObjectKeyVal), yyDollar[1].value.(*ConstObjectKeyVal)) + } + case 128: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:610 + { + yyVAL.value = &ConstObjectKeyVal{Key: yyDollar[1].token, Val: yyDollar[3].value.(*ConstTerm)} + } + case 129: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:614 + { + yyVAL.value = &ConstObjectKeyVal{Key: yyDollar[1].token, Val: yyDollar[3].value.(*ConstTerm)} + } + case 130: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:618 + { + yyVAL.value = &ConstObjectKeyVal{KeyString: yyDollar[1].token, Val: yyDollar[3].value.(*ConstTerm)} + } + case 131: + yyDollar = yyS[yypt-2 : yypt+1] +//line parser.go.y:624 + { + yyVAL.value = &ConstArray{} + } + case 132: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:628 + { + yyVAL.value = &ConstArray{yyDollar[2].value.([]*ConstTerm)} + } + case 133: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:634 + { + yyVAL.value = []*ConstTerm{yyDollar[1].value.(*ConstTerm)} + } + case 134: + yyDollar = yyS[yypt-3 : yypt+1] +//line parser.go.y:638 + { + yyVAL.value = append(yyDollar[1].value.([]*ConstTerm), yyDollar[3].value.(*ConstTerm)) + } + case 135: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:643 + { + } + case 136: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:644 + { + } + case 137: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:645 + { + } + case 138: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:646 + { + } + case 139: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:647 + { + } + case 140: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:648 + { + } + case 141: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:649 + { + } + case 142: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:650 + { + } + case 143: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:651 + { + } + case 144: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:652 + { + } + case 145: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:653 + { + } + case 146: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:654 + { + } + case 147: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:655 + { + } + case 148: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:656 + { + } + case 149: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:657 + { + } + case 150: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:658 + { + } + case 151: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:659 + { + } + case 152: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:660 + { + } + case 153: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:661 + { + } + case 154: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:662 + { + } + case 155: + yyDollar = yyS[yypt-1 : yypt+1] +//line parser.go.y:663 + { } } - return &module, nil + goto yystack /* stack new state and value */ } diff --git a/vendor/github.com/itchyny/gojq/parser.go.y b/vendor/github.com/itchyny/gojq/parser.go.y new file mode 100644 index 00000000..7fc3aee3 --- /dev/null +++ b/vendor/github.com/itchyny/gojq/parser.go.y @@ -0,0 +1,665 @@ +%{ +package gojq + +// Parse parses a query. +func Parse(src string) (*Query, error) { + l := newLexer(src) + if yyParse(l) > 0 { + return nil, l.err + } + return l.result, nil +} +%} + +%union { + value interface{} + token string + operator Operator +} + +%type program moduleheader programbody imports import metaopt funcdefs funcdef funcdefargs query +%type bindpatterns pattern arraypatterns objectpatterns objectpattern +%type term string stringparts suffix args ifelifs ifelse trycatch +%type object objectkeyval objectval +%type constterm constobject constobjectkeyvals constobjectkeyval constarray constarrayelems +%type tokIdentVariable tokIdentModuleIdent tokVariableModuleVariable tokKeyword objectkey +%token tokAltOp tokUpdateOp tokDestAltOp tokOrOp tokAndOp tokCompareOp +%token tokModule tokImport tokInclude tokDef tokAs tokLabel tokBreak +%token tokNull tokTrue tokFalse +%token tokIdent tokVariable tokModuleIdent tokModuleVariable +%token tokIndex tokNumber tokFormat tokInvalid +%token tokString tokStringStart tokStringQuery tokStringEnd +%token tokIf tokThen tokElif tokElse tokEnd +%token tokTry tokCatch tokReduce tokForeach +%token tokRecurse tokFuncDefPost tokTermPost tokEmptyCatch + +%nonassoc tokFuncDefPost tokTermPost tokEmptyCatch +%right '|' +%left ',' +%right tokAltOp +%nonassoc tokUpdateOp +%left tokOrOp +%left tokAndOp +%nonassoc tokCompareOp +%left '+' '-' +%left '*' '/' '%' +%nonassoc tokAs tokIndex '.' '?' +%nonassoc '[' tokTry tokCatch + +%% + +program + : moduleheader programbody + { + if $1 != nil { $2.(*Query).Meta = $1.(*ConstObject) } + yylex.(*lexer).result = $2.(*Query) + } + +moduleheader + : + { + $$ = nil + } + | tokModule constobject ';' + { + $$ = $2; + } + +programbody + : imports funcdefs + { + $$ = &Query{Imports: $1.([]*Import), FuncDefs: $2.([]*FuncDef), Term: &Term{Type: TermTypeIdentity}} + } + | imports query + { + if $1 != nil { $2.(*Query).Imports = $1.([]*Import) } + $$ = $2 + } + +imports + : + { + $$ = []*Import(nil) + } + | import imports + { + $$ = prependImport($2.([]*Import), $1.(*Import)) + } + +import + : tokImport tokString tokAs tokIdentVariable metaopt ';' + { + $$ = &Import{ImportPath: $2, ImportAlias: $4, Meta: $5.(*ConstObject)} + } + | tokInclude tokString metaopt ';' + { + $$ = &Import{IncludePath: $2, Meta: $3.(*ConstObject)} + } + +metaopt + : + { + $$ = (*ConstObject)(nil) + } + | constobject {} + +funcdefs + : + { + $$ = []*FuncDef(nil) + } + | funcdef funcdefs + { + $$ = prependFuncDef($2.([]*FuncDef), $1.(*FuncDef)) + } + +funcdef + : tokDef tokIdent ':' query ';' + { + $$ = &FuncDef{Name: $2, Body: $4.(*Query)} + } + | tokDef tokIdent '(' funcdefargs ')' ':' query ';' + { + $$ = &FuncDef{$2, $4.([]string), $7.(*Query)} + } + +funcdefargs + : tokIdentVariable + { + $$ = []string{$1} + } + | funcdefargs ';' tokIdentVariable + { + $$ = append($1.([]string), $3) + } + +tokIdentVariable + : tokIdent {} + | tokVariable {} + +query + : funcdef query %prec tokFuncDefPost + { + $2.(*Query).FuncDefs = prependFuncDef($2.(*Query).FuncDefs, $1.(*FuncDef)) + $$ = $2 + } + | query '|' query + { + $$ = &Query{Left: $1.(*Query), Op: OpPipe, Right: $3.(*Query)} + } + | term tokAs bindpatterns '|' query + { + $1.(*Term).SuffixList = append($1.(*Term).SuffixList, &Suffix{Bind: &Bind{$3.([]*Pattern), $5.(*Query)}}) + $$ = &Query{Term: $1.(*Term)} + } + | tokReduce term tokAs pattern '(' query ';' query ')' + { + $$ = &Query{Term: &Term{Type: TermTypeReduce, Reduce: &Reduce{$2.(*Term), $4.(*Pattern), $6.(*Query), $8.(*Query)}}} + } + | tokForeach term tokAs pattern '(' query ';' query ')' + { + $$ = &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{$2.(*Term), $4.(*Pattern), $6.(*Query), $8.(*Query), nil}}} + } + | tokForeach term tokAs pattern '(' query ';' query ';' query ')' + { + $$ = &Query{Term: &Term{Type: TermTypeForeach, Foreach: &Foreach{$2.(*Term), $4.(*Pattern), $6.(*Query), $8.(*Query), $10.(*Query)}}} + } + | tokIf query tokThen query ifelifs ifelse tokEnd + { + $$ = &Query{Term: &Term{Type: TermTypeIf, If: &If{$2.(*Query), $4.(*Query), $5.([]*IfElif), $6.(*Query)}}} + } + | tokTry query trycatch + { + $$ = &Query{Term: &Term{Type: TermTypeTry, Try: &Try{$2.(*Query), $3.(*Query)}}} + } + | tokLabel tokVariable '|' query + { + $$ = &Query{Term: &Term{Type: TermTypeLabel, Label: &Label{$2, $4.(*Query)}}} + } + | query '?' + { + if t := $1.(*Query).Term; t != nil { + t.SuffixList = append(t.SuffixList, &Suffix{Optional: true}) + } else { + $$ = &Query{Term: &Term{Type: TermTypeQuery, Query: $1.(*Query), SuffixList: []*Suffix{{Optional: true}}}} + } + } + | query ',' query + { + $$ = &Query{Left: $1.(*Query), Op: OpComma, Right: $3.(*Query)} + } + | query tokAltOp query + { + $$ = &Query{Left: $1.(*Query), Op: $2, Right: $3.(*Query)} + } + | query tokUpdateOp query + { + $$ = &Query{Left: $1.(*Query), Op: $2, Right: $3.(*Query)} + } + | query tokOrOp query + { + $$ = &Query{Left: $1.(*Query), Op: OpOr, Right: $3.(*Query)} + } + | query tokAndOp query + { + $$ = &Query{Left: $1.(*Query), Op: OpAnd, Right: $3.(*Query)} + } + | query tokCompareOp query + { + $$ = &Query{Left: $1.(*Query), Op: $2, Right: $3.(*Query)} + } + | query '+' query + { + $$ = &Query{Left: $1.(*Query), Op: OpAdd, Right: $3.(*Query)} + } + | query '-' query + { + $$ = &Query{Left: $1.(*Query), Op: OpSub, Right: $3.(*Query)} + } + | query '*' query + { + $$ = &Query{Left: $1.(*Query), Op: OpMul, Right: $3.(*Query)} + } + | query '/' query + { + $$ = &Query{Left: $1.(*Query), Op: OpDiv, Right: $3.(*Query)} + } + | query '%' query + { + $$ = &Query{Left: $1.(*Query), Op: OpMod, Right: $3.(*Query)} + } + | term %prec tokTermPost + { + $$ = &Query{Term: $1.(*Term)} + } + +bindpatterns + : pattern + { + $$ = []*Pattern{$1.(*Pattern)} + } + | bindpatterns tokDestAltOp pattern + { + $$ = append($1.([]*Pattern), $3.(*Pattern)) + } + +pattern + : tokVariable + { + $$ = &Pattern{Name: $1} + } + | '[' arraypatterns ']' + { + $$ = &Pattern{Array: $2.([]*Pattern)} + } + | '{' objectpatterns '}' + { + $$ = &Pattern{Object: $2.([]*PatternObject)} + } + +arraypatterns + : pattern + { + $$ = []*Pattern{$1.(*Pattern)} + } + | arraypatterns ',' pattern + { + $$ = append($1.([]*Pattern), $3.(*Pattern)) + } + +objectpatterns + : objectpattern + { + $$ = []*PatternObject{$1.(*PatternObject)} + } + | objectpatterns ',' objectpattern + { + $$ = append($1.([]*PatternObject), $3.(*PatternObject)) + } + +objectpattern + : objectkey ':' pattern + { + $$ = &PatternObject{Key: $1, Val: $3.(*Pattern)} + } + | string ':' pattern + { + $$ = &PatternObject{KeyString: $1.(*String), Val: $3.(*Pattern)} + } + | '(' query ')' ':' pattern + { + $$ = &PatternObject{KeyQuery: $2.(*Query), Val: $5.(*Pattern)} + } + | tokVariable + { + $$ = &PatternObject{KeyOnly: $1} + } + +term + : '.' + { + $$ = &Term{Type: TermTypeIdentity} + } + | tokRecurse + { + $$ = &Term{Type: TermTypeRecurse} + } + | tokIndex + { + $$ = &Term{Type: TermTypeIndex, Index: &Index{Name: $1}} + } + | '.' suffix + { + if $2.(*Suffix).Iter { + $$ = &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{$2.(*Suffix)}} + } else { + $$ = &Term{Type: TermTypeIndex, Index: $2.(*Suffix).Index} + } + } + | '.' string + { + $$ = &Term{Type: TermTypeIndex, Index: &Index{Str: $2.(*String)}} + } + | tokNull + { + $$ = &Term{Type: TermTypeNull} + } + | tokTrue + { + $$ = &Term{Type: TermTypeTrue} + } + | tokFalse + { + $$ = &Term{Type: TermTypeFalse} + } + | tokIdentModuleIdent + { + $$ = &Term{Type: TermTypeFunc, Func: &Func{Name: $1}} + } + | tokIdentModuleIdent '(' args ')' + { + $$ = &Term{Type: TermTypeFunc, Func: &Func{Name: $1, Args: $3.([]*Query)}} + } + | tokVariableModuleVariable + { + $$ = &Term{Type: TermTypeFunc, Func: &Func{Name: $1}} + } + | tokNumber + { + $$ = &Term{Type: TermTypeNumber, Number: $1} + } + | tokFormat + { + $$ = &Term{Type: TermTypeFormat, Format: $1} + } + | tokFormat string + { + $$ = &Term{Type: TermTypeFormat, Format: $1, Str: $2.(*String)} + } + | string + { + $$ = &Term{Type: TermTypeString, Str: $1.(*String)} + } + | '(' query ')' + { + $$ = &Term{Type: TermTypeQuery, Query: $2.(*Query)} + } + | '-' term + { + $$ = &Term{Type: TermTypeUnary, Unary: &Unary{OpSub, $2.(*Term)}} + } + | '+' term + { + $$ = &Term{Type: TermTypeUnary, Unary: &Unary{OpAdd, $2.(*Term)}} + } + | '{' object '}' + { + $$ = &Term{Type: TermTypeObject, Object: &Object{$2.([]*ObjectKeyVal)}} + } + | '[' query ']' + { + $$ = &Term{Type: TermTypeArray, Array: &Array{$2.(*Query)}} + } + | '[' ']' + { + $$ = &Term{Type: TermTypeArray, Array: &Array{}} + } + | tokBreak tokVariable + { + $$ = &Term{Type: TermTypeBreak, Break: $2} + } + | term tokIndex + { + $1.(*Term).SuffixList = append($1.(*Term).SuffixList, &Suffix{Index: &Index{Name: $2}}) + } + | term suffix + { + $1.(*Term).SuffixList = append($1.(*Term).SuffixList, $2.(*Suffix)) + } + | term '?' + { + $1.(*Term).SuffixList = append($1.(*Term).SuffixList, &Suffix{Optional: true}) + } + | term '.' suffix + { + $1.(*Term).SuffixList = append($1.(*Term).SuffixList, $3.(*Suffix)) + } + | term '.' string + { + $1.(*Term).SuffixList = append($1.(*Term).SuffixList, &Suffix{Index: &Index{Str: $3.(*String)}}) + } + +string + : tokString + { + $$ = &String{Str: $1} + } + | tokStringStart stringparts tokStringEnd + { + $$ = &String{Queries: $2.([]*Query)} + } + +stringparts + : + { + $$ = []*Query{} + } + | stringparts tokString + { + $$ = append($1.([]*Query), &Query{Term: &Term{Type: TermTypeString, Str: &String{Str: $2}}}) + } + | stringparts tokStringQuery query ')' + { + yylex.(*lexer).inString = true + $$ = append($1.([]*Query), &Query{Term: &Term{Type: TermTypeQuery, Query: $3.(*Query)}}) + } + +tokIdentModuleIdent + : tokIdent {} + | tokModuleIdent {} + +tokVariableModuleVariable + : tokVariable {} + | tokModuleVariable {} + +suffix + : '[' ']' + { + $$ = &Suffix{Iter: true} + } + | '[' query ']' + { + $$ = &Suffix{Index: &Index{Start: $2.(*Query)}} + } + | '[' query ':' ']' + { + $$ = &Suffix{Index: &Index{Start: $2.(*Query), IsSlice: true}} + } + | '[' ':' query ']' + { + $$ = &Suffix{Index: &Index{End: $3.(*Query)}} + } + | '[' query ':' query ']' + { + $$ = &Suffix{Index: &Index{Start: $2.(*Query), IsSlice: true, End: $4.(*Query)}} + } + +args + : query + { + $$ = []*Query{$1.(*Query)} + } + | args ';' query + { + $$ = append($1.([]*Query), $3.(*Query)) + } + +ifelifs + : + { + $$ = []*IfElif(nil) + } + | tokElif query tokThen query ifelifs + { + $$ = prependIfElif($5.([]*IfElif), &IfElif{$2.(*Query), $4.(*Query)}) + } + +ifelse + : + { + $$ = (*Query)(nil) + } + | tokElse query + { + $$ = $2 + } + +trycatch + : %prec tokEmptyCatch + { + $$ = (*Query)(nil) + } + | tokCatch query + { + $$ = $2 + } + +object + : + { + $$ = []*ObjectKeyVal(nil) + } + | objectkeyval + { + $$ = []*ObjectKeyVal{$1.(*ObjectKeyVal)} + } + | objectkeyval ',' object + { + $$ = prependObjectKeyVal($3.([]*ObjectKeyVal), $1.(*ObjectKeyVal)) + } + +objectkeyval + : objectkey ':' objectval + { + $$ = &ObjectKeyVal{Key: $1, Val: $3.(*ObjectVal)} + } + | string ':' objectval + { + $$ = &ObjectKeyVal{KeyString: $1.(*String), Val: $3.(*ObjectVal)} + } + | '(' query ')' ':' objectval + { + $$ = &ObjectKeyVal{KeyQuery: $2.(*Query), Val: $5.(*ObjectVal)} + } + | objectkey + { + $$ = &ObjectKeyVal{KeyOnly: $1} + } + | string + { + $$ = &ObjectKeyVal{KeyOnlyString: $1.(*String)} + } + +objectkey + : tokIdent {} + | tokVariable {} + | tokKeyword {} + +objectval + : term + { + $$ = &ObjectVal{[]*Query{{Term: $1.(*Term)}}} + } + | term '|' objectval + { + $$ = &ObjectVal{prependQuery($3.(*ObjectVal).Queries, &Query{Term: $1.(*Term)})} + } + +constterm + : constobject + { + $$ = &ConstTerm{Object: $1.(*ConstObject)} + } + | constarray + { + $$ = &ConstTerm{Array: $1.(*ConstArray)} + } + | tokNumber + { + $$ = &ConstTerm{Number: $1} + } + | tokString + { + $$ = &ConstTerm{Str: $1} + } + | tokNull + { + $$ = &ConstTerm{Null: true} + } + | tokTrue + { + $$ = &ConstTerm{True: true} + } + | tokFalse + { + $$ = &ConstTerm{False: true} + } + +constobject + : '{' constobjectkeyvals '}' + { + $$ = &ConstObject{$2.([]*ConstObjectKeyVal)} + } + +constobjectkeyvals + : + { + $$ = []*ConstObjectKeyVal(nil) + } + | constobjectkeyval + { + $$ = []*ConstObjectKeyVal{$1.(*ConstObjectKeyVal)} + } + | constobjectkeyval ',' constobjectkeyvals + { + $$ = prependConstObjectKeyVal($3.([]*ConstObjectKeyVal), $1.(*ConstObjectKeyVal)) + } + +constobjectkeyval + : tokIdent ':' constterm + { + $$ = &ConstObjectKeyVal{Key: $1, Val: $3.(*ConstTerm)} + } + | tokKeyword ':' constterm + { + $$ = &ConstObjectKeyVal{Key: $1, Val: $3.(*ConstTerm)} + } + | tokString ':' constterm + { + $$ = &ConstObjectKeyVal{KeyString: $1, Val: $3.(*ConstTerm)} + } + +constarray + : '[' ']' + { + $$ = &ConstArray{} + } + | '[' constarrayelems ']' + { + $$ = &ConstArray{$2.([]*ConstTerm)} + } + +constarrayelems + : constterm + { + $$ = []*ConstTerm{$1.(*ConstTerm)} + } + | constarrayelems ',' constterm + { + $$ = append($1.([]*ConstTerm), $3.(*ConstTerm)) + } + +tokKeyword + : tokOrOp {} + | tokAndOp {} + | tokModule {} + | tokImport {} + | tokInclude {} + | tokDef {} + | tokAs {} + | tokLabel {} + | tokBreak {} + | tokNull {} + | tokTrue {} + | tokFalse {} + | tokIf {} + | tokThen {} + | tokElif {} + | tokElse {} + | tokEnd {} + | tokTry {} + | tokCatch {} + | tokReduce {} + | tokForeach {} + +%% diff --git a/vendor/github.com/itchyny/gojq/prepend.go b/vendor/github.com/itchyny/gojq/prepend.go new file mode 100644 index 00000000..6b57bbf8 --- /dev/null +++ b/vendor/github.com/itchyny/gojq/prepend.go @@ -0,0 +1,43 @@ +package gojq + +func prependQuery(xs []*Query, x *Query) []*Query { + xs = append(xs, nil) + copy(xs[1:], xs) + xs[0] = x + return xs +} + +func prependImport(xs []*Import, x *Import) []*Import { + xs = append(xs, nil) + copy(xs[1:], xs) + xs[0] = x + return xs +} + +func prependFuncDef(xs []*FuncDef, x *FuncDef) []*FuncDef { + xs = append(xs, nil) + copy(xs[1:], xs) + xs[0] = x + return xs +} + +func prependIfElif(xs []*IfElif, x *IfElif) []*IfElif { + xs = append(xs, nil) + copy(xs[1:], xs) + xs[0] = x + return xs +} + +func prependObjectKeyVal(xs []*ObjectKeyVal, x *ObjectKeyVal) []*ObjectKeyVal { + xs = append(xs, nil) + copy(xs[1:], xs) + xs[0] = x + return xs +} + +func prependConstObjectKeyVal(xs []*ConstObjectKeyVal, x *ConstObjectKeyVal) []*ConstObjectKeyVal { + xs = append(xs, nil) + copy(xs[1:], xs) + xs[0] = x + return xs +} diff --git a/vendor/github.com/itchyny/gojq/query.go b/vendor/github.com/itchyny/gojq/query.go index 512d6090..22f16a10 100644 --- a/vendor/github.com/itchyny/gojq/query.go +++ b/vendor/github.com/itchyny/gojq/query.go @@ -8,110 +8,16 @@ import ( "strings" ) -// Module ... -type Module struct { - Meta *ConstObject `( "module" @@ ";" )?` - Imports []*Import `@@*` - FuncDefs []*FuncDef `@@*` -} - -func (e *Module) String() string { - var s strings.Builder - if e.Meta != nil { - fmt.Fprintf(&s, "module %s;\n", e.Meta) - } - for _, i := range e.Imports { - fmt.Fprint(&s, i) - } - for i, fd := range e.FuncDefs { - if i > 0 { - s.WriteByte(' ') - } - fmt.Fprint(&s, fd) - } - return s.String() -} - -// Import ... -type Import struct { - ImportPath string `( "import" @String` - ImportAlias string ` "as" ( @Ident | @Variable )` - IncludePath string `| "include" @String )` - Meta *ConstObject `@@? ";"` -} - -func (e *Import) String() string { - var s strings.Builder - if e.ImportPath != "" { - s.WriteString("import ") - s.WriteString(e.ImportPath) - s.WriteString(" as ") - s.WriteString(e.ImportAlias) - } else { - s.WriteString("include ") - s.WriteString(e.IncludePath) - } - if e.Meta != nil { - fmt.Fprintf(&s, " %s", e.Meta) - } - s.WriteString(";\n") - return s.String() -} - -// FuncDef ... -type FuncDef struct { - Name string `"def" @Ident` - Args []string `("(" ( @Ident | @Variable ) (";" ( @Ident | @Variable ))* ")")? ":"` - Body *Query `@@ ";"` -} - -func (e *FuncDef) String() string { - var s strings.Builder - fmt.Fprintf(&s, "def %s", e.Name) - if len(e.Args) > 0 { - s.WriteByte('(') - for i, e := range e.Args { - if i > 0 { - s.WriteString("; ") - } - fmt.Fprint(&s, e) - } - s.WriteByte(')') - } - fmt.Fprintf(&s, ": %s;", e.Body) - return s.String() -} - // Query ... type Query struct { - Imports []*Import `@@*` - Commas []*Comma `@@ ("|" @@)*` -} - -func (e *Query) String() string { - var s strings.Builder - for _, i := range e.Imports { - fmt.Fprint(&s, i) - } - for i, e := range e.Commas { - if i > 0 { - s.WriteString(" | ") - } - fmt.Fprint(&s, e) - } - return s.String() -} - -func (e *Query) toIndices() []interface{} { - var xs []interface{} - for _, e := range e.Commas { - x := e.toIndices() - if x == nil { - return nil - } - xs = append(xs, x...) - } - return xs + Meta *ConstObject + Imports []*Import + FuncDefs []*FuncDef + Term *Term + Left *Query + Op Operator + Right *Query + Func string } // Run query. @@ -128,446 +34,186 @@ func (e *Query) RunWithContext(ctx context.Context, v interface{}) Iter { return code.RunWithContext(ctx, v) } -// Comma ... -type Comma struct { - Filters []*Filter `@@ ("," @@)*` -} - -func (e *Comma) String() string { +func (e *Query) String() string { var s strings.Builder - for i, e := range e.Filters { - if i > 0 { - s.WriteString(", ") - } - fmt.Fprint(&s, e) + if e.Meta != nil { + fmt.Fprintf(&s, "module %s;\n", e.Meta) } - return s.String() -} - -func (e *Comma) toQuery() *Query { - return &Query{Commas: []*Comma{e}} -} - -func (e *Comma) toIndices() []interface{} { - if len(e.Filters) != 1 { - return nil + for _, im := range e.Imports { + fmt.Fprint(&s, im) } - return e.Filters[0].toIndices() -} - -// Filter ... -type Filter struct { - FuncDefs []*FuncDef `@@*` - Alt *Alt `@@` -} - -func (e *Filter) String() string { - var s strings.Builder for i, fd := range e.FuncDefs { if i > 0 { s.WriteByte(' ') } fmt.Fprint(&s, fd) } - if e.Alt != nil { - if len(e.FuncDefs) > 0 { - s.WriteByte(' ') - } - fmt.Fprint(&s, e.Alt) + if len(e.FuncDefs) > 0 { + s.WriteByte(' ') } - return s.String() -} - -func (e *Filter) toQuery() *Query { - return (&Comma{[]*Filter{e}}).toQuery() -} - -func (e *Filter) toIndices() []interface{} { - if len(e.FuncDefs) != 0 { - return nil - } - return e.Alt.toIndices() -} - -// Alt ... -type Alt struct { - Left *Expr `@@` - Right []AltRight `@@*` -} - -func (e *Alt) String() string { - var s strings.Builder - fmt.Fprint(&s, e.Left) - for _, e := range e.Right { - fmt.Fprint(&s, e) - } - return s.String() -} - -func (e *Alt) toQuery() *Query { - return (&Filter{Alt: e}).toQuery() -} - -func (e *Alt) toFilter() *Filter { - return &Filter{Alt: e} -} - -func (e *Alt) toIndices() []interface{} { - if len(e.Right) != 0 { - return nil - } - return e.Left.toIndices() -} - -// AltRight ... -type AltRight struct { - Op Operator `@"//"` - Right *Expr `@@` -} - -func (e AltRight) String() string { - return fmt.Sprintf(" %s %s", e.Op, e.Right) -} - -// Expr ... -type Expr struct { - Logic *Logic `@@` - UpdateOp Operator `( ( @UpdateOp | @UpdateAltOp )` - Update *Alt ` @@` - Bind *Bind `| @@ )?` - Label *Label `| @@` -} - -func (e *Expr) toQuery() *Query { - return (&Alt{Left: e}).toQuery() -} - -func (e *Expr) toFilter() *Filter { - return (&Alt{Left: e}).toFilter() -} - -func (e *Expr) String() string { - var s strings.Builder - if e.Logic != nil { - fmt.Fprint(&s, e.Logic) - } - if e.Update != nil { - fmt.Fprintf(&s, " %s %s", e.UpdateOp, e.Update) - } else if e.Bind != nil { - fmt.Fprint(&s, e.Bind) - } else if e.Label != nil { - fmt.Fprint(&s, e.Label) + if e.Func != "" { + s.WriteString(e.Func) + } else if e.Term != nil { + fmt.Fprint(&s, e.Term) + } else if e.Right != nil { + if e.Op == OpComma { + fmt.Fprintf(&s, "%s, %s", e.Left, e.Right) + } else { + fmt.Fprintf(&s, "%s %s %s", e.Left, e.Op, e.Right) + } } return s.String() } -func (e *Expr) toIndices() []interface{} { - if e.Update != nil || e.Bind != nil || e.Logic == nil { - return nil +func (e *Query) minify() { + for _, e := range e.FuncDefs { + e.Minify() } - return e.Logic.toIndices() -} - -// Bind ... -type Bind struct { - Patterns []*Pattern `"as" @@ ("?//" @@)*` - Body *Query `"|" @@` -} - -func (e *Bind) String() string { - var s strings.Builder - for i, p := range e.Patterns { - if i == 0 { - fmt.Fprintf(&s, " as %s ", p) + if e.Term != nil { + if name := e.Term.toFunc(); name != "" { + e.Term = nil + e.Func = name } else { - fmt.Fprintf(&s, "?// %s ", p) + e.Term.minify() } + } else if e.Right != nil { + e.Left.minify() + e.Right.minify() } - fmt.Fprintf(&s, "| %s ", e.Body) - return s.String() } -// Logic ... -type Logic struct { - Left *AndExpr `@@` - Right []LogicRight `@@*` -} - -func (e *Logic) String() string { - var s strings.Builder - fmt.Fprint(&s, e.Left) - for _, e := range e.Right { - fmt.Fprint(&s, e) - } - return s.String() -} - -func (e *Logic) toQuery() *Query { - return (&Expr{Logic: e}).toQuery() -} - -func (e *Logic) toFilter() *Filter { - return (&Expr{Logic: e}).toFilter() -} - -func (e *Logic) toIndices() []interface{} { - if len(e.Right) != 0 { +func (e *Query) toIndices() []interface{} { + if e.FuncDefs != nil || e.Right != nil || e.Term == nil { return nil } - return e.Left.toIndices() -} - -// LogicRight ... -type LogicRight struct { - Op Operator `@"or"` - Right *AndExpr `@@` -} - -func (e LogicRight) String() string { - return fmt.Sprintf(" %s %s", e.Op, e.Right) -} - -// AndExpr ... -type AndExpr struct { - Left *Compare `@@` - Right []AndExprRight `@@*` -} - -func (e *AndExpr) String() string { - var s strings.Builder - fmt.Fprint(&s, e.Left) - for _, e := range e.Right { - fmt.Fprint(&s, e) - } - return s.String() + return e.Term.toIndices() } -func (e *AndExpr) toQuery() *Query { - return (&Logic{Left: e}).toQuery() -} - -func (e *AndExpr) toFilter() *Filter { - return (&Logic{Left: e}).toFilter() -} - -func (e *AndExpr) toLogic() *Logic { - return &Logic{Left: e} -} - -func (e *AndExpr) toIndices() []interface{} { - if len(e.Right) != 0 { - return nil +func (e *Query) countCommaQueries() int { + if e.Op == OpComma { + return e.Left.countCommaQueries() + e.Right.countCommaQueries() } - return e.Left.toIndices() + return 1 } -// AndExprRight ... -type AndExprRight struct { - Op Operator `@"and"` - Right *Compare `@@` -} - -func (e AndExprRight) String() string { - return fmt.Sprintf(" %s %s", e.Op, e.Right) -} - -// Compare ... -type Compare struct { - Left *Arith `@@` - Right *CompareRight `@@?` -} - -func (e *Compare) toQuery() *Query { - return (&AndExpr{Left: e}).toQuery() -} - -func (e *Compare) toFilter() *Filter { - return (&AndExpr{Left: e}).toFilter() -} - -func (e *Compare) toLogic() *Logic { - return (&AndExpr{Left: e}).toLogic() +// Import ... +type Import struct { + ImportPath string + ImportAlias string + IncludePath string + Meta *ConstObject } -func (e *Compare) String() string { +func (e *Import) String() string { var s strings.Builder - fmt.Fprint(&s, e.Left) - if e.Right != nil { - fmt.Fprint(&s, e.Right) - } - return s.String() -} - -func (e *Compare) toIndices() []interface{} { - if e.Right != nil { - return nil + if e.ImportPath != "" { + fmt.Fprintf(&s, "import %q as %s", e.ImportPath, e.ImportAlias) + } else { + fmt.Fprintf(&s, "include %q", e.IncludePath) } - return e.Left.toIndices() -} - -// CompareRight ... -type CompareRight struct { - Op Operator `@CompareOp` - Right *Arith `@@` -} - -func (e *CompareRight) String() string { - return fmt.Sprintf(" %s %s", e.Op, e.Right) -} - -// Arith ... -type Arith struct { - Left *Factor `@@` - Right []ArithRight `@@*` -} - -func (e *Arith) String() string { - var s strings.Builder - fmt.Fprint(&s, e.Left) - for _, e := range e.Right { - fmt.Fprint(&s, e) + if e.Meta != nil { + fmt.Fprintf(&s, " %s", e.Meta) } + s.WriteString(";\n") return s.String() } -func (e *Arith) toQuery() *Query { - return (&Compare{Left: e}).toQuery() -} - -func (e *Arith) toFilter() *Filter { - return (&Compare{Left: e}).toFilter() -} - -func (e *Arith) toLogic() *Logic { - return (&Compare{Left: e}).toLogic() -} - -func (e *Arith) toIndices() []interface{} { - if len(e.Right) != 0 { - return nil - } - return e.Left.toIndices() -} - -// ArithRight ... -type ArithRight struct { - Op Operator `@("+" | "-")` - Right *Factor `@@` -} - -func (e ArithRight) String() string { - return fmt.Sprintf(" %s %s", e.Op, e.Right) -} - -// Factor ... -type Factor struct { - Left *Term `@@` - Right []FactorRight `@@*` +// FuncDef ... +type FuncDef struct { + Name string + Args []string + Body *Query } -func (e *Factor) String() string { +func (e *FuncDef) String() string { var s strings.Builder - fmt.Fprint(&s, e.Left) - for _, e := range e.Right { - fmt.Fprint(&s, e) + fmt.Fprintf(&s, "def %s", e.Name) + if len(e.Args) > 0 { + s.WriteByte('(') + for i, e := range e.Args { + if i > 0 { + s.WriteString("; ") + } + fmt.Fprint(&s, e) + } + s.WriteByte(')') } + fmt.Fprintf(&s, ": %s;", e.Body) return s.String() } -func (e *Factor) toQuery() *Query { - return (&Arith{Left: e}).toQuery() -} - -func (e *Factor) toFilter() *Filter { - return (&Arith{Left: e}).toFilter() -} - -func (e *Factor) toLogic() *Logic { - return (&Arith{Left: e}).toLogic() -} - -func (e *Factor) toIndices() []interface{} { - if len(e.Right) != 0 { - return nil - } - return e.Left.toIndices() -} - -// FactorRight ... -type FactorRight struct { - Op Operator `@("*" | "/" | "%")` - Right *Term `@@` -} - -func (e FactorRight) String() string { - return fmt.Sprintf(" %s %s", e.Op, e.Right) +// Minify ... +func (e *FuncDef) Minify() { + e.Body.minify() } // Term ... type Term struct { - Index *Index `( @@` - Identity bool `| @"."` - Recurse bool `| @".."` - Null bool `| @"null"` - True bool `| @"true"` - False bool `| @"false"` - Func *Func `| @@` - Object *Object `| @@` - Array *Array `| @@` - Number string `| @Number` - Unary *Unary `| @@` - Format string `| ( @Format` - FormatStr string ` @String? )` - Str string `| @String` - RawStr string `| @" "` // never matches, used in compiler - If *If `| @@` - Try *Try `| @@` - Reduce *Reduce `| @@` - Foreach *Foreach `| @@` - Break string `| "break" @Variable` - Query *Query `| "(" @@ ")" )` - SuffixList []*Suffix `@@*` + Type TermType + Index *Index + Func *Func + Object *Object + Array *Array + Number string + Unary *Unary + Format string + Str *String + If *If + Try *Try + Reduce *Reduce + Foreach *Foreach + Label *Label + Break string + Query *Query + SuffixList []*Suffix } func (e *Term) String() string { var s strings.Builder - if e.Index != nil { - fmt.Fprint(&s, e.Index) - } else if e.Identity { + switch e.Type { + case TermTypeIdentity: s.WriteString(".") - } else if e.Recurse { + case TermTypeRecurse: s.WriteString("..") - } else if e.Null { + case TermTypeNull: s.WriteString("null") - } else if e.True { + case TermTypeTrue: s.WriteString("true") - } else if e.False { + case TermTypeFalse: s.WriteString("false") - } else if e.Func != nil { + case TermTypeIndex: + fmt.Fprint(&s, e.Index) + case TermTypeFunc: fmt.Fprint(&s, e.Func) - } else if e.Object != nil { + case TermTypeObject: fmt.Fprint(&s, e.Object) - } else if e.Array != nil { + case TermTypeArray: fmt.Fprint(&s, e.Array) - } else if e.Number != "" { + case TermTypeNumber: fmt.Fprint(&s, e.Number) - } else if e.Unary != nil { + case TermTypeUnary: fmt.Fprint(&s, e.Unary) - } else if e.Str != "" { + case TermTypeFormat: + if e.Str == nil { + s.WriteString(e.Format) + } else { + fmt.Fprintf(&s, "%s %s", e.Format, e.Str) + } + case TermTypeString: fmt.Fprint(&s, e.Str) - } else if e.RawStr != "" { - fmt.Fprint(&s, strconv.Quote(e.RawStr)) - } else if e.If != nil { + case TermTypeIf: fmt.Fprint(&s, e.If) - } else if e.Try != nil { + case TermTypeTry: fmt.Fprint(&s, e.Try) - } else if e.Reduce != nil { + case TermTypeReduce: fmt.Fprint(&s, e.Reduce) - } else if e.Foreach != nil { + case TermTypeForeach: fmt.Fprint(&s, e.Foreach) - } else if e.Break != "" { + case TermTypeLabel: + fmt.Fprint(&s, e.Label) + case TermTypeBreak: fmt.Fprintf(&s, "break %s", e.Break) - } else if e.Query != nil { + case TermTypeQuery: fmt.Fprintf(&s, "(%s)", e.Query) } for _, e := range e.SuffixList { @@ -576,16 +222,63 @@ func (e *Term) String() string { return s.String() } -func (e *Term) toQuery() *Query { - return (&Factor{Left: e}).toQuery() -} - -func (e *Term) toFilter() *Filter { - return (&Factor{Left: e}).toFilter() +func (e *Term) minify() { + switch e.Type { + case TermTypeIndex: + e.Index.minify() + case TermTypeFunc: + e.Func.minify() + case TermTypeObject: + e.Object.minify() + case TermTypeArray: + e.Array.minify() + case TermTypeUnary: + e.Unary.minify() + case TermTypeFormat: + if e.Str != nil { + e.Str.minify() + } + case TermTypeString: + e.Str.minify() + case TermTypeIf: + e.If.minify() + case TermTypeTry: + e.Try.minify() + case TermTypeReduce: + e.Reduce.minify() + case TermTypeForeach: + e.Foreach.minify() + case TermTypeLabel: + e.Label.minify() + case TermTypeQuery: + e.Query.minify() + } + for _, e := range e.SuffixList { + e.minify() + } } -func (e *Term) toLogic() *Logic { - return (&Factor{Left: e}).toLogic() +func (e *Term) toFunc() string { + if len(e.SuffixList) != 0 { + return "" + } + // ref: compiler#compileQuery + switch e.Type { + case TermTypeIdentity: + return "." + case TermTypeRecurse: + return ".." + case TermTypeNull: + return "null" + case TermTypeTrue: + return "true" + case TermTypeFalse: + return "false" + case TermTypeFunc: + return e.Func.toFunc() + default: + return "" + } } func (e *Term) toIndices() []interface{} { @@ -611,19 +304,23 @@ func (e *Term) toIndices() []interface{} { // Unary ... type Unary struct { - Op Operator `@("+" | "-")` - Term *Term `@@` + Op Operator + Term *Term } func (e *Unary) String() string { return fmt.Sprintf("%s%s", e.Op, e.Term) } +func (e *Unary) minify() { + e.Term.minify() +} + // Pattern ... type Pattern struct { - Name string ` @Variable` - Array []*Pattern `| "[" @@ ("," @@)* "]"` - Object []PatternObject `| "{" @@ ("," @@)* "}"` + Name string + Array []*Pattern + Object []*PatternObject } func (e *Pattern) String() string { @@ -645,7 +342,7 @@ func (e *Pattern) String() string { if i > 0 { s.WriteString(", ") } - fmt.Fprint(&s, &e) + fmt.Fprint(&s, e) } s.WriteRune('}') } @@ -654,21 +351,21 @@ func (e *Pattern) String() string { // PatternObject ... type PatternObject struct { - Key string `( ( @Ident | @Variable | @Keyword )` - KeyString string ` | @String` - Query *Query ` | "(" @@ ")" ) ":"` - Val *Pattern `@@` - KeyOnly string `| @Variable` + Key string + KeyString *String + KeyQuery *Query + Val *Pattern + KeyOnly string } func (e *PatternObject) String() string { var s strings.Builder if e.Key != "" { s.WriteString(e.Key) - } else if e.KeyString != "" { - s.WriteString(e.KeyString) - } else if e.Query != nil { - fmt.Fprintf(&s, "(%s)", e.Query) + } else if e.KeyString != nil { + fmt.Fprint(&s, e.KeyString) + } else if e.KeyQuery != nil { + fmt.Fprintf(&s, "(%s)", e.KeyQuery) } if e.Val != nil { s.WriteString(": ") @@ -682,21 +379,21 @@ func (e *PatternObject) String() string { // Index ... type Index struct { - Name string `@Index` - Str string `| "." ( @String` - Start *Query `| "[" ( @@` - IsSlice bool `( @":"` - End *Query `@@? )? | ":" @@ ) "]" )` + Name string + Str *String + Start *Query + IsSlice bool + End *Query } func (e *Index) String() string { var s strings.Builder + s.WriteByte('.') if e.Name != "" { s.WriteString(e.Name) } else { - s.WriteByte('.') - if e.Str != "" { - s.WriteString(e.Str) + if e.Str != nil { + fmt.Fprint(&s, e.Str) } else { s.WriteByte('[') if e.Start != nil { @@ -717,17 +414,26 @@ func (e *Index) String() string { return s.String() } +func (e *Index) minify() { + if e.Start != nil { + e.Start.minify() + } + if e.End != nil { + e.End.minify() + } +} + func (e *Index) toIndices() []interface{} { if e.Name == "" { return nil } - return []interface{}{e.Name[1:]} + return []interface{}{e.Name} } // Func ... type Func struct { - Name string `( @Ident | @Variable | @ModuleIdent )` - Args []*Query `( "(" @@ (";" @@)* ")" )?` + Name string + Args []*Query } func (e *Func) String() string { @@ -746,9 +452,52 @@ func (e *Func) String() string { return s.String() } +func (e *Func) minify() { + for _, x := range e.Args { + x.minify() + } +} + +func (e *Func) toFunc() string { + if len(e.Args) != 0 { + return "" + } + return e.Name +} + +// String ... +type String struct { + Str string + Queries []*Query +} + +func (e *String) String() string { + if e.Queries == nil { + return strconv.Quote(e.Str) + } + var s strings.Builder + s.WriteRune('"') + for _, e := range e.Queries { + if e.Term.Str == nil { + fmt.Fprintf(&s, "\\%s", e) + } else { + es := e.String() + fmt.Fprint(&s, es[1:len(es)-1]) + } + } + s.WriteRune('"') + return s.String() +} + +func (e *String) minify() { + for _, e := range e.Queries { + e.minify() + } +} + // Object ... type Object struct { - KeyVals []ObjectKeyVal `"{" (@@ ("," @@)*)? "}"` + KeyVals []*ObjectKeyVal } func (e *Object) String() string { @@ -761,51 +510,65 @@ func (e *Object) String() string { if i > 0 { s.WriteString(", ") } - fmt.Fprint(&s, &kv) + fmt.Fprint(&s, kv) } s.WriteString(" }") return s.String() } +func (e *Object) minify() { + for _, e := range e.KeyVals { + e.minify() + } +} + // ObjectKeyVal ... type ObjectKeyVal struct { - Key string `( ( ( @Ident | @Variable | @Keyword )` - KeyString string ` | @String )` - Query *Query `| "(" @@ ")" ) ":"` - Val *ObjectVal `@@` - KeyOnly *string `| @Ident | @Variable` - KeyOnlyString string `| @String` + Key string + KeyString *String + KeyQuery *Query + Val *ObjectVal + KeyOnly string + KeyOnlyString *String } func (e *ObjectKeyVal) String() string { var s strings.Builder if e.Key != "" { s.WriteString(e.Key) - } else if e.KeyString != "" { - s.WriteString(e.KeyString) - } else if e.Query != nil { - fmt.Fprintf(&s, "(%s)", e.Query) + } else if e.KeyString != nil { + fmt.Fprint(&s, e.KeyString) + } else if e.KeyQuery != nil { + fmt.Fprintf(&s, "(%s)", e.KeyQuery) } if e.Val != nil { fmt.Fprintf(&s, ": %s", e.Val) } - if e.KeyOnly != nil { - s.WriteString(*e.KeyOnly) - } - if e.KeyOnlyString != "" { - s.WriteString(e.KeyOnlyString) + if e.KeyOnly != "" { + s.WriteString(e.KeyOnly) + } else if e.KeyOnlyString != nil { + fmt.Fprint(&s, e.KeyOnlyString) } return s.String() } +func (e *ObjectKeyVal) minify() { + if e.KeyQuery != nil { + e.KeyQuery.minify() + } + if e.Val != nil { + e.Val.minify() + } +} + // ObjectVal ... type ObjectVal struct { - Alts []*Alt `@@ ("|" @@)*` + Queries []*Query } func (e *ObjectVal) String() string { var s strings.Builder - for i, e := range e.Alts { + for i, e := range e.Queries { if i > 0 { s.WriteString(" | ") } @@ -814,9 +577,15 @@ func (e *ObjectVal) String() string { return s.String() } +func (e *ObjectVal) minify() { + for _, e := range e.Queries { + e.minify() + } +} + // Array ... type Array struct { - Query *Query `"[" @@? "]"` + Query *Query } func (e *Array) String() string { @@ -826,35 +595,51 @@ func (e *Array) String() string { return fmt.Sprintf("[%s]", e.Query) } +func (e *Array) minify() { + if e.Query != nil { + e.Query.minify() + } +} + // Suffix ... type Suffix struct { - Index *Index ` @@` - SuffixIndex *SuffixIndex `| @@` - Iter bool `| @("[" "]")` - Optional bool `| @"?"` + Index *Index + Iter bool + Optional bool + Bind *Bind } func (e *Suffix) String() string { var s strings.Builder if e.Index != nil { - fmt.Fprint(&s, e.Index) - } else if e.SuffixIndex != nil { - fmt.Fprint(&s, e.SuffixIndex) + if e.Index.Name != "" || e.Index.Str != nil { + fmt.Fprint(&s, e.Index) + } else { + s.WriteString(e.Index.String()[1:]) + } } else if e.Iter { s.WriteString("[]") } else if e.Optional { s.WriteString("?") + } else if e.Bind != nil { + fmt.Fprint(&s, e.Bind) } return s.String() } +func (e *Suffix) minify() { + if e.Index != nil { + e.Index.minify() + } else if e.Bind != nil { + e.Bind.minify() + } +} + func (e *Suffix) toTerm() (*Term, bool) { if e.Index != nil { - return &Term{Index: e.Index}, true - } else if e.SuffixIndex != nil { - return &Term{Index: e.SuffixIndex.toIndex()}, true + return &Term{Type: TermTypeIndex, Index: e.Index}, true } else if e.Iter { - return &Term{Identity: true, SuffixList: []*Suffix{{Iter: true}}}, true + return &Term{Type: TermTypeIdentity, SuffixList: []*Suffix{{Iter: true}}}, true } else { return nil, false } @@ -867,38 +652,42 @@ func (e *Suffix) toIndices() []interface{} { return e.Index.toIndices() } -// SuffixIndex ... -type SuffixIndex struct { - Start *Query `"[" ( @@` - IsSlice bool `( @":"` - End *Query `@@? )? | ":" @@ ) "]"` +// Bind ... +type Bind struct { + Patterns []*Pattern + Body *Query } -func (e *SuffixIndex) String() string { - return e.toIndex().String()[1:] +func (e *Bind) String() string { + var s strings.Builder + for i, p := range e.Patterns { + if i == 0 { + fmt.Fprintf(&s, " as %s ", p) + } else { + fmt.Fprintf(&s, "?// %s ", p) + } + } + fmt.Fprintf(&s, "| %s", e.Body) + return s.String() } -func (e *SuffixIndex) toIndex() *Index { - return &Index{ - Start: e.Start, - IsSlice: e.IsSlice, - End: e.End, - } +func (e *Bind) minify() { + e.Body.minify() } // If ... type If struct { - Cond *Query `"if" @@` - Then *Query `"then" @@` - Elif []IfElif `@@*` - Else *Query `("else" @@)? "end"` + Cond *Query + Then *Query + Elif []*IfElif + Else *Query } func (e *If) String() string { var s strings.Builder fmt.Fprintf(&s, "if %s then %s", e.Cond, e.Then) for _, e := range e.Elif { - fmt.Fprintf(&s, " %s", &e) + fmt.Fprintf(&s, " %s", e) } if e.Else != nil { fmt.Fprintf(&s, " else %s", e.Else) @@ -907,20 +696,36 @@ func (e *If) String() string { return s.String() } +func (e *If) minify() { + e.Cond.minify() + e.Then.minify() + for _, x := range e.Elif { + x.minify() + } + if e.Else != nil { + e.Else.minify() + } +} + // IfElif ... type IfElif struct { - Cond *Query `"elif" @@` - Then *Query `"then" @@` + Cond *Query + Then *Query } func (e *IfElif) String() string { return fmt.Sprintf("elif %s then %s", e.Cond, e.Then) } +func (e *IfElif) minify() { + e.Cond.minify() + e.Then.minify() +} + // Try ... type Try struct { - Body *Query `"try" @@` - Catch *Term `("catch" @@)?` + Body *Query + Catch *Query } func (e *Try) String() string { @@ -932,25 +737,38 @@ func (e *Try) String() string { return s.String() } +func (e *Try) minify() { + e.Body.minify() + if e.Catch != nil { + e.Catch.minify() + } +} + // Reduce ... type Reduce struct { - Term *Term `"reduce" @@` - Pattern *Pattern `"as" @@` - Start *Query `"(" @@` - Update *Query `";" @@ ")"` + Term *Term + Pattern *Pattern + Start *Query + Update *Query } func (e *Reduce) String() string { return fmt.Sprintf("reduce %s as %s (%s; %s)", e.Term, e.Pattern, e.Start, e.Update) } +func (e *Reduce) minify() { + e.Term.minify() + e.Start.minify() + e.Update.minify() +} + // Foreach ... type Foreach struct { - Term *Term `"foreach" @@` - Pattern *Pattern `"as" @@` - Start *Query `"(" @@` - Update *Query `";" @@` - Extract *Query `(";" @@)? ")"` + Term *Term + Pattern *Pattern + Start *Query + Update *Query + Extract *Query } func (e *Foreach) String() string { @@ -963,25 +781,38 @@ func (e *Foreach) String() string { return s.String() } +func (e *Foreach) minify() { + e.Term.minify() + e.Start.minify() + e.Update.minify() + if e.Extract != nil { + e.Extract.minify() + } +} + // Label ... type Label struct { - Ident string `"label" @Variable` - Body *Query `"|" @@` + Ident string + Body *Query } func (e *Label) String() string { return fmt.Sprintf("label %s | %s", e.Ident, e.Body) } +func (e *Label) minify() { + e.Body.minify() +} + // ConstTerm ... type ConstTerm struct { - Object *ConstObject ` @@` - Array *ConstArray `| @@` - Number string `| @Number` - Str string `| @String` - Null bool `| @"null"` - True bool `| @"true"` - False bool `| @"false"` + Object *ConstObject + Array *ConstArray + Number string + Str string + Null bool + True bool + False bool } func (e *ConstTerm) String() string { @@ -993,7 +824,7 @@ func (e *ConstTerm) String() string { } else if e.Number != "" { fmt.Fprint(&s, e.Number) } else if e.Str != "" { - fmt.Fprint(&s, e.Str) + fmt.Fprint(&s, strconv.Quote(e.Str)) } else if e.Null { s.WriteString("null") } else if e.True { @@ -1011,21 +842,20 @@ func (e *ConstTerm) toValue() interface{} { return e.Array.toValue() } else if e.Number != "" { return normalizeNumbers(json.Number(e.Number)) - } else if e.Str != "" { - s, _ := strconv.Unquote(e.Str) - return s + } else if e.Null { + return nil } else if e.True { return true } else if e.False { return false } else { - return nil + return e.Str } } // ConstObject ... type ConstObject struct { - KeyVals []ConstObjectKeyVal `"{" (@@ ("," @@)*)? "}"` + KeyVals []*ConstObjectKeyVal } func (e *ConstObject) String() string { @@ -1038,7 +868,7 @@ func (e *ConstObject) String() string { if i > 0 { s.WriteString(", ") } - fmt.Fprint(&s, &kv) + fmt.Fprint(&s, kv) } s.WriteString(" }") return s.String() @@ -1053,7 +883,7 @@ func (e *ConstObject) ToValue() map[string]interface{} { for _, e := range e.KeyVals { key := e.Key if key == "" { - key, _ = strconv.Unquote(e.KeyString) + key = e.KeyString } v[key] = e.Val.toValue() } @@ -1062,9 +892,9 @@ func (e *ConstObject) ToValue() map[string]interface{} { // ConstObjectKeyVal ... type ConstObjectKeyVal struct { - Key string `( @Ident | @Keyword` - KeyString string `| @String ) ":"` - Val *ConstTerm `@@` + Key string + KeyString string + Val *ConstTerm } func (e *ConstObjectKeyVal) String() string { @@ -1081,7 +911,7 @@ func (e *ConstObjectKeyVal) String() string { // ConstArray ... type ConstArray struct { - Elems []*ConstTerm `"[" (@@ ("," @@)*)? "]"` + Elems []*ConstTerm } func (e *ConstArray) String() string { diff --git a/vendor/github.com/itchyny/gojq/string.go b/vendor/github.com/itchyny/gojq/string.go deleted file mode 100644 index beea93fd..00000000 --- a/vendor/github.com/itchyny/gojq/string.go +++ /dev/null @@ -1,11 +0,0 @@ -// Code generated by _tools/gen_string.go; DO NOT EDIT. - -package gojq - -import "regexp" - -const stringPatternStr = `"(?:[^"\\]|\\(?:[[:alnum:]\\'"]|\(` + queryPatternStr + `\)))*"` - -const queryPatternStr = `(?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\([^"()]+\)|"[^"\\]*"))+(?:\s|#[^\n]*)*\)|"(?:[^"\\]|\\(?:[[:alnum:]\\'"]|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\([^"()]+\)|"[^"\\]*"))+(?:\s|#[^\n]*)*\)))*"))+(?:\s|#[^\n]*)*\)|"(?:[^"\\]|\\(?:[[:alnum:]\\'"]|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\([^"()]+\)|"[^"\\]*"))+(?:\s|#[^\n]*)*\)|"(?:[^"\\]|\\(?:[[:alnum:]\\'"]|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\([^"()]+\)|"[^"\\]*"))+(?:\s|#[^\n]*)*\)))*"))+(?:\s|#[^\n]*)*\)))*"))+(?:\s|#[^\n]*)*\)|"(?:[^"\\]|\\(?:[[:alnum:]\\'"]|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\([^"()]+\)|"[^"\\]*"))+(?:\s|#[^\n]*)*\)|"(?:[^"\\]|\\(?:[[:alnum:]\\'"]|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\([^"()]+\)|"[^"\\]*"))+(?:\s|#[^\n]*)*\)))*"))+(?:\s|#[^\n]*)*\)|"(?:[^"\\]|\\(?:[[:alnum:]\\'"]|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\([^"()]+\)|"[^"\\]*"))+(?:\s|#[^\n]*)*\)|"(?:[^"\\]|\\(?:[[:alnum:]\\'"]|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\([^"()]+\)|"[^"\\]*"))+(?:\s|#[^\n]*)*\)))*"))+(?:\s|#[^\n]*)*\)))*"))+(?:\s|#[^\n]*)*\)))*"))+(?:\s|#[^\n]*)*\)|"(?:[^"\\]|\\(?:[[:alnum:]\\'"]|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\([^"()]+\)|"[^"\\]*"))+(?:\s|#[^\n]*)*\)|"(?:[^"\\]|\\(?:[[:alnum:]\\'"]|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\([^"()]+\)|"[^"\\]*"))+(?:\s|#[^\n]*)*\)))*"))+(?:\s|#[^\n]*)*\)|"(?:[^"\\]|\\(?:[[:alnum:]\\'"]|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\([^"()]+\)|"[^"\\]*"))+(?:\s|#[^\n]*)*\)|"(?:[^"\\]|\\(?:[[:alnum:]\\'"]|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\([^"()]+\)|"[^"\\]*"))+(?:\s|#[^\n]*)*\)))*"))+(?:\s|#[^\n]*)*\)))*"))+(?:\s|#[^\n]*)*\)|"(?:[^"\\]|\\(?:[[:alnum:]\\'"]|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\([^"()]+\)|"[^"\\]*"))+(?:\s|#[^\n]*)*\)|"(?:[^"\\]|\\(?:[[:alnum:]\\'"]|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\([^"()]+\)|"[^"\\]*"))+(?:\s|#[^\n]*)*\)))*"))+(?:\s|#[^\n]*)*\)|"(?:[^"\\]|\\(?:[[:alnum:]\\'"]|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\([^"()]+\)|"[^"\\]*"))+(?:\s|#[^\n]*)*\)|"(?:[^"\\]|\\(?:[[:alnum:]\\'"]|\((?:(?:\s|#[^\n]*)*(?:[^"()#[:space:]]+|\([^"()]+\)|"[^"\\]*"))+(?:\s|#[^\n]*)*\)))*"))+(?:\s|#[^\n]*)*\)))*"))+(?:\s|#[^\n]*)*\)))*"))+(?:\s|#[^\n]*)*\)))*"))+(?:\s|#[^\n]*)*` - -var queryInStringPattern = regexp.MustCompile(`^\\\(` + queryPatternStr + `\)`) diff --git a/vendor/github.com/itchyny/gojq/term_type.go b/vendor/github.com/itchyny/gojq/term_type.go new file mode 100644 index 00000000..cad0c94c --- /dev/null +++ b/vendor/github.com/itchyny/gojq/term_type.go @@ -0,0 +1,76 @@ +package gojq + +// TermType represents the type of Term. +type TermType int + +// TermType list. +const ( + TermTypeIdentity TermType = iota + 1 + TermTypeRecurse + TermTypeNull + TermTypeTrue + TermTypeFalse + TermTypeIndex + TermTypeFunc + TermTypeObject + TermTypeArray + TermTypeNumber + TermTypeUnary + TermTypeFormat + TermTypeString + TermTypeIf + TermTypeTry + TermTypeReduce + TermTypeForeach + TermTypeLabel + TermTypeBreak + TermTypeQuery +) + +// GoString implements GoStringer. +func (termType TermType) GoString() string { + switch termType { + case TermTypeIdentity: + return "TermTypeIdentity" + case TermTypeRecurse: + return "TermTypeRecurse" + case TermTypeNull: + return "TermTypeNull" + case TermTypeTrue: + return "TermTypeTrue" + case TermTypeFalse: + return "TermTypeFalse" + case TermTypeIndex: + return "TermTypeIndex" + case TermTypeFunc: + return "TermTypeFunc" + case TermTypeObject: + return "TermTypeObject" + case TermTypeArray: + return "TermTypeArray" + case TermTypeNumber: + return "TermTypeNumber" + case TermTypeUnary: + return "TermTypeUnary" + case TermTypeFormat: + return "TermTypeFormat" + case TermTypeString: + return "TermTypeString" + case TermTypeIf: + return "TermTypeIf" + case TermTypeTry: + return "TermTypeTry" + case TermTypeReduce: + return "TermTypeReduce" + case TermTypeForeach: + return "TermTypeForeach" + case TermTypeLabel: + return "TermTypeLabel" + case TermTypeBreak: + return "TermTypeBreak" + case TermTypeQuery: + return "TermTypeQuery" + default: + panic(termType) + } +} diff --git a/vendor/github.com/lestrrat-go/strftime/LICENSE b/vendor/github.com/itchyny/timefmt-go/LICENSE similarity index 95% rename from vendor/github.com/lestrrat-go/strftime/LICENSE rename to vendor/github.com/itchyny/timefmt-go/LICENSE index eed69381..7085e92d 100644 --- a/vendor/github.com/lestrrat-go/strftime/LICENSE +++ b/vendor/github.com/itchyny/timefmt-go/LICENSE @@ -1,6 +1,6 @@ -MIT License +The MIT License (MIT) -Copyright (c) 2016 lestrrat +Copyright (c) 2020 itchyny Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/github.com/itchyny/timefmt-go/Makefile b/vendor/github.com/itchyny/timefmt-go/Makefile new file mode 100644 index 00000000..bacef7bf --- /dev/null +++ b/vendor/github.com/itchyny/timefmt-go/Makefile @@ -0,0 +1,21 @@ +GOBIN ?= $(shell go env GOPATH)/bin +export GO111MODULE=on + +.PHONY: all +all: test + +.PHONY: test +test: + go test -v ./... + +.PHONY: lint +lint: $(GOBIN)/golint + go vet ./... + golint -set_exit_status ./... + +$(GOBIN)/golint: + cd && go get golang.org/x/lint/golint + +.PHONY: clean +clean: + go clean diff --git a/vendor/github.com/itchyny/timefmt-go/README.md b/vendor/github.com/itchyny/timefmt-go/README.md new file mode 100644 index 00000000..2d16a715 --- /dev/null +++ b/vendor/github.com/itchyny/timefmt-go/README.md @@ -0,0 +1,66 @@ +# timefmt-go +[![CI Status](https://github.com/itchyny/timefmt-go/workflows/CI/badge.svg)](https://github.com/itchyny/timefmt-go/actions) +[![Go Report Card](https://goreportcard.com/badge/github.com/itchyny/timefmt-go)](https://goreportcard.com/report/github.com/itchyny/timefmt-go) +[![MIT License](http://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/itchyny/timefmt-go/blob/master/LICENSE) +[![release](https://img.shields.io/github/release/itchyny/timefmt-go/all.svg)](https://github.com/itchyny/timefmt-go/releases) +[![pkg.go.dev](https://pkg.go.dev/badge/github.com/itchyny/timefmt-go)](https://pkg.go.dev/github.com/itchyny/timefmt-go) + +### Efficient time formatting library (strftime, strptime) for Golang +This is a Go language package for formatting and parsing date time strings. + +```go +package main + +import ( + "fmt" + "log" + + "github.com/itchyny/timefmt-go" +) + +func main() { + t, err := timefmt.Parse("2020/07/24 09:07:29", "%Y/%m/%d %H:%M:%S") + if err != nil { + log.Fatal(err) + } + fmt.Println(t) // 2020-07-24 09:07:29 +0000 UTC + + str := timefmt.Format(t, "%Y/%m/%d %H:%M:%S") + fmt.Println(str) // 2020/07/24 09:07:29 + + str = timefmt.Format(t, "%a, %d %b %Y %T %z") + fmt.Println(str) // Fri, 24 Jul 2020 09:07:29 +0000 +} +``` + +Please refer to [`man 3 strftime`](https://linux.die.net/man/3/strftime) and +[`man 3 strptime`](https://linux.die.net/man/3/strptime) for formatters. +Note that `E` and `O` modifier characters are not supported. + +## Comparison to other libraries +- This library + - provides both formatting and parsing functions in pure Go language, + - depends only on the Go standard libraries not to grows up the module file. +- `Format` (`strftime`) implements glibc extensions including + - width specifier like `%10A, %10B %2k:%M`, + - omitting padding modifier like `%-y-%-m-%-d`, + - space padding modifier like `%_y-%_m-%_d`, + - upper case modifier like `%^a %^b`, + - swapping case modifier like `%#Z`, + - and its performance is very good. +- `AppendFormat` is provided for zero-allocations in most formats. +- `Parse` (`strptime`) allows to parse + - composed directives like `%F %T`, + - century years like `%C %y`, + - week names like `%A` `%a` (parsed results are discarded). + +![](https://user-images.githubusercontent.com/375258/88606920-de475c80-d0b8-11ea-8d40-cbfee9e35c2e.jpg) + +## Bug Tracker +Report bug at [Issues・itchyny/timefmt-go - GitHub](https://github.com/itchyny/timefmt-go/issues). + +## Author +itchyny (https://github.com/itchyny) + +## License +This software is released under the MIT License, see LICENSE. diff --git a/vendor/github.com/itchyny/timefmt-go/format.go b/vendor/github.com/itchyny/timefmt-go/format.go new file mode 100644 index 00000000..42b171bf --- /dev/null +++ b/vendor/github.com/itchyny/timefmt-go/format.go @@ -0,0 +1,476 @@ +package timefmt + +import ( + "strconv" + "strings" + "time" +) + +// Format time to string using the format. +func Format(t time.Time, format string) string { + return string(AppendFormat(make([]byte, 0, 64), t, format)) +} + +// AppendFormat appends formatted time to the bytes. +// You can use this method to reduce allocations. +func AppendFormat(buf []byte, t time.Time, format string) []byte { + year, month, day := t.Date() + hour, min, sec := t.Clock() + var width int + var padding byte + var pending string + var upper, swap bool + for i := 0; i < len(format); i++ { + if b := format[i]; b == '%' { + if i++; i == len(format) { + buf = append(buf, '%') + break + } + b, width, padding, upper, swap = format[i], 0, '0', false, false + L: + switch b { + case '-': + if pending != "" { + buf = append(buf, '-') + break + } + if i++; i == len(format) { + buf = appendLast(buf, format, width, padding) + break + } + padding = ^paddingMask + b = format[i] + goto L + case '_': + if i++; i == len(format) { + buf = appendLast(buf, format, width, padding) + break + } + padding = ' ' | ^paddingMask + b = format[i] + goto L + case '^': + if i++; i == len(format) { + buf = appendLast(buf, format, width, padding) + break + } + upper = true + b = format[i] + goto L + case '#': + if i++; i == len(format) { + buf = appendLast(buf, format, width, padding) + break + } + swap = true + b = format[i] + goto L + case '0': + if i++; i == len(format) { + buf = appendLast(buf, format, width, padding) + break + } + padding = '0' | ^paddingMask + b = format[i] + goto L + case '1', '2', '3', '4', '5', '6', '7', '8', '9': + width = int(b & 0x0F) + const maxWidth = 1024 + for i++; i < len(format); i++ { + b = format[i] + if b <= '9' && '0' <= b { + width = width*10 + int(b&0x0F) + if width >= int((^uint(0)>>1)/10) { + width = maxWidth + } + } else { + break + } + } + if width > maxWidth { + width = maxWidth + } + if padding == ^paddingMask { + padding = ' ' | ^paddingMask + } + if i == len(format) { + buf = appendLast(buf, format, width, padding) + break + } + goto L + case 'Y': + if width == 0 { + width = 4 + } + buf = appendInt(buf, year, width, padding) + case 'y': + if width < 2 { + width = 2 + } + buf = appendInt(buf, year%100, width, padding) + case 'C': + if width < 2 { + width = 2 + } + buf = appendInt(buf, year/100, width, padding) + case 'g': + if width < 2 { + width = 2 + } + year, _ := t.ISOWeek() + buf = appendInt(buf, year%100, width, padding) + case 'G': + if width == 0 { + width = 4 + } + year, _ := t.ISOWeek() + buf = appendInt(buf, year, width, padding) + case 'm': + if width < 2 { + width = 2 + } + buf = appendInt(buf, int(month), width, padding) + case 'B': + buf = appendString(buf, longMonthNames[month-1], width, padding, upper, swap) + case 'b', 'h': + buf = appendString(buf, shortMonthNames[month-1], width, padding, upper, swap) + case 'A': + buf = appendString(buf, longWeekNames[t.Weekday()], width, padding, upper, swap) + case 'a': + buf = appendString(buf, shortWeekNames[t.Weekday()], width, padding, upper, swap) + case 'w': + for ; width > 1; width-- { + buf = append(buf, padding&paddingMask) + } + buf = append(buf, '0'+byte(t.Weekday())) + case 'u': + w := int(t.Weekday()) + if w == 0 { + w = 7 + } + for ; width > 1; width-- { + buf = append(buf, padding&paddingMask) + } + buf = append(buf, '0'+byte(w)) + case 'V': + if width < 2 { + width = 2 + } + _, week := t.ISOWeek() + buf = appendInt(buf, week, width, padding) + case 'U': + if width < 2 { + width = 2 + } + week := (t.YearDay() + 6 - int(t.Weekday())) / 7 + buf = appendInt(buf, week, width, padding) + case 'W': + if width < 2 { + width = 2 + } + week := t.YearDay() + if int(t.Weekday()) > 0 { + week -= int(t.Weekday()) - 7 + } + week /= 7 + buf = appendInt(buf, week, width, padding) + case 'e': + if padding < ^paddingMask { + padding = ' ' + } + fallthrough + case 'd': + if width < 2 { + width = 2 + } + buf = appendInt(buf, day, width, padding) + case 'j': + if width < 3 { + width = 3 + } + buf = appendInt(buf, t.YearDay(), width, padding) + case 'k': + if padding < ^paddingMask { + padding = ' ' + } + fallthrough + case 'H': + if width < 2 { + width = 2 + } + buf = appendInt(buf, hour, width, padding) + case 'l': + if width < 2 { + width = 2 + } + if padding < ^paddingMask { + padding = ' ' + } + h := hour + if h > 12 { + h -= 12 + } + buf = appendInt(buf, h, width, padding) + case 'I': + if width < 2 { + width = 2 + } + h := hour + if h > 12 { + h -= 12 + } else if h == 0 { + h = 12 + } + buf = appendInt(buf, h, width, padding) + case 'p': + if hour < 12 { + buf = appendString(buf, "AM", width, padding, upper, swap) + } else { + buf = appendString(buf, "PM", width, padding, upper, swap) + } + case 'P': + if hour < 12 { + buf = appendString(buf, "am", width, padding, upper, swap) + } else { + buf = appendString(buf, "pm", width, padding, upper, swap) + } + case 'M': + if width < 2 { + width = 2 + } + buf = appendInt(buf, min, width, padding) + case 'S': + if width < 2 { + width = 2 + } + buf = appendInt(buf, sec, width, padding) + case 's': + if padding < ^paddingMask { + padding = ' ' + } + buf = appendInt(buf, int(t.Unix()), width, padding) + case 'f': + if width == 0 { + width = 6 + } + buf = appendInt(buf, t.Nanosecond()/1000, width, padding) + case 'Z', 'z': + name, offset := t.Zone() + if b == 'Z' && name != "" { + buf = appendString(buf, name, width, padding, upper, swap) + break + } + if width < 4 { + width = 4 + } + if offset < 0 { + buf = append(buf, '-') + offset = -offset + } else { + buf = append(buf, '+') + } + offset /= 60 + buf = appendInt(buf, (offset/60)*100+offset%60, width, padding) + case 't': + buf = appendString(buf, "\t", width, padding, false, false) + case 'n': + buf = appendString(buf, "\n", width, padding, false, false) + case '%': + buf = appendString(buf, "%", width, padding, false, false) + default: + if pending == "" { + var ok bool + if pending, ok = compositions[b]; ok { + swap = false + break + } + buf = appendLast(buf, format[:i], width-1, padding) + } + buf = append(buf, b) + } + if pending != "" { + b, pending, width, padding = pending[0], pending[1:], 0, '0' + goto L + } + } else { + buf = append(buf, b) + } + } + return buf +} + +func appendInt(buf []byte, num, width int, padding byte) []byte { + if padding != ^paddingMask { + padding &= paddingMask + switch width { + case 2: + if num < 10 { + buf = append(buf, padding) + goto L1 + } else if num < 100 { + goto L2 + } else if num < 1000 { + goto L3 + } else if num < 10000 { + goto L4 + } + case 4: + if num < 1000 { + buf = append(buf, padding) + if num < 100 { + buf = append(buf, padding) + if num < 10 { + buf = append(buf, padding) + goto L1 + } + goto L2 + } + goto L3 + } else if num < 10000 { + goto L4 + } + default: + i := len(buf) + for ; width > 1; width-- { + buf = append(buf, padding) + } + j := len(buf) + buf = strconv.AppendInt(buf, int64(num), 10) + l := len(buf) + if j+1 == l || i == j { + return buf + } + k := j + 1 - (l - j) + if k < i { + l = j + 1 + i - k + k = i + } else { + l = j + 1 + } + copy(buf[k:], buf[j:]) + return buf[:l] + } + } + if num < 100 { + if num < 10 { + goto L1 + } + goto L2 + } else if num < 10000 { + if num < 1000 { + goto L3 + } + goto L4 + } + return strconv.AppendInt(buf, int64(num), 10) +L4: + buf = append(buf, byte(num/1000)|'0') + num %= 1000 +L3: + buf = append(buf, byte(num/100)|'0') + num %= 100 +L2: + buf = append(buf, byte(num/10)|'0') + num %= 10 +L1: + return append(buf, byte(num)|'0') +} + +func appendString(buf []byte, str string, width int, padding byte, upper, swap bool) []byte { + if width > len(str) && padding != ^paddingMask { + if padding < ^paddingMask { + padding = ' ' + } else { + padding &= paddingMask + } + for width -= len(str); width > 0; width-- { + buf = append(buf, padding) + } + } + switch { + case swap: + if str[len(str)-1] < 'a' { + for _, b := range []byte(str) { + buf = append(buf, b|0x20) + } + break + } + fallthrough + case upper: + for _, b := range []byte(str) { + buf = append(buf, b&0x5F) + } + default: + buf = append(buf, str...) + } + return buf +} + +func appendLast(buf []byte, format string, width int, padding byte) []byte { + return appendString(buf, format[strings.LastIndexByte(format, '%'):], width, padding, false, false) +} + +const paddingMask byte = 0x7F + +var longMonthNames = []string{ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", +} + +var shortMonthNames = []string{ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dec", +} + +var longWeekNames = []string{ + "Sunday", + "Monday", + "Tuesday", + "Wednesday", + "Thursday", + "Friday", + "Saturday", +} + +var shortWeekNames = []string{ + "Sun", + "Mon", + "Tue", + "Wed", + "Thu", + "Fri", + "Sat", +} + +var compositions = map[byte]string{ + 'c': "a b e H:M:S Y", + '+': "a b e H:M:S Z Y", + 'F': "Y-m-d", + 'D': "m/d/y", + 'x': "m/d/y", + 'v': "e-b-Y", + 'T': "H:M:S", + 'X': "H:M:S", + 'r': "I:M:S p", + 'R': "H:M", +} diff --git a/vendor/github.com/itchyny/timefmt-go/go.mod b/vendor/github.com/itchyny/timefmt-go/go.mod new file mode 100644 index 00000000..047e976f --- /dev/null +++ b/vendor/github.com/itchyny/timefmt-go/go.mod @@ -0,0 +1,3 @@ +module github.com/itchyny/timefmt-go + +go 1.14 diff --git a/vendor/github.com/itchyny/timefmt-go/parse.go b/vendor/github.com/itchyny/timefmt-go/parse.go new file mode 100644 index 00000000..38fcabf9 --- /dev/null +++ b/vendor/github.com/itchyny/timefmt-go/parse.go @@ -0,0 +1,329 @@ +package timefmt + +import ( + "errors" + "fmt" + "strconv" + "time" +) + +type parseError struct { + source, format string + err error +} + +func (err *parseError) Error() string { + return fmt.Sprintf("failed to parse %q with %q: %s", err.source, err.format, err.err) +} + +// Parse time string using the format. +func Parse(source, format string) (t time.Time, err error) { + year, month, day, hour, min, sec, nsec, loc := 1900, 1, 1, 0, 0, 0, 0, time.UTC + defer func() { + if err != nil { + err = &parseError{source, format, err} + } + }() + var j, diff, century, yday int + var pm bool + var pending string + for i, l := 0, len(source); i < len(format); i++ { + if b := format[i]; b == '%' { + i++ + if i == len(format) { + err = errors.New("stray %") + return + } + b = format[i] + L: + switch b { + case 'Y': + if year, diff, err = parseNumber(source[j:], 4, 'Y'); err != nil { + return + } + j += diff + case 'y': + if year, diff, err = parseNumber(source[j:], 2, 'y'); err != nil { + return + } + j += diff + if year < 69 { + year += 2000 + } else { + year += 1900 + } + case 'C': + if century, diff, err = parseNumber(source[j:], 2, 'C'); err != nil { + return + } + j += diff + case 'g': + if year, diff, err = parseNumber(source[j:], 2, b); err != nil { + return + } + j += diff + year += 2000 + case 'G': + if year, diff, err = parseNumber(source[j:], 4, b); err != nil { + return + } + j += diff + case 'm': + if month, diff, err = parseNumber(source[j:], 2, 'm'); err != nil { + return + } + j += diff + case 'B': + if month, diff, err = lookup(source[j:], longMonthNames, 'B'); err != nil { + return + } + j += diff + case 'b', 'h': + if month, diff, err = lookup(source[j:], shortMonthNames, b); err != nil { + return + } + j += diff + case 'A': + if _, diff, err = lookup(source[j:], longWeekNames, 'A'); err != nil { + return + } + j += diff + case 'a': + if _, diff, err = lookup(source[j:], shortWeekNames, 'a'); err != nil { + return + } + j += diff + case 'w': + if j >= l || source[j] < '0' || '6' < source[j] { + err = parseFormatError(b) + return + } + j++ + case 'u': + if j >= l || source[j] < '1' || '7' < source[j] { + err = parseFormatError(b) + return + } + j++ + case 'V', 'U', 'W': + if _, diff, err = parseNumber(source[j:], 2, b); err != nil { + return + } + j += diff + case 'e': + if j < l && source[j] == ' ' { + j++ + } + fallthrough + case 'd': + if day, diff, err = parseNumber(source[j:], 2, b); err != nil { + return + } + j += diff + case 'j': + if yday, diff, err = parseNumber(source[j:], 3, 'j'); err != nil { + return + } + j += diff + case 'k': + if j < l && source[j] == ' ' { + j++ + } + fallthrough + case 'H': + if hour, diff, err = parseNumber(source[j:], 2, b); err != nil { + return + } + j += diff + case 'l': + if j < l && source[j] == ' ' { + j++ + } + fallthrough + case 'I': + if hour, diff, err = parseNumber(source[j:], 2, b); err != nil { + return + } + j += diff + if hour == 12 { + hour = 0 + } + case 'p', 'P': + var ampm int + if ampm, diff, err = lookup(source[j:], []string{"AM", "PM"}, 'p'); err != nil { + return + } + j += diff + pm = ampm == 2 + case 'M': + if min, diff, err = parseNumber(source[j:], 2, 'M'); err != nil { + return + } + j += diff + case 'S': + if sec, diff, err = parseNumber(source[j:], 2, 'S'); err != nil { + return + } + j += diff + case 's': + var unix int + if unix, diff, err = parseNumber(source[j:], 10, 's'); err != nil { + return + } + t = time.Unix(int64(unix), 0).In(time.UTC) + var mon time.Month + year, mon, day = t.Date() + hour, min, sec = t.Clock() + month = int(mon) + j += diff + case 'f': + var msec int + if msec, diff, err = parseNumber(source[j:], 6, 'f'); err != nil { + return + } + j += diff + nsec = msec * 1000 + for diff < 6 { + nsec *= 10 + diff++ + } + case 'Z': + k := j + for ; k < l; k++ { + if c := source[k]; c < 'A' || 'Z' < c { + break + } + } + t, err = time.Parse("MST", source[j:k]) + if err != nil { + return + } + loc = t.Location() + j = k + case 'z': + if j+5 > l { + err = parseFormatError(b) + return + } + var offset int + switch source[j] { + case '+', '-': + var hour, min int + if hour, err = strconv.Atoi(source[j+1 : j+3]); err != nil { + return + } + if min, err = strconv.Atoi(source[j+3 : j+5]); err != nil { + return + } + offset = (hour*60 + min) * 60 + if source[j] == '-' { + offset = -offset + } + default: + err = parseFormatError(b) + return + } + loc = time.FixedZone("", offset) + j += 5 + case 't', 'n': + k := j + K: + for ; k < l; k++ { + switch source[k] { + case ' ', '\t', '\n', '\v', '\f', '\r': + default: + break K + } + } + if k == j { + err = errors.New("expected a space") + return + } + j = k + case '%': + if j >= l || source[j] != b { + err = fmt.Errorf("expected %q", b) + return + } + j++ + default: + if pending == "" { + var ok bool + if pending, ok = compositions[b]; ok { + break + } + err = fmt.Errorf(`unexpected format: "%%%c"`, b) + return + } + if j >= l || source[j] != b { + err = fmt.Errorf("expected %q", b) + return + } + j++ + } + if pending != "" { + b, pending = pending[0], pending[1:] + goto L + } + } else if j >= len(source) || source[j] != b { + err = fmt.Errorf("expected %q", b) + return + } else { + j++ + } + } + if j < len(source) { + err = fmt.Errorf("unconverted string: %q", source[j:]) + return + } + if pm { + hour += 12 + } + if century > 0 { + year = century*100 + year%100 + } + if yday > 0 { + return time.Date(year, time.January, 1, hour, min, sec, nsec, loc).AddDate(0, 0, yday-1), nil + } + return time.Date(year, time.Month(month), day, hour, min, sec, nsec, loc), nil +} + +func isDigit(c byte) bool { + return '0' <= c && c <= '9' +} + +type parseFormatError byte + +func (err parseFormatError) Error() string { + return fmt.Sprintf("cannot parse %%%c", byte(err)) +} + +func parseNumber(source string, max int, format byte) (int, int, error) { + if len(source) > 0 && isDigit(source[0]) { + for i := 1; i < max; i++ { + if i >= len(source) || !isDigit(source[i]) { + val, err := strconv.Atoi(string(source[:i])) + return val, i, err + } + } + val, err := strconv.Atoi(string(source[:max])) + return val, max, err + } + return 0, 0, parseFormatError(format) +} + +func lookup(source string, candidates []string, format byte) (int, int, error) { +L: + for i, xs := range candidates { + for j, x := range []byte(xs) { + if j >= len(source) { + continue L + } + if y := source[j]; x != y && x|('a'-'A') != y|('a'-'A') { + continue L + } + } + return i + 1, len(xs), nil + } + return 0, 0, parseFormatError(format) +} diff --git a/vendor/github.com/lestrrat-go/strftime/.gitignore b/vendor/github.com/lestrrat-go/strftime/.gitignore deleted file mode 100644 index daf913b1..00000000 --- a/vendor/github.com/lestrrat-go/strftime/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof diff --git a/vendor/github.com/lestrrat-go/strftime/.travis.yml b/vendor/github.com/lestrrat-go/strftime/.travis.yml deleted file mode 100644 index 7345555a..00000000 --- a/vendor/github.com/lestrrat-go/strftime/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: go -sudo: false -go: - - 1.13.x - - tip diff --git a/vendor/github.com/lestrrat-go/strftime/Makefile b/vendor/github.com/lestrrat-go/strftime/Makefile deleted file mode 100644 index e5594613..00000000 --- a/vendor/github.com/lestrrat-go/strftime/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -bench: - go test -tags bench -benchmem -bench . - @git checkout go.mod - @rm go.sum diff --git a/vendor/github.com/lestrrat-go/strftime/README.md b/vendor/github.com/lestrrat-go/strftime/README.md deleted file mode 100644 index f94f38e0..00000000 --- a/vendor/github.com/lestrrat-go/strftime/README.md +++ /dev/null @@ -1,202 +0,0 @@ -# strftime - -Fast strftime for Go - -[![Build Status](https://travis-ci.org/lestrrat-go/strftime.png?branch=master)](https://travis-ci.org/lestrrat-go/strftime) - -[![GoDoc](https://godoc.org/github.com/lestrrat-go/strftime?status.svg)](https://godoc.org/github.com/lestrrat-go/strftime) - -# SYNOPSIS - -```go -f := strftime.New(`.... pattern ...`) -if err := f.Format(buf, time.Now()); err != nil { - log.Println(err.Error()) -} -``` - -# DESCRIPTION - -The goals for this library are - -* Optimized for the same pattern being called repeatedly -* Be flexible about destination to write the results out -* Be as complete as possible in terms of conversion specifications - -# API - -## Format(string, time.Time) (string, error) - -Takes the pattern and the time, and formats it. This function is a utility function that recompiles the pattern every time the function is called. If you know beforehand that you will be formatting the same pattern multiple times, consider using `New` to create a `Strftime` object and reuse it. - -## New(string) (\*Strftime, error) - -Takes the pattern and creates a new `Strftime` object. - -## obj.Pattern() string - -Returns the pattern string used to create this `Strftime` object - -## obj.Format(io.Writer, time.Time) error - -Formats the time according to the pre-compiled pattern, and writes the result to the specified `io.Writer` - -## obj.FormatString(time.Time) string - -Formats the time according to the pre-compiled pattern, and returns the result string. - -# SUPPORTED CONVERSION SPECIFICATIONS - -| pattern | description | -|:--------|:------------| -| %A | national representation of the full weekday name | -| %a | national representation of the abbreviated weekday | -| %B | national representation of the full month name | -| %b | national representation of the abbreviated month name | -| %C | (year / 100) as decimal number; single digits are preceded by a zero | -| %c | national representation of time and date | -| %D | equivalent to %m/%d/%y | -| %d | day of the month as a decimal number (01-31) | -| %e | the day of the month as a decimal number (1-31); single digits are preceded by a blank | -| %F | equivalent to %Y-%m-%d | -| %H | the hour (24-hour clock) as a decimal number (00-23) | -| %h | same as %b | -| %I | the hour (12-hour clock) as a decimal number (01-12) | -| %j | the day of the year as a decimal number (001-366) | -| %k | the hour (24-hour clock) as a decimal number (0-23); single digits are preceded by a blank | -| %l | the hour (12-hour clock) as a decimal number (1-12); single digits are preceded by a blank | -| %M | the minute as a decimal number (00-59) | -| %m | the month as a decimal number (01-12) | -| %n | a newline | -| %p | national representation of either "ante meridiem" (a.m.) or "post meridiem" (p.m.) as appropriate. | -| %R | equivalent to %H:%M | -| %r | equivalent to %I:%M:%S %p | -| %S | the second as a decimal number (00-60) | -| %T | equivalent to %H:%M:%S | -| %t | a tab | -| %U | the week number of the year (Sunday as the first day of the week) as a decimal number (00-53) | -| %u | the weekday (Monday as the first day of the week) as a decimal number (1-7) | -| %V | the week number of the year (Monday as the first day of the week) as a decimal number (01-53) | -| %v | equivalent to %e-%b-%Y | -| %W | the week number of the year (Monday as the first day of the week) as a decimal number (00-53) | -| %w | the weekday (Sunday as the first day of the week) as a decimal number (0-6) | -| %X | national representation of the time | -| %x | national representation of the date | -| %Y | the year with century as a decimal number | -| %y | the year without century as a decimal number (00-99) | -| %Z | the time zone name | -| %z | the time zone offset from UTC | -| %% | a '%' | - -# EXTENSIONS / CUSTOM SPECIFICATIONS - -This library in general tries to be POSIX compliant, but sometimes you just need that -extra specification or two that is relatively widely used but is not included in the -POSIX specification. - -For example, POSIX does not specify how to print out milliseconds, -but popular implementations allow `%f` or `%L` to achieve this. - -For those instances, `strftime.Strftime` can be configured to use a custom set of -specifications: - -``` -ss := strftime.NewSpecificationSet() -ss.Set('L', ...) // provide implementation for `%L` - -// pass this new specification set to the strftime instance -p, err := strftime.New(`%L`, strftime.WithSpecificationSet(ss)) -p.Format(..., time.Now()) -``` - -The implementation must implement the `Appender` interface, which is - -``` -type Appender interface { - Append([]byte, time.Time) []byte -} -``` - -For commonly used extensions such as the millisecond example, we provide a default -implementation so the user can do one of the following: - -``` -// (1) Pass a speficication byte and the Appender -// This allows you to pass arbitrary Appenders -p, err := strftime.New( - `%L`, - strftime.WithSpecification('L', strftime.Milliseconds), -) - -// (2) Pass an option that knows to use strftime.Milliseconds -p, err := strftime.New( - `%L`, - strftime.WithMilliseconds('L'), -) -``` - -If a common specification is missing, please feel free to submit a PR -(but please be sure to be able to defend how "common" it is) - -# PERFORMANCE / OTHER LIBRARIES - -The following benchmarks were run separately because some libraries were using cgo on specific platforms (notabley, the fastly version) - -``` -// On my OS X 10.14.6, 2.3 GHz Intel Core i5, 16GB memory. -// go version go1.13.4 darwin/amd64 -hummingbird% go test -tags bench -benchmem -bench . - -BenchmarkTebeka-4 297471 3905 ns/op 257 B/op 20 allocs/op -BenchmarkJehiah-4 818444 1773 ns/op 256 B/op 17 allocs/op -BenchmarkFastly-4 2330794 550 ns/op 80 B/op 5 allocs/op -BenchmarkLestrrat-4 916365 1458 ns/op 80 B/op 2 allocs/op -BenchmarkLestrratCachedString-4 2527428 546 ns/op 128 B/op 2 allocs/op -BenchmarkLestrratCachedWriter-4 537422 2155 ns/op 192 B/op 3 allocs/op -PASS -ok github.com/lestrrat-go/strftime 25.618s -``` - -``` -// On a host on Google Cloud Platform, machine-type: f1-micro (vCPU x 1, memory: 0.6GB) -// (Yes, I was being skimpy) -// Linux 4.9.0-11-amd64 #1 SMP Debian 4.9.189-3+deb9u1 (2019-09-20) x86_64 GNU/Linux -// go version go1.13.4 linux/amd64 -hummingbird% go test -tags bench -benchmem -bench . - -BenchmarkTebeka 254997 4726 ns/op 256 B/op 20 allocs/op -BenchmarkJehiah 659289 1882 ns/op 256 B/op 17 allocs/op -BenchmarkFastly 389150 3044 ns/op 224 B/op 13 allocs/op -BenchmarkLestrrat 699069 1780 ns/op 80 B/op 2 allocs/op -BenchmarkLestrratCachedString 2081594 589 ns/op 128 B/op 2 allocs/op -BenchmarkLestrratCachedWriter 825763 1480 ns/op 192 B/op 3 allocs/op -PASS -ok github.com/lestrrat-go/strftime 11.355s -``` - -This library is much faster than other libraries *IF* you can reuse the format pattern. - -Here's the annotated list from the benchmark results. You can clearly see that (re)using a `Strftime` object -and producing a string is the fastest. Writing to an `io.Writer` seems a bit sluggish, but since -the one producing the string is doing almost exactly the same thing, we believe this is purely the overhead of -writing to an `io.Writer` - -| Import Path | Score | Note | -|:------------------------------------|--------:|:--------------------------------| -| github.com/lestrrat-go/strftime | 3000000 | Using `FormatString()` (cached) | -| github.com/fastly/go-utils/strftime | 2000000 | Pure go version on OS X | -| github.com/lestrrat-go/strftime | 1000000 | Using `Format()` (NOT cached) | -| github.com/jehiah/go-strftime | 1000000 | | -| github.com/fastly/go-utils/strftime | 1000000 | cgo version on Linux | -| github.com/lestrrat-go/strftime | 500000 | Using `Format()` (cached) | -| github.com/tebeka/strftime | 300000 | | - -However, depending on your pattern, this speed may vary. If you find a particular pattern that seems sluggish, -please send in patches or tests. - -Please also note that this benchmark only uses the subset of conversion specifications that are supported by *ALL* of the libraries compared. - -Somethings to consider when making performance comparisons in the future: - -* Can it write to io.Writer? -* Which `%specification` does it handle? diff --git a/vendor/github.com/lestrrat-go/strftime/appenders.go b/vendor/github.com/lestrrat-go/strftime/appenders.go deleted file mode 100644 index e4b4204d..00000000 --- a/vendor/github.com/lestrrat-go/strftime/appenders.go +++ /dev/null @@ -1,293 +0,0 @@ -package strftime - -import ( - "bytes" - "fmt" - "io" - "strconv" - "strings" - "time" -) - -// These are all of the standard, POSIX compliant specifications. -// Extensions should be in extensions.go -var ( - fullWeekDayName = StdlibFormat("Monday") - abbrvWeekDayName = StdlibFormat("Mon") - fullMonthName = StdlibFormat("January") - abbrvMonthName = StdlibFormat("Jan") - centuryDecimal = AppendFunc(appendCentury) - timeAndDate = StdlibFormat("Mon Jan _2 15:04:05 2006") - mdy = StdlibFormat("01/02/06") - dayOfMonthZeroPad = StdlibFormat("02") - dayOfMonthSpacePad = StdlibFormat("_2") - ymd = StdlibFormat("2006-01-02") - twentyFourHourClockZeroPad = StdlibFormat("15") - twelveHourClockZeroPad = StdlibFormat("3") - dayOfYear = AppendFunc(appendDayOfYear) - twentyFourHourClockSpacePad = hourwblank(false) - twelveHourClockSpacePad = hourwblank(true) - minutesZeroPad = StdlibFormat("04") - monthNumberZeroPad = StdlibFormat("01") - newline = Verbatim("\n") - ampm = StdlibFormat("PM") - hm = StdlibFormat("15:04") - imsp = StdlibFormat("3:04:05 PM") - secondsNumberZeroPad = StdlibFormat("05") - hms = StdlibFormat("15:04:05") - tab = Verbatim("\t") - weekNumberSundayOrigin = weeknumberOffset(0) // week number of the year, Sunday first - weekdayMondayOrigin = weekday(1) - // monday as the first day, and 01 as the first value - weekNumberMondayOriginOneOrigin = AppendFunc(appendWeekNumber) - eby = StdlibFormat("_2-Jan-2006") - // monday as the first day, and 00 as the first value - weekNumberMondayOrigin = weeknumberOffset(1) // week number of the year, Monday first - weekdaySundayOrigin = weekday(0) - natReprTime = StdlibFormat("15:04:05") // national representation of the time XXX is this correct? - natReprDate = StdlibFormat("01/02/06") // national representation of the date XXX is this correct? - year = StdlibFormat("2006") // year with century - yearNoCentury = StdlibFormat("06") // year w/o century - timezone = StdlibFormat("MST") // time zone name - timezoneOffset = StdlibFormat("-0700") // time zone ofset from UTC - percent = Verbatim("%") -) - -// Appender is the interface that must be fulfilled by components that -// implement the translation of specifications to actual time value. -// -// The Append method takes the accumulated byte buffer, and the time to -// use to generate the textual representation. The resulting byte -// sequence must be returned by this method, normally by using the -// append() builtin function. -type Appender interface { - Append([]byte, time.Time) []byte -} - -// AppendFunc is an utility type to allow users to create a -// function-only version of an Appender -type AppendFunc func([]byte, time.Time) []byte - -func (af AppendFunc) Append(b []byte, t time.Time) []byte { - return af(b, t) -} - -type appenderList []Appender - -type dumper interface { - dump(io.Writer) -} - -func (l appenderList) dump(out io.Writer) { - var buf bytes.Buffer - ll := len(l) - for i, a := range l { - if dumper, ok := a.(dumper); ok { - dumper.dump(&buf) - } else { - fmt.Fprintf(&buf, "%#v", a) - } - - if i < ll-1 { - fmt.Fprintf(&buf, ",\n") - } - } - buf.WriteTo(out) -} - -// does the time.Format thing -type stdlibFormat struct { - s string -} - -// StdlibFormat returns an Appender that simply goes through `time.Format()` -// For example, if you know you want to display the abbreviated month name for %b, -// you can create a StdlibFormat with the pattern `Jan` and register that -// for specification `b`: -// -// a := StdlibFormat(`Jan`) -// ss := NewSpecificationSet() -// ss.Set('b', a) // does %b -> abbreviated month name -func StdlibFormat(s string) Appender { - return &stdlibFormat{s: s} -} - -func (v stdlibFormat) Append(b []byte, t time.Time) []byte { - return t.AppendFormat(b, v.s) -} - -func (v stdlibFormat) str() string { - return v.s -} - -func (v stdlibFormat) canCombine() bool { - return true -} - -func (v stdlibFormat) combine(w combiner) Appender { - return StdlibFormat(v.s + w.str()) -} - -func (v stdlibFormat) dump(out io.Writer) { - fmt.Fprintf(out, "stdlib: %s", v.s) -} - -type verbatimw struct { - s string -} - -// Verbatim returns an Appender suitable for generating static text. -// For static text, this method is slightly favorable than creating -// your own appender, as adjacent verbatim blocks will be combined -// at compile time to produce more efficient Appenders -func Verbatim(s string) Appender { - return &verbatimw{s: s} -} - -func (v verbatimw) Append(b []byte, _ time.Time) []byte { - return append(b, v.s...) -} - -func (v verbatimw) canCombine() bool { - return canCombine(v.s) -} - -func (v verbatimw) combine(w combiner) Appender { - if _, ok := w.(*stdlibFormat); ok { - return StdlibFormat(v.s + w.str()) - } - return Verbatim(v.s + w.str()) -} - -func (v verbatimw) str() string { - return v.s -} - -func (v verbatimw) dump(out io.Writer) { - fmt.Fprintf(out, "verbatim: %s", v.s) -} - -// These words below, as well as any decimal character -var combineExclusion = []string{ - "Mon", - "Monday", - "Jan", - "January", - "MST", - "PM", - "pm", -} - -func canCombine(s string) bool { - if strings.ContainsAny(s, "0123456789") { - return false - } - for _, word := range combineExclusion { - if strings.Contains(s, word) { - return false - } - } - return true -} - -type combiner interface { - canCombine() bool - combine(combiner) Appender - str() string -} - -// this is container for the compiler to keep track of appenders, -// and combine them as we parse and compile the pattern -type combiningAppend struct { - list appenderList - prev Appender - prevCanCombine bool -} - -func (ca *combiningAppend) Append(w Appender) { - if ca.prevCanCombine { - if wc, ok := w.(combiner); ok && wc.canCombine() { - ca.prev = ca.prev.(combiner).combine(wc) - ca.list[len(ca.list)-1] = ca.prev - return - } - } - - ca.list = append(ca.list, w) - ca.prev = w - ca.prevCanCombine = false - if comb, ok := w.(combiner); ok { - if comb.canCombine() { - ca.prevCanCombine = true - } - } -} - -func appendCentury(b []byte, t time.Time) []byte { - n := t.Year() / 100 - if n < 10 { - b = append(b, '0') - } - return append(b, strconv.Itoa(n)...) -} - -type weekday int - -func (v weekday) Append(b []byte, t time.Time) []byte { - n := int(t.Weekday()) - if n < int(v) { - n += 7 - } - return append(b, byte(n+48)) -} - -type weeknumberOffset int - -func (v weeknumberOffset) Append(b []byte, t time.Time) []byte { - yd := t.YearDay() - offset := int(t.Weekday()) - int(v) - if offset < 0 { - offset += 7 - } - - if yd < offset { - return append(b, '0', '0') - } - - n := ((yd - offset) / 7) + 1 - if n < 10 { - b = append(b, '0') - } - return append(b, strconv.Itoa(n)...) -} - -func appendWeekNumber(b []byte, t time.Time) []byte { - _, n := t.ISOWeek() - if n < 10 { - b = append(b, '0') - } - return append(b, strconv.Itoa(n)...) -} - -func appendDayOfYear(b []byte, t time.Time) []byte { - n := t.YearDay() - if n < 10 { - b = append(b, '0', '0') - } else if n < 100 { - b = append(b, '0') - } - return append(b, strconv.Itoa(n)...) -} - -type hourwblank bool - -func (v hourwblank) Append(b []byte, t time.Time) []byte { - h := t.Hour() - if bool(v) && h > 12 { - h = h - 12 - } - if h < 10 { - b = append(b, ' ') - } - return append(b, strconv.Itoa(h)...) -} diff --git a/vendor/github.com/lestrrat-go/strftime/extension.go b/vendor/github.com/lestrrat-go/strftime/extension.go deleted file mode 100644 index b0218b9a..00000000 --- a/vendor/github.com/lestrrat-go/strftime/extension.go +++ /dev/null @@ -1,31 +0,0 @@ -package strftime - -import ( - "strconv" - "time" -) - -// NOTE: declare private variable and iniitalize once in init(), -// and leave the Milliseconds() function as returning static content. -// This way, `go doc -all` does not show the contents of the -// milliseconds function -var milliseconds Appender - -func init() { - milliseconds = AppendFunc(func(b []byte, t time.Time) []byte { - millisecond := int(t.Nanosecond()) / int(time.Millisecond) - if millisecond < 100 { - b = append(b, '0') - } - if millisecond < 10 { - b = append(b, '0') - } - return append(b, strconv.Itoa(millisecond)...) - }) -} - -// Milliseconds returns the Appender suitable for creating a zero-padded, -// 3-digit millisecond textual representation. -func Milliseconds() Appender { - return milliseconds -} diff --git a/vendor/github.com/lestrrat-go/strftime/go.mod b/vendor/github.com/lestrrat-go/strftime/go.mod deleted file mode 100644 index d74b99a6..00000000 --- a/vendor/github.com/lestrrat-go/strftime/go.mod +++ /dev/null @@ -1,9 +0,0 @@ -module github.com/lestrrat-go/strftime - -go 1.12 - -require ( - github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc - github.com/pkg/errors v0.8.1 - github.com/stretchr/testify v1.3.0 -) diff --git a/vendor/github.com/lestrrat-go/strftime/options.go b/vendor/github.com/lestrrat-go/strftime/options.go deleted file mode 100644 index 8697a9b5..00000000 --- a/vendor/github.com/lestrrat-go/strftime/options.go +++ /dev/null @@ -1,51 +0,0 @@ -package strftime - -type Option interface { - Name() string - Value() interface{} -} - -type option struct { - name string - value interface{} -} - -func (o *option) Name() string { return o.name } -func (o *option) Value() interface{} { return o.value } - -const optSpecificationSet = `opt-specification-set` - -// WithSpecification allows you to specify a custom specification set -func WithSpecificationSet(ds SpecificationSet) Option { - return &option{ - name: optSpecificationSet, - value: ds, - } -} - -type optSpecificationPair struct { - name byte - appender Appender -} - -const optSpecification = `opt-specification` - -// WithSpecification allows you to create a new specification set on the fly, -// to be used only for that invocation. -func WithSpecification(b byte, a Appender) Option { - return &option{ - name: optSpecification, - value: &optSpecificationPair{ - name: b, - appender: a, - }, - } -} - -// WithMilliseconds is similar to WithSpecification, and specifies that -// the Strftime object should interpret the pattern `%b` (where b -// is the byte that you specify as the argument) -// as the zero-padded, 3 letter milliseconds of the time. -func WithMilliseconds(b byte) Option { - return WithSpecification(b, Milliseconds()) -} diff --git a/vendor/github.com/lestrrat-go/strftime/specifications.go b/vendor/github.com/lestrrat-go/strftime/specifications.go deleted file mode 100644 index 9d3f55b9..00000000 --- a/vendor/github.com/lestrrat-go/strftime/specifications.go +++ /dev/null @@ -1,143 +0,0 @@ -package strftime - -import ( - "sync" - - "github.com/pkg/errors" -) - -// because there is no such thing was a sync.RWLocker -type rwLocker interface { - RLock() - RUnlock() - sync.Locker -} - -// SpecificationSet is a container for patterns that Strftime uses. -// If you want a custom strftime, you can copy the default -// SpecificationSet and tweak it -type SpecificationSet interface { - Lookup(byte) (Appender, error) - Delete(byte) error - Set(byte, Appender) error -} - -type specificationSet struct { - mutable bool - lock rwLocker - store map[byte]Appender -} - -// The default specification set does not need any locking as it is never -// accessed from the outside, and is never mutated. -var defaultSpecificationSet SpecificationSet - -func init() { - defaultSpecificationSet = newImmutableSpecificationSet() -} - -func newImmutableSpecificationSet() SpecificationSet { - // Create a mutable one so that populateDefaultSpecifications work through - // its magic, then copy the associated map - // (NOTE: this is done this way because there used to be - // two struct types for specification set, united under an interface. - // it can now be removed, but we would need to change the entire - // populateDefaultSpecifications method, and I'm currently too lazy - // PRs welcome) - tmp := NewSpecificationSet() - - ss := &specificationSet{ - mutable: false, - lock: nil, // never used, so intentionally not initialized - store: tmp.(*specificationSet).store, - } - - return ss -} - -// NewSpecificationSet creates a specification set with the default specifications. -func NewSpecificationSet() SpecificationSet { - ds := &specificationSet{ - mutable: true, - lock: &sync.RWMutex{}, - store: make(map[byte]Appender), - } - populateDefaultSpecifications(ds) - - return ds -} - -func populateDefaultSpecifications(ds SpecificationSet) { - ds.Set('A', fullWeekDayName) - ds.Set('a', abbrvWeekDayName) - ds.Set('B', fullMonthName) - ds.Set('b', abbrvMonthName) - ds.Set('C', centuryDecimal) - ds.Set('c', timeAndDate) - ds.Set('D', mdy) - ds.Set('d', dayOfMonthZeroPad) - ds.Set('e', dayOfMonthSpacePad) - ds.Set('F', ymd) - ds.Set('H', twentyFourHourClockZeroPad) - ds.Set('h', abbrvMonthName) - ds.Set('I', twelveHourClockZeroPad) - ds.Set('j', dayOfYear) - ds.Set('k', twentyFourHourClockSpacePad) - ds.Set('l', twelveHourClockSpacePad) - ds.Set('M', minutesZeroPad) - ds.Set('m', monthNumberZeroPad) - ds.Set('n', newline) - ds.Set('p', ampm) - ds.Set('R', hm) - ds.Set('r', imsp) - ds.Set('S', secondsNumberZeroPad) - ds.Set('T', hms) - ds.Set('t', tab) - ds.Set('U', weekNumberSundayOrigin) - ds.Set('u', weekdayMondayOrigin) - ds.Set('V', weekNumberMondayOriginOneOrigin) - ds.Set('v', eby) - ds.Set('W', weekNumberMondayOrigin) - ds.Set('w', weekdaySundayOrigin) - ds.Set('X', natReprTime) - ds.Set('x', natReprDate) - ds.Set('Y', year) - ds.Set('y', yearNoCentury) - ds.Set('Z', timezone) - ds.Set('z', timezoneOffset) - ds.Set('%', percent) -} - -func (ds *specificationSet) Lookup(b byte) (Appender, error) { - if ds.mutable { - ds.lock.RLock() - defer ds.lock.RLock() - } - v, ok := ds.store[b] - if !ok { - return nil, errors.Errorf(`lookup failed: '%%%c' was not found in specification set`, b) - } - return v, nil -} - -func (ds *specificationSet) Delete(b byte) error { - if !ds.mutable { - return errors.New(`delete failed: this specification set is marked immutable`) - } - - ds.lock.Lock() - defer ds.lock.Unlock() - delete(ds.store, b) - return nil -} - -func (ds *specificationSet) Set(b byte, a Appender) error { - if !ds.mutable { - return errors.New(`set failed: this specification set is marked immutable`) - } - - ds.lock.Lock() - defer ds.lock.Unlock() - ds.store[b] = a - return nil -} diff --git a/vendor/github.com/lestrrat-go/strftime/strftime.go b/vendor/github.com/lestrrat-go/strftime/strftime.go deleted file mode 100644 index 81c0d887..00000000 --- a/vendor/github.com/lestrrat-go/strftime/strftime.go +++ /dev/null @@ -1,213 +0,0 @@ -package strftime - -import ( - "io" - "strings" - "sync" - "time" - - "github.com/pkg/errors" -) - -type compileHandler interface { - handle(Appender) -} - -// compile, and create an appender list -type appenderListBuilder struct { - list *combiningAppend -} - -func (alb *appenderListBuilder) handle(a Appender) { - alb.list.Append(a) -} - -// compile, and execute the appenders on the fly -type appenderExecutor struct { - t time.Time - dst []byte -} - -func (ae *appenderExecutor) handle(a Appender) { - ae.dst = a.Append(ae.dst, ae.t) -} - -func compile(handler compileHandler, p string, ds SpecificationSet) error { - for l := len(p); l > 0; l = len(p) { - // This is a really tight loop, so we don't even calls to - // Verbatim() to cuase extra stuff - var verbatim verbatimw - - i := strings.IndexByte(p, '%') - if i < 0 { - verbatim.s = p - handler.handle(&verbatim) - // this is silly, but I don't trust break keywords when there's a - // possibility of this piece of code being rearranged - p = p[l:] - continue - } - if i == l-1 { - return errors.New(`stray % at the end of pattern`) - } - - // we found a '%'. we need the next byte to decide what to do next - // we already know that i < l - 1 - // everything up to the i is verbatim - if i > 0 { - verbatim.s = p[:i] - handler.handle(&verbatim) - p = p[i:] - } - - specification, err := ds.Lookup(p[1]) - if err != nil { - return errors.Wrap(err, `pattern compilation failed`) - } - - handler.handle(specification) - p = p[2:] - } - return nil -} - -func getSpecificationSetFor(options ...Option) SpecificationSet { - var ds SpecificationSet = defaultSpecificationSet - var extraSpecifications []*optSpecificationPair - for _, option := range options { - switch option.Name() { - case optSpecificationSet: - ds = option.Value().(SpecificationSet) - case optSpecification: - extraSpecifications = append(extraSpecifications, option.Value().(*optSpecificationPair)) - } - } - - if len(extraSpecifications) > 0 { - // If ds is immutable, we're going to need to create a new - // one. oh what a waste! - if raw, ok := ds.(*specificationSet); ok && !raw.mutable { - ds = NewSpecificationSet() - } - for _, v := range extraSpecifications { - ds.Set(v.name, v.appender) - } - } - return ds -} - -var fmtAppendExecutorPool = sync.Pool{ - New: func() interface{} { - var h appenderExecutor - h.dst = make([]byte, 0, 32) - return &h - }, -} - -func getFmtAppendExecutor() *appenderExecutor { - return fmtAppendExecutorPool.Get().(*appenderExecutor) -} - -func releasdeFmtAppendExecutor(v *appenderExecutor) { - // TODO: should we discard the buffer if it's too long? - v.dst = v.dst[:0] - fmtAppendExecutorPool.Put(v) -} - -// Format takes the format `s` and the time `t` to produce the -// format date/time. Note that this function re-compiles the -// pattern every time it is called. -// -// If you know beforehand that you will be reusing the pattern -// within your application, consider creating a `Strftime` object -// and reusing it. -func Format(p string, t time.Time, options ...Option) (string, error) { - // TODO: this may be premature optimization - ds := getSpecificationSetFor(options...) - h := getFmtAppendExecutor() - defer releasdeFmtAppendExecutor(h) - - h.t = t - if err := compile(h, p, ds); err != nil { - return "", errors.Wrap(err, `failed to compile format`) - } - - return string(h.dst), nil -} - -// Strftime is the object that represents a compiled strftime pattern -type Strftime struct { - pattern string - compiled appenderList -} - -// New creates a new Strftime object. If the compilation fails, then -// an error is returned in the second argument. -func New(p string, options ...Option) (*Strftime, error) { - // TODO: this may be premature optimization - ds := getSpecificationSetFor(options...) - - var h appenderListBuilder - h.list = &combiningAppend{} - - if err := compile(&h, p, ds); err != nil { - return nil, errors.Wrap(err, `failed to compile format`) - } - - return &Strftime{ - pattern: p, - compiled: h.list.list, - }, nil -} - -// Pattern returns the original pattern string -func (f *Strftime) Pattern() string { - return f.pattern -} - -// Format takes the destination `dst` and time `t`. It formats the date/time -// using the pre-compiled pattern, and outputs the results to `dst` -func (f *Strftime) Format(dst io.Writer, t time.Time) error { - const bufSize = 64 - var b []byte - max := len(f.pattern) + 10 - if max < bufSize { - var buf [bufSize]byte - b = buf[:0] - } else { - b = make([]byte, 0, max) - } - if _, err := dst.Write(f.format(b, t)); err != nil { - return err - } - return nil -} - -// Dump outputs the internal structure of the formatter, for debugging purposes. -// Please do NOT assume the output format to be fixed: it is expected to change -// in the future. -func (f *Strftime) Dump(out io.Writer) { - f.compiled.dump(out) -} - -func (f *Strftime) format(b []byte, t time.Time) []byte { - for _, w := range f.compiled { - b = w.Append(b, t) - } - return b -} - -// FormatString takes the time `t` and formats it, returning the -// string containing the formated data. -func (f *Strftime) FormatString(t time.Time) string { - const bufSize = 64 - var b []byte - max := len(f.pattern) + 10 - if max < bufSize { - var buf [bufSize]byte - b = buf[:0] - } else { - b = make([]byte, 0, max) - } - return string(f.format(b, t)) -} diff --git a/vendor/github.com/mattn/go-colorable/colorable_windows.go b/vendor/github.com/mattn/go-colorable/colorable_windows.go index b9e93634..04c4229c 100644 --- a/vendor/github.com/mattn/go-colorable/colorable_windows.go +++ b/vendor/github.com/mattn/go-colorable/colorable_windows.go @@ -10,6 +10,7 @@ import ( "os" "strconv" "strings" + "sync" "syscall" "unsafe" @@ -27,6 +28,7 @@ const ( backgroundRed = 0x40 backgroundIntensity = 0x80 backgroundMask = (backgroundRed | backgroundBlue | backgroundGreen | backgroundIntensity) + commonLvbUnderscore = 0x8000 cENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x4 ) @@ -93,6 +95,7 @@ type Writer struct { oldattr word oldpos coord rest bytes.Buffer + mutex sync.Mutex } // NewColorable returns new instance of Writer which handles escape sequence from File. @@ -432,6 +435,8 @@ func atoiWithDefault(s string, def int) (int, error) { // Write writes data on console func (w *Writer) Write(data []byte) (n int, err error) { + w.mutex.Lock() + defer w.mutex.Unlock() var csbi consoleScreenBufferInfo procGetConsoleScreenBufferInfo.Call(uintptr(w.handle), uintptr(unsafe.Pointer(&csbi))) @@ -683,14 +688,19 @@ loop: switch { case n == 0 || n == 100: attr = w.oldattr - case 1 <= n && n <= 5: + case n == 4: + attr |= commonLvbUnderscore + case (1 <= n && n <= 3) || n == 5: attr |= foregroundIntensity - case n == 7: - attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4) - case n == 22 || n == 25: - attr |= foregroundIntensity - case n == 27: - attr = ((attr & foregroundMask) << 4) | ((attr & backgroundMask) >> 4) + case n == 7 || n == 27: + attr = + (attr &^ (foregroundMask | backgroundMask)) | + ((attr & foregroundMask) << 4) | + ((attr & backgroundMask) >> 4) + case n == 22: + attr &^= foregroundIntensity + case n == 24: + attr &^= commonLvbUnderscore case 30 <= n && n <= 37: attr &= backgroundMask if (n-30)&1 != 0 { diff --git a/vendor/github.com/pbnjay/strptime/README.md b/vendor/github.com/pbnjay/strptime/README.md deleted file mode 100644 index 64afef2b..00000000 --- a/vendor/github.com/pbnjay/strptime/README.md +++ /dev/null @@ -1,26 +0,0 @@ -Strptime -======== - -Simple C-style strptime wrappers for Go's `time.Parse`. Support is available -for the following subset of format strings (descriptions blatantly stolen from -python docs): - - %d Day of the month as a zero-padded decimal number. - %b Month as locale’s abbreviated name. - %B Month as locale’s full name. - %m Month as a zero-padded decimal number. - %y Year without century as a zero-padded decimal number. - %Y Year with century as a decimal number. - %H Hour (24-hour clock) as a zero-padded decimal number. - %I Hour (12-hour clock) as a zero-padded decimal number. - %p Locale’s equivalent of either AM or PM. - %M Minute as a zero-padded decimal number. - %S Second as a zero-padded decimal number. - %f Microsecond as a decimal number, zero-padded on the left. - %z UTC offset in the form +HHMM or -HHMM. - %Z Time zone name. UTC, EST, CST - %% A literal '%' character. - -A small test suite is included to test many common use cases. Code is available -under the MIT License in case anyone else has a need for it like I do. - diff --git a/vendor/github.com/pbnjay/strptime/strptime.go b/vendor/github.com/pbnjay/strptime/strptime.go deleted file mode 100644 index 94b88f8f..00000000 --- a/vendor/github.com/pbnjay/strptime/strptime.go +++ /dev/null @@ -1,202 +0,0 @@ -/* -Copyright (c) 2013 Jeremy Jay - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ - -// Package strptime provides a C-style strptime wrappers for time.Parse. -// -// It supports the following subset of format strings (stolen from python docs): -// %d Day of the month as a zero-padded decimal number. -// %b Month as locale’s abbreviated name. -// %B Month as locale’s full name. -// %m Month as a zero-padded decimal number. -// %y Year without century as a zero-padded decimal number. -// %Y Year with century as a decimal number. -// %H Hour (24-hour clock) as a zero-padded decimal number. -// %I Hour (12-hour clock) as a zero-padded decimal number. -// %p Locale’s equivalent of either AM or PM. -// %M Minute as a zero-padded decimal number. -// %S Second as a zero-padded decimal number. -// %f Microsecond as a decimal number, zero-padded on the left. -// %z UTC offset in the form +HHMM or -HHMM. -// %Z Time zone name. UTC, EST, CST -// %% A literal '%' character. -// -// BUG(pbnjay): If an unsupported specifier is used, it may NOT directly precede a -// supported specifier (i.e. there must be intervening text to match first) -package strptime - -import ( - "errors" - "strings" - "time" -) - -// Parse accepts a percent-encoded strptime format string, converts it for use with -// time.Parse, and returns the resulting time.Time value. If non-date-related format -// text does not match within the string value, then ErrFormatMismatch will be returned. -// Errors from time.Parse are passed through untouched. -// -// If a unsupported format specifier is provided, it will be ignored and matching -// text will be skipped. To receive errors for unsupported formats, use ParseStrict or call Check. -func Parse(value, format string) (time.Time, error) { - return strptime(value, format, true) -} - -// ParseStrict returns ErrFormatUnsupported for unsupported formats strings, but is otherwise -// identical to Parse. -func ParseStrict(value, format string) (time.Time, error) { - return strptime(value, format, false) -} - -// MustParse is a wrapper for Parse which panics on any error. -func MustParse(value, format string) time.Time { - t, err := strptime(value, format, true) - if err != nil { - panic(err) - } - return t -} - -// Check verifies that format is a fully-supported strptime format string for this implementation. -func Check(format string) error { - parts := strings.Split(format, "%") - for _, ps := range parts { - // since we split on '%', this is the format code - c := int(ps[0]) - if c == '%' { - continue - } - if _, found := formatMap[c]; !found { - return ErrFormatUnsupported - } - } - - return nil -} - -func strptime(value, format string, ignoreUnsupported bool) (time.Time, error) { - parseStr := "" - parseFmt := "" - vi := 0 - - parts := strings.Split(format, "%") - for pi, ps := range parts { - if pi == 0 { - // check prefix string - if value[:len(ps)] != ps { - return time.Time{}, ErrFormatMismatch - } - vi += len(ps) - continue - } - // since we split on '%', this is the format code - c := int(ps[0]) - - if c == '%' { // handle %% quickly - if ps != value[vi:vi+len(ps)] { - return time.Time{}, ErrFormatMismatch - } - vi += len(ps) - continue - } - - // Check if format is supported and get the time.Parse translation - f, supported := formatMap[c] - if !supported && !ignoreUnsupported { - return time.Time{}, ErrFormatUnsupported - } - - // Check the intervening text between format strings. - // There may be some edge cases where this isn't quite right - // but if that's the case you've got other problems... - vj := len(ps) - 1 - if vj > 0 { - vj = strings.Index(value[vi:], ps[1:]) - } - if vj == -1 { - return time.Time{}, ErrFormatMismatch - } - - if supported { - // Build up a new format and date string - if vj == 0 { // no intervening text - if c == 'f' { - vj = len(value) - vi - } else { - vj = len(f) - if vj > len(value)-vi { - return time.Time{}, ErrFormatMismatch - } - } - } - - if c == 'f' { - parseFmt += "." + f - parseStr += "." + value[vi:vi+vj] - } else if c == 'p' { - parseFmt += " " + f - parseStr += " " + strings.ToUpper(value[vi:vi+vj]) - } else { - parseFmt += " " + f - parseStr += " " + value[vi:vi+vj] - } - } - - if !supported && vj == 0 { - // ignore to the end of the string - vi = len(value) - } else { - vi += (len(ps) - 1) + vj - } - } - - if vi < len(value) { - // extra text on end of value - return time.Time{}, ErrFormatMismatch - } - - return time.Parse(parseFmt, parseStr) -} - -var ( - // ErrFormatMismatch means that intervening text in the strptime format string did not - // match within the parsed string. - ErrFormatMismatch = errors.New("date format mismatch") - // ErrFormatUnsupported means that the format string includes unsupport percent-escapes. - ErrFormatUnsupported = errors.New("date format contains unsupported percent-encodings") - - formatMap = map[int]string{ - 'd': "02", - 'b': "Jan", - 'B': "January", - 'm': "01", - 'y': "06", - 'Y': "2006", - 'H': "15", - 'I': "03", - 'p': "PM", - 'M': "04", - 'S': "05", - 'f': "999999", - 'z': "-0700", - 'Z': "MST", - } -) diff --git a/vendor/github.com/pkg/errors/.gitignore b/vendor/github.com/pkg/errors/.gitignore deleted file mode 100644 index daf913b1..00000000 --- a/vendor/github.com/pkg/errors/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Compiled Object files, Static and Dynamic libs (Shared Objects) -*.o -*.a -*.so - -# Folders -_obj -_test - -# Architecture specific extensions/prefixes -*.[568vq] -[568vq].out - -*.cgo1.go -*.cgo2.c -_cgo_defun.c -_cgo_gotypes.go -_cgo_export.* - -_testmain.go - -*.exe -*.test -*.prof diff --git a/vendor/github.com/pkg/errors/.travis.yml b/vendor/github.com/pkg/errors/.travis.yml deleted file mode 100644 index 9159de03..00000000 --- a/vendor/github.com/pkg/errors/.travis.yml +++ /dev/null @@ -1,10 +0,0 @@ -language: go -go_import_path: github.com/pkg/errors -go: - - 1.11.x - - 1.12.x - - 1.13.x - - tip - -script: - - make check diff --git a/vendor/github.com/pkg/errors/LICENSE b/vendor/github.com/pkg/errors/LICENSE deleted file mode 100644 index 835ba3e7..00000000 --- a/vendor/github.com/pkg/errors/LICENSE +++ /dev/null @@ -1,23 +0,0 @@ -Copyright (c) 2015, Dave Cheney -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/pkg/errors/Makefile b/vendor/github.com/pkg/errors/Makefile deleted file mode 100644 index ce9d7cde..00000000 --- a/vendor/github.com/pkg/errors/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -PKGS := github.com/pkg/errors -SRCDIRS := $(shell go list -f '{{.Dir}}' $(PKGS)) -GO := go - -check: test vet gofmt misspell unconvert staticcheck ineffassign unparam - -test: - $(GO) test $(PKGS) - -vet: | test - $(GO) vet $(PKGS) - -staticcheck: - $(GO) get honnef.co/go/tools/cmd/staticcheck - staticcheck -checks all $(PKGS) - -misspell: - $(GO) get github.com/client9/misspell/cmd/misspell - misspell \ - -locale GB \ - -error \ - *.md *.go - -unconvert: - $(GO) get github.com/mdempsky/unconvert - unconvert -v $(PKGS) - -ineffassign: - $(GO) get github.com/gordonklaus/ineffassign - find $(SRCDIRS) -name '*.go' | xargs ineffassign - -pedantic: check errcheck - -unparam: - $(GO) get mvdan.cc/unparam - unparam ./... - -errcheck: - $(GO) get github.com/kisielk/errcheck - errcheck $(PKGS) - -gofmt: - @echo Checking code is gofmted - @test -z "$(shell gofmt -s -l -d -e $(SRCDIRS) | tee /dev/stderr)" diff --git a/vendor/github.com/pkg/errors/README.md b/vendor/github.com/pkg/errors/README.md deleted file mode 100644 index 54dfdcb1..00000000 --- a/vendor/github.com/pkg/errors/README.md +++ /dev/null @@ -1,59 +0,0 @@ -# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors) [![Sourcegraph](https://sourcegraph.com/github.com/pkg/errors/-/badge.svg)](https://sourcegraph.com/github.com/pkg/errors?badge) - -Package errors provides simple error handling primitives. - -`go get github.com/pkg/errors` - -The traditional error handling idiom in Go is roughly akin to -```go -if err != nil { - return err -} -``` -which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error. - -## Adding context to an error - -The errors.Wrap function returns a new error that adds context to the original error. For example -```go -_, err := ioutil.ReadAll(r) -if err != nil { - return errors.Wrap(err, "read failed") -} -``` -## Retrieving the cause of an error - -Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`. -```go -type causer interface { - Cause() error -} -``` -`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example: -```go -switch err := errors.Cause(err).(type) { -case *MyError: - // handle specifically -default: - // unknown error -} -``` - -[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors). - -## Roadmap - -With the upcoming [Go2 error proposals](https://go.googlesource.com/proposal/+/master/design/go2draft.md) this package is moving into maintenance mode. The roadmap for a 1.0 release is as follows: - -- 0.9. Remove pre Go 1.9 and Go 1.10 support, address outstanding pull requests (if possible) -- 1.0. Final release. - -## Contributing - -Because of the Go2 errors changes, this package is not accepting proposals for new functionality. With that said, we welcome pull requests, bug fixes and issue reports. - -Before sending a PR, please discuss your change by raising an issue. - -## License - -BSD-2-Clause diff --git a/vendor/github.com/pkg/errors/appveyor.yml b/vendor/github.com/pkg/errors/appveyor.yml deleted file mode 100644 index a932eade..00000000 --- a/vendor/github.com/pkg/errors/appveyor.yml +++ /dev/null @@ -1,32 +0,0 @@ -version: build-{build}.{branch} - -clone_folder: C:\gopath\src\github.com\pkg\errors -shallow_clone: true # for startup speed - -environment: - GOPATH: C:\gopath - -platform: - - x64 - -# http://www.appveyor.com/docs/installed-software -install: - # some helpful output for debugging builds - - go version - - go env - # pre-installed MinGW at C:\MinGW is 32bit only - # but MSYS2 at C:\msys64 has mingw64 - - set PATH=C:\msys64\mingw64\bin;%PATH% - - gcc --version - - g++ --version - -build_script: - - go install -v ./... - -test_script: - - set PATH=C:\gopath\bin;%PATH% - - go test -v ./... - -#artifacts: -# - path: '%GOPATH%\bin\*.exe' -deploy: off diff --git a/vendor/github.com/pkg/errors/errors.go b/vendor/github.com/pkg/errors/errors.go deleted file mode 100644 index 161aea25..00000000 --- a/vendor/github.com/pkg/errors/errors.go +++ /dev/null @@ -1,288 +0,0 @@ -// Package errors provides simple error handling primitives. -// -// The traditional error handling idiom in Go is roughly akin to -// -// if err != nil { -// return err -// } -// -// which when applied recursively up the call stack results in error reports -// without context or debugging information. The errors package allows -// programmers to add context to the failure path in their code in a way -// that does not destroy the original value of the error. -// -// Adding context to an error -// -// The errors.Wrap function returns a new error that adds context to the -// original error by recording a stack trace at the point Wrap is called, -// together with the supplied message. For example -// -// _, err := ioutil.ReadAll(r) -// if err != nil { -// return errors.Wrap(err, "read failed") -// } -// -// If additional control is required, the errors.WithStack and -// errors.WithMessage functions destructure errors.Wrap into its component -// operations: annotating an error with a stack trace and with a message, -// respectively. -// -// Retrieving the cause of an error -// -// Using errors.Wrap constructs a stack of errors, adding context to the -// preceding error. Depending on the nature of the error it may be necessary -// to reverse the operation of errors.Wrap to retrieve the original error -// for inspection. Any error value which implements this interface -// -// type causer interface { -// Cause() error -// } -// -// can be inspected by errors.Cause. errors.Cause will recursively retrieve -// the topmost error that does not implement causer, which is assumed to be -// the original cause. For example: -// -// switch err := errors.Cause(err).(type) { -// case *MyError: -// // handle specifically -// default: -// // unknown error -// } -// -// Although the causer interface is not exported by this package, it is -// considered a part of its stable public interface. -// -// Formatted printing of errors -// -// All error values returned from this package implement fmt.Formatter and can -// be formatted by the fmt package. The following verbs are supported: -// -// %s print the error. If the error has a Cause it will be -// printed recursively. -// %v see %s -// %+v extended format. Each Frame of the error's StackTrace will -// be printed in detail. -// -// Retrieving the stack trace of an error or wrapper -// -// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are -// invoked. This information can be retrieved with the following interface: -// -// type stackTracer interface { -// StackTrace() errors.StackTrace -// } -// -// The returned errors.StackTrace type is defined as -// -// type StackTrace []Frame -// -// The Frame type represents a call site in the stack trace. Frame supports -// the fmt.Formatter interface that can be used for printing information about -// the stack trace of this error. For example: -// -// if err, ok := err.(stackTracer); ok { -// for _, f := range err.StackTrace() { -// fmt.Printf("%+s:%d\n", f, f) -// } -// } -// -// Although the stackTracer interface is not exported by this package, it is -// considered a part of its stable public interface. -// -// See the documentation for Frame.Format for more details. -package errors - -import ( - "fmt" - "io" -) - -// New returns an error with the supplied message. -// New also records the stack trace at the point it was called. -func New(message string) error { - return &fundamental{ - msg: message, - stack: callers(), - } -} - -// Errorf formats according to a format specifier and returns the string -// as a value that satisfies error. -// Errorf also records the stack trace at the point it was called. -func Errorf(format string, args ...interface{}) error { - return &fundamental{ - msg: fmt.Sprintf(format, args...), - stack: callers(), - } -} - -// fundamental is an error that has a message and a stack, but no caller. -type fundamental struct { - msg string - *stack -} - -func (f *fundamental) Error() string { return f.msg } - -func (f *fundamental) Format(s fmt.State, verb rune) { - switch verb { - case 'v': - if s.Flag('+') { - io.WriteString(s, f.msg) - f.stack.Format(s, verb) - return - } - fallthrough - case 's': - io.WriteString(s, f.msg) - case 'q': - fmt.Fprintf(s, "%q", f.msg) - } -} - -// WithStack annotates err with a stack trace at the point WithStack was called. -// If err is nil, WithStack returns nil. -func WithStack(err error) error { - if err == nil { - return nil - } - return &withStack{ - err, - callers(), - } -} - -type withStack struct { - error - *stack -} - -func (w *withStack) Cause() error { return w.error } - -// Unwrap provides compatibility for Go 1.13 error chains. -func (w *withStack) Unwrap() error { return w.error } - -func (w *withStack) Format(s fmt.State, verb rune) { - switch verb { - case 'v': - if s.Flag('+') { - fmt.Fprintf(s, "%+v", w.Cause()) - w.stack.Format(s, verb) - return - } - fallthrough - case 's': - io.WriteString(s, w.Error()) - case 'q': - fmt.Fprintf(s, "%q", w.Error()) - } -} - -// Wrap returns an error annotating err with a stack trace -// at the point Wrap is called, and the supplied message. -// If err is nil, Wrap returns nil. -func Wrap(err error, message string) error { - if err == nil { - return nil - } - err = &withMessage{ - cause: err, - msg: message, - } - return &withStack{ - err, - callers(), - } -} - -// Wrapf returns an error annotating err with a stack trace -// at the point Wrapf is called, and the format specifier. -// If err is nil, Wrapf returns nil. -func Wrapf(err error, format string, args ...interface{}) error { - if err == nil { - return nil - } - err = &withMessage{ - cause: err, - msg: fmt.Sprintf(format, args...), - } - return &withStack{ - err, - callers(), - } -} - -// WithMessage annotates err with a new message. -// If err is nil, WithMessage returns nil. -func WithMessage(err error, message string) error { - if err == nil { - return nil - } - return &withMessage{ - cause: err, - msg: message, - } -} - -// WithMessagef annotates err with the format specifier. -// If err is nil, WithMessagef returns nil. -func WithMessagef(err error, format string, args ...interface{}) error { - if err == nil { - return nil - } - return &withMessage{ - cause: err, - msg: fmt.Sprintf(format, args...), - } -} - -type withMessage struct { - cause error - msg string -} - -func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() } -func (w *withMessage) Cause() error { return w.cause } - -// Unwrap provides compatibility for Go 1.13 error chains. -func (w *withMessage) Unwrap() error { return w.cause } - -func (w *withMessage) Format(s fmt.State, verb rune) { - switch verb { - case 'v': - if s.Flag('+') { - fmt.Fprintf(s, "%+v\n", w.Cause()) - io.WriteString(s, w.msg) - return - } - fallthrough - case 's', 'q': - io.WriteString(s, w.Error()) - } -} - -// Cause returns the underlying cause of the error, if possible. -// An error value has a cause if it implements the following -// interface: -// -// type causer interface { -// Cause() error -// } -// -// If the error does not implement Cause, the original error will -// be returned. If the error is nil, nil will be returned without further -// investigation. -func Cause(err error) error { - type causer interface { - Cause() error - } - - for err != nil { - cause, ok := err.(causer) - if !ok { - break - } - err = cause.Cause() - } - return err -} diff --git a/vendor/github.com/pkg/errors/go113.go b/vendor/github.com/pkg/errors/go113.go deleted file mode 100644 index be0d10d0..00000000 --- a/vendor/github.com/pkg/errors/go113.go +++ /dev/null @@ -1,38 +0,0 @@ -// +build go1.13 - -package errors - -import ( - stderrors "errors" -) - -// Is reports whether any error in err's chain matches target. -// -// The chain consists of err itself followed by the sequence of errors obtained by -// repeatedly calling Unwrap. -// -// An error is considered to match a target if it is equal to that target or if -// it implements a method Is(error) bool such that Is(target) returns true. -func Is(err, target error) bool { return stderrors.Is(err, target) } - -// As finds the first error in err's chain that matches target, and if so, sets -// target to that error value and returns true. -// -// The chain consists of err itself followed by the sequence of errors obtained by -// repeatedly calling Unwrap. -// -// An error matches target if the error's concrete value is assignable to the value -// pointed to by target, or if the error has a method As(interface{}) bool such that -// As(target) returns true. In the latter case, the As method is responsible for -// setting target. -// -// As will panic if target is not a non-nil pointer to either a type that implements -// error, or to any interface type. As returns false if err is nil. -func As(err error, target interface{}) bool { return stderrors.As(err, target) } - -// Unwrap returns the result of calling the Unwrap method on err, if err's -// type contains an Unwrap method returning error. -// Otherwise, Unwrap returns nil. -func Unwrap(err error) error { - return stderrors.Unwrap(err) -} diff --git a/vendor/github.com/pkg/errors/stack.go b/vendor/github.com/pkg/errors/stack.go deleted file mode 100644 index 779a8348..00000000 --- a/vendor/github.com/pkg/errors/stack.go +++ /dev/null @@ -1,177 +0,0 @@ -package errors - -import ( - "fmt" - "io" - "path" - "runtime" - "strconv" - "strings" -) - -// Frame represents a program counter inside a stack frame. -// For historical reasons if Frame is interpreted as a uintptr -// its value represents the program counter + 1. -type Frame uintptr - -// pc returns the program counter for this frame; -// multiple frames may have the same PC value. -func (f Frame) pc() uintptr { return uintptr(f) - 1 } - -// file returns the full path to the file that contains the -// function for this Frame's pc. -func (f Frame) file() string { - fn := runtime.FuncForPC(f.pc()) - if fn == nil { - return "unknown" - } - file, _ := fn.FileLine(f.pc()) - return file -} - -// line returns the line number of source code of the -// function for this Frame's pc. -func (f Frame) line() int { - fn := runtime.FuncForPC(f.pc()) - if fn == nil { - return 0 - } - _, line := fn.FileLine(f.pc()) - return line -} - -// name returns the name of this function, if known. -func (f Frame) name() string { - fn := runtime.FuncForPC(f.pc()) - if fn == nil { - return "unknown" - } - return fn.Name() -} - -// Format formats the frame according to the fmt.Formatter interface. -// -// %s source file -// %d source line -// %n function name -// %v equivalent to %s:%d -// -// Format accepts flags that alter the printing of some verbs, as follows: -// -// %+s function name and path of source file relative to the compile time -// GOPATH separated by \n\t (\n\t) -// %+v equivalent to %+s:%d -func (f Frame) Format(s fmt.State, verb rune) { - switch verb { - case 's': - switch { - case s.Flag('+'): - io.WriteString(s, f.name()) - io.WriteString(s, "\n\t") - io.WriteString(s, f.file()) - default: - io.WriteString(s, path.Base(f.file())) - } - case 'd': - io.WriteString(s, strconv.Itoa(f.line())) - case 'n': - io.WriteString(s, funcname(f.name())) - case 'v': - f.Format(s, 's') - io.WriteString(s, ":") - f.Format(s, 'd') - } -} - -// MarshalText formats a stacktrace Frame as a text string. The output is the -// same as that of fmt.Sprintf("%+v", f), but without newlines or tabs. -func (f Frame) MarshalText() ([]byte, error) { - name := f.name() - if name == "unknown" { - return []byte(name), nil - } - return []byte(fmt.Sprintf("%s %s:%d", name, f.file(), f.line())), nil -} - -// StackTrace is stack of Frames from innermost (newest) to outermost (oldest). -type StackTrace []Frame - -// Format formats the stack of Frames according to the fmt.Formatter interface. -// -// %s lists source files for each Frame in the stack -// %v lists the source file and line number for each Frame in the stack -// -// Format accepts flags that alter the printing of some verbs, as follows: -// -// %+v Prints filename, function, and line number for each Frame in the stack. -func (st StackTrace) Format(s fmt.State, verb rune) { - switch verb { - case 'v': - switch { - case s.Flag('+'): - for _, f := range st { - io.WriteString(s, "\n") - f.Format(s, verb) - } - case s.Flag('#'): - fmt.Fprintf(s, "%#v", []Frame(st)) - default: - st.formatSlice(s, verb) - } - case 's': - st.formatSlice(s, verb) - } -} - -// formatSlice will format this StackTrace into the given buffer as a slice of -// Frame, only valid when called with '%s' or '%v'. -func (st StackTrace) formatSlice(s fmt.State, verb rune) { - io.WriteString(s, "[") - for i, f := range st { - if i > 0 { - io.WriteString(s, " ") - } - f.Format(s, verb) - } - io.WriteString(s, "]") -} - -// stack represents a stack of program counters. -type stack []uintptr - -func (s *stack) Format(st fmt.State, verb rune) { - switch verb { - case 'v': - switch { - case st.Flag('+'): - for _, pc := range *s { - f := Frame(pc) - fmt.Fprintf(st, "\n%+v", f) - } - } - } -} - -func (s *stack) StackTrace() StackTrace { - f := make([]Frame, len(*s)) - for i := 0; i < len(f); i++ { - f[i] = Frame((*s)[i]) - } - return f -} - -func callers() *stack { - const depth = 32 - var pcs [depth]uintptr - n := runtime.Callers(3, pcs[:]) - var st stack = pcs[0:n] - return &st -} - -// funcname removes the path prefix component of a function's name reported by func.Name(). -func funcname(name string) string { - i := strings.LastIndex(name, "/") - name = name[i+1:] - i = strings.Index(name, ".") - return name[i+1:] -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 8c67ce95..b0a45c2b 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -2,16 +2,13 @@ github.com/Eun/go-convert # github.com/Eun/go-doppelgangerreader v0.0.0-20190911075941-30f1527f16b2 github.com/Eun/go-doppelgangerreader -# github.com/Eun/yaegi-template v1.5.5 +# github.com/Eun/yaegi-template v1.5.10 github.com/Eun/yaegi-template/codebuffer # github.com/aaw/maybe_tls v0.0.0-20160803104303-89c499bcc6aa github.com/aaw/maybe_tls -# github.com/alecthomas/participle v0.4.2-0.20191220090139-9fbceec1d131 -github.com/alecthomas/participle -github.com/alecthomas/participle/lexer # github.com/araddon/dateparse v0.0.0-20200409225146-d820a6159ab1 github.com/araddon/dateparse -# github.com/dave/jennifer v1.4.0 +# github.com/dave/jennifer v1.4.1 github.com/dave/jennifer/jen # github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew/spew @@ -21,21 +18,21 @@ github.com/google/go-cmp/cmp/internal/diff github.com/google/go-cmp/cmp/internal/flags github.com/google/go-cmp/cmp/internal/function github.com/google/go-cmp/cmp/internal/value -# github.com/gookit/color v1.2.3 +# github.com/gookit/color v1.3.2 github.com/gookit/color -# github.com/itchyny/astgen-go v0.0.0-20200116103543-aaa595cf980e +# github.com/itchyny/astgen-go v0.0.0-20200815150004-12a293722290 github.com/itchyny/astgen-go -# github.com/itchyny/gojq v0.10.1 +# github.com/itchyny/gojq v0.11.2 github.com/itchyny/gojq +# github.com/itchyny/timefmt-go v0.1.1 +github.com/itchyny/timefmt-go # github.com/json-iterator/go v1.1.10 github.com/json-iterator/go # github.com/k0kubun/pp v3.0.1+incompatible github.com/k0kubun/pp -# github.com/lestrrat-go/strftime v1.0.1 -github.com/lestrrat-go/strftime # github.com/lunixbochs/vtclean v1.0.0 github.com/lunixbochs/vtclean -# github.com/mattn/go-colorable v0.1.6 +# github.com/mattn/go-colorable v0.1.7 github.com/mattn/go-colorable # github.com/mattn/go-isatty v0.0.12 github.com/mattn/go-isatty @@ -43,16 +40,12 @@ github.com/mattn/go-isatty github.com/modern-go/concurrent # github.com/modern-go/reflect2 v1.0.1 github.com/modern-go/reflect2 -# github.com/pbnjay/strptime v0.0.0-20140226051138-5c05b0d668c9 -github.com/pbnjay/strptime -# github.com/pkg/errors v0.9.1 -github.com/pkg/errors # github.com/pmezard/go-difflib v1.0.0 github.com/pmezard/go-difflib/difflib # github.com/stretchr/testify v1.6.1 github.com/stretchr/testify/assert github.com/stretchr/testify/require -# github.com/tidwall/pretty v1.0.1 +# github.com/tidwall/pretty v1.0.2 github.com/tidwall/pretty # go.uber.org/atomic v1.7.0 go.uber.org/atomic