Repository: expr-lang/expr Branch: master Commit: b90e77c64fb9 Files: 230 Total size: 2.8 MB Directory structure: gitextract_ewtnex4r/ ├── .gitattributes ├── .github/ │ ├── FUNDING.yml │ ├── images/ │ │ └── demo.tape │ ├── scripts/ │ │ └── coverage.mjs │ └── workflows/ │ ├── build.yml │ ├── check.yml │ ├── diff.yml │ ├── fuzz.yml │ └── test.yml ├── .gitignore ├── LICENSE ├── README.md ├── SECURITY.md ├── ast/ │ ├── dump.go │ ├── find.go │ ├── find_test.go │ ├── node.go │ ├── print.go │ ├── print_test.go │ ├── visitor.go │ └── visitor_test.go ├── bench_test.go ├── builtin/ │ ├── builtin.go │ ├── builtin_test.go │ ├── function.go │ ├── lib.go │ ├── utils.go │ └── validation.go ├── checker/ │ ├── checker.go │ ├── checker_bench_test.go │ ├── checker_test.go │ ├── info.go │ ├── info_test.go │ └── nature/ │ ├── nature.go │ └── utils.go ├── compiler/ │ ├── compiler.go │ └── compiler_test.go ├── conf/ │ ├── config.go │ └── env.go ├── debug/ │ ├── debugger.go │ ├── go.mod │ └── go.sum ├── docgen/ │ ├── README.md │ ├── docgen.go │ ├── docgen_test.go │ └── markdown.go ├── docs/ │ ├── configuration.md │ ├── environment.md │ ├── functions.md │ ├── getting-started.md │ ├── language-definition.md │ ├── patch.md │ └── visitor.md ├── expr.go ├── expr_test.go ├── file/ │ ├── error.go │ ├── location.go │ ├── source.go │ └── source_test.go ├── go.mod ├── internal/ │ ├── deref/ │ │ ├── deref.go │ │ └── deref_test.go │ ├── difflib/ │ │ ├── difflib.go │ │ └── difflib_test.go │ ├── ring/ │ │ ├── ring.go │ │ └── ring_test.go │ ├── spew/ │ │ ├── bypass.go │ │ ├── bypasssafe.go │ │ ├── common.go │ │ ├── common_test.go │ │ ├── config.go │ │ ├── doc.go │ │ ├── dump.go │ │ ├── dump_test.go │ │ ├── dumpcgo_test.go │ │ ├── dumpnocgo_test.go │ │ ├── example_test.go │ │ ├── format.go │ │ ├── format_test.go │ │ ├── internal_test.go │ │ ├── internalunsafe_test.go │ │ ├── spew.go │ │ ├── spew_test.go │ │ └── testdata/ │ │ └── dumpcgo.go │ └── testify/ │ ├── assert/ │ │ ├── assertion_compare.go │ │ ├── assertion_compare_test.go │ │ ├── assertion_format.go │ │ ├── assertion_format.go.tmpl │ │ ├── assertion_forward.go │ │ ├── assertion_forward.go.tmpl │ │ ├── assertion_order.go │ │ ├── assertion_order_test.go │ │ ├── assertions.go │ │ ├── assertions_test.go │ │ ├── doc.go │ │ ├── errors.go │ │ ├── forward_assertions.go │ │ ├── forward_assertions_test.go │ │ ├── http_assertions.go │ │ ├── http_assertions_test.go │ │ └── internal/ │ │ └── unsafetests/ │ │ ├── doc.go │ │ └── unsafetests_test.go │ └── require/ │ ├── doc.go │ ├── forward_requirements.go │ ├── forward_requirements_test.go │ ├── require.go │ ├── require.go.tmpl │ ├── require_forward.go │ ├── require_forward.go.tmpl │ ├── requirements.go │ └── requirements_test.go ├── optimizer/ │ ├── const_expr.go │ ├── count_any.go │ ├── count_any_test.go │ ├── count_threshold.go │ ├── count_threshold_test.go │ ├── filter_first.go │ ├── filter_last.go │ ├── filter_len.go │ ├── filter_map.go │ ├── filter_map_test.go │ ├── fold.go │ ├── fold_test.go │ ├── in_array.go │ ├── in_range.go │ ├── optimizer.go │ ├── optimizer_test.go │ ├── predicate_combination.go │ ├── sum_array.go │ ├── sum_array_test.go │ ├── sum_map.go │ ├── sum_map_test.go │ ├── sum_range.go │ └── sum_range_test.go ├── parser/ │ ├── bench_test.go │ ├── lexer/ │ │ ├── lexer.go │ │ ├── lexer_test.go │ │ ├── state.go │ │ ├── token.go │ │ └── utils.go │ ├── operator/ │ │ └── operator.go │ ├── parser.go │ ├── parser_test.go │ └── utils/ │ └── utils.go ├── patcher/ │ ├── operator_override.go │ ├── value/ │ │ ├── bench_test.go │ │ ├── value.go │ │ ├── value_example_test.go │ │ └── value_test.go │ ├── with_context.go │ ├── with_context_test.go │ ├── with_timezone.go │ └── with_timezone_test.go ├── repl/ │ ├── go.mod │ ├── go.sum │ └── repl.go ├── test/ │ ├── bench/ │ │ └── bench_call_test.go │ ├── coredns/ │ │ ├── coredns.go │ │ └── coredns_test.go │ ├── crowdsec/ │ │ ├── crowdsec.go │ │ ├── crowdsec_test.go │ │ └── funcs.go │ ├── deref/ │ │ └── deref_test.go │ ├── examples/ │ │ ├── examples_test.go │ │ └── markdown.go │ ├── fuzz/ │ │ ├── fuzz_corpus.sh │ │ ├── fuzz_corpus.txt │ │ ├── fuzz_env.go │ │ ├── fuzz_expr.dict │ │ └── fuzz_test.go │ ├── gen/ │ │ ├── env.go │ │ ├── gen.go │ │ ├── gen_test.go │ │ └── utils.go │ ├── interface/ │ │ ├── interface_method_test.go │ │ └── interface_test.go │ ├── issues/ │ │ ├── 461/ │ │ │ └── issue_test.go │ │ ├── 567/ │ │ │ └── issue_test.go │ │ ├── 688/ │ │ │ └── issue_test.go │ │ ├── 723/ │ │ │ └── issue_test.go │ │ ├── 730/ │ │ │ └── issue_test.go │ │ ├── 739/ │ │ │ └── issue_test.go │ │ ├── 756/ │ │ │ └── issue_test.go │ │ ├── 785/ │ │ │ └── issue_test.go │ │ ├── 817/ │ │ │ └── issue_test.go │ │ ├── 819/ │ │ │ └── issue_test.go │ │ ├── 823/ │ │ │ └── issue_test.go │ │ ├── 830/ │ │ │ └── issue_test.go │ │ ├── 836/ │ │ │ └── issue_test.go │ │ ├── 840/ │ │ │ └── issue_test.go │ │ ├── 844/ │ │ │ └── issue_test.go │ │ ├── 854/ │ │ │ └── issue_test.go │ │ ├── 857/ │ │ │ └── issue_test.go │ │ ├── 888/ │ │ │ └── issue_test.go │ │ ├── 924/ │ │ │ └── issue_test.go │ │ └── 934/ │ │ └── issue_test.go │ ├── mock/ │ │ └── mock.go │ ├── operator/ │ │ ├── issues584/ │ │ │ └── issues584_test.go │ │ └── operator_test.go │ ├── patch/ │ │ ├── change_ident_test.go │ │ ├── patch_count_test.go │ │ ├── patch_test.go │ │ └── set_type/ │ │ └── set_type_test.go │ ├── pipes/ │ │ └── pipes_test.go │ ├── playground/ │ │ ├── data.go │ │ └── env.go │ └── time/ │ └── time_test.go ├── testdata/ │ ├── crash.txt │ ├── crowdsec.json │ ├── examples.md │ └── generated.txt ├── types/ │ ├── types.go │ └── types_test.go └── vm/ ├── debug.go ├── debug_off.go ├── debug_test.go ├── func_types/ │ └── main.go ├── func_types[generated].go ├── opcodes.go ├── program.go ├── program_test.go ├── runtime/ │ ├── helpers/ │ │ └── main.go │ ├── helpers[generated].go │ ├── helpers_test.go │ ├── runtime.go │ └── sort.go ├── utils.go ├── vm.go ├── vm_bench_test.go └── vm_test.go ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ *\[generated\].go linguist-language=txt ================================================ FILE: .github/FUNDING.yml ================================================ github: antonmedv ================================================ FILE: .github/images/demo.tape ================================================ Set Shell zsh Sleep 500ms Type "repl" Enter Sleep 500ms Type "1..9 | filter(" Sleep 500ms Type "# " Sleep 500ms Type "% 2 == 0) | map(" Sleep 500ms Type "# ^ 2" Sleep 500ms Type ")" Enter Sleep 1s Type "de" Sleep 500ms Type "bug" Enter Sleep 1.5s Enter 50 Escape Type "OB" Escape Type "OB" Escape Type "OB" Escape Type "OB" Escape Type "OB" Escape Type "OB" Escape Type "OB" Escape Type "OB" Escape Type "OB" Escape Type "OB" Escape Type "OB" Escape Type "OB" Escape Type "OB" Escape Type "OB" Enter Sleep 1.5s Escape Type "OB" Escape Type "OB" Escape Type "OB" Escape Type "OB" Escape Type "OB" Escape Type "OB" Escape Type "OB" Escape Type "OB" Escape Type "OB" Escape Type "OB" Enter Sleep 2s Escape Type "OB" Escape Type "OB" Ctrl+C Sleep 1s Ctrl+D Ctrl+D ================================================ FILE: .github/scripts/coverage.mjs ================================================ #!/usr/bin/env zx const expected = 90 const exclude = [ 'expr/test', // We do not need to test the test package. 'checker/mock', // Mocks only used for testing. 'vm/func_types', // Generated files. 'vm/runtime/helpers', // Generated files. 'internal/difflib', // Test dependency. This is vendored dependency, and ideally we also have good tests for it. 'internal/spew', // Test dependency. 'internal/testify', // Test dependency. 'patcher/value', // Contains a lot of repeating code. Ideally we should have a test for it. 'pro', // Expr Pro is not a part of the main codebase. ] cd(path.resolve(__dirname, '..', '..')) await spinner('Running tests', async () => { await $`go test -coverprofile=coverage.out -coverpkg=github.com/expr-lang/expr/... ./...` const coverage = fs.readFileSync('coverage.out').toString() .split('\n') .filter(line => { for (const ex of exclude) if (line.includes(ex)) return false return true }) .join('\n') fs.writeFileSync('coverage.out', coverage) await $`go tool cover -html=coverage.out -o coverage.html` }) const cover = await $({verbose: true})`go tool cover -func=coverage.out` const total = +cover.stdout.match(/total:\s+\(statements\)\s+(\d+\.\d+)%/)[1] if (total < expected) { echo(chalk.red(`Coverage is too low: ${total}% < ${expected}% (expected)`)) process.exit(1) } else { echo(`Coverage is good: ${chalk.green(total + '%')} >= ${expected}% (expected)`) } ================================================ FILE: .github/workflows/build.yml ================================================ name: build on: push: branches: [ master ] pull_request: branches: [ master ] jobs: test: runs-on: ubuntu-latest strategy: matrix: go-versions: [ '1.18', '1.22', '1.24', '1.25', '1.26' ] go-arch: [ '386' ] steps: - uses: actions/checkout@v3 - name: Setup Go ${{ matrix.go-version }} uses: actions/setup-go@v4 with: go-version: ${{ matrix.go-version }} - name: Build run: GOARCH=${{ matrix.go-arch }} go build ================================================ FILE: .github/workflows/check.yml ================================================ name: check on: push: branches: [ master ] pull_request: branches: [ master ] jobs: coverage: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup Go 1.18 uses: actions/setup-go@v4 with: go-version: 1.18 - name: Test run: npx zx .github/scripts/coverage.mjs ================================================ FILE: .github/workflows/diff.yml ================================================ name: diff on: pull_request: branches: [ master ] jobs: bench: runs-on: ubuntu-latest steps: - name: Setup Go 1.18 uses: actions/setup-go@v4 with: go-version: 1.18 - name: Install benchstat # NOTE: benchstat@latest requires go 1.23 since 2025-02-14 - this is the last go 1.18 ref # https://cs.opensource.google/go/x/perf/+/c95ad7d5b636f67d322a7e4832e83103d0fdd292 run: go install golang.org/x/perf/cmd/benchstat@884df5810d2850d775c2cb4885a7ea339128a17d - uses: actions/checkout@v3 - name: Benchmark new code run: go test -bench=. -benchmem -run=^$ -count=10 -timeout=30m | tee /tmp/new.txt - name: Checkout master uses: actions/checkout@v3 with: ref: master - name: Benchmark master run: go test -bench=. -benchmem -run=^$ -count=10 -timeout=30m | tee /tmp/old.txt - name: Diff run: benchstat /tmp/old.txt /tmp/new.txt ================================================ FILE: .github/workflows/fuzz.yml ================================================ name: fuzz on: [pull_request] permissions: {} jobs: fuzzing: runs-on: ubuntu-latest permissions: security-events: write steps: - name: Build Fuzzers id: build uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master with: oss-fuzz-project-name: 'expr' language: 'go' - name: Run Fuzzers uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master with: oss-fuzz-project-name: 'expr' language: 'go' fuzz-seconds: 600 output-sarif: true - name: Upload Crash uses: actions/upload-artifact@v4 if: failure() && steps.build.outcome == 'success' with: name: artifacts path: ./out/artifacts - name: Upload Sarif if: always() && steps.build.outcome == 'success' uses: github/codeql-action/upload-sarif@v3 with: # Path to SARIF file relative to the root of the repository sarif_file: cifuzz-sarif/results.sarif checkout_path: cifuzz-sarif ================================================ FILE: .github/workflows/test.yml ================================================ name: test on: push: branches: [ master ] pull_request: branches: [ master ] jobs: test: runs-on: ubuntu-latest strategy: matrix: go-versions: [ '1.18', '1.19', '1.20', '1.21', '1.22', '1.23', '1.24', '1.25', '1.26' ] steps: - uses: actions/checkout@v3 - name: Setup Go ${{ matrix.go-version }} uses: actions/setup-go@v4 with: go-version: ${{ matrix.go-version }} - name: Test run: go test ./... debug: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup Go 1.18 uses: actions/setup-go@v4 with: go-version: 1.18 - name: Test run: go test -tags=expr_debug -run=TestDebugger -v ./vm race: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup Go 1.21 uses: actions/setup-go@v4 with: go-version: 1.21 - name: Test run: go test -race . ================================================ FILE: .gitignore ================================================ *.exe *.exe~ *.dll *.so *.dylib *.test *.out *.html custom_tests.json pro/ test/avs/ ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2018 Anton Medvedev 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. ================================================ FILE: README.md ================================================

Zx logo Expr

[![test](https://github.com/expr-lang/expr/actions/workflows/test.yml/badge.svg)](https://github.com/expr-lang/expr/actions/workflows/test.yml) [![Go Report Card](https://goreportcard.com/badge/github.com/expr-lang/expr)](https://goreportcard.com/report/github.com/expr-lang/expr) [![Fuzzing Status](https://oss-fuzz-build-logs.storage.googleapis.com/badges/expr.svg)](https://bugs.chromium.org/p/oss-fuzz/issues/list?sort=-opened&can=1&q=proj:expr) [![GoDoc](https://godoc.org/github.com/expr-lang/expr?status.svg)](https://godoc.org/github.com/expr-lang/expr) **Expr** is a Go-centric expression language designed to deliver dynamic configurations with unparalleled accuracy, safety, and speed. **Expr** combines simple [syntax](https://expr-lang.org/docs/language-definition) with powerful features for ease of use: ```js // Allow only admins and moderators to moderate comments. user.Group in ["admin", "moderator"] || user.Id == comment.UserId ``` ```js // Determine whether the request is in the permitted time window. request.Time - resource.Age < duration("24h") ``` ```js // Ensure all tweets are less than 240 characters. all(tweets, len(.Content) <= 240) ``` ## Features **Expr** is a safe, fast, and intuitive expression evaluator optimized for the Go language. Here are its standout features: ### Safety and Isolation * **Memory-Safe**: Expr is designed with a focus on safety, ensuring that programs do not access unrelated memory or introduce memory vulnerabilities. * **Side-Effect-Free**: Expressions evaluated in Expr only compute outputs from their inputs, ensuring no side-effects that can change state or produce unintended results. * **Always Terminating**: Expr is designed to prevent infinite loops, ensuring that every program will conclude in a reasonable amount of time. ### Go Integration * **Seamless with Go**: Integrate Expr into your Go projects without the need to redefine types. ### Static Typing * Ensures type correctness and prevents runtime type errors. ```go out, err := expr.Compile(`name + age`) // err: invalid operation + (mismatched types string and int) // | name + age // | .....^ ``` ### User-Friendly * Provides user-friendly error messages to assist with debugging and development. ### Flexibility and Utility * **Rich Operators**: Offers a reasonable set of basic operators for a variety of applications. * **Built-in Functions**: Functions like `all`, `none`, `any`, `one`, `filter`, and `map` are provided out-of-the-box. ### Performance * **Optimized for Speed**: Expr stands out in its performance, utilizing an optimizing compiler and a bytecode virtual machine. Check out these [benchmarks](https://github.com/antonmedv/golang-expression-evaluation-comparison#readme) for more details. ## Install ``` go get github.com/expr-lang/expr ``` ## Documentation * See [Getting Started](https://expr-lang.org/docs/Getting-Started) page for developer documentation. * See [Language Definition](https://expr-lang.org/docs/language-definition) page to learn the syntax. ## Examples [Play Online](https://go.dev/play/p/XCoNXEjm3TS) ```go package main import ( "fmt" "github.com/expr-lang/expr" ) func main() { env := map[string]interface{}{ "greet": "Hello, %v!", "names": []string{"world", "you"}, "sprintf": fmt.Sprintf, } code := `sprintf(greet, names[0])` program, err := expr.Compile(code, expr.Env(env)) if err != nil { panic(err) } output, err := expr.Run(program, env) if err != nil { panic(err) } fmt.Println(output) } ``` [Play Online](https://go.dev/play/p/tz-ZneBfSuw) ```go package main import ( "fmt" "github.com/expr-lang/expr" ) type Tweet struct { Len int } type Env struct { Tweets []Tweet } func main() { code := `all(Tweets, {.Len <= 240})` program, err := expr.Compile(code, expr.Env(Env{})) if err != nil { panic(err) } env := Env{ Tweets: []Tweet{{42}, {98}, {69}}, } output, err := expr.Run(program, env) if err != nil { panic(err) } fmt.Println(output) } ``` ## Who uses Expr? * [Google](https://google.com) uses Expr as one of its expression languages on the [Google Cloud Platform](https://cloud.google.com). * [Uber](https://uber.com) uses Expr to allow customization of its Uber Eats marketplace. * [GoDaddy](https://godaddy.com) employs Expr for the customization of its GoDaddy Pro product. * [ByteDance](https://bytedance.com) incorporates Expr into its internal business rule engine. * [Aviasales](https://aviasales.ru) utilizes Expr as a business rule engine for its flight search engine. * [Alibaba](https://alibaba.com) uses Expr in a web framework for building recommendation services. * [Argo](https://argoproj.github.io) integrates Expr into Argo Rollouts and Argo Workflows for Kubernetes. * [Wish.com](https://www.wish.com) employs Expr in its decision-making rule engine for the Wish Assistant. * [OpenTelemetry](https://opentelemetry.io) integrates Expr into the OpenTelemetry Collector. * [Philips Labs](https://github.com/philips-labs/tabia) employs Expr in Tabia, a tool designed to collect insights on their code bases. * [CrowdSec](https://crowdsec.net) incorporates Expr into its security automation tool. * [CoreDNS](https://coredns.io) uses Expr in CoreDNS, which is a DNS server. * [qiniu](https://www.qiniu.com) implements Expr in its trade systems. * [Junglee Games](https://www.jungleegames.com/) uses Expr for its in-house marketing retention tool, Project Audience. * [Faceit](https://www.faceit.com) uses Expr to enhance customization of its eSports matchmaking algorithm. * [Chaos Mesh](https://chaos-mesh.org) incorporates Expr into Chaos Mesh, a cloud-native Chaos Engineering platform. * [Visually.io](https://visually.io) employs Expr as a business rule engine for its personalization targeting algorithm. * [Akvorado](https://github.com/akvorado/akvorado) utilizes Expr to classify exporters and interfaces in network flows. * [keda.sh](https://keda.sh) uses Expr to allow customization of its Kubernetes-based event-driven autoscaling. * [Span Digital](https://spandigital.com/) uses Expr in its Knowledge Management products. * [Xiaohongshu](https://www.xiaohongshu.com/) combining yaml with Expr for dynamically policies delivery. * [Melrōse](https://melrōse.org) uses Expr to implement its music programming language. * [Tork](https://www.tork.run/) integrates Expr into its workflow execution. * [Critical Moments](https://criticalmoments.io) uses Expr for its mobile realtime conditional targeting system. * [WoodpeckerCI](https://woodpecker-ci.org) uses Expr for [filtering workflows/steps](https://woodpecker-ci.org/docs/usage/workflow-syntax#evaluate). * [FastSchema](https://github.com/fastschema/fastschema) - A BaaS leveraging Expr for its customizable and dynamic Access Control system. * [WunderGraph Cosmo](https://github.com/wundergraph/cosmo) - GraphQL Federeration Router uses Expr to customize Middleware behaviour * [SOLO](https://solo.one) uses Expr interally to allow dynamic code execution with custom defined functions. * [Naoma.AI](https://www.naoma.ai) uses Expr as a part of its call scoring engine. * [GlassFlow.dev](https://github.com/glassflow/clickhouse-etl) uses Expr to do realtime data transformation in ETL pipelines * [Kargo](https://kargo.io/) uses Expr to evaluate and manipulate variables dynamically during [promotion steps](https://docs.kargo.io/user-guide/reference-docs/expressions/) [Add your company too](https://github.com/expr-lang/expr/edit/master/README.md) ## License [MIT](https://github.com/expr-lang/expr/blob/master/LICENSE)

================================================ FILE: SECURITY.md ================================================ # Security Policy ## Supported Versions Expr is generally backwards compatible with very few exceptions, so we recommend users to always use the latest version to experience stability, performance and security. We generally backport security issues to a single previous minor version, unless this is not possible or feasible with a reasonable effort. | Version | Supported | |---------|--------------------| | 1.x | :white_check_mark: | | 0.x | :x: | ## Reporting a Vulnerability If you believe you've discovered a serious vulnerability, please contact the Expr core team at anton+security@medv.io. We will evaluate your report and if necessary issue a fix and an advisory. If the issue was previously undisclosed, we'll also mention your name in the credits. ================================================ FILE: ast/dump.go ================================================ package ast import ( "fmt" "reflect" "regexp" ) func Dump(node Node) string { return dump(reflect.ValueOf(node), "") } func dump(v reflect.Value, ident string) string { if !v.IsValid() { return "nil" } t := v.Type() switch t.Kind() { case reflect.Struct: out := t.Name() + "{\n" for i := 0; i < t.NumField(); i++ { f := t.Field(i) if isPrivate(f.Name) { continue } s := v.Field(i) out += fmt.Sprintf("%v%v: %v,\n", ident+"\t", f.Name, dump(s, ident+"\t")) } return out + ident + "}" case reflect.Slice: if v.Len() == 0 { return t.String() + "{}" } out := t.String() + "{\n" for i := 0; i < v.Len(); i++ { s := v.Index(i) out += fmt.Sprintf("%v%v,", ident+"\t", dump(s, ident+"\t")) if i+1 < v.Len() { out += "\n" } } return out + "\n" + ident + "}" case reflect.Ptr: return dump(v.Elem(), ident) case reflect.Interface: return dump(reflect.ValueOf(v.Interface()), ident) case reflect.String: return fmt.Sprintf("%q", v) default: return fmt.Sprintf("%v", v) } } var isCapital = regexp.MustCompile("^[A-Z]") func isPrivate(s string) bool { return !isCapital.Match([]byte(s)) } ================================================ FILE: ast/find.go ================================================ package ast func Find(node Node, fn func(node Node) bool) Node { v := &finder{fn: fn} Walk(&node, v) return v.node } type finder struct { node Node fn func(node Node) bool } func (f *finder) Visit(node *Node) { if f.fn(*node) { f.node = *node } } ================================================ FILE: ast/find_test.go ================================================ package ast_test import ( "testing" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr/ast" ) func TestFind(t *testing.T) { left := &ast.IdentifierNode{ Value: "a", } var root ast.Node = &ast.BinaryNode{ Operator: "+", Left: left, Right: &ast.IdentifierNode{ Value: "b", }, } x := ast.Find(root, func(node ast.Node) bool { if n, ok := node.(*ast.IdentifierNode); ok { return n.Value == "a" } return false }) require.Equal(t, left, x) } ================================================ FILE: ast/node.go ================================================ package ast import ( "reflect" "github.com/expr-lang/expr/checker/nature" "github.com/expr-lang/expr/file" ) var ( anyType = reflect.TypeOf(new(any)).Elem() ) // Node represents items of abstract syntax tree. type Node interface { Location() file.Location SetLocation(file.Location) Nature() *nature.Nature SetNature(nature.Nature) Type() reflect.Type SetType(reflect.Type) String() string } // Patch replaces the node with a new one. // Location information is preserved. // Type information is lost. func Patch(node *Node, newNode Node) { newNode.SetLocation((*node).Location()) *node = newNode } // base is a base struct for all nodes. type base struct { loc file.Location nature nature.Nature } // Location returns the location of the node in the source code. func (n *base) Location() file.Location { return n.loc } // SetLocation sets the location of the node in the source code. func (n *base) SetLocation(loc file.Location) { n.loc = loc } // Nature returns the nature of the node. func (n *base) Nature() *nature.Nature { return &n.nature } // SetNature sets the nature of the node. func (n *base) SetNature(nature nature.Nature) { n.nature = nature } // Type returns the type of the node. func (n *base) Type() reflect.Type { if n.nature.Type == nil { return anyType } return n.nature.Type } // SetType sets the type of the node. func (n *base) SetType(t reflect.Type) { n.nature = nature.FromType(t) } // NilNode represents nil. type NilNode struct { base } // IdentifierNode represents an identifier. type IdentifierNode struct { base Value string // Name of the identifier. Like "foo" in "foo.bar". } // IntegerNode represents an integer. type IntegerNode struct { base Value int // Value of the integer. } // FloatNode represents a float. type FloatNode struct { base Value float64 // Value of the float. } // BoolNode represents a boolean. type BoolNode struct { base Value bool // Value of the boolean. } // StringNode represents a string. type StringNode struct { base Value string // Value of the string. } // BytesNode represents a byte slice. type BytesNode struct { base Value []byte // Value of the byte slice. } // ConstantNode represents a constant. // Constants are predefined values like nil, true, false, array, map, etc. // The parser.Parse will never generate ConstantNode, it is only generated // by the optimizer. type ConstantNode struct { base Value any // Value of the constant. } // UnaryNode represents a unary operator. type UnaryNode struct { base Operator string // Operator of the unary operator. Like "!" in "!foo" or "not" in "not foo". Node Node // Node of the unary operator. Like "foo" in "!foo". } // BinaryNode represents a binary operator. type BinaryNode struct { base Operator string // Operator of the binary operator. Like "+" in "foo + bar" or "matches" in "foo matches bar". Left Node // Left node of the binary operator. Right Node // Right node of the binary operator. } // ChainNode represents an optional chaining group. // A few MemberNode nodes can be chained together, // and will be wrapped in a ChainNode. Example: // // foo.bar?.baz?.qux // // The whole chain will be wrapped in a ChainNode. type ChainNode struct { base Node Node // Node of the chain. } // MemberNode represents a member access. // It can be a field access, a method call, // or an array element access. // Example: // // foo.bar or foo["bar"] // foo.bar() // array[0] type MemberNode struct { base Node Node // Node of the member access. Like "foo" in "foo.bar". Property Node // Property of the member access. For property access it is a StringNode. Optional bool // If true then the member access is optional. Like "foo?.bar". Method bool } // SliceNode represents access to a slice of an array. // Example: // // array[1:4] type SliceNode struct { base Node Node // Node of the slice. Like "array" in "array[1:4]". From Node // From an index of the array. Like "1" in "array[1:4]". To Node // To an index of the array. Like "4" in "array[1:4]". } // CallNode represents a function or a method call. type CallNode struct { base Callee Node // Node of the call. Like "foo" in "foo()". Arguments []Node // Arguments of the call. } // BuiltinNode represents a builtin function call. type BuiltinNode struct { base Name string // Name of the builtin function. Like "len" in "len(foo)". Arguments []Node // Arguments of the builtin function. Throws bool // If true then accessing a field or array index can throw an error. Used by optimizer. Map Node // Used by optimizer to fold filter() and map() builtins. Threshold *int // Used by optimizer for count() early termination. } // PredicateNode represents a predicate. // Example: // // filter(foo, .bar == 1) // // The predicate is ".bar == 1". type PredicateNode struct { base Node Node // Node of the predicate body. } // PointerNode represents a pointer to a current value in predicate. type PointerNode struct { base Name string // Name of the pointer. Like "index" in "#index". } // ConditionalNode represents a ternary operator or if/else operator. type ConditionalNode struct { base Ternary bool // Is it ternary or if/else operator? Cond Node // Condition Exp1 Node // Expression 1 Exp2 Node // Expression 2 } // VariableDeclaratorNode represents a variable declaration. type VariableDeclaratorNode struct { base Name string // Name of the variable. Like "foo" in "let foo = 1; foo + 1". Value Node // Value of the variable. Like "1" in "let foo = 1; foo + 1". Expr Node // Expression of the variable. Like "foo + 1" in "let foo = 1; foo + 1". } // SequenceNode represents a sequence of nodes separated by semicolons. // All nodes are executed, only the last node will be returned. type SequenceNode struct { base Nodes []Node } // ArrayNode represents an array. type ArrayNode struct { base Nodes []Node // Nodes of the array. } // MapNode represents a map. type MapNode struct { base Pairs []Node // PairNode nodes. } // PairNode represents a key-value pair of a map. type PairNode struct { base Key Node // Key of the pair. Value Node // Value of the pair. } ================================================ FILE: ast/print.go ================================================ package ast import ( "encoding/json" "fmt" "strings" "github.com/expr-lang/expr/parser/operator" "github.com/expr-lang/expr/parser/utils" ) func (n *NilNode) String() string { return "nil" } func (n *IdentifierNode) String() string { return n.Value } func (n *IntegerNode) String() string { return fmt.Sprintf("%d", n.Value) } func (n *FloatNode) String() string { return fmt.Sprintf("%v", n.Value) } func (n *BoolNode) String() string { return fmt.Sprintf("%t", n.Value) } func (n *StringNode) String() string { return fmt.Sprintf("%q", n.Value) } func (n *BytesNode) String() string { return fmt.Sprintf("b%q", n.Value) } func (n *ConstantNode) String() string { if n.Value == nil { return "nil" } b, err := json.Marshal(n.Value) if err != nil { panic(err) } return string(b) } func (n *UnaryNode) String() string { op := n.Operator if n.Operator == "not" { op = fmt.Sprintf("%s ", n.Operator) } wrap := false switch b := n.Node.(type) { case *BinaryNode: if operator.Binary[b.Operator].Precedence < operator.Unary[n.Operator].Precedence { wrap = true } case *ConditionalNode: wrap = true } if wrap { return fmt.Sprintf("%s(%s)", op, n.Node.String()) } return fmt.Sprintf("%s%s", op, n.Node.String()) } func (n *BinaryNode) String() string { if n.Operator == ".." { return fmt.Sprintf("%s..%s", n.Left, n.Right) } var lhs, rhs string var lwrap, rwrap bool if l, ok := n.Left.(*UnaryNode); ok { if operator.Unary[l.Operator].Precedence < operator.Binary[n.Operator].Precedence { lwrap = true } } if lb, ok := n.Left.(*BinaryNode); ok { if operator.Less(lb.Operator, n.Operator) { lwrap = true } if operator.Binary[lb.Operator].Precedence == operator.Binary[n.Operator].Precedence && operator.Binary[n.Operator].Associativity == operator.Right { lwrap = true } if lb.Operator == "??" { lwrap = true } if operator.IsBoolean(lb.Operator) && n.Operator != lb.Operator { lwrap = true } } if rb, ok := n.Right.(*BinaryNode); ok { if operator.Less(rb.Operator, n.Operator) { rwrap = true } if operator.Binary[rb.Operator].Precedence == operator.Binary[n.Operator].Precedence && operator.Binary[n.Operator].Associativity == operator.Left { rwrap = true } if operator.IsBoolean(rb.Operator) && n.Operator != rb.Operator { rwrap = true } } if _, ok := n.Left.(*ConditionalNode); ok { lwrap = true } if _, ok := n.Right.(*ConditionalNode); ok { rwrap = true } if lwrap { lhs = fmt.Sprintf("(%s)", n.Left.String()) } else { lhs = n.Left.String() } if rwrap { rhs = fmt.Sprintf("(%s)", n.Right.String()) } else { rhs = n.Right.String() } return fmt.Sprintf("%s %s %s", lhs, n.Operator, rhs) } func (n *ChainNode) String() string { return n.Node.String() } func (n *MemberNode) String() string { node := n.Node.String() if _, ok := n.Node.(*BinaryNode); ok { node = fmt.Sprintf("(%s)", node) } if n.Optional { if str, ok := n.Property.(*StringNode); ok && utils.IsValidIdentifier(str.Value) { return fmt.Sprintf("%s?.%s", node, str.Value) } else { return fmt.Sprintf("%s?.[%s]", node, n.Property.String()) } } if str, ok := n.Property.(*StringNode); ok && utils.IsValidIdentifier(str.Value) { if _, ok := n.Node.(*PointerNode); ok { return fmt.Sprintf(".%s", str.Value) } return fmt.Sprintf("%s.%s", node, str.Value) } return fmt.Sprintf("%s[%s]", node, n.Property.String()) } func (n *SliceNode) String() string { if n.From == nil && n.To == nil { return fmt.Sprintf("%s[:]", n.Node.String()) } if n.From == nil { return fmt.Sprintf("%s[:%s]", n.Node.String(), n.To.String()) } if n.To == nil { return fmt.Sprintf("%s[%s:]", n.Node.String(), n.From.String()) } return fmt.Sprintf("%s[%s:%s]", n.Node.String(), n.From.String(), n.To.String()) } func (n *CallNode) String() string { arguments := make([]string, len(n.Arguments)) for i, arg := range n.Arguments { arguments[i] = arg.String() } return fmt.Sprintf("%s(%s)", n.Callee.String(), strings.Join(arguments, ", ")) } func (n *BuiltinNode) String() string { arguments := make([]string, len(n.Arguments)) for i, arg := range n.Arguments { arguments[i] = arg.String() } return fmt.Sprintf("%s(%s)", n.Name, strings.Join(arguments, ", ")) } func (n *PredicateNode) String() string { return n.Node.String() } func (n *PointerNode) String() string { return fmt.Sprintf("#%s", n.Name) } func (n *VariableDeclaratorNode) String() string { return fmt.Sprintf("let %s = %s; %s", n.Name, n.Value.String(), n.Expr.String()) } func (n *SequenceNode) String() string { nodes := make([]string, len(n.Nodes)) for i, node := range n.Nodes { nodes[i] = node.String() } return strings.Join(nodes, "; ") } func (n *ConditionalNode) String() string { if !n.Ternary { cond := n.Cond.String() exp1 := n.Exp1.String() if c2, ok := n.Exp2.(*ConditionalNode); ok && !c2.Ternary { return fmt.Sprintf("if %s { %s } else %s", cond, exp1, c2.String()) } exp2 := n.Exp2.String() return fmt.Sprintf("if %s { %s } else { %s }", cond, exp1, exp2) } var cond, exp1, exp2 string if _, ok := n.Cond.(*ConditionalNode); ok { cond = fmt.Sprintf("(%s)", n.Cond.String()) } else { cond = n.Cond.String() } if _, ok := n.Exp1.(*ConditionalNode); ok { exp1 = fmt.Sprintf("(%s)", n.Exp1.String()) } else { exp1 = n.Exp1.String() } if _, ok := n.Exp2.(*ConditionalNode); ok { exp2 = fmt.Sprintf("(%s)", n.Exp2.String()) } else { exp2 = n.Exp2.String() } return fmt.Sprintf("%s ? %s : %s", cond, exp1, exp2) } func (n *ArrayNode) String() string { nodes := make([]string, len(n.Nodes)) for i, node := range n.Nodes { nodes[i] = node.String() } return fmt.Sprintf("[%s]", strings.Join(nodes, ", ")) } func (n *MapNode) String() string { pairs := make([]string, len(n.Pairs)) for i, pair := range n.Pairs { pairs[i] = pair.String() } return fmt.Sprintf("{%s}", strings.Join(pairs, ", ")) } func (n *PairNode) String() string { if str, ok := n.Key.(*StringNode); ok { if utils.IsValidIdentifier(str.Value) { return fmt.Sprintf("%s: %s", str.Value, n.Value.String()) } return fmt.Sprintf("%s: %s", str.String(), n.Value.String()) } return fmt.Sprintf("(%s): %s", n.Key.String(), n.Value.String()) } ================================================ FILE: ast/print_test.go ================================================ package ast_test import ( "testing" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/parser" ) func TestPrint(t *testing.T) { tests := []struct { input string want string }{ {`nil`, `nil`}, {`true`, `true`}, {`false`, `false`}, {`1`, `1`}, {`1.1`, `1.1`}, {`"a"`, `"a"`}, {`'a'`, `"a"`}, {`a`, `a`}, {`a.b`, `a.b`}, {`a[0]`, `a[0]`}, {`a["the b"]`, `a["the b"]`}, {`a.b[0]`, `a.b[0]`}, {`a?.b`, `a?.b`}, {`x[0][1]`, `x[0][1]`}, {`x?.[0]?.[1]`, `x?.[0]?.[1]`}, {`-a`, `-a`}, {`!a`, `!a`}, {`not a`, `not a`}, {`a + b`, `a + b`}, {`a + b * c`, `a + b * c`}, {`(a + b) * c`, `(a + b) * c`}, {`a * (b + c)`, `a * (b + c)`}, {`-(a + b) * c`, `-(a + b) * c`}, {`a == b`, `a == b`}, {`a matches b`, `a matches b`}, {`a in b`, `a in b`}, {`a not in b`, `not (a in b)`}, {`a and b`, `a and b`}, {`a or b`, `a or b`}, {`a or b and c`, `a or (b and c)`}, {`a or (b and c)`, `a or (b and c)`}, {`(a or b) and c`, `(a or b) and c`}, {`a ? b : c`, `a ? b : c`}, {`a ? b : c ? d : e`, `a ? b : (c ? d : e)`}, {`(a ? b : c) ? d : e`, `(a ? b : c) ? d : e`}, {`a ? (b ? c : d) : e`, `a ? (b ? c : d) : e`}, {`func()`, `func()`}, {`func(a)`, `func(a)`}, {`func(a, b)`, `func(a, b)`}, {`{}`, `{}`}, {`{a: b}`, `{a: b}`}, {`{a: b, c: d}`, `{a: b, c: d}`}, {`{"a": b, 'c': d}`, `{a: b, c: d}`}, {`{"a": b, c: d}`, `{a: b, c: d}`}, {`{"a": b, 8: 8}`, `{a: b, "8": 8}`}, {`{"9": 9, '8': 8, "foo": d}`, `{"9": 9, "8": 8, foo: d}`}, {`[]`, `[]`}, {`[a]`, `[a]`}, {`[a, b]`, `[a, b]`}, {`len(a)`, `len(a)`}, {`map(a, # > 0)`, `map(a, # > 0)`}, {`map(a, {# > 0})`, `map(a, # > 0)`}, {`map(a, .b)`, `map(a, .b)`}, {`a.b()`, `a.b()`}, {`a.b(c)`, `a.b(c)`}, {`a[1:-1]`, `a[1:-1]`}, {`a[1:]`, `a[1:]`}, {`a[1:]`, `a[1:]`}, {`a[:]`, `a[:]`}, {`(nil ?? 1) > 0`, `(nil ?? 1) > 0`}, {`{("a" + "b"): 42}`, `{("a" + "b"): 42}`}, {`(One == 1 ? true : false) && Two == 2`, `(One == 1 ? true : false) && Two == 2`}, {`not (a == 1 ? b > 1 : b < 2)`, `not (a == 1 ? b > 1 : b < 2)`}, {`(-(1+1)) ** 2`, `(-(1 + 1)) ** 2`}, {`2 ** (-(1+1))`, `2 ** -(1 + 1)`}, {`(2 ** 2) ** 3`, `(2 ** 2) ** 3`}, {`(3 + 5) / (5 % 3)`, `(3 + 5) / (5 % 3)`}, {`(-(1+1)) == 2`, `-(1 + 1) == 2`}, {`if true { 1 } else { 2 }`, `if true { 1 } else { 2 }`}, {`if true { 1 } else if false { 2 } else { 3 }`, `if true { 1 } else if false { 2 } else { 3 }`}, } for _, tt := range tests { t.Run(tt.input, func(t *testing.T) { tree, err := parser.Parse(tt.input) require.NoError(t, err) assert.Equal(t, tt.want, tree.Node.String()) }) } } func TestPrint_MemberNode(t *testing.T) { node := &ast.MemberNode{ Node: &ast.IdentifierNode{ Value: "a", }, Property: &ast.StringNode{Value: "b c"}, Optional: true, } require.Equal(t, `a?.["b c"]`, node.String()) } func TestPrint_ConstantNode(t *testing.T) { tests := []struct { input any want string }{ {nil, `nil`}, {true, `true`}, {false, `false`}, {1, `1`}, {1.1, `1.1`}, {"a", `"a"`}, {[]int{1, 2, 3}, `[1,2,3]`}, {map[string]int{"a": 1}, `{"a":1}`}, } for _, tt := range tests { t.Run(tt.want, func(t *testing.T) { node := &ast.ConstantNode{ Value: tt.input, } require.Equal(t, tt.want, node.String()) }) } } ================================================ FILE: ast/visitor.go ================================================ package ast import "fmt" type Visitor interface { Visit(node *Node) } func Walk(node *Node, v Visitor) { if *node == nil { return } switch n := (*node).(type) { case *NilNode: case *IdentifierNode: case *IntegerNode: case *FloatNode: case *BoolNode: case *StringNode: case *BytesNode: case *ConstantNode: case *UnaryNode: Walk(&n.Node, v) case *BinaryNode: Walk(&n.Left, v) Walk(&n.Right, v) case *ChainNode: Walk(&n.Node, v) case *MemberNode: Walk(&n.Node, v) Walk(&n.Property, v) case *SliceNode: Walk(&n.Node, v) if n.From != nil { Walk(&n.From, v) } if n.To != nil { Walk(&n.To, v) } case *CallNode: Walk(&n.Callee, v) for i := range n.Arguments { Walk(&n.Arguments[i], v) } case *BuiltinNode: for i := range n.Arguments { Walk(&n.Arguments[i], v) } case *PredicateNode: Walk(&n.Node, v) case *PointerNode: case *VariableDeclaratorNode: Walk(&n.Value, v) Walk(&n.Expr, v) case *SequenceNode: for i := range n.Nodes { Walk(&n.Nodes[i], v) } case *ConditionalNode: Walk(&n.Cond, v) Walk(&n.Exp1, v) Walk(&n.Exp2, v) case *ArrayNode: for i := range n.Nodes { Walk(&n.Nodes[i], v) } case *MapNode: for i := range n.Pairs { Walk(&n.Pairs[i], v) } case *PairNode: Walk(&n.Key, v) Walk(&n.Value, v) default: panic(fmt.Sprintf("undefined node type (%T)", node)) } v.Visit(node) } ================================================ FILE: ast/visitor_test.go ================================================ package ast_test import ( "testing" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr/ast" ) type visitor struct { identifiers []string } func (v *visitor) Visit(node *ast.Node) { if n, ok := (*node).(*ast.IdentifierNode); ok { v.identifiers = append(v.identifiers, n.Value) } } func TestWalk(t *testing.T) { var node ast.Node node = &ast.BinaryNode{ Operator: "+", Left: &ast.IdentifierNode{Value: "foo"}, Right: &ast.IdentifierNode{Value: "bar"}, } visitor := &visitor{} ast.Walk(&node, visitor) assert.Equal(t, []string{"foo", "bar"}, visitor.identifiers) } type patcher struct{} func (p *patcher) Visit(node *ast.Node) { if _, ok := (*node).(*ast.IdentifierNode); ok { *node = &ast.NilNode{} } } func TestWalk_patch(t *testing.T) { var node ast.Node node = &ast.BinaryNode{ Operator: "+", Left: &ast.IdentifierNode{Value: "foo"}, Right: &ast.IdentifierNode{Value: "bar"}, } patcher := &patcher{} ast.Walk(&node, patcher) assert.IsType(t, &ast.NilNode{}, node.(*ast.BinaryNode).Left) assert.IsType(t, &ast.NilNode{}, node.(*ast.BinaryNode).Right) } ================================================ FILE: bench_test.go ================================================ package expr_test import ( "testing" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr" "github.com/expr-lang/expr/vm" ) func Benchmark_expr(b *testing.B) { params := make(map[string]any) params["Origin"] = "MOW" params["Country"] = "RU" params["Adults"] = 1 params["Value"] = 100 program, err := expr.Compile(`(Origin == "MOW" || Country == "RU") && (Value >= 100 || Adults == 1)`, expr.Env(params)) require.NoError(b, err) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, err = vm.Run(program, params) } b.StopTimer() require.NoError(b, err) require.True(b, out.(bool)) } func Benchmark_expr_eval(b *testing.B) { params := make(map[string]any) params["Origin"] = "MOW" params["Country"] = "RU" params["Adults"] = 1 params["Value"] = 100 var out any var err error b.ResetTimer() for n := 0; n < b.N; n++ { out, err = expr.Eval(`(Origin == "MOW" || Country == "RU") && (Value >= 100 || Adults == 1)`, params) } b.StopTimer() require.NoError(b, err) require.True(b, out.(bool)) } func Benchmark_expr_reuseVm(b *testing.B) { params := make(map[string]any) params["Origin"] = "MOW" params["Country"] = "RU" params["Adults"] = 1 params["Value"] = 100 program, err := expr.Compile(`(Origin == "MOW" || Country == "RU") && (Value >= 100 || Adults == 1)`, expr.Env(params)) require.NoError(b, err) var out any v := vm.VM{} b.ResetTimer() for n := 0; n < b.N; n++ { out, err = v.Run(program, params) } b.StopTimer() require.NoError(b, err) require.True(b, out.(bool)) } func Benchmark_len(b *testing.B) { env := map[string]any{ "arr": make([]int, 100), } program, err := expr.Compile(`len(arr)`, expr.Env(env)) require.NoError(b, err) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, err = vm.Run(program, env) } b.StopTimer() require.NoError(b, err) require.Equal(b, 100, out) } func Benchmark_filter(b *testing.B) { type Env struct { Ints []int } env := Env{ Ints: make([]int, 1000), } for i := 1; i <= len(env.Ints); i++ { env.Ints[i-1] = i } program, err := expr.Compile(`filter(Ints, # % 7 == 0)`, expr.Env(Env{})) require.NoError(b, err) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, err = vm.Run(program, env) } b.StopTimer() require.NoError(b, err) require.Len(b, out.([]any), 142) } func Benchmark_filterLen(b *testing.B) { type Env struct { Ints []int } env := Env{ Ints: make([]int, 1000), } for i := 1; i <= len(env.Ints); i++ { env.Ints[i-1] = i } program, err := expr.Compile(`len(filter(Ints, # % 7 == 0))`, expr.Env(Env{})) require.NoError(b, err) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, err = vm.Run(program, env) } b.StopTimer() require.NoError(b, err) require.Equal(b, 142, out) } func Benchmark_filterFirst(b *testing.B) { type Env struct { Ints []int } env := Env{ Ints: make([]int, 1000), } for i := 1; i <= len(env.Ints); i++ { env.Ints[i-1] = i } program, err := expr.Compile(`filter(Ints, # % 7 == 0)[0]`, expr.Env(Env{})) require.NoError(b, err) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, err = vm.Run(program, env) } b.StopTimer() require.NoError(b, err) require.Equal(b, 7, out) } func Benchmark_filterLast(b *testing.B) { type Env struct { Ints []int } env := Env{ Ints: make([]int, 1000), } for i := 1; i <= len(env.Ints); i++ { env.Ints[i-1] = i } program, err := expr.Compile(`filter(Ints, # % 7 == 0)[-1]`, expr.Env(Env{})) require.NoError(b, err) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, err = vm.Run(program, env) } b.StopTimer() require.NoError(b, err) require.Equal(b, 994, out) } func Benchmark_filterMap(b *testing.B) { type Env struct { Ints []int } env := Env{ Ints: make([]int, 100), } for i := 1; i <= len(env.Ints); i++ { env.Ints[i-1] = i } program, err := expr.Compile(`map(filter(Ints, # % 7 == 0), # * 2)`, expr.Env(Env{})) require.NoError(b, err) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, err = vm.Run(program, env) } b.StopTimer() require.NoError(b, err) require.Len(b, out.([]any), 14) require.Equal(b, 14, out.([]any)[0]) } func Benchmark_arrayIndex(b *testing.B) { env := map[string]any{ "arr": make([]int, 100), } for i := 0; i < 100; i++ { env["arr"].([]int)[i] = i } program, err := expr.Compile(`arr[50]`, expr.Env(env)) require.NoError(b, err) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, err = vm.Run(program, env) } b.StopTimer() require.NoError(b, err) require.Equal(b, 50, out) } func Benchmark_envStruct(b *testing.B) { type Price struct { Value int } type Env struct { Price Price } program, err := expr.Compile(`Price.Value > 0`, expr.Env(Env{})) require.NoError(b, err) env := Env{Price: Price{Value: 1}} var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, err = vm.Run(program, env) } b.StopTimer() require.NoError(b, err) require.True(b, out.(bool)) } func Benchmark_envStruct_noEnv(b *testing.B) { type Price struct { Value int } type Env struct { Price Price } program, err := expr.Compile(`Price.Value > 0`) require.NoError(b, err) env := Env{Price: Price{Value: 1}} var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, err = vm.Run(program, env) } b.StopTimer() require.NoError(b, err) require.True(b, out.(bool)) } func Benchmark_envMap(b *testing.B) { type Price struct { Value int } env := map[string]any{ "price": Price{Value: 1}, } program, err := expr.Compile(`price.Value > 0`, expr.Env(env)) require.NoError(b, err) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, err = vm.Run(program, env) } b.StopTimer() require.NoError(b, err) require.True(b, out.(bool)) } type CallEnv struct { A int B int C int Fn func() bool FnFast func(...any) any Foo CallFoo } func (CallEnv) Func() string { return "func" } type CallFoo struct { D int E int F int } func (CallFoo) Method() string { return "method" } func Benchmark_callFunc(b *testing.B) { program, err := expr.Compile(`Func()`, expr.Env(CallEnv{})) require.NoError(b, err) env := CallEnv{} var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, err = vm.Run(program, env) } b.StopTimer() require.NoError(b, err) require.Equal(b, "func", out) } func Benchmark_callMethod(b *testing.B) { program, err := expr.Compile(`Foo.Method()`, expr.Env(CallEnv{})) require.NoError(b, err) env := CallEnv{} var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, err = vm.Run(program, env) } b.StopTimer() require.NoError(b, err) require.Equal(b, "method", out) } func Benchmark_callField(b *testing.B) { program, err := expr.Compile(`Fn()`, expr.Env(CallEnv{})) require.NoError(b, err) env := CallEnv{ Fn: func() bool { return true }, } var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, err = vm.Run(program, env) } b.StopTimer() require.NoError(b, err) require.True(b, out.(bool)) } func Benchmark_callFast(b *testing.B) { program, err := expr.Compile(`FnFast()`, expr.Env(CallEnv{})) if err != nil { b.Fatal(err) } env := CallEnv{ FnFast: func(s ...any) any { return "fn_fast" }, } var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, err = vm.Run(program, env) } b.StopTimer() require.NoError(b, err) require.Equal(b, "fn_fast", out) } func Benchmark_callConstExpr(b *testing.B) { program, err := expr.Compile(`Func()`, expr.Env(CallEnv{}), expr.ConstExpr("Func")) require.NoError(b, err) env := CallEnv{} var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, err = vm.Run(program, env) } b.StopTimer() require.NoError(b, err) require.Equal(b, "func", out) } func Benchmark_largeStructAccess(b *testing.B) { type Env struct { Data [1024 * 1024 * 10]byte Field int } program, err := expr.Compile(`Field > 0 && Field > 1 && Field < 99`, expr.Env(Env{})) require.NoError(b, err) env := Env{Field: 21} var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, err = vm.Run(program, &env) } b.StopTimer() require.NoError(b, err) require.True(b, out.(bool)) } func Benchmark_largeNestedStructAccess(b *testing.B) { type Env struct { Inner struct { Data [1024 * 1024 * 10]byte Field int } } program, err := expr.Compile(`Inner.Field > 0 && Inner.Field > 1 && Inner.Field < 99`, expr.Env(Env{})) require.NoError(b, err) env := Env{} env.Inner.Field = 21 var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, err = vm.Run(program, &env) } b.StopTimer() require.NoError(b, err) require.True(b, out.(bool)) } func Benchmark_largeNestedArrayAccess(b *testing.B) { type Env struct { Data [1][1024 * 1024 * 10]byte } program, err := expr.Compile(`Data[0][0] > 0`, expr.Env(Env{})) require.NoError(b, err) env := Env{} env.Data[0][0] = 1 var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, err = vm.Run(program, &env) } b.StopTimer() require.NoError(b, err) require.True(b, out.(bool)) } func Benchmark_sort(b *testing.B) { env := map[string]any{ "arr": []any{55, 58, 42, 61, 75, 52, 64, 62, 16, 79, 40, 14, 50, 76, 23, 2, 5, 80, 89, 51, 21, 96, 91, 13, 71, 82, 65, 63, 11, 17, 94, 81, 74, 4, 97, 1, 39, 3, 28, 8, 84, 90, 47, 85, 7, 56, 49, 93, 33, 12, 19, 60, 86, 100, 44, 45, 36, 72, 95, 77, 34, 92, 24, 73, 18, 38, 43, 26, 41, 69, 67, 57, 9, 27, 66, 87, 46, 35, 59, 70, 10, 20, 53, 15, 32, 98, 68, 31, 54, 25, 83, 88, 22, 48, 29, 37, 6, 78, 99, 30}, } program, err := expr.Compile(`sort(arr)`, expr.Env(env)) require.NoError(b, err) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = vm.Run(program, env) } b.StopTimer() require.Equal(b, 1, out.([]any)[0]) require.Equal(b, 100, out.([]any)[99]) } func Benchmark_sortBy(b *testing.B) { type Foo struct { Value int } arr := []any{55, 58, 42, 61, 75, 52, 64, 62, 16, 79, 40, 14, 50, 76, 23, 2, 5, 80, 89, 51, 21, 96, 91, 13, 71, 82, 65, 63, 11, 17, 94, 81, 74, 4, 97, 1, 39, 3, 28, 8, 84, 90, 47, 85, 7, 56, 49, 93, 33, 12, 19, 60, 86, 100, 44, 45, 36, 72, 95, 77, 34, 92, 24, 73, 18, 38, 43, 26, 41, 69, 67, 57, 9, 27, 66, 87, 46, 35, 59, 70, 10, 20, 53, 15, 32, 98, 68, 31, 54, 25, 83, 88, 22, 48, 29, 37, 6, 78, 99, 30} env := map[string]any{ "arr": make([]Foo, len(arr)), } for i, v := range arr { env["arr"].([]Foo)[i] = Foo{Value: v.(int)} } program, err := expr.Compile(`sortBy(arr, .Value)`, expr.Env(env)) require.NoError(b, err) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = vm.Run(program, env) } b.StopTimer() require.Equal(b, 1, out.([]any)[0].(Foo).Value) require.Equal(b, 100, out.([]any)[99].(Foo).Value) } func Benchmark_groupBy(b *testing.B) { program, err := expr.Compile(`groupBy(1..100, # % 7)[6]`) require.NoError(b, err) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = vm.Run(program, nil) } b.StopTimer() require.Equal(b, 6, out.([]any)[0]) } func Benchmark_reduce(b *testing.B) { program, err := expr.Compile(`reduce(1..100, # + #acc)`) require.NoError(b, err) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = vm.Run(program, nil) } b.StopTimer() require.Equal(b, 5050, out.(int)) } func Benchmark_min(b *testing.B) { arr := []any{55, 58, 42, 61, 75, 52, 64, 62, 16, 79, 40, 14, 50, 76, 23, 2, 5, 80, 89, 51, 21, 96, 91, 13, 71, 82, 65, 63, 11, 17, 94, 81, 74, 4, 97, 1, 39, 3, 28, 8, 84, 90, 47, 85, 7, 56, 49, 93, 33, 12, 19, 60, 86, 100, 44, 45, 36, 72, 95, 77, 34, 92, 24, 73, 18, 38, 43, 26, 41, 69, 67, 57, 9, 27, 66, 87, 46, 35, 59, 70, 10, 20, 53, 15, 32, 98, 68, 31, 54, 25, 83, 88, 22, 48, 29, 37, 6, 78, 99, 30} env := map[string]any{"arr": arr} program, err := expr.Compile(`min(arr)`, expr.Env(env)) require.NoError(b, err) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = vm.Run(program, env) } b.StopTimer() require.Equal(b, 1, out) } func Benchmark_max(b *testing.B) { arr := []any{55, 58, 42, 61, 75, 52, 64, 62, 16, 79, 40, 14, 50, 76, 23, 2, 5, 80, 89, 51, 21, 96, 91, 13, 71, 82, 65, 63, 11, 17, 94, 81, 74, 4, 97, 1, 39, 3, 28, 8, 84, 90, 47, 85, 7, 56, 49, 93, 33, 12, 19, 60, 86, 100, 44, 45, 36, 72, 95, 77, 34, 92, 24, 73, 18, 38, 43, 26, 41, 69, 67, 57, 9, 27, 66, 87, 46, 35, 59, 70, 10, 20, 53, 15, 32, 98, 68, 31, 54, 25, 83, 88, 22, 48, 29, 37, 6, 78, 99, 30} env := map[string]any{"arr": arr} program, err := expr.Compile(`max(arr)`, expr.Env(env)) require.NoError(b, err) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = vm.Run(program, env) } b.StopTimer() require.Equal(b, 100, out) } func Benchmark_mean(b *testing.B) { arr := []any{55, 58, 42, 61, 75, 52, 64, 62, 16, 79, 40, 14, 50, 76, 23, 2, 5, 80, 89, 51, 21, 96, 91, 13, 71, 82, 65, 63, 11, 17, 94, 81, 74, 4, 97, 1, 39, 3, 28, 8, 84, 90, 47, 85, 7, 56, 49, 93, 33, 12, 19, 60, 86, 100, 44, 45, 36, 72, 95, 77, 34, 92, 24, 73, 18, 38, 43, 26, 41, 69, 67, 57, 9, 27, 66, 87, 46, 35, 59, 70, 10, 20, 53, 15, 32, 98, 68, 31, 54, 25, 83, 88, 22, 48, 29, 37, 6, 78, 99, 30} env := map[string]any{"arr": arr} program, err := expr.Compile(`mean(arr)`, expr.Env(env)) require.NoError(b, err) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = vm.Run(program, env) } b.StopTimer() require.Equal(b, 50.5, out) } func Benchmark_median(b *testing.B) { arr := []any{55, 58, 42, 61, 75, 52, 64, 62, 16, 79, 40, 14, 50, 76, 23, 2, 5, 80, 89, 51, 21, 96, 91, 13, 71, 82, 65, 63, 11, 17, 94, 81, 74, 4, 97, 1, 39, 3, 28, 8, 84, 90, 47, 85, 7, 56, 49, 93, 33, 12, 19, 60, 86, 100, 44, 45, 36, 72, 95, 77, 34, 92, 24, 73, 18, 38, 43, 26, 41, 69, 67, 57, 9, 27, 66, 87, 46, 35, 59, 70, 10, 20, 53, 15, 32, 98, 68, 31, 54, 25, 83, 88, 22, 48, 29, 37, 6, 78, 99, 30} env := map[string]any{"arr": arr} program, err := expr.Compile(`median(arr)`, expr.Env(env)) require.NoError(b, err) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = vm.Run(program, env) } b.StopTimer() require.Equal(b, 50.5, out) } ================================================ FILE: builtin/builtin.go ================================================ package builtin import ( "encoding/base64" "encoding/json" "errors" "fmt" "reflect" "sort" "strings" "time" "github.com/expr-lang/expr/internal/deref" "github.com/expr-lang/expr/vm/runtime" ) var ( Index map[string]int Names []string // MaxDepth limits the recursion depth for nested structures. MaxDepth = 10000 ErrorMaxDepth = errors.New("recursion depth exceeded") ) func init() { Index = make(map[string]int) Names = make([]string, len(Builtins)) for i, fn := range Builtins { Index[fn.Name] = i Names[i] = fn.Name } } var Builtins = []*Function{ { Name: "all", Predicate: true, Types: types(new(func([]any, func(any) bool) bool)), }, { Name: "none", Predicate: true, Types: types(new(func([]any, func(any) bool) bool)), }, { Name: "any", Predicate: true, Types: types(new(func([]any, func(any) bool) bool)), }, { Name: "one", Predicate: true, Types: types(new(func([]any, func(any) bool) bool)), }, { Name: "filter", Predicate: true, Types: types(new(func([]any, func(any) bool) []any)), }, { Name: "map", Predicate: true, Types: types(new(func([]any, func(any) any) []any)), }, { Name: "find", Predicate: true, Types: types(new(func([]any, func(any) bool) any)), }, { Name: "findIndex", Predicate: true, Types: types(new(func([]any, func(any) bool) int)), }, { Name: "findLast", Predicate: true, Types: types(new(func([]any, func(any) bool) any)), }, { Name: "findLastIndex", Predicate: true, Types: types(new(func([]any, func(any) bool) int)), }, { Name: "count", Predicate: true, Types: types(new(func([]any, func(any) bool) int)), }, { Name: "sum", Predicate: true, Types: types(new(func([]any, func(any) bool) int)), }, { Name: "groupBy", Predicate: true, Types: types(new(func([]any, func(any) any) map[any][]any)), }, { Name: "sortBy", Predicate: true, Types: types(new(func([]any, func(any) bool, string) []any)), }, { Name: "reduce", Predicate: true, Types: types(new(func([]any, func(any, any) any, any) any)), }, { Name: "len", Fast: Len, Validate: func(args []reflect.Type) (reflect.Type, error) { if len(args) != 1 { return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args)) } switch kind(args[0]) { case reflect.Array, reflect.Map, reflect.Slice, reflect.String, reflect.Interface: return integerType, nil } return anyType, fmt.Errorf("invalid argument for len (type %s)", args[0]) }, }, { Name: "type", Fast: Type, Types: types(new(func(any) string)), }, { Name: "abs", Fast: Abs, Validate: func(args []reflect.Type) (reflect.Type, error) { if len(args) != 1 { return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args)) } switch kind(args[0]) { case reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Interface: return args[0], nil } return anyType, fmt.Errorf("invalid argument for abs (type %s)", args[0]) }, }, { Name: "ceil", Fast: Ceil, Validate: func(args []reflect.Type) (reflect.Type, error) { return validateRoundFunc("ceil", args) }, }, { Name: "floor", Fast: Floor, Validate: func(args []reflect.Type) (reflect.Type, error) { return validateRoundFunc("floor", args) }, }, { Name: "round", Fast: Round, Validate: func(args []reflect.Type) (reflect.Type, error) { return validateRoundFunc("round", args) }, }, { Name: "int", Fast: Int, Validate: func(args []reflect.Type) (reflect.Type, error) { if len(args) != 1 { return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args)) } switch kind(args[0]) { case reflect.Interface: return integerType, nil case reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return integerType, nil case reflect.String: return integerType, nil } return anyType, fmt.Errorf("invalid argument for int (type %s)", args[0]) }, }, { Name: "float", Fast: Float, Validate: func(args []reflect.Type) (reflect.Type, error) { if len(args) != 1 { return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args)) } switch kind(args[0]) { case reflect.Interface: return floatType, nil case reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return floatType, nil case reflect.String: return floatType, nil } return anyType, fmt.Errorf("invalid argument for float (type %s)", args[0]) }, }, { Name: "string", Fast: String, Types: types(new(func(any any) string)), }, { Name: "trim", Func: func(args ...any) (any, error) { if len(args) == 1 { return strings.TrimSpace(args[0].(string)), nil } else if len(args) == 2 { return strings.Trim(args[0].(string), args[1].(string)), nil } else { return nil, fmt.Errorf("invalid number of arguments for trim (expected 1 or 2, got %d)", len(args)) } }, Types: types( strings.TrimSpace, strings.Trim, ), }, { Name: "trimPrefix", Func: func(args ...any) (any, error) { s := " " if len(args) == 2 { s = args[1].(string) } return strings.TrimPrefix(args[0].(string), s), nil }, Types: types( strings.TrimPrefix, new(func(string) string), ), }, { Name: "trimSuffix", Func: func(args ...any) (any, error) { s := " " if len(args) == 2 { s = args[1].(string) } return strings.TrimSuffix(args[0].(string), s), nil }, Types: types( strings.TrimSuffix, new(func(string) string), ), }, { Name: "upper", Fast: func(arg any) any { return strings.ToUpper(arg.(string)) }, Types: types(strings.ToUpper), }, { Name: "lower", Fast: func(arg any) any { return strings.ToLower(arg.(string)) }, Types: types(strings.ToLower), }, { Name: "split", Func: func(args ...any) (any, error) { if len(args) == 2 { return strings.Split(args[0].(string), args[1].(string)), nil } else if len(args) == 3 { return strings.SplitN(args[0].(string), args[1].(string), runtime.ToInt(args[2])), nil } else { return nil, fmt.Errorf("invalid number of arguments for split (expected 2 or 3, got %d)", len(args)) } }, Types: types( strings.Split, strings.SplitN, ), }, { Name: "splitAfter", Func: func(args ...any) (any, error) { if len(args) == 2 { return strings.SplitAfter(args[0].(string), args[1].(string)), nil } else if len(args) == 3 { return strings.SplitAfterN(args[0].(string), args[1].(string), runtime.ToInt(args[2])), nil } else { return nil, fmt.Errorf("invalid number of arguments for splitAfter (expected 2 or 3, got %d)", len(args)) } }, Types: types( strings.SplitAfter, strings.SplitAfterN, ), }, { Name: "replace", Func: func(args ...any) (any, error) { if len(args) == 4 { return strings.Replace(args[0].(string), args[1].(string), args[2].(string), runtime.ToInt(args[3])), nil } else if len(args) == 3 { return strings.ReplaceAll(args[0].(string), args[1].(string), args[2].(string)), nil } else { return nil, fmt.Errorf("invalid number of arguments for replace (expected 3 or 4, got %d)", len(args)) } }, Types: types( strings.Replace, strings.ReplaceAll, ), }, { Name: "repeat", Safe: func(args ...any) (any, uint, error) { s := args[0].(string) n := runtime.ToInt(args[1]) if n < 0 { return nil, 0, fmt.Errorf("invalid argument for repeat (expected positive integer, got %d)", n) } if n > 1e6 { return nil, 0, fmt.Errorf("memory budget exceeded") } return strings.Repeat(s, n), uint(len(s) * n), nil }, Types: types(strings.Repeat), }, { Name: "join", Func: func(args ...any) (any, error) { glue := "" if len(args) == 2 { glue = args[1].(string) } switch args[0].(type) { case []string: return strings.Join(args[0].([]string), glue), nil case []any: var s []string for _, arg := range args[0].([]any) { s = append(s, arg.(string)) } return strings.Join(s, glue), nil } return nil, fmt.Errorf("invalid argument for join (type %s)", reflect.TypeOf(args[0])) }, Types: types( strings.Join, new(func([]any, string) string), new(func([]any) string), new(func([]string, string) string), new(func([]string) string), ), }, { Name: "indexOf", Func: func(args ...any) (any, error) { return strings.Index(args[0].(string), args[1].(string)), nil }, Types: types(strings.Index), }, { Name: "lastIndexOf", Func: func(args ...any) (any, error) { return strings.LastIndex(args[0].(string), args[1].(string)), nil }, Types: types(strings.LastIndex), }, { Name: "hasPrefix", Func: func(args ...any) (any, error) { return strings.HasPrefix(args[0].(string), args[1].(string)), nil }, Types: types(strings.HasPrefix), }, { Name: "hasSuffix", Func: func(args ...any) (any, error) { return strings.HasSuffix(args[0].(string), args[1].(string)), nil }, Types: types(strings.HasSuffix), }, { Name: "max", Func: func(args ...any) (any, error) { return minMax("max", runtime.Less, 0, args...) }, Validate: func(args []reflect.Type) (reflect.Type, error) { return validateAggregateFunc("max", args) }, }, { Name: "min", Func: func(args ...any) (any, error) { return minMax("min", runtime.More, 0, args...) }, Validate: func(args []reflect.Type) (reflect.Type, error) { return validateAggregateFunc("min", args) }, }, { Name: "mean", Func: func(args ...any) (any, error) { count, sum, err := mean(0, args...) if err != nil { return nil, err } if count == 0 { return 0.0, nil } return sum / float64(count), nil }, Validate: func(args []reflect.Type) (reflect.Type, error) { return validateAggregateFunc("mean", args) }, }, { Name: "median", Func: func(args ...any) (any, error) { values, err := median(0, args...) if err != nil { return nil, err } if n := len(values); n > 0 { sort.Float64s(values) if n%2 == 1 { return values[n/2], nil } return (values[n/2-1] + values[n/2]) / 2, nil } return 0.0, nil }, Validate: func(args []reflect.Type) (reflect.Type, error) { return validateAggregateFunc("median", args) }, }, { Name: "toJSON", Func: func(args ...any) (any, error) { b, err := json.MarshalIndent(args[0], "", " ") if err != nil { return nil, err } return string(b), nil }, Types: types(new(func(any) string)), }, { Name: "fromJSON", Func: func(args ...any) (any, error) { var v any err := json.Unmarshal([]byte(args[0].(string)), &v) if err != nil { return nil, err } return v, nil }, Types: types(new(func(string) any)), }, { Name: "toBase64", Func: func(args ...any) (any, error) { return base64.StdEncoding.EncodeToString([]byte(args[0].(string))), nil }, Types: types(new(func(string) string)), }, { Name: "fromBase64", Func: func(args ...any) (any, error) { b, err := base64.StdEncoding.DecodeString(args[0].(string)) if err != nil { return nil, err } return string(b), nil }, Types: types(new(func(string) string)), }, { Name: "now", Func: func(args ...any) (any, error) { if len(args) == 0 { return time.Now(), nil } if len(args) == 1 { if tz, ok := args[0].(*time.Location); ok { return time.Now().In(tz), nil } } return nil, fmt.Errorf("invalid number of arguments (expected 0, got %d)", len(args)) }, Validate: func(args []reflect.Type) (reflect.Type, error) { if len(args) == 0 { return timeType, nil } if len(args) == 1 { if args[0] != nil && args[0].AssignableTo(locationType) { return timeType, nil } } return anyType, fmt.Errorf("invalid number of arguments (expected 0, got %d)", len(args)) }, Deref: func(i int, arg reflect.Type) bool { return false }, }, { Name: "duration", Func: func(args ...any) (any, error) { return time.ParseDuration(args[0].(string)) }, Types: types(time.ParseDuration), }, { Name: "date", Func: func(args ...any) (any, error) { tz, ok := args[0].(*time.Location) if ok { args = args[1:] } date := args[0].(string) if len(args) == 2 { layout := args[1].(string) if tz != nil { return time.ParseInLocation(layout, date, tz) } return time.Parse(layout, date) } if len(args) == 3 { layout := args[1].(string) timeZone := args[2].(string) tz, err := time.LoadLocation(timeZone) if err != nil { return nil, fmt.Errorf("unknown time zone %s", timeZone) } t, err := time.ParseInLocation(layout, date, tz) if err != nil { return nil, err } return t, nil } layouts := []string{ "2006-01-02", "15:04:05", "2006-01-02 15:04:05", time.RFC3339, time.RFC822, time.RFC850, time.RFC1123, } for _, layout := range layouts { if tz == nil { t, err := time.Parse(layout, date) if err == nil { return t, nil } } else { t, err := time.ParseInLocation(layout, date, tz) if err == nil { return t, nil } } } return nil, fmt.Errorf("invalid date %s", date) }, Validate: func(args []reflect.Type) (reflect.Type, error) { if len(args) < 1 { return anyType, fmt.Errorf("invalid number of arguments (expected at least 1, got %d)", len(args)) } if args[0] != nil && args[0].AssignableTo(locationType) { args = args[1:] } if len(args) > 3 { return anyType, fmt.Errorf("invalid number of arguments (expected at most 3, got %d)", len(args)) } return timeType, nil }, Deref: func(i int, arg reflect.Type) bool { if arg.AssignableTo(locationType) { return false } return true }, }, { Name: "timezone", Func: func(args ...any) (any, error) { tz, err := time.LoadLocation(args[0].(string)) if err != nil { return nil, err } return tz, nil }, Types: types(time.LoadLocation), }, { Name: "first", Func: func(args ...any) (any, error) { defer func() { if r := recover(); r != nil { return } }() return runtime.Fetch(args[0], 0), nil }, Validate: func(args []reflect.Type) (reflect.Type, error) { if len(args) != 1 { return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args)) } switch kind(args[0]) { case reflect.Interface: return anyType, nil case reflect.Slice, reflect.Array: return args[0].Elem(), nil } return anyType, fmt.Errorf("cannot get first element from %s", args[0]) }, }, { Name: "last", Func: func(args ...any) (any, error) { defer func() { if r := recover(); r != nil { return } }() return runtime.Fetch(args[0], -1), nil }, Validate: func(args []reflect.Type) (reflect.Type, error) { if len(args) != 1 { return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args)) } switch kind(args[0]) { case reflect.Interface: return anyType, nil case reflect.Slice, reflect.Array: return args[0].Elem(), nil } return anyType, fmt.Errorf("cannot get last element from %s", args[0]) }, }, { Name: "get", Func: get, }, { Name: "take", Func: func(args ...any) (any, error) { if len(args) != 2 { return nil, fmt.Errorf("invalid number of arguments (expected 2, got %d)", len(args)) } v := reflect.ValueOf(args[0]) if v.Kind() != reflect.Slice && v.Kind() != reflect.Array { return nil, fmt.Errorf("cannot take from %s", v.Kind()) } n := reflect.ValueOf(args[1]) if !n.CanInt() { return nil, fmt.Errorf("cannot take %s elements", n.Kind()) } to := 0 if n.Int() > int64(v.Len()) { to = v.Len() } else { to = int(n.Int()) } return v.Slice(0, to).Interface(), nil }, Validate: func(args []reflect.Type) (reflect.Type, error) { if len(args) != 2 { return anyType, fmt.Errorf("invalid number of arguments (expected 2, got %d)", len(args)) } switch kind(args[0]) { case reflect.Interface, reflect.Slice, reflect.Array: default: return anyType, fmt.Errorf("cannot take from %s", args[0]) } switch kind(args[1]) { case reflect.Interface, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: default: return anyType, fmt.Errorf("cannot take %s elements", args[1]) } return args[0], nil }, }, { Name: "keys", Func: func(args ...any) (any, error) { if len(args) != 1 { return nil, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args)) } v := reflect.ValueOf(args[0]) if v.Kind() != reflect.Map { return nil, fmt.Errorf("cannot get keys from %s", v.Kind()) } keys := v.MapKeys() out := make([]any, len(keys)) for i, key := range keys { out[i] = key.Interface() } return out, nil }, Validate: func(args []reflect.Type) (reflect.Type, error) { if len(args) != 1 { return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args)) } switch kind(args[0]) { case reflect.Interface: return arrayType, nil case reflect.Map: return arrayType, nil } return anyType, fmt.Errorf("cannot get keys from %s", args[0]) }, }, { Name: "values", Func: func(args ...any) (any, error) { if len(args) != 1 { return nil, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args)) } v := reflect.ValueOf(args[0]) if v.Kind() != reflect.Map { return nil, fmt.Errorf("cannot get values from %s", v.Kind()) } keys := v.MapKeys() out := make([]any, len(keys)) for i, key := range keys { out[i] = v.MapIndex(key).Interface() } return out, nil }, Validate: func(args []reflect.Type) (reflect.Type, error) { if len(args) != 1 { return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args)) } switch kind(args[0]) { case reflect.Interface: return arrayType, nil case reflect.Map: return arrayType, nil } return anyType, fmt.Errorf("cannot get values from %s", args[0]) }, }, { Name: "toPairs", Func: func(args ...any) (any, error) { if len(args) != 1 { return nil, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args)) } v := reflect.ValueOf(args[0]) if v.Kind() != reflect.Map { return nil, fmt.Errorf("cannot transform %s to pairs", v.Kind()) } keys := v.MapKeys() out := make([][2]any, len(keys)) for i, key := range keys { out[i] = [2]any{key.Interface(), v.MapIndex(key).Interface()} } return out, nil }, Validate: func(args []reflect.Type) (reflect.Type, error) { if len(args) != 1 { return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args)) } switch kind(args[0]) { case reflect.Interface, reflect.Map: return arrayType, nil } return anyType, fmt.Errorf("cannot transform %s to pairs", args[0]) }, }, { Name: "fromPairs", Func: func(args ...any) (any, error) { if len(args) != 1 { return nil, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args)) } v := reflect.ValueOf(args[0]) if v.Kind() != reflect.Slice && v.Kind() != reflect.Array { return nil, fmt.Errorf("cannot transform %s from pairs", v) } out := reflect.MakeMap(mapType) for i := 0; i < v.Len(); i++ { pair := deref.Value(v.Index(i)) if pair.Kind() != reflect.Array && pair.Kind() != reflect.Slice { return nil, fmt.Errorf("invalid pair %v", pair) } if pair.Len() != 2 { return nil, fmt.Errorf("invalid pair length %v", pair) } key := pair.Index(0) value := pair.Index(1) out.SetMapIndex(key, value) } return out.Interface(), nil }, Validate: func(args []reflect.Type) (reflect.Type, error) { if len(args) != 1 { return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args)) } switch kind(args[0]) { case reflect.Interface, reflect.Slice, reflect.Array: return mapType, nil } return anyType, fmt.Errorf("cannot transform %s from pairs", args[0]) }, }, { Name: "reverse", Safe: func(args ...any) (any, uint, error) { if len(args) != 1 { return nil, 0, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args)) } v := reflect.ValueOf(args[0]) if v.Kind() != reflect.Slice && v.Kind() != reflect.Array { return nil, 0, fmt.Errorf("cannot reverse %s", v.Kind()) } size := v.Len() arr := make([]any, size) for i := 0; i < size; i++ { arr[i] = v.Index(size - i - 1).Interface() } return arr, uint(size), nil }, Validate: func(args []reflect.Type) (reflect.Type, error) { if len(args) != 1 { return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args)) } switch kind(args[0]) { case reflect.Interface, reflect.Slice, reflect.Array: return arrayType, nil default: return anyType, fmt.Errorf("cannot reverse %s", args[0]) } }, }, { Name: "uniq", Func: func(args ...any) (any, error) { if len(args) != 1 { return nil, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args)) } v := reflect.ValueOf(args[0]) if v.Kind() != reflect.Array && v.Kind() != reflect.Slice { return nil, fmt.Errorf("cannot uniq %s", v.Kind()) } size := v.Len() ret := []any{} eq := func(i int) bool { for _, r := range ret { if runtime.Equal(v.Index(i).Interface(), r) { return true } } return false } for i := 0; i < size; i += 1 { if eq(i) { continue } ret = append(ret, v.Index(i).Interface()) } return ret, nil }, Validate: func(args []reflect.Type) (reflect.Type, error) { if len(args) != 1 { return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args)) } switch kind(args[0]) { case reflect.Interface, reflect.Slice, reflect.Array: return arrayType, nil default: return anyType, fmt.Errorf("cannot uniq %s", args[0]) } }, }, { Name: "concat", Safe: func(args ...any) (any, uint, error) { if len(args) == 0 { return nil, 0, fmt.Errorf("invalid number of arguments (expected at least 1, got 0)") } var size uint var arr []any for _, arg := range args { v := reflect.ValueOf(arg) if v.Kind() != reflect.Slice && v.Kind() != reflect.Array { return nil, 0, fmt.Errorf("cannot concat %s", v.Kind()) } size += uint(v.Len()) for i := 0; i < v.Len(); i++ { item := v.Index(i) arr = append(arr, item.Interface()) } } return arr, size, nil }, Validate: func(args []reflect.Type) (reflect.Type, error) { if len(args) == 0 { return anyType, fmt.Errorf("invalid number of arguments (expected at least 1, got 0)") } for _, arg := range args { switch kind(arg) { case reflect.Interface, reflect.Slice, reflect.Array: default: return anyType, fmt.Errorf("cannot concat %s", arg) } } return arrayType, nil }, }, { Name: "flatten", Safe: func(args ...any) (any, uint, error) { var size uint if len(args) != 1 { return nil, 0, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args)) } v := reflect.ValueOf(args[0]) if v.Kind() != reflect.Array && v.Kind() != reflect.Slice { return nil, size, fmt.Errorf("cannot flatten %s", v.Kind()) } ret, err := flatten(v, 0) if err != nil { return nil, 0, err } size = uint(len(ret)) return ret, size, nil }, Validate: func(args []reflect.Type) (reflect.Type, error) { if len(args) != 1 { return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args)) } for _, arg := range args { switch kind(arg) { case reflect.Interface, reflect.Slice, reflect.Array: default: return anyType, fmt.Errorf("cannot flatten %s", arg) } } return arrayType, nil }, }, { Name: "sort", Safe: func(args ...any) (any, uint, error) { if len(args) != 1 && len(args) != 2 { return nil, 0, fmt.Errorf("invalid number of arguments (expected 1 or 2, got %d)", len(args)) } var array []any switch in := args[0].(type) { case []any: array = make([]any, len(in)) copy(array, in) case []int: array = make([]any, len(in)) for i, v := range in { array[i] = v } case []float64: array = make([]any, len(in)) for i, v := range in { array[i] = v } case []string: array = make([]any, len(in)) for i, v := range in { array[i] = v } } var desc bool if len(args) == 2 { order, ok := args[1].(string) if !ok { return nil, 0, fmt.Errorf("sort order argument must be a string (got %T)", args[1]) } switch order { case "asc": desc = false case "desc": desc = true default: return nil, 0, fmt.Errorf("invalid order %s, expected asc or desc", order) } } sortable := &runtime.Sort{ Desc: desc, Array: array, } sort.Sort(sortable) return sortable.Array, uint(len(array)), nil }, Types: types( new(func([]any, string) []any), new(func([]int, string) []any), new(func([]float64, string) []any), new(func([]string, string) []any), new(func([]any) []any), new(func([]float64) []any), new(func([]string) []any), new(func([]int) []any), ), }, bitFunc("bitand", func(x, y int) (any, error) { return x & y, nil }), bitFunc("bitor", func(x, y int) (any, error) { return x | y, nil }), bitFunc("bitxor", func(x, y int) (any, error) { return x ^ y, nil }), bitFunc("bitnand", func(x, y int) (any, error) { return x &^ y, nil }), bitFunc("bitshl", func(x, y int) (any, error) { if y < 0 { return nil, fmt.Errorf("invalid operation: negative shift count %d (type int)", y) } return x << y, nil }), bitFunc("bitshr", func(x, y int) (any, error) { if y < 0 { return nil, fmt.Errorf("invalid operation: negative shift count %d (type int)", y) } return x >> y, nil }), bitFunc("bitushr", func(x, y int) (any, error) { if y < 0 { return nil, fmt.Errorf("invalid operation: negative shift count %d (type int)", y) } return int(uint(x) >> y), nil }), { Name: "bitnot", Func: func(args ...any) (any, error) { if len(args) != 1 { return nil, fmt.Errorf("invalid number of arguments for bitnot (expected 1, got %d)", len(args)) } x, err := toInt(args[0]) if err != nil { return nil, fmt.Errorf("%v to call bitnot", err) } return ^x, nil }, Types: types(new(func(int) int)), }, } ================================================ FILE: builtin/builtin_test.go ================================================ package builtin_test import ( "fmt" "reflect" "strings" "testing" "time" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr" "github.com/expr-lang/expr/builtin" "github.com/expr-lang/expr/checker" "github.com/expr-lang/expr/conf" "github.com/expr-lang/expr/parser" "github.com/expr-lang/expr/test/mock" ) func TestBuiltin(t *testing.T) { ArrayWithNil := []any{42} env := map[string]any{ "ArrayOfString": []string{"foo", "bar", "baz"}, "ArrayOfInt": []int{1, 2, 3}, "ArrayOfFloat": []float64{1.5, 2.5, 3.5}, "ArrayOfInt32": []int32{1, 2, 3}, "ArrayOfAny": []any{1, "2", true}, "ArrayOfFoo": []mock.Foo{{Value: "a"}, {Value: "b"}, {Value: "c"}}, "PtrArrayWithNil": &ArrayWithNil, "EmptyIntArray": []int{}, "EmptyFloatArray": []float64{}, "NestedIntArrays": []any{[]int{1, 2}, []int{3, 4}}, "NestedAnyArrays": []any{[]any{1, 2}, []any{3, 4}}, "MixedNestedArray": []any{1, []int{2, 3}, []float64{4.0, 5.0}}, "NestedInt32Array": []any{[]int32{1, 2}, []int32{3, 4}}, } var tests = []struct { input string want any }{ {`len(1..10)`, 10}, {`len({foo: 1, bar: 2})`, 2}, {`len("hello")`, 5}, {`abs(-5)`, 5}, {`abs(.5)`, .5}, {`abs(-.5)`, .5}, {`ceil(5.5)`, 6.0}, {`ceil(5)`, 5.0}, {`floor(5.5)`, 5.0}, {`floor(5)`, 5.0}, {`round(5.5)`, 6.0}, {`round(5)`, 5.0}, {`round(5.49)`, 5.0}, {`int(5.5)`, 5}, {`int(5)`, 5}, {`int("5")`, 5}, {`float(5)`, 5.0}, {`float(5.5)`, 5.5}, {`float("5.5")`, 5.5}, {`string(5)`, "5"}, {`string(5.5)`, "5.5"}, {`string("5.5")`, "5.5"}, {`trim(" foo ")`, "foo"}, {`trim("__foo___", "_")`, "foo"}, {`trimPrefix("prefix_foo", "prefix_")`, "foo"}, {`trimSuffix("foo_suffix", "_suffix")`, "foo"}, {`upper("foo")`, "FOO"}, {`lower("FOO")`, "foo"}, {`split("foo,bar,baz", ",")`, []string{"foo", "bar", "baz"}}, {`split("foo,bar,baz", ",", 2)`, []string{"foo", "bar,baz"}}, {`splitAfter("foo,bar,baz", ",")`, []string{"foo,", "bar,", "baz"}}, {`splitAfter("foo,bar,baz", ",", 2)`, []string{"foo,", "bar,baz"}}, {`replace("foo,bar,baz", ",", ";")`, "foo;bar;baz"}, {`replace("foo,bar,baz,goo", ",", ";", 2)`, "foo;bar;baz,goo"}, {`repeat("foo", 3)`, "foofoofoo"}, {`join(ArrayOfString, ",")`, "foo,bar,baz"}, {`join(ArrayOfString)`, "foobarbaz"}, {`join(["foo", "bar", "baz"], ",")`, "foo,bar,baz"}, {`join(["foo", "bar", "baz"])`, "foobarbaz"}, {`indexOf("foo,bar,baz", ",")`, 3}, {`lastIndexOf("foo,bar,baz", ",")`, 7}, {`hasPrefix("foo,bar,baz", "foo")`, true}, {`hasSuffix("foo,bar,baz", "baz")`, true}, {`max(1, 2, 3)`, 3}, {`max(1.5, 2.5, 3.5)`, 3.5}, {`max([1, 2, 3])`, 3}, {`max([1.5, 2.5, 3.5])`, 3.5}, {`max([1, 2, 4, 10], 20, [29, 23, -19])`, 29}, {`min([1, 2, 4, 10], 20, [29, 23, -19])`, -19}, {`min(1, 2, 3)`, 1}, {`min(1.5, 2.5, 3.5)`, 1.5}, {`min([1, 2, 3])`, 1}, {`min([1.5, 2.5, 3.5])`, 1.5}, {`min(-1, [1.5, 2.5, 3.5])`, -1}, {`max(ArrayOfInt)`, 3}, {`min(ArrayOfInt)`, 1}, {`max(ArrayOfFloat)`, 3.5}, {`min(ArrayOfFloat)`, 1.5}, {`max(EmptyIntArray, 5)`, 5}, {`min(EmptyFloatArray, 5)`, 5}, {`max(NestedIntArrays)`, 4}, {`min(NestedIntArrays)`, 1}, {`max(NestedAnyArrays)`, 4}, {`min(NestedAnyArrays)`, 1}, {`max(MixedNestedArray)`, 5.0}, {`min(MixedNestedArray)`, 1}, {`max(ArrayOfInt32)`, int32(3)}, {`min(ArrayOfInt32)`, int32(1)}, {`max(NestedInt32Array)`, int32(4)}, {`min(NestedInt32Array)`, int32(1)}, {`sum(1..9)`, 45}, {`sum([.5, 1.5, 2.5])`, 4.5}, {`sum([])`, 0}, {`sum([1, 2, 3.0, 4])`, 10.0}, {`mean(1..9)`, 5.0}, {`mean([.5, 1.5, 2.5])`, 1.5}, {`mean([])`, 0.0}, {`mean([1, 2, 3.0, 4])`, 2.5}, {`mean(10, [1, 2, 3], 1..9)`, 4.6923076923076925}, {`mean(-10, [1, 2, 3, 4])`, 0.0}, {`mean(10.9, 1..9)`, 5.59}, {`mean(ArrayOfInt)`, 2.0}, {`mean(ArrayOfFloat)`, 2.5}, {`mean(NestedIntArrays)`, 2.5}, {`mean(NestedAnyArrays)`, 2.5}, {`mean(MixedNestedArray)`, 3.0}, {`mean(ArrayOfInt32)`, 2.0}, {`mean(NestedInt32Array)`, 2.5}, {`median(1..9)`, 5.0}, {`median([.5, 1.5, 2.5])`, 1.5}, {`median([])`, 0.0}, {`median([1, 2, 3])`, 2.0}, {`median([1, 2, 3, 4])`, 2.5}, {`median(10, [1, 2, 3], 1..9)`, 4.0}, {`median(-10, [1, 2, 3, 4])`, 2.0}, {`median(1..5, 4.9)`, 3.5}, {`median(ArrayOfInt)`, 2.0}, {`median(ArrayOfFloat)`, 2.5}, {`median(NestedIntArrays)`, 2.5}, {`median(NestedAnyArrays)`, 2.5}, {`median(MixedNestedArray)`, 3.0}, {`median(ArrayOfInt32)`, 2.0}, {`median(NestedInt32Array)`, 2.5}, {`toJSON({foo: 1, bar: 2})`, "{\n \"bar\": 2,\n \"foo\": 1\n}"}, {`fromJSON("[1, 2, 3]")`, []any{1.0, 2.0, 3.0}}, {`toBase64("hello")`, "aGVsbG8="}, {`fromBase64("aGVsbG8=")`, "hello"}, {`now().Format("2006-01-02T15:04Z")`, time.Now().Format("2006-01-02T15:04Z")}, {`duration("1h")`, time.Hour}, {`date("2006-01-02T15:04:05Z")`, time.Date(2006, 1, 2, 15, 4, 5, 0, time.UTC)}, {`date("2006.01.02", "2006.01.02")`, time.Date(2006, 1, 2, 0, 0, 0, 0, time.UTC)}, {`date("2023-04-23T00:30:00.000+0100", "2006-01-02T15:04:05-0700", "America/Chicago").Format("2006-01-02")`, "2023-04-23"}, {`date("2023-04-23T00:30:00", "2006-01-02T15:04:05", "America/Chicago").Format("2006-01-02")`, "2023-04-23"}, {`date("2023-04-23", "2006-01-02", "America/Chicago").Format("2006-01-02")`, "2023-04-23"}, {`timezone("UTC").String()`, "UTC"}, {`timezone("Europe/Moscow").String()`, "Europe/Moscow"}, {`first(ArrayOfString)`, "foo"}, {`first(ArrayOfInt)`, 1}, {`first(ArrayOfAny)`, 1}, {`first([])`, nil}, {`last(ArrayOfString)`, "baz"}, {`last(ArrayOfInt)`, 3}, {`last(ArrayOfAny)`, true}, {`last([])`, nil}, {`get(ArrayOfString, 1)`, "bar"}, {`get(ArrayOfString, 99)`, nil}, {`get(ArrayOfInt, 1)`, 2}, {`get(ArrayOfInt, -1)`, 3}, {`get(ArrayOfAny, 1)`, "2"}, {`get({foo: 1, bar: 2}, "foo")`, 1}, {`get({foo: 1, bar: 2}, "unknown")`, nil}, {`take(ArrayOfString, 2)`, []string{"foo", "bar"}}, {`take(ArrayOfString, 99)`, []string{"foo", "bar", "baz"}}, {`"foo" in keys({foo: 1, bar: 2})`, true}, {`1 in values({foo: 1, bar: 2})`, true}, {`len(toPairs({foo: 1, bar: 2}))`, 2}, {`len(toPairs({}))`, 0}, {`fromPairs([["foo", 1], ["bar", 2]])`, map[any]any{"foo": 1, "bar": 2}}, {`fromPairs(toPairs({foo: 1, bar: 2}))`, map[any]any{"foo": 1, "bar": 2}}, {`groupBy(1..9, # % 2)`, map[any][]any{0: {2, 4, 6, 8}, 1: {1, 3, 5, 7, 9}}}, {`groupBy(1..9, # % 2)[0]`, []any{2, 4, 6, 8}}, {`groupBy(1..3, # > 1)[true]`, []any{2, 3}}, {`groupBy(1..3, # > 1 ? nil : "")[nil]`, []any{2, 3}}, {`groupBy(ArrayOfFoo, .Value).a`, []any{mock.Foo{Value: "a"}}}, {`reduce(1..9, # + #acc, 0)`, 45}, {`reduce(1..9, # + #acc)`, 45}, {`reduce([.5, 1.5, 2.5], # + #acc, 0)`, 4.5}, {`reduce([], 5, 0)`, 0}, {`reduce(10..1, # + #acc, 100)`, 100}, {`reduce([], # + #acc, 42)`, 42}, {`concat(ArrayOfString, ArrayOfInt)`, []any{"foo", "bar", "baz", 1, 2, 3}}, {`concat(PtrArrayWithNil, [nil])`, []any{42, nil}}, {`flatten([["a", "b"], [1, 2]])`, []any{"a", "b", 1, 2}}, {`flatten([["a", "b"], [1, 2, [3, 4]]])`, []any{"a", "b", 1, 2, 3, 4}}, {`flatten([["a", "b"], [1, 2, [3, [[[["c", "d"], "e"]]], 4]]])`, []any{"a", "b", 1, 2, 3, "c", "d", "e", 4}}, {`uniq([1, 15, "a", 2, 3, 5, 2, "a", 2, "b"])`, []any{1, 15, "a", 2, 3, 5, "b"}}, {`uniq([[1, 2], "a", 2, 3, [1, 2], [1, 3]])`, []any{[]any{1, 2}, "a", 2, 3, []any{1, 3}}}, } for _, test := range tests { t.Run(test.input, func(t *testing.T) { program, err := expr.Compile(test.input, expr.Env(env)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) assert.Equal(t, test.want, out) }) } } func TestBuiltin_works_with_any(t *testing.T) { config := map[string]struct { arity int }{ "now": {0}, "get": {2}, "take": {2}, "sortBy": {2}, } for _, b := range builtin.Builtins { if b.Predicate { continue } t.Run(b.Name, func(t *testing.T) { arity := 1 if c, ok := config[b.Name]; ok { arity = c.arity } if len(b.Types) > 0 { arity = b.Types[0].NumIn() } args := make([]string, arity) for i := 1; i <= arity; i++ { args[i-1] = fmt.Sprintf("arg%d", i) } _, err := expr.Compile(fmt.Sprintf(`%s(%s)`, b.Name, strings.Join(args, ", "))) // expr.Env(env) is not needed assert.NoError(t, err) }) } } func TestBuiltin_errors(t *testing.T) { var errorTests = []struct { input string err string }{ {`len()`, `invalid number of arguments (expected 1, got 0)`}, {`len(1)`, `invalid argument for len (type int)`}, {`abs()`, `invalid number of arguments (expected 1, got 0)`}, {`abs(1, 2)`, `invalid number of arguments (expected 1, got 2)`}, {`abs("foo")`, `invalid argument for abs (type string)`}, {`int()`, `invalid number of arguments (expected 1, got 0)`}, {`int(1, 2)`, `invalid number of arguments (expected 1, got 2)`}, {`float()`, `invalid number of arguments (expected 1, got 0)`}, {`float(1, 2)`, `invalid number of arguments (expected 1, got 2)`}, {`string(1, 2)`, `too many arguments to call string`}, {`trim()`, `not enough arguments to call trim`}, {`max()`, `not enough arguments to call max`}, {`max(1, "2")`, `invalid argument for max (type string)`}, {`max([1, "2"])`, `invalid argument for max (type string)`}, {`min()`, `not enough arguments to call min`}, {`min(1, "2")`, `invalid argument for min (type string)`}, {`min([1, "2"])`, `invalid argument for min (type string)`}, {`median(1..9, "t")`, "invalid argument for median (type string)"}, {`mean("s", 1..9)`, "invalid argument for mean (type string)"}, {`duration("error")`, `invalid duration`}, {`date("error")`, `invalid date`}, {`get()`, `invalid number of arguments (expected 2, got 0)`}, {`get(1, 2)`, `type int does not support indexing`}, {`bitnot("1")`, "cannot use string as argument (type int) to call bitnot (1:8)"}, {`bitand("1", 1)`, "cannot use string as argument (type int) to call bitand (1:8)"}, {`"10" | bitor(1)`, "cannot use string as argument (type int) to call bitor (1:1)"}, {`bitshr("5", 1)`, "cannot use string as argument (type int) to call bitshr (1:8)"}, {`bitshr(-5, -2)`, "invalid operation: negative shift count -2 (type int) (1:1)"}, {`bitshl(1, -1)`, "invalid operation: negative shift count -1 (type int) (1:1)"}, {`bitushr(-5, -2)`, "invalid operation: negative shift count -2 (type int) (1:1)"}, {`now(nil)`, "invalid number of arguments (expected 0, got 1)"}, {`date(nil)`, "interface {} is nil, not string (1:1)"}, {`timezone(nil)`, "cannot use nil as argument (type string) to call timezone (1:10)"}, {`flatten([1, 2], [3, 4])`, "invalid number of arguments (expected 1, got 2)"}, {`flatten(1)`, "cannot flatten int"}, {`fromJSON("5e2482")`, "cannot unmarshal number"}, } for _, test := range errorTests { t.Run(test.input, func(t *testing.T) { program, err := expr.Compile(test.input) if err != nil { assert.Error(t, err) assert.Contains(t, err.Error(), test.err) } else { _, err = expr.Run(program, nil) assert.Error(t, err) assert.Contains(t, err.Error(), test.err) } }) } } func TestBuiltin_env_not_callable(t *testing.T) { code := `$env(''matches'i'?t:get().UTC())` env := map[string]any{"t": 1} _, err := expr.Compile(code, expr.Env(env)) require.Error(t, err) assert.Contains(t, err.Error(), "is not callable") } func TestBuiltin_types(t *testing.T) { env := map[string]any{ "num": 42, "str": "foo", "ArrayOfString": []string{"foo", "bar", "baz"}, "ArrayOfInt": []int{1, 2, 3}, } tests := []struct { input string want reflect.Kind }{ {`get(ArrayOfString, 0)`, reflect.String}, {`get(ArrayOfInt, 0)`, reflect.Int}, {`first(ArrayOfString)`, reflect.String}, {`first(ArrayOfInt)`, reflect.Int}, {`last(ArrayOfString)`, reflect.String}, {`last(ArrayOfInt)`, reflect.Int}, {`get($env, 'str')`, reflect.String}, {`get($env, 'num')`, reflect.Int}, {`get($env, 'ArrayOfString')`, reflect.Slice}, } for _, test := range tests { t.Run(test.input, func(t *testing.T) { tree, err := parser.Parse(test.input) require.NoError(t, err) rtype, err := checker.Check(tree, conf.New(env)) require.NoError(t, err) require.True(t, rtype.Kind() == test.want, fmt.Sprintf("expected %s, got %s", test.want, rtype.Kind())) }) } } func TestBuiltin_memory_limits(t *testing.T) { tests := []struct { input string }{ {`repeat("\xc4<\xc4\xc4\xc4",10009999990)`}, } for _, test := range tests { t.Run(test.input, func(t *testing.T) { timeout := make(chan bool, 1) go func() { time.Sleep(time.Second) timeout <- true }() done := make(chan bool, 1) go func() { _, err := expr.Eval(test.input, nil) assert.Error(t, err) assert.Contains(t, err.Error(), "memory budget exceeded") done <- true }() select { case <-done: // Success. case <-timeout: t.Fatal("timeout") } }) } } func TestBuiltin_allow_builtins_override(t *testing.T) { t.Run("via env var", func(t *testing.T) { for _, name := range builtin.Names { t.Run(name, func(t *testing.T) { env := map[string]any{ name: "hello world", } program, err := expr.Compile(name, expr.Env(env)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) assert.Equal(t, "hello world", out) }) } }) t.Run("via env func", func(t *testing.T) { for _, name := range builtin.Names { t.Run(name, func(t *testing.T) { env := map[string]any{ name: func() int { return 1 }, } program, err := expr.Compile(fmt.Sprintf("%s()", name), expr.Env(env)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) assert.Equal(t, 1, out) }) } }) t.Run("via expr.Function", func(t *testing.T) { for _, name := range builtin.Names { t.Run(name, func(t *testing.T) { fn := expr.Function(name, func(params ...any) (any, error) { return 42, nil }, new(func() int), ) program, err := expr.Compile(fmt.Sprintf("%s()", name), fn) require.NoError(t, err) out, err := expr.Run(program, nil) require.NoError(t, err) assert.Equal(t, 42, out) }) } }) t.Run("via expr.Function as pipe", func(t *testing.T) { for _, name := range builtin.Names { t.Run(name, func(t *testing.T) { fn := expr.Function(name, func(params ...any) (any, error) { return 42, nil }, new(func(s string) int), ) program, err := expr.Compile(fmt.Sprintf("'str' | %s()", name), fn) require.NoError(t, err) out, err := expr.Run(program, nil) require.NoError(t, err) assert.Equal(t, 42, out) }) } }) } func TestBuiltin_override_and_still_accessible(t *testing.T) { env := map[string]any{ "len": func() int { return 42 }, "all": []int{1, 2, 3}, } program, err := expr.Compile(`::all(all, #>0) && len() == 42 && ::len(all) == 3`, expr.Env(env)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) assert.Equal(t, true, out) } func TestBuiltin_DisableBuiltin(t *testing.T) { t.Run("via env", func(t *testing.T) { for _, b := range builtin.Builtins { if b.Predicate { continue // TODO: allow to disable predicates } t.Run(b.Name, func(t *testing.T) { env := map[string]any{ b.Name: func() int { return 42 }, } program, err := expr.Compile(b.Name+"()", expr.Env(env), expr.DisableBuiltin(b.Name)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) assert.Equal(t, 42, out) }) } }) t.Run("via expr.Function", func(t *testing.T) { for _, b := range builtin.Builtins { if b.Predicate { continue // TODO: allow to disable predicates } t.Run(b.Name, func(t *testing.T) { fn := expr.Function(b.Name, func(params ...any) (any, error) { return 42, nil }, new(func() int), ) program, err := expr.Compile(b.Name+"()", fn, expr.DisableBuiltin(b.Name)) require.NoError(t, err) out, err := expr.Run(program, nil) require.NoError(t, err) assert.Equal(t, 42, out) }) } }) } func TestBuiltin_DisableAllBuiltins(t *testing.T) { _, err := expr.Compile(`len("foo")`, expr.Env(nil), expr.DisableAllBuiltins()) require.Error(t, err) assert.Contains(t, err.Error(), "unknown name len") } func TestBuiltin_EnableBuiltin(t *testing.T) { t.Run("via env", func(t *testing.T) { env := map[string]any{ "repeat": func() string { return "repeat" }, } program, err := expr.Compile(`len(repeat())`, expr.Env(env), expr.DisableAllBuiltins(), expr.EnableBuiltin("len")) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) assert.Equal(t, 6, out) }) t.Run("via expr.Function", func(t *testing.T) { fn := expr.Function("repeat", func(params ...any) (any, error) { return "repeat", nil }, new(func() string), ) program, err := expr.Compile(`len(repeat())`, fn, expr.DisableAllBuiltins(), expr.EnableBuiltin("len")) require.NoError(t, err) out, err := expr.Run(program, nil) require.NoError(t, err) assert.Equal(t, 6, out) }) } func TestBuiltin_type(t *testing.T) { type Foo struct{} var b any = 1 var a any = &b tests := []struct { obj any want string }{ {nil, "nil"}, {true, "bool"}, {1, "int"}, {int8(1), "int"}, {uint(1), "uint"}, {1.0, "float"}, {float32(1.0), "float"}, {"string", "string"}, {[]string{"foo", "bar"}, "array"}, {map[string]any{"foo": "bar"}, "map"}, {func() {}, "func"}, {time.Now(), "time.Time"}, {time.Second, "time.Duration"}, {Foo{}, "github.com/expr-lang/expr/builtin_test.Foo"}, {struct{}{}, "struct"}, {a, "int"}, } for _, test := range tests { t.Run(test.want, func(t *testing.T) { env := map[string]any{ "obj": test.obj, } program, err := expr.Compile(`type(obj)`, expr.Env(env)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) assert.Equal(t, test.want, out) }) } } func TestBuiltin_reverse(t *testing.T) { env := map[string]any{ "ArrayOfString": []string{"foo", "bar", "baz"}, "ArrayOfInt": []int{2, 1, 3}, "ArrayOfFloat": []float64{3.0, 2.0, 1.0}, "ArrayOfFoo": []mock.Foo{{Value: "c"}, {Value: "a"}, {Value: "b"}}, } tests := []struct { input string want any }{ {`reverse([])`, []any{}}, {`reverse(ArrayOfInt)`, []any{3, 1, 2}}, {`reverse(ArrayOfFloat)`, []any{1.0, 2.0, 3.0}}, {`reverse(ArrayOfFoo)`, []any{mock.Foo{Value: "b"}, mock.Foo{Value: "a"}, mock.Foo{Value: "c"}}}, {`reverse([[1,2], [2,2]])`, []any{[]any{2, 2}, []any{1, 2}}}, {`reverse(reverse([[1,2], [2,2]]))`, []any{[]any{1, 2}, []any{2, 2}}}, {`reverse([{"test": true}, {id:4}, {name: "value"}])`, []any{map[string]any{"name": "value"}, map[string]any{"id": 4}, map[string]any{"test": true}}}, } for _, test := range tests { t.Run(test.input, func(t *testing.T) { program, err := expr.Compile(test.input, expr.Env(env)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) assert.Equal(t, test.want, out) }) } } func TestBuiltin_sort(t *testing.T) { env := map[string]any{ "ArrayOfString": []string{"foo", "bar", "baz"}, "ArrayOfInt": []int{3, 2, 1}, "ArrayOfFloat": []float64{3.0, 2.0, 1.0}, "ArrayOfFoo": []mock.Foo{{Value: "c"}, {Value: "a"}, {Value: "b"}}, } tests := []struct { input string want any }{ {`sort([])`, []any{}}, {`sort(ArrayOfInt)`, []any{1, 2, 3}}, {`sort(ArrayOfFloat)`, []any{1.0, 2.0, 3.0}}, {`sort(ArrayOfInt, 'desc')`, []any{3, 2, 1}}, {`sortBy(ArrayOfFoo, .Value)`, []any{mock.Foo{Value: "a"}, mock.Foo{Value: "b"}, mock.Foo{Value: "c"}}}, {`sortBy([{id: "a"}, {id: "b"}], .id, "desc")`, []any{map[string]any{"id": "b"}, map[string]any{"id": "a"}}}, } for _, test := range tests { t.Run(test.input, func(t *testing.T) { program, err := expr.Compile(test.input, expr.Env(env)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) assert.Equal(t, test.want, out) }) } } func TestBuiltin_sort_i64(t *testing.T) { env := map[string]any{ "array": []int{1, 2, 3}, "i64": int64(1), } program, err := expr.Compile(`sort(map(array, i64))`, expr.Env(env)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) assert.Equal(t, []any{int64(1), int64(1), int64(1)}, out) } func TestBuiltin_bitOpsFunc(t *testing.T) { tests := []struct { input string want int }{ {`bitnot(156)`, -157}, {`bitand(bitnot(156), 255)`, 99}, {`bitor(987, -123)`, -33}, {`bitxor(15, 32)`, 47}, {`bitshl(39, 3)`, 312}, {`bitshr(5, 1)`, 2}, {`bitushr(-5, 2)`, 4611686018427387902}, {`bitnand(35, 9)`, 34}, } for _, test := range tests { t.Run(test.input, func(t *testing.T) { program, err := expr.Compile(test.input, expr.Env(nil)) require.NoError(t, err) out, err := expr.Run(program, nil) fmt.Printf("%v : %v", test.input, out) require.NoError(t, err) assert.Equal(t, test.want, out) }) } } type customInt int func Test_int_unwraps_underlying_value(t *testing.T) { env := map[string]any{ "customInt": customInt(42), } program, err := expr.Compile(`int(customInt) == 42`, expr.Env(env)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) assert.Equal(t, true, out) } func TestBuiltin_with_deref(t *testing.T) { x := 42 arr := []int{1, 2, 3} arrStr := []string{"1", "2", "3"} m := map[string]any{"a": 1, "b": 2} jsonString := `["1"]` str := "1,2,3" env := map[string]any{ "x": &x, "arr": &arr, "arrStr": &arrStr, "m": &m, "json": &jsonString, "str": &str, } tests := []struct { input string want any }{ {`all(arr, # > 0)`, true}, {`none(arr, # < 0)`, true}, {`any(arr, # > 0)`, true}, {`one(arr, # > 2)`, true}, {`filter(arr, # > 0)`, []any{1, 2, 3}}, {`map(arr, # * #)`, []any{1, 4, 9}}, {`count(arr, # > 0)`, 3}, {`sum(arr)`, 6}, {`find(arr, # > 0)`, 1}, {`findIndex(arr, # > 1)`, 1}, {`findLast(arr, # > 0)`, 3}, {`findLastIndex(arr, # > 0)`, 2}, {`groupBy(arr, # % 2 == 0)`, map[any][]any{false: {1, 3}, true: {2}}}, {`sortBy(arr, -#)`, []any{3, 2, 1}}, {`reduce(arr, # + #acc, x)`, 6 + 42}, {`ceil(x)`, 42.0}, {`floor(x)`, 42.0}, {`round(x)`, 42.0}, {`int(x)`, 42}, {`float(x)`, 42.0}, {`abs(x)`, 42}, {`first(arr)`, 1}, {`last(arr)`, 3}, {`take(arr, 1)`, []int{1}}, {`take(arr, x)`, []int{1, 2, 3}}, {`'a' in keys(m)`, true}, {`1 in values(m)`, true}, {`len(arr)`, 3}, {`type(arr)`, "array"}, {`type(m)`, "map"}, {`reverse(arr)`, []any{3, 2, 1}}, {`uniq(arr)`, []any{1, 2, 3}}, {`concat(arr, arr)`, []any{1, 2, 3, 1, 2, 3}}, {`flatten([arr, [arr]])`, []any{1, 2, 3, 1, 2, 3}}, {`flatten(arr)`, []any{1, 2, 3}}, {`toJSON(arr)`, "[\n 1,\n 2,\n 3\n]"}, {`fromJSON(json)`, []any{"1"}}, {`split(str, ",")`, []string{"1", "2", "3"}}, {`join(arrStr, ",")`, "1,2,3"}, } for _, test := range tests { t.Run(test.input, func(t *testing.T) { program, err := expr.Compile(test.input, expr.Env(env)) require.NoError(t, err) println(program.Disassemble()) out, err := expr.Run(program, env) require.NoError(t, err) assert.Equal(t, test.want, out) out, err = expr.Eval(test.input, env) require.NoError(t, err) assert.Equal(t, test.want, out) }) } } func TestBuiltin_flatten_recursion(t *testing.T) { var s []any s = append(s, &s) // s contains a pointer to itself env := map[string]any{ "arr": s, } program, err := expr.Compile("flatten(arr)", expr.Env(env)) require.NoError(t, err) _, err = expr.Run(program, env) require.Error(t, err) assert.Contains(t, err.Error(), builtin.ErrorMaxDepth.Error()) } func TestBuiltin_flatten_recursion_slice(t *testing.T) { s := make([]any, 1) s[0] = s env := map[string]any{ "arr": s, } program, err := expr.Compile("flatten(arr)", expr.Env(env)) require.NoError(t, err) _, err = expr.Run(program, env) require.Error(t, err) assert.Contains(t, err.Error(), builtin.ErrorMaxDepth.Error()) } func TestBuiltin_numerical_recursion(t *testing.T) { s := make([]any, 1) s[0] = s env := map[string]any{ "arr": s, } tests := []string{ "max(arr)", "min(arr)", "mean(arr)", "median(arr)", } for _, input := range tests { t.Run(input, func(t *testing.T) { program, err := expr.Compile(input, expr.Env(env)) require.NoError(t, err) _, err = expr.Run(program, env) require.Error(t, err) assert.Contains(t, err.Error(), builtin.ErrorMaxDepth.Error()) }) } } func TestBuiltin_recursion_custom_max_depth(t *testing.T) { originalMaxDepth := builtin.MaxDepth defer func() { builtin.MaxDepth = originalMaxDepth }() // Set a small depth limit builtin.MaxDepth = 2 // Create a deeply nested array (depth 5) // [1, [2, [3, [4, [5]]]]] arr := []any{1, []any{2, []any{3, []any{4, []any{5}}}}} env := map[string]any{ "arr": arr, } t.Run("flatten exceeds max depth", func(t *testing.T) { program, err := expr.Compile("flatten(arr)", expr.Env(env)) require.NoError(t, err) _, err = expr.Run(program, env) require.Error(t, err) assert.Contains(t, err.Error(), builtin.ErrorMaxDepth.Error()) }) t.Run("flatten within max depth", func(t *testing.T) { // Depth 2: [1, [2]] shallowArr := []any{1, []any{2}} envShallow := map[string]any{"arr": shallowArr} program, err := expr.Compile("flatten(arr)", expr.Env(envShallow)) require.NoError(t, err) _, err = expr.Run(program, envShallow) require.NoError(t, err) }) } func TestAbs_UnsignedIntegers(t *testing.T) { // Test that abs() correctly handles unsigned integers // Unsigned integers are always non-negative, so abs() should return them unchanged tests := []struct { name string env map[string]any expr string want any }{ {"uint", map[string]any{"x": uint(42)}, "abs(x)", uint(42)}, {"uint8", map[string]any{"x": uint8(42)}, "abs(x)", uint8(42)}, {"uint16", map[string]any{"x": uint16(42)}, "abs(x)", uint16(42)}, {"uint32", map[string]any{"x": uint32(42)}, "abs(x)", uint32(42)}, {"uint64", map[string]any{"x": uint64(42)}, "abs(x)", uint64(42)}, {"uint zero", map[string]any{"x": uint(0)}, "abs(x)", uint(0)}, {"uint8 zero", map[string]any{"x": uint8(0)}, "abs(x)", uint8(0)}, {"uint16 zero", map[string]any{"x": uint16(0)}, "abs(x)", uint16(0)}, {"uint32 zero", map[string]any{"x": uint32(0)}, "abs(x)", uint32(0)}, {"uint64 zero", map[string]any{"x": uint64(0)}, "abs(x)", uint64(0)}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { program, err := expr.Compile(tt.expr, expr.Env(tt.env)) require.NoError(t, err) result, err := expr.Run(program, tt.env) require.NoError(t, err) assert.Equal(t, tt.want, result) }) } } ================================================ FILE: builtin/function.go ================================================ package builtin import ( "reflect" ) type Function struct { Name string Fast func(arg any) any Func func(args ...any) (any, error) Safe func(args ...any) (any, uint, error) Types []reflect.Type Validate func(args []reflect.Type) (reflect.Type, error) Deref func(i int, arg reflect.Type) bool Predicate bool } func (f *Function) Type() reflect.Type { if len(f.Types) > 0 { return f.Types[0] } return reflect.TypeOf(f.Func) } ================================================ FILE: builtin/lib.go ================================================ package builtin import ( "fmt" "math" "reflect" "strconv" "unicode/utf8" "github.com/expr-lang/expr/internal/deref" "github.com/expr-lang/expr/vm/runtime" ) func Len(x any) any { v := reflect.ValueOf(x) switch v.Kind() { case reflect.Array, reflect.Slice, reflect.Map: return v.Len() case reflect.String: return utf8.RuneCountInString(v.String()) default: panic(fmt.Sprintf("invalid argument for len (type %T)", x)) } } func Type(arg any) any { if arg == nil { return "nil" } v := reflect.ValueOf(arg) if v.Type().Name() != "" && v.Type().PkgPath() != "" { return fmt.Sprintf("%s.%s", v.Type().PkgPath(), v.Type().Name()) } switch v.Type().Kind() { case reflect.Invalid: return "invalid" case reflect.Bool: return "bool" case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return "int" case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: return "uint" case reflect.Float32, reflect.Float64: return "float" case reflect.String: return "string" case reflect.Array, reflect.Slice: return "array" case reflect.Map: return "map" case reflect.Func: return "func" case reflect.Struct: return "struct" default: return "unknown" } } func Abs(x any) any { switch x := x.(type) { case float32: if x < 0 { return -x } else { return x } case float64: if x < 0 { return -x } else { return x } case int: if x < 0 { return -x } else { return x } case int8: if x < 0 { return -x } else { return x } case int16: if x < 0 { return -x } else { return x } case int32: if x < 0 { return -x } else { return x } case int64: if x < 0 { return -x } else { return x } case uint: return x case uint8: return x case uint16: return x case uint32: return x case uint64: return x } panic(fmt.Sprintf("invalid argument for abs (type %T)", x)) } func Ceil(x any) any { switch x := x.(type) { case float32: return math.Ceil(float64(x)) case float64: return math.Ceil(x) case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64: return Float(x) } panic(fmt.Sprintf("invalid argument for ceil (type %T)", x)) } func Floor(x any) any { switch x := x.(type) { case float32: return math.Floor(float64(x)) case float64: return math.Floor(x) case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64: return Float(x) } panic(fmt.Sprintf("invalid argument for floor (type %T)", x)) } func Round(x any) any { switch x := x.(type) { case float32: return math.Round(float64(x)) case float64: return math.Round(x) case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64: return Float(x) } panic(fmt.Sprintf("invalid argument for round (type %T)", x)) } func Int(x any) any { switch x := x.(type) { case float32: return int(x) case float64: return int(x) case int: return x case int8: return int(x) case int16: return int(x) case int32: return int(x) case int64: return int(x) case uint: return int(x) case uint8: return int(x) case uint16: return int(x) case uint32: return int(x) case uint64: return int(x) case string: i, err := strconv.Atoi(x) if err != nil { panic(fmt.Sprintf("invalid operation: int(%s)", x)) } return i default: val := reflect.ValueOf(x) if val.CanConvert(integerType) { return val.Convert(integerType).Interface() } panic(fmt.Sprintf("invalid operation: int(%T)", x)) } } func Float(x any) any { switch x := x.(type) { case float32: return float64(x) case float64: return x case int: return float64(x) case int8: return float64(x) case int16: return float64(x) case int32: return float64(x) case int64: return float64(x) case uint: return float64(x) case uint8: return float64(x) case uint16: return float64(x) case uint32: return float64(x) case uint64: return float64(x) case string: f, err := strconv.ParseFloat(x, 64) if err != nil { panic(fmt.Sprintf("invalid operation: float(%s)", x)) } return f default: panic(fmt.Sprintf("invalid operation: float(%T)", x)) } } func String(arg any) any { return fmt.Sprintf("%v", arg) } func minMax(name string, fn func(any, any) bool, depth int, args ...any) (any, error) { if depth > MaxDepth { return nil, ErrorMaxDepth } var val any for _, arg := range args { // Fast paths for common typed slices - avoid reflection and allocations switch arr := arg.(type) { case []int: if len(arr) == 0 { continue } m := arr[0] for i := 1; i < len(arr); i++ { if fn(m, arr[i]) { m = arr[i] } } if val == nil || fn(val, m) { val = m } continue case []float64: if len(arr) == 0 { continue } m := arr[0] for i := 1; i < len(arr); i++ { if fn(m, arr[i]) { m = arr[i] } } if val == nil || fn(val, m) { val = m } continue case []any: // Fast path for []any with simple numeric types for _, elem := range arr { switch e := elem.(type) { case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64: if val == nil || fn(val, e) { val = e } case []int, []float64, []any: // Nested array - recurse nested, err := minMax(name, fn, depth+1, e) if err != nil { return nil, err } if nested != nil && (val == nil || fn(val, nested)) { val = nested } default: // Could be another slice type, use reflection rv := reflect.ValueOf(e) if rv.Kind() == reflect.Slice || rv.Kind() == reflect.Array { nested, err := minMax(name, fn, depth+1, e) if err != nil { return nil, err } if nested != nil && (val == nil || fn(val, nested)) { val = nested } } else { return nil, fmt.Errorf("invalid argument for %s (type %T)", name, e) } } } continue } // Slow path: use reflection for other types rv := reflect.ValueOf(arg) switch rv.Kind() { case reflect.Array, reflect.Slice: size := rv.Len() for i := 0; i < size; i++ { elemVal, err := minMax(name, fn, depth+1, rv.Index(i).Interface()) if err != nil { return nil, err } switch elemVal.(type) { case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, float32, float64: if elemVal != nil && (val == nil || fn(val, elemVal)) { val = elemVal } default: return nil, fmt.Errorf("invalid argument for %s (type %T)", name, elemVal) } } case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64: elemVal := rv.Interface() if val == nil || fn(val, elemVal) { val = elemVal } default: if len(args) == 1 { return args[0], nil } return nil, fmt.Errorf("invalid argument for %s (type %T)", name, arg) } } return val, nil } func mean(depth int, args ...any) (int, float64, error) { if depth > MaxDepth { return 0, 0, ErrorMaxDepth } var total float64 var count int for _, arg := range args { // Fast paths for common typed slices - avoid reflection and allocations switch arr := arg.(type) { case []int: for _, v := range arr { total += float64(v) } count += len(arr) continue case []float64: for _, v := range arr { total += v } count += len(arr) continue case []any: // Fast path for []any - single pass without recursive calls for flat arrays for _, elem := range arr { switch e := elem.(type) { case int: total += float64(e) count++ case float64: total += e count++ case []int, []float64, []any: // Nested array - recurse nestedCount, nestedSum, err := mean(depth+1, e) if err != nil { return 0, 0, err } total += nestedSum count += nestedCount default: // Other numeric types or slices - use reflection rv := reflect.ValueOf(e) switch rv.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: total += float64(rv.Int()) count++ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: total += float64(rv.Uint()) count++ case reflect.Float32, reflect.Float64: total += rv.Float() count++ case reflect.Slice, reflect.Array: nestedCount, nestedSum, err := mean(depth+1, e) if err != nil { return 0, 0, err } total += nestedSum count += nestedCount default: return 0, 0, fmt.Errorf("invalid argument for mean (type %T)", e) } } } continue } // Slow path: use reflection for other types rv := reflect.ValueOf(arg) switch rv.Kind() { case reflect.Array, reflect.Slice: size := rv.Len() for i := 0; i < size; i++ { elemCount, elemSum, err := mean(depth+1, rv.Index(i).Interface()) if err != nil { return 0, 0, err } total += elemSum count += elemCount } case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: total += float64(rv.Int()) count++ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: total += float64(rv.Uint()) count++ case reflect.Float32, reflect.Float64: total += rv.Float() count++ default: return 0, 0, fmt.Errorf("invalid argument for mean (type %T)", arg) } } return count, total, nil } func median(depth int, args ...any) ([]float64, error) { if depth > MaxDepth { return nil, ErrorMaxDepth } var values []float64 for _, arg := range args { // Fast paths for common typed slices - avoid reflection and allocations switch arr := arg.(type) { case []int: for _, v := range arr { values = append(values, float64(v)) } continue case []float64: values = append(values, arr...) continue case []any: // Fast path for []any - single pass without recursive calls for flat arrays for _, elem := range arr { switch e := elem.(type) { case int: values = append(values, float64(e)) case float64: values = append(values, e) case []int, []float64, []any: // Nested array - recurse elems, err := median(depth+1, e) if err != nil { return nil, err } values = append(values, elems...) default: // Other numeric types or slices - use reflection rv := reflect.ValueOf(e) switch rv.Kind() { case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: values = append(values, float64(rv.Int())) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: values = append(values, float64(rv.Uint())) case reflect.Float32, reflect.Float64: values = append(values, rv.Float()) case reflect.Slice, reflect.Array: elems, err := median(depth+1, e) if err != nil { return nil, err } values = append(values, elems...) default: return nil, fmt.Errorf("invalid argument for median (type %T)", e) } } } continue } // Slow path: use reflection for other types rv := reflect.ValueOf(arg) switch rv.Kind() { case reflect.Array, reflect.Slice: size := rv.Len() for i := 0; i < size; i++ { elems, err := median(depth+1, rv.Index(i).Interface()) if err != nil { return nil, err } values = append(values, elems...) } case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: values = append(values, float64(rv.Int())) case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: values = append(values, float64(rv.Uint())) case reflect.Float32, reflect.Float64: values = append(values, rv.Float()) default: return nil, fmt.Errorf("invalid argument for median (type %T)", arg) } } return values, nil } func flatten(arg reflect.Value, depth int) ([]any, error) { if depth > MaxDepth { return nil, ErrorMaxDepth } ret := []any{} for i := 0; i < arg.Len(); i++ { v := deref.Value(arg.Index(i)) if v.Kind() == reflect.Array || v.Kind() == reflect.Slice { x, err := flatten(v, depth+1) if err != nil { return nil, err } ret = append(ret, x...) } else { ret = append(ret, v.Interface()) } } return ret, nil } func get(params ...any) (out any, err error) { if len(params) < 2 { return nil, fmt.Errorf("invalid number of arguments (expected 2, got %d)", len(params)) } from := params[0] i := params[1] v := reflect.ValueOf(from) if from == nil { return nil, nil } if v.Kind() == reflect.Invalid { panic(fmt.Sprintf("cannot fetch %v from %T", i, from)) } // Methods can be defined on any type. if v.NumMethod() > 0 { if methodName, ok := i.(string); ok { method := v.MethodByName(methodName) if method.IsValid() { return method.Interface(), nil } } } switch v.Kind() { case reflect.Array, reflect.Slice, reflect.String: index := runtime.ToInt(i) l := v.Len() if index < 0 { index = l + index } if 0 <= index && index < l { value := v.Index(index) if value.IsValid() { return value.Interface(), nil } } case reflect.Map: var value reflect.Value if i == nil { value = v.MapIndex(reflect.Zero(v.Type().Key())) } else { value = v.MapIndex(reflect.ValueOf(i)) } if value.IsValid() { return value.Interface(), nil } case reflect.Struct: fieldName := i.(string) t := v.Type() field, ok := t.FieldByNameFunc(func(name string) bool { f, _ := t.FieldByName(name) switch f.Tag.Get("expr") { case "-": return false case fieldName: return true default: return name == fieldName } }) if ok && field.IsExported() { value := v.FieldByIndex(field.Index) if value.IsValid() { return value.Interface(), nil } } } // Main difference from runtime.Fetch // is that we return `nil` instead of panic. return nil, nil } ================================================ FILE: builtin/utils.go ================================================ package builtin import ( "fmt" "reflect" "time" "github.com/expr-lang/expr/internal/deref" ) var ( anyType = reflect.TypeOf(new(any)).Elem() integerType = reflect.TypeOf(0) floatType = reflect.TypeOf(float64(0)) arrayType = reflect.TypeOf([]any{}) mapType = reflect.TypeOf(map[any]any{}) timeType = reflect.TypeOf(new(time.Time)).Elem() locationType = reflect.TypeOf(new(time.Location)) ) func kind(t reflect.Type) reflect.Kind { if t == nil { return reflect.Invalid } t = deref.Type(t) return t.Kind() } func types(types ...any) []reflect.Type { ts := make([]reflect.Type, len(types)) for i, t := range types { t := reflect.TypeOf(t) if t.Kind() == reflect.Ptr { t = t.Elem() } if t.Kind() != reflect.Func { panic("not a function") } ts[i] = t } return ts } func toInt(val any) (int, error) { switch v := val.(type) { case int: return v, nil case int8: return int(v), nil case int16: return int(v), nil case int32: return int(v), nil case int64: return int(v), nil case uint: return int(v), nil case uint8: return int(v), nil case uint16: return int(v), nil case uint32: return int(v), nil case uint64: return int(v), nil default: return 0, fmt.Errorf("cannot use %T as argument (type int)", val) } } func bitFunc(name string, fn func(x, y int) (any, error)) *Function { return &Function{ Name: name, Func: func(args ...any) (any, error) { if len(args) != 2 { return nil, fmt.Errorf("invalid number of arguments for %s (expected 2, got %d)", name, len(args)) } x, err := toInt(args[0]) if err != nil { return nil, fmt.Errorf("%v to call %s", err, name) } y, err := toInt(args[1]) if err != nil { return nil, fmt.Errorf("%v to call %s", err, name) } return fn(x, y) }, Types: types(new(func(int, int) int)), } } ================================================ FILE: builtin/validation.go ================================================ package builtin import ( "fmt" "reflect" "github.com/expr-lang/expr/internal/deref" ) func validateAggregateFunc(name string, args []reflect.Type) (reflect.Type, error) { switch len(args) { case 0: return anyType, fmt.Errorf("not enough arguments to call %s", name) default: for _, arg := range args { switch kind(deref.Type(arg)) { case reflect.Interface, reflect.Array, reflect.Slice: return anyType, nil case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64: default: return anyType, fmt.Errorf("invalid argument for %s (type %s)", name, arg) } } return args[0], nil } } func validateRoundFunc(name string, args []reflect.Type) (reflect.Type, error) { if len(args) != 1 { return anyType, fmt.Errorf("invalid number of arguments (expected 1, got %d)", len(args)) } switch kind(args[0]) { case reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Interface: return floatType, nil default: return anyType, fmt.Errorf("invalid argument for %s (type %s)", name, args[0]) } } ================================================ FILE: checker/checker.go ================================================ package checker import ( "fmt" "reflect" "regexp" "time" "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/builtin" . "github.com/expr-lang/expr/checker/nature" "github.com/expr-lang/expr/conf" "github.com/expr-lang/expr/file" "github.com/expr-lang/expr/parser" ) var ( anyType = reflect.TypeOf(new(any)).Elem() boolType = reflect.TypeOf(true) intType = reflect.TypeOf(0) floatType = reflect.TypeOf(float64(0)) stringType = reflect.TypeOf("") arrayType = reflect.TypeOf([]any{}) mapType = reflect.TypeOf(map[string]any{}) timeType = reflect.TypeOf(time.Time{}) durationType = reflect.TypeOf(time.Duration(0)) byteSliceType = reflect.TypeOf([]byte(nil)) anyTypeSlice = []reflect.Type{anyType} ) // ParseCheck parses input expression and checks its types. Also, it applies // all provided patchers. In case of error, it returns error with a tree. func ParseCheck(input string, config *conf.Config) (*parser.Tree, error) { tree, err := parser.ParseWithConfig(input, config) if err != nil { return tree, err } _, err = new(Checker).PatchAndCheck(tree, config) if err != nil { return tree, err } return tree, nil } // Check calls Check on a disposable Checker. func Check(tree *parser.Tree, config *conf.Config) (reflect.Type, error) { return new(Checker).Check(tree, config) } type Checker struct { config *conf.Config predicateScopes []predicateScope varScopes []varScope err *file.Error needsReset bool } type predicateScope struct { collection Nature vars []varScope } type varScope struct { name string nature Nature } // PatchAndCheck applies all patchers and checks the tree. func (v *Checker) PatchAndCheck(tree *parser.Tree, config *conf.Config) (reflect.Type, error) { v.reset(config) if len(config.Visitors) > 0 { // Run all patchers that dont support being run repeatedly first v.runVisitors(tree, false) // Run patchers that require multiple passes next (currently only Operator patching) v.runVisitors(tree, true) } return v.Check(tree, config) } // Check checks types of the expression tree. It returns type of the expression // and error if any. If config is nil, then default configuration will be used. func (v *Checker) Check(tree *parser.Tree, config *conf.Config) (reflect.Type, error) { v.reset(config) return v.check(tree) } // Run visitors in a given config over the given tree // runRepeatable controls whether to filter for only vistors that require multiple passes or not func (v *Checker) runVisitors(tree *parser.Tree, runRepeatable bool) { for { more := false for _, visitor := range v.config.Visitors { // We need to perform types check, because some visitors may rely on // types information available in the tree. _, _ = v.Check(tree, v.config) r, repeatable := visitor.(interface { Reset() ShouldRepeat() bool }) if repeatable { if runRepeatable { r.Reset() ast.Walk(&tree.Node, visitor) more = more || r.ShouldRepeat() } } else { if !runRepeatable { ast.Walk(&tree.Node, visitor) } } } if !more { break } } } func (v *Checker) check(tree *parser.Tree) (reflect.Type, error) { nt := v.visit(tree.Node) // To keep compatibility with previous versions, we should return any, if nature is unknown. t := nt.Type if t == nil { t = anyType } if v.err != nil { return t, v.err.Bind(tree.Source) } if v.config.Expect != reflect.Invalid { if v.config.ExpectAny { if nt.IsUnknown(&v.config.NtCache) { return t, nil } } switch v.config.Expect { case reflect.Int, reflect.Int64, reflect.Float64: if !nt.IsNumber() { return nil, fmt.Errorf("expected %v, but got %s", v.config.Expect, nt.String()) } default: if nt.Kind != v.config.Expect { return nil, fmt.Errorf("expected %v, but got %s", v.config.Expect, nt.String()) } } } return t, nil } func (v *Checker) reset(config *conf.Config) { if v.needsReset { clearSlice(v.predicateScopes) clearSlice(v.varScopes) v.predicateScopes = v.predicateScopes[:0] v.varScopes = v.varScopes[:0] v.err = nil } v.needsReset = true if config == nil { config = conf.New(nil) } v.config = config } func clearSlice[S ~[]E, E any](s S) { var zero E for i := range s { s[i] = zero } } func (v *Checker) visit(node ast.Node) Nature { var nt Nature switch n := node.(type) { case *ast.NilNode: nt = v.config.NtCache.NatureOf(nil) case *ast.IdentifierNode: nt = v.identifierNode(n) case *ast.IntegerNode: nt = v.config.NtCache.FromType(intType) case *ast.FloatNode: nt = v.config.NtCache.FromType(floatType) case *ast.BoolNode: nt = v.config.NtCache.FromType(boolType) case *ast.StringNode: nt = v.config.NtCache.FromType(stringType) case *ast.BytesNode: nt = v.config.NtCache.FromType(byteSliceType) case *ast.ConstantNode: nt = v.config.NtCache.FromType(reflect.TypeOf(n.Value)) case *ast.UnaryNode: nt = v.unaryNode(n) case *ast.BinaryNode: nt = v.binaryNode(n) case *ast.ChainNode: nt = v.chainNode(n) case *ast.MemberNode: nt = v.memberNode(n) case *ast.SliceNode: nt = v.sliceNode(n) case *ast.CallNode: nt = v.callNode(n) case *ast.BuiltinNode: nt = v.builtinNode(n) case *ast.PredicateNode: nt = v.predicateNode(n) case *ast.PointerNode: nt = v.pointerNode(n) case *ast.VariableDeclaratorNode: nt = v.variableDeclaratorNode(n) case *ast.SequenceNode: nt = v.sequenceNode(n) case *ast.ConditionalNode: nt = v.conditionalNode(n) case *ast.ArrayNode: nt = v.arrayNode(n) case *ast.MapNode: nt = v.mapNode(n) case *ast.PairNode: nt = v.pairNode(n) default: panic(fmt.Sprintf("undefined node type (%T)", node)) } node.SetNature(nt) return nt } func (v *Checker) error(node ast.Node, format string, args ...any) Nature { if v.err == nil { // show first error v.err = &file.Error{ Location: node.Location(), Message: fmt.Sprintf(format, args...), } } return Nature{} } func (v *Checker) identifierNode(node *ast.IdentifierNode) Nature { for i := len(v.varScopes) - 1; i >= 0; i-- { if v.varScopes[i].name == node.Value { return v.varScopes[i].nature } } if node.Value == "$env" { return Nature{} } return v.ident(node, node.Value, v.config.Strict, true) } // ident method returns type of environment variable, builtin or function. func (v *Checker) ident(node ast.Node, name string, strict, builtins bool) Nature { if nt, ok := v.config.Env.Get(&v.config.NtCache, name); ok { return nt } if builtins { if fn, ok := v.config.Functions[name]; ok { nt := v.config.NtCache.FromType(fn.Type()) if nt.TypeData == nil { nt.TypeData = new(TypeData) } nt.TypeData.Func = fn return nt } if fn, ok := v.config.Builtins[name]; ok { nt := v.config.NtCache.FromType(fn.Type()) if nt.TypeData == nil { nt.TypeData = new(TypeData) } nt.TypeData.Func = fn return nt } } if v.config.Strict && strict { return v.error(node, "unknown name %s", name) } return Nature{} } func (v *Checker) unaryNode(node *ast.UnaryNode) Nature { nt := v.visit(node.Node) nt = nt.Deref(&v.config.NtCache) switch node.Operator { case "!", "not": if nt.IsBool() { return v.config.NtCache.FromType(boolType) } if nt.IsUnknown(&v.config.NtCache) { return v.config.NtCache.FromType(boolType) } case "+", "-": if nt.IsNumber() { return nt } if nt.IsUnknown(&v.config.NtCache) { return Nature{} } default: return v.error(node, "unknown operator (%s)", node.Operator) } return v.error(node, `invalid operation: %s (mismatched type %s)`, node.Operator, nt.String()) } func (v *Checker) binaryNode(node *ast.BinaryNode) Nature { l := v.visit(node.Left) r := v.visit(node.Right) l = l.Deref(&v.config.NtCache) r = r.Deref(&v.config.NtCache) switch node.Operator { case "==", "!=": if l.ComparableTo(&v.config.NtCache, r) { return v.config.NtCache.FromType(boolType) } case "or", "||", "and", "&&": if l.IsBool() && r.IsBool() { return v.config.NtCache.FromType(boolType) } if l.MaybeCompatible(&v.config.NtCache, r, BoolCheck) { return v.config.NtCache.FromType(boolType) } case "<", ">", ">=", "<=": if l.IsNumber() && r.IsNumber() { return v.config.NtCache.FromType(boolType) } if l.IsString() && r.IsString() { return v.config.NtCache.FromType(boolType) } if l.IsTime() && r.IsTime() { return v.config.NtCache.FromType(boolType) } if l.IsDuration() && r.IsDuration() { return v.config.NtCache.FromType(boolType) } if l.MaybeCompatible(&v.config.NtCache, r, NumberCheck, StringCheck, TimeCheck, DurationCheck) { return v.config.NtCache.FromType(boolType) } case "-": if l.IsNumber() && r.IsNumber() { return l.PromoteNumericNature(&v.config.NtCache, r) } if l.IsTime() && r.IsTime() { return v.config.NtCache.FromType(durationType) } if l.IsTime() && r.IsDuration() { return v.config.NtCache.FromType(timeType) } if l.IsDuration() && r.IsDuration() { return v.config.NtCache.FromType(durationType) } if l.MaybeCompatible(&v.config.NtCache, r, NumberCheck, TimeCheck, DurationCheck) { return Nature{} } case "*": if l.IsNumber() && r.IsNumber() { return l.PromoteNumericNature(&v.config.NtCache, r) } if l.IsNumber() && r.IsDuration() { return v.config.NtCache.FromType(durationType) } if l.IsDuration() && r.IsNumber() { return v.config.NtCache.FromType(durationType) } if l.IsDuration() && r.IsDuration() { return v.config.NtCache.FromType(durationType) } if l.MaybeCompatible(&v.config.NtCache, r, NumberCheck, DurationCheck) { return Nature{} } case "/": if l.IsNumber() && r.IsNumber() { return v.config.NtCache.FromType(floatType) } if l.MaybeCompatible(&v.config.NtCache, r, NumberCheck) { return v.config.NtCache.FromType(floatType) } case "**", "^": if l.IsNumber() && r.IsNumber() { return v.config.NtCache.FromType(floatType) } if l.MaybeCompatible(&v.config.NtCache, r, NumberCheck) { return v.config.NtCache.FromType(floatType) } case "%": if l.IsInteger && r.IsInteger { return v.config.NtCache.FromType(intType) } if l.MaybeCompatible(&v.config.NtCache, r, IntegerCheck) { return v.config.NtCache.FromType(intType) } case "+": if l.IsNumber() && r.IsNumber() { return l.PromoteNumericNature(&v.config.NtCache, r) } if l.IsString() && r.IsString() { return v.config.NtCache.FromType(stringType) } if l.IsTime() && r.IsDuration() { return v.config.NtCache.FromType(timeType) } if l.IsDuration() && r.IsTime() { return v.config.NtCache.FromType(timeType) } if l.IsDuration() && r.IsDuration() { return v.config.NtCache.FromType(durationType) } if l.MaybeCompatible(&v.config.NtCache, r, NumberCheck, StringCheck, TimeCheck, DurationCheck) { return Nature{} } case "in": if (l.IsString() || l.IsUnknown(&v.config.NtCache)) && r.IsStruct() { return v.config.NtCache.FromType(boolType) } if r.IsMap() { rKey := r.Key(&v.config.NtCache) if !l.IsUnknown(&v.config.NtCache) && !l.AssignableTo(rKey) { return v.error(node, "cannot use %s as type %s in map key", l.String(), rKey.String()) } return v.config.NtCache.FromType(boolType) } if r.IsArray() { rElem := r.Elem(&v.config.NtCache) if !l.ComparableTo(&v.config.NtCache, rElem) { return v.error(node, "cannot use %s as type %s in array", l.String(), rElem.String()) } return v.config.NtCache.FromType(boolType) } if l.IsUnknown(&v.config.NtCache) && r.IsAnyOf(StringCheck, ArrayCheck, MapCheck) { return v.config.NtCache.FromType(boolType) } if r.IsUnknown(&v.config.NtCache) { return v.config.NtCache.FromType(boolType) } case "matches": if s, ok := node.Right.(*ast.StringNode); ok { _, err := regexp.Compile(s.Value) if err != nil { return v.error(node, err.Error()) } } if (l.IsString() || l.IsByteSlice()) && r.IsString() { return v.config.NtCache.FromType(boolType) } if l.MaybeCompatible(&v.config.NtCache, r, StringCheck) { return v.config.NtCache.FromType(boolType) } case "contains", "startsWith", "endsWith": if l.IsString() && r.IsString() { return v.config.NtCache.FromType(boolType) } if l.MaybeCompatible(&v.config.NtCache, r, StringCheck) { return v.config.NtCache.FromType(boolType) } case "..": if l.IsInteger && r.IsInteger || l.MaybeCompatible(&v.config.NtCache, r, IntegerCheck) { return ArrayFromType(&v.config.NtCache, intType) } case "??": if l.Nil && !r.Nil { return r } if !l.Nil && r.Nil { return l } if l.Nil && r.Nil { return v.config.NtCache.NatureOf(nil) } if r.AssignableTo(l) { return l } return Nature{} default: return v.error(node, "unknown operator (%s)", node.Operator) } return v.error(node, `invalid operation: %s (mismatched types %s and %s)`, node.Operator, l.String(), r.String()) } func (v *Checker) chainNode(node *ast.ChainNode) Nature { return v.visit(node.Node) } func (v *Checker) memberNode(node *ast.MemberNode) Nature { // $env variable if an, ok := node.Node.(*ast.IdentifierNode); ok && an.Value == "$env" { if name, ok := node.Property.(*ast.StringNode); ok { strict := v.config.Strict if node.Optional { // If user explicitly set optional flag, then we should not // throw error if field is not found (as user trying to handle // this case). But if user did not set optional flag, then we // should throw error if field is not found & v.config.Strict. strict = false } return v.ident(node, name.Value, strict, false /* no builtins and no functions */) } return Nature{} } base := v.visit(node.Node) prop := v.visit(node.Property) if base.IsUnknown(&v.config.NtCache) { return Nature{} } if name, ok := node.Property.(*ast.StringNode); ok { if base.Nil { return v.error(node, "type nil has no field %s", name.Value) } // First, check methods defined on base type itself, // independent of which type it is. Without dereferencing. if m, ok := base.MethodByName(&v.config.NtCache, name.Value); ok { return m } } base = base.Deref(&v.config.NtCache) switch base.Kind { case reflect.Map: // If the map key is a pointer, we should not dereference the property. if !prop.AssignableTo(base.Key(&v.config.NtCache)) { propDeref := prop.Deref(&v.config.NtCache) if propDeref.AssignableTo(base.Key(&v.config.NtCache)) { prop = propDeref } } if !prop.AssignableTo(base.Key(&v.config.NtCache)) && !prop.IsUnknown(&v.config.NtCache) { return v.error(node.Property, "cannot use %s to get an element from %s", prop.String(), base.String()) } if prop, ok := node.Property.(*ast.StringNode); ok && base.TypeData != nil { if field, ok := base.Fields[prop.Value]; ok { return field } else if base.Strict { return v.error(node.Property, "unknown field %s", prop.Value) } } return base.Elem(&v.config.NtCache) case reflect.Array, reflect.Slice: prop = prop.Deref(&v.config.NtCache) if !prop.IsInteger && !prop.IsUnknown(&v.config.NtCache) { return v.error(node.Property, "array elements can only be selected using an integer (got %s)", prop.String()) } return base.Elem(&v.config.NtCache) case reflect.Struct: if name, ok := node.Property.(*ast.StringNode); ok { propertyName := name.Value if field, ok := base.FieldByName(&v.config.NtCache, propertyName); ok { return v.config.NtCache.FromType(field.Type) } if node.Method { return v.error(node, "type %v has no method %v", base.String(), propertyName) } return v.error(node, "type %v has no field %v", base.String(), propertyName) } } // Not found. if name, ok := node.Property.(*ast.StringNode); ok { if node.Method { return v.error(node, "type %v has no method %v", base.String(), name.Value) } return v.error(node, "type %v has no field %v", base.String(), name.Value) } return v.error(node, "type %v[%v] is undefined", base.String(), prop.String()) } func (v *Checker) sliceNode(node *ast.SliceNode) Nature { nt := v.visit(node.Node) if nt.IsUnknown(&v.config.NtCache) { return Nature{} } switch nt.Kind { case reflect.String, reflect.Array, reflect.Slice: // ok default: return v.error(node, "cannot slice %s", nt.String()) } if node.From != nil { from := v.visit(node.From) from = from.Deref(&v.config.NtCache) if !from.IsInteger && !from.IsUnknown(&v.config.NtCache) { return v.error(node.From, "non-integer slice index %v", from.String()) } } if node.To != nil { to := v.visit(node.To) to = to.Deref(&v.config.NtCache) if !to.IsInteger && !to.IsUnknown(&v.config.NtCache) { return v.error(node.To, "non-integer slice index %v", to.String()) } } return nt } func (v *Checker) callNode(node *ast.CallNode) Nature { // Check if type was set on node (for example, by patcher) // and use node type instead of function return type. // // If node type is anyType, then we should use function // return type. For example, on error we return anyType // for a call `errCall().Method()` and method will be // evaluated on `anyType.Method()`, so return type will // be anyType `anyType.Method(): anyType`. Patcher can // fix `errCall()` to return proper type, so on second // checker pass we should replace anyType on method node // with new correct function return type. if typ := node.Type(); typ != nil && typ != anyType { return *node.Nature() } // $env is not callable. if id, ok := node.Callee.(*ast.IdentifierNode); ok && id.Value == "$env" { return v.error(node, "%s is not callable", v.config.Env.String()) } nt := v.visit(node.Callee) if nt.IsUnknown(&v.config.NtCache) { return Nature{} } if nt.TypeData != nil && nt.TypeData.Func != nil { return v.checkFunction(nt.TypeData.Func, node, node.Arguments) } fnName := "function" if identifier, ok := node.Callee.(*ast.IdentifierNode); ok { fnName = identifier.Value } if member, ok := node.Callee.(*ast.MemberNode); ok { if name, ok := member.Property.(*ast.StringNode); ok { fnName = name.Value } } if nt.Nil { return v.error(node, "%v is nil; cannot call nil as function", fnName) } if nt.Kind == reflect.Func { outType, err := v.checkArguments(fnName, nt, node.Arguments, node) if err != nil { if v.err == nil { v.err = err } return Nature{} } return outType } return v.error(node, "%s is not callable", nt.String()) } func (v *Checker) builtinNode(node *ast.BuiltinNode) Nature { switch node.Name { case "all", "none", "any", "one": collection := v.visit(node.Arguments[0]) collection = collection.Deref(&v.config.NtCache) if !collection.IsArray() && !collection.IsUnknown(&v.config.NtCache) { return v.error(node.Arguments[0], "builtin %v takes only array (got %v)", node.Name, collection.String()) } v.begin(collection) predicate := v.visit(node.Arguments[1]) v.end() if predicate.IsFunc() && predicate.NumOut() == 1 && predicate.NumIn() == 1 && predicate.IsFirstArgUnknown(&v.config.NtCache) { predicateOut := predicate.Out(&v.config.NtCache, 0) if !predicateOut.IsBool() && !predicateOut.IsUnknown(&v.config.NtCache) { return v.error(node.Arguments[1], "predicate should return boolean (got %s)", predicateOut.String()) } return v.config.NtCache.FromType(boolType) } return v.error(node.Arguments[1], "predicate should has one input and one output param") case "filter": collection := v.visit(node.Arguments[0]) collection = collection.Deref(&v.config.NtCache) if !collection.IsArray() && !collection.IsUnknown(&v.config.NtCache) { return v.error(node.Arguments[0], "builtin %v takes only array (got %v)", node.Name, collection.String()) } v.begin(collection) predicate := v.visit(node.Arguments[1]) v.end() if predicate.IsFunc() && predicate.NumOut() == 1 && predicate.NumIn() == 1 && predicate.IsFirstArgUnknown(&v.config.NtCache) { predicateOut := predicate.Out(&v.config.NtCache, 0) if !predicateOut.IsBool() && !predicateOut.IsUnknown(&v.config.NtCache) { return v.error(node.Arguments[1], "predicate should return boolean (got %s)", predicateOut.String()) } if collection.IsUnknown(&v.config.NtCache) { return v.config.NtCache.FromType(arrayType) } collection = collection.Elem(&v.config.NtCache) return collection.MakeArrayOf(&v.config.NtCache) } return v.error(node.Arguments[1], "predicate should has one input and one output param") case "map": collection := v.visit(node.Arguments[0]) collection = collection.Deref(&v.config.NtCache) if !collection.IsArray() && !collection.IsUnknown(&v.config.NtCache) { return v.error(node.Arguments[0], "builtin %v takes only array (got %v)", node.Name, collection.String()) } v.begin(collection, varScope{"index", v.config.NtCache.FromType(intType)}) predicate := v.visit(node.Arguments[1]) v.end() if predicate.IsFunc() && predicate.NumOut() == 1 && predicate.NumIn() == 1 && predicate.IsFirstArgUnknown(&v.config.NtCache) { return predicate.Ref.MakeArrayOf(&v.config.NtCache) } return v.error(node.Arguments[1], "predicate should has one input and one output param") case "count": collection := v.visit(node.Arguments[0]) collection = collection.Deref(&v.config.NtCache) if !collection.IsArray() && !collection.IsUnknown(&v.config.NtCache) { return v.error(node.Arguments[0], "builtin %v takes only array (got %v)", node.Name, collection.String()) } if len(node.Arguments) == 1 { return v.config.NtCache.FromType(intType) } v.begin(collection) predicate := v.visit(node.Arguments[1]) v.end() if predicate.IsFunc() && predicate.NumOut() == 1 && predicate.NumIn() == 1 && predicate.IsFirstArgUnknown(&v.config.NtCache) { predicateOut := predicate.Out(&v.config.NtCache, 0) if !predicateOut.IsBool() && !predicateOut.IsUnknown(&v.config.NtCache) { return v.error(node.Arguments[1], "predicate should return boolean (got %s)", predicateOut.String()) } return v.config.NtCache.FromType(intType) } return v.error(node.Arguments[1], "predicate should has one input and one output param") case "sum": collection := v.visit(node.Arguments[0]) collection = collection.Deref(&v.config.NtCache) if !collection.IsArray() && !collection.IsUnknown(&v.config.NtCache) { return v.error(node.Arguments[0], "builtin %v takes only array (got %v)", node.Name, collection.String()) } if len(node.Arguments) == 2 { v.begin(collection) predicate := v.visit(node.Arguments[1]) v.end() if predicate.IsFunc() && predicate.NumOut() == 1 && predicate.NumIn() == 1 && predicate.IsFirstArgUnknown(&v.config.NtCache) { return predicate.Out(&v.config.NtCache, 0) } } else { if collection.IsUnknown(&v.config.NtCache) { return Nature{} } return collection.Elem(&v.config.NtCache) } case "find", "findLast": collection := v.visit(node.Arguments[0]) collection = collection.Deref(&v.config.NtCache) if !collection.IsArray() && !collection.IsUnknown(&v.config.NtCache) { return v.error(node.Arguments[0], "builtin %v takes only array (got %v)", node.Name, collection.String()) } v.begin(collection) predicate := v.visit(node.Arguments[1]) v.end() if predicate.IsFunc() && predicate.NumOut() == 1 && predicate.NumIn() == 1 && predicate.IsFirstArgUnknown(&v.config.NtCache) { predicateOut := predicate.Out(&v.config.NtCache, 0) if !predicateOut.IsBool() && !predicateOut.IsUnknown(&v.config.NtCache) { return v.error(node.Arguments[1], "predicate should return boolean (got %s)", predicateOut.String()) } if collection.IsUnknown(&v.config.NtCache) { return Nature{} } return collection.Elem(&v.config.NtCache) } return v.error(node.Arguments[1], "predicate should has one input and one output param") case "findIndex", "findLastIndex": collection := v.visit(node.Arguments[0]) collection = collection.Deref(&v.config.NtCache) if !collection.IsArray() && !collection.IsUnknown(&v.config.NtCache) { return v.error(node.Arguments[0], "builtin %v takes only array (got %v)", node.Name, collection.String()) } v.begin(collection) predicate := v.visit(node.Arguments[1]) v.end() if predicate.IsFunc() && predicate.NumOut() == 1 && predicate.NumIn() == 1 && predicate.IsFirstArgUnknown(&v.config.NtCache) { predicateOut := predicate.Out(&v.config.NtCache, 0) if !predicateOut.IsBool() && !predicateOut.IsUnknown(&v.config.NtCache) { return v.error(node.Arguments[1], "predicate should return boolean (got %s)", predicateOut.String()) } return v.config.NtCache.FromType(intType) } return v.error(node.Arguments[1], "predicate should has one input and one output param") case "groupBy": collection := v.visit(node.Arguments[0]) collection = collection.Deref(&v.config.NtCache) if !collection.IsArray() && !collection.IsUnknown(&v.config.NtCache) { return v.error(node.Arguments[0], "builtin %v takes only array (got %v)", node.Name, collection.String()) } v.begin(collection) predicate := v.visit(node.Arguments[1]) v.end() if predicate.IsFunc() && predicate.NumOut() == 1 && predicate.NumIn() == 1 && predicate.IsFirstArgUnknown(&v.config.NtCache) { collection = collection.Elem(&v.config.NtCache) collection = collection.MakeArrayOf(&v.config.NtCache) nt := v.config.NtCache.NatureOf(map[any][]any{}) nt.Ref = &collection return nt } return v.error(node.Arguments[1], "predicate should has one input and one output param") case "sortBy": collection := v.visit(node.Arguments[0]) collection = collection.Deref(&v.config.NtCache) if !collection.IsArray() && !collection.IsUnknown(&v.config.NtCache) { return v.error(node.Arguments[0], "builtin %v takes only array (got %v)", node.Name, collection.String()) } v.begin(collection) predicate := v.visit(node.Arguments[1]) v.end() if len(node.Arguments) == 3 { order := v.visit(node.Arguments[2]) if !order.IsString() && !order.IsUnknown(&v.config.NtCache) { return v.error(node.Arguments[2], "sortBy order argument must be a string (got %v)", order.String()) } } if predicate.IsFunc() && predicate.NumOut() == 1 && predicate.NumIn() == 1 && predicate.IsFirstArgUnknown(&v.config.NtCache) { return collection } return v.error(node.Arguments[1], "predicate should has one input and one output param") case "reduce": collection := v.visit(node.Arguments[0]) collection = collection.Deref(&v.config.NtCache) if !collection.IsArray() && !collection.IsUnknown(&v.config.NtCache) { return v.error(node.Arguments[0], "builtin %v takes only array (got %v)", node.Name, collection.String()) } v.begin(collection, varScope{"index", v.config.NtCache.FromType(intType)}, varScope{"acc", Nature{}}) predicate := v.visit(node.Arguments[1]) v.end() if len(node.Arguments) == 3 { _ = v.visit(node.Arguments[2]) } if predicate.IsFunc() && predicate.NumOut() == 1 { return *predicate.Ref } return v.error(node.Arguments[1], "predicate should has two input and one output param") } if id, ok := builtin.Index[node.Name]; ok { switch node.Name { case "get": return v.checkBuiltinGet(node) } return v.checkFunction(builtin.Builtins[id], node, node.Arguments) } return v.error(node, "unknown builtin %v", node.Name) } func (v *Checker) begin(collectionNature Nature, vars ...varScope) { v.predicateScopes = append(v.predicateScopes, predicateScope{ collection: collectionNature, vars: vars, }) } func (v *Checker) end() { v.predicateScopes = v.predicateScopes[:len(v.predicateScopes)-1] } func (v *Checker) checkBuiltinGet(node *ast.BuiltinNode) Nature { if len(node.Arguments) != 2 { return v.error(node, "invalid number of arguments (expected 2, got %d)", len(node.Arguments)) } base := v.visit(node.Arguments[0]) prop := v.visit(node.Arguments[1]) prop = prop.Deref(&v.config.NtCache) if id, ok := node.Arguments[0].(*ast.IdentifierNode); ok && id.Value == "$env" { if s, ok := node.Arguments[1].(*ast.StringNode); ok { if nt, ok := v.config.Env.Get(&v.config.NtCache, s.Value); ok { return nt } } return Nature{} } if base.IsUnknown(&v.config.NtCache) { return Nature{} } switch base.Kind { case reflect.Slice, reflect.Array: if !prop.IsInteger && !prop.IsUnknown(&v.config.NtCache) { return v.error(node.Arguments[1], "non-integer slice index %s", prop.String()) } return base.Elem(&v.config.NtCache) case reflect.Map: if !prop.AssignableTo(base.Key(&v.config.NtCache)) && !prop.IsUnknown(&v.config.NtCache) { return v.error(node.Arguments[1], "cannot use %s to get an element from %s", prop.String(), base.String()) } return base.Elem(&v.config.NtCache) } return v.error(node.Arguments[0], "type %v does not support indexing", base.String()) } func (v *Checker) checkFunction(f *builtin.Function, node ast.Node, arguments []ast.Node) Nature { if f.Validate != nil { args := make([]reflect.Type, len(arguments)) for i, arg := range arguments { argNature := v.visit(arg) if argNature.IsUnknown(&v.config.NtCache) { args[i] = anyType } else { args[i] = argNature.Type } } t, err := f.Validate(args) if err != nil { return v.error(node, "%v", err) } return v.config.NtCache.FromType(t) } else if len(f.Types) == 0 { nt, err := v.checkArguments(f.Name, v.config.NtCache.FromType(f.Type()), arguments, node) if err != nil { if v.err == nil { v.err = err } return Nature{} } // No type was specified, so we assume the function returns any. return nt } var lastErr *file.Error for _, t := range f.Types { outNature, err := v.checkArguments(f.Name, v.config.NtCache.FromType(t), arguments, node) if err != nil { lastErr = err continue } // As we found the correct function overload, we can stop the loop. // Also, we need to set the correct nature of the callee so compiler, // can correctly handle OpDeref opcode. if callNode, ok := node.(*ast.CallNode); ok { callNode.Callee.SetType(t) } return outNature } if lastErr != nil { if v.err == nil { v.err = lastErr } return Nature{} } return v.error(node, "no matching overload for %v", f.Name) } func (v *Checker) checkArguments( name string, fn Nature, arguments []ast.Node, node ast.Node, ) (Nature, *file.Error) { if fn.IsUnknown(&v.config.NtCache) { return Nature{}, nil } numOut := fn.NumOut() if numOut == 0 { return Nature{}, &file.Error{ Location: node.Location(), Message: fmt.Sprintf("func %v doesn't return value", name), } } if numOut > 2 { return Nature{}, &file.Error{ Location: node.Location(), Message: fmt.Sprintf("func %v returns more then two values", name), } } // If func is method on an env, first argument should be a receiver, // and actual arguments less than fnNumIn by one. fnNumIn := fn.NumIn() if fn.Method { // TODO: Move subtraction to the Nature.NumIn() and Nature.In() methods. fnNumIn-- } // Skip first argument in case of the receiver. fnInOffset := 0 if fn.Method { fnInOffset = 1 } var err *file.Error isVariadic := fn.IsVariadic() if isVariadic { if len(arguments) < fnNumIn-1 { err = &file.Error{ Location: node.Location(), Message: fmt.Sprintf("not enough arguments to call %v", name), } } } else { if len(arguments) > fnNumIn { err = &file.Error{ Location: node.Location(), Message: fmt.Sprintf("too many arguments to call %v", name), } } if len(arguments) < fnNumIn { err = &file.Error{ Location: node.Location(), Message: fmt.Sprintf("not enough arguments to call %v", name), } } } if err != nil { // If we have an error, we should still visit all arguments to // type check them, as a patch can fix the error later. for _, arg := range arguments { _ = v.visit(arg) } return fn.Out(&v.config.NtCache, 0), err } for i, arg := range arguments { argNature := v.visit(arg) var in Nature if isVariadic && i >= fnNumIn-1 { // For variadic arguments fn(xs ...int), go replaces type of xs (int) with ([]int). // As we compare arguments one by one, we need underling type. in = fn.InElem(&v.config.NtCache, fnNumIn-1+fnInOffset) } else { in = fn.In(&v.config.NtCache, i+fnInOffset) } if in.IsFloat && argNature.IsInteger { traverseAndReplaceIntegerNodesWithFloatNodes(&arguments[i], in) continue } if in.IsInteger && argNature.IsInteger && argNature.Kind != in.Kind { traverseAndReplaceIntegerNodesWithIntegerNodes(&arguments[i], in) continue } if argNature.Nil { if in.Kind == reflect.Ptr || in.Kind == reflect.Interface { continue } return Nature{}, &file.Error{ Location: arg.Location(), Message: fmt.Sprintf("cannot use nil as argument (type %s) to call %v", in.String(), name), } } // Check if argument is assignable to the function input type. // We check original type (like *time.Time), not dereferenced type, // as function input type can be pointer to a struct. assignable := argNature.AssignableTo(in) // We also need to check if dereference arg type is assignable to the function input type. // For example, func(int) and argument *int. In this case we will add OpDeref to the argument, // so we can call the function with *int argument. if !assignable && argNature.IsPointer() { nt := argNature.Deref(&v.config.NtCache) assignable = nt.AssignableTo(in) } if !assignable && !argNature.IsUnknown(&v.config.NtCache) { return Nature{}, &file.Error{ Location: arg.Location(), Message: fmt.Sprintf("cannot use %s as argument (type %s) to call %v ", argNature.String(), in.String(), name), } } } return fn.Out(&v.config.NtCache, 0), nil } func traverseAndReplaceIntegerNodesWithFloatNodes(node *ast.Node, newNature Nature) { switch (*node).(type) { case *ast.IntegerNode: *node = &ast.FloatNode{Value: float64((*node).(*ast.IntegerNode).Value)} (*node).SetType(newNature.Type) case *ast.UnaryNode: unaryNode := (*node).(*ast.UnaryNode) traverseAndReplaceIntegerNodesWithFloatNodes(&unaryNode.Node, newNature) case *ast.BinaryNode: binaryNode := (*node).(*ast.BinaryNode) switch binaryNode.Operator { case "+", "-", "*": traverseAndReplaceIntegerNodesWithFloatNodes(&binaryNode.Left, newNature) traverseAndReplaceIntegerNodesWithFloatNodes(&binaryNode.Right, newNature) } } } func traverseAndReplaceIntegerNodesWithIntegerNodes(node *ast.Node, newNature Nature) { switch (*node).(type) { case *ast.IntegerNode: (*node).SetType(newNature.Type) case *ast.UnaryNode: (*node).SetType(newNature.Type) unaryNode := (*node).(*ast.UnaryNode) traverseAndReplaceIntegerNodesWithIntegerNodes(&unaryNode.Node, newNature) case *ast.BinaryNode: // TODO: Binary node return type is dependent on the type of the operands. We can't just change the type of the node. binaryNode := (*node).(*ast.BinaryNode) switch binaryNode.Operator { case "+", "-", "*": traverseAndReplaceIntegerNodesWithIntegerNodes(&binaryNode.Left, newNature) traverseAndReplaceIntegerNodesWithIntegerNodes(&binaryNode.Right, newNature) } } } func (v *Checker) predicateNode(node *ast.PredicateNode) Nature { nt := v.visit(node.Node) var out []reflect.Type if nt.IsUnknown(&v.config.NtCache) { out = append(out, anyType) } else if !nt.Nil { out = append(out, nt.Type) } n := v.config.NtCache.FromType(reflect.FuncOf(anyTypeSlice, out, false)) n.Ref = &nt return n } func (v *Checker) pointerNode(node *ast.PointerNode) Nature { if len(v.predicateScopes) == 0 { return v.error(node, "cannot use pointer accessor outside predicate") } scope := v.predicateScopes[len(v.predicateScopes)-1] if node.Name == "" { if scope.collection.IsUnknown(&v.config.NtCache) { return Nature{} } switch scope.collection.Kind { case reflect.Array, reflect.Slice: return scope.collection.Elem(&v.config.NtCache) } return v.error(node, "cannot use %v as array", scope) } if scope.vars != nil { for i := range scope.vars { if node.Name == scope.vars[i].name { return scope.vars[i].nature } } } return v.error(node, "unknown pointer #%v", node.Name) } func (v *Checker) variableDeclaratorNode(node *ast.VariableDeclaratorNode) Nature { if _, ok := v.config.Env.Get(&v.config.NtCache, node.Name); ok { return v.error(node, "cannot redeclare %v", node.Name) } if _, ok := v.config.Functions[node.Name]; ok { return v.error(node, "cannot redeclare function %v", node.Name) } if _, ok := v.config.Builtins[node.Name]; ok { return v.error(node, "cannot redeclare builtin %v", node.Name) } for i := len(v.varScopes) - 1; i >= 0; i-- { if v.varScopes[i].name == node.Name { return v.error(node, "cannot redeclare variable %v", node.Name) } } varNature := v.visit(node.Value) v.varScopes = append(v.varScopes, varScope{node.Name, varNature}) exprNature := v.visit(node.Expr) v.varScopes = v.varScopes[:len(v.varScopes)-1] return exprNature } func (v *Checker) sequenceNode(node *ast.SequenceNode) Nature { if len(node.Nodes) == 0 { return v.error(node, "empty sequence expression") } var last Nature for _, node := range node.Nodes { last = v.visit(node) } return last } func (v *Checker) conditionalNode(node *ast.ConditionalNode) Nature { c := v.visit(node.Cond) c = c.Deref(&v.config.NtCache) if !c.IsBool() && !c.IsUnknown(&v.config.NtCache) { return v.error(node.Cond, "non-bool expression (type %v) used as condition", c.String()) } t1 := v.visit(node.Exp1) t2 := v.visit(node.Exp2) if t1.Nil && !t2.Nil { return t2 } if !t1.Nil && t2.Nil { return t1 } if t1.Nil && t2.Nil { return v.config.NtCache.NatureOf(nil) } if t1.AssignableTo(t2) { if t1.IsArray() && t2.IsArray() { e1 := t1.Elem(&v.config.NtCache) e2 := t2.Elem(&v.config.NtCache) if !e1.AssignableTo(e2) || !e2.AssignableTo(e1) { return v.config.NtCache.FromType(arrayType) } } return t1 } return Nature{} } func (v *Checker) arrayNode(node *ast.ArrayNode) Nature { var prev Nature allElementsAreSameType := true for i, node := range node.Nodes { curr := v.visit(node) if i > 0 { if curr.Kind != prev.Kind { allElementsAreSameType = false } } prev = curr } if allElementsAreSameType { return prev.MakeArrayOf(&v.config.NtCache) } return v.config.NtCache.FromType(arrayType) } func (v *Checker) mapNode(node *ast.MapNode) Nature { for _, pair := range node.Pairs { v.visit(pair) } return v.config.NtCache.FromType(mapType) } func (v *Checker) pairNode(node *ast.PairNode) Nature { v.visit(node.Key) v.visit(node.Value) return v.config.NtCache.NatureOf(nil) } ================================================ FILE: checker/checker_bench_test.go ================================================ package checker_test import ( "runtime" "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/checker" "github.com/expr-lang/expr/checker/nature" "github.com/expr-lang/expr/conf" "github.com/expr-lang/expr/parser" ) func BenchmarkChecker(b *testing.B) { cases := []struct { name, input string }{ {"function calls", ` func( func( func(func(a, 'a', 1, nil), func(a, 'a', 1, nil), func(a, 'a', 1, nil)), func(func(a, 'a', 1, nil), func(a, 'a', 1, nil), func(a, 'a', 1, nil)), func(func(a, 'a', 1, nil), func(a, 'a', 1, nil), func(a, 'a', 1, nil)), ), func( func(func(a, 'a', 1, nil), func(a, 'a', 1, nil), func(a, 'a', 1, nil)), func(func(a, 'a', 1, nil), func(a, 'a', 1, nil), func(a, 'a', 1, nil)), func(func(a, 'a', 1, nil), func(a, 'a', 1, nil), func(a, 'a', 1, nil)), ), func( func(func(a, 'a', 1, nil), func(a, 'a', 1, nil), func(a, 'a', 1, nil)), func(func(a, 'a', 1, nil), func(a, 'a', 1, nil), func(a, 'a', 1, nil)), func(func(a, 'a', 1, nil), func(a, 'a', 1, nil), func(a, 'a', 1, nil)), ) ) `}, {"unary and binary operations", ` !b && !b || !b == !b && !b != !b || 1 < 1.0 && 0.1 > 1 || 0 <= 1.0 && 0.1 >= 1 && !b && !b || !b == !b && !b != !b || 1 < 1.0 && 0.1 > 1 || 0 <= 1.0 && 0.1 >= 1 && !b && !b || !b == !b && !b != !b || 1 < 1.0 && 0.1 > 1 || 0 <= 1.0 && 0.1 >= 1 && !b && !b || !b == !b && !b != !b || 1 < 1.0 && 0.1 > 1 || 0 <= 1.0 && 0.1 >= 1 && !b && !b || !b == !b && !b != !b || 1 < 1.0 && 0.1 > 1 || 0 <= 1.0 && 0.1 >= 1 && !b && !b || !b == !b && !b != !b || 1 < 1.0 && 0.1 > 1 || 0 <= 1.0 && 0.1 >= 1 `}, {"deep struct access", ` a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a. a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a. a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a. a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a `}, } f := func(params ...any) (any, error) { return nil, nil } env := map[string]any{ "a": new(recursive), "b": true, "func": f, } config := conf.New(env) expr.Function("func", f, f)(config) expr.ConstExpr("func")(config) for _, c := range cases { batchSize := 100_000 if batchSize > b.N { batchSize = b.N } trees := make([]*parser.Tree, 0, batchSize) for i := 0; i < batchSize; i++ { tree, err := parser.ParseWithConfig(c.input, config) if err != nil { b.Fatal(err) } trees = append(trees, tree) } runtime.GC() // try to cleanup the mess from the initialization b.Run("name="+c.name, func(b *testing.B) { var err error for i := 0; i < b.N; i++ { j := i if j < 0 || j >= len(trees) { b.StopTimer() invalidateTrees(trees...) j = 0 b.StartTimer() } _, err = checker.Check(trees[j], config) } b.StopTimer() if err != nil { b.Fatal(err) } }) } } type visitorFunc func(*ast.Node) func (f visitorFunc) Visit(node *ast.Node) { f(node) } func invalidateTrees(trees ...*parser.Tree) { for _, tree := range trees { ast.Walk(&tree.Node, visitorFunc(func(node *ast.Node) { (*node).SetNature(nature.Nature{}) })) } } type recursive struct { Inner *recursive `expr:"a"` } ================================================ FILE: checker/checker_test.go ================================================ package checker_test import ( "context" "fmt" "reflect" "regexp" "strings" "testing" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr/types" "github.com/expr-lang/expr" "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/checker" "github.com/expr-lang/expr/conf" "github.com/expr-lang/expr/parser" "github.com/expr-lang/expr/test/mock" ) func TestCheck(t *testing.T) { var tests = []struct { input string }{ {"nil == nil"}, {"nil == IntPtr"}, {"nil == nil"}, {"nil in ArrayOfFoo"}, {"!Bool"}, {"!BoolPtr == Bool"}, {"'a' == 'b' + 'c'"}, {"'foo' contains 'bar'"}, {"'foo' endsWith 'bar'"}, {"'foo' startsWith 'bar'"}, {"(1 == 1) || (String matches Any)"}, {"Int % Int > 1"}, {"Int + Int + Int > 0"}, {"Int == Any"}, {"Int in Int..Int"}, {"IntPtrPtr + 1 > 0"}, {"1 + 2 + Int64 > 0"}, {"Int64 % 1 > 0"}, {"IntPtr == Int"}, {"FloatPtr == 1 + 2."}, {"1 + 2 + Float + 3 + 4 < 0"}, {"1 + Int + Float == 0.5"}, {"-1 + +1 == 0"}, {"1 / 2 == 0"}, {"2**3 + 1 != 0"}, {"2^3 + 1 != 0"}, {"Float == 1"}, {"Float < 1.0"}, {"Float <= 1.0"}, {"Float > 1.0"}, {"Float >= 1.0"}, {`"a" < "b"`}, {"String + (true ? String : String) == ''"}, {"(Any ? nil : '') == ''"}, {"(Any ? 0 : nil) == 0"}, {"(Any ? nil : nil) == nil"}, {"!(Any ? Foo : Foo.Bar).Anything"}, {"Int in ArrayOfInt"}, {"Int not in ArrayOfAny"}, {"String in ArrayOfAny"}, {"String in ArrayOfString"}, {"String in Foo"}, {"String in MapOfFoo"}, {"String matches 'ok'"}, {"String matches Any"}, {"String not matches Any"}, {"StringPtr == nil"}, {"[1, 2, 3] == []"}, {"len([]) > 0"}, {"Any matches Any"}, {"!Any.Things.Contains.Any"}, {"!ArrayOfAny[0].next.goes['any thing']"}, {"ArrayOfFoo[0].Bar.Baz == ''"}, {"ArrayOfFoo[0:10][0].Bar.Baz == ''"}, {"!ArrayOfAny[Any]"}, {"Bool && Any"}, {"FuncParam(true, 1, 'str')"}, {"FuncParamAny(nil)"}, {"!Fast(Any, String)"}, {"Foo.Method().Baz == ''"}, {"Foo.Bar == MapOfAny.id.Bar"}, {"Foo.Bar.Baz == ''"}, {"MapOfFoo['any'].Bar.Baz == ''"}, {"Func() == 0"}, {"FuncFoo(Foo) > 1"}, {"Any() > 0"}, {"Embed.EmbedString == ''"}, {"EmbedString == ''"}, {"EmbedMethod(0) == ''"}, {"Embed.EmbedMethod(0) == ''"}, {"Embed.EmbedString == ''"}, {"EmbedString == ''"}, {"{id: Foo.Bar.Baz, 'str': String} == {}"}, {"Variadic(0, 1, 2) || Variadic(0)"}, {"count(1..30, {# % 3 == 0}) > 0"}, {"map(1..3, {#}) == [1,2,3]"}, {"map(1..3, #index) == [0,1,2]"}, {"map(filter(ArrayOfFoo, {.Bar.Baz != ''}), {.Bar}) == []"}, {"filter(Any, {.AnyMethod()})[0] == ''"}, {"Time == Time"}, {"Any == Time"}, {"Any != Time"}, {"Any > Time"}, {"Any >= Time"}, {"Any < Time"}, {"Any <= Time"}, {"Any - Time > Duration"}, {"Any == Any"}, {"Any != Any"}, {"Any > Any"}, {"Any >= Any"}, {"Any < Any"}, {"Any <= Any"}, {"Any - Any < Duration"}, {"Time == Any"}, {"Time != Any"}, {"Time > Any"}, {"Time >= Any"}, {"Time < Any"}, {"Time <= Any"}, {"Time - Any == Duration"}, {"Time + Duration == Time"}, {"Duration + Time == Time"}, {"Duration + Any == Time"}, {"Any + Duration == Time"}, {"Any.A?.B == nil"}, {"(Any.Bool ?? Bool) > 0"}, {"Bool ?? Bool"}, {"let foo = 1; foo == 1"}, {"(Embed).EmbedPointerEmbedInt > 0"}, {"(true ? [1] : [[1]])[0][0] == 1"}, {"Foo.VariadicMethod('a', 'b', 'c')"}, } c := new(checker.Checker) for _, tt := range tests { t.Run(tt.input, func(t *testing.T) { var err error tree, err := parser.Parse(tt.input) require.NoError(t, err) config := conf.New(mock.Env{}) expr.AsBool()(config) _, err = c.Check(tree, config) assert.NoError(t, err) }) } } func TestCheck_error(t *testing.T) { errorTests := []struct{ code, err string }{ { `Foo.Bar.Not`, ` type mock.Bar has no field Not (1:9) | Foo.Bar.Not | ........^ `, }, { `Noo`, ` unknown name Noo (1:1) | Noo | ^ `, }, { `Foo()`, ` mock.Foo is not callable (1:1) | Foo() | ^ `, }, { `Foo['bar']`, ` type mock.Foo has no field bar (1:4) | Foo['bar'] | ...^ `, }, { `Foo.Method(42)`, ` too many arguments to call Method (1:5) | Foo.Method(42) | ....^ `, }, {`Foo.Bar()`, ` mock.Bar is not callable (1:5) | Foo.Bar() | ....^ `, }, {`Foo.Bar.Not()`, ` type mock.Bar has no method Not (1:9) | Foo.Bar.Not() | ........^ `, }, {`ArrayOfFoo[0].Not`, ` type mock.Foo has no field Not (1:15) | ArrayOfFoo[0].Not | ..............^ `, }, {`ArrayOfFoo[Not]`, ` unknown name Not (1:12) | ArrayOfFoo[Not] | ...........^ `, }, {`Not[0]`, ` unknown name Not (1:1) | Not[0] | ^ `, }, {`Not.Bar`, ` unknown name Not (1:1) | Not.Bar | ^ `, }, {`ArrayOfFoo.Not`, ` array elements can only be selected using an integer (got string) (1:12) | ArrayOfFoo.Not | ...........^ `, }, {`FuncParam(true)`, ` not enough arguments to call FuncParam (1:1) | FuncParam(true) | ^ `, }, {`MapOfFoo['str'].Not`, ` type mock.Foo has no field Not (1:17) | MapOfFoo['str'].Not | ................^ `, }, {`Bool && IntPtr`, ` invalid operation: && (mismatched types bool and int) (1:6) | Bool && IntPtr | .....^ `, }, {`No ? Any.Bool : Any.Not`, ` unknown name No (1:1) | No ? Any.Bool : Any.Not | ^ `, }, {`Any.Cond ? No : Any.Not`, ` unknown name No (1:12) | Any.Cond ? No : Any.Not | ...........^ `, }, {`Any.Cond ? Any.Bool : No`, ` unknown name No (1:23) | Any.Cond ? Any.Bool : No | ......................^ `, }, {`MapOfAny ? Any : Any`, ` non-bool expression (type map[string]interface {}) used as condition (1:1) | MapOfAny ? Any : Any | ^ `, }, {`String matches Int`, ` invalid operation: matches (mismatched types string and int) (1:8) | String matches Int | .......^ `, }, {`Int matches String`, ` invalid operation: matches (mismatched types int and string) (1:5) | Int matches String | ....^ `, }, {`String contains Int`, ` invalid operation: contains (mismatched types string and int) (1:8) | String contains Int | .......^ `, }, {`Int contains String`, ` invalid operation: contains (mismatched types int and string) (1:5) | Int contains String | ....^ `, }, {`!Not`, ` unknown name Not (1:2) | !Not | .^ `, }, {`Not == Any`, ` unknown name Not (1:1) | Not == Any | ^ `, }, {`[Not]`, ` unknown name Not (1:2) | [Not] | .^ `, }, {`{id: Not}`, ` unknown name Not (1:6) | {id: Not} | .....^ `, }, {`(nil).Foo`, ` type nil has no field Foo (1:7) | (nil).Foo | ......^ `, }, {`(nil)['Foo']`, ` type nil has no field Foo (1:6) | (nil)['Foo'] | .....^ `, }, {`1 and false`, ` invalid operation: and (mismatched types int and bool) (1:3) | 1 and false | ..^ `, }, {`true or 0`, ` invalid operation: or (mismatched types bool and int) (1:6) | true or 0 | .....^ `, }, {`not IntPtr`, ` invalid operation: not (mismatched type int) (1:1) | not IntPtr | ^ `, }, {`len(Not)`, ` unknown name Not (1:5) | len(Not) | ....^ `, }, {`Int < Bool`, ` invalid operation: < (mismatched types int and bool) (1:5) | Int < Bool | ....^ `, }, {`Int > Bool`, ` invalid operation: > (mismatched types int and bool) (1:5) | Int > Bool | ....^ `, }, {`Int >= Bool`, ` invalid operation: >= (mismatched types int and bool) (1:5) | Int >= Bool | ....^ `, }, {`Int <= Bool`, ` invalid operation: <= (mismatched types int and bool) (1:5) | Int <= Bool | ....^ `, }, {`Int + Bool`, ` invalid operation: + (mismatched types int and bool) (1:5) | Int + Bool | ....^ `, }, {`Int - Bool`, ` invalid operation: - (mismatched types int and bool) (1:5) | Int - Bool | ....^ `, }, {`Int * Bool`, ` invalid operation: * (mismatched types int and bool) (1:5) | Int * Bool | ....^ `, }, {`Int / Bool`, ` invalid operation: / (mismatched types int and bool) (1:5) | Int / Bool | ....^ `, }, {`Int % Bool`, ` invalid operation: % (mismatched types int and bool) (1:5) | Int % Bool | ....^ `, }, {`Int ** Bool`, ` invalid operation: ** (mismatched types int and bool) (1:5) | Int ** Bool | ....^ `, }, {`Int .. Bool`, ` invalid operation: .. (mismatched types int and bool) (1:5) | Int .. Bool | ....^ `, }, {`Any > Foo`, ` invalid operation: > (mismatched types interface {} and mock.Foo) (1:5) | Any > Foo | ....^ `, }, {`NilFn() and BoolFn()`, ` func NilFn doesn't return value (1:1) | NilFn() and BoolFn() | ^ `, }, {`'str' in String`, ` invalid operation: in (mismatched types string and string) (1:7) | 'str' in String | ......^ `, }, {`1 in Foo`, ` invalid operation: in (mismatched types int and mock.Foo) (1:3) | 1 in Foo | ..^ `, }, {`1 + ''`, ` invalid operation: + (mismatched types int and string) (1:3) | 1 + '' | ..^ `, }, {`all(ArrayOfFoo, {#.Method() < 0})`, ` invalid operation: < (mismatched types mock.Bar and int) (1:29) | all(ArrayOfFoo, {#.Method() < 0}) | ............................^ `, }, {`Variadic()`, ` not enough arguments to call Variadic (1:1) | Variadic() | ^ `, }, {`Variadic(0, '')`, ` cannot use string as argument (type int) to call Variadic (1:13) | Variadic(0, '') | ............^ `, }, {`count(1, {#})`, ` builtin count takes only array (got int) (1:7) | count(1, {#}) | ......^ `, }, {`count(ArrayOfInt, {#})`, ` predicate should return boolean (got int) (1:19) | count(ArrayOfInt, {#}) | ..................^ `, }, {`all(ArrayOfInt, {# + 1})`, ` predicate should return boolean (got int) (1:17) | all(ArrayOfInt, {# + 1}) | ................^ `, }, {`filter(ArrayOfFoo, {.Bar.Baz})`, ` predicate should return boolean (got string) (1:20) | filter(ArrayOfFoo, {.Bar.Baz}) | ...................^ `, }, {`find(ArrayOfFoo, {.Bar.Baz})`, ` predicate should return boolean (got string) (1:18) | find(ArrayOfFoo, {.Bar.Baz}) | .................^ `, }, {`map(1, {2})`, ` builtin map takes only array (got int) (1:5) | map(1, {2}) | ....^ `, }, {`ArrayOfFoo[Foo]`, ` array elements can only be selected using an integer (got mock.Foo) (1:12) | ArrayOfFoo[Foo] | ...........^ `, }, {`ArrayOfFoo[Bool:]`, ` non-integer slice index bool (1:12) | ArrayOfFoo[Bool:] | ...........^ `, }, {`ArrayOfFoo[1:Bool]`, ` non-integer slice index bool (1:14) | ArrayOfFoo[1:Bool] | .............^ `, }, {`Bool[:]`, ` cannot slice bool (1:5) | Bool[:] | ....^ `, }, {`FuncTooManyReturns()`, ` func FuncTooManyReturns returns more then two values (1:1) | FuncTooManyReturns() | ^ `, }, {`len(42)`, ` invalid argument for len (type int) (1:1) | len(42) | ^ `, }, {`any(42, {#})`, ` builtin any takes only array (got int) (1:5) | any(42, {#}) | ....^ `, }, {`filter(42, {#})`, ` builtin filter takes only array (got int) (1:8) | filter(42, {#}) | .......^ `, }, {`MapOfAny[0]`, ` cannot use int to get an element from map[string]interface {} (1:10) | MapOfAny[0] | .........^ `, }, {`1 /* one */ + "2"`, ` invalid operation: + (mismatched types int and string) (1:13) | 1 /* one */ + "2" | ............^ `, }, {`FuncTyped(42)`, ` cannot use int as argument (type string) to call FuncTyped (1:11) | FuncTyped(42) | ..........^ `, }, {`.0 in MapOfFoo`, ` cannot use float64 as type string in map key (1:4) | .0 in MapOfFoo | ...^ `, }, {`1/2 in MapIntAny`, ` cannot use float64 as type int in map key (1:5) | 1/2 in MapIntAny | ....^ `, }, {`0.5 in ArrayOfFoo`, ` cannot use float64 as type *mock.Foo in array (1:5) | 0.5 in ArrayOfFoo | ....^ `, }, {`repeat("0", 1/0)`, ` cannot use float64 as argument (type int) to call repeat (1:14) | repeat("0", 1/0) | .............^ `, }, {`let map = 42; map`, ` cannot redeclare builtin map (1:5) | let map = 42; map | ....^ `, }, {`let len = 42; len`, ` cannot redeclare builtin len (1:5) | let len = 42; len | ....^ `, }, {`let Float = 42; Float`, ` cannot redeclare Float (1:5) | let Float = 42; Float | ....^ `, }, {`let foo = 1; let foo = 2; foo`, ` cannot redeclare variable foo (1:18) | let foo = 1; let foo = 2; foo | .................^ `, }, {`map(1..9, #unknown)`, ` unknown pointer #unknown (1:11) | map(1..9, #unknown) | ..........^ `, }, {`42 in ["a", "b", "c"]`, ` cannot use int as type string in array (1:4) | 42 in ["a", "b", "c"] | ...^ `, }, {`"foo" matches "[+"`, ` error parsing regexp: missing closing ]: ` + "`[+`" + ` (1:7) | "foo" matches "[+" | ......^ `, }, {`get(false, 2)`, ` type bool does not support indexing (1:5) | get(false, 2) | ....^ `, }, {`get(1..2, 0.5)`, ` non-integer slice index float64 (1:11) | get(1..2, 0.5) | ..........^`, }, {`trimPrefix(nil)`, ` cannot use nil as argument (type string) to call trimPrefix (1:12) | trimPrefix(nil) | ...........^ `, }, {`1..3 | filter(# > 1) | filter(# == "str")`, ` invalid operation: == (mismatched types int and string) (1:33) | 1..3 | filter(# > 1) | filter(# == "str") | ................................^ `, }, {`1..3 | map("str") | filter(# > 1)`, ` invalid operation: > (mismatched types string and int) (1:30) | 1..3 | map("str") | filter(# > 1) | .............................^ `, }, { `1; 2 + true; 3`, ` invalid operation: + (mismatched types int and bool) (1:6) | 1; 2 + true; 3 | .....^ `, }, { `$env()`, ` mock.Env is not callable (1:1) | $env() | ^ `, }, { `$env(1)`, ` mock.Env is not callable (1:1) | $env(1) | ^ `, }, { `$env(abs())`, ` mock.Env is not callable (1:1) | $env(abs()) | ^ `, }, } c := new(checker.Checker) for _, tt := range errorTests { t.Run(tt.code, func(t *testing.T) { tree, err := parser.Parse(tt.code) require.NoError(t, err) _, err = c.Check(tree, conf.New(mock.Env{})) if err == nil { err = fmt.Errorf("") } assert.Equal(t, strings.Trim(tt.err, "\n"), err.Error()) }) } } func TestCheck_FloatVsInt(t *testing.T) { tree, err := parser.Parse(`Int + Float`) require.NoError(t, err) typ, err := checker.Check(tree, conf.New(mock.Env{})) assert.NoError(t, err) assert.Equal(t, typ.Kind(), reflect.Float64) } func TestCheck_IntSums(t *testing.T) { tree, err := parser.Parse(`Uint32 + Int32`) require.NoError(t, err) typ, err := checker.Check(tree, conf.New(mock.Env{})) assert.NoError(t, err) assert.Equal(t, typ.Kind(), reflect.Int) } func TestVisitor_ConstantNode(t *testing.T) { tree, err := parser.Parse(`re("[a-z]")`) require.NoError(t, err) regexValue := regexp.MustCompile("[a-z]") constNode := &ast.ConstantNode{Value: regexValue} ast.Patch(&tree.Node, constNode) _, err = checker.Check(tree, nil) assert.NoError(t, err) assert.Equal(t, reflect.TypeOf(regexValue), tree.Node.Type()) } func TestCheck_AsBool(t *testing.T) { tree, err := parser.Parse(`1+2`) require.NoError(t, err) config := &conf.Config{} expr.AsBool()(config) _, err = checker.Check(tree, config) assert.Error(t, err) assert.Equal(t, "expected bool, but got int", err.Error()) } func TestCheck_AsInt64(t *testing.T) { tree, err := parser.Parse(`true`) require.NoError(t, err) config := &conf.Config{} expr.AsInt64()(config) _, err = checker.Check(tree, config) assert.Error(t, err) assert.Equal(t, "expected int64, but got bool", err.Error()) } func TestCheck_TaggedFieldName(t *testing.T) { tree, err := parser.Parse(`foo.bar`) require.NoError(t, err) config := conf.CreateNew() expr.Env(struct { X struct { Y bool `expr:"bar"` } `expr:"foo"` }{})(config) expr.AsBool()(config) _, err = checker.Check(tree, config) assert.NoError(t, err) } func TestCheck_NoConfig(t *testing.T) { tree, err := parser.Parse(`any`) require.NoError(t, err) _, err = checker.Check(tree, conf.CreateNew()) assert.NoError(t, err) } func TestCheck_AllowUndefinedVariables(t *testing.T) { type Env struct { A int } tree, err := parser.Parse(`Any + fn()`) require.NoError(t, err) config := conf.New(Env{}) expr.AllowUndefinedVariables()(config) _, err = checker.Check(tree, config) assert.NoError(t, err) } func TestCheck_AllowUndefinedVariables_DefaultType(t *testing.T) { env := map[string]bool{} tree, err := parser.Parse(`Any`) require.NoError(t, err) config := conf.New(env) expr.AllowUndefinedVariables()(config) expr.AsBool()(config) _, err = checker.Check(tree, config) assert.NoError(t, err) } func TestCheck_AllowUndefinedVariables_OptionalChaining(t *testing.T) { type Env struct{} tree, err := parser.Parse("Not?.A.B == nil") require.NoError(t, err) config := conf.New(Env{}) expr.AllowUndefinedVariables()(config) _, err = checker.Check(tree, config) assert.NoError(t, err) } func TestCheck_PointerNode(t *testing.T) { _, err := checker.Check(&parser.Tree{Node: &ast.PointerNode{}}, nil) assert.Error(t, err) assert.Contains(t, err.Error(), "cannot use pointer accessor outside predicate") } func TestCheck_TypeWeights(t *testing.T) { types := map[string]any{ "Uint": uint(1), "Uint8": uint8(2), "Uint16": uint16(3), "Uint32": uint32(4), "Uint64": uint64(5), "Int": 6, "Int8": int8(7), "Int16": int16(8), "Int32": int32(9), "Int64": int64(10), "Float32": float32(11), "Float64": float64(12), } c := new(checker.Checker) for a := range types { for b := range types { tree, err := parser.Parse(fmt.Sprintf("%s + %s", a, b)) require.NoError(t, err) config := conf.New(types) _, err = c.Check(tree, config) require.NoError(t, err) } } } func TestCheck_works_with_nil_types(t *testing.T) { env := map[string]any{ "null": nil, } tree, err := parser.Parse("null") require.NoError(t, err) _, err = checker.Check(tree, conf.New(env)) require.NoError(t, err) } func TestCheck_cast_to_expected_works_with_interface(t *testing.T) { t.Run("float64", func(t *testing.T) { type Env struct { Any any } tree, err := parser.Parse("Any") require.NoError(t, err) config := conf.New(Env{}) expr.AsFloat64()(config) expr.AsAny()(config) _, err = checker.Check(tree, config) require.NoError(t, err) }) t.Run("kind", func(t *testing.T) { env := map[string]any{ "Any": any("foo"), } tree, err := parser.Parse("Any") require.NoError(t, err) config := conf.New(env) expr.AsKind(reflect.String)(config) _, err = checker.Check(tree, config) require.NoError(t, err) }) } func TestCheck_operator_in_works_with_interfaces(t *testing.T) { tree, err := parser.Parse(`'Tom' in names`) require.NoError(t, err) config := conf.New(nil) expr.AllowUndefinedVariables()(config) _, err = checker.Check(tree, config) require.NoError(t, err) } func TestCheck_Function_types_are_checked(t *testing.T) { add := expr.Function( "add", func(p ...any) (any, error) { out := 0 for _, each := range p { out += each.(int) } return out, nil }, new(func(int) int), new(func(int, int) int), new(func(int, int, int) int), new(func(...int) int), ) config := conf.CreateNew() add(config) c := new(checker.Checker) tests := []string{ "add(1)", "add(1, 2)", "add(1, 2, 3)", "add(1, 2, 3, 4)", } for _, test := range tests { t.Run(test, func(t *testing.T) { tree, err := parser.Parse(test) require.NoError(t, err) _, err = c.Check(tree, config) require.NoError(t, err) require.Equal(t, reflect.Int, tree.Node.Type().Kind()) }) } t.Run("errors", func(t *testing.T) { tree, err := parser.Parse("add(1, '2')") require.NoError(t, err) _, err = c.Check(tree, config) require.Error(t, err) require.Equal(t, "cannot use string as argument (type int) to call add (1:8)\n | add(1, '2')\n | .......^", err.Error()) }) } func TestCheck_Function_without_types(t *testing.T) { add := expr.Function( "add", func(p ...any) (any, error) { out := 0 for _, each := range p { out += each.(int) } return out, nil }, ) tree, err := parser.Parse("add(1, 2, 3)") require.NoError(t, err) config := conf.CreateNew() add(config) _, err = checker.Check(tree, config) require.NoError(t, err) require.Equal(t, reflect.Interface, tree.Node.Type().Kind()) } func TestCheck_dont_panic_on_nil_arguments_for_builtins(t *testing.T) { tests := []string{ "len(nil)", "abs(nil)", "int(nil)", "float(nil)", } for _, test := range tests { t.Run(test, func(t *testing.T) { tree, err := parser.Parse(test) require.NoError(t, err) _, err = checker.Check(tree, conf.New(nil)) require.Error(t, err) }) } } func TestCheck_do_not_override_params_for_functions(t *testing.T) { env := map[string]any{ "foo": func(p string) string { return "foo" }, } config := conf.New(env) expr.Function( "bar", func(p ...any) (any, error) { return p[0].(string), nil }, new(func(string) string), )(config) config.Check() t.Run("func from env", func(t *testing.T) { tree, err := parser.Parse("foo(1)") require.NoError(t, err) _, err = checker.Check(tree, config) require.Error(t, err) require.Contains(t, err.Error(), "cannot use int as argument") }) t.Run("func from function", func(t *testing.T) { tree, err := parser.Parse("bar(1)") require.NoError(t, err) _, err = checker.Check(tree, config) require.Error(t, err) require.Contains(t, err.Error(), "cannot use int as argument") }) } func TestCheck_env_keyword(t *testing.T) { env := map[string]any{ "num": 42, "str": "foo", "name": "str", } tests := []struct { input string want reflect.Kind }{ {`$env['str']`, reflect.String}, {`$env['num']`, reflect.Int}, {`$env[name]`, reflect.Interface}, } c := new(checker.Checker) for _, test := range tests { t.Run(test.input, func(t *testing.T) { tree, err := parser.Parse(test.input) require.NoError(t, err) rtype, err := c.Check(tree, conf.New(env)) require.NoError(t, err) require.True(t, rtype.Kind() == test.want, fmt.Sprintf("expected %s, got %s", test.want, rtype.Kind())) }) } } func TestCheck_builtin_without_call(t *testing.T) { tests := []struct { input string err string }{ {`len + 1`, "invalid operation: + (mismatched types func(...interface {}) (interface {}, error) and int) (1:5)\n | len + 1\n | ....^"}, {`string.A`, "type func(interface {}) string has no field A (1:8)\n | string.A\n | .......^"}, } c := new(checker.Checker) for _, test := range tests { t.Run(test.input, func(t *testing.T) { tree, err := parser.Parse(test.input) require.NoError(t, err) _, err = c.Check(tree, conf.New(nil)) require.Error(t, err) require.Equal(t, test.err, err.Error()) }) } } func TestCheck_EmbeddedInterface(t *testing.T) { t.Run("embedded interface lookup returns compile-error not panic", func(t *testing.T) { type Env struct { context.Context Country string } type Wrapper struct { Ctx Env } config := conf.New(Wrapper{ Ctx: Env{ Context: context.Background(), Country: "TR", }, }) expr.WithContext("Ctx")(config) _, err := checker.ParseCheck("Ctx.C", config) require.Error(t, err) require.Contains(t, err.Error(), "has no field C") }) } func TestCheck_types(t *testing.T) { env := types.Map{ "foo": types.Map{ "bar": types.Map{ "baz": types.String, types.Extra: types.String, }, }, "arr": types.Array(types.Map{ "value": types.String, }), types.Extra: types.Any, } noerr := "no error" tests := []struct { code string err string }{ {`unknown`, noerr}, {`[unknown + 42, another_unknown + "foo"]`, noerr}, {`foo.bar.baz > 0`, `invalid operation: > (mismatched types string and int)`}, {`foo.unknown.baz`, `unknown field unknown (1:5)`}, {`foo.bar.unknown`, noerr}, {`foo.bar.unknown + 42`, `invalid operation: + (mismatched types string and int)`}, {`[foo] | map(.unknown)`, `unknown field unknown`}, {`[foo] | map(.bar) | filter(.baz)`, `predicate should return boolean (got string)`}, {`arr | filter(.value > 0)`, `invalid operation: > (mismatched types string and int)`}, {`arr | filter(.value contains "a") | filter(.value == 0)`, `invalid operation: == (mismatched types string and int)`}, } c := new(checker.Checker) for _, test := range tests { t.Run(test.code, func(t *testing.T) { tree, err := parser.Parse(test.code) require.NoError(t, err) config := conf.New(env) _, err = c.Check(tree, config) if test.err == noerr { require.NoError(t, err) } else { require.Error(t, err) require.Contains(t, err.Error(), test.err) } }) } } ================================================ FILE: checker/info.go ================================================ package checker import ( "reflect" "github.com/expr-lang/expr/ast" . "github.com/expr-lang/expr/checker/nature" "github.com/expr-lang/expr/vm" ) func FieldIndex(c *Cache, env Nature, node ast.Node) (bool, []int, string) { switch n := node.(type) { case *ast.IdentifierNode: if idx, ok := env.FieldIndex(c, n.Value); ok { return true, idx, n.Value } case *ast.MemberNode: base := n.Node.Nature().Deref(c) if base.Kind == reflect.Struct { if prop, ok := n.Property.(*ast.StringNode); ok { if idx, ok := base.FieldIndex(c, prop.Value); ok { return true, idx, prop.Value } } } } return false, nil, "" } func MethodIndex(c *Cache, env Nature, node ast.Node) (bool, int, string) { switch n := node.(type) { case *ast.IdentifierNode: if env.Kind == reflect.Struct { if m, ok := env.Get(c, n.Value); ok && m.TypeData != nil { return m.Method, m.MethodIndex, n.Value } } case *ast.MemberNode: if name, ok := n.Property.(*ast.StringNode); ok { base := n.Node.Type() if base != nil && base.Kind() != reflect.Interface { if m, ok := base.MethodByName(name.Value); ok { return true, m.Index, name.Value } } } } return false, 0, "" } func TypedFuncIndex(fn reflect.Type, method bool) (int, bool) { if fn == nil { return 0, false } if fn.Kind() != reflect.Func { return 0, false } // OnCallTyped doesn't work for functions with variadic arguments. if fn.IsVariadic() { return 0, false } // OnCallTyped doesn't work named function, like `type MyFunc func() int`. if fn.PkgPath() != "" { // If PkgPath() is not empty, it means that function is named. return 0, false } fnNumIn := fn.NumIn() fnInOffset := 0 if method { fnNumIn-- fnInOffset = 1 } funcTypes: for i := range vm.FuncTypes { if i == 0 { continue } typed := reflect.ValueOf(vm.FuncTypes[i]).Elem().Type() if typed.Kind() != reflect.Func { continue } if typed.NumOut() != fn.NumOut() { continue } for j := 0; j < typed.NumOut(); j++ { if typed.Out(j) != fn.Out(j) { continue funcTypes } } if typed.NumIn() != fnNumIn { continue } for j := 0; j < typed.NumIn(); j++ { if typed.In(j) != fn.In(j+fnInOffset) { continue funcTypes } } return i, true } return 0, false } func IsFastFunc(fn reflect.Type, method bool) bool { if fn == nil { return false } if fn.Kind() != reflect.Func { return false } numIn := 1 if method { numIn = 2 } if fn.IsVariadic() && fn.NumIn() == numIn && fn.NumOut() == 1 && fn.Out(0).Kind() == reflect.Interface { rest := fn.In(fn.NumIn() - 1) // function has only one param for functions and two for methods if rest != nil && rest.Kind() == reflect.Slice && rest.Elem().Kind() == reflect.Interface { return true } } return false } ================================================ FILE: checker/info_test.go ================================================ package checker_test import ( "reflect" "testing" "time" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr/checker" "github.com/expr-lang/expr/test/mock" ) func TestTypedFuncIndex(t *testing.T) { fn := func() time.Duration { return 1 * time.Second } index, ok := checker.TypedFuncIndex(reflect.TypeOf(fn), false) require.True(t, ok) require.Equal(t, 1, index) } func TestTypedFuncIndex_excludes_named_functions(t *testing.T) { var fn mock.MyFunc _, ok := checker.TypedFuncIndex(reflect.TypeOf(fn), false) require.False(t, ok) } ================================================ FILE: checker/nature/nature.go ================================================ package nature import ( "fmt" "reflect" "time" "github.com/expr-lang/expr/builtin" "github.com/expr-lang/expr/internal/deref" ) var ( intType = reflect.TypeOf(0) floatType = reflect.TypeOf(float64(0)) arrayType = reflect.TypeOf([]any{}) byteSliceType = reflect.TypeOf([]byte{}) timeType = reflect.TypeOf(time.Time{}) durationType = reflect.TypeOf(time.Duration(0)) builtinInt = map[reflect.Type]struct{}{ reflect.TypeOf(int(0)): {}, reflect.TypeOf(int8(0)): {}, reflect.TypeOf(int16(0)): {}, reflect.TypeOf(int32(0)): {}, reflect.TypeOf(int64(0)): {}, reflect.TypeOf(uintptr(0)): {}, reflect.TypeOf(uint(0)): {}, reflect.TypeOf(uint8(0)): {}, reflect.TypeOf(uint16(0)): {}, reflect.TypeOf(uint32(0)): {}, reflect.TypeOf(uint64(0)): {}, } builtinFloat = map[reflect.Type]struct{}{ reflect.TypeOf(float32(0)): {}, reflect.TypeOf(float64(0)): {}, } ) type NatureCheck int const ( _ NatureCheck = iota BoolCheck StringCheck IntegerCheck NumberCheck MapCheck ArrayCheck TimeCheck DurationCheck ) type Nature struct { // The order of the fields matter, check alignment before making changes. Type reflect.Type // Type of the value. If nil, then value is unknown. Kind reflect.Kind // Kind of the value. *TypeData // Ref is a reference used for multiple, disjoint purposes. When the Nature // is for a: // - Predicate: then Ref is the nature of the Out of the predicate. // - Array-like types: then Ref is the Elem nature of array type (usually Type is []any, but ArrayOf can be any nature). Ref *Nature Nil bool // If value is nil. Strict bool // If map is types.StrictMap. Method bool // If value retrieved from method. Usually used to determine amount of in arguments. IsInteger bool // If it's a builtin integer or unsigned integer type. IsFloat bool // If it's a builtin float type. } type TypeData struct { methodset *methodset // optional to avoid the map in *Cache *structData // map-only data Fields map[string]Nature // Fields of map type. DefaultMapValue *Nature // Default value of map type. // callable-only data Func *builtin.Function // Used to pass function type from callee to CallNode. MethodIndex int // Index of method in type. inElem, outZero *Nature numIn, numOut int isVariadic bool isVariadicSet bool numInSet bool numOutSet bool } // Cache is a shared cache of type information. It is only used in the stages // where type information becomes relevant, so packages like ast, parser, types, // and lexer do not need to use the cache because they don't need any service // from the Nature type, they only describe. However, when receiving a Nature // from one of those packages, the cache must be set immediately. type Cache struct { methods map[reflect.Type]*methodset structs map[reflect.Type]Nature } // NatureOf returns a Nature describing "i". If "i" is nil then it returns a // Nature describing the value "nil". func (c *Cache) NatureOf(i any) Nature { // reflect.TypeOf(nil) returns nil, but in FromType we want to differentiate // what nil means for us if i == nil { return Nature{Nil: true} } return c.FromType(reflect.TypeOf(i)) } // FromType returns a Nature describing a value of type "t". If "t" is nil then // it returns a Nature describing an unknown value. func (c *Cache) FromType(t reflect.Type) Nature { if t == nil { return Nature{} } var td *TypeData var isInteger, isFloat bool k := t.Kind() switch k { case reflect.Struct: // c can be nil when we call the package function FromType, which uses a // nil *Cache to call this method. if c != nil { return c.getStruct(t) } fallthrough case reflect.Func: td = new(TypeData) case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: _, isInteger = builtinInt[t] case reflect.Float32, reflect.Float64: _, isFloat = builtinFloat[t] } return Nature{ Type: t, Kind: k, TypeData: td, IsInteger: isInteger, IsFloat: isFloat, } } func (c *Cache) getStruct(t reflect.Type) Nature { if c.structs == nil { c.structs = map[reflect.Type]Nature{} } else if nt, ok := c.structs[t]; ok { return nt } nt := Nature{ Type: t, Kind: reflect.Struct, TypeData: &TypeData{ structData: &structData{ rType: t, numField: t.NumField(), anonIdx: -1, // do not lookup embedded fields yet }, }, } c.structs[t] = nt return nt } func (c *Cache) getMethodset(t reflect.Type, k reflect.Kind) *methodset { if t == nil || c == nil { return nil } if c.methods == nil { c.methods = map[reflect.Type]*methodset{ t: nil, } } else if s, ok := c.methods[t]; ok { return s } numMethod := t.NumMethod() if numMethod < 1 { c.methods[t] = nil // negative cache return nil } s := &methodset{ rType: t, kind: k, numMethod: numMethod, } c.methods[t] = s return s } // NatureOf calls NatureOf on a nil *Cache. See the comment on Cache. func NatureOf(i any) Nature { var c *Cache return c.NatureOf(i) } // FromType calls FromType on a nil *Cache. See the comment on Cache. func FromType(t reflect.Type) Nature { var c *Cache return c.FromType(t) } func ArrayFromType(c *Cache, t reflect.Type) Nature { elem := c.FromType(t) nt := c.FromType(arrayType) nt.Ref = &elem return nt } func (n *Nature) IsAny(c *Cache) bool { return n.Type != nil && n.Kind == reflect.Interface && n.NumMethods(c) == 0 } func (n *Nature) IsUnknown(c *Cache) bool { return n.Type == nil && !n.Nil || n.IsAny(c) } func (n *Nature) String() string { if n.Type != nil { return n.Type.String() } return "unknown" } func (n *Nature) Deref(c *Cache) Nature { t, _, changed := deref.TypeKind(n.Type, n.Kind) if !changed { return *n } return c.FromType(t) } func (n *Nature) Key(c *Cache) Nature { if n.Kind == reflect.Map { return c.FromType(n.Type.Key()) } return Nature{} } func (n *Nature) Elem(c *Cache) Nature { switch n.Kind { case reflect.Ptr: return c.FromType(n.Type.Elem()) case reflect.Map: if n.TypeData != nil && n.DefaultMapValue != nil { return *n.DefaultMapValue } return c.FromType(n.Type.Elem()) case reflect.Slice, reflect.Array: if n.Ref != nil { return *n.Ref } return c.FromType(n.Type.Elem()) } return Nature{} } func (n *Nature) AssignableTo(nt Nature) bool { if n.Nil { switch nt.Kind { case reflect.Pointer, reflect.Interface, reflect.Chan, reflect.Func, reflect.Map, reflect.Slice: // nil can be assigned to these kinds return true } } if n.Type == nil || nt.Type == nil || n.Kind != nt.Kind && nt.Kind != reflect.Interface { return false } return n.Type.AssignableTo(nt.Type) } func (n *Nature) getMethodset(c *Cache) *methodset { if n.TypeData != nil && n.TypeData.methodset != nil { return n.TypeData.methodset } s := c.getMethodset(n.Type, n.Kind) if n.TypeData != nil { n.TypeData.methodset = s // cache locally if possible } return s } func (n *Nature) NumMethods(c *Cache) int { if s := n.getMethodset(c); s != nil { return s.numMethod } return 0 } func (n *Nature) MethodByName(c *Cache, name string) (Nature, bool) { if s := n.getMethodset(c); s != nil { if m := s.method(c, name); m != nil { return m.nature, true } } return Nature{}, false } func (n *Nature) NumIn() int { if n.numInSet { return n.numIn } n.numInSet = true n.numIn = n.Type.NumIn() return n.numIn } func (n *Nature) InElem(c *Cache, i int) Nature { if n.inElem == nil { n2 := c.FromType(n.Type.In(i)) n2 = n2.Elem(c) n.inElem = &n2 } return *n.inElem } func (n *Nature) In(c *Cache, i int) Nature { return c.FromType(n.Type.In(i)) } func (n *Nature) IsFirstArgUnknown(c *Cache) bool { if n.Type != nil { n2 := c.FromType(n.Type.In(0)) return n2.IsUnknown(c) } return false } func (n *Nature) NumOut() int { if n.numOutSet { return n.numOut } n.numOutSet = true n.numOut = n.Type.NumOut() return n.numOut } func (n *Nature) Out(c *Cache, i int) Nature { if i != 0 { return n.out(c, i) } if n.outZero != nil { return *n.outZero } nt := n.out(c, 0) n.outZero = &nt return nt } func (n *Nature) out(c *Cache, i int) Nature { if n.Type == nil { return Nature{} } return c.FromType(n.Type.Out(i)) } func (n *Nature) IsVariadic() bool { if n.isVariadicSet { return n.isVariadic } n.isVariadicSet = true n.isVariadic = n.Type.IsVariadic() return n.isVariadic } func (n *Nature) FieldByName(c *Cache, name string) (Nature, bool) { if n.Kind != reflect.Struct { return Nature{}, false } var sd *structData if n.TypeData != nil && n.structData != nil { sd = n.structData } else { sd = c.getStruct(n.Type).structData } if sf := sd.structField(c, nil, name); sf != nil { return sf.Nature, true } return Nature{}, false } func (n *Nature) IsFastMap() bool { return n.Type != nil && n.Type.Kind() == reflect.Map && n.Type.Key().Kind() == reflect.String && n.Type.Elem().Kind() == reflect.Interface } func (n *Nature) Get(c *Cache, name string) (Nature, bool) { if n.Kind == reflect.Map && n.TypeData != nil { f, ok := n.Fields[name] return f, ok } return n.getSlow(c, name) } func (n *Nature) getSlow(c *Cache, name string) (Nature, bool) { if nt, ok := n.MethodByName(c, name); ok { return nt, true } t, k, changed := deref.TypeKind(n.Type, n.Kind) if k == reflect.Struct { var sd *structData if changed { sd = c.getStruct(t).structData } else { sd = n.structData } if sf := sd.structField(c, nil, name); sf != nil { return sf.Nature, true } } return Nature{}, false } func (n *Nature) FieldIndex(c *Cache, name string) ([]int, bool) { if n.Kind != reflect.Struct { return nil, false } if sf := n.structField(c, nil, name); sf != nil { return sf.Index, true } return nil, false } func (n *Nature) All(c *Cache) map[string]Nature { table := make(map[string]Nature) if n.Type == nil { return table } for i := 0; i < n.NumMethods(c); i++ { method := n.Type.Method(i) nt := c.FromType(method.Type) if nt.TypeData == nil { nt.TypeData = new(TypeData) } nt.Method = true nt.MethodIndex = method.Index table[method.Name] = nt } t := deref.Type(n.Type) switch t.Kind() { case reflect.Struct: for name, nt := range StructFields(c, t) { if _, ok := table[name]; ok { continue } table[name] = nt } case reflect.Map: if n.TypeData != nil { for key, nt := range n.Fields { if _, ok := table[key]; ok { continue } table[key] = nt } } } return table } func (n *Nature) IsNumber() bool { return n.IsInteger || n.IsFloat } func (n *Nature) PromoteNumericNature(c *Cache, rhs Nature) Nature { if n.IsUnknown(c) || rhs.IsUnknown(c) { return Nature{} } if n.IsFloat || rhs.IsFloat { return c.FromType(floatType) } return c.FromType(intType) } func (n *Nature) IsTime() bool { return n.Type == timeType } func (n *Nature) IsDuration() bool { return n.Type == durationType } func (n *Nature) IsBool() bool { return n.Kind == reflect.Bool } func (n *Nature) IsString() bool { return n.Kind == reflect.String } func (n *Nature) IsByteSlice() bool { return n.Type == byteSliceType } func (n *Nature) IsArray() bool { return n.Kind == reflect.Slice || n.Kind == reflect.Array } func (n *Nature) IsMap() bool { return n.Kind == reflect.Map } func (n *Nature) IsStruct() bool { return n.Kind == reflect.Struct } func (n *Nature) IsFunc() bool { return n.Kind == reflect.Func } func (n *Nature) IsPointer() bool { return n.Kind == reflect.Ptr } func (n *Nature) IsAnyOf(cs ...NatureCheck) bool { var result bool for i := 0; i < len(cs) && !result; i++ { switch cs[i] { case BoolCheck: result = n.IsBool() case StringCheck: result = n.IsString() case IntegerCheck: result = n.IsInteger case NumberCheck: result = n.IsNumber() case MapCheck: result = n.IsMap() case ArrayCheck: result = n.IsArray() case TimeCheck: result = n.IsTime() case DurationCheck: result = n.IsDuration() default: panic(fmt.Sprintf("unknown check value %d", cs[i])) } } return result } func (n *Nature) ComparableTo(c *Cache, rhs Nature) bool { return n.IsUnknown(c) || rhs.IsUnknown(c) || n.Nil || rhs.Nil || n.IsNumber() && rhs.IsNumber() || n.IsDuration() && rhs.IsDuration() || n.IsTime() && rhs.IsTime() || n.IsArray() && rhs.IsArray() || n.AssignableTo(rhs) } func (n *Nature) MaybeCompatible(c *Cache, rhs Nature, cs ...NatureCheck) bool { nIsUnknown := n.IsUnknown(c) rshIsUnknown := rhs.IsUnknown(c) return nIsUnknown && rshIsUnknown || nIsUnknown && rhs.IsAnyOf(cs...) || rshIsUnknown && n.IsAnyOf(cs...) } func (n *Nature) MakeArrayOf(c *Cache) Nature { nt := c.FromType(arrayType) nt.Ref = n return nt } ================================================ FILE: checker/nature/utils.go ================================================ package nature import ( "reflect" "github.com/expr-lang/expr/internal/deref" ) func fieldName(fieldName string, tag reflect.StructTag) (string, bool) { switch taggedName := tag.Get("expr"); taggedName { case "-": return "", false case "": return fieldName, true default: return taggedName, true } } type structData struct { rType reflect.Type fields map[string]*structField numField, ownIdx, anonIdx int curParent, curChild *structData curChildIndex []int } type structField struct { Nature Index []int } func (s *structData) finished() bool { return s.ownIdx >= s.numField && // no own fields left to visit s.anonIdx >= s.numField && // no embedded fields to visit s.curChild == nil // no child in process of visiting } func (s *structData) structField(c *Cache, parentEmbed *structData, name string) *structField { if s.fields == nil { if s.numField > 0 { s.fields = make(map[string]*structField, s.numField) } } else if f := s.fields[name]; f != nil { return f } if s.finished() { return nil } // Lookup own fields first. for ; s.ownIdx < s.numField; s.ownIdx++ { field := s.rType.Field(s.ownIdx) if field.Anonymous && s.anonIdx < 0 { // start iterating anon fields on the first instead of zero s.anonIdx = s.ownIdx } if !field.IsExported() { continue } fName, ok := fieldName(field.Name, field.Tag) if !ok || fName == "" { // name can still be empty for a type created at runtime with // reflect continue } nt := c.FromType(field.Type) sf := &structField{ Nature: nt, Index: field.Index, } s.fields[fName] = sf if parentEmbed != nil { parentEmbed.trySet(fName, sf) } if fName == name { return sf } } if s.curChild != nil { sf := s.findInEmbedded(c, parentEmbed, s.curChild, s.curChildIndex, name) if sf != nil { return sf } } // Lookup embedded fields through anon own fields for ; s.anonIdx >= 0 && s.anonIdx < s.numField; s.anonIdx++ { field := s.rType.Field(s.anonIdx) // we do enter embedded non-exported types because they could contain // exported fields if !field.Anonymous { continue } t, k, _ := deref.TypeKind(field.Type, field.Type.Kind()) if k != reflect.Struct { continue } childEmbed := c.getStruct(t).structData sf := s.findInEmbedded(c, parentEmbed, childEmbed, field.Index, name) if sf != nil { return sf } } return nil } func (s *structData) findInEmbedded( c *Cache, parentEmbed, childEmbed *structData, childIndex []int, name string, ) *structField { // Set current parent/child data. This allows trySet to handle child fields // and add them to our struct and to the parent as well if needed s.curParent = parentEmbed s.curChild = childEmbed s.curChildIndex = childIndex defer func() { // Ensure to cleanup references s.curParent = nil if childEmbed.finished() { // If the child can still have more fields to explore then keep it // referened to look it up again if we need to s.curChild = nil s.curChildIndex = nil } }() // See if the child has already cached its fields. This is still important // to check even if it's the s.unfinishedEmbedded because it may have // explored new fields since the last time we visited it for name, sf := range childEmbed.fields { s.trySet(name, sf) } // Recheck if we have what we needed from the above sync if sf := s.fields[name]; sf != nil { return sf } // Try finding in the child again in case it hasn't finished if !childEmbed.finished() { if childEmbed.structField(c, s, name) != nil { return s.fields[name] } } return nil } func (s *structData) trySet(name string, sf *structField) { if _, ok := s.fields[name]; ok { return } sf = &structField{ Nature: sf.Nature, Index: append(s.curChildIndex, sf.Index...), } s.fields[name] = sf if s.curParent != nil { s.curParent.trySet(name, sf) } } func StructFields(c *Cache, t reflect.Type) map[string]Nature { table := make(map[string]Nature) if t == nil { return table } t, k, _ := deref.TypeKind(t, t.Kind()) if k == reflect.Struct { // lookup for a field with an empty name, which will cause to never find a // match, meaning everything will have been cached. sd := c.getStruct(t).structData sd.structField(c, nil, "") for name, sf := range sd.fields { table[name] = sf.Nature } } return table } type methodset struct { rType reflect.Type kind reflect.Kind methods map[string]*method numMethod, idx int } type method struct { reflect.Method nature Nature } func (s *methodset) method(c *Cache, name string) *method { if s.methods == nil { s.methods = make(map[string]*method, s.numMethod) } else if m := s.methods[name]; m != nil { return m } for ; s.idx < s.numMethod; s.idx++ { rm := s.rType.Method(s.idx) if !rm.IsExported() { continue } nt := c.FromType(rm.Type) if s.rType.Kind() != reflect.Interface { nt.Method = true nt.MethodIndex = rm.Index // In case of interface type method will not have a receiver, // and to prevent checker decreasing numbers of in arguments // return method type as not method (second argument is false). // Also, we can not use m.Index here, because it will be // different indexes for different types which implement // the same interface. } m := &method{ Method: rm, nature: nt, } s.methods[rm.Name] = m if rm.Name == name { return m } } return nil } ================================================ FILE: compiler/compiler.go ================================================ package compiler import ( "fmt" "math" "reflect" "regexp" "runtime/debug" "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/builtin" "github.com/expr-lang/expr/checker" . "github.com/expr-lang/expr/checker/nature" "github.com/expr-lang/expr/conf" "github.com/expr-lang/expr/file" "github.com/expr-lang/expr/parser" . "github.com/expr-lang/expr/vm" "github.com/expr-lang/expr/vm/runtime" ) const ( placeholder = 12345 ) func Compile(tree *parser.Tree, config *conf.Config) (program *Program, err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("%v\n%s", r, debug.Stack()) } }() c := &compiler{ config: config, locations: make([]file.Location, 0), constantsIndex: make(map[any]int), functionsIndex: make(map[string]int), debugInfo: make(map[string]string), } if config != nil { c.ntCache = &c.config.NtCache } else { c.ntCache = new(Cache) } c.compile(tree.Node) if c.config != nil { switch c.config.Expect { case reflect.Int: c.emit(OpCast, 0) case reflect.Int64: c.emit(OpCast, 1) case reflect.Float64: c.emit(OpCast, 2) case reflect.Bool: c.emit(OpCast, 3) } if c.config.Optimize { c.optimize() } } var span *Span if len(c.spans) > 0 { span = c.spans[0] } program = NewProgram( tree.Source, tree.Node, c.locations, c.variables, c.constants, c.bytecode, c.arguments, c.functions, c.debugInfo, span, ) return } type compiler struct { config *conf.Config ntCache *Cache locations []file.Location bytecode []Opcode variables int scopes []scope constants []any constantsIndex map[any]int functions []Function functionsIndex map[string]int debugInfo map[string]string nodes []ast.Node spans []*Span chains [][]int arguments []int } type scope struct { variableName string index int } func (c *compiler) nodeParent() ast.Node { if len(c.nodes) > 1 { return c.nodes[len(c.nodes)-2] } return nil } func (c *compiler) emitLocation(loc file.Location, op Opcode, arg int) int { c.bytecode = append(c.bytecode, op) current := len(c.bytecode) c.arguments = append(c.arguments, arg) c.locations = append(c.locations, loc) return current } func (c *compiler) emit(op Opcode, args ...int) int { arg := 0 if len(args) > 1 { panic("too many arguments") } if len(args) == 1 { arg = args[0] } var loc file.Location if len(c.nodes) > 0 { loc = c.nodes[len(c.nodes)-1].Location() } return c.emitLocation(loc, op, arg) } func (c *compiler) emitPush(value any) int { return c.emit(OpPush, c.addConstant(value)) } func (c *compiler) addConstant(constant any) int { indexable := true hash := constant switch reflect.TypeOf(constant).Kind() { case reflect.Slice, reflect.Map, reflect.Struct, reflect.Func: indexable = false } if field, ok := constant.(*runtime.Field); ok { indexable = true hash = fmt.Sprintf("%v", field) } if method, ok := constant.(*runtime.Method); ok { indexable = true hash = fmt.Sprintf("%v", method) } if indexable { if p, ok := c.constantsIndex[hash]; ok { return p } } c.constants = append(c.constants, constant) p := len(c.constants) - 1 if indexable { c.constantsIndex[hash] = p } return p } func (c *compiler) addVariable(name string) int { c.variables++ c.debugInfo[fmt.Sprintf("var_%d", c.variables-1)] = name return c.variables - 1 } // emitFunction adds builtin.Function.Func to the program.functions and emits call opcode. func (c *compiler) emitFunction(fn *builtin.Function, argsLen int) { switch argsLen { case 0: c.emit(OpCall0, c.addFunction(fn.Name, fn.Func)) case 1: c.emit(OpCall1, c.addFunction(fn.Name, fn.Func)) case 2: c.emit(OpCall2, c.addFunction(fn.Name, fn.Func)) case 3: c.emit(OpCall3, c.addFunction(fn.Name, fn.Func)) default: c.emit(OpLoadFunc, c.addFunction(fn.Name, fn.Func)) c.emit(OpCallN, argsLen) } } // addFunction adds builtin.Function.Func to the program.functions and returns its index. func (c *compiler) addFunction(name string, fn Function) int { if fn == nil { panic("function is nil") } if p, ok := c.functionsIndex[name]; ok { return p } p := len(c.functions) c.functions = append(c.functions, fn) c.functionsIndex[name] = p c.debugInfo[fmt.Sprintf("func_%d", p)] = name return p } func (c *compiler) patchJump(placeholder int) { offset := len(c.bytecode) - placeholder c.arguments[placeholder-1] = offset } func (c *compiler) calcBackwardJump(to int) int { return len(c.bytecode) + 1 - to } func (c *compiler) compile(node ast.Node) { c.nodes = append(c.nodes, node) defer func() { c.nodes = c.nodes[:len(c.nodes)-1] }() if c.config != nil && c.config.Profile { span := &Span{ Name: reflect.TypeOf(node).String(), Expression: node.String(), } if len(c.spans) > 0 { prev := c.spans[len(c.spans)-1] prev.Children = append(prev.Children, span) } c.spans = append(c.spans, span) defer func() { if len(c.spans) > 1 { c.spans = c.spans[:len(c.spans)-1] } }() c.emit(OpProfileStart, c.addConstant(span)) defer func() { c.emit(OpProfileEnd, c.addConstant(span)) }() } switch n := node.(type) { case *ast.NilNode: c.NilNode(n) case *ast.IdentifierNode: c.IdentifierNode(n) case *ast.IntegerNode: c.IntegerNode(n) case *ast.FloatNode: c.FloatNode(n) case *ast.BoolNode: c.BoolNode(n) case *ast.StringNode: c.StringNode(n) case *ast.BytesNode: c.BytesNode(n) case *ast.ConstantNode: c.ConstantNode(n) case *ast.UnaryNode: c.UnaryNode(n) case *ast.BinaryNode: c.BinaryNode(n) case *ast.ChainNode: c.ChainNode(n) case *ast.MemberNode: c.MemberNode(n) case *ast.SliceNode: c.SliceNode(n) case *ast.CallNode: c.CallNode(n) case *ast.BuiltinNode: c.BuiltinNode(n) case *ast.PredicateNode: c.PredicateNode(n) case *ast.PointerNode: c.PointerNode(n) case *ast.VariableDeclaratorNode: c.VariableDeclaratorNode(n) case *ast.SequenceNode: c.SequenceNode(n) case *ast.ConditionalNode: c.ConditionalNode(n) case *ast.ArrayNode: c.ArrayNode(n) case *ast.MapNode: c.MapNode(n) case *ast.PairNode: c.PairNode(n) default: panic(fmt.Sprintf("undefined node type (%T)", node)) } } func (c *compiler) NilNode(_ *ast.NilNode) { c.emit(OpNil) } func (c *compiler) IdentifierNode(node *ast.IdentifierNode) { if index, ok := c.lookupVariable(node.Value); ok { c.emit(OpLoadVar, index) return } if node.Value == "$env" { c.emit(OpLoadEnv) return } var env Nature if c.config != nil { env = c.config.Env } if env.IsFastMap() { c.emit(OpLoadFast, c.addConstant(node.Value)) } else if ok, index, name := checker.FieldIndex(c.ntCache, env, node); ok { c.emit(OpLoadField, c.addConstant(&runtime.Field{ Index: index, Path: []string{name}, })) } else if ok, index, name := checker.MethodIndex(c.ntCache, env, node); ok { c.emit(OpLoadMethod, c.addConstant(&runtime.Method{ Name: name, Index: index, })) } else { c.emit(OpLoadConst, c.addConstant(node.Value)) } } func (c *compiler) IntegerNode(node *ast.IntegerNode) { t := node.Type() if t == nil { c.emitPush(node.Value) return } switch t.Kind() { case reflect.Float32: c.emitPush(float32(node.Value)) case reflect.Float64: c.emitPush(float64(node.Value)) case reflect.Int: c.emitPush(node.Value) case reflect.Int8: if node.Value > math.MaxInt8 || node.Value < math.MinInt8 { panic(fmt.Sprintf("constant %d overflows int8", node.Value)) } c.emitPush(int8(node.Value)) case reflect.Int16: if node.Value > math.MaxInt16 || node.Value < math.MinInt16 { panic(fmt.Sprintf("constant %d overflows int16", node.Value)) } c.emitPush(int16(node.Value)) case reflect.Int32: if node.Value > math.MaxInt32 || node.Value < math.MinInt32 { panic(fmt.Sprintf("constant %d overflows int32", node.Value)) } c.emitPush(int32(node.Value)) case reflect.Int64: c.emitPush(int64(node.Value)) case reflect.Uint: if node.Value < 0 { panic(fmt.Sprintf("constant %d overflows uint", node.Value)) } c.emitPush(uint(node.Value)) case reflect.Uint8: if node.Value > math.MaxUint8 || node.Value < 0 { panic(fmt.Sprintf("constant %d overflows uint8", node.Value)) } c.emitPush(uint8(node.Value)) case reflect.Uint16: if node.Value > math.MaxUint16 || node.Value < 0 { panic(fmt.Sprintf("constant %d overflows uint16", node.Value)) } c.emitPush(uint16(node.Value)) case reflect.Uint32: if node.Value < 0 { panic(fmt.Sprintf("constant %d overflows uint32", node.Value)) } c.emitPush(uint32(node.Value)) case reflect.Uint64: if node.Value < 0 { panic(fmt.Sprintf("constant %d overflows uint64", node.Value)) } c.emitPush(uint64(node.Value)) default: c.emitPush(node.Value) } } func (c *compiler) FloatNode(node *ast.FloatNode) { switch node.Type().Kind() { case reflect.Float32: c.emitPush(float32(node.Value)) case reflect.Float64: c.emitPush(node.Value) default: c.emitPush(node.Value) } } func (c *compiler) BoolNode(node *ast.BoolNode) { if node.Value { c.emit(OpTrue) } else { c.emit(OpFalse) } } func (c *compiler) StringNode(node *ast.StringNode) { c.emitPush(node.Value) } func (c *compiler) BytesNode(node *ast.BytesNode) { c.emitPush(node.Value) } func (c *compiler) ConstantNode(node *ast.ConstantNode) { if node.Value == nil { c.emit(OpNil) return } c.emitPush(node.Value) } func (c *compiler) UnaryNode(node *ast.UnaryNode) { c.compile(node.Node) c.derefInNeeded(node.Node) switch node.Operator { case "!", "not": c.emit(OpNot) case "+": // Do nothing case "-": c.emit(OpNegate) default: panic(fmt.Sprintf("unknown operator (%v)", node.Operator)) } } func (c *compiler) BinaryNode(node *ast.BinaryNode) { switch node.Operator { case "==": c.equalBinaryNode(node) case "!=": c.equalBinaryNode(node) c.emit(OpNot) case "or", "||": if c.config != nil && !c.config.ShortCircuit { c.compile(node.Left) c.derefInNeeded(node.Left) c.compile(node.Right) c.derefInNeeded(node.Right) c.emit(OpOr) break } c.compile(node.Left) c.derefInNeeded(node.Left) end := c.emit(OpJumpIfTrue, placeholder) c.emit(OpPop) c.compile(node.Right) c.derefInNeeded(node.Right) c.patchJump(end) case "and", "&&": if c.config != nil && !c.config.ShortCircuit { c.compile(node.Left) c.derefInNeeded(node.Left) c.compile(node.Right) c.derefInNeeded(node.Right) c.emit(OpAnd) break } c.compile(node.Left) c.derefInNeeded(node.Left) end := c.emit(OpJumpIfFalse, placeholder) c.emit(OpPop) c.compile(node.Right) c.derefInNeeded(node.Right) c.patchJump(end) case "<": c.compile(node.Left) c.derefInNeeded(node.Left) c.compile(node.Right) c.derefInNeeded(node.Right) c.emit(OpLess) case ">": c.compile(node.Left) c.derefInNeeded(node.Left) c.compile(node.Right) c.derefInNeeded(node.Right) c.emit(OpMore) case "<=": c.compile(node.Left) c.derefInNeeded(node.Left) c.compile(node.Right) c.derefInNeeded(node.Right) c.emit(OpLessOrEqual) case ">=": c.compile(node.Left) c.derefInNeeded(node.Left) c.compile(node.Right) c.derefInNeeded(node.Right) c.emit(OpMoreOrEqual) case "+": c.compile(node.Left) c.derefInNeeded(node.Left) c.compile(node.Right) c.derefInNeeded(node.Right) c.emit(OpAdd) case "-": c.compile(node.Left) c.derefInNeeded(node.Left) c.compile(node.Right) c.derefInNeeded(node.Right) c.emit(OpSubtract) case "*": c.compile(node.Left) c.derefInNeeded(node.Left) c.compile(node.Right) c.derefInNeeded(node.Right) c.emit(OpMultiply) case "/": c.compile(node.Left) c.derefInNeeded(node.Left) c.compile(node.Right) c.derefInNeeded(node.Right) c.emit(OpDivide) case "%": c.compile(node.Left) c.derefInNeeded(node.Left) c.compile(node.Right) c.derefInNeeded(node.Right) c.emit(OpModulo) case "**", "^": c.compile(node.Left) c.derefInNeeded(node.Left) c.compile(node.Right) c.derefInNeeded(node.Right) c.emit(OpExponent) case "in": c.compile(node.Left) c.derefInNeeded(node.Left) c.compile(node.Right) c.derefInNeeded(node.Right) c.emit(OpIn) case "matches": if str, ok := node.Right.(*ast.StringNode); ok { re, err := regexp.Compile(str.Value) if err != nil { panic(err) } c.compile(node.Left) c.derefInNeeded(node.Left) c.emit(OpMatchesConst, c.addConstant(re)) } else { c.compile(node.Left) c.derefInNeeded(node.Left) c.compile(node.Right) c.derefInNeeded(node.Right) c.emit(OpMatches) } case "contains": c.compile(node.Left) c.derefInNeeded(node.Left) c.compile(node.Right) c.derefInNeeded(node.Right) c.emit(OpContains) case "startsWith": c.compile(node.Left) c.derefInNeeded(node.Left) c.compile(node.Right) c.derefInNeeded(node.Right) c.emit(OpStartsWith) case "endsWith": c.compile(node.Left) c.derefInNeeded(node.Left) c.compile(node.Right) c.derefInNeeded(node.Right) c.emit(OpEndsWith) case "..": c.compile(node.Left) c.derefInNeeded(node.Left) c.compile(node.Right) c.derefInNeeded(node.Right) c.emit(OpRange) case "??": c.compile(node.Left) c.derefInNeeded(node.Left) end := c.emit(OpJumpIfNotNil, placeholder) c.emit(OpPop) c.compile(node.Right) c.derefInNeeded(node.Right) c.patchJump(end) default: panic(fmt.Sprintf("unknown operator (%v)", node.Operator)) } } func (c *compiler) equalBinaryNode(node *ast.BinaryNode) { l := kind(node.Left.Type()) r := kind(node.Right.Type()) leftIsSimple := isSimpleType(node.Left) rightIsSimple := isSimpleType(node.Right) leftAndRightAreSimple := leftIsSimple && rightIsSimple c.compile(node.Left) c.derefInNeeded(node.Left) c.compile(node.Right) c.derefInNeeded(node.Right) if l == r && l == reflect.Int && leftAndRightAreSimple { c.emit(OpEqualInt) } else if l == r && l == reflect.String && leftAndRightAreSimple { c.emit(OpEqualString) } else { c.emit(OpEqual) } } func isSimpleType(node ast.Node) bool { if node == nil { return false } t := node.Type() if t == nil { return false } return t.PkgPath() == "" } func (c *compiler) ChainNode(node *ast.ChainNode) { c.chains = append(c.chains, []int{}) c.compile(node.Node) for _, ph := range c.chains[len(c.chains)-1] { c.patchJump(ph) // If chain activated jump here (got nit somewhere). } parent := c.nodeParent() if binary, ok := parent.(*ast.BinaryNode); ok && binary.Operator == "??" { // If chain is used in nil coalescing operator, we can omit // nil push at the end of the chain. The ?? operator will // handle it. } else { // We need to put the nil on the stack, otherwise "typed" // nil will be used as a result of the chain. j := c.emit(OpJumpIfNotNil, placeholder) c.emit(OpPop) c.emit(OpNil) c.patchJump(j) } c.chains = c.chains[:len(c.chains)-1] } func (c *compiler) MemberNode(node *ast.MemberNode) { var env Nature if c.config != nil { env = c.config.Env } if ok, index, name := checker.MethodIndex(c.ntCache, env, node); ok { c.compile(node.Node) c.emit(OpMethod, c.addConstant(&runtime.Method{ Name: name, Index: index, })) return } op := OpFetch base := node.Node ok, index, nodeName := checker.FieldIndex(c.ntCache, env, node) path := []string{nodeName} if ok { op = OpFetchField for !node.Optional { if ident, isIdent := base.(*ast.IdentifierNode); isIdent { if ok, identIndex, name := checker.FieldIndex(c.ntCache, env, ident); ok { index = append(identIndex, index...) path = append([]string{name}, path...) c.emitLocation(ident.Location(), OpLoadField, c.addConstant( &runtime.Field{Index: index, Path: path}, )) return } } if member, isMember := base.(*ast.MemberNode); isMember { if ok, memberIndex, name := checker.FieldIndex(c.ntCache, env, member); ok { index = append(memberIndex, index...) path = append([]string{name}, path...) node = member base = member.Node } else { break } } else { break } } } c.compile(base) // If the field is optional, we need to jump over the fetch operation. // If no ChainNode (none c.chains) is used, do not compile the optional fetch. if node.Optional && len(c.chains) > 0 { ph := c.emit(OpJumpIfNil, placeholder) c.chains[len(c.chains)-1] = append(c.chains[len(c.chains)-1], ph) } if op == OpFetch { c.compile(node.Property) deref := true // If the map key is a pointer, we should not dereference the property. if node.Node.Type() != nil && node.Node.Type().Kind() == reflect.Map { keyType := node.Node.Type().Key() propType := node.Property.Type() if propType != nil && propType.AssignableTo(keyType) { deref = false } } if deref { c.derefInNeeded(node.Property) } c.emit(OpFetch) } else { c.emitLocation(node.Location(), op, c.addConstant( &runtime.Field{Index: index, Path: path}, )) } } func (c *compiler) SliceNode(node *ast.SliceNode) { c.compile(node.Node) if node.To != nil { c.compile(node.To) c.derefInNeeded(node.To) } else { c.emit(OpLen) } if node.From != nil { c.compile(node.From) c.derefInNeeded(node.From) } else { c.emitPush(0) } c.emit(OpSlice) } func (c *compiler) CallNode(node *ast.CallNode) { fn := node.Callee.Type() if fn.Kind() == reflect.Func { fnInOffset := 0 fnNumIn := fn.NumIn() switch callee := node.Callee.(type) { case *ast.MemberNode: if prop, ok := callee.Property.(*ast.StringNode); ok { if _, ok = callee.Node.Type().MethodByName(prop.Value); ok && callee.Node.Type().Kind() != reflect.Interface { fnInOffset = 1 fnNumIn-- } } case *ast.IdentifierNode: if t, ok := c.config.Env.MethodByName(c.ntCache, callee.Value); ok && t.Method { fnInOffset = 1 fnNumIn-- } } for i, arg := range node.Arguments { c.compile(arg) var in reflect.Type if fn.IsVariadic() && i >= fnNumIn-1 { in = fn.In(fn.NumIn() - 1).Elem() } else { in = fn.In(i + fnInOffset) } c.derefParam(in, arg) } } else { for _, arg := range node.Arguments { c.compile(arg) } } if ident, ok := node.Callee.(*ast.IdentifierNode); ok { if c.config != nil { if fn, ok := c.config.Functions[ident.Value]; ok { c.emitFunction(fn, len(node.Arguments)) return } } } c.compile(node.Callee) if c.config != nil { isMethod, _, _ := checker.MethodIndex(c.ntCache, c.config.Env, node.Callee) if index, ok := checker.TypedFuncIndex(node.Callee.Type(), isMethod); ok { c.emit(OpCallTyped, index) return } else if checker.IsFastFunc(node.Callee.Type(), isMethod) { c.emit(OpCallFast, len(node.Arguments)) } else { c.emit(OpCall, len(node.Arguments)) } } else { c.emit(OpCall, len(node.Arguments)) } } func (c *compiler) BuiltinNode(node *ast.BuiltinNode) { switch node.Name { case "all": c.compile(node.Arguments[0]) c.derefInNeeded(node.Arguments[0]) c.emit(OpBegin) var loopBreak int c.emitLoop(func() { c.compile(node.Arguments[1]) loopBreak = c.emit(OpJumpIfFalse, placeholder) c.emit(OpPop) }) c.emit(OpTrue) c.patchJump(loopBreak) c.emit(OpEnd) return case "none": c.compile(node.Arguments[0]) c.derefInNeeded(node.Arguments[0]) c.emit(OpBegin) var loopBreak int c.emitLoop(func() { c.compile(node.Arguments[1]) c.emit(OpNot) loopBreak = c.emit(OpJumpIfFalse, placeholder) c.emit(OpPop) }) c.emit(OpTrue) c.patchJump(loopBreak) c.emit(OpEnd) return case "any": c.compile(node.Arguments[0]) c.derefInNeeded(node.Arguments[0]) c.emit(OpBegin) var loopBreak int c.emitLoop(func() { c.compile(node.Arguments[1]) loopBreak = c.emit(OpJumpIfTrue, placeholder) c.emit(OpPop) }) c.emit(OpFalse) c.patchJump(loopBreak) c.emit(OpEnd) return case "one": c.compile(node.Arguments[0]) c.derefInNeeded(node.Arguments[0]) c.emit(OpBegin) c.emitLoop(func() { c.compile(node.Arguments[1]) c.emitCond(func() { c.emit(OpIncrementCount) }) }) c.emit(OpGetCount) c.emitPush(1) c.emit(OpEqual) c.emit(OpEnd) return case "filter": c.compile(node.Arguments[0]) c.derefInNeeded(node.Arguments[0]) c.emit(OpBegin) c.emitLoop(func() { c.compile(node.Arguments[1]) c.emitCond(func() { c.emit(OpIncrementCount) if node.Map != nil { c.compile(node.Map) } else { c.emit(OpPointer) } }) }) c.emit(OpGetCount) c.emit(OpEnd) c.emit(OpArray) return case "map": c.compile(node.Arguments[0]) c.derefInNeeded(node.Arguments[0]) c.emit(OpBegin) c.emitLoop(func() { c.compile(node.Arguments[1]) }) c.emit(OpGetLen) c.emit(OpEnd) c.emit(OpArray) return case "count": c.compile(node.Arguments[0]) c.derefInNeeded(node.Arguments[0]) c.emit(OpBegin) var loopBreak int c.emitLoop(func() { if len(node.Arguments) == 2 { c.compile(node.Arguments[1]) } else { c.emit(OpPointer) } c.emitCond(func() { c.emit(OpIncrementCount) // Early termination if threshold is set if node.Threshold != nil { c.emit(OpGetCount) c.emit(OpInt, *node.Threshold) c.emit(OpMoreOrEqual) loopBreak = c.emit(OpJumpIfTrue, placeholder) c.emit(OpPop) } }) }) c.emit(OpGetCount) if node.Threshold != nil { end := c.emit(OpJump, placeholder) c.patchJump(loopBreak) // Early exit path: pop the bool comparison result, push count c.emit(OpPop) c.emit(OpGetCount) c.patchJump(end) } c.emit(OpEnd) return case "sum": c.compile(node.Arguments[0]) c.derefInNeeded(node.Arguments[0]) c.emit(OpBegin) c.emit(OpInt, 0) c.emit(OpSetAcc) c.emitLoop(func() { if len(node.Arguments) == 2 { c.compile(node.Arguments[1]) } else { c.emit(OpPointer) } c.emit(OpGetAcc) c.emit(OpAdd) c.emit(OpSetAcc) }) c.emit(OpGetAcc) c.emit(OpEnd) return case "find": c.compile(node.Arguments[0]) c.derefInNeeded(node.Arguments[0]) c.emit(OpBegin) var loopBreak int c.emitLoop(func() { c.compile(node.Arguments[1]) noop := c.emit(OpJumpIfFalse, placeholder) c.emit(OpPop) if node.Map != nil { c.compile(node.Map) } else { c.emit(OpPointer) } loopBreak = c.emit(OpJump, placeholder) c.patchJump(noop) c.emit(OpPop) }) if node.Throws { c.emit(OpPush, c.addConstant(fmt.Errorf("reflect: slice index out of range"))) c.emit(OpThrow) } else { c.emit(OpNil) } c.patchJump(loopBreak) c.emit(OpEnd) return case "findIndex": c.compile(node.Arguments[0]) c.derefInNeeded(node.Arguments[0]) c.emit(OpBegin) var loopBreak int c.emitLoop(func() { c.compile(node.Arguments[1]) noop := c.emit(OpJumpIfFalse, placeholder) c.emit(OpPop) c.emit(OpGetIndex) loopBreak = c.emit(OpJump, placeholder) c.patchJump(noop) c.emit(OpPop) }) c.emit(OpNil) c.patchJump(loopBreak) c.emit(OpEnd) return case "findLast": c.compile(node.Arguments[0]) c.derefInNeeded(node.Arguments[0]) c.emit(OpBegin) var loopBreak int c.emitLoopBackwards(func() { c.compile(node.Arguments[1]) noop := c.emit(OpJumpIfFalse, placeholder) c.emit(OpPop) if node.Map != nil { c.compile(node.Map) } else { c.emit(OpPointer) } loopBreak = c.emit(OpJump, placeholder) c.patchJump(noop) c.emit(OpPop) }) if node.Throws { c.emit(OpPush, c.addConstant(fmt.Errorf("reflect: slice index out of range"))) c.emit(OpThrow) } else { c.emit(OpNil) } c.patchJump(loopBreak) c.emit(OpEnd) return case "findLastIndex": c.compile(node.Arguments[0]) c.derefInNeeded(node.Arguments[0]) c.emit(OpBegin) var loopBreak int c.emitLoopBackwards(func() { c.compile(node.Arguments[1]) noop := c.emit(OpJumpIfFalse, placeholder) c.emit(OpPop) c.emit(OpGetIndex) loopBreak = c.emit(OpJump, placeholder) c.patchJump(noop) c.emit(OpPop) }) c.emit(OpNil) c.patchJump(loopBreak) c.emit(OpEnd) return case "groupBy": c.compile(node.Arguments[0]) c.derefInNeeded(node.Arguments[0]) c.emit(OpBegin) c.emit(OpCreate, 1) c.emit(OpSetAcc) c.emitLoop(func() { c.compile(node.Arguments[1]) c.emit(OpGroupBy) }) c.emit(OpGetAcc) c.emit(OpEnd) return case "sortBy": c.compile(node.Arguments[0]) c.derefInNeeded(node.Arguments[0]) c.emit(OpBegin) if len(node.Arguments) == 3 { c.compile(node.Arguments[2]) } else { c.emit(OpPush, c.addConstant("asc")) } c.emit(OpCreate, 2) c.emit(OpSetAcc) c.emitLoop(func() { c.compile(node.Arguments[1]) c.emit(OpSortBy) }) c.emit(OpSort) c.emit(OpEnd) return case "reduce": c.compile(node.Arguments[0]) c.derefInNeeded(node.Arguments[0]) c.emit(OpBegin) if len(node.Arguments) == 3 { c.compile(node.Arguments[2]) c.derefInNeeded(node.Arguments[2]) c.emit(OpSetAcc) } else { // When no initial value is provided, we use the first element as the // accumulator. But first we must check if the array is empty to avoid // an index out of range panic. empty := c.emit(OpJumpIfEnd, placeholder) c.emit(OpPointer) c.emit(OpIncrementIndex) c.emit(OpSetAcc) jumpPastError := c.emit(OpJump, placeholder) c.patchJump(empty) c.emit(OpPush, c.addConstant(fmt.Errorf("reduce of empty array with no initial value"))) c.emit(OpThrow) c.patchJump(jumpPastError) } c.emitLoop(func() { c.compile(node.Arguments[1]) c.emit(OpSetAcc) }) c.emit(OpGetAcc) c.emit(OpEnd) return } if id, ok := builtin.Index[node.Name]; ok { f := builtin.Builtins[id] for i, arg := range node.Arguments { c.compile(arg) argType := arg.Type() if argType.Kind() == reflect.Ptr || arg.Nature().IsUnknown(c.ntCache) { if f.Deref == nil { // By default, builtins expect arguments to be dereferenced. c.emit(OpDeref) } else { if f.Deref(i, argType) { c.emit(OpDeref) } } } } if f.Fast != nil { c.emit(OpCallBuiltin1, id) } else if f.Safe != nil { id := c.addConstant(f.Safe) c.emit(OpPush, id) c.debugInfo[fmt.Sprintf("const_%d", id)] = node.Name c.emit(OpCallSafe, len(node.Arguments)) } else if f.Func != nil { c.emitFunction(f, len(node.Arguments)) } return } panic(fmt.Sprintf("unknown builtin %v", node.Name)) } func (c *compiler) emitCond(body func()) { noop := c.emit(OpJumpIfFalse, placeholder) c.emit(OpPop) body() jmp := c.emit(OpJump, placeholder) c.patchJump(noop) c.emit(OpPop) c.patchJump(jmp) } func (c *compiler) emitLoop(body func()) { begin := len(c.bytecode) end := c.emit(OpJumpIfEnd, placeholder) body() c.emit(OpIncrementIndex) c.emit(OpJumpBackward, c.calcBackwardJump(begin)) c.patchJump(end) } func (c *compiler) emitLoopBackwards(body func()) { c.emit(OpGetLen) c.emit(OpInt, 1) c.emit(OpSubtract) c.emit(OpSetIndex) begin := len(c.bytecode) c.emit(OpGetIndex) c.emit(OpInt, 0) c.emit(OpMoreOrEqual) end := c.emit(OpJumpIfFalse, placeholder) body() c.emit(OpDecrementIndex) c.emit(OpJumpBackward, c.calcBackwardJump(begin)) c.patchJump(end) } func (c *compiler) PredicateNode(node *ast.PredicateNode) { c.compile(node.Node) } func (c *compiler) PointerNode(node *ast.PointerNode) { switch node.Name { case "index": c.emit(OpGetIndex) case "acc": c.emit(OpGetAcc) case "": c.emit(OpPointer) default: panic(fmt.Sprintf("unknown pointer %v", node.Name)) } } func (c *compiler) VariableDeclaratorNode(node *ast.VariableDeclaratorNode) { c.compile(node.Value) index := c.addVariable(node.Name) c.emit(OpStore, index) c.beginScope(node.Name, index) c.compile(node.Expr) c.endScope() } func (c *compiler) SequenceNode(node *ast.SequenceNode) { for i, n := range node.Nodes { c.compile(n) if i < len(node.Nodes)-1 { c.emit(OpPop) } } } func (c *compiler) beginScope(name string, index int) { c.scopes = append(c.scopes, scope{name, index}) } func (c *compiler) endScope() { c.scopes = c.scopes[:len(c.scopes)-1] } func (c *compiler) lookupVariable(name string) (int, bool) { for i := len(c.scopes) - 1; i >= 0; i-- { if c.scopes[i].variableName == name { return c.scopes[i].index, true } } return 0, false } func (c *compiler) ConditionalNode(node *ast.ConditionalNode) { c.compile(node.Cond) c.derefInNeeded(node.Cond) otherwise := c.emit(OpJumpIfFalse, placeholder) c.emit(OpPop) c.compile(node.Exp1) end := c.emit(OpJump, placeholder) c.patchJump(otherwise) c.emit(OpPop) c.compile(node.Exp2) c.patchJump(end) } func (c *compiler) ArrayNode(node *ast.ArrayNode) { for _, node := range node.Nodes { c.compile(node) } c.emitPush(len(node.Nodes)) c.emit(OpArray) } func (c *compiler) MapNode(node *ast.MapNode) { for _, pair := range node.Pairs { c.compile(pair) } c.emitPush(len(node.Pairs)) c.emit(OpMap) } func (c *compiler) PairNode(node *ast.PairNode) { c.compile(node.Key) c.compile(node.Value) } func (c *compiler) derefInNeeded(node ast.Node) { if node.Nature().Nil { return } switch node.Type().Kind() { case reflect.Ptr, reflect.Interface: c.emit(OpDeref) } } func (c *compiler) derefParam(in reflect.Type, param ast.Node) { if param.Nature().Nil { return } if param.Type().AssignableTo(in) { return } if in.Kind() != reflect.Ptr && param.Type().Kind() == reflect.Ptr { c.emit(OpDeref) } } func (c *compiler) optimize() { for i, op := range c.bytecode { switch op { case OpJumpIfTrue, OpJumpIfFalse, OpJumpIfNil, OpJumpIfNotNil: target := i + c.arguments[i] + 1 for target < len(c.bytecode) && c.bytecode[target] == op { target += c.arguments[target] + 1 } c.arguments[i] = target - i - 1 } } } func kind(t reflect.Type) reflect.Kind { if t == nil { return reflect.Invalid } return t.Kind() } ================================================ FILE: compiler/compiler_test.go ================================================ package compiler_test import ( "math" "reflect" "testing" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr" "github.com/expr-lang/expr/test/mock" "github.com/expr-lang/expr/test/playground" "github.com/expr-lang/expr/vm" "github.com/expr-lang/expr/vm/runtime" ) type B struct { _ byte _ byte C struct { _ byte _ byte _ byte D int } } func (B) FuncInB() int { return 0 } type Env struct { A struct { _ byte B B Map map[string]B Ptr *int } } // AFunc is a method what goes before Func in the alphabet. func (e Env) AFunc() int { return 0 } func (e Env) Func() B { return B{} } func TestCompile(t *testing.T) { var tests = []struct { code string want vm.Program }{ { `65535`, vm.Program{ Constants: []any{ math.MaxUint16, }, Bytecode: []vm.Opcode{ vm.OpPush, }, Arguments: []int{0}, }, }, { `.5`, vm.Program{ Constants: []any{ .5, }, Bytecode: []vm.Opcode{ vm.OpPush, }, Arguments: []int{0}, }, }, { `true`, vm.Program{ Bytecode: []vm.Opcode{ vm.OpTrue, }, Arguments: []int{0}, }, }, { `"string"`, vm.Program{ Constants: []any{ "string", }, Bytecode: []vm.Opcode{ vm.OpPush, }, Arguments: []int{0}, }, }, { `"string" == "string"`, vm.Program{ Constants: []any{ "string", }, Bytecode: []vm.Opcode{ vm.OpPush, vm.OpPush, vm.OpEqualString, }, Arguments: []int{0, 0, 0}, }, }, { `1000000 == 1000000`, vm.Program{ Constants: []any{ int64(1000000), }, Bytecode: []vm.Opcode{ vm.OpPush, vm.OpPush, vm.OpEqualInt, }, Arguments: []int{0, 0, 0}, }, }, { `-1`, vm.Program{ Constants: []any{1}, Bytecode: []vm.Opcode{ vm.OpPush, vm.OpNegate, }, Arguments: []int{0, 0}, }, }, { `true && true || true`, vm.Program{ Bytecode: []vm.Opcode{ vm.OpTrue, vm.OpJumpIfFalse, vm.OpPop, vm.OpTrue, vm.OpJumpIfTrue, vm.OpPop, vm.OpTrue, }, Arguments: []int{0, 2, 0, 0, 2, 0, 0}, }, }, { `true && (true || true)`, vm.Program{ Bytecode: []vm.Opcode{ vm.OpTrue, vm.OpJumpIfFalse, vm.OpPop, vm.OpTrue, vm.OpJumpIfTrue, vm.OpPop, vm.OpTrue, }, Arguments: []int{0, 5, 0, 0, 2, 0, 0}, }, }, { `A.B.C.D`, vm.Program{ Constants: []any{ &runtime.Field{ Index: []int{0, 1, 2, 3}, Path: []string{"A", "B", "C", "D"}, }, }, Bytecode: []vm.Opcode{ vm.OpLoadField, }, Arguments: []int{0}, }, }, { `A?.B.C.D`, vm.Program{ Constants: []any{ &runtime.Field{ Index: []int{0}, Path: []string{"A"}, }, &runtime.Field{ Index: []int{1, 2, 3}, Path: []string{"B", "C", "D"}, }, }, Bytecode: []vm.Opcode{ vm.OpLoadField, vm.OpJumpIfNil, vm.OpFetchField, vm.OpJumpIfNotNil, vm.OpPop, vm.OpNil, }, Arguments: []int{0, 1, 1, 2, 0, 0}, }, }, { `A.B?.C.D`, vm.Program{ Constants: []any{ &runtime.Field{ Index: []int{0, 1}, Path: []string{"A", "B"}, }, &runtime.Field{ Index: []int{2, 3}, Path: []string{"C", "D"}, }, }, Bytecode: []vm.Opcode{ vm.OpLoadField, vm.OpJumpIfNil, vm.OpFetchField, vm.OpJumpIfNotNil, vm.OpPop, vm.OpNil, }, Arguments: []int{0, 1, 1, 2, 0, 0}, }, }, { `A?.B`, vm.Program{ Constants: []any{ &runtime.Field{ Index: []int{0}, Path: []string{"A"}, }, &runtime.Field{ Index: []int{1}, Path: []string{"B"}, }, }, Bytecode: []vm.Opcode{ vm.OpLoadField, vm.OpJumpIfNil, vm.OpFetchField, vm.OpJumpIfNotNil, vm.OpPop, vm.OpNil, }, Arguments: []int{0, 1, 1, 2, 0, 0}, }, }, { `A?.B ?? 42`, vm.Program{ Constants: []any{ &runtime.Field{ Index: []int{0}, Path: []string{"A"}, }, &runtime.Field{ Index: []int{1}, Path: []string{"B"}, }, 42, }, Bytecode: []vm.Opcode{ vm.OpLoadField, vm.OpJumpIfNil, vm.OpFetchField, vm.OpJumpIfNotNil, vm.OpPop, vm.OpPush, }, Arguments: []int{0, 1, 1, 2, 0, 2}, }, }, { `A.Map["B"].C.D`, vm.Program{ Constants: []any{ &runtime.Field{ Index: []int{0, 2}, Path: []string{"A", "Map"}, }, "B", &runtime.Field{ Index: []int{2, 3}, Path: []string{"C", "D"}, }, }, Bytecode: []vm.Opcode{ vm.OpLoadField, vm.OpPush, vm.OpFetch, vm.OpFetchField, }, Arguments: []int{0, 1, 0, 2}, }, }, { `A ?? 1`, vm.Program{ Constants: []any{ &runtime.Field{ Index: []int{0}, Path: []string{"A"}, }, 1, }, Bytecode: []vm.Opcode{ vm.OpLoadField, vm.OpJumpIfNotNil, vm.OpPop, vm.OpPush, }, Arguments: []int{0, 2, 0, 1}, }, }, { `A.Ptr + 1`, vm.Program{ Constants: []any{ &runtime.Field{ Index: []int{0, 3}, Path: []string{"A", "Ptr"}, }, 1, }, Bytecode: []vm.Opcode{ vm.OpLoadField, vm.OpDeref, vm.OpPush, vm.OpAdd, }, Arguments: []int{0, 0, 1, 0}, }, }, { `Func()`, vm.Program{ Constants: []any{ &runtime.Method{ Index: 1, Name: "Func", }, }, Bytecode: []vm.Opcode{ vm.OpLoadMethod, vm.OpCall, }, Arguments: []int{0, 0}, }, }, { `Func().FuncInB()`, vm.Program{ Constants: []any{ &runtime.Method{ Index: 1, Name: "Func", }, &runtime.Method{ Index: 0, Name: "FuncInB", }, }, Bytecode: []vm.Opcode{ vm.OpLoadMethod, vm.OpCall, vm.OpMethod, vm.OpCallTyped, }, Arguments: []int{0, 0, 1, 12}, }, }, { `1; 2; 3`, vm.Program{ Constants: []any{ 1, 2, 3, }, Bytecode: []vm.Opcode{ vm.OpPush, vm.OpPop, vm.OpPush, vm.OpPop, vm.OpPush, }, Arguments: []int{0, 0, 1, 0, 2}, }, }, } for _, test := range tests { t.Run(test.code, func(t *testing.T) { program, err := expr.Compile(test.code, expr.Env(Env{}), expr.Optimize(false)) require.NoError(t, err) assert.Equal(t, test.want.Disassemble(), program.Disassemble()) }) } } func TestCompile_panic(t *testing.T) { tests := []string{ `(TotalPosts.Profile[Authors > TotalPosts == get(nil, TotalLikes)] > Authors) ^ (TotalLikes / (Posts?.PublishDate[TotalPosts] < Posts))`, `one(Posts, nil)`, `trim(TotalViews, Posts) <= get(Authors, nil)`, `Authors.IsZero(nil * Authors) - (TotalViews && Posts ? nil : nil)[TotalViews.IsZero(false, " ").IsZero(Authors)]`, } for _, test := range tests { t.Run(test, func(t *testing.T) { _, err := expr.Compile(test, expr.Env(playground.Blog{})) require.Error(t, err) }) } } func TestCompile_FuncTypes(t *testing.T) { env := map[string]any{ "fn": func([]any, string) string { return "foo" }, } program, err := expr.Compile("fn([1, 2], 'bar')", expr.Env(env)) require.NoError(t, err) require.Equal(t, vm.OpCallTyped, program.Bytecode[3]) require.Equal(t, 32, program.Arguments[3]) } func TestCompile_FuncTypes_with_Method(t *testing.T) { env := mock.Env{} program, err := expr.Compile("FuncTyped('bar')", expr.Env(env)) require.NoError(t, err) require.Equal(t, vm.OpCallTyped, program.Bytecode[2]) require.Equal(t, 76, program.Arguments[2]) } func TestCompile_FuncTypes_excludes_named_functions(t *testing.T) { env := mock.Env{} program, err := expr.Compile("FuncNamed('bar')", expr.Env(env)) require.NoError(t, err) require.Equal(t, vm.OpCall, program.Bytecode[2]) require.Equal(t, 1, program.Arguments[2]) } func TestCompile_OpCallFast(t *testing.T) { env := mock.Env{} program, err := expr.Compile("Fast(3, 2, 1)", expr.Env(env)) require.NoError(t, err) require.Equal(t, vm.OpCallFast, program.Bytecode[4]) require.Equal(t, 3, program.Arguments[4]) } func TestCompile_optimizes_jumps(t *testing.T) { env := map[string]any{ "a": true, "b": true, "c": true, "d": true, "i64": int64(1), } tests := []struct { code string want string }{ { `let foo = true; let bar = false; let baz = true; foo || bar || baz`, `0 OpTrue 1 OpStore <0> foo 2 OpFalse 3 OpStore <1> bar 4 OpTrue 5 OpStore <2> baz 6 OpLoadVar <0> foo 7 OpJumpIfTrue <5> (13) 8 OpPop 9 OpLoadVar <1> bar 10 OpJumpIfTrue <2> (13) 11 OpPop 12 OpLoadVar <2> baz `, }, { `a && b && c`, `0 OpLoadFast <0> a 1 OpJumpIfFalse <5> (7) 2 OpPop 3 OpLoadFast <1> b 4 OpJumpIfFalse <2> (7) 5 OpPop 6 OpLoadFast <2> c `, }, { `a && b || c && d`, `0 OpLoadFast <0> a 1 OpJumpIfFalse <2> (4) 2 OpPop 3 OpLoadFast <1> b 4 OpJumpIfTrue <5> (10) 5 OpPop 6 OpLoadFast <2> c 7 OpJumpIfFalse <2> (10) 8 OpPop 9 OpLoadFast <3> d `, }, { `filter([1, 2, 3, 4, 5], # > 3 && # != 4 && # != 5)`, `0 OpPush <0> [1 2 3 4 5] 1 OpBegin 2 OpJumpIfEnd <23> (26) 3 OpPointer 4 OpPush <1> 3 5 OpMore 6 OpJumpIfFalse <16> (23) 7 OpPop 8 OpPointer 9 OpPush <2> 4 10 OpEqualInt 11 OpNot 12 OpJumpIfFalse <10> (23) 13 OpPop 14 OpPointer 15 OpPush <3> 5 16 OpEqualInt 17 OpNot 18 OpJumpIfFalse <4> (23) 19 OpPop 20 OpIncrementCount 21 OpPointer 22 OpJump <1> (24) 23 OpPop 24 OpIncrementIndex 25 OpJumpBackward <24> (2) 26 OpGetCount 27 OpEnd 28 OpArray `, }, { `let foo = true; let bar = false; let baz = true; foo && bar || baz`, `0 OpTrue 1 OpStore <0> foo 2 OpFalse 3 OpStore <1> bar 4 OpTrue 5 OpStore <2> baz 6 OpLoadVar <0> foo 7 OpJumpIfFalse <2> (10) 8 OpPop 9 OpLoadVar <1> bar 10 OpJumpIfTrue <2> (13) 11 OpPop 12 OpLoadVar <2> baz `, }, { `true ?? nil ?? nil ?? nil`, `0 OpTrue 1 OpJumpIfNotNil <8> (10) 2 OpPop 3 OpNil 4 OpJumpIfNotNil <5> (10) 5 OpPop 6 OpNil 7 OpJumpIfNotNil <2> (10) 8 OpPop 9 OpNil `, }, { `let m = {"a": {"b": {"c": 1}}}; m?.a?.b?.c`, `0 OpPush <0> a 1 OpPush <1> b 2 OpPush <2> c 3 OpPush <3> 1 4 OpPush <3> 1 5 OpMap 6 OpPush <3> 1 7 OpMap 8 OpPush <3> 1 9 OpMap 10 OpStore <0> m 11 OpLoadVar <0> m 12 OpJumpIfNil <8> (21) 13 OpPush <0> a 14 OpFetch 15 OpJumpIfNil <5> (21) 16 OpPush <1> b 17 OpFetch 18 OpJumpIfNil <2> (21) 19 OpPush <2> c 20 OpFetch 21 OpJumpIfNotNil <2> (24) 22 OpPop 23 OpNil `, }, { `-1 not in [1, 2, 5]`, `0 OpPush <0> -1 1 OpPush <1> map[1:{} 2:{} 5:{}] 2 OpIn 3 OpNot `, }, { `1 + 8 not in [1, 2, 5]`, `0 OpPush <0> 9 1 OpPush <1> map[1:{} 2:{} 5:{}] 2 OpIn 3 OpNot `, }, { `true ? false : 8 not in [1, 2, 5]`, `0 OpTrue 1 OpJumpIfFalse <3> (5) 2 OpPop 3 OpFalse 4 OpJump <5> (10) 5 OpPop 6 OpPush <0> 8 7 OpPush <1> map[1:{} 2:{} 5:{}] 8 OpIn 9 OpNot `, }, } for _, test := range tests { t.Run(test.code, func(t *testing.T) { program, err := expr.Compile(test.code, expr.Env(env)) require.NoError(t, err) require.Equal(t, test.want, program.Disassemble()) }) } } func TestCompile_IntegerArgsFunc(t *testing.T) { env := mock.Env{} tests := []struct{ code string }{ {"FuncInt(0)"}, {"FuncInt8(0)"}, {"FuncInt16(0)"}, {"FuncInt32(0)"}, {"FuncInt64(0)"}, {"FuncUint(0)"}, {"FuncUint8(0)"}, {"FuncUint16(0)"}, {"FuncUint32(0)"}, {"FuncUint64(0)"}, } for _, tt := range tests { t.Run(tt.code, func(t *testing.T) { _, err := expr.Compile(tt.code, expr.Env(env)) require.NoError(t, err) }) } } func TestCompile_call_on_nil(t *testing.T) { env := map[string]any{ "foo": nil, } _, err := expr.Compile(`foo()`, expr.Env(env)) require.Error(t, err) require.Contains(t, err.Error(), "foo is nil; cannot call nil as function") } func TestCompile_Expect(t *testing.T) { tests := []struct { input string option expr.Option op vm.Opcode arg int }{ { input: "1", option: expr.AsKind(reflect.Int), op: vm.OpCast, arg: 0, }, { input: "1", option: expr.AsInt64(), op: vm.OpCast, arg: 1, }, { input: "1", option: expr.AsFloat64(), op: vm.OpCast, arg: 2, }, { input: "true", option: expr.AsBool(), op: vm.OpCast, arg: 3, }, } for _, tt := range tests { t.Run(tt.input, func(t *testing.T) { program, err := expr.Compile(tt.input, tt.option) require.NoError(t, err) lastOp := program.Bytecode[len(program.Bytecode)-1] lastArg := program.Arguments[len(program.Arguments)-1] assert.Equal(t, tt.op, lastOp) assert.Equal(t, tt.arg, lastArg) }) } } ================================================ FILE: conf/config.go ================================================ package conf import ( "fmt" "reflect" "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/builtin" "github.com/expr-lang/expr/checker/nature" "github.com/expr-lang/expr/vm/runtime" ) var ( // DefaultMemoryBudget represents default maximum allowed memory usage by the vm.VM. DefaultMemoryBudget uint = 1e6 // DefaultMaxNodes represents default maximum allowed AST nodes by the compiler. DefaultMaxNodes uint = 1e4 ) type FunctionsTable map[string]*builtin.Function type Config struct { EnvObject any Env nature.Nature Expect reflect.Kind ExpectAny bool Optimize bool Strict bool ShortCircuit bool Profile bool MaxNodes uint ConstFns map[string]reflect.Value Visitors []ast.Visitor Functions FunctionsTable Builtins FunctionsTable Disabled map[string]bool // disabled builtins NtCache nature.Cache // DisableIfOperator disables the built-in `if ... { } else { }` operator syntax // so that users can use a custom function named `if(...)` without conflicts. // When enabled, the lexer treats `if`/`else` as identifiers and the parser // will not parse `if` statements. DisableIfOperator bool } // CreateNew creates new config with default values. func CreateNew() *Config { c := &Config{ Optimize: true, ShortCircuit: true, MaxNodes: DefaultMaxNodes, ConstFns: make(map[string]reflect.Value), Functions: make(map[string]*builtin.Function), Builtins: make(map[string]*builtin.Function), Disabled: make(map[string]bool), } for _, f := range builtin.Builtins { c.Builtins[f.Name] = f } return c } // New creates new config with environment. func New(env any) *Config { c := CreateNew() c.WithEnv(env) return c } func (c *Config) WithEnv(env any) { c.EnvObject = env c.Env = EnvWithCache(&c.NtCache, env) c.Strict = c.Env.Strict } func (c *Config) ConstExpr(name string) { if c.EnvObject == nil { panic("no environment is specified for ConstExpr()") } fn := reflect.ValueOf(runtime.Fetch(c.EnvObject, name)) if fn.Kind() != reflect.Func { panic(fmt.Errorf("const expression %q must be a function", name)) } c.ConstFns[name] = fn } type Checker interface { Check() } func (c *Config) Check() { for _, v := range c.Visitors { if c, ok := v.(Checker); ok { c.Check() } } } func (c *Config) IsOverridden(name string) bool { if _, ok := c.Functions[name]; ok { return true } if _, ok := c.Env.Get(&c.NtCache, name); ok { return true } return false } ================================================ FILE: conf/env.go ================================================ package conf import ( "fmt" "reflect" . "github.com/expr-lang/expr/checker/nature" "github.com/expr-lang/expr/internal/deref" "github.com/expr-lang/expr/types" ) // Env returns the Nature of the given environment. // // Deprecated: use EnvWithCache instead. func Env(env any) Nature { return EnvWithCache(new(Cache), env) } func EnvWithCache(c *Cache, env any) Nature { if env == nil { n := c.NatureOf(map[string]any{}) n.Strict = true return n } switch env := env.(type) { case types.Map: nt := env.Nature() return nt } v := reflect.ValueOf(env) t := v.Type() switch deref.Value(v).Kind() { case reflect.Struct: n := c.FromType(t) n.Strict = true return n case reflect.Map: n := c.FromType(v.Type()) if n.TypeData == nil { n.TypeData = new(TypeData) } n.Strict = true n.Fields = make(map[string]Nature, v.Len()) for _, key := range v.MapKeys() { elem := v.MapIndex(key) if !elem.IsValid() || !elem.CanInterface() { panic(fmt.Sprintf("invalid map value: %s", key)) } face := elem.Interface() switch face := face.(type) { case types.Map: nt := face.Nature() n.Fields[key.String()] = nt default: if face == nil { n.Fields[key.String()] = c.NatureOf(nil) continue } n.Fields[key.String()] = c.NatureOf(face) } } return n } panic(fmt.Sprintf("unknown type %T", env)) } ================================================ FILE: debug/debugger.go ================================================ package debug import ( "fmt" "os" "strconv" "strings" "time" "github.com/gdamore/tcell/v2" "github.com/rivo/tview" . "github.com/expr-lang/expr/vm" ) func StartDebugger(program *Program, env any) { vm := Debug() app := tview.NewApplication() table := tview.NewTable() stack := tview.NewTable() stack. SetBorder(true). SetTitle("Stack") scope := tview.NewTable() scope. SetBorder(true). SetTitle("Scope") sub := tview.NewFlex(). SetDirection(tview.FlexRow). AddItem(stack, 0, 3, false). AddItem(scope, 0, 1, false) flex := tview.NewFlex(). AddItem(table, 0, 1, true). AddItem(sub, 0, 1, false) app.SetRoot(flex, true) done := false go func() { out, err := vm.Run(program, env) done = true app.QueueUpdateDraw(func() { sub.RemoveItem(stack) sub.RemoveItem(scope) result := tview.NewTextView() result. SetBorder(true). SetTitle("Output") result.SetText(fmt.Sprintf("%#v", out)) sub.AddItem(result, 0, 1, false) if err != nil { errorView := tview.NewTextView() errorView. SetBorder(true). SetTitle("Error") errorView.SetText(err.Error()) sub.AddItem(errorView, 0, 1, false) } }) }() index := make(map[int]int) var buf strings.Builder program.DisassembleWriter(&buf) for row, line := range strings.Split(buf.String(), "\n") { if line == "" { continue } parts := strings.Split(line, "\t") ip, err := strconv.Atoi(parts[0]) check(err) index[ip] = row table.SetCellSimple(row, 0, fmt.Sprintf("% *d", 5, ip)) for col := 1; col < len(parts); col++ { table.SetCellSimple(row, col, parts[col]) } for col := len(parts); col < 4; col++ { table.SetCellSimple(row, col, "") } table.SetCell(row, 4, tview.NewTableCell("").SetExpansion(1)) } draw := func(ip int) { app.QueueUpdateDraw(func() { for row := 0; row < table.GetRowCount(); row++ { for col := 0; col < table.GetColumnCount(); col++ { table.GetCell(row, col).SetBackgroundColor(tcell.ColorBlack) } } if row, ok := index[ip]; ok { table.Select(row, 0) for col := 0; col < 5; col++ { table.GetCell(row, col).SetBackgroundColor(tcell.ColorMediumBlue) } table.SetOffset(row-10, 0) opcode := table.GetCell(row, 1).Text if strings.HasPrefix(opcode, "OpJump") { jump := table.GetCell(row, 3).Text jump = strings.Trim(jump, "()") ip, err := strconv.Atoi(jump) if err == nil { if row, ok := index[ip]; ok { for col := 0; col < 5; col++ { table.GetCell(row, col).SetBackgroundColor(tcell.ColorDimGrey) } } } } } stack.Clear() for i, value := range vm.Stack { stack.SetCellSimple(i, 0, fmt.Sprintf("% *d: ", 2, i)) stack.SetCellSimple(i, 1, fmt.Sprintf("%#v", value)) } stack.ScrollToEnd() scope.Clear() var s *Scope if len(vm.Scopes) > 0 { s = vm.Scopes[len(vm.Scopes)-1] } if s != nil { type pair struct { key string value any } var keys []pair keys = append(keys, pair{"Array", s.Array}) keys = append(keys, pair{"Index", s.Index}) keys = append(keys, pair{"Len", s.Len}) keys = append(keys, pair{"Count", s.Count}) if s.Acc != nil { keys = append(keys, pair{"Acc", s.Acc}) } row := 0 for _, pair := range keys { scope.SetCellSimple(row, 0, fmt.Sprintf("%v: ", pair.key)) scope.SetCellSimple(row, 1, fmt.Sprintf("%v", pair.value)) row++ } } }) } getSelectedPosition := func() int { row, _ := table.GetSelection() ip, err := strconv.Atoi(strings.TrimSpace(table.GetCell(row, 0).Text)) check(err) return ip } autostep := false var breakpoint int go func() { draw(0) for ip := range vm.Position() { draw(ip) if autostep { if breakpoint != ip { time.Sleep(20 * time.Millisecond) if !done { vm.Step() } } else { autostep = false } } } }() app.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { if event.Key() == tcell.KeyDown || event.Key() == tcell.KeyUp { table.SetSelectable(true, false) } if event.Key() == tcell.KeyEnter { selectable, _ := table.GetSelectable() if selectable { table.SetSelectable(false, false) breakpoint = getSelectedPosition() autostep = true } if !done { vm.Step() } } return event }) err := app.Run() check(err) } func check(err error) { if err != nil { _, _ = fmt.Fprintf(os.Stderr, "%v\n", err) os.Exit(1) } } ================================================ FILE: debug/go.mod ================================================ module github.com/expr-lang/expr/debug go 1.18 require ( github.com/expr-lang/expr v0.0.0 github.com/gdamore/tcell/v2 v2.6.0 github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703 ) require ( github.com/gdamore/encoding v1.0.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/rivo/uniseg v0.4.4 // indirect golang.org/x/sys v0.11.0 // indirect golang.org/x/term v0.11.0 // indirect golang.org/x/text v0.12.0 // indirect ) replace github.com/expr-lang/expr => ../ ================================================ FILE: debug/go.sum ================================================ github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= github.com/gdamore/tcell/v2 v2.6.0 h1:OKbluoP9VYmJwZwq/iLb4BxwKcwGthaa1YNBJIyCySg= github.com/gdamore/tcell/v2 v2.6.0/go.mod h1:be9omFATkdr0D9qewWW3d+MEvl5dha+Etb5y65J2H8Y= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703 h1:ZyM/+FYnpbZsFWuCohniM56kRoHRB4r5EuIzXEYkpxo= github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703/go.mod h1:nVwGv4MP47T0jvlk7KuTTjjuSmrGO4JF0iaiNt4bufE= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= ================================================ FILE: docgen/README.md ================================================ # DocGen This package provides documentation generator with JSON or Markdown output. ## Usage Create a file and put next code into it. ```go package main import ( "encoding/json" "fmt" "github.com/expr-lang/expr/docgen" ) func main() { // TODO: Replace env with your own types. doc := docgen.CreateDoc(env) buf, err := json.MarshalIndent(doc, "", " ") if err != nil { panic(err) } fmt.Println(string(buf)) } ``` Run `go run your_file.go`. Documentation will be printed in JSON format. ## Markdown To generate markdown documentation: ```go package main import "github.com/expr-lang/expr/docgen" func main() { // TODO: Replace env with your own types. doc := docgen.CreateDoc(env) print(doc.Markdown()) } ``` ================================================ FILE: docgen/docgen.go ================================================ package docgen import ( "reflect" "regexp" "strings" "github.com/expr-lang/expr/checker/nature" "github.com/expr-lang/expr/conf" "github.com/expr-lang/expr/internal/deref" ) // Kind can be any of array, map, struct, func, string, int, float, bool or any. type Kind string // Identifier represents variable names and field names. type Identifier string // TypeName is a name of type in types map. type TypeName string type Context struct { Variables map[Identifier]*Type `json:"variables"` Types map[TypeName]*Type `json:"types"` PkgPath string } type Type struct { Name TypeName `json:"name,omitempty"` Kind Kind `json:"kind,omitempty"` Type *Type `json:"type,omitempty"` Key *Type `json:"key_type,omitempty"` Fields map[Identifier]*Type `json:"fields,omitempty"` Arguments []*Type `json:"arguments,omitempty"` Return *Type `json:"return,omitempty"` } var ( Operators = []string{"matches", "contains", "startsWith", "endsWith"} Builtins = map[Identifier]*Type{ "true": {Kind: "bool"}, "false": {Kind: "bool"}, "len": {Kind: "func", Arguments: []*Type{{Kind: "array", Type: &Type{Kind: "any"}}}, Return: &Type{Kind: "int"}}, "all": {Kind: "func", Arguments: []*Type{{Kind: "array", Type: &Type{Kind: "any"}}, {Kind: "func"}}, Return: &Type{Kind: "bool"}}, "none": {Kind: "func", Arguments: []*Type{{Kind: "array", Type: &Type{Kind: "any"}}, {Kind: "func"}}, Return: &Type{Kind: "bool"}}, "any": {Kind: "func", Arguments: []*Type{{Kind: "array", Type: &Type{Kind: "any"}}, {Kind: "func"}}, Return: &Type{Kind: "bool"}}, "one": {Kind: "func", Arguments: []*Type{{Kind: "array", Type: &Type{Kind: "any"}}, {Kind: "func"}}, Return: &Type{Kind: "bool"}}, "filter": {Kind: "func", Arguments: []*Type{{Kind: "array", Type: &Type{Kind: "any"}}, {Kind: "func"}}, Return: &Type{Kind: "array", Type: &Type{Kind: "any"}}}, "map": {Kind: "func", Arguments: []*Type{{Kind: "array", Type: &Type{Kind: "any"}}, {Kind: "func"}}, Return: &Type{Kind: "array", Type: &Type{Kind: "any"}}}, "count": {Kind: "func", Arguments: []*Type{{Kind: "array", Type: &Type{Kind: "any"}}, {Kind: "func"}}, Return: &Type{Kind: "int"}}, "trim": {Kind: "func", Arguments: []*Type{{Name: "string", Kind: "string"}, {Name: "cutstr", Kind: "string"}}, Return: &Type{Name: "string", Kind: "string"}}, "trimPrefix": {Kind: "func", Arguments: []*Type{{Name: "string", Kind: "string"}, {Name: "cutstr", Kind: "string"}}, Return: &Type{Name: "string", Kind: "string"}}, "trimSuffix": {Kind: "func", Arguments: []*Type{{Name: "string", Kind: "string"}, {Name: "cutstr", Kind: "string"}}, Return: &Type{Name: "string", Kind: "string"}}, "upper": {Kind: "func", Arguments: []*Type{{Name: "string", Kind: "string"}}, Return: &Type{Name: "string", Kind: "string"}}, "lower": {Kind: "func", Arguments: []*Type{{Name: "string", Kind: "string"}}, Return: &Type{Name: "string", Kind: "string"}}, "repeat": {Kind: "func", Arguments: []*Type{{Name: "n", Kind: "int"}}, Return: &Type{Name: "string", Kind: "string"}}, "join": {Kind: "func", Arguments: []*Type{{Kind: "array", Type: &Type{Kind: "any"}}, {Name: "glue", Kind: "string"}}, Return: &Type{Name: "string", Kind: "string"}}, "indexOf": {Kind: "func", Arguments: []*Type{{Name: "string", Kind: "string"}, {Name: "substr", Kind: "string"}}, Return: &Type{Name: "index", Kind: "int"}}, "lastIndexOf": {Kind: "func", Arguments: []*Type{{Name: "string", Kind: "string"}, {Name: "substr", Kind: "string"}}, Return: &Type{Name: "index", Kind: "int"}}, "hasPrefix": {Kind: "func", Arguments: []*Type{{Name: "string", Kind: "string"}, {Name: "prefix", Kind: "string"}}, Return: &Type{Kind: "bool"}}, "hasSuffix": {Kind: "func", Arguments: []*Type{{Name: "string", Kind: "string"}, {Name: "prefix", Kind: "string"}}, Return: &Type{Kind: "bool"}}, "toJSON": {Kind: "func", Arguments: []*Type{{Kind: "any"}}, Return: &Type{Kind: "string"}}, "fromJSON": {Kind: "func", Arguments: []*Type{{Kind: "string"}}, Return: &Type{Kind: "any"}}, "toBase64": {Kind: "func", Arguments: []*Type{{Kind: "string"}}, Return: &Type{Kind: "string"}}, "fromBase64": {Kind: "func", Arguments: []*Type{{Kind: "string"}}, Return: &Type{Kind: "string"}}, "first": {Kind: "func", Arguments: []*Type{{Kind: "array", Type: &Type{Kind: "any"}}}, Return: &Type{Kind: "any"}}, "last": {Kind: "func", Arguments: []*Type{{Kind: "array", Type: &Type{Kind: "any"}}}, Return: &Type{Kind: "any"}}, "now": {Kind: "func", Return: &Type{Name: "time.Time", Kind: "struct"}}, "duration": {Kind: "func", Arguments: []*Type{{Kind: "string"}}, Return: &Type{Kind: "time.Duration"}}, } ) func CreateDoc(i any) *Context { c := &Context{ Variables: make(map[Identifier]*Type), Types: make(map[TypeName]*Type), PkgPath: deref.Type(reflect.TypeOf(i)).PkgPath(), } cache := new(nature.Cache) env := conf.EnvWithCache(cache, i) for name, t := range env.All(cache) { if _, ok := c.Variables[Identifier(name)]; ok { continue } c.Variables[Identifier(name)] = c.use(t.Type, fromMethod(t.Method)) } for _, op := range Operators { c.Variables[Identifier(op)] = &Type{ Kind: "operator", } } for builtin, t := range Builtins { c.Variables[builtin] = t } return c } type config struct { method bool } type option func(c *config) func fromMethod(b bool) option { return func(c *config) { c.method = b } } func (c *Context) use(t reflect.Type, ops ...option) *Type { config := &config{} for _, op := range ops { op(config) } methods := make([]reflect.Method, 0) // Methods of struct should be gathered from original struct with pointer, // as methods maybe declared on pointer receiver. Also this method retrieves // all embedded structs methods as well, no need to recursion. for i := 0; i < t.NumMethod(); i++ { m := t.Method(i) if isPrivate(m.Name) || isProtobuf(m.Name) { continue } methods = append(methods, m) } t = deref.Type(t) // Only named types will have methods defined on them. // It maybe not even struct, but we gonna call then // structs in appendix anyway. if len(methods) > 0 { goto appendix } // This switch only for "simple" types. switch t.Kind() { case reflect.Bool: return &Type{Kind: "bool"} case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: fallthrough case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: return &Type{Kind: "int"} case reflect.Float32, reflect.Float64: return &Type{Kind: "float"} case reflect.String: return &Type{Kind: "string"} case reflect.Interface: return &Type{Kind: "any"} case reflect.Array, reflect.Slice: return &Type{ Kind: "array", Type: c.use(t.Elem()), } case reflect.Map: return &Type{ Kind: "map", Key: c.use(t.Key()), Type: c.use(t.Elem()), } case reflect.Struct: goto appendix case reflect.Func: arguments := make([]*Type, 0) start := 0 if config.method { start = 1 } for i := start; i < t.NumIn(); i++ { arguments = append(arguments, c.use(t.In(i))) } f := &Type{ Kind: "func", Arguments: arguments, } if t.NumOut() > 0 { f.Return = c.use(t.Out(0)) } return f } appendix: name := TypeName(t.String()) if c.PkgPath == t.PkgPath() { name = TypeName(t.Name()) } anonymous := t.Name() == "" a, ok := c.Types[name] if !ok { a = &Type{ Kind: "struct", Fields: make(map[Identifier]*Type), } // baseNode a should be saved before starting recursion, or it will never end. if !anonymous { c.Types[name] = a } ntCache := new(nature.Cache) for name, field := range nature.StructFields(ntCache, t) { if isPrivate(name) || isProtobuf(name) { continue } if _, ok := a.Fields[Identifier(name)]; ok { continue } a.Fields[Identifier(name)] = c.use(field.Type) } for _, m := range methods { if isPrivate(m.Name) || isProtobuf(m.Name) { continue } a.Fields[Identifier(m.Name)] = c.use(m.Type, fromMethod(true)) } } if anonymous { return a } return &Type{ Kind: "struct", Name: name, } } var isCapital = regexp.MustCompile("^[A-Z]") func isPrivate(s string) bool { return !isCapital.Match([]byte(s)) } func isProtobuf(s string) bool { return strings.HasPrefix(s, "XXX_") } ================================================ FILE: docgen/docgen_test.go ================================================ package docgen_test import ( "math" "testing" "time" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr/internal/testify/require" . "github.com/expr-lang/expr/docgen" ) type Tweet struct { Size int Message string } type Env struct { Tweets []Tweet Config struct { MaxSize int32 } Env map[string]any // NOTE: conflicting type name TimeWeekday time.Weekday Weekday Weekday } type Weekday int func (Weekday) String() string { return "" } type Duration int func (Duration) String() string { return "" } func (*Env) Duration(s string) Duration { return Duration(0) } func TestCreateDoc(t *testing.T) { Operators = nil Builtins = nil doc := CreateDoc(&Env{}) expected := &Context{ Variables: map[Identifier]*Type{ "Tweets": { Kind: "array", Type: &Type{ Kind: "struct", Name: "Tweet", }, }, "Config": { Kind: "struct", Fields: map[Identifier]*Type{ "MaxSize": {Kind: "int"}, }, }, "Env": { Kind: "map", Key: &Type{Kind: "string"}, Type: &Type{Kind: "any"}, }, "Duration": { Kind: "func", Arguments: []*Type{ {Kind: "string"}, }, Return: &Type{Kind: "struct", Name: "Duration"}, }, "TimeWeekday": { Name: "time.Weekday", Kind: "struct", }, "Weekday": { Name: "Weekday", Kind: "struct", }, }, Types: map[TypeName]*Type{ "Tweet": { Kind: "struct", Fields: map[Identifier]*Type{ "Size": {Kind: "int"}, "Message": {Kind: "string"}, }, }, "Duration": { Kind: "struct", Fields: map[Identifier]*Type{ "String": { Kind: "func", Arguments: []*Type{}, Return: &Type{ Kind: "string", }, }, }, }, "time.Weekday": { Kind: "struct", Fields: map[Identifier]*Type{ "String": { Kind: "func", Arguments: []*Type{}, Return: &Type{ Kind: "string", }, }, }, }, "Weekday": { Kind: "struct", Fields: map[Identifier]*Type{ "String": { Kind: "func", Arguments: []*Type{}, Return: &Type{ Kind: "string", }, }, }, }, }, PkgPath: "github.com/expr-lang/expr/docgen_test", } assert.Equal(t, expected.Markdown(), doc.Markdown()) } type A struct { AmbiguousField int OkField int } type B struct { AmbiguousField string } type C struct { A B } type EnvAmbiguous struct { A B C C } func TestCreateDoc_Ambiguous(t *testing.T) { doc := CreateDoc(&EnvAmbiguous{}) expected := &Context{ Variables: map[Identifier]*Type{ "A": { Kind: "struct", Name: "A", }, "AmbiguousField": { Kind: "int", }, "B": { Kind: "struct", Name: "B", }, "OkField": { Kind: "int", }, "C": { Kind: "struct", Name: "C", }, }, Types: map[TypeName]*Type{ "A": { Kind: "struct", Fields: map[Identifier]*Type{ "AmbiguousField": {Kind: "int"}, "OkField": {Kind: "int"}, }, }, "B": { Kind: "struct", Fields: map[Identifier]*Type{ "AmbiguousField": {Kind: "string"}, }, }, "C": { Kind: "struct", Fields: map[Identifier]*Type{ "A": {Kind: "struct", Name: "A"}, "AmbiguousField": {Kind: "int"}, "B": {Kind: "struct", Name: "B"}, "OkField": {Kind: "int"}, }, }, }, PkgPath: "github.com/expr-lang/expr/docgen_test", } assert.Equal(t, expected.Markdown(), doc.Markdown()) } func TestCreateDoc_FromMap(t *testing.T) { env := map[string]any{ "Tweets": []*Tweet{}, "Config": struct { MaxSize int }{}, "Max": math.Max, } Operators = nil Builtins = nil doc := CreateDoc(env) expected := &Context{ Variables: map[Identifier]*Type{ "Tweets": { Kind: "array", Type: &Type{ Kind: "struct", Name: "docgen_test.Tweet", }, }, "Config": { Kind: "struct", Fields: map[Identifier]*Type{ "MaxSize": {Kind: "int"}, }, }, "Max": { Kind: "func", Arguments: []*Type{ {Kind: "float"}, {Kind: "float"}, }, Return: &Type{Kind: "float"}, }, }, Types: map[TypeName]*Type{ "docgen_test.Tweet": { Kind: "struct", Fields: map[Identifier]*Type{ "Size": {Kind: "int"}, "Message": {Kind: "string"}, }, }, }, } require.EqualValues(t, expected.Markdown(), doc.Markdown()) } func TestContext_Markdown(t *testing.T) { doc := CreateDoc(&Env{}) md := doc.Markdown() require.True(t, len(md) > 0) } ================================================ FILE: docgen/markdown.go ================================================ package docgen import ( "fmt" "sort" "strings" ) func (c *Context) Markdown() string { var variables []string for name := range c.Variables { variables = append(variables, string(name)) } var types []string for name := range c.Types { types = append(types, string(name)) } sort.Strings(variables) sort.Strings(types) out := `### Variables | Name | Type | |------|------| ` for _, name := range variables { v := c.Variables[Identifier(name)] if v.Kind == "func" { continue } if v.Kind == "operator" { continue } out += fmt.Sprintf("| %v | %v |\n", name, link(v)) } out += ` ### Functions | Name | Return type | |------|-------------| ` for _, name := range variables { v := c.Variables[Identifier(name)] if v.Kind == "func" { args := make([]string, len(v.Arguments)) for i, arg := range v.Arguments { args[i] = link(arg) } out += fmt.Sprintf("| %v(%v) | %v |\n", name, strings.Join(args, ", "), link(v.Return)) } } out += "\n### Types\n" for _, name := range types { t := c.Types[TypeName(name)] out += fmt.Sprintf("#### %v\n", name) out += fields(t) out += "\n" } return out } func link(t *Type) string { if t == nil { return "nil" } if t.Name != "" { return fmt.Sprintf("[%v](#%v)", t.Name, t.Name) } if t.Kind == "array" { return fmt.Sprintf("array(%v)", link(t.Type)) } if t.Kind == "map" { return fmt.Sprintf("map(%v => %v)", link(t.Key), link(t.Type)) } return fmt.Sprintf("`%v`", t.Kind) } func fields(t *Type) string { var fields []string for field := range t.Fields { fields = append(fields, string(field)) } sort.Strings(fields) out := "" foundFields := false for _, name := range fields { v := t.Fields[Identifier(name)] if v.Kind != "func" { if !foundFields { out += "| Field | Type |\n|---|---|\n" } foundFields = true out += fmt.Sprintf("| %v | %v |\n", name, link(v)) } } foundMethod := false for _, name := range fields { v := t.Fields[Identifier(name)] if v.Kind == "func" { if !foundMethod { out += "\n| Method | Returns |\n|---|---|\n" } foundMethod = true args := make([]string, len(v.Arguments)) for i, arg := range v.Arguments { args[i] = link(arg) } out += fmt.Sprintf("| %v(%v) | %v |\n", name, strings.Join(args, ", "), link(v.Return)) } } return out } ================================================ FILE: docs/configuration.md ================================================ # Configuration ## Return type Usually, the return type of expression is anything. But we can instruct type checker to verify the return type of the expression. For example, in filter expressions, we expect the return type to be a boolean. ```go program, err := expr.Compile(code, expr.AsBool()) if err != nil { panic(err) } output, err := expr.Run(program, env) if err != nil { panic(err) } ok := output.(bool) // It is safe to assert the output to bool, if the expression is type checked as bool. ``` If `code` variable for example returns a string, the compiler will return an error. Expr has a few options to specify the return type: - [expr.AsBool()](https://pkg.go.dev/github.com/expr-lang/expr#AsBool) - expects the return type to be a bool. - [expr.AsInt()](https://pkg.go.dev/github.com/expr-lang/expr#AsInt) - expects the return type to be an int (float64, uint, int32, and other will be cast to int). - [expr.AsInt64()](https://pkg.go.dev/github.com/expr-lang/expr#AsInt64) - expects the return type to be an int64 ( float64, uint, int32, and other will be cast to int64). - [expr.AsFloat64()](https://pkg.go.dev/github.com/expr-lang/expr#AsFloat64) - expects the return type to be a float64 ( float32 will be cast to float64). - [expr.AsAny()](https://pkg.go.dev/github.com/expr-lang/expr#AsAny) - expects the return type to be anything. - [expr.AsKind(reflect.Kind)](https://pkg.go.dev/github.com/expr-lang/expr#AsKind) - expects the return type to be a specific kind. :::tip Warn on any By default, type checker will accept any type, even if the return type is specified. Consider following examples: ```expr let arr = [1, 2, 3]; arr[0] ``` The return type of the expression is `any`. Arrays created in Expr are of type `[]any`. The type checker will not return an error if the return type is specified as `expr.AsInt()`. The output of the expression is `1`, which is an int, but the type checker will not return an error. But we can instruct the type checker to warn us if the return type is `any`. Use [`expr.WarnOnAny()`](https://pkg.go.dev/github.com/expr-lang/expr#WarnOnAny) to enable this behavior. ```go program, err := expr.Compile(code, expr.AsInt(), expr.WarnOnAny()) ``` The type checker will return an error if the return type is `any`. We need to modify the expression to return a specific type. ```expr let arr = [1, 2, 3]; int(arr[0]) ``` ::: ## WithContext Although the compiled program is guaranteed to be terminated, some user defined functions may not be. For example, if a user defined function calls a remote service, we may want to pass a context to the function. This is possible via the [`WithContext`](https://pkg.go.dev/github.com/expr-lang/expr#WithContext) option. This option will modify function calls to include the context as the first argument (only if the function signature accepts a context). ```expr customFunc(42) // will be transformed to customFunc(ctx, 42) ``` Function `expr.WithContext()` takes the name of context variable. The context variable must be defined in the environment. ```go env := map[string]any{ "ctx": context.Background(), "customFunc": func(ctx context.Context, a int) int { return a }, } program, err := expr.Compile(code, expr.Env(env), expr.WithContext("ctx")) ``` ## ConstExpr For some user defined functions, we may want to evaluate the expression at compile time. This is possible via the [`ConstExpr`](https://pkg.go.dev/github.com/expr-lang/expr#ConstExpr) option. ```go func fib(n int) int { if n <= 1 { return n } return fib(n-1) + fib(n-2) } env := map[string]any{ "fib": fib, } program, err := expr.Compile(`fib(10)`, expr.Env(env), expr.ConstExpr("fib")) ``` If all arguments of the function are constants, the function will be evaluated at compile time. The result of the function will be used as a constant in the expression. ```expr fib(10) // will be transformed to 55 during the compilation fib(12+12) // will be transformed to 267914296 during the compilation fib(x) // will **not** be transformed and will be evaluated at runtime ``` ## Timezone By default, the timezone is set to `time.Local`. We can change the timezone via the [`Timezone`](https://pkg.go.dev/github.com/expr-lang/expr#Timezone) option. ```go program, err := expr.Compile(code, expr.Timezone(time.UTC)) ``` The timezone is used for the following functions: ```expr date("2024-11-23 12:00:00") // parses the date in the specified timezone now() // returns the current time in the specified timezone ``` ================================================ FILE: docs/environment.md ================================================ # Environment The environment is a map or a struct that contains the variables and functions that the expression can access. ## Struct as Environment Let's consider the following example: ```go type Env struct { UpdatedAt time.Time Posts []Post Map map[string]string `expr:"tags"` } ``` The `Env` struct contains 3 variables that the expression can access: `UpdatedAt`, `Posts`, and `tags`. :::info The `expr` tag is used to rename the `Map` field to `tags` variable in the expression. ::: The `Env` struct can also contain methods. The methods defined on the struct become functions that the expression can call. ```go func (Env) Format(t time.Time) string { return t.Format(time.RFC822) } ``` :::tip Methods defined on embedded structs are also accessible. ```go type Env struct { Helpers } type Helpers struct{} func (Helpers) Format(t time.Time) string { return t.Format(time.RFC822) } ``` ::: We can use an empty struct `Env{}` to with [expr.Env](https://pkg.go.dev/github.com/expr-lang/expr#Env) to create an environment. Expr will use reflection to find the fields and methods of the struct. ```go program, err := expr.Compile(code, expr.Env(Env{})) ``` Compiler will type check the expression against the environment. After the compilation, we can run the program with the environment. You should use the same type of environment that you passed to the `expr.Env` function. ```go output, err := expr.Run(program, Env{ UpdatedAt: time.Now(), Posts: []Post{{Title: "Hello, World!"}}, Map: map[string]string{"tag1": "value1"}, }) ``` ## Map as Environment You can also use a map as an environment. ```go env := map[string]any{ "UpdatedAt": time.Time{}, "Posts": []Post{}, "tags": map[string]string{}, "sprintf": fmt.Sprintf, } program, err := expr.Compile(code, expr.Env(env)) ``` A map defines variables and functions that the expression can access. The key is the variable name, and the type is the value's type. ```go env := map[string]any{ "object": map[string]any{ "field": 42, }, "struct": struct { Field int `expr:"field"` }{42}, } ``` Expr will infer the type of the `object` variable as `map[string]any`. Accessing fields of the `object` and `struct` variables will return the following results. ```expr object.field // 42 object.unknown // nil (no error) struct.field // 42 struct.unknown // error (unknown field) foobar // error (unknown variable) ``` :::note The `foobar` variable is not defined in the environment. By default, Expr will return an error if unknown variables are used in the expression. You can disable this behavior by passing [`AllowUndefinedVariables`](https://pkg.go.dev/github.com/expr-lang/expr#AllowUndefinedVariables) option to the compiler. ::: ================================================ FILE: docs/functions.md ================================================ # Functions Expr comes with a set of [builtin](language-definition.md) functions, but you can also define your own functions. The easiest way to define a custom function is to add it to the environment. ```go env := map[string]any{ "add": func(a, b int) int { return a + b }, } ``` Or you can use functions defined on a struct: ```go type Env struct{} func (Env) Add(a, b int) int { return a + b } ``` :::info If functions are marked with [`ConstExpr`](./configuration.md#constexpr) option, they will be evaluated at compile time. ::: The best way to define a function from a performance perspective is to use a [`Function`](https://pkg.go.dev/github.com/expr-lang/expr#Function) option. ```go atoi := expr.Function( "atoi", func(params ...any) (any, error) { return strconv.Atoi(params[0].(string)) }, ) program, err := expr.Compile(`atoi("42")`, atoi) ``` Type checker sees the `atoi` function as a function with a variadic number of arguments of type `any`, and returns a value of type `any`. But, we can specify the types of arguments and the return value by adding the correct function signature or multiple signatures. ```go atoi := expr.Function( "atoi", func(params ...any) (any, error) { return strconv.Atoi(params[0].(string)) }, // highlight-next-line new(func(string) int), ) ``` Or we can simply reuse the strconv.Atoi function as a type: ```go atoi := expr.Function( "atoi", func(params ...any) (any, error) { return strconv.Atoi(params[0].(string)) }, // highlight-next-line strconv.Atoi, ) ``` It is possible to define multiple signatures for a function: ```go toInt := expr.Function( "toInt", func(params ...any) (any, error) { switch params[0].(type) { case float64: return int(params[0].(float64)), nil case string: return strconv.Atoi(params[0].(string)) } return nil, fmt.Errorf("invalid type") }, // highlight-start new(func(float64) int), new(func(string) int), // highlight-end ) ``` ================================================ FILE: docs/getting-started.md ================================================ # Getting Started **Expr** is a simple, fast and extensible expression language for Go. It is designed to be easy to use and integrate into your Go application. Let's delve deeper into its core features: - **Memory safe** - Designed to prevent vulnerabilities like buffer overflows and memory leaks. - **Type safe** - Enforces strict type rules, aligning with Go's type system. - **Terminating** - Ensures every expression evaluation cannot loop indefinitely. - **Side effects free** - Evaluations won't modify global states or variables. Let's start with a simple example: ```go program, err := expr.Compile(`2 + 2`) if err != nil { panic(err) } output, err := expr.Run(program, nil) if err != nil { panic(err) } fmt.Print(output) // 4 ``` Expr compiles the expression `2 + 2` into a bytecode program. Then we run the program and get the output. :::tip In performance-critical applications, you can reuse the compiled program. Compiled programs are safe for concurrent use. **Compile once** and run **multiple** times. ::: The `expr.Compile` function returns a `*vm.Program` and an error. The `expr.Run` function takes a program and an environment. The environment is a map of variables that can be used in the expression. In this example, we use `nil` as an environment because we don't need any variables. Now let's pass some variables to the expression: ```go env := map[string]any{ "foo": 100, "bar": 200, } program, err := expr.Compile(`foo + bar`, expr.Env(env)) if err != nil { panic(err) } output, err := expr.Run(program, env) if err != nil { panic(err) } fmt.Print(output) // 300 ``` Why do we need to pass the environment to the `expr.Compile` function? Expr can be used as a type-safe language. Expr can infer the type of the expression and check it against the environment. Here is an example: ```go env := map[string]any{ "name": "Anton", "age": 35, } program, err := expr.Compile(`name + age`, expr.Env(env)) if err != nil { // highlight-next-line panic(err) // Will panic with "invalid operation: string + int" } ``` Expr can work with any Go types: ```go env := map[string]any{ "greet": "Hello, %v!", "names": []string{"world", "you"}, "sprintf": fmt.Sprintf, } program, err := expr.Compile(`sprintf(greet, names[0])`, expr.Env(env)) if err != nil { panic(err) } output, err := expr.Run(program, env) if err != nil { panic(err) } fmt.Print(output) // Hello, world! ``` Also, Expr can use a struct as an environment. Here is an example: ```go type Env struct { Posts []Post `expr:"posts"` } func (Env) Format(t time.Time) string { // Methods defined on the struct become functions. return t.Format(time.RFC822) } type Post struct { Body string Date time.Time } func main() { code := `map(posts, Format(.Date) + ": " + .Body)` program, err := expr.Compile(code, expr.Env(Env{})) // Pass the struct as an environment. if err != nil { panic(err) } env := Env{ Posts: []Post{ {"Oh My God!", time.Now()}, {"How you doin?", time.Now()}, {"Could I be wearing any more clothes?", time.Now()}, }, } output, err := expr.Run(program, env) if err != nil { panic(err) } fmt.Print(output) } ``` The compiled program can be reused between runs. ```go type Env struct { X int Y int } program, err := expr.Compile(`X + Y`, expr.Env(Env{})) if err != nil { panic(err) } output, err := expr.Run(program, Env{1, 2}) if err != nil { panic(err) } fmt.Print(output) // 3 output, err = expr.Run(program, Env{3, 4}) if err != nil { panic(err) } fmt.Print(output) // 7 ``` :::info Eval = Compile + Run For one-off expressions, you can use the `expr.Eval` function. It compiles and runs the expression in one step. ```go output, err := expr.Eval(`2 + 2`, env) ``` ::: ================================================ FILE: docs/language-definition.md ================================================ # Language Definition **Expr** is a simple expression language that can be used to evaluate expressions. ## Literals
Comment /* */ or //
Boolean true, false
Integer 42, 0x2A, 0o52, 0b101010
Float 0.5, .5
String "foo", 'bar'
Array [1, 2, 3]
Map {a: 1, b: 2, c: 3}
Nil nil
Bytes b"hello", b'\xff\x00'
### Strings Strings can be enclosed in single quotes or double quotes. Strings can contain escape sequences, like `\n` for newline, `\t` for tab, `\uXXXX` for Unicode code points. ```expr "Hello\nWorld" ``` For multiline strings, use backticks: ```expr `Hello World` ``` Backticks strings are raw strings, they do not support escape sequences. ### Bytes Bytes literals are represented by string literals preceded by a `b` or `B` character. The bytes literal returns a `[]byte` value. ```expr b"abc" // []byte{97, 98, 99} ``` Non-ASCII characters are UTF-8 encoded: ```expr b"ÿ" // []byte{195, 191} - UTF-8 encoding of ÿ ``` Bytes literals support escape sequences for specifying arbitrary byte values: - `\xNN` - hexadecimal escape (2 hex digits, value 0-255) - `\NNN` - octal escape (3 octal digits, value 0-377) - `\n`, `\t`, `\r`, etc. - standard escape sequences ```expr b"\xff" // []byte{255} b"\x00\x01" // []byte{0, 1} b"\101" // []byte{65} - octal for 'A' ``` :::note Unlike string literals, bytes literals do not support `\u` or `\U` Unicode escapes. Use `\x` escapes for arbitrary byte values. ::: ## Operators
Arithmetic +, -, *, /, % (modulus), ^ or ** (exponent)
Comparison ==, !=, <, >, <=, >=
Logical not or !, and or &&, or or ||
Conditional ?: (ternary), ?? (nil coalescing), if {} else {} (multiline)
Membership [], ., ?., in
String + (concatenation), contains, startsWith, endsWith
Regex matches
Range ..
Slice [:]
Pipe |
### Membership Operator Fields of structs and items of maps can be accessed with `.` operator or `[]` operator. Next two expressions are equivalent: ```expr user.Name user["Name"] ``` Elements of arrays and slices can be accessed with `[]` operator. Negative indices are supported with `-1` being the last element. ```expr array[0] // first element array[-1] // last element ``` The `in` operator can be used to check if an item is in an array or a map. ```expr "John" in ["John", "Jane"] "name" in {"name": "John", "age": 30} ``` #### Optional chaining The `?.` operator can be used to access a field of a struct or an item of a map without checking if the struct or the map is `nil`. If the struct or the map is `nil`, the result of the expression is `nil`. ```expr author.User?.Name ``` Is equivalent to: ```expr author.User != nil ? author.User.Name : nil ``` #### Nil coalescing The `??` operator can be used to return the left-hand side if it is not `nil`, otherwise the right-hand side is returned. ```expr author.User?.Name ?? "Anonymous" ``` Is equivalent to: ```expr author.User != nil ? author.User.Name : "Anonymous" ``` ### Slice Operator The slice operator `[:]` can be used to access a slice of an array. For example, variable **array** is `[1, 2, 3, 4, 5]`: ```expr array[1:4] == [2, 3, 4] array[1:-1] == [2, 3, 4] array[:3] == [1, 2, 3] array[3:] == [4, 5] array[:] == array ``` ### Pipe Operator The pipe operator `|` can be used to pass the result of the left-hand side expression as the first argument of the right-hand side expression. ```expr user.Name | lower() | split(" ") ``` Is equivalent to: ```expr split(lower(user.Name), " ") ``` ### Range Operator The range operator `..` can be used to create a range of integers. ```expr 1..3 == [1, 2, 3] ``` ## Variables Variables can be declared with the `let` keyword. The variable name must start with a letter or an underscore. The variable name can contain letters, digits and underscores. After the variable is declared, it can be used in the expression. ```expr let x = 42; x * 2 ``` A few variables can be declared by a few `let` statements separated by a semicolon. ```expr let x = 42; let y = 2; x * y ``` Here is an example of variable with pipe operator: ```expr let name = user.Name | lower() | split(" "); "Hello, " + name[0] + "!" ``` ### $env The `$env` variable is a map of all variables passed to the expression. ```expr foo.Name == $env["foo"].Name $env["var with spaces"] ``` Think of `$env` as a global variable that contains all variables. The `$env` can be used to check if a variable is defined: ```expr 'foo' in $env ``` ## Predicate The predicate is an expression. Predicates can be used in functions like `filter`, `all`, `any`, `one`, `none`, etc. For example, next expression creates a new array from 0 to 9 and then filters it by even numbers: ```expr filter(0..9, {# % 2 == 0}) ``` If items of the array is a struct or a map, it is possible to access fields with omitted `#` symbol (`#.Value` becomes `.Value`). ```expr filter(tweets, {len(.Content) > 240}) ``` Braces `{` `}` can be omitted: ```expr filter(tweets, len(.Content) > 240) ``` :::tip In nested predicates, to access the outer variable, use [variables](#variables). ```expr filter(posts, { let post = #; any(.Comments, .Author == post.Author) }) ``` ::: ## String Functions ### trim(str[, chars]) {#trim} Removes white spaces from both ends of a string `str`. If the optional `chars` argument is given, it is a string specifying the set of characters to be removed. ```expr trim(" Hello ") == "Hello" trim("__Hello__", "_") == "Hello" ``` ### trimPrefix(str, prefix) {#trimPrefix} Removes the specified prefix from the string `str` if it starts with that prefix. ```expr trimPrefix("HelloWorld", "Hello") == "World" ``` ### trimSuffix(str, suffix) {#trimSuffix} Removes the specified suffix from the string `str` if it ends with that suffix. ```expr trimSuffix("HelloWorld", "World") == "Hello" ``` ### upper(str) {#upper} Converts all the characters in string `str` to uppercase. ```expr upper("hello") == "HELLO" ``` ### lower(str) {#lower} Converts all the characters in string `str` to lowercase. ```expr lower("HELLO") == "hello" ``` ### split(str, delimiter[, n]) {#split} Splits the string `str` at each instance of the delimiter and returns an array of substrings. ```expr split("apple,orange,grape", ",") == ["apple", "orange", "grape"] split("apple,orange,grape", ",", 2) == ["apple", "orange,grape"] ``` ### splitAfter(str, delimiter[, n]) {#splitAfter} Splits the string `str` after each instance of the delimiter. ```expr splitAfter("apple,orange,grape", ",") == ["apple,", "orange,", "grape"] splitAfter("apple,orange,grape", ",", 2) == ["apple,", "orange,grape"] ``` ### replace(str, old, new) {#replace} Replaces all occurrences of `old` in string `str` with `new`. ```expr replace("Hello World", "World", "Universe") == "Hello Universe" ``` ### repeat(str, n) {#repeat} Repeats the string `str` `n` times. ```expr repeat("Hi", 3) == "HiHiHi" ``` ### indexOf(str, substring) {#indexOf} Returns the index of the first occurrence of the substring in string `str` or -1 if not found. ```expr indexOf("apple pie", "pie") == 6 ``` ### lastIndexOf(str, substring) {#lastIndexOf} Returns the index of the last occurrence of the substring in string `str` or -1 if not found. ```expr lastIndexOf("apple pie apple", "apple") == 10 ``` ### hasPrefix(str, prefix) {#hasPrefix} Returns `true` if string `str` starts with the given prefix. ```expr hasPrefix("HelloWorld", "Hello") == true ``` ### hasSuffix(str, suffix) {#hasSuffix} Returns `true` if string `str` ends with the given suffix. ```expr hasSuffix("HelloWorld", "World") == true ``` ## Date Functions Expr has a built-in support for Go's [time package](https://pkg.go.dev/time). It is possible to subtract two dates and get the duration between them: ```expr createdAt - now() ``` It is possible to add a duration to a date: ```expr createdAt + duration("1h") ``` And it is possible to compare dates: ```expr createdAt > now() - duration("1h") ``` ### now() {#now} Returns the current date as a [time.Time](https://pkg.go.dev/time#Time) value. ```expr now().Year() == 2024 ``` ### duration(str) {#duration} Returns [time.Duration](https://pkg.go.dev/time#Duration) value of the given string `str`. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". ```expr duration("1h").Seconds() == 3600 ``` ### date(str[, format[, timezone]]) {#date} Converts the given string `str` into a date representation. If the optional `format` argument is given, it is a string specifying the format of the date. The format string uses the same formatting rules as the standard Go [time package](https://pkg.go.dev/time#pkg-constants). If the optional `timezone` argument is given, it is a string specifying the timezone of the date. If the `format` argument is not given, the `v` argument must be in one of the following formats: - 2006-01-02 - 15:04:05 - 2006-01-02 15:04:05 - RFC3339 - RFC822, - RFC850, - RFC1123, ```expr date("2023-08-14") date("15:04:05") date("2023-08-14T00:00:00Z") date("2023-08-14 00:00:00", "2006-01-02 15:04:05", "Europe/Zurich") ``` Available methods on the date: - `Year()` - returns the year - `Month()` - returns the month (starting from 1) - `Day()` - returns the day of the month - `Hour()` - returns the hour - `Minute()` - returns the minute - `Second()` - returns the second - `Weekday()` - returns the day of the week - `YearDay()` - returns the day of the year - and [more](https://pkg.go.dev/time#Time). ```expr date("2023-08-14").Year() == 2023 ``` ### timezone(str) {#timezone} Returns the timezone of the given string `str`. List of available timezones can be found [here](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). ```expr timezone("Europe/Zurich") timezone("UTC") ``` To convert a date to a different timezone, use the [`In()`](https://pkg.go.dev/time#Time.In) method: ```expr date("2023-08-14 00:00:00").In(timezone("Europe/Zurich")) ``` ## Number Functions ### max(n1, n2) {#max} Returns the maximum of the two numbers `n1` and `n2`. ```expr max(5, 7) == 7 ``` ### min(n1, n2) {#min} Returns the minimum of the two numbers `n1` and `n2`. ```expr min(5, 7) == 5 ``` ### abs(n) {#abs} Returns the absolute value of a number. ```expr abs(-5) == 5 ``` ### ceil(n) {#ceil} Returns the least integer value greater than or equal to x. ```expr ceil(1.5) == 2.0 ``` ### floor(n) {#floor} Returns the greatest integer value less than or equal to x. ```expr floor(1.5) == 1.0 ``` ### round(n) {#round} Returns the nearest integer, rounding half away from zero. ```expr round(1.5) == 2.0 ``` ## Array Functions ### all(array, predicate) {#all} Returns **true** if all elements satisfies the [predicate](#predicate). If the array is empty, returns **true**. ```expr all(tweets, {.Size < 280}) ``` ### any(array, predicate) {#any} Returns **true** if any elements satisfies the [predicate](#predicate). If the array is empty, returns **false**. ```expr any(tweets, {.Size > 280}) ``` ### one(array, predicate) {#one} Returns **true** if _exactly one_ element satisfies the [predicate](#predicate). If the array is empty, returns **false**. ```expr one(participants, {.Winner}) ``` ### none(array, predicate) {#none} Returns **true** if _all elements does not_ satisfy the [predicate](#predicate). If the array is empty, returns **true**. ```expr none(tweets, {.Size > 280}) ``` ### map(array, predicate) {#map} Returns new array by applying the [predicate](#predicate) to each element of the array. ```expr map(tweets, {.Size}) ``` ### filter(array, predicate) {#filter} Returns new array by filtering elements of the array by [predicate](#predicate). ```expr filter(users, .Name startsWith "J") ``` ### find(array, predicate) {#find} Finds the first element in an array that satisfies the [predicate](#predicate). ```expr find([1, 2, 3, 4], # > 2) == 3 ``` ### findIndex(array, predicate) {#findIndex} Finds the index of the first element in an array that satisfies the [predicate](#predicate). ```expr findIndex([1, 2, 3, 4], # > 2) == 2 ``` ### findLast(array, predicate) {#findLast} Finds the last element in an array that satisfies the [predicate](#predicate). ```expr findLast([1, 2, 3, 4], # > 2) == 4 ``` ### findLastIndex(array, predicate) {#findLastIndex} Finds the index of the last element in an array that satisfies the [predicate](#predicate). ```expr findLastIndex([1, 2, 3, 4], # > 2) == 3 ``` ### groupBy(array, predicate) {#groupBy} Groups the elements of an array by the result of the [predicate](#predicate). ```expr groupBy(users, .Age) ``` ### count(array[, predicate]) {#count} Returns the number of elements what satisfies the [predicate](#predicate). ```expr count(users, .Age > 18) ``` Equivalent to: ```expr len(filter(users, .Age > 18)) ``` If the predicate is not given, returns the number of `true` elements in the array. ```expr count([true, false, true]) == 2 ``` ### concat(array1, array2[, ...]) {#concat} Concatenates two or more arrays. ```expr concat([1, 2], [3, 4]) == [1, 2, 3, 4] ``` ### flatten(array) {#flatten} Flattens given array into one-dimensional array. ```expr flatten([1, 2, [3, 4]]) == [1, 2, 3, 4] ``` ### uniq(array) {#uniq} Removes duplicates from an array. ```expr uniq([1, 2, 3, 2, 1]) == [1, 2, 3] ``` ### join(array[, delimiter]) {#join} Joins an array of strings into a single string with the given delimiter. If no delimiter is given, an empty string is used. ```expr join(["apple", "orange", "grape"], ",") == "apple,orange,grape" join(["apple", "orange", "grape"]) == "appleorangegrape" ``` ### reduce(array, predicate[, initialValue]) {#reduce} Applies a predicate to each element in the array, reducing the array to a single value. Optional `initialValue` argument can be used to specify the initial value of the accumulator. If `initialValue` is not given, the first element of the array is used as the initial value. Following variables are available in the predicate: - `#` - the current element - `#acc` - the accumulator - `#index` - the index of the current element ```expr reduce(1..9, #acc + #) reduce(1..9, #acc + #, 0) ``` ### sum(array[, predicate]) {#sum} Returns the sum of all numbers in the array. ```expr sum([1, 2, 3]) == 6 ``` If the optional `predicate` argument is given, it is a predicate that is applied on each element of the array before summing. ```expr sum(accounts, .Balance) ``` Equivalent to: ```expr reduce(accounts, #acc + .Balance, 0) // or sum(map(accounts, .Balance)) ``` ### mean(array) {#mean} Returns the average of all numbers in the array. ```expr mean([1, 2, 3]) == 2.0 ``` ### median(array) {#median} Returns the median of all numbers in the array. ```expr median([1, 2, 3]) == 2.0 ``` ### first(array) {#first} Returns the first element from an array. If the array is empty, returns `nil`. ```expr first([1, 2, 3]) == 1 ``` ### last(array) {#last} Returns the last element from an array. If the array is empty, returns `nil`. ```expr last([1, 2, 3]) == 3 ``` ### take(array, n) {#take} Returns the first `n` elements from an array. If the array has fewer than `n` elements, returns the whole array. ```expr take([1, 2, 3, 4], 2) == [1, 2] ``` ### reverse(array) {#reverse} Return new reversed copy of the array. ```expr reverse([3, 1, 4]) == [4, 1, 3] reverse(reverse([3, 1, 4])) == [3, 1, 4] ``` ### sort(array[, order]) {#sort} Sorts an array in ascending order. Optional `order` argument can be used to specify the order of sorting: `asc` or `desc`. ```expr sort([3, 1, 4]) == [1, 3, 4] sort([3, 1, 4], "desc") == [4, 3, 1] ``` ### sortBy(array[, predicate, order]) {#sortBy} Sorts an array by the result of the [predicate](#predicate). Optional `order` argument can be used to specify the order of sorting: `asc` or `desc`. ```expr sortBy(users, .Age) sortBy(users, .Age, "desc") ``` ## Map Functions ### keys(map) {#keys} Returns an array containing the keys of the map. ```expr keys({"name": "John", "age": 30}) == ["name", "age"] ``` ### values(map) {#values} Returns an array containing the values of the map. ```expr values({"name": "John", "age": 30}) == ["John", 30] ``` ## Type Conversion Functions ### type(v) {#type} Returns the type of the given value `v`. Returns on of the following types: - `nil` - `bool` - `int` - `uint` - `float` - `string` - `array` - `map`. For named types and structs, the type name is returned. ```expr type(42) == "int" type("hello") == "string" type(now()) == "time.Time" ``` ### int(v) {#int} Returns the integer value of a number or a string. ```expr int("123") == 123 ``` ### float(v) {#float} Returns the float value of a number or a string. ```expr float("123.45") == 123.45 ``` ### string(v) {#string} Converts the given value `v` into a string representation. ```expr string(123) == "123" ``` ### toJSON(v) {#toJSON} Converts the given value `v` to its JSON string representation. ```expr toJSON({"name": "John", "age": 30}) ``` ### fromJSON(v) {#fromJSON} Parses the given JSON string `v` and returns the corresponding value. ```expr fromJSON('{"name": "John", "age": 30}') ``` ### toBase64(v) {#toBase64} Encodes the string `v` into Base64 format. ```expr toBase64("Hello World") == "SGVsbG8gV29ybGQ=" ``` ### fromBase64(v) {#fromBase64} Decodes the Base64 encoded string `v` back to its original form. ```expr fromBase64("SGVsbG8gV29ybGQ=") == "Hello World" ``` ### toPairs(map) {#toPairs} Converts a map to an array of key-value pairs. ```expr toPairs({"name": "John", "age": 30}) == [["name", "John"], ["age", 30]] ``` ### fromPairs(array) {#fromPairs} Converts an array of key-value pairs to a map. ```expr fromPairs([["name", "John"], ["age", 30]]) == {"name": "John", "age": 30} ``` ## Miscellaneous Functions ### len(v) {#len} Returns the length of an array, a map or a string. ```expr len([1, 2, 3]) == 3 len({"name": "John", "age": 30}) == 2 len("Hello") == 5 ``` ### get(v, index) {#get} Retrieves the element at the specified index from an array or map `v`. If the index is out of range, returns `nil`. Or the key does not exist, returns `nil`. ```expr get([1, 2, 3], 1) == 2 get({"name": "John", "age": 30}, "name") == "John" ``` ## Bitwise Functions ### bitand(int, int) {#bitand} Returns the values resulting from the bitwise AND operation. ```expr bitand(0b1010, 0b1100) == 0b1000 ``` ### bitor(int, int) {#bitor} Returns the values resulting from the bitwise OR operation. ```expr bitor(0b1010, 0b1100) == 0b1110 ``` ### bitxor(int, int) {#bitxor} Returns the values resulting from the bitwise XOR operation. ```expr bitxor(0b1010, 0b1100) == 0b110 ``` ### bitnand(int, int) {#bitnand} Returns the values resulting from the bitwise AND NOT operation. ```expr bitnand(0b1010, 0b1100) == 0b10 ``` ### bitnot(int) {#bitnot} Returns the values resulting from the bitwise NOT operation. ```expr bitnot(0b1010) == -0b1011 ``` ### bitshl(int, int) {#bitshl} Returns the values resulting from the Left Shift operation. ```expr bitshl(0b101101, 2) == 0b10110100 ``` ### bitshr(int, int) {#bitshr} Returns the values resulting from the Right Shift operation. ```expr bitshr(0b101101, 2) == 0b1011 ``` ### bitushr(int, int) {#bitushr} Returns the values resulting from the unsigned Right Shift operation. ```expr bitushr(-0b101, 2) == 4611686018427387902 ``` ================================================ FILE: docs/patch.md ================================================ # Patch Sometimes it may be necessary to modify an expression before the compilation. For example, you may want to replace a variable with a constant, transform an expression into a function call, or even modify the expression to use a different operator. ## Simple example Let's start with a simple example. We have an expression that uses a variable `foo`: ```go program, err := expr.Compile(`foo + bar`) ``` We want to replace the `foo` variable with a constant `42`. First, we need to implement a [visitor](./visitor.md): ```go type FooPatcher struct{} func (FooPatcher) Visit(node *ast.Node) { if n, ok := (*node).(*ast.IdentifierNode); ok && n.Value == "foo" { // highlight-next-line ast.Patch(node, &ast.IntegerNode{Value: 42}) } } ``` We used the [ast.Patch](https://pkg.go.dev/github.com/expr-lang/expr/ast#Patch) function to replace the `foo` variable with an integer node. Now we can use the `FooPatcher` to modify the expression on compilation via the [expr.Patch](https://pkg.go.dev/github.com/expr-lang/expr#Patch) option: ```go program, err := expr.Compile(`foo + bar`, expr.Patch(FooPatcher{})) ``` ## Advanced example Let's consider a more complex example. We have an expression that uses variables `foo` and `bar` of type `Decimal`: ```go type Decimal struct { Value int } ``` And we want to transform the following expression: ```expr a + b + c ``` Into functions calls that accept `Decimal` arguments: ```expr add(add(a, b), c) ``` First, we need to implement a visitor that will transform the expression: ```go type DecimalPatcher struct{} var decimalType = reflect.TypeOf(Decimal{}) func (DecimalPatcher) Visit(node *ast.Node) { if n, ok := (*node).(*ast.BinaryNode); ok && n.Operator == "+" { if !n.Left.Type().AssignableTo(decimalType) { return // skip, left side is not a Decimal } if !n.Right.Type().AssignableTo(decimalType) { return // skip, right side is not a Decimal } // highlight-start callNode := &ast.CallNode{ Callee: &ast.IdentifierNode{Value: "add"}, Arguments: []ast.Node{n.Left, n.Right}, } ast.Patch(node, callNode) // highlight-end (*node).SetType(decimalType) // set the type, so the patcher can be applied recursively } } ``` We used [Type()](https://pkg.go.dev/github.com/expr-lang/expr/ast#Node.Type) method to get the type of the expression node. The `AssignableTo` method is used to check if the type is `Decimal`. If both sides are `Decimal`, we replace the expression with a function call. The important part of this patcher is to set correct types for the nodes. As we constructed a new `CallNode`, it lacks the type information. So after the first patcher run, if we want the patcher to be applied recursively, we need to set the type of the node. Now we can use the `DecimalPatcher` to modify the expression: ```go env := map[string]interface{}{ "a": Decimal{1}, "b": Decimal{2}, "c": Decimal{3}, "add": func(x, y Decimal) Decimal { return Decimal{x.Value + y.Value} }, } code := `a + b + c` // highlight-next-line program, err := expr.Compile(code, expr.Env(env), expr.Patch(DecimalPatcher{})) if err != nil { panic(err) } output, err := expr.Run(program, env) if err != nil { panic(err) } fmt.Println(output) // Decimal{6} ``` :::info Expr comes with already implemented patcher that simplifies operator overloading. The `DecimalPatcher` can be replaced with the [Operator](https://pkg.go.dev/github.com/expr-lang/expr#Operator) option. ```go program, err := expr.Compile(code, expr.Env(env), expr.Operator("+", "add")) ``` Operator overloading patcher will check if provided functions (`"add"`) satisfy the operator (`"+"`), and replace the operator with the function call. ::: ================================================ FILE: docs/visitor.md ================================================ # Visitor Expr provides an interface to traverse the AST of the expression before the compilation. The `Visitor` interface allows you to collect information about the expression, modify the expression, or even generate a new expression. Let's start with an [ast.Visitor](https://pkg.go.dev/github.com/expr-lang/expr/ast#Visitor) implementation which will collect all variables used in the expression. Visitor must implement a single method `Visit(*ast.Node)`, which will be called for each node in the AST. ```go type Visitor struct { Identifiers []string } func (v *Visitor) Visit(node *ast.Node) { if n, ok := (*node).(*ast.IdentifierNode); ok { v.Identifiers = append(v.Identifiers, n.Value) } } ``` Full list of available AST nodes can be found in the [ast](https://pkg.go.dev/github.com/expr-lang/expr/ast) documentation. Let's parse the expression and use [ast.Walk](https://pkg.go.dev/github.com/expr-lang/expr/ast#Walk) to traverse the AST: ```go tree, err := parser.Parse(`foo + bar`) if err != nil { panic(err) } v := &Visitor{} // highlight-next-line ast.Walk(&tree.Node, v) fmt.Println(v.Identifiers) // [foo, bar] ``` :::note Although it is possible to access the AST of compiled program, it may be already be modified by patchers, optimizers, etc. ```go program, err := expr.Compile(`foo + bar`) if err != nil { panic(err) } // highlight-next-line node := program.Node() v := &Visitor{} ast.Walk(&node, v) ``` ::: ================================================ FILE: expr.go ================================================ package expr import ( "errors" "fmt" "reflect" "time" "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/builtin" "github.com/expr-lang/expr/checker" "github.com/expr-lang/expr/compiler" "github.com/expr-lang/expr/conf" "github.com/expr-lang/expr/file" "github.com/expr-lang/expr/optimizer" "github.com/expr-lang/expr/parser" "github.com/expr-lang/expr/patcher" "github.com/expr-lang/expr/vm" ) // Option for configuring config. type Option func(c *conf.Config) // Env specifies expected input of env for type checks. // If struct is passed, all fields will be treated as variables, // as well as all fields of embedded structs and struct itself. // If map is passed, all items will be treated as variables. // Methods defined on this type will be available as functions. func Env(env any) Option { return func(c *conf.Config) { c.WithEnv(env) } } // AllowUndefinedVariables allows to use undefined variables inside expressions. // This can be used with expr.Env option to partially define a few variables. func AllowUndefinedVariables() Option { return func(c *conf.Config) { c.Strict = false } } // Operator allows to replace a binary operator with a function. func Operator(operator string, fn ...string) Option { return func(c *conf.Config) { p := &patcher.OperatorOverloading{ Operator: operator, Overloads: fn, Env: &c.Env, Functions: c.Functions, NtCache: &c.NtCache, } c.Visitors = append(c.Visitors, p) } } // ConstExpr defines func expression as constant. If all argument to this function is constants, // then it can be replaced by result of this func call on compile step. func ConstExpr(fn string) Option { return func(c *conf.Config) { c.ConstExpr(fn) } } // AsAny tells the compiler to expect any result. func AsAny() Option { return func(c *conf.Config) { c.ExpectAny = true } } // AsKind tells the compiler to expect kind of the result. func AsKind(kind reflect.Kind) Option { return func(c *conf.Config) { c.Expect = kind c.ExpectAny = true } } // AsBool tells the compiler to expect a boolean result. func AsBool() Option { return func(c *conf.Config) { c.Expect = reflect.Bool c.ExpectAny = true } } // AsInt tells the compiler to expect an int result. func AsInt() Option { return func(c *conf.Config) { c.Expect = reflect.Int c.ExpectAny = true } } // AsInt64 tells the compiler to expect an int64 result. func AsInt64() Option { return func(c *conf.Config) { c.Expect = reflect.Int64 c.ExpectAny = true } } // AsFloat64 tells the compiler to expect a float64 result. func AsFloat64() Option { return func(c *conf.Config) { c.Expect = reflect.Float64 c.ExpectAny = true } } // DisableIfOperator disables the `if ... else ...` operator syntax so a custom // function named `if(...)` can be used without conflicts. func DisableIfOperator() Option { return func(c *conf.Config) { c.DisableIfOperator = true } } // WarnOnAny tells the compiler to warn if expression return any type. func WarnOnAny() Option { return func(c *conf.Config) { if c.Expect == reflect.Invalid { panic("WarnOnAny() works only with combination with AsInt(), AsBool(), etc. options") } c.ExpectAny = false } } // Optimize turns optimizations on or off. func Optimize(b bool) Option { return func(c *conf.Config) { c.Optimize = b } } // DisableShortCircuit turns short circuit off. func DisableShortCircuit() Option { return func(c *conf.Config) { c.ShortCircuit = false } } // Patch adds visitor to list of visitors what will be applied before compiling AST to bytecode. func Patch(visitor ast.Visitor) Option { return func(c *conf.Config) { c.Visitors = append(c.Visitors, visitor) } } // Function adds function to list of functions what will be available in expressions. func Function(name string, fn func(params ...any) (any, error), types ...any) Option { return func(c *conf.Config) { ts := make([]reflect.Type, len(types)) for i, t := range types { t := reflect.TypeOf(t) if t.Kind() == reflect.Ptr { t = t.Elem() } if t.Kind() != reflect.Func { panic(fmt.Sprintf("expr: type of %s is not a function", name)) } ts[i] = t } c.Functions[name] = &builtin.Function{ Name: name, Func: fn, Types: ts, } } } // DisableAllBuiltins disables all builtins. func DisableAllBuiltins() Option { return func(c *conf.Config) { for name := range c.Builtins { c.Disabled[name] = true } } } // DisableBuiltin disables builtin function. func DisableBuiltin(name string) Option { return func(c *conf.Config) { c.Disabled[name] = true } } // EnableBuiltin enables builtin function. func EnableBuiltin(name string) Option { return func(c *conf.Config) { delete(c.Disabled, name) } } // WithContext passes context to all functions calls with a context.Context argument. func WithContext(name string) Option { return func(c *conf.Config) { c.Visitors = append(c.Visitors, patcher.WithContext{ Name: name, Functions: c.Functions, Env: &c.Env, NtCache: &c.NtCache, }) } } // Timezone sets default timezone for date() and now() builtin functions. func Timezone(name string) Option { tz, err := time.LoadLocation(name) if err != nil { panic(err) } return Patch(patcher.WithTimezone{ Location: tz, }) } // MaxNodes sets the maximum number of nodes allowed in the expression. // By default, the maximum number of nodes is conf.DefaultMaxNodes. // If MaxNodes is set to 0, the node budget check is disabled. func MaxNodes(n uint) Option { return func(c *conf.Config) { c.MaxNodes = n } } // Compile parses and compiles given input expression to bytecode program. func Compile(input string, ops ...Option) (*vm.Program, error) { config := conf.CreateNew() for _, op := range ops { op(config) } for name := range config.Disabled { delete(config.Builtins, name) } config.Check() tree, err := checker.ParseCheck(input, config) if err != nil { return nil, err } if config.Optimize { err = optimizer.Optimize(&tree.Node, config) if err != nil { var fileError *file.Error if errors.As(err, &fileError) { return nil, fileError.Bind(tree.Source) } return nil, err } } program, err := compiler.Compile(tree, config) if err != nil { return nil, err } return program, nil } // Run evaluates given bytecode program. func Run(program *vm.Program, env any) (any, error) { return vm.Run(program, env) } // Eval parses, compiles and runs given input. func Eval(input string, env any) (any, error) { if _, ok := env.(Option); ok { return nil, fmt.Errorf("misused expr.Eval: second argument (env) should be passed without expr.Env") } tree, err := parser.Parse(input) if err != nil { return nil, err } program, err := compiler.Compile(tree, nil) if err != nil { return nil, err } output, err := Run(program, env) if err != nil { return nil, err } return output, nil } ================================================ FILE: expr_test.go ================================================ package expr_test import ( "context" "encoding/json" "fmt" "os" "reflect" "strings" "sync" "testing" "time" "github.com/expr-lang/expr/conf" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr/types" "github.com/expr-lang/expr/vm" "github.com/expr-lang/expr" "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/file" "github.com/expr-lang/expr/test/mock" ) func ExampleEval() { output, err := expr.Eval("greet + name", map[string]any{ "greet": "Hello, ", "name": "world!", }) if err != nil { fmt.Printf("err: %v", err) return } fmt.Printf("%v", output) // Output: Hello, world! } func ExampleEval_runtime_error() { _, err := expr.Eval(`map(1..3, {1 % (# - 3)})`, nil) fmt.Print(err) // Output: runtime error: integer divide by zero (1:14) // | map(1..3, {1 % (# - 3)}) // | .............^ } func ExampleCompile() { env := map[string]any{ "foo": 1, "bar": 99, } program, err := expr.Compile("foo in 1..99 and bar in 1..99", expr.Env(env)) if err != nil { fmt.Printf("%v", err) return } output, err := expr.Run(program, env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) // Output: true } func ExampleEval_bytes_literal() { // Bytes literal returns []byte. output, err := expr.Eval(`b"abc"`, nil) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) // Output: [97 98 99] } func TestDisableIfOperator_AllowsIfFunction(t *testing.T) { env := map[string]any{ "if": func(x int) int { return x + 1 }, } program, err := expr.Compile("if(41)", expr.Env(env), expr.DisableIfOperator()) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) assert.Equal(t, 42, out) } func ExampleEnv() { type Segment struct { Origin string } type Passengers struct { Adults int } type Meta struct { Tags map[string]string } type Env struct { Meta Segments []*Segment Passengers *Passengers Marker string } code := `all(Segments, {.Origin == "MOW"}) && Passengers.Adults > 0 && Tags["foo"] startsWith "bar"` program, err := expr.Compile(code, expr.Env(Env{})) if err != nil { fmt.Printf("%v", err) return } env := Env{ Meta: Meta{ Tags: map[string]string{ "foo": "bar", }, }, Segments: []*Segment{ {Origin: "MOW"}, }, Passengers: &Passengers{ Adults: 2, }, Marker: "test", } output, err := expr.Run(program, env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) // Output: true } func ExampleEnv_tagged_field_names() { env := struct { FirstWord string Separator string `expr:"Space"` SecondWord string `expr:"second_word"` }{ FirstWord: "Hello", Separator: " ", SecondWord: "World", } output, err := expr.Eval(`FirstWord + Space + second_word`, env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) // Output: Hello World } func ExampleEnv_hidden_tagged_field_names() { type Internal struct { Visible string Hidden string `expr:"-"` } type environment struct { Visible string Hidden string `expr:"-"` HiddenInternal Internal `expr:"-"` VisibleInternal Internal } env := environment{ Hidden: "First level secret", HiddenInternal: Internal{ Visible: "Second level secret", Hidden: "Also hidden", }, VisibleInternal: Internal{ Visible: "Not a secret", Hidden: "Hidden too", }, } hiddenValues := []string{ `Hidden`, `HiddenInternal`, `HiddenInternal.Visible`, `HiddenInternal.Hidden`, `VisibleInternal["Hidden"]`, } for _, expression := range hiddenValues { output, err := expr.Eval(expression, env) if err == nil || !strings.Contains(err.Error(), "cannot fetch") { fmt.Printf("unexpected output: %v; err: %v\n", output, err) return } fmt.Printf("%q is hidden as expected\n", expression) } visibleValues := []string{ `Visible`, `VisibleInternal`, `VisibleInternal["Visible"]`, } for _, expression := range visibleValues { _, err := expr.Eval(expression, env) if err != nil { fmt.Printf("unexpected error: %v\n", err) return } fmt.Printf("%q is visible as expected\n", expression) } testWithIn := []string{ `not ("Hidden" in $env)`, `"Visible" in $env`, `not ("Hidden" in VisibleInternal)`, `"Visible" in VisibleInternal`, } for _, expression := range testWithIn { val, err := expr.Eval(expression, env) shouldBeTrue, ok := val.(bool) if err != nil || !ok || !shouldBeTrue { fmt.Printf("unexpected result; value: %v; error: %v\n", val, err) return } } // Output: "Hidden" is hidden as expected // "HiddenInternal" is hidden as expected // "HiddenInternal.Visible" is hidden as expected // "HiddenInternal.Hidden" is hidden as expected // "VisibleInternal[\"Hidden\"]" is hidden as expected // "Visible" is visible as expected // "VisibleInternal" is visible as expected // "VisibleInternal[\"Visible\"]" is visible as expected } func ExampleAsKind() { program, err := expr.Compile("{a: 1, b: 2}", expr.AsKind(reflect.Map)) if err != nil { fmt.Printf("%v", err) return } output, err := expr.Run(program, nil) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) // Output: map[a:1 b:2] } func ExampleAsBool() { env := map[string]int{ "foo": 0, } program, err := expr.Compile("foo >= 0", expr.Env(env), expr.AsBool()) if err != nil { fmt.Printf("%v", err) return } output, err := expr.Run(program, env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output.(bool)) // Output: true } func ExampleAsBool_error() { env := map[string]any{ "foo": 0, } _, err := expr.Compile("foo + 42", expr.Env(env), expr.AsBool()) fmt.Printf("%v", err) // Output: expected bool, but got int } func ExampleAsInt() { program, err := expr.Compile("42", expr.AsInt()) if err != nil { fmt.Printf("%v", err) return } output, err := expr.Run(program, nil) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%T(%v)", output, output) // Output: int(42) } func ExampleAsInt64() { env := map[string]any{ "rating": 5.5, } program, err := expr.Compile("rating", expr.Env(env), expr.AsInt64()) if err != nil { fmt.Printf("%v", err) return } output, err := expr.Run(program, env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output.(int64)) // Output: 5 } func ExampleAsFloat64() { program, err := expr.Compile("42", expr.AsFloat64()) if err != nil { fmt.Printf("%v", err) return } output, err := expr.Run(program, nil) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output.(float64)) // Output: 42 } func ExampleAsFloat64_error() { _, err := expr.Compile(`!!true`, expr.AsFloat64()) fmt.Printf("%v", err) // Output: expected float64, but got bool } func ExampleWarnOnAny() { // Arrays always have []any type. The expression return type is any. // AsInt() instructs compiler to expect int or any, and cast to int, // if possible. WarnOnAny() instructs to return an error on any type. _, err := expr.Compile(`[42, true, "yes"][0]`, expr.AsInt(), expr.WarnOnAny()) fmt.Printf("%v", err) // Output: expected int, but got interface {} } func ExampleOperator() { code := ` Now() > CreatedAt && (Now() - CreatedAt).Hours() > 24 ` type Env struct { CreatedAt time.Time Now func() time.Time Sub func(a, b time.Time) time.Duration After func(a, b time.Time) bool } options := []expr.Option{ expr.Env(Env{}), expr.Operator(">", "After"), expr.Operator("-", "Sub"), } program, err := expr.Compile(code, options...) if err != nil { fmt.Printf("%v", err) return } env := Env{ CreatedAt: time.Date(2018, 7, 14, 0, 0, 0, 0, time.UTC), Now: func() time.Time { return time.Now() }, Sub: func(a, b time.Time) time.Duration { return a.Sub(b) }, After: func(a, b time.Time) bool { return a.After(b) }, } output, err := expr.Run(program, env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) // Output: true } func ExampleOperator_with_decimal() { type Decimal struct{ N float64 } code := `A + B - C` type Env struct { A, B, C Decimal Sub func(a, b Decimal) Decimal Add func(a, b Decimal) Decimal } options := []expr.Option{ expr.Env(Env{}), expr.Operator("+", "Add"), expr.Operator("-", "Sub"), } program, err := expr.Compile(code, options...) if err != nil { fmt.Printf("Compile error: %v", err) return } env := Env{ A: Decimal{3}, B: Decimal{2}, C: Decimal{1}, Sub: func(a, b Decimal) Decimal { return Decimal{a.N - b.N} }, Add: func(a, b Decimal) Decimal { return Decimal{a.N + b.N} }, } output, err := expr.Run(program, env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) // Output: {4} } func fib(n int) int { if n <= 1 { return n } return fib(n-1) + fib(n-2) } func ExampleConstExpr() { code := `[fib(5), fib(3+3), fib(dyn)]` env := map[string]any{ "fib": fib, "dyn": 0, } options := []expr.Option{ expr.Env(env), expr.ConstExpr("fib"), // Mark fib func as constant expression. } program, err := expr.Compile(code, options...) if err != nil { fmt.Printf("%v", err) return } // Only fib(5) and fib(6) calculated on Compile, fib(dyn) can be called at runtime. env["dyn"] = 7 output, err := expr.Run(program, env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v\n", output) // Output: [5 8 13] } func ExampleAllowUndefinedVariables() { code := `name == nil ? "Hello, world!" : sprintf("Hello, %v!", name)` env := map[string]any{ "sprintf": fmt.Sprintf, } options := []expr.Option{ expr.Env(env), expr.AllowUndefinedVariables(), // Allow to use undefined variables. } program, err := expr.Compile(code, options...) if err != nil { fmt.Printf("%v", err) return } output, err := expr.Run(program, env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v\n", output) env["name"] = "you" // Define variables later on. output, err = expr.Run(program, env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v\n", output) // Output: Hello, world! // Hello, you! } func ExampleAllowUndefinedVariables_zero_value() { code := `name == "" ? foo + bar : foo + name` // If environment has different zero values, then undefined variables // will have it as default value. env := map[string]string{} options := []expr.Option{ expr.Env(env), expr.AllowUndefinedVariables(), // Allow to use undefined variables. } program, err := expr.Compile(code, options...) if err != nil { fmt.Printf("%v", err) return } env = map[string]string{ "foo": "Hello, ", "bar": "world!", } output, err := expr.Run(program, env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) // Output: Hello, world! } func ExampleAllowUndefinedVariables_zero_value_functions() { code := `words == "" ? Split("foo,bar", ",") : Split(words, ",")` // Env is map[string]string type on which methods are defined. env := mock.MapStringStringEnv{} options := []expr.Option{ expr.Env(env), expr.AllowUndefinedVariables(), // Allow to use undefined variables. } program, err := expr.Compile(code, options...) if err != nil { fmt.Printf("%v", err) return } output, err := expr.Run(program, env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) // Output: [foo bar] } type patcher struct{} func (p *patcher) Visit(node *ast.Node) { switch n := (*node).(type) { case *ast.MemberNode: ast.Patch(node, &ast.CallNode{ Callee: &ast.IdentifierNode{Value: "get"}, Arguments: []ast.Node{n.Node, n.Property}, }) } } func ExamplePatch() { program, err := expr.Compile( `greet.you.world + "!"`, expr.Patch(&patcher{}), ) if err != nil { fmt.Printf("%v", err) return } env := map[string]any{ "greet": "Hello", "get": func(a, b string) string { return a + ", " + b }, } output, err := expr.Run(program, env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) // Output: Hello, you, world! } func ExampleWithContext() { env := map[string]any{ "fn": func(ctx context.Context, _, _ int) int { // An infinite loop that can be canceled by context. for { select { case <-ctx.Done(): return 42 } } }, "ctx": context.TODO(), // Context should be passed as a variable. } program, err := expr.Compile(`fn(1, 2)`, expr.Env(env), expr.WithContext("ctx"), // Pass context variable name. ) if err != nil { fmt.Printf("%v", err) return } // Cancel context after 100 milliseconds. ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond*100) defer cancel() // After program is compiled, context can be passed to Run. env["ctx"] = ctx // Run will return 42 after 100 milliseconds. output, err := expr.Run(program, env) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) // Output: 42 } func ExampleTimezone() { program, err := expr.Compile(`now().Location().String()`, expr.Timezone("Asia/Kamchatka")) if err != nil { fmt.Printf("%v", err) return } output, err := expr.Run(program, nil) if err != nil { fmt.Printf("%v", err) return } fmt.Printf("%v", output) // Output: Asia/Kamchatka } func TestExpr_readme_example(t *testing.T) { env := map[string]any{ "greet": "Hello, %v!", "names": []string{"world", "you"}, "sprintf": fmt.Sprintf, } code := `sprintf(greet, names[0])` program, err := expr.Compile(code, expr.Env(env)) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, "Hello, world!", output) } func TestExpr(t *testing.T) { date := time.Date(2017, time.October, 23, 18, 30, 0, 0, time.UTC) oneDay, _ := time.ParseDuration("24h") timeNowPlusOneDay := date.Add(oneDay) env := mock.Env{ Embed: mock.Embed{}, Ambiguous: "", Any: nil, Bool: true, Float: 0, Int64: 0, Int32: 0, Int: 0, One: 1, Two: 2, Uint32: 0, String: "string", BoolPtr: nil, FloatPtr: nil, IntPtr: nil, IntPtrPtr: nil, StringPtr: nil, Foo: mock.Foo{ Value: "foo", Bar: mock.Bar{ Baz: "baz", }, }, Abstract: nil, ArrayOfAny: nil, ArrayOfInt: []int{1, 2, 3, 4, 5}, ArrayOfFoo: []*mock.Foo{{Value: "foo"}, {Value: "bar"}, {Value: "baz"}}, MapOfFoo: nil, MapOfAny: nil, FuncParam: nil, FuncParamAny: nil, FuncTooManyReturns: nil, FuncNamed: nil, NilAny: nil, NilFn: nil, NilStruct: nil, Variadic: func(head int, xs ...int) bool { sum := 0 for _, x := range xs { sum += x } return head == sum }, Fast: nil, Time: date, TimePlusDay: timeNowPlusOneDay, Duration: oneDay, } tests := []struct { code string want any }{ { `1`, 1, }, { `-.5`, -.5, }, { `true && false || false`, false, }, { `Int == 0 && Int32 == 0 && Int64 == 0 && Float64 == 0 && Bool && String == "string"`, true, }, { `-Int64 == 0`, true, }, { `"a" != "b"`, true, }, { `"a" != "b" || 1 == 2`, true, }, { `Int + 0`, 0, }, { `Uint64 + 0`, 0, }, { `Uint64 + Int64`, 0, }, { `Int32 + Int64`, 0, }, { `Float64 + 0`, float64(0), }, { `0 + Float64`, float64(0), }, { `0 <= Float64`, true, }, { `Float64 < 1`, true, }, { `Int < 1`, true, }, { `2 + 2 == 4`, true, }, { `8 % 3`, 2, }, { `2 ** 8`, float64(256), }, { `2 ^ 8`, float64(256), }, { `-(2-5)**3-2/(+4-3)+-2`, float64(23), }, { `"hello" + " " + "world"`, "hello world", }, { `0 in -1..1 and 1 in 1..1`, true, }, { `Int in 0..1`, true, }, { `Int32 in 0..1`, true, }, { `Int64 in 0..1`, true, }, { `1 in [1, 2, 3] && "foo" in {foo: 0, bar: 1} && "Bar" in Foo`, true, }, { `1 in [1.5] || 1 not in [1]`, false, }, { `One in 0..1 && Two not in 0..1`, true, }, { `Two not in 0..1`, true, }, { `Two not in 0..1`, true, }, { `-1 not in [1]`, true, }, { `Int32 in [10, 20]`, false, }, { `String matches "s.+"`, true, }, { `String matches ("^" + String + "$")`, true, }, { `'foo' + 'bar' not matches 'foobar'`, false, }, { `"foobar" contains "bar"`, true, }, { `"foobar" startsWith "foo"`, true, }, { `"foobar" endsWith "bar"`, true, }, { `(0..10)[5]`, 5, }, { `Foo.Bar.Baz`, "baz", }, { `Add(10, 5) + GetInt()`, 15, }, { `Foo.Method().Baz`, `baz (from Foo.Method)`, }, { `Foo.MethodWithArgs("prefix ")`, "prefix foo", }, { `len([1, 2, 3])`, 3, }, { `len([1, Two, 3])`, 3, }, { `len(["hello", "world"])`, 2, }, { `len("hello, world")`, 12, }, { `len('北京')`, 2, }, { `len('👍🏻')`, // one grapheme cluster, two code points 2, }, { `len('👍')`, // one grapheme cluster, one code point 1, }, { `len(ArrayOfInt)`, 5, }, { `len({a: 1, b: 2, c: 2})`, 3, }, { `max([1, 2, 3])`, 3, }, { `max(1, 2, 3)`, 3, }, { `min([1, 2, 3])`, 1, }, { `min(1, 2, 3)`, 1, }, { `{foo: 0, bar: 1}`, map[string]any{"foo": 0, "bar": 1}, }, { `{foo: 0, bar: 1}`, map[string]any{"foo": 0, "bar": 1}, }, { `(true ? 0+1 : 2+3) + (false ? -1 : -2)`, -1, }, { `filter(1..9, {# > 7})`, []any{8, 9}, }, { `map(1..3, {# * #})`, []any{1, 4, 9}, }, { `all(1..3, {# > 0})`, true, }, { `count(1..30, {# % 3 == 0})`, 10, }, { `count([true, true, false])`, 2, }, { `"a" < "b"`, true, }, { `Time.Sub(Time).String() == "0s"`, true, }, { `1 + 1`, 2, }, { `(One * Two) * 3 == One * (Two * 3)`, true, }, { `ArrayOfInt[1]`, 2, }, { `ArrayOfInt[0] < ArrayOfInt[1]`, true, }, { `ArrayOfInt[-1]`, 5, }, { `ArrayOfInt[1:2]`, []int{2}, }, { `ArrayOfInt[1:4]`, []int{2, 3, 4}, }, { `ArrayOfInt[-4:-1]`, []int{2, 3, 4}, }, { `ArrayOfInt[:3]`, []int{1, 2, 3}, }, { `ArrayOfInt[3:]`, []int{4, 5}, }, { `ArrayOfInt[0:5] == ArrayOfInt`, true, }, { `ArrayOfInt[0:] == ArrayOfInt`, true, }, { `ArrayOfInt[:5] == ArrayOfInt`, true, }, { `ArrayOfInt[:] == ArrayOfInt`, true, }, { `4 in 5..1`, false, }, { `4..0`, []int{}, }, { `NilStruct`, (*mock.Foo)(nil), }, { `NilAny == nil && nil == NilAny && nil == nil && NilAny == NilAny && NilInt == nil && NilSlice == nil && NilStruct == nil`, true, }, { `0 == nil || "str" == nil || true == nil`, false, }, { `Variadic(6, 1, 2, 3)`, true, }, { `Variadic(0)`, true, }, { `String[:]`, "string", }, { `String[:3]`, "str", }, { `String[:9]`, "string", }, { `String[3:9]`, "ing", }, { `String[7:9]`, "", }, { `map(filter(ArrayOfInt, # >= 3), # + 1)`, []any{4, 5, 6}, }, { `Time < Time + Duration`, true, }, { `Time + Duration > Time`, true, }, { `Time == Time`, true, }, { `Time >= Time`, true, }, { `Time <= Time`, true, }, { `Time == Time + Duration`, false, }, { `Time != Time`, false, }, { `TimePlusDay - Duration`, date, }, { `duration("1h") == duration("1h")`, true, }, { `TimePlusDay - Time >= duration("24h")`, true, }, { `duration("1h") > duration("1m")`, true, }, { `duration("1h") < duration("1m")`, false, }, { `duration("1h") >= duration("1m")`, true, }, { `duration("1h") <= duration("1m")`, false, }, { `duration("1h") > duration("1m")`, true, }, { `duration("1h") + duration("1m")`, time.Hour + time.Minute, }, { `duration("1h") - duration("1m")`, time.Hour - time.Minute, }, { `7 * duration("1h")`, 7 * time.Hour, }, { `duration("1h") * 7`, 7 * time.Hour, }, { `duration("1s") * .5`, 5e8, }, { `1 /* one */ + 2 // two`, 3, }, { `let x = 1; x + 2`, 3, }, { `map(1..3, let x = #; let y = x * x; y * y)`, []any{1, 16, 81}, }, { `map(1..2, let x = #; map(2..3, let y = #; x + y))`, []any{[]any{3, 4}, []any{4, 5}}, }, { `len(filter(1..99, # % 7 == 0))`, 14, }, { `find(ArrayOfFoo, .Value == "baz")`, env.ArrayOfFoo[2], }, { `findIndex(ArrayOfFoo, .Value == "baz")`, 2, }, { `filter(ArrayOfFoo, .Value == "baz")[0]`, env.ArrayOfFoo[2], }, { `first(filter(ArrayOfFoo, .Value == "baz"))`, env.ArrayOfFoo[2], }, { `first(filter(ArrayOfFoo, false))`, nil, }, { `findLast(1..9, # % 2 == 0)`, 8, }, { `findLastIndex(1..9, # % 2 == 0)`, 7, }, { `filter(1..9, # % 2 == 0)[-1]`, 8, }, { `last(filter(1..9, # % 2 == 0))`, 8, }, { `map(filter(1..9, # % 2 == 0), # * 2)`, []any{4, 8, 12, 16}, }, { `map(map(filter(1..9, # % 2 == 0), # * 2), # * 2)`, []any{8, 16, 24, 32}, }, { `first(map(filter(1..9, # % 2 == 0), # * 2))`, 4, }, { `map(filter(1..9, # % 2 == 0), # * 2)[-1]`, 16, }, { `len(map(filter(1..9, # % 2 == 0), # * 2))`, 4, }, { `len(filter(map(1..9, # * 2), # % 2 == 0))`, 9, }, { `first(filter(map(1..9, # * 2), # % 2 == 0))`, 2, }, { `first(map(filter(1..9, # % 2 == 0), # * 2))`, 4, }, { `2^3 == 8`, true, }, { `4/2 == 2`, true, }, { `.5 in 0..1`, false, }, { `.5 in ArrayOfInt`, false, }, { `bitnot(10)`, -11, }, { `bitxor(15, 32)`, 47, }, { `bitand(90, 34)`, 2, }, { `bitnand(35, 9)`, 34, }, { `bitor(10, 5)`, 15, }, { `bitshr(7, 2)`, 1, }, { `bitshl(7, 2)`, 28, }, { `bitushr(-100, 5)`, 576460752303423484, }, { `"hello"[1:3]`, "el", }, { `[1, 2, 3]?.[0]`, 1, }, { `[[1, 2], 3, 4]?.[0]?.[1]`, 2, }, { `[nil, 3, 4]?.[0]?.[1]`, nil, }, { `1 > 2 < 3`, false, }, { `1 < 2 < 3`, true, }, { `1 < 2 < 3 > 4`, false, }, { `1 < 2 < 3 > 2`, true, }, { `1 < 2 < 3 == true`, true, }, { `if 1 > 2 { 333 * 2 + 1 } else { 444 }`, 444, }, { `let a = 3; let b = 2; if a>b {let c = Add(a, b); c+1} else {Add(10, b)} `, 6, }, { `if "a" < "b" {let x = "a"; x} else {"abc"}`, "a", }, { `if 1 == 2 { "no" } else if 1 == 1 { "yes" } else { "maybe" }`, "yes", }, { `1; 2; 3`, 3, }, { `let a = 1; Add(2, 2); let b = 2; a + b`, 3, }, } for _, tt := range tests { t.Run(tt.code, func(t *testing.T) { { program, err := expr.Compile(tt.code, expr.Env(mock.Env{})) require.NoError(t, err, "compile error") got, err := expr.Run(program, env) require.NoError(t, err, "run error") assert.Equal(t, tt.want, got) } { program, err := expr.Compile(tt.code, expr.Optimize(false)) require.NoError(t, err, "unoptimized") got, err := expr.Run(program, env) require.NoError(t, err, "unoptimized") assert.Equal(t, tt.want, got, "unoptimized") } { got, err := expr.Eval(tt.code, env) require.NoError(t, err, "eval") assert.Equal(t, tt.want, got, "eval") } { program, err := expr.Compile(tt.code, expr.Env(mock.Env{}), expr.Optimize(false)) require.NoError(t, err) code := program.Node().String() got, err := expr.Eval(code, env) require.NoError(t, err, code) assert.Equal(t, tt.want, got, code) } }) } } func TestExpr_error(t *testing.T) { env := mock.Env{ ArrayOfAny: []any{1, "2", 3, true}, } tests := []struct { code string want string }{ { `filter(1..9, # > 9)[0]`, `reflect: slice index out of range (1:20) | filter(1..9, # > 9)[0] | ...................^`, }, { `ArrayOfAny[-7]`, `index out of range: -3 (array length is 4) (1:11) | ArrayOfAny[-7] | ..........^`, }, { `reduce(10..1, # + #acc)`, `reduce of empty array with no initial value (1:1) | reduce(10..1, # + #acc) | ^`, }, } for _, tt := range tests { t.Run(tt.code, func(t *testing.T) { program, err := expr.Compile(tt.code, expr.Env(mock.Env{})) require.NoError(t, err) _, err = expr.Run(program, env) require.Error(t, err) assert.Equal(t, tt.want, err.Error()) }) } } func TestExpr_optional_chaining(t *testing.T) { env := map[string]any{} program, err := expr.Compile("foo?.bar.baz", expr.Env(env), expr.AllowUndefinedVariables()) require.NoError(t, err) got, err := expr.Run(program, env) require.NoError(t, err) assert.Equal(t, nil, got) } func TestExpr_optional_chaining_property(t *testing.T) { env := map[string]any{ "foo": map[string]any{}, } program, err := expr.Compile("foo.bar?.baz", expr.Env(env)) require.NoError(t, err) got, err := expr.Run(program, env) require.NoError(t, err) assert.Equal(t, nil, got) } func TestExpr_optional_chaining_nested_chains(t *testing.T) { env := map[string]any{ "foo": map[string]any{ "id": 1, "bar": []map[string]any{ 1: { "baz": "baz", }, }, }, } program, err := expr.Compile("foo?.bar[foo?.id]?.baz", expr.Env(env)) require.NoError(t, err) got, err := expr.Run(program, env) require.NoError(t, err) assert.Equal(t, "baz", got) } func TestExpr_optional_chaining_array(t *testing.T) { env := map[string]any{} program, err := expr.Compile("foo?.[1]?.[2]?.[3]", expr.Env(env), expr.AllowUndefinedVariables()) require.NoError(t, err) got, err := expr.Run(program, env) require.NoError(t, err) assert.Equal(t, nil, got) } func TestExpr_eval_with_env(t *testing.T) { _, err := expr.Eval("true", expr.Env(map[string]any{})) assert.Error(t, err) assert.Contains(t, err.Error(), "misused") } func TestExpr_fetch_from_func(t *testing.T) { _, err := expr.Eval("foo.Value", map[string]any{ "foo": func() {}, }) assert.Error(t, err) assert.Contains(t, err.Error(), "cannot fetch Value from func()") } func TestExpr_map_default_values(t *testing.T) { env := map[string]any{ "foo": map[string]string{}, "bar": map[string]*string{}, } input := `foo['missing'] == '' && bar['missing'] == nil` program, err := expr.Compile(input, expr.Env(env)) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, true, output) } func TestExpr_map_default_values_compile_check(t *testing.T) { tests := []struct { env any input string }{ { mock.MapStringStringEnv{"foo": "bar"}, `Split(foo, sep)`, }, { mock.MapStringIntEnv{"foo": 1}, `foo / bar`, }, } for _, tt := range tests { _, err := expr.Compile(tt.input, expr.Env(tt.env), expr.AllowUndefinedVariables()) require.NoError(t, err) } } func TestExpr_calls_with_nil(t *testing.T) { env := map[string]any{ "equals": func(a, b any) any { assert.Nil(t, a, "a is not nil") assert.Nil(t, b, "b is not nil") return a == b }, "is": mock.Is{}, } p, err := expr.Compile( "a == nil && equals(b, nil) && is.Nil(c)", expr.Env(env), expr.Operator("==", "equals"), expr.AllowUndefinedVariables(), ) require.NoError(t, err) out, err := expr.Run(p, env) require.NoError(t, err) require.Equal(t, true, out) } func TestExpr_call_float_arg_func_with_int(t *testing.T) { env := map[string]any{ "cnv": func(f float64) any { return f }, } tests := []struct { input string expected float64 }{ {"-1", -1.0}, {"1+1", 2.0}, {"+1", 1.0}, {"1-1", 0.0}, {"1/1", 1.0}, {"1*1", 1.0}, {"1^1", 1.0}, } for _, tt := range tests { t.Run(tt.input, func(t *testing.T) { p, err := expr.Compile(fmt.Sprintf("cnv(%s)", tt.input), expr.Env(env)) require.NoError(t, err) out, err := expr.Run(p, env) require.NoError(t, err) require.Equal(t, tt.expected, out) }) } } func TestConstExpr_error_panic(t *testing.T) { env := map[string]any{ "divide": func(a, b int) int { return a / b }, } _, err := expr.Compile( `1 + divide(1, 0)`, expr.Env(env), expr.ConstExpr("divide"), ) require.Error(t, err) require.Equal(t, "compile error: integer divide by zero (1:5)\n | 1 + divide(1, 0)\n | ....^", err.Error()) } type divideError struct{ Message string } func (e divideError) Error() string { return e.Message } func TestConstExpr_error_as_error(t *testing.T) { env := map[string]any{ "divide": func(a, b int) (int, error) { if b == 0 { return 0, divideError{"integer divide by zero"} } return a / b, nil }, } _, err := expr.Compile( `1 + divide(1, 0)`, expr.Env(env), expr.ConstExpr("divide"), ) require.Error(t, err) require.Equal(t, "integer divide by zero", err.Error()) require.IsType(t, divideError{}, err) } func TestConstExpr_error_wrong_type(t *testing.T) { env := map[string]any{ "divide": 0, } assert.Panics(t, func() { _, _ = expr.Compile( `1 + divide(1, 0)`, expr.Env(env), expr.ConstExpr("divide"), ) }) } func TestConstExpr_error_no_env(t *testing.T) { assert.Panics(t, func() { _, _ = expr.Compile( `1 + divide(1, 0)`, expr.ConstExpr("divide"), ) }) } var stringer = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() type stringerPatcher struct{} func (p *stringerPatcher) Visit(node *ast.Node) { t := (*node).Type() if t == nil { return } if t.Implements(stringer) { ast.Patch(node, &ast.CallNode{ Callee: &ast.MemberNode{ Node: *node, Property: &ast.StringNode{Value: "String"}, }, }) } } func TestPatch(t *testing.T) { program, err := expr.Compile( `Foo == "Foo.String"`, expr.Env(mock.Env{}), expr.Patch(&mock.StringerPatcher{}), ) require.NoError(t, err) output, err := expr.Run(program, mock.Env{}) require.NoError(t, err) require.Equal(t, true, output) } func TestCompile_exposed_error(t *testing.T) { _, err := expr.Compile(`1 == true`) require.Error(t, err) fileError, ok := err.(*file.Error) require.True(t, ok, "error should be of type *file.Error") require.Equal(t, "invalid operation: == (mismatched types int and bool) (1:3)\n | 1 == true\n | ..^", fileError.Error()) require.Equal(t, 2, fileError.Column) require.Equal(t, 1, fileError.Line) b, err := json.Marshal(err) require.NoError(t, err) require.Equal(t, `{"from":2,"to":4,"line":1,"column":2,"message":"invalid operation: == (mismatched types int and bool)","snippet":"\n | 1 == true\n | ..^","prev":null}`, string(b), ) } func TestAsBool_exposed_error(t *testing.T) { _, err := expr.Compile(`42`, expr.AsBool()) require.Error(t, err) _, ok := err.(*file.Error) require.False(t, ok, "error must not be of type *file.Error") require.Equal(t, "expected bool, but got int", err.Error()) } func TestEval_exposed_error(t *testing.T) { _, err := expr.Eval(`1 % 0`, nil) require.Error(t, err) fileError, ok := err.(*file.Error) require.True(t, ok, "error should be of type *file.Error") require.Equal(t, "runtime error: integer divide by zero (1:3)\n | 1 % 0\n | ..^", fileError.Error()) require.Equal(t, 2, fileError.Column) require.Equal(t, 1, fileError.Line) } func TestCompile_exposed_error_with_multiline_script(t *testing.T) { _, err := expr.Compile("{\n\ta: 1,\n\tb: #,\n\tc: 3,\n}") require.Error(t, err) fileError, ok := err.(*file.Error) require.True(t, ok, "error should be of type *file.Error") require.Equal(t, "unexpected token Operator(\"#\") (3:5)\n | b: #,\n | ....^", fileError.Error()) require.Equal(t, 4, fileError.Column) require.Equal(t, 3, fileError.Line) } func TestIssue105(t *testing.T) { type A struct { Field string } type B struct { Field int } type C struct { A B } type Env struct { C } code := ` A.Field == '' && C.A.Field == '' && B.Field == 0 && C.B.Field == 0 ` _, err := expr.Compile(code, expr.Env(Env{})) require.NoError(t, err) } func TestIssue_nested_closures(t *testing.T) { code := `all(1..3, { all(1..3, { # > 0 }) and # > 0 })` program, err := expr.Compile(code) require.NoError(t, err) output, err := expr.Run(program, nil) require.NoError(t, err) require.True(t, output.(bool)) } func TestIssue138(t *testing.T) { env := map[string]any{} _, err := expr.Compile(`1 / (1 - 1)`, expr.Env(env)) require.NoError(t, err) _, err = expr.Compile(`1 % 0`, expr.Env(env)) require.Error(t, err) require.Equal(t, "integer divide by zero (1:3)\n | 1 % 0\n | ..^", err.Error()) } func TestIssue154(t *testing.T) { type Data struct { Array *[2]any Slice *[]any Map *map[string]any String *string } type Env struct { Data *Data } b := true i := 10 s := "value" Array := [2]any{ &b, &i, } Slice := []any{ &b, &i, } Map := map[string]any{ "Bool": &b, "Int": &i, } env := Env{ Data: &Data{ Array: &Array, Slice: &Slice, Map: &Map, String: &s, }, } tests := []string{ `Data.Array[0] == true`, `Data.Array[1] == 10`, `Data.Slice[0] == true`, `Data.Slice[1] == 10`, `Data.Map["Bool"] == true`, `Data.Map["Int"] == 10`, `Data.String == "value"`, } for _, input := range tests { program, err := expr.Compile(input, expr.Env(env)) require.NoError(t, err, input) output, err := expr.Run(program, env) require.NoError(t, err) assert.True(t, output.(bool), input) } } func TestIssue270(t *testing.T) { env := map[string]any{ "int8": int8(1), "int16": int16(3), "int32": int32(5), "int64": int64(7), "uint8": uint8(11), "uint16": uint16(13), "uint32": uint32(17), "uint64": uint64(19), "int8a": uint(23), "int8b": uint(29), "int16a": uint(31), "int16b": uint(37), "int32a": uint(41), "int32b": uint(43), "int64a": uint(47), "int64b": uint(53), "uint8a": uint(59), "uint8b": uint(61), "uint16a": uint(67), "uint16b": uint(71), "uint32a": uint(73), "uint32b": uint(79), "uint64a": uint(83), "uint64b": uint(89), "float32a": float32(97), "float32b": float32(101), "float64a": float64(103), "float64b": float64(107), } for _, each := range []struct { input string }{ {"int8 / int16"}, {"int32 / int64"}, {"uint8 / uint16"}, {"uint32 / uint64"}, {"int8 / uint64"}, {"int64 / uint8"}, {"int8a / int8b"}, {"int16a / int16b"}, {"int32a / int32b"}, {"int64a / int64b"}, {"uint8a / uint8b"}, {"uint16a / uint16b"}, {"uint32a / uint32b"}, {"uint64a / uint64b"}, {"float32a / float32b"}, {"float64a / float64b"}, } { p, err := expr.Compile(each.input, expr.Env(env)) require.NoError(t, err) out, err := expr.Run(p, env) require.NoError(t, err) require.IsType(t, float64(0), out) } } func TestIssue271(t *testing.T) { type BarArray []float64 type Foo struct { Bar BarArray Baz int } type Env struct { Foo Foo } code := `Foo.Bar[0]` program, err := expr.Compile(code, expr.Env(Env{})) require.NoError(t, err) output, err := expr.Run(program, Env{ Foo: Foo{ Bar: BarArray{1.0, 2.0, 3.0}, }, }) require.NoError(t, err) require.Equal(t, 1.0, output) } type Issue346Array []Issue346Type type Issue346Type struct { Bar string } func (i Issue346Array) Len() int { return len(i) } func TestIssue346(t *testing.T) { code := `Foo[0].Bar` env := map[string]any{ "Foo": Issue346Array{ {Bar: "bar"}, }, } program, err := expr.Compile(code, expr.Env(env)) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, "bar", output) } func TestCompile_allow_to_use_interface_to_get_an_element_from_map(t *testing.T) { code := `{"value": "ok"}[vars.key]` env := map[string]any{ "vars": map[string]any{ "key": "value", }, } program, err := expr.Compile(code, expr.Env(env)) assert.NoError(t, err) out, err := expr.Run(program, env) assert.NoError(t, err) assert.Equal(t, "ok", out) t.Run("with allow undefined variables", func(t *testing.T) { code := `{'key': 'value'}[Key]` env := mock.MapStringStringEnv{} options := []expr.Option{ expr.AllowUndefinedVariables(), } program, err := expr.Compile(code, options...) assert.NoError(t, err) out, err := expr.Run(program, env) assert.NoError(t, err) assert.Equal(t, nil, out) }) } func TestFastCall(t *testing.T) { env := map[string]any{ "func": func(in any) float64 { return 8 }, } code := `func("8")` program, err := expr.Compile(code, expr.Env(env)) assert.NoError(t, err) out, err := expr.Run(program, env) assert.NoError(t, err) assert.Equal(t, float64(8), out) } func TestFastCall_OpCallFastErr(t *testing.T) { env := map[string]any{ "func": func(...any) (any, error) { return 8, nil }, } code := `func("8")` program, err := expr.Compile(code, expr.Env(env)) assert.NoError(t, err) out, err := expr.Run(program, env) assert.NoError(t, err) assert.Equal(t, 8, out) } func TestRun_custom_func_returns_an_error_as_second_arg(t *testing.T) { env := map[string]any{ "semver": func(value string, cmp string) (bool, error) { return true, nil }, } p, err := expr.Compile(`semver("1.2.3", "= 1.2.3")`, expr.Env(env)) assert.NoError(t, err) out, err := expr.Run(p, env) assert.NoError(t, err) assert.Equal(t, true, out) } func TestFunction(t *testing.T) { add := expr.Function( "add", func(p ...any) (any, error) { out := 0 for _, each := range p { out += each.(int) } return out, nil }, new(func(...int) int), ) p, err := expr.Compile(`add() + add(1) + add(1, 2) + add(1, 2, 3) + add(1, 2, 3, 4)`, add) assert.NoError(t, err) out, err := expr.Run(p, nil) assert.NoError(t, err) assert.Equal(t, 20, out) } // Nil coalescing operator func TestRun_NilCoalescingOperator(t *testing.T) { env := map[string]any{ "foo": map[string]any{ "bar": "value", }, } t.Run("value", func(t *testing.T) { p, err := expr.Compile(`foo.bar ?? "default"`, expr.Env(env)) assert.NoError(t, err) out, err := expr.Run(p, env) assert.NoError(t, err) assert.Equal(t, "value", out) }) t.Run("default", func(t *testing.T) { p, err := expr.Compile(`foo.baz ?? "default"`, expr.Env(env)) assert.NoError(t, err) out, err := expr.Run(p, env) assert.NoError(t, err) assert.Equal(t, "default", out) }) t.Run("default with chain", func(t *testing.T) { p, err := expr.Compile(`foo?.bar ?? "default"`, expr.Env(env)) assert.NoError(t, err) out, err := expr.Run(p, map[string]any{}) assert.NoError(t, err) assert.Equal(t, "default", out) }) } func TestEval_nil_in_maps(t *testing.T) { env := map[string]any{ "m": map[any]any{nil: "bar"}, "empty": map[any]any{}, } t.Run("nil key exists", func(t *testing.T) { p, err := expr.Compile(`m[nil]`, expr.Env(env)) assert.NoError(t, err) out, err := expr.Run(p, env) assert.NoError(t, err) assert.Equal(t, "bar", out) }) t.Run("no nil key", func(t *testing.T) { p, err := expr.Compile(`empty[nil]`, expr.Env(env)) assert.NoError(t, err) out, err := expr.Run(p, env) assert.NoError(t, err) assert.Equal(t, nil, out) }) t.Run("nil in m", func(t *testing.T) { p, err := expr.Compile(`nil in m`, expr.Env(env)) assert.NoError(t, err) out, err := expr.Run(p, env) assert.NoError(t, err) assert.Equal(t, true, out) }) t.Run("nil in empty", func(t *testing.T) { p, err := expr.Compile(`nil in empty`, expr.Env(env)) assert.NoError(t, err) out, err := expr.Run(p, env) assert.NoError(t, err) assert.Equal(t, false, out) }) } // Test the use of env keyword. Forms env[] and env[”] are valid. // The enclosed identifier must be in the expression env. func TestEnv_keyword(t *testing.T) { env := map[string]any{ "space test": "ok", "space_test": "not ok", // Seems to be some underscore substituting happening, check that. "Section 1-2a": "ok", `c:\ndrive\2015 Information Table`: "ok", "%*worst function name ever!!": func() string { return "ok" }(), "1": "o", "2": "k", "num": 10, "mylist": []int{1, 2, 3, 4, 5}, "MIN": func(a, b int) int { if a < b { return a } else { return b } }, "red": "n", "irect": "um", "String Map": map[string]string{ "one": "two", "three": "four", }, "OtherMap": map[string]string{ "a": "b", "c": "d", }, } // No error cases var tests = []struct { code string want any }{ {"$env['space test']", "ok"}, {"$env['Section 1-2a']", "ok"}, {`$env["c:\\ndrive\\2015 Information Table"]`, "ok"}, {"$env['%*worst function name ever!!']", "ok"}, {"$env['String Map'].one", "two"}, {"$env['1'] + $env['2']", "ok"}, {"1 + $env['num'] + $env['num']", 21}, {"MIN($env['num'],0)", 0}, {"$env['nu' + 'm']", 10}, {"$env[red + irect]", 10}, {"$env['String Map']?.five", ""}, {"$env.red", "n"}, {"$env?.unknown", nil}, {"$env.mylist[1]", 2}, {"$env?.OtherMap?.a", "b"}, {"$env?.OtherMap?.d", ""}, {"'num' in $env", true}, {"get($env, 'num')", 10}, } for _, tt := range tests { t.Run(tt.code, func(t *testing.T) { program, err := expr.Compile(tt.code, expr.Env(env)) require.NoError(t, err, "compile error") got, err := expr.Run(program, env) require.NoError(t, err, "execution error") assert.Equal(t, tt.want, got, tt.code) }) } for _, tt := range tests { t.Run(tt.code, func(t *testing.T) { got, err := expr.Eval(tt.code, env) require.NoError(t, err, "eval error: "+tt.code) assert.Equal(t, tt.want, got, "eval: "+tt.code) }) } // error cases tests = []struct { code string want any }{ {"env()", "bad"}, } for _, tt := range tests { t.Run(tt.code, func(t *testing.T) { _, err := expr.Eval(tt.code, expr.Env(env)) require.Error(t, err, "compile error") }) } } func TestEnv_keyword_with_custom_functions(t *testing.T) { fn := expr.Function("fn", func(params ...any) (any, error) { return "ok", nil }) var tests = []struct { code string error bool }{ {`fn()`, false}, {`$env.fn()`, true}, {`$env["fn"]`, true}, } for _, tt := range tests { t.Run(tt.code, func(t *testing.T) { _, err := expr.Compile(tt.code, expr.Env(mock.Env{}), fn) if tt.error { require.Error(t, err) } else { require.NoError(t, err) } }) } } func TestIssue401(t *testing.T) { program, err := expr.Compile("(a - b + c) / d", expr.AllowUndefinedVariables()) require.NoError(t, err, "compile error") output, err := expr.Run(program, map[string]any{ "a": 1, "b": 2, "c": 3, "d": 4, }) require.NoError(t, err, "run error") require.Equal(t, 0.5, output) } func TestEval_slices_out_of_bound(t *testing.T) { tests := []struct { code string want any }{ {"[1, 2, 3][:99]", []any{1, 2, 3}}, {"[1, 2, 3][99:]", []any{}}, {"[1, 2, 3][:-99]", []any{}}, {"[1, 2, 3][-99:]", []any{1, 2, 3}}, } for _, tt := range tests { t.Run(tt.code, func(t *testing.T) { got, err := expr.Eval(tt.code, nil) require.NoError(t, err, "eval error: "+tt.code) assert.Equal(t, tt.want, got, "eval: "+tt.code) }) } } func TestExpr_timeout(t *testing.T) { tests := []struct{ code string }{ {`-999999..999999`}, {`map(1..999999, 1..999999)`}, {`map(1..999999, repeat('a', #))`}, } for _, tt := range tests { t.Run(tt.code, func(t *testing.T) { program, err := expr.Compile(tt.code) require.NoError(t, err) timeout := make(chan bool, 1) go func() { time.Sleep(time.Second) timeout <- true }() done := make(chan bool, 1) go func() { out, err := expr.Run(program, nil) // Make sure out is used. _ = fmt.Sprintf("%v", out) assert.Error(t, err) done <- true }() select { case <-done: // Success. case <-timeout: t.Fatal("timeout") } }) } } func TestIssue432(t *testing.T) { env := map[string]any{ "func": func( paramUint32 uint32, paramUint16 uint16, paramUint8 uint8, paramUint uint, paramInt32 int32, paramInt16 int16, paramInt8 int8, paramInt int, paramFloat64 float64, paramFloat32 float32, ) float64 { return float64(paramUint32) + float64(paramUint16) + float64(paramUint8) + float64(paramUint) + float64(paramInt32) + float64(paramInt16) + float64(paramInt8) + float64(paramInt) + float64(paramFloat64) + float64(paramFloat32) }, } code := `func(1,1,1,1,1,1,1,1,1,1)` program, err := expr.Compile(code, expr.Env(env)) assert.NoError(t, err) out, err := expr.Run(program, env) assert.NoError(t, err) assert.Equal(t, float64(10), out) } func TestIssue462(t *testing.T) { env := map[string]any{ "foo": func() (string, error) { return "bar", nil }, } _, err := expr.Compile(`$env.unknown(int())`, expr.Env(env)) require.Error(t, err) } func TestIssue_embedded_pointer_struct(t *testing.T) { var tests = []struct { input string env mock.Env want any }{ { input: "EmbedPointerEmbedInt > 0", env: mock.Env{ Embed: mock.Embed{ EmbedPointerEmbed: &mock.EmbedPointerEmbed{ EmbedPointerEmbedInt: 123, }, }, }, want: true, }, { input: "(Embed).EmbedPointerEmbedInt > 0", env: mock.Env{ Embed: mock.Embed{ EmbedPointerEmbed: &mock.EmbedPointerEmbed{ EmbedPointerEmbedInt: 123, }, }, }, want: true, }, { input: "(Embed).EmbedPointerEmbedInt > 0", env: mock.Env{ Embed: mock.Embed{ EmbedPointerEmbed: &mock.EmbedPointerEmbed{ EmbedPointerEmbedInt: 0, }, }, }, want: false, }, { input: "(Embed).EmbedPointerEmbedMethod(0)", env: mock.Env{ Embed: mock.Embed{ EmbedPointerEmbed: &mock.EmbedPointerEmbed{ EmbedPointerEmbedInt: 0, }, }, }, want: "", }, { input: "(Embed).EmbedPointerEmbedPointerReceiverMethod(0)", env: mock.Env{ Embed: mock.Embed{ EmbedPointerEmbed: nil, }, }, want: "", }, } for _, tt := range tests { t.Run(tt.input, func(t *testing.T) { program, err := expr.Compile(tt.input, expr.Env(tt.env)) require.NoError(t, err) out, err := expr.Run(program, tt.env) require.NoError(t, err) require.Equal(t, tt.want, out) }) } } func TestIssue474(t *testing.T) { testCases := []struct { code string fail bool }{ { code: `func("invalid")`, fail: true, }, { code: `func(true)`, fail: true, }, { code: `func([])`, fail: true, }, { code: `func({})`, fail: true, }, { code: `func(1)`, fail: false, }, { code: `func(1.5)`, fail: false, }, } for _, tc := range testCases { ltc := tc t.Run(ltc.code, func(t *testing.T) { t.Parallel() function := expr.Function("func", func(params ...any) (any, error) { return true, nil }, new(func(float64) bool)) _, err := expr.Compile(ltc.code, function) if ltc.fail { if err == nil { t.Error("expected an error, but it was nil") t.FailNow() } } else { if err != nil { t.Errorf("expected nil, but it was %v", err) t.FailNow() } } }) } } func TestRaceCondition_variables(t *testing.T) { program, err := expr.Compile(`let foo = 1; foo + 1`, expr.Env(mock.Env{})) require.NoError(t, err) var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) go func() { defer wg.Done() out, err := expr.Run(program, mock.Env{}) require.NoError(t, err) require.Equal(t, 2, out) }() } wg.Wait() } func TestOperatorDependsOnEnv(t *testing.T) { env := map[string]any{ "plus": func(a, b int) int { return 42 }, } program, err := expr.Compile(`1 + 2`, expr.Operator("+", "plus"), expr.Env(env)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) assert.Equal(t, 42, out) } func TestIssue624(t *testing.T) { type tag struct { Name string } type item struct { Tags []tag } i := item{ Tags: []tag{ {Name: "one"}, {Name: "two"}, }, } rule := `[ true && true, one(Tags, .Name in ["one"]), one(Tags, .Name in ["two"]), one(Tags, .Name in ["one"]) && one(Tags, .Name in ["two"]) ]` resp, err := expr.Eval(rule, i) require.NoError(t, err) require.Equal(t, []interface{}{true, true, true, true}, resp) } func TestPredicateCombination(t *testing.T) { tests := []struct { code1 string code2 string }{ {"all(1..3, {# > 0}) && all(1..3, {# < 4})", "all(1..3, {# > 0 && # < 4})"}, {"all(1..3, {# > 1}) && all(1..3, {# < 4})", "all(1..3, {# > 1 && # < 4})"}, {"all(1..3, {# > 0}) && all(1..3, {# < 2})", "all(1..3, {# > 0 && # < 2})"}, {"all(1..3, {# > 1}) && all(1..3, {# < 2})", "all(1..3, {# > 1 && # < 2})"}, {"any(1..3, {# > 0}) || any(1..3, {# < 4})", "any(1..3, {# > 0 || # < 4})"}, {"any(1..3, {# > 1}) || any(1..3, {# < 4})", "any(1..3, {# > 1 || # < 4})"}, {"any(1..3, {# > 0}) || any(1..3, {# < 2})", "any(1..3, {# > 0 || # < 2})"}, {"any(1..3, {# > 1}) || any(1..3, {# < 2})", "any(1..3, {# > 1 || # < 2})"}, {"none(1..3, {# > 0}) && none(1..3, {# < 4})", "none(1..3, {# > 0 || # < 4})"}, {"none(1..3, {# > 1}) && none(1..3, {# < 4})", "none(1..3, {# > 1 || # < 4})"}, {"none(1..3, {# > 0}) && none(1..3, {# < 2})", "none(1..3, {# > 0 || # < 2})"}, {"none(1..3, {# > 1}) && none(1..3, {# < 2})", "none(1..3, {# > 1 || # < 2})"}, } for _, tt := range tests { t.Run(tt.code1, func(t *testing.T) { out1, err := expr.Eval(tt.code1, nil) require.NoError(t, err) out2, err := expr.Eval(tt.code2, nil) require.NoError(t, err) require.Equal(t, out1, out2) }) } } func TestArrayComparison(t *testing.T) { tests := []struct { env any code string }{ {[]string{"A", "B"}, "foo == ['A', 'B']"}, {[]int{1, 2}, "foo == [1, 2]"}, {[]uint8{1, 2}, "foo == [1, 2]"}, {[]float64{1.1, 2.2}, "foo == [1.1, 2.2]"}, {[]any{"A", 1, 1.1, true}, "foo == ['A', 1, 1.1, true]"}, {[]string{"A", "B"}, "foo != [1, 2]"}, } for _, tt := range tests { t.Run(tt.code, func(t *testing.T) { env := map[string]any{"foo": tt.env} program, err := expr.Compile(tt.code, expr.Env(env)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, true, out) }) } } func TestIssue_570(t *testing.T) { type Student struct { Name string } env := map[string]any{ "student": (*Student)(nil), } program, err := expr.Compile("student?.Name", expr.Env(env)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) require.IsType(t, nil, out) } func TestIssue_integer_truncated_by_compiler(t *testing.T) { env := map[string]any{ "fn": func(x byte) byte { return x }, } _, err := expr.Compile("fn(255)", expr.Env(env)) require.NoError(t, err) _, err = expr.Compile("fn(256)", expr.Env(env)) require.Error(t, err) } func TestExpr_crash(t *testing.T) { content, err := os.ReadFile("testdata/crash.txt") require.NoError(t, err) _, err = expr.Compile(string(content)) require.Error(t, err) } func TestExpr_crash_with_zero(t *testing.T) { code := "if\x00" _, err := expr.Compile(code) require.Error(t, err) } func TestExpr_nil_op_str(t *testing.T) { // Let's test operators, which do `.(string)` in VM, also check for nil. var str *string = nil env := map[string]any{ "nilString": str, } tests := []struct{ code string }{ {`nilString == "str"`}, {`nilString contains "str"`}, {`nilString matches "str"`}, {`nilString startsWith "str"`}, {`nilString endsWith "str"`}, {`"str" == nilString`}, {`"str" contains nilString`}, {`"str" matches nilString`}, {`"str" startsWith nilString`}, {`"str" endsWith nilString`}, } for _, tt := range tests { t.Run(tt.code, func(t *testing.T) { program, err := expr.Compile(tt.code) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, false, output) }) } } func TestExpr_env_types_map(t *testing.T) { envTypes := types.Map{ "foo": types.Map{ "bar": types.String, }, } program, err := expr.Compile(`foo.bar`, expr.Env(envTypes)) require.NoError(t, err) env := map[string]any{ "foo": map[string]any{ "bar": "value", }, } output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, "value", output) } func TestExpr_env_types_map_error(t *testing.T) { envTypes := types.Map{ "foo": types.Map{ "bar": types.String, }, } program, err := expr.Compile(`foo.bar`, expr.Env(envTypes)) require.NoError(t, err) _, err = expr.Run(program, envTypes) require.Error(t, err) } func TestIssue758_filter_map_index(t *testing.T) { env := map[string]interface{}{} exprStr := ` let a_map = 0..5 | filter(# % 2 == 0) | map(#index); let b_filter = 0..5 | filter(# % 2 == 0); let b_map = b_filter | map(#index); [a_map, b_map] ` result, err := expr.Eval(exprStr, env) require.NoError(t, err) expected := []interface{}{ []interface{}{0, 1, 2}, []interface{}{0, 1, 2}, } require.Equal(t, expected, result) } func TestExpr_wierd_cases(t *testing.T) { env := map[string]any{} _, err := expr.Compile(`A(A)`, expr.Env(env)) require.Error(t, err) require.Contains(t, err.Error(), "unknown name A") } func TestIssue785_get_nil(t *testing.T) { exprStrs := []string{ `get(nil, "a")`, `get({}, "a")`, `get(nil, "a")`, `get({}, "a")`, `({} | get("a") | get("b"))`, } for _, exprStr := range exprStrs { t.Run("get returns nil", func(t *testing.T) { env := map[string]interface{}{} result, err := expr.Eval(exprStr, env) require.NoError(t, err) require.Equal(t, nil, result) }) } } func TestMaxNodes(t *testing.T) { maxNodes := uint(100) code := "" for i := 0; i < int(maxNodes); i++ { code += "1; " } _, err := expr.Compile(code, expr.MaxNodes(maxNodes)) require.Error(t, err) assert.Contains(t, err.Error(), "exceeds maximum allowed nodes") _, err = expr.Compile(code, expr.MaxNodes(maxNodes+1)) require.NoError(t, err) } func TestMaxNodesDisabled(t *testing.T) { code := "" for i := 0; i < 2*int(conf.DefaultMaxNodes); i++ { code += "1; " } _, err := expr.Compile(code, expr.MaxNodes(0)) require.NoError(t, err) } func TestMemoryBudget(t *testing.T) { tests := []struct { code string max int }{ {`map(1..100, {map(1..100, {map(1..100, {0})})})`, -1}, {`len(1..10000000)`, -1}, {`1..100`, 100}, } for _, tt := range tests { t.Run(tt.code, func(t *testing.T) { program, err := expr.Compile(tt.code) require.NoError(t, err, "compile error") vm := vm.VM{} if tt.max > 0 { vm.MemoryBudget = uint(tt.max) } _, err = vm.Run(program, nil) require.Error(t, err, "run error") assert.Contains(t, err.Error(), "memory budget exceeded") }) } } func TestIssue802(t *testing.T) { prog, err := expr.Compile(`arr[1:2][0]`) if err != nil { t.Fatalf("error compiling program: %v", err) } val, err := expr.Run(prog, map[string]any{ "arr": [5]int{0, 1, 2, 3, 4}, }) if err != nil { t.Fatalf("error running program: %v", err) } valInt, ok := val.(int) if !ok || valInt != 1 { t.Fatalf("invalid result, expected 1, got %v", val) } } func TestIssue807(t *testing.T) { type MyStruct struct { nonExported string } out, err := expr.Eval(` "nonExported" in $env `, MyStruct{}) if err != nil { t.Fatalf("unexpected error: %v", err) } b, ok := out.(bool) if !ok { t.Fatalf("expected boolean type, got %T: %v", b, b) } if b { t.Fatalf("expected 'in' operator to return false for unexported field") } } func TestDisableShortCircuit(t *testing.T) { count := 0 exprStr := "foo() or bar()" env := map[string]any{ "foo": func() bool { count++ return true }, "bar": func() bool { count++ return true }, } program, _ := expr.Compile(exprStr, expr.DisableShortCircuit()) got, _ := expr.Run(program, env) assert.Equal(t, 2, count) assert.True(t, got.(bool)) program, _ = expr.Compile(exprStr) got, _ = expr.Run(program, env) assert.Equal(t, 3, count) assert.True(t, got.(bool)) } func TestBytesLiteral(t *testing.T) { tests := []struct { code string want []byte }{ {`b"hello"`, []byte("hello")}, {`b'world'`, []byte("world")}, {`b""`, []byte{}}, {`b'\x00\xff'`, []byte{0, 255}}, {`b"\x41\x42\x43"`, []byte("ABC")}, {`b'\101\102\103'`, []byte("ABC")}, {`b'\n\t\r'`, []byte{'\n', '\t', '\r'}}, {`b'hello\x00world'`, []byte("hello\x00world")}, {`b"ÿ"`, []byte{0xc3, 0xbf}}, // UTF-8 encoding of ÿ } for _, tt := range tests { t.Run(tt.code, func(t *testing.T) { program, err := expr.Compile(tt.code) require.NoError(t, err) output, err := expr.Run(program, nil) require.NoError(t, err) assert.Equal(t, tt.want, output) }) } } func TestBytesLiteral_type(t *testing.T) { env := map[string]any{ "data": []byte("test"), } // Verify bytes literal has []byte type and can be compared with []byte program, err := expr.Compile(`data == b"test"`, expr.Env(env)) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) assert.Equal(t, true, output) } func TestBytesLiteral_errors(t *testing.T) { // \u and \U escapes should not be allowed in bytes literals errorCases := []string{ `b'\u0041'`, `b"\U00000041"`, } for _, code := range errorCases { t.Run(code, func(t *testing.T) { _, err := expr.Compile(code) require.Error(t, err) }) } } ================================================ FILE: file/error.go ================================================ package file import ( "fmt" "strings" ) type Error struct { Location Line int `json:"line"` Column int `json:"column"` Message string `json:"message"` Snippet string `json:"snippet"` Prev error `json:"prev"` } func (e *Error) Error() string { return e.format() } var tabReplacer = strings.NewReplacer("\t", " ") func (e *Error) Bind(source Source) *Error { src := source.String() var runeCount, lineStart int e.Line = 1 e.Column = 0 for i, r := range src { if runeCount == e.From { break } if r == '\n' { lineStart = i + 1 e.Line++ e.Column = 0 } else { e.Column++ } runeCount++ } lineEnd := lineStart + strings.IndexByte(src[lineStart:], '\n') if lineEnd < lineStart { lineEnd = len(src) } if lineStart == lineEnd { return e } const prefix = "\n | " line := src[lineStart:lineEnd] snippet := new(strings.Builder) snippet.Grow(2*len(prefix) + len(line) + e.Column + 1) snippet.WriteString(prefix) tabReplacer.WriteString(snippet, line) snippet.WriteString(prefix) for i := 0; i < e.Column; i++ { snippet.WriteByte('.') } snippet.WriteByte('^') e.Snippet = snippet.String() return e } func (e *Error) Unwrap() error { return e.Prev } func (e *Error) Wrap(err error) { e.Prev = err } func (e *Error) format() string { if e.Snippet == "" { return e.Message } return fmt.Sprintf( "%s (%d:%d)%s", e.Message, e.Line, e.Column+1, // add one to the 0-based column for display e.Snippet, ) } ================================================ FILE: file/location.go ================================================ package file type Location struct { From int `json:"from"` To int `json:"to"` } ================================================ FILE: file/source.go ================================================ package file import "strings" type Source struct { raw string } func NewSource(contents string) Source { return Source{ raw: contents, } } func (s Source) String() string { return s.raw } func (s Source) Snippet(line int) (string, bool) { if s.raw == "" { return "", false } var start int for i := 1; i < line; i++ { pos := strings.IndexByte(s.raw[start:], '\n') if pos < 0 { return "", false } start += pos + 1 } end := start + strings.IndexByte(s.raw[start:], '\n') if end < start { end = len(s.raw) } return s.raw[start:end], true } ================================================ FILE: file/source_test.go ================================================ package file import ( "testing" ) const ( unexpectedSnippet = "%s got snippet '%s', want '%v'" snippetNotFound = "%s snippet not found, wanted '%v'" snippetFound = "%s snippet found at Line %d, wanted none" ) func TestStringSource_SnippetMultiLine(t *testing.T) { source := NewSource("hello\nworld\nmy\nbub\n") if str, found := source.Snippet(1); !found { t.Errorf(snippetNotFound, t.Name(), 1) } else if str != "hello" { t.Errorf(unexpectedSnippet, t.Name(), str, "hello") } if str2, found := source.Snippet(2); !found { t.Errorf(snippetNotFound, t.Name(), 2) } else if str2 != "world" { t.Errorf(unexpectedSnippet, t.Name(), str2, "world") } if str3, found := source.Snippet(3); !found { t.Errorf(snippetNotFound, t.Name(), 3) } else if str3 != "my" { t.Errorf(unexpectedSnippet, t.Name(), str3, "my") } if str4, found := source.Snippet(4); !found { t.Errorf(snippetNotFound, t.Name(), 4) } else if str4 != "bub" { t.Errorf(unexpectedSnippet, t.Name(), str4, "bub") } if str5, found := source.Snippet(5); !found { t.Errorf(snippetNotFound, t.Name(), 5) } else if str5 != "" { t.Errorf(unexpectedSnippet, t.Name(), str5, "") } } func TestStringSource_SnippetSingleLine(t *testing.T) { source := NewSource("hello, world") if str, found := source.Snippet(1); !found { t.Errorf(snippetNotFound, t.Name(), 1) } else if str != "hello, world" { t.Errorf(unexpectedSnippet, t.Name(), str, "hello, world") } if str2, found := source.Snippet(2); found { t.Errorf(snippetFound, t.Name(), 2) } else if str2 != "" { t.Errorf(unexpectedSnippet, t.Name(), str2, "") } } ================================================ FILE: go.mod ================================================ module github.com/expr-lang/expr go 1.18 ================================================ FILE: internal/deref/deref.go ================================================ package deref import ( "fmt" "reflect" ) func Interface(p any) any { if p == nil { return nil } v := reflect.ValueOf(p) for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface { if v.IsNil() { return nil } v = v.Elem() } if v.IsValid() { return v.Interface() } panic(fmt.Sprintf("cannot dereference %v", p)) } func Type(t reflect.Type) reflect.Type { if t == nil { return nil } for t.Kind() == reflect.Ptr { t = t.Elem() } return t } func Value(v reflect.Value) reflect.Value { for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface { if v.IsNil() { return v } v = v.Elem() } return v } func TypeKind(t reflect.Type, k reflect.Kind) (_ reflect.Type, _ reflect.Kind, changed bool) { for k == reflect.Pointer { changed = true t = t.Elem() k = t.Kind() } return t, k, changed } ================================================ FILE: internal/deref/deref_test.go ================================================ package deref_test import ( "reflect" "testing" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr/internal/deref" ) func TestDeref(t *testing.T) { a := uint(42) b := &a c := &b d := &c got := deref.Interface(d) assert.Equal(t, uint(42), got) } func TestDeref_mix_ptr_with_interface(t *testing.T) { a := uint(42) var b any = &a var c any = &b d := &c got := deref.Interface(d) assert.Equal(t, uint(42), got) } func TestDeref_nil(t *testing.T) { var a *int assert.Nil(t, deref.Interface(a)) assert.Nil(t, deref.Interface(nil)) } func TestType(t *testing.T) { a := uint(42) b := &a c := &b d := &c dt := deref.Type(reflect.TypeOf(d)) assert.Equal(t, reflect.Uint, dt.Kind()) } func TestType_two_ptr_with_interface(t *testing.T) { a := uint(42) var b any = &a dt := deref.Type(reflect.TypeOf(b)) assert.Equal(t, reflect.Uint, dt.Kind()) } func TestType_three_ptr_with_interface(t *testing.T) { a := uint(42) var b any = &a var c any = &b dt := deref.Type(reflect.TypeOf(c)) assert.Equal(t, reflect.Interface, dt.Kind()) } func TestType_nil(t *testing.T) { assert.Nil(t, deref.Type(nil)) } func TestValue(t *testing.T) { a := uint(42) b := &a c := &b d := &c got := deref.Value(reflect.ValueOf(d)) assert.Equal(t, uint(42), got.Interface()) } func TestValue_two_ptr_with_interface(t *testing.T) { a := uint(42) var b any = &a got := deref.Value(reflect.ValueOf(b)) assert.Equal(t, uint(42), got.Interface()) } func TestValue_three_ptr_with_interface(t *testing.T) { a := uint(42) var b any = &a c := &b got := deref.Value(reflect.ValueOf(c)) assert.Equal(t, uint(42), got.Interface()) } func TestValue_nil(t *testing.T) { got := deref.Value(reflect.ValueOf(nil)) assert.False(t, got.IsValid()) } func TestValue_nil_in_chain(t *testing.T) { var a any = nil var b any = &a c := &b got := deref.Value(reflect.ValueOf(c)) assert.True(t, got.IsValid()) assert.True(t, got.IsNil()) assert.Nil(t, got.Interface()) } ================================================ FILE: internal/difflib/difflib.go ================================================ // Package difflib is a partial port of Python difflib module. // // It provides tools to compare sequences of strings and generate textual diffs. // // The following class and functions have been ported: // // - SequenceMatcher // // - unified_diff // // - context_diff // // Getting unified diffs was the main goal of the port. Keep in mind this code // is mostly suitable to output text differences in a human friendly way, there // are no guarantees generated diffs are consumable by patch(1). package difflib import ( "bufio" "bytes" "fmt" "io" "strings" ) func min(a, b int) int { if a < b { return a } return b } func max(a, b int) int { if a > b { return a } return b } func calculateRatio(matches, length int) float64 { if length > 0 { return 2.0 * float64(matches) / float64(length) } return 1.0 } type Match struct { A int B int Size int } type OpCode struct { Tag byte I1 int I2 int J1 int J2 int } // SequenceMatcher compares sequence of strings. The basic // algorithm predates, and is a little fancier than, an algorithm // published in the late 1980's by Ratcliff and Obershelp under the // hyperbolic name "gestalt pattern matching". The basic idea is to find // the longest contiguous matching subsequence that contains no "junk" // elements (R-O doesn't address junk). The same idea is then applied // recursively to the pieces of the sequences to the left and to the right // of the matching subsequence. This does not yield minimal edit // sequences, but does tend to yield matches that "look right" to people. // // SequenceMatcher tries to compute a "human-friendly diff" between two // sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the // longest *contiguous* & junk-free matching subsequence. That's what // catches peoples' eyes. The Windows(tm) windiff has another interesting // notion, pairing up elements that appear uniquely in each sequence. // That, and the method here, appear to yield more intuitive difference // reports than does diff. This method appears to be the least vulnerable // to synching up on blocks of "junk lines", though (like blank lines in // ordinary text files, or maybe "

" lines in HTML files). That may be // because this is the only method of the 3 that has a *concept* of // "junk" . // // Timing: Basic R-O is cubic time worst case and quadratic time expected // case. SequenceMatcher is quadratic time for the worst case and has // expected-case behavior dependent in a complicated way on how many // elements the sequences have in common; best case time is linear. type SequenceMatcher struct { a []string b []string b2j map[string][]int IsJunk func(string) bool autoJunk bool bJunk map[string]struct{} matchingBlocks []Match fullBCount map[string]int bPopular map[string]struct{} opCodes []OpCode } func NewMatcher(a, b []string) *SequenceMatcher { m := SequenceMatcher{autoJunk: true} m.SetSeqs(a, b) return &m } func NewMatcherWithJunk(a, b []string, autoJunk bool, isJunk func(string) bool) *SequenceMatcher { m := SequenceMatcher{IsJunk: isJunk, autoJunk: autoJunk} m.SetSeqs(a, b) return &m } // Set two sequences to be compared. func (m *SequenceMatcher) SetSeqs(a, b []string) { m.SetSeq1(a) m.SetSeq2(b) } // Set the first sequence to be compared. The second sequence to be compared is // not changed. // // SequenceMatcher computes and caches detailed information about the second // sequence, so if you want to compare one sequence S against many sequences, // use .SetSeq2(s) once and call .SetSeq1(x) repeatedly for each of the other // sequences. // // See also SetSeqs() and SetSeq2(). func (m *SequenceMatcher) SetSeq1(a []string) { if &a == &m.a { return } m.a = a m.matchingBlocks = nil m.opCodes = nil } // Set the second sequence to be compared. The first sequence to be compared is // not changed. func (m *SequenceMatcher) SetSeq2(b []string) { if &b == &m.b { return } m.b = b m.matchingBlocks = nil m.opCodes = nil m.fullBCount = nil m.chainB() } func (m *SequenceMatcher) chainB() { // Populate line -> index mapping b2j := map[string][]int{} for i, s := range m.b { indices := b2j[s] indices = append(indices, i) b2j[s] = indices } // Purge junk elements m.bJunk = map[string]struct{}{} if m.IsJunk != nil { junk := m.bJunk for s, _ := range b2j { if m.IsJunk(s) { junk[s] = struct{}{} } } for s, _ := range junk { delete(b2j, s) } } // Purge remaining popular elements popular := map[string]struct{}{} n := len(m.b) if m.autoJunk && n >= 200 { ntest := n/100 + 1 for s, indices := range b2j { if len(indices) > ntest { popular[s] = struct{}{} } } for s, _ := range popular { delete(b2j, s) } } m.bPopular = popular m.b2j = b2j } func (m *SequenceMatcher) isBJunk(s string) bool { _, ok := m.bJunk[s] return ok } // Find longest matching block in a[alo:ahi] and b[blo:bhi]. // // If IsJunk is not defined: // // Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where // // alo <= i <= i+k <= ahi // blo <= j <= j+k <= bhi // // and for all (i',j',k') meeting those conditions, // // k >= k' // i <= i' // and if i == i', j <= j' // // In other words, of all maximal matching blocks, return one that // starts earliest in a, and of all those maximal matching blocks that // start earliest in a, return the one that starts earliest in b. // // If IsJunk is defined, first the longest matching block is // determined as above, but with the additional restriction that no // junk element appears in the block. Then that block is extended as // far as possible by matching (only) junk elements on both sides. So // the resulting block never matches on junk except as identical junk // happens to be adjacent to an "interesting" match. // // If no blocks match, return (alo, blo, 0). func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match { // CAUTION: stripping common prefix or suffix would be incorrect. // E.g., // ab // acab // Longest matching block is "ab", but if common prefix is // stripped, it's "a" (tied with "b"). UNIX(tm) diff does so // strip, so ends up claiming that ab is changed to acab by // inserting "ca" in the middle. That's minimal but unintuitive: // "it's obvious" that someone inserted "ac" at the front. // Windiff ends up at the same place as diff, but by pairing up // the unique 'b's and then matching the first two 'a's. besti, bestj, bestsize := alo, blo, 0 // find longest junk-free match // during an iteration of the loop, j2len[j] = length of longest // junk-free match ending with a[i-1] and b[j] j2len := map[int]int{} for i := alo; i != ahi; i++ { // look at all instances of a[i] in b; note that because // b2j has no junk keys, the loop is skipped if a[i] is junk newj2len := map[int]int{} for _, j := range m.b2j[m.a[i]] { // a[i] matches b[j] if j < blo { continue } if j >= bhi { break } k := j2len[j-1] + 1 newj2len[j] = k if k > bestsize { besti, bestj, bestsize = i-k+1, j-k+1, k } } j2len = newj2len } // Extend the best by non-junk elements on each end. In particular, // "popular" non-junk elements aren't in b2j, which greatly speeds // the inner loop above, but also means "the best" match so far // doesn't contain any junk *or* popular non-junk elements. for besti > alo && bestj > blo && !m.isBJunk(m.b[bestj-1]) && m.a[besti-1] == m.b[bestj-1] { besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 } for besti+bestsize < ahi && bestj+bestsize < bhi && !m.isBJunk(m.b[bestj+bestsize]) && m.a[besti+bestsize] == m.b[bestj+bestsize] { bestsize += 1 } // Now that we have a wholly interesting match (albeit possibly // empty!), we may as well suck up the matching junk on each // side of it too. Can't think of a good reason not to, and it // saves post-processing the (possibly considerable) expense of // figuring out what to do with it. In the case of an empty // interesting match, this is clearly the right thing to do, // because no other kind of match is possible in the regions. for besti > alo && bestj > blo && m.isBJunk(m.b[bestj-1]) && m.a[besti-1] == m.b[bestj-1] { besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 } for besti+bestsize < ahi && bestj+bestsize < bhi && m.isBJunk(m.b[bestj+bestsize]) && m.a[besti+bestsize] == m.b[bestj+bestsize] { bestsize += 1 } return Match{A: besti, B: bestj, Size: bestsize} } // Return list of triples describing matching subsequences. // // Each triple is of the form (i, j, n), and means that // a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in // i and in j. It's also guaranteed that if (i, j, n) and (i', j', n') are // adjacent triples in the list, and the second is not the last triple in the // list, then i+n != i' or j+n != j'. IOW, adjacent triples never describe // adjacent equal blocks. // // The last triple is a dummy, (len(a), len(b), 0), and is the only // triple with n==0. func (m *SequenceMatcher) GetMatchingBlocks() []Match { if m.matchingBlocks != nil { return m.matchingBlocks } var matchBlocks func(alo, ahi, blo, bhi int, matched []Match) []Match matchBlocks = func(alo, ahi, blo, bhi int, matched []Match) []Match { match := m.findLongestMatch(alo, ahi, blo, bhi) i, j, k := match.A, match.B, match.Size if match.Size > 0 { if alo < i && blo < j { matched = matchBlocks(alo, i, blo, j, matched) } matched = append(matched, match) if i+k < ahi && j+k < bhi { matched = matchBlocks(i+k, ahi, j+k, bhi, matched) } } return matched } matched := matchBlocks(0, len(m.a), 0, len(m.b), nil) // It's possible that we have adjacent equal blocks in the // matching_blocks list now. nonAdjacent := []Match{} i1, j1, k1 := 0, 0, 0 for _, b := range matched { // Is this block adjacent to i1, j1, k1? i2, j2, k2 := b.A, b.B, b.Size if i1+k1 == i2 && j1+k1 == j2 { // Yes, so collapse them -- this just increases the length of // the first block by the length of the second, and the first // block so lengthened remains the block to compare against. k1 += k2 } else { // Not adjacent. Remember the first block (k1==0 means it's // the dummy we started with), and make the second block the // new block to compare against. if k1 > 0 { nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) } i1, j1, k1 = i2, j2, k2 } } if k1 > 0 { nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) } nonAdjacent = append(nonAdjacent, Match{len(m.a), len(m.b), 0}) m.matchingBlocks = nonAdjacent return m.matchingBlocks } // Return list of 5-tuples describing how to turn a into b. // // Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple // has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the // tuple preceding it, and likewise for j1 == the previous j2. // // The tags are characters, with these meanings: // // 'r' (replace): a[i1:i2] should be replaced by b[j1:j2] // // 'd' (delete): a[i1:i2] should be deleted, j1==j2 in this case. // // 'i' (insert): b[j1:j2] should be inserted at a[i1:i1], i1==i2 in this case. // // 'e' (equal): a[i1:i2] == b[j1:j2] func (m *SequenceMatcher) GetOpCodes() []OpCode { if m.opCodes != nil { return m.opCodes } i, j := 0, 0 matching := m.GetMatchingBlocks() opCodes := make([]OpCode, 0, len(matching)) for _, m := range matching { // invariant: we've pumped out correct diffs to change // a[:i] into b[:j], and the next matching block is // a[ai:ai+size] == b[bj:bj+size]. So we need to pump // out a diff to change a[i:ai] into b[j:bj], pump out // the matching block, and move (i,j) beyond the match ai, bj, size := m.A, m.B, m.Size tag := byte(0) if i < ai && j < bj { tag = 'r' } else if i < ai { tag = 'd' } else if j < bj { tag = 'i' } if tag > 0 { opCodes = append(opCodes, OpCode{tag, i, ai, j, bj}) } i, j = ai+size, bj+size // the list of matching blocks is terminated by a // sentinel with size 0 if size > 0 { opCodes = append(opCodes, OpCode{'e', ai, i, bj, j}) } } m.opCodes = opCodes return m.opCodes } // Isolate change clusters by eliminating ranges with no changes. // // Return a generator of groups with up to n lines of context. // Each group is in the same format as returned by GetOpCodes(). func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode { if n < 0 { n = 3 } codes := m.GetOpCodes() if len(codes) == 0 { codes = []OpCode{OpCode{'e', 0, 1, 0, 1}} } // Fixup leading and trailing groups if they show no changes. if codes[0].Tag == 'e' { c := codes[0] i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2} } if codes[len(codes)-1].Tag == 'e' { c := codes[len(codes)-1] i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)} } nn := n + n groups := [][]OpCode{} group := []OpCode{} for _, c := range codes { i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 // End the current group and start a new one whenever // there is a large range with no changes. if c.Tag == 'e' && i2-i1 > nn { group = append(group, OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)}) groups = append(groups, group) group = []OpCode{} i1, j1 = max(i1, i2-n), max(j1, j2-n) } group = append(group, OpCode{c.Tag, i1, i2, j1, j2}) } if len(group) > 0 && !(len(group) == 1 && group[0].Tag == 'e') { groups = append(groups, group) } return groups } // Return a measure of the sequences' similarity (float in [0,1]). // // Where T is the total number of elements in both sequences, and // M is the number of matches, this is 2.0*M / T. // Note that this is 1 if the sequences are identical, and 0 if // they have nothing in common. // // .Ratio() is expensive to compute if you haven't already computed // .GetMatchingBlocks() or .GetOpCodes(), in which case you may // want to try .QuickRatio() or .RealQuickRation() first to get an // upper bound. func (m *SequenceMatcher) Ratio() float64 { matches := 0 for _, m := range m.GetMatchingBlocks() { matches += m.Size } return calculateRatio(matches, len(m.a)+len(m.b)) } // Return an upper bound on ratio() relatively quickly. // // This isn't defined beyond that it is an upper bound on .Ratio(), and // is faster to compute. func (m *SequenceMatcher) QuickRatio() float64 { // viewing a and b as multisets, set matches to the cardinality // of their intersection; this counts the number of matches // without regard to order, so is clearly an upper bound if m.fullBCount == nil { m.fullBCount = map[string]int{} for _, s := range m.b { m.fullBCount[s] = m.fullBCount[s] + 1 } } // avail[x] is the number of times x appears in 'b' less the // number of times we've seen it in 'a' so far ... kinda avail := map[string]int{} matches := 0 for _, s := range m.a { n, ok := avail[s] if !ok { n = m.fullBCount[s] } avail[s] = n - 1 if n > 0 { matches += 1 } } return calculateRatio(matches, len(m.a)+len(m.b)) } // Return an upper bound on ratio() very quickly. // // This isn't defined beyond that it is an upper bound on .Ratio(), and // is faster to compute than either .Ratio() or .QuickRatio(). func (m *SequenceMatcher) RealQuickRatio() float64 { la, lb := len(m.a), len(m.b) return calculateRatio(min(la, lb), la+lb) } // Convert range to the "ed" format func formatRangeUnified(start, stop int) string { // Per the diff spec at http://www.unix.org/single_unix_specification/ beginning := start + 1 // lines start numbering with one length := stop - start if length == 1 { return fmt.Sprintf("%d", beginning) } if length == 0 { beginning -= 1 // empty ranges begin at line just before the range } return fmt.Sprintf("%d,%d", beginning, length) } // Unified diff parameters type UnifiedDiff struct { A []string // First sequence lines FromFile string // First file name FromDate string // First file time B []string // Second sequence lines ToFile string // Second file name ToDate string // Second file time Eol string // Headers end of line, defaults to LF Context int // Number of context lines } // Compare two sequences of lines; generate the delta as a unified diff. // // Unified diffs are a compact way of showing line changes and a few // lines of context. The number of context lines is set by 'n' which // defaults to three. // // By default, the diff control lines (those with ---, +++, or @@) are // created with a trailing newline. This is helpful so that inputs // created from file.readlines() result in diffs that are suitable for // file.writelines() since both the inputs and outputs have trailing // newlines. // // For inputs that do not have trailing newlines, set the lineterm // argument to "" so that the output will be uniformly newline free. // // The unidiff format normally has a header for filenames and modification // times. Any or all of these may be specified using strings for // 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. // The modification times are normally expressed in the ISO 8601 format. func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error { buf := bufio.NewWriter(writer) defer buf.Flush() wf := func(format string, args ...interface{}) error { _, err := buf.WriteString(fmt.Sprintf(format, args...)) return err } ws := func(s string) error { _, err := buf.WriteString(s) return err } if len(diff.Eol) == 0 { diff.Eol = "\n" } started := false m := NewMatcher(diff.A, diff.B) for _, g := range m.GetGroupedOpCodes(diff.Context) { if !started { started = true fromDate := "" if len(diff.FromDate) > 0 { fromDate = "\t" + diff.FromDate } toDate := "" if len(diff.ToDate) > 0 { toDate = "\t" + diff.ToDate } if diff.FromFile != "" || diff.ToFile != "" { err := wf("--- %s%s%s", diff.FromFile, fromDate, diff.Eol) if err != nil { return err } err = wf("+++ %s%s%s", diff.ToFile, toDate, diff.Eol) if err != nil { return err } } } first, last := g[0], g[len(g)-1] range1 := formatRangeUnified(first.I1, last.I2) range2 := formatRangeUnified(first.J1, last.J2) if err := wf("@@ -%s +%s @@%s", range1, range2, diff.Eol); err != nil { return err } for _, c := range g { i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 if c.Tag == 'e' { for _, line := range diff.A[i1:i2] { if err := ws(" " + line); err != nil { return err } } continue } if c.Tag == 'r' || c.Tag == 'd' { for _, line := range diff.A[i1:i2] { if err := ws("-" + line); err != nil { return err } } } if c.Tag == 'r' || c.Tag == 'i' { for _, line := range diff.B[j1:j2] { if err := ws("+" + line); err != nil { return err } } } } } return nil } // Like WriteUnifiedDiff but returns the diff a string. func GetUnifiedDiffString(diff UnifiedDiff) (string, error) { w := &bytes.Buffer{} err := WriteUnifiedDiff(w, diff) return string(w.Bytes()), err } // Convert range to the "ed" format. func formatRangeContext(start, stop int) string { // Per the diff spec at http://www.unix.org/single_unix_specification/ beginning := start + 1 // lines start numbering with one length := stop - start if length == 0 { beginning -= 1 // empty ranges begin at line just before the range } if length <= 1 { return fmt.Sprintf("%d", beginning) } return fmt.Sprintf("%d,%d", beginning, beginning+length-1) } type ContextDiff UnifiedDiff // Compare two sequences of lines; generate the delta as a context diff. // // Context diffs are a compact way of showing line changes and a few // lines of context. The number of context lines is set by diff.Context // which defaults to three. // // By default, the diff control lines (those with *** or ---) are // created with a trailing newline. // // For inputs that do not have trailing newlines, set the diff.Eol // argument to "" so that the output will be uniformly newline free. // // The context diff format normally has a header for filenames and // modification times. Any or all of these may be specified using // strings for diff.FromFile, diff.ToFile, diff.FromDate, diff.ToDate. // The modification times are normally expressed in the ISO 8601 format. // If not specified, the strings default to blanks. func WriteContextDiff(writer io.Writer, diff ContextDiff) error { buf := bufio.NewWriter(writer) defer buf.Flush() var diffErr error wf := func(format string, args ...interface{}) { _, err := buf.WriteString(fmt.Sprintf(format, args...)) if diffErr == nil && err != nil { diffErr = err } } ws := func(s string) { _, err := buf.WriteString(s) if diffErr == nil && err != nil { diffErr = err } } if len(diff.Eol) == 0 { diff.Eol = "\n" } prefix := map[byte]string{ 'i': "+ ", 'd': "- ", 'r': "! ", 'e': " ", } started := false m := NewMatcher(diff.A, diff.B) for _, g := range m.GetGroupedOpCodes(diff.Context) { if !started { started = true fromDate := "" if len(diff.FromDate) > 0 { fromDate = "\t" + diff.FromDate } toDate := "" if len(diff.ToDate) > 0 { toDate = "\t" + diff.ToDate } if diff.FromFile != "" || diff.ToFile != "" { wf("*** %s%s%s", diff.FromFile, fromDate, diff.Eol) wf("--- %s%s%s", diff.ToFile, toDate, diff.Eol) } } first, last := g[0], g[len(g)-1] ws("***************" + diff.Eol) range1 := formatRangeContext(first.I1, last.I2) wf("*** %s ****%s", range1, diff.Eol) for _, c := range g { if c.Tag == 'r' || c.Tag == 'd' { for _, cc := range g { if cc.Tag == 'i' { continue } for _, line := range diff.A[cc.I1:cc.I2] { ws(prefix[cc.Tag] + line) } } break } } range2 := formatRangeContext(first.J1, last.J2) wf("--- %s ----%s", range2, diff.Eol) for _, c := range g { if c.Tag == 'r' || c.Tag == 'i' { for _, cc := range g { if cc.Tag == 'd' { continue } for _, line := range diff.B[cc.J1:cc.J2] { ws(prefix[cc.Tag] + line) } } break } } } return diffErr } // Like WriteContextDiff but returns the diff a string. func GetContextDiffString(diff ContextDiff) (string, error) { w := &bytes.Buffer{} err := WriteContextDiff(w, diff) return string(w.Bytes()), err } // Split a string on "\n" while preserving them. The output can be used // as input for UnifiedDiff and ContextDiff structures. func SplitLines(s string) []string { lines := strings.SplitAfter(s, "\n") lines[len(lines)-1] += "\n" return lines } ================================================ FILE: internal/difflib/difflib_test.go ================================================ package difflib import ( "bytes" "fmt" "math" "reflect" "strings" "testing" ) func assertAlmostEqual(t *testing.T, a, b float64, places int) { if math.Abs(a-b) > math.Pow10(-places) { t.Errorf("%.7f != %.7f", a, b) } } func assertEqual(t *testing.T, a, b interface{}) { if !reflect.DeepEqual(a, b) { t.Errorf("%v != %v", a, b) } } func splitChars(s string) []string { chars := make([]string, 0, len(s)) // Assume ASCII inputs for i := 0; i != len(s); i++ { chars = append(chars, string(s[i])) } return chars } func TestSequenceMatcherRatio(t *testing.T) { s := NewMatcher(splitChars("abcd"), splitChars("bcde")) assertEqual(t, s.Ratio(), 0.75) assertEqual(t, s.QuickRatio(), 0.75) assertEqual(t, s.RealQuickRatio(), 1.0) } func TestGetOptCodes(t *testing.T) { a := "qabxcd" b := "abycdf" s := NewMatcher(splitChars(a), splitChars(b)) w := &bytes.Buffer{} for _, op := range s.GetOpCodes() { fmt.Fprintf(w, "%s a[%d:%d], (%s) b[%d:%d] (%s)\n", string(op.Tag), op.I1, op.I2, a[op.I1:op.I2], op.J1, op.J2, b[op.J1:op.J2]) } result := string(w.Bytes()) expected := `d a[0:1], (q) b[0:0] () e a[1:3], (ab) b[0:2] (ab) r a[3:4], (x) b[2:3] (y) e a[4:6], (cd) b[3:5] (cd) i a[6:6], () b[5:6] (f) ` if expected != result { t.Errorf("unexpected op codes: \n%s", result) } } func TestGroupedOpCodes(t *testing.T) { a := []string{} for i := 0; i != 39; i++ { a = append(a, fmt.Sprintf("%02d", i)) } b := []string{} b = append(b, a[:8]...) b = append(b, " i") b = append(b, a[8:19]...) b = append(b, " x") b = append(b, a[20:22]...) b = append(b, a[27:34]...) b = append(b, " y") b = append(b, a[35:]...) s := NewMatcher(a, b) w := &bytes.Buffer{} for _, g := range s.GetGroupedOpCodes(-1) { fmt.Fprintf(w, "group\n") for _, op := range g { fmt.Fprintf(w, " %s, %d, %d, %d, %d\n", string(op.Tag), op.I1, op.I2, op.J1, op.J2) } } result := string(w.Bytes()) expected := `group e, 5, 8, 5, 8 i, 8, 8, 8, 9 e, 8, 11, 9, 12 group e, 16, 19, 17, 20 r, 19, 20, 20, 21 e, 20, 22, 21, 23 d, 22, 27, 23, 23 e, 27, 30, 23, 26 group e, 31, 34, 27, 30 r, 34, 35, 30, 31 e, 35, 38, 31, 34 ` if expected != result { t.Errorf("unexpected op codes: \n%s", result) } } func ExampleGetUnifiedDiffString() { a := `one two three four fmt.Printf("%s,%T",a,b)` b := `zero one three four` diff := UnifiedDiff{ A: SplitLines(a), B: SplitLines(b), FromFile: "Original", FromDate: "2005-01-26 23:30:50", ToFile: "Current", ToDate: "2010-04-02 10:20:52", Context: 3, } result, _ := GetUnifiedDiffString(diff) fmt.Println(strings.Replace(result, "\t", " ", -1)) // Output: // --- Original 2005-01-26 23:30:50 // +++ Current 2010-04-02 10:20:52 // @@ -1,5 +1,4 @@ // +zero // one // -two // three // four // -fmt.Printf("%s,%T",a,b) } func ExampleGetContextDiffString() { a := `one two three four fmt.Printf("%s,%T",a,b)` b := `zero one tree four` diff := ContextDiff{ A: SplitLines(a), B: SplitLines(b), FromFile: "Original", ToFile: "Current", Context: 3, Eol: "\n", } result, _ := GetContextDiffString(diff) fmt.Print(strings.Replace(result, "\t", " ", -1)) // Output: // *** Original // --- Current // *************** // *** 1,5 **** // one // ! two // ! three // four // - fmt.Printf("%s,%T",a,b) // --- 1,4 ---- // + zero // one // ! tree // four } func ExampleGetContextDiffString_second() { a := `one two three four` b := `zero one tree four` diff := ContextDiff{ A: SplitLines(a), B: SplitLines(b), FromFile: "Original", ToFile: "Current", Context: 3, Eol: "\n", } result, _ := GetContextDiffString(diff) fmt.Printf(strings.Replace(result, "\t", " ", -1)) // Output: // *** Original // --- Current // *************** // *** 1,4 **** // one // ! two // ! three // four // --- 1,4 ---- // + zero // one // ! tree // four } func rep(s string, count int) string { return strings.Repeat(s, count) } func TestWithAsciiOneInsert(t *testing.T) { sm := NewMatcher(splitChars(rep("b", 100)), splitChars("a"+rep("b", 100))) assertAlmostEqual(t, sm.Ratio(), 0.995, 3) assertEqual(t, sm.GetOpCodes(), []OpCode{{'i', 0, 0, 0, 1}, {'e', 0, 100, 1, 101}}) assertEqual(t, len(sm.bPopular), 0) sm = NewMatcher(splitChars(rep("b", 100)), splitChars(rep("b", 50)+"a"+rep("b", 50))) assertAlmostEqual(t, sm.Ratio(), 0.995, 3) assertEqual(t, sm.GetOpCodes(), []OpCode{{'e', 0, 50, 0, 50}, {'i', 50, 50, 50, 51}, {'e', 50, 100, 51, 101}}) assertEqual(t, len(sm.bPopular), 0) } func TestWithAsciiOnDelete(t *testing.T) { sm := NewMatcher(splitChars(rep("a", 40)+"c"+rep("b", 40)), splitChars(rep("a", 40)+rep("b", 40))) assertAlmostEqual(t, sm.Ratio(), 0.994, 3) assertEqual(t, sm.GetOpCodes(), []OpCode{{'e', 0, 40, 0, 40}, {'d', 40, 41, 40, 40}, {'e', 41, 81, 40, 80}}) } func TestWithAsciiBJunk(t *testing.T) { isJunk := func(s string) bool { return s == " " } sm := NewMatcherWithJunk(splitChars(rep("a", 40)+rep("b", 40)), splitChars(rep("a", 44)+rep("b", 40)), true, isJunk) assertEqual(t, sm.bJunk, map[string]struct{}{}) sm = NewMatcherWithJunk(splitChars(rep("a", 40)+rep("b", 40)), splitChars(rep("a", 44)+rep("b", 40)+rep(" ", 20)), false, isJunk) assertEqual(t, sm.bJunk, map[string]struct{}{" ": struct{}{}}) isJunk = func(s string) bool { return s == " " || s == "b" } sm = NewMatcherWithJunk(splitChars(rep("a", 40)+rep("b", 40)), splitChars(rep("a", 44)+rep("b", 40)+rep(" ", 20)), false, isJunk) assertEqual(t, sm.bJunk, map[string]struct{}{" ": struct{}{}, "b": struct{}{}}) } func TestSFBugsRatioForNullSeqn(t *testing.T) { sm := NewMatcher(nil, nil) assertEqual(t, sm.Ratio(), 1.0) assertEqual(t, sm.QuickRatio(), 1.0) assertEqual(t, sm.RealQuickRatio(), 1.0) } func TestSFBugsComparingEmptyLists(t *testing.T) { groups := NewMatcher(nil, nil).GetGroupedOpCodes(-1) assertEqual(t, len(groups), 0) diff := UnifiedDiff{ FromFile: "Original", ToFile: "Current", Context: 3, } result, err := GetUnifiedDiffString(diff) assertEqual(t, err, nil) assertEqual(t, result, "") } func TestOutputFormatRangeFormatUnified(t *testing.T) { // Per the diff spec at http://www.unix.org/single_unix_specification/ // // Each field shall be of the form: // %1d", if the range contains exactly one line, // and: // "%1d,%1d", , otherwise. // If a range is empty, its beginning line number shall be the number of // the line just before the range, or 0 if the empty range starts the file. fm := formatRangeUnified assertEqual(t, fm(3, 3), "3,0") assertEqual(t, fm(3, 4), "4") assertEqual(t, fm(3, 5), "4,2") assertEqual(t, fm(3, 6), "4,3") assertEqual(t, fm(0, 0), "0,0") } func TestOutputFormatRangeFormatContext(t *testing.T) { // Per the diff spec at http://www.unix.org/single_unix_specification/ // // The range of lines in file1 shall be written in the following format // if the range contains two or more lines: // "*** %d,%d ****\n", , // and the following format otherwise: // "*** %d ****\n", // The ending line number of an empty range shall be the number of the preceding line, // or 0 if the range is at the start of the file. // // Next, the range of lines in file2 shall be written in the following format // if the range contains two or more lines: // "--- %d,%d ----\n", , // and the following format otherwise: // "--- %d ----\n", fm := formatRangeContext assertEqual(t, fm(3, 3), "3") assertEqual(t, fm(3, 4), "4") assertEqual(t, fm(3, 5), "4,5") assertEqual(t, fm(3, 6), "4,6") assertEqual(t, fm(0, 0), "0") } func TestOutputFormatTabDelimiter(t *testing.T) { diff := UnifiedDiff{ A: splitChars("one"), B: splitChars("two"), FromFile: "Original", FromDate: "2005-01-26 23:30:50", ToFile: "Current", ToDate: "2010-04-12 10:20:52", Eol: "\n", } ud, err := GetUnifiedDiffString(diff) assertEqual(t, err, nil) assertEqual(t, SplitLines(ud)[:2], []string{ "--- Original\t2005-01-26 23:30:50\n", "+++ Current\t2010-04-12 10:20:52\n", }) cd, err := GetContextDiffString(ContextDiff(diff)) assertEqual(t, err, nil) assertEqual(t, SplitLines(cd)[:2], []string{ "*** Original\t2005-01-26 23:30:50\n", "--- Current\t2010-04-12 10:20:52\n", }) } func TestOutputFormatNoTrailingTabOnEmptyFiledate(t *testing.T) { diff := UnifiedDiff{ A: splitChars("one"), B: splitChars("two"), FromFile: "Original", ToFile: "Current", Eol: "\n", } ud, err := GetUnifiedDiffString(diff) assertEqual(t, err, nil) assertEqual(t, SplitLines(ud)[:2], []string{"--- Original\n", "+++ Current\n"}) cd, err := GetContextDiffString(ContextDiff(diff)) assertEqual(t, err, nil) assertEqual(t, SplitLines(cd)[:2], []string{"*** Original\n", "--- Current\n"}) } func TestOmitFilenames(t *testing.T) { diff := UnifiedDiff{ A: SplitLines("o\nn\ne\n"), B: SplitLines("t\nw\no\n"), Eol: "\n", } ud, err := GetUnifiedDiffString(diff) assertEqual(t, err, nil) assertEqual(t, SplitLines(ud), []string{ "@@ -0,0 +1,2 @@\n", "+t\n", "+w\n", "@@ -2,2 +3,0 @@\n", "-n\n", "-e\n", "\n", }) cd, err := GetContextDiffString(ContextDiff(diff)) assertEqual(t, err, nil) assertEqual(t, SplitLines(cd), []string{ "***************\n", "*** 0 ****\n", "--- 1,2 ----\n", "+ t\n", "+ w\n", "***************\n", "*** 2,3 ****\n", "- n\n", "- e\n", "--- 3 ----\n", "\n", }) } func TestSplitLines(t *testing.T) { allTests := []struct { input string want []string }{ {"foo", []string{"foo\n"}}, {"foo\nbar", []string{"foo\n", "bar\n"}}, {"foo\nbar\n", []string{"foo\n", "bar\n", "\n"}}, } for _, test := range allTests { assertEqual(t, SplitLines(test.input), test.want) } } func benchmarkSplitLines(b *testing.B, count int) { str := strings.Repeat("foo\n", count) b.ResetTimer() n := 0 for i := 0; i < b.N; i++ { n += len(SplitLines(str)) } } func BenchmarkSplitLines100(b *testing.B) { benchmarkSplitLines(b, 100) } func BenchmarkSplitLines10000(b *testing.B) { benchmarkSplitLines(b, 10000) } ================================================ FILE: internal/ring/ring.go ================================================ package ring // Ring is a very simple ring buffer implementation that uses a slice. The // internal slice will only grow, never shrink. When it grows, it grows in // chunks of "chunkSize" (given as argument in the [New] function). Pointer and // reference types can be safely used because memory is cleared. type Ring[T any] struct { data []T back, len, chunkSize int } func New[T any](chunkSize int) *Ring[T] { if chunkSize < 1 { panic("chunkSize must be greater than zero") } return &Ring[T]{ chunkSize: chunkSize, } } func (r *Ring[T]) Len() int { return r.len } func (r *Ring[T]) Cap() int { return len(r.data) } func (r *Ring[T]) Reset() { var zero T for i := range r.data { r.data[i] = zero // clear mem, optimized by the compiler, in Go 1.21 the "clear" builtin can be used } r.back = 0 r.len = 0 } // Nth returns the n-th oldest value (zero-based) in the ring without making // any change. func (r *Ring[T]) Nth(n int) (v T, ok bool) { if n < 0 || n >= r.len || len(r.data) == 0 { return v, false } n = (n + r.back) % len(r.data) return r.data[n], true } // Dequeue returns the oldest value. func (r *Ring[T]) Dequeue() (v T, ok bool) { if r.len == 0 { return v, false } v, r.data[r.back] = r.data[r.back], v // retrieve and clear mem r.len-- r.back = (r.back + 1) % len(r.data) return v, true } // Enqueue adds an item to the ring. func (r *Ring[T]) Enqueue(v T) { if r.len == len(r.data) { r.grow() } writePos := (r.back + r.len) % len(r.data) r.data[writePos] = v r.len++ } func (r *Ring[T]) grow() { s := make([]T, len(r.data)+r.chunkSize) if r.len > 0 { chunk1 := r.back + r.len if chunk1 > len(r.data) { chunk1 = len(r.data) } copied := copy(s, r.data[r.back:chunk1]) if copied < r.len { // wrapped slice chunk2 := r.len - copied copy(s[copied:], r.data[:chunk2]) } } r.back = 0 r.data = s } ================================================ FILE: internal/ring/ring_test.go ================================================ package ring import ( "fmt" "testing" ) func TestRing(t *testing.T) { type op = ringOp[int] testRing(t, New[int](3), // noops on empty ring op{cap: 0, opType: opRst, value: 0, items: []int{}}, op{cap: 0, opType: opDeq, value: 0, items: []int{}}, // basic op{cap: 3, opType: opEnq, value: 1, items: []int{1}}, op{cap: 3, opType: opDeq, value: 1, items: []int{}}, // wrapping op{cap: 3, opType: opEnq, value: 2, items: []int{2}}, op{cap: 3, opType: opEnq, value: 3, items: []int{2, 3}}, op{cap: 3, opType: opEnq, value: 4, items: []int{2, 3, 4}}, op{cap: 3, opType: opDeq, value: 2, items: []int{3, 4}}, op{cap: 3, opType: opDeq, value: 3, items: []int{4}}, op{cap: 3, opType: opDeq, value: 4, items: []int{}}, // resetting op{cap: 3, opType: opEnq, value: 2, items: []int{2}}, op{cap: 3, opType: opRst, value: 0, items: []int{}}, op{cap: 3, opType: opDeq, value: 0, items: []int{}}, // growing without wrapping op{cap: 3, opType: opEnq, value: 5, items: []int{5}}, op{cap: 3, opType: opEnq, value: 6, items: []int{5, 6}}, op{cap: 3, opType: opEnq, value: 7, items: []int{5, 6, 7}}, op{cap: 6, opType: opEnq, value: 8, items: []int{5, 6, 7, 8}}, op{cap: 6, opType: opRst, value: 0, items: []int{}}, op{cap: 6, opType: opDeq, value: 0, items: []int{}}, // growing and wrapping op{cap: 6, opType: opEnq, value: 9, items: []int{9}}, op{cap: 6, opType: opEnq, value: 10, items: []int{9, 10}}, op{cap: 6, opType: opEnq, value: 11, items: []int{9, 10, 11}}, op{cap: 6, opType: opEnq, value: 12, items: []int{9, 10, 11, 12}}, op{cap: 6, opType: opEnq, value: 13, items: []int{9, 10, 11, 12, 13}}, op{cap: 6, opType: opEnq, value: 14, items: []int{9, 10, 11, 12, 13, 14}}, op{cap: 6, opType: opDeq, value: 9, items: []int{10, 11, 12, 13, 14}}, op{cap: 6, opType: opDeq, value: 10, items: []int{11, 12, 13, 14}}, op{cap: 6, opType: opEnq, value: 15, items: []int{11, 12, 13, 14, 15}}, op{cap: 6, opType: opEnq, value: 16, items: []int{11, 12, 13, 14, 15, 16}}, op{cap: 9, opType: opEnq, value: 17, items: []int{11, 12, 13, 14, 15, 16, 17}}, // grows wrapped op{cap: 9, opType: opDeq, value: 11, items: []int{12, 13, 14, 15, 16, 17}}, op{cap: 9, opType: opDeq, value: 12, items: []int{13, 14, 15, 16, 17}}, op{cap: 9, opType: opDeq, value: 13, items: []int{14, 15, 16, 17}}, op{cap: 9, opType: opDeq, value: 14, items: []int{15, 16, 17}}, op{cap: 9, opType: opDeq, value: 15, items: []int{16, 17}}, op{cap: 9, opType: opDeq, value: 16, items: []int{17}}, op{cap: 9, opType: opDeq, value: 17, items: []int{}}, op{cap: 9, opType: opDeq, value: 0, items: []int{}}, ) t.Run("should panic on invalid chunkSize", func(t *testing.T) { defer func() { if r := recover(); r == nil { t.Fatalf("should have panicked") } }() New[int](0) }) } const ( opEnq = iota // enqueue an item opDeq // dequeue an item and an item was available opRst // reset ) type ringOp[T comparable] struct { cap int // expected values opType int // opEnq or opDeq value T // value to enqueue or value expected for dequeue; ignored for opRst items []T // items left } func testRing[T comparable](t *testing.T, r *Ring[T], ops ...ringOp[T]) { for i, op := range ops { testOK := t.Run(fmt.Sprintf("opIndex=%v", i), func(t *testing.T) { testRingOp(t, r, op) }) if !testOK { return } } } func testRingOp[T comparable](t *testing.T, r *Ring[T], op ringOp[T]) { var zero T switch op.opType { case opEnq: r.Enqueue(op.value) case opDeq: shouldSucceed := r.Len() > 0 v, ok := r.Dequeue() switch { case ok != shouldSucceed: t.Fatalf("should have succeeded: %v", shouldSucceed) case ok && v != op.value: t.Fatalf("expected value: %v; got: %v", op.value, v) case !ok && v != zero: t.Fatalf("expected zero value; got: %v", v) } case opRst: r.Reset() } if c := r.Cap(); c != op.cap { t.Fatalf("expected cap: %v; got: %v", op.cap, c) } if l := r.Len(); l != len(op.items) { t.Errorf("expected Len(): %v; got: %v", len(op.items), l) } var got []T for i := 0; ; i++ { v, ok := r.Nth(i) if !ok { break } got = append(got, v) } if l := len(got); l != len(op.items) { t.Errorf("expected items: %v\ngot items: %v", op.items, got) } for i := range op.items { if op.items[i] != got[i] { t.Fatalf("expected items: %v\ngot items: %v", op.items, got) } } if v, ok := r.Nth(len(op.items)); ok || v != zero { t.Fatalf("expected no more items, got: v=%v; ok=%v", v, ok) } } ================================================ FILE: internal/spew/bypass.go ================================================ // Copyright (c) 2015-2016 Dave Collins // // Permission to use, copy, modify, and distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // NOTE: Due to the following build constraints, this file will only be compiled // when the code is not running on Google App Engine, compiled by GopherJS, and // "-tags safe" is not added to the go build command line. The "disableunsafe" // tag is deprecated and thus should not be used. // Go versions prior to 1.4 are disabled because they use a different layout // for interfaces which make the implementation of unsafeReflectValue more complex. //go:build !js && !appengine && !safe && !disableunsafe && go1.4 // +build !js,!appengine,!safe,!disableunsafe,go1.4 package spew import ( "reflect" "unsafe" ) const ( // UnsafeDisabled is a build-time constant which specifies whether or // not access to the unsafe package is available. UnsafeDisabled = false // ptrSize is the size of a pointer on the current arch. ptrSize = unsafe.Sizeof((*byte)(nil)) ) type flag uintptr var ( // flagRO indicates whether the value field of a reflect.Value // is read-only. flagRO flag // flagAddr indicates whether the address of the reflect.Value's // value may be taken. flagAddr flag ) // flagKindMask holds the bits that make up the kind // part of the flags field. In all the supported versions, // it is in the lower 5 bits. const flagKindMask = flag(0x1f) // Different versions of Go have used different // bit layouts for the flags type. This table // records the known combinations. var okFlags = []struct { ro, addr flag }{{ // From Go 1.4 to 1.5 ro: 1 << 5, addr: 1 << 7, }, { // Up to Go tip. ro: 1<<5 | 1<<6, addr: 1 << 8, }} var flagValOffset = func() uintptr { field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag") if !ok { panic("reflect.Value has no flag field") } return field.Offset }() // flagField returns a pointer to the flag field of a reflect.Value. func flagField(v *reflect.Value) *flag { return (*flag)(unsafe.Pointer(uintptr(unsafe.Pointer(v)) + flagValOffset)) } // unsafeReflectValue converts the passed reflect.Value into a one that bypasses // the typical safety restrictions preventing access to unaddressable and // unexported data. It works by digging the raw pointer to the underlying // value out of the protected value and generating a new unprotected (unsafe) // reflect.Value to it. // // This allows us to check for implementations of the Stringer and error // interfaces to be used for pretty printing ordinarily unaddressable and // inaccessible values such as unexported struct fields. func unsafeReflectValue(v reflect.Value) reflect.Value { if !v.IsValid() || (v.CanInterface() && v.CanAddr()) { return v } flagFieldPtr := flagField(&v) *flagFieldPtr &^= flagRO *flagFieldPtr |= flagAddr return v } // Sanity checks against future reflect package changes // to the type or semantics of the Value.flag field. func init() { field, ok := reflect.TypeOf(reflect.Value{}).FieldByName("flag") if !ok { panic("reflect.Value has no flag field") } if field.Type.Kind() != reflect.TypeOf(flag(0)).Kind() { panic("reflect.Value flag field has changed kind") } type t0 int var t struct { A t0 // t0 will have flagEmbedRO set. t0 // a will have flagStickyRO set a t0 } vA := reflect.ValueOf(t).FieldByName("A") va := reflect.ValueOf(t).FieldByName("a") vt0 := reflect.ValueOf(t).FieldByName("t0") // Infer flagRO from the difference between the flags // for the (otherwise identical) fields in t. flagPublic := *flagField(&vA) flagWithRO := *flagField(&va) | *flagField(&vt0) flagRO = flagPublic ^ flagWithRO // Infer flagAddr from the difference between a value // taken from a pointer and not. vPtrA := reflect.ValueOf(&t).Elem().FieldByName("A") flagNoPtr := *flagField(&vA) flagPtr := *flagField(&vPtrA) flagAddr = flagNoPtr ^ flagPtr // Check that the inferred flags tally with one of the known versions. for _, f := range okFlags { if flagRO == f.ro && flagAddr == f.addr { return } } panic("reflect.Value read-only flag has changed semantics") } ================================================ FILE: internal/spew/bypasssafe.go ================================================ // Copyright (c) 2015-2016 Dave Collins // // Permission to use, copy, modify, and distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // NOTE: Due to the following build constraints, this file will only be compiled // when the code is running on Google App Engine, compiled by GopherJS, or // "-tags safe" is added to the go build command line. The "disableunsafe" // tag is deprecated and thus should not be used. //go:build js || appengine || safe || disableunsafe || !go1.4 // +build js appengine safe disableunsafe !go1.4 package spew import "reflect" const ( // UnsafeDisabled is a build-time constant which specifies whether or // not access to the unsafe package is available. UnsafeDisabled = true ) // unsafeReflectValue typically converts the passed reflect.Value into a one // that bypasses the typical safety restrictions preventing access to // unaddressable and unexported data. However, doing this relies on access to // the unsafe package. This is a stub version which simply returns the passed // reflect.Value when the unsafe package is not available. func unsafeReflectValue(v reflect.Value) reflect.Value { return v } ================================================ FILE: internal/spew/common.go ================================================ /* * Copyright (c) 2013-2016 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ package spew import ( "bytes" "fmt" "io" "reflect" "sort" "strconv" ) // Some constants in the form of bytes to avoid string overhead. This mirrors // the technique used in the fmt package. var ( panicBytes = []byte("(PANIC=") plusBytes = []byte("+") iBytes = []byte("i") trueBytes = []byte("true") falseBytes = []byte("false") interfaceBytes = []byte("(interface {})") commaNewlineBytes = []byte(",\n") newlineBytes = []byte("\n") openBraceBytes = []byte("{") openBraceNewlineBytes = []byte("{\n") closeBraceBytes = []byte("}") asteriskBytes = []byte("*") colonBytes = []byte(":") colonSpaceBytes = []byte(": ") openParenBytes = []byte("(") closeParenBytes = []byte(")") spaceBytes = []byte(" ") pointerChainBytes = []byte("->") nilAngleBytes = []byte("") maxNewlineBytes = []byte("\n") maxShortBytes = []byte("") circularBytes = []byte("") circularShortBytes = []byte("") invalidAngleBytes = []byte("") openBracketBytes = []byte("[") closeBracketBytes = []byte("]") percentBytes = []byte("%") precisionBytes = []byte(".") openAngleBytes = []byte("<") closeAngleBytes = []byte(">") openMapBytes = []byte("map[") closeMapBytes = []byte("]") lenEqualsBytes = []byte("len=") capEqualsBytes = []byte("cap=") ) // hexDigits is used to map a decimal value to a hex digit. var hexDigits = "0123456789abcdef" // catchPanic handles any panics that might occur during the handleMethods // calls. func catchPanic(w io.Writer, v reflect.Value) { if err := recover(); err != nil { w.Write(panicBytes) fmt.Fprintf(w, "%v", err) w.Write(closeParenBytes) } } // handleMethods attempts to call the Error and String methods on the underlying // type the passed reflect.Value represents and outputs the result to Writer w. // // It handles panics in any called methods by catching and displaying the error // as the formatted value. func handleMethods(cs *ConfigState, w io.Writer, v reflect.Value) (handled bool) { // We need an interface to check if the type implements the error or // Stringer interface. However, the reflect package won't give us an // interface on certain things like unexported struct fields in order // to enforce visibility rules. We use unsafe, when it's available, // to bypass these restrictions since this package does not mutate the // values. if !v.CanInterface() { if UnsafeDisabled { return false } v = unsafeReflectValue(v) } // Choose whether or not to do error and Stringer interface lookups against // the base type or a pointer to the base type depending on settings. // Technically calling one of these methods with a pointer receiver can // mutate the value, however, types which choose to satisfy an error or // Stringer interface with a pointer receiver should not be mutating their // state inside these interface methods. if !cs.DisablePointerMethods && !UnsafeDisabled && !v.CanAddr() { v = unsafeReflectValue(v) } if v.CanAddr() { v = v.Addr() } // Is it an error or Stringer? switch iface := v.Interface().(type) { case error: defer catchPanic(w, v) if cs.ContinueOnMethod { w.Write(openParenBytes) w.Write([]byte(iface.Error())) w.Write(closeParenBytes) w.Write(spaceBytes) return false } w.Write([]byte(iface.Error())) return true case fmt.Stringer: defer catchPanic(w, v) if cs.ContinueOnMethod { w.Write(openParenBytes) w.Write([]byte(iface.String())) w.Write(closeParenBytes) w.Write(spaceBytes) return false } w.Write([]byte(iface.String())) return true } return false } // printBool outputs a boolean value as true or false to Writer w. func printBool(w io.Writer, val bool) { if val { w.Write(trueBytes) } else { w.Write(falseBytes) } } // printInt outputs a signed integer value to Writer w. func printInt(w io.Writer, val int64, base int) { w.Write([]byte(strconv.FormatInt(val, base))) } // printUint outputs an unsigned integer value to Writer w. func printUint(w io.Writer, val uint64, base int) { w.Write([]byte(strconv.FormatUint(val, base))) } // printFloat outputs a floating point value using the specified precision, // which is expected to be 32 or 64bit, to Writer w. func printFloat(w io.Writer, val float64, precision int) { w.Write([]byte(strconv.FormatFloat(val, 'g', -1, precision))) } // printComplex outputs a complex value using the specified float precision // for the real and imaginary parts to Writer w. func printComplex(w io.Writer, c complex128, floatPrecision int) { r := real(c) w.Write(openParenBytes) w.Write([]byte(strconv.FormatFloat(r, 'g', -1, floatPrecision))) i := imag(c) if i >= 0 { w.Write(plusBytes) } w.Write([]byte(strconv.FormatFloat(i, 'g', -1, floatPrecision))) w.Write(iBytes) w.Write(closeParenBytes) } // printHexPtr outputs a uintptr formatted as hexadecimal with a leading '0x' // prefix to Writer w. func printHexPtr(w io.Writer, p uintptr) { // Null pointer. num := uint64(p) if num == 0 { w.Write(nilAngleBytes) return } // Max uint64 is 16 bytes in hex + 2 bytes for '0x' prefix buf := make([]byte, 18) // It's simpler to construct the hex string right to left. base := uint64(16) i := len(buf) - 1 for num >= base { buf[i] = hexDigits[num%base] num /= base i-- } buf[i] = hexDigits[num] // Add '0x' prefix. i-- buf[i] = 'x' i-- buf[i] = '0' // Strip unused leading bytes. buf = buf[i:] w.Write(buf) } // valuesSorter implements sort.Interface to allow a slice of reflect.Value // elements to be sorted. type valuesSorter struct { values []reflect.Value strings []string // either nil or same len and values cs *ConfigState } // newValuesSorter initializes a valuesSorter instance, which holds a set of // surrogate keys on which the data should be sorted. It uses flags in // ConfigState to decide if and how to populate those surrogate keys. func newValuesSorter(values []reflect.Value, cs *ConfigState) sort.Interface { vs := &valuesSorter{values: values, cs: cs} if canSortSimply(vs.values[0].Kind()) { return vs } if !cs.DisableMethods { vs.strings = make([]string, len(values)) for i := range vs.values { b := bytes.Buffer{} if !handleMethods(cs, &b, vs.values[i]) { vs.strings = nil break } vs.strings[i] = b.String() } } if vs.strings == nil && cs.SpewKeys { vs.strings = make([]string, len(values)) for i := range vs.values { vs.strings[i] = Sprintf("%#v", vs.values[i].Interface()) } } return vs } // canSortSimply tests whether a reflect.Kind is a primitive that can be sorted // directly, or whether it should be considered for sorting by surrogate keys // (if the ConfigState allows it). func canSortSimply(kind reflect.Kind) bool { // This switch parallels valueSortLess, except for the default case. switch kind { case reflect.Bool: return true case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: return true case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: return true case reflect.Float32, reflect.Float64: return true case reflect.String: return true case reflect.Uintptr: return true case reflect.Array: return true } return false } // Len returns the number of values in the slice. It is part of the // sort.Interface implementation. func (s *valuesSorter) Len() int { return len(s.values) } // Swap swaps the values at the passed indices. It is part of the // sort.Interface implementation. func (s *valuesSorter) Swap(i, j int) { s.values[i], s.values[j] = s.values[j], s.values[i] if s.strings != nil { s.strings[i], s.strings[j] = s.strings[j], s.strings[i] } } // valueSortLess returns whether the first value should sort before the second // value. It is used by valueSorter.Less as part of the sort.Interface // implementation. func valueSortLess(a, b reflect.Value) bool { switch a.Kind() { case reflect.Bool: return !a.Bool() && b.Bool() case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: return a.Int() < b.Int() case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: return a.Uint() < b.Uint() case reflect.Float32, reflect.Float64: return a.Float() < b.Float() case reflect.String: return a.String() < b.String() case reflect.Uintptr: return a.Uint() < b.Uint() case reflect.Array: // Compare the contents of both arrays. l := a.Len() for i := 0; i < l; i++ { av := a.Index(i) bv := b.Index(i) if av.Interface() == bv.Interface() { continue } return valueSortLess(av, bv) } } return a.String() < b.String() } // Less returns whether the value at index i should sort before the // value at index j. It is part of the sort.Interface implementation. func (s *valuesSorter) Less(i, j int) bool { if s.strings == nil { return valueSortLess(s.values[i], s.values[j]) } return s.strings[i] < s.strings[j] } // sortValues is a sort function that handles both native types and any type that // can be converted to error or Stringer. Other inputs are sorted according to // their Value.String() value to ensure display stability. func sortValues(values []reflect.Value, cs *ConfigState) { if len(values) == 0 { return } sort.Sort(newValuesSorter(values, cs)) } ================================================ FILE: internal/spew/common_test.go ================================================ /* * Copyright (c) 2013-2016 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ package spew_test import ( "fmt" "reflect" "testing" "github.com/expr-lang/expr/internal/spew" ) // custom type to test Stinger interface on non-pointer receiver. type stringer string // String implements the Stringer interface for testing invocation of custom // stringers on types with non-pointer receivers. func (s stringer) String() string { return "stringer " + string(s) } // custom type to test Stinger interface on pointer receiver. type pstringer string // String implements the Stringer interface for testing invocation of custom // stringers on types with only pointer receivers. func (s *pstringer) String() string { return "stringer " + string(*s) } // xref1 and xref2 are cross referencing structs for testing circular reference // detection. type xref1 struct { ps2 *xref2 } type xref2 struct { ps1 *xref1 } // indirCir1, indirCir2, and indirCir3 are used to generate an indirect circular // reference for testing detection. type indirCir1 struct { ps2 *indirCir2 } type indirCir2 struct { ps3 *indirCir3 } type indirCir3 struct { ps1 *indirCir1 } // embed is used to test embedded structures. type embed struct { a string } // embedwrap is used to test embedded structures. type embedwrap struct { *embed e *embed } // panicer is used to intentionally cause a panic for testing spew properly // handles them type panicer int func (p panicer) String() string { panic("test panic") } // customError is used to test custom error interface invocation. type customError int func (e customError) Error() string { return fmt.Sprintf("error: %d", int(e)) } // stringizeWants converts a slice of wanted test output into a format suitable // for a test error message. func stringizeWants(wants []string) string { s := "" for i, want := range wants { if i > 0 { s += fmt.Sprintf("want%d: %s", i+1, want) } else { s += "want: " + want } } return s } // testFailed returns whether or not a test failed by checking if the result // of the test is in the slice of wanted strings. func testFailed(result string, wants []string) bool { for _, want := range wants { if result == want { return false } } return true } type sortableStruct struct { x int } func (ss sortableStruct) String() string { return fmt.Sprintf("ss.%d", ss.x) } type unsortableStruct struct { x int } type sortTestCase struct { input []reflect.Value expected []reflect.Value } func helpTestSortValues(tests []sortTestCase, cs *spew.ConfigState, t *testing.T) { getInterfaces := func(values []reflect.Value) []interface{} { interfaces := []interface{}{} for _, v := range values { interfaces = append(interfaces, v.Interface()) } return interfaces } for _, test := range tests { spew.SortValues(test.input, cs) // reflect.DeepEqual cannot really make sense of reflect.Value, // probably because of all the pointer tricks. For instance, // v(2.0) != v(2.0) on a 32-bits system. Turn them into interface{} // instead. input := getInterfaces(test.input) expected := getInterfaces(test.expected) if !reflect.DeepEqual(input, expected) { t.Errorf("Sort mismatch:\n %v != %v", input, expected) } } } // TestSortValues ensures the sort functionality for reflect.Value based sorting // works as intended. func TestSortValues(t *testing.T) { v := reflect.ValueOf a := v("a") b := v("b") c := v("c") embedA := v(embed{"a"}) embedB := v(embed{"b"}) embedC := v(embed{"c"}) tests := []sortTestCase{ // No values. { []reflect.Value{}, []reflect.Value{}, }, // Bools. { []reflect.Value{v(false), v(true), v(false)}, []reflect.Value{v(false), v(false), v(true)}, }, // Ints. { []reflect.Value{v(2), v(1), v(3)}, []reflect.Value{v(1), v(2), v(3)}, }, // Uints. { []reflect.Value{v(uint8(2)), v(uint8(1)), v(uint8(3))}, []reflect.Value{v(uint8(1)), v(uint8(2)), v(uint8(3))}, }, // Floats. { []reflect.Value{v(2.0), v(1.0), v(3.0)}, []reflect.Value{v(1.0), v(2.0), v(3.0)}, }, // Strings. { []reflect.Value{b, a, c}, []reflect.Value{a, b, c}, }, // Array { []reflect.Value{v([3]int{3, 2, 1}), v([3]int{1, 3, 2}), v([3]int{1, 2, 3})}, []reflect.Value{v([3]int{1, 2, 3}), v([3]int{1, 3, 2}), v([3]int{3, 2, 1})}, }, // Uintptrs. { []reflect.Value{v(uintptr(2)), v(uintptr(1)), v(uintptr(3))}, []reflect.Value{v(uintptr(1)), v(uintptr(2)), v(uintptr(3))}, }, // SortableStructs. { // Note: not sorted - DisableMethods is set. []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})}, []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})}, }, // UnsortableStructs. { // Note: not sorted - SpewKeys is false. []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, }, // Invalid. { []reflect.Value{embedB, embedA, embedC}, []reflect.Value{embedB, embedA, embedC}, }, } cs := spew.ConfigState{DisableMethods: true, SpewKeys: false} helpTestSortValues(tests, &cs, t) } // TestSortValuesWithMethods ensures the sort functionality for reflect.Value // based sorting works as intended when using string methods. func TestSortValuesWithMethods(t *testing.T) { v := reflect.ValueOf a := v("a") b := v("b") c := v("c") tests := []sortTestCase{ // Ints. { []reflect.Value{v(2), v(1), v(3)}, []reflect.Value{v(1), v(2), v(3)}, }, // Strings. { []reflect.Value{b, a, c}, []reflect.Value{a, b, c}, }, // SortableStructs. { []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})}, []reflect.Value{v(sortableStruct{1}), v(sortableStruct{2}), v(sortableStruct{3})}, }, // UnsortableStructs. { // Note: not sorted - SpewKeys is false. []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, }, } cs := spew.ConfigState{DisableMethods: false, SpewKeys: false} helpTestSortValues(tests, &cs, t) } // TestSortValuesWithSpew ensures the sort functionality for reflect.Value // based sorting works as intended when using spew to stringify keys. func TestSortValuesWithSpew(t *testing.T) { v := reflect.ValueOf a := v("a") b := v("b") c := v("c") tests := []sortTestCase{ // Ints. { []reflect.Value{v(2), v(1), v(3)}, []reflect.Value{v(1), v(2), v(3)}, }, // Strings. { []reflect.Value{b, a, c}, []reflect.Value{a, b, c}, }, // SortableStructs. { []reflect.Value{v(sortableStruct{2}), v(sortableStruct{1}), v(sortableStruct{3})}, []reflect.Value{v(sortableStruct{1}), v(sortableStruct{2}), v(sortableStruct{3})}, }, // UnsortableStructs. { []reflect.Value{v(unsortableStruct{2}), v(unsortableStruct{1}), v(unsortableStruct{3})}, []reflect.Value{v(unsortableStruct{1}), v(unsortableStruct{2}), v(unsortableStruct{3})}, }, } cs := spew.ConfigState{DisableMethods: true, SpewKeys: true} helpTestSortValues(tests, &cs, t) } ================================================ FILE: internal/spew/config.go ================================================ /* * Copyright (c) 2013-2016 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ package spew import ( "bytes" "fmt" "io" "os" ) // ConfigState houses the configuration options used by spew to format and // display values. There is a global instance, Config, that is used to control // all top-level Formatter and Dump functionality. Each ConfigState instance // provides methods equivalent to the top-level functions. // // The zero value for ConfigState provides no indentation. You would typically // want to set it to a space or a tab. // // Alternatively, you can use NewDefaultConfig to get a ConfigState instance // with default settings. See the documentation of NewDefaultConfig for default // values. type ConfigState struct { // Indent specifies the string to use for each indentation level. The // global config instance that all top-level functions use set this to a // single space by default. If you would like more indentation, you might // set this to a tab with "\t" or perhaps two spaces with " ". Indent string // MaxDepth controls the maximum number of levels to descend into nested // data structures. The default, 0, means there is no limit. // // NOTE: Circular data structures are properly detected, so it is not // necessary to set this value unless you specifically want to limit deeply // nested data structures. MaxDepth int // DisableMethods specifies whether or not error and Stringer interfaces are // invoked for types that implement them. DisableMethods bool // DisablePointerMethods specifies whether or not to check for and invoke // error and Stringer interfaces on types which only accept a pointer // receiver when the current type is not a pointer. // // NOTE: This might be an unsafe action since calling one of these methods // with a pointer receiver could technically mutate the value, however, // in practice, types which choose to satisfy an error or Stringer // interface with a pointer receiver should not be mutating their state // inside these interface methods. As a result, this option relies on // access to the unsafe package, so it will not have any effect when // running in environments without access to the unsafe package such as // Google App Engine or with the "safe" build tag specified. DisablePointerMethods bool // DisablePointerAddresses specifies whether to disable the printing of // pointer addresses. This is useful when diffing data structures in tests. DisablePointerAddresses bool // DisableCapacities specifies whether to disable the printing of capacities // for arrays, slices, maps and channels. This is useful when diffing // data structures in tests. DisableCapacities bool // ContinueOnMethod specifies whether or not recursion should continue once // a custom error or Stringer interface is invoked. The default, false, // means it will print the results of invoking the custom error or Stringer // interface and return immediately instead of continuing to recurse into // the internals of the data type. // // NOTE: This flag does not have any effect if method invocation is disabled // via the DisableMethods or DisablePointerMethods options. ContinueOnMethod bool // SortKeys specifies map keys should be sorted before being printed. Use // this to have a more deterministic, diffable output. Note that only // native types (bool, int, uint, floats, uintptr and string) and types // that support the error or Stringer interfaces (if methods are // enabled) are supported, with other types sorted according to the // reflect.Value.String() output which guarantees display stability. SortKeys bool // SpewKeys specifies that, as a last resort attempt, map keys should // be spewed to strings and sorted by those strings. This is only // considered if SortKeys is true. SpewKeys bool } // Config is the active configuration of the top-level functions. // The configuration can be changed by modifying the contents of spew.Config. var Config = ConfigState{Indent: " "} // Errorf is a wrapper for fmt.Errorf that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the formatted string as a value that satisfies error. See NewFormatter // for formatting details. // // This function is shorthand for the following syntax: // // fmt.Errorf(format, c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Errorf(format string, a ...interface{}) (err error) { return fmt.Errorf(format, c.convertArgs(a)...) } // Fprint is a wrapper for fmt.Fprint that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Fprint(w, c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Fprint(w io.Writer, a ...interface{}) (n int, err error) { return fmt.Fprint(w, c.convertArgs(a)...) } // Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Fprintf(w, format, c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { return fmt.Fprintf(w, format, c.convertArgs(a)...) } // Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it // passed with a Formatter interface returned by c.NewFormatter. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Fprintln(w, c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Fprintln(w io.Writer, a ...interface{}) (n int, err error) { return fmt.Fprintln(w, c.convertArgs(a)...) } // Print is a wrapper for fmt.Print that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Print(c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Print(a ...interface{}) (n int, err error) { return fmt.Print(c.convertArgs(a)...) } // Printf is a wrapper for fmt.Printf that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Printf(format, c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Printf(format string, a ...interface{}) (n int, err error) { return fmt.Printf(format, c.convertArgs(a)...) } // Println is a wrapper for fmt.Println that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Println(c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Println(a ...interface{}) (n int, err error) { return fmt.Println(c.convertArgs(a)...) } // Sprint is a wrapper for fmt.Sprint that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the resulting string. See NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Sprint(c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Sprint(a ...interface{}) string { return fmt.Sprint(c.convertArgs(a)...) } // Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were // passed with a Formatter interface returned by c.NewFormatter. It returns // the resulting string. See NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Sprintf(format, c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Sprintf(format string, a ...interface{}) string { return fmt.Sprintf(format, c.convertArgs(a)...) } // Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it // were passed with a Formatter interface returned by c.NewFormatter. It // returns the resulting string. See NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Sprintln(c.NewFormatter(a), c.NewFormatter(b)) func (c *ConfigState) Sprintln(a ...interface{}) string { return fmt.Sprintln(c.convertArgs(a)...) } /* NewFormatter returns a custom formatter that satisfies the fmt.Formatter interface. As a result, it integrates cleanly with standard fmt package printing functions. The formatter is useful for inline printing of smaller data types similar to the standard %v format specifier. The custom formatter only responds to the %v (most compact), %+v (adds pointer addresses), %#v (adds types), and %#+v (adds types and pointer addresses) verb combinations. Any other verbs such as %x and %q will be sent to the standard fmt package for formatting. In addition, the custom formatter ignores the width and precision arguments (however they will still work on the format specifiers not handled by the custom formatter). Typically this function shouldn't be called directly. It is much easier to make use of the custom formatter by calling one of the convenience functions such as c.Printf, c.Println, or c.Printf. */ func (c *ConfigState) NewFormatter(v interface{}) fmt.Formatter { return newFormatter(c, v) } // Fdump formats and displays the passed arguments to io.Writer w. It formats // exactly the same as Dump. func (c *ConfigState) Fdump(w io.Writer, a ...interface{}) { fdump(c, w, a...) } /* Dump displays the passed parameters to standard out with newlines, customizable indentation, and additional debug information such as complete types and all pointer addresses used to indirect to the final value. It provides the following features over the built-in printing facilities provided by the fmt package: - Pointers are dereferenced and followed - Circular data structures are detected and handled properly - Custom Stringer/error interfaces are optionally invoked, including on unexported types - Custom types which only implement the Stringer/error interfaces via a pointer receiver are optionally invoked when passing non-pointer variables - Byte arrays and slices are dumped like the hexdump -C command which includes offsets, byte values in hex, and ASCII output The configuration options are controlled by modifying the public members of c. See ConfigState for options documentation. See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to get the formatted result as a string. */ func (c *ConfigState) Dump(a ...interface{}) { fdump(c, os.Stdout, a...) } // Sdump returns a string with the passed arguments formatted exactly the same // as Dump. func (c *ConfigState) Sdump(a ...interface{}) string { var buf bytes.Buffer fdump(c, &buf, a...) return buf.String() } // convertArgs accepts a slice of arguments and returns a slice of the same // length with each argument converted to a spew Formatter interface using // the ConfigState associated with s. func (c *ConfigState) convertArgs(args []interface{}) (formatters []interface{}) { formatters = make([]interface{}, len(args)) for index, arg := range args { formatters[index] = newFormatter(c, arg) } return formatters } // NewDefaultConfig returns a ConfigState with the following default settings. // // Indent: " " // MaxDepth: 0 // DisableMethods: false // DisablePointerMethods: false // ContinueOnMethod: false // SortKeys: false func NewDefaultConfig() *ConfigState { return &ConfigState{Indent: " "} } ================================================ FILE: internal/spew/doc.go ================================================ /* * Copyright (c) 2013-2016 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* Package spew implements a deep pretty printer for Go data structures to aid in debugging. A quick overview of the additional features spew provides over the built-in printing facilities for Go data types are as follows: - Pointers are dereferenced and followed - Circular data structures are detected and handled properly - Custom Stringer/error interfaces are optionally invoked, including on unexported types - Custom types which only implement the Stringer/error interfaces via a pointer receiver are optionally invoked when passing non-pointer variables - Byte arrays and slices are dumped like the hexdump -C command which includes offsets, byte values in hex, and ASCII output (only when using Dump style) There are two different approaches spew allows for dumping Go data structures: - Dump style which prints with newlines, customizable indentation, and additional debug information such as types and all pointer addresses used to indirect to the final value - A custom Formatter interface that integrates cleanly with the standard fmt package and replaces %v, %+v, %#v, and %#+v to provide inline printing similar to the default %v while providing the additional functionality outlined above and passing unsupported format verbs such as %x and %q along to fmt # Quick Start This section demonstrates how to quickly get started with spew. See the sections below for further details on formatting and configuration options. To dump a variable with full newlines, indentation, type, and pointer information use Dump, Fdump, or Sdump: spew.Dump(myVar1, myVar2, ...) spew.Fdump(someWriter, myVar1, myVar2, ...) str := spew.Sdump(myVar1, myVar2, ...) Alternatively, if you would prefer to use format strings with a compacted inline printing style, use the convenience wrappers Printf, Fprintf, etc with %v (most compact), %+v (adds pointer addresses), %#v (adds types), or %#+v (adds types and pointer addresses): spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) spew.Fprintf(someWriter, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) spew.Fprintf(someWriter, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) # Configuration Options Configuration of spew is handled by fields in the ConfigState type. For convenience, all of the top-level functions use a global state available via the spew.Config global. It is also possible to create a ConfigState instance that provides methods equivalent to the top-level functions. This allows concurrent configuration options. See the ConfigState documentation for more details. The following configuration options are available: - Indent String to use for each indentation level for Dump functions. It is a single space by default. A popular alternative is "\t". - MaxDepth Maximum number of levels to descend into nested data structures. There is no limit by default. - DisableMethods Disables invocation of error and Stringer interface methods. Method invocation is enabled by default. - DisablePointerMethods Disables invocation of error and Stringer interface methods on types which only accept pointer receivers from non-pointer variables. Pointer method invocation is enabled by default. - DisablePointerAddresses DisablePointerAddresses specifies whether to disable the printing of pointer addresses. This is useful when diffing data structures in tests. - DisableCapacities DisableCapacities specifies whether to disable the printing of capacities for arrays, slices, maps and channels. This is useful when diffing data structures in tests. - ContinueOnMethod Enables recursion into types after invoking error and Stringer interface methods. Recursion after method invocation is disabled by default. - SortKeys Specifies map keys should be sorted before being printed. Use this to have a more deterministic, diffable output. Note that only native types (bool, int, uint, floats, uintptr and string) and types which implement error or Stringer interfaces are supported with other types sorted according to the reflect.Value.String() output which guarantees display stability. Natural map order is used by default. - SpewKeys Specifies that, as a last resort attempt, map keys should be spewed to strings and sorted by those strings. This is only considered if SortKeys is true. # Dump Usage Simply call spew.Dump with a list of variables you want to dump: spew.Dump(myVar1, myVar2, ...) You may also call spew.Fdump if you would prefer to output to an arbitrary io.Writer. For example, to dump to standard error: spew.Fdump(os.Stderr, myVar1, myVar2, ...) A third option is to call spew.Sdump to get the formatted output as a string: str := spew.Sdump(myVar1, myVar2, ...) # Sample Dump Output See the Dump example for details on the setup of the types and variables being shown here. (main.Foo) { unexportedField: (*main.Bar)(0xf84002e210)({ flag: (main.Flag) flagTwo, data: (uintptr) }), ExportedField: (map[interface {}]interface {}) (len=1) { (string) (len=3) "one": (bool) true } } Byte (and uint8) arrays and slices are displayed uniquely like the hexdump -C command as shown. ([]uint8) (len=32 cap=32) { 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... | 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0| 00000020 31 32 |12| } # Custom Formatter Spew provides a custom formatter that implements the fmt.Formatter interface so that it integrates cleanly with standard fmt package printing functions. The formatter is useful for inline printing of smaller data types similar to the standard %v format specifier. The custom formatter only responds to the %v (most compact), %+v (adds pointer addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb combinations. Any other verbs such as %x and %q will be sent to the standard fmt package for formatting. In addition, the custom formatter ignores the width and precision arguments (however they will still work on the format specifiers not handled by the custom formatter). # Custom Formatter Usage The simplest way to make use of the spew custom formatter is to call one of the convenience functions such as spew.Printf, spew.Println, or spew.Printf. The functions have syntax you are most likely already familiar with: spew.Printf("myVar1: %v -- myVar2: %+v", myVar1, myVar2) spew.Printf("myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) spew.Println(myVar, myVar2) spew.Fprintf(os.Stderr, "myVar1: %v -- myVar2: %+v", myVar1, myVar2) spew.Fprintf(os.Stderr, "myVar3: %#v -- myVar4: %#+v", myVar3, myVar4) See the Index for the full list convenience functions. # Sample Formatter Output Double pointer to a uint8: %v: <**>5 %+v: <**>(0xf8400420d0->0xf8400420c8)5 %#v: (**uint8)5 %#+v: (**uint8)(0xf8400420d0->0xf8400420c8)5 Pointer to circular struct with a uint8 field and a pointer to itself: %v: <*>{1 <*>} %+v: <*>(0xf84003e260){ui8:1 c:<*>(0xf84003e260)} %#v: (*main.circular){ui8:(uint8)1 c:(*main.circular)} %#+v: (*main.circular)(0xf84003e260){ui8:(uint8)1 c:(*main.circular)(0xf84003e260)} See the Printf example for details on the setup of variables being shown here. # Errors Since it is possible for custom Stringer/error interfaces to panic, spew detects them and handles them internally by printing the panic information inline with the output. Since spew is intended to provide deep pretty printing capabilities on structures, it intentionally does not return any errors. */ package spew ================================================ FILE: internal/spew/dump.go ================================================ /* * Copyright (c) 2013-2016 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ package spew import ( "bytes" "encoding/hex" "fmt" "io" "os" "reflect" "regexp" "strconv" "strings" ) var ( // uint8Type is a reflect.Type representing a uint8. It is used to // convert cgo types to uint8 slices for hexdumping. uint8Type = reflect.TypeOf(uint8(0)) // cCharRE is a regular expression that matches a cgo char. // It is used to detect character arrays to hexdump them. cCharRE = regexp.MustCompile(`^.*\._Ctype_char$`) // cUnsignedCharRE is a regular expression that matches a cgo unsigned // char. It is used to detect unsigned character arrays to hexdump // them. cUnsignedCharRE = regexp.MustCompile(`^.*\._Ctype_unsignedchar$`) // cUint8tCharRE is a regular expression that matches a cgo uint8_t. // It is used to detect uint8_t arrays to hexdump them. cUint8tCharRE = regexp.MustCompile(`^.*\._Ctype_uint8_t$`) ) // dumpState contains information about the state of a dump operation. type dumpState struct { w io.Writer depth int pointers map[uintptr]int ignoreNextType bool ignoreNextIndent bool cs *ConfigState } // indent performs indentation according to the depth level and cs.Indent // option. func (d *dumpState) indent() { if d.ignoreNextIndent { d.ignoreNextIndent = false return } d.w.Write(bytes.Repeat([]byte(d.cs.Indent), d.depth)) } // unpackValue returns values inside of non-nil interfaces when possible. // This is useful for data types like structs, arrays, slices, and maps which // can contain varying types packed inside an interface. func (d *dumpState) unpackValue(v reflect.Value) reflect.Value { if v.Kind() == reflect.Interface && !v.IsNil() { v = v.Elem() } return v } // dumpPtr handles formatting of pointers by indirecting them as necessary. func (d *dumpState) dumpPtr(v reflect.Value) { // Remove pointers at or below the current depth from map used to detect // circular refs. for k, depth := range d.pointers { if depth >= d.depth { delete(d.pointers, k) } } // Keep list of all dereferenced pointers to show later. pointerChain := make([]uintptr, 0) // Figure out how many levels of indirection there are by dereferencing // pointers and unpacking interfaces down the chain while detecting circular // references. nilFound := false cycleFound := false indirects := 0 ve := v for ve.Kind() == reflect.Ptr { if ve.IsNil() { nilFound = true break } indirects++ addr := ve.Pointer() pointerChain = append(pointerChain, addr) if pd, ok := d.pointers[addr]; ok && pd < d.depth { cycleFound = true indirects-- break } d.pointers[addr] = d.depth ve = ve.Elem() if ve.Kind() == reflect.Interface { if ve.IsNil() { nilFound = true break } ve = ve.Elem() } } // Display type information. d.w.Write(openParenBytes) d.w.Write(bytes.Repeat(asteriskBytes, indirects)) d.w.Write([]byte(ve.Type().String())) d.w.Write(closeParenBytes) // Display pointer information. if !d.cs.DisablePointerAddresses && len(pointerChain) > 0 { d.w.Write(openParenBytes) for i, addr := range pointerChain { if i > 0 { d.w.Write(pointerChainBytes) } printHexPtr(d.w, addr) } d.w.Write(closeParenBytes) } // Display dereferenced value. d.w.Write(openParenBytes) switch { case nilFound: d.w.Write(nilAngleBytes) case cycleFound: d.w.Write(circularBytes) default: d.ignoreNextType = true d.dump(ve) } d.w.Write(closeParenBytes) } // dumpSlice handles formatting of arrays and slices. Byte (uint8 under // reflection) arrays and slices are dumped in hexdump -C fashion. func (d *dumpState) dumpSlice(v reflect.Value) { // Determine whether this type should be hex dumped or not. Also, // for types which should be hexdumped, try to use the underlying data // first, then fall back to trying to convert them to a uint8 slice. var buf []uint8 doConvert := false doHexDump := false numEntries := v.Len() if numEntries > 0 { vt := v.Index(0).Type() vts := vt.String() switch { // C types that need to be converted. case cCharRE.MatchString(vts): fallthrough case cUnsignedCharRE.MatchString(vts): fallthrough case cUint8tCharRE.MatchString(vts): doConvert = true // Try to use existing uint8 slices and fall back to converting // and copying if that fails. case vt.Kind() == reflect.Uint8: // We need an addressable interface to convert the type // to a byte slice. However, the reflect package won't // give us an interface on certain things like // unexported struct fields in order to enforce // visibility rules. We use unsafe, when available, to // bypass these restrictions since this package does not // mutate the values. vs := v if !vs.CanInterface() || !vs.CanAddr() { vs = unsafeReflectValue(vs) } if !UnsafeDisabled { vs = vs.Slice(0, numEntries) // Use the existing uint8 slice if it can be // type asserted. iface := vs.Interface() if slice, ok := iface.([]uint8); ok { buf = slice doHexDump = true break } } // The underlying data needs to be converted if it can't // be type asserted to a uint8 slice. doConvert = true } // Copy and convert the underlying type if needed. if doConvert && vt.ConvertibleTo(uint8Type) { // Convert and copy each element into a uint8 byte // slice. buf = make([]uint8, numEntries) for i := 0; i < numEntries; i++ { vv := v.Index(i) buf[i] = uint8(vv.Convert(uint8Type).Uint()) } doHexDump = true } } // Hexdump the entire slice as needed. if doHexDump { indent := strings.Repeat(d.cs.Indent, d.depth) str := indent + hex.Dump(buf) str = strings.Replace(str, "\n", "\n"+indent, -1) str = strings.TrimRight(str, d.cs.Indent) d.w.Write([]byte(str)) return } // Recursively call dump for each item. for i := 0; i < numEntries; i++ { d.dump(d.unpackValue(v.Index(i))) if i < (numEntries - 1) { d.w.Write(commaNewlineBytes) } else { d.w.Write(newlineBytes) } } } // dump is the main workhorse for dumping a value. It uses the passed reflect // value to figure out what kind of object we are dealing with and formats it // appropriately. It is a recursive function, however circular data structures // are detected and handled properly. func (d *dumpState) dump(v reflect.Value) { // Handle invalid reflect values immediately. kind := v.Kind() if kind == reflect.Invalid { d.w.Write(invalidAngleBytes) return } // Handle pointers specially. if kind == reflect.Ptr { d.indent() d.dumpPtr(v) return } // Print type information unless already handled elsewhere. if !d.ignoreNextType { d.indent() d.w.Write(openParenBytes) d.w.Write([]byte(v.Type().String())) d.w.Write(closeParenBytes) d.w.Write(spaceBytes) } d.ignoreNextType = false // Display length and capacity if the built-in len and cap functions // work with the value's kind and the len/cap itself is non-zero. valueLen, valueCap := 0, 0 switch v.Kind() { case reflect.Array, reflect.Slice, reflect.Chan: valueLen, valueCap = v.Len(), v.Cap() case reflect.Map, reflect.String: valueLen = v.Len() } if valueLen != 0 || !d.cs.DisableCapacities && valueCap != 0 { d.w.Write(openParenBytes) if valueLen != 0 { d.w.Write(lenEqualsBytes) printInt(d.w, int64(valueLen), 10) } if !d.cs.DisableCapacities && valueCap != 0 { if valueLen != 0 { d.w.Write(spaceBytes) } d.w.Write(capEqualsBytes) printInt(d.w, int64(valueCap), 10) } d.w.Write(closeParenBytes) d.w.Write(spaceBytes) } // Call Stringer/error interfaces if they exist and the handle methods flag // is enabled if !d.cs.DisableMethods { if (kind != reflect.Invalid) && (kind != reflect.Interface) { if handled := handleMethods(d.cs, d.w, v); handled { return } } } switch kind { case reflect.Invalid: // Do nothing. We should never get here since invalid has already // been handled above. case reflect.Bool: printBool(d.w, v.Bool()) case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: printInt(d.w, v.Int(), 10) case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: printUint(d.w, v.Uint(), 10) case reflect.Float32: printFloat(d.w, v.Float(), 32) case reflect.Float64: printFloat(d.w, v.Float(), 64) case reflect.Complex64: printComplex(d.w, v.Complex(), 32) case reflect.Complex128: printComplex(d.w, v.Complex(), 64) case reflect.Slice: if v.IsNil() { d.w.Write(nilAngleBytes) break } fallthrough case reflect.Array: d.w.Write(openBraceNewlineBytes) d.depth++ if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { d.indent() d.w.Write(maxNewlineBytes) } else { d.dumpSlice(v) } d.depth-- d.indent() d.w.Write(closeBraceBytes) case reflect.String: d.w.Write([]byte(strconv.Quote(v.String()))) case reflect.Interface: // The only time we should get here is for nil interfaces due to // unpackValue calls. if v.IsNil() { d.w.Write(nilAngleBytes) } case reflect.Ptr: // Do nothing. We should never get here since pointers have already // been handled above. case reflect.Map: // nil maps should be indicated as different than empty maps if v.IsNil() { d.w.Write(nilAngleBytes) break } d.w.Write(openBraceNewlineBytes) d.depth++ if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { d.indent() d.w.Write(maxNewlineBytes) } else { numEntries := v.Len() keys := v.MapKeys() if d.cs.SortKeys { sortValues(keys, d.cs) } for i, key := range keys { d.dump(d.unpackValue(key)) d.w.Write(colonSpaceBytes) d.ignoreNextIndent = true d.dump(d.unpackValue(v.MapIndex(key))) if i < (numEntries - 1) { d.w.Write(commaNewlineBytes) } else { d.w.Write(newlineBytes) } } } d.depth-- d.indent() d.w.Write(closeBraceBytes) case reflect.Struct: d.w.Write(openBraceNewlineBytes) d.depth++ if (d.cs.MaxDepth != 0) && (d.depth > d.cs.MaxDepth) { d.indent() d.w.Write(maxNewlineBytes) } else { vt := v.Type() numFields := v.NumField() for i := 0; i < numFields; i++ { d.indent() vtf := vt.Field(i) d.w.Write([]byte(vtf.Name)) d.w.Write(colonSpaceBytes) d.ignoreNextIndent = true d.dump(d.unpackValue(v.Field(i))) if i < (numFields - 1) { d.w.Write(commaNewlineBytes) } else { d.w.Write(newlineBytes) } } } d.depth-- d.indent() d.w.Write(closeBraceBytes) case reflect.Uintptr: printHexPtr(d.w, uintptr(v.Uint())) case reflect.UnsafePointer, reflect.Chan, reflect.Func: printHexPtr(d.w, v.Pointer()) // There were not any other types at the time this code was written, but // fall back to letting the default fmt package handle it in case any new // types are added. default: if v.CanInterface() { fmt.Fprintf(d.w, "%v", v.Interface()) } else { fmt.Fprintf(d.w, "%v", v.String()) } } } // fdump is a helper function to consolidate the logic from the various public // methods which take varying writers and config states. func fdump(cs *ConfigState, w io.Writer, a ...interface{}) { for _, arg := range a { if arg == nil { w.Write(interfaceBytes) w.Write(spaceBytes) w.Write(nilAngleBytes) w.Write(newlineBytes) continue } d := dumpState{w: w, cs: cs} d.pointers = make(map[uintptr]int) d.dump(reflect.ValueOf(arg)) d.w.Write(newlineBytes) } } // Fdump formats and displays the passed arguments to io.Writer w. It formats // exactly the same as Dump. func Fdump(w io.Writer, a ...interface{}) { fdump(&Config, w, a...) } // Sdump returns a string with the passed arguments formatted exactly the same // as Dump. func Sdump(a ...interface{}) string { var buf bytes.Buffer fdump(&Config, &buf, a...) return buf.String() } /* Dump displays the passed parameters to standard out with newlines, customizable indentation, and additional debug information such as complete types and all pointer addresses used to indirect to the final value. It provides the following features over the built-in printing facilities provided by the fmt package: - Pointers are dereferenced and followed - Circular data structures are detected and handled properly - Custom Stringer/error interfaces are optionally invoked, including on unexported types - Custom types which only implement the Stringer/error interfaces via a pointer receiver are optionally invoked when passing non-pointer variables - Byte arrays and slices are dumped like the hexdump -C command which includes offsets, byte values in hex, and ASCII output The configuration options are controlled by an exported package global, spew.Config. See ConfigState for options documentation. See Fdump if you would prefer dumping to an arbitrary io.Writer or Sdump to get the formatted result as a string. */ func Dump(a ...interface{}) { fdump(&Config, os.Stdout, a...) } ================================================ FILE: internal/spew/dump_test.go ================================================ /* * Copyright (c) 2013-2016 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* Test Summary: NOTE: For each test, a nil pointer, a single pointer and double pointer to the base test element are also tested to ensure proper indirection across all types. - Max int8, int16, int32, int64, int - Max uint8, uint16, uint32, uint64, uint - Boolean true and false - Standard complex64 and complex128 - Array containing standard ints - Array containing type with custom formatter on pointer receiver only - Array containing interfaces - Array containing bytes - Slice containing standard float32 values - Slice containing type with custom formatter on pointer receiver only - Slice containing interfaces - Slice containing bytes - Nil slice - Standard string - Nil interface - Sub-interface - Map with string keys and int vals - Map with custom formatter type on pointer receiver only keys and vals - Map with interface keys and values - Map with nil interface value - Struct with primitives - Struct that contains another struct - Struct that contains custom type with Stringer pointer interface via both exported and unexported fields - Struct that contains embedded struct and field to same struct - Uintptr to 0 (null pointer) - Uintptr address of real variable - Unsafe.Pointer to 0 (null pointer) - Unsafe.Pointer to address of real variable - Nil channel - Standard int channel - Function with no params and no returns - Function with param and no returns - Function with multiple params and multiple returns - Struct that is circular through self referencing - Structs that are circular through cross referencing - Structs that are indirectly circular - Type that panics in its Stringer interface */ package spew_test import ( "bytes" "fmt" "testing" "unsafe" "github.com/expr-lang/expr/internal/spew" ) // dumpTest is used to describe a test to be performed against the Dump method. type dumpTest struct { in interface{} wants []string } // dumpTests houses all of the tests to be performed against the Dump method. var dumpTests = make([]dumpTest, 0) // addDumpTest is a helper method to append the passed input and desired result // to dumpTests func addDumpTest(in interface{}, wants ...string) { test := dumpTest{in, wants} dumpTests = append(dumpTests, test) } func addIntDumpTests() { // Max int8. v := int8(127) nv := (*int8)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "int8" vs := "127" addDumpTest(v, "("+vt+") "+vs+"\n") addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") addDumpTest(nv, "(*"+vt+")()\n") // Max int16. v2 := int16(32767) nv2 := (*int16)(nil) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "int16" v2s := "32767" addDumpTest(v2, "("+v2t+") "+v2s+"\n") addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") addDumpTest(nv2, "(*"+v2t+")()\n") // Max int32. v3 := int32(2147483647) nv3 := (*int32)(nil) pv3 := &v3 v3Addr := fmt.Sprintf("%p", pv3) pv3Addr := fmt.Sprintf("%p", &pv3) v3t := "int32" v3s := "2147483647" addDumpTest(v3, "("+v3t+") "+v3s+"\n") addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n") addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n") addDumpTest(nv3, "(*"+v3t+")()\n") // Max int64. v4 := int64(9223372036854775807) nv4 := (*int64)(nil) pv4 := &v4 v4Addr := fmt.Sprintf("%p", pv4) pv4Addr := fmt.Sprintf("%p", &pv4) v4t := "int64" v4s := "9223372036854775807" addDumpTest(v4, "("+v4t+") "+v4s+"\n") addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n") addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n") addDumpTest(nv4, "(*"+v4t+")()\n") // Max int. v5 := int(2147483647) nv5 := (*int)(nil) pv5 := &v5 v5Addr := fmt.Sprintf("%p", pv5) pv5Addr := fmt.Sprintf("%p", &pv5) v5t := "int" v5s := "2147483647" addDumpTest(v5, "("+v5t+") "+v5s+"\n") addDumpTest(pv5, "(*"+v5t+")("+v5Addr+")("+v5s+")\n") addDumpTest(&pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")("+v5s+")\n") addDumpTest(nv5, "(*"+v5t+")()\n") } func addUintDumpTests() { // Max uint8. v := uint8(255) nv := (*uint8)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "uint8" vs := "255" addDumpTest(v, "("+vt+") "+vs+"\n") addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") addDumpTest(nv, "(*"+vt+")()\n") // Max uint16. v2 := uint16(65535) nv2 := (*uint16)(nil) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "uint16" v2s := "65535" addDumpTest(v2, "("+v2t+") "+v2s+"\n") addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") addDumpTest(nv2, "(*"+v2t+")()\n") // Max uint32. v3 := uint32(4294967295) nv3 := (*uint32)(nil) pv3 := &v3 v3Addr := fmt.Sprintf("%p", pv3) pv3Addr := fmt.Sprintf("%p", &pv3) v3t := "uint32" v3s := "4294967295" addDumpTest(v3, "("+v3t+") "+v3s+"\n") addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n") addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n") addDumpTest(nv3, "(*"+v3t+")()\n") // Max uint64. v4 := uint64(18446744073709551615) nv4 := (*uint64)(nil) pv4 := &v4 v4Addr := fmt.Sprintf("%p", pv4) pv4Addr := fmt.Sprintf("%p", &pv4) v4t := "uint64" v4s := "18446744073709551615" addDumpTest(v4, "("+v4t+") "+v4s+"\n") addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n") addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n") addDumpTest(nv4, "(*"+v4t+")()\n") // Max uint. v5 := uint(4294967295) nv5 := (*uint)(nil) pv5 := &v5 v5Addr := fmt.Sprintf("%p", pv5) pv5Addr := fmt.Sprintf("%p", &pv5) v5t := "uint" v5s := "4294967295" addDumpTest(v5, "("+v5t+") "+v5s+"\n") addDumpTest(pv5, "(*"+v5t+")("+v5Addr+")("+v5s+")\n") addDumpTest(&pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")("+v5s+")\n") addDumpTest(nv5, "(*"+v5t+")()\n") } func addBoolDumpTests() { // Boolean true. v := bool(true) nv := (*bool)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "bool" vs := "true" addDumpTest(v, "("+vt+") "+vs+"\n") addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") addDumpTest(nv, "(*"+vt+")()\n") // Boolean false. v2 := bool(false) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "bool" v2s := "false" addDumpTest(v2, "("+v2t+") "+v2s+"\n") addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") } func addFloatDumpTests() { // Standard float32. v := float32(3.1415) nv := (*float32)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "float32" vs := "3.1415" addDumpTest(v, "("+vt+") "+vs+"\n") addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") addDumpTest(nv, "(*"+vt+")()\n") // Standard float64. v2 := float64(3.1415926) nv2 := (*float64)(nil) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "float64" v2s := "3.1415926" addDumpTest(v2, "("+v2t+") "+v2s+"\n") addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") addDumpTest(nv2, "(*"+v2t+")()\n") } func addComplexDumpTests() { // Standard complex64. v := complex(float32(6), -2) nv := (*complex64)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "complex64" vs := "(6-2i)" addDumpTest(v, "("+vt+") "+vs+"\n") addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") addDumpTest(nv, "(*"+vt+")()\n") // Standard complex128. v2 := complex(float64(-6), 2) nv2 := (*complex128)(nil) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "complex128" v2s := "(-6+2i)" addDumpTest(v2, "("+v2t+") "+v2s+"\n") addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") addDumpTest(nv2, "(*"+v2t+")()\n") } func addArrayDumpTests() { // Array containing standard ints. v := [3]int{1, 2, 3} vLen := fmt.Sprintf("%d", len(v)) vCap := fmt.Sprintf("%d", cap(v)) nv := (*[3]int)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "int" vs := "(len=" + vLen + " cap=" + vCap + ") {\n (" + vt + ") 1,\n (" + vt + ") 2,\n (" + vt + ") 3\n}" addDumpTest(v, "([3]"+vt+") "+vs+"\n") addDumpTest(pv, "(*[3]"+vt+")("+vAddr+")("+vs+")\n") addDumpTest(&pv, "(**[3]"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") addDumpTest(nv, "(*[3]"+vt+")()\n") // Array containing type with custom formatter on pointer receiver only. v2i0 := pstringer("1") v2i1 := pstringer("2") v2i2 := pstringer("3") v2 := [3]pstringer{v2i0, v2i1, v2i2} v2i0Len := fmt.Sprintf("%d", len(v2i0)) v2i1Len := fmt.Sprintf("%d", len(v2i1)) v2i2Len := fmt.Sprintf("%d", len(v2i2)) v2Len := fmt.Sprintf("%d", len(v2)) v2Cap := fmt.Sprintf("%d", cap(v2)) nv2 := (*[3]pstringer)(nil) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "spew_test.pstringer" v2sp := "(len=" + v2Len + " cap=" + v2Cap + ") {\n (" + v2t + ") (len=" + v2i0Len + ") stringer 1,\n (" + v2t + ") (len=" + v2i1Len + ") stringer 2,\n (" + v2t + ") (len=" + v2i2Len + ") " + "stringer 3\n}" v2s := v2sp if spew.UnsafeDisabled { v2s = "(len=" + v2Len + " cap=" + v2Cap + ") {\n (" + v2t + ") (len=" + v2i0Len + ") \"1\",\n (" + v2t + ") (len=" + v2i1Len + ") \"2\",\n (" + v2t + ") (len=" + v2i2Len + ") " + "\"3\"\n}" } addDumpTest(v2, "([3]"+v2t+") "+v2s+"\n") addDumpTest(pv2, "(*[3]"+v2t+")("+v2Addr+")("+v2sp+")\n") addDumpTest(&pv2, "(**[3]"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2sp+")\n") addDumpTest(nv2, "(*[3]"+v2t+")()\n") // Array containing interfaces. v3i0 := "one" v3 := [3]interface{}{v3i0, int(2), uint(3)} v3i0Len := fmt.Sprintf("%d", len(v3i0)) v3Len := fmt.Sprintf("%d", len(v3)) v3Cap := fmt.Sprintf("%d", cap(v3)) nv3 := (*[3]interface{})(nil) pv3 := &v3 v3Addr := fmt.Sprintf("%p", pv3) pv3Addr := fmt.Sprintf("%p", &pv3) v3t := "[3]interface {}" v3t2 := "string" v3t3 := "int" v3t4 := "uint" v3s := "(len=" + v3Len + " cap=" + v3Cap + ") {\n (" + v3t2 + ") " + "(len=" + v3i0Len + ") \"one\",\n (" + v3t3 + ") 2,\n (" + v3t4 + ") 3\n}" addDumpTest(v3, "("+v3t+") "+v3s+"\n") addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n") addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n") addDumpTest(nv3, "(*"+v3t+")()\n") // Array containing bytes. v4 := [34]byte{ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, } v4Len := fmt.Sprintf("%d", len(v4)) v4Cap := fmt.Sprintf("%d", cap(v4)) nv4 := (*[34]byte)(nil) pv4 := &v4 v4Addr := fmt.Sprintf("%p", pv4) pv4Addr := fmt.Sprintf("%p", &pv4) v4t := "[34]uint8" v4s := "(len=" + v4Len + " cap=" + v4Cap + ") " + "{\n 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20" + " |............... |\n" + " 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30" + " |!\"#$%&'()*+,-./0|\n" + " 00000020 31 32 " + " |12|\n}" addDumpTest(v4, "("+v4t+") "+v4s+"\n") addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n") addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n") addDumpTest(nv4, "(*"+v4t+")()\n") } func addSliceDumpTests() { // Slice containing standard float32 values. v := []float32{3.14, 6.28, 12.56} vLen := fmt.Sprintf("%d", len(v)) vCap := fmt.Sprintf("%d", cap(v)) nv := (*[]float32)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "float32" vs := "(len=" + vLen + " cap=" + vCap + ") {\n (" + vt + ") 3.14,\n (" + vt + ") 6.28,\n (" + vt + ") 12.56\n}" addDumpTest(v, "([]"+vt+") "+vs+"\n") addDumpTest(pv, "(*[]"+vt+")("+vAddr+")("+vs+")\n") addDumpTest(&pv, "(**[]"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") addDumpTest(nv, "(*[]"+vt+")()\n") // Slice containing type with custom formatter on pointer receiver only. v2i0 := pstringer("1") v2i1 := pstringer("2") v2i2 := pstringer("3") v2 := []pstringer{v2i0, v2i1, v2i2} v2i0Len := fmt.Sprintf("%d", len(v2i0)) v2i1Len := fmt.Sprintf("%d", len(v2i1)) v2i2Len := fmt.Sprintf("%d", len(v2i2)) v2Len := fmt.Sprintf("%d", len(v2)) v2Cap := fmt.Sprintf("%d", cap(v2)) nv2 := (*[]pstringer)(nil) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "spew_test.pstringer" v2s := "(len=" + v2Len + " cap=" + v2Cap + ") {\n (" + v2t + ") (len=" + v2i0Len + ") stringer 1,\n (" + v2t + ") (len=" + v2i1Len + ") stringer 2,\n (" + v2t + ") (len=" + v2i2Len + ") " + "stringer 3\n}" addDumpTest(v2, "([]"+v2t+") "+v2s+"\n") addDumpTest(pv2, "(*[]"+v2t+")("+v2Addr+")("+v2s+")\n") addDumpTest(&pv2, "(**[]"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") addDumpTest(nv2, "(*[]"+v2t+")()\n") // Slice containing interfaces. v3i0 := "one" v3 := []interface{}{v3i0, int(2), uint(3), nil} v3i0Len := fmt.Sprintf("%d", len(v3i0)) v3Len := fmt.Sprintf("%d", len(v3)) v3Cap := fmt.Sprintf("%d", cap(v3)) nv3 := (*[]interface{})(nil) pv3 := &v3 v3Addr := fmt.Sprintf("%p", pv3) pv3Addr := fmt.Sprintf("%p", &pv3) v3t := "[]interface {}" v3t2 := "string" v3t3 := "int" v3t4 := "uint" v3t5 := "interface {}" v3s := "(len=" + v3Len + " cap=" + v3Cap + ") {\n (" + v3t2 + ") " + "(len=" + v3i0Len + ") \"one\",\n (" + v3t3 + ") 2,\n (" + v3t4 + ") 3,\n (" + v3t5 + ") \n}" addDumpTest(v3, "("+v3t+") "+v3s+"\n") addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n") addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n") addDumpTest(nv3, "(*"+v3t+")()\n") // Slice containing bytes. v4 := []byte{ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, } v4Len := fmt.Sprintf("%d", len(v4)) v4Cap := fmt.Sprintf("%d", cap(v4)) nv4 := (*[]byte)(nil) pv4 := &v4 v4Addr := fmt.Sprintf("%p", pv4) pv4Addr := fmt.Sprintf("%p", &pv4) v4t := "[]uint8" v4s := "(len=" + v4Len + " cap=" + v4Cap + ") " + "{\n 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20" + " |............... |\n" + " 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30" + " |!\"#$%&'()*+,-./0|\n" + " 00000020 31 32 " + " |12|\n}" addDumpTest(v4, "("+v4t+") "+v4s+"\n") addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n") addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n") addDumpTest(nv4, "(*"+v4t+")()\n") // Nil slice. v5 := []int(nil) nv5 := (*[]int)(nil) pv5 := &v5 v5Addr := fmt.Sprintf("%p", pv5) pv5Addr := fmt.Sprintf("%p", &pv5) v5t := "[]int" v5s := "" addDumpTest(v5, "("+v5t+") "+v5s+"\n") addDumpTest(pv5, "(*"+v5t+")("+v5Addr+")("+v5s+")\n") addDumpTest(&pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")("+v5s+")\n") addDumpTest(nv5, "(*"+v5t+")()\n") } func addStringDumpTests() { // Standard string. v := "test" vLen := fmt.Sprintf("%d", len(v)) nv := (*string)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "string" vs := "(len=" + vLen + ") \"test\"" addDumpTest(v, "("+vt+") "+vs+"\n") addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") addDumpTest(nv, "(*"+vt+")()\n") } func addInterfaceDumpTests() { // Nil interface. var v interface{} nv := (*interface{})(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "interface {}" vs := "" addDumpTest(v, "("+vt+") "+vs+"\n") addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") addDumpTest(nv, "(*"+vt+")()\n") // Sub-interface. v2 := interface{}(uint16(65535)) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "uint16" v2s := "65535" addDumpTest(v2, "("+v2t+") "+v2s+"\n") addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") } func addMapDumpTests() { // Map with string keys and int vals. k := "one" kk := "two" m := map[string]int{k: 1, kk: 2} klen := fmt.Sprintf("%d", len(k)) // not kLen to shut golint up kkLen := fmt.Sprintf("%d", len(kk)) mLen := fmt.Sprintf("%d", len(m)) nilMap := map[string]int(nil) nm := (*map[string]int)(nil) pm := &m mAddr := fmt.Sprintf("%p", pm) pmAddr := fmt.Sprintf("%p", &pm) mt := "map[string]int" mt1 := "string" mt2 := "int" ms := "(len=" + mLen + ") {\n (" + mt1 + ") (len=" + klen + ") " + "\"one\": (" + mt2 + ") 1,\n (" + mt1 + ") (len=" + kkLen + ") \"two\": (" + mt2 + ") 2\n}" ms2 := "(len=" + mLen + ") {\n (" + mt1 + ") (len=" + kkLen + ") " + "\"two\": (" + mt2 + ") 2,\n (" + mt1 + ") (len=" + klen + ") \"one\": (" + mt2 + ") 1\n}" addDumpTest(m, "("+mt+") "+ms+"\n", "("+mt+") "+ms2+"\n") addDumpTest(pm, "(*"+mt+")("+mAddr+")("+ms+")\n", "(*"+mt+")("+mAddr+")("+ms2+")\n") addDumpTest(&pm, "(**"+mt+")("+pmAddr+"->"+mAddr+")("+ms+")\n", "(**"+mt+")("+pmAddr+"->"+mAddr+")("+ms2+")\n") addDumpTest(nm, "(*"+mt+")()\n") addDumpTest(nilMap, "("+mt+") \n") // Map with custom formatter type on pointer receiver only keys and vals. k2 := pstringer("one") v2 := pstringer("1") m2 := map[pstringer]pstringer{k2: v2} k2Len := fmt.Sprintf("%d", len(k2)) v2Len := fmt.Sprintf("%d", len(v2)) m2Len := fmt.Sprintf("%d", len(m2)) nilMap2 := map[pstringer]pstringer(nil) nm2 := (*map[pstringer]pstringer)(nil) pm2 := &m2 m2Addr := fmt.Sprintf("%p", pm2) pm2Addr := fmt.Sprintf("%p", &pm2) m2t := "map[spew_test.pstringer]spew_test.pstringer" m2t1 := "spew_test.pstringer" m2t2 := "spew_test.pstringer" m2s := "(len=" + m2Len + ") {\n (" + m2t1 + ") (len=" + k2Len + ") " + "stringer one: (" + m2t2 + ") (len=" + v2Len + ") stringer 1\n}" if spew.UnsafeDisabled { m2s = "(len=" + m2Len + ") {\n (" + m2t1 + ") (len=" + k2Len + ") " + "\"one\": (" + m2t2 + ") (len=" + v2Len + ") \"1\"\n}" } addDumpTest(m2, "("+m2t+") "+m2s+"\n") addDumpTest(pm2, "(*"+m2t+")("+m2Addr+")("+m2s+")\n") addDumpTest(&pm2, "(**"+m2t+")("+pm2Addr+"->"+m2Addr+")("+m2s+")\n") addDumpTest(nm2, "(*"+m2t+")()\n") addDumpTest(nilMap2, "("+m2t+") \n") // Map with interface keys and values. k3 := "one" k3Len := fmt.Sprintf("%d", len(k3)) m3 := map[interface{}]interface{}{k3: 1} m3Len := fmt.Sprintf("%d", len(m3)) nilMap3 := map[interface{}]interface{}(nil) nm3 := (*map[interface{}]interface{})(nil) pm3 := &m3 m3Addr := fmt.Sprintf("%p", pm3) pm3Addr := fmt.Sprintf("%p", &pm3) m3t := "map[interface {}]interface {}" m3t1 := "string" m3t2 := "int" m3s := "(len=" + m3Len + ") {\n (" + m3t1 + ") (len=" + k3Len + ") " + "\"one\": (" + m3t2 + ") 1\n}" addDumpTest(m3, "("+m3t+") "+m3s+"\n") addDumpTest(pm3, "(*"+m3t+")("+m3Addr+")("+m3s+")\n") addDumpTest(&pm3, "(**"+m3t+")("+pm3Addr+"->"+m3Addr+")("+m3s+")\n") addDumpTest(nm3, "(*"+m3t+")()\n") addDumpTest(nilMap3, "("+m3t+") \n") // Map with nil interface value. k4 := "nil" k4Len := fmt.Sprintf("%d", len(k4)) m4 := map[string]interface{}{k4: nil} m4Len := fmt.Sprintf("%d", len(m4)) nilMap4 := map[string]interface{}(nil) nm4 := (*map[string]interface{})(nil) pm4 := &m4 m4Addr := fmt.Sprintf("%p", pm4) pm4Addr := fmt.Sprintf("%p", &pm4) m4t := "map[string]interface {}" m4t1 := "string" m4t2 := "interface {}" m4s := "(len=" + m4Len + ") {\n (" + m4t1 + ") (len=" + k4Len + ")" + " \"nil\": (" + m4t2 + ") \n}" addDumpTest(m4, "("+m4t+") "+m4s+"\n") addDumpTest(pm4, "(*"+m4t+")("+m4Addr+")("+m4s+")\n") addDumpTest(&pm4, "(**"+m4t+")("+pm4Addr+"->"+m4Addr+")("+m4s+")\n") addDumpTest(nm4, "(*"+m4t+")()\n") addDumpTest(nilMap4, "("+m4t+") \n") } func addStructDumpTests() { // Struct with primitives. type s1 struct { a int8 b uint8 } v := s1{127, 255} nv := (*s1)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "spew_test.s1" vt2 := "int8" vt3 := "uint8" vs := "{\n a: (" + vt2 + ") 127,\n b: (" + vt3 + ") 255\n}" addDumpTest(v, "("+vt+") "+vs+"\n") addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") addDumpTest(nv, "(*"+vt+")()\n") // Struct that contains another struct. type s2 struct { s1 s1 b bool } v2 := s2{s1{127, 255}, true} nv2 := (*s2)(nil) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "spew_test.s2" v2t2 := "spew_test.s1" v2t3 := "int8" v2t4 := "uint8" v2t5 := "bool" v2s := "{\n s1: (" + v2t2 + ") {\n a: (" + v2t3 + ") 127,\n b: (" + v2t4 + ") 255\n },\n b: (" + v2t5 + ") true\n}" addDumpTest(v2, "("+v2t+") "+v2s+"\n") addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") addDumpTest(nv2, "(*"+v2t+")()\n") // Struct that contains custom type with Stringer pointer interface via both // exported and unexported fields. type s3 struct { s pstringer S pstringer } v3 := s3{"test", "test2"} nv3 := (*s3)(nil) pv3 := &v3 v3Addr := fmt.Sprintf("%p", pv3) pv3Addr := fmt.Sprintf("%p", &pv3) v3t := "spew_test.s3" v3t2 := "spew_test.pstringer" v3s := "{\n s: (" + v3t2 + ") (len=4) stringer test,\n S: (" + v3t2 + ") (len=5) stringer test2\n}" v3sp := v3s if spew.UnsafeDisabled { v3s = "{\n s: (" + v3t2 + ") (len=4) \"test\",\n S: (" + v3t2 + ") (len=5) \"test2\"\n}" v3sp = "{\n s: (" + v3t2 + ") (len=4) \"test\",\n S: (" + v3t2 + ") (len=5) stringer test2\n}" } addDumpTest(v3, "("+v3t+") "+v3s+"\n") addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3sp+")\n") addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3sp+")\n") addDumpTest(nv3, "(*"+v3t+")()\n") // Struct that contains embedded struct and field to same struct. e := embed{"embedstr"} eLen := fmt.Sprintf("%d", len("embedstr")) v4 := embedwrap{embed: &e, e: &e} nv4 := (*embedwrap)(nil) pv4 := &v4 eAddr := fmt.Sprintf("%p", &e) v4Addr := fmt.Sprintf("%p", pv4) pv4Addr := fmt.Sprintf("%p", &pv4) v4t := "spew_test.embedwrap" v4t2 := "spew_test.embed" v4t3 := "string" v4s := "{\n embed: (*" + v4t2 + ")(" + eAddr + ")({\n a: (" + v4t3 + ") (len=" + eLen + ") \"embedstr\"\n }),\n e: (*" + v4t2 + ")(" + eAddr + ")({\n a: (" + v4t3 + ") (len=" + eLen + ")" + " \"embedstr\"\n })\n}" addDumpTest(v4, "("+v4t+") "+v4s+"\n") addDumpTest(pv4, "(*"+v4t+")("+v4Addr+")("+v4s+")\n") addDumpTest(&pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")("+v4s+")\n") addDumpTest(nv4, "(*"+v4t+")()\n") } func addUintptrDumpTests() { // Null pointer. v := uintptr(0) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "uintptr" vs := "" addDumpTest(v, "("+vt+") "+vs+"\n") addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") // Address of real variable. i := 1 v2 := uintptr(unsafe.Pointer(&i)) nv2 := (*uintptr)(nil) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "uintptr" v2s := fmt.Sprintf("%p", &i) addDumpTest(v2, "("+v2t+") "+v2s+"\n") addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") addDumpTest(nv2, "(*"+v2t+")()\n") } func addUnsafePointerDumpTests() { // Null pointer. v := unsafe.Pointer(nil) nv := (*unsafe.Pointer)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "unsafe.Pointer" vs := "" addDumpTest(v, "("+vt+") "+vs+"\n") addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") addDumpTest(nv, "(*"+vt+")()\n") // Address of real variable. i := 1 v2 := unsafe.Pointer(&i) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "unsafe.Pointer" v2s := fmt.Sprintf("%p", &i) addDumpTest(v2, "("+v2t+") "+v2s+"\n") addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") addDumpTest(nv, "(*"+vt+")()\n") } func addChanDumpTests() { // Nil channel. var v chan int pv := &v nv := (*chan int)(nil) vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "chan int" vs := "" addDumpTest(v, "("+vt+") "+vs+"\n") addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") addDumpTest(nv, "(*"+vt+")()\n") // Real channel. v2 := make(chan int) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "chan int" v2s := fmt.Sprintf("%p", v2) addDumpTest(v2, "("+v2t+") "+v2s+"\n") addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") } func addFuncDumpTests() { // Function with no params and no returns. v := addIntDumpTests nv := (*func())(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "func()" vs := fmt.Sprintf("%p", v) addDumpTest(v, "("+vt+") "+vs+"\n") addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") addDumpTest(nv, "(*"+vt+")()\n") // Function with param and no returns. v2 := TestDump nv2 := (*func(*testing.T))(nil) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "func(*testing.T)" v2s := fmt.Sprintf("%p", v2) addDumpTest(v2, "("+v2t+") "+v2s+"\n") addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s+")\n") addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s+")\n") addDumpTest(nv2, "(*"+v2t+")()\n") // Function with multiple params and multiple returns. var v3 = func(i int, s string) (b bool, err error) { return true, nil } nv3 := (*func(int, string) (bool, error))(nil) pv3 := &v3 v3Addr := fmt.Sprintf("%p", pv3) pv3Addr := fmt.Sprintf("%p", &pv3) v3t := "func(int, string) (bool, error)" v3s := fmt.Sprintf("%p", v3) addDumpTest(v3, "("+v3t+") "+v3s+"\n") addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s+")\n") addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s+")\n") addDumpTest(nv3, "(*"+v3t+")()\n") } func addCircularDumpTests() { // Struct that is circular through self referencing. type circular struct { c *circular } v := circular{nil} v.c = &v pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "spew_test.circular" vs := "{\n c: (*" + vt + ")(" + vAddr + ")({\n c: (*" + vt + ")(" + vAddr + ")()\n })\n}" vs2 := "{\n c: (*" + vt + ")(" + vAddr + ")()\n}" addDumpTest(v, "("+vt+") "+vs+"\n") addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs2+")\n") addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs2+")\n") // Structs that are circular through cross referencing. v2 := xref1{nil} ts2 := xref2{&v2} v2.ps2 = &ts2 pv2 := &v2 ts2Addr := fmt.Sprintf("%p", &ts2) v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "spew_test.xref1" v2t2 := "spew_test.xref2" v2s := "{\n ps2: (*" + v2t2 + ")(" + ts2Addr + ")({\n ps1: (*" + v2t + ")(" + v2Addr + ")({\n ps2: (*" + v2t2 + ")(" + ts2Addr + ")()\n })\n })\n}" v2s2 := "{\n ps2: (*" + v2t2 + ")(" + ts2Addr + ")({\n ps1: (*" + v2t + ")(" + v2Addr + ")()\n })\n}" addDumpTest(v2, "("+v2t+") "+v2s+"\n") addDumpTest(pv2, "(*"+v2t+")("+v2Addr+")("+v2s2+")\n") addDumpTest(&pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")("+v2s2+")\n") // Structs that are indirectly circular. v3 := indirCir1{nil} tic2 := indirCir2{nil} tic3 := indirCir3{&v3} tic2.ps3 = &tic3 v3.ps2 = &tic2 pv3 := &v3 tic2Addr := fmt.Sprintf("%p", &tic2) tic3Addr := fmt.Sprintf("%p", &tic3) v3Addr := fmt.Sprintf("%p", pv3) pv3Addr := fmt.Sprintf("%p", &pv3) v3t := "spew_test.indirCir1" v3t2 := "spew_test.indirCir2" v3t3 := "spew_test.indirCir3" v3s := "{\n ps2: (*" + v3t2 + ")(" + tic2Addr + ")({\n ps3: (*" + v3t3 + ")(" + tic3Addr + ")({\n ps1: (*" + v3t + ")(" + v3Addr + ")({\n ps2: (*" + v3t2 + ")(" + tic2Addr + ")()\n })\n })\n })\n}" v3s2 := "{\n ps2: (*" + v3t2 + ")(" + tic2Addr + ")({\n ps3: (*" + v3t3 + ")(" + tic3Addr + ")({\n ps1: (*" + v3t + ")(" + v3Addr + ")()\n })\n })\n}" addDumpTest(v3, "("+v3t+") "+v3s+"\n") addDumpTest(pv3, "(*"+v3t+")("+v3Addr+")("+v3s2+")\n") addDumpTest(&pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")("+v3s2+")\n") } func addPanicDumpTests() { // Type that panics in its Stringer interface. v := panicer(127) nv := (*panicer)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "spew_test.panicer" vs := "(PANIC=test panic)127" addDumpTest(v, "("+vt+") "+vs+"\n") addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") addDumpTest(nv, "(*"+vt+")()\n") } func addErrorDumpTests() { // Type that has a custom Error interface. v := customError(127) nv := (*customError)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "spew_test.customError" vs := "error: 127" addDumpTest(v, "("+vt+") "+vs+"\n") addDumpTest(pv, "(*"+vt+")("+vAddr+")("+vs+")\n") addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")("+vs+")\n") addDumpTest(nv, "(*"+vt+")()\n") } // TestDump executes all of the tests described by dumpTests. func TestDump(t *testing.T) { // Setup tests. addIntDumpTests() addUintDumpTests() addBoolDumpTests() addFloatDumpTests() addComplexDumpTests() addArrayDumpTests() addSliceDumpTests() addStringDumpTests() addInterfaceDumpTests() addMapDumpTests() addStructDumpTests() addUintptrDumpTests() addUnsafePointerDumpTests() addChanDumpTests() addFuncDumpTests() addCircularDumpTests() addPanicDumpTests() addErrorDumpTests() addCgoDumpTests() t.Logf("Running %d tests", len(dumpTests)) for i, test := range dumpTests { buf := new(bytes.Buffer) spew.Fdump(buf, test.in) s := buf.String() if testFailed(s, test.wants) { t.Errorf("Dump #%d\n got: %s %s", i, s, stringizeWants(test.wants)) continue } } } func TestDumpSortedKeys(t *testing.T) { cfg := spew.ConfigState{SortKeys: true} s := cfg.Sdump(map[int]string{1: "1", 3: "3", 2: "2"}) expected := "(map[int]string) (len=3) {\n(int) 1: (string) (len=1) " + "\"1\",\n(int) 2: (string) (len=1) \"2\",\n(int) 3: (string) " + "(len=1) \"3\"\n" + "}\n" if s != expected { t.Errorf("Sorted keys mismatch:\n %v %v", s, expected) } s = cfg.Sdump(map[stringer]int{"1": 1, "3": 3, "2": 2}) expected = "(map[spew_test.stringer]int) (len=3) {\n" + "(spew_test.stringer) (len=1) stringer 1: (int) 1,\n" + "(spew_test.stringer) (len=1) stringer 2: (int) 2,\n" + "(spew_test.stringer) (len=1) stringer 3: (int) 3\n" + "}\n" if s != expected { t.Errorf("Sorted keys mismatch:\n %v %v", s, expected) } s = cfg.Sdump(map[pstringer]int{pstringer("1"): 1, pstringer("3"): 3, pstringer("2"): 2}) expected = "(map[spew_test.pstringer]int) (len=3) {\n" + "(spew_test.pstringer) (len=1) stringer 1: (int) 1,\n" + "(spew_test.pstringer) (len=1) stringer 2: (int) 2,\n" + "(spew_test.pstringer) (len=1) stringer 3: (int) 3\n" + "}\n" if spew.UnsafeDisabled { expected = "(map[spew_test.pstringer]int) (len=3) {\n" + "(spew_test.pstringer) (len=1) \"1\": (int) 1,\n" + "(spew_test.pstringer) (len=1) \"2\": (int) 2,\n" + "(spew_test.pstringer) (len=1) \"3\": (int) 3\n" + "}\n" } if s != expected { t.Errorf("Sorted keys mismatch:\n %v %v", s, expected) } s = cfg.Sdump(map[customError]int{customError(1): 1, customError(3): 3, customError(2): 2}) expected = "(map[spew_test.customError]int) (len=3) {\n" + "(spew_test.customError) error: 1: (int) 1,\n" + "(spew_test.customError) error: 2: (int) 2,\n" + "(spew_test.customError) error: 3: (int) 3\n" + "}\n" if s != expected { t.Errorf("Sorted keys mismatch:\n %v %v", s, expected) } } ================================================ FILE: internal/spew/dumpcgo_test.go ================================================ // Copyright (c) 2013-2016 Dave Collins // // Permission to use, copy, modify, and distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // NOTE: Due to the following build constraints, this file will only be compiled // when both cgo is supported and "-tags testcgo" is added to the go test // command line. This means the cgo tests are only added (and hence run) when // specifically requested. This configuration is used because spew itself // does not require cgo to run even though it does handle certain cgo types // specially. Rather than forcing all clients to require cgo and an external // C compiler just to run the tests, this scheme makes them optional. //go:build cgo && testcgo // +build cgo,testcgo package spew_test import ( "fmt" "github.com/expr-lang/expr/internal/spew/testdata" ) func addCgoDumpTests() { // C char pointer. v := testdata.GetCgoCharPointer() nv := testdata.GetCgoNullCharPointer() pv := &v vcAddr := fmt.Sprintf("%p", v) vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "*testdata._Ctype_char" vs := "116" addDumpTest(v, "("+vt+")("+vcAddr+")("+vs+")\n") addDumpTest(pv, "(*"+vt+")("+vAddr+"->"+vcAddr+")("+vs+")\n") addDumpTest(&pv, "(**"+vt+")("+pvAddr+"->"+vAddr+"->"+vcAddr+")("+vs+")\n") addDumpTest(nv, "("+vt+")()\n") // C char array. v2, v2l, v2c := testdata.GetCgoCharArray() v2Len := fmt.Sprintf("%d", v2l) v2Cap := fmt.Sprintf("%d", v2c) v2t := "[6]testdata._Ctype_char" v2s := "(len=" + v2Len + " cap=" + v2Cap + ") " + "{\n 00000000 74 65 73 74 32 00 " + " |test2.|\n}" addDumpTest(v2, "("+v2t+") "+v2s+"\n") // C unsigned char array. v3, v3l, v3c := testdata.GetCgoUnsignedCharArray() v3Len := fmt.Sprintf("%d", v3l) v3Cap := fmt.Sprintf("%d", v3c) v3t := "[6]testdata._Ctype_unsignedchar" v3t2 := "[6]testdata._Ctype_uchar" v3s := "(len=" + v3Len + " cap=" + v3Cap + ") " + "{\n 00000000 74 65 73 74 33 00 " + " |test3.|\n}" addDumpTest(v3, "("+v3t+") "+v3s+"\n", "("+v3t2+") "+v3s+"\n") // C signed char array. v4, v4l, v4c := testdata.GetCgoSignedCharArray() v4Len := fmt.Sprintf("%d", v4l) v4Cap := fmt.Sprintf("%d", v4c) v4t := "[6]testdata._Ctype_schar" v4t2 := "testdata._Ctype_schar" v4s := "(len=" + v4Len + " cap=" + v4Cap + ") " + "{\n (" + v4t2 + ") 116,\n (" + v4t2 + ") 101,\n (" + v4t2 + ") 115,\n (" + v4t2 + ") 116,\n (" + v4t2 + ") 52,\n (" + v4t2 + ") 0\n}" addDumpTest(v4, "("+v4t+") "+v4s+"\n") // C uint8_t array. v5, v5l, v5c := testdata.GetCgoUint8tArray() v5Len := fmt.Sprintf("%d", v5l) v5Cap := fmt.Sprintf("%d", v5c) v5t := "[6]testdata._Ctype_uint8_t" v5t2 := "[6]testdata._Ctype_uchar" v5s := "(len=" + v5Len + " cap=" + v5Cap + ") " + "{\n 00000000 74 65 73 74 35 00 " + " |test5.|\n}" addDumpTest(v5, "("+v5t+") "+v5s+"\n", "("+v5t2+") "+v5s+"\n") // C typedefed unsigned char array. v6, v6l, v6c := testdata.GetCgoTypedefedUnsignedCharArray() v6Len := fmt.Sprintf("%d", v6l) v6Cap := fmt.Sprintf("%d", v6c) v6t := "[6]testdata._Ctype_custom_uchar_t" v6t2 := "[6]testdata._Ctype_uchar" v6s := "(len=" + v6Len + " cap=" + v6Cap + ") " + "{\n 00000000 74 65 73 74 36 00 " + " |test6.|\n}" addDumpTest(v6, "("+v6t+") "+v6s+"\n", "("+v6t2+") "+v6s+"\n") } ================================================ FILE: internal/spew/dumpnocgo_test.go ================================================ // Copyright (c) 2013 Dave Collins // // Permission to use, copy, modify, and distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // NOTE: Due to the following build constraints, this file will only be compiled // when either cgo is not supported or "-tags testcgo" is not added to the go // test command line. This file intentionally does not setup any cgo tests in // this scenario. //go:build !cgo || !testcgo // +build !cgo !testcgo package spew_test func addCgoDumpTests() { // Don't add any tests for cgo since this file is only compiled when // there should not be any cgo tests. } ================================================ FILE: internal/spew/example_test.go ================================================ /* * Copyright (c) 2013-2016 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ package spew_test import ( "fmt" "github.com/expr-lang/expr/internal/spew" ) type Flag int const ( flagOne Flag = iota flagTwo ) var flagStrings = map[Flag]string{ flagOne: "flagOne", flagTwo: "flagTwo", } func (f Flag) String() string { if s, ok := flagStrings[f]; ok { return s } return fmt.Sprintf("Unknown flag (%d)", int(f)) } type Bar struct { data uintptr } type Foo struct { unexportedField Bar ExportedField map[interface{}]interface{} } // This example demonstrates how to use Dump to dump variables to stdout. func ExampleDump() { // The following package level declarations are assumed for this example: /* type Flag int const ( flagOne Flag = iota flagTwo ) var flagStrings = map[Flag]string{ flagOne: "flagOne", flagTwo: "flagTwo", } func (f Flag) String() string { if s, ok := flagStrings[f]; ok { return s } return fmt.Sprintf("Unknown flag (%d)", int(f)) } type Bar struct { data uintptr } type Foo struct { unexportedField Bar ExportedField map[interface{}]interface{} } */ // Setup some sample data structures for the example. bar := Bar{uintptr(0)} s1 := Foo{bar, map[interface{}]interface{}{"one": true}} f := Flag(5) b := []byte{ 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, } // Dump! spew.Dump(s1, f, b) // Output: // (spew_test.Foo) { // unexportedField: (spew_test.Bar) { // data: (uintptr) // }, // ExportedField: (map[interface {}]interface {}) (len=1) { // (string) (len=3) "one": (bool) true // } // } // (spew_test.Flag) Unknown flag (5) // ([]uint8) (len=34 cap=34) { // 00000000 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 |............... | // 00000010 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f 30 |!"#$%&'()*+,-./0| // 00000020 31 32 |12| // } // } // This example demonstrates how to use Printf to display a variable with a // format string and inline formatting. func ExamplePrintf() { // Create a double pointer to a uint 8. ui8 := uint8(5) pui8 := &ui8 ppui8 := &pui8 // Create a circular data type. type circular struct { ui8 uint8 c *circular } c := circular{ui8: 1} c.c = &c // Print! spew.Printf("ppui8: %v\n", ppui8) spew.Printf("circular: %v\n", c) // Output: // ppui8: <**>5 // circular: {1 <*>{1 <*>}} } // This example demonstrates how to use a ConfigState. func ExampleConfigState() { // Modify the indent level of the ConfigState only. The global // configuration is not modified. scs := spew.ConfigState{Indent: "\t"} // Output using the ConfigState instance. v := map[string]int{"one": 1} scs.Printf("v: %v\n", v) scs.Dump(v) // Output: // v: map[one:1] // (map[string]int) (len=1) { // (string) (len=3) "one": (int) 1 // } } // This example demonstrates how to use ConfigState.Dump to dump variables to // stdout func ExampleConfigState_Dump() { // See the top-level Dump example for details on the types used in this // example. // Create two ConfigState instances with different indentation. scs := spew.ConfigState{Indent: "\t"} scs2 := spew.ConfigState{Indent: " "} // Setup some sample data structures for the example. bar := Bar{uintptr(0)} s1 := Foo{bar, map[interface{}]interface{}{"one": true}} // Dump using the ConfigState instances. scs.Dump(s1) scs2.Dump(s1) // Output: // (spew_test.Foo) { // unexportedField: (spew_test.Bar) { // data: (uintptr) // }, // ExportedField: (map[interface {}]interface {}) (len=1) { // (string) (len=3) "one": (bool) true // } // } // (spew_test.Foo) { // unexportedField: (spew_test.Bar) { // data: (uintptr) // }, // ExportedField: (map[interface {}]interface {}) (len=1) { // (string) (len=3) "one": (bool) true // } // } // } // This example demonstrates how to use ConfigState.Printf to display a variable // with a format string and inline formatting. func ExampleConfigState_Printf() { // See the top-level Dump example for details on the types used in this // example. // Create two ConfigState instances and modify the method handling of the // first ConfigState only. scs := spew.NewDefaultConfig() scs2 := spew.NewDefaultConfig() scs.DisableMethods = true // Alternatively // scs := spew.ConfigState{Indent: " ", DisableMethods: true} // scs2 := spew.ConfigState{Indent: " "} // This is of type Flag which implements a Stringer and has raw value 1. f := flagTwo // Dump using the ConfigState instances. scs.Printf("f: %v\n", f) scs2.Printf("f: %v\n", f) // Output: // f: 1 // f: flagTwo } ================================================ FILE: internal/spew/format.go ================================================ /* * Copyright (c) 2013-2016 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ package spew import ( "bytes" "fmt" "reflect" "strconv" "strings" ) // supportedFlags is a list of all the character flags supported by fmt package. const supportedFlags = "0-+# " // formatState implements the fmt.Formatter interface and contains information // about the state of a formatting operation. The NewFormatter function can // be used to get a new Formatter which can be used directly as arguments // in standard fmt package printing calls. type formatState struct { value interface{} fs fmt.State depth int pointers map[uintptr]int ignoreNextType bool cs *ConfigState } // buildDefaultFormat recreates the original format string without precision // and width information to pass in to fmt.Sprintf in the case of an // unrecognized type. Unless new types are added to the language, this // function won't ever be called. func (f *formatState) buildDefaultFormat() (format string) { buf := bytes.NewBuffer(percentBytes) for _, flag := range supportedFlags { if f.fs.Flag(int(flag)) { buf.WriteRune(flag) } } buf.WriteRune('v') format = buf.String() return format } // constructOrigFormat recreates the original format string including precision // and width information to pass along to the standard fmt package. This allows // automatic deferral of all format strings this package doesn't support. func (f *formatState) constructOrigFormat(verb rune) (format string) { buf := bytes.NewBuffer(percentBytes) for _, flag := range supportedFlags { if f.fs.Flag(int(flag)) { buf.WriteRune(flag) } } if width, ok := f.fs.Width(); ok { buf.WriteString(strconv.Itoa(width)) } if precision, ok := f.fs.Precision(); ok { buf.Write(precisionBytes) buf.WriteString(strconv.Itoa(precision)) } buf.WriteRune(verb) format = buf.String() return format } // unpackValue returns values inside of non-nil interfaces when possible and // ensures that types for values which have been unpacked from an interface // are displayed when the show types flag is also set. // This is useful for data types like structs, arrays, slices, and maps which // can contain varying types packed inside an interface. func (f *formatState) unpackValue(v reflect.Value) reflect.Value { if v.Kind() == reflect.Interface { f.ignoreNextType = false if !v.IsNil() { v = v.Elem() } } return v } // formatPtr handles formatting of pointers by indirecting them as necessary. func (f *formatState) formatPtr(v reflect.Value) { // Display nil if top level pointer is nil. showTypes := f.fs.Flag('#') if v.IsNil() && (!showTypes || f.ignoreNextType) { f.fs.Write(nilAngleBytes) return } // Remove pointers at or below the current depth from map used to detect // circular refs. for k, depth := range f.pointers { if depth >= f.depth { delete(f.pointers, k) } } // Keep list of all dereferenced pointers to possibly show later. pointerChain := make([]uintptr, 0) // Figure out how many levels of indirection there are by dereferencing // pointers and unpacking interfaces down the chain while detecting circular // references. nilFound := false cycleFound := false indirects := 0 ve := v for ve.Kind() == reflect.Ptr { if ve.IsNil() { nilFound = true break } indirects++ addr := ve.Pointer() pointerChain = append(pointerChain, addr) if pd, ok := f.pointers[addr]; ok && pd < f.depth { cycleFound = true indirects-- break } f.pointers[addr] = f.depth ve = ve.Elem() if ve.Kind() == reflect.Interface { if ve.IsNil() { nilFound = true break } ve = ve.Elem() } } // Display type or indirection level depending on flags. if showTypes && !f.ignoreNextType { f.fs.Write(openParenBytes) f.fs.Write(bytes.Repeat(asteriskBytes, indirects)) f.fs.Write([]byte(ve.Type().String())) f.fs.Write(closeParenBytes) } else { if nilFound || cycleFound { indirects += strings.Count(ve.Type().String(), "*") } f.fs.Write(openAngleBytes) f.fs.Write([]byte(strings.Repeat("*", indirects))) f.fs.Write(closeAngleBytes) } // Display pointer information depending on flags. if f.fs.Flag('+') && (len(pointerChain) > 0) { f.fs.Write(openParenBytes) for i, addr := range pointerChain { if i > 0 { f.fs.Write(pointerChainBytes) } printHexPtr(f.fs, addr) } f.fs.Write(closeParenBytes) } // Display dereferenced value. switch { case nilFound: f.fs.Write(nilAngleBytes) case cycleFound: f.fs.Write(circularShortBytes) default: f.ignoreNextType = true f.format(ve) } } // format is the main workhorse for providing the Formatter interface. It // uses the passed reflect value to figure out what kind of object we are // dealing with and formats it appropriately. It is a recursive function, // however circular data structures are detected and handled properly. func (f *formatState) format(v reflect.Value) { // Handle invalid reflect values immediately. kind := v.Kind() if kind == reflect.Invalid { f.fs.Write(invalidAngleBytes) return } // Handle pointers specially. if kind == reflect.Ptr { f.formatPtr(v) return } // Print type information unless already handled elsewhere. if !f.ignoreNextType && f.fs.Flag('#') { f.fs.Write(openParenBytes) f.fs.Write([]byte(v.Type().String())) f.fs.Write(closeParenBytes) } f.ignoreNextType = false // Call Stringer/error interfaces if they exist and the handle methods // flag is enabled. if !f.cs.DisableMethods { if (kind != reflect.Invalid) && (kind != reflect.Interface) { if handled := handleMethods(f.cs, f.fs, v); handled { return } } } switch kind { case reflect.Invalid: // Do nothing. We should never get here since invalid has already // been handled above. case reflect.Bool: printBool(f.fs, v.Bool()) case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: printInt(f.fs, v.Int(), 10) case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: printUint(f.fs, v.Uint(), 10) case reflect.Float32: printFloat(f.fs, v.Float(), 32) case reflect.Float64: printFloat(f.fs, v.Float(), 64) case reflect.Complex64: printComplex(f.fs, v.Complex(), 32) case reflect.Complex128: printComplex(f.fs, v.Complex(), 64) case reflect.Slice: if v.IsNil() { f.fs.Write(nilAngleBytes) break } fallthrough case reflect.Array: f.fs.Write(openBracketBytes) f.depth++ if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { f.fs.Write(maxShortBytes) } else { numEntries := v.Len() for i := 0; i < numEntries; i++ { if i > 0 { f.fs.Write(spaceBytes) } f.ignoreNextType = true f.format(f.unpackValue(v.Index(i))) } } f.depth-- f.fs.Write(closeBracketBytes) case reflect.String: f.fs.Write([]byte(v.String())) case reflect.Interface: // The only time we should get here is for nil interfaces due to // unpackValue calls. if v.IsNil() { f.fs.Write(nilAngleBytes) } case reflect.Ptr: // Do nothing. We should never get here since pointers have already // been handled above. case reflect.Map: // nil maps should be indicated as different than empty maps if v.IsNil() { f.fs.Write(nilAngleBytes) break } f.fs.Write(openMapBytes) f.depth++ if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { f.fs.Write(maxShortBytes) } else { keys := v.MapKeys() if f.cs.SortKeys { sortValues(keys, f.cs) } for i, key := range keys { if i > 0 { f.fs.Write(spaceBytes) } f.ignoreNextType = true f.format(f.unpackValue(key)) f.fs.Write(colonBytes) f.ignoreNextType = true f.format(f.unpackValue(v.MapIndex(key))) } } f.depth-- f.fs.Write(closeMapBytes) case reflect.Struct: numFields := v.NumField() f.fs.Write(openBraceBytes) f.depth++ if (f.cs.MaxDepth != 0) && (f.depth > f.cs.MaxDepth) { f.fs.Write(maxShortBytes) } else { vt := v.Type() for i := 0; i < numFields; i++ { if i > 0 { f.fs.Write(spaceBytes) } vtf := vt.Field(i) if f.fs.Flag('+') || f.fs.Flag('#') { f.fs.Write([]byte(vtf.Name)) f.fs.Write(colonBytes) } f.format(f.unpackValue(v.Field(i))) } } f.depth-- f.fs.Write(closeBraceBytes) case reflect.Uintptr: printHexPtr(f.fs, uintptr(v.Uint())) case reflect.UnsafePointer, reflect.Chan, reflect.Func: printHexPtr(f.fs, v.Pointer()) // There were not any other types at the time this code was written, but // fall back to letting the default fmt package handle it if any get added. default: format := f.buildDefaultFormat() if v.CanInterface() { fmt.Fprintf(f.fs, format, v.Interface()) } else { fmt.Fprintf(f.fs, format, v.String()) } } } // Format satisfies the fmt.Formatter interface. See NewFormatter for usage // details. func (f *formatState) Format(fs fmt.State, verb rune) { f.fs = fs // Use standard formatting for verbs that are not v. if verb != 'v' { format := f.constructOrigFormat(verb) fmt.Fprintf(fs, format, f.value) return } if f.value == nil { if fs.Flag('#') { fs.Write(interfaceBytes) } fs.Write(nilAngleBytes) return } f.format(reflect.ValueOf(f.value)) } // newFormatter is a helper function to consolidate the logic from the various // public methods which take varying config states. func newFormatter(cs *ConfigState, v interface{}) fmt.Formatter { fs := &formatState{value: v, cs: cs} fs.pointers = make(map[uintptr]int) return fs } /* NewFormatter returns a custom formatter that satisfies the fmt.Formatter interface. As a result, it integrates cleanly with standard fmt package printing functions. The formatter is useful for inline printing of smaller data types similar to the standard %v format specifier. The custom formatter only responds to the %v (most compact), %+v (adds pointer addresses), %#v (adds types), or %#+v (adds types and pointer addresses) verb combinations. Any other verbs such as %x and %q will be sent to the standard fmt package for formatting. In addition, the custom formatter ignores the width and precision arguments (however they will still work on the format specifiers not handled by the custom formatter). Typically this function shouldn't be called directly. It is much easier to make use of the custom formatter by calling one of the convenience functions such as Printf, Println, or Fprintf. */ func NewFormatter(v interface{}) fmt.Formatter { return newFormatter(&Config, v) } ================================================ FILE: internal/spew/format_test.go ================================================ /* * Copyright (c) 2013-2016 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* Test Summary: NOTE: For each test, a nil pointer, a single pointer and double pointer to the base test element are also tested to ensure proper indirection across all types. - Max int8, int16, int32, int64, int - Max uint8, uint16, uint32, uint64, uint - Boolean true and false - Standard complex64 and complex128 - Array containing standard ints - Array containing type with custom formatter on pointer receiver only - Array containing interfaces - Slice containing standard float32 values - Slice containing type with custom formatter on pointer receiver only - Slice containing interfaces - Nil slice - Standard string - Nil interface - Sub-interface - Map with string keys and int vals - Map with custom formatter type on pointer receiver only keys and vals - Map with interface keys and values - Map with nil interface value - Struct with primitives - Struct that contains another struct - Struct that contains custom type with Stringer pointer interface via both exported and unexported fields - Struct that contains embedded struct and field to same struct - Uintptr to 0 (null pointer) - Uintptr address of real variable - Unsafe.Pointer to 0 (null pointer) - Unsafe.Pointer to address of real variable - Nil channel - Standard int channel - Function with no params and no returns - Function with param and no returns - Function with multiple params and multiple returns - Struct that is circular through self referencing - Structs that are circular through cross referencing - Structs that are indirectly circular - Type that panics in its Stringer interface - Type that has a custom Error interface - %x passthrough with uint - %#x passthrough with uint - %f passthrough with precision - %f passthrough with width and precision - %d passthrough with width - %q passthrough with string */ package spew_test import ( "bytes" "fmt" "testing" "unsafe" "github.com/expr-lang/expr/internal/spew" ) // formatterTest is used to describe a test to be performed against NewFormatter. type formatterTest struct { format string in interface{} wants []string } // formatterTests houses all of the tests to be performed against NewFormatter. var formatterTests = make([]formatterTest, 0) // addFormatterTest is a helper method to append the passed input and desired // result to formatterTests. func addFormatterTest(format string, in interface{}, wants ...string) { test := formatterTest{format, in, wants} formatterTests = append(formatterTests, test) } func addIntFormatterTests() { // Max int8. v := int8(127) nv := (*int8)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "int8" vs := "127" addFormatterTest("%v", v, vs) addFormatterTest("%v", pv, "<*>"+vs) addFormatterTest("%v", &pv, "<**>"+vs) addFormatterTest("%v", nv, "") addFormatterTest("%+v", v, vs) addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%#v", v, "("+vt+")"+vs) addFormatterTest("%#v", pv, "(*"+vt+")"+vs) addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) addFormatterTest("%#v", nv, "(*"+vt+")"+"") addFormatterTest("%#+v", v, "("+vt+")"+vs) addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%#+v", nv, "(*"+vt+")"+"") // Max int16. v2 := int16(32767) nv2 := (*int16)(nil) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "int16" v2s := "32767" addFormatterTest("%v", v2, v2s) addFormatterTest("%v", pv2, "<*>"+v2s) addFormatterTest("%v", &pv2, "<**>"+v2s) addFormatterTest("%v", nv2, "") addFormatterTest("%+v", v2, v2s) addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) addFormatterTest("%+v", nv2, "") addFormatterTest("%#v", v2, "("+v2t+")"+v2s) addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") // Max int32. v3 := int32(2147483647) nv3 := (*int32)(nil) pv3 := &v3 v3Addr := fmt.Sprintf("%p", pv3) pv3Addr := fmt.Sprintf("%p", &pv3) v3t := "int32" v3s := "2147483647" addFormatterTest("%v", v3, v3s) addFormatterTest("%v", pv3, "<*>"+v3s) addFormatterTest("%v", &pv3, "<**>"+v3s) addFormatterTest("%v", nv3, "") addFormatterTest("%+v", v3, v3s) addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) addFormatterTest("%+v", nv3, "") addFormatterTest("%#v", v3, "("+v3t+")"+v3s) addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s) addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s) addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") addFormatterTest("%#+v", v3, "("+v3t+")"+v3s) addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s) addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s) addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") // Max int64. v4 := int64(9223372036854775807) nv4 := (*int64)(nil) pv4 := &v4 v4Addr := fmt.Sprintf("%p", pv4) pv4Addr := fmt.Sprintf("%p", &pv4) v4t := "int64" v4s := "9223372036854775807" addFormatterTest("%v", v4, v4s) addFormatterTest("%v", pv4, "<*>"+v4s) addFormatterTest("%v", &pv4, "<**>"+v4s) addFormatterTest("%v", nv4, "") addFormatterTest("%+v", v4, v4s) addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s) addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s) addFormatterTest("%+v", nv4, "") addFormatterTest("%#v", v4, "("+v4t+")"+v4s) addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s) addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s) addFormatterTest("%#v", nv4, "(*"+v4t+")"+"") addFormatterTest("%#+v", v4, "("+v4t+")"+v4s) addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s) addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s) addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"") // Max int. v5 := int(2147483647) nv5 := (*int)(nil) pv5 := &v5 v5Addr := fmt.Sprintf("%p", pv5) pv5Addr := fmt.Sprintf("%p", &pv5) v5t := "int" v5s := "2147483647" addFormatterTest("%v", v5, v5s) addFormatterTest("%v", pv5, "<*>"+v5s) addFormatterTest("%v", &pv5, "<**>"+v5s) addFormatterTest("%v", nv5, "") addFormatterTest("%+v", v5, v5s) addFormatterTest("%+v", pv5, "<*>("+v5Addr+")"+v5s) addFormatterTest("%+v", &pv5, "<**>("+pv5Addr+"->"+v5Addr+")"+v5s) addFormatterTest("%+v", nv5, "") addFormatterTest("%#v", v5, "("+v5t+")"+v5s) addFormatterTest("%#v", pv5, "(*"+v5t+")"+v5s) addFormatterTest("%#v", &pv5, "(**"+v5t+")"+v5s) addFormatterTest("%#v", nv5, "(*"+v5t+")"+"") addFormatterTest("%#+v", v5, "("+v5t+")"+v5s) addFormatterTest("%#+v", pv5, "(*"+v5t+")("+v5Addr+")"+v5s) addFormatterTest("%#+v", &pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")"+v5s) addFormatterTest("%#+v", nv5, "(*"+v5t+")"+"") } func addUintFormatterTests() { // Max uint8. v := uint8(255) nv := (*uint8)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "uint8" vs := "255" addFormatterTest("%v", v, vs) addFormatterTest("%v", pv, "<*>"+vs) addFormatterTest("%v", &pv, "<**>"+vs) addFormatterTest("%v", nv, "") addFormatterTest("%+v", v, vs) addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%#v", v, "("+vt+")"+vs) addFormatterTest("%#v", pv, "(*"+vt+")"+vs) addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) addFormatterTest("%#v", nv, "(*"+vt+")"+"") addFormatterTest("%#+v", v, "("+vt+")"+vs) addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%#+v", nv, "(*"+vt+")"+"") // Max uint16. v2 := uint16(65535) nv2 := (*uint16)(nil) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "uint16" v2s := "65535" addFormatterTest("%v", v2, v2s) addFormatterTest("%v", pv2, "<*>"+v2s) addFormatterTest("%v", &pv2, "<**>"+v2s) addFormatterTest("%v", nv2, "") addFormatterTest("%+v", v2, v2s) addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) addFormatterTest("%+v", nv2, "") addFormatterTest("%#v", v2, "("+v2t+")"+v2s) addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") // Max uint32. v3 := uint32(4294967295) nv3 := (*uint32)(nil) pv3 := &v3 v3Addr := fmt.Sprintf("%p", pv3) pv3Addr := fmt.Sprintf("%p", &pv3) v3t := "uint32" v3s := "4294967295" addFormatterTest("%v", v3, v3s) addFormatterTest("%v", pv3, "<*>"+v3s) addFormatterTest("%v", &pv3, "<**>"+v3s) addFormatterTest("%v", nv3, "") addFormatterTest("%+v", v3, v3s) addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) addFormatterTest("%+v", nv3, "") addFormatterTest("%#v", v3, "("+v3t+")"+v3s) addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s) addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s) addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") addFormatterTest("%#+v", v3, "("+v3t+")"+v3s) addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s) addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s) addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") // Max uint64. v4 := uint64(18446744073709551615) nv4 := (*uint64)(nil) pv4 := &v4 v4Addr := fmt.Sprintf("%p", pv4) pv4Addr := fmt.Sprintf("%p", &pv4) v4t := "uint64" v4s := "18446744073709551615" addFormatterTest("%v", v4, v4s) addFormatterTest("%v", pv4, "<*>"+v4s) addFormatterTest("%v", &pv4, "<**>"+v4s) addFormatterTest("%v", nv4, "") addFormatterTest("%+v", v4, v4s) addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s) addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s) addFormatterTest("%+v", nv4, "") addFormatterTest("%#v", v4, "("+v4t+")"+v4s) addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s) addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s) addFormatterTest("%#v", nv4, "(*"+v4t+")"+"") addFormatterTest("%#+v", v4, "("+v4t+")"+v4s) addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s) addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s) addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"") // Max uint. v5 := uint(4294967295) nv5 := (*uint)(nil) pv5 := &v5 v5Addr := fmt.Sprintf("%p", pv5) pv5Addr := fmt.Sprintf("%p", &pv5) v5t := "uint" v5s := "4294967295" addFormatterTest("%v", v5, v5s) addFormatterTest("%v", pv5, "<*>"+v5s) addFormatterTest("%v", &pv5, "<**>"+v5s) addFormatterTest("%v", nv5, "") addFormatterTest("%+v", v5, v5s) addFormatterTest("%+v", pv5, "<*>("+v5Addr+")"+v5s) addFormatterTest("%+v", &pv5, "<**>("+pv5Addr+"->"+v5Addr+")"+v5s) addFormatterTest("%+v", nv5, "") addFormatterTest("%#v", v5, "("+v5t+")"+v5s) addFormatterTest("%#v", pv5, "(*"+v5t+")"+v5s) addFormatterTest("%#v", &pv5, "(**"+v5t+")"+v5s) addFormatterTest("%#v", nv5, "(*"+v5t+")"+"") addFormatterTest("%#+v", v5, "("+v5t+")"+v5s) addFormatterTest("%#+v", pv5, "(*"+v5t+")("+v5Addr+")"+v5s) addFormatterTest("%#+v", &pv5, "(**"+v5t+")("+pv5Addr+"->"+v5Addr+")"+v5s) addFormatterTest("%#v", nv5, "(*"+v5t+")"+"") } func addBoolFormatterTests() { // Boolean true. v := bool(true) nv := (*bool)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "bool" vs := "true" addFormatterTest("%v", v, vs) addFormatterTest("%v", pv, "<*>"+vs) addFormatterTest("%v", &pv, "<**>"+vs) addFormatterTest("%v", nv, "") addFormatterTest("%+v", v, vs) addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%#v", v, "("+vt+")"+vs) addFormatterTest("%#v", pv, "(*"+vt+")"+vs) addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) addFormatterTest("%#v", nv, "(*"+vt+")"+"") addFormatterTest("%#+v", v, "("+vt+")"+vs) addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%#+v", nv, "(*"+vt+")"+"") // Boolean false. v2 := bool(false) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "bool" v2s := "false" addFormatterTest("%v", v2, v2s) addFormatterTest("%v", pv2, "<*>"+v2s) addFormatterTest("%v", &pv2, "<**>"+v2s) addFormatterTest("%+v", v2, v2s) addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) addFormatterTest("%#v", v2, "("+v2t+")"+v2s) addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) } func addFloatFormatterTests() { // Standard float32. v := float32(3.1415) nv := (*float32)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "float32" vs := "3.1415" addFormatterTest("%v", v, vs) addFormatterTest("%v", pv, "<*>"+vs) addFormatterTest("%v", &pv, "<**>"+vs) addFormatterTest("%v", nv, "") addFormatterTest("%+v", v, vs) addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%#v", v, "("+vt+")"+vs) addFormatterTest("%#v", pv, "(*"+vt+")"+vs) addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) addFormatterTest("%#v", nv, "(*"+vt+")"+"") addFormatterTest("%#+v", v, "("+vt+")"+vs) addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%#+v", nv, "(*"+vt+")"+"") // Standard float64. v2 := float64(3.1415926) nv2 := (*float64)(nil) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "float64" v2s := "3.1415926" addFormatterTest("%v", v2, v2s) addFormatterTest("%v", pv2, "<*>"+v2s) addFormatterTest("%v", &pv2, "<**>"+v2s) addFormatterTest("%+v", nv2, "") addFormatterTest("%+v", v2, v2s) addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) addFormatterTest("%+v", nv2, "") addFormatterTest("%#v", v2, "("+v2t+")"+v2s) addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") } func addComplexFormatterTests() { // Standard complex64. v := complex(float32(6), -2) nv := (*complex64)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "complex64" vs := "(6-2i)" addFormatterTest("%v", v, vs) addFormatterTest("%v", pv, "<*>"+vs) addFormatterTest("%v", &pv, "<**>"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%+v", v, vs) addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%#v", v, "("+vt+")"+vs) addFormatterTest("%#v", pv, "(*"+vt+")"+vs) addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) addFormatterTest("%#v", nv, "(*"+vt+")"+"") addFormatterTest("%#+v", v, "("+vt+")"+vs) addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%#+v", nv, "(*"+vt+")"+"") // Standard complex128. v2 := complex(float64(-6), 2) nv2 := (*complex128)(nil) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "complex128" v2s := "(-6+2i)" addFormatterTest("%v", v2, v2s) addFormatterTest("%v", pv2, "<*>"+v2s) addFormatterTest("%v", &pv2, "<**>"+v2s) addFormatterTest("%+v", nv2, "") addFormatterTest("%+v", v2, v2s) addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) addFormatterTest("%+v", nv2, "") addFormatterTest("%#v", v2, "("+v2t+")"+v2s) addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") } func addArrayFormatterTests() { // Array containing standard ints. v := [3]int{1, 2, 3} nv := (*[3]int)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "[3]int" vs := "[1 2 3]" addFormatterTest("%v", v, vs) addFormatterTest("%v", pv, "<*>"+vs) addFormatterTest("%v", &pv, "<**>"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%+v", v, vs) addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%#v", v, "("+vt+")"+vs) addFormatterTest("%#v", pv, "(*"+vt+")"+vs) addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) addFormatterTest("%#v", nv, "(*"+vt+")"+"") addFormatterTest("%#+v", v, "("+vt+")"+vs) addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%#+v", nv, "(*"+vt+")"+"") // Array containing type with custom formatter on pointer receiver only. v2 := [3]pstringer{"1", "2", "3"} nv2 := (*[3]pstringer)(nil) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "[3]spew_test.pstringer" v2sp := "[stringer 1 stringer 2 stringer 3]" v2s := v2sp if spew.UnsafeDisabled { v2s = "[1 2 3]" } addFormatterTest("%v", v2, v2s) addFormatterTest("%v", pv2, "<*>"+v2sp) addFormatterTest("%v", &pv2, "<**>"+v2sp) addFormatterTest("%+v", nv2, "") addFormatterTest("%+v", v2, v2s) addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2sp) addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2sp) addFormatterTest("%+v", nv2, "") addFormatterTest("%#v", v2, "("+v2t+")"+v2s) addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2sp) addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2sp) addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2sp) addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2sp) addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") // Array containing interfaces. v3 := [3]interface{}{"one", int(2), uint(3)} nv3 := (*[3]interface{})(nil) pv3 := &v3 v3Addr := fmt.Sprintf("%p", pv3) pv3Addr := fmt.Sprintf("%p", &pv3) v3t := "[3]interface {}" v3t2 := "string" v3t3 := "int" v3t4 := "uint" v3s := "[one 2 3]" v3s2 := "[(" + v3t2 + ")one (" + v3t3 + ")2 (" + v3t4 + ")3]" addFormatterTest("%v", v3, v3s) addFormatterTest("%v", pv3, "<*>"+v3s) addFormatterTest("%v", &pv3, "<**>"+v3s) addFormatterTest("%+v", nv3, "") addFormatterTest("%+v", v3, v3s) addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) addFormatterTest("%+v", nv3, "") addFormatterTest("%#v", v3, "("+v3t+")"+v3s2) addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s2) addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s2) addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") addFormatterTest("%#+v", v3, "("+v3t+")"+v3s2) addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s2) addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s2) addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"") } func addSliceFormatterTests() { // Slice containing standard float32 values. v := []float32{3.14, 6.28, 12.56} nv := (*[]float32)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "[]float32" vs := "[3.14 6.28 12.56]" addFormatterTest("%v", v, vs) addFormatterTest("%v", pv, "<*>"+vs) addFormatterTest("%v", &pv, "<**>"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%+v", v, vs) addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%#v", v, "("+vt+")"+vs) addFormatterTest("%#v", pv, "(*"+vt+")"+vs) addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) addFormatterTest("%#v", nv, "(*"+vt+")"+"") addFormatterTest("%#+v", v, "("+vt+")"+vs) addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%#+v", nv, "(*"+vt+")"+"") // Slice containing type with custom formatter on pointer receiver only. v2 := []pstringer{"1", "2", "3"} nv2 := (*[]pstringer)(nil) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "[]spew_test.pstringer" v2s := "[stringer 1 stringer 2 stringer 3]" addFormatterTest("%v", v2, v2s) addFormatterTest("%v", pv2, "<*>"+v2s) addFormatterTest("%v", &pv2, "<**>"+v2s) addFormatterTest("%+v", nv2, "") addFormatterTest("%+v", v2, v2s) addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) addFormatterTest("%+v", nv2, "") addFormatterTest("%#v", v2, "("+v2t+")"+v2s) addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") // Slice containing interfaces. v3 := []interface{}{"one", int(2), uint(3), nil} nv3 := (*[]interface{})(nil) pv3 := &v3 v3Addr := fmt.Sprintf("%p", pv3) pv3Addr := fmt.Sprintf("%p", &pv3) v3t := "[]interface {}" v3t2 := "string" v3t3 := "int" v3t4 := "uint" v3t5 := "interface {}" v3s := "[one 2 3 ]" v3s2 := "[(" + v3t2 + ")one (" + v3t3 + ")2 (" + v3t4 + ")3 (" + v3t5 + ")]" addFormatterTest("%v", v3, v3s) addFormatterTest("%v", pv3, "<*>"+v3s) addFormatterTest("%v", &pv3, "<**>"+v3s) addFormatterTest("%+v", nv3, "") addFormatterTest("%+v", v3, v3s) addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) addFormatterTest("%+v", nv3, "") addFormatterTest("%#v", v3, "("+v3t+")"+v3s2) addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s2) addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s2) addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") addFormatterTest("%#+v", v3, "("+v3t+")"+v3s2) addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s2) addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s2) addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"") // Nil slice. var v4 []int nv4 := (*[]int)(nil) pv4 := &v4 v4Addr := fmt.Sprintf("%p", pv4) pv4Addr := fmt.Sprintf("%p", &pv4) v4t := "[]int" v4s := "" addFormatterTest("%v", v4, v4s) addFormatterTest("%v", pv4, "<*>"+v4s) addFormatterTest("%v", &pv4, "<**>"+v4s) addFormatterTest("%+v", nv4, "") addFormatterTest("%+v", v4, v4s) addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s) addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s) addFormatterTest("%+v", nv4, "") addFormatterTest("%#v", v4, "("+v4t+")"+v4s) addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s) addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s) addFormatterTest("%#v", nv4, "(*"+v4t+")"+"") addFormatterTest("%#+v", v4, "("+v4t+")"+v4s) addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s) addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s) addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"") } func addStringFormatterTests() { // Standard string. v := "test" nv := (*string)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "string" vs := "test" addFormatterTest("%v", v, vs) addFormatterTest("%v", pv, "<*>"+vs) addFormatterTest("%v", &pv, "<**>"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%+v", v, vs) addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%#v", v, "("+vt+")"+vs) addFormatterTest("%#v", pv, "(*"+vt+")"+vs) addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) addFormatterTest("%#v", nv, "(*"+vt+")"+"") addFormatterTest("%#+v", v, "("+vt+")"+vs) addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%#+v", nv, "(*"+vt+")"+"") } func addInterfaceFormatterTests() { // Nil interface. var v interface{} nv := (*interface{})(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "interface {}" vs := "" addFormatterTest("%v", v, vs) addFormatterTest("%v", pv, "<*>"+vs) addFormatterTest("%v", &pv, "<**>"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%+v", v, vs) addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%#v", v, "("+vt+")"+vs) addFormatterTest("%#v", pv, "(*"+vt+")"+vs) addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) addFormatterTest("%#v", nv, "(*"+vt+")"+"") addFormatterTest("%#+v", v, "("+vt+")"+vs) addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%#+v", nv, "(*"+vt+")"+"") // Sub-interface. v2 := interface{}(uint16(65535)) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "uint16" v2s := "65535" addFormatterTest("%v", v2, v2s) addFormatterTest("%v", pv2, "<*>"+v2s) addFormatterTest("%v", &pv2, "<**>"+v2s) addFormatterTest("%+v", v2, v2s) addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) addFormatterTest("%#v", v2, "("+v2t+")"+v2s) addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) } func addMapFormatterTests() { // Map with string keys and int vals. v := map[string]int{"one": 1, "two": 2} nilMap := map[string]int(nil) nv := (*map[string]int)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "map[string]int" vs := "map[one:1 two:2]" vs2 := "map[two:2 one:1]" addFormatterTest("%v", v, vs, vs2) addFormatterTest("%v", pv, "<*>"+vs, "<*>"+vs2) addFormatterTest("%v", &pv, "<**>"+vs, "<**>"+vs2) addFormatterTest("%+v", nilMap, "") addFormatterTest("%+v", nv, "") addFormatterTest("%+v", v, vs, vs2) addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs, "<*>("+vAddr+")"+vs2) addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs, "<**>("+pvAddr+"->"+vAddr+")"+vs2) addFormatterTest("%+v", nilMap, "") addFormatterTest("%+v", nv, "") addFormatterTest("%#v", v, "("+vt+")"+vs, "("+vt+")"+vs2) addFormatterTest("%#v", pv, "(*"+vt+")"+vs, "(*"+vt+")"+vs2) addFormatterTest("%#v", &pv, "(**"+vt+")"+vs, "(**"+vt+")"+vs2) addFormatterTest("%#v", nilMap, "("+vt+")"+"") addFormatterTest("%#v", nv, "(*"+vt+")"+"") addFormatterTest("%#+v", v, "("+vt+")"+vs, "("+vt+")"+vs2) addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs, "(*"+vt+")("+vAddr+")"+vs2) addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs2) addFormatterTest("%#+v", nilMap, "("+vt+")"+"") addFormatterTest("%#+v", nv, "(*"+vt+")"+"") // Map with custom formatter type on pointer receiver only keys and vals. v2 := map[pstringer]pstringer{"one": "1"} nv2 := (*map[pstringer]pstringer)(nil) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "map[spew_test.pstringer]spew_test.pstringer" v2s := "map[stringer one:stringer 1]" if spew.UnsafeDisabled { v2s = "map[one:1]" } addFormatterTest("%v", v2, v2s) addFormatterTest("%v", pv2, "<*>"+v2s) addFormatterTest("%v", &pv2, "<**>"+v2s) addFormatterTest("%+v", nv2, "") addFormatterTest("%+v", v2, v2s) addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) addFormatterTest("%+v", nv2, "") addFormatterTest("%#v", v2, "("+v2t+")"+v2s) addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") // Map with interface keys and values. v3 := map[interface{}]interface{}{"one": 1} nv3 := (*map[interface{}]interface{})(nil) pv3 := &v3 v3Addr := fmt.Sprintf("%p", pv3) pv3Addr := fmt.Sprintf("%p", &pv3) v3t := "map[interface {}]interface {}" v3t1 := "string" v3t2 := "int" v3s := "map[one:1]" v3s2 := "map[(" + v3t1 + ")one:(" + v3t2 + ")1]" addFormatterTest("%v", v3, v3s) addFormatterTest("%v", pv3, "<*>"+v3s) addFormatterTest("%v", &pv3, "<**>"+v3s) addFormatterTest("%+v", nv3, "") addFormatterTest("%+v", v3, v3s) addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) addFormatterTest("%+v", nv3, "") addFormatterTest("%#v", v3, "("+v3t+")"+v3s2) addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s2) addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s2) addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") addFormatterTest("%#+v", v3, "("+v3t+")"+v3s2) addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s2) addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s2) addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"") // Map with nil interface value v4 := map[string]interface{}{"nil": nil} nv4 := (*map[string]interface{})(nil) pv4 := &v4 v4Addr := fmt.Sprintf("%p", pv4) pv4Addr := fmt.Sprintf("%p", &pv4) v4t := "map[string]interface {}" v4t1 := "interface {}" v4s := "map[nil:]" v4s2 := "map[nil:(" + v4t1 + ")]" addFormatterTest("%v", v4, v4s) addFormatterTest("%v", pv4, "<*>"+v4s) addFormatterTest("%v", &pv4, "<**>"+v4s) addFormatterTest("%+v", nv4, "") addFormatterTest("%+v", v4, v4s) addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s) addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s) addFormatterTest("%+v", nv4, "") addFormatterTest("%#v", v4, "("+v4t+")"+v4s2) addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s2) addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s2) addFormatterTest("%#v", nv4, "(*"+v4t+")"+"") addFormatterTest("%#+v", v4, "("+v4t+")"+v4s2) addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s2) addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s2) addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"") } func addStructFormatterTests() { // Struct with primitives. type s1 struct { a int8 b uint8 } v := s1{127, 255} nv := (*s1)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "spew_test.s1" vt2 := "int8" vt3 := "uint8" vs := "{127 255}" vs2 := "{a:127 b:255}" vs3 := "{a:(" + vt2 + ")127 b:(" + vt3 + ")255}" addFormatterTest("%v", v, vs) addFormatterTest("%v", pv, "<*>"+vs) addFormatterTest("%v", &pv, "<**>"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%+v", v, vs2) addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs2) addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs2) addFormatterTest("%+v", nv, "") addFormatterTest("%#v", v, "("+vt+")"+vs3) addFormatterTest("%#v", pv, "(*"+vt+")"+vs3) addFormatterTest("%#v", &pv, "(**"+vt+")"+vs3) addFormatterTest("%#v", nv, "(*"+vt+")"+"") addFormatterTest("%#+v", v, "("+vt+")"+vs3) addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs3) addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs3) addFormatterTest("%#+v", nv, "(*"+vt+")"+"") // Struct that contains another struct. type s2 struct { s1 s1 b bool } v2 := s2{s1{127, 255}, true} nv2 := (*s2)(nil) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "spew_test.s2" v2t2 := "spew_test.s1" v2t3 := "int8" v2t4 := "uint8" v2t5 := "bool" v2s := "{{127 255} true}" v2s2 := "{s1:{a:127 b:255} b:true}" v2s3 := "{s1:(" + v2t2 + "){a:(" + v2t3 + ")127 b:(" + v2t4 + ")255} b:(" + v2t5 + ")true}" addFormatterTest("%v", v2, v2s) addFormatterTest("%v", pv2, "<*>"+v2s) addFormatterTest("%v", &pv2, "<**>"+v2s) addFormatterTest("%+v", nv2, "") addFormatterTest("%+v", v2, v2s2) addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s2) addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s2) addFormatterTest("%+v", nv2, "") addFormatterTest("%#v", v2, "("+v2t+")"+v2s3) addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s3) addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s3) addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") addFormatterTest("%#+v", v2, "("+v2t+")"+v2s3) addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s3) addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s3) addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") // Struct that contains custom type with Stringer pointer interface via both // exported and unexported fields. type s3 struct { s pstringer S pstringer } v3 := s3{"test", "test2"} nv3 := (*s3)(nil) pv3 := &v3 v3Addr := fmt.Sprintf("%p", pv3) pv3Addr := fmt.Sprintf("%p", &pv3) v3t := "spew_test.s3" v3t2 := "spew_test.pstringer" v3s := "{stringer test stringer test2}" v3sp := v3s v3s2 := "{s:stringer test S:stringer test2}" v3s2p := v3s2 v3s3 := "{s:(" + v3t2 + ")stringer test S:(" + v3t2 + ")stringer test2}" v3s3p := v3s3 if spew.UnsafeDisabled { v3s = "{test test2}" v3sp = "{test stringer test2}" v3s2 = "{s:test S:test2}" v3s2p = "{s:test S:stringer test2}" v3s3 = "{s:(" + v3t2 + ")test S:(" + v3t2 + ")test2}" v3s3p = "{s:(" + v3t2 + ")test S:(" + v3t2 + ")stringer test2}" } addFormatterTest("%v", v3, v3s) addFormatterTest("%v", pv3, "<*>"+v3sp) addFormatterTest("%v", &pv3, "<**>"+v3sp) addFormatterTest("%+v", nv3, "") addFormatterTest("%+v", v3, v3s2) addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s2p) addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s2p) addFormatterTest("%+v", nv3, "") addFormatterTest("%#v", v3, "("+v3t+")"+v3s3) addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s3p) addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s3p) addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") addFormatterTest("%#+v", v3, "("+v3t+")"+v3s3) addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s3p) addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s3p) addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"") // Struct that contains embedded struct and field to same struct. e := embed{"embedstr"} v4 := embedwrap{embed: &e, e: &e} nv4 := (*embedwrap)(nil) pv4 := &v4 eAddr := fmt.Sprintf("%p", &e) v4Addr := fmt.Sprintf("%p", pv4) pv4Addr := fmt.Sprintf("%p", &pv4) v4t := "spew_test.embedwrap" v4t2 := "spew_test.embed" v4t3 := "string" v4s := "{<*>{embedstr} <*>{embedstr}}" v4s2 := "{embed:<*>(" + eAddr + "){a:embedstr} e:<*>(" + eAddr + "){a:embedstr}}" v4s3 := "{embed:(*" + v4t2 + "){a:(" + v4t3 + ")embedstr} e:(*" + v4t2 + "){a:(" + v4t3 + ")embedstr}}" v4s4 := "{embed:(*" + v4t2 + ")(" + eAddr + "){a:(" + v4t3 + ")embedstr} e:(*" + v4t2 + ")(" + eAddr + "){a:(" + v4t3 + ")embedstr}}" addFormatterTest("%v", v4, v4s) addFormatterTest("%v", pv4, "<*>"+v4s) addFormatterTest("%v", &pv4, "<**>"+v4s) addFormatterTest("%+v", nv4, "") addFormatterTest("%+v", v4, v4s2) addFormatterTest("%+v", pv4, "<*>("+v4Addr+")"+v4s2) addFormatterTest("%+v", &pv4, "<**>("+pv4Addr+"->"+v4Addr+")"+v4s2) addFormatterTest("%+v", nv4, "") addFormatterTest("%#v", v4, "("+v4t+")"+v4s3) addFormatterTest("%#v", pv4, "(*"+v4t+")"+v4s3) addFormatterTest("%#v", &pv4, "(**"+v4t+")"+v4s3) addFormatterTest("%#v", nv4, "(*"+v4t+")"+"") addFormatterTest("%#+v", v4, "("+v4t+")"+v4s4) addFormatterTest("%#+v", pv4, "(*"+v4t+")("+v4Addr+")"+v4s4) addFormatterTest("%#+v", &pv4, "(**"+v4t+")("+pv4Addr+"->"+v4Addr+")"+v4s4) addFormatterTest("%#+v", nv4, "(*"+v4t+")"+"") } func addUintptrFormatterTests() { // Null pointer. v := uintptr(0) nv := (*uintptr)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "uintptr" vs := "" addFormatterTest("%v", v, vs) addFormatterTest("%v", pv, "<*>"+vs) addFormatterTest("%v", &pv, "<**>"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%+v", v, vs) addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%#v", v, "("+vt+")"+vs) addFormatterTest("%#v", pv, "(*"+vt+")"+vs) addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) addFormatterTest("%#v", nv, "(*"+vt+")"+"") addFormatterTest("%#+v", v, "("+vt+")"+vs) addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%#+v", nv, "(*"+vt+")"+"") // Address of real variable. i := 1 v2 := uintptr(unsafe.Pointer(&i)) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "uintptr" v2s := fmt.Sprintf("%p", &i) addFormatterTest("%v", v2, v2s) addFormatterTest("%v", pv2, "<*>"+v2s) addFormatterTest("%v", &pv2, "<**>"+v2s) addFormatterTest("%+v", v2, v2s) addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) addFormatterTest("%#v", v2, "("+v2t+")"+v2s) addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) } func addUnsafePointerFormatterTests() { // Null pointer. v := unsafe.Pointer(nil) nv := (*unsafe.Pointer)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "unsafe.Pointer" vs := "" addFormatterTest("%v", v, vs) addFormatterTest("%v", pv, "<*>"+vs) addFormatterTest("%v", &pv, "<**>"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%+v", v, vs) addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%#v", v, "("+vt+")"+vs) addFormatterTest("%#v", pv, "(*"+vt+")"+vs) addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) addFormatterTest("%#v", nv, "(*"+vt+")"+"") addFormatterTest("%#+v", v, "("+vt+")"+vs) addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%#+v", nv, "(*"+vt+")"+"") // Address of real variable. i := 1 v2 := unsafe.Pointer(&i) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "unsafe.Pointer" v2s := fmt.Sprintf("%p", &i) addFormatterTest("%v", v2, v2s) addFormatterTest("%v", pv2, "<*>"+v2s) addFormatterTest("%v", &pv2, "<**>"+v2s) addFormatterTest("%+v", v2, v2s) addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) addFormatterTest("%#v", v2, "("+v2t+")"+v2s) addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) } func addChanFormatterTests() { // Nil channel. var v chan int pv := &v nv := (*chan int)(nil) vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "chan int" vs := "" addFormatterTest("%v", v, vs) addFormatterTest("%v", pv, "<*>"+vs) addFormatterTest("%v", &pv, "<**>"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%+v", v, vs) addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%#v", v, "("+vt+")"+vs) addFormatterTest("%#v", pv, "(*"+vt+")"+vs) addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) addFormatterTest("%#v", nv, "(*"+vt+")"+"") addFormatterTest("%#+v", v, "("+vt+")"+vs) addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%#+v", nv, "(*"+vt+")"+"") // Real channel. v2 := make(chan int) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "chan int" v2s := fmt.Sprintf("%p", v2) addFormatterTest("%v", v2, v2s) addFormatterTest("%v", pv2, "<*>"+v2s) addFormatterTest("%v", &pv2, "<**>"+v2s) addFormatterTest("%+v", v2, v2s) addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) addFormatterTest("%#v", v2, "("+v2t+")"+v2s) addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) } func addFuncFormatterTests() { // Function with no params and no returns. v := addIntFormatterTests nv := (*func())(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "func()" vs := fmt.Sprintf("%p", v) addFormatterTest("%v", v, vs) addFormatterTest("%v", pv, "<*>"+vs) addFormatterTest("%v", &pv, "<**>"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%+v", v, vs) addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%#v", v, "("+vt+")"+vs) addFormatterTest("%#v", pv, "(*"+vt+")"+vs) addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) addFormatterTest("%#v", nv, "(*"+vt+")"+"") addFormatterTest("%#+v", v, "("+vt+")"+vs) addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%#+v", nv, "(*"+vt+")"+"") // Function with param and no returns. v2 := TestFormatter nv2 := (*func(*testing.T))(nil) pv2 := &v2 v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "func(*testing.T)" v2s := fmt.Sprintf("%p", v2) addFormatterTest("%v", v2, v2s) addFormatterTest("%v", pv2, "<*>"+v2s) addFormatterTest("%v", &pv2, "<**>"+v2s) addFormatterTest("%+v", nv2, "") addFormatterTest("%+v", v2, v2s) addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s) addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s) addFormatterTest("%+v", nv2, "") addFormatterTest("%#v", v2, "("+v2t+")"+v2s) addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s) addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s) addFormatterTest("%#v", nv2, "(*"+v2t+")"+"") addFormatterTest("%#+v", v2, "("+v2t+")"+v2s) addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s) addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s) addFormatterTest("%#+v", nv2, "(*"+v2t+")"+"") // Function with multiple params and multiple returns. var v3 = func(i int, s string) (b bool, err error) { return true, nil } nv3 := (*func(int, string) (bool, error))(nil) pv3 := &v3 v3Addr := fmt.Sprintf("%p", pv3) pv3Addr := fmt.Sprintf("%p", &pv3) v3t := "func(int, string) (bool, error)" v3s := fmt.Sprintf("%p", v3) addFormatterTest("%v", v3, v3s) addFormatterTest("%v", pv3, "<*>"+v3s) addFormatterTest("%v", &pv3, "<**>"+v3s) addFormatterTest("%+v", nv3, "") addFormatterTest("%+v", v3, v3s) addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s) addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s) addFormatterTest("%+v", nv3, "") addFormatterTest("%#v", v3, "("+v3t+")"+v3s) addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s) addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s) addFormatterTest("%#v", nv3, "(*"+v3t+")"+"") addFormatterTest("%#+v", v3, "("+v3t+")"+v3s) addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s) addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s) addFormatterTest("%#+v", nv3, "(*"+v3t+")"+"") } func addCircularFormatterTests() { // Struct that is circular through self referencing. type circular struct { c *circular } v := circular{nil} v.c = &v pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "spew_test.circular" vs := "{<*>{<*>}}" vs2 := "{<*>}" vs3 := "{c:<*>(" + vAddr + "){c:<*>(" + vAddr + ")}}" vs4 := "{c:<*>(" + vAddr + ")}" vs5 := "{c:(*" + vt + "){c:(*" + vt + ")}}" vs6 := "{c:(*" + vt + ")}" vs7 := "{c:(*" + vt + ")(" + vAddr + "){c:(*" + vt + ")(" + vAddr + ")}}" vs8 := "{c:(*" + vt + ")(" + vAddr + ")}" addFormatterTest("%v", v, vs) addFormatterTest("%v", pv, "<*>"+vs2) addFormatterTest("%v", &pv, "<**>"+vs2) addFormatterTest("%+v", v, vs3) addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs4) addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs4) addFormatterTest("%#v", v, "("+vt+")"+vs5) addFormatterTest("%#v", pv, "(*"+vt+")"+vs6) addFormatterTest("%#v", &pv, "(**"+vt+")"+vs6) addFormatterTest("%#+v", v, "("+vt+")"+vs7) addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs8) addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs8) // Structs that are circular through cross referencing. v2 := xref1{nil} ts2 := xref2{&v2} v2.ps2 = &ts2 pv2 := &v2 ts2Addr := fmt.Sprintf("%p", &ts2) v2Addr := fmt.Sprintf("%p", pv2) pv2Addr := fmt.Sprintf("%p", &pv2) v2t := "spew_test.xref1" v2t2 := "spew_test.xref2" v2s := "{<*>{<*>{<*>}}}" v2s2 := "{<*>{<*>}}" v2s3 := "{ps2:<*>(" + ts2Addr + "){ps1:<*>(" + v2Addr + "){ps2:<*>(" + ts2Addr + ")}}}" v2s4 := "{ps2:<*>(" + ts2Addr + "){ps1:<*>(" + v2Addr + ")}}" v2s5 := "{ps2:(*" + v2t2 + "){ps1:(*" + v2t + "){ps2:(*" + v2t2 + ")}}}" v2s6 := "{ps2:(*" + v2t2 + "){ps1:(*" + v2t + ")}}" v2s7 := "{ps2:(*" + v2t2 + ")(" + ts2Addr + "){ps1:(*" + v2t + ")(" + v2Addr + "){ps2:(*" + v2t2 + ")(" + ts2Addr + ")}}}" v2s8 := "{ps2:(*" + v2t2 + ")(" + ts2Addr + "){ps1:(*" + v2t + ")(" + v2Addr + ")}}" addFormatterTest("%v", v2, v2s) addFormatterTest("%v", pv2, "<*>"+v2s2) addFormatterTest("%v", &pv2, "<**>"+v2s2) addFormatterTest("%+v", v2, v2s3) addFormatterTest("%+v", pv2, "<*>("+v2Addr+")"+v2s4) addFormatterTest("%+v", &pv2, "<**>("+pv2Addr+"->"+v2Addr+")"+v2s4) addFormatterTest("%#v", v2, "("+v2t+")"+v2s5) addFormatterTest("%#v", pv2, "(*"+v2t+")"+v2s6) addFormatterTest("%#v", &pv2, "(**"+v2t+")"+v2s6) addFormatterTest("%#+v", v2, "("+v2t+")"+v2s7) addFormatterTest("%#+v", pv2, "(*"+v2t+")("+v2Addr+")"+v2s8) addFormatterTest("%#+v", &pv2, "(**"+v2t+")("+pv2Addr+"->"+v2Addr+")"+v2s8) // Structs that are indirectly circular. v3 := indirCir1{nil} tic2 := indirCir2{nil} tic3 := indirCir3{&v3} tic2.ps3 = &tic3 v3.ps2 = &tic2 pv3 := &v3 tic2Addr := fmt.Sprintf("%p", &tic2) tic3Addr := fmt.Sprintf("%p", &tic3) v3Addr := fmt.Sprintf("%p", pv3) pv3Addr := fmt.Sprintf("%p", &pv3) v3t := "spew_test.indirCir1" v3t2 := "spew_test.indirCir2" v3t3 := "spew_test.indirCir3" v3s := "{<*>{<*>{<*>{<*>}}}}" v3s2 := "{<*>{<*>{<*>}}}" v3s3 := "{ps2:<*>(" + tic2Addr + "){ps3:<*>(" + tic3Addr + "){ps1:<*>(" + v3Addr + "){ps2:<*>(" + tic2Addr + ")}}}}" v3s4 := "{ps2:<*>(" + tic2Addr + "){ps3:<*>(" + tic3Addr + "){ps1:<*>(" + v3Addr + ")}}}" v3s5 := "{ps2:(*" + v3t2 + "){ps3:(*" + v3t3 + "){ps1:(*" + v3t + "){ps2:(*" + v3t2 + ")}}}}" v3s6 := "{ps2:(*" + v3t2 + "){ps3:(*" + v3t3 + "){ps1:(*" + v3t + ")}}}" v3s7 := "{ps2:(*" + v3t2 + ")(" + tic2Addr + "){ps3:(*" + v3t3 + ")(" + tic3Addr + "){ps1:(*" + v3t + ")(" + v3Addr + "){ps2:(*" + v3t2 + ")(" + tic2Addr + ")}}}}" v3s8 := "{ps2:(*" + v3t2 + ")(" + tic2Addr + "){ps3:(*" + v3t3 + ")(" + tic3Addr + "){ps1:(*" + v3t + ")(" + v3Addr + ")}}}" addFormatterTest("%v", v3, v3s) addFormatterTest("%v", pv3, "<*>"+v3s2) addFormatterTest("%v", &pv3, "<**>"+v3s2) addFormatterTest("%+v", v3, v3s3) addFormatterTest("%+v", pv3, "<*>("+v3Addr+")"+v3s4) addFormatterTest("%+v", &pv3, "<**>("+pv3Addr+"->"+v3Addr+")"+v3s4) addFormatterTest("%#v", v3, "("+v3t+")"+v3s5) addFormatterTest("%#v", pv3, "(*"+v3t+")"+v3s6) addFormatterTest("%#v", &pv3, "(**"+v3t+")"+v3s6) addFormatterTest("%#+v", v3, "("+v3t+")"+v3s7) addFormatterTest("%#+v", pv3, "(*"+v3t+")("+v3Addr+")"+v3s8) addFormatterTest("%#+v", &pv3, "(**"+v3t+")("+pv3Addr+"->"+v3Addr+")"+v3s8) } func addPanicFormatterTests() { // Type that panics in its Stringer interface. v := panicer(127) nv := (*panicer)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "spew_test.panicer" vs := "(PANIC=test panic)127" addFormatterTest("%v", v, vs) addFormatterTest("%v", pv, "<*>"+vs) addFormatterTest("%v", &pv, "<**>"+vs) addFormatterTest("%v", nv, "") addFormatterTest("%+v", v, vs) addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%#v", v, "("+vt+")"+vs) addFormatterTest("%#v", pv, "(*"+vt+")"+vs) addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) addFormatterTest("%#v", nv, "(*"+vt+")"+"") addFormatterTest("%#+v", v, "("+vt+")"+vs) addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%#+v", nv, "(*"+vt+")"+"") } func addErrorFormatterTests() { // Type that has a custom Error interface. v := customError(127) nv := (*customError)(nil) pv := &v vAddr := fmt.Sprintf("%p", pv) pvAddr := fmt.Sprintf("%p", &pv) vt := "spew_test.customError" vs := "error: 127" addFormatterTest("%v", v, vs) addFormatterTest("%v", pv, "<*>"+vs) addFormatterTest("%v", &pv, "<**>"+vs) addFormatterTest("%v", nv, "") addFormatterTest("%+v", v, vs) addFormatterTest("%+v", pv, "<*>("+vAddr+")"+vs) addFormatterTest("%+v", &pv, "<**>("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%+v", nv, "") addFormatterTest("%#v", v, "("+vt+")"+vs) addFormatterTest("%#v", pv, "(*"+vt+")"+vs) addFormatterTest("%#v", &pv, "(**"+vt+")"+vs) addFormatterTest("%#v", nv, "(*"+vt+")"+"") addFormatterTest("%#+v", v, "("+vt+")"+vs) addFormatterTest("%#+v", pv, "(*"+vt+")("+vAddr+")"+vs) addFormatterTest("%#+v", &pv, "(**"+vt+")("+pvAddr+"->"+vAddr+")"+vs) addFormatterTest("%#+v", nv, "(*"+vt+")"+"") } func addPassthroughFormatterTests() { // %x passthrough with uint. v := uint(4294967295) pv := &v vAddr := fmt.Sprintf("%x", pv) pvAddr := fmt.Sprintf("%x", &pv) vs := "ffffffff" addFormatterTest("%x", v, vs) addFormatterTest("%x", pv, vAddr) addFormatterTest("%x", &pv, pvAddr) // %#x passthrough with uint. v2 := int(2147483647) pv2 := &v2 v2Addr := fmt.Sprintf("%#x", pv2) pv2Addr := fmt.Sprintf("%#x", &pv2) v2s := "0x7fffffff" addFormatterTest("%#x", v2, v2s) addFormatterTest("%#x", pv2, v2Addr) addFormatterTest("%#x", &pv2, pv2Addr) // %f passthrough with precision. addFormatterTest("%.2f", 3.1415, "3.14") addFormatterTest("%.3f", 3.1415, "3.142") addFormatterTest("%.4f", 3.1415, "3.1415") // %f passthrough with width and precision. addFormatterTest("%5.2f", 3.1415, " 3.14") addFormatterTest("%6.3f", 3.1415, " 3.142") addFormatterTest("%7.4f", 3.1415, " 3.1415") // %d passthrough with width. addFormatterTest("%3d", 127, "127") addFormatterTest("%4d", 127, " 127") addFormatterTest("%5d", 127, " 127") // %q passthrough with string. addFormatterTest("%q", "test", "\"test\"") } // TestFormatter executes all of the tests described by formatterTests. func TestFormatter(t *testing.T) { // Setup tests. addIntFormatterTests() addUintFormatterTests() addBoolFormatterTests() addFloatFormatterTests() addComplexFormatterTests() addArrayFormatterTests() addSliceFormatterTests() addStringFormatterTests() addInterfaceFormatterTests() addMapFormatterTests() addStructFormatterTests() addUintptrFormatterTests() addUnsafePointerFormatterTests() addChanFormatterTests() addFuncFormatterTests() addCircularFormatterTests() addPanicFormatterTests() addErrorFormatterTests() addPassthroughFormatterTests() t.Logf("Running %d tests", len(formatterTests)) for i, test := range formatterTests { buf := new(bytes.Buffer) spew.Fprintf(buf, test.format, test.in) s := buf.String() if testFailed(s, test.wants) { t.Errorf("Formatter #%d format: %s got: %s %s", i, test.format, s, stringizeWants(test.wants)) continue } } } type testStruct struct { x int } func (ts testStruct) String() string { return fmt.Sprintf("ts.%d", ts.x) } type testStructP struct { x int } func (ts *testStructP) String() string { return fmt.Sprintf("ts.%d", ts.x) } func TestPrintSortedKeys(t *testing.T) { cfg := spew.ConfigState{SortKeys: true} s := cfg.Sprint(map[int]string{1: "1", 3: "3", 2: "2"}) expected := "map[1:1 2:2 3:3]" if s != expected { t.Errorf("Sorted keys mismatch 1:\n %v %v", s, expected) } s = cfg.Sprint(map[stringer]int{"1": 1, "3": 3, "2": 2}) expected = "map[stringer 1:1 stringer 2:2 stringer 3:3]" if s != expected { t.Errorf("Sorted keys mismatch 2:\n %v %v", s, expected) } s = cfg.Sprint(map[pstringer]int{pstringer("1"): 1, pstringer("3"): 3, pstringer("2"): 2}) expected = "map[stringer 1:1 stringer 2:2 stringer 3:3]" if spew.UnsafeDisabled { expected = "map[1:1 2:2 3:3]" } if s != expected { t.Errorf("Sorted keys mismatch 3:\n %v %v", s, expected) } s = cfg.Sprint(map[testStruct]int{{1}: 1, {3}: 3, {2}: 2}) expected = "map[ts.1:1 ts.2:2 ts.3:3]" if s != expected { t.Errorf("Sorted keys mismatch 4:\n %v %v", s, expected) } if !spew.UnsafeDisabled { s = cfg.Sprint(map[testStructP]int{{1}: 1, {3}: 3, {2}: 2}) expected = "map[ts.1:1 ts.2:2 ts.3:3]" if s != expected { t.Errorf("Sorted keys mismatch 5:\n %v %v", s, expected) } } s = cfg.Sprint(map[customError]int{customError(1): 1, customError(3): 3, customError(2): 2}) expected = "map[error: 1:1 error: 2:2 error: 3:3]" if s != expected { t.Errorf("Sorted keys mismatch 6:\n %v %v", s, expected) } } ================================================ FILE: internal/spew/internal_test.go ================================================ /* * Copyright (c) 2013-2016 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ /* This test file is part of the spew package rather than the spew_test package because it needs access to internals to properly test certain cases which are not possible via the public interface since they should never happen. */ package spew import ( "bytes" "reflect" "testing" ) // dummyFmtState implements a fake fmt.State to use for testing invalid // reflect.Value handling. This is necessary because the fmt package catches // invalid values before invoking the formatter on them. type dummyFmtState struct { bytes.Buffer } func (dfs *dummyFmtState) Flag(f int) bool { return f == int('+') } func (dfs *dummyFmtState) Precision() (int, bool) { return 0, false } func (dfs *dummyFmtState) Width() (int, bool) { return 0, false } // TestInvalidReflectValue ensures the dump and formatter code handles an // invalid reflect value properly. This needs access to internal state since it // should never happen in real code and therefore can't be tested via the public // API. func TestInvalidReflectValue(t *testing.T) { i := 1 // Dump invalid reflect value. v := new(reflect.Value) buf := new(bytes.Buffer) d := dumpState{w: buf, cs: &Config} d.dump(*v) s := buf.String() want := "" if s != want { t.Errorf("InvalidReflectValue #%d\n got: %s want: %s", i, s, want) } i++ // Formatter invalid reflect value. buf2 := new(dummyFmtState) f := formatState{value: *v, cs: &Config, fs: buf2} f.format(*v) s = buf2.String() want = "" if s != want { t.Errorf("InvalidReflectValue #%d got: %s want: %s", i, s, want) } } // SortValues makes the internal sortValues function available to the test // package. func SortValues(values []reflect.Value, cs *ConfigState) { sortValues(values, cs) } ================================================ FILE: internal/spew/internalunsafe_test.go ================================================ // Copyright (c) 2013-2016 Dave Collins // Permission to use, copy, modify, and distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // NOTE: Due to the following build constraints, this file will only be compiled // when the code is not running on Google App Engine, compiled by GopherJS, and // "-tags safe" is not added to the go build command line. The "disableunsafe" // tag is deprecated and thus should not be used. //go:build !js && !appengine && !safe && !disableunsafe && go1.4 // +build !js,!appengine,!safe,!disableunsafe,go1.4 /* This test file is part of the spew package rather than the spew_test package because it needs access to internals to properly test certain cases which are not possible via the public interface since they should never happen. */ package spew import ( "bytes" "reflect" "testing" ) // changeKind uses unsafe to intentionally change the kind of a reflect.Value to // the maximum kind value which does not exist. This is needed to test the // fallback code which punts to the standard fmt library for new types that // might get added to the language. func changeKind(v *reflect.Value, readOnly bool) { flags := flagField(v) if readOnly { *flags |= flagRO } else { *flags &^= flagRO } *flags |= flagKindMask } // TestAddedReflectValue tests functionality of the dump and formatter code which // falls back to the standard fmt library for new types that might get added to // the language. func TestAddedReflectValue(t *testing.T) { i := 1 // Dump using a reflect.Value that is exported. v := reflect.ValueOf(int8(5)) changeKind(&v, false) buf := new(bytes.Buffer) d := dumpState{w: buf, cs: &Config} d.dump(v) s := buf.String() want := "(int8) 5" if s != want { t.Errorf("TestAddedReflectValue #%d\n got: %s want: %s", i, s, want) } i++ // Dump using a reflect.Value that is not exported. changeKind(&v, true) buf.Reset() d.dump(v) s = buf.String() want = "(int8) " if s != want { t.Errorf("TestAddedReflectValue #%d\n got: %s want: %s", i, s, want) } i++ // Formatter using a reflect.Value that is exported. changeKind(&v, false) buf2 := new(dummyFmtState) f := formatState{value: v, cs: &Config, fs: buf2} f.format(v) s = buf2.String() want = "5" if s != want { t.Errorf("TestAddedReflectValue #%d got: %s want: %s", i, s, want) } i++ // Formatter using a reflect.Value that is not exported. changeKind(&v, true) buf2.Reset() f = formatState{value: v, cs: &Config, fs: buf2} f.format(v) s = buf2.String() want = "" if s != want { t.Errorf("TestAddedReflectValue #%d got: %s want: %s", i, s, want) } } ================================================ FILE: internal/spew/spew.go ================================================ /* * Copyright (c) 2013-2016 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ package spew import ( "fmt" "io" ) // Errorf is a wrapper for fmt.Errorf that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the formatted string as a value that satisfies error. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Errorf(format, spew.NewFormatter(a), spew.NewFormatter(b)) func Errorf(format string, a ...interface{}) (err error) { return fmt.Errorf(format, convertArgs(a)...) } // Fprint is a wrapper for fmt.Fprint that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Fprint(w, spew.NewFormatter(a), spew.NewFormatter(b)) func Fprint(w io.Writer, a ...interface{}) (n int, err error) { return fmt.Fprint(w, convertArgs(a)...) } // Fprintf is a wrapper for fmt.Fprintf that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Fprintf(w, format, spew.NewFormatter(a), spew.NewFormatter(b)) func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) { return fmt.Fprintf(w, format, convertArgs(a)...) } // Fprintln is a wrapper for fmt.Fprintln that treats each argument as if it // passed with a default Formatter interface returned by NewFormatter. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Fprintln(w, spew.NewFormatter(a), spew.NewFormatter(b)) func Fprintln(w io.Writer, a ...interface{}) (n int, err error) { return fmt.Fprintln(w, convertArgs(a)...) } // Print is a wrapper for fmt.Print that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Print(spew.NewFormatter(a), spew.NewFormatter(b)) func Print(a ...interface{}) (n int, err error) { return fmt.Print(convertArgs(a)...) } // Printf is a wrapper for fmt.Printf that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Printf(format, spew.NewFormatter(a), spew.NewFormatter(b)) func Printf(format string, a ...interface{}) (n int, err error) { return fmt.Printf(format, convertArgs(a)...) } // Println is a wrapper for fmt.Println that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the number of bytes written and any write error encountered. See // NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Println(spew.NewFormatter(a), spew.NewFormatter(b)) func Println(a ...interface{}) (n int, err error) { return fmt.Println(convertArgs(a)...) } // Sprint is a wrapper for fmt.Sprint that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the resulting string. See NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Sprint(spew.NewFormatter(a), spew.NewFormatter(b)) func Sprint(a ...interface{}) string { return fmt.Sprint(convertArgs(a)...) } // Sprintf is a wrapper for fmt.Sprintf that treats each argument as if it were // passed with a default Formatter interface returned by NewFormatter. It // returns the resulting string. See NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Sprintf(format, spew.NewFormatter(a), spew.NewFormatter(b)) func Sprintf(format string, a ...interface{}) string { return fmt.Sprintf(format, convertArgs(a)...) } // Sprintln is a wrapper for fmt.Sprintln that treats each argument as if it // were passed with a default Formatter interface returned by NewFormatter. It // returns the resulting string. See NewFormatter for formatting details. // // This function is shorthand for the following syntax: // // fmt.Sprintln(spew.NewFormatter(a), spew.NewFormatter(b)) func Sprintln(a ...interface{}) string { return fmt.Sprintln(convertArgs(a)...) } // convertArgs accepts a slice of arguments and returns a slice of the same // length with each argument converted to a default spew Formatter interface. func convertArgs(args []interface{}) (formatters []interface{}) { formatters = make([]interface{}, len(args)) for index, arg := range args { formatters[index] = NewFormatter(arg) } return formatters } ================================================ FILE: internal/spew/spew_test.go ================================================ /* * Copyright (c) 2013-2016 Dave Collins * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ package spew_test import ( "bytes" "fmt" "io/ioutil" "os" "testing" "github.com/expr-lang/expr/internal/spew" ) // spewFunc is used to identify which public function of the spew package or // ConfigState a test applies to. type spewFunc int const ( fCSFdump spewFunc = iota fCSFprint fCSFprintf fCSFprintln fCSPrint fCSPrintln fCSSdump fCSSprint fCSSprintf fCSSprintln fCSErrorf fCSNewFormatter fErrorf fFprint fFprintln fPrint fPrintln fSdump fSprint fSprintf fSprintln ) // Map of spewFunc values to names for pretty printing. var spewFuncStrings = map[spewFunc]string{ fCSFdump: "ConfigState.Fdump", fCSFprint: "ConfigState.Fprint", fCSFprintf: "ConfigState.Fprintf", fCSFprintln: "ConfigState.Fprintln", fCSSdump: "ConfigState.Sdump", fCSPrint: "ConfigState.Print", fCSPrintln: "ConfigState.Println", fCSSprint: "ConfigState.Sprint", fCSSprintf: "ConfigState.Sprintf", fCSSprintln: "ConfigState.Sprintln", fCSErrorf: "ConfigState.Errorf", fCSNewFormatter: "ConfigState.NewFormatter", fErrorf: "spew.Errorf", fFprint: "spew.Fprint", fFprintln: "spew.Fprintln", fPrint: "spew.Print", fPrintln: "spew.Println", fSdump: "spew.Sdump", fSprint: "spew.Sprint", fSprintf: "spew.Sprintf", fSprintln: "spew.Sprintln", } func (f spewFunc) String() string { if s, ok := spewFuncStrings[f]; ok { return s } return fmt.Sprintf("Unknown spewFunc (%d)", int(f)) } // spewTest is used to describe a test to be performed against the public // functions of the spew package or ConfigState. type spewTest struct { cs *spew.ConfigState f spewFunc format string in interface{} want string } // spewTests houses the tests to be performed against the public functions of // the spew package and ConfigState. // // These tests are only intended to ensure the public functions are exercised // and are intentionally not exhaustive of types. The exhaustive type // tests are handled in the dump and format tests. var spewTests []spewTest // redirStdout is a helper function to return the standard output from f as a // byte slice. func redirStdout(f func()) ([]byte, error) { tempFile, err := ioutil.TempFile("", "ss-test") if err != nil { return nil, err } fileName := tempFile.Name() defer os.Remove(fileName) // Ignore error origStdout := os.Stdout os.Stdout = tempFile f() os.Stdout = origStdout tempFile.Close() return ioutil.ReadFile(fileName) } func initSpewTests() { // Config states with various settings. scsDefault := spew.NewDefaultConfig() scsNoMethods := &spew.ConfigState{Indent: " ", DisableMethods: true} scsNoPmethods := &spew.ConfigState{Indent: " ", DisablePointerMethods: true} scsMaxDepth := &spew.ConfigState{Indent: " ", MaxDepth: 1} scsContinue := &spew.ConfigState{Indent: " ", ContinueOnMethod: true} scsNoPtrAddr := &spew.ConfigState{DisablePointerAddresses: true} scsNoCap := &spew.ConfigState{DisableCapacities: true} // Variables for tests on types which implement Stringer interface with and // without a pointer receiver. ts := stringer("test") tps := pstringer("test") type ptrTester struct { s *struct{} } tptr := &ptrTester{s: &struct{}{}} // depthTester is used to test max depth handling for structs, array, slices // and maps. type depthTester struct { ic indirCir1 arr [1]string slice []string m map[string]int } dt := depthTester{indirCir1{nil}, [1]string{"arr"}, []string{"slice"}, map[string]int{"one": 1}} // Variable for tests on types which implement error interface. te := customError(10) spewTests = []spewTest{ {scsDefault, fCSFdump, "", int8(127), "(int8) 127\n"}, {scsDefault, fCSFprint, "", int16(32767), "32767"}, {scsDefault, fCSFprintf, "%v", int32(2147483647), "2147483647"}, {scsDefault, fCSFprintln, "", int(2147483647), "2147483647\n"}, {scsDefault, fCSPrint, "", int64(9223372036854775807), "9223372036854775807"}, {scsDefault, fCSPrintln, "", uint8(255), "255\n"}, {scsDefault, fCSSdump, "", uint8(64), "(uint8) 64\n"}, {scsDefault, fCSSprint, "", complex(1, 2), "(1+2i)"}, {scsDefault, fCSSprintf, "%v", complex(float32(3), 4), "(3+4i)"}, {scsDefault, fCSSprintln, "", complex(float64(5), 6), "(5+6i)\n"}, {scsDefault, fCSErrorf, "%#v", uint16(65535), "(uint16)65535"}, {scsDefault, fCSNewFormatter, "%v", uint32(4294967295), "4294967295"}, {scsDefault, fErrorf, "%v", uint64(18446744073709551615), "18446744073709551615"}, {scsDefault, fFprint, "", float32(3.14), "3.14"}, {scsDefault, fFprintln, "", float64(6.28), "6.28\n"}, {scsDefault, fPrint, "", true, "true"}, {scsDefault, fPrintln, "", false, "false\n"}, {scsDefault, fSdump, "", complex(-10, -20), "(complex128) (-10-20i)\n"}, {scsDefault, fSprint, "", complex(-1, -2), "(-1-2i)"}, {scsDefault, fSprintf, "%v", complex(float32(-3), -4), "(-3-4i)"}, {scsDefault, fSprintln, "", complex(float64(-5), -6), "(-5-6i)\n"}, {scsNoMethods, fCSFprint, "", ts, "test"}, {scsNoMethods, fCSFprint, "", &ts, "<*>test"}, {scsNoMethods, fCSFprint, "", tps, "test"}, {scsNoMethods, fCSFprint, "", &tps, "<*>test"}, {scsNoPmethods, fCSFprint, "", ts, "stringer test"}, {scsNoPmethods, fCSFprint, "", &ts, "<*>stringer test"}, {scsNoPmethods, fCSFprint, "", tps, "test"}, {scsNoPmethods, fCSFprint, "", &tps, "<*>stringer test"}, {scsMaxDepth, fCSFprint, "", dt, "{{} [] [] map[]}"}, {scsMaxDepth, fCSFdump, "", dt, "(spew_test.depthTester) {\n" + " ic: (spew_test.indirCir1) {\n \n },\n" + " arr: ([1]string) (len=1 cap=1) {\n \n },\n" + " slice: ([]string) (len=1 cap=1) {\n \n },\n" + " m: (map[string]int) (len=1) {\n \n }\n}\n"}, {scsContinue, fCSFprint, "", ts, "(stringer test) test"}, {scsContinue, fCSFdump, "", ts, "(spew_test.stringer) " + "(len=4) (stringer test) \"test\"\n"}, {scsContinue, fCSFprint, "", te, "(error: 10) 10"}, {scsContinue, fCSFdump, "", te, "(spew_test.customError) " + "(error: 10) 10\n"}, {scsNoPtrAddr, fCSFprint, "", tptr, "<*>{<*>{}}"}, {scsNoPtrAddr, fCSSdump, "", tptr, "(*spew_test.ptrTester)({\ns: (*struct {})({\n})\n})\n"}, {scsNoCap, fCSSdump, "", make([]string, 0, 10), "([]string) {\n}\n"}, {scsNoCap, fCSSdump, "", make([]string, 1, 10), "([]string) (len=1) {\n(string) \"\"\n}\n"}, } } // TestSpew executes all of the tests described by spewTests. func TestSpew(t *testing.T) { initSpewTests() t.Logf("Running %d tests", len(spewTests)) for i, test := range spewTests { buf := new(bytes.Buffer) switch test.f { case fCSFdump: test.cs.Fdump(buf, test.in) case fCSFprint: test.cs.Fprint(buf, test.in) case fCSFprintf: test.cs.Fprintf(buf, test.format, test.in) case fCSFprintln: test.cs.Fprintln(buf, test.in) case fCSPrint: b, err := redirStdout(func() { test.cs.Print(test.in) }) if err != nil { t.Errorf("%v #%d %v", test.f, i, err) continue } buf.Write(b) case fCSPrintln: b, err := redirStdout(func() { test.cs.Println(test.in) }) if err != nil { t.Errorf("%v #%d %v", test.f, i, err) continue } buf.Write(b) case fCSSdump: str := test.cs.Sdump(test.in) buf.WriteString(str) case fCSSprint: str := test.cs.Sprint(test.in) buf.WriteString(str) case fCSSprintf: str := test.cs.Sprintf(test.format, test.in) buf.WriteString(str) case fCSSprintln: str := test.cs.Sprintln(test.in) buf.WriteString(str) case fCSErrorf: err := test.cs.Errorf(test.format, test.in) buf.WriteString(err.Error()) case fCSNewFormatter: fmt.Fprintf(buf, test.format, test.cs.NewFormatter(test.in)) case fErrorf: err := spew.Errorf(test.format, test.in) buf.WriteString(err.Error()) case fFprint: spew.Fprint(buf, test.in) case fFprintln: spew.Fprintln(buf, test.in) case fPrint: b, err := redirStdout(func() { spew.Print(test.in) }) if err != nil { t.Errorf("%v #%d %v", test.f, i, err) continue } buf.Write(b) case fPrintln: b, err := redirStdout(func() { spew.Println(test.in) }) if err != nil { t.Errorf("%v #%d %v", test.f, i, err) continue } buf.Write(b) case fSdump: str := spew.Sdump(test.in) buf.WriteString(str) case fSprint: str := spew.Sprint(test.in) buf.WriteString(str) case fSprintf: str := spew.Sprintf(test.format, test.in) buf.WriteString(str) case fSprintln: str := spew.Sprintln(test.in) buf.WriteString(str) default: t.Errorf("%v #%d unrecognized function", test.f, i) continue } s := buf.String() if test.want != s { t.Errorf("ConfigState #%d\n got: %s want: %s", i, s, test.want) continue } } } ================================================ FILE: internal/spew/testdata/dumpcgo.go ================================================ // Copyright (c) 2013 Dave Collins // // Permission to use, copy, modify, and distribute this software for any // purpose with or without fee is hereby granted, provided that the above // copyright notice and this permission notice appear in all copies. // // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN // ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF // OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. // NOTE: Due to the following build constraints, this file will only be compiled // when both cgo is supported and "-tags testcgo" is added to the go test // command line. This code should really only be in the dumpcgo_test.go file, // but unfortunately Go will not allow cgo in test files, so this is a // workaround to allow cgo types to be tested. This configuration is used // because spew itself does not require cgo to run even though it does handle // certain cgo types specially. Rather than forcing all clients to require cgo // and an external C compiler just to run the tests, this scheme makes them // optional. //go:build cgo && testcgo // +build cgo,testcgo package testdata /* #include typedef unsigned char custom_uchar_t; char *ncp = 0; char *cp = "test"; char ca[6] = {'t', 'e', 's', 't', '2', '\0'}; unsigned char uca[6] = {'t', 'e', 's', 't', '3', '\0'}; signed char sca[6] = {'t', 'e', 's', 't', '4', '\0'}; uint8_t ui8ta[6] = {'t', 'e', 's', 't', '5', '\0'}; custom_uchar_t tuca[6] = {'t', 'e', 's', 't', '6', '\0'}; */ import "C" // GetCgoNullCharPointer returns a null char pointer via cgo. This is only // used for tests. func GetCgoNullCharPointer() interface{} { return C.ncp } // GetCgoCharPointer returns a char pointer via cgo. This is only used for // tests. func GetCgoCharPointer() interface{} { return C.cp } // GetCgoCharArray returns a char array via cgo and the array's len and cap. // This is only used for tests. func GetCgoCharArray() (interface{}, int, int) { return C.ca, len(C.ca), cap(C.ca) } // GetCgoUnsignedCharArray returns an unsigned char array via cgo and the // array's len and cap. This is only used for tests. func GetCgoUnsignedCharArray() (interface{}, int, int) { return C.uca, len(C.uca), cap(C.uca) } // GetCgoSignedCharArray returns a signed char array via cgo and the array's len // and cap. This is only used for tests. func GetCgoSignedCharArray() (interface{}, int, int) { return C.sca, len(C.sca), cap(C.sca) } // GetCgoUint8tArray returns a uint8_t array via cgo and the array's len and // cap. This is only used for tests. func GetCgoUint8tArray() (interface{}, int, int) { return C.ui8ta, len(C.ui8ta), cap(C.ui8ta) } // GetCgoTypedefedUnsignedCharArray returns a typedefed unsigned char array via // cgo and the array's len and cap. This is only used for tests. func GetCgoTypedefedUnsignedCharArray() (interface{}, int, int) { return C.tuca, len(C.tuca), cap(C.tuca) } ================================================ FILE: internal/testify/assert/assertion_compare.go ================================================ package assert import ( "bytes" "fmt" "reflect" "time" ) // Deprecated: CompareType has only ever been for internal use and has accidentally been published since v1.6.0. Do not use it. type CompareType = compareResult type compareResult int const ( compareLess compareResult = iota - 1 compareEqual compareGreater ) var ( intType = reflect.TypeOf(int(1)) int8Type = reflect.TypeOf(int8(1)) int16Type = reflect.TypeOf(int16(1)) int32Type = reflect.TypeOf(int32(1)) int64Type = reflect.TypeOf(int64(1)) uintType = reflect.TypeOf(uint(1)) uint8Type = reflect.TypeOf(uint8(1)) uint16Type = reflect.TypeOf(uint16(1)) uint32Type = reflect.TypeOf(uint32(1)) uint64Type = reflect.TypeOf(uint64(1)) uintptrType = reflect.TypeOf(uintptr(1)) float32Type = reflect.TypeOf(float32(1)) float64Type = reflect.TypeOf(float64(1)) stringType = reflect.TypeOf("") timeType = reflect.TypeOf(time.Time{}) bytesType = reflect.TypeOf([]byte{}) ) func compare(obj1, obj2 interface{}, kind reflect.Kind) (compareResult, bool) { obj1Value := reflect.ValueOf(obj1) obj2Value := reflect.ValueOf(obj2) // throughout this switch we try and avoid calling .Convert() if possible, // as this has a pretty big performance impact switch kind { case reflect.Int: { intobj1, ok := obj1.(int) if !ok { intobj1 = obj1Value.Convert(intType).Interface().(int) } intobj2, ok := obj2.(int) if !ok { intobj2 = obj2Value.Convert(intType).Interface().(int) } if intobj1 > intobj2 { return compareGreater, true } if intobj1 == intobj2 { return compareEqual, true } if intobj1 < intobj2 { return compareLess, true } } case reflect.Int8: { int8obj1, ok := obj1.(int8) if !ok { int8obj1 = obj1Value.Convert(int8Type).Interface().(int8) } int8obj2, ok := obj2.(int8) if !ok { int8obj2 = obj2Value.Convert(int8Type).Interface().(int8) } if int8obj1 > int8obj2 { return compareGreater, true } if int8obj1 == int8obj2 { return compareEqual, true } if int8obj1 < int8obj2 { return compareLess, true } } case reflect.Int16: { int16obj1, ok := obj1.(int16) if !ok { int16obj1 = obj1Value.Convert(int16Type).Interface().(int16) } int16obj2, ok := obj2.(int16) if !ok { int16obj2 = obj2Value.Convert(int16Type).Interface().(int16) } if int16obj1 > int16obj2 { return compareGreater, true } if int16obj1 == int16obj2 { return compareEqual, true } if int16obj1 < int16obj2 { return compareLess, true } } case reflect.Int32: { int32obj1, ok := obj1.(int32) if !ok { int32obj1 = obj1Value.Convert(int32Type).Interface().(int32) } int32obj2, ok := obj2.(int32) if !ok { int32obj2 = obj2Value.Convert(int32Type).Interface().(int32) } if int32obj1 > int32obj2 { return compareGreater, true } if int32obj1 == int32obj2 { return compareEqual, true } if int32obj1 < int32obj2 { return compareLess, true } } case reflect.Int64: { int64obj1, ok := obj1.(int64) if !ok { int64obj1 = obj1Value.Convert(int64Type).Interface().(int64) } int64obj2, ok := obj2.(int64) if !ok { int64obj2 = obj2Value.Convert(int64Type).Interface().(int64) } if int64obj1 > int64obj2 { return compareGreater, true } if int64obj1 == int64obj2 { return compareEqual, true } if int64obj1 < int64obj2 { return compareLess, true } } case reflect.Uint: { uintobj1, ok := obj1.(uint) if !ok { uintobj1 = obj1Value.Convert(uintType).Interface().(uint) } uintobj2, ok := obj2.(uint) if !ok { uintobj2 = obj2Value.Convert(uintType).Interface().(uint) } if uintobj1 > uintobj2 { return compareGreater, true } if uintobj1 == uintobj2 { return compareEqual, true } if uintobj1 < uintobj2 { return compareLess, true } } case reflect.Uint8: { uint8obj1, ok := obj1.(uint8) if !ok { uint8obj1 = obj1Value.Convert(uint8Type).Interface().(uint8) } uint8obj2, ok := obj2.(uint8) if !ok { uint8obj2 = obj2Value.Convert(uint8Type).Interface().(uint8) } if uint8obj1 > uint8obj2 { return compareGreater, true } if uint8obj1 == uint8obj2 { return compareEqual, true } if uint8obj1 < uint8obj2 { return compareLess, true } } case reflect.Uint16: { uint16obj1, ok := obj1.(uint16) if !ok { uint16obj1 = obj1Value.Convert(uint16Type).Interface().(uint16) } uint16obj2, ok := obj2.(uint16) if !ok { uint16obj2 = obj2Value.Convert(uint16Type).Interface().(uint16) } if uint16obj1 > uint16obj2 { return compareGreater, true } if uint16obj1 == uint16obj2 { return compareEqual, true } if uint16obj1 < uint16obj2 { return compareLess, true } } case reflect.Uint32: { uint32obj1, ok := obj1.(uint32) if !ok { uint32obj1 = obj1Value.Convert(uint32Type).Interface().(uint32) } uint32obj2, ok := obj2.(uint32) if !ok { uint32obj2 = obj2Value.Convert(uint32Type).Interface().(uint32) } if uint32obj1 > uint32obj2 { return compareGreater, true } if uint32obj1 == uint32obj2 { return compareEqual, true } if uint32obj1 < uint32obj2 { return compareLess, true } } case reflect.Uint64: { uint64obj1, ok := obj1.(uint64) if !ok { uint64obj1 = obj1Value.Convert(uint64Type).Interface().(uint64) } uint64obj2, ok := obj2.(uint64) if !ok { uint64obj2 = obj2Value.Convert(uint64Type).Interface().(uint64) } if uint64obj1 > uint64obj2 { return compareGreater, true } if uint64obj1 == uint64obj2 { return compareEqual, true } if uint64obj1 < uint64obj2 { return compareLess, true } } case reflect.Float32: { float32obj1, ok := obj1.(float32) if !ok { float32obj1 = obj1Value.Convert(float32Type).Interface().(float32) } float32obj2, ok := obj2.(float32) if !ok { float32obj2 = obj2Value.Convert(float32Type).Interface().(float32) } if float32obj1 > float32obj2 { return compareGreater, true } if float32obj1 == float32obj2 { return compareEqual, true } if float32obj1 < float32obj2 { return compareLess, true } } case reflect.Float64: { float64obj1, ok := obj1.(float64) if !ok { float64obj1 = obj1Value.Convert(float64Type).Interface().(float64) } float64obj2, ok := obj2.(float64) if !ok { float64obj2 = obj2Value.Convert(float64Type).Interface().(float64) } if float64obj1 > float64obj2 { return compareGreater, true } if float64obj1 == float64obj2 { return compareEqual, true } if float64obj1 < float64obj2 { return compareLess, true } } case reflect.String: { stringobj1, ok := obj1.(string) if !ok { stringobj1 = obj1Value.Convert(stringType).Interface().(string) } stringobj2, ok := obj2.(string) if !ok { stringobj2 = obj2Value.Convert(stringType).Interface().(string) } if stringobj1 > stringobj2 { return compareGreater, true } if stringobj1 == stringobj2 { return compareEqual, true } if stringobj1 < stringobj2 { return compareLess, true } } // Check for known struct types we can check for compare results. case reflect.Struct: { // All structs enter here. We're not interested in most types. if !obj1Value.CanConvert(timeType) { break } // time.Time can be compared! timeObj1, ok := obj1.(time.Time) if !ok { timeObj1 = obj1Value.Convert(timeType).Interface().(time.Time) } timeObj2, ok := obj2.(time.Time) if !ok { timeObj2 = obj2Value.Convert(timeType).Interface().(time.Time) } if timeObj1.Before(timeObj2) { return compareLess, true } if timeObj1.Equal(timeObj2) { return compareEqual, true } return compareGreater, true } case reflect.Slice: { // We only care about the []byte type. if !obj1Value.CanConvert(bytesType) { break } // []byte can be compared! bytesObj1, ok := obj1.([]byte) if !ok { bytesObj1 = obj1Value.Convert(bytesType).Interface().([]byte) } bytesObj2, ok := obj2.([]byte) if !ok { bytesObj2 = obj2Value.Convert(bytesType).Interface().([]byte) } return compareResult(bytes.Compare(bytesObj1, bytesObj2)), true } case reflect.Uintptr: { uintptrObj1, ok := obj1.(uintptr) if !ok { uintptrObj1 = obj1Value.Convert(uintptrType).Interface().(uintptr) } uintptrObj2, ok := obj2.(uintptr) if !ok { uintptrObj2 = obj2Value.Convert(uintptrType).Interface().(uintptr) } if uintptrObj1 > uintptrObj2 { return compareGreater, true } if uintptrObj1 == uintptrObj2 { return compareEqual, true } if uintptrObj1 < uintptrObj2 { return compareLess, true } } } return compareEqual, false } // Greater asserts that the first element is greater than the second // // assert.Greater(t, 2, 1) // assert.Greater(t, float64(2), float64(1)) // assert.Greater(t, "b", "a") func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return compareTwoValues(t, e1, e2, []compareResult{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...) } // GreaterOrEqual asserts that the first element is greater than or equal to the second // // assert.GreaterOrEqual(t, 2, 1) // assert.GreaterOrEqual(t, 2, 2) // assert.GreaterOrEqual(t, "b", "a") // assert.GreaterOrEqual(t, "b", "b") func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return compareTwoValues(t, e1, e2, []compareResult{compareGreater, compareEqual}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...) } // Less asserts that the first element is less than the second // // assert.Less(t, 1, 2) // assert.Less(t, float64(1), float64(2)) // assert.Less(t, "a", "b") func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return compareTwoValues(t, e1, e2, []compareResult{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...) } // LessOrEqual asserts that the first element is less than or equal to the second // // assert.LessOrEqual(t, 1, 2) // assert.LessOrEqual(t, 2, 2) // assert.LessOrEqual(t, "a", "b") // assert.LessOrEqual(t, "b", "b") func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return compareTwoValues(t, e1, e2, []compareResult{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...) } // Positive asserts that the specified element is positive // // assert.Positive(t, 1) // assert.Positive(t, 1.23) func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } zero := reflect.Zero(reflect.TypeOf(e)) return compareTwoValues(t, e, zero.Interface(), []compareResult{compareGreater}, "\"%v\" is not positive", msgAndArgs...) } // Negative asserts that the specified element is negative // // assert.Negative(t, -1) // assert.Negative(t, -1.23) func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } zero := reflect.Zero(reflect.TypeOf(e)) return compareTwoValues(t, e, zero.Interface(), []compareResult{compareLess}, "\"%v\" is not negative", msgAndArgs...) } func compareTwoValues(t TestingT, e1 interface{}, e2 interface{}, allowedComparesResults []compareResult, failMessage string, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } e1Kind := reflect.ValueOf(e1).Kind() e2Kind := reflect.ValueOf(e2).Kind() if e1Kind != e2Kind { return Fail(t, "Elements should be the same type", msgAndArgs...) } compareResult, isComparable := compare(e1, e2, e1Kind) if !isComparable { return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...) } if !containsValue(allowedComparesResults, compareResult) { return Fail(t, fmt.Sprintf(failMessage, e1, e2), msgAndArgs...) } return true } func containsValue(values []compareResult, value compareResult) bool { for _, v := range values { if v == value { return true } } return false } ================================================ FILE: internal/testify/assert/assertion_compare_test.go ================================================ package assert import ( "bytes" "fmt" "reflect" "runtime" "testing" "time" ) func TestCompare(t *testing.T) { type customString string type customInt int type customInt8 int8 type customInt16 int16 type customInt32 int32 type customInt64 int64 type customUInt uint type customUInt8 uint8 type customUInt16 uint16 type customUInt32 uint32 type customUInt64 uint64 type customFloat32 float32 type customFloat64 float64 type customUintptr uintptr type customTime time.Time type customBytes []byte for _, currCase := range []struct { less interface{} greater interface{} cType string }{ {less: customString("a"), greater: customString("b"), cType: "string"}, {less: "a", greater: "b", cType: "string"}, {less: customInt(1), greater: customInt(2), cType: "int"}, {less: int(1), greater: int(2), cType: "int"}, {less: customInt8(1), greater: customInt8(2), cType: "int8"}, {less: int8(1), greater: int8(2), cType: "int8"}, {less: customInt16(1), greater: customInt16(2), cType: "int16"}, {less: int16(1), greater: int16(2), cType: "int16"}, {less: customInt32(1), greater: customInt32(2), cType: "int32"}, {less: int32(1), greater: int32(2), cType: "int32"}, {less: customInt64(1), greater: customInt64(2), cType: "int64"}, {less: int64(1), greater: int64(2), cType: "int64"}, {less: customUInt(1), greater: customUInt(2), cType: "uint"}, {less: uint8(1), greater: uint8(2), cType: "uint8"}, {less: customUInt8(1), greater: customUInt8(2), cType: "uint8"}, {less: uint16(1), greater: uint16(2), cType: "uint16"}, {less: customUInt16(1), greater: customUInt16(2), cType: "uint16"}, {less: uint32(1), greater: uint32(2), cType: "uint32"}, {less: customUInt32(1), greater: customUInt32(2), cType: "uint32"}, {less: uint64(1), greater: uint64(2), cType: "uint64"}, {less: customUInt64(1), greater: customUInt64(2), cType: "uint64"}, {less: float32(1.23), greater: float32(2.34), cType: "float32"}, {less: customFloat32(1.23), greater: customFloat32(2.23), cType: "float32"}, {less: float64(1.23), greater: float64(2.34), cType: "float64"}, {less: customFloat64(1.23), greater: customFloat64(2.34), cType: "float64"}, {less: uintptr(1), greater: uintptr(2), cType: "uintptr"}, {less: customUintptr(1), greater: customUintptr(2), cType: "uint64"}, {less: time.Now(), greater: time.Now().Add(time.Hour), cType: "time.Time"}, {less: time.Date(2024, 0, 0, 0, 0, 0, 0, time.Local), greater: time.Date(2263, 0, 0, 0, 0, 0, 0, time.Local), cType: "time.Time"}, {less: customTime(time.Now()), greater: customTime(time.Now().Add(time.Hour)), cType: "time.Time"}, {less: []byte{1, 1}, greater: []byte{1, 2}, cType: "[]byte"}, {less: customBytes([]byte{1, 1}), greater: customBytes([]byte{1, 2}), cType: "[]byte"}, } { resLess, isComparable := compare(currCase.less, currCase.greater, reflect.ValueOf(currCase.less).Kind()) if !isComparable { t.Error("object should be comparable for type " + currCase.cType) } if resLess != compareLess { t.Errorf("object less (%v) should be less than greater (%v) for type "+currCase.cType, currCase.less, currCase.greater) } resGreater, isComparable := compare(currCase.greater, currCase.less, reflect.ValueOf(currCase.less).Kind()) if !isComparable { t.Error("object are comparable for type " + currCase.cType) } if resGreater != compareGreater { t.Errorf("object greater should be greater than less for type " + currCase.cType) } resEqual, isComparable := compare(currCase.less, currCase.less, reflect.ValueOf(currCase.less).Kind()) if !isComparable { t.Error("object are comparable for type " + currCase.cType) } if resEqual != 0 { t.Errorf("objects should be equal for type " + currCase.cType) } } } type outputT struct { buf *bytes.Buffer helpers map[string]struct{} } // Implements TestingT func (t *outputT) Errorf(format string, args ...interface{}) { s := fmt.Sprintf(format, args...) t.buf.WriteString(s) } func (t *outputT) Helper() { if t.helpers == nil { t.helpers = make(map[string]struct{}) } t.helpers[callerName(1)] = struct{}{} } // callerName gives the function name (qualified with a package path) // for the caller after skip frames (where 0 means the current function). func callerName(skip int) string { // Make room for the skip PC. var pc [1]uintptr n := runtime.Callers(skip+2, pc[:]) // skip + runtime.Callers + callerName if n == 0 { panic("testing: zero callers found") } frames := runtime.CallersFrames(pc[:n]) frame, _ := frames.Next() return frame.Function } func TestGreater(t *testing.T) { mockT := new(testing.T) if !Greater(mockT, 2, 1) { t.Error("Greater should return true") } if Greater(mockT, 1, 1) { t.Error("Greater should return false") } if Greater(mockT, 1, 2) { t.Error("Greater should return false") } // Check error report for _, currCase := range []struct { less interface{} greater interface{} msg string }{ {less: "a", greater: "b", msg: `"a" is not greater than "b"`}, {less: int(1), greater: int(2), msg: `"1" is not greater than "2"`}, {less: int8(1), greater: int8(2), msg: `"1" is not greater than "2"`}, {less: int16(1), greater: int16(2), msg: `"1" is not greater than "2"`}, {less: int32(1), greater: int32(2), msg: `"1" is not greater than "2"`}, {less: int64(1), greater: int64(2), msg: `"1" is not greater than "2"`}, {less: uint8(1), greater: uint8(2), msg: `"1" is not greater than "2"`}, {less: uint16(1), greater: uint16(2), msg: `"1" is not greater than "2"`}, {less: uint32(1), greater: uint32(2), msg: `"1" is not greater than "2"`}, {less: uint64(1), greater: uint64(2), msg: `"1" is not greater than "2"`}, {less: float32(1.23), greater: float32(2.34), msg: `"1.23" is not greater than "2.34"`}, {less: float64(1.23), greater: float64(2.34), msg: `"1.23" is not greater than "2.34"`}, {less: uintptr(1), greater: uintptr(2), msg: `"1" is not greater than "2"`}, {less: time.Time{}, greater: time.Time{}.Add(time.Hour), msg: `"0001-01-01 00:00:00 +0000 UTC" is not greater than "0001-01-01 01:00:00 +0000 UTC"`}, {less: []byte{1, 1}, greater: []byte{1, 2}, msg: `"[1 1]" is not greater than "[1 2]"`}, } { out := &outputT{buf: bytes.NewBuffer(nil)} False(t, Greater(out, currCase.less, currCase.greater)) Contains(t, out.buf.String(), currCase.msg) Contains(t, out.helpers, "github.com/expr-lang/expr/internal/testify/assert.Greater") } } func TestGreaterOrEqual(t *testing.T) { mockT := new(testing.T) if !GreaterOrEqual(mockT, 2, 1) { t.Error("GreaterOrEqual should return true") } if !GreaterOrEqual(mockT, 1, 1) { t.Error("GreaterOrEqual should return true") } if GreaterOrEqual(mockT, 1, 2) { t.Error("GreaterOrEqual should return false") } // Check error report for _, currCase := range []struct { less interface{} greater interface{} msg string }{ {less: "a", greater: "b", msg: `"a" is not greater than or equal to "b"`}, {less: int(1), greater: int(2), msg: `"1" is not greater than or equal to "2"`}, {less: int8(1), greater: int8(2), msg: `"1" is not greater than or equal to "2"`}, {less: int16(1), greater: int16(2), msg: `"1" is not greater than or equal to "2"`}, {less: int32(1), greater: int32(2), msg: `"1" is not greater than or equal to "2"`}, {less: int64(1), greater: int64(2), msg: `"1" is not greater than or equal to "2"`}, {less: uint8(1), greater: uint8(2), msg: `"1" is not greater than or equal to "2"`}, {less: uint16(1), greater: uint16(2), msg: `"1" is not greater than or equal to "2"`}, {less: uint32(1), greater: uint32(2), msg: `"1" is not greater than or equal to "2"`}, {less: uint64(1), greater: uint64(2), msg: `"1" is not greater than or equal to "2"`}, {less: float32(1.23), greater: float32(2.34), msg: `"1.23" is not greater than or equal to "2.34"`}, {less: float64(1.23), greater: float64(2.34), msg: `"1.23" is not greater than or equal to "2.34"`}, {less: uintptr(1), greater: uintptr(2), msg: `"1" is not greater than or equal to "2"`}, {less: time.Time{}, greater: time.Time{}.Add(time.Hour), msg: `"0001-01-01 00:00:00 +0000 UTC" is not greater than or equal to "0001-01-01 01:00:00 +0000 UTC"`}, {less: []byte{1, 1}, greater: []byte{1, 2}, msg: `"[1 1]" is not greater than or equal to "[1 2]"`}, } { out := &outputT{buf: bytes.NewBuffer(nil)} False(t, GreaterOrEqual(out, currCase.less, currCase.greater)) Contains(t, out.buf.String(), currCase.msg) Contains(t, out.helpers, "github.com/expr-lang/expr/internal/testify/assert.GreaterOrEqual") } } func TestLess(t *testing.T) { mockT := new(testing.T) if !Less(mockT, 1, 2) { t.Error("Less should return true") } if Less(mockT, 1, 1) { t.Error("Less should return false") } if Less(mockT, 2, 1) { t.Error("Less should return false") } // Check error report for _, currCase := range []struct { less interface{} greater interface{} msg string }{ {less: "a", greater: "b", msg: `"b" is not less than "a"`}, {less: int(1), greater: int(2), msg: `"2" is not less than "1"`}, {less: int8(1), greater: int8(2), msg: `"2" is not less than "1"`}, {less: int16(1), greater: int16(2), msg: `"2" is not less than "1"`}, {less: int32(1), greater: int32(2), msg: `"2" is not less than "1"`}, {less: int64(1), greater: int64(2), msg: `"2" is not less than "1"`}, {less: uint8(1), greater: uint8(2), msg: `"2" is not less than "1"`}, {less: uint16(1), greater: uint16(2), msg: `"2" is not less than "1"`}, {less: uint32(1), greater: uint32(2), msg: `"2" is not less than "1"`}, {less: uint64(1), greater: uint64(2), msg: `"2" is not less than "1"`}, {less: float32(1.23), greater: float32(2.34), msg: `"2.34" is not less than "1.23"`}, {less: float64(1.23), greater: float64(2.34), msg: `"2.34" is not less than "1.23"`}, {less: uintptr(1), greater: uintptr(2), msg: `"2" is not less than "1"`}, {less: time.Time{}, greater: time.Time{}.Add(time.Hour), msg: `"0001-01-01 01:00:00 +0000 UTC" is not less than "0001-01-01 00:00:00 +0000 UTC"`}, {less: []byte{1, 1}, greater: []byte{1, 2}, msg: `"[1 2]" is not less than "[1 1]"`}, } { out := &outputT{buf: bytes.NewBuffer(nil)} False(t, Less(out, currCase.greater, currCase.less)) Contains(t, out.buf.String(), currCase.msg) Contains(t, out.helpers, "github.com/expr-lang/expr/internal/testify/assert.Less") } } func TestLessOrEqual(t *testing.T) { mockT := new(testing.T) if !LessOrEqual(mockT, 1, 2) { t.Error("LessOrEqual should return true") } if !LessOrEqual(mockT, 1, 1) { t.Error("LessOrEqual should return true") } if LessOrEqual(mockT, 2, 1) { t.Error("LessOrEqual should return false") } // Check error report for _, currCase := range []struct { less interface{} greater interface{} msg string }{ {less: "a", greater: "b", msg: `"b" is not less than or equal to "a"`}, {less: int(1), greater: int(2), msg: `"2" is not less than or equal to "1"`}, {less: int8(1), greater: int8(2), msg: `"2" is not less than or equal to "1"`}, {less: int16(1), greater: int16(2), msg: `"2" is not less than or equal to "1"`}, {less: int32(1), greater: int32(2), msg: `"2" is not less than or equal to "1"`}, {less: int64(1), greater: int64(2), msg: `"2" is not less than or equal to "1"`}, {less: uint8(1), greater: uint8(2), msg: `"2" is not less than or equal to "1"`}, {less: uint16(1), greater: uint16(2), msg: `"2" is not less than or equal to "1"`}, {less: uint32(1), greater: uint32(2), msg: `"2" is not less than or equal to "1"`}, {less: uint64(1), greater: uint64(2), msg: `"2" is not less than or equal to "1"`}, {less: float32(1.23), greater: float32(2.34), msg: `"2.34" is not less than or equal to "1.23"`}, {less: float64(1.23), greater: float64(2.34), msg: `"2.34" is not less than or equal to "1.23"`}, {less: uintptr(1), greater: uintptr(2), msg: `"2" is not less than or equal to "1"`}, {less: time.Time{}, greater: time.Time{}.Add(time.Hour), msg: `"0001-01-01 01:00:00 +0000 UTC" is not less than or equal to "0001-01-01 00:00:00 +0000 UTC"`}, {less: []byte{1, 1}, greater: []byte{1, 2}, msg: `"[1 2]" is not less than or equal to "[1 1]"`}, } { out := &outputT{buf: bytes.NewBuffer(nil)} False(t, LessOrEqual(out, currCase.greater, currCase.less)) Contains(t, out.buf.String(), currCase.msg) Contains(t, out.helpers, "github.com/expr-lang/expr/internal/testify/assert.LessOrEqual") } } func TestPositive(t *testing.T) { mockT := new(testing.T) if !Positive(mockT, 1) { t.Error("Positive should return true") } if !Positive(mockT, 1.23) { t.Error("Positive should return true") } if Positive(mockT, -1) { t.Error("Positive should return false") } if Positive(mockT, -1.23) { t.Error("Positive should return false") } // Check error report for _, currCase := range []struct { e interface{} msg string }{ {e: int(-1), msg: `"-1" is not positive`}, {e: int8(-1), msg: `"-1" is not positive`}, {e: int16(-1), msg: `"-1" is not positive`}, {e: int32(-1), msg: `"-1" is not positive`}, {e: int64(-1), msg: `"-1" is not positive`}, {e: float32(-1.23), msg: `"-1.23" is not positive`}, {e: float64(-1.23), msg: `"-1.23" is not positive`}, } { out := &outputT{buf: bytes.NewBuffer(nil)} False(t, Positive(out, currCase.e)) Contains(t, out.buf.String(), currCase.msg) Contains(t, out.helpers, "github.com/expr-lang/expr/internal/testify/assert.Positive") } } func TestNegative(t *testing.T) { mockT := new(testing.T) if !Negative(mockT, -1) { t.Error("Negative should return true") } if !Negative(mockT, -1.23) { t.Error("Negative should return true") } if Negative(mockT, 1) { t.Error("Negative should return false") } if Negative(mockT, 1.23) { t.Error("Negative should return false") } // Check error report for _, currCase := range []struct { e interface{} msg string }{ {e: int(1), msg: `"1" is not negative`}, {e: int8(1), msg: `"1" is not negative`}, {e: int16(1), msg: `"1" is not negative`}, {e: int32(1), msg: `"1" is not negative`}, {e: int64(1), msg: `"1" is not negative`}, {e: float32(1.23), msg: `"1.23" is not negative`}, {e: float64(1.23), msg: `"1.23" is not negative`}, } { out := &outputT{buf: bytes.NewBuffer(nil)} False(t, Negative(out, currCase.e)) Contains(t, out.buf.String(), currCase.msg) Contains(t, out.helpers, "github.com/expr-lang/expr/internal/testify/assert.Negative") } } func Test_compareTwoValuesDifferentValuesTypes(t *testing.T) { mockT := new(testing.T) for _, currCase := range []struct { v1 interface{} v2 interface{} compareResult bool }{ {v1: 123, v2: "abc"}, {v1: "abc", v2: 123456}, {v1: float64(12), v2: "123"}, {v1: "float(12)", v2: float64(1)}, } { result := compareTwoValues(mockT, currCase.v1, currCase.v2, []compareResult{compareLess, compareEqual, compareGreater}, "testFailMessage") False(t, result) } } func Test_compareTwoValuesNotComparableValues(t *testing.T) { mockT := new(testing.T) type CompareStruct struct { } for _, currCase := range []struct { v1 interface{} v2 interface{} }{ {v1: CompareStruct{}, v2: CompareStruct{}}, {v1: map[string]int{}, v2: map[string]int{}}, {v1: make([]int, 5), v2: make([]int, 5)}, } { result := compareTwoValues(mockT, currCase.v1, currCase.v2, []compareResult{compareLess, compareEqual, compareGreater}, "testFailMessage") False(t, result) } } func Test_compareTwoValuesCorrectCompareResult(t *testing.T) { mockT := new(testing.T) for _, currCase := range []struct { v1 interface{} v2 interface{} allowedResults []compareResult }{ {v1: 1, v2: 2, allowedResults: []compareResult{compareLess}}, {v1: 1, v2: 2, allowedResults: []compareResult{compareLess, compareEqual}}, {v1: 2, v2: 2, allowedResults: []compareResult{compareGreater, compareEqual}}, {v1: 2, v2: 2, allowedResults: []compareResult{compareEqual}}, {v1: 2, v2: 1, allowedResults: []compareResult{compareEqual, compareGreater}}, {v1: 2, v2: 1, allowedResults: []compareResult{compareGreater}}, } { result := compareTwoValues(mockT, currCase.v1, currCase.v2, currCase.allowedResults, "testFailMessage") True(t, result) } } func Test_containsValue(t *testing.T) { for _, currCase := range []struct { values []compareResult value compareResult result bool }{ {values: []compareResult{compareGreater}, value: compareGreater, result: true}, {values: []compareResult{compareGreater, compareLess}, value: compareGreater, result: true}, {values: []compareResult{compareGreater, compareLess}, value: compareLess, result: true}, {values: []compareResult{compareGreater, compareLess}, value: compareEqual, result: false}, } { result := containsValue(currCase.values, currCase.value) Equal(t, currCase.result, result) } } func TestComparingMsgAndArgsForwarding(t *testing.T) { msgAndArgs := []interface{}{"format %s %x", "this", 0xc001} expectedOutput := "format this c001\n" funcs := []func(t TestingT){ func(t TestingT) { Greater(t, 1, 2, msgAndArgs...) }, func(t TestingT) { GreaterOrEqual(t, 1, 2, msgAndArgs...) }, func(t TestingT) { Less(t, 2, 1, msgAndArgs...) }, func(t TestingT) { LessOrEqual(t, 2, 1, msgAndArgs...) }, func(t TestingT) { Positive(t, 0, msgAndArgs...) }, func(t TestingT) { Negative(t, 0, msgAndArgs...) }, } for _, f := range funcs { out := &outputT{buf: bytes.NewBuffer(nil)} f(out) Contains(t, out.buf.String(), expectedOutput) } } ================================================ FILE: internal/testify/assert/assertion_format.go ================================================ // Code generated with github.com/expr-lang/expr/internal/_codegen; DO NOT EDIT. package assert import ( http "net/http" url "net/url" time "time" ) // Conditionf uses a Comparison to assert a complex condition. func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return Condition(t, comp, append([]interface{}{msg}, args...)...) } // Containsf asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // // assert.Containsf(t, "Hello World", "World", "error message %s", "formatted") // assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") // assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return Contains(t, s, contains, append([]interface{}{msg}, args...)...) } // DirExistsf checks whether a directory exists in the given path. It also fails // if the path is a file rather a directory or there is an error checking whether it exists. func DirExistsf(t TestingT, path string, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return DirExists(t, path, append([]interface{}{msg}, args...)...) } // ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // // assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return ElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...) } // Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // // assert.Emptyf(t, obj, "error message %s", "formatted") func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return Empty(t, object, append([]interface{}{msg}, args...)...) } // Equalf asserts that two objects are equal. // // assert.Equalf(t, 123, 123, "error message %s", "formatted") // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return Equal(t, expected, actual, append([]interface{}{msg}, args...)...) } // EqualErrorf asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // // actualObj, err := SomeFunction() // assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...) } // EqualExportedValuesf asserts that the types of two objects are equal and their public // fields are also equal. This is useful for comparing structs that have private fields // that could potentially differ. // // type S struct { // Exported int // notExported int // } // assert.EqualExportedValuesf(t, S{1, 2}, S{1, 3}, "error message %s", "formatted") => true // assert.EqualExportedValuesf(t, S{1, 2}, S{2, 3}, "error message %s", "formatted") => false func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return EqualExportedValues(t, expected, actual, append([]interface{}{msg}, args...)...) } // EqualValuesf asserts that two objects are equal or convertible to the same types // and equal. // // assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted") func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return EqualValues(t, expected, actual, append([]interface{}{msg}, args...)...) } // Errorf asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() // if assert.Errorf(t, err, "error message %s", "formatted") { // assert.Equal(t, expectedErrorf, err) // } func Errorf(t TestingT, err error, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return Error(t, err, append([]interface{}{msg}, args...)...) } // ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. // This is a wrapper for errors.As. func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return ErrorAs(t, err, target, append([]interface{}{msg}, args...)...) } // ErrorContainsf asserts that a function returned an error (i.e. not `nil`) // and that the error contains the specified substring. // // actualObj, err := SomeFunction() // assert.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted") func ErrorContainsf(t TestingT, theError error, contains string, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return ErrorContains(t, theError, contains, append([]interface{}{msg}, args...)...) } // ErrorIsf asserts that at least one of the errors in err's chain matches target. // This is a wrapper for errors.Is. func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return ErrorIs(t, err, target, append([]interface{}{msg}, args...)...) } // Eventuallyf asserts that given condition will be met in waitFor time, // periodically checking target function each tick. // // assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return Eventually(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...) } // EventuallyWithTf asserts that given condition will be met in waitFor time, // periodically checking target function each tick. In contrast to Eventually, // it supplies a CollectT to the condition function, so that the condition // function can use the CollectT to call other assertions. // The condition is considered "met" if no errors are raised in a tick. // The supplied CollectT collects all errors from one tick (if there are any). // If the condition is not met before waitFor, the collected errors of // the last tick are copied to t. // // externalValue := false // go func() { // time.Sleep(8*time.Second) // externalValue = true // }() // assert.EventuallyWithTf(t, func(c *assert.CollectT, "error message %s", "formatted") { // // add assertions as needed; any assertion failure will fail the current tick // assert.True(c, externalValue, "expected 'externalValue' to be true") // }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false") func EventuallyWithTf(t TestingT, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return EventuallyWithT(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...) } // Exactlyf asserts that two objects are equal in value and type. // // assert.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted") func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return Exactly(t, expected, actual, append([]interface{}{msg}, args...)...) } // Failf reports a failure through func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return Fail(t, failureMessage, append([]interface{}{msg}, args...)...) } // FailNowf fails test func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return FailNow(t, failureMessage, append([]interface{}{msg}, args...)...) } // Falsef asserts that the specified value is false. // // assert.Falsef(t, myBool, "error message %s", "formatted") func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return False(t, value, append([]interface{}{msg}, args...)...) } // FileExistsf checks whether a file exists in the given path. It also fails if // the path points to a directory or there is an error when trying to check the file. func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return FileExists(t, path, append([]interface{}{msg}, args...)...) } // Greaterf asserts that the first element is greater than the second // // assert.Greaterf(t, 2, 1, "error message %s", "formatted") // assert.Greaterf(t, float64(2), float64(1), "error message %s", "formatted") // assert.Greaterf(t, "b", "a", "error message %s", "formatted") func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return Greater(t, e1, e2, append([]interface{}{msg}, args...)...) } // GreaterOrEqualf asserts that the first element is greater than or equal to the second // // assert.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted") // assert.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted") // assert.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted") // assert.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted") func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return GreaterOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...) } // HTTPBodyContainsf asserts that a specified handler returns a // body that contains a string. // // assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return HTTPBodyContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...) } // HTTPBodyNotContainsf asserts that a specified handler returns a // body that does not contain a string. // // assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return HTTPBodyNotContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...) } // HTTPErrorf asserts that a specified handler returns an error status code. // // assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return HTTPError(t, handler, method, url, values, append([]interface{}{msg}, args...)...) } // HTTPRedirectf asserts that a specified handler returns a redirect status code. // // assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return HTTPRedirect(t, handler, method, url, values, append([]interface{}{msg}, args...)...) } // HTTPStatusCodef asserts that a specified handler returns a specified status code. // // assert.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return HTTPStatusCode(t, handler, method, url, values, statuscode, append([]interface{}{msg}, args...)...) } // HTTPSuccessf asserts that a specified handler returns a success status code. // // assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return HTTPSuccess(t, handler, method, url, values, append([]interface{}{msg}, args...)...) } // Implementsf asserts that an object is implemented by the specified interface. // // assert.Implementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return Implements(t, interfaceObject, object, append([]interface{}{msg}, args...)...) } // InDeltaf asserts that the two numerals are within delta of each other. // // assert.InDeltaf(t, math.Pi, 22/7.0, 0.01, "error message %s", "formatted") func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return InDelta(t, expected, actual, delta, append([]interface{}{msg}, args...)...) } // InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return InDeltaMapValues(t, expected, actual, delta, append([]interface{}{msg}, args...)...) } // InDeltaSlicef is the same as InDelta, except it compares two slices. func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return InDeltaSlice(t, expected, actual, delta, append([]interface{}{msg}, args...)...) } // InEpsilonf asserts that expected and actual have a relative error less than epsilon func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return InEpsilon(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) } // InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) } // IsDecreasingf asserts that the collection is decreasing // // assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted") // assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted") // assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted") func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return IsDecreasing(t, object, append([]interface{}{msg}, args...)...) } // IsIncreasingf asserts that the collection is increasing // // assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted") // assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted") // assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted") func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return IsIncreasing(t, object, append([]interface{}{msg}, args...)...) } // IsNonDecreasingf asserts that the collection is not decreasing // // assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted") // assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted") // assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted") func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return IsNonDecreasing(t, object, append([]interface{}{msg}, args...)...) } // IsNonIncreasingf asserts that the collection is not increasing // // assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted") // assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted") // assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted") func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return IsNonIncreasing(t, object, append([]interface{}{msg}, args...)...) } // IsTypef asserts that the specified objects are of the same type. func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return IsType(t, expectedType, object, append([]interface{}{msg}, args...)...) } // JSONEqf asserts that two JSON strings are equivalent. // // assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...) } // Lenf asserts that the specified object has specific length. // Lenf also fails if the object has a type that len() not accept. // // assert.Lenf(t, mySlice, 3, "error message %s", "formatted") func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return Len(t, object, length, append([]interface{}{msg}, args...)...) } // Lessf asserts that the first element is less than the second // // assert.Lessf(t, 1, 2, "error message %s", "formatted") // assert.Lessf(t, float64(1), float64(2), "error message %s", "formatted") // assert.Lessf(t, "a", "b", "error message %s", "formatted") func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return Less(t, e1, e2, append([]interface{}{msg}, args...)...) } // LessOrEqualf asserts that the first element is less than or equal to the second // // assert.LessOrEqualf(t, 1, 2, "error message %s", "formatted") // assert.LessOrEqualf(t, 2, 2, "error message %s", "formatted") // assert.LessOrEqualf(t, "a", "b", "error message %s", "formatted") // assert.LessOrEqualf(t, "b", "b", "error message %s", "formatted") func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return LessOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...) } // Negativef asserts that the specified element is negative // // assert.Negativef(t, -1, "error message %s", "formatted") // assert.Negativef(t, -1.23, "error message %s", "formatted") func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return Negative(t, e, append([]interface{}{msg}, args...)...) } // Neverf asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // // assert.Neverf(t, func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") func Neverf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return Never(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...) } // Nilf asserts that the specified object is nil. // // assert.Nilf(t, err, "error message %s", "formatted") func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return Nil(t, object, append([]interface{}{msg}, args...)...) } // NoDirExistsf checks whether a directory does not exist in the given path. // It fails if the path points to an existing _directory_ only. func NoDirExistsf(t TestingT, path string, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return NoDirExists(t, path, append([]interface{}{msg}, args...)...) } // NoErrorf asserts that a function returned no error (i.e. `nil`). // // actualObj, err := SomeFunction() // if assert.NoErrorf(t, err, "error message %s", "formatted") { // assert.Equal(t, expectedObj, actualObj) // } func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return NoError(t, err, append([]interface{}{msg}, args...)...) } // NoFileExistsf checks whether a file does not exist in a given path. It fails // if the path points to an existing _file_ only. func NoFileExistsf(t TestingT, path string, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return NoFileExists(t, path, append([]interface{}{msg}, args...)...) } // NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // // assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted") // assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") // assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return NotContains(t, s, contains, append([]interface{}{msg}, args...)...) } // NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // // if assert.NotEmptyf(t, obj, "error message %s", "formatted") { // assert.Equal(t, "two", obj[1]) // } func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return NotEmpty(t, object, append([]interface{}{msg}, args...)...) } // NotEqualf asserts that the specified values are NOT equal. // // assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted") // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return NotEqual(t, expected, actual, append([]interface{}{msg}, args...)...) } // NotEqualValuesf asserts that two objects are not equal even when converted to the same type // // assert.NotEqualValuesf(t, obj1, obj2, "error message %s", "formatted") func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return NotEqualValues(t, expected, actual, append([]interface{}{msg}, args...)...) } // NotErrorIsf asserts that at none of the errors in err's chain matches target. // This is a wrapper for errors.Is. func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return NotErrorIs(t, err, target, append([]interface{}{msg}, args...)...) } // NotImplementsf asserts that an object does not implement the specified interface. // // assert.NotImplementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return NotImplements(t, interfaceObject, object, append([]interface{}{msg}, args...)...) } // NotNilf asserts that the specified object is not nil. // // assert.NotNilf(t, err, "error message %s", "formatted") func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return NotNil(t, object, append([]interface{}{msg}, args...)...) } // NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. // // assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return NotPanics(t, f, append([]interface{}{msg}, args...)...) } // NotRegexpf asserts that a specified regexp does not match a string. // // assert.NotRegexpf(t, regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") // assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return NotRegexp(t, rx, str, append([]interface{}{msg}, args...)...) } // NotSamef asserts that two pointers do not reference the same object. // // assert.NotSamef(t, ptr1, ptr2, "error message %s", "formatted") // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...) } // NotSubsetf asserts that the specified list(array, slice...) or map does NOT // contain all elements given in the specified subset list(array, slice...) or // map. // // assert.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted") // assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return NotSubset(t, list, subset, append([]interface{}{msg}, args...)...) } // NotZerof asserts that i is not the zero value for its type. func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return NotZero(t, i, append([]interface{}{msg}, args...)...) } // Panicsf asserts that the code inside the specified PanicTestFunc panics. // // assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return Panics(t, f, append([]interface{}{msg}, args...)...) } // PanicsWithErrorf asserts that the code inside the specified PanicTestFunc // panics, and that the recovered panic value is an error that satisfies the // EqualError comparison. // // assert.PanicsWithErrorf(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") func PanicsWithErrorf(t TestingT, errString string, f PanicTestFunc, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return PanicsWithError(t, errString, f, append([]interface{}{msg}, args...)...) } // PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // // assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...) } // Positivef asserts that the specified element is positive // // assert.Positivef(t, 1, "error message %s", "formatted") // assert.Positivef(t, 1.23, "error message %s", "formatted") func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return Positive(t, e, append([]interface{}{msg}, args...)...) } // Regexpf asserts that a specified regexp matches a string. // // assert.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") // assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return Regexp(t, rx, str, append([]interface{}{msg}, args...)...) } // Samef asserts that two pointers reference the same object. // // assert.Samef(t, ptr1, ptr2, "error message %s", "formatted") // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. func Samef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return Same(t, expected, actual, append([]interface{}{msg}, args...)...) } // Subsetf asserts that the specified list(array, slice...) or map contains all // elements given in the specified subset list(array, slice...) or map. // // assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted") // assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return Subset(t, list, subset, append([]interface{}{msg}, args...)...) } // Truef asserts that the specified value is true. // // assert.Truef(t, myBool, "error message %s", "formatted") func Truef(t TestingT, value bool, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return True(t, value, append([]interface{}{msg}, args...)...) } // WithinDurationf asserts that the two times are within duration delta of each other. // // assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...) } // WithinRangef asserts that a time is within a time range (inclusive). // // assert.WithinRangef(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") func WithinRangef(t TestingT, actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return WithinRange(t, actual, start, end, append([]interface{}{msg}, args...)...) } // Zerof asserts that i is the zero value for its type. func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return Zero(t, i, append([]interface{}{msg}, args...)...) } ================================================ FILE: internal/testify/assert/assertion_format.go.tmpl ================================================ {{.CommentFormat}} func {{.DocInfo.Name}}f(t TestingT, {{.ParamsFormat}}) bool { if h, ok := t.(tHelper); ok { h.Helper() } return {{.DocInfo.Name}}(t, {{.ForwardedParamsFormat}}) } ================================================ FILE: internal/testify/assert/assertion_forward.go ================================================ // Code generated with github.com/expr-lang/expr/internal/_codegen; DO NOT EDIT. package assert import ( http "net/http" url "net/url" time "time" ) // Condition uses a Comparison to assert a complex condition. func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Condition(a.t, comp, msgAndArgs...) } // Conditionf uses a Comparison to assert a complex condition. func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Conditionf(a.t, comp, msg, args...) } // Contains asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // // a.Contains("Hello World", "World") // a.Contains(["Hello", "World"], "World") // a.Contains({"Hello": "World"}, "Hello") func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Contains(a.t, s, contains, msgAndArgs...) } // Containsf asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // // a.Containsf("Hello World", "World", "error message %s", "formatted") // a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") // a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Containsf(a.t, s, contains, msg, args...) } // DirExists checks whether a directory exists in the given path. It also fails // if the path is a file rather a directory or there is an error checking whether it exists. func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return DirExists(a.t, path, msgAndArgs...) } // DirExistsf checks whether a directory exists in the given path. It also fails // if the path is a file rather a directory or there is an error checking whether it exists. func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return DirExistsf(a.t, path, msg, args...) } // ElementsMatch asserts that the specified listA(array, slice...) is equal to specified // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // // a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2]) func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return ElementsMatch(a.t, listA, listB, msgAndArgs...) } // ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // // a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return ElementsMatchf(a.t, listA, listB, msg, args...) } // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // // a.Empty(obj) func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Empty(a.t, object, msgAndArgs...) } // Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // // a.Emptyf(obj, "error message %s", "formatted") func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Emptyf(a.t, object, msg, args...) } // Equal asserts that two objects are equal. // // a.Equal(123, 123) // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Equal(a.t, expected, actual, msgAndArgs...) } // EqualError asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // // actualObj, err := SomeFunction() // a.EqualError(err, expectedErrorString) func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return EqualError(a.t, theError, errString, msgAndArgs...) } // EqualErrorf asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // // actualObj, err := SomeFunction() // a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return EqualErrorf(a.t, theError, errString, msg, args...) } // EqualExportedValues asserts that the types of two objects are equal and their public // fields are also equal. This is useful for comparing structs that have private fields // that could potentially differ. // // type S struct { // Exported int // notExported int // } // a.EqualExportedValues(S{1, 2}, S{1, 3}) => true // a.EqualExportedValues(S{1, 2}, S{2, 3}) => false func (a *Assertions) EqualExportedValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return EqualExportedValues(a.t, expected, actual, msgAndArgs...) } // EqualExportedValuesf asserts that the types of two objects are equal and their public // fields are also equal. This is useful for comparing structs that have private fields // that could potentially differ. // // type S struct { // Exported int // notExported int // } // a.EqualExportedValuesf(S{1, 2}, S{1, 3}, "error message %s", "formatted") => true // a.EqualExportedValuesf(S{1, 2}, S{2, 3}, "error message %s", "formatted") => false func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return EqualExportedValuesf(a.t, expected, actual, msg, args...) } // EqualValues asserts that two objects are equal or convertible to the same types // and equal. // // a.EqualValues(uint32(123), int32(123)) func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return EqualValues(a.t, expected, actual, msgAndArgs...) } // EqualValuesf asserts that two objects are equal or convertible to the same types // and equal. // // a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted") func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return EqualValuesf(a.t, expected, actual, msg, args...) } // Equalf asserts that two objects are equal. // // a.Equalf(123, 123, "error message %s", "formatted") // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Equalf(a.t, expected, actual, msg, args...) } // Error asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() // if a.Error(err) { // assert.Equal(t, expectedError, err) // } func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Error(a.t, err, msgAndArgs...) } // ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. // This is a wrapper for errors.As. func (a *Assertions) ErrorAs(err error, target interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return ErrorAs(a.t, err, target, msgAndArgs...) } // ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. // This is a wrapper for errors.As. func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return ErrorAsf(a.t, err, target, msg, args...) } // ErrorContains asserts that a function returned an error (i.e. not `nil`) // and that the error contains the specified substring. // // actualObj, err := SomeFunction() // a.ErrorContains(err, expectedErrorSubString) func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return ErrorContains(a.t, theError, contains, msgAndArgs...) } // ErrorContainsf asserts that a function returned an error (i.e. not `nil`) // and that the error contains the specified substring. // // actualObj, err := SomeFunction() // a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted") func (a *Assertions) ErrorContainsf(theError error, contains string, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return ErrorContainsf(a.t, theError, contains, msg, args...) } // ErrorIs asserts that at least one of the errors in err's chain matches target. // This is a wrapper for errors.Is. func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return ErrorIs(a.t, err, target, msgAndArgs...) } // ErrorIsf asserts that at least one of the errors in err's chain matches target. // This is a wrapper for errors.Is. func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return ErrorIsf(a.t, err, target, msg, args...) } // Errorf asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() // if a.Errorf(err, "error message %s", "formatted") { // assert.Equal(t, expectedErrorf, err) // } func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Errorf(a.t, err, msg, args...) } // Eventually asserts that given condition will be met in waitFor time, // periodically checking target function each tick. // // a.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond) func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Eventually(a.t, condition, waitFor, tick, msgAndArgs...) } // EventuallyWithT asserts that given condition will be met in waitFor time, // periodically checking target function each tick. In contrast to Eventually, // it supplies a CollectT to the condition function, so that the condition // function can use the CollectT to call other assertions. // The condition is considered "met" if no errors are raised in a tick. // The supplied CollectT collects all errors from one tick (if there are any). // If the condition is not met before waitFor, the collected errors of // the last tick are copied to t. // // externalValue := false // go func() { // time.Sleep(8*time.Second) // externalValue = true // }() // a.EventuallyWithT(func(c *assert.CollectT) { // // add assertions as needed; any assertion failure will fail the current tick // assert.True(c, externalValue, "expected 'externalValue' to be true") // }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false") func (a *Assertions) EventuallyWithT(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return EventuallyWithT(a.t, condition, waitFor, tick, msgAndArgs...) } // EventuallyWithTf asserts that given condition will be met in waitFor time, // periodically checking target function each tick. In contrast to Eventually, // it supplies a CollectT to the condition function, so that the condition // function can use the CollectT to call other assertions. // The condition is considered "met" if no errors are raised in a tick. // The supplied CollectT collects all errors from one tick (if there are any). // If the condition is not met before waitFor, the collected errors of // the last tick are copied to t. // // externalValue := false // go func() { // time.Sleep(8*time.Second) // externalValue = true // }() // a.EventuallyWithTf(func(c *assert.CollectT, "error message %s", "formatted") { // // add assertions as needed; any assertion failure will fail the current tick // assert.True(c, externalValue, "expected 'externalValue' to be true") // }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false") func (a *Assertions) EventuallyWithTf(condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return EventuallyWithTf(a.t, condition, waitFor, tick, msg, args...) } // Eventuallyf asserts that given condition will be met in waitFor time, // periodically checking target function each tick. // // a.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Eventuallyf(a.t, condition, waitFor, tick, msg, args...) } // Exactly asserts that two objects are equal in value and type. // // a.Exactly(int32(123), int64(123)) func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Exactly(a.t, expected, actual, msgAndArgs...) } // Exactlyf asserts that two objects are equal in value and type. // // a.Exactlyf(int32(123), int64(123), "error message %s", "formatted") func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Exactlyf(a.t, expected, actual, msg, args...) } // Fail reports a failure through func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Fail(a.t, failureMessage, msgAndArgs...) } // FailNow fails test func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return FailNow(a.t, failureMessage, msgAndArgs...) } // FailNowf fails test func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return FailNowf(a.t, failureMessage, msg, args...) } // Failf reports a failure through func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Failf(a.t, failureMessage, msg, args...) } // False asserts that the specified value is false. // // a.False(myBool) func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return False(a.t, value, msgAndArgs...) } // Falsef asserts that the specified value is false. // // a.Falsef(myBool, "error message %s", "formatted") func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Falsef(a.t, value, msg, args...) } // FileExists checks whether a file exists in the given path. It also fails if // the path points to a directory or there is an error when trying to check the file. func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return FileExists(a.t, path, msgAndArgs...) } // FileExistsf checks whether a file exists in the given path. It also fails if // the path points to a directory or there is an error when trying to check the file. func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return FileExistsf(a.t, path, msg, args...) } // Greater asserts that the first element is greater than the second // // a.Greater(2, 1) // a.Greater(float64(2), float64(1)) // a.Greater("b", "a") func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Greater(a.t, e1, e2, msgAndArgs...) } // GreaterOrEqual asserts that the first element is greater than or equal to the second // // a.GreaterOrEqual(2, 1) // a.GreaterOrEqual(2, 2) // a.GreaterOrEqual("b", "a") // a.GreaterOrEqual("b", "b") func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return GreaterOrEqual(a.t, e1, e2, msgAndArgs...) } // GreaterOrEqualf asserts that the first element is greater than or equal to the second // // a.GreaterOrEqualf(2, 1, "error message %s", "formatted") // a.GreaterOrEqualf(2, 2, "error message %s", "formatted") // a.GreaterOrEqualf("b", "a", "error message %s", "formatted") // a.GreaterOrEqualf("b", "b", "error message %s", "formatted") func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return GreaterOrEqualf(a.t, e1, e2, msg, args...) } // Greaterf asserts that the first element is greater than the second // // a.Greaterf(2, 1, "error message %s", "formatted") // a.Greaterf(float64(2), float64(1), "error message %s", "formatted") // a.Greaterf("b", "a", "error message %s", "formatted") func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Greaterf(a.t, e1, e2, msg, args...) } // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // // a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...) } // HTTPBodyContainsf asserts that a specified handler returns a // body that contains a string. // // a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...) } // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // // a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...) } // HTTPBodyNotContainsf asserts that a specified handler returns a // body that does not contain a string. // // a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...) } // HTTPError asserts that a specified handler returns an error status code. // // a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return HTTPError(a.t, handler, method, url, values, msgAndArgs...) } // HTTPErrorf asserts that a specified handler returns an error status code. // // a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return HTTPErrorf(a.t, handler, method, url, values, msg, args...) } // HTTPRedirect asserts that a specified handler returns a redirect status code. // // a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...) } // HTTPRedirectf asserts that a specified handler returns a redirect status code. // // a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return HTTPRedirectf(a.t, handler, method, url, values, msg, args...) } // HTTPStatusCode asserts that a specified handler returns a specified status code. // // a.HTTPStatusCode(myHandler, "GET", "/notImplemented", nil, 501) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPStatusCode(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return HTTPStatusCode(a.t, handler, method, url, values, statuscode, msgAndArgs...) } // HTTPStatusCodef asserts that a specified handler returns a specified status code. // // a.HTTPStatusCodef(myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPStatusCodef(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return HTTPStatusCodef(a.t, handler, method, url, values, statuscode, msg, args...) } // HTTPSuccess asserts that a specified handler returns a success status code. // // a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...) } // HTTPSuccessf asserts that a specified handler returns a success status code. // // a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return HTTPSuccessf(a.t, handler, method, url, values, msg, args...) } // Implements asserts that an object is implemented by the specified interface. // // a.Implements((*MyInterface)(nil), new(MyObject)) func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Implements(a.t, interfaceObject, object, msgAndArgs...) } // Implementsf asserts that an object is implemented by the specified interface. // // a.Implementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Implementsf(a.t, interfaceObject, object, msg, args...) } // InDelta asserts that the two numerals are within delta of each other. // // a.InDelta(math.Pi, 22/7.0, 0.01) func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return InDelta(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...) } // InDeltaSlice is the same as InDelta, except it compares two slices. func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaSlicef is the same as InDelta, except it compares two slices. func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return InDeltaSlicef(a.t, expected, actual, delta, msg, args...) } // InDeltaf asserts that the two numerals are within delta of each other. // // a.InDeltaf(math.Pi, 22/7.0, 0.01, "error message %s", "formatted") func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return InDeltaf(a.t, expected, actual, delta, msg, args...) } // InEpsilon asserts that expected and actual have a relative error less than epsilon func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) } // InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...) } // InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...) } // InEpsilonf asserts that expected and actual have a relative error less than epsilon func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return InEpsilonf(a.t, expected, actual, epsilon, msg, args...) } // IsDecreasing asserts that the collection is decreasing // // a.IsDecreasing([]int{2, 1, 0}) // a.IsDecreasing([]float{2, 1}) // a.IsDecreasing([]string{"b", "a"}) func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return IsDecreasing(a.t, object, msgAndArgs...) } // IsDecreasingf asserts that the collection is decreasing // // a.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted") // a.IsDecreasingf([]float{2, 1}, "error message %s", "formatted") // a.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted") func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return IsDecreasingf(a.t, object, msg, args...) } // IsIncreasing asserts that the collection is increasing // // a.IsIncreasing([]int{1, 2, 3}) // a.IsIncreasing([]float{1, 2}) // a.IsIncreasing([]string{"a", "b"}) func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return IsIncreasing(a.t, object, msgAndArgs...) } // IsIncreasingf asserts that the collection is increasing // // a.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted") // a.IsIncreasingf([]float{1, 2}, "error message %s", "formatted") // a.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted") func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return IsIncreasingf(a.t, object, msg, args...) } // IsNonDecreasing asserts that the collection is not decreasing // // a.IsNonDecreasing([]int{1, 1, 2}) // a.IsNonDecreasing([]float{1, 2}) // a.IsNonDecreasing([]string{"a", "b"}) func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return IsNonDecreasing(a.t, object, msgAndArgs...) } // IsNonDecreasingf asserts that the collection is not decreasing // // a.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted") // a.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted") // a.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted") func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return IsNonDecreasingf(a.t, object, msg, args...) } // IsNonIncreasing asserts that the collection is not increasing // // a.IsNonIncreasing([]int{2, 1, 1}) // a.IsNonIncreasing([]float{2, 1}) // a.IsNonIncreasing([]string{"b", "a"}) func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return IsNonIncreasing(a.t, object, msgAndArgs...) } // IsNonIncreasingf asserts that the collection is not increasing // // a.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted") // a.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted") // a.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted") func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return IsNonIncreasingf(a.t, object, msg, args...) } // IsType asserts that the specified objects are of the same type. func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return IsType(a.t, expectedType, object, msgAndArgs...) } // IsTypef asserts that the specified objects are of the same type. func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return IsTypef(a.t, expectedType, object, msg, args...) } // JSONEq asserts that two JSON strings are equivalent. // // a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return JSONEq(a.t, expected, actual, msgAndArgs...) } // JSONEqf asserts that two JSON strings are equivalent. // // a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return JSONEqf(a.t, expected, actual, msg, args...) } // Len asserts that the specified object has specific length. // Len also fails if the object has a type that len() not accept. // // a.Len(mySlice, 3) func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Len(a.t, object, length, msgAndArgs...) } // Lenf asserts that the specified object has specific length. // Lenf also fails if the object has a type that len() not accept. // // a.Lenf(mySlice, 3, "error message %s", "formatted") func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Lenf(a.t, object, length, msg, args...) } // Less asserts that the first element is less than the second // // a.Less(1, 2) // a.Less(float64(1), float64(2)) // a.Less("a", "b") func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Less(a.t, e1, e2, msgAndArgs...) } // LessOrEqual asserts that the first element is less than or equal to the second // // a.LessOrEqual(1, 2) // a.LessOrEqual(2, 2) // a.LessOrEqual("a", "b") // a.LessOrEqual("b", "b") func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return LessOrEqual(a.t, e1, e2, msgAndArgs...) } // LessOrEqualf asserts that the first element is less than or equal to the second // // a.LessOrEqualf(1, 2, "error message %s", "formatted") // a.LessOrEqualf(2, 2, "error message %s", "formatted") // a.LessOrEqualf("a", "b", "error message %s", "formatted") // a.LessOrEqualf("b", "b", "error message %s", "formatted") func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return LessOrEqualf(a.t, e1, e2, msg, args...) } // Lessf asserts that the first element is less than the second // // a.Lessf(1, 2, "error message %s", "formatted") // a.Lessf(float64(1), float64(2), "error message %s", "formatted") // a.Lessf("a", "b", "error message %s", "formatted") func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Lessf(a.t, e1, e2, msg, args...) } // Negative asserts that the specified element is negative // // a.Negative(-1) // a.Negative(-1.23) func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Negative(a.t, e, msgAndArgs...) } // Negativef asserts that the specified element is negative // // a.Negativef(-1, "error message %s", "formatted") // a.Negativef(-1.23, "error message %s", "formatted") func (a *Assertions) Negativef(e interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Negativef(a.t, e, msg, args...) } // Never asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // // a.Never(func() bool { return false; }, time.Second, 10*time.Millisecond) func (a *Assertions) Never(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Never(a.t, condition, waitFor, tick, msgAndArgs...) } // Neverf asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // // a.Neverf(func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") func (a *Assertions) Neverf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Neverf(a.t, condition, waitFor, tick, msg, args...) } // Nil asserts that the specified object is nil. // // a.Nil(err) func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Nil(a.t, object, msgAndArgs...) } // Nilf asserts that the specified object is nil. // // a.Nilf(err, "error message %s", "formatted") func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Nilf(a.t, object, msg, args...) } // NoDirExists checks whether a directory does not exist in the given path. // It fails if the path points to an existing _directory_ only. func (a *Assertions) NoDirExists(path string, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NoDirExists(a.t, path, msgAndArgs...) } // NoDirExistsf checks whether a directory does not exist in the given path. // It fails if the path points to an existing _directory_ only. func (a *Assertions) NoDirExistsf(path string, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NoDirExistsf(a.t, path, msg, args...) } // NoError asserts that a function returned no error (i.e. `nil`). // // actualObj, err := SomeFunction() // if a.NoError(err) { // assert.Equal(t, expectedObj, actualObj) // } func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NoError(a.t, err, msgAndArgs...) } // NoErrorf asserts that a function returned no error (i.e. `nil`). // // actualObj, err := SomeFunction() // if a.NoErrorf(err, "error message %s", "formatted") { // assert.Equal(t, expectedObj, actualObj) // } func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NoErrorf(a.t, err, msg, args...) } // NoFileExists checks whether a file does not exist in a given path. It fails // if the path points to an existing _file_ only. func (a *Assertions) NoFileExists(path string, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NoFileExists(a.t, path, msgAndArgs...) } // NoFileExistsf checks whether a file does not exist in a given path. It fails // if the path points to an existing _file_ only. func (a *Assertions) NoFileExistsf(path string, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NoFileExistsf(a.t, path, msg, args...) } // NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // // a.NotContains("Hello World", "Earth") // a.NotContains(["Hello", "World"], "Earth") // a.NotContains({"Hello": "World"}, "Earth") func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotContains(a.t, s, contains, msgAndArgs...) } // NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // // a.NotContainsf("Hello World", "Earth", "error message %s", "formatted") // a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") // a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotContainsf(a.t, s, contains, msg, args...) } // NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // // if a.NotEmpty(obj) { // assert.Equal(t, "two", obj[1]) // } func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotEmpty(a.t, object, msgAndArgs...) } // NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // // if a.NotEmptyf(obj, "error message %s", "formatted") { // assert.Equal(t, "two", obj[1]) // } func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotEmptyf(a.t, object, msg, args...) } // NotEqual asserts that the specified values are NOT equal. // // a.NotEqual(obj1, obj2) // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotEqual(a.t, expected, actual, msgAndArgs...) } // NotEqualValues asserts that two objects are not equal even when converted to the same type // // a.NotEqualValues(obj1, obj2) func (a *Assertions) NotEqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotEqualValues(a.t, expected, actual, msgAndArgs...) } // NotEqualValuesf asserts that two objects are not equal even when converted to the same type // // a.NotEqualValuesf(obj1, obj2, "error message %s", "formatted") func (a *Assertions) NotEqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotEqualValuesf(a.t, expected, actual, msg, args...) } // NotEqualf asserts that the specified values are NOT equal. // // a.NotEqualf(obj1, obj2, "error message %s", "formatted") // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotEqualf(a.t, expected, actual, msg, args...) } // NotErrorIs asserts that at none of the errors in err's chain matches target. // This is a wrapper for errors.Is. func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotErrorIs(a.t, err, target, msgAndArgs...) } // NotErrorIsf asserts that at none of the errors in err's chain matches target. // This is a wrapper for errors.Is. func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotErrorIsf(a.t, err, target, msg, args...) } // NotImplements asserts that an object does not implement the specified interface. // // a.NotImplements((*MyInterface)(nil), new(MyObject)) func (a *Assertions) NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotImplements(a.t, interfaceObject, object, msgAndArgs...) } // NotImplementsf asserts that an object does not implement the specified interface. // // a.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotImplementsf(a.t, interfaceObject, object, msg, args...) } // NotNil asserts that the specified object is not nil. // // a.NotNil(err) func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotNil(a.t, object, msgAndArgs...) } // NotNilf asserts that the specified object is not nil. // // a.NotNilf(err, "error message %s", "formatted") func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotNilf(a.t, object, msg, args...) } // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. // // a.NotPanics(func(){ RemainCalm() }) func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotPanics(a.t, f, msgAndArgs...) } // NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. // // a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotPanicsf(a.t, f, msg, args...) } // NotRegexp asserts that a specified regexp does not match a string. // // a.NotRegexp(regexp.MustCompile("starts"), "it's starting") // a.NotRegexp("^start", "it's not starting") func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotRegexp(a.t, rx, str, msgAndArgs...) } // NotRegexpf asserts that a specified regexp does not match a string. // // a.NotRegexpf(regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") // a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotRegexpf(a.t, rx, str, msg, args...) } // NotSame asserts that two pointers do not reference the same object. // // a.NotSame(ptr1, ptr2) // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. func (a *Assertions) NotSame(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotSame(a.t, expected, actual, msgAndArgs...) } // NotSamef asserts that two pointers do not reference the same object. // // a.NotSamef(ptr1, ptr2, "error message %s", "formatted") // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotSamef(a.t, expected, actual, msg, args...) } // NotSubset asserts that the specified list(array, slice...) or map does NOT // contain all elements given in the specified subset list(array, slice...) or // map. // // a.NotSubset([1, 3, 4], [1, 2]) // a.NotSubset({"x": 1, "y": 2}, {"z": 3}) func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotSubset(a.t, list, subset, msgAndArgs...) } // NotSubsetf asserts that the specified list(array, slice...) or map does NOT // contain all elements given in the specified subset list(array, slice...) or // map. // // a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted") // a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotSubsetf(a.t, list, subset, msg, args...) } // NotZero asserts that i is not the zero value for its type. func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotZero(a.t, i, msgAndArgs...) } // NotZerof asserts that i is not the zero value for its type. func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return NotZerof(a.t, i, msg, args...) } // Panics asserts that the code inside the specified PanicTestFunc panics. // // a.Panics(func(){ GoCrazy() }) func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Panics(a.t, f, msgAndArgs...) } // PanicsWithError asserts that the code inside the specified PanicTestFunc // panics, and that the recovered panic value is an error that satisfies the // EqualError comparison. // // a.PanicsWithError("crazy error", func(){ GoCrazy() }) func (a *Assertions) PanicsWithError(errString string, f PanicTestFunc, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return PanicsWithError(a.t, errString, f, msgAndArgs...) } // PanicsWithErrorf asserts that the code inside the specified PanicTestFunc // panics, and that the recovered panic value is an error that satisfies the // EqualError comparison. // // a.PanicsWithErrorf("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") func (a *Assertions) PanicsWithErrorf(errString string, f PanicTestFunc, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return PanicsWithErrorf(a.t, errString, f, msg, args...) } // PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // // a.PanicsWithValue("crazy error", func(){ GoCrazy() }) func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return PanicsWithValue(a.t, expected, f, msgAndArgs...) } // PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // // a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return PanicsWithValuef(a.t, expected, f, msg, args...) } // Panicsf asserts that the code inside the specified PanicTestFunc panics. // // a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Panicsf(a.t, f, msg, args...) } // Positive asserts that the specified element is positive // // a.Positive(1) // a.Positive(1.23) func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Positive(a.t, e, msgAndArgs...) } // Positivef asserts that the specified element is positive // // a.Positivef(1, "error message %s", "formatted") // a.Positivef(1.23, "error message %s", "formatted") func (a *Assertions) Positivef(e interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Positivef(a.t, e, msg, args...) } // Regexp asserts that a specified regexp matches a string. // // a.Regexp(regexp.MustCompile("start"), "it's starting") // a.Regexp("start...$", "it's not starting") func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Regexp(a.t, rx, str, msgAndArgs...) } // Regexpf asserts that a specified regexp matches a string. // // a.Regexpf(regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") // a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Regexpf(a.t, rx, str, msg, args...) } // Same asserts that two pointers reference the same object. // // a.Same(ptr1, ptr2) // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. func (a *Assertions) Same(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Same(a.t, expected, actual, msgAndArgs...) } // Samef asserts that two pointers reference the same object. // // a.Samef(ptr1, ptr2, "error message %s", "formatted") // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Samef(a.t, expected, actual, msg, args...) } // Subset asserts that the specified list(array, slice...) or map contains all // elements given in the specified subset list(array, slice...) or map. // // a.Subset([1, 2, 3], [1, 2]) // a.Subset({"x": 1, "y": 2}, {"x": 1}) func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Subset(a.t, list, subset, msgAndArgs...) } // Subsetf asserts that the specified list(array, slice...) or map contains all // elements given in the specified subset list(array, slice...) or map. // // a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted") // a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Subsetf(a.t, list, subset, msg, args...) } // True asserts that the specified value is true. // // a.True(myBool) func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return True(a.t, value, msgAndArgs...) } // Truef asserts that the specified value is true. // // a.Truef(myBool, "error message %s", "formatted") func (a *Assertions) Truef(value bool, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Truef(a.t, value, msg, args...) } // WithinDuration asserts that the two times are within duration delta of each other. // // a.WithinDuration(time.Now(), time.Now(), 10*time.Second) func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return WithinDuration(a.t, expected, actual, delta, msgAndArgs...) } // WithinDurationf asserts that the two times are within duration delta of each other. // // a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return WithinDurationf(a.t, expected, actual, delta, msg, args...) } // WithinRange asserts that a time is within a time range (inclusive). // // a.WithinRange(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) func (a *Assertions) WithinRange(actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return WithinRange(a.t, actual, start, end, msgAndArgs...) } // WithinRangef asserts that a time is within a time range (inclusive). // // a.WithinRangef(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") func (a *Assertions) WithinRangef(actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return WithinRangef(a.t, actual, start, end, msg, args...) } // Zero asserts that i is the zero value for its type. func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Zero(a.t, i, msgAndArgs...) } // Zerof asserts that i is the zero value for its type. func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return Zerof(a.t, i, msg, args...) } ================================================ FILE: internal/testify/assert/assertion_forward.go.tmpl ================================================ {{.CommentWithoutT "a"}} func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) bool { if h, ok := a.t.(tHelper); ok { h.Helper() } return {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) } ================================================ FILE: internal/testify/assert/assertion_order.go ================================================ package assert import ( "fmt" "reflect" ) // isOrdered checks that collection contains orderable elements. func isOrdered(t TestingT, object interface{}, allowedComparesResults []compareResult, failMessage string, msgAndArgs ...interface{}) bool { objKind := reflect.TypeOf(object).Kind() if objKind != reflect.Slice && objKind != reflect.Array { return false } objValue := reflect.ValueOf(object) objLen := objValue.Len() if objLen <= 1 { return true } value := objValue.Index(0) valueInterface := value.Interface() firstValueKind := value.Kind() for i := 1; i < objLen; i++ { prevValue := value prevValueInterface := valueInterface value = objValue.Index(i) valueInterface = value.Interface() compareResult, isComparable := compare(prevValueInterface, valueInterface, firstValueKind) if !isComparable { return Fail(t, fmt.Sprintf("Can not compare type \"%s\" and \"%s\"", reflect.TypeOf(value), reflect.TypeOf(prevValue)), msgAndArgs...) } if !containsValue(allowedComparesResults, compareResult) { return Fail(t, fmt.Sprintf(failMessage, prevValue, value), msgAndArgs...) } } return true } // IsIncreasing asserts that the collection is increasing // // assert.IsIncreasing(t, []int{1, 2, 3}) // assert.IsIncreasing(t, []float{1, 2}) // assert.IsIncreasing(t, []string{"a", "b"}) func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { return isOrdered(t, object, []compareResult{compareLess}, "\"%v\" is not less than \"%v\"", msgAndArgs...) } // IsNonIncreasing asserts that the collection is not increasing // // assert.IsNonIncreasing(t, []int{2, 1, 1}) // assert.IsNonIncreasing(t, []float{2, 1}) // assert.IsNonIncreasing(t, []string{"b", "a"}) func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { return isOrdered(t, object, []compareResult{compareEqual, compareGreater}, "\"%v\" is not greater than or equal to \"%v\"", msgAndArgs...) } // IsDecreasing asserts that the collection is decreasing // // assert.IsDecreasing(t, []int{2, 1, 0}) // assert.IsDecreasing(t, []float{2, 1}) // assert.IsDecreasing(t, []string{"b", "a"}) func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { return isOrdered(t, object, []compareResult{compareGreater}, "\"%v\" is not greater than \"%v\"", msgAndArgs...) } // IsNonDecreasing asserts that the collection is not decreasing // // assert.IsNonDecreasing(t, []int{1, 1, 2}) // assert.IsNonDecreasing(t, []float{1, 2}) // assert.IsNonDecreasing(t, []string{"a", "b"}) func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { return isOrdered(t, object, []compareResult{compareLess, compareEqual}, "\"%v\" is not less than or equal to \"%v\"", msgAndArgs...) } ================================================ FILE: internal/testify/assert/assertion_order_test.go ================================================ package assert import ( "bytes" "testing" ) func TestIsIncreasing(t *testing.T) { mockT := new(testing.T) if !IsIncreasing(mockT, []int{1, 2}) { t.Error("IsIncreasing should return true") } if !IsIncreasing(mockT, []int{1, 2, 3, 4, 5}) { t.Error("IsIncreasing should return true") } if IsIncreasing(mockT, []int{1, 1}) { t.Error("IsIncreasing should return false") } if IsIncreasing(mockT, []int{2, 1}) { t.Error("IsIncreasing should return false") } // Check error report for _, currCase := range []struct { collection interface{} msg string }{ {collection: []string{"b", "a"}, msg: `"b" is not less than "a"`}, {collection: []int{2, 1}, msg: `"2" is not less than "1"`}, {collection: []int{2, 1, 3, 4, 5, 6, 7}, msg: `"2" is not less than "1"`}, {collection: []int{-1, 0, 2, 1}, msg: `"2" is not less than "1"`}, {collection: []int8{2, 1}, msg: `"2" is not less than "1"`}, {collection: []int16{2, 1}, msg: `"2" is not less than "1"`}, {collection: []int32{2, 1}, msg: `"2" is not less than "1"`}, {collection: []int64{2, 1}, msg: `"2" is not less than "1"`}, {collection: []uint8{2, 1}, msg: `"2" is not less than "1"`}, {collection: []uint16{2, 1}, msg: `"2" is not less than "1"`}, {collection: []uint32{2, 1}, msg: `"2" is not less than "1"`}, {collection: []uint64{2, 1}, msg: `"2" is not less than "1"`}, {collection: []float32{2.34, 1.23}, msg: `"2.34" is not less than "1.23"`}, {collection: []float64{2.34, 1.23}, msg: `"2.34" is not less than "1.23"`}, } { out := &outputT{buf: bytes.NewBuffer(nil)} False(t, IsIncreasing(out, currCase.collection)) Contains(t, out.buf.String(), currCase.msg) } } func TestIsNonIncreasing(t *testing.T) { mockT := new(testing.T) if !IsNonIncreasing(mockT, []int{2, 1}) { t.Error("IsNonIncreasing should return true") } if !IsNonIncreasing(mockT, []int{5, 4, 4, 3, 2, 1}) { t.Error("IsNonIncreasing should return true") } if !IsNonIncreasing(mockT, []int{1, 1}) { t.Error("IsNonIncreasing should return true") } if IsNonIncreasing(mockT, []int{1, 2}) { t.Error("IsNonIncreasing should return false") } // Check error report for _, currCase := range []struct { collection interface{} msg string }{ {collection: []string{"a", "b"}, msg: `"a" is not greater than or equal to "b"`}, {collection: []int{1, 2}, msg: `"1" is not greater than or equal to "2"`}, {collection: []int{1, 2, 7, 6, 5, 4, 3}, msg: `"1" is not greater than or equal to "2"`}, {collection: []int{5, 4, 3, 1, 2}, msg: `"1" is not greater than or equal to "2"`}, {collection: []int8{1, 2}, msg: `"1" is not greater than or equal to "2"`}, {collection: []int16{1, 2}, msg: `"1" is not greater than or equal to "2"`}, {collection: []int32{1, 2}, msg: `"1" is not greater than or equal to "2"`}, {collection: []int64{1, 2}, msg: `"1" is not greater than or equal to "2"`}, {collection: []uint8{1, 2}, msg: `"1" is not greater than or equal to "2"`}, {collection: []uint16{1, 2}, msg: `"1" is not greater than or equal to "2"`}, {collection: []uint32{1, 2}, msg: `"1" is not greater than or equal to "2"`}, {collection: []uint64{1, 2}, msg: `"1" is not greater than or equal to "2"`}, {collection: []float32{1.23, 2.34}, msg: `"1.23" is not greater than or equal to "2.34"`}, {collection: []float64{1.23, 2.34}, msg: `"1.23" is not greater than or equal to "2.34"`}, } { out := &outputT{buf: bytes.NewBuffer(nil)} False(t, IsNonIncreasing(out, currCase.collection)) Contains(t, out.buf.String(), currCase.msg) } } func TestIsDecreasing(t *testing.T) { mockT := new(testing.T) if !IsDecreasing(mockT, []int{2, 1}) { t.Error("IsDecreasing should return true") } if !IsDecreasing(mockT, []int{5, 4, 3, 2, 1}) { t.Error("IsDecreasing should return true") } if IsDecreasing(mockT, []int{1, 1}) { t.Error("IsDecreasing should return false") } if IsDecreasing(mockT, []int{1, 2}) { t.Error("IsDecreasing should return false") } // Check error report for _, currCase := range []struct { collection interface{} msg string }{ {collection: []string{"a", "b"}, msg: `"a" is not greater than "b"`}, {collection: []int{1, 2}, msg: `"1" is not greater than "2"`}, {collection: []int{1, 2, 7, 6, 5, 4, 3}, msg: `"1" is not greater than "2"`}, {collection: []int{5, 4, 3, 1, 2}, msg: `"1" is not greater than "2"`}, {collection: []int8{1, 2}, msg: `"1" is not greater than "2"`}, {collection: []int16{1, 2}, msg: `"1" is not greater than "2"`}, {collection: []int32{1, 2}, msg: `"1" is not greater than "2"`}, {collection: []int64{1, 2}, msg: `"1" is not greater than "2"`}, {collection: []uint8{1, 2}, msg: `"1" is not greater than "2"`}, {collection: []uint16{1, 2}, msg: `"1" is not greater than "2"`}, {collection: []uint32{1, 2}, msg: `"1" is not greater than "2"`}, {collection: []uint64{1, 2}, msg: `"1" is not greater than "2"`}, {collection: []float32{1.23, 2.34}, msg: `"1.23" is not greater than "2.34"`}, {collection: []float64{1.23, 2.34}, msg: `"1.23" is not greater than "2.34"`}, } { out := &outputT{buf: bytes.NewBuffer(nil)} False(t, IsDecreasing(out, currCase.collection)) Contains(t, out.buf.String(), currCase.msg) } } func TestIsNonDecreasing(t *testing.T) { mockT := new(testing.T) if !IsNonDecreasing(mockT, []int{1, 2}) { t.Error("IsNonDecreasing should return true") } if !IsNonDecreasing(mockT, []int{1, 1, 2, 3, 4, 5}) { t.Error("IsNonDecreasing should return true") } if !IsNonDecreasing(mockT, []int{1, 1}) { t.Error("IsNonDecreasing should return false") } if IsNonDecreasing(mockT, []int{2, 1}) { t.Error("IsNonDecreasing should return false") } // Check error report for _, currCase := range []struct { collection interface{} msg string }{ {collection: []string{"b", "a"}, msg: `"b" is not less than or equal to "a"`}, {collection: []int{2, 1}, msg: `"2" is not less than or equal to "1"`}, {collection: []int{2, 1, 3, 4, 5, 6, 7}, msg: `"2" is not less than or equal to "1"`}, {collection: []int{-1, 0, 2, 1}, msg: `"2" is not less than or equal to "1"`}, {collection: []int8{2, 1}, msg: `"2" is not less than or equal to "1"`}, {collection: []int16{2, 1}, msg: `"2" is not less than or equal to "1"`}, {collection: []int32{2, 1}, msg: `"2" is not less than or equal to "1"`}, {collection: []int64{2, 1}, msg: `"2" is not less than or equal to "1"`}, {collection: []uint8{2, 1}, msg: `"2" is not less than or equal to "1"`}, {collection: []uint16{2, 1}, msg: `"2" is not less than or equal to "1"`}, {collection: []uint32{2, 1}, msg: `"2" is not less than or equal to "1"`}, {collection: []uint64{2, 1}, msg: `"2" is not less than or equal to "1"`}, {collection: []float32{2.34, 1.23}, msg: `"2.34" is not less than or equal to "1.23"`}, {collection: []float64{2.34, 1.23}, msg: `"2.34" is not less than or equal to "1.23"`}, } { out := &outputT{buf: bytes.NewBuffer(nil)} False(t, IsNonDecreasing(out, currCase.collection)) Contains(t, out.buf.String(), currCase.msg) } } func TestOrderingMsgAndArgsForwarding(t *testing.T) { msgAndArgs := []interface{}{"format %s %x", "this", 0xc001} expectedOutput := "format this c001\n" collection := []int{1, 2, 1} funcs := []func(t TestingT){ func(t TestingT) { IsIncreasing(t, collection, msgAndArgs...) }, func(t TestingT) { IsNonIncreasing(t, collection, msgAndArgs...) }, func(t TestingT) { IsDecreasing(t, collection, msgAndArgs...) }, func(t TestingT) { IsNonDecreasing(t, collection, msgAndArgs...) }, } for _, f := range funcs { out := &outputT{buf: bytes.NewBuffer(nil)} f(out) Contains(t, out.buf.String(), expectedOutput) } } ================================================ FILE: internal/testify/assert/assertions.go ================================================ package assert import ( "bufio" "bytes" "encoding/json" "errors" "fmt" "math" "os" "reflect" "regexp" "runtime" "runtime/debug" "strings" "time" "unicode" "unicode/utf8" "github.com/expr-lang/expr/internal/spew" "github.com/expr-lang/expr/internal/difflib" ) //go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl" // TestingT is an interface wrapper around *testing.T type TestingT interface { Errorf(format string, args ...interface{}) } // ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful // for table driven tests. type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) bool // ValueAssertionFunc is a common function prototype when validating a single value. Can be useful // for table driven tests. type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) bool // BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful // for table driven tests. type BoolAssertionFunc func(TestingT, bool, ...interface{}) bool // ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful // for table driven tests. type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool // PanicAssertionFunc is a common function prototype when validating a panic value. Can be useful // for table driven tests. type PanicAssertionFunc = func(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool // Comparison is a custom function that returns true on success and false on failure type Comparison func() (success bool) /* Helper functions */ // ObjectsAreEqual determines if two objects are considered equal. // // This function does no assertion of any kind. func ObjectsAreEqual(expected, actual interface{}) bool { if expected == nil || actual == nil { return expected == actual } exp, ok := expected.([]byte) if !ok { return reflect.DeepEqual(expected, actual) } act, ok := actual.([]byte) if !ok { return false } if exp == nil || act == nil { return exp == nil && act == nil } return bytes.Equal(exp, act) } // copyExportedFields iterates downward through nested data structures and creates a copy // that only contains the exported struct fields. func copyExportedFields(expected interface{}) interface{} { if isNil(expected) { return expected } expectedType := reflect.TypeOf(expected) expectedKind := expectedType.Kind() expectedValue := reflect.ValueOf(expected) switch expectedKind { case reflect.Struct: result := reflect.New(expectedType).Elem() for i := 0; i < expectedType.NumField(); i++ { field := expectedType.Field(i) isExported := field.IsExported() if isExported { fieldValue := expectedValue.Field(i) if isNil(fieldValue) || isNil(fieldValue.Interface()) { continue } newValue := copyExportedFields(fieldValue.Interface()) result.Field(i).Set(reflect.ValueOf(newValue)) } } return result.Interface() case reflect.Ptr: result := reflect.New(expectedType.Elem()) unexportedRemoved := copyExportedFields(expectedValue.Elem().Interface()) result.Elem().Set(reflect.ValueOf(unexportedRemoved)) return result.Interface() case reflect.Array, reflect.Slice: var result reflect.Value if expectedKind == reflect.Array { result = reflect.New(reflect.ArrayOf(expectedValue.Len(), expectedType.Elem())).Elem() } else { result = reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len()) } for i := 0; i < expectedValue.Len(); i++ { index := expectedValue.Index(i) if isNil(index) { continue } unexportedRemoved := copyExportedFields(index.Interface()) result.Index(i).Set(reflect.ValueOf(unexportedRemoved)) } return result.Interface() case reflect.Map: result := reflect.MakeMap(expectedType) for _, k := range expectedValue.MapKeys() { index := expectedValue.MapIndex(k) unexportedRemoved := copyExportedFields(index.Interface()) result.SetMapIndex(k, reflect.ValueOf(unexportedRemoved)) } return result.Interface() default: return expected } } // ObjectsExportedFieldsAreEqual determines if the exported (public) fields of two objects are // considered equal. This comparison of only exported fields is applied recursively to nested data // structures. // // This function does no assertion of any kind. // // Deprecated: Use [EqualExportedValues] instead. func ObjectsExportedFieldsAreEqual(expected, actual interface{}) bool { expectedCleaned := copyExportedFields(expected) actualCleaned := copyExportedFields(actual) return ObjectsAreEqualValues(expectedCleaned, actualCleaned) } // ObjectsAreEqualValues gets whether two objects are equal, or if their // values are equal. func ObjectsAreEqualValues(expected, actual interface{}) bool { if ObjectsAreEqual(expected, actual) { return true } expectedValue := reflect.ValueOf(expected) actualValue := reflect.ValueOf(actual) if !expectedValue.IsValid() || !actualValue.IsValid() { return false } expectedType := expectedValue.Type() actualType := actualValue.Type() if !expectedType.ConvertibleTo(actualType) { return false } if !isNumericType(expectedType) || !isNumericType(actualType) { // Attempt comparison after type conversion return reflect.DeepEqual( expectedValue.Convert(actualType).Interface(), actual, ) } // If BOTH values are numeric, there are chances of false positives due // to overflow or underflow. So, we need to make sure to always convert // the smaller type to a larger type before comparing. if expectedType.Size() >= actualType.Size() { return actualValue.Convert(expectedType).Interface() == expected } return expectedValue.Convert(actualType).Interface() == actual } // isNumericType returns true if the type is one of: // int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, // float32, float64, complex64, complex128 func isNumericType(t reflect.Type) bool { return t.Kind() >= reflect.Int && t.Kind() <= reflect.Complex128 } /* CallerInfo is necessary because the assert functions use the testing object internally, causing it to print the file:line of the assert method, rather than where the problem actually occurred in calling code.*/ // CallerInfo returns an array of strings containing the file and line number // of each stack frame leading from the current test to the assert call that // failed. func CallerInfo() []string { var pc uintptr var ok bool var file string var line int var name string callers := []string{} for i := 0; ; i++ { pc, file, line, ok = runtime.Caller(i) if !ok { // The breaks below failed to terminate the loop, and we ran off the // end of the call stack. break } // This is a huge edge case, but it will panic if this is the case, see #180 if file == "" { break } f := runtime.FuncForPC(pc) if f == nil { break } name = f.Name() // testing.tRunner is the standard library function that calls // tests. Subtests are called directly by tRunner, without going through // the Test/Benchmark/Example function that contains the t.Run calls, so // with subtests we should break when we hit tRunner, without adding it // to the list of callers. if name == "testing.tRunner" { break } parts := strings.Split(file, "/") if len(parts) > 1 { filename := parts[len(parts)-1] dir := parts[len(parts)-2] if (dir != "assert" && dir != "mock" && dir != "require") || filename == "mock_test.go" { callers = append(callers, fmt.Sprintf("%s:%d", file, line)) } } // Drop the package segments := strings.Split(name, ".") name = segments[len(segments)-1] if isTest(name, "Test") || isTest(name, "Benchmark") || isTest(name, "Example") { break } } return callers } // Stolen from the `go test` tool. // isTest tells whether name looks like a test (or benchmark, according to prefix). // It is a Test (say) if there is a character after Test that is not a lower-case letter. // We don't want TesticularCancer. func isTest(name, prefix string) bool { if !strings.HasPrefix(name, prefix) { return false } if len(name) == len(prefix) { // "Test" is ok return true } r, _ := utf8.DecodeRuneInString(name[len(prefix):]) return !unicode.IsLower(r) } func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { if len(msgAndArgs) == 0 || msgAndArgs == nil { return "" } if len(msgAndArgs) == 1 { msg := msgAndArgs[0] if msgAsStr, ok := msg.(string); ok { return msgAsStr } return fmt.Sprintf("%+v", msg) } if len(msgAndArgs) > 1 { return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...) } return "" } // Aligns the provided message so that all lines after the first line start at the same location as the first line. // Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab). // The longestLabelLen parameter specifies the length of the longest label in the output (required because this is the // basis on which the alignment occurs). func indentMessageLines(message string, longestLabelLen int) string { outBuf := new(bytes.Buffer) for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ { // no need to align first line because it starts at the correct location (after the label) if i != 0 { // append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab outBuf.WriteString("\n\t" + strings.Repeat(" ", longestLabelLen+1) + "\t") } outBuf.WriteString(scanner.Text()) } return outBuf.String() } type failNower interface { FailNow() } // FailNow fails test func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } Fail(t, failureMessage, msgAndArgs...) // We cannot extend TestingT with FailNow() and // maintain backwards compatibility, so we fallback // to panicking when FailNow is not available in // TestingT. // See issue #263 if t, ok := t.(failNower); ok { t.FailNow() } else { panic("test failed and t is missing `FailNow()`") } return false } // Fail reports a failure through func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } content := []labeledContent{ {"Error Trace", strings.Join(CallerInfo(), "\n\t\t\t")}, {"Error", failureMessage}, } // Add test name if the Go version supports it if n, ok := t.(interface { Name() string }); ok { content = append(content, labeledContent{"Test", n.Name()}) } message := messageFromMsgAndArgs(msgAndArgs...) if len(message) > 0 { content = append(content, labeledContent{"Messages", message}) } t.Errorf("\n%s", ""+labeledOutput(content...)) return false } type labeledContent struct { label string content string } // labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner: // // \t{{label}}:{{align_spaces}}\t{{content}}\n // // The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label. // If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this // alignment is achieved, "\t{{content}}\n" is added for the output. // // If the content of the labeledOutput contains line breaks, the subsequent lines are aligned so that they start at the same location as the first line. func labeledOutput(content ...labeledContent) string { longestLabel := 0 for _, v := range content { if len(v.label) > longestLabel { longestLabel = len(v.label) } } var output string for _, v := range content { output += "\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n" } return output } // Implements asserts that an object is implemented by the specified interface. // // assert.Implements(t, (*MyInterface)(nil), new(MyObject)) func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } interfaceType := reflect.TypeOf(interfaceObject).Elem() if object == nil { return Fail(t, fmt.Sprintf("Cannot check if nil implements %v", interfaceType), msgAndArgs...) } if !reflect.TypeOf(object).Implements(interfaceType) { return Fail(t, fmt.Sprintf("%T must implement %v", object, interfaceType), msgAndArgs...) } return true } // NotImplements asserts that an object does not implement the specified interface. // // assert.NotImplements(t, (*MyInterface)(nil), new(MyObject)) func NotImplements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } interfaceType := reflect.TypeOf(interfaceObject).Elem() if object == nil { return Fail(t, fmt.Sprintf("Cannot check if nil does not implement %v", interfaceType), msgAndArgs...) } if reflect.TypeOf(object).Implements(interfaceType) { return Fail(t, fmt.Sprintf("%T implements %v", object, interfaceType), msgAndArgs...) } return true } // IsType asserts that the specified objects are of the same type. func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) { return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...) } return true } // Equal asserts that two objects are equal. // // assert.Equal(t, 123, 123) // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } if err := validateEqualArgs(expected, actual); err != nil { return Fail(t, fmt.Sprintf("Invalid operation: %#v == %#v (%s)", expected, actual, err), msgAndArgs...) } if !ObjectsAreEqual(expected, actual) { diff := diff(expected, actual) expected, actual = formatUnequalValues(expected, actual) return Fail(t, fmt.Sprintf("Not equal: \n"+ "expected: %s\n"+ "actual : %s%s", expected, actual, diff), msgAndArgs...) } return true } // validateEqualArgs checks whether provided arguments can be safely used in the // Equal/NotEqual functions. func validateEqualArgs(expected, actual interface{}) error { if expected == nil && actual == nil { return nil } if isFunction(expected) || isFunction(actual) { return errors.New("cannot take func type as argument") } return nil } // Same asserts that two pointers reference the same object. // // assert.Same(t, ptr1, ptr2) // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } if !samePointers(expected, actual) { return Fail(t, fmt.Sprintf("Not same: \n"+ "expected: %p %#v\n"+ "actual : %p %#v", expected, expected, actual, actual), msgAndArgs...) } return true } // NotSame asserts that two pointers do not reference the same object. // // assert.NotSame(t, ptr1, ptr2) // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. func NotSame(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } if samePointers(expected, actual) { return Fail(t, fmt.Sprintf( "Expected and actual point to the same object: %p %#v", expected, expected), msgAndArgs...) } return true } // samePointers compares two generic interface objects and returns whether // they point to the same object func samePointers(first, second interface{}) bool { firstPtr, secondPtr := reflect.ValueOf(first), reflect.ValueOf(second) if firstPtr.Kind() != reflect.Ptr || secondPtr.Kind() != reflect.Ptr { return false } firstType, secondType := reflect.TypeOf(first), reflect.TypeOf(second) if firstType != secondType { return false } // compare pointer addresses return first == second } // formatUnequalValues takes two values of arbitrary types and returns string // representations appropriate to be presented to the user. // // If the values are not of like type, the returned strings will be prefixed // with the type name, and the value will be enclosed in parentheses similar // to a type conversion in the Go grammar. func formatUnequalValues(expected, actual interface{}) (e string, a string) { if reflect.TypeOf(expected) != reflect.TypeOf(actual) { return fmt.Sprintf("%T(%s)", expected, truncatingFormat(expected)), fmt.Sprintf("%T(%s)", actual, truncatingFormat(actual)) } switch expected.(type) { case time.Duration: return fmt.Sprintf("%v", expected), fmt.Sprintf("%v", actual) } return truncatingFormat(expected), truncatingFormat(actual) } // truncatingFormat formats the data and truncates it if it's too long. // // This helps keep formatted error messages lines from exceeding the // bufio.MaxScanTokenSize max line length that the go testing framework imposes. func truncatingFormat(data interface{}) string { value := fmt.Sprintf("%#v", data) max := bufio.MaxScanTokenSize - 100 // Give us some space the type info too if needed. if len(value) > max { value = value[0:max] + "<... truncated>" } return value } // EqualValues asserts that two objects are equal or convertible to the same types // and equal. // // assert.EqualValues(t, uint32(123), int32(123)) func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } if !ObjectsAreEqualValues(expected, actual) { diff := diff(expected, actual) expected, actual = formatUnequalValues(expected, actual) return Fail(t, fmt.Sprintf("Not equal: \n"+ "expected: %s\n"+ "actual : %s%s", expected, actual, diff), msgAndArgs...) } return true } // EqualExportedValues asserts that the types of two objects are equal and their public // fields are also equal. This is useful for comparing structs that have private fields // that could potentially differ. // // type S struct { // Exported int // notExported int // } // assert.EqualExportedValues(t, S{1, 2}, S{1, 3}) => true // assert.EqualExportedValues(t, S{1, 2}, S{2, 3}) => false func EqualExportedValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } aType := reflect.TypeOf(expected) bType := reflect.TypeOf(actual) if aType != bType { return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...) } if aType.Kind() == reflect.Ptr { aType = aType.Elem() } if bType.Kind() == reflect.Ptr { bType = bType.Elem() } if aType.Kind() != reflect.Struct { return Fail(t, fmt.Sprintf("Types expected to both be struct or pointer to struct \n\t%v != %v", aType.Kind(), reflect.Struct), msgAndArgs...) } if bType.Kind() != reflect.Struct { return Fail(t, fmt.Sprintf("Types expected to both be struct or pointer to struct \n\t%v != %v", bType.Kind(), reflect.Struct), msgAndArgs...) } expected = copyExportedFields(expected) actual = copyExportedFields(actual) if !ObjectsAreEqualValues(expected, actual) { diff := diff(expected, actual) expected, actual = formatUnequalValues(expected, actual) return Fail(t, fmt.Sprintf("Not equal (comparing only exported fields): \n"+ "expected: %s\n"+ "actual : %s%s", expected, actual, diff), msgAndArgs...) } return true } // Exactly asserts that two objects are equal in value and type. // // assert.Exactly(t, int32(123), int64(123)) func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } aType := reflect.TypeOf(expected) bType := reflect.TypeOf(actual) if aType != bType { return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...) } return Equal(t, expected, actual, msgAndArgs...) } // NotNil asserts that the specified object is not nil. // // assert.NotNil(t, err) func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { if !isNil(object) { return true } if h, ok := t.(tHelper); ok { h.Helper() } return Fail(t, "Expected value not to be nil.", msgAndArgs...) } // isNil checks if a specified object is nil or not, without Failing. func isNil(object interface{}) bool { if object == nil { return true } value := reflect.ValueOf(object) switch value.Kind() { case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer: return value.IsNil() } return false } // Nil asserts that the specified object is nil. // // assert.Nil(t, err) func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { if isNil(object) { return true } if h, ok := t.(tHelper); ok { h.Helper() } return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...) } // isEmpty gets whether the specified object is considered empty or not. func isEmpty(object interface{}) bool { // get nil case out of the way if object == nil { return true } objValue := reflect.ValueOf(object) switch objValue.Kind() { // collection types are empty when they have no element case reflect.Chan, reflect.Map, reflect.Slice: return objValue.Len() == 0 // pointers are empty if nil or if the value they point to is empty case reflect.Ptr: if objValue.IsNil() { return true } deref := objValue.Elem().Interface() return isEmpty(deref) // for all other types, compare against the zero value // array types are empty when they match their zero-initialized state default: zero := reflect.Zero(objValue.Type()) return reflect.DeepEqual(object, zero.Interface()) } } // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // // assert.Empty(t, obj) func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { pass := isEmpty(object) if !pass { if h, ok := t.(tHelper); ok { h.Helper() } Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...) } return pass } // NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // // if assert.NotEmpty(t, obj) { // assert.Equal(t, "two", obj[1]) // } func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { pass := !isEmpty(object) if !pass { if h, ok := t.(tHelper); ok { h.Helper() } Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...) } return pass } // getLen tries to get the length of an object. // It returns (0, false) if impossible. func getLen(x interface{}) (length int, ok bool) { v := reflect.ValueOf(x) defer func() { ok = recover() == nil }() return v.Len(), true } // Len asserts that the specified object has specific length. // Len also fails if the object has a type that len() not accept. // // assert.Len(t, mySlice, 3) func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } l, ok := getLen(object) if !ok { return Fail(t, fmt.Sprintf("\"%v\" could not be applied builtin len()", object), msgAndArgs...) } if l != length { return Fail(t, fmt.Sprintf("\"%v\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) } return true } // True asserts that the specified value is true. // // assert.True(t, myBool) func True(t TestingT, value bool, msgAndArgs ...interface{}) bool { if !value { if h, ok := t.(tHelper); ok { h.Helper() } return Fail(t, "Should be true", msgAndArgs...) } return true } // False asserts that the specified value is false. // // assert.False(t, myBool) func False(t TestingT, value bool, msgAndArgs ...interface{}) bool { if value { if h, ok := t.(tHelper); ok { h.Helper() } return Fail(t, "Should be false", msgAndArgs...) } return true } // NotEqual asserts that the specified values are NOT equal. // // assert.NotEqual(t, obj1, obj2) // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } if err := validateEqualArgs(expected, actual); err != nil { return Fail(t, fmt.Sprintf("Invalid operation: %#v != %#v (%s)", expected, actual, err), msgAndArgs...) } if ObjectsAreEqual(expected, actual) { return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...) } return true } // NotEqualValues asserts that two objects are not equal even when converted to the same type // // assert.NotEqualValues(t, obj1, obj2) func NotEqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } if ObjectsAreEqualValues(expected, actual) { return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...) } return true } // containsElement try loop over the list check if the list includes the element. // return (false, false) if impossible. // return (true, false) if element was not found. // return (true, true) if element was found. func containsElement(list interface{}, element interface{}) (ok, found bool) { listValue := reflect.ValueOf(list) listType := reflect.TypeOf(list) if listType == nil { return false, false } listKind := listType.Kind() defer func() { if e := recover(); e != nil { ok = false found = false } }() if listKind == reflect.String { elementValue := reflect.ValueOf(element) return true, strings.Contains(listValue.String(), elementValue.String()) } if listKind == reflect.Map { mapKeys := listValue.MapKeys() for i := 0; i < len(mapKeys); i++ { if ObjectsAreEqual(mapKeys[i].Interface(), element) { return true, true } } return true, false } for i := 0; i < listValue.Len(); i++ { if ObjectsAreEqual(listValue.Index(i).Interface(), element) { return true, true } } return true, false } // Contains asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // // assert.Contains(t, "Hello World", "World") // assert.Contains(t, ["Hello", "World"], "World") // assert.Contains(t, {"Hello": "World"}, "Hello") func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } ok, found := containsElement(s, contains) if !ok { return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...) } if !found { return Fail(t, fmt.Sprintf("%#v does not contain %#v", s, contains), msgAndArgs...) } return true } // NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // // assert.NotContains(t, "Hello World", "Earth") // assert.NotContains(t, ["Hello", "World"], "Earth") // assert.NotContains(t, {"Hello": "World"}, "Earth") func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } ok, found := containsElement(s, contains) if !ok { return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", s), msgAndArgs...) } if found { return Fail(t, fmt.Sprintf("%#v should not contain %#v", s, contains), msgAndArgs...) } return true } // Subset asserts that the specified list(array, slice...) or map contains all // elements given in the specified subset list(array, slice...) or map. // // assert.Subset(t, [1, 2, 3], [1, 2]) // assert.Subset(t, {"x": 1, "y": 2}, {"x": 1}) func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { if h, ok := t.(tHelper); ok { h.Helper() } if subset == nil { return true // we consider nil to be equal to the nil set } listKind := reflect.TypeOf(list).Kind() if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map { return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) } subsetKind := reflect.TypeOf(subset).Kind() if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map { return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) } if subsetKind == reflect.Map && listKind == reflect.Map { subsetMap := reflect.ValueOf(subset) actualMap := reflect.ValueOf(list) for _, k := range subsetMap.MapKeys() { ev := subsetMap.MapIndex(k) av := actualMap.MapIndex(k) if !av.IsValid() { return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...) } if !ObjectsAreEqual(ev.Interface(), av.Interface()) { return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, subset), msgAndArgs...) } } return true } subsetList := reflect.ValueOf(subset) for i := 0; i < subsetList.Len(); i++ { element := subsetList.Index(i).Interface() ok, found := containsElement(list, element) if !ok { return Fail(t, fmt.Sprintf("%#v could not be applied builtin len()", list), msgAndArgs...) } if !found { return Fail(t, fmt.Sprintf("%#v does not contain %#v", list, element), msgAndArgs...) } } return true } // NotSubset asserts that the specified list(array, slice...) or map does NOT // contain all elements given in the specified subset list(array, slice...) or // map. // // assert.NotSubset(t, [1, 3, 4], [1, 2]) // assert.NotSubset(t, {"x": 1, "y": 2}, {"z": 3}) func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { if h, ok := t.(tHelper); ok { h.Helper() } if subset == nil { return Fail(t, "nil is the empty set which is a subset of every set", msgAndArgs...) } listKind := reflect.TypeOf(list).Kind() if listKind != reflect.Array && listKind != reflect.Slice && listKind != reflect.Map { return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) } subsetKind := reflect.TypeOf(subset).Kind() if subsetKind != reflect.Array && subsetKind != reflect.Slice && listKind != reflect.Map { return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) } if subsetKind == reflect.Map && listKind == reflect.Map { subsetMap := reflect.ValueOf(subset) actualMap := reflect.ValueOf(list) for _, k := range subsetMap.MapKeys() { ev := subsetMap.MapIndex(k) av := actualMap.MapIndex(k) if !av.IsValid() { return true } if !ObjectsAreEqual(ev.Interface(), av.Interface()) { return true } } return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...) } subsetList := reflect.ValueOf(subset) for i := 0; i < subsetList.Len(); i++ { element := subsetList.Index(i).Interface() ok, found := containsElement(list, element) if !ok { return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) } if !found { return true } } return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...) } // ElementsMatch asserts that the specified listA(array, slice...) is equal to specified // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // // assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2]) func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) { if h, ok := t.(tHelper); ok { h.Helper() } if isEmpty(listA) && isEmpty(listB) { return true } if !isList(t, listA, msgAndArgs...) || !isList(t, listB, msgAndArgs...) { return false } extraA, extraB := diffLists(listA, listB) if len(extraA) == 0 && len(extraB) == 0 { return true } return Fail(t, formatListDiff(listA, listB, extraA, extraB), msgAndArgs...) } // isList checks that the provided value is array or slice. func isList(t TestingT, list interface{}, msgAndArgs ...interface{}) (ok bool) { kind := reflect.TypeOf(list).Kind() if kind != reflect.Array && kind != reflect.Slice { return Fail(t, fmt.Sprintf("%q has an unsupported type %s, expecting array or slice", list, kind), msgAndArgs...) } return true } // diffLists diffs two arrays/slices and returns slices of elements that are only in A and only in B. // If some element is present multiple times, each instance is counted separately (e.g. if something is 2x in A and // 5x in B, it will be 0x in extraA and 3x in extraB). The order of items in both lists is ignored. func diffLists(listA, listB interface{}) (extraA, extraB []interface{}) { aValue := reflect.ValueOf(listA) bValue := reflect.ValueOf(listB) aLen := aValue.Len() bLen := bValue.Len() // Mark indexes in bValue that we already used visited := make([]bool, bLen) for i := 0; i < aLen; i++ { element := aValue.Index(i).Interface() found := false for j := 0; j < bLen; j++ { if visited[j] { continue } if ObjectsAreEqual(bValue.Index(j).Interface(), element) { visited[j] = true found = true break } } if !found { extraA = append(extraA, element) } } for j := 0; j < bLen; j++ { if visited[j] { continue } extraB = append(extraB, bValue.Index(j).Interface()) } return } func formatListDiff(listA, listB interface{}, extraA, extraB []interface{}) string { var msg bytes.Buffer msg.WriteString("elements differ") if len(extraA) > 0 { msg.WriteString("\n\nextra elements in list A:\n") msg.WriteString(spewConfig.Sdump(extraA)) } if len(extraB) > 0 { msg.WriteString("\n\nextra elements in list B:\n") msg.WriteString(spewConfig.Sdump(extraB)) } msg.WriteString("\n\nlistA:\n") msg.WriteString(spewConfig.Sdump(listA)) msg.WriteString("\n\nlistB:\n") msg.WriteString(spewConfig.Sdump(listB)) return msg.String() } // Condition uses a Comparison to assert a complex condition. func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } result := comp() if !result { Fail(t, "Condition failed!", msgAndArgs...) } return result } // PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics // methods, and represents a simple func that takes no arguments, and returns nothing. type PanicTestFunc func() // didPanic returns true if the function passed to it panics. Otherwise, it returns false. func didPanic(f PanicTestFunc) (didPanic bool, message interface{}, stack string) { didPanic = true defer func() { message = recover() if didPanic { stack = string(debug.Stack()) } }() // call the target function f() didPanic = false return } // Panics asserts that the code inside the specified PanicTestFunc panics. // // assert.Panics(t, func(){ GoCrazy() }) func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } if funcDidPanic, panicValue, _ := didPanic(f); !funcDidPanic { return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) } return true } // PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // // assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } funcDidPanic, panicValue, panickedStack := didPanic(f) if !funcDidPanic { return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) } if panicValue != expected { return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, expected, panicValue, panickedStack), msgAndArgs...) } return true } // PanicsWithError asserts that the code inside the specified PanicTestFunc // panics, and that the recovered panic value is an error that satisfies the // EqualError comparison. // // assert.PanicsWithError(t, "crazy error", func(){ GoCrazy() }) func PanicsWithError(t TestingT, errString string, f PanicTestFunc, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } funcDidPanic, panicValue, panickedStack := didPanic(f) if !funcDidPanic { return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) } panicErr, ok := panicValue.(error) if !ok || panicErr.Error() != errString { return Fail(t, fmt.Sprintf("func %#v should panic with error message:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, errString, panicValue, panickedStack), msgAndArgs...) } return true } // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. // // assert.NotPanics(t, func(){ RemainCalm() }) func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } if funcDidPanic, panicValue, panickedStack := didPanic(f); funcDidPanic { return Fail(t, fmt.Sprintf("func %#v should not panic\n\tPanic value:\t%v\n\tPanic stack:\t%s", f, panicValue, panickedStack), msgAndArgs...) } return true } // WithinDuration asserts that the two times are within duration delta of each other. // // assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } dt := expected.Sub(actual) if dt < -delta || dt > delta { return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) } return true } // WithinRange asserts that a time is within a time range (inclusive). // // assert.WithinRange(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) func WithinRange(t TestingT, actual, start, end time.Time, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } if end.Before(start) { return Fail(t, "Start should be before end", msgAndArgs...) } if actual.Before(start) { return Fail(t, fmt.Sprintf("Time %v expected to be in time range %v to %v, but is before the range", actual, start, end), msgAndArgs...) } else if actual.After(end) { return Fail(t, fmt.Sprintf("Time %v expected to be in time range %v to %v, but is after the range", actual, start, end), msgAndArgs...) } return true } func toFloat(x interface{}) (float64, bool) { var xf float64 xok := true switch xn := x.(type) { case uint: xf = float64(xn) case uint8: xf = float64(xn) case uint16: xf = float64(xn) case uint32: xf = float64(xn) case uint64: xf = float64(xn) case int: xf = float64(xn) case int8: xf = float64(xn) case int16: xf = float64(xn) case int32: xf = float64(xn) case int64: xf = float64(xn) case float32: xf = float64(xn) case float64: xf = xn case time.Duration: xf = float64(xn) default: xok = false } return xf, xok } // InDelta asserts that the two numerals are within delta of each other. // // assert.InDelta(t, math.Pi, 22/7.0, 0.01) func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } af, aok := toFloat(expected) bf, bok := toFloat(actual) if !aok || !bok { return Fail(t, "Parameters must be numerical", msgAndArgs...) } if math.IsNaN(af) && math.IsNaN(bf) { return true } if math.IsNaN(af) { return Fail(t, "Expected must not be NaN", msgAndArgs...) } if math.IsNaN(bf) { return Fail(t, fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...) } dt := af - bf if dt < -delta || dt > delta { return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) } return true } // InDeltaSlice is the same as InDelta, except it compares two slices. func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } if expected == nil || actual == nil || reflect.TypeOf(actual).Kind() != reflect.Slice || reflect.TypeOf(expected).Kind() != reflect.Slice { return Fail(t, "Parameters must be slice", msgAndArgs...) } actualSlice := reflect.ValueOf(actual) expectedSlice := reflect.ValueOf(expected) for i := 0; i < actualSlice.Len(); i++ { result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta, msgAndArgs...) if !result { return result } } return true } // InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } if expected == nil || actual == nil || reflect.TypeOf(actual).Kind() != reflect.Map || reflect.TypeOf(expected).Kind() != reflect.Map { return Fail(t, "Arguments must be maps", msgAndArgs...) } expectedMap := reflect.ValueOf(expected) actualMap := reflect.ValueOf(actual) if expectedMap.Len() != actualMap.Len() { return Fail(t, "Arguments must have the same number of keys", msgAndArgs...) } for _, k := range expectedMap.MapKeys() { ev := expectedMap.MapIndex(k) av := actualMap.MapIndex(k) if !ev.IsValid() { return Fail(t, fmt.Sprintf("missing key %q in expected map", k), msgAndArgs...) } if !av.IsValid() { return Fail(t, fmt.Sprintf("missing key %q in actual map", k), msgAndArgs...) } if !InDelta( t, ev.Interface(), av.Interface(), delta, msgAndArgs..., ) { return false } } return true } func calcRelativeError(expected, actual interface{}) (float64, error) { af, aok := toFloat(expected) bf, bok := toFloat(actual) if !aok || !bok { return 0, fmt.Errorf("Parameters must be numerical") } if math.IsNaN(af) && math.IsNaN(bf) { return 0, nil } if math.IsNaN(af) { return 0, errors.New("expected value must not be NaN") } if af == 0 { return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error") } if math.IsNaN(bf) { return 0, errors.New("actual value must not be NaN") } return math.Abs(af-bf) / math.Abs(af), nil } // InEpsilon asserts that expected and actual have a relative error less than epsilon func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } if math.IsNaN(epsilon) { return Fail(t, "epsilon must not be NaN", msgAndArgs...) } actualEpsilon, err := calcRelativeError(expected, actual) if err != nil { return Fail(t, err.Error(), msgAndArgs...) } if actualEpsilon > epsilon { return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+ " < %#v (actual)", epsilon, actualEpsilon), msgAndArgs...) } return true } // InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } if expected == nil || actual == nil { return Fail(t, "Parameters must be slice", msgAndArgs...) } expectedSlice := reflect.ValueOf(expected) actualSlice := reflect.ValueOf(actual) if expectedSlice.Type().Kind() != reflect.Slice { return Fail(t, "Expected value must be slice", msgAndArgs...) } expectedLen := expectedSlice.Len() if !IsType(t, expected, actual) || !Len(t, actual, expectedLen) { return false } for i := 0; i < expectedLen; i++ { if !InEpsilon(t, expectedSlice.Index(i).Interface(), actualSlice.Index(i).Interface(), epsilon, "at index %d", i) { return false } } return true } /* Errors */ // NoError asserts that a function returned no error (i.e. `nil`). // // actualObj, err := SomeFunction() // if assert.NoError(t, err) { // assert.Equal(t, expectedObj, actualObj) // } func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool { if err != nil { if h, ok := t.(tHelper); ok { h.Helper() } return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...) } return true } // Error asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() // if assert.Error(t, err) { // assert.Equal(t, expectedError, err) // } func Error(t TestingT, err error, msgAndArgs ...interface{}) bool { if err == nil { if h, ok := t.(tHelper); ok { h.Helper() } return Fail(t, "An error is expected but got nil.", msgAndArgs...) } return true } // EqualError asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // // actualObj, err := SomeFunction() // assert.EqualError(t, err, expectedErrorString) func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } if !Error(t, theError, msgAndArgs...) { return false } expected := errString actual := theError.Error() // don't need to use deep equals here, we know they are both strings if expected != actual { return Fail(t, fmt.Sprintf("Error message not equal:\n"+ "expected: %q\n"+ "actual : %q", expected, actual), msgAndArgs...) } return true } // ErrorContains asserts that a function returned an error (i.e. not `nil`) // and that the error contains the specified substring. // // actualObj, err := SomeFunction() // assert.ErrorContains(t, err, expectedErrorSubString) func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } if !Error(t, theError, msgAndArgs...) { return false } actual := theError.Error() if !strings.Contains(actual, contains) { return Fail(t, fmt.Sprintf("Error %#v does not contain %#v", actual, contains), msgAndArgs...) } return true } // matchRegexp return true if a specified regexp matches a string. func matchRegexp(rx interface{}, str interface{}) bool { var r *regexp.Regexp if rr, ok := rx.(*regexp.Regexp); ok { r = rr } else { r = regexp.MustCompile(fmt.Sprint(rx)) } return (r.FindStringIndex(fmt.Sprint(str)) != nil) } // Regexp asserts that a specified regexp matches a string. // // assert.Regexp(t, regexp.MustCompile("start"), "it's starting") // assert.Regexp(t, "start...$", "it's not starting") func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } match := matchRegexp(rx, str) if !match { Fail(t, fmt.Sprintf("Expect \"%v\" to match \"%v\"", str, rx), msgAndArgs...) } return match } // NotRegexp asserts that a specified regexp does not match a string. // // assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") // assert.NotRegexp(t, "^start", "it's not starting") func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } match := matchRegexp(rx, str) if match { Fail(t, fmt.Sprintf("Expect \"%v\" to NOT match \"%v\"", str, rx), msgAndArgs...) } return !match } // Zero asserts that i is the zero value for its type. func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...) } return true } // NotZero asserts that i is not the zero value for its type. func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...) } return true } // FileExists checks whether a file exists in the given path. It also fails if // the path points to a directory or there is an error when trying to check the file. func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } info, err := os.Lstat(path) if err != nil { if os.IsNotExist(err) { return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...) } return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...) } if info.IsDir() { return Fail(t, fmt.Sprintf("%q is a directory", path), msgAndArgs...) } return true } // NoFileExists checks whether a file does not exist in a given path. It fails // if the path points to an existing _file_ only. func NoFileExists(t TestingT, path string, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } info, err := os.Lstat(path) if err != nil { return true } if info.IsDir() { return true } return Fail(t, fmt.Sprintf("file %q exists", path), msgAndArgs...) } // DirExists checks whether a directory exists in the given path. It also fails // if the path is a file rather a directory or there is an error checking whether it exists. func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } info, err := os.Lstat(path) if err != nil { if os.IsNotExist(err) { return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...) } return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...) } if !info.IsDir() { return Fail(t, fmt.Sprintf("%q is a file", path), msgAndArgs...) } return true } // NoDirExists checks whether a directory does not exist in the given path. // It fails if the path points to an existing _directory_ only. func NoDirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } info, err := os.Lstat(path) if err != nil { if os.IsNotExist(err) { return true } return true } if !info.IsDir() { return true } return Fail(t, fmt.Sprintf("directory %q exists", path), msgAndArgs...) } // JSONEq asserts that two JSON strings are equivalent. // // assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } var expectedJSONAsInterface, actualJSONAsInterface interface{} if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil { return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid json.\nJSON parsing error: '%s'", expected, err.Error()), msgAndArgs...) } if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil { return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...) } return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...) } func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) { t := reflect.TypeOf(v) k := t.Kind() if k == reflect.Ptr { t = t.Elem() k = t.Kind() } return t, k } // diff returns a diff of both values as long as both are of the same type and // are a struct, map, slice, array or string. Otherwise it returns an empty string. func diff(expected interface{}, actual interface{}) string { if expected == nil || actual == nil { return "" } et, ek := typeAndKind(expected) at, _ := typeAndKind(actual) if et != at { return "" } if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array && ek != reflect.String { return "" } var e, a string switch et { case reflect.TypeOf(""): e = reflect.ValueOf(expected).String() a = reflect.ValueOf(actual).String() case reflect.TypeOf(time.Time{}): e = spewConfigStringerEnabled.Sdump(expected) a = spewConfigStringerEnabled.Sdump(actual) default: e = spewConfig.Sdump(expected) a = spewConfig.Sdump(actual) } diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ A: difflib.SplitLines(e), B: difflib.SplitLines(a), FromFile: "Expected", FromDate: "", ToFile: "Actual", ToDate: "", Context: 1, }) return "\n\nDiff:\n" + diff } func isFunction(arg interface{}) bool { if arg == nil { return false } return reflect.TypeOf(arg).Kind() == reflect.Func } var spewConfig = spew.ConfigState{ Indent: " ", DisablePointerAddresses: true, DisableCapacities: true, SortKeys: true, DisableMethods: true, MaxDepth: 10, } var spewConfigStringerEnabled = spew.ConfigState{ Indent: " ", DisablePointerAddresses: true, DisableCapacities: true, SortKeys: true, MaxDepth: 10, } type tHelper = interface { Helper() } // Eventually asserts that given condition will be met in waitFor time, // periodically checking target function each tick. // // assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond) func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } ch := make(chan bool, 1) timer := time.NewTimer(waitFor) defer timer.Stop() ticker := time.NewTicker(tick) defer ticker.Stop() for tick := ticker.C; ; { select { case <-timer.C: return Fail(t, "Condition never satisfied", msgAndArgs...) case <-tick: tick = nil go func() { ch <- condition() }() case v := <-ch: if v { return true } tick = ticker.C } } } // CollectT implements the TestingT interface and collects all errors. type CollectT struct { errors []error } // Errorf collects the error. func (c *CollectT) Errorf(format string, args ...interface{}) { c.errors = append(c.errors, fmt.Errorf(format, args...)) } // FailNow panics. func (*CollectT) FailNow() { panic("Assertion failed") } // Deprecated: That was a method for internal usage that should not have been published. Now just panics. func (*CollectT) Reset() { panic("Reset() is deprecated") } // Deprecated: That was a method for internal usage that should not have been published. Now just panics. func (*CollectT) Copy(TestingT) { panic("Copy() is deprecated") } // EventuallyWithT asserts that given condition will be met in waitFor time, // periodically checking target function each tick. In contrast to Eventually, // it supplies a CollectT to the condition function, so that the condition // function can use the CollectT to call other assertions. // The condition is considered "met" if no errors are raised in a tick. // The supplied CollectT collects all errors from one tick (if there are any). // If the condition is not met before waitFor, the collected errors of // the last tick are copied to t. // // externalValue := false // go func() { // time.Sleep(8*time.Second) // externalValue = true // }() // assert.EventuallyWithT(t, func(c *assert.CollectT) { // // add assertions as needed; any assertion failure will fail the current tick // assert.True(c, externalValue, "expected 'externalValue' to be true") // }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false") func EventuallyWithT(t TestingT, condition func(collect *CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } var lastFinishedTickErrs []error ch := make(chan []error, 1) timer := time.NewTimer(waitFor) defer timer.Stop() ticker := time.NewTicker(tick) defer ticker.Stop() for tick := ticker.C; ; { select { case <-timer.C: for _, err := range lastFinishedTickErrs { t.Errorf("%v", err) } return Fail(t, "Condition never satisfied", msgAndArgs...) case <-tick: tick = nil go func() { collect := new(CollectT) defer func() { ch <- collect.errors }() condition(collect) }() case errs := <-ch: if len(errs) == 0 { return true } // Keep the errors from the last ended condition, so that they can be copied to t if timeout is reached. lastFinishedTickErrs = errs tick = ticker.C } } } // Never asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // // assert.Never(t, func() bool { return false; }, time.Second, 10*time.Millisecond) func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } ch := make(chan bool, 1) timer := time.NewTimer(waitFor) defer timer.Stop() ticker := time.NewTicker(tick) defer ticker.Stop() for tick := ticker.C; ; { select { case <-timer.C: return true case <-tick: tick = nil go func() { ch <- condition() }() case v := <-ch: if v { return Fail(t, "Condition satisfied", msgAndArgs...) } tick = ticker.C } } } // ErrorIs asserts that at least one of the errors in err's chain matches target. // This is a wrapper for errors.Is. func ErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } if errors.Is(err, target) { return true } var expectedText string if target != nil { expectedText = target.Error() } chain := buildErrorChainString(err) return Fail(t, fmt.Sprintf("Target error should be in err chain:\n"+ "expected: %q\n"+ "in chain: %s", expectedText, chain, ), msgAndArgs...) } // NotErrorIs asserts that at none of the errors in err's chain matches target. // This is a wrapper for errors.Is. func NotErrorIs(t TestingT, err, target error, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } if !errors.Is(err, target) { return true } var expectedText string if target != nil { expectedText = target.Error() } chain := buildErrorChainString(err) return Fail(t, fmt.Sprintf("Target error should not be in err chain:\n"+ "found: %q\n"+ "in chain: %s", expectedText, chain, ), msgAndArgs...) } // ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. // This is a wrapper for errors.As. func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } if errors.As(err, target) { return true } chain := buildErrorChainString(err) return Fail(t, fmt.Sprintf("Should be in error chain:\n"+ "expected: %q\n"+ "in chain: %s", target, chain, ), msgAndArgs...) } func buildErrorChainString(err error) string { if err == nil { return "" } e := errors.Unwrap(err) chain := fmt.Sprintf("%q", err.Error()) for e != nil { chain += fmt.Sprintf("\n\t%q", e.Error()) e = errors.Unwrap(e) } return chain } ================================================ FILE: internal/testify/assert/assertions_test.go ================================================ package assert import ( "bufio" "bytes" "encoding/json" "errors" "fmt" "io" "math" "os" "path/filepath" "reflect" "regexp" "runtime" "strings" "testing" "time" ) var ( i interface{} zeros = []interface{}{ false, byte(0), complex64(0), complex128(0), float32(0), float64(0), int(0), int8(0), int16(0), int32(0), int64(0), rune(0), uint(0), uint8(0), uint16(0), uint32(0), uint64(0), uintptr(0), "", [0]interface{}{}, []interface{}(nil), struct{ x int }{}, (*interface{})(nil), (func())(nil), nil, interface{}(nil), map[interface{}]interface{}(nil), (chan interface{})(nil), (<-chan interface{})(nil), (chan<- interface{})(nil), } nonZeros = []interface{}{ true, byte(1), complex64(1), complex128(1), float32(1), float64(1), int(1), int8(1), int16(1), int32(1), int64(1), rune(1), uint(1), uint8(1), uint16(1), uint32(1), uint64(1), uintptr(1), "s", [1]interface{}{1}, []interface{}{}, struct{ x int }{1}, (&i), (func() {}), interface{}(1), map[interface{}]interface{}{}, (make(chan interface{})), (<-chan interface{})(make(chan interface{})), (chan<- interface{})(make(chan interface{})), } ) // AssertionTesterInterface defines an interface to be used for testing assertion methods type AssertionTesterInterface interface { TestMethod() } // AssertionTesterConformingObject is an object that conforms to the AssertionTesterInterface interface type AssertionTesterConformingObject struct { } func (a *AssertionTesterConformingObject) TestMethod() { } // AssertionTesterNonConformingObject is an object that does not conform to the AssertionTesterInterface interface type AssertionTesterNonConformingObject struct { } func TestObjectsAreEqual(t *testing.T) { cases := []struct { expected interface{} actual interface{} result bool }{ // cases that are expected to be equal {"Hello World", "Hello World", true}, {123, 123, true}, {123.5, 123.5, true}, {[]byte("Hello World"), []byte("Hello World"), true}, {nil, nil, true}, // cases that are expected not to be equal {map[int]int{5: 10}, map[int]int{10: 20}, false}, {'x', "x", false}, {"x", 'x', false}, {0, 0.1, false}, {0.1, 0, false}, {time.Now, time.Now, false}, {func() {}, func() {}, false}, {uint32(10), int32(10), false}, } for _, c := range cases { t.Run(fmt.Sprintf("ObjectsAreEqual(%#v, %#v)", c.expected, c.actual), func(t *testing.T) { res := ObjectsAreEqual(c.expected, c.actual) if res != c.result { t.Errorf("ObjectsAreEqual(%#v, %#v) should return %#v", c.expected, c.actual, c.result) } }) } } func TestObjectsAreEqualValues(t *testing.T) { now := time.Now() cases := []struct { expected interface{} actual interface{} result bool }{ {uint32(10), int32(10), true}, {0, nil, false}, {nil, 0, false}, {now, now.In(time.Local), false}, // should not be time zone independent {int(270), int8(14), false}, // should handle overflow/underflow {int8(14), int(270), false}, {[]int{270, 270}, []int8{14, 14}, false}, {complex128(1e+100 + 1e+100i), complex64(complex(math.Inf(0), math.Inf(0))), false}, {complex64(complex(math.Inf(0), math.Inf(0))), complex128(1e+100 + 1e+100i), false}, {complex128(1e+100 + 1e+100i), 270, false}, {270, complex128(1e+100 + 1e+100i), false}, {complex128(1e+100 + 1e+100i), 3.14, false}, {3.14, complex128(1e+100 + 1e+100i), false}, {complex128(1e+10 + 1e+10i), complex64(1e+10 + 1e+10i), true}, {complex64(1e+10 + 1e+10i), complex128(1e+10 + 1e+10i), true}, } for _, c := range cases { t.Run(fmt.Sprintf("ObjectsAreEqualValues(%#v, %#v)", c.expected, c.actual), func(t *testing.T) { res := ObjectsAreEqualValues(c.expected, c.actual) if res != c.result { t.Errorf("ObjectsAreEqualValues(%#v, %#v) should return %#v", c.expected, c.actual, c.result) } }) } } type Nested struct { Exported interface{} notExported interface{} } type S struct { Exported1 interface{} Exported2 Nested notExported1 interface{} notExported2 Nested } type S2 struct { foo interface{} } type S3 struct { Exported1 *Nested Exported2 *Nested } type S4 struct { Exported1 []*Nested } type S5 struct { Exported Nested } type S6 struct { Exported string unexported string } func TestObjectsExportedFieldsAreEqual(t *testing.T) { intValue := 1 cases := []struct { expected interface{} actual interface{} result bool }{ {S{1, Nested{2, 3}, 4, Nested{5, 6}}, S{1, Nested{2, 3}, 4, Nested{5, 6}}, true}, {S{1, Nested{2, 3}, 4, Nested{5, 6}}, S{1, Nested{2, 3}, "a", Nested{5, 6}}, true}, {S{1, Nested{2, 3}, 4, Nested{5, 6}}, S{1, Nested{2, 3}, 4, Nested{5, "a"}}, true}, {S{1, Nested{2, 3}, 4, Nested{5, 6}}, S{1, Nested{2, 3}, 4, Nested{"a", "a"}}, true}, {S{1, Nested{2, 3}, 4, Nested{5, 6}}, S{1, Nested{2, "a"}, 4, Nested{5, 6}}, true}, {S{1, Nested{2, 3}, 4, Nested{5, 6}}, S{"a", Nested{2, 3}, 4, Nested{5, 6}}, false}, {S{1, Nested{2, 3}, 4, Nested{5, 6}}, S{1, Nested{"a", 3}, 4, Nested{5, 6}}, false}, {S{1, Nested{2, 3}, 4, Nested{5, 6}}, S2{1}, false}, {1, S{1, Nested{2, 3}, 4, Nested{5, 6}}, false}, {S3{&Nested{1, 2}, &Nested{3, 4}}, S3{&Nested{1, 2}, &Nested{3, 4}}, true}, {S3{nil, &Nested{3, 4}}, S3{nil, &Nested{3, 4}}, true}, {S3{&Nested{1, 2}, &Nested{3, 4}}, S3{&Nested{1, 2}, &Nested{3, "b"}}, true}, {S3{&Nested{1, 2}, &Nested{3, 4}}, S3{&Nested{1, "a"}, &Nested{3, "b"}}, true}, {S3{&Nested{1, 2}, &Nested{3, 4}}, S3{&Nested{"a", 2}, &Nested{3, 4}}, false}, {S3{&Nested{1, 2}, &Nested{3, 4}}, S3{}, false}, {S3{}, S3{}, true}, {S4{[]*Nested{{1, 2}}}, S4{[]*Nested{{1, 2}}}, true}, {S4{[]*Nested{{1, 2}}}, S4{[]*Nested{{1, 3}}}, true}, {S4{[]*Nested{{1, 2}, {3, 4}}}, S4{[]*Nested{{1, "a"}, {3, "b"}}}, true}, {S4{[]*Nested{{1, 2}, {3, 4}}}, S4{[]*Nested{{1, "a"}, {2, "b"}}}, false}, {Nested{&intValue, 2}, Nested{&intValue, 2}, true}, {Nested{&Nested{1, 2}, 3}, Nested{&Nested{1, "b"}, 3}, true}, {Nested{&Nested{1, 2}, 3}, Nested{nil, 3}, false}, { Nested{map[interface{}]*Nested{nil: nil}, 2}, Nested{map[interface{}]*Nested{nil: nil}, 2}, true, }, { Nested{map[interface{}]*Nested{"a": nil}, 2}, Nested{map[interface{}]*Nested{"a": nil}, 2}, true, }, { Nested{map[interface{}]*Nested{"a": nil}, 2}, Nested{map[interface{}]*Nested{"a": {1, 2}}, 2}, false, }, { Nested{map[interface{}]Nested{"a": {1, 2}, "b": {3, 4}}, 2}, Nested{map[interface{}]Nested{"a": {1, 5}, "b": {3, 7}}, 2}, true, }, { Nested{map[interface{}]Nested{"a": {1, 2}, "b": {3, 4}}, 2}, Nested{map[interface{}]Nested{"a": {2, 2}, "b": {3, 4}}, 2}, false, }, } for _, c := range cases { t.Run(fmt.Sprintf("ObjectsExportedFieldsAreEqual(%#v, %#v)", c.expected, c.actual), func(t *testing.T) { res := ObjectsExportedFieldsAreEqual(c.expected, c.actual) if res != c.result { t.Errorf("ObjectsExportedFieldsAreEqual(%#v, %#v) should return %#v", c.expected, c.actual, c.result) } }) } } func TestCopyExportedFields(t *testing.T) { intValue := 1 cases := []struct { input interface{} expected interface{} }{ { input: Nested{"a", "b"}, expected: Nested{"a", nil}, }, { input: Nested{&intValue, 2}, expected: Nested{&intValue, nil}, }, { input: Nested{nil, 3}, expected: Nested{nil, nil}, }, { input: S{1, Nested{2, 3}, 4, Nested{5, 6}}, expected: S{1, Nested{2, nil}, nil, Nested{}}, }, { input: S3{}, expected: S3{}, }, { input: S3{&Nested{1, 2}, &Nested{3, 4}}, expected: S3{&Nested{1, nil}, &Nested{3, nil}}, }, { input: S3{Exported1: &Nested{"a", "b"}}, expected: S3{Exported1: &Nested{"a", nil}}, }, { input: S4{[]*Nested{ nil, {1, 2}, }}, expected: S4{[]*Nested{ nil, {1, nil}, }}, }, { input: S4{[]*Nested{ {1, 2}}, }, expected: S4{[]*Nested{ {1, nil}}, }, }, { input: S4{[]*Nested{ {1, 2}, {3, 4}, }}, expected: S4{[]*Nested{ {1, nil}, {3, nil}, }}, }, { input: S5{Exported: Nested{"a", "b"}}, expected: S5{Exported: Nested{"a", nil}}, }, { input: S6{"a", "b"}, expected: S6{"a", ""}, }, } for _, c := range cases { t.Run("", func(t *testing.T) { output := copyExportedFields(c.input) if !ObjectsAreEqualValues(c.expected, output) { t.Errorf("%#v, %#v should be equal", c.expected, output) } }) } } func TestEqualExportedValues(t *testing.T) { cases := []struct { value1 interface{} value2 interface{} expectedEqual bool expectedFail string }{ { value1: S{1, Nested{2, 3}, 4, Nested{5, 6}}, value2: S{1, Nested{2, nil}, nil, Nested{}}, expectedEqual: true, }, { value1: S{1, Nested{2, 3}, 4, Nested{5, 6}}, value2: S{1, Nested{1, nil}, nil, Nested{}}, expectedEqual: false, expectedFail: ` Diff: --- Expected +++ Actual @@ -3,3 +3,3 @@ Exported2: (assert.Nested) { - Exported: (int) 2, + Exported: (int) 1, notExported: (interface {}) `, }, { value1: S3{&Nested{1, 2}, &Nested{3, 4}}, value2: S3{&Nested{"a", 2}, &Nested{3, 4}}, expectedEqual: false, expectedFail: ` Diff: --- Expected +++ Actual @@ -2,3 +2,3 @@ Exported1: (*assert.Nested)({ - Exported: (int) 1, + Exported: (string) (len=1) "a", notExported: (interface {}) `, }, { value1: S4{[]*Nested{ {1, 2}, {3, 4}, }}, value2: S4{[]*Nested{ {1, "a"}, {2, "b"}, }}, expectedEqual: false, expectedFail: ` Diff: --- Expected +++ Actual @@ -7,3 +7,3 @@ (*assert.Nested)({ - Exported: (int) 3, + Exported: (int) 2, notExported: (interface {}) `, }, { value1: S{[2]int{1, 2}, Nested{2, 3}, 4, Nested{5, 6}}, value2: S{[2]int{1, 2}, Nested{2, nil}, nil, Nested{}}, expectedEqual: true, }, { value1: &S{1, Nested{2, 3}, 4, Nested{5, 6}}, value2: &S{1, Nested{2, nil}, nil, Nested{}}, expectedEqual: true, }, { value1: &S{1, Nested{2, 3}, 4, Nested{5, 6}}, value2: &S{1, Nested{1, nil}, nil, Nested{}}, expectedEqual: false, expectedFail: ` Diff: --- Expected +++ Actual @@ -3,3 +3,3 @@ Exported2: (assert.Nested) { - Exported: (int) 2, + Exported: (int) 1, notExported: (interface {}) `, }, } for _, c := range cases { t.Run("", func(t *testing.T) { mockT := new(mockTestingT) actual := EqualExportedValues(mockT, c.value1, c.value2) if actual != c.expectedEqual { t.Errorf("Expected EqualExportedValues to be %t, but was %t", c.expectedEqual, actual) } actualFail := mockT.errorString() if !strings.Contains(actualFail, c.expectedFail) { t.Errorf("Contains failure should include %q but was %q", c.expectedFail, actualFail) } }) } } func TestImplements(t *testing.T) { mockT := new(testing.T) if !Implements(mockT, (*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject)) { t.Error("Implements method should return true: AssertionTesterConformingObject implements AssertionTesterInterface") } if Implements(mockT, (*AssertionTesterInterface)(nil), new(AssertionTesterNonConformingObject)) { t.Error("Implements method should return false: AssertionTesterNonConformingObject does not implements AssertionTesterInterface") } if Implements(mockT, (*AssertionTesterInterface)(nil), nil) { t.Error("Implements method should return false: nil does not implement AssertionTesterInterface") } } func TestNotImplements(t *testing.T) { mockT := new(testing.T) if !NotImplements(mockT, (*AssertionTesterInterface)(nil), new(AssertionTesterNonConformingObject)) { t.Error("NotImplements method should return true: AssertionTesterNonConformingObject does not implement AssertionTesterInterface") } if NotImplements(mockT, (*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject)) { t.Error("NotImplements method should return false: AssertionTesterConformingObject implements AssertionTesterInterface") } if NotImplements(mockT, (*AssertionTesterInterface)(nil), nil) { t.Error("NotImplements method should return false: nil can't be checked to be implementing AssertionTesterInterface or not") } } func TestIsType(t *testing.T) { mockT := new(testing.T) if !IsType(mockT, new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) { t.Error("IsType should return true: AssertionTesterConformingObject is the same type as AssertionTesterConformingObject") } if IsType(mockT, new(AssertionTesterConformingObject), new(AssertionTesterNonConformingObject)) { t.Error("IsType should return false: AssertionTesterConformingObject is not the same type as AssertionTesterNonConformingObject") } } func TestEqual(t *testing.T) { type myType string mockT := new(testing.T) var m map[string]interface{} cases := []struct { expected interface{} actual interface{} result bool remark string }{ {"Hello World", "Hello World", true, ""}, {123, 123, true, ""}, {123.5, 123.5, true, ""}, {[]byte("Hello World"), []byte("Hello World"), true, ""}, {nil, nil, true, ""}, {int32(123), int32(123), true, ""}, {uint64(123), uint64(123), true, ""}, {myType("1"), myType("1"), true, ""}, {&struct{}{}, &struct{}{}, true, "pointer equality is based on equality of underlying value"}, // Not expected to be equal {m["bar"], "something", false, ""}, {myType("1"), myType("2"), false, ""}, // A case that might be confusing, especially with numeric literals {10, uint(10), false, ""}, } for _, c := range cases { t.Run(fmt.Sprintf("Equal(%#v, %#v)", c.expected, c.actual), func(t *testing.T) { res := Equal(mockT, c.expected, c.actual) if res != c.result { t.Errorf("Equal(%#v, %#v) should return %#v: %s", c.expected, c.actual, c.result, c.remark) } }) } } func ptr(i int) *int { return &i } func TestSame(t *testing.T) { mockT := new(testing.T) if Same(mockT, ptr(1), ptr(1)) { t.Error("Same should return false") } if Same(mockT, 1, 1) { t.Error("Same should return false") } p := ptr(2) if Same(mockT, p, *p) { t.Error("Same should return false") } if !Same(mockT, p, p) { t.Error("Same should return true") } } func TestNotSame(t *testing.T) { mockT := new(testing.T) if !NotSame(mockT, ptr(1), ptr(1)) { t.Error("NotSame should return true; different pointers") } if !NotSame(mockT, 1, 1) { t.Error("NotSame should return true; constant inputs") } p := ptr(2) if !NotSame(mockT, p, *p) { t.Error("NotSame should return true; mixed-type inputs") } if NotSame(mockT, p, p) { t.Error("NotSame should return false") } } func Test_samePointers(t *testing.T) { p := ptr(2) type args struct { first interface{} second interface{} } tests := []struct { name string args args assertion BoolAssertionFunc }{ { name: "1 != 2", args: args{first: 1, second: 2}, assertion: False, }, { name: "1 != 1 (not same ptr)", args: args{first: 1, second: 1}, assertion: False, }, { name: "ptr(1) == ptr(1)", args: args{first: p, second: p}, assertion: True, }, { name: "int(1) != float32(1)", args: args{first: int(1), second: float32(1)}, assertion: False, }, { name: "array != slice", args: args{first: [2]int{1, 2}, second: []int{1, 2}}, assertion: False, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, samePointers(tt.args.first, tt.args.second)) }) } } // bufferT implements TestingT. Its implementation of Errorf writes the output that would be produced by // testing.T.Errorf to an internal bytes.Buffer. type bufferT struct { buf bytes.Buffer } func (t *bufferT) Errorf(format string, args ...interface{}) { // implementation of decorate is copied from testing.T decorate := func(s string) string { _, file, line, ok := runtime.Caller(3) // decorate + log + public function. if ok { // Truncate file name at last file name separator. if index := strings.LastIndex(file, "/"); index >= 0 { file = file[index+1:] } else if index = strings.LastIndex(file, "\\"); index >= 0 { file = file[index+1:] } } else { file = "???" line = 1 } buf := new(bytes.Buffer) // Every line is indented at least one tab. buf.WriteByte('\t') fmt.Fprintf(buf, "%s:%d: ", file, line) lines := strings.Split(s, "\n") if l := len(lines); l > 1 && lines[l-1] == "" { lines = lines[:l-1] } for i, line := range lines { if i > 0 { // Second and subsequent lines are indented an extra tab. buf.WriteString("\n\t\t") } buf.WriteString(line) } buf.WriteByte('\n') return buf.String() } t.buf.WriteString(decorate(fmt.Sprintf(format, args...))) } func TestStringEqual(t *testing.T) { for i, currCase := range []struct { equalWant string equalGot string msgAndArgs []interface{} want string }{ {equalWant: "hi, \nmy name is", equalGot: "what,\nmy name is", want: "\tassertions.go:\\d+: \n\t+Error Trace:\t\n\t+Error:\\s+Not equal:\\s+\n\\s+expected: \"hi, \\\\nmy name is\"\n\\s+actual\\s+: \"what,\\\\nmy name is\"\n\\s+Diff:\n\\s+-+ Expected\n\\s+\\++ Actual\n\\s+@@ -1,2 \\+1,2 @@\n\\s+-hi, \n\\s+\\+what,\n\\s+my name is"}, } { mockT := &bufferT{} Equal(mockT, currCase.equalWant, currCase.equalGot, currCase.msgAndArgs...) Regexp(t, regexp.MustCompile(currCase.want), mockT.buf.String(), "Case %d", i) } } func TestEqualFormatting(t *testing.T) { for i, currCase := range []struct { equalWant string equalGot string msgAndArgs []interface{} want string }{ {equalWant: "want", equalGot: "got", want: "\tassertions.go:\\d+: \n\t+Error Trace:\t\n\t+Error:\\s+Not equal:\\s+\n\\s+expected: \"want\"\n\\s+actual\\s+: \"got\"\n\\s+Diff:\n\\s+-+ Expected\n\\s+\\++ Actual\n\\s+@@ -1 \\+1 @@\n\\s+-want\n\\s+\\+got\n"}, {equalWant: "want", equalGot: "got", msgAndArgs: []interface{}{"hello, %v!", "world"}, want: "\tassertions.go:[0-9]+: \n\t+Error Trace:\t\n\t+Error:\\s+Not equal:\\s+\n\\s+expected: \"want\"\n\\s+actual\\s+: \"got\"\n\\s+Diff:\n\\s+-+ Expected\n\\s+\\++ Actual\n\\s+@@ -1 \\+1 @@\n\\s+-want\n\\s+\\+got\n\\s+Messages:\\s+hello, world!\n"}, {equalWant: "want", equalGot: "got", msgAndArgs: []interface{}{123}, want: "\tassertions.go:[0-9]+: \n\t+Error Trace:\t\n\t+Error:\\s+Not equal:\\s+\n\\s+expected: \"want\"\n\\s+actual\\s+: \"got\"\n\\s+Diff:\n\\s+-+ Expected\n\\s+\\++ Actual\n\\s+@@ -1 \\+1 @@\n\\s+-want\n\\s+\\+got\n\\s+Messages:\\s+123\n"}, {equalWant: "want", equalGot: "got", msgAndArgs: []interface{}{struct{ a string }{"hello"}}, want: "\tassertions.go:[0-9]+: \n\t+Error Trace:\t\n\t+Error:\\s+Not equal:\\s+\n\\s+expected: \"want\"\n\\s+actual\\s+: \"got\"\n\\s+Diff:\n\\s+-+ Expected\n\\s+\\++ Actual\n\\s+@@ -1 \\+1 @@\n\\s+-want\n\\s+\\+got\n\\s+Messages:\\s+{a:hello}\n"}, } { mockT := &bufferT{} Equal(mockT, currCase.equalWant, currCase.equalGot, currCase.msgAndArgs...) Regexp(t, regexp.MustCompile(currCase.want), mockT.buf.String(), "Case %d", i) } } func TestFormatUnequalValues(t *testing.T) { expected, actual := formatUnequalValues("foo", "bar") Equal(t, `"foo"`, expected, "value should not include type") Equal(t, `"bar"`, actual, "value should not include type") expected, actual = formatUnequalValues(123, 123) Equal(t, `123`, expected, "value should not include type") Equal(t, `123`, actual, "value should not include type") expected, actual = formatUnequalValues(int64(123), int32(123)) Equal(t, `int64(123)`, expected, "value should include type") Equal(t, `int32(123)`, actual, "value should include type") expected, actual = formatUnequalValues(int64(123), nil) Equal(t, `int64(123)`, expected, "value should include type") Equal(t, `()`, actual, "value should include type") type testStructType struct { Val string } expected, actual = formatUnequalValues(&testStructType{Val: "test"}, &testStructType{Val: "test"}) Equal(t, `&assert.testStructType{Val:"test"}`, expected, "value should not include type annotation") Equal(t, `&assert.testStructType{Val:"test"}`, actual, "value should not include type annotation") } func TestNotNil(t *testing.T) { mockT := new(testing.T) if !NotNil(mockT, new(AssertionTesterConformingObject)) { t.Error("NotNil should return true: object is not nil") } if NotNil(mockT, nil) { t.Error("NotNil should return false: object is nil") } if NotNil(mockT, (*struct{})(nil)) { t.Error("NotNil should return false: object is (*struct{})(nil)") } } func TestNil(t *testing.T) { mockT := new(testing.T) if !Nil(mockT, nil) { t.Error("Nil should return true: object is nil") } if !Nil(mockT, (*struct{})(nil)) { t.Error("Nil should return true: object is (*struct{})(nil)") } if Nil(mockT, new(AssertionTesterConformingObject)) { t.Error("Nil should return false: object is not nil") } } func TestTrue(t *testing.T) { mockT := new(testing.T) if !True(mockT, true) { t.Error("True should return true") } if True(mockT, false) { t.Error("True should return false") } } func TestFalse(t *testing.T) { mockT := new(testing.T) if !False(mockT, false) { t.Error("False should return true") } if False(mockT, true) { t.Error("False should return false") } } func TestExactly(t *testing.T) { mockT := new(testing.T) a := float32(1) b := float64(1) c := float32(1) d := float32(2) cases := []struct { expected interface{} actual interface{} result bool }{ {a, b, false}, {a, d, false}, {a, c, true}, {nil, a, false}, {a, nil, false}, } for _, c := range cases { t.Run(fmt.Sprintf("Exactly(%#v, %#v)", c.expected, c.actual), func(t *testing.T) { res := Exactly(mockT, c.expected, c.actual) if res != c.result { t.Errorf("Exactly(%#v, %#v) should return %#v", c.expected, c.actual, c.result) } }) } } func TestNotEqual(t *testing.T) { mockT := new(testing.T) cases := []struct { expected interface{} actual interface{} result bool }{ // cases that are expected not to match {"Hello World", "Hello World!", true}, {123, 1234, true}, {123.5, 123.55, true}, {[]byte("Hello World"), []byte("Hello World!"), true}, {nil, new(AssertionTesterConformingObject), true}, // cases that are expected to match {nil, nil, false}, {"Hello World", "Hello World", false}, {123, 123, false}, {123.5, 123.5, false}, {[]byte("Hello World"), []byte("Hello World"), false}, {new(AssertionTesterConformingObject), new(AssertionTesterConformingObject), false}, {&struct{}{}, &struct{}{}, false}, {func() int { return 23 }, func() int { return 24 }, false}, // A case that might be confusing, especially with numeric literals {int(10), uint(10), true}, } for _, c := range cases { t.Run(fmt.Sprintf("NotEqual(%#v, %#v)", c.expected, c.actual), func(t *testing.T) { res := NotEqual(mockT, c.expected, c.actual) if res != c.result { t.Errorf("NotEqual(%#v, %#v) should return %#v", c.expected, c.actual, c.result) } }) } } func TestNotEqualValues(t *testing.T) { mockT := new(testing.T) cases := []struct { expected interface{} actual interface{} result bool }{ // cases that are expected not to match {"Hello World", "Hello World!", true}, {123, 1234, true}, {123.5, 123.55, true}, {[]byte("Hello World"), []byte("Hello World!"), true}, {nil, new(AssertionTesterConformingObject), true}, // cases that are expected to match {nil, nil, false}, {"Hello World", "Hello World", false}, {123, 123, false}, {123.5, 123.5, false}, {[]byte("Hello World"), []byte("Hello World"), false}, {new(AssertionTesterConformingObject), new(AssertionTesterConformingObject), false}, {&struct{}{}, &struct{}{}, false}, // Different behavior from NotEqual() {func() int { return 23 }, func() int { return 24 }, true}, {int(10), int(11), true}, {int(10), uint(10), false}, {struct{}{}, struct{}{}, false}, } for _, c := range cases { t.Run(fmt.Sprintf("NotEqualValues(%#v, %#v)", c.expected, c.actual), func(t *testing.T) { res := NotEqualValues(mockT, c.expected, c.actual) if res != c.result { t.Errorf("NotEqualValues(%#v, %#v) should return %#v", c.expected, c.actual, c.result) } }) } } func TestContainsNotContains(t *testing.T) { type A struct { Name, Value string } list := []string{"Foo", "Bar"} complexList := []*A{ {"b", "c"}, {"d", "e"}, {"g", "h"}, {"j", "k"}, } simpleMap := map[interface{}]interface{}{"Foo": "Bar"} var zeroMap map[interface{}]interface{} cases := []struct { expected interface{} actual interface{} result bool }{ {"Hello World", "Hello", true}, {"Hello World", "Salut", false}, {list, "Bar", true}, {list, "Salut", false}, {complexList, &A{"g", "h"}, true}, {complexList, &A{"g", "e"}, false}, {simpleMap, "Foo", true}, {simpleMap, "Bar", false}, {zeroMap, "Bar", false}, } for _, c := range cases { t.Run(fmt.Sprintf("Contains(%#v, %#v)", c.expected, c.actual), func(t *testing.T) { mockT := new(testing.T) res := Contains(mockT, c.expected, c.actual) if res != c.result { if res { t.Errorf("Contains(%#v, %#v) should return true:\n\t%#v contains %#v", c.expected, c.actual, c.expected, c.actual) } else { t.Errorf("Contains(%#v, %#v) should return false:\n\t%#v does not contain %#v", c.expected, c.actual, c.expected, c.actual) } } }) } for _, c := range cases { t.Run(fmt.Sprintf("NotContains(%#v, %#v)", c.expected, c.actual), func(t *testing.T) { mockT := new(testing.T) res := NotContains(mockT, c.expected, c.actual) // NotContains should be inverse of Contains. If it's not, something is wrong if res == Contains(mockT, c.expected, c.actual) { if res { t.Errorf("NotContains(%#v, %#v) should return true:\n\t%#v does not contains %#v", c.expected, c.actual, c.expected, c.actual) } else { t.Errorf("NotContains(%#v, %#v) should return false:\n\t%#v contains %#v", c.expected, c.actual, c.expected, c.actual) } } }) } } func TestContainsNotContainsFailMessage(t *testing.T) { mockT := new(mockTestingT) type nonContainer struct { Value string } cases := []struct { assertion func(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool container interface{} instance interface{} expected string }{ { assertion: Contains, container: "Hello World", instance: errors.New("Hello"), expected: "\"Hello World\" does not contain &errors.errorString{s:\"Hello\"}", }, { assertion: Contains, container: map[string]int{"one": 1}, instance: "two", expected: "map[string]int{\"one\":1} does not contain \"two\"\n", }, { assertion: NotContains, container: map[string]int{"one": 1}, instance: "one", expected: "map[string]int{\"one\":1} should not contain \"one\"", }, { assertion: Contains, container: nonContainer{Value: "Hello"}, instance: "Hello", expected: "assert.nonContainer{Value:\"Hello\"} could not be applied builtin len()\n", }, { assertion: NotContains, container: nonContainer{Value: "Hello"}, instance: "Hello", expected: "assert.nonContainer{Value:\"Hello\"} could not be applied builtin len()\n", }, } for _, c := range cases { name := filepath.Base(runtime.FuncForPC(reflect.ValueOf(c.assertion).Pointer()).Name()) t.Run(fmt.Sprintf("%v(%T, %T)", name, c.container, c.instance), func(t *testing.T) { c.assertion(mockT, c.container, c.instance) actualFail := mockT.errorString() if !strings.Contains(actualFail, c.expected) { t.Errorf("Contains failure should include %q but was %q", c.expected, actualFail) } }) } } func TestContainsNotContainsOnNilValue(t *testing.T) { mockT := new(mockTestingT) Contains(mockT, nil, "key") expectedFail := " could not be applied builtin len()" actualFail := mockT.errorString() if !strings.Contains(actualFail, expectedFail) { t.Errorf("Contains failure should include %q but was %q", expectedFail, actualFail) } NotContains(mockT, nil, "key") if !strings.Contains(actualFail, expectedFail) { t.Errorf("Contains failure should include %q but was %q", expectedFail, actualFail) } } func TestSubsetNotSubset(t *testing.T) { cases := []struct { list interface{} subset interface{} result bool message string }{ // cases that are expected to contain {[]int{1, 2, 3}, nil, true, `nil is the empty set which is a subset of every set`}, {[]int{1, 2, 3}, []int{}, true, `[] is a subset of ['\x01' '\x02' '\x03']`}, {[]int{1, 2, 3}, []int{1, 2}, true, `['\x01' '\x02'] is a subset of ['\x01' '\x02' '\x03']`}, {[]int{1, 2, 3}, []int{1, 2, 3}, true, `['\x01' '\x02' '\x03'] is a subset of ['\x01' '\x02' '\x03']`}, {[]string{"hello", "world"}, []string{"hello"}, true, `["hello"] is a subset of ["hello" "world"]`}, {map[string]string{ "a": "x", "c": "z", "b": "y", }, map[string]string{ "a": "x", "b": "y", }, true, `map["a":"x" "b":"y"] is a subset of map["a":"x" "b":"y" "c":"z"]`}, // cases that are expected not to contain {[]string{"hello", "world"}, []string{"hello", "testify"}, false, `[]string{"hello", "world"} does not contain "testify"`}, {[]int{1, 2, 3}, []int{4, 5}, false, `[]int{1, 2, 3} does not contain 4`}, {[]int{1, 2, 3}, []int{1, 5}, false, `[]int{1, 2, 3} does not contain 5`}, {map[string]string{ "a": "x", "c": "z", "b": "y", }, map[string]string{ "a": "x", "b": "z", }, false, `map[string]string{"a":"x", "b":"y", "c":"z"} does not contain map[string]string{"a":"x", "b":"z"}`}, {map[string]string{ "a": "x", "b": "y", }, map[string]string{ "a": "x", "b": "y", "c": "z", }, false, `map[string]string{"a":"x", "b":"y"} does not contain map[string]string{"a":"x", "b":"y", "c":"z"}`}, } for _, c := range cases { t.Run("SubSet: "+c.message, func(t *testing.T) { mockT := new(mockTestingT) res := Subset(mockT, c.list, c.subset) if res != c.result { t.Errorf("Subset should return %t: %s", c.result, c.message) } if !c.result { expectedFail := c.message actualFail := mockT.errorString() if !strings.Contains(actualFail, expectedFail) { t.Log(actualFail) t.Errorf("Subset failure should contain %q but was %q", expectedFail, actualFail) } } }) } for _, c := range cases { t.Run("NotSubSet: "+c.message, func(t *testing.T) { mockT := new(mockTestingT) res := NotSubset(mockT, c.list, c.subset) // NotSubset should match the inverse of Subset. If it doesn't, something is wrong if res == Subset(mockT, c.list, c.subset) { t.Errorf("NotSubset should return %t: %s", !c.result, c.message) } if c.result { expectedFail := c.message actualFail := mockT.errorString() if !strings.Contains(actualFail, expectedFail) { t.Log(actualFail) t.Errorf("NotSubset failure should contain %q but was %q", expectedFail, actualFail) } } }) } } func TestNotSubsetNil(t *testing.T) { mockT := new(testing.T) NotSubset(mockT, []string{"foo"}, nil) if !mockT.Failed() { t.Error("NotSubset on nil set should have failed the test") } } func Test_containsElement(t *testing.T) { list1 := []string{"Foo", "Bar"} list2 := []int{1, 2} simpleMap := map[interface{}]interface{}{"Foo": "Bar"} ok, found := containsElement("Hello World", "World") True(t, ok) True(t, found) ok, found = containsElement(list1, "Foo") True(t, ok) True(t, found) ok, found = containsElement(list1, "Bar") True(t, ok) True(t, found) ok, found = containsElement(list2, 1) True(t, ok) True(t, found) ok, found = containsElement(list2, 2) True(t, ok) True(t, found) ok, found = containsElement(list1, "Foo!") True(t, ok) False(t, found) ok, found = containsElement(list2, 3) True(t, ok) False(t, found) ok, found = containsElement(list2, "1") True(t, ok) False(t, found) ok, found = containsElement(simpleMap, "Foo") True(t, ok) True(t, found) ok, found = containsElement(simpleMap, "Bar") True(t, ok) False(t, found) ok, found = containsElement(1433, "1") False(t, ok) False(t, found) } func TestElementsMatch(t *testing.T) { mockT := new(testing.T) cases := []struct { expected interface{} actual interface{} result bool }{ // matching {nil, nil, true}, {nil, nil, true}, {[]int{}, []int{}, true}, {[]int{1}, []int{1}, true}, {[]int{1, 1}, []int{1, 1}, true}, {[]int{1, 2}, []int{1, 2}, true}, {[]int{1, 2}, []int{2, 1}, true}, {[2]int{1, 2}, [2]int{2, 1}, true}, {[]string{"hello", "world"}, []string{"world", "hello"}, true}, {[]string{"hello", "hello"}, []string{"hello", "hello"}, true}, {[]string{"hello", "hello", "world"}, []string{"hello", "world", "hello"}, true}, {[3]string{"hello", "hello", "world"}, [3]string{"hello", "world", "hello"}, true}, {[]int{}, nil, true}, // not matching {[]int{1}, []int{1, 1}, false}, {[]int{1, 2}, []int{2, 2}, false}, {[]string{"hello", "hello"}, []string{"hello"}, false}, } for _, c := range cases { t.Run(fmt.Sprintf("ElementsMatch(%#v, %#v)", c.expected, c.actual), func(t *testing.T) { res := ElementsMatch(mockT, c.actual, c.expected) if res != c.result { t.Errorf("ElementsMatch(%#v, %#v) should return %v", c.actual, c.expected, c.result) } }) } } func TestDiffLists(t *testing.T) { tests := []struct { name string listA interface{} listB interface{} extraA []interface{} extraB []interface{} }{ { name: "equal empty", listA: []string{}, listB: []string{}, extraA: nil, extraB: nil, }, { name: "equal same order", listA: []string{"hello", "world"}, listB: []string{"hello", "world"}, extraA: nil, extraB: nil, }, { name: "equal different order", listA: []string{"hello", "world"}, listB: []string{"world", "hello"}, extraA: nil, extraB: nil, }, { name: "extra A", listA: []string{"hello", "hello", "world"}, listB: []string{"hello", "world"}, extraA: []interface{}{"hello"}, extraB: nil, }, { name: "extra A twice", listA: []string{"hello", "hello", "hello", "world"}, listB: []string{"hello", "world"}, extraA: []interface{}{"hello", "hello"}, extraB: nil, }, { name: "extra B", listA: []string{"hello", "world"}, listB: []string{"hello", "hello", "world"}, extraA: nil, extraB: []interface{}{"hello"}, }, { name: "extra B twice", listA: []string{"hello", "world"}, listB: []string{"hello", "hello", "world", "hello"}, extraA: nil, extraB: []interface{}{"hello", "hello"}, }, { name: "integers 1", listA: []int{1, 2, 3, 4, 5}, listB: []int{5, 4, 3, 2, 1}, extraA: nil, extraB: nil, }, { name: "integers 2", listA: []int{1, 2, 1, 2, 1}, listB: []int{2, 1, 2, 1, 2}, extraA: []interface{}{1}, extraB: []interface{}{2}, }, } for _, test := range tests { test := test t.Run(test.name, func(t *testing.T) { actualExtraA, actualExtraB := diffLists(test.listA, test.listB) Equal(t, test.extraA, actualExtraA, "extra A does not match for listA=%v listB=%v", test.listA, test.listB) Equal(t, test.extraB, actualExtraB, "extra B does not match for listA=%v listB=%v", test.listA, test.listB) }) } } func TestCondition(t *testing.T) { mockT := new(testing.T) if !Condition(mockT, func() bool { return true }, "Truth") { t.Error("Condition should return true") } if Condition(mockT, func() bool { return false }, "Lie") { t.Error("Condition should return false") } } func TestDidPanic(t *testing.T) { const panicMsg = "Panic!" if funcDidPanic, msg, _ := didPanic(func() { panic(panicMsg) }); !funcDidPanic || msg != panicMsg { t.Error("didPanic should return true, panicMsg") } if funcDidPanic, msg, _ := didPanic(func() { panic(nil) }); !funcDidPanic || msg != nil { t.Error("didPanic should return true, nil") } if funcDidPanic, _, _ := didPanic(func() { }); funcDidPanic { t.Error("didPanic should return false") } } func TestPanics(t *testing.T) { mockT := new(testing.T) if !Panics(mockT, func() { panic("Panic!") }) { t.Error("Panics should return true") } if Panics(mockT, func() { }) { t.Error("Panics should return false") } } func TestPanicsWithValue(t *testing.T) { mockT := new(testing.T) if !PanicsWithValue(mockT, "Panic!", func() { panic("Panic!") }) { t.Error("PanicsWithValue should return true") } if !PanicsWithValue(mockT, nil, func() { panic(nil) }) { t.Error("PanicsWithValue should return true") } if PanicsWithValue(mockT, "Panic!", func() { }) { t.Error("PanicsWithValue should return false") } if PanicsWithValue(mockT, "at the disco", func() { panic("Panic!") }) { t.Error("PanicsWithValue should return false") } } func TestPanicsWithError(t *testing.T) { mockT := new(testing.T) if !PanicsWithError(mockT, "panic", func() { panic(errors.New("panic")) }) { t.Error("PanicsWithError should return true") } if PanicsWithError(mockT, "Panic!", func() { }) { t.Error("PanicsWithError should return false") } if PanicsWithError(mockT, "at the disco", func() { panic(errors.New("panic")) }) { t.Error("PanicsWithError should return false") } if PanicsWithError(mockT, "Panic!", func() { panic("panic") }) { t.Error("PanicsWithError should return false") } } func TestNotPanics(t *testing.T) { mockT := new(testing.T) if !NotPanics(mockT, func() { }) { t.Error("NotPanics should return true") } if NotPanics(mockT, func() { panic("Panic!") }) { t.Error("NotPanics should return false") } } func TestNoError(t *testing.T) { mockT := new(testing.T) // start with a nil error var err error True(t, NoError(mockT, err), "NoError should return True for nil arg") // now set an error err = errors.New("some error") False(t, NoError(mockT, err), "NoError with error should return False") // returning an empty error interface err = func() error { var err *customError return err }() if err == nil { // err is not nil here! t.Errorf("Error should be nil due to empty interface: %s", err) } False(t, NoError(mockT, err), "NoError should fail with empty error interface") } type customError struct{} func (*customError) Error() string { return "fail" } func TestError(t *testing.T) { mockT := new(testing.T) // start with a nil error var err error False(t, Error(mockT, err), "Error should return False for nil arg") // now set an error err = errors.New("some error") True(t, Error(mockT, err), "Error with error should return True") // go vet check True(t, Errorf(mockT, err, "example with %s", "formatted message"), "Errorf with error should return True") // returning an empty error interface err = func() error { var err *customError return err }() if err == nil { // err is not nil here! t.Errorf("Error should be nil due to empty interface: %s", err) } True(t, Error(mockT, err), "Error should pass with empty error interface") } func TestEqualError(t *testing.T) { mockT := new(testing.T) // start with a nil error var err error False(t, EqualError(mockT, err, ""), "EqualError should return false for nil arg") // now set an error err = errors.New("some error") False(t, EqualError(mockT, err, "Not some error"), "EqualError should return false for different error string") True(t, EqualError(mockT, err, "some error"), "EqualError should return true") } func TestErrorContains(t *testing.T) { mockT := new(testing.T) // start with a nil error var err error False(t, ErrorContains(mockT, err, ""), "ErrorContains should return false for nil arg") // now set an error err = errors.New("some error: another error") False(t, ErrorContains(mockT, err, "bad error"), "ErrorContains should return false for different error string") True(t, ErrorContains(mockT, err, "some error"), "ErrorContains should return true") True(t, ErrorContains(mockT, err, "another error"), "ErrorContains should return true") } func Test_isEmpty(t *testing.T) { chWithValue := make(chan struct{}, 1) chWithValue <- struct{}{} True(t, isEmpty("")) True(t, isEmpty(nil)) True(t, isEmpty([]string{})) True(t, isEmpty(0)) True(t, isEmpty(int32(0))) True(t, isEmpty(int64(0))) True(t, isEmpty(false)) True(t, isEmpty(map[string]string{})) True(t, isEmpty(new(time.Time))) True(t, isEmpty(time.Time{})) True(t, isEmpty(make(chan struct{}))) True(t, isEmpty([1]int{})) False(t, isEmpty("something")) False(t, isEmpty(errors.New("something"))) False(t, isEmpty([]string{"something"})) False(t, isEmpty(1)) False(t, isEmpty(true)) False(t, isEmpty(map[string]string{"Hello": "World"})) False(t, isEmpty(chWithValue)) False(t, isEmpty([1]int{42})) } func TestEmpty(t *testing.T) { mockT := new(testing.T) chWithValue := make(chan struct{}, 1) chWithValue <- struct{}{} var tiP *time.Time var tiNP time.Time var s *string var f *os.File sP := &s x := 1 xP := &x type TString string type TStruct struct { x int } True(t, Empty(mockT, ""), "Empty string is empty") True(t, Empty(mockT, nil), "Nil is empty") True(t, Empty(mockT, []string{}), "Empty string array is empty") True(t, Empty(mockT, 0), "Zero int value is empty") True(t, Empty(mockT, false), "False value is empty") True(t, Empty(mockT, make(chan struct{})), "Channel without values is empty") True(t, Empty(mockT, s), "Nil string pointer is empty") True(t, Empty(mockT, f), "Nil os.File pointer is empty") True(t, Empty(mockT, tiP), "Nil time.Time pointer is empty") True(t, Empty(mockT, tiNP), "time.Time is empty") True(t, Empty(mockT, TStruct{}), "struct with zero values is empty") True(t, Empty(mockT, TString("")), "empty aliased string is empty") True(t, Empty(mockT, sP), "ptr to nil value is empty") True(t, Empty(mockT, [1]int{}), "array is state") False(t, Empty(mockT, "something"), "Non Empty string is not empty") False(t, Empty(mockT, errors.New("something")), "Non nil object is not empty") False(t, Empty(mockT, []string{"something"}), "Non empty string array is not empty") False(t, Empty(mockT, 1), "Non-zero int value is not empty") False(t, Empty(mockT, true), "True value is not empty") False(t, Empty(mockT, chWithValue), "Channel with values is not empty") False(t, Empty(mockT, TStruct{x: 1}), "struct with initialized values is empty") False(t, Empty(mockT, TString("abc")), "non-empty aliased string is empty") False(t, Empty(mockT, xP), "ptr to non-nil value is not empty") False(t, Empty(mockT, [1]int{42}), "array is not state") } func TestNotEmpty(t *testing.T) { mockT := new(testing.T) chWithValue := make(chan struct{}, 1) chWithValue <- struct{}{} False(t, NotEmpty(mockT, ""), "Empty string is empty") False(t, NotEmpty(mockT, nil), "Nil is empty") False(t, NotEmpty(mockT, []string{}), "Empty string array is empty") False(t, NotEmpty(mockT, 0), "Zero int value is empty") False(t, NotEmpty(mockT, false), "False value is empty") False(t, NotEmpty(mockT, make(chan struct{})), "Channel without values is empty") False(t, NotEmpty(mockT, [1]int{}), "array is state") True(t, NotEmpty(mockT, "something"), "Non Empty string is not empty") True(t, NotEmpty(mockT, errors.New("something")), "Non nil object is not empty") True(t, NotEmpty(mockT, []string{"something"}), "Non empty string array is not empty") True(t, NotEmpty(mockT, 1), "Non-zero int value is not empty") True(t, NotEmpty(mockT, true), "True value is not empty") True(t, NotEmpty(mockT, chWithValue), "Channel with values is not empty") True(t, NotEmpty(mockT, [1]int{42}), "array is not state") } func Test_getLen(t *testing.T) { falseCases := []interface{}{ nil, 0, true, false, 'A', struct{}{}, } for _, v := range falseCases { l, ok := getLen(v) False(t, ok, "Expected getLen fail to get length of %#v", v) Equal(t, 0, l, "getLen should return 0 for %#v", v) } ch := make(chan int, 5) ch <- 1 ch <- 2 ch <- 3 trueCases := []struct { v interface{} l int }{ {[]int{1, 2, 3}, 3}, {[...]int{1, 2, 3}, 3}, {"ABC", 3}, {map[int]int{1: 2, 2: 4, 3: 6}, 3}, {ch, 3}, {[]int{}, 0}, {map[int]int{}, 0}, {make(chan int), 0}, {[]int(nil), 0}, {map[int]int(nil), 0}, {(chan int)(nil), 0}, } for _, c := range trueCases { l, ok := getLen(c.v) True(t, ok, "Expected getLen success to get length of %#v", c.v) Equal(t, c.l, l) } } func TestLen(t *testing.T) { mockT := new(testing.T) False(t, Len(mockT, nil, 0), "nil does not have length") False(t, Len(mockT, 0, 0), "int does not have length") False(t, Len(mockT, true, 0), "true does not have length") False(t, Len(mockT, false, 0), "false does not have length") False(t, Len(mockT, 'A', 0), "Rune does not have length") False(t, Len(mockT, struct{}{}, 0), "Struct does not have length") ch := make(chan int, 5) ch <- 1 ch <- 2 ch <- 3 cases := []struct { v interface{} l int expected1234567 string // message when expecting 1234567 items }{ {[]int{1, 2, 3}, 3, `"[1 2 3]" should have 1234567 item(s), but has 3`}, {[...]int{1, 2, 3}, 3, `"[1 2 3]" should have 1234567 item(s), but has 3`}, {"ABC", 3, `"ABC" should have 1234567 item(s), but has 3`}, {map[int]int{1: 2, 2: 4, 3: 6}, 3, `"map[1:2 2:4 3:6]" should have 1234567 item(s), but has 3`}, {ch, 3, ""}, {[]int{}, 0, `"[]" should have 1234567 item(s), but has 0`}, {map[int]int{}, 0, `"map[]" should have 1234567 item(s), but has 0`}, {make(chan int), 0, ""}, {[]int(nil), 0, `"[]" should have 1234567 item(s), but has 0`}, {map[int]int(nil), 0, `"map[]" should have 1234567 item(s), but has 0`}, {(chan int)(nil), 0, `"" should have 1234567 item(s), but has 0`}, } for _, c := range cases { True(t, Len(mockT, c.v, c.l), "%#v have %d items", c.v, c.l) False(t, Len(mockT, c.v, c.l+1), "%#v have %d items", c.v, c.l) if c.expected1234567 != "" { msgMock := new(mockTestingT) Len(msgMock, c.v, 1234567) Contains(t, msgMock.errorString(), c.expected1234567) } } } func TestWithinDuration(t *testing.T) { mockT := new(testing.T) a := time.Now() b := a.Add(10 * time.Second) True(t, WithinDuration(mockT, a, b, 10*time.Second), "A 10s difference is within a 10s time difference") True(t, WithinDuration(mockT, b, a, 10*time.Second), "A 10s difference is within a 10s time difference") False(t, WithinDuration(mockT, a, b, 9*time.Second), "A 10s difference is not within a 9s time difference") False(t, WithinDuration(mockT, b, a, 9*time.Second), "A 10s difference is not within a 9s time difference") False(t, WithinDuration(mockT, a, b, -9*time.Second), "A 10s difference is not within a 9s time difference") False(t, WithinDuration(mockT, b, a, -9*time.Second), "A 10s difference is not within a 9s time difference") False(t, WithinDuration(mockT, a, b, -11*time.Second), "A 10s difference is not within a 9s time difference") False(t, WithinDuration(mockT, b, a, -11*time.Second), "A 10s difference is not within a 9s time difference") } func TestWithinRange(t *testing.T) { mockT := new(testing.T) n := time.Now() s := n.Add(-time.Second) e := n.Add(time.Second) True(t, WithinRange(mockT, n, n, n), "Exact same actual, start, and end values return true") True(t, WithinRange(mockT, n, s, e), "Time in range is within the time range") True(t, WithinRange(mockT, s, s, e), "The start time is within the time range") True(t, WithinRange(mockT, e, s, e), "The end time is within the time range") False(t, WithinRange(mockT, s.Add(-time.Nanosecond), s, e, "Just before the start time is not within the time range")) False(t, WithinRange(mockT, e.Add(time.Nanosecond), s, e, "Just after the end time is not within the time range")) False(t, WithinRange(mockT, n, e, s, "Just after the end time is not within the time range")) } func TestInDelta(t *testing.T) { mockT := new(testing.T) True(t, InDelta(mockT, 1.001, 1, 0.01), "|1.001 - 1| <= 0.01") True(t, InDelta(mockT, 1, 1.001, 0.01), "|1 - 1.001| <= 0.01") True(t, InDelta(mockT, 1, 2, 1), "|1 - 2| <= 1") False(t, InDelta(mockT, 1, 2, 0.5), "Expected |1 - 2| <= 0.5 to fail") False(t, InDelta(mockT, 2, 1, 0.5), "Expected |2 - 1| <= 0.5 to fail") False(t, InDelta(mockT, "", nil, 1), "Expected non numerals to fail") False(t, InDelta(mockT, 42, math.NaN(), 0.01), "Expected NaN for actual to fail") False(t, InDelta(mockT, math.NaN(), 42, 0.01), "Expected NaN for expected to fail") True(t, InDelta(mockT, math.NaN(), math.NaN(), 0.01), "Expected NaN for both to pass") cases := []struct { a, b interface{} delta float64 }{ {uint(2), uint(1), 1}, {uint8(2), uint8(1), 1}, {uint16(2), uint16(1), 1}, {uint32(2), uint32(1), 1}, {uint64(2), uint64(1), 1}, {int(2), int(1), 1}, {int8(2), int8(1), 1}, {int16(2), int16(1), 1}, {int32(2), int32(1), 1}, {int64(2), int64(1), 1}, {float32(2), float32(1), 1}, {float64(2), float64(1), 1}, } for _, tc := range cases { True(t, InDelta(mockT, tc.a, tc.b, tc.delta), "Expected |%V - %V| <= %v", tc.a, tc.b, tc.delta) } } func TestInDeltaSlice(t *testing.T) { mockT := new(testing.T) True(t, InDeltaSlice(mockT, []float64{1.001, math.NaN(), 0.999}, []float64{1, math.NaN(), 1}, 0.1), "{1.001, NaN, 0.009} is element-wise close to {1, NaN, 1} in delta=0.1") True(t, InDeltaSlice(mockT, []float64{1, math.NaN(), 2}, []float64{0, math.NaN(), 3}, 1), "{1, NaN, 2} is element-wise close to {0, NaN, 3} in delta=1") False(t, InDeltaSlice(mockT, []float64{1, math.NaN(), 2}, []float64{0, math.NaN(), 3}, 0.1), "{1, NaN, 2} is not element-wise close to {0, NaN, 3} in delta=0.1") False(t, InDeltaSlice(mockT, "", nil, 1), "Expected non numeral slices to fail") } func TestInDeltaMapValues(t *testing.T) { mockT := new(testing.T) for _, tc := range []struct { title string expect interface{} actual interface{} f func(TestingT, bool, ...interface{}) bool delta float64 }{ { title: "Within delta", expect: map[string]float64{ "foo": 1.0, "bar": 2.0, "baz": math.NaN(), }, actual: map[string]float64{ "foo": 1.01, "bar": 1.99, "baz": math.NaN(), }, delta: 0.1, f: True, }, { title: "Within delta", expect: map[int]float64{ 1: 1.0, 2: 2.0, }, actual: map[int]float64{ 1: 1.0, 2: 1.99, }, delta: 0.1, f: True, }, { title: "Different number of keys", expect: map[int]float64{ 1: 1.0, 2: 2.0, }, actual: map[int]float64{ 1: 1.0, }, delta: 0.1, f: False, }, { title: "Within delta with zero value", expect: map[string]float64{ "zero": 0, }, actual: map[string]float64{ "zero": 0, }, delta: 0.1, f: True, }, { title: "With missing key with zero value", expect: map[string]float64{ "zero": 0, "foo": 0, }, actual: map[string]float64{ "zero": 0, "bar": 0, }, f: False, }, } { tc.f(t, InDeltaMapValues(mockT, tc.expect, tc.actual, tc.delta), tc.title+"\n"+diff(tc.expect, tc.actual)) } } func TestInEpsilon(t *testing.T) { mockT := new(testing.T) cases := []struct { a, b interface{} epsilon float64 }{ {uint8(2), uint16(2), .001}, {2.1, 2.2, 0.1}, {2.2, 2.1, 0.1}, {-2.1, -2.2, 0.1}, {-2.2, -2.1, 0.1}, {uint64(100), uint8(101), 0.01}, {0.1, -0.1, 2}, {0.1, 0, 2}, {math.NaN(), math.NaN(), 1}, {time.Second, time.Second + time.Millisecond, 0.002}, } for _, tc := range cases { True(t, InEpsilon(t, tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon), "test: %q", tc) } cases = []struct { a, b interface{} epsilon float64 }{ {uint8(2), int16(-2), .001}, {uint64(100), uint8(102), 0.01}, {2.1, 2.2, 0.001}, {2.2, 2.1, 0.001}, {2.1, -2.2, 1}, {2.1, "bla-bla", 0}, {0.1, -0.1, 1.99}, {0, 0.1, 2}, // expected must be different to zero {time.Second, time.Second + 10*time.Millisecond, 0.002}, {math.NaN(), 0, 1}, {0, math.NaN(), 1}, {0, 0, math.NaN()}, } for _, tc := range cases { False(t, InEpsilon(mockT, tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon)) } } func TestInEpsilonSlice(t *testing.T) { mockT := new(testing.T) True(t, InEpsilonSlice(mockT, []float64{2.2, math.NaN(), 2.0}, []float64{2.1, math.NaN(), 2.1}, 0.06), "{2.2, NaN, 2.0} is element-wise close to {2.1, NaN, 2.1} in epsilon=0.06") False(t, InEpsilonSlice(mockT, []float64{2.2, 2.0}, []float64{2.1, 2.1}, 0.04), "{2.2, 2.0} is not element-wise close to {2.1, 2.1} in epsilon=0.04") False(t, InEpsilonSlice(mockT, "", nil, 1), "Expected non numeral slices to fail") } func TestRegexp(t *testing.T) { mockT := new(testing.T) cases := []struct { rx, str string }{ {"^start", "start of the line"}, {"end$", "in the end"}, {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12.34"}, } for _, tc := range cases { True(t, Regexp(mockT, tc.rx, tc.str)) True(t, Regexp(mockT, regexp.MustCompile(tc.rx), tc.str)) False(t, NotRegexp(mockT, tc.rx, tc.str)) False(t, NotRegexp(mockT, regexp.MustCompile(tc.rx), tc.str)) } cases = []struct { rx, str string }{ {"^asdfastart", "Not the start of the line"}, {"end$", "in the end."}, {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12a.34"}, } for _, tc := range cases { False(t, Regexp(mockT, tc.rx, tc.str), "Expected \"%s\" to not match \"%s\"", tc.rx, tc.str) False(t, Regexp(mockT, regexp.MustCompile(tc.rx), tc.str)) True(t, NotRegexp(mockT, tc.rx, tc.str)) True(t, NotRegexp(mockT, regexp.MustCompile(tc.rx), tc.str)) } } func testAutogeneratedFunction() { defer func() { if err := recover(); err == nil { panic("did not panic") } CallerInfo() }() t := struct { io.Closer }{} c := t c.Close() } func TestCallerInfoWithAutogeneratedFunctions(t *testing.T) { NotPanics(t, func() { testAutogeneratedFunction() }) } func TestZero(t *testing.T) { mockT := new(testing.T) for _, test := range zeros { True(t, Zero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test))) } for _, test := range nonZeros { False(t, Zero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test))) } } func TestNotZero(t *testing.T) { mockT := new(testing.T) for _, test := range zeros { False(t, NotZero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test))) } for _, test := range nonZeros { True(t, NotZero(mockT, test, "%#v is not the %v zero value", test, reflect.TypeOf(test))) } } func TestFileExists(t *testing.T) { mockT := new(testing.T) True(t, FileExists(mockT, "assertions.go")) mockT = new(testing.T) False(t, FileExists(mockT, "random_file")) mockT = new(testing.T) False(t, FileExists(mockT, "../_codegen")) var tempFiles []string link, err := getTempSymlinkPath("assertions.go") if err != nil { t.Fatal("could not create temp symlink, err:", err) } tempFiles = append(tempFiles, link) mockT = new(testing.T) True(t, FileExists(mockT, link)) link, err = getTempSymlinkPath("non_existent_file") if err != nil { t.Fatal("could not create temp symlink, err:", err) } tempFiles = append(tempFiles, link) mockT = new(testing.T) True(t, FileExists(mockT, link)) errs := cleanUpTempFiles(tempFiles) if len(errs) > 0 { t.Fatal("could not clean up temporary files") } } func TestNoFileExists(t *testing.T) { mockT := new(testing.T) False(t, NoFileExists(mockT, "assertions.go")) mockT = new(testing.T) True(t, NoFileExists(mockT, "non_existent_file")) mockT = new(testing.T) True(t, NoFileExists(mockT, "../_codegen")) var tempFiles []string link, err := getTempSymlinkPath("assertions.go") if err != nil { t.Fatal("could not create temp symlink, err:", err) } tempFiles = append(tempFiles, link) mockT = new(testing.T) False(t, NoFileExists(mockT, link)) link, err = getTempSymlinkPath("non_existent_file") if err != nil { t.Fatal("could not create temp symlink, err:", err) } tempFiles = append(tempFiles, link) mockT = new(testing.T) False(t, NoFileExists(mockT, link)) errs := cleanUpTempFiles(tempFiles) if len(errs) > 0 { t.Fatal("could not clean up temporary files") } } func getTempSymlinkPath(file string) (string, error) { link := file + "_symlink" err := os.Symlink(file, link) return link, err } func cleanUpTempFiles(paths []string) []error { var res []error for _, path := range paths { err := os.Remove(path) if err != nil { res = append(res, err) } } return res } func TestDirExists(t *testing.T) { mockT := new(testing.T) False(t, DirExists(mockT, "assertions.go")) mockT = new(testing.T) False(t, DirExists(mockT, "non_existent_dir")) mockT = new(testing.T) True(t, DirExists(mockT, "../assert")) var tempFiles []string link, err := getTempSymlinkPath("assertions.go") if err != nil { t.Fatal("could not create temp symlink, err:", err) } tempFiles = append(tempFiles, link) mockT = new(testing.T) False(t, DirExists(mockT, link)) link, err = getTempSymlinkPath("non_existent_dir") if err != nil { t.Fatal("could not create temp symlink, err:", err) } tempFiles = append(tempFiles, link) mockT = new(testing.T) False(t, DirExists(mockT, link)) errs := cleanUpTempFiles(tempFiles) if len(errs) > 0 { t.Fatal("could not clean up temporary files") } } func TestNoDirExists(t *testing.T) { mockT := new(testing.T) True(t, NoDirExists(mockT, "assertions.go")) mockT = new(testing.T) True(t, NoDirExists(mockT, "non_existent_dir")) mockT = new(testing.T) False(t, NoDirExists(mockT, "../assert")) var tempFiles []string link, err := getTempSymlinkPath("assertions.go") if err != nil { t.Fatal("could not create temp symlink, err:", err) } tempFiles = append(tempFiles, link) mockT = new(testing.T) True(t, NoDirExists(mockT, link)) link, err = getTempSymlinkPath("non_existent_dir") if err != nil { t.Fatal("could not create temp symlink, err:", err) } tempFiles = append(tempFiles, link) mockT = new(testing.T) True(t, NoDirExists(mockT, link)) errs := cleanUpTempFiles(tempFiles) if len(errs) > 0 { t.Fatal("could not clean up temporary files") } } func TestJSONEq_EqualSONString(t *testing.T) { mockT := new(testing.T) True(t, JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`)) } func TestJSONEq_EquivalentButNotEqual(t *testing.T) { mockT := new(testing.T) True(t, JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)) } func TestJSONEq_HashOfArraysAndHashes(t *testing.T) { mockT := new(testing.T) True(t, JSONEq(mockT, "{\r\n\t\"numeric\": 1.5,\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]],\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\"\r\n}", "{\r\n\t\"numeric\": 1.5,\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\",\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]]\r\n}")) } func TestJSONEq_Array(t *testing.T) { mockT := new(testing.T) True(t, JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`)) } func TestJSONEq_HashAndArrayNotEquivalent(t *testing.T) { mockT := new(testing.T) False(t, JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`)) } func TestJSONEq_HashesNotEquivalent(t *testing.T) { mockT := new(testing.T) False(t, JSONEq(mockT, `{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`)) } func TestJSONEq_ActualIsNotJSON(t *testing.T) { mockT := new(testing.T) False(t, JSONEq(mockT, `{"foo": "bar"}`, "Not JSON")) } func TestJSONEq_ExpectedIsNotJSON(t *testing.T) { mockT := new(testing.T) False(t, JSONEq(mockT, "Not JSON", `{"foo": "bar", "hello": "world"}`)) } func TestJSONEq_ExpectedAndActualNotJSON(t *testing.T) { mockT := new(testing.T) False(t, JSONEq(mockT, "Not JSON", "Not JSON")) } func TestJSONEq_ArraysOfDifferentOrder(t *testing.T) { mockT := new(testing.T) False(t, JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`)) } type diffTestingStruct struct { A string B int } func (d *diffTestingStruct) String() string { return d.A } func TestDiff(t *testing.T) { expected := ` Diff: --- Expected +++ Actual @@ -1,3 +1,3 @@ (struct { foo string }) { - foo: (string) (len=5) "hello" + foo: (string) (len=3) "bar" } ` actual := diff( struct{ foo string }{"hello"}, struct{ foo string }{"bar"}, ) Equal(t, expected, actual) expected = ` Diff: --- Expected +++ Actual @@ -2,5 +2,5 @@ (int) 1, - (int) 2, (int) 3, - (int) 4 + (int) 5, + (int) 7 } ` actual = diff( []int{1, 2, 3, 4}, []int{1, 3, 5, 7}, ) Equal(t, expected, actual) expected = ` Diff: --- Expected +++ Actual @@ -2,4 +2,4 @@ (int) 1, - (int) 2, - (int) 3 + (int) 3, + (int) 5 } ` actual = diff( []int{1, 2, 3, 4}[0:3], []int{1, 3, 5, 7}[0:3], ) Equal(t, expected, actual) expected = ` Diff: --- Expected +++ Actual @@ -1,6 +1,6 @@ (map[string]int) (len=4) { - (string) (len=4) "four": (int) 4, + (string) (len=4) "five": (int) 5, (string) (len=3) "one": (int) 1, - (string) (len=5) "three": (int) 3, - (string) (len=3) "two": (int) 2 + (string) (len=5) "seven": (int) 7, + (string) (len=5) "three": (int) 3 } ` actual = diff( map[string]int{"one": 1, "two": 2, "three": 3, "four": 4}, map[string]int{"one": 1, "three": 3, "five": 5, "seven": 7}, ) Equal(t, expected, actual) expected = ` Diff: --- Expected +++ Actual @@ -1,3 +1,3 @@ (*errors.errorString)({ - s: (string) (len=19) "some expected error" + s: (string) (len=12) "actual error" }) ` actual = diff( errors.New("some expected error"), errors.New("actual error"), ) Equal(t, expected, actual) expected = ` Diff: --- Expected +++ Actual @@ -2,3 +2,3 @@ A: (string) (len=11) "some string", - B: (int) 10 + B: (int) 15 } ` actual = diff( diffTestingStruct{A: "some string", B: 10}, diffTestingStruct{A: "some string", B: 15}, ) Equal(t, expected, actual) expected = ` Diff: --- Expected +++ Actual @@ -1,2 +1,2 @@ -(time.Time) 2020-09-24 00:00:00 +0000 UTC +(time.Time) 2020-09-25 00:00:00 +0000 UTC ` actual = diff( time.Date(2020, 9, 24, 0, 0, 0, 0, time.UTC), time.Date(2020, 9, 25, 0, 0, 0, 0, time.UTC), ) Equal(t, expected, actual) } func TestTimeEqualityErrorFormatting(t *testing.T) { mockT := new(mockTestingT) Equal(mockT, time.Second*2, time.Millisecond) expectedErr := "\\s+Error Trace:\\s+Error:\\s+Not equal:\\s+\n\\s+expected: 2s\n\\s+actual\\s+: 1ms\n" Regexp(t, regexp.MustCompile(expectedErr), mockT.errorString()) } func TestDiffEmptyCases(t *testing.T) { Equal(t, "", diff(nil, nil)) Equal(t, "", diff(struct{ foo string }{}, nil)) Equal(t, "", diff(nil, struct{ foo string }{})) Equal(t, "", diff(1, 2)) Equal(t, "", diff(1, 2)) Equal(t, "", diff([]int{1}, []bool{true})) } // Ensure there are no data races func TestDiffRace(t *testing.T) { t.Parallel() expected := map[string]string{ "a": "A", "b": "B", "c": "C", } actual := map[string]string{ "d": "D", "e": "E", "f": "F", } // run diffs in parallel simulating tests with t.Parallel() numRoutines := 10 rChans := make([]chan string, numRoutines) for idx := range rChans { rChans[idx] = make(chan string) go func(ch chan string) { defer close(ch) ch <- diff(expected, actual) }(rChans[idx]) } for _, ch := range rChans { for msg := range ch { NotZero(t, msg) // dummy assert } } } type mockTestingT struct { errorFmt string args []interface{} } func (m *mockTestingT) errorString() string { return fmt.Sprintf(m.errorFmt, m.args...) } func (m *mockTestingT) Errorf(format string, args ...interface{}) { m.errorFmt = format m.args = args } func (m *mockTestingT) Failed() bool { return m.errorFmt != "" } func TestFailNowWithPlainTestingT(t *testing.T) { mockT := &mockTestingT{} Panics(t, func() { FailNow(mockT, "failed") }, "should panic since mockT is missing FailNow()") } type mockFailNowTestingT struct { } func (m *mockFailNowTestingT) Errorf(format string, args ...interface{}) {} func (m *mockFailNowTestingT) FailNow() {} func TestFailNowWithFullTestingT(t *testing.T) { mockT := &mockFailNowTestingT{} NotPanics(t, func() { FailNow(mockT, "failed") }, "should call mockT.FailNow() rather than panicking") } func TestBytesEqual(t *testing.T) { var cases = []struct { a, b []byte }{ {make([]byte, 2), make([]byte, 2)}, {make([]byte, 2), make([]byte, 2, 3)}, {nil, make([]byte, 0)}, } for i, c := range cases { Equal(t, reflect.DeepEqual(c.a, c.b), ObjectsAreEqual(c.a, c.b), "case %d failed", i+1) } } func BenchmarkBytesEqual(b *testing.B) { const size = 1024 * 8 s := make([]byte, size) for i := range s { s[i] = byte(i % 255) } s2 := make([]byte, size) copy(s2, s) mockT := &mockFailNowTestingT{} b.ResetTimer() for i := 0; i < b.N; i++ { Equal(mockT, s, s2) } } func BenchmarkNotNil(b *testing.B) { for i := 0; i < b.N; i++ { NotNil(b, b) } } func ExampleComparisonAssertionFunc() { t := &testing.T{} // provided by test adder := func(x, y int) int { return x + y } type args struct { x int y int } tests := []struct { name string args args expect int assertion ComparisonAssertionFunc }{ {"2+2=4", args{2, 2}, 4, Equal}, {"2+2!=5", args{2, 2}, 5, NotEqual}, {"2+3==5", args{2, 3}, 5, Exactly}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, tt.expect, adder(tt.args.x, tt.args.y)) }) } } func TestComparisonAssertionFunc(t *testing.T) { type iface interface { Name() string } tests := []struct { name string expect interface{} got interface{} assertion ComparisonAssertionFunc }{ {"implements", (*iface)(nil), t, Implements}, {"isType", (*testing.T)(nil), t, IsType}, {"equal", t, t, Equal}, {"equalValues", t, t, EqualValues}, {"notEqualValues", t, nil, NotEqualValues}, {"exactly", t, t, Exactly}, {"notEqual", t, nil, NotEqual}, {"notContains", []int{1, 2, 3}, 4, NotContains}, {"subset", []int{1, 2, 3, 4}, []int{2, 3}, Subset}, {"notSubset", []int{1, 2, 3, 4}, []int{0, 3}, NotSubset}, {"elementsMatch", []byte("abc"), []byte("bac"), ElementsMatch}, {"regexp", "^t.*y$", "testify", Regexp}, {"notRegexp", "^t.*y$", "Testify", NotRegexp}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, tt.expect, tt.got) }) } } func ExampleValueAssertionFunc() { t := &testing.T{} // provided by test dumbParse := func(input string) interface{} { var x interface{} _ = json.Unmarshal([]byte(input), &x) return x } tests := []struct { name string arg string assertion ValueAssertionFunc }{ {"true is not nil", "true", NotNil}, {"empty string is nil", "", Nil}, {"zero is not nil", "0", NotNil}, {"zero is zero", "0", Zero}, {"false is zero", "false", Zero}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, dumbParse(tt.arg)) }) } } func TestValueAssertionFunc(t *testing.T) { tests := []struct { name string value interface{} assertion ValueAssertionFunc }{ {"notNil", true, NotNil}, {"nil", nil, Nil}, {"empty", []int{}, Empty}, {"notEmpty", []int{1}, NotEmpty}, {"zero", false, Zero}, {"notZero", 42, NotZero}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, tt.value) }) } } func ExampleBoolAssertionFunc() { t := &testing.T{} // provided by test isOkay := func(x int) bool { return x >= 42 } tests := []struct { name string arg int assertion BoolAssertionFunc }{ {"-1 is bad", -1, False}, {"42 is good", 42, True}, {"41 is bad", 41, False}, {"45 is cool", 45, True}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, isOkay(tt.arg)) }) } } func TestBoolAssertionFunc(t *testing.T) { tests := []struct { name string value bool assertion BoolAssertionFunc }{ {"true", true, True}, {"false", false, False}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, tt.value) }) } } func ExampleErrorAssertionFunc() { t := &testing.T{} // provided by test dumbParseNum := func(input string, v interface{}) error { return json.Unmarshal([]byte(input), v) } tests := []struct { name string arg string assertion ErrorAssertionFunc }{ {"1.2 is number", "1.2", NoError}, {"1.2.3 not number", "1.2.3", Error}, {"true is not number", "true", Error}, {"3 is number", "3", NoError}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { var x float64 tt.assertion(t, dumbParseNum(tt.arg, &x)) }) } } func TestErrorAssertionFunc(t *testing.T) { tests := []struct { name string err error assertion ErrorAssertionFunc }{ {"noError", nil, NoError}, {"error", errors.New("whoops"), Error}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, tt.err) }) } } func ExamplePanicAssertionFunc() { t := &testing.T{} // provided by test tests := []struct { name string panicFn PanicTestFunc assertion PanicAssertionFunc }{ {"with panic", func() { panic(nil) }, Panics}, {"without panic", func() {}, NotPanics}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, tt.panicFn) }) } } func TestPanicAssertionFunc(t *testing.T) { tests := []struct { name string panicFn PanicTestFunc assertion PanicAssertionFunc }{ {"not panic", func() {}, NotPanics}, {"panic", func() { panic(nil) }, Panics}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, tt.panicFn) }) } } func TestEventuallyFalse(t *testing.T) { mockT := new(testing.T) condition := func() bool { return false } False(t, Eventually(mockT, condition, 100*time.Millisecond, 20*time.Millisecond)) } func TestEventuallyTrue(t *testing.T) { state := 0 condition := func() bool { defer func() { state += 1 }() return state == 2 } True(t, Eventually(t, condition, 100*time.Millisecond, 20*time.Millisecond)) } // errorsCapturingT is a mock implementation of TestingT that captures errors reported with Errorf. type errorsCapturingT struct { errors []error } func (t *errorsCapturingT) Errorf(format string, args ...interface{}) { t.errors = append(t.errors, fmt.Errorf(format, args...)) } func (t *errorsCapturingT) Helper() {} func TestEventuallyWithTFalse(t *testing.T) { mockT := new(errorsCapturingT) condition := func(collect *CollectT) { Fail(collect, "condition fixed failure") } False(t, EventuallyWithT(mockT, condition, 100*time.Millisecond, 20*time.Millisecond)) Len(t, mockT.errors, 2) } func TestEventuallyWithTTrue(t *testing.T) { mockT := new(errorsCapturingT) state := 0 condition := func(collect *CollectT) { defer func() { state += 1 }() True(collect, state == 2) } True(t, EventuallyWithT(mockT, condition, 100*time.Millisecond, 20*time.Millisecond)) Len(t, mockT.errors, 0) } func TestEventuallyWithT_ConcurrencySafe(t *testing.T) { mockT := new(errorsCapturingT) condition := func(collect *CollectT) { Fail(collect, "condition fixed failure") } // To trigger race conditions, we run EventuallyWithT with a nanosecond tick. False(t, EventuallyWithT(mockT, condition, 100*time.Millisecond, time.Nanosecond)) Len(t, mockT.errors, 2) } func TestEventuallyWithT_ReturnsTheLatestFinishedConditionErrors(t *testing.T) { // We'll use a channel to control whether a condition should sleep or not. mustSleep := make(chan bool, 2) mustSleep <- false mustSleep <- true close(mustSleep) condition := func(collect *CollectT) { if <-mustSleep { // Sleep to ensure that the second condition runs longer than timeout. time.Sleep(time.Second) return } // The first condition will fail. We expect to get this error as a result. Fail(collect, "condition fixed failure") } mockT := new(errorsCapturingT) False(t, EventuallyWithT(mockT, condition, 100*time.Millisecond, 20*time.Millisecond)) Len(t, mockT.errors, 2) } func TestNeverFalse(t *testing.T) { condition := func() bool { return false } True(t, Never(t, condition, 100*time.Millisecond, 20*time.Millisecond)) } // TestNeverTrue checks Never with a condition that returns true on second call. func TestNeverTrue(t *testing.T) { mockT := new(testing.T) // A list of values returned by condition. // Channel protects against concurrent access. returns := make(chan bool, 2) returns <- false returns <- true defer close(returns) // Will return true on second call. condition := func() bool { return <-returns } False(t, Never(mockT, condition, 100*time.Millisecond, 20*time.Millisecond)) } // Check that a long running condition doesn't block Eventually. // See issue 805 (and its long tail of following issues) func TestEventuallyTimeout(t *testing.T) { mockT := new(testing.T) NotPanics(t, func() { done, done2 := make(chan struct{}), make(chan struct{}) // A condition function that returns after the Eventually timeout condition := func() bool { // Wait until Eventually times out and terminates <-done close(done2) return true } False(t, Eventually(mockT, condition, time.Millisecond, time.Microsecond)) close(done) <-done2 }) } func Test_validateEqualArgs(t *testing.T) { if validateEqualArgs(func() {}, func() {}) == nil { t.Error("non-nil functions should error") } if validateEqualArgs(func() {}, func() {}) == nil { t.Error("non-nil functions should error") } if validateEqualArgs(nil, nil) != nil { t.Error("nil functions are equal") } } func Test_truncatingFormat(t *testing.T) { original := strings.Repeat("a", bufio.MaxScanTokenSize-102) result := truncatingFormat(original) Equal(t, fmt.Sprintf("%#v", original), result, "string should not be truncated") original = original + "x" result = truncatingFormat(original) NotEqual(t, fmt.Sprintf("%#v", original), result, "string should have been truncated.") if !strings.HasSuffix(result, "<... truncated>") { t.Error("truncated string should have <... truncated> suffix") } } // parseLabeledOutput does the inverse of labeledOutput - it takes a formatted // output string and turns it back into a slice of labeledContent. func parseLabeledOutput(output string) []labeledContent { labelPattern := regexp.MustCompile(`^\t([^\t]*): *\t(.*)$`) contentPattern := regexp.MustCompile(`^\t *\t(.*)$`) var contents []labeledContent lines := strings.Split(output, "\n") i := -1 for _, line := range lines { if line == "" { // skip blank lines continue } matches := labelPattern.FindStringSubmatch(line) if len(matches) == 3 { // a label contents = append(contents, labeledContent{ label: matches[1], content: matches[2] + "\n", }) i++ continue } matches = contentPattern.FindStringSubmatch(line) if len(matches) == 2 { // just content if i >= 0 { contents[i].content += matches[1] + "\n" continue } } // Couldn't parse output return nil } return contents } type captureTestingT struct { msg string } func (ctt *captureTestingT) Errorf(format string, args ...interface{}) { ctt.msg = fmt.Sprintf(format, args...) } func (ctt *captureTestingT) checkResultAndErrMsg(t *testing.T, expectedRes, res bool, expectedErrMsg string) { t.Helper() if res != expectedRes { t.Errorf("Should return %t", expectedRes) return } contents := parseLabeledOutput(ctt.msg) if res == true { if contents != nil { t.Errorf("Should not log an error") } return } if contents == nil { t.Errorf("Should log an error. Log output: %v", ctt.msg) return } for _, content := range contents { if content.label == "Error" { if expectedErrMsg == content.content { return } t.Errorf("Logged Error: %v", content.content) } } t.Errorf("Should log Error: %v", expectedErrMsg) } func TestErrorIs(t *testing.T) { tests := []struct { err error target error result bool resultErrMsg string }{ { err: io.EOF, target: io.EOF, result: true, }, { err: fmt.Errorf("wrap: %w", io.EOF), target: io.EOF, result: true, }, { err: io.EOF, target: io.ErrClosedPipe, result: false, resultErrMsg: "" + "Target error should be in err chain:\n" + "expected: \"io: read/write on closed pipe\"\n" + "in chain: \"EOF\"\n", }, { err: nil, target: io.EOF, result: false, resultErrMsg: "" + "Target error should be in err chain:\n" + "expected: \"EOF\"\n" + "in chain: \n", }, { err: io.EOF, target: nil, result: false, resultErrMsg: "" + "Target error should be in err chain:\n" + "expected: \"\"\n" + "in chain: \"EOF\"\n", }, { err: nil, target: nil, result: true, }, { err: fmt.Errorf("abc: %w", errors.New("def")), target: io.EOF, result: false, resultErrMsg: "" + "Target error should be in err chain:\n" + "expected: \"EOF\"\n" + "in chain: \"abc: def\"\n" + "\t\"def\"\n", }, } for _, tt := range tests { tt := tt t.Run(fmt.Sprintf("ErrorIs(%#v,%#v)", tt.err, tt.target), func(t *testing.T) { mockT := new(captureTestingT) res := ErrorIs(mockT, tt.err, tt.target) mockT.checkResultAndErrMsg(t, tt.result, res, tt.resultErrMsg) }) } } func TestNotErrorIs(t *testing.T) { tests := []struct { err error target error result bool resultErrMsg string }{ { err: io.EOF, target: io.EOF, result: false, resultErrMsg: "" + "Target error should not be in err chain:\n" + "found: \"EOF\"\n" + "in chain: \"EOF\"\n", }, { err: fmt.Errorf("wrap: %w", io.EOF), target: io.EOF, result: false, resultErrMsg: "" + "Target error should not be in err chain:\n" + "found: \"EOF\"\n" + "in chain: \"wrap: EOF\"\n" + "\t\"EOF\"\n", }, { err: io.EOF, target: io.ErrClosedPipe, result: true, }, { err: nil, target: io.EOF, result: true, }, { err: io.EOF, target: nil, result: true, }, { err: nil, target: nil, result: false, resultErrMsg: "" + "Target error should not be in err chain:\n" + "found: \"\"\n" + "in chain: \n", }, { err: fmt.Errorf("abc: %w", errors.New("def")), target: io.EOF, result: true, }, } for _, tt := range tests { tt := tt t.Run(fmt.Sprintf("NotErrorIs(%#v,%#v)", tt.err, tt.target), func(t *testing.T) { mockT := new(captureTestingT) res := NotErrorIs(mockT, tt.err, tt.target) mockT.checkResultAndErrMsg(t, tt.result, res, tt.resultErrMsg) }) } } func TestErrorAs(t *testing.T) { mockT := new(testing.T) tests := []struct { err error result bool }{ {fmt.Errorf("wrap: %w", &customError{}), true}, {io.EOF, false}, {nil, false}, } for _, tt := range tests { tt := tt var target *customError t.Run(fmt.Sprintf("ErrorAs(%#v,%#v)", tt.err, target), func(t *testing.T) { res := ErrorAs(mockT, tt.err, &target) if res != tt.result { t.Errorf("ErrorAs(%#v,%#v) should return %t)", tt.err, target, tt.result) } }) } } ================================================ FILE: internal/testify/assert/doc.go ================================================ // Package assert provides a set of comprehensive testing tools for use with the normal Go testing system. // // # Example Usage // // The following is a complete example using assert in a standard test function: // // import ( // "testing" // "github.com/expr-lang/expr/internal/testify/assert" // ) // // func TestSomething(t *testing.T) { // // var a string = "Hello" // var b string = "Hello" // // assert.Equal(t, a, b, "The two words should be the same.") // // } // // if you assert many times, use the format below: // // import ( // "testing" // "github.com/expr-lang/expr/internal/testify/assert" // ) // // func TestSomething(t *testing.T) { // assert := assert.New(t) // // var a string = "Hello" // var b string = "Hello" // // assert.Equal(a, b, "The two words should be the same.") // } // // # Assertions // // Assertions allow you to easily write test code, and are global funcs in the `assert` package. // All assertion functions take, as the first argument, the `*testing.T` object provided by the // testing framework. This allows the assertion funcs to write the failings and other details to // the correct place. // // Every assertion function also takes an optional string message as the final argument, // allowing custom error messages to be appended to the message the assertion method outputs. package assert ================================================ FILE: internal/testify/assert/errors.go ================================================ package assert import ( "errors" ) // AnError is an error instance useful for testing. If the code does not care // about error specifics, and only needs to return the error for example, this // error should be used to make the test code more readable. var AnError = errors.New("assert.AnError general error for testing") ================================================ FILE: internal/testify/assert/forward_assertions.go ================================================ package assert // Assertions provides assertion methods around the // TestingT interface. type Assertions struct { t TestingT } // New makes a new Assertions object for the specified TestingT. func New(t TestingT) *Assertions { return &Assertions{ t: t, } } //go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_forward.go.tmpl -include-format-funcs" ================================================ FILE: internal/testify/assert/forward_assertions_test.go ================================================ package assert import ( "errors" "regexp" "testing" "time" ) func TestImplementsWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.Implements((*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject)) { t.Error("Implements method should return true: AssertionTesterConformingObject implements AssertionTesterInterface") } if assert.Implements((*AssertionTesterInterface)(nil), new(AssertionTesterNonConformingObject)) { t.Error("Implements method should return false: AssertionTesterNonConformingObject does not implements AssertionTesterInterface") } } func TestIsTypeWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.IsType(new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) { t.Error("IsType should return true: AssertionTesterConformingObject is the same type as AssertionTesterConformingObject") } if assert.IsType(new(AssertionTesterConformingObject), new(AssertionTesterNonConformingObject)) { t.Error("IsType should return false: AssertionTesterConformingObject is not the same type as AssertionTesterNonConformingObject") } } func TestEqualWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.Equal("Hello World", "Hello World") { t.Error("Equal should return true") } if !assert.Equal(123, 123) { t.Error("Equal should return true") } if !assert.Equal(123.5, 123.5) { t.Error("Equal should return true") } if !assert.Equal([]byte("Hello World"), []byte("Hello World")) { t.Error("Equal should return true") } if !assert.Equal(nil, nil) { t.Error("Equal should return true") } } func TestEqualValuesWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.EqualValues(uint32(10), int32(10)) { t.Error("EqualValues should return true") } } func TestNotNilWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.NotNil(new(AssertionTesterConformingObject)) { t.Error("NotNil should return true: object is not nil") } if assert.NotNil(nil) { t.Error("NotNil should return false: object is nil") } } func TestNilWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.Nil(nil) { t.Error("Nil should return true: object is nil") } if assert.Nil(new(AssertionTesterConformingObject)) { t.Error("Nil should return false: object is not nil") } } func TestTrueWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.True(true) { t.Error("True should return true") } if assert.True(false) { t.Error("True should return false") } } func TestFalseWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.False(false) { t.Error("False should return true") } if assert.False(true) { t.Error("False should return false") } } func TestExactlyWrapper(t *testing.T) { assert := New(new(testing.T)) a := float32(1) b := float64(1) c := float32(1) d := float32(2) if assert.Exactly(a, b) { t.Error("Exactly should return false") } if assert.Exactly(a, d) { t.Error("Exactly should return false") } if !assert.Exactly(a, c) { t.Error("Exactly should return true") } if assert.Exactly(nil, a) { t.Error("Exactly should return false") } if assert.Exactly(a, nil) { t.Error("Exactly should return false") } } func TestNotEqualWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.NotEqual("Hello World", "Hello World!") { t.Error("NotEqual should return true") } if !assert.NotEqual(123, 1234) { t.Error("NotEqual should return true") } if !assert.NotEqual(123.5, 123.55) { t.Error("NotEqual should return true") } if !assert.NotEqual([]byte("Hello World"), []byte("Hello World!")) { t.Error("NotEqual should return true") } if !assert.NotEqual(nil, new(AssertionTesterConformingObject)) { t.Error("NotEqual should return true") } } func TestNotEqualValuesWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.NotEqualValues("Hello World", "Hello World!") { t.Error("NotEqualValues should return true") } if !assert.NotEqualValues(123, 1234) { t.Error("NotEqualValues should return true") } if !assert.NotEqualValues(123.5, 123.55) { t.Error("NotEqualValues should return true") } if !assert.NotEqualValues([]byte("Hello World"), []byte("Hello World!")) { t.Error("NotEqualValues should return true") } if !assert.NotEqualValues(nil, new(AssertionTesterConformingObject)) { t.Error("NotEqualValues should return true") } if assert.NotEqualValues(10, uint(10)) { t.Error("NotEqualValues should return false") } } func TestContainsWrapper(t *testing.T) { assert := New(new(testing.T)) list := []string{"Foo", "Bar"} if !assert.Contains("Hello World", "Hello") { t.Error("Contains should return true: \"Hello World\" contains \"Hello\"") } if assert.Contains("Hello World", "Salut") { t.Error("Contains should return false: \"Hello World\" does not contain \"Salut\"") } if !assert.Contains(list, "Foo") { t.Error("Contains should return true: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"") } if assert.Contains(list, "Salut") { t.Error("Contains should return false: \"[\"Foo\", \"Bar\"]\" does not contain \"Salut\"") } } func TestNotContainsWrapper(t *testing.T) { assert := New(new(testing.T)) list := []string{"Foo", "Bar"} if !assert.NotContains("Hello World", "Hello!") { t.Error("NotContains should return true: \"Hello World\" does not contain \"Hello!\"") } if assert.NotContains("Hello World", "Hello") { t.Error("NotContains should return false: \"Hello World\" contains \"Hello\"") } if !assert.NotContains(list, "Foo!") { t.Error("NotContains should return true: \"[\"Foo\", \"Bar\"]\" does not contain \"Foo!\"") } if assert.NotContains(list, "Foo") { t.Error("NotContains should return false: \"[\"Foo\", \"Bar\"]\" contains \"Foo\"") } } func TestConditionWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.Condition(func() bool { return true }, "Truth") { t.Error("Condition should return true") } if assert.Condition(func() bool { return false }, "Lie") { t.Error("Condition should return false") } } func TestDidPanicWrapper(t *testing.T) { if funcDidPanic, _, _ := didPanic(func() { panic("Panic!") }); !funcDidPanic { t.Error("didPanic should return true") } if funcDidPanic, _, _ := didPanic(func() { }); funcDidPanic { t.Error("didPanic should return false") } } func TestPanicsWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.Panics(func() { panic("Panic!") }) { t.Error("Panics should return true") } if assert.Panics(func() { }) { t.Error("Panics should return false") } } func TestNotPanicsWrapper(t *testing.T) { assert := New(new(testing.T)) if !assert.NotPanics(func() { }) { t.Error("NotPanics should return true") } if assert.NotPanics(func() { panic("Panic!") }) { t.Error("NotPanics should return false") } } func TestNoErrorWrapper(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) // start with a nil error var err error assert.True(mockAssert.NoError(err), "NoError should return True for nil arg") // now set an error err = errors.New("Some error") assert.False(mockAssert.NoError(err), "NoError with error should return False") } func TestErrorWrapper(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) // start with a nil error var err error assert.False(mockAssert.Error(err), "Error should return False for nil arg") // now set an error err = errors.New("Some error") assert.True(mockAssert.Error(err), "Error with error should return True") } func TestErrorContainsWrapper(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) // start with a nil error var err error assert.False(mockAssert.ErrorContains(err, ""), "ErrorContains should return false for nil arg") // now set an error err = errors.New("some error: another error") assert.False(mockAssert.ErrorContains(err, "different error"), "ErrorContains should return false for different error string") assert.True(mockAssert.ErrorContains(err, "some error"), "ErrorContains should return true") assert.True(mockAssert.ErrorContains(err, "another error"), "ErrorContains should return true") } func TestEqualErrorWrapper(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) // start with a nil error var err error assert.False(mockAssert.EqualError(err, ""), "EqualError should return false for nil arg") // now set an error err = errors.New("some error") assert.False(mockAssert.EqualError(err, "Not some error"), "EqualError should return false for different error string") assert.True(mockAssert.EqualError(err, "some error"), "EqualError should return true") } func TestEmptyWrapper(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) assert.True(mockAssert.Empty(""), "Empty string is empty") assert.True(mockAssert.Empty(nil), "Nil is empty") assert.True(mockAssert.Empty([]string{}), "Empty string array is empty") assert.True(mockAssert.Empty(0), "Zero int value is empty") assert.True(mockAssert.Empty(false), "False value is empty") assert.False(mockAssert.Empty("something"), "Non Empty string is not empty") assert.False(mockAssert.Empty(errors.New("something")), "Non nil object is not empty") assert.False(mockAssert.Empty([]string{"something"}), "Non empty string array is not empty") assert.False(mockAssert.Empty(1), "Non-zero int value is not empty") assert.False(mockAssert.Empty(true), "True value is not empty") } func TestNotEmptyWrapper(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) assert.False(mockAssert.NotEmpty(""), "Empty string is empty") assert.False(mockAssert.NotEmpty(nil), "Nil is empty") assert.False(mockAssert.NotEmpty([]string{}), "Empty string array is empty") assert.False(mockAssert.NotEmpty(0), "Zero int value is empty") assert.False(mockAssert.NotEmpty(false), "False value is empty") assert.True(mockAssert.NotEmpty("something"), "Non Empty string is not empty") assert.True(mockAssert.NotEmpty(errors.New("something")), "Non nil object is not empty") assert.True(mockAssert.NotEmpty([]string{"something"}), "Non empty string array is not empty") assert.True(mockAssert.NotEmpty(1), "Non-zero int value is not empty") assert.True(mockAssert.NotEmpty(true), "True value is not empty") } func TestLenWrapper(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) assert.False(mockAssert.Len(nil, 0), "nil does not have length") assert.False(mockAssert.Len(0, 0), "int does not have length") assert.False(mockAssert.Len(true, 0), "true does not have length") assert.False(mockAssert.Len(false, 0), "false does not have length") assert.False(mockAssert.Len('A', 0), "Rune does not have length") assert.False(mockAssert.Len(struct{}{}, 0), "Struct does not have length") ch := make(chan int, 5) ch <- 1 ch <- 2 ch <- 3 cases := []struct { v interface{} l int }{ {[]int{1, 2, 3}, 3}, {[...]int{1, 2, 3}, 3}, {"ABC", 3}, {map[int]int{1: 2, 2: 4, 3: 6}, 3}, {ch, 3}, {[]int{}, 0}, {map[int]int{}, 0}, {make(chan int), 0}, {[]int(nil), 0}, {map[int]int(nil), 0}, {(chan int)(nil), 0}, } for _, c := range cases { assert.True(mockAssert.Len(c.v, c.l), "%#v have %d items", c.v, c.l) } } func TestWithinDurationWrapper(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) a := time.Now() b := a.Add(10 * time.Second) assert.True(mockAssert.WithinDuration(a, b, 10*time.Second), "A 10s difference is within a 10s time difference") assert.True(mockAssert.WithinDuration(b, a, 10*time.Second), "A 10s difference is within a 10s time difference") assert.False(mockAssert.WithinDuration(a, b, 9*time.Second), "A 10s difference is not within a 9s time difference") assert.False(mockAssert.WithinDuration(b, a, 9*time.Second), "A 10s difference is not within a 9s time difference") assert.False(mockAssert.WithinDuration(a, b, -9*time.Second), "A 10s difference is not within a 9s time difference") assert.False(mockAssert.WithinDuration(b, a, -9*time.Second), "A 10s difference is not within a 9s time difference") assert.False(mockAssert.WithinDuration(a, b, -11*time.Second), "A 10s difference is not within a 9s time difference") assert.False(mockAssert.WithinDuration(b, a, -11*time.Second), "A 10s difference is not within a 9s time difference") } func TestInDeltaWrapper(t *testing.T) { assert := New(new(testing.T)) True(t, assert.InDelta(1.001, 1, 0.01), "|1.001 - 1| <= 0.01") True(t, assert.InDelta(1, 1.001, 0.01), "|1 - 1.001| <= 0.01") True(t, assert.InDelta(1, 2, 1), "|1 - 2| <= 1") False(t, assert.InDelta(1, 2, 0.5), "Expected |1 - 2| <= 0.5 to fail") False(t, assert.InDelta(2, 1, 0.5), "Expected |2 - 1| <= 0.5 to fail") False(t, assert.InDelta("", nil, 1), "Expected non numerals to fail") cases := []struct { a, b interface{} delta float64 }{ {uint8(2), uint8(1), 1}, {uint16(2), uint16(1), 1}, {uint32(2), uint32(1), 1}, {uint64(2), uint64(1), 1}, {int(2), int(1), 1}, {int8(2), int8(1), 1}, {int16(2), int16(1), 1}, {int32(2), int32(1), 1}, {int64(2), int64(1), 1}, {float32(2), float32(1), 1}, {float64(2), float64(1), 1}, } for _, tc := range cases { True(t, assert.InDelta(tc.a, tc.b, tc.delta), "Expected |%V - %V| <= %v", tc.a, tc.b, tc.delta) } } func TestInEpsilonWrapper(t *testing.T) { assert := New(new(testing.T)) cases := []struct { a, b interface{} epsilon float64 }{ {uint8(2), uint16(2), .001}, {2.1, 2.2, 0.1}, {2.2, 2.1, 0.1}, {-2.1, -2.2, 0.1}, {-2.2, -2.1, 0.1}, {uint64(100), uint8(101), 0.01}, {0.1, -0.1, 2}, } for _, tc := range cases { True(t, assert.InEpsilon(tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon)) } cases = []struct { a, b interface{} epsilon float64 }{ {uint8(2), int16(-2), .001}, {uint64(100), uint8(102), 0.01}, {2.1, 2.2, 0.001}, {2.2, 2.1, 0.001}, {2.1, -2.2, 1}, {2.1, "bla-bla", 0}, {0.1, -0.1, 1.99}, } for _, tc := range cases { False(t, assert.InEpsilon(tc.a, tc.b, tc.epsilon, "Expected %V and %V to have a relative difference of %v", tc.a, tc.b, tc.epsilon)) } } func TestRegexpWrapper(t *testing.T) { assert := New(new(testing.T)) cases := []struct { rx, str string }{ {"^start", "start of the line"}, {"end$", "in the end"}, {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12.34"}, } for _, tc := range cases { True(t, assert.Regexp(tc.rx, tc.str)) True(t, assert.Regexp(regexp.MustCompile(tc.rx), tc.str)) False(t, assert.NotRegexp(tc.rx, tc.str)) False(t, assert.NotRegexp(regexp.MustCompile(tc.rx), tc.str)) } cases = []struct { rx, str string }{ {"^asdfastart", "Not the start of the line"}, {"end$", "in the end."}, {"[0-9]{3}[.-]?[0-9]{2}[.-]?[0-9]{2}", "My phone number is 650.12a.34"}, } for _, tc := range cases { False(t, assert.Regexp(tc.rx, tc.str), "Expected \"%s\" to not match \"%s\"", tc.rx, tc.str) False(t, assert.Regexp(regexp.MustCompile(tc.rx), tc.str)) True(t, assert.NotRegexp(tc.rx, tc.str)) True(t, assert.NotRegexp(regexp.MustCompile(tc.rx), tc.str)) } } func TestZeroWrapper(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) for _, test := range zeros { assert.True(mockAssert.Zero(test), "Zero should return true for %v", test) } for _, test := range nonZeros { assert.False(mockAssert.Zero(test), "Zero should return false for %v", test) } } func TestNotZeroWrapper(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) for _, test := range zeros { assert.False(mockAssert.NotZero(test), "Zero should return true for %v", test) } for _, test := range nonZeros { assert.True(mockAssert.NotZero(test), "Zero should return false for %v", test) } } func TestJSONEqWrapper_EqualSONString(t *testing.T) { assert := New(new(testing.T)) if !assert.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`) { t.Error("JSONEq should return true") } } func TestJSONEqWrapper_EquivalentButNotEqual(t *testing.T) { assert := New(new(testing.T)) if !assert.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) { t.Error("JSONEq should return true") } } func TestJSONEqWrapper_HashOfArraysAndHashes(t *testing.T) { assert := New(new(testing.T)) if !assert.JSONEq("{\r\n\t\"numeric\": 1.5,\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]],\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\"\r\n}", "{\r\n\t\"numeric\": 1.5,\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\",\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]]\r\n}") { t.Error("JSONEq should return true") } } func TestJSONEqWrapper_Array(t *testing.T) { assert := New(new(testing.T)) if !assert.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`) { t.Error("JSONEq should return true") } } func TestJSONEqWrapper_HashAndArrayNotEquivalent(t *testing.T) { assert := New(new(testing.T)) if assert.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`) { t.Error("JSONEq should return false") } } func TestJSONEqWrapper_HashesNotEquivalent(t *testing.T) { assert := New(new(testing.T)) if assert.JSONEq(`{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) { t.Error("JSONEq should return false") } } func TestJSONEqWrapper_ActualIsNotJSON(t *testing.T) { assert := New(new(testing.T)) if assert.JSONEq(`{"foo": "bar"}`, "Not JSON") { t.Error("JSONEq should return false") } } func TestJSONEqWrapper_ExpectedIsNotJSON(t *testing.T) { assert := New(new(testing.T)) if assert.JSONEq("Not JSON", `{"foo": "bar", "hello": "world"}`) { t.Error("JSONEq should return false") } } func TestJSONEqWrapper_ExpectedAndActualNotJSON(t *testing.T) { assert := New(new(testing.T)) if assert.JSONEq("Not JSON", "Not JSON") { t.Error("JSONEq should return false") } } func TestJSONEqWrapper_ArraysOfDifferentOrder(t *testing.T) { assert := New(new(testing.T)) if assert.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`) { t.Error("JSONEq should return false") } } ================================================ FILE: internal/testify/assert/http_assertions.go ================================================ package assert import ( "fmt" "net/http" "net/http/httptest" "net/url" "strings" ) // httpCode is a helper that returns HTTP code of the response. It returns -1 and // an error if building a new request fails. func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) { w := httptest.NewRecorder() req, err := http.NewRequest(method, url, http.NoBody) if err != nil { return -1, err } req.URL.RawQuery = values.Encode() handler(w, req) return w.Code, nil } // HTTPSuccess asserts that a specified handler returns a success status code. // // assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) // // Returns whether the assertion was successful (true) or not (false). func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } code, err := httpCode(handler, method, url, values) if err != nil { Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent if !isSuccessCode { Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) } return isSuccessCode } // HTTPRedirect asserts that a specified handler returns a redirect status code. // // assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } code, err := httpCode(handler, method, url, values) if err != nil { Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect if !isRedirectCode { Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) } return isRedirectCode } // HTTPError asserts that a specified handler returns an error status code. // // assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } code, err := httpCode(handler, method, url, values) if err != nil { Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } isErrorCode := code >= http.StatusBadRequest if !isErrorCode { Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code), msgAndArgs...) } return isErrorCode } // HTTPStatusCode asserts that a specified handler returns a specified status code. // // assert.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501) // // Returns whether the assertion was successful (true) or not (false). func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } code, err := httpCode(handler, method, url, values) if err != nil { Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err), msgAndArgs...) } successful := code == statuscode if !successful { Fail(t, fmt.Sprintf("Expected HTTP status code %d for %q but received %d", statuscode, url+"?"+values.Encode(), code), msgAndArgs...) } return successful } // HTTPBody is a helper that returns HTTP body of the response. It returns // empty string if building a new request fails. func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string { w := httptest.NewRecorder() if len(values) > 0 { url += "?" + values.Encode() } req, err := http.NewRequest(method, url, http.NoBody) if err != nil { return "" } handler(w, req) return w.Body.String() } // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // // assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } body := HTTPBody(handler, method, url, values) contains := strings.Contains(body, fmt.Sprint(str)) if !contains { Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...) } return contains } // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // // assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { if h, ok := t.(tHelper); ok { h.Helper() } body := HTTPBody(handler, method, url, values) contains := strings.Contains(body, fmt.Sprint(str)) if contains { Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body), msgAndArgs...) } return !contains } ================================================ FILE: internal/testify/assert/http_assertions_test.go ================================================ package assert import ( "fmt" "io" "net/http" "net/url" "testing" ) func httpOK(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusOK) } func httpReadBody(w http.ResponseWriter, r *http.Request) { _, _ = io.Copy(io.Discard, r.Body) w.WriteHeader(http.StatusOK) _, _ = w.Write([]byte("hello")) } func httpRedirect(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusTemporaryRedirect) } func httpError(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusInternalServerError) } func httpStatusCode(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusSwitchingProtocols) } func TestHTTPSuccess(t *testing.T) { assert := New(t) mockT1 := new(testing.T) assert.Equal(HTTPSuccess(mockT1, httpOK, "GET", "/", nil), true) assert.False(mockT1.Failed()) mockT2 := new(testing.T) assert.Equal(HTTPSuccess(mockT2, httpRedirect, "GET", "/", nil), false) assert.True(mockT2.Failed()) mockT3 := new(mockTestingT) assert.Equal(HTTPSuccess( mockT3, httpError, "GET", "/", nil, "was not expecting a failure here", ), false) assert.True(mockT3.Failed()) assert.Contains(mockT3.errorString(), "was not expecting a failure here") mockT4 := new(testing.T) assert.Equal(HTTPSuccess(mockT4, httpStatusCode, "GET", "/", nil), false) assert.True(mockT4.Failed()) mockT5 := new(testing.T) assert.Equal(HTTPSuccess(mockT5, httpReadBody, "POST", "/", nil), true) assert.False(mockT5.Failed()) } func TestHTTPRedirect(t *testing.T) { assert := New(t) mockT1 := new(mockTestingT) assert.Equal(HTTPRedirect( mockT1, httpOK, "GET", "/", nil, "was expecting a 3xx status code. Got 200.", ), false) assert.True(mockT1.Failed()) assert.Contains(mockT1.errorString(), "was expecting a 3xx status code. Got 200.") mockT2 := new(testing.T) assert.Equal(HTTPRedirect(mockT2, httpRedirect, "GET", "/", nil), true) assert.False(mockT2.Failed()) mockT3 := new(testing.T) assert.Equal(HTTPRedirect(mockT3, httpError, "GET", "/", nil), false) assert.True(mockT3.Failed()) mockT4 := new(testing.T) assert.Equal(HTTPRedirect(mockT4, httpStatusCode, "GET", "/", nil), false) assert.True(mockT4.Failed()) } func TestHTTPError(t *testing.T) { assert := New(t) mockT1 := new(testing.T) assert.Equal(HTTPError(mockT1, httpOK, "GET", "/", nil), false) assert.True(mockT1.Failed()) mockT2 := new(mockTestingT) assert.Equal(HTTPError( mockT2, httpRedirect, "GET", "/", nil, "Expected this request to error out. But it didn't", ), false) assert.True(mockT2.Failed()) assert.Contains(mockT2.errorString(), "Expected this request to error out. But it didn't") mockT3 := new(testing.T) assert.Equal(HTTPError(mockT3, httpError, "GET", "/", nil), true) assert.False(mockT3.Failed()) mockT4 := new(testing.T) assert.Equal(HTTPError(mockT4, httpStatusCode, "GET", "/", nil), false) assert.True(mockT4.Failed()) } func TestHTTPStatusCode(t *testing.T) { assert := New(t) mockT1 := new(testing.T) assert.Equal(HTTPStatusCode(mockT1, httpOK, "GET", "/", nil, http.StatusSwitchingProtocols), false) assert.True(mockT1.Failed()) mockT2 := new(testing.T) assert.Equal(HTTPStatusCode(mockT2, httpRedirect, "GET", "/", nil, http.StatusSwitchingProtocols), false) assert.True(mockT2.Failed()) mockT3 := new(mockTestingT) assert.Equal(HTTPStatusCode( mockT3, httpError, "GET", "/", nil, http.StatusSwitchingProtocols, "Expected the status code to be %d", http.StatusSwitchingProtocols, ), false) assert.True(mockT3.Failed()) assert.Contains(mockT3.errorString(), "Expected the status code to be 101") mockT4 := new(testing.T) assert.Equal(HTTPStatusCode(mockT4, httpStatusCode, "GET", "/", nil, http.StatusSwitchingProtocols), true) assert.False(mockT4.Failed()) } func TestHTTPStatusesWrapper(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) assert.Equal(mockAssert.HTTPSuccess(httpOK, "GET", "/", nil), true) assert.Equal(mockAssert.HTTPSuccess(httpRedirect, "GET", "/", nil), false) assert.Equal(mockAssert.HTTPSuccess(httpError, "GET", "/", nil), false) assert.Equal(mockAssert.HTTPRedirect(httpOK, "GET", "/", nil), false) assert.Equal(mockAssert.HTTPRedirect(httpRedirect, "GET", "/", nil), true) assert.Equal(mockAssert.HTTPRedirect(httpError, "GET", "/", nil), false) assert.Equal(mockAssert.HTTPError(httpOK, "GET", "/", nil), false) assert.Equal(mockAssert.HTTPError(httpRedirect, "GET", "/", nil), false) assert.Equal(mockAssert.HTTPError(httpError, "GET", "/", nil), true) } func httpHelloName(w http.ResponseWriter, r *http.Request) { name := r.FormValue("name") _, _ = fmt.Fprintf(w, "Hello, %s!", name) } func TestHTTPRequestWithNoParams(t *testing.T) { var got *http.Request handler := func(w http.ResponseWriter, r *http.Request) { got = r w.WriteHeader(http.StatusOK) } True(t, HTTPSuccess(t, handler, "GET", "/url", nil)) Empty(t, got.URL.Query()) Equal(t, "/url", got.URL.RequestURI()) } func TestHTTPRequestWithParams(t *testing.T) { var got *http.Request handler := func(w http.ResponseWriter, r *http.Request) { got = r w.WriteHeader(http.StatusOK) } params := url.Values{} params.Add("id", "12345") True(t, HTTPSuccess(t, handler, "GET", "/url", params)) Equal(t, url.Values{"id": []string{"12345"}}, got.URL.Query()) Equal(t, "/url?id=12345", got.URL.String()) Equal(t, "/url?id=12345", got.URL.RequestURI()) } func TestHttpBody(t *testing.T) { assert := New(t) mockT := new(mockTestingT) assert.True(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!")) assert.True(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World")) assert.False(HTTPBodyContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world")) assert.False(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!")) assert.False(HTTPBodyNotContains( mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World", "Expected the request body to not contain 'World'. But it did.", )) assert.True(HTTPBodyNotContains(mockT, httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world")) assert.Contains(mockT.errorString(), "Expected the request body to not contain 'World'. But it did.") assert.True(HTTPBodyContains(mockT, httpReadBody, "GET", "/", nil, "hello")) } func TestHttpBodyWrappers(t *testing.T) { assert := New(t) mockAssert := New(new(testing.T)) assert.True(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!")) assert.True(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World")) assert.False(mockAssert.HTTPBodyContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world")) assert.False(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "Hello, World!")) assert.False(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "World")) assert.True(mockAssert.HTTPBodyNotContains(httpHelloName, "GET", "/", url.Values{"name": []string{"World"}}, "world")) } ================================================ FILE: internal/testify/assert/internal/unsafetests/doc.go ================================================ // This package exists just to isolate tests that reference the [unsafe] package. // // The tests in this package are totally safe. package unsafetests ================================================ FILE: internal/testify/assert/internal/unsafetests/unsafetests_test.go ================================================ package unsafetests_test import ( "fmt" "testing" "unsafe" "github.com/expr-lang/expr/internal/testify/assert" ) type ignoreTestingT struct{} var _ assert.TestingT = ignoreTestingT{} func (ignoreTestingT) Helper() {} func (ignoreTestingT) Errorf(format string, args ...interface{}) { // Run the formatting, but ignore the result msg := fmt.Sprintf(format, args...) _ = msg } func TestUnsafePointers(t *testing.T) { var ignore ignoreTestingT assert.True(t, assert.Nil(t, unsafe.Pointer(nil), "unsafe.Pointer(nil) is nil")) assert.False(t, assert.NotNil(ignore, unsafe.Pointer(nil), "unsafe.Pointer(nil) is nil")) assert.True(t, assert.Nil(t, unsafe.Pointer((*int)(nil)), "unsafe.Pointer((*int)(nil)) is nil")) assert.False(t, assert.NotNil(ignore, unsafe.Pointer((*int)(nil)), "unsafe.Pointer((*int)(nil)) is nil")) assert.False(t, assert.Nil(ignore, unsafe.Pointer(new(int)), "unsafe.Pointer(new(int)) is NOT nil")) assert.True(t, assert.NotNil(t, unsafe.Pointer(new(int)), "unsafe.Pointer(new(int)) is NOT nil")) } ================================================ FILE: internal/testify/require/doc.go ================================================ // Package require implements the same assertions as the `assert` package but // stops test execution when a test fails. // // # Example Usage // // The following is a complete example using require in a standard test function: // // import ( // "testing" // "github.com/expr-lang/expr/internal/testify/require" // ) // // func TestSomething(t *testing.T) { // // var a string = "Hello" // var b string = "Hello" // // require.Equal(t, a, b, "The two words should be the same.") // // } // // # Assertions // // The `require` package have same global functions as in the `assert` package, // but instead of returning a boolean result they call `t.FailNow()`. // // Every assertion function also takes an optional string message as the final argument, // allowing custom error messages to be appended to the message the assertion method outputs. package require ================================================ FILE: internal/testify/require/forward_requirements.go ================================================ package require // Assertions provides assertion methods around the // TestingT interface. type Assertions struct { t TestingT } // New makes a new Assertions object for the specified TestingT. func New(t TestingT) *Assertions { return &Assertions{ t: t, } } //go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=require -template=require_forward.go.tmpl -include-format-funcs" ================================================ FILE: internal/testify/require/forward_requirements_test.go ================================================ package require import ( "errors" "testing" "time" ) func TestImplementsWrapper(t *testing.T) { require := New(t) require.Implements((*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject)) mockT := new(MockT) mockRequire := New(mockT) mockRequire.Implements((*AssertionTesterInterface)(nil), new(AssertionTesterNonConformingObject)) if !mockT.Failed { t.Error("Check should fail") } } func TestIsTypeWrapper(t *testing.T) { require := New(t) require.IsType(new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) mockT := new(MockT) mockRequire := New(mockT) mockRequire.IsType(new(AssertionTesterConformingObject), new(AssertionTesterNonConformingObject)) if !mockT.Failed { t.Error("Check should fail") } } func TestEqualWrapper(t *testing.T) { require := New(t) require.Equal(1, 1) mockT := new(MockT) mockRequire := New(mockT) mockRequire.Equal(1, 2) if !mockT.Failed { t.Error("Check should fail") } } func TestNotEqualWrapper(t *testing.T) { require := New(t) require.NotEqual(1, 2) mockT := new(MockT) mockRequire := New(mockT) mockRequire.NotEqual(2, 2) if !mockT.Failed { t.Error("Check should fail") } } func TestExactlyWrapper(t *testing.T) { require := New(t) a := float32(1) b := float32(1) c := float64(1) require.Exactly(a, b) mockT := new(MockT) mockRequire := New(mockT) mockRequire.Exactly(a, c) if !mockT.Failed { t.Error("Check should fail") } } func TestNotNilWrapper(t *testing.T) { require := New(t) require.NotNil(t, new(AssertionTesterConformingObject)) mockT := new(MockT) mockRequire := New(mockT) mockRequire.NotNil(nil) if !mockT.Failed { t.Error("Check should fail") } } func TestNilWrapper(t *testing.T) { require := New(t) require.Nil(nil) mockT := new(MockT) mockRequire := New(mockT) mockRequire.Nil(new(AssertionTesterConformingObject)) if !mockT.Failed { t.Error("Check should fail") } } func TestTrueWrapper(t *testing.T) { require := New(t) require.True(true) mockT := new(MockT) mockRequire := New(mockT) mockRequire.True(false) if !mockT.Failed { t.Error("Check should fail") } } func TestFalseWrapper(t *testing.T) { require := New(t) require.False(false) mockT := new(MockT) mockRequire := New(mockT) mockRequire.False(true) if !mockT.Failed { t.Error("Check should fail") } } func TestContainsWrapper(t *testing.T) { require := New(t) require.Contains("Hello World", "Hello") mockT := new(MockT) mockRequire := New(mockT) mockRequire.Contains("Hello World", "Salut") if !mockT.Failed { t.Error("Check should fail") } } func TestNotContainsWrapper(t *testing.T) { require := New(t) require.NotContains("Hello World", "Hello!") mockT := new(MockT) mockRequire := New(mockT) mockRequire.NotContains("Hello World", "Hello") if !mockT.Failed { t.Error("Check should fail") } } func TestPanicsWrapper(t *testing.T) { require := New(t) require.Panics(func() { panic("Panic!") }) mockT := new(MockT) mockRequire := New(mockT) mockRequire.Panics(func() {}) if !mockT.Failed { t.Error("Check should fail") } } func TestNotPanicsWrapper(t *testing.T) { require := New(t) require.NotPanics(func() {}) mockT := new(MockT) mockRequire := New(mockT) mockRequire.NotPanics(func() { panic("Panic!") }) if !mockT.Failed { t.Error("Check should fail") } } func TestNoErrorWrapper(t *testing.T) { require := New(t) require.NoError(nil) mockT := new(MockT) mockRequire := New(mockT) mockRequire.NoError(errors.New("some error")) if !mockT.Failed { t.Error("Check should fail") } } func TestErrorWrapper(t *testing.T) { require := New(t) require.Error(errors.New("some error")) mockT := new(MockT) mockRequire := New(mockT) mockRequire.Error(nil) if !mockT.Failed { t.Error("Check should fail") } } func TestErrorContainsWrapper(t *testing.T) { require := New(t) require.ErrorContains(errors.New("some error: another error"), "some error") mockT := new(MockT) mockRequire := New(mockT) mockRequire.ErrorContains(errors.New("some error: another error"), "different error") if !mockT.Failed { t.Error("Check should fail") } } func TestEqualErrorWrapper(t *testing.T) { require := New(t) require.EqualError(errors.New("some error"), "some error") mockT := new(MockT) mockRequire := New(mockT) mockRequire.EqualError(errors.New("some error"), "Not some error") if !mockT.Failed { t.Error("Check should fail") } } func TestEmptyWrapper(t *testing.T) { require := New(t) require.Empty("") mockT := new(MockT) mockRequire := New(mockT) mockRequire.Empty("x") if !mockT.Failed { t.Error("Check should fail") } } func TestNotEmptyWrapper(t *testing.T) { require := New(t) require.NotEmpty("x") mockT := new(MockT) mockRequire := New(mockT) mockRequire.NotEmpty("") if !mockT.Failed { t.Error("Check should fail") } } func TestWithinDurationWrapper(t *testing.T) { require := New(t) a := time.Now() b := a.Add(10 * time.Second) require.WithinDuration(a, b, 15*time.Second) mockT := new(MockT) mockRequire := New(mockT) mockRequire.WithinDuration(a, b, 5*time.Second) if !mockT.Failed { t.Error("Check should fail") } } func TestInDeltaWrapper(t *testing.T) { require := New(t) require.InDelta(1.001, 1, 0.01) mockT := new(MockT) mockRequire := New(mockT) mockRequire.InDelta(1, 2, 0.5) if !mockT.Failed { t.Error("Check should fail") } } func TestZeroWrapper(t *testing.T) { require := New(t) require.Zero(0) mockT := new(MockT) mockRequire := New(mockT) mockRequire.Zero(1) if !mockT.Failed { t.Error("Check should fail") } } func TestNotZeroWrapper(t *testing.T) { require := New(t) require.NotZero(1) mockT := new(MockT) mockRequire := New(mockT) mockRequire.NotZero(0) if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEqWrapper_EqualSONString(t *testing.T) { mockT := new(MockT) mockRequire := New(mockT) mockRequire.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`) if mockT.Failed { t.Error("Check should pass") } } func TestJSONEqWrapper_EquivalentButNotEqual(t *testing.T) { mockT := new(MockT) mockRequire := New(mockT) mockRequire.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) if mockT.Failed { t.Error("Check should pass") } } func TestJSONEqWrapper_HashOfArraysAndHashes(t *testing.T) { mockT := new(MockT) mockRequire := New(mockT) mockRequire.JSONEq("{\r\n\t\"numeric\": 1.5,\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]],\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\"\r\n}", "{\r\n\t\"numeric\": 1.5,\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\",\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]]\r\n}") if mockT.Failed { t.Error("Check should pass") } } func TestJSONEqWrapper_Array(t *testing.T) { mockT := new(MockT) mockRequire := New(mockT) mockRequire.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`) if mockT.Failed { t.Error("Check should pass") } } func TestJSONEqWrapper_HashAndArrayNotEquivalent(t *testing.T) { mockT := new(MockT) mockRequire := New(mockT) mockRequire.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`) if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEqWrapper_HashesNotEquivalent(t *testing.T) { mockT := new(MockT) mockRequire := New(mockT) mockRequire.JSONEq(`{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEqWrapper_ActualIsNotJSON(t *testing.T) { mockT := new(MockT) mockRequire := New(mockT) mockRequire.JSONEq(`{"foo": "bar"}`, "Not JSON") if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEqWrapper_ExpectedIsNotJSON(t *testing.T) { mockT := new(MockT) mockRequire := New(mockT) mockRequire.JSONEq("Not JSON", `{"foo": "bar", "hello": "world"}`) if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEqWrapper_ExpectedAndActualNotJSON(t *testing.T) { mockT := new(MockT) mockRequire := New(mockT) mockRequire.JSONEq("Not JSON", "Not JSON") if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEqWrapper_ArraysOfDifferentOrder(t *testing.T) { mockT := new(MockT) mockRequire := New(mockT) mockRequire.JSONEq(`["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`) if !mockT.Failed { t.Error("Check should fail") } } ================================================ FILE: internal/testify/require/require.go ================================================ // Code generated with github.com/expr-lang/expr/internal/_codegen; DO NOT EDIT. package require import ( http "net/http" url "net/url" time "time" assert "github.com/expr-lang/expr/internal/testify/assert" ) // Condition uses a Comparison to assert a complex condition. func Condition(t TestingT, comp assert.Comparison, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Condition(t, comp, msgAndArgs...) { return } t.FailNow() } // Conditionf uses a Comparison to assert a complex condition. func Conditionf(t TestingT, comp assert.Comparison, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Conditionf(t, comp, msg, args...) { return } t.FailNow() } // Contains asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // // assert.Contains(t, "Hello World", "World") // assert.Contains(t, ["Hello", "World"], "World") // assert.Contains(t, {"Hello": "World"}, "Hello") func Contains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Contains(t, s, contains, msgAndArgs...) { return } t.FailNow() } // Containsf asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // // assert.Containsf(t, "Hello World", "World", "error message %s", "formatted") // assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") // assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Containsf(t, s, contains, msg, args...) { return } t.FailNow() } // DirExists checks whether a directory exists in the given path. It also fails // if the path is a file rather a directory or there is an error checking whether it exists. func DirExists(t TestingT, path string, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.DirExists(t, path, msgAndArgs...) { return } t.FailNow() } // DirExistsf checks whether a directory exists in the given path. It also fails // if the path is a file rather a directory or there is an error checking whether it exists. func DirExistsf(t TestingT, path string, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.DirExistsf(t, path, msg, args...) { return } t.FailNow() } // ElementsMatch asserts that the specified listA(array, slice...) is equal to specified // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // // assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2]) func ElementsMatch(t TestingT, listA interface{}, listB interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.ElementsMatch(t, listA, listB, msgAndArgs...) { return } t.FailNow() } // ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // // assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.ElementsMatchf(t, listA, listB, msg, args...) { return } t.FailNow() } // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // // assert.Empty(t, obj) func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Empty(t, object, msgAndArgs...) { return } t.FailNow() } // Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // // assert.Emptyf(t, obj, "error message %s", "formatted") func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Emptyf(t, object, msg, args...) { return } t.FailNow() } // Equal asserts that two objects are equal. // // assert.Equal(t, 123, 123) // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func Equal(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Equal(t, expected, actual, msgAndArgs...) { return } t.FailNow() } // EqualError asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // // actualObj, err := SomeFunction() // assert.EqualError(t, err, expectedErrorString) func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.EqualError(t, theError, errString, msgAndArgs...) { return } t.FailNow() } // EqualErrorf asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // // actualObj, err := SomeFunction() // assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.EqualErrorf(t, theError, errString, msg, args...) { return } t.FailNow() } // EqualExportedValues asserts that the types of two objects are equal and their public // fields are also equal. This is useful for comparing structs that have private fields // that could potentially differ. // // type S struct { // Exported int // notExported int // } // assert.EqualExportedValues(t, S{1, 2}, S{1, 3}) => true // assert.EqualExportedValues(t, S{1, 2}, S{2, 3}) => false func EqualExportedValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.EqualExportedValues(t, expected, actual, msgAndArgs...) { return } t.FailNow() } // EqualExportedValuesf asserts that the types of two objects are equal and their public // fields are also equal. This is useful for comparing structs that have private fields // that could potentially differ. // // type S struct { // Exported int // notExported int // } // assert.EqualExportedValuesf(t, S{1, 2}, S{1, 3}, "error message %s", "formatted") => true // assert.EqualExportedValuesf(t, S{1, 2}, S{2, 3}, "error message %s", "formatted") => false func EqualExportedValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.EqualExportedValuesf(t, expected, actual, msg, args...) { return } t.FailNow() } // EqualValues asserts that two objects are equal or convertible to the same types // and equal. // // assert.EqualValues(t, uint32(123), int32(123)) func EqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.EqualValues(t, expected, actual, msgAndArgs...) { return } t.FailNow() } // EqualValuesf asserts that two objects are equal or convertible to the same types // and equal. // // assert.EqualValuesf(t, uint32(123), int32(123), "error message %s", "formatted") func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.EqualValuesf(t, expected, actual, msg, args...) { return } t.FailNow() } // Equalf asserts that two objects are equal. // // assert.Equalf(t, 123, 123, "error message %s", "formatted") // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Equalf(t, expected, actual, msg, args...) { return } t.FailNow() } // Error asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() // if assert.Error(t, err) { // assert.Equal(t, expectedError, err) // } func Error(t TestingT, err error, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Error(t, err, msgAndArgs...) { return } t.FailNow() } // ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. // This is a wrapper for errors.As. func ErrorAs(t TestingT, err error, target interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.ErrorAs(t, err, target, msgAndArgs...) { return } t.FailNow() } // ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. // This is a wrapper for errors.As. func ErrorAsf(t TestingT, err error, target interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.ErrorAsf(t, err, target, msg, args...) { return } t.FailNow() } // ErrorContains asserts that a function returned an error (i.e. not `nil`) // and that the error contains the specified substring. // // actualObj, err := SomeFunction() // assert.ErrorContains(t, err, expectedErrorSubString) func ErrorContains(t TestingT, theError error, contains string, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.ErrorContains(t, theError, contains, msgAndArgs...) { return } t.FailNow() } // ErrorContainsf asserts that a function returned an error (i.e. not `nil`) // and that the error contains the specified substring. // // actualObj, err := SomeFunction() // assert.ErrorContainsf(t, err, expectedErrorSubString, "error message %s", "formatted") func ErrorContainsf(t TestingT, theError error, contains string, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.ErrorContainsf(t, theError, contains, msg, args...) { return } t.FailNow() } // ErrorIs asserts that at least one of the errors in err's chain matches target. // This is a wrapper for errors.Is. func ErrorIs(t TestingT, err error, target error, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.ErrorIs(t, err, target, msgAndArgs...) { return } t.FailNow() } // ErrorIsf asserts that at least one of the errors in err's chain matches target. // This is a wrapper for errors.Is. func ErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.ErrorIsf(t, err, target, msg, args...) { return } t.FailNow() } // Errorf asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() // if assert.Errorf(t, err, "error message %s", "formatted") { // assert.Equal(t, expectedErrorf, err) // } func Errorf(t TestingT, err error, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Errorf(t, err, msg, args...) { return } t.FailNow() } // Eventually asserts that given condition will be met in waitFor time, // periodically checking target function each tick. // // assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond) func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Eventually(t, condition, waitFor, tick, msgAndArgs...) { return } t.FailNow() } // EventuallyWithT asserts that given condition will be met in waitFor time, // periodically checking target function each tick. In contrast to Eventually, // it supplies a CollectT to the condition function, so that the condition // function can use the CollectT to call other assertions. // The condition is considered "met" if no errors are raised in a tick. // The supplied CollectT collects all errors from one tick (if there are any). // If the condition is not met before waitFor, the collected errors of // the last tick are copied to t. // // externalValue := false // go func() { // time.Sleep(8*time.Second) // externalValue = true // }() // assert.EventuallyWithT(t, func(c *assert.CollectT) { // // add assertions as needed; any assertion failure will fail the current tick // assert.True(c, externalValue, "expected 'externalValue' to be true") // }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false") func EventuallyWithT(t TestingT, condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.EventuallyWithT(t, condition, waitFor, tick, msgAndArgs...) { return } t.FailNow() } // EventuallyWithTf asserts that given condition will be met in waitFor time, // periodically checking target function each tick. In contrast to Eventually, // it supplies a CollectT to the condition function, so that the condition // function can use the CollectT to call other assertions. // The condition is considered "met" if no errors are raised in a tick. // The supplied CollectT collects all errors from one tick (if there are any). // If the condition is not met before waitFor, the collected errors of // the last tick are copied to t. // // externalValue := false // go func() { // time.Sleep(8*time.Second) // externalValue = true // }() // assert.EventuallyWithTf(t, func(c *assert.CollectT, "error message %s", "formatted") { // // add assertions as needed; any assertion failure will fail the current tick // assert.True(c, externalValue, "expected 'externalValue' to be true") // }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false") func EventuallyWithTf(t TestingT, condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.EventuallyWithTf(t, condition, waitFor, tick, msg, args...) { return } t.FailNow() } // Eventuallyf asserts that given condition will be met in waitFor time, // periodically checking target function each tick. // // assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Eventuallyf(t, condition, waitFor, tick, msg, args...) { return } t.FailNow() } // Exactly asserts that two objects are equal in value and type. // // assert.Exactly(t, int32(123), int64(123)) func Exactly(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Exactly(t, expected, actual, msgAndArgs...) { return } t.FailNow() } // Exactlyf asserts that two objects are equal in value and type. // // assert.Exactlyf(t, int32(123), int64(123), "error message %s", "formatted") func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Exactlyf(t, expected, actual, msg, args...) { return } t.FailNow() } // Fail reports a failure through func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Fail(t, failureMessage, msgAndArgs...) { return } t.FailNow() } // FailNow fails test func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.FailNow(t, failureMessage, msgAndArgs...) { return } t.FailNow() } // FailNowf fails test func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.FailNowf(t, failureMessage, msg, args...) { return } t.FailNow() } // Failf reports a failure through func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Failf(t, failureMessage, msg, args...) { return } t.FailNow() } // False asserts that the specified value is false. // // assert.False(t, myBool) func False(t TestingT, value bool, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.False(t, value, msgAndArgs...) { return } t.FailNow() } // Falsef asserts that the specified value is false. // // assert.Falsef(t, myBool, "error message %s", "formatted") func Falsef(t TestingT, value bool, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Falsef(t, value, msg, args...) { return } t.FailNow() } // FileExists checks whether a file exists in the given path. It also fails if // the path points to a directory or there is an error when trying to check the file. func FileExists(t TestingT, path string, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.FileExists(t, path, msgAndArgs...) { return } t.FailNow() } // FileExistsf checks whether a file exists in the given path. It also fails if // the path points to a directory or there is an error when trying to check the file. func FileExistsf(t TestingT, path string, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.FileExistsf(t, path, msg, args...) { return } t.FailNow() } // Greater asserts that the first element is greater than the second // // assert.Greater(t, 2, 1) // assert.Greater(t, float64(2), float64(1)) // assert.Greater(t, "b", "a") func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Greater(t, e1, e2, msgAndArgs...) { return } t.FailNow() } // GreaterOrEqual asserts that the first element is greater than or equal to the second // // assert.GreaterOrEqual(t, 2, 1) // assert.GreaterOrEqual(t, 2, 2) // assert.GreaterOrEqual(t, "b", "a") // assert.GreaterOrEqual(t, "b", "b") func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.GreaterOrEqual(t, e1, e2, msgAndArgs...) { return } t.FailNow() } // GreaterOrEqualf asserts that the first element is greater than or equal to the second // // assert.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted") // assert.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted") // assert.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted") // assert.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted") func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.GreaterOrEqualf(t, e1, e2, msg, args...) { return } t.FailNow() } // Greaterf asserts that the first element is greater than the second // // assert.Greaterf(t, 2, 1, "error message %s", "formatted") // assert.Greaterf(t, float64(2), float64(1), "error message %s", "formatted") // assert.Greaterf(t, "b", "a", "error message %s", "formatted") func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Greaterf(t, e1, e2, msg, args...) { return } t.FailNow() } // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // // assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.HTTPBodyContains(t, handler, method, url, values, str, msgAndArgs...) { return } t.FailNow() } // HTTPBodyContainsf asserts that a specified handler returns a // body that contains a string. // // assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.HTTPBodyContainsf(t, handler, method, url, values, str, msg, args...) { return } t.FailNow() } // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // // assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.HTTPBodyNotContains(t, handler, method, url, values, str, msgAndArgs...) { return } t.FailNow() } // HTTPBodyNotContainsf asserts that a specified handler returns a // body that does not contain a string. // // assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.HTTPBodyNotContainsf(t, handler, method, url, values, str, msg, args...) { return } t.FailNow() } // HTTPError asserts that a specified handler returns an error status code. // // assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPError(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.HTTPError(t, handler, method, url, values, msgAndArgs...) { return } t.FailNow() } // HTTPErrorf asserts that a specified handler returns an error status code. // // assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.HTTPErrorf(t, handler, method, url, values, msg, args...) { return } t.FailNow() } // HTTPRedirect asserts that a specified handler returns a redirect status code. // // assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPRedirect(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.HTTPRedirect(t, handler, method, url, values, msgAndArgs...) { return } t.FailNow() } // HTTPRedirectf asserts that a specified handler returns a redirect status code. // // assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.HTTPRedirectf(t, handler, method, url, values, msg, args...) { return } t.FailNow() } // HTTPStatusCode asserts that a specified handler returns a specified status code. // // assert.HTTPStatusCode(t, myHandler, "GET", "/notImplemented", nil, 501) // // Returns whether the assertion was successful (true) or not (false). func HTTPStatusCode(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.HTTPStatusCode(t, handler, method, url, values, statuscode, msgAndArgs...) { return } t.FailNow() } // HTTPStatusCodef asserts that a specified handler returns a specified status code. // // assert.HTTPStatusCodef(t, myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPStatusCodef(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.HTTPStatusCodef(t, handler, method, url, values, statuscode, msg, args...) { return } t.FailNow() } // HTTPSuccess asserts that a specified handler returns a success status code. // // assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) // // Returns whether the assertion was successful (true) or not (false). func HTTPSuccess(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.HTTPSuccess(t, handler, method, url, values, msgAndArgs...) { return } t.FailNow() } // HTTPSuccessf asserts that a specified handler returns a success status code. // // assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.HTTPSuccessf(t, handler, method, url, values, msg, args...) { return } t.FailNow() } // Implements asserts that an object is implemented by the specified interface. // // assert.Implements(t, (*MyInterface)(nil), new(MyObject)) func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Implements(t, interfaceObject, object, msgAndArgs...) { return } t.FailNow() } // Implementsf asserts that an object is implemented by the specified interface. // // assert.Implementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Implementsf(t, interfaceObject, object, msg, args...) { return } t.FailNow() } // InDelta asserts that the two numerals are within delta of each other. // // assert.InDelta(t, math.Pi, 22/7.0, 0.01) func InDelta(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.InDelta(t, expected, actual, delta, msgAndArgs...) { return } t.FailNow() } // InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func InDeltaMapValues(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.InDeltaMapValues(t, expected, actual, delta, msgAndArgs...) { return } t.FailNow() } // InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.InDeltaMapValuesf(t, expected, actual, delta, msg, args...) { return } t.FailNow() } // InDeltaSlice is the same as InDelta, except it compares two slices. func InDeltaSlice(t TestingT, expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.InDeltaSlice(t, expected, actual, delta, msgAndArgs...) { return } t.FailNow() } // InDeltaSlicef is the same as InDelta, except it compares two slices. func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.InDeltaSlicef(t, expected, actual, delta, msg, args...) { return } t.FailNow() } // InDeltaf asserts that the two numerals are within delta of each other. // // assert.InDeltaf(t, math.Pi, 22/7.0, 0.01, "error message %s", "formatted") func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.InDeltaf(t, expected, actual, delta, msg, args...) { return } t.FailNow() } // InEpsilon asserts that expected and actual have a relative error less than epsilon func InEpsilon(t TestingT, expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.InEpsilon(t, expected, actual, epsilon, msgAndArgs...) { return } t.FailNow() } // InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. func InEpsilonSlice(t TestingT, expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.InEpsilonSlice(t, expected, actual, epsilon, msgAndArgs...) { return } t.FailNow() } // InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.InEpsilonSlicef(t, expected, actual, epsilon, msg, args...) { return } t.FailNow() } // InEpsilonf asserts that expected and actual have a relative error less than epsilon func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.InEpsilonf(t, expected, actual, epsilon, msg, args...) { return } t.FailNow() } // IsDecreasing asserts that the collection is decreasing // // assert.IsDecreasing(t, []int{2, 1, 0}) // assert.IsDecreasing(t, []float{2, 1}) // assert.IsDecreasing(t, []string{"b", "a"}) func IsDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.IsDecreasing(t, object, msgAndArgs...) { return } t.FailNow() } // IsDecreasingf asserts that the collection is decreasing // // assert.IsDecreasingf(t, []int{2, 1, 0}, "error message %s", "formatted") // assert.IsDecreasingf(t, []float{2, 1}, "error message %s", "formatted") // assert.IsDecreasingf(t, []string{"b", "a"}, "error message %s", "formatted") func IsDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.IsDecreasingf(t, object, msg, args...) { return } t.FailNow() } // IsIncreasing asserts that the collection is increasing // // assert.IsIncreasing(t, []int{1, 2, 3}) // assert.IsIncreasing(t, []float{1, 2}) // assert.IsIncreasing(t, []string{"a", "b"}) func IsIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.IsIncreasing(t, object, msgAndArgs...) { return } t.FailNow() } // IsIncreasingf asserts that the collection is increasing // // assert.IsIncreasingf(t, []int{1, 2, 3}, "error message %s", "formatted") // assert.IsIncreasingf(t, []float{1, 2}, "error message %s", "formatted") // assert.IsIncreasingf(t, []string{"a", "b"}, "error message %s", "formatted") func IsIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.IsIncreasingf(t, object, msg, args...) { return } t.FailNow() } // IsNonDecreasing asserts that the collection is not decreasing // // assert.IsNonDecreasing(t, []int{1, 1, 2}) // assert.IsNonDecreasing(t, []float{1, 2}) // assert.IsNonDecreasing(t, []string{"a", "b"}) func IsNonDecreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.IsNonDecreasing(t, object, msgAndArgs...) { return } t.FailNow() } // IsNonDecreasingf asserts that the collection is not decreasing // // assert.IsNonDecreasingf(t, []int{1, 1, 2}, "error message %s", "formatted") // assert.IsNonDecreasingf(t, []float{1, 2}, "error message %s", "formatted") // assert.IsNonDecreasingf(t, []string{"a", "b"}, "error message %s", "formatted") func IsNonDecreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.IsNonDecreasingf(t, object, msg, args...) { return } t.FailNow() } // IsNonIncreasing asserts that the collection is not increasing // // assert.IsNonIncreasing(t, []int{2, 1, 1}) // assert.IsNonIncreasing(t, []float{2, 1}) // assert.IsNonIncreasing(t, []string{"b", "a"}) func IsNonIncreasing(t TestingT, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.IsNonIncreasing(t, object, msgAndArgs...) { return } t.FailNow() } // IsNonIncreasingf asserts that the collection is not increasing // // assert.IsNonIncreasingf(t, []int{2, 1, 1}, "error message %s", "formatted") // assert.IsNonIncreasingf(t, []float{2, 1}, "error message %s", "formatted") // assert.IsNonIncreasingf(t, []string{"b", "a"}, "error message %s", "formatted") func IsNonIncreasingf(t TestingT, object interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.IsNonIncreasingf(t, object, msg, args...) { return } t.FailNow() } // IsType asserts that the specified objects are of the same type. func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.IsType(t, expectedType, object, msgAndArgs...) { return } t.FailNow() } // IsTypef asserts that the specified objects are of the same type. func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.IsTypef(t, expectedType, object, msg, args...) { return } t.FailNow() } // JSONEq asserts that two JSON strings are equivalent. // // assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.JSONEq(t, expected, actual, msgAndArgs...) { return } t.FailNow() } // JSONEqf asserts that two JSON strings are equivalent. // // assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.JSONEqf(t, expected, actual, msg, args...) { return } t.FailNow() } // Len asserts that the specified object has specific length. // Len also fails if the object has a type that len() not accept. // // assert.Len(t, mySlice, 3) func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Len(t, object, length, msgAndArgs...) { return } t.FailNow() } // Lenf asserts that the specified object has specific length. // Lenf also fails if the object has a type that len() not accept. // // assert.Lenf(t, mySlice, 3, "error message %s", "formatted") func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Lenf(t, object, length, msg, args...) { return } t.FailNow() } // Less asserts that the first element is less than the second // // assert.Less(t, 1, 2) // assert.Less(t, float64(1), float64(2)) // assert.Less(t, "a", "b") func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Less(t, e1, e2, msgAndArgs...) { return } t.FailNow() } // LessOrEqual asserts that the first element is less than or equal to the second // // assert.LessOrEqual(t, 1, 2) // assert.LessOrEqual(t, 2, 2) // assert.LessOrEqual(t, "a", "b") // assert.LessOrEqual(t, "b", "b") func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.LessOrEqual(t, e1, e2, msgAndArgs...) { return } t.FailNow() } // LessOrEqualf asserts that the first element is less than or equal to the second // // assert.LessOrEqualf(t, 1, 2, "error message %s", "formatted") // assert.LessOrEqualf(t, 2, 2, "error message %s", "formatted") // assert.LessOrEqualf(t, "a", "b", "error message %s", "formatted") // assert.LessOrEqualf(t, "b", "b", "error message %s", "formatted") func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.LessOrEqualf(t, e1, e2, msg, args...) { return } t.FailNow() } // Lessf asserts that the first element is less than the second // // assert.Lessf(t, 1, 2, "error message %s", "formatted") // assert.Lessf(t, float64(1), float64(2), "error message %s", "formatted") // assert.Lessf(t, "a", "b", "error message %s", "formatted") func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Lessf(t, e1, e2, msg, args...) { return } t.FailNow() } // Negative asserts that the specified element is negative // // assert.Negative(t, -1) // assert.Negative(t, -1.23) func Negative(t TestingT, e interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Negative(t, e, msgAndArgs...) { return } t.FailNow() } // Negativef asserts that the specified element is negative // // assert.Negativef(t, -1, "error message %s", "formatted") // assert.Negativef(t, -1.23, "error message %s", "formatted") func Negativef(t TestingT, e interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Negativef(t, e, msg, args...) { return } t.FailNow() } // Never asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // // assert.Never(t, func() bool { return false; }, time.Second, 10*time.Millisecond) func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Never(t, condition, waitFor, tick, msgAndArgs...) { return } t.FailNow() } // Neverf asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // // assert.Neverf(t, func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") func Neverf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Neverf(t, condition, waitFor, tick, msg, args...) { return } t.FailNow() } // Nil asserts that the specified object is nil. // // assert.Nil(t, err) func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Nil(t, object, msgAndArgs...) { return } t.FailNow() } // Nilf asserts that the specified object is nil. // // assert.Nilf(t, err, "error message %s", "formatted") func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Nilf(t, object, msg, args...) { return } t.FailNow() } // NoDirExists checks whether a directory does not exist in the given path. // It fails if the path points to an existing _directory_ only. func NoDirExists(t TestingT, path string, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NoDirExists(t, path, msgAndArgs...) { return } t.FailNow() } // NoDirExistsf checks whether a directory does not exist in the given path. // It fails if the path points to an existing _directory_ only. func NoDirExistsf(t TestingT, path string, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NoDirExistsf(t, path, msg, args...) { return } t.FailNow() } // NoError asserts that a function returned no error (i.e. `nil`). // // actualObj, err := SomeFunction() // if assert.NoError(t, err) { // assert.Equal(t, expectedObj, actualObj) // } func NoError(t TestingT, err error, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NoError(t, err, msgAndArgs...) { return } t.FailNow() } // NoErrorf asserts that a function returned no error (i.e. `nil`). // // actualObj, err := SomeFunction() // if assert.NoErrorf(t, err, "error message %s", "formatted") { // assert.Equal(t, expectedObj, actualObj) // } func NoErrorf(t TestingT, err error, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NoErrorf(t, err, msg, args...) { return } t.FailNow() } // NoFileExists checks whether a file does not exist in a given path. It fails // if the path points to an existing _file_ only. func NoFileExists(t TestingT, path string, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NoFileExists(t, path, msgAndArgs...) { return } t.FailNow() } // NoFileExistsf checks whether a file does not exist in a given path. It fails // if the path points to an existing _file_ only. func NoFileExistsf(t TestingT, path string, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NoFileExistsf(t, path, msg, args...) { return } t.FailNow() } // NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // // assert.NotContains(t, "Hello World", "Earth") // assert.NotContains(t, ["Hello", "World"], "Earth") // assert.NotContains(t, {"Hello": "World"}, "Earth") func NotContains(t TestingT, s interface{}, contains interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotContains(t, s, contains, msgAndArgs...) { return } t.FailNow() } // NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // // assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted") // assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") // assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotContainsf(t, s, contains, msg, args...) { return } t.FailNow() } // NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // // if assert.NotEmpty(t, obj) { // assert.Equal(t, "two", obj[1]) // } func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotEmpty(t, object, msgAndArgs...) { return } t.FailNow() } // NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // // if assert.NotEmptyf(t, obj, "error message %s", "formatted") { // assert.Equal(t, "two", obj[1]) // } func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotEmptyf(t, object, msg, args...) { return } t.FailNow() } // NotEqual asserts that the specified values are NOT equal. // // assert.NotEqual(t, obj1, obj2) // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func NotEqual(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotEqual(t, expected, actual, msgAndArgs...) { return } t.FailNow() } // NotEqualValues asserts that two objects are not equal even when converted to the same type // // assert.NotEqualValues(t, obj1, obj2) func NotEqualValues(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotEqualValues(t, expected, actual, msgAndArgs...) { return } t.FailNow() } // NotEqualValuesf asserts that two objects are not equal even when converted to the same type // // assert.NotEqualValuesf(t, obj1, obj2, "error message %s", "formatted") func NotEqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotEqualValuesf(t, expected, actual, msg, args...) { return } t.FailNow() } // NotEqualf asserts that the specified values are NOT equal. // // assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted") // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotEqualf(t, expected, actual, msg, args...) { return } t.FailNow() } // NotErrorIs asserts that at none of the errors in err's chain matches target. // This is a wrapper for errors.Is. func NotErrorIs(t TestingT, err error, target error, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotErrorIs(t, err, target, msgAndArgs...) { return } t.FailNow() } // NotErrorIsf asserts that at none of the errors in err's chain matches target. // This is a wrapper for errors.Is. func NotErrorIsf(t TestingT, err error, target error, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotErrorIsf(t, err, target, msg, args...) { return } t.FailNow() } // NotImplements asserts that an object does not implement the specified interface. // // assert.NotImplements(t, (*MyInterface)(nil), new(MyObject)) func NotImplements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotImplements(t, interfaceObject, object, msgAndArgs...) { return } t.FailNow() } // NotImplementsf asserts that an object does not implement the specified interface. // // assert.NotImplementsf(t, (*MyInterface)(nil), new(MyObject), "error message %s", "formatted") func NotImplementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotImplementsf(t, interfaceObject, object, msg, args...) { return } t.FailNow() } // NotNil asserts that the specified object is not nil. // // assert.NotNil(t, err) func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotNil(t, object, msgAndArgs...) { return } t.FailNow() } // NotNilf asserts that the specified object is not nil. // // assert.NotNilf(t, err, "error message %s", "formatted") func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotNilf(t, object, msg, args...) { return } t.FailNow() } // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. // // assert.NotPanics(t, func(){ RemainCalm() }) func NotPanics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotPanics(t, f, msgAndArgs...) { return } t.FailNow() } // NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. // // assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") func NotPanicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotPanicsf(t, f, msg, args...) { return } t.FailNow() } // NotRegexp asserts that a specified regexp does not match a string. // // assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") // assert.NotRegexp(t, "^start", "it's not starting") func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotRegexp(t, rx, str, msgAndArgs...) { return } t.FailNow() } // NotRegexpf asserts that a specified regexp does not match a string. // // assert.NotRegexpf(t, regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") // assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotRegexpf(t, rx, str, msg, args...) { return } t.FailNow() } // NotSame asserts that two pointers do not reference the same object. // // assert.NotSame(t, ptr1, ptr2) // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. func NotSame(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotSame(t, expected, actual, msgAndArgs...) { return } t.FailNow() } // NotSamef asserts that two pointers do not reference the same object. // // assert.NotSamef(t, ptr1, ptr2, "error message %s", "formatted") // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotSamef(t, expected, actual, msg, args...) { return } t.FailNow() } // NotSubset asserts that the specified list(array, slice...) or map does NOT // contain all elements given in the specified subset list(array, slice...) or // map. // // assert.NotSubset(t, [1, 3, 4], [1, 2]) // assert.NotSubset(t, {"x": 1, "y": 2}, {"z": 3}) func NotSubset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotSubset(t, list, subset, msgAndArgs...) { return } t.FailNow() } // NotSubsetf asserts that the specified list(array, slice...) or map does NOT // contain all elements given in the specified subset list(array, slice...) or // map. // // assert.NotSubsetf(t, [1, 3, 4], [1, 2], "error message %s", "formatted") // assert.NotSubsetf(t, {"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotSubsetf(t, list, subset, msg, args...) { return } t.FailNow() } // NotZero asserts that i is not the zero value for its type. func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotZero(t, i, msgAndArgs...) { return } t.FailNow() } // NotZerof asserts that i is not the zero value for its type. func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.NotZerof(t, i, msg, args...) { return } t.FailNow() } // Panics asserts that the code inside the specified PanicTestFunc panics. // // assert.Panics(t, func(){ GoCrazy() }) func Panics(t TestingT, f assert.PanicTestFunc, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Panics(t, f, msgAndArgs...) { return } t.FailNow() } // PanicsWithError asserts that the code inside the specified PanicTestFunc // panics, and that the recovered panic value is an error that satisfies the // EqualError comparison. // // assert.PanicsWithError(t, "crazy error", func(){ GoCrazy() }) func PanicsWithError(t TestingT, errString string, f assert.PanicTestFunc, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.PanicsWithError(t, errString, f, msgAndArgs...) { return } t.FailNow() } // PanicsWithErrorf asserts that the code inside the specified PanicTestFunc // panics, and that the recovered panic value is an error that satisfies the // EqualError comparison. // // assert.PanicsWithErrorf(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") func PanicsWithErrorf(t TestingT, errString string, f assert.PanicTestFunc, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.PanicsWithErrorf(t, errString, f, msg, args...) { return } t.FailNow() } // PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // // assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) func PanicsWithValue(t TestingT, expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.PanicsWithValue(t, expected, f, msgAndArgs...) { return } t.FailNow() } // PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // // assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") func PanicsWithValuef(t TestingT, expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.PanicsWithValuef(t, expected, f, msg, args...) { return } t.FailNow() } // Panicsf asserts that the code inside the specified PanicTestFunc panics. // // assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") func Panicsf(t TestingT, f assert.PanicTestFunc, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Panicsf(t, f, msg, args...) { return } t.FailNow() } // Positive asserts that the specified element is positive // // assert.Positive(t, 1) // assert.Positive(t, 1.23) func Positive(t TestingT, e interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Positive(t, e, msgAndArgs...) { return } t.FailNow() } // Positivef asserts that the specified element is positive // // assert.Positivef(t, 1, "error message %s", "formatted") // assert.Positivef(t, 1.23, "error message %s", "formatted") func Positivef(t TestingT, e interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Positivef(t, e, msg, args...) { return } t.FailNow() } // Regexp asserts that a specified regexp matches a string. // // assert.Regexp(t, regexp.MustCompile("start"), "it's starting") // assert.Regexp(t, "start...$", "it's not starting") func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Regexp(t, rx, str, msgAndArgs...) { return } t.FailNow() } // Regexpf asserts that a specified regexp matches a string. // // assert.Regexpf(t, regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") // assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Regexpf(t, rx, str, msg, args...) { return } t.FailNow() } // Same asserts that two pointers reference the same object. // // assert.Same(t, ptr1, ptr2) // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. func Same(t TestingT, expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Same(t, expected, actual, msgAndArgs...) { return } t.FailNow() } // Samef asserts that two pointers reference the same object. // // assert.Samef(t, ptr1, ptr2, "error message %s", "formatted") // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. func Samef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Samef(t, expected, actual, msg, args...) { return } t.FailNow() } // Subset asserts that the specified list(array, slice...) or map contains all // elements given in the specified subset list(array, slice...) or map. // // assert.Subset(t, [1, 2, 3], [1, 2]) // assert.Subset(t, {"x": 1, "y": 2}, {"x": 1}) func Subset(t TestingT, list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Subset(t, list, subset, msgAndArgs...) { return } t.FailNow() } // Subsetf asserts that the specified list(array, slice...) or map contains all // elements given in the specified subset list(array, slice...) or map. // // assert.Subsetf(t, [1, 2, 3], [1, 2], "error message %s", "formatted") // assert.Subsetf(t, {"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Subsetf(t, list, subset, msg, args...) { return } t.FailNow() } // True asserts that the specified value is true. // // assert.True(t, myBool) func True(t TestingT, value bool, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.True(t, value, msgAndArgs...) { return } t.FailNow() } // Truef asserts that the specified value is true. // // assert.Truef(t, myBool, "error message %s", "formatted") func Truef(t TestingT, value bool, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Truef(t, value, msg, args...) { return } t.FailNow() } // WithinDuration asserts that the two times are within duration delta of each other. // // assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) func WithinDuration(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.WithinDuration(t, expected, actual, delta, msgAndArgs...) { return } t.FailNow() } // WithinDurationf asserts that the two times are within duration delta of each other. // // assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.WithinDurationf(t, expected, actual, delta, msg, args...) { return } t.FailNow() } // WithinRange asserts that a time is within a time range (inclusive). // // assert.WithinRange(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) func WithinRange(t TestingT, actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.WithinRange(t, actual, start, end, msgAndArgs...) { return } t.FailNow() } // WithinRangef asserts that a time is within a time range (inclusive). // // assert.WithinRangef(t, time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") func WithinRangef(t TestingT, actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.WithinRangef(t, actual, start, end, msg, args...) { return } t.FailNow() } // Zero asserts that i is the zero value for its type. func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Zero(t, i, msgAndArgs...) { return } t.FailNow() } // Zerof asserts that i is the zero value for its type. func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.Zerof(t, i, msg, args...) { return } t.FailNow() } ================================================ FILE: internal/testify/require/require.go.tmpl ================================================ {{.Comment}} func {{.DocInfo.Name}}(t TestingT, {{.Params}}) { if h, ok := t.(tHelper); ok { h.Helper() } if assert.{{.DocInfo.Name}}(t, {{.ForwardedParams}}) { return } t.FailNow() } ================================================ FILE: internal/testify/require/require_forward.go ================================================ // Code generated with github.com/expr-lang/expr/internal/_codegen; DO NOT EDIT. package require import ( http "net/http" url "net/url" time "time" assert "github.com/expr-lang/expr/internal/testify/assert" ) // Condition uses a Comparison to assert a complex condition. func (a *Assertions) Condition(comp assert.Comparison, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Condition(a.t, comp, msgAndArgs...) } // Conditionf uses a Comparison to assert a complex condition. func (a *Assertions) Conditionf(comp assert.Comparison, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Conditionf(a.t, comp, msg, args...) } // Contains asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // // a.Contains("Hello World", "World") // a.Contains(["Hello", "World"], "World") // a.Contains({"Hello": "World"}, "Hello") func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Contains(a.t, s, contains, msgAndArgs...) } // Containsf asserts that the specified string, list(array, slice...) or map contains the // specified substring or element. // // a.Containsf("Hello World", "World", "error message %s", "formatted") // a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") // a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Containsf(a.t, s, contains, msg, args...) } // DirExists checks whether a directory exists in the given path. It also fails // if the path is a file rather a directory or there is an error checking whether it exists. func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } DirExists(a.t, path, msgAndArgs...) } // DirExistsf checks whether a directory exists in the given path. It also fails // if the path is a file rather a directory or there is an error checking whether it exists. func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } DirExistsf(a.t, path, msg, args...) } // ElementsMatch asserts that the specified listA(array, slice...) is equal to specified // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // // a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2]) func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } ElementsMatch(a.t, listA, listB, msgAndArgs...) } // ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified // listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, // the number of appearances of each of them in both lists should match. // // a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } ElementsMatchf(a.t, listA, listB, msg, args...) } // Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // // a.Empty(obj) func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Empty(a.t, object, msgAndArgs...) } // Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either // a slice or a channel with len == 0. // // a.Emptyf(obj, "error message %s", "formatted") func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Emptyf(a.t, object, msg, args...) } // Equal asserts that two objects are equal. // // a.Equal(123, 123) // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Equal(a.t, expected, actual, msgAndArgs...) } // EqualError asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // // actualObj, err := SomeFunction() // a.EqualError(err, expectedErrorString) func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } EqualError(a.t, theError, errString, msgAndArgs...) } // EqualErrorf asserts that a function returned an error (i.e. not `nil`) // and that it is equal to the provided error. // // actualObj, err := SomeFunction() // a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } EqualErrorf(a.t, theError, errString, msg, args...) } // EqualExportedValues asserts that the types of two objects are equal and their public // fields are also equal. This is useful for comparing structs that have private fields // that could potentially differ. // // type S struct { // Exported int // notExported int // } // a.EqualExportedValues(S{1, 2}, S{1, 3}) => true // a.EqualExportedValues(S{1, 2}, S{2, 3}) => false func (a *Assertions) EqualExportedValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } EqualExportedValues(a.t, expected, actual, msgAndArgs...) } // EqualExportedValuesf asserts that the types of two objects are equal and their public // fields are also equal. This is useful for comparing structs that have private fields // that could potentially differ. // // type S struct { // Exported int // notExported int // } // a.EqualExportedValuesf(S{1, 2}, S{1, 3}, "error message %s", "formatted") => true // a.EqualExportedValuesf(S{1, 2}, S{2, 3}, "error message %s", "formatted") => false func (a *Assertions) EqualExportedValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } EqualExportedValuesf(a.t, expected, actual, msg, args...) } // EqualValues asserts that two objects are equal or convertible to the same types // and equal. // // a.EqualValues(uint32(123), int32(123)) func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } EqualValues(a.t, expected, actual, msgAndArgs...) } // EqualValuesf asserts that two objects are equal or convertible to the same types // and equal. // // a.EqualValuesf(uint32(123), int32(123), "error message %s", "formatted") func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } EqualValuesf(a.t, expected, actual, msg, args...) } // Equalf asserts that two objects are equal. // // a.Equalf(123, 123, "error message %s", "formatted") // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). Function equality // cannot be determined and will always fail. func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Equalf(a.t, expected, actual, msg, args...) } // Error asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() // if a.Error(err) { // assert.Equal(t, expectedError, err) // } func (a *Assertions) Error(err error, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Error(a.t, err, msgAndArgs...) } // ErrorAs asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. // This is a wrapper for errors.As. func (a *Assertions) ErrorAs(err error, target interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } ErrorAs(a.t, err, target, msgAndArgs...) } // ErrorAsf asserts that at least one of the errors in err's chain matches target, and if so, sets target to that error value. // This is a wrapper for errors.As. func (a *Assertions) ErrorAsf(err error, target interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } ErrorAsf(a.t, err, target, msg, args...) } // ErrorContains asserts that a function returned an error (i.e. not `nil`) // and that the error contains the specified substring. // // actualObj, err := SomeFunction() // a.ErrorContains(err, expectedErrorSubString) func (a *Assertions) ErrorContains(theError error, contains string, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } ErrorContains(a.t, theError, contains, msgAndArgs...) } // ErrorContainsf asserts that a function returned an error (i.e. not `nil`) // and that the error contains the specified substring. // // actualObj, err := SomeFunction() // a.ErrorContainsf(err, expectedErrorSubString, "error message %s", "formatted") func (a *Assertions) ErrorContainsf(theError error, contains string, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } ErrorContainsf(a.t, theError, contains, msg, args...) } // ErrorIs asserts that at least one of the errors in err's chain matches target. // This is a wrapper for errors.Is. func (a *Assertions) ErrorIs(err error, target error, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } ErrorIs(a.t, err, target, msgAndArgs...) } // ErrorIsf asserts that at least one of the errors in err's chain matches target. // This is a wrapper for errors.Is. func (a *Assertions) ErrorIsf(err error, target error, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } ErrorIsf(a.t, err, target, msg, args...) } // Errorf asserts that a function returned an error (i.e. not `nil`). // // actualObj, err := SomeFunction() // if a.Errorf(err, "error message %s", "formatted") { // assert.Equal(t, expectedErrorf, err) // } func (a *Assertions) Errorf(err error, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Errorf(a.t, err, msg, args...) } // Eventually asserts that given condition will be met in waitFor time, // periodically checking target function each tick. // // a.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond) func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Eventually(a.t, condition, waitFor, tick, msgAndArgs...) } // EventuallyWithT asserts that given condition will be met in waitFor time, // periodically checking target function each tick. In contrast to Eventually, // it supplies a CollectT to the condition function, so that the condition // function can use the CollectT to call other assertions. // The condition is considered "met" if no errors are raised in a tick. // The supplied CollectT collects all errors from one tick (if there are any). // If the condition is not met before waitFor, the collected errors of // the last tick are copied to t. // // externalValue := false // go func() { // time.Sleep(8*time.Second) // externalValue = true // }() // a.EventuallyWithT(func(c *assert.CollectT) { // // add assertions as needed; any assertion failure will fail the current tick // assert.True(c, externalValue, "expected 'externalValue' to be true") // }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false") func (a *Assertions) EventuallyWithT(condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } EventuallyWithT(a.t, condition, waitFor, tick, msgAndArgs...) } // EventuallyWithTf asserts that given condition will be met in waitFor time, // periodically checking target function each tick. In contrast to Eventually, // it supplies a CollectT to the condition function, so that the condition // function can use the CollectT to call other assertions. // The condition is considered "met" if no errors are raised in a tick. // The supplied CollectT collects all errors from one tick (if there are any). // If the condition is not met before waitFor, the collected errors of // the last tick are copied to t. // // externalValue := false // go func() { // time.Sleep(8*time.Second) // externalValue = true // }() // a.EventuallyWithTf(func(c *assert.CollectT, "error message %s", "formatted") { // // add assertions as needed; any assertion failure will fail the current tick // assert.True(c, externalValue, "expected 'externalValue' to be true") // }, 10*time.Second, 1*time.Second, "external state has not changed to 'true'; still false") func (a *Assertions) EventuallyWithTf(condition func(collect *assert.CollectT), waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } EventuallyWithTf(a.t, condition, waitFor, tick, msg, args...) } // Eventuallyf asserts that given condition will be met in waitFor time, // periodically checking target function each tick. // // a.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Eventuallyf(a.t, condition, waitFor, tick, msg, args...) } // Exactly asserts that two objects are equal in value and type. // // a.Exactly(int32(123), int64(123)) func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Exactly(a.t, expected, actual, msgAndArgs...) } // Exactlyf asserts that two objects are equal in value and type. // // a.Exactlyf(int32(123), int64(123), "error message %s", "formatted") func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Exactlyf(a.t, expected, actual, msg, args...) } // Fail reports a failure through func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Fail(a.t, failureMessage, msgAndArgs...) } // FailNow fails test func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } FailNow(a.t, failureMessage, msgAndArgs...) } // FailNowf fails test func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } FailNowf(a.t, failureMessage, msg, args...) } // Failf reports a failure through func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Failf(a.t, failureMessage, msg, args...) } // False asserts that the specified value is false. // // a.False(myBool) func (a *Assertions) False(value bool, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } False(a.t, value, msgAndArgs...) } // Falsef asserts that the specified value is false. // // a.Falsef(myBool, "error message %s", "formatted") func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Falsef(a.t, value, msg, args...) } // FileExists checks whether a file exists in the given path. It also fails if // the path points to a directory or there is an error when trying to check the file. func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } FileExists(a.t, path, msgAndArgs...) } // FileExistsf checks whether a file exists in the given path. It also fails if // the path points to a directory or there is an error when trying to check the file. func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } FileExistsf(a.t, path, msg, args...) } // Greater asserts that the first element is greater than the second // // a.Greater(2, 1) // a.Greater(float64(2), float64(1)) // a.Greater("b", "a") func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Greater(a.t, e1, e2, msgAndArgs...) } // GreaterOrEqual asserts that the first element is greater than or equal to the second // // a.GreaterOrEqual(2, 1) // a.GreaterOrEqual(2, 2) // a.GreaterOrEqual("b", "a") // a.GreaterOrEqual("b", "b") func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } GreaterOrEqual(a.t, e1, e2, msgAndArgs...) } // GreaterOrEqualf asserts that the first element is greater than or equal to the second // // a.GreaterOrEqualf(2, 1, "error message %s", "formatted") // a.GreaterOrEqualf(2, 2, "error message %s", "formatted") // a.GreaterOrEqualf("b", "a", "error message %s", "formatted") // a.GreaterOrEqualf("b", "b", "error message %s", "formatted") func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } GreaterOrEqualf(a.t, e1, e2, msg, args...) } // Greaterf asserts that the first element is greater than the second // // a.Greaterf(2, 1, "error message %s", "formatted") // a.Greaterf(float64(2), float64(1), "error message %s", "formatted") // a.Greaterf("b", "a", "error message %s", "formatted") func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Greaterf(a.t, e1, e2, msg, args...) } // HTTPBodyContains asserts that a specified handler returns a // body that contains a string. // // a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...) } // HTTPBodyContainsf asserts that a specified handler returns a // body that contains a string. // // a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...) } // HTTPBodyNotContains asserts that a specified handler returns a // body that does not contain a string. // // a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...) } // HTTPBodyNotContainsf asserts that a specified handler returns a // body that does not contain a string. // // a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...) } // HTTPError asserts that a specified handler returns an error status code. // // a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } HTTPError(a.t, handler, method, url, values, msgAndArgs...) } // HTTPErrorf asserts that a specified handler returns an error status code. // // a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } HTTPErrorf(a.t, handler, method, url, values, msg, args...) } // HTTPRedirect asserts that a specified handler returns a redirect status code. // // a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...) } // HTTPRedirectf asserts that a specified handler returns a redirect status code. // // a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } HTTPRedirectf(a.t, handler, method, url, values, msg, args...) } // HTTPStatusCode asserts that a specified handler returns a specified status code. // // a.HTTPStatusCode(myHandler, "GET", "/notImplemented", nil, 501) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPStatusCode(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } HTTPStatusCode(a.t, handler, method, url, values, statuscode, msgAndArgs...) } // HTTPStatusCodef asserts that a specified handler returns a specified status code. // // a.HTTPStatusCodef(myHandler, "GET", "/notImplemented", nil, 501, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPStatusCodef(handler http.HandlerFunc, method string, url string, values url.Values, statuscode int, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } HTTPStatusCodef(a.t, handler, method, url, values, statuscode, msg, args...) } // HTTPSuccess asserts that a specified handler returns a success status code. // // a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...) } // HTTPSuccessf asserts that a specified handler returns a success status code. // // a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") // // Returns whether the assertion was successful (true) or not (false). func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } HTTPSuccessf(a.t, handler, method, url, values, msg, args...) } // Implements asserts that an object is implemented by the specified interface. // // a.Implements((*MyInterface)(nil), new(MyObject)) func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Implements(a.t, interfaceObject, object, msgAndArgs...) } // Implementsf asserts that an object is implemented by the specified interface. // // a.Implementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Implementsf(a.t, interfaceObject, object, msg, args...) } // InDelta asserts that the two numerals are within delta of each other. // // a.InDelta(math.Pi, 22/7.0, 0.01) func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } InDelta(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...) } // InDeltaSlice is the same as InDelta, except it compares two slices. func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...) } // InDeltaSlicef is the same as InDelta, except it compares two slices. func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } InDeltaSlicef(a.t, expected, actual, delta, msg, args...) } // InDeltaf asserts that the two numerals are within delta of each other. // // a.InDeltaf(math.Pi, 22/7.0, 0.01, "error message %s", "formatted") func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } InDeltaf(a.t, expected, actual, delta, msg, args...) } // InEpsilon asserts that expected and actual have a relative error less than epsilon func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) } // InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...) } // InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...) } // InEpsilonf asserts that expected and actual have a relative error less than epsilon func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } InEpsilonf(a.t, expected, actual, epsilon, msg, args...) } // IsDecreasing asserts that the collection is decreasing // // a.IsDecreasing([]int{2, 1, 0}) // a.IsDecreasing([]float{2, 1}) // a.IsDecreasing([]string{"b", "a"}) func (a *Assertions) IsDecreasing(object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } IsDecreasing(a.t, object, msgAndArgs...) } // IsDecreasingf asserts that the collection is decreasing // // a.IsDecreasingf([]int{2, 1, 0}, "error message %s", "formatted") // a.IsDecreasingf([]float{2, 1}, "error message %s", "formatted") // a.IsDecreasingf([]string{"b", "a"}, "error message %s", "formatted") func (a *Assertions) IsDecreasingf(object interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } IsDecreasingf(a.t, object, msg, args...) } // IsIncreasing asserts that the collection is increasing // // a.IsIncreasing([]int{1, 2, 3}) // a.IsIncreasing([]float{1, 2}) // a.IsIncreasing([]string{"a", "b"}) func (a *Assertions) IsIncreasing(object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } IsIncreasing(a.t, object, msgAndArgs...) } // IsIncreasingf asserts that the collection is increasing // // a.IsIncreasingf([]int{1, 2, 3}, "error message %s", "formatted") // a.IsIncreasingf([]float{1, 2}, "error message %s", "formatted") // a.IsIncreasingf([]string{"a", "b"}, "error message %s", "formatted") func (a *Assertions) IsIncreasingf(object interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } IsIncreasingf(a.t, object, msg, args...) } // IsNonDecreasing asserts that the collection is not decreasing // // a.IsNonDecreasing([]int{1, 1, 2}) // a.IsNonDecreasing([]float{1, 2}) // a.IsNonDecreasing([]string{"a", "b"}) func (a *Assertions) IsNonDecreasing(object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } IsNonDecreasing(a.t, object, msgAndArgs...) } // IsNonDecreasingf asserts that the collection is not decreasing // // a.IsNonDecreasingf([]int{1, 1, 2}, "error message %s", "formatted") // a.IsNonDecreasingf([]float{1, 2}, "error message %s", "formatted") // a.IsNonDecreasingf([]string{"a", "b"}, "error message %s", "formatted") func (a *Assertions) IsNonDecreasingf(object interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } IsNonDecreasingf(a.t, object, msg, args...) } // IsNonIncreasing asserts that the collection is not increasing // // a.IsNonIncreasing([]int{2, 1, 1}) // a.IsNonIncreasing([]float{2, 1}) // a.IsNonIncreasing([]string{"b", "a"}) func (a *Assertions) IsNonIncreasing(object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } IsNonIncreasing(a.t, object, msgAndArgs...) } // IsNonIncreasingf asserts that the collection is not increasing // // a.IsNonIncreasingf([]int{2, 1, 1}, "error message %s", "formatted") // a.IsNonIncreasingf([]float{2, 1}, "error message %s", "formatted") // a.IsNonIncreasingf([]string{"b", "a"}, "error message %s", "formatted") func (a *Assertions) IsNonIncreasingf(object interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } IsNonIncreasingf(a.t, object, msg, args...) } // IsType asserts that the specified objects are of the same type. func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } IsType(a.t, expectedType, object, msgAndArgs...) } // IsTypef asserts that the specified objects are of the same type. func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } IsTypef(a.t, expectedType, object, msg, args...) } // JSONEq asserts that two JSON strings are equivalent. // // a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } JSONEq(a.t, expected, actual, msgAndArgs...) } // JSONEqf asserts that two JSON strings are equivalent. // // a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } JSONEqf(a.t, expected, actual, msg, args...) } // Len asserts that the specified object has specific length. // Len also fails if the object has a type that len() not accept. // // a.Len(mySlice, 3) func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Len(a.t, object, length, msgAndArgs...) } // Lenf asserts that the specified object has specific length. // Lenf also fails if the object has a type that len() not accept. // // a.Lenf(mySlice, 3, "error message %s", "formatted") func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Lenf(a.t, object, length, msg, args...) } // Less asserts that the first element is less than the second // // a.Less(1, 2) // a.Less(float64(1), float64(2)) // a.Less("a", "b") func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Less(a.t, e1, e2, msgAndArgs...) } // LessOrEqual asserts that the first element is less than or equal to the second // // a.LessOrEqual(1, 2) // a.LessOrEqual(2, 2) // a.LessOrEqual("a", "b") // a.LessOrEqual("b", "b") func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } LessOrEqual(a.t, e1, e2, msgAndArgs...) } // LessOrEqualf asserts that the first element is less than or equal to the second // // a.LessOrEqualf(1, 2, "error message %s", "formatted") // a.LessOrEqualf(2, 2, "error message %s", "formatted") // a.LessOrEqualf("a", "b", "error message %s", "formatted") // a.LessOrEqualf("b", "b", "error message %s", "formatted") func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } LessOrEqualf(a.t, e1, e2, msg, args...) } // Lessf asserts that the first element is less than the second // // a.Lessf(1, 2, "error message %s", "formatted") // a.Lessf(float64(1), float64(2), "error message %s", "formatted") // a.Lessf("a", "b", "error message %s", "formatted") func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Lessf(a.t, e1, e2, msg, args...) } // Negative asserts that the specified element is negative // // a.Negative(-1) // a.Negative(-1.23) func (a *Assertions) Negative(e interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Negative(a.t, e, msgAndArgs...) } // Negativef asserts that the specified element is negative // // a.Negativef(-1, "error message %s", "formatted") // a.Negativef(-1.23, "error message %s", "formatted") func (a *Assertions) Negativef(e interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Negativef(a.t, e, msg, args...) } // Never asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // // a.Never(func() bool { return false; }, time.Second, 10*time.Millisecond) func (a *Assertions) Never(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Never(a.t, condition, waitFor, tick, msgAndArgs...) } // Neverf asserts that the given condition doesn't satisfy in waitFor time, // periodically checking the target function each tick. // // a.Neverf(func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") func (a *Assertions) Neverf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Neverf(a.t, condition, waitFor, tick, msg, args...) } // Nil asserts that the specified object is nil. // // a.Nil(err) func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Nil(a.t, object, msgAndArgs...) } // Nilf asserts that the specified object is nil. // // a.Nilf(err, "error message %s", "formatted") func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Nilf(a.t, object, msg, args...) } // NoDirExists checks whether a directory does not exist in the given path. // It fails if the path points to an existing _directory_ only. func (a *Assertions) NoDirExists(path string, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NoDirExists(a.t, path, msgAndArgs...) } // NoDirExistsf checks whether a directory does not exist in the given path. // It fails if the path points to an existing _directory_ only. func (a *Assertions) NoDirExistsf(path string, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NoDirExistsf(a.t, path, msg, args...) } // NoError asserts that a function returned no error (i.e. `nil`). // // actualObj, err := SomeFunction() // if a.NoError(err) { // assert.Equal(t, expectedObj, actualObj) // } func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NoError(a.t, err, msgAndArgs...) } // NoErrorf asserts that a function returned no error (i.e. `nil`). // // actualObj, err := SomeFunction() // if a.NoErrorf(err, "error message %s", "formatted") { // assert.Equal(t, expectedObj, actualObj) // } func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NoErrorf(a.t, err, msg, args...) } // NoFileExists checks whether a file does not exist in a given path. It fails // if the path points to an existing _file_ only. func (a *Assertions) NoFileExists(path string, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NoFileExists(a.t, path, msgAndArgs...) } // NoFileExistsf checks whether a file does not exist in a given path. It fails // if the path points to an existing _file_ only. func (a *Assertions) NoFileExistsf(path string, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NoFileExistsf(a.t, path, msg, args...) } // NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // // a.NotContains("Hello World", "Earth") // a.NotContains(["Hello", "World"], "Earth") // a.NotContains({"Hello": "World"}, "Earth") func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotContains(a.t, s, contains, msgAndArgs...) } // NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the // specified substring or element. // // a.NotContainsf("Hello World", "Earth", "error message %s", "formatted") // a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") // a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotContainsf(a.t, s, contains, msg, args...) } // NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // // if a.NotEmpty(obj) { // assert.Equal(t, "two", obj[1]) // } func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotEmpty(a.t, object, msgAndArgs...) } // NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either // a slice or a channel with len == 0. // // if a.NotEmptyf(obj, "error message %s", "formatted") { // assert.Equal(t, "two", obj[1]) // } func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotEmptyf(a.t, object, msg, args...) } // NotEqual asserts that the specified values are NOT equal. // // a.NotEqual(obj1, obj2) // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotEqual(a.t, expected, actual, msgAndArgs...) } // NotEqualValues asserts that two objects are not equal even when converted to the same type // // a.NotEqualValues(obj1, obj2) func (a *Assertions) NotEqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotEqualValues(a.t, expected, actual, msgAndArgs...) } // NotEqualValuesf asserts that two objects are not equal even when converted to the same type // // a.NotEqualValuesf(obj1, obj2, "error message %s", "formatted") func (a *Assertions) NotEqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotEqualValuesf(a.t, expected, actual, msg, args...) } // NotEqualf asserts that the specified values are NOT equal. // // a.NotEqualf(obj1, obj2, "error message %s", "formatted") // // Pointer variable equality is determined based on the equality of the // referenced values (as opposed to the memory addresses). func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotEqualf(a.t, expected, actual, msg, args...) } // NotErrorIs asserts that at none of the errors in err's chain matches target. // This is a wrapper for errors.Is. func (a *Assertions) NotErrorIs(err error, target error, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotErrorIs(a.t, err, target, msgAndArgs...) } // NotErrorIsf asserts that at none of the errors in err's chain matches target. // This is a wrapper for errors.Is. func (a *Assertions) NotErrorIsf(err error, target error, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotErrorIsf(a.t, err, target, msg, args...) } // NotImplements asserts that an object does not implement the specified interface. // // a.NotImplements((*MyInterface)(nil), new(MyObject)) func (a *Assertions) NotImplements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotImplements(a.t, interfaceObject, object, msgAndArgs...) } // NotImplementsf asserts that an object does not implement the specified interface. // // a.NotImplementsf((*MyInterface)(nil), new(MyObject), "error message %s", "formatted") func (a *Assertions) NotImplementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotImplementsf(a.t, interfaceObject, object, msg, args...) } // NotNil asserts that the specified object is not nil. // // a.NotNil(err) func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotNil(a.t, object, msgAndArgs...) } // NotNilf asserts that the specified object is not nil. // // a.NotNilf(err, "error message %s", "formatted") func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotNilf(a.t, object, msg, args...) } // NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. // // a.NotPanics(func(){ RemainCalm() }) func (a *Assertions) NotPanics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotPanics(a.t, f, msgAndArgs...) } // NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. // // a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") func (a *Assertions) NotPanicsf(f assert.PanicTestFunc, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotPanicsf(a.t, f, msg, args...) } // NotRegexp asserts that a specified regexp does not match a string. // // a.NotRegexp(regexp.MustCompile("starts"), "it's starting") // a.NotRegexp("^start", "it's not starting") func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotRegexp(a.t, rx, str, msgAndArgs...) } // NotRegexpf asserts that a specified regexp does not match a string. // // a.NotRegexpf(regexp.MustCompile("starts"), "it's starting", "error message %s", "formatted") // a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotRegexpf(a.t, rx, str, msg, args...) } // NotSame asserts that two pointers do not reference the same object. // // a.NotSame(ptr1, ptr2) // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. func (a *Assertions) NotSame(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotSame(a.t, expected, actual, msgAndArgs...) } // NotSamef asserts that two pointers do not reference the same object. // // a.NotSamef(ptr1, ptr2, "error message %s", "formatted") // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotSamef(a.t, expected, actual, msg, args...) } // NotSubset asserts that the specified list(array, slice...) or map does NOT // contain all elements given in the specified subset list(array, slice...) or // map. // // a.NotSubset([1, 3, 4], [1, 2]) // a.NotSubset({"x": 1, "y": 2}, {"z": 3}) func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotSubset(a.t, list, subset, msgAndArgs...) } // NotSubsetf asserts that the specified list(array, slice...) or map does NOT // contain all elements given in the specified subset list(array, slice...) or // map. // // a.NotSubsetf([1, 3, 4], [1, 2], "error message %s", "formatted") // a.NotSubsetf({"x": 1, "y": 2}, {"z": 3}, "error message %s", "formatted") func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotSubsetf(a.t, list, subset, msg, args...) } // NotZero asserts that i is not the zero value for its type. func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotZero(a.t, i, msgAndArgs...) } // NotZerof asserts that i is not the zero value for its type. func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } NotZerof(a.t, i, msg, args...) } // Panics asserts that the code inside the specified PanicTestFunc panics. // // a.Panics(func(){ GoCrazy() }) func (a *Assertions) Panics(f assert.PanicTestFunc, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Panics(a.t, f, msgAndArgs...) } // PanicsWithError asserts that the code inside the specified PanicTestFunc // panics, and that the recovered panic value is an error that satisfies the // EqualError comparison. // // a.PanicsWithError("crazy error", func(){ GoCrazy() }) func (a *Assertions) PanicsWithError(errString string, f assert.PanicTestFunc, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } PanicsWithError(a.t, errString, f, msgAndArgs...) } // PanicsWithErrorf asserts that the code inside the specified PanicTestFunc // panics, and that the recovered panic value is an error that satisfies the // EqualError comparison. // // a.PanicsWithErrorf("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") func (a *Assertions) PanicsWithErrorf(errString string, f assert.PanicTestFunc, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } PanicsWithErrorf(a.t, errString, f, msg, args...) } // PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // // a.PanicsWithValue("crazy error", func(){ GoCrazy() }) func (a *Assertions) PanicsWithValue(expected interface{}, f assert.PanicTestFunc, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } PanicsWithValue(a.t, expected, f, msgAndArgs...) } // PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that // the recovered panic value equals the expected panic value. // // a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") func (a *Assertions) PanicsWithValuef(expected interface{}, f assert.PanicTestFunc, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } PanicsWithValuef(a.t, expected, f, msg, args...) } // Panicsf asserts that the code inside the specified PanicTestFunc panics. // // a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") func (a *Assertions) Panicsf(f assert.PanicTestFunc, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Panicsf(a.t, f, msg, args...) } // Positive asserts that the specified element is positive // // a.Positive(1) // a.Positive(1.23) func (a *Assertions) Positive(e interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Positive(a.t, e, msgAndArgs...) } // Positivef asserts that the specified element is positive // // a.Positivef(1, "error message %s", "formatted") // a.Positivef(1.23, "error message %s", "formatted") func (a *Assertions) Positivef(e interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Positivef(a.t, e, msg, args...) } // Regexp asserts that a specified regexp matches a string. // // a.Regexp(regexp.MustCompile("start"), "it's starting") // a.Regexp("start...$", "it's not starting") func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Regexp(a.t, rx, str, msgAndArgs...) } // Regexpf asserts that a specified regexp matches a string. // // a.Regexpf(regexp.MustCompile("start"), "it's starting", "error message %s", "formatted") // a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Regexpf(a.t, rx, str, msg, args...) } // Same asserts that two pointers reference the same object. // // a.Same(ptr1, ptr2) // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. func (a *Assertions) Same(expected interface{}, actual interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Same(a.t, expected, actual, msgAndArgs...) } // Samef asserts that two pointers reference the same object. // // a.Samef(ptr1, ptr2, "error message %s", "formatted") // // Both arguments must be pointer variables. Pointer variable sameness is // determined based on the equality of both type and value. func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Samef(a.t, expected, actual, msg, args...) } // Subset asserts that the specified list(array, slice...) or map contains all // elements given in the specified subset list(array, slice...) or map. // // a.Subset([1, 2, 3], [1, 2]) // a.Subset({"x": 1, "y": 2}, {"x": 1}) func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Subset(a.t, list, subset, msgAndArgs...) } // Subsetf asserts that the specified list(array, slice...) or map contains all // elements given in the specified subset list(array, slice...) or map. // // a.Subsetf([1, 2, 3], [1, 2], "error message %s", "formatted") // a.Subsetf({"x": 1, "y": 2}, {"x": 1}, "error message %s", "formatted") func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Subsetf(a.t, list, subset, msg, args...) } // True asserts that the specified value is true. // // a.True(myBool) func (a *Assertions) True(value bool, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } True(a.t, value, msgAndArgs...) } // Truef asserts that the specified value is true. // // a.Truef(myBool, "error message %s", "formatted") func (a *Assertions) Truef(value bool, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Truef(a.t, value, msg, args...) } // WithinDuration asserts that the two times are within duration delta of each other. // // a.WithinDuration(time.Now(), time.Now(), 10*time.Second) func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } WithinDuration(a.t, expected, actual, delta, msgAndArgs...) } // WithinDurationf asserts that the two times are within duration delta of each other. // // a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } WithinDurationf(a.t, expected, actual, delta, msg, args...) } // WithinRange asserts that a time is within a time range (inclusive). // // a.WithinRange(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second)) func (a *Assertions) WithinRange(actual time.Time, start time.Time, end time.Time, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } WithinRange(a.t, actual, start, end, msgAndArgs...) } // WithinRangef asserts that a time is within a time range (inclusive). // // a.WithinRangef(time.Now(), time.Now().Add(-time.Second), time.Now().Add(time.Second), "error message %s", "formatted") func (a *Assertions) WithinRangef(actual time.Time, start time.Time, end time.Time, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } WithinRangef(a.t, actual, start, end, msg, args...) } // Zero asserts that i is the zero value for its type. func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Zero(a.t, i, msgAndArgs...) } // Zerof asserts that i is the zero value for its type. func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) { if h, ok := a.t.(tHelper); ok { h.Helper() } Zerof(a.t, i, msg, args...) } ================================================ FILE: internal/testify/require/require_forward.go.tmpl ================================================ {{.CommentWithoutT "a"}} func (a *Assertions) {{.DocInfo.Name}}({{.Params}}) { if h, ok := a.t.(tHelper); ok { h.Helper() } {{.DocInfo.Name}}(a.t, {{.ForwardedParams}}) } ================================================ FILE: internal/testify/require/requirements.go ================================================ package require // TestingT is an interface wrapper around *testing.T type TestingT interface { Errorf(format string, args ...interface{}) FailNow() } type tHelper = interface { Helper() } // ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful // for table driven tests. type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) // ValueAssertionFunc is a common function prototype when validating a single value. Can be useful // for table driven tests. type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) // BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful // for table driven tests. type BoolAssertionFunc func(TestingT, bool, ...interface{}) // ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful // for table driven tests. type ErrorAssertionFunc func(TestingT, error, ...interface{}) //go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=require -template=require.go.tmpl -include-format-funcs" ================================================ FILE: internal/testify/require/requirements_test.go ================================================ package require import ( "encoding/json" "errors" "testing" "time" ) // AssertionTesterInterface defines an interface to be used for testing assertion methods type AssertionTesterInterface interface { TestMethod() } // AssertionTesterConformingObject is an object that conforms to the AssertionTesterInterface interface type AssertionTesterConformingObject struct { } func (a *AssertionTesterConformingObject) TestMethod() { } // AssertionTesterNonConformingObject is an object that does not conform to the AssertionTesterInterface interface type AssertionTesterNonConformingObject struct { } type MockT struct { Failed bool } func (t *MockT) FailNow() { t.Failed = true } func (t *MockT) Errorf(format string, args ...interface{}) { _, _ = format, args } func TestImplements(t *testing.T) { Implements(t, (*AssertionTesterInterface)(nil), new(AssertionTesterConformingObject)) mockT := new(MockT) Implements(mockT, (*AssertionTesterInterface)(nil), new(AssertionTesterNonConformingObject)) if !mockT.Failed { t.Error("Check should fail") } } func TestIsType(t *testing.T) { IsType(t, new(AssertionTesterConformingObject), new(AssertionTesterConformingObject)) mockT := new(MockT) IsType(mockT, new(AssertionTesterConformingObject), new(AssertionTesterNonConformingObject)) if !mockT.Failed { t.Error("Check should fail") } } func TestEqual(t *testing.T) { Equal(t, 1, 1) mockT := new(MockT) Equal(mockT, 1, 2) if !mockT.Failed { t.Error("Check should fail") } } func TestNotEqual(t *testing.T) { NotEqual(t, 1, 2) mockT := new(MockT) NotEqual(mockT, 2, 2) if !mockT.Failed { t.Error("Check should fail") } } func TestExactly(t *testing.T) { a := float32(1) b := float32(1) c := float64(1) Exactly(t, a, b) mockT := new(MockT) Exactly(mockT, a, c) if !mockT.Failed { t.Error("Check should fail") } } func TestNotNil(t *testing.T) { NotNil(t, new(AssertionTesterConformingObject)) mockT := new(MockT) NotNil(mockT, nil) if !mockT.Failed { t.Error("Check should fail") } } func TestNil(t *testing.T) { Nil(t, nil) mockT := new(MockT) Nil(mockT, new(AssertionTesterConformingObject)) if !mockT.Failed { t.Error("Check should fail") } } func TestTrue(t *testing.T) { True(t, true) mockT := new(MockT) True(mockT, false) if !mockT.Failed { t.Error("Check should fail") } } func TestFalse(t *testing.T) { False(t, false) mockT := new(MockT) False(mockT, true) if !mockT.Failed { t.Error("Check should fail") } } func TestContains(t *testing.T) { Contains(t, "Hello World", "Hello") mockT := new(MockT) Contains(mockT, "Hello World", "Salut") if !mockT.Failed { t.Error("Check should fail") } } func TestNotContains(t *testing.T) { NotContains(t, "Hello World", "Hello!") mockT := new(MockT) NotContains(mockT, "Hello World", "Hello") if !mockT.Failed { t.Error("Check should fail") } } func TestPanics(t *testing.T) { Panics(t, func() { panic("Panic!") }) mockT := new(MockT) Panics(mockT, func() {}) if !mockT.Failed { t.Error("Check should fail") } } func TestNotPanics(t *testing.T) { NotPanics(t, func() {}) mockT := new(MockT) NotPanics(mockT, func() { panic("Panic!") }) if !mockT.Failed { t.Error("Check should fail") } } func TestNoError(t *testing.T) { NoError(t, nil) mockT := new(MockT) NoError(mockT, errors.New("some error")) if !mockT.Failed { t.Error("Check should fail") } } func TestError(t *testing.T) { Error(t, errors.New("some error")) mockT := new(MockT) Error(mockT, nil) if !mockT.Failed { t.Error("Check should fail") } } func TestErrorContains(t *testing.T) { ErrorContains(t, errors.New("some error: another error"), "some error") mockT := new(MockT) ErrorContains(mockT, errors.New("some error"), "different error") if !mockT.Failed { t.Error("Check should fail") } } func TestEqualError(t *testing.T) { EqualError(t, errors.New("some error"), "some error") mockT := new(MockT) EqualError(mockT, errors.New("some error"), "Not some error") if !mockT.Failed { t.Error("Check should fail") } } func TestEmpty(t *testing.T) { Empty(t, "") mockT := new(MockT) Empty(mockT, "x") if !mockT.Failed { t.Error("Check should fail") } } func TestNotEmpty(t *testing.T) { NotEmpty(t, "x") mockT := new(MockT) NotEmpty(mockT, "") if !mockT.Failed { t.Error("Check should fail") } } func TestWithinDuration(t *testing.T) { a := time.Now() b := a.Add(10 * time.Second) WithinDuration(t, a, b, 15*time.Second) mockT := new(MockT) WithinDuration(mockT, a, b, 5*time.Second) if !mockT.Failed { t.Error("Check should fail") } } func TestInDelta(t *testing.T) { InDelta(t, 1.001, 1, 0.01) mockT := new(MockT) InDelta(mockT, 1, 2, 0.5) if !mockT.Failed { t.Error("Check should fail") } } func TestZero(t *testing.T) { Zero(t, "") mockT := new(MockT) Zero(mockT, "x") if !mockT.Failed { t.Error("Check should fail") } } func TestNotZero(t *testing.T) { NotZero(t, "x") mockT := new(MockT) NotZero(mockT, "") if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEq_EqualSONString(t *testing.T) { mockT := new(MockT) JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"hello": "world", "foo": "bar"}`) if mockT.Failed { t.Error("Check should pass") } } func TestJSONEq_EquivalentButNotEqual(t *testing.T) { mockT := new(MockT) JSONEq(mockT, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) if mockT.Failed { t.Error("Check should pass") } } func TestJSONEq_HashOfArraysAndHashes(t *testing.T) { mockT := new(MockT) JSONEq(mockT, "{\r\n\t\"numeric\": 1.5,\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]],\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\"\r\n}", "{\r\n\t\"numeric\": 1.5,\r\n\t\"hash\": {\"nested\": \"hash\", \"nested_slice\": [\"this\", \"is\", \"nested\"]},\r\n\t\"string\": \"foo\",\r\n\t\"array\": [{\"foo\": \"bar\"}, 1, \"string\", [\"nested\", \"array\", 5.5]]\r\n}") if mockT.Failed { t.Error("Check should pass") } } func TestJSONEq_Array(t *testing.T) { mockT := new(MockT) JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `["foo", {"nested": "hash", "hello": "world"}]`) if mockT.Failed { t.Error("Check should pass") } } func TestJSONEq_HashAndArrayNotEquivalent(t *testing.T) { mockT := new(MockT) JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `{"foo": "bar", {"nested": "hash", "hello": "world"}}`) if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEq_HashesNotEquivalent(t *testing.T) { mockT := new(MockT) JSONEq(mockT, `{"foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEq_ActualIsNotJSON(t *testing.T) { mockT := new(MockT) JSONEq(mockT, `{"foo": "bar"}`, "Not JSON") if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEq_ExpectedIsNotJSON(t *testing.T) { mockT := new(MockT) JSONEq(mockT, "Not JSON", `{"foo": "bar", "hello": "world"}`) if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEq_ExpectedAndActualNotJSON(t *testing.T) { mockT := new(MockT) JSONEq(mockT, "Not JSON", "Not JSON") if !mockT.Failed { t.Error("Check should fail") } } func TestJSONEq_ArraysOfDifferentOrder(t *testing.T) { mockT := new(MockT) JSONEq(mockT, `["foo", {"hello": "world", "nested": "hash"}]`, `[{ "hello": "world", "nested": "hash"}, "foo"]`) if !mockT.Failed { t.Error("Check should fail") } } func ExampleComparisonAssertionFunc() { t := &testing.T{} // provided by test adder := func(x, y int) int { return x + y } type args struct { x int y int } tests := []struct { name string args args expect int assertion ComparisonAssertionFunc }{ {"2+2=4", args{2, 2}, 4, Equal}, {"2+2!=5", args{2, 2}, 5, NotEqual}, {"2+3==5", args{2, 3}, 5, Exactly}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, tt.expect, adder(tt.args.x, tt.args.y)) }) } } func TestComparisonAssertionFunc(t *testing.T) { type iface interface { Name() string } tests := []struct { name string expect interface{} got interface{} assertion ComparisonAssertionFunc }{ {"implements", (*iface)(nil), t, Implements}, {"isType", (*testing.T)(nil), t, IsType}, {"equal", t, t, Equal}, {"equalValues", t, t, EqualValues}, {"exactly", t, t, Exactly}, {"notEqual", t, nil, NotEqual}, {"NotEqualValues", t, nil, NotEqualValues}, {"notContains", []int{1, 2, 3}, 4, NotContains}, {"subset", []int{1, 2, 3, 4}, []int{2, 3}, Subset}, {"notSubset", []int{1, 2, 3, 4}, []int{0, 3}, NotSubset}, {"elementsMatch", []byte("abc"), []byte("bac"), ElementsMatch}, {"regexp", "^t.*y$", "testify", Regexp}, {"notRegexp", "^t.*y$", "Testify", NotRegexp}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, tt.expect, tt.got) }) } } func ExampleValueAssertionFunc() { t := &testing.T{} // provided by test dumbParse := func(input string) interface{} { var x interface{} json.Unmarshal([]byte(input), &x) return x } tests := []struct { name string arg string assertion ValueAssertionFunc }{ {"true is not nil", "true", NotNil}, {"empty string is nil", "", Nil}, {"zero is not nil", "0", NotNil}, {"zero is zero", "0", Zero}, {"false is zero", "false", Zero}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, dumbParse(tt.arg)) }) } } func TestValueAssertionFunc(t *testing.T) { tests := []struct { name string value interface{} assertion ValueAssertionFunc }{ {"notNil", true, NotNil}, {"nil", nil, Nil}, {"empty", []int{}, Empty}, {"notEmpty", []int{1}, NotEmpty}, {"zero", false, Zero}, {"notZero", 42, NotZero}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, tt.value) }) } } func ExampleBoolAssertionFunc() { t := &testing.T{} // provided by test isOkay := func(x int) bool { return x >= 42 } tests := []struct { name string arg int assertion BoolAssertionFunc }{ {"-1 is bad", -1, False}, {"42 is good", 42, True}, {"41 is bad", 41, False}, {"45 is cool", 45, True}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, isOkay(tt.arg)) }) } } func TestBoolAssertionFunc(t *testing.T) { tests := []struct { name string value bool assertion BoolAssertionFunc }{ {"true", true, True}, {"false", false, False}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, tt.value) }) } } func ExampleErrorAssertionFunc() { t := &testing.T{} // provided by test dumbParseNum := func(input string, v interface{}) error { return json.Unmarshal([]byte(input), v) } tests := []struct { name string arg string assertion ErrorAssertionFunc }{ {"1.2 is number", "1.2", NoError}, {"1.2.3 not number", "1.2.3", Error}, {"true is not number", "true", Error}, {"3 is number", "3", NoError}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { var x float64 tt.assertion(t, dumbParseNum(tt.arg, &x)) }) } } func TestErrorAssertionFunc(t *testing.T) { tests := []struct { name string err error assertion ErrorAssertionFunc }{ {"noError", nil, NoError}, {"error", errors.New("whoops"), Error}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { tt.assertion(t, tt.err) }) } } ================================================ FILE: optimizer/const_expr.go ================================================ package optimizer import ( "fmt" "reflect" "strings" . "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/file" ) var errorType = reflect.TypeOf((*error)(nil)).Elem() type constExpr struct { applied bool err error fns map[string]reflect.Value } func (c *constExpr) Visit(node *Node) { defer func() { if r := recover(); r != nil { msg := fmt.Sprintf("%v", r) // Make message more actual, it's a runtime error, but at compile step. msg = strings.Replace(msg, "runtime error:", "compile error:", 1) c.err = &file.Error{ Location: (*node).Location(), Message: msg, } } }() if call, ok := (*node).(*CallNode); ok { if name, ok := call.Callee.(*IdentifierNode); ok { fn, ok := c.fns[name.Value] if ok { in := make([]reflect.Value, len(call.Arguments)) for i := 0; i < len(call.Arguments); i++ { arg := call.Arguments[i] var param any switch a := arg.(type) { case *NilNode: param = nil case *IntegerNode: param = a.Value case *FloatNode: param = a.Value case *BoolNode: param = a.Value case *StringNode: param = a.Value case *ConstantNode: param = a.Value default: return // Const expr optimization not applicable. } if param == nil && reflect.TypeOf(param) == nil { // In case of nil value and nil type use this hack, // otherwise reflect.Call will panic on zero value. in[i] = reflect.ValueOf(¶m).Elem() } else { in[i] = reflect.ValueOf(param) } } out := fn.Call(in) value := out[0].Interface() if len(out) == 2 && out[1].Type() == errorType && !out[1].IsNil() { c.err = out[1].Interface().(error) return } constNode := &ConstantNode{Value: value} patchWithType(node, constNode) c.applied = true } } } } ================================================ FILE: optimizer/count_any.go ================================================ package optimizer import ( . "github.com/expr-lang/expr/ast" ) // countAny optimizes count comparisons to use any for early termination. // Patterns: // - count(arr, pred) > 0 → any(arr, pred) // - count(arr, pred) >= 1 → any(arr, pred) type countAny struct{} func (*countAny) Visit(node *Node) { binary, ok := (*node).(*BinaryNode) if !ok { return } count, ok := binary.Left.(*BuiltinNode) if !ok || count.Name != "count" || len(count.Arguments) != 2 { return } integer, ok := binary.Right.(*IntegerNode) if !ok { return } if (binary.Operator == ">" && integer.Value == 0) || (binary.Operator == ">=" && integer.Value == 1) { patchCopyType(node, &BuiltinNode{ Name: "any", Arguments: count.Arguments, }) } } ================================================ FILE: optimizer/count_any_test.go ================================================ package optimizer_test import ( "testing" "github.com/expr-lang/expr" . "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr/optimizer" "github.com/expr-lang/expr/parser" "github.com/expr-lang/expr/vm" ) func TestOptimize_count_any(t *testing.T) { tree, err := parser.Parse(`count(items, .active) > 0`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &BuiltinNode{ Name: "any", Arguments: []Node{ &IdentifierNode{Value: "items"}, &PredicateNode{ Node: &MemberNode{ Node: &PointerNode{}, Property: &StringNode{Value: "active"}, }, }, }, } assert.Equal(t, Dump(expected), Dump(tree.Node)) } func TestOptimize_count_any_gte_one(t *testing.T) { tree, err := parser.Parse(`count(items, .valid) >= 1`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &BuiltinNode{ Name: "any", Arguments: []Node{ &IdentifierNode{Value: "items"}, &PredicateNode{ Node: &MemberNode{ Node: &PointerNode{}, Property: &StringNode{Value: "valid"}, }, }, }, } assert.Equal(t, Dump(expected), Dump(tree.Node)) } func TestOptimize_count_any_correctness(t *testing.T) { tests := []struct { expr string want bool }{ // count > 0 → any {`count(1..100, # == 1) > 0`, true}, {`count(1..100, # == 50) > 0`, true}, {`count(1..100, # == 100) > 0`, true}, {`count(1..100, # == 0) > 0`, false}, // count >= 1 → any {`count(1..100, # % 10 == 0) >= 1`, true}, {`count(1..100, # > 100) >= 1`, false}, } for _, tt := range tests { t.Run(tt.expr, func(t *testing.T) { program, err := expr.Compile(tt.expr) require.NoError(t, err) output, err := expr.Run(program, nil) require.NoError(t, err) assert.Equal(t, tt.want, output) }) } } func TestOptimize_count_no_optimization(t *testing.T) { // These should NOT be optimized tests := []string{ `count(items, .active) > 1`, // not > 0 `count(items, .active) >= 2`, // not >= 1 `count(items, .active) == 0`, // not optimized (none has overhead) `count(items, .active) == 1`, // not == 0 `count(items, .active) < 1`, // not optimized (none has overhead) `count(items, .active) <= 0`, // not optimized (none has overhead) `count(items, .active) != 0`, // different operator } for _, code := range tests { t.Run(code, func(t *testing.T) { tree, err := parser.Parse(code) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) // Should still be a BinaryNode (not optimized to any) _, ok := tree.Node.(*BinaryNode) assert.True(t, ok, "expected BinaryNode, got %T", tree.Node) }) } } // Benchmarks for count > 0 → any func BenchmarkCountGtZero(b *testing.B) { program, _ := expr.Compile(`count(1..1000, # == 1) > 0`) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = vm.Run(program, nil) } _ = out } func BenchmarkCountGtZeroLargeEarlyMatch(b *testing.B) { program, _ := expr.Compile(`count(1..10000, # == 1) > 0`) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = vm.Run(program, nil) } _ = out } func BenchmarkCountGtZeroNoMatch(b *testing.B) { program, _ := expr.Compile(`count(1..1000, # == 0) > 0`) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = vm.Run(program, nil) } _ = out } // Benchmarks for count >= 1 → any func BenchmarkCountGteOneEarlyMatch(b *testing.B) { program, _ := expr.Compile(`count(1..1000, # == 1) >= 1`) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = vm.Run(program, nil) } _ = out } func BenchmarkCountGteOneNoMatch(b *testing.B) { program, _ := expr.Compile(`count(1..1000, # == 0) >= 1`) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = vm.Run(program, nil) } _ = out } ================================================ FILE: optimizer/count_threshold.go ================================================ package optimizer import ( . "github.com/expr-lang/expr/ast" ) // countThreshold optimizes count comparisons by setting a threshold for early termination. // The threshold allows the count loop to exit early once enough matches are found. // Patterns: // - count(arr, pred) > N → threshold = N + 1 (exit proves > N is true) // - count(arr, pred) >= N → threshold = N (exit proves >= N is true) // - count(arr, pred) < N → threshold = N (exit proves < N is false) // - count(arr, pred) <= N → threshold = N + 1 (exit proves <= N is false) type countThreshold struct{} func (*countThreshold) Visit(node *Node) { binary, ok := (*node).(*BinaryNode) if !ok { return } count, ok := binary.Left.(*BuiltinNode) if !ok || count.Name != "count" || len(count.Arguments) != 2 { return } integer, ok := binary.Right.(*IntegerNode) if !ok || integer.Value < 0 { return } var threshold int switch binary.Operator { case ">": threshold = integer.Value + 1 case ">=": threshold = integer.Value case "<": threshold = integer.Value case "<=": threshold = integer.Value + 1 default: return } // Skip if threshold is 0 or 1 (handled by count_any optimizer) if threshold <= 1 { return } // Set threshold on the count node for early termination // The original comparison remains unchanged count.Threshold = &threshold } ================================================ FILE: optimizer/count_threshold_test.go ================================================ package optimizer_test import ( "testing" "github.com/expr-lang/expr" . "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr/optimizer" "github.com/expr-lang/expr/parser" "github.com/expr-lang/expr/vm" ) func TestOptimize_count_threshold_gt(t *testing.T) { tree, err := parser.Parse(`count(items, .active) > 100`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) // Operator should remain >, but count should have threshold set binary, ok := tree.Node.(*BinaryNode) require.True(t, ok, "expected BinaryNode, got %T", tree.Node) assert.Equal(t, ">", binary.Operator) count, ok := binary.Left.(*BuiltinNode) require.True(t, ok, "expected BuiltinNode, got %T", binary.Left) assert.Equal(t, "count", count.Name) require.NotNil(t, count.Threshold) assert.Equal(t, 101, *count.Threshold) // threshold = N + 1 for > operator } func TestOptimize_count_threshold_gte(t *testing.T) { tree, err := parser.Parse(`count(items, .active) >= 50`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) // Operator should remain >=, but count should have threshold set binary, ok := tree.Node.(*BinaryNode) require.True(t, ok, "expected BinaryNode, got %T", tree.Node) assert.Equal(t, ">=", binary.Operator) count, ok := binary.Left.(*BuiltinNode) require.True(t, ok, "expected BuiltinNode, got %T", binary.Left) assert.Equal(t, "count", count.Name) require.NotNil(t, count.Threshold) assert.Equal(t, 50, *count.Threshold) // threshold = N for >= operator } func TestOptimize_count_threshold_lt(t *testing.T) { tree, err := parser.Parse(`count(items, .active) < 100`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) // Operator should remain <, but count should have threshold set binary, ok := tree.Node.(*BinaryNode) require.True(t, ok, "expected BinaryNode, got %T", tree.Node) assert.Equal(t, "<", binary.Operator) count, ok := binary.Left.(*BuiltinNode) require.True(t, ok, "expected BuiltinNode, got %T", binary.Left) assert.Equal(t, "count", count.Name) require.NotNil(t, count.Threshold) assert.Equal(t, 100, *count.Threshold) // threshold = N for < operator } func TestOptimize_count_threshold_lte(t *testing.T) { tree, err := parser.Parse(`count(items, .active) <= 50`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) // Operator should remain <=, but count should have threshold set binary, ok := tree.Node.(*BinaryNode) require.True(t, ok, "expected BinaryNode, got %T", tree.Node) assert.Equal(t, "<=", binary.Operator) count, ok := binary.Left.(*BuiltinNode) require.True(t, ok, "expected BuiltinNode, got %T", binary.Left) assert.Equal(t, "count", count.Name) require.NotNil(t, count.Threshold) assert.Equal(t, 51, *count.Threshold) // threshold = N + 1 for <= operator } func TestOptimize_count_threshold_correctness(t *testing.T) { tests := []struct { expr string want bool }{ // count > N (threshold = N + 1) {`count(1..1000, # <= 100) > 50`, true}, // 100 matches > 50 {`count(1..1000, # <= 100) > 100`, false}, // 100 matches not > 100 {`count(1..1000, # <= 100) > 99`, true}, // 100 matches > 99 {`count(1..100, # > 0) > 50`, true}, // 100 matches > 50 {`count(1..100, # > 0) > 100`, false}, // 100 matches not > 100 // count >= N (threshold = N) {`count(1..1000, # <= 100) >= 100`, true}, // 100 matches >= 100 {`count(1..1000, # <= 100) >= 101`, false}, // 100 matches not >= 101 {`count(1..100, # > 0) >= 50`, true}, // 100 matches >= 50 {`count(1..100, # > 0) >= 100`, true}, // 100 matches >= 100 // count < N (threshold = N) {`count(1..1000, # <= 100) < 101`, true}, // 100 matches < 101 {`count(1..1000, # <= 100) < 100`, false}, // 100 matches not < 100 {`count(1..1000, # <= 100) < 50`, false}, // 100 matches not < 50 {`count(1..100, # > 0) < 101`, true}, // 100 matches < 101 {`count(1..100, # > 0) < 100`, false}, // 100 matches not < 100 // count <= N (threshold = N + 1) {`count(1..1000, # <= 100) <= 100`, true}, // 100 matches <= 100 {`count(1..1000, # <= 100) <= 99`, false}, // 100 matches not <= 99 {`count(1..1000, # <= 100) <= 50`, false}, // 100 matches not <= 50 {`count(1..100, # > 0) <= 100`, true}, // 100 matches <= 100 {`count(1..100, # > 0) <= 99`, false}, // 100 matches not <= 99 } for _, tt := range tests { t.Run(tt.expr, func(t *testing.T) { program, err := expr.Compile(tt.expr) require.NoError(t, err) output, err := expr.Run(program, nil) require.NoError(t, err) assert.Equal(t, tt.want, output) }) } } func TestOptimize_count_threshold_no_optimization(t *testing.T) { // These should NOT get a threshold (handled by count_any or not optimizable) tests := []struct { code string threshold bool }{ {`count(items, .active) > 0`, false}, // handled by count_any {`count(items, .active) >= 1`, false}, // handled by count_any {`count(items, .active) < 1`, false}, // threshold = 1, skipped {`count(items, .active) <= 0`, false}, // threshold = 1, skipped {`count(items, .active) == 10`, false}, // not supported } for _, tt := range tests { t.Run(tt.code, func(t *testing.T) { tree, err := parser.Parse(tt.code) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) // Check if count has threshold set var count *BuiltinNode if binary, ok := tree.Node.(*BinaryNode); ok { count, _ = binary.Left.(*BuiltinNode) } else if builtin, ok := tree.Node.(*BuiltinNode); ok { count = builtin } if count != nil && count.Name == "count" { if tt.threshold { assert.NotNil(t, count.Threshold, "expected threshold to be set") } else { assert.Nil(t, count.Threshold, "expected threshold to be nil") } } }) } } // Benchmark: count > 100 with early match (element 101 matches early) func BenchmarkCountThresholdEarlyMatch(b *testing.B) { // Array of 10000 elements, all match predicate, threshold is 101 // Should exit after ~101 iterations program, _ := expr.Compile(`count(1..10000, # > 0) > 100`) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = vm.Run(program, nil) } _ = out } // Benchmark: count >= 50 with early match func BenchmarkCountThresholdGteEarlyMatch(b *testing.B) { // All elements match, threshold is 50 // Should exit after ~50 iterations program, _ := expr.Compile(`count(1..10000, # > 0) >= 50`) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = vm.Run(program, nil) } _ = out } // Benchmark: count > 100 with no early exit (not enough matches) func BenchmarkCountThresholdNoEarlyExit(b *testing.B) { // Only 100 elements match (# <= 100), threshold is 101 // Must scan entire array program, _ := expr.Compile(`count(1..10000, # <= 100) > 100`) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = vm.Run(program, nil) } _ = out } // Benchmark: Large threshold with early match func BenchmarkCountThresholdLargeEarlyMatch(b *testing.B) { // All 10000 match, threshold is 1000 // Should exit after ~1000 iterations program, _ := expr.Compile(`count(1..10000, # > 0) > 999`) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = vm.Run(program, nil) } _ = out } // Benchmark: count < N with early exit (result is false) func BenchmarkCountThresholdLtEarlyExit(b *testing.B) { // All 10000 match, threshold is 100 // Should exit after ~100 iterations with result = false program, _ := expr.Compile(`count(1..10000, # > 0) < 100`) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = vm.Run(program, nil) } _ = out } // Benchmark: count <= N with early exit (result is false) func BenchmarkCountThresholdLteEarlyExit(b *testing.B) { // All 10000 match, threshold is 51 // Should exit after ~51 iterations with result = false program, _ := expr.Compile(`count(1..10000, # > 0) <= 50`) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = vm.Run(program, nil) } _ = out } // Benchmark: count < N without early exit (result is true) func BenchmarkCountThresholdLtNoEarlyExit(b *testing.B) { // Only 100 elements match (# <= 100), threshold is 200 // Must scan entire array, result = true program, _ := expr.Compile(`count(1..10000, # <= 100) < 200`) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = vm.Run(program, nil) } _ = out } // Benchmark: count <= N without early exit (result is true) func BenchmarkCountThresholdLteNoEarlyExit(b *testing.B) { // Only 100 elements match (# <= 100), threshold is 101 // Must scan entire array, result = true program, _ := expr.Compile(`count(1..10000, # <= 100) <= 100`) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = vm.Run(program, nil) } _ = out } ================================================ FILE: optimizer/filter_first.go ================================================ package optimizer import ( . "github.com/expr-lang/expr/ast" ) type filterFirst struct{} func (*filterFirst) Visit(node *Node) { if member, ok := (*node).(*MemberNode); ok && member.Property != nil && !member.Optional { if prop, ok := member.Property.(*IntegerNode); ok && prop.Value == 0 { if filter, ok := member.Node.(*BuiltinNode); ok && filter.Name == "filter" && len(filter.Arguments) == 2 { patchCopyType(node, &BuiltinNode{ Name: "find", Arguments: filter.Arguments, Throws: true, // to match the behavior of filter()[0] Map: filter.Map, }) } } } if first, ok := (*node).(*BuiltinNode); ok && first.Name == "first" && len(first.Arguments) == 1 { if filter, ok := first.Arguments[0].(*BuiltinNode); ok && filter.Name == "filter" && len(filter.Arguments) == 2 { patchCopyType(node, &BuiltinNode{ Name: "find", Arguments: filter.Arguments, Throws: false, // as first() will return nil if not found Map: filter.Map, }) } } } ================================================ FILE: optimizer/filter_last.go ================================================ package optimizer import ( . "github.com/expr-lang/expr/ast" ) type filterLast struct{} func (*filterLast) Visit(node *Node) { if member, ok := (*node).(*MemberNode); ok && member.Property != nil && !member.Optional { if prop, ok := member.Property.(*IntegerNode); ok && prop.Value == -1 { if filter, ok := member.Node.(*BuiltinNode); ok && filter.Name == "filter" && len(filter.Arguments) == 2 { patchCopyType(node, &BuiltinNode{ Name: "findLast", Arguments: filter.Arguments, Throws: true, // to match the behavior of filter()[-1] Map: filter.Map, }) } } } if first, ok := (*node).(*BuiltinNode); ok && first.Name == "last" && len(first.Arguments) == 1 { if filter, ok := first.Arguments[0].(*BuiltinNode); ok && filter.Name == "filter" && len(filter.Arguments) == 2 { patchCopyType(node, &BuiltinNode{ Name: "findLast", Arguments: filter.Arguments, Throws: false, // as last() will return nil if not found Map: filter.Map, }) } } } ================================================ FILE: optimizer/filter_len.go ================================================ package optimizer import ( . "github.com/expr-lang/expr/ast" ) type filterLen struct{} func (*filterLen) Visit(node *Node) { if ln, ok := (*node).(*BuiltinNode); ok && ln.Name == "len" && len(ln.Arguments) == 1 { if filter, ok := ln.Arguments[0].(*BuiltinNode); ok && filter.Name == "filter" && len(filter.Arguments) == 2 { patchCopyType(node, &BuiltinNode{ Name: "count", Arguments: filter.Arguments, }) } } } ================================================ FILE: optimizer/filter_map.go ================================================ package optimizer import ( . "github.com/expr-lang/expr/ast" ) type filterMap struct{} func (*filterMap) Visit(node *Node) { if mapBuiltin, ok := (*node).(*BuiltinNode); ok && mapBuiltin.Name == "map" && len(mapBuiltin.Arguments) == 2 && Find(mapBuiltin.Arguments[1], isIndexPointer) == nil { if predicate, ok := mapBuiltin.Arguments[1].(*PredicateNode); ok { if filter, ok := mapBuiltin.Arguments[0].(*BuiltinNode); ok && filter.Name == "filter" && filter.Map == nil /* not already optimized */ { patchCopyType(node, &BuiltinNode{ Name: "filter", Arguments: filter.Arguments, Map: predicate.Node, }) } } } } func isIndexPointer(node Node) bool { if pointer, ok := node.(*PointerNode); ok && pointer.Name == "index" { return true } return false } ================================================ FILE: optimizer/filter_map_test.go ================================================ package optimizer_test import ( "testing" . "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr/optimizer" "github.com/expr-lang/expr/parser" ) func TestOptimize_filter_map(t *testing.T) { tree, err := parser.Parse(`map(filter(users, .Name == "Bob"), .Age)`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &BuiltinNode{ Name: "filter", Arguments: []Node{ &IdentifierNode{Value: "users"}, &PredicateNode{ Node: &BinaryNode{ Operator: "==", Left: &MemberNode{ Node: &PointerNode{}, Property: &StringNode{Value: "Name"}, }, Right: &StringNode{Value: "Bob"}, }, }, }, Map: &MemberNode{ Node: &PointerNode{}, Property: &StringNode{Value: "Age"}, }, } assert.Equal(t, Dump(expected), Dump(tree.Node)) } func TestOptimize_filter_map_with_index_pointer(t *testing.T) { tree, err := parser.Parse(`map(filter(users, true), #index)`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &BuiltinNode{ Name: "map", Arguments: []Node{ &BuiltinNode{ Name: "filter", Arguments: []Node{ &IdentifierNode{Value: "users"}, &PredicateNode{ Node: &BoolNode{Value: true}, }, }, Throws: false, Map: nil, }, &PredicateNode{ Node: &PointerNode{Name: "index"}, }, }, Throws: false, Map: nil, } assert.Equal(t, Dump(expected), Dump(tree.Node)) } func TestOptimize_filter_map_with_index_pointer_with_index_pointer_in_first_argument(t *testing.T) { tree, err := parser.Parse(`1..2 | map(map(filter([#index], true), 42))`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &BuiltinNode{ Name: "map", Arguments: []Node{ &BinaryNode{ Operator: "..", Left: &IntegerNode{Value: 1}, Right: &IntegerNode{Value: 2}, }, &PredicateNode{ Node: &BuiltinNode{ Name: "filter", Arguments: []Node{ &ArrayNode{ Nodes: []Node{ &PointerNode{Name: "index"}, }, }, &PredicateNode{ Node: &BoolNode{Value: true}, }, }, Throws: false, Map: &IntegerNode{Value: 42}, }, }, }, Throws: false, Map: nil, } assert.Equal(t, Dump(expected), Dump(tree.Node)) } ================================================ FILE: optimizer/fold.go ================================================ package optimizer import ( "math" . "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/file" ) type fold struct { applied bool err *file.Error } func (fold *fold) Visit(node *Node) { patch := func(newNode Node) { fold.applied = true patchWithType(node, newNode) } patchCopy := func(newNode Node) { fold.applied = true patchCopyType(node, newNode) } switch n := (*node).(type) { case *UnaryNode: switch n.Operator { case "-": if i, ok := n.Node.(*IntegerNode); ok { patch(&IntegerNode{Value: -i.Value}) } if i, ok := n.Node.(*FloatNode); ok { patch(&FloatNode{Value: -i.Value}) } case "+": if i, ok := n.Node.(*IntegerNode); ok { patch(&IntegerNode{Value: i.Value}) } if i, ok := n.Node.(*FloatNode); ok { patch(&FloatNode{Value: i.Value}) } case "!", "not": if a := toBool(n.Node); a != nil { patch(&BoolNode{Value: !a.Value}) } } case *BinaryNode: switch n.Operator { case "+": { a := toInteger(n.Left) b := toInteger(n.Right) if a != nil && b != nil { patch(&IntegerNode{Value: a.Value + b.Value}) } } { a := toInteger(n.Left) b := toFloat(n.Right) if a != nil && b != nil { patch(&FloatNode{Value: float64(a.Value) + b.Value}) } } { a := toFloat(n.Left) b := toInteger(n.Right) if a != nil && b != nil { patch(&FloatNode{Value: a.Value + float64(b.Value)}) } } { a := toFloat(n.Left) b := toFloat(n.Right) if a != nil && b != nil { patch(&FloatNode{Value: a.Value + b.Value}) } } { a := toString(n.Left) b := toString(n.Right) if a != nil && b != nil { patch(&StringNode{Value: a.Value + b.Value}) } } case "-": { a := toInteger(n.Left) b := toInteger(n.Right) if a != nil && b != nil { patch(&IntegerNode{Value: a.Value - b.Value}) } } { a := toInteger(n.Left) b := toFloat(n.Right) if a != nil && b != nil { patch(&FloatNode{Value: float64(a.Value) - b.Value}) } } { a := toFloat(n.Left) b := toInteger(n.Right) if a != nil && b != nil { patch(&FloatNode{Value: a.Value - float64(b.Value)}) } } { a := toFloat(n.Left) b := toFloat(n.Right) if a != nil && b != nil { patch(&FloatNode{Value: a.Value - b.Value}) } } case "*": { a := toInteger(n.Left) b := toInteger(n.Right) if a != nil && b != nil { patch(&IntegerNode{Value: a.Value * b.Value}) } } { a := toInteger(n.Left) b := toFloat(n.Right) if a != nil && b != nil { patch(&FloatNode{Value: float64(a.Value) * b.Value}) } } { a := toFloat(n.Left) b := toInteger(n.Right) if a != nil && b != nil { patch(&FloatNode{Value: a.Value * float64(b.Value)}) } } { a := toFloat(n.Left) b := toFloat(n.Right) if a != nil && b != nil { patch(&FloatNode{Value: a.Value * b.Value}) } } case "/": { a := toInteger(n.Left) b := toInteger(n.Right) if a != nil && b != nil { patch(&FloatNode{Value: float64(a.Value) / float64(b.Value)}) } } { a := toInteger(n.Left) b := toFloat(n.Right) if a != nil && b != nil { patch(&FloatNode{Value: float64(a.Value) / b.Value}) } } { a := toFloat(n.Left) b := toInteger(n.Right) if a != nil && b != nil { patch(&FloatNode{Value: a.Value / float64(b.Value)}) } } { a := toFloat(n.Left) b := toFloat(n.Right) if a != nil && b != nil { patch(&FloatNode{Value: a.Value / b.Value}) } } case "%": if a, ok := n.Left.(*IntegerNode); ok { if b, ok := n.Right.(*IntegerNode); ok { if b.Value == 0 { fold.err = &file.Error{ Location: (*node).Location(), Message: "integer divide by zero", } return } patch(&IntegerNode{Value: a.Value % b.Value}) } } case "**", "^": { a := toInteger(n.Left) b := toInteger(n.Right) if a != nil && b != nil { patch(&FloatNode{Value: math.Pow(float64(a.Value), float64(b.Value))}) } } { a := toInteger(n.Left) b := toFloat(n.Right) if a != nil && b != nil { patch(&FloatNode{Value: math.Pow(float64(a.Value), b.Value)}) } } { a := toFloat(n.Left) b := toInteger(n.Right) if a != nil && b != nil { patch(&FloatNode{Value: math.Pow(a.Value, float64(b.Value))}) } } { a := toFloat(n.Left) b := toFloat(n.Right) if a != nil && b != nil { patch(&FloatNode{Value: math.Pow(a.Value, b.Value)}) } } case "and", "&&": a := toBool(n.Left) b := toBool(n.Right) if a != nil && a.Value { // true and x patchCopy(n.Right) } else if b != nil && b.Value { // x and true patchCopy(n.Left) } else if (a != nil && !a.Value) || (b != nil && !b.Value) { // "x and false" or "false and x" patch(&BoolNode{Value: false}) } case "or", "||": a := toBool(n.Left) b := toBool(n.Right) if a != nil && !a.Value { // false or x patchCopy(n.Right) } else if b != nil && !b.Value { // x or false patchCopy(n.Left) } else if (a != nil && a.Value) || (b != nil && b.Value) { // "x or true" or "true or x" patch(&BoolNode{Value: true}) } case "==": { a := toInteger(n.Left) b := toInteger(n.Right) if a != nil && b != nil { patch(&BoolNode{Value: a.Value == b.Value}) } } { a := toString(n.Left) b := toString(n.Right) if a != nil && b != nil { patch(&BoolNode{Value: a.Value == b.Value}) } } { a := toBool(n.Left) b := toBool(n.Right) if a != nil && b != nil { patch(&BoolNode{Value: a.Value == b.Value}) } } } case *ArrayNode: if len(n.Nodes) > 0 { for _, a := range n.Nodes { switch a.(type) { case *IntegerNode, *FloatNode, *StringNode, *BoolNode: continue default: return } } value := make([]any, len(n.Nodes)) for i, a := range n.Nodes { switch b := a.(type) { case *IntegerNode: value[i] = b.Value case *FloatNode: value[i] = b.Value case *StringNode: value[i] = b.Value case *BoolNode: value[i] = b.Value } } patch(&ConstantNode{Value: value}) } case *BuiltinNode: // TODO: Move this to a separate visitor filter_filter.go switch n.Name { case "filter": if len(n.Arguments) != 2 { return } if base, ok := n.Arguments[0].(*BuiltinNode); ok && base.Name == "filter" { patchCopy(&BuiltinNode{ Name: "filter", Arguments: []Node{ base.Arguments[0], &PredicateNode{ Node: &BinaryNode{ Operator: "&&", Left: base.Arguments[1].(*PredicateNode).Node, Right: n.Arguments[1].(*PredicateNode).Node, }, }, }, }) } } } } func toString(n Node) *StringNode { switch a := n.(type) { case *StringNode: return a } return nil } func toInteger(n Node) *IntegerNode { switch a := n.(type) { case *IntegerNode: return a } return nil } func toFloat(n Node) *FloatNode { switch a := n.(type) { case *FloatNode: return a } return nil } func toBool(n Node) *BoolNode { switch a := n.(type) { case *BoolNode: return a } return nil } ================================================ FILE: optimizer/fold_test.go ================================================ package optimizer_test import ( "reflect" "testing" "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr/optimizer" "github.com/expr-lang/expr/parser" ) func TestOptimize_constant_folding(t *testing.T) { tree, err := parser.Parse(`[1,2,3][5*5-25]`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &ast.MemberNode{ Node: &ast.ConstantNode{Value: []any{1, 2, 3}}, Property: &ast.IntegerNode{Value: 0}, } assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node)) } func TestOptimize_constant_folding_with_floats(t *testing.T) { tree, err := parser.Parse(`1 + 2.0 * ((1.0 * 2) / 2) - 0`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &ast.FloatNode{Value: 3.0} assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node)) assert.Equal(t, reflect.Float64, tree.Node.Type().Kind()) } func TestOptimize_constant_folding_with_bools(t *testing.T) { tree, err := parser.Parse(`(true and false) or (true or false) or (false and false) or (true and (true == false))`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &ast.BoolNode{Value: true} assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node)) } func TestOptimize_constant_folding_filter_filter(t *testing.T) { tree, err := parser.Parse(`filter(filter(1..2, true), true)`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &ast.BuiltinNode{ Name: "filter", Arguments: []ast.Node{ &ast.BinaryNode{ Operator: "..", Left: &ast.IntegerNode{ Value: 1, }, Right: &ast.IntegerNode{ Value: 2, }, }, &ast.PredicateNode{ Node: &ast.BoolNode{ Value: true, }, }, }, Throws: false, Map: nil, } assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node)) } ================================================ FILE: optimizer/in_array.go ================================================ package optimizer import ( "reflect" . "github.com/expr-lang/expr/ast" ) type inArray struct{} func (*inArray) Visit(node *Node) { switch n := (*node).(type) { case *BinaryNode: if n.Operator == "in" { if array, ok := n.Right.(*ArrayNode); ok { if len(array.Nodes) > 0 { t := n.Left.Type() if t == nil || t.Kind() != reflect.Int { // This optimization can be only performed if left side is int type, // as runtime.in func uses reflect.Map.MapIndex and keys of map must, // be same as checked value type. goto string } for _, a := range array.Nodes { if _, ok := a.(*IntegerNode); !ok { goto string } } { value := make(map[int]struct{}) for _, a := range array.Nodes { value[a.(*IntegerNode).Value] = struct{}{} } m := &ConstantNode{Value: value} m.SetType(reflect.TypeOf(value)) patchCopyType(node, &BinaryNode{ Operator: n.Operator, Left: n.Left, Right: m, }) } string: for _, a := range array.Nodes { if _, ok := a.(*StringNode); !ok { return } } { value := make(map[string]struct{}) for _, a := range array.Nodes { value[a.(*StringNode).Value] = struct{}{} } m := &ConstantNode{Value: value} m.SetType(reflect.TypeOf(value)) patchCopyType(node, &BinaryNode{ Operator: n.Operator, Left: n.Left, Right: m, }) } } } } } } ================================================ FILE: optimizer/in_range.go ================================================ package optimizer import ( "reflect" . "github.com/expr-lang/expr/ast" ) type inRange struct{} func (*inRange) Visit(node *Node) { switch n := (*node).(type) { case *BinaryNode: if n.Operator == "in" { t := n.Left.Type() if t == nil { return } if t.Kind() != reflect.Int { return } if rangeOp, ok := n.Right.(*BinaryNode); ok && rangeOp.Operator == ".." { if from, ok := rangeOp.Left.(*IntegerNode); ok { if to, ok := rangeOp.Right.(*IntegerNode); ok { patchCopyType(node, &BinaryNode{ Operator: "and", Left: &BinaryNode{ Operator: ">=", Left: n.Left, Right: from, }, Right: &BinaryNode{ Operator: "<=", Left: n.Left, Right: to, }, }) } } } } } } ================================================ FILE: optimizer/optimizer.go ================================================ package optimizer import ( "fmt" "reflect" . "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/conf" ) func Optimize(node *Node, config *conf.Config) error { Walk(node, &inArray{}) for limit := 1000; limit >= 0; limit-- { fold := &fold{} Walk(node, fold) if fold.err != nil { return fold.err } if !fold.applied { break } } if config != nil && len(config.ConstFns) > 0 { for limit := 100; limit >= 0; limit-- { constExpr := &constExpr{ fns: config.ConstFns, } Walk(node, constExpr) if constExpr.err != nil { return constExpr.err } if !constExpr.applied { break } } } Walk(node, &inRange{}) Walk(node, &filterMap{}) Walk(node, &filterLen{}) Walk(node, &filterLast{}) Walk(node, &filterFirst{}) Walk(node, &predicateCombination{}) Walk(node, &sumRange{}) Walk(node, &sumArray{}) Walk(node, &sumMap{}) Walk(node, &countAny{}) Walk(node, &countThreshold{}) return nil } var ( boolType = reflect.TypeOf(true) integerType = reflect.TypeOf(0) floatType = reflect.TypeOf(float64(0)) stringType = reflect.TypeOf("") ) func patchWithType(node *Node, newNode Node) { switch n := newNode.(type) { case *BoolNode: newNode.SetType(boolType) case *IntegerNode: newNode.SetType(integerType) case *FloatNode: newNode.SetType(floatType) case *StringNode: newNode.SetType(stringType) case *ConstantNode: newNode.SetType(reflect.TypeOf(n.Value)) case *BinaryNode: newNode.SetType(n.Type()) default: panic(fmt.Sprintf("unknown type %T", newNode)) } Patch(node, newNode) } func patchCopyType(node *Node, newNode Node) { t := (*node).Type() newNode.SetType(t) Patch(node, newNode) } ================================================ FILE: optimizer/optimizer_test.go ================================================ package optimizer_test import ( "fmt" "strings" "testing" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr" "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/checker" "github.com/expr-lang/expr/conf" "github.com/expr-lang/expr/optimizer" "github.com/expr-lang/expr/parser" ) func TestOptimize(t *testing.T) { env := map[string]any{ "a": 1, "b": 2, "c": 3, } tests := []struct { expr string want any }{ {`1 + 2`, 3}, {`sum([])`, 0}, {`sum([a])`, 1}, {`sum([a, b])`, 3}, {`sum([a, b, c])`, 6}, {`sum([a, b, c, 4])`, 10}, {`sum(1..10, # * 1000)`, 55000}, {`sum(map(1..10, # * 1000), # / 1000)`, float64(55)}, {`all(1..3, {# > 0}) && all(1..3, {# < 4})`, true}, {`all(1..3, {# > 2}) && all(1..3, {# < 4})`, false}, {`all(1..3, {# > 0}) && all(1..3, {# < 2})`, false}, {`all(1..3, {# > 2}) && all(1..3, {# < 2})`, false}, {`all(1..3, {# > 0}) || all(1..3, {# < 4})`, true}, {`all(1..3, {# > 0}) || all(1..3, {# != 2})`, true}, {`all(1..3, {# != 3}) || all(1..3, {# < 4})`, true}, {`all(1..3, {# != 3}) || all(1..3, {# != 2})`, false}, {`none(1..3, {# == 0})`, true}, {`none(1..3, {# == 0}) && none(1..3, {# == 4})`, true}, {`none(1..3, {# == 0}) && none(1..3, {# == 3})`, false}, {`none(1..3, {# == 1}) && none(1..3, {# == 4})`, false}, {`none(1..3, {# == 1}) && none(1..3, {# == 3})`, false}, {`none(1..3, {# == 0}) || none(1..3, {# == 4})`, true}, {`none(1..3, {# == 0}) || none(1..3, {# == 3})`, true}, {`none(1..3, {# == 1}) || none(1..3, {# == 4})`, true}, {`none(1..3, {# == 1}) || none(1..3, {# == 3})`, false}, {`any([1, 1, 0, 1], {# == 0})`, true}, {`any(1..3, {# == 1}) && any(1..3, {# == 2})`, true}, {`any(1..3, {# == 0}) && any(1..3, {# == 2})`, false}, {`any(1..3, {# == 1}) && any(1..3, {# == 4})`, false}, {`any(1..3, {# == 0}) && any(1..3, {# == 4})`, false}, {`any(1..3, {# == 1}) || any(1..3, {# == 2})`, true}, {`any(1..3, {# == 0}) || any(1..3, {# == 2})`, true}, {`any(1..3, {# == 1}) || any(1..3, {# == 4})`, true}, {`any(1..3, {# == 0}) || any(1..3, {# == 4})`, false}, {`one([1, 1, 0, 1], {# == 0}) and not one([1, 0, 0, 1], {# == 0})`, true}, {`one(1..3, {# == 1}) and one(1..3, {# == 2})`, true}, {`one(1..3, {# == 1 || # == 2}) and one(1..3, {# == 2})`, false}, {`one(1..3, {# == 1}) and one(1..3, {# == 2 || # == 3})`, false}, {`one(1..3, {# == 1 || # == 2}) and one(1..3, {# == 2 || # == 3})`, false}, {`one(1..3, {# == 1}) or one(1..3, {# == 2})`, true}, {`one(1..3, {# == 1 || # == 2}) or one(1..3, {# == 2})`, true}, {`one(1..3, {# == 1}) or one(1..3, {# == 2 || # == 3})`, true}, {`one(1..3, {# == 1 || # == 2}) or one(1..3, {# == 2 || # == 3})`, false}, } for _, tt := range tests { t.Run(tt.expr, func(t *testing.T) { program, err := expr.Compile(tt.expr, expr.Env(env)) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) assert.Equal(t, tt.want, output) unoptimizedProgram, err := expr.Compile(tt.expr, expr.Env(env), expr.Optimize(false)) require.NoError(t, err) unoptimizedOutput, err := expr.Run(unoptimizedProgram, env) require.NoError(t, err) assert.Equal(t, tt.want, unoptimizedOutput) }) } } func TestOptimize_in_array(t *testing.T) { config := conf.New(map[string]int{"v": 0}) tree, err := parser.Parse(`v in [1,2,3]`) require.NoError(t, err) _, err = checker.Check(tree, config) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &ast.BinaryNode{ Operator: "in", Left: &ast.IdentifierNode{Value: "v"}, Right: &ast.ConstantNode{Value: map[int]struct{}{1: {}, 2: {}, 3: {}}}, } assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node)) } func TestOptimize_in_range(t *testing.T) { tree, err := parser.Parse(`age in 18..31`) require.NoError(t, err) config := conf.New(map[string]int{"age": 30}) _, err = checker.Check(tree, config) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) left := &ast.IdentifierNode{ Value: "age", } expected := &ast.BinaryNode{ Operator: "and", Left: &ast.BinaryNode{ Operator: ">=", Left: left, Right: &ast.IntegerNode{ Value: 18, }, }, Right: &ast.BinaryNode{ Operator: "<=", Left: left, Right: &ast.IntegerNode{ Value: 31, }, }, } assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node)) } func TestOptimize_in_range_with_floats(t *testing.T) { out, err := expr.Eval(`f in 1..3`, map[string]any{"f": 1.5}) require.NoError(t, err) assert.Equal(t, false, out) } func TestOptimize_const_expr(t *testing.T) { tree, err := parser.Parse(`toUpper("hello")`) require.NoError(t, err) env := map[string]any{ "toUpper": strings.ToUpper, } config := conf.New(env) config.ConstExpr("toUpper") err = optimizer.Optimize(&tree.Node, config) require.NoError(t, err) expected := &ast.ConstantNode{ Value: "HELLO", } assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node)) } func TestOptimize_filter_len(t *testing.T) { tree, err := parser.Parse(`len(filter(users, .Name == "Bob"))`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &ast.BuiltinNode{ Name: "count", Arguments: []ast.Node{ &ast.IdentifierNode{Value: "users"}, &ast.PredicateNode{ Node: &ast.BinaryNode{ Operator: "==", Left: &ast.MemberNode{ Node: &ast.PointerNode{}, Property: &ast.StringNode{Value: "Name"}, }, Right: &ast.StringNode{Value: "Bob"}, }, }, }, } assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node)) } func TestOptimize_filter_0(t *testing.T) { tree, err := parser.Parse(`filter(users, .Name == "Bob")[0]`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &ast.BuiltinNode{ Name: "find", Arguments: []ast.Node{ &ast.IdentifierNode{Value: "users"}, &ast.PredicateNode{ Node: &ast.BinaryNode{ Operator: "==", Left: &ast.MemberNode{ Node: &ast.PointerNode{}, Property: &ast.StringNode{Value: "Name"}, }, Right: &ast.StringNode{Value: "Bob"}, }, }, }, Throws: true, } assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node)) } func TestOptimize_filter_first(t *testing.T) { tree, err := parser.Parse(`first(filter(users, .Name == "Bob"))`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &ast.BuiltinNode{ Name: "find", Arguments: []ast.Node{ &ast.IdentifierNode{Value: "users"}, &ast.PredicateNode{ Node: &ast.BinaryNode{ Operator: "==", Left: &ast.MemberNode{ Node: &ast.PointerNode{}, Property: &ast.StringNode{Value: "Name"}, }, Right: &ast.StringNode{Value: "Bob"}, }, }, }, Throws: false, } assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node)) } func TestOptimize_filter_minus_1(t *testing.T) { tree, err := parser.Parse(`filter(users, .Name == "Bob")[-1]`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &ast.BuiltinNode{ Name: "findLast", Arguments: []ast.Node{ &ast.IdentifierNode{Value: "users"}, &ast.PredicateNode{ Node: &ast.BinaryNode{ Operator: "==", Left: &ast.MemberNode{ Node: &ast.PointerNode{}, Property: &ast.StringNode{Value: "Name"}, }, Right: &ast.StringNode{Value: "Bob"}, }, }, }, Throws: true, } assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node)) } func TestOptimize_filter_last(t *testing.T) { tree, err := parser.Parse(`last(filter(users, .Name == "Bob"))`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &ast.BuiltinNode{ Name: "findLast", Arguments: []ast.Node{ &ast.IdentifierNode{Value: "users"}, &ast.PredicateNode{ Node: &ast.BinaryNode{ Operator: "==", Left: &ast.MemberNode{ Node: &ast.PointerNode{}, Property: &ast.StringNode{Value: "Name"}, }, Right: &ast.StringNode{Value: "Bob"}, }, }, }, Throws: false, } assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node)) } func TestOptimize_filter_map_first(t *testing.T) { tree, err := parser.Parse(`first(map(filter(users, .Name == "Bob"), .Age))`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &ast.BuiltinNode{ Name: "find", Arguments: []ast.Node{ &ast.IdentifierNode{Value: "users"}, &ast.PredicateNode{ Node: &ast.BinaryNode{ Operator: "==", Left: &ast.MemberNode{ Node: &ast.PointerNode{}, Property: &ast.StringNode{Value: "Name"}, }, Right: &ast.StringNode{Value: "Bob"}, }, }, }, Map: &ast.MemberNode{ Node: &ast.PointerNode{}, Property: &ast.StringNode{Value: "Age"}, }, Throws: false, } assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node)) } func TestOptimize_predicate_combination(t *testing.T) { tests := []struct { op string fn string wantOp string }{ {"and", "all", "and"}, {"&&", "all", "&&"}, {"or", "any", "or"}, {"||", "any", "||"}, {"and", "none", "or"}, {"&&", "none", "||"}, } for _, tt := range tests { rule := fmt.Sprintf(`%s(users, .Age > 18 and .Name != "Bob") %s %s(users, .Age < 30)`, tt.fn, tt.op, tt.fn) t.Run(rule, func(t *testing.T) { tree, err := parser.Parse(rule) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &ast.BuiltinNode{ Name: tt.fn, Arguments: []ast.Node{ &ast.IdentifierNode{Value: "users"}, &ast.PredicateNode{ Node: &ast.BinaryNode{ Operator: tt.wantOp, Left: &ast.BinaryNode{ Operator: "and", Left: &ast.BinaryNode{ Operator: ">", Left: &ast.MemberNode{ Node: &ast.PointerNode{}, Property: &ast.StringNode{Value: "Age"}, }, Right: &ast.IntegerNode{Value: 18}, }, Right: &ast.BinaryNode{ Operator: "!=", Left: &ast.MemberNode{ Node: &ast.PointerNode{}, Property: &ast.StringNode{Value: "Name"}, }, Right: &ast.StringNode{Value: "Bob"}, }, }, Right: &ast.BinaryNode{ Operator: "<", Left: &ast.MemberNode{ Node: &ast.PointerNode{}, Property: &ast.StringNode{Value: "Age"}, }, Right: &ast.IntegerNode{Value: 30}, }, }, }, }, } assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node)) }) } } func TestOptimize_predicate_combination_nested(t *testing.T) { tree, err := parser.Parse(`all(users, {all(.Friends, {.Age == 18 })}) && all(users, {all(.Friends, {.Name != "Bob" })})`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &ast.BuiltinNode{ Name: "all", Arguments: []ast.Node{ &ast.IdentifierNode{Value: "users"}, &ast.PredicateNode{ Node: &ast.BuiltinNode{ Name: "all", Arguments: []ast.Node{ &ast.MemberNode{ Node: &ast.PointerNode{}, Property: &ast.StringNode{Value: "Friends"}, }, &ast.PredicateNode{ Node: &ast.BinaryNode{ Operator: "&&", Left: &ast.BinaryNode{ Operator: "==", Left: &ast.MemberNode{ Node: &ast.PointerNode{}, Property: &ast.StringNode{Value: "Age"}, }, Right: &ast.IntegerNode{Value: 18}, }, Right: &ast.BinaryNode{ Operator: "!=", Left: &ast.MemberNode{ Node: &ast.PointerNode{}, Property: &ast.StringNode{Value: "Name"}, }, Right: &ast.StringNode{Value: "Bob"}, }, }, }, }, }, }, }, } assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node)) } ================================================ FILE: optimizer/predicate_combination.go ================================================ package optimizer import ( . "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/parser/operator" ) /* predicateCombination is a visitor that combines multiple predicate calls into a single call. For example, the following expression: all(x, x > 1) && all(x, x < 10) -> all(x, x > 1 && x < 10) any(x, x > 1) || any(x, x < 10) -> any(x, x > 1 || x < 10) none(x, x > 1) && none(x, x < 10) -> none(x, x > 1 || x < 10) */ type predicateCombination struct{} func (v *predicateCombination) Visit(node *Node) { if op, ok := (*node).(*BinaryNode); ok && operator.IsBoolean(op.Operator) { if left, ok := op.Left.(*BuiltinNode); ok { if combinedOp, ok := combinedOperator(left.Name, op.Operator); ok { if right, ok := op.Right.(*BuiltinNode); ok && right.Name == left.Name { if left.Arguments[0].Type() == right.Arguments[0].Type() && left.Arguments[0].String() == right.Arguments[0].String() { predicate := &PredicateNode{ Node: &BinaryNode{ Operator: combinedOp, Left: left.Arguments[1].(*PredicateNode).Node, Right: right.Arguments[1].(*PredicateNode).Node, }, } v.Visit(&predicate.Node) patchCopyType(node, &BuiltinNode{ Name: left.Name, Arguments: []Node{ left.Arguments[0], predicate, }, }) } } } } } } func combinedOperator(fn, op string) (string, bool) { switch { case fn == "all" && (op == "and" || op == "&&"): return op, true case fn == "any" && (op == "or" || op == "||"): return op, true case fn == "none" && (op == "and" || op == "&&"): switch op { case "and": return "or", true case "&&": return "||", true } } return "", false } ================================================ FILE: optimizer/sum_array.go ================================================ package optimizer import ( "fmt" . "github.com/expr-lang/expr/ast" ) type sumArray struct{} func (*sumArray) Visit(node *Node) { if sumBuiltin, ok := (*node).(*BuiltinNode); ok && sumBuiltin.Name == "sum" && len(sumBuiltin.Arguments) == 1 { if array, ok := sumBuiltin.Arguments[0].(*ArrayNode); ok && len(array.Nodes) >= 2 { patchCopyType(node, sumArrayFold(array)) } } } func sumArrayFold(array *ArrayNode) *BinaryNode { if len(array.Nodes) > 2 { return &BinaryNode{ Operator: "+", Left: array.Nodes[0], Right: sumArrayFold(&ArrayNode{Nodes: array.Nodes[1:]}), } } else if len(array.Nodes) == 2 { return &BinaryNode{ Operator: "+", Left: array.Nodes[0], Right: array.Nodes[1], } } panic(fmt.Errorf("sumArrayFold: invalid array length %d", len(array.Nodes))) } ================================================ FILE: optimizer/sum_array_test.go ================================================ package optimizer_test import ( "testing" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr" "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/optimizer" "github.com/expr-lang/expr/parser" "github.com/expr-lang/expr/vm" ) func BenchmarkSumArray(b *testing.B) { env := map[string]any{ "a": 1, "b": 2, "c": 3, "d": 4, } program, err := expr.Compile(`sum([a, b, c, d])`, expr.Env(env)) require.NoError(b, err) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, err = vm.Run(program, env) } b.StopTimer() require.NoError(b, err) require.Equal(b, 10, out) } func TestOptimize_sum_array(t *testing.T) { tree, err := parser.Parse(`sum([a, b])`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &ast.BinaryNode{ Operator: "+", Left: &ast.IdentifierNode{Value: "a"}, Right: &ast.IdentifierNode{Value: "b"}, } assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node)) } func TestOptimize_sum_array_3(t *testing.T) { tree, err := parser.Parse(`sum([a, b, c])`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &ast.BinaryNode{ Operator: "+", Left: &ast.IdentifierNode{Value: "a"}, Right: &ast.BinaryNode{ Operator: "+", Left: &ast.IdentifierNode{Value: "b"}, Right: &ast.IdentifierNode{Value: "c"}, }, } assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node)) } ================================================ FILE: optimizer/sum_map.go ================================================ package optimizer import ( . "github.com/expr-lang/expr/ast" ) type sumMap struct{} func (*sumMap) Visit(node *Node) { if sumBuiltin, ok := (*node).(*BuiltinNode); ok && sumBuiltin.Name == "sum" && len(sumBuiltin.Arguments) == 1 { if mapBuiltin, ok := sumBuiltin.Arguments[0].(*BuiltinNode); ok && mapBuiltin.Name == "map" && len(mapBuiltin.Arguments) == 2 { patchCopyType(node, &BuiltinNode{ Name: "sum", Arguments: []Node{ mapBuiltin.Arguments[0], mapBuiltin.Arguments[1], }, }) } } } ================================================ FILE: optimizer/sum_map_test.go ================================================ package optimizer_test import ( "testing" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/optimizer" "github.com/expr-lang/expr/parser" ) func TestOptimize_sum_map(t *testing.T) { tree, err := parser.Parse(`sum(map(users, {.Age}))`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &ast.BuiltinNode{ Name: "sum", Arguments: []ast.Node{ &ast.IdentifierNode{Value: "users"}, &ast.PredicateNode{ Node: &ast.MemberNode{ Node: &ast.PointerNode{}, Property: &ast.StringNode{Value: "Age"}, }, }, }, } assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node)) } ================================================ FILE: optimizer/sum_range.go ================================================ package optimizer import ( . "github.com/expr-lang/expr/ast" ) type sumRange struct{} func (*sumRange) Visit(node *Node) { // Pattern 1: sum(m..n) or sum(m..n, predicate) where m and n are constant integers if sumBuiltin, ok := (*node).(*BuiltinNode); ok && sumBuiltin.Name == "sum" && (len(sumBuiltin.Arguments) == 1 || len(sumBuiltin.Arguments) == 2) { if rangeOp, ok := sumBuiltin.Arguments[0].(*BinaryNode); ok && rangeOp.Operator == ".." { if from, ok := rangeOp.Left.(*IntegerNode); ok { if to, ok := rangeOp.Right.(*IntegerNode); ok { m := from.Value n := to.Value if n >= m { count := n - m + 1 // Use the arithmetic series formula: (n - m + 1) * (m + n) / 2 sum := count * (m + n) / 2 if len(sumBuiltin.Arguments) == 1 { // sum(m..n) patchWithType(node, &IntegerNode{Value: sum}) } else if len(sumBuiltin.Arguments) == 2 { // sum(m..n, predicate) if result, ok := applySumPredicate(sum, count, sumBuiltin.Arguments[1]); ok { patchWithType(node, &IntegerNode{Value: result}) } } } } } } } // Pattern 2: reduce(m..n, # + #acc) where m and n are constant integers if reduceBuiltin, ok := (*node).(*BuiltinNode); ok && reduceBuiltin.Name == "reduce" && (len(reduceBuiltin.Arguments) == 2 || len(reduceBuiltin.Arguments) == 3) { if rangeOp, ok := reduceBuiltin.Arguments[0].(*BinaryNode); ok && rangeOp.Operator == ".." { if from, ok := rangeOp.Left.(*IntegerNode); ok { if to, ok := rangeOp.Right.(*IntegerNode); ok { if isPointerPlusAcc(reduceBuiltin.Arguments[1]) { m := from.Value n := to.Value if n >= m { // Use the arithmetic series formula: (n - m + 1) * (m + n) / 2 sum := (n - m + 1) * (m + n) / 2 // Check for optional initialValue (3rd argument) if len(reduceBuiltin.Arguments) == 3 { if initialValue, ok := reduceBuiltin.Arguments[2].(*IntegerNode); ok { result := initialValue.Value + sum patchWithType(node, &IntegerNode{Value: result}) } } else { patchWithType(node, &IntegerNode{Value: sum}) } } } } } } } } // isPointerPlusAcc checks if the node represents `# + #acc` pattern func isPointerPlusAcc(node Node) bool { predicate, ok := node.(*PredicateNode) if !ok { return false } binary, ok := predicate.Node.(*BinaryNode) if !ok { return false } if binary.Operator != "+" { return false } // Check for # + #acc (pointer + accumulator) leftPointer, leftIsPointer := binary.Left.(*PointerNode) rightPointer, rightIsPointer := binary.Right.(*PointerNode) if leftIsPointer && rightIsPointer { // # + #acc: Left is pointer (Name=""), Right is acc (Name="acc") if leftPointer.Name == "" && rightPointer.Name == "acc" { return true } // #acc + #: Left is acc (Name="acc"), Right is pointer (Name="") if leftPointer.Name == "acc" && rightPointer.Name == "" { return true } } return false } // applySumPredicate tries to compute the result of sum(m..n, predicate) at compile time. // Returns (result, true) if optimization is possible, (0, false) otherwise. // Supported predicates: // - # (identity): result = sum // - # * k (multiply by constant): result = k * sum // - k * # (multiply by constant): result = k * sum // - # + k (add constant): result = sum + count * k // - k + # (add constant): result = sum + count * k // - # - k (subtract constant): result = sum - count * k func applySumPredicate(sum, count int, predicateArg Node) (int, bool) { predicate, ok := predicateArg.(*PredicateNode) if !ok { return 0, false } // Case 1: # (identity) - just return the sum if pointer, ok := predicate.Node.(*PointerNode); ok && pointer.Name == "" { return sum, true } // Case 2: Binary operations with pointer and constant binary, ok := predicate.Node.(*BinaryNode) if !ok { return 0, false } pointer, constant, pointerOnLeft := extractPointerAndConstantWithPosition(binary) if pointer == nil || constant == nil { return 0, false } switch binary.Operator { case "*": // # * k or k * # => k * sum return constant.Value * sum, true case "+": // # + k or k + # => sum + count * k return sum + count*constant.Value, true case "-": if pointerOnLeft { // # - k => sum - count * k return sum - count*constant.Value, true } // k - # => count * k - sum return count*constant.Value - sum, true } return 0, false } // extractPointerAndConstantWithPosition extracts pointer (#) and integer constant from a binary node. // Returns (pointer, constant, pointerOnLeft) or (nil, nil, false) if not matching the expected pattern. func extractPointerAndConstantWithPosition(binary *BinaryNode) (*PointerNode, *IntegerNode, bool) { // Try left=pointer, right=constant if pointer, ok := binary.Left.(*PointerNode); ok && pointer.Name == "" { if constant, ok := binary.Right.(*IntegerNode); ok { return pointer, constant, true } } // Try left=constant, right=pointer if constant, ok := binary.Left.(*IntegerNode); ok { if pointer, ok := binary.Right.(*PointerNode); ok && pointer.Name == "" { return pointer, constant, false } } return nil, nil, false } ================================================ FILE: optimizer/sum_range_test.go ================================================ package optimizer_test import ( "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr/optimizer" "github.com/expr-lang/expr/parser" ) func TestOptimize_sum_range(t *testing.T) { tree, err := parser.Parse(`sum(1..100)`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &ast.IntegerNode{Value: 5050} assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node)) } func TestOptimize_sum_range_different_values(t *testing.T) { tests := []struct { expr string want int }{ {`sum(1..10)`, 55}, {`sum(1..100)`, 5050}, {`sum(5..10)`, 45}, {`sum(0..100)`, 5050}, {`sum(1..1)`, 1}, {`sum(0..0)`, 0}, {`sum(10..20)`, 165}, } for _, tt := range tests { t.Run(tt.expr, func(t *testing.T) { program, err := expr.Compile(tt.expr) require.NoError(t, err) output, err := expr.Run(program, nil) require.NoError(t, err) assert.Equal(t, tt.want, output) }) } } func TestOptimize_sum_range_with_predicate(t *testing.T) { tests := []struct { expr string want int }{ // # (identity) - same as sum(m..n) {`sum(1..10, #)`, 55}, {`sum(1..100, #)`, 5050}, // # * k (multiply by constant) {`sum(1..10, # * 2)`, 110}, // 2 * 55 {`sum(1..100, # * 2)`, 10100}, // 2 * 5050 {`sum(1..10, # * 0)`, 0}, {`sum(1..10, # * 1)`, 55}, // k * # (multiply by constant, reversed) {`sum(1..10, 2 * #)`, 110}, {`sum(1..100, 3 * #)`, 15150}, // 3 * 5050 // # + k (add constant to each element) {`sum(1..10, # + 1)`, 65}, // 55 + 10*1 {`sum(1..100, # + 1)`, 5150}, // 5050 + 100*1 {`sum(1..10, # + 0)`, 55}, {`sum(1..10, # + 10)`, 155}, // 55 + 10*10 // k + # (add constant, reversed) {`sum(1..10, 1 + #)`, 65}, {`sum(1..100, 5 + #)`, 5550}, // 5050 + 100*5 // # - k (subtract constant from each element) {`sum(1..10, # - 1)`, 45}, // 55 - 10*1 {`sum(1..100, # - 1)`, 4950}, // 5050 - 100*1 {`sum(1..10, # - 0)`, 55}, // k - # (constant minus each element) {`sum(1..10, 10 - #)`, 45}, // 10*10 - 55 {`sum(1..10, 0 - #)`, -55}, // 10*0 - 55 } for _, tt := range tests { t.Run(tt.expr, func(t *testing.T) { program, err := expr.Compile(tt.expr) require.NoError(t, err) output, err := expr.Run(program, nil) require.NoError(t, err) assert.Equal(t, tt.want, output) }) } } func TestOptimize_sum_range_with_predicate_ast(t *testing.T) { // Verify that sum(1..10, # * 2) is optimized to a constant tree, err := parser.Parse(`sum(1..10, # * 2)`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &ast.IntegerNode{Value: 110} assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node)) } func TestOptimize_reduce_range_sum(t *testing.T) { tree, err := parser.Parse(`reduce(1..100, # + #acc)`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &ast.IntegerNode{Value: 5050} assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node)) } func TestOptimize_reduce_range_sum_different_values(t *testing.T) { tests := []struct { expr string want int }{ {`reduce(1..10, # + #acc)`, 55}, {`reduce(1..100, # + #acc)`, 5050}, {`reduce(5..10, # + #acc)`, 45}, {`reduce(0..100, # + #acc)`, 5050}, {`reduce(1..1, # + #acc)`, 1}, {`reduce(10..20, # + #acc)`, 165}, } for _, tt := range tests { t.Run(tt.expr, func(t *testing.T) { program, err := expr.Compile(tt.expr) require.NoError(t, err) output, err := expr.Run(program, nil) require.NoError(t, err) assert.Equal(t, tt.want, output) }) } } func TestOptimize_reduce_range_sum_reverse_order(t *testing.T) { // Test #acc + # (reverse order) - should also be optimized tree, err := parser.Parse(`reduce(1..100, #acc + #)`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &ast.IntegerNode{Value: 5050} assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node)) } func TestOptimize_reduce_range_sum_with_initial_value(t *testing.T) { // Test reduce with initialValue: reduce(1..100, # + #acc, 10) => 5050 + 10 = 5060 tree, err := parser.Parse(`reduce(1..100, # + #acc, 10)`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) expected := &ast.IntegerNode{Value: 5060} assert.Equal(t, ast.Dump(expected), ast.Dump(tree.Node)) } func TestOptimize_reduce_range_sum_with_initial_value_different_values(t *testing.T) { tests := []struct { expr string want int }{ {`reduce(1..10, # + #acc, 0)`, 55}, {`reduce(1..10, # + #acc, 10)`, 65}, {`reduce(1..100, # + #acc, 0)`, 5050}, {`reduce(1..100, # + #acc, 100)`, 5150}, {`reduce(5..10, # + #acc, 5)`, 50}, } for _, tt := range tests { t.Run(tt.expr, func(t *testing.T) { program, err := expr.Compile(tt.expr) require.NoError(t, err) output, err := expr.Run(program, nil) require.NoError(t, err) assert.Equal(t, tt.want, output) }) } } func TestOptimize_sum_range_reversed(t *testing.T) { // When n < m (e.g., 10..1), the range is empty and sum should return 0. // The optimization should NOT apply (n >= m check), so runtime handles it. tests := []struct { expr string want int }{ {`sum(10..1)`, 0}, {`sum(5..3)`, 0}, {`sum(100..1)`, 0}, } for _, tt := range tests { t.Run(tt.expr, func(t *testing.T) { program, err := expr.Compile(tt.expr) require.NoError(t, err) output, err := expr.Run(program, nil) require.NoError(t, err) assert.Equal(t, tt.want, output) }) } } func TestOptimize_sum_range_reversed_not_optimized(t *testing.T) { // Verify that reversed ranges are NOT optimized (left as BuiltinNode) tree, err := parser.Parse(`sum(10..1)`) require.NoError(t, err) err = optimizer.Optimize(&tree.Node, nil) require.NoError(t, err) // Should still be a BuiltinNode, not an IntegerNode _, isBuiltin := tree.Node.(*ast.BuiltinNode) assert.True(t, isBuiltin, "reversed range should not be optimized") } func TestOptimize_reduce_range_reversed_errors(t *testing.T) { // reduce on empty range (reversed) should error at runtime program, err := expr.Compile(`reduce(10..1, # + #acc)`) require.NoError(t, err) _, err = expr.Run(program, nil) require.Error(t, err, "reduce on empty range should error") } func BenchmarkSumRange_Optimized(b *testing.B) { program, err := expr.Compile(`sum(1..100)`) require.NoError(b, err) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = expr.Run(program, nil) } b.StopTimer() require.Equal(b, 5050, out) } func BenchmarkReduceRangeSum_Optimized(b *testing.B) { program, err := expr.Compile(`reduce(1..100, # + #acc)`) require.NoError(b, err) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = expr.Run(program, nil) } b.StopTimer() require.Equal(b, 5050, out) } func BenchmarkSumRange_Unoptimized(b *testing.B) { program, err := expr.Compile(`sum(1..100)`, expr.Optimize(false)) require.NoError(b, err) var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, _ = expr.Run(program, nil) } b.StopTimer() require.Equal(b, 5050, out) } ================================================ FILE: parser/bench_test.go ================================================ package parser import "testing" func BenchmarkParser(b *testing.B) { const source = ` /* Showing worst case scenario */ let value = trim("contains escapes \n\"\\ \U0001F600 and non ASCII ñ"); // inline comment len(value) == 0x2A // let's introduce an error too whatever ` b.ReportAllocs() p := new(Parser) for i := 0; i < b.N; i++ { p.Parse(source, nil) } } ================================================ FILE: parser/lexer/lexer.go ================================================ package lexer import ( "fmt" "io" "strings" "unicode/utf8" "github.com/expr-lang/expr/file" "github.com/expr-lang/expr/internal/ring" ) const ringChunkSize = 10 // Lex will buffer and return the tokens of a disposable *[Lexer]. func Lex(source file.Source) ([]Token, error) { tokens := make([]Token, 0, ringChunkSize) l := New() l.Reset(source) for { t, err := l.Next() switch err { case nil: tokens = append(tokens, t) case io.EOF: return tokens, nil default: return nil, err } } } // New returns a reusable lexer. func New() *Lexer { return &Lexer{ tokens: ring.New[Token](ringChunkSize), } } type Lexer struct { state stateFn source file.Source tokens *ring.Ring[Token] err *file.Error start, end struct { byte, rune int } eof bool // When true, keywords `if`/`else` are not treated as operators and // will be emitted as identifiers instead (for compatibility with custom if()). DisableIfOperator bool } func (l *Lexer) Reset(source file.Source) { l.source = source l.tokens.Reset() l.state = root } func (l *Lexer) Next() (Token, error) { for l.state != nil && l.err == nil && l.tokens.Len() == 0 { l.state = l.state(l) } if l.err != nil { return Token{}, l.err.Bind(l.source) } if t, ok := l.tokens.Dequeue(); ok { return t, nil } return Token{}, io.EOF } const eof rune = -1 func (l *Lexer) commit() { l.start = l.end } func (l *Lexer) next() rune { if l.end.byte >= len(l.source.String()) { l.eof = true return eof } r, sz := utf8.DecodeRuneInString(l.source.String()[l.end.byte:]) l.end.rune++ l.end.byte += sz return r } func (l *Lexer) peek() rune { if l.end.byte < len(l.source.String()) { r, _ := utf8.DecodeRuneInString(l.source.String()[l.end.byte:]) return r } return eof } func (l *Lexer) backup() { if l.eof { l.eof = false } else if l.end.rune > 0 { _, sz := utf8.DecodeLastRuneInString(l.source.String()[:l.end.byte]) l.end.byte -= sz l.end.rune-- } } func (l *Lexer) emit(t Kind) { l.emitValue(t, l.word()) } func (l *Lexer) emitValue(t Kind, value string) { l.tokens.Enqueue(Token{ Location: file.Location{From: l.start.rune, To: l.end.rune}, Kind: t, Value: value, }) l.commit() } func (l *Lexer) emitEOF() { from := l.end.rune - 1 if from < 0 { from = 0 } to := l.end.rune - 0 if to < 0 { to = 0 } l.tokens.Enqueue(Token{ Location: file.Location{From: from, To: to}, Kind: EOF, }) l.commit() } func (l *Lexer) skip() { l.commit() } func (l *Lexer) word() string { return l.source.String()[l.start.byte:l.end.byte] } func (l *Lexer) accept(valid string) bool { if strings.ContainsRune(valid, l.peek()) { l.next() return true } return false } func (l *Lexer) acceptRun(valid string) { for l.accept(valid) { } } func (l *Lexer) skipSpaces() { l.acceptRun(" ") l.skip() } func (l *Lexer) error(format string, args ...any) stateFn { if l.err == nil { // show first error end := l.end.rune if l.eof { end++ } l.err = &file.Error{ Location: file.Location{ From: end - 1, To: end, }, Message: fmt.Sprintf(format, args...), } } return nil } func digitVal(ch rune) int { switch { case '0' <= ch && ch <= '9': return int(ch - '0') case 'a' <= lower(ch) && lower(ch) <= 'f': return int(lower(ch) - 'a' + 10) } return 16 // larger than any legal digit val } func lower(ch rune) rune { return ('a' - 'A') | ch } // returns lower-case ch iff ch is ASCII letter func (l *Lexer) scanDigits(ch rune, base, n int) rune { for n > 0 && digitVal(ch) < base { ch = l.next() n-- } if n > 0 { l.error("invalid char escape") } return ch } func (l *Lexer) scanEscape(quote rune) rune { ch := l.next() // read character after '/' switch ch { case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', quote: // nothing to do ch = l.next() case '0', '1', '2', '3', '4', '5', '6', '7': ch = l.scanDigits(ch, 8, 3) case 'x': ch = l.scanDigits(l.next(), 16, 2) case 'u': // Support variable-length form: \u{XXXXXX} if l.peek() == '{' { // consume '{' l.next() // read 1-6 hex digits digits := 0 for { p := l.peek() if p == '}' { break } if digitVal(p) >= 16 { l.error("invalid char escape") return eof } if digits >= 6 { l.error("invalid char escape") return eof } l.next() digits++ } if l.peek() != '}' || digits == 0 { l.error("invalid char escape") return eof } // consume '}' and continue l.next() ch = l.next() break } ch = l.scanDigits(l.next(), 16, 4) case 'U': ch = l.scanDigits(l.next(), 16, 8) default: l.error("invalid char escape") } return ch } func (l *Lexer) scanString(quote rune) (n int) { ch := l.next() // read character after quote for ch != quote { if ch == '\n' || ch == eof { l.error("literal not terminated") return } if ch == '\\' { ch = l.scanEscape(quote) } else { ch = l.next() } n++ } return } func (l *Lexer) scanRawString(quote rune) (n int) { var escapedQuotes int loop: for { ch := l.next() for ch == quote && l.peek() == quote { // skip current and next char which are the quote escape sequence l.next() ch = l.next() escapedQuotes++ } switch ch { case quote: break loop case eof: l.error("literal not terminated") return } n++ } str := l.source.String()[l.start.byte+1 : l.end.byte-1] // handle simple case where no quoted backtick was found, then no allocation // is needed for the new string if escapedQuotes == 0 { l.emitValue(String, str) return } var b strings.Builder var skipped bool b.Grow(len(str) - escapedQuotes) for _, r := range str { if r == quote { if !skipped { skipped = true continue } skipped = false } b.WriteRune(r) } l.emitValue(String, b.String()) return } ================================================ FILE: parser/lexer/lexer_test.go ================================================ package lexer_test import ( "fmt" "strings" "testing" "github.com/expr-lang/expr/file" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr/internal/testify/require" . "github.com/expr-lang/expr/parser/lexer" ) func TestLex(t *testing.T) { tests := []struct { input string tokens []Token }{ { "1", []Token{ {Kind: Number, Value: "1"}, {Kind: EOF}, }, }, { ".5 0.025 1 02 1e3 0xFF 0b0101 0o600 1.2e-4 1_000_000 _42 -.5", []Token{ {Kind: Number, Value: ".5"}, {Kind: Number, Value: "0.025"}, {Kind: Number, Value: "1"}, {Kind: Number, Value: "02"}, {Kind: Number, Value: "1e3"}, {Kind: Number, Value: "0xFF"}, {Kind: Number, Value: "0b0101"}, {Kind: Number, Value: "0o600"}, {Kind: Number, Value: "1.2e-4"}, {Kind: Number, Value: "1_000_000"}, {Kind: Identifier, Value: "_42"}, {Kind: Operator, Value: "-"}, {Kind: Number, Value: ".5"}, {Kind: EOF}, }, }, { `"double" 'single' "abc \n\t\"\\" '"\'' "'\"" "\xC3\xBF\u263A\U000003A8" '❤️'`, []Token{ {Kind: String, Value: "double"}, {Kind: String, Value: "single"}, {Kind: String, Value: "abc \n\t\"\\"}, {Kind: String, Value: "\"'"}, {Kind: String, Value: "'\""}, {Kind: String, Value: "ÿ☺Ψ"}, {Kind: String, Value: "❤️"}, {Kind: EOF}, }, }, { "`backtick` `hello\u263Aworld` `hello\n\tworld` `hello\"world'` `\xC3\xBF\u263A\U000003A8` `❤️`", []Token{ {Kind: String, Value: `backtick`}, {Kind: String, Value: `hello☺world`}, {Kind: String, Value: `hello world`}, {Kind: String, Value: `hello"world'`}, {Kind: String, Value: `ÿ☺Ψ`}, {Kind: String, Value: "❤️"}, {Kind: EOF}, }, }, { "`escaped backticks` `` `a``b` ```` `a``` ```b` ```a````b``` ```````` ```a````` `````b```", []Token{ {Kind: String, Value: "escaped backticks"}, {Kind: String, Value: ""}, {Kind: String, Value: "a`b"}, {Kind: String, Value: "`"}, {Kind: String, Value: "a`"}, {Kind: String, Value: "`b"}, {Kind: String, Value: "`a``b`"}, {Kind: String, Value: "```"}, {Kind: String, Value: "`a``"}, {Kind: String, Value: "``b`"}, {Kind: EOF}, }, }, { "a and orb().val #.", []Token{ {Kind: Identifier, Value: "a"}, {Kind: Operator, Value: "and"}, {Kind: Identifier, Value: "orb"}, {Kind: Bracket, Value: "("}, {Kind: Bracket, Value: ")"}, {Kind: Operator, Value: "."}, {Kind: Identifier, Value: "val"}, {Kind: Operator, Value: "#"}, {Kind: Operator, Value: "."}, {Kind: EOF}, }, }, { "foo?.bar", []Token{ {Kind: Identifier, Value: "foo"}, {Kind: Operator, Value: "?."}, {Kind: Identifier, Value: "bar"}, {Kind: EOF}, }, }, { "foo ? .bar : .baz", []Token{ {Kind: Identifier, Value: "foo"}, {Kind: Operator, Value: "?"}, {Kind: Operator, Value: "."}, {Kind: Identifier, Value: "bar"}, {Kind: Operator, Value: ":"}, {Kind: Operator, Value: "."}, {Kind: Identifier, Value: "baz"}, {Kind: EOF}, }, }, { "func?()", []Token{ {Kind: Identifier, Value: "func"}, {Kind: Operator, Value: "?"}, {Kind: Bracket, Value: "("}, {Kind: Bracket, Value: ")"}, {Kind: EOF}, }, }, { "array?[]", []Token{ {Kind: Identifier, Value: "array"}, {Kind: Operator, Value: "?"}, {Kind: Bracket, Value: "["}, {Kind: Bracket, Value: "]"}, {Kind: EOF}, }, }, { `not in not abc not i not(false) not in not in`, []Token{ {Kind: Operator, Value: "not"}, {Kind: Operator, Value: "in"}, {Kind: Operator, Value: "not"}, {Kind: Identifier, Value: "abc"}, {Kind: Operator, Value: "not"}, {Kind: Identifier, Value: "i"}, {Kind: Operator, Value: "not"}, {Kind: Bracket, Value: "("}, {Kind: Identifier, Value: "false"}, {Kind: Bracket, Value: ")"}, {Kind: Operator, Value: "not"}, {Kind: Operator, Value: "in"}, {Kind: Operator, Value: "not"}, {Kind: Operator, Value: "in"}, {Kind: EOF}, }, }, { "not in_var", []Token{ {Kind: Operator, Value: "not"}, {Kind: Identifier, Value: "in_var"}, {Kind: EOF}, }, }, { "not in", []Token{ {Kind: Operator, Value: "not"}, {Kind: Operator, Value: "in"}, {Kind: EOF}, }, }, { `1..5`, []Token{ {Kind: Number, Value: "1"}, {Kind: Operator, Value: ".."}, {Kind: Number, Value: "5"}, {Kind: EOF}, }, }, { `$i _0 früh`, []Token{ {Kind: Identifier, Value: "$i"}, {Kind: Identifier, Value: "_0"}, {Kind: Identifier, Value: "früh"}, {Kind: EOF}, }, }, { `foo // comment bar // comment`, []Token{ {Kind: Identifier, Value: "foo"}, {Kind: Identifier, Value: "bar"}, {Kind: EOF}, }, }, { `foo /* comment */ bar`, []Token{ {Kind: Identifier, Value: "foo"}, {Kind: Identifier, Value: "bar"}, {Kind: EOF}, }, }, { `foo ?? bar`, []Token{ {Kind: Identifier, Value: "foo"}, {Kind: Operator, Value: "??"}, {Kind: Identifier, Value: "bar"}, {Kind: EOF}, }, }, { `let foo = bar;`, []Token{ {Kind: Operator, Value: "let"}, {Kind: Identifier, Value: "foo"}, {Kind: Operator, Value: "="}, {Kind: Identifier, Value: "bar"}, {Kind: Operator, Value: ";"}, {Kind: EOF}, }, }, { `#index #1 #`, []Token{ {Kind: Operator, Value: "#"}, {Kind: Identifier, Value: "index"}, {Kind: Operator, Value: "#"}, {Kind: Identifier, Value: "1"}, {Kind: Operator, Value: "#"}, {Kind: EOF}, }, }, { `: ::`, []Token{ {Kind: Operator, Value: ":"}, {Kind: Operator, Value: "::"}, {Kind: EOF}, }, }, { `if a>b {x1+x2} else {x2}`, []Token{ {Kind: Operator, Value: "if"}, {Kind: Identifier, Value: "a"}, {Kind: Operator, Value: ">"}, {Kind: Identifier, Value: "b"}, {Kind: Bracket, Value: "{"}, {Kind: Identifier, Value: "x1"}, {Kind: Operator, Value: "+"}, {Kind: Identifier, Value: "x2"}, {Kind: Bracket, Value: "}"}, {Kind: Operator, Value: "else"}, {Kind: Bracket, Value: "{"}, {Kind: Identifier, Value: "x2"}, {Kind: Bracket, Value: "}"}, {Kind: EOF}, }, }, { `a>b if {x1} else {x2}`, []Token{ {Kind: Identifier, Value: "a"}, {Kind: Operator, Value: ">"}, {Kind: Identifier, Value: "b"}, {Kind: Operator, Value: "if"}, {Kind: Bracket, Value: "{"}, {Kind: Identifier, Value: "x1"}, {Kind: Bracket, Value: "}"}, {Kind: Operator, Value: "else"}, {Kind: Bracket, Value: "{"}, {Kind: Identifier, Value: "x2"}, {Kind: Bracket, Value: "}"}, {Kind: EOF}, }, }, { "\"\\u{61}\\u{1F600}\" '\\u{61}\\u{1F600}'", []Token{ {Kind: String, Value: "a😀"}, {Kind: String, Value: "a😀"}, {Kind: EOF}, }, }, { `b"hello" b'world'`, []Token{ {Kind: Bytes, Value: "hello"}, {Kind: Bytes, Value: "world"}, {Kind: EOF}, }, }, { `b"\x00\xff" b'\x41\x42\x43'`, []Token{ {Kind: Bytes, Value: "\x00\xff"}, {Kind: Bytes, Value: "ABC"}, {Kind: EOF}, }, }, { `b"\101\102\103" b'\n\t\r'`, []Token{ {Kind: Bytes, Value: "ABC"}, {Kind: Bytes, Value: "\n\t\r"}, {Kind: EOF}, }, }, { `b""`, []Token{ {Kind: Bytes, Value: ""}, {Kind: EOF}, }, }, { `B"hello" B'world'`, []Token{ {Kind: Bytes, Value: "hello"}, {Kind: Bytes, Value: "world"}, {Kind: EOF}, }, }, { `b"ÿ"`, []Token{ {Kind: Bytes, Value: "\xc3\xbf"}, {Kind: EOF}, }, }, } for _, test := range tests { t.Run(test.input, func(t *testing.T) { tokens, err := Lex(file.NewSource(test.input)) if err != nil { t.Errorf("%s:\n%v", test.input, err) return } if !compareTokens(tokens, test.tokens) { t.Errorf("%s:\ngot\n\t%+v\nexpected\n\t%v", test.input, tokens, test.tokens) } }) } } func compareTokens(i1, i2 []Token) bool { if len(i1) != len(i2) { return false } for k := range i1 { if i1[k].Kind != i2[k].Kind { return false } if i1[k].Value != i2[k].Value { return false } } return true } func TestLex_location(t *testing.T) { source := file.NewSource("1..2\n3..4") tokens, err := Lex(source) require.NoError(t, err) require.Equal(t, []Token{ {Location: file.Location{From: 0, To: 1}, Kind: Number, Value: "1"}, {Location: file.Location{From: 1, To: 3}, Kind: Operator, Value: ".."}, {Location: file.Location{From: 3, To: 4}, Kind: Number, Value: "2"}, {Location: file.Location{From: 5, To: 6}, Kind: Number, Value: "3"}, {Location: file.Location{From: 6, To: 8}, Kind: Operator, Value: ".."}, {Location: file.Location{From: 8, To: 9}, Kind: Number, Value: "4"}, {Location: file.Location{From: 8, To: 9}, Kind: EOF, Value: ""}, }, tokens) } const errorTests = ` "\xQA" invalid char escape (1:4) | "\xQA" | ...^ id "hello literal not terminated (1:10) | id "hello | .........^ id ` + "`" + `hello literal not terminated (1:10) | id ` + "`" + `hello | .........^ id ` + "`" + `hello` + "``" + ` literal not terminated (1:12) | id ` + "`" + `hello` + "``" + ` | ...........^ id ` + "```" + `hello literal not terminated (1:12) | id ` + "```" + `hello | ...........^ id ` + "`" + `hello` + "``" + ` world literal not terminated (1:18) | id ` + "`" + `hello` + "``" + ` world | .................^ früh ♥︎ unrecognized character: U+2665 '♥' (1:6) | früh ♥︎ | .....^ b"\u0041" unable to unescape string (1:9) | b"\u0041" | ........^ b'\U00000041' unable to unescape string (1:13) | b'\U00000041' | ............^ ` func TestLex_error(t *testing.T) { tests := strings.Split(strings.Trim(errorTests, "\n"), "\n\n") for _, test := range tests { input := strings.SplitN(test, "\n", 2) if len(input) != 2 { t.Errorf("syntax error in test: %q", test) break } _, err := Lex(file.NewSource(input[0])) if err == nil { err = fmt.Errorf("") } assert.Equal(t, input[1], err.Error(), input[0]) } } ================================================ FILE: parser/lexer/state.go ================================================ package lexer import ( "strings" "github.com/expr-lang/expr/parser/utils" ) type stateFn func(*Lexer) stateFn func root(l *Lexer) stateFn { switch r := l.next(); { case r == eof: l.emitEOF() return nil case utils.IsSpace(r): l.skip() return root case r == '\'' || r == '"': l.scanString(r) str, err := unescape(l.word()) if err != nil { l.error("%v", err) } l.emitValue(String, str) case r == '`': l.scanRawString(r) case (r == 'b' || r == 'B') && (l.peek() == '\'' || l.peek() == '"'): quote := l.next() l.scanString(quote) str, err := unescapeBytes(l.word()[1:]) // skip 'b' if err != nil { l.error("%v", err) } l.emitValue(Bytes, str) case '0' <= r && r <= '9': l.backup() return number case r == '?': return questionMark case r == '/': return slash case r == '#': return pointer case r == '|': l.accept("|") l.emit(Operator) case r == ':': l.accept(":") l.emit(Operator) case strings.ContainsRune("([{", r): l.emit(Bracket) case strings.ContainsRune(")]}", r): l.emit(Bracket) case strings.ContainsRune(",;%+-^", r): // single rune operator l.emit(Operator) case strings.ContainsRune("&!=*<>", r): // possible double rune operator l.accept("&=*") l.emit(Operator) case r == '.': l.backup() return dot case utils.IsAlphaNumeric(r): l.backup() return identifier default: return l.error("unrecognized character: %#U", r) } return root } func number(l *Lexer) stateFn { if !l.scanNumber() { return l.error("bad number syntax: %q", l.word()) } l.emit(Number) return root } func (l *Lexer) scanNumber() bool { digits := "0123456789_" // Is it hex? if l.accept("0") { // Note: Leading 0 does not mean octal in floats. if l.accept("xX") { digits = "0123456789abcdefABCDEF_" } else if l.accept("oO") { digits = "01234567_" } else if l.accept("bB") { digits = "01_" } } l.acceptRun(digits) end := l.end if l.accept(".") { // Lookup for .. operator: if after dot there is another dot (1..2), it maybe a range operator. if l.peek() == '.' { // We can't backup() here, as it would require two backups, // and backup() func supports only one for now. So, save and // restore it here. l.end = end return true } l.acceptRun(digits) } if l.accept("eE") { l.accept("+-") l.acceptRun(digits) } // Next thing mustn't be alphanumeric. if utils.IsAlphaNumeric(l.peek()) { l.next() return false } return true } func dot(l *Lexer) stateFn { l.next() if l.accept("0123456789") { l.backup() return number } l.accept(".") l.emit(Operator) return root } func identifier(l *Lexer) stateFn { loop: for { switch r := l.next(); { case utils.IsAlphaNumeric(r): // absorb default: l.backup() switch l.word() { case "not": return not case "in", "or", "and", "matches", "contains", "startsWith", "endsWith", "let": l.emit(Operator) case "if", "else": if !l.DisableIfOperator { l.emit(Operator) } else { l.emit(Identifier) } default: l.emit(Identifier) } break loop } } return root } func not(l *Lexer) stateFn { l.emit(Operator) l.skipSpaces() end := l.end // Get the next word. for { r := l.next() if utils.IsAlphaNumeric(r) { // absorb } else { l.backup() break } } switch l.word() { case "in", "matches", "contains", "startsWith", "endsWith": l.emit(Operator) default: l.end = end } return root } func questionMark(l *Lexer) stateFn { l.accept(".?") l.emit(Operator) return root } func slash(l *Lexer) stateFn { if l.accept("/") { return singleLineComment } if l.accept("*") { return multiLineComment } l.emit(Operator) return root } func singleLineComment(l *Lexer) stateFn { for { r := l.next() if r == eof || r == '\n' { break } } l.skip() return root } func multiLineComment(l *Lexer) stateFn { for { r := l.next() if r == eof { return l.error("unclosed comment") } if r == '*' && l.accept("/") { break } } l.skip() return root } func pointer(l *Lexer) stateFn { l.accept("#") l.emit(Operator) for { switch r := l.next(); { case utils.IsAlphaNumeric(r): // absorb default: l.backup() if l.word() != "" { l.emit(Identifier) } return root } } } ================================================ FILE: parser/lexer/token.go ================================================ package lexer import ( "fmt" "github.com/expr-lang/expr/file" ) type Kind string const ( Identifier Kind = "Identifier" Number Kind = "Number" String Kind = "String" Bytes Kind = "Bytes" Operator Kind = "Operator" Bracket Kind = "Bracket" EOF Kind = "EOF" ) type Token struct { file.Location Kind Kind Value string } func (t Token) String() string { if t.Value == "" { return string(t.Kind) } return fmt.Sprintf("%s(%#v)", t.Kind, t.Value) } func (t Token) Is(kind Kind, values ...string) bool { if kind != t.Kind { return false } for _, v := range values { if v == t.Value { return true } } return len(values) == 0 } ================================================ FILE: parser/lexer/utils.go ================================================ package lexer import ( "fmt" "math" "strings" "unicode/utf8" ) var ( newlineNormalizer = strings.NewReplacer("\r\n", "\n", "\r", "\n") ) // Unescape takes a quoted string, unquotes, and unescapes it. func unescape(value string) (string, error) { // All strings normalize newlines to the \n representation. value = newlineNormalizer.Replace(value) n := len(value) // Nothing to unescape / decode. if n < 2 { return value, fmt.Errorf("unable to unescape string") } // Quoted string of some form, must have same first and last char. if value[0] != value[n-1] || (value[0] != '"' && value[0] != '\'') { return value, fmt.Errorf("unable to unescape string") } value = value[1 : n-1] // The string contains escape characters. // The following logic is adapted from `strconv/quote.go` var runeTmp [utf8.UTFMax]byte size := 3 * uint64(n) / 2 if size >= math.MaxInt { return "", fmt.Errorf("too large string") } buf := new(strings.Builder) buf.Grow(int(size)) for len(value) > 0 { c, multibyte, rest, err := unescapeChar(value) if err != nil { return "", err } value = rest if c < utf8.RuneSelf || !multibyte { buf.WriteByte(byte(c)) } else { n := utf8.EncodeRune(runeTmp[:], c) buf.Write(runeTmp[:n]) } } return buf.String(), nil } // unescapeBytes takes a quoted string, unquotes, and unescapes it as bytes. func unescapeBytes(value string) (string, error) { // All strings normalize newlines to the \n representation. value = newlineNormalizer.Replace(value) n := len(value) // Nothing to unescape / decode. if n < 2 { return value, fmt.Errorf("unable to unescape string") } // Quoted string of some form, must have same first and last char. if value[0] != value[n-1] || (value[0] != '"' && value[0] != '\'') { return value, fmt.Errorf("unable to unescape string") } value = value[1 : n-1] // The string contains escape characters. // The following logic is adapted from `strconv/quote.go` var runeTmp [utf8.UTFMax]byte size := 3 * uint64(n) / 2 if size >= math.MaxInt { return "", fmt.Errorf("too large string") } buf := new(strings.Builder) buf.Grow(int(size)) for len(value) > 0 { c, multibyte, rest, err := unescapeByteChar(value) if err != nil { return "", err } value = rest if c < utf8.RuneSelf || !multibyte { buf.WriteByte(byte(c)) } else { n := utf8.EncodeRune(runeTmp[:], c) buf.Write(runeTmp[:n]) } } return buf.String(), nil } // unescapeChar takes a string input and returns the following info: // // value - the escaped unicode rune at the front of the string. // multibyte - whether the rune value might require multiple bytes to represent. // tail - the remainder of the input string. // err - error value, if the character could not be unescaped. // // When multibyte is true the return value may still fit within a single byte, // but a multibyte conversion is attempted which is more expensive than when the // value is known to fit within one byte. func unescapeChar(s string) (value rune, multibyte bool, tail string, err error) { // 1. Character is not an escape sequence. switch c := s[0]; { case c >= utf8.RuneSelf: r, size := utf8.DecodeRuneInString(s) return r, true, s[size:], nil case c != '\\': return rune(s[0]), false, s[1:], nil } // 2. Last character is the start of an escape sequence. if len(s) <= 1 { err = fmt.Errorf("unable to unescape string, found '\\' as last character") return } c := s[1] s = s[2:] // 3. Common escape sequences shared with Google SQL switch c { case 'a': value = '\a' case 'b': value = '\b' case 'f': value = '\f' case 'n': value = '\n' case 'r': value = '\r' case 't': value = '\t' case 'v': value = '\v' case '\\': value = '\\' case '\'': value = '\'' case '"': value = '"' case '`': value = '`' case '?': value = '?' // 4. Unicode escape sequences, reproduced from `strconv/quote.go` case 'x', 'X', 'u', 'U': // Support Go/Rust-style variable-length form: \u{XXXXXX} if c == 'u' && len(s) > 0 && s[0] == '{' { // consume '{' s = s[1:] var v rune digits := 0 for len(s) > 0 && s[0] != '}' { x, ok := unhex(s[0]) if !ok { err = fmt.Errorf("unable to unescape string") return } if digits >= 6 { // at most 6 hex digits err = fmt.Errorf("unable to unescape string") return } v = v<<4 | x s = s[1:] digits++ } // require closing '}' and at least 1 digit if len(s) == 0 || s[0] != '}' || digits == 0 { err = fmt.Errorf("unable to unescape string") return } // consume '}' s = s[1:] if v > utf8.MaxRune { err = fmt.Errorf("unable to unescape string") return } value = v multibyte = true break } n := 0 switch c { case 'x', 'X': n = 2 case 'u': n = 4 case 'U': n = 8 } var v rune if len(s) < n { err = fmt.Errorf("unable to unescape string") return } for j := 0; j < n; j++ { x, ok := unhex(s[j]) if !ok { err = fmt.Errorf("unable to unescape string") return } v = v<<4 | x } s = s[n:] if v > utf8.MaxRune { err = fmt.Errorf("unable to unescape string") return } value = v multibyte = true // 5. Octal escape sequences, must be three digits \[0-3][0-7][0-7] case '0', '1', '2', '3': if len(s) < 2 { err = fmt.Errorf("unable to unescape octal sequence in string") return } v := rune(c - '0') for j := 0; j < 2; j++ { x := s[j] if x < '0' || x > '7' { err = fmt.Errorf("unable to unescape octal sequence in string") return } v = v*8 + rune(x-'0') } if v > utf8.MaxRune { err = fmt.Errorf("unable to unescape string") return } value = v s = s[2:] multibyte = true // Unknown escape sequence. default: err = fmt.Errorf("unable to unescape string") } tail = s return } // unescapeByteChar unescapes a single character or escape sequence from a bytes literal. // Unlike unescapeChar, this only supports byte-level escapes (\x, octal) and rejects // Unicode escapes (\u, \U) since bytes literals represent raw byte sequences. // // Note: We cannot use strconv.UnquoteChar here because it interprets \x and octal // escapes as Unicode codepoints (e.g., \xff → codepoint 255 → 2 UTF-8 bytes), // whereas bytes literals require them as raw byte values (\xff → single byte 255). func unescapeByteChar(s string) (value rune, multibyte bool, tail string, err error) { // Non-escape: return the character as-is. // For bytes literals, we accept UTF-8 sequences but they get encoded back to bytes. c := s[0] if c != '\\' { if c >= utf8.RuneSelf { r, size := utf8.DecodeRuneInString(s) return r, true, s[size:], nil } return rune(c), false, s[1:], nil } // Escape sequence: need at least one more character. if len(s) <= 1 { return 0, false, "", fmt.Errorf("unable to unescape string, found '\\' as last character") } c = s[1] s = s[2:] switch c { // Simple escape sequences case 'a': return '\a', false, s, nil case 'b': return '\b', false, s, nil case 'f': return '\f', false, s, nil case 'n': return '\n', false, s, nil case 'r': return '\r', false, s, nil case 't': return '\t', false, s, nil case 'v': return '\v', false, s, nil case '\\': return '\\', false, s, nil case '\'': return '\'', false, s, nil case '"': return '"', false, s, nil case '`': return '`', false, s, nil case '?': return '?', false, s, nil // Hex escape: \xNN (exactly 2 hex digits, value 0-255) case 'x', 'X': if len(s) < 2 { return 0, false, "", fmt.Errorf("unable to unescape string") } hi, ok1 := unhex(s[0]) lo, ok2 := unhex(s[1]) if !ok1 || !ok2 { return 0, false, "", fmt.Errorf("unable to unescape string") } return hi<<4 | lo, false, s[2:], nil // Octal escape: \NNN (3 octal digits, value 0-255) case '0', '1', '2', '3': if len(s) < 2 { return 0, false, "", fmt.Errorf("unable to unescape octal sequence in string") } if s[0] < '0' || s[0] > '7' || s[1] < '0' || s[1] > '7' { return 0, false, "", fmt.Errorf("unable to unescape octal sequence in string") } v := rune(c-'0')*64 + rune(s[0]-'0')*8 + rune(s[1]-'0') if v > 255 { return 0, false, "", fmt.Errorf("unable to unescape string") } return v, false, s[2:], nil default: return 0, false, "", fmt.Errorf("unable to unescape string") } } func unhex(b byte) (rune, bool) { c := rune(b) switch { case '0' <= c && c <= '9': return c - '0', true case 'a' <= c && c <= 'f': return c - 'a' + 10, true case 'A' <= c && c <= 'F': return c - 'A' + 10, true } return 0, false } ================================================ FILE: parser/operator/operator.go ================================================ package operator type Associativity int const ( Left Associativity = iota + 1 Right ) type Operator struct { Precedence int Associativity Associativity } func Less(a, b string) bool { return Binary[a].Precedence < Binary[b].Precedence } func IsBoolean(op string) bool { return op == "and" || op == "or" || op == "&&" || op == "||" } func AllowedNegateSuffix(op string) bool { switch op { case "contains", "matches", "startsWith", "endsWith", "in": return true default: return false } } var Unary = map[string]Operator{ "not": {50, Left}, "!": {50, Left}, "-": {90, Left}, "+": {90, Left}, } var Binary = map[string]Operator{ "|": {0, Left}, "or": {10, Left}, "||": {10, Left}, "and": {15, Left}, "&&": {15, Left}, "==": {20, Left}, "!=": {20, Left}, "<": {20, Left}, ">": {20, Left}, ">=": {20, Left}, "<=": {20, Left}, "in": {20, Left}, "matches": {20, Left}, "contains": {20, Left}, "startsWith": {20, Left}, "endsWith": {20, Left}, "..": {25, Left}, "+": {30, Left}, "-": {30, Left}, "*": {60, Left}, "/": {60, Left}, "%": {60, Left}, "**": {100, Right}, "^": {100, Right}, "??": {500, Left}, } func IsComparison(op string) bool { return op == "<" || op == ">" || op == ">=" || op == "<=" } ================================================ FILE: parser/parser.go ================================================ package parser import ( "errors" "fmt" "io" "math" "strconv" "strings" . "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/builtin" "github.com/expr-lang/expr/conf" "github.com/expr-lang/expr/file" . "github.com/expr-lang/expr/parser/lexer" "github.com/expr-lang/expr/parser/operator" "github.com/expr-lang/expr/parser/utils" ) type arg byte const ( expr arg = 1 << iota predicate ) const optional arg = 1 << 7 var predicates = map[string]struct { args []arg }{ "all": {[]arg{expr, predicate}}, "none": {[]arg{expr, predicate}}, "any": {[]arg{expr, predicate}}, "one": {[]arg{expr, predicate}}, "filter": {[]arg{expr, predicate}}, "map": {[]arg{expr, predicate}}, "count": {[]arg{expr, predicate | optional}}, "sum": {[]arg{expr, predicate | optional}}, "find": {[]arg{expr, predicate}}, "findIndex": {[]arg{expr, predicate}}, "findLast": {[]arg{expr, predicate}}, "findLastIndex": {[]arg{expr, predicate}}, "groupBy": {[]arg{expr, predicate}}, "sortBy": {[]arg{expr, predicate, expr | optional}}, "reduce": {[]arg{expr, predicate, expr | optional}}, } // Parser is a reusable parser. The zero value is ready for use. type Parser struct { lexer *Lexer current, stashed Token hasStash bool err *file.Error config *conf.Config depth int // predicate call depth nodeCount uint // tracks number of AST nodes created } func (p *Parser) Parse(input string, config *conf.Config) (*Tree, error) { if p.lexer == nil { p.lexer = New() } p.config = config // propagate config flags to lexer if p.lexer != nil { if config != nil { p.lexer.DisableIfOperator = config.DisableIfOperator } else { p.lexer.DisableIfOperator = false } } source := file.NewSource(input) p.lexer.Reset(source) p.next() node := p.parseSequenceExpression() if !p.current.Is(EOF) { p.error("unexpected token %v", p.current) } tree := &Tree{ Node: node, Source: source, } err := p.err // cleanup non-reusable pointer values and reset state p.err = nil p.config = nil p.lexer.Reset(file.Source{}) if err != nil { return tree, err.Bind(source) } return tree, nil } func (p *Parser) checkNodeLimit() error { p.nodeCount++ if p.config == nil { if p.nodeCount > conf.DefaultMaxNodes { p.error("compilation failed: expression exceeds maximum allowed nodes") return nil } return nil } if p.config.MaxNodes > 0 && p.nodeCount > p.config.MaxNodes { p.error("compilation failed: expression exceeds maximum allowed nodes") return nil } return nil } func (p *Parser) createNode(n Node, loc file.Location) Node { if err := p.checkNodeLimit(); err != nil { return nil } if n == nil || p.err != nil { return nil } n.SetLocation(loc) return n } func (p *Parser) createMemberNode(n *MemberNode, loc file.Location) *MemberNode { if err := p.checkNodeLimit(); err != nil { return nil } if n == nil || p.err != nil { return nil } n.SetLocation(loc) return n } type Tree struct { Node Node Source file.Source } func Parse(input string) (*Tree, error) { return ParseWithConfig(input, nil) } func ParseWithConfig(input string, config *conf.Config) (*Tree, error) { return new(Parser).Parse(input, config) } func (p *Parser) error(format string, args ...any) { p.errorAt(p.current, format, args...) } func (p *Parser) errorAt(token Token, format string, args ...any) { if p.err == nil { // show first error p.err = &file.Error{ Location: token.Location, Message: fmt.Sprintf(format, args...), } } } func (p *Parser) next() { if p.hasStash { p.current = p.stashed p.hasStash = false return } token, err := p.lexer.Next() var e *file.Error switch { case err == nil: p.current = token case errors.Is(err, io.EOF): p.error("unexpected end of expression") case errors.As(err, &e): p.err = e default: p.err = &file.Error{ Location: p.current.Location, Message: "unknown lexing error", Prev: err, } } } func (p *Parser) expect(kind Kind, values ...string) { if p.current.Is(kind, values...) { p.next() return } p.error("unexpected token %v", p.current) } // parse functions func (p *Parser) parseSequenceExpression() Node { nodes := []Node{p.parseExpression(0)} for p.current.Is(Operator, ";") && p.err == nil { p.next() // If a trailing semicolon is present, break out. if p.current.Is(EOF) { break } nodes = append(nodes, p.parseExpression(0)) } if len(nodes) == 1 { return nodes[0] } return p.createNode(&SequenceNode{ Nodes: nodes, }, nodes[0].Location()) } func (p *Parser) parseExpression(precedence int) Node { if p.err != nil { return nil } if precedence == 0 && p.current.Is(Operator, "let") { return p.parseVariableDeclaration() } if precedence == 0 && (p.config == nil || !p.config.DisableIfOperator) && p.current.Is(Operator, "if") { return p.parseConditionalIf() } nodeLeft := p.parsePrimary() prevOperator := "" opToken := p.current for opToken.Is(Operator) && p.err == nil { negate := opToken.Is(Operator, "not") var notToken Token // Handle "not *" operator, like "not in" or "not contains". if negate { tokenBackup := p.current p.next() if operator.AllowedNegateSuffix(p.current.Value) { if op, ok := operator.Binary[p.current.Value]; ok && op.Precedence >= precedence { notToken = p.current opToken = p.current } else { p.hasStash = true p.stashed = p.current p.current = tokenBackup break } } else { p.error("unexpected token %v", p.current) break } } if op, ok := operator.Binary[opToken.Value]; ok && op.Precedence >= precedence { p.next() if opToken.Value == "|" { identToken := p.current p.expect(Identifier) nodeLeft = p.parseCall(identToken, []Node{nodeLeft}, true) goto next } if prevOperator == "??" && opToken.Value != "??" && !opToken.Is(Bracket, "(") { p.errorAt(opToken, "Operator (%v) and coalesce expressions (??) cannot be mixed. Wrap either by parentheses.", opToken.Value) break } if operator.IsComparison(opToken.Value) { nodeLeft = p.parseComparison(nodeLeft, opToken, op.Precedence) goto next } var nodeRight Node if op.Associativity == operator.Left { nodeRight = p.parseExpression(op.Precedence + 1) } else { nodeRight = p.parseExpression(op.Precedence) } nodeLeft = p.createNode(&BinaryNode{ Operator: opToken.Value, Left: nodeLeft, Right: nodeRight, }, opToken.Location) if nodeLeft == nil { return nil } if negate { nodeLeft = p.createNode(&UnaryNode{ Operator: "not", Node: nodeLeft, }, notToken.Location) if nodeLeft == nil { return nil } } goto next } break next: prevOperator = opToken.Value opToken = p.current } if precedence == 0 { nodeLeft = p.parseConditional(nodeLeft) } return nodeLeft } func (p *Parser) parseVariableDeclaration() Node { p.expect(Operator, "let") variableName := p.current p.expect(Identifier) p.expect(Operator, "=") value := p.parseExpression(0) p.expect(Operator, ";") node := p.parseSequenceExpression() return p.createNode(&VariableDeclaratorNode{ Name: variableName.Value, Value: value, Expr: node, }, variableName.Location) } func (p *Parser) parseConditionalIf() Node { p.next() if p.err != nil { return nil } nodeCondition := p.parseExpression(0) p.expect(Bracket, "{") expr1 := p.parseSequenceExpression() p.expect(Bracket, "}") p.expect(Operator, "else") var expr2 Node if p.current.Is(Operator, "if") { expr2 = p.parseConditionalIf() } else { p.expect(Bracket, "{") expr2 = p.parseSequenceExpression() p.expect(Bracket, "}") } return &ConditionalNode{ Cond: nodeCondition, Exp1: expr1, Exp2: expr2, } } func (p *Parser) parseConditional(node Node) Node { var expr1, expr2 Node for p.current.Is(Operator, "?") && p.err == nil { p.next() if !p.current.Is(Operator, ":") { expr1 = p.parseExpression(0) p.expect(Operator, ":") expr2 = p.parseExpression(0) } else { p.next() expr1 = node expr2 = p.parseExpression(0) } node = p.createNode(&ConditionalNode{ Ternary: true, Cond: node, Exp1: expr1, Exp2: expr2, }, p.current.Location) if node == nil { return nil } } return node } func (p *Parser) parsePrimary() Node { token := p.current if token.Is(Operator) { if op, ok := operator.Unary[token.Value]; ok { p.next() expr := p.parseExpression(op.Precedence) node := p.createNode(&UnaryNode{ Operator: token.Value, Node: expr, }, token.Location) if node == nil { return nil } return p.parsePostfixExpression(node) } } if token.Is(Bracket, "(") { p.next() expr := p.parseSequenceExpression() p.expect(Bracket, ")") // "an opened parenthesis is not properly closed" return p.parsePostfixExpression(expr) } if p.depth > 0 { if token.Is(Operator, "#") || token.Is(Operator, ".") { name := "" if token.Is(Operator, "#") { p.next() if p.current.Is(Identifier) { name = p.current.Value p.next() } } node := p.createNode(&PointerNode{Name: name}, token.Location) if node == nil { return nil } return p.parsePostfixExpression(node) } } if token.Is(Operator, "::") { p.next() token = p.current p.expect(Identifier) return p.parsePostfixExpression(p.parseCall(token, []Node{}, false)) } return p.parseSecondary() } func (p *Parser) parseSecondary() Node { var node Node token := p.current switch token.Kind { case Identifier: p.next() switch token.Value { case "true": node = p.createNode(&BoolNode{Value: true}, token.Location) if node == nil { return nil } return node case "false": node = p.createNode(&BoolNode{Value: false}, token.Location) if node == nil { return nil } return node case "nil": node = p.createNode(&NilNode{}, token.Location) if node == nil { return nil } return node default: if p.current.Is(Bracket, "(") { node = p.parseCall(token, []Node{}, true) } else { node = p.createNode(&IdentifierNode{Value: token.Value}, token.Location) if node == nil { return nil } } } case Number: p.next() value := strings.Replace(token.Value, "_", "", -1) var node Node valueLower := strings.ToLower(value) switch { case strings.HasPrefix(valueLower, "0x"): number, err := strconv.ParseInt(value, 0, 64) if err != nil { p.error("invalid hex literal: %v", err) } node = p.toIntegerNode(number) case strings.ContainsAny(valueLower, ".e"): number, err := strconv.ParseFloat(value, 64) if err != nil { p.error("invalid float literal: %v", err) } node = p.toFloatNode(number) case strings.HasPrefix(valueLower, "0b"): number, err := strconv.ParseInt(value, 0, 64) if err != nil { p.error("invalid binary literal: %v", err) } node = p.toIntegerNode(number) case strings.HasPrefix(valueLower, "0o"): number, err := strconv.ParseInt(value, 0, 64) if err != nil { p.error("invalid octal literal: %v", err) } node = p.toIntegerNode(number) default: number, err := strconv.ParseInt(value, 10, 64) if err != nil { p.error("invalid integer literal: %v", err) } node = p.toIntegerNode(number) } if node != nil { node.SetLocation(token.Location) } return node case String: p.next() node = p.createNode(&StringNode{Value: token.Value}, token.Location) if node == nil { return nil } case Bytes: p.next() node = p.createNode(&BytesNode{Value: []byte(token.Value)}, token.Location) if node == nil { return nil } default: if token.Is(Bracket, "[") { node = p.parseArrayExpression(token) } else if token.Is(Bracket, "{") { node = p.parseMapExpression(token) } else { p.error("unexpected token %v", token) } } return p.parsePostfixExpression(node) } func (p *Parser) toIntegerNode(number int64) Node { if number > math.MaxInt { p.error("integer literal is too large") return nil } return p.createNode(&IntegerNode{Value: int(number)}, p.current.Location) } func (p *Parser) toFloatNode(number float64) Node { if number > math.MaxFloat64 { p.error("float literal is too large") return nil } return p.createNode(&FloatNode{Value: number}, p.current.Location) } func (p *Parser) parseCall(token Token, arguments []Node, checkOverrides bool) Node { var node Node isOverridden := false if p.config != nil { isOverridden = p.config.IsOverridden(token.Value) } isOverridden = isOverridden && checkOverrides if b, ok := predicates[token.Value]; ok && !isOverridden { p.expect(Bracket, "(") // In case of the pipe operator, the first argument is the left-hand side // of the operator, so we do not parse it as an argument inside brackets. args := b.args[len(arguments):] for i, arg := range args { if arg&optional == optional { if p.current.Is(Bracket, ")") { break } } else { if p.current.Is(Bracket, ")") { p.error("expected at least %d arguments", len(args)) } } if i > 0 { p.expect(Operator, ",") } var node Node switch { case arg&expr == expr: node = p.parseExpression(0) case arg&predicate == predicate: node = p.parsePredicate() } arguments = append(arguments, node) } // skip last comma if p.current.Is(Operator, ",") { p.next() } p.expect(Bracket, ")") node = p.createNode(&BuiltinNode{ Name: token.Value, Arguments: arguments, }, token.Location) if node == nil { return nil } } else if _, ok := builtin.Index[token.Value]; ok && (p.config == nil || !p.config.Disabled[token.Value]) && !isOverridden { node = p.createNode(&BuiltinNode{ Name: token.Value, Arguments: p.parseArguments(arguments), }, token.Location) if node == nil { return nil } } else { callee := p.createNode(&IdentifierNode{Value: token.Value}, token.Location) if callee == nil { return nil } node = p.createNode(&CallNode{ Callee: callee, Arguments: p.parseArguments(arguments), }, token.Location) if node == nil { return nil } } return node } func (p *Parser) parseArguments(arguments []Node) []Node { // If pipe operator is used, the first argument is the left-hand side // of the operator, so we do not parse it as an argument inside brackets. offset := len(arguments) p.expect(Bracket, "(") for !p.current.Is(Bracket, ")") && p.err == nil { if len(arguments) > offset { p.expect(Operator, ",") } if p.current.Is(Bracket, ")") { break } node := p.parseExpression(0) arguments = append(arguments, node) } p.expect(Bracket, ")") return arguments } func (p *Parser) parsePredicate() Node { startToken := p.current withBrackets := false if p.current.Is(Bracket, "{") { p.next() withBrackets = true } p.depth++ var node Node if withBrackets { node = p.parseSequenceExpression() } else { node = p.parseExpression(0) if p.current.Is(Operator, ";") { p.error("wrap predicate with brackets { and }") } } p.depth-- if withBrackets { p.expect(Bracket, "}") } predicateNode := p.createNode(&PredicateNode{ Node: node, }, startToken.Location) if predicateNode == nil { return nil } return predicateNode } func (p *Parser) parseArrayExpression(token Token) Node { nodes := make([]Node, 0) p.expect(Bracket, "[") for !p.current.Is(Bracket, "]") && p.err == nil { if len(nodes) > 0 { p.expect(Operator, ",") if p.current.Is(Bracket, "]") { goto end } } node := p.parseExpression(0) nodes = append(nodes, node) } end: p.expect(Bracket, "]") node := p.createNode(&ArrayNode{Nodes: nodes}, token.Location) if node == nil { return nil } return node } func (p *Parser) parseMapExpression(token Token) Node { p.expect(Bracket, "{") nodes := make([]Node, 0) for !p.current.Is(Bracket, "}") && p.err == nil { if len(nodes) > 0 { p.expect(Operator, ",") if p.current.Is(Bracket, "}") { goto end } if p.current.Is(Operator, ",") { p.error("unexpected token %v", p.current) } } var key Node // Map key can be one of: // * number // * string // * identifier, which is equivalent to a string // * expression, which must be enclosed in parentheses -- (1 + 2) if p.current.Is(Number) || p.current.Is(String) || p.current.Is(Identifier) { key = p.createNode(&StringNode{Value: p.current.Value}, p.current.Location) if key == nil { return nil } p.next() } else if p.current.Is(Bracket, "(") { key = p.parseExpression(0) } else { p.error("a map key must be a quoted string, a number, a identifier, or an expression enclosed in parentheses (unexpected token %v)", p.current) } p.expect(Operator, ":") node := p.parseExpression(0) pair := p.createNode(&PairNode{Key: key, Value: node}, token.Location) if pair == nil { return nil } nodes = append(nodes, pair) } end: p.expect(Bracket, "}") node := p.createNode(&MapNode{Pairs: nodes}, token.Location) if node == nil { return nil } return node } func (p *Parser) parsePostfixExpression(node Node) Node { postfixToken := p.current for (postfixToken.Is(Operator) || postfixToken.Is(Bracket)) && p.err == nil { optional := postfixToken.Value == "?." parseToken: if postfixToken.Value == "." || postfixToken.Value == "?." { p.next() propertyToken := p.current if optional && propertyToken.Is(Bracket, "[") { postfixToken = propertyToken goto parseToken } p.next() if propertyToken.Kind != Identifier && // Operators like "not" and "matches" are valid methods or property names. (propertyToken.Kind != Operator || !utils.IsValidIdentifier(propertyToken.Value)) { p.error("expected name") } property := p.createNode(&StringNode{Value: propertyToken.Value}, propertyToken.Location) if property == nil { return nil } chainNode, isChain := node.(*ChainNode) optional := postfixToken.Value == "?." if isChain { node = chainNode.Node } memberNode := p.createMemberNode(&MemberNode{ Node: node, Property: property, Optional: optional, }, propertyToken.Location) if memberNode == nil { return nil } if p.current.Is(Bracket, "(") { memberNode.Method = true node = p.createNode(&CallNode{ Callee: memberNode, Arguments: p.parseArguments([]Node{}), }, propertyToken.Location) if node == nil { return nil } } else { node = memberNode } if isChain || optional { node = p.createNode(&ChainNode{Node: node}, propertyToken.Location) if node == nil { return nil } } } else if postfixToken.Value == "[" { p.next() var from, to Node if p.current.Is(Operator, ":") { // slice without from [:1] p.next() if !p.current.Is(Bracket, "]") { // slice without from and to [:] to = p.parseExpression(0) } node = p.createNode(&SliceNode{ Node: node, To: to, }, postfixToken.Location) if node == nil { return nil } p.expect(Bracket, "]") } else { from = p.parseExpression(0) if p.current.Is(Operator, ":") { p.next() if !p.current.Is(Bracket, "]") { // slice without to [1:] to = p.parseExpression(0) } node = p.createNode(&SliceNode{ Node: node, From: from, To: to, }, postfixToken.Location) if node == nil { return nil } p.expect(Bracket, "]") } else { // Slice operator [:] was not found, // it should be just an index node. node = p.createNode(&MemberNode{ Node: node, Property: from, Optional: optional, }, postfixToken.Location) if node == nil { return nil } if optional { node = p.createNode(&ChainNode{Node: node}, postfixToken.Location) if node == nil { return nil } } p.expect(Bracket, "]") } } } else { break } postfixToken = p.current } return node } func (p *Parser) parseComparison(left Node, token Token, precedence int) Node { var rootNode Node for { comparator := p.parseExpression(precedence + 1) cmpNode := p.createNode(&BinaryNode{ Operator: token.Value, Left: left, Right: comparator, }, token.Location) if cmpNode == nil { return nil } if rootNode == nil { rootNode = cmpNode } else { rootNode = p.createNode(&BinaryNode{ Operator: "&&", Left: rootNode, Right: cmpNode, }, token.Location) if rootNode == nil { return nil } } left = comparator token = p.current if !(token.Is(Operator) && operator.IsComparison(token.Value) && p.err == nil) { break } p.next() } return rootNode } ================================================ FILE: parser/parser_test.go ================================================ package parser_test import ( "fmt" "strings" "testing" "github.com/expr-lang/expr/conf" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr/internal/testify/require" . "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/parser" ) func TestParse(t *testing.T) { tests := []struct { input string want Node }{ { "a", &IdentifierNode{Value: "a"}, }, { `"str"`, &StringNode{Value: "str"}, }, { "`hello\nworld`", &StringNode{Value: `hello world`}, }, { "3", &IntegerNode{Value: 3}, }, { "0xFF", &IntegerNode{Value: 255}, }, { "0x6E", &IntegerNode{Value: 110}, }, { "0X63", &IntegerNode{Value: 99}, }, { "0o600", &IntegerNode{Value: 384}, }, { "0O45", &IntegerNode{Value: 37}, }, { "0b10", &IntegerNode{Value: 2}, }, { "0B101011", &IntegerNode{Value: 43}, }, { "10_000_000", &IntegerNode{Value: 10_000_000}, }, { "2.5", &FloatNode{Value: 2.5}, }, { "1e9", &FloatNode{Value: 1e9}, }, { "true", &BoolNode{Value: true}, }, { "false", &BoolNode{Value: false}, }, { "nil", &NilNode{}, }, { `b"hello"`, &BytesNode{Value: []byte("hello")}, }, { `b'\xff\x00'`, &BytesNode{Value: []byte{255, 0}}, }, { "-3", &UnaryNode{Operator: "-", Node: &IntegerNode{Value: 3}}, }, { "-2^2", &UnaryNode{ Operator: "-", Node: &BinaryNode{ Operator: "^", Left: &IntegerNode{Value: 2}, Right: &IntegerNode{Value: 2}, }, }, }, { "1 - 2", &BinaryNode{Operator: "-", Left: &IntegerNode{Value: 1}, Right: &IntegerNode{Value: 2}}, }, { "(1 - 2) * 3", &BinaryNode{ Operator: "*", Left: &BinaryNode{ Operator: "-", Left: &IntegerNode{Value: 1}, Right: &IntegerNode{Value: 2}, }, Right: &IntegerNode{Value: 3}, }, }, { "a or b or c", &BinaryNode{Operator: "or", Left: &BinaryNode{Operator: "or", Left: &IdentifierNode{Value: "a"}, Right: &IdentifierNode{Value: "b"}}, Right: &IdentifierNode{Value: "c"}}, }, { "a or b and c", &BinaryNode{Operator: "or", Left: &IdentifierNode{Value: "a"}, Right: &BinaryNode{Operator: "and", Left: &IdentifierNode{Value: "b"}, Right: &IdentifierNode{Value: "c"}}}, }, { "(a or b) and c", &BinaryNode{Operator: "and", Left: &BinaryNode{Operator: "or", Left: &IdentifierNode{Value: "a"}, Right: &IdentifierNode{Value: "b"}}, Right: &IdentifierNode{Value: "c"}}, }, { "2**4-1", &BinaryNode{Operator: "-", Left: &BinaryNode{Operator: "**", Left: &IntegerNode{Value: 2}, Right: &IntegerNode{Value: 4}}, Right: &IntegerNode{Value: 1}}, }, { "foo(bar())", &CallNode{Callee: &IdentifierNode{Value: "foo"}, Arguments: []Node{&CallNode{Callee: &IdentifierNode{Value: "bar"}, Arguments: []Node{}}}}, }, { `foo("arg1", 2, true)`, &CallNode{Callee: &IdentifierNode{Value: "foo"}, Arguments: []Node{&StringNode{Value: "arg1"}, &IntegerNode{Value: 2}, &BoolNode{Value: true}}}, }, { "foo.bar", &MemberNode{Node: &IdentifierNode{Value: "foo"}, Property: &StringNode{Value: "bar"}}, }, { "foo['all']", &MemberNode{Node: &IdentifierNode{Value: "foo"}, Property: &StringNode{Value: "all"}}, }, { "foo.bar()", &CallNode{Callee: &MemberNode{Node: &IdentifierNode{Value: "foo"}, Property: &StringNode{Value: "bar"}, Method: true}, Arguments: []Node{}}, }, { `foo.bar("arg1", 2, true)`, &CallNode{Callee: &MemberNode{Node: &IdentifierNode{Value: "foo"}, Property: &StringNode{Value: "bar"}, Method: true}, Arguments: []Node{&StringNode{Value: "arg1"}, &IntegerNode{Value: 2}, &BoolNode{Value: true}}}, }, { "foo[3]", &MemberNode{Node: &IdentifierNode{Value: "foo"}, Property: &IntegerNode{Value: 3}}, }, { "true ? true : false", &ConditionalNode{ Ternary: true, Cond: &BoolNode{Value: true}, Exp1: &BoolNode{Value: true}, Exp2: &BoolNode{}}, }, { "a?[b]:c", &ConditionalNode{ Ternary: true, Cond: &IdentifierNode{Value: "a"}, Exp1: &ArrayNode{Nodes: []Node{&IdentifierNode{Value: "b"}}}, Exp2: &IdentifierNode{Value: "c"}}, }, { "a.b().c().d[33]", &MemberNode{ Node: &MemberNode{ Node: &CallNode{ Callee: &MemberNode{ Node: &CallNode{ Callee: &MemberNode{ Node: &IdentifierNode{ Value: "a", }, Property: &StringNode{ Value: "b", }, Method: true, }, Arguments: []Node{}, }, Property: &StringNode{ Value: "c", }, Method: true, }, Arguments: []Node{}, }, Property: &StringNode{ Value: "d", }, }, Property: &IntegerNode{Value: 33}}, }, { "'a' == 'b'", &BinaryNode{Operator: "==", Left: &StringNode{Value: "a"}, Right: &StringNode{Value: "b"}}, }, { "+0 != -0", &BinaryNode{Operator: "!=", Left: &UnaryNode{Operator: "+", Node: &IntegerNode{}}, Right: &UnaryNode{Operator: "-", Node: &IntegerNode{}}}, }, { "[a, b, c]", &ArrayNode{Nodes: []Node{&IdentifierNode{Value: "a"}, &IdentifierNode{Value: "b"}, &IdentifierNode{Value: "c"}}}, }, { "{foo:1, bar:2}", &MapNode{Pairs: []Node{&PairNode{Key: &StringNode{Value: "foo"}, Value: &IntegerNode{Value: 1}}, &PairNode{Key: &StringNode{Value: "bar"}, Value: &IntegerNode{Value: 2}}}}, }, { "{foo:1, bar:2, }", &MapNode{Pairs: []Node{&PairNode{Key: &StringNode{Value: "foo"}, Value: &IntegerNode{Value: 1}}, &PairNode{Key: &StringNode{Value: "bar"}, Value: &IntegerNode{Value: 2}}}}, }, { `{"a": 1, 'b': 2}`, &MapNode{Pairs: []Node{&PairNode{Key: &StringNode{Value: "a"}, Value: &IntegerNode{Value: 1}}, &PairNode{Key: &StringNode{Value: "b"}, Value: &IntegerNode{Value: 2}}}}, }, { "[1].foo", &MemberNode{Node: &ArrayNode{Nodes: []Node{&IntegerNode{Value: 1}}}, Property: &StringNode{Value: "foo"}}, }, { "{foo:1}.bar", &MemberNode{Node: &MapNode{Pairs: []Node{&PairNode{Key: &StringNode{Value: "foo"}, Value: &IntegerNode{Value: 1}}}}, Property: &StringNode{Value: "bar"}}, }, { "len(foo)", &BuiltinNode{ Name: "len", Arguments: []Node{ &IdentifierNode{Value: "foo"}, }, }, }, { `foo matches "foo"`, &BinaryNode{ Operator: "matches", Left: &IdentifierNode{Value: "foo"}, Right: &StringNode{Value: "foo"}}, }, { `foo not matches "foo"`, &UnaryNode{ Operator: "not", Node: &BinaryNode{ Operator: "matches", Left: &IdentifierNode{Value: "foo"}, Right: &StringNode{Value: "foo"}}}, }, { `foo matches regex`, &BinaryNode{ Operator: "matches", Left: &IdentifierNode{Value: "foo"}, Right: &IdentifierNode{Value: "regex"}}, }, { `foo contains "foo"`, &BinaryNode{ Operator: "contains", Left: &IdentifierNode{Value: "foo"}, Right: &StringNode{Value: "foo"}}, }, { `foo not contains "foo"`, &UnaryNode{ Operator: "not", Node: &BinaryNode{Operator: "contains", Left: &IdentifierNode{Value: "foo"}, Right: &StringNode{Value: "foo"}}}, }, { `foo startsWith "foo"`, &BinaryNode{Operator: "startsWith", Left: &IdentifierNode{Value: "foo"}, Right: &StringNode{Value: "foo"}}, }, { `foo endsWith "foo"`, &BinaryNode{Operator: "endsWith", Left: &IdentifierNode{Value: "foo"}, Right: &StringNode{Value: "foo"}}, }, { "1..9", &BinaryNode{Operator: "..", Left: &IntegerNode{Value: 1}, Right: &IntegerNode{Value: 9}}, }, { "0 in []", &BinaryNode{Operator: "in", Left: &IntegerNode{}, Right: &ArrayNode{Nodes: []Node{}}}, }, { "not in_var", &UnaryNode{Operator: "not", Node: &IdentifierNode{Value: "in_var"}}, }, { "-1 not in [1, 2, 3, 4]", &UnaryNode{Operator: "not", Node: &BinaryNode{Operator: "in", Left: &UnaryNode{Operator: "-", Node: &IntegerNode{Value: 1}}, Right: &ArrayNode{Nodes: []Node{ &IntegerNode{Value: 1}, &IntegerNode{Value: 2}, &IntegerNode{Value: 3}, &IntegerNode{Value: 4}, }}}}, }, { "1*8 not in [1, 2, 3, 4]", &UnaryNode{Operator: "not", Node: &BinaryNode{Operator: "in", Left: &BinaryNode{Operator: "*", Left: &IntegerNode{Value: 1}, Right: &IntegerNode{Value: 8}, }, Right: &ArrayNode{Nodes: []Node{ &IntegerNode{Value: 1}, &IntegerNode{Value: 2}, &IntegerNode{Value: 3}, &IntegerNode{Value: 4}, }}}}, }, { "2==2 ? false : 3 not in [1, 2, 5]", &ConditionalNode{ Ternary: true, Cond: &BinaryNode{ Operator: "==", Left: &IntegerNode{Value: 2}, Right: &IntegerNode{Value: 2}, }, Exp1: &BoolNode{Value: false}, Exp2: &UnaryNode{ Operator: "not", Node: &BinaryNode{ Operator: "in", Left: &IntegerNode{Value: 3}, Right: &ArrayNode{Nodes: []Node{ &IntegerNode{Value: 1}, &IntegerNode{Value: 2}, &IntegerNode{Value: 5}, }}}}}, }, { "'foo' + 'bar' not matches 'foobar'", &UnaryNode{Operator: "not", Node: &BinaryNode{Operator: "matches", Left: &BinaryNode{Operator: "+", Left: &StringNode{Value: "foo"}, Right: &StringNode{Value: "bar"}}, Right: &StringNode{Value: "foobar"}}}, }, { "all(Tickets, #)", &BuiltinNode{ Name: "all", Arguments: []Node{ &IdentifierNode{Value: "Tickets"}, &PredicateNode{ Node: &PointerNode{}, }}}, }, { "all(Tickets, {.Price > 0})", &BuiltinNode{ Name: "all", Arguments: []Node{ &IdentifierNode{Value: "Tickets"}, &PredicateNode{ Node: &BinaryNode{ Operator: ">", Left: &MemberNode{Node: &PointerNode{}, Property: &StringNode{Value: "Price"}}, Right: &IntegerNode{Value: 0}}}}}, }, { "one(Tickets, {#.Price > 0})", &BuiltinNode{ Name: "one", Arguments: []Node{ &IdentifierNode{Value: "Tickets"}, &PredicateNode{ Node: &BinaryNode{ Operator: ">", Left: &MemberNode{ Node: &PointerNode{}, Property: &StringNode{Value: "Price"}, }, Right: &IntegerNode{Value: 0}}}}}, }, { "filter(Prices, {# > 100})", &BuiltinNode{Name: "filter", Arguments: []Node{&IdentifierNode{Value: "Prices"}, &PredicateNode{Node: &BinaryNode{Operator: ">", Left: &PointerNode{}, Right: &IntegerNode{Value: 100}}}}}, }, { "array[1:2]", &SliceNode{Node: &IdentifierNode{Value: "array"}, From: &IntegerNode{Value: 1}, To: &IntegerNode{Value: 2}}, }, { "array[:2]", &SliceNode{Node: &IdentifierNode{Value: "array"}, To: &IntegerNode{Value: 2}}, }, { "array[1:]", &SliceNode{Node: &IdentifierNode{Value: "array"}, From: &IntegerNode{Value: 1}}, }, { "array[:]", &SliceNode{Node: &IdentifierNode{Value: "array"}}, }, { "[]", &ArrayNode{}, }, { "foo ?? bar", &BinaryNode{Operator: "??", Left: &IdentifierNode{Value: "foo"}, Right: &IdentifierNode{Value: "bar"}}, }, { "foo ?? bar ?? baz", &BinaryNode{Operator: "??", Left: &BinaryNode{Operator: "??", Left: &IdentifierNode{Value: "foo"}, Right: &IdentifierNode{Value: "bar"}}, Right: &IdentifierNode{Value: "baz"}}, }, { "foo ?? (bar || baz)", &BinaryNode{Operator: "??", Left: &IdentifierNode{Value: "foo"}, Right: &BinaryNode{Operator: "||", Left: &IdentifierNode{Value: "bar"}, Right: &IdentifierNode{Value: "baz"}}}, }, { "foo || bar ?? baz", &BinaryNode{Operator: "||", Left: &IdentifierNode{Value: "foo"}, Right: &BinaryNode{Operator: "??", Left: &IdentifierNode{Value: "bar"}, Right: &IdentifierNode{Value: "baz"}}}, }, { "foo ?? bar()", &BinaryNode{Operator: "??", Left: &IdentifierNode{Value: "foo"}, Right: &CallNode{Callee: &IdentifierNode{Value: "bar"}}}, }, { "true | ok()", &CallNode{ Callee: &IdentifierNode{Value: "ok"}, Arguments: []Node{ &BoolNode{Value: true}}}}, { `let foo = a + b; foo + c`, &VariableDeclaratorNode{ Name: "foo", Value: &BinaryNode{Operator: "+", Left: &IdentifierNode{Value: "a"}, Right: &IdentifierNode{Value: "b"}}, Expr: &BinaryNode{Operator: "+", Left: &IdentifierNode{Value: "foo"}, Right: &IdentifierNode{Value: "c"}}}, }, { `map([], #index)`, &BuiltinNode{ Name: "map", Arguments: []Node{ &ArrayNode{}, &PredicateNode{ Node: &PointerNode{Name: "index"}, }, }, }, }, { `::split("a,b,c", ",")`, &BuiltinNode{ Name: "split", Arguments: []Node{ &StringNode{Value: "a,b,c"}, &StringNode{Value: ","}, }, }, }, { `::split("a,b,c", ",")[0]`, &MemberNode{ Node: &BuiltinNode{ Name: "split", Arguments: []Node{ &StringNode{Value: "a,b,c"}, &StringNode{Value: ","}, }, }, Property: &IntegerNode{Value: 0}, }, }, { `"hello"[1:3]`, &SliceNode{ Node: &StringNode{Value: "hello"}, From: &IntegerNode{Value: 1}, To: &IntegerNode{Value: 3}, }, }, { `1 < 2 > 3`, &BinaryNode{ Operator: "&&", Left: &BinaryNode{ Operator: "<", Left: &IntegerNode{Value: 1}, Right: &IntegerNode{Value: 2}, }, Right: &BinaryNode{ Operator: ">", Left: &IntegerNode{Value: 2}, Right: &IntegerNode{Value: 3}, }, }, }, { `1 < 2 < 3 < 4`, &BinaryNode{ Operator: "&&", Left: &BinaryNode{ Operator: "&&", Left: &BinaryNode{ Operator: "<", Left: &IntegerNode{Value: 1}, Right: &IntegerNode{Value: 2}, }, Right: &BinaryNode{ Operator: "<", Left: &IntegerNode{Value: 2}, Right: &IntegerNode{Value: 3}, }, }, Right: &BinaryNode{ Operator: "<", Left: &IntegerNode{Value: 3}, Right: &IntegerNode{Value: 4}, }, }, }, { `1 < 2 < 3 == true`, &BinaryNode{ Operator: "==", Left: &BinaryNode{ Operator: "&&", Left: &BinaryNode{ Operator: "<", Left: &IntegerNode{Value: 1}, Right: &IntegerNode{Value: 2}, }, Right: &BinaryNode{ Operator: "<", Left: &IntegerNode{Value: 2}, Right: &IntegerNode{Value: 3}, }, }, Right: &BoolNode{Value: true}, }, }, { "if a>b {true} else {x}", &ConditionalNode{ Cond: &BinaryNode{ Operator: ">", Left: &IdentifierNode{Value: "a"}, Right: &IdentifierNode{Value: "b"}, }, Exp1: &BoolNode{Value: true}, Exp2: &IdentifierNode{Value: "x"}}, }, { "if a { 1 } else if b { 2 } else { 3 }", &ConditionalNode{ Cond: &IdentifierNode{Value: "a"}, Exp1: &IntegerNode{Value: 1}, Exp2: &ConditionalNode{ Cond: &IdentifierNode{Value: "b"}, Exp1: &IntegerNode{Value: 2}, Exp2: &IntegerNode{Value: 3}}}, }, { "if a { 1 } else if b { 2 } else if c { 3 } else { 4 }", &ConditionalNode{ Cond: &IdentifierNode{Value: "a"}, Exp1: &IntegerNode{Value: 1}, Exp2: &ConditionalNode{ Cond: &IdentifierNode{Value: "b"}, Exp1: &IntegerNode{Value: 2}, Exp2: &ConditionalNode{ Cond: &IdentifierNode{Value: "c"}, Exp1: &IntegerNode{Value: 3}, Exp2: &IntegerNode{Value: 4}}}}, }, { "1; 2; 3", &SequenceNode{ Nodes: []Node{ &IntegerNode{Value: 1}, &IntegerNode{Value: 2}, &IntegerNode{Value: 3}, }, }, }, { "1; (2; 3)", &SequenceNode{ Nodes: []Node{ &IntegerNode{Value: 1}, &SequenceNode{ Nodes: []Node{ &IntegerNode{Value: 2}, &IntegerNode{Value: 3}}, }, }, }, }, { "true ? 1 : 2; 3 ; 4", &SequenceNode{ Nodes: []Node{ &ConditionalNode{ Ternary: true, Cond: &BoolNode{Value: true}, Exp1: &IntegerNode{Value: 1}, Exp2: &IntegerNode{Value: 2}}, &IntegerNode{Value: 3}, &IntegerNode{Value: 4}, }, }, }, { "true ? 1 : ( 2; 3; 4 )", &ConditionalNode{ Ternary: true, Cond: &BoolNode{Value: true}, Exp1: &IntegerNode{Value: 1}, Exp2: &SequenceNode{ Nodes: []Node{ &IntegerNode{Value: 2}, &IntegerNode{Value: 3}, &IntegerNode{Value: 4}, }, }, }, }, { "true ?: 1; 2; 3", &SequenceNode{ Nodes: []Node{ &ConditionalNode{ Ternary: true, Cond: &BoolNode{Value: true}, Exp1: &BoolNode{Value: true}, Exp2: &IntegerNode{Value: 1}}, &IntegerNode{Value: 2}, &IntegerNode{Value: 3}, }, }, }, { `let x = true ? 1 : 2; x`, &VariableDeclaratorNode{ Name: "x", Value: &ConditionalNode{ Ternary: true, Cond: &BoolNode{Value: true}, Exp1: &IntegerNode{Value: 1}, Exp2: &IntegerNode{Value: 2}}, Expr: &IdentifierNode{Value: "x"}}, }, { "let x = true ? 1 : ( 2; 3; 4 ); x", &VariableDeclaratorNode{ Name: "x", Value: &ConditionalNode{ Ternary: true, Cond: &BoolNode{Value: true}, Exp1: &IntegerNode{Value: 1}, Exp2: &SequenceNode{ Nodes: []Node{ &IntegerNode{Value: 2}, &IntegerNode{Value: 3}, &IntegerNode{Value: 4}, }, }, }, Expr: &IdentifierNode{Value: "x"}}, }, { "if true { 1; 2; 3 } else { 4; 5; 6 }", &ConditionalNode{ Cond: &BoolNode{Value: true}, Exp1: &SequenceNode{ Nodes: []Node{ &IntegerNode{Value: 1}, &IntegerNode{Value: 2}, &IntegerNode{Value: 3}}}, Exp2: &SequenceNode{ Nodes: []Node{ &IntegerNode{Value: 4}, &IntegerNode{Value: 5}, &IntegerNode{Value: 6}}}, }, }, { `all(ls, if true { 1 } else { 2 })`, &BuiltinNode{ Name: "all", Arguments: []Node{ &IdentifierNode{Value: "ls"}, &PredicateNode{ Node: &ConditionalNode{ Cond: &BoolNode{Value: true}, Exp1: &IntegerNode{Value: 1}, Exp2: &IntegerNode{Value: 2}, }}}}, }, { `let x = if true { 1 } else { 2 }; x`, &VariableDeclaratorNode{ Name: "x", Value: &ConditionalNode{ Cond: &BoolNode{Value: true}, Exp1: &IntegerNode{Value: 1}, Exp2: &IntegerNode{Value: 2}, }, Expr: &IdentifierNode{Value: "x"}}, }, { `call(if true { 1 } else { 2 })`, &CallNode{ Callee: &IdentifierNode{Value: "call"}, Arguments: []Node{ &ConditionalNode{ Cond: &BoolNode{Value: true}, Exp1: &IntegerNode{Value: 1}, Exp2: &IntegerNode{Value: 2}, }}}, }, { `[if true { 1 } else { 2 }]`, &ArrayNode{ Nodes: []Node{ &ConditionalNode{ Cond: &BoolNode{Value: true}, Exp1: &IntegerNode{Value: 1}, Exp2: &IntegerNode{Value: 2}, }}}, }, { `map(ls, { 1; 2; 3 })`, &BuiltinNode{ Name: "map", Arguments: []Node{ &IdentifierNode{Value: "ls"}, &PredicateNode{ Node: &SequenceNode{ Nodes: []Node{ &IntegerNode{Value: 1}, &IntegerNode{Value: 2}, &IntegerNode{Value: 3}, }, }, }, }}, }, { `let x = 1; 2; 3 + x`, &VariableDeclaratorNode{ Name: "x", Value: &IntegerNode{Value: 1}, Expr: &SequenceNode{ Nodes: []Node{ &IntegerNode{Value: 2}, &BinaryNode{ Operator: "+", Left: &IntegerNode{Value: 3}, Right: &IdentifierNode{Value: "x"}, }, }, }, }, }, { `let x = 1; let y = 2; 3; 4; x + y`, &VariableDeclaratorNode{ Name: "x", Value: &IntegerNode{Value: 1}, Expr: &VariableDeclaratorNode{ Name: "y", Value: &IntegerNode{Value: 2}, Expr: &SequenceNode{ Nodes: []Node{ &IntegerNode{Value: 3}, &IntegerNode{Value: 4}, &BinaryNode{ Operator: "+", Left: &IdentifierNode{Value: "x"}, Right: &IdentifierNode{Value: "y"}, }, }, }}}, }, { `let x = (1; 2; 3); x`, &VariableDeclaratorNode{ Name: "x", Value: &SequenceNode{ Nodes: []Node{ &IntegerNode{Value: 1}, &IntegerNode{Value: 2}, &IntegerNode{Value: 3}, }, }, Expr: &IdentifierNode{Value: "x"}, }, }, { `all( [ true, false, ], #, )`, &BuiltinNode{ Name: "all", Arguments: []Node{ &ArrayNode{ Nodes: []Node{ &BoolNode{Value: true}, &BoolNode{Value: false}, }, }, &PredicateNode{ Node: &PointerNode{}, }, }, }, }, { `list | all(#,)`, &BuiltinNode{ Name: "all", Arguments: []Node{ &IdentifierNode{Value: "list"}, &PredicateNode{ Node: &PointerNode{}, }, }, }, }, { `func( parameter1, parameter2, )`, &CallNode{ Callee: &IdentifierNode{Value: "func"}, Arguments: []Node{ &IdentifierNode{Value: "parameter1"}, &IdentifierNode{Value: "parameter2"}, }, }, }, } for _, test := range tests { t.Run(test.input, func(t *testing.T) { actual, err := parser.Parse(test.input) require.NoError(t, err) assert.Equal(t, Dump(test.want), Dump(actual.Node)) }) } } func TestParse_error(t *testing.T) { var tests = []struct { input string err string }{ {`foo.`, `unexpected end of expression (1:4) | foo. | ...^`}, {`a+`, `unexpected token EOF (1:2) | a+ | .^`}, {`a ? (1+2) c`, `unexpected token Identifier("c") (1:11) | a ? (1+2) c | ..........^`}, {`[a b]`, `unexpected token Identifier("b") (1:4) | [a b] | ...^`}, {`foo.bar(a b)`, `unexpected token Identifier("b") (1:11) | foo.bar(a b) | ..........^`}, {`{-}`, `a map key must be a quoted string, a number, a identifier, or an expression enclosed in parentheses (unexpected token Operator("-")) (1:2) | {-} | .^`}, {`foo({.bar})`, `a map key must be a quoted string, a number, a identifier, or an expression enclosed in parentheses (unexpected token Operator(".")) (1:6) | foo({.bar}) | .....^`}, {`[1, 2, 3,,]`, `unexpected token Operator(",") (1:10) | [1, 2, 3,,] | .........^`}, {`[,]`, `unexpected token Operator(",") (1:2) | [,] | .^`}, {`{,}`, `a map key must be a quoted string, a number, a identifier, or an expression enclosed in parentheses (unexpected token Operator(",")) (1:2) | {,} | .^`}, {`{foo:1, bar:2, ,}`, `unexpected token Operator(",") (1:16) | {foo:1, bar:2, ,} | ...............^`}, {`foo ?? bar || baz`, `Operator (||) and coalesce expressions (??) cannot be mixed. Wrap either by parentheses. (1:12) | foo ?? bar || baz | ...........^`}, {`0b15`, `bad number syntax: "0b15" (1:4) | 0b15 | ...^`}, {`0X10G`, `bad number syntax: "0X10G" (1:5) | 0X10G | ....^`}, {`0o1E`, `invalid float literal: strconv.ParseFloat: parsing "0o1E": invalid syntax (1:4) | 0o1E | ...^`}, {`0b1E`, `invalid float literal: strconv.ParseFloat: parsing "0b1E": invalid syntax (1:4) | 0b1E | ...^`}, {`0b1E+6`, `bad number syntax: "0b1E+6" (1:6) | 0b1E+6 | .....^`}, {`0b1E+1`, `invalid float literal: strconv.ParseFloat: parsing "0b1E+1": invalid syntax (1:6) | 0b1E+1 | .....^`}, {`0o1E+1`, `invalid float literal: strconv.ParseFloat: parsing "0o1E+1": invalid syntax (1:6) | 0o1E+1 | .....^`}, {`1E`, `invalid float literal: strconv.ParseFloat: parsing "1E": invalid syntax (1:2) | 1E | .^`}, {`1 not == [1, 2, 5]`, `unexpected token Operator("==") (1:7) | 1 not == [1, 2, 5] | ......^`}, {`foo(1; 2; 3)`, `unexpected token Operator(";") (1:6) | foo(1; 2; 3) | .....^`}, { `map(ls, 1; 2; 3)`, `wrap predicate with brackets { and } (1:10) | map(ls, 1; 2; 3) | .........^`, }, { `[1; 2; 3]`, `unexpected token Operator(";") (1:3) | [1; 2; 3] | ..^`, }, { `1 + if true { 2 } else { 3 }`, `unexpected token Operator("if") (1:5) | 1 + if true { 2 } else { 3 } | ....^`, }, { `if a { 1 } else b`, `unexpected token Identifier("b") (1:17) | if a { 1 } else b | ................^`, }, { `list | all(#,,)`, `unexpected token Operator(",") (1:14) | list | all(#,,) | .............^`, }, } for _, test := range tests { t.Run(test.input, func(t *testing.T) { _, err := parser.Parse(test.input) if err == nil { err = fmt.Errorf("") } assert.Equal(t, test.err, err.Error(), test.input) }) } } func TestParse_optional_chaining(t *testing.T) { parseTests := []struct { input string expected Node }{ { "foo?.bar.baz", &ChainNode{ Node: &MemberNode{ Node: &MemberNode{ Node: &IdentifierNode{Value: "foo"}, Property: &StringNode{Value: "bar"}, Optional: true, }, Property: &StringNode{Value: "baz"}, }, }, }, { "foo.bar?.baz", &ChainNode{ Node: &MemberNode{ Node: &MemberNode{ Node: &IdentifierNode{Value: "foo"}, Property: &StringNode{Value: "bar"}, }, Property: &StringNode{Value: "baz"}, Optional: true, }, }, }, { "foo?.bar?.baz", &ChainNode{ Node: &MemberNode{ Node: &MemberNode{ Node: &IdentifierNode{Value: "foo"}, Property: &StringNode{Value: "bar"}, Optional: true, }, Property: &StringNode{Value: "baz"}, Optional: true, }, }, }, { "!foo?.bar.baz", &UnaryNode{ Operator: "!", Node: &ChainNode{ Node: &MemberNode{ Node: &MemberNode{ Node: &IdentifierNode{Value: "foo"}, Property: &StringNode{Value: "bar"}, Optional: true, }, Property: &StringNode{Value: "baz"}, }, }, }, }, { "foo.bar[a?.b]?.baz", &ChainNode{ Node: &MemberNode{ Node: &MemberNode{ Node: &MemberNode{ Node: &IdentifierNode{Value: "foo"}, Property: &StringNode{Value: "bar"}, }, Property: &ChainNode{ Node: &MemberNode{ Node: &IdentifierNode{Value: "a"}, Property: &StringNode{Value: "b"}, Optional: true, }, }, }, Property: &StringNode{Value: "baz"}, Optional: true, }, }, }, { "foo.bar?.[0]", &ChainNode{ Node: &MemberNode{ Node: &MemberNode{ Node: &IdentifierNode{Value: "foo"}, Property: &StringNode{Value: "bar"}, }, Property: &IntegerNode{Value: 0}, Optional: true, }, }, }, } for _, test := range parseTests { actual, err := parser.Parse(test.input) if err != nil { t.Errorf("%s:\n%v", test.input, err) continue } assert.Equal(t, Dump(test.expected), Dump(actual.Node), test.input) } } func TestParse_pipe_operator(t *testing.T) { input := "arr | map(.foo) | len() | Foo()" expect := &CallNode{ Callee: &IdentifierNode{Value: "Foo"}, Arguments: []Node{ &BuiltinNode{ Name: "len", Arguments: []Node{ &BuiltinNode{ Name: "map", Arguments: []Node{ &IdentifierNode{Value: "arr"}, &PredicateNode{ Node: &MemberNode{ Node: &PointerNode{}, Property: &StringNode{Value: "foo"}, }}}}}}}} actual, err := parser.Parse(input) require.NoError(t, err) assert.Equal(t, Dump(expect), Dump(actual.Node)) } func TestNodeBudget(t *testing.T) { tests := []struct { name string expr string maxNodes uint shouldError bool }{ { name: "simple expression equal to limit", expr: "a + b", maxNodes: 3, shouldError: false, }, { name: "medium expression under limit", expr: "a + b * c / d", maxNodes: 20, shouldError: false, }, { name: "deeply nested expression over limit", expr: "1 + (2 + (3 + (4 + (5 + (6 + (7 + 8))))))", maxNodes: 10, shouldError: true, }, { name: "array expression over limit", expr: "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]", maxNodes: 5, shouldError: true, }, { name: "disabled node budget", expr: "1 + (2 + (3 + (4 + (5 + (6 + (7 + 8))))))", maxNodes: 0, shouldError: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { config := conf.CreateNew() config.MaxNodes = tt.maxNodes config.Disabled = make(map[string]bool, 0) _, err := parser.ParseWithConfig(tt.expr, config) hasError := err != nil && strings.Contains(err.Error(), "exceeds maximum allowed nodes") if hasError != tt.shouldError { t.Errorf("ParseWithConfig(%q) error = %v, shouldError %v", tt.expr, err, tt.shouldError) } // Verify error message format when expected if tt.shouldError && err != nil { expected := "compilation failed: expression exceeds maximum allowed nodes" if !strings.Contains(err.Error(), expected) { t.Errorf("Expected error message to contain %q, got %q", expected, err.Error()) } } }) } } func TestNodeBudgetDisabled(t *testing.T) { config := conf.CreateNew() config.MaxNodes = 0 // Disable node budget expr := strings.Repeat("a + ", 1000) + "b" _, err := parser.ParseWithConfig(expr, config) if err != nil && strings.Contains(err.Error(), "exceeds maximum allowed nodes") { t.Error("Node budget check should be disabled when MaxNodes is 0") } } ================================================ FILE: parser/utils/utils.go ================================================ package utils import ( "unicode" "unicode/utf8" ) func IsValidIdentifier(str string) bool { if len(str) == 0 { return false } h, w := utf8.DecodeRuneInString(str) if !IsAlphabetic(h) { return false } for _, r := range str[w:] { if !IsAlphaNumeric(r) { return false } } return true } func IsSpace(r rune) bool { return unicode.IsSpace(r) } func IsAlphaNumeric(r rune) bool { return IsAlphabetic(r) || unicode.IsDigit(r) } func IsAlphabetic(r rune) bool { return r == '_' || r == '$' || unicode.IsLetter(r) } ================================================ FILE: patcher/operator_override.go ================================================ package patcher import ( "fmt" "reflect" "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/builtin" "github.com/expr-lang/expr/checker/nature" "github.com/expr-lang/expr/conf" ) type OperatorOverloading struct { Operator string // Operator token to overload. Overloads []string // List of function names to replace operator with. Env *nature.Nature // Env type. Functions conf.FunctionsTable // Env functions. applied bool // Flag to indicate if any changes were made to the tree. NtCache *nature.Cache } func (p *OperatorOverloading) Visit(node *ast.Node) { binaryNode, ok := (*node).(*ast.BinaryNode) if !ok { return } if binaryNode.Operator != p.Operator { return } leftType := binaryNode.Left.Type() rightType := binaryNode.Right.Type() ret, fn, ok := p.FindSuitableOperatorOverload(leftType, rightType) if ok { newNode := &ast.CallNode{ Callee: &ast.IdentifierNode{Value: fn}, Arguments: []ast.Node{binaryNode.Left, binaryNode.Right}, } newNode.SetType(ret) ast.Patch(node, newNode) p.applied = true } } // Tracking must be reset before every walk over the AST tree func (p *OperatorOverloading) Reset() { p.applied = false } func (p *OperatorOverloading) ShouldRepeat() bool { return p.applied } func (p *OperatorOverloading) FindSuitableOperatorOverload(l, r reflect.Type) (reflect.Type, string, bool) { t, fn, ok := p.findSuitableOperatorOverloadInFunctions(l, r) if !ok { t, fn, ok = p.findSuitableOperatorOverloadInTypes(l, r) } return t, fn, ok } func (p *OperatorOverloading) findSuitableOperatorOverloadInTypes(l, r reflect.Type) (reflect.Type, string, bool) { for _, fn := range p.Overloads { fnType, ok := p.Env.Get(p.NtCache, fn) if !ok { continue } firstInIndex := 0 if fnType.Method { firstInIndex = 1 // As first argument to method is receiver. } ret, done := checkTypeSuits(fnType.Type, l, r, firstInIndex) if done { return ret, fn, true } } return nil, "", false } func (p *OperatorOverloading) findSuitableOperatorOverloadInFunctions(l, r reflect.Type) (reflect.Type, string, bool) { for _, fn := range p.Overloads { fnType, ok := p.Functions[fn] if !ok { continue } firstInIndex := 0 for _, overload := range fnType.Types { ret, done := checkTypeSuits(overload, l, r, firstInIndex) if done { return ret, fn, true } } } return nil, "", false } func checkTypeSuits(t reflect.Type, l reflect.Type, r reflect.Type, firstInIndex int) (reflect.Type, bool) { firstArgType := t.In(firstInIndex) secondArgType := t.In(firstInIndex + 1) firstArgumentFit := l == firstArgType || (firstArgType.Kind() == reflect.Interface && (l == nil || l.Implements(firstArgType))) secondArgumentFit := r == secondArgType || (secondArgType.Kind() == reflect.Interface && (r == nil || r.Implements(secondArgType))) if firstArgumentFit && secondArgumentFit { return t.Out(0), true } return nil, false } func (p *OperatorOverloading) Check() { for _, fn := range p.Overloads { fnType, foundType := p.Env.Get(p.NtCache, fn) fnFunc, foundFunc := p.Functions[fn] if !foundFunc && (!foundType || fnType.Type.Kind() != reflect.Func) { panic(fmt.Errorf("function %s for %s operator does not exist in the environment", fn, p.Operator)) } if foundType { checkType(fnType, fn, p.Operator) } if foundFunc { checkFunc(fnFunc, fn, p.Operator) } } } func checkType(fnType nature.Nature, fn string, operator string) { requiredNumIn := 2 if fnType.Method { requiredNumIn = 3 // As first argument of method is receiver. } if fnType.Type.NumIn() != requiredNumIn || fnType.Type.NumOut() != 1 { panic(fmt.Errorf("function %s for %s operator does not have a correct signature", fn, operator)) } } func checkFunc(fn *builtin.Function, name string, operator string) { if len(fn.Types) == 0 { panic(fmt.Errorf("function %q for %q operator misses types", name, operator)) } for _, t := range fn.Types { if t.NumIn() != 2 || t.NumOut() != 1 { panic(fmt.Errorf("function %q for %q operator does not have a correct signature", name, operator)) } } } ================================================ FILE: patcher/value/bench_test.go ================================================ package value import ( "testing" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr" "github.com/expr-lang/expr/vm" ) func Benchmark_valueAdd(b *testing.B) { env := make(map[string]any) env["ValueOne"] = &customInt{1} env["ValueTwo"] = &customInt{2} program, err := expr.Compile("ValueOne + ValueTwo", expr.Env(env), ValueGetter) require.NoError(b, err) var out any v := vm.VM{} b.ResetTimer() for n := 0; n < b.N; n++ { out, err = v.Run(program, env) } b.StopTimer() require.NoError(b, err) require.Equal(b, 3, out.(int)) } func Benchmark_valueUntypedAdd(b *testing.B) { env := make(map[string]any) env["ValueOne"] = &customUntypedInt{1} env["ValueTwo"] = &customUntypedInt{2} program, err := expr.Compile("ValueOne + ValueTwo", expr.Env(env), ValueGetter) require.NoError(b, err) var out any v := vm.VM{} b.ResetTimer() for n := 0; n < b.N; n++ { out, err = v.Run(program, env) } b.StopTimer() require.NoError(b, err) require.Equal(b, 3, out.(int)) } func Benchmark_valueTypedAdd(b *testing.B) { env := make(map[string]any) env["ValueOne"] = &customTypedInt{1} env["ValueTwo"] = &customTypedInt{2} program, err := expr.Compile("ValueOne + ValueTwo", expr.Env(env), ValueGetter) require.NoError(b, err) var out any v := vm.VM{} b.ResetTimer() for n := 0; n < b.N; n++ { out, err = v.Run(program, env) } b.StopTimer() require.NoError(b, err) require.Equal(b, 3, out.(int)) } ================================================ FILE: patcher/value/value.go ================================================ // Package value provides a Patcher that uses interfaces to allow custom types that can be represented as standard go values to be used more easily in expressions. package value import ( "reflect" "time" "github.com/expr-lang/expr" "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/conf" ) // ValueGetter is a Patcher that allows custom types to be represented as standard go values for use with expr. // It also adds the `$patcher_value_getter` function to the program for efficiently calling matching interfaces. // // The purpose of this Patcher is to make it seamless to use custom types in expressions without the need to // first convert them to standard go values. It may also facilitate using already existing structs or maps as // environments when they contain compatible types. // // An example usage may be modeling a database record with columns that have varying data types and constraints. // In such an example you may have custom types that, beyond storing a simple value, such as an integer, may // contain metadata such as column type and if a value is specifically a NULL value. // // Use it directly as an Option to expr.Compile() var ValueGetter = expr.Option(func(c *conf.Config) { c.Visitors = append(c.Visitors, patcher{}) getValueFunc(c) }) // A AnyValuer provides a generic function for a custom type to return standard go values. // It allows for returning a `nil` value but does not provide any type checking at expression compile. // // A custom type may implement both AnyValuer and a type specific interface to enable both // compile time checking and the ability to return a `nil` value. type AnyValuer interface { AsAny() any } type IntValuer interface { AsInt() int } type BoolValuer interface { AsBool() bool } type Int8Valuer interface { AsInt8() int8 } type Int16Valuer interface { AsInt16() int16 } type Int32Valuer interface { AsInt32() int32 } type Int64Valuer interface { AsInt64() int64 } type UintValuer interface { AsUint() uint } type Uint8Valuer interface { AsUint8() uint8 } type Uint16Valuer interface { AsUint16() uint16 } type Uint32Valuer interface { AsUint32() uint32 } type Uint64Valuer interface { AsUint64() uint64 } type Float32Valuer interface { AsFloat32() float32 } type Float64Valuer interface { AsFloat64() float64 } type StringValuer interface { AsString() string } type TimeValuer interface { AsTime() time.Time } type DurationValuer interface { AsDuration() time.Duration } type ArrayValuer interface { AsArray() []any } type MapValuer interface { AsMap() map[string]any } var supportedInterfaces = []reflect.Type{ reflect.TypeOf((*AnyValuer)(nil)).Elem(), reflect.TypeOf((*BoolValuer)(nil)).Elem(), reflect.TypeOf((*IntValuer)(nil)).Elem(), reflect.TypeOf((*Int8Valuer)(nil)).Elem(), reflect.TypeOf((*Int16Valuer)(nil)).Elem(), reflect.TypeOf((*Int32Valuer)(nil)).Elem(), reflect.TypeOf((*Int64Valuer)(nil)).Elem(), reflect.TypeOf((*UintValuer)(nil)).Elem(), reflect.TypeOf((*Uint8Valuer)(nil)).Elem(), reflect.TypeOf((*Uint16Valuer)(nil)).Elem(), reflect.TypeOf((*Uint32Valuer)(nil)).Elem(), reflect.TypeOf((*Uint64Valuer)(nil)).Elem(), reflect.TypeOf((*Float32Valuer)(nil)).Elem(), reflect.TypeOf((*Float64Valuer)(nil)).Elem(), reflect.TypeOf((*StringValuer)(nil)).Elem(), reflect.TypeOf((*TimeValuer)(nil)).Elem(), reflect.TypeOf((*DurationValuer)(nil)).Elem(), reflect.TypeOf((*ArrayValuer)(nil)).Elem(), reflect.TypeOf((*MapValuer)(nil)).Elem(), } type patcher struct{} func (patcher) Visit(node *ast.Node) { switch id := (*node).(type) { case *ast.IdentifierNode, *ast.MemberNode: nodeType := id.Type() for _, t := range supportedInterfaces { if nodeType.Implements(t) { ast.Patch(node, &ast.CallNode{ Callee: &ast.IdentifierNode{Value: "$patcher_value_getter"}, Arguments: []ast.Node{id}, }) return } } } } func getValue(params ...any) (any, error) { switch v := params[0].(type) { case AnyValuer: return v.AsAny(), nil case BoolValuer: return v.AsBool(), nil case IntValuer: return v.AsInt(), nil case Int8Valuer: return v.AsInt8(), nil case Int16Valuer: return v.AsInt16(), nil case Int32Valuer: return v.AsInt32(), nil case Int64Valuer: return v.AsInt64(), nil case UintValuer: return v.AsUint(), nil case Uint8Valuer: return v.AsUint8(), nil case Uint16Valuer: return v.AsUint16(), nil case Uint32Valuer: return v.AsUint32(), nil case Uint64Valuer: return v.AsUint64(), nil case Float32Valuer: return v.AsFloat32(), nil case Float64Valuer: return v.AsFloat64(), nil case StringValuer: return v.AsString(), nil case TimeValuer: return v.AsTime(), nil case DurationValuer: return v.AsDuration(), nil case ArrayValuer: return v.AsArray(), nil case MapValuer: return v.AsMap(), nil } return params[0], nil } var getValueFunc = expr.Function("$patcher_value_getter", getValue, new(func(BoolValuer) bool), new(func(IntValuer) int), new(func(Int8Valuer) int8), new(func(Int16Valuer) int16), new(func(Int32Valuer) int32), new(func(Int64Valuer) int64), new(func(UintValuer) uint), new(func(Uint8Valuer) uint8), new(func(Uint16Valuer) uint16), new(func(Uint32Valuer) uint32), new(func(Uint64Valuer) uint64), new(func(Float32Valuer) float32), new(func(Float64Valuer) float64), new(func(StringValuer) string), new(func(TimeValuer) time.Time), new(func(DurationValuer) time.Duration), new(func(ArrayValuer) []any), new(func(MapValuer) map[string]any), new(func(any) any), ) ================================================ FILE: patcher/value/value_example_test.go ================================================ package value_test import ( "fmt" "github.com/expr-lang/expr" "github.com/expr-lang/expr/patcher/value" "github.com/expr-lang/expr/vm" ) type myInt struct { Int int } func (v *myInt) AsInt() int { return v.Int } func (v *myInt) AsAny() any { return v.Int } func ExampleAnyValuer() { env := make(map[string]any) env["ValueOne"] = &myInt{1} env["ValueTwo"] = &myInt{2} program, err := expr.Compile("ValueOne + ValueTwo", expr.Env(env), value.ValueGetter) if err != nil { panic(err) } out, err := vm.Run(program, env) if err != nil { panic(err) } fmt.Println(out) // Output: 3 } ================================================ FILE: patcher/value/value_test.go ================================================ package value import ( "testing" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr" "github.com/expr-lang/expr/vm" ) type customInt struct { Int int } func (v *customInt) AsInt() int { return v.Int } func (v *customInt) AsAny() any { return v.Int } type customTypedInt struct { Int int } func (v *customTypedInt) AsInt() int { return v.Int } type customUntypedInt struct { Int int } func (v *customUntypedInt) AsAny() any { return v.Int } type customString struct { String string } func (v *customString) AsString() string { return v.String } func (v *customString) AsAny() any { return v.String } type customTypedString struct { String string } func (v *customTypedString) AsString() string { return v.String } type customUntypedString struct { String string } func (v *customUntypedString) AsAny() any { return v.String } type customTypedArray struct { Array []any } func (v *customTypedArray) AsArray() []any { return v.Array } type customTypedMap struct { Map map[string]any } func (v *customTypedMap) AsMap() map[string]any { return v.Map } func Test_valueAddInt(t *testing.T) { env := make(map[string]any) env["ValueOne"] = &customInt{1} env["ValueTwo"] = &customInt{2} program, err := expr.Compile("ValueOne + ValueTwo", expr.Env(env), ValueGetter) require.NoError(t, err) out, err := vm.Run(program, env) require.NoError(t, err) require.Equal(t, 3, out.(int)) } func Test_valueUntypedAddInt(t *testing.T) { env := make(map[string]any) env["ValueOne"] = &customUntypedInt{1} env["ValueTwo"] = &customUntypedInt{2} program, err := expr.Compile("ValueOne + ValueTwo", expr.Env(env), ValueGetter) require.NoError(t, err) out, err := vm.Run(program, env) require.NoError(t, err) require.Equal(t, 3, out.(int)) } func Test_valueTypedAddInt(t *testing.T) { env := make(map[string]any) env["ValueOne"] = &customTypedInt{1} env["ValueTwo"] = &customTypedInt{2} program, err := expr.Compile("ValueOne + ValueTwo", expr.Env(env), ValueGetter) require.NoError(t, err) out, err := vm.Run(program, env) require.NoError(t, err) require.Equal(t, 3, out.(int)) } func Test_valueTypedAddMismatch(t *testing.T) { env := make(map[string]any) env["ValueOne"] = &customTypedInt{1} env["ValueTwo"] = &customTypedString{"test"} _, err := expr.Compile("ValueOne + ValueTwo", expr.Env(env), ValueGetter) require.Error(t, err) } func Test_valueUntypedAddMismatch(t *testing.T) { env := make(map[string]any) env["ValueOne"] = &customUntypedInt{1} env["ValueTwo"] = &customUntypedString{"test"} program, err := expr.Compile("ValueOne + ValueTwo", expr.Env(env), ValueGetter) require.NoError(t, err) _, err = vm.Run(program, env) require.Error(t, err) } func Test_valueTypedArray(t *testing.T) { env := make(map[string]any) env["ValueOne"] = &customTypedArray{[]any{1, 2}} program, err := expr.Compile("ValueOne[0] + ValueOne[1]", expr.Env(env), ValueGetter) require.NoError(t, err) out, err := vm.Run(program, env) require.NoError(t, err) require.Equal(t, 3, out.(int)) } func Test_valueTypedMap(t *testing.T) { env := make(map[string]any) env["ValueOne"] = &customTypedMap{map[string]any{"one": 1, "two": 2}} program, err := expr.Compile("ValueOne.one + ValueOne.two", expr.Env(env), ValueGetter) require.NoError(t, err) out, err := vm.Run(program, env) require.NoError(t, err) require.Equal(t, 3, out.(int)) } ================================================ FILE: patcher/with_context.go ================================================ package patcher import ( "reflect" "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/checker/nature" "github.com/expr-lang/expr/conf" ) // WithContext adds WithContext.Name argument to all functions calls with a context.Context argument. type WithContext struct { Name string Functions conf.FunctionsTable // Optional: used to look up function types when callee type is unknown. Env *nature.Nature // Optional: used to look up method types when callee type is unknown. NtCache *nature.Cache // Optional: cache for nature lookups. } // Visit adds WithContext.Name argument to all functions calls with a context.Context argument. func (w WithContext) Visit(node *ast.Node) { switch call := (*node).(type) { case *ast.CallNode: fn := call.Callee.Type() if fn == nil { return } // If callee type is interface{} (unknown), look up the function type from // the Functions table or Env. This handles cases where the checker returns early // without visiting nested call arguments (e.g., Date2() in Now2().After(Date2())) // because the outer call's type is unknown due to missing context arguments. if fn.Kind() == reflect.Interface { if ident, ok := call.Callee.(*ast.IdentifierNode); ok { if w.Functions != nil { if f, ok := w.Functions[ident.Value]; ok { fn = f.Type() } } if fn.Kind() == reflect.Interface && w.Env != nil { if m, ok := w.Env.MethodByName(w.NtCache, ident.Value); ok { fn = m.Type } } } } if fn.Kind() != reflect.Func { return } switch fn.NumIn() { case 0: return case 1: if fn.In(0).String() != "context.Context" { return } default: if fn.In(0).String() != "context.Context" && fn.In(1).String() != "context.Context" { return } } ast.Patch(node, &ast.CallNode{ Callee: call.Callee, Arguments: append([]ast.Node{ &ast.IdentifierNode{Value: w.Name}, }, call.Arguments...), }) } } ================================================ FILE: patcher/with_context_test.go ================================================ package patcher_test import ( "context" "testing" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr" "github.com/expr-lang/expr/patcher" ) func TestWithContext(t *testing.T) { env := map[string]any{ "fn": func(ctx context.Context, a int) int { return ctx.Value("value").(int) + a }, "ctx": context.TODO(), } withContext := patcher.WithContext{Name: "ctx"} program, err := expr.Compile(`fn(40)`, expr.Env(env), expr.Patch(withContext)) require.NoError(t, err) ctx := context.WithValue(context.Background(), "value", 2) env["ctx"] = ctx output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, 42, output) } func TestWithContext_with_env_Function(t *testing.T) { env := map[string]any{ "ctx": context.TODO(), } fn := expr.Function("fn", func(params ...any) (any, error) { ctx := params[0].(context.Context) a := params[1].(int) return ctx.Value("value").(int) + a, nil }, new(func(context.Context, int) int), ) program, err := expr.Compile( `fn(40)`, expr.Env(env), expr.WithContext("ctx"), fn, ) require.NoError(t, err) ctx := context.WithValue(context.Background(), "value", 2) env["ctx"] = ctx output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, 42, output) } type testEnvContext struct { Context context.Context `expr:"ctx"` } func (testEnvContext) Fn(ctx context.Context, a int) int { return ctx.Value("value").(int) + a } func TestWithContext_env_struct(t *testing.T) { withContext := patcher.WithContext{Name: "ctx"} program, err := expr.Compile(`Fn(40)`, expr.Env(testEnvContext{}), expr.Patch(withContext)) require.NoError(t, err) ctx := context.WithValue(context.Background(), "value", 2) env := testEnvContext{ Context: ctx, } output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, 42, output) } type TestFoo struct { contextValue int } func (f *TestFoo) GetValue(a int) int64 { return int64(f.contextValue + a) } func TestWithContext_with_env_method_chain(t *testing.T) { env := map[string]any{ "ctx": context.TODO(), } fn := expr.Function("fn", func(params ...any) (any, error) { ctx := params[0].(context.Context) contextValue := ctx.Value("value").(int) return &TestFoo{ contextValue: contextValue, }, nil }, new(func(context.Context) *TestFoo), ) program, err := expr.Compile( `fn().GetValue(40)`, expr.Env(env), expr.WithContext("ctx"), fn, expr.AsInt64(), ) require.NoError(t, err) ctx := context.WithValue(context.Background(), "value", 2) env["ctx"] = ctx output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, int64(42), output) } func TestWithContext_issue529(t *testing.T) { env := map[string]any{ "ctx": context.Background(), "foo": func(ctx context.Context, n int) int { if ctx == nil { panic("wanted a context") } return n + 1 }, } options := []expr.Option{ expr.Env(env), expr.WithContext("ctx"), } code := "foo(0) | foo()" program, err := expr.Compile(code, options...) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, 2, out) } ================================================ FILE: patcher/with_timezone.go ================================================ package patcher import ( "time" "github.com/expr-lang/expr/ast" ) // WithTimezone passes Location to date() and now() functions. type WithTimezone struct { Location *time.Location } func (t WithTimezone) Visit(node *ast.Node) { if btin, ok := (*node).(*ast.BuiltinNode); ok { switch btin.Name { case "date", "now": loc := &ast.ConstantNode{Value: t.Location} ast.Patch(node, &ast.BuiltinNode{ Name: btin.Name, Arguments: append([]ast.Node{loc}, btin.Arguments...), }) } } } ================================================ FILE: patcher/with_timezone_test.go ================================================ package patcher_test import ( "testing" "time" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr" ) func TestWithTimezone_date(t *testing.T) { program, err := expr.Compile(`date("2024-05-07 23:00:00")`, expr.Timezone("Europe/Zurich")) require.NoError(t, err) out, err := expr.Run(program, nil) require.NoError(t, err) require.Equal(t, "2024-05-07T23:00:00+02:00", out.(time.Time).Format(time.RFC3339)) } func TestWithTimezone_now(t *testing.T) { program, err := expr.Compile(`now()`, expr.Timezone("Asia/Kamchatka")) require.NoError(t, err) out, err := expr.Run(program, nil) require.NoError(t, err) require.Equal(t, "Asia/Kamchatka", out.(time.Time).Location().String()) } ================================================ FILE: repl/go.mod ================================================ module github.com/expr-lang/expr/repl go 1.20 require ( github.com/bettercap/readline v0.0.0-20210228151553-655e48bcb7bf github.com/expr-lang/expr v1.13.0 github.com/expr-lang/expr/debug v0.0.0 ) require ( github.com/chzyer/test v1.0.0 // indirect github.com/gdamore/encoding v1.0.0 // indirect github.com/gdamore/tcell/v2 v2.6.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703 // indirect github.com/rivo/uniseg v0.4.4 // indirect golang.org/x/sys v0.11.0 // indirect golang.org/x/term v0.11.0 // indirect golang.org/x/text v0.12.0 // indirect ) replace github.com/expr-lang/expr => ../ replace github.com/expr-lang/expr/debug => ../debug ================================================ FILE: repl/go.sum ================================================ github.com/bettercap/readline v0.0.0-20210228151553-655e48bcb7bf h1:pwGPRc5PIp4KCF9QbKn0iLVMhfigUMw4IzGZEZ81m1I= github.com/bettercap/readline v0.0.0-20210228151553-655e48bcb7bf/go.mod h1:03rWiUf60r1miMVzMEtgtkq7RdZniecZFw3/Zgvyxcs= github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= github.com/gdamore/tcell/v2 v2.6.0 h1:OKbluoP9VYmJwZwq/iLb4BxwKcwGthaa1YNBJIyCySg= github.com/gdamore/tcell/v2 v2.6.0/go.mod h1:be9omFATkdr0D9qewWW3d+MEvl5dha+Etb5y65J2H8Y= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703 h1:ZyM/+FYnpbZsFWuCohniM56kRoHRB4r5EuIzXEYkpxo= github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703/go.mod h1:nVwGv4MP47T0jvlk7KuTTjjuSmrGO4JF0iaiNt4bufE= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.11.0 h1:F9tnn/DA/Im8nCwm+fX+1/eBwi4qFjRT++MhtVC4ZX0= golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= ================================================ FILE: repl/repl.go ================================================ package main import ( "fmt" "os" "runtime" "strings" "github.com/expr-lang/expr/test/fuzz" "github.com/bettercap/readline" "github.com/expr-lang/expr" "github.com/expr-lang/expr/builtin" "github.com/expr-lang/expr/debug" "github.com/expr-lang/expr/vm" ) var keywords = []string{ // Commands: "exit", "opcodes", "debug", "mem", // Operators: "and", "or", "in", "not", "not in", "contains", "matches", "startsWith", "endsWith", } func main() { env := fuzz.NewEnv() for name := range env { keywords = append(keywords, name) } fn := fuzz.Func() keywords = append(keywords, "fn") home, err := os.UserHomeDir() if err != nil { panic(err) } rl, err := readline.NewEx(&readline.Config{ Prompt: "❯ ", AutoComplete: completer{append(builtin.Names, keywords...)}, HistoryFile: home + "/.expr_history", }) if err != nil { panic(err) } defer rl.Close() var memUsage uint64 var program *vm.Program for { line, err := rl.Readline() if err != nil { // io.EOF when Ctrl-D is pressed break } line = strings.TrimSpace(line) switch line { case "": continue case "exit": return case "mem": fmt.Printf("memory usage: %s\n", humanizeBytes(memUsage)) continue case "opcodes": if program == nil { fmt.Println("no program") continue } fmt.Println(program.Disassemble()) continue case "debug": if program == nil { fmt.Println("no program") continue } debug.StartDebugger(program, env) continue } program, err = expr.Compile(line, expr.Env(env), fn) if err != nil { fmt.Printf("compile error: %s\n", err) continue } start := memoryUsage() output, err := expr.Run(program, env) if err != nil { fmt.Printf("runtime error: %s\n", err) continue } memUsage = memoryUsage() - start fmt.Println(output) } } type completer struct { words []string } func (c completer) Do(line []rune, pos int) ([][]rune, int) { var lastWord string for i := pos - 1; i >= 0; i-- { if line[i] == ' ' { break } lastWord = string(line[i]) + lastWord } var words [][]rune for _, word := range c.words { if strings.HasPrefix(word, lastWord) { words = append(words, []rune(strings.TrimPrefix(word, lastWord))) } } return words, len(lastWord) } func memoryUsage() uint64 { var m runtime.MemStats runtime.ReadMemStats(&m) return m.Alloc } func humanizeBytes(b uint64) string { const unit = 1024 if b < unit { return fmt.Sprintf("%d B", b) } div, exp := uint64(unit), 0 for n := b / unit; n >= unit; n /= unit { div *= unit exp++ } return fmt.Sprintf("%.2f %ciB", float64(b)/float64(div), "KMGTPE"[exp]) } ================================================ FILE: test/bench/bench_call_test.go ================================================ package bench_test import ( "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr/vm" ) type Env struct { Fn func() bool } func BenchmarkCall_callTyped(b *testing.B) { code := `Fn()` p, err := expr.Compile(code, expr.Env(Env{})) require.NoError(b, err) require.Equal(b, p.Bytecode[1], vm.OpCallTyped) env := Env{ Fn: func() bool { return true }, } var out any b.ResetTimer() for n := 0; n < b.N; n++ { program, _ := expr.Compile(code, expr.Env(env)) out, err = vm.Run(program, env) } b.StopTimer() require.NoError(b, err) require.True(b, out.(bool)) } func BenchmarkCall_eval(b *testing.B) { code := `Fn()` p, err := expr.Compile(code) require.NoError(b, err) require.Equal(b, p.Bytecode[1], vm.OpCall) env := Env{ Fn: func() bool { return true }, } var out any b.ResetTimer() for n := 0; n < b.N; n++ { out, err = expr.Eval(code, env) } b.StopTimer() require.NoError(b, err) require.True(b, out.(bool)) } ================================================ FILE: test/coredns/coredns.go ================================================ package coredns import ( "context" "errors" "net" ) func DefaultEnv(ctx context.Context, state *Request) map[string]any { return map[string]any{ "incidr": func(ipStr, cidrStr string) (bool, error) { ip := net.ParseIP(ipStr) if ip == nil { return false, errors.New("first argument is not an IP address") } _, cidr, err := net.ParseCIDR(cidrStr) if err != nil { return false, err } return cidr.Contains(ip), nil }, "metadata": func(label string) string { return "" }, "type": state.Type, "name": state.Name, "class": state.Class, "proto": state.Proto, "size": state.Len, "client_ip": state.IP, "port": state.Port, "id": func() int { return int(state.Req.Id) }, "opcode": func() int { return state.Req.Opcode }, "do": state.Do, "bufsize": state.Size, "server_ip": state.LocalIP, "server_port": state.LocalPort, } } type Request struct { Req *Msg W ResponseWriter Zone string } func (r *Request) NewWithQuestion(name string, typ uint16) Request { return Request{} } func (r *Request) IP() string { return "" } func (r *Request) LocalIP() string { return "" } func (r *Request) Port() string { return "" } func (r *Request) LocalPort() string { return "" } func (r *Request) RemoteAddr() string { return r.W.RemoteAddr().String() } func (r *Request) LocalAddr() string { return r.W.LocalAddr().String() } func (r *Request) Proto() string { return "udp" } func (r *Request) Family() int { return 2 } func (r *Request) Do() bool { return true } func (r *Request) Len() int { return 0 } func (r *Request) Size() int { return 0 } func (r *Request) SizeAndDo(m *Msg) bool { return true } func (r *Request) Scrub(reply *Msg) *Msg { return reply } func (r *Request) Type() string { return "" } func (r *Request) QType() uint16 { return 0 } func (r *Request) Name() string { return "." } func (r *Request) QName() string { return "." } func (r *Request) Class() string { return "" } func (r *Request) QClass() uint16 { return 0 } func (r *Request) Clear() { } func (r *Request) Match(reply *Msg) bool { return true } type Msg struct { MsgHdr Compress bool `json:"-"` Question []Question Answer []RR Ns []RR Extra []RR } type MsgHdr struct { Id uint16 Response bool Opcode int Authoritative bool Truncated bool RecursionDesired bool RecursionAvailable bool Zero bool AuthenticatedData bool CheckingDisabled bool Rcode int } type Question struct { Name string `dns:"cdomain-name"` Qtype uint16 Qclass uint16 } type RR interface { Header() *RR_Header String() string } type RR_Header struct { Name string `dns:"cdomain-name"` Rrtype uint16 Class uint16 Ttl uint32 Rdlength uint16 } type ResponseWriter interface { LocalAddr() net.Addr RemoteAddr() net.Addr WriteMsg(*Msg) error Write([]byte) (int, error) Close() error TsigStatus() error TsigTimersOnly(bool) Hijack() } ================================================ FILE: test/coredns/coredns_test.go ================================================ package coredns_test import ( "context" "testing" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr" "github.com/expr-lang/expr/test/coredns" ) func TestCoreDNS(t *testing.T) { env := coredns.DefaultEnv(context.Background(), &coredns.Request{}) tests := []struct { input string }{ {`metadata('geoip/city/name') == 'Exampleshire'`}, {`(type() == 'A' && name() == 'example.com') || client_ip() == '1.2.3.4'`}, {`name() matches '^abc\\..*\\.example\\.com\\.$'`}, {`type() in ['A', 'AAAA']`}, {`incidr(client_ip(), '192.168.0.0/16')`}, {`incidr(client_ip(), '127.0.0.0/24')`}, } for _, test := range tests { t.Run(test.input, func(t *testing.T) { _, err := expr.Compile(test.input, expr.Env(env), expr.DisableBuiltin("type")) assert.NoError(t, err) }) } } ================================================ FILE: test/crowdsec/crowdsec.go ================================================ package crowdsec import ( "time" ) type Event struct { Type int `yaml:"Type,omitempty" json:"Type,omitempty"` ExpectMode int `yaml:"ExpectMode,omitempty" json:"ExpectMode,omitempty"` Whitelisted bool `yaml:"Whitelisted,omitempty" json:"Whitelisted,omitempty"` WhitelistReason string `yaml:"WhitelistReason,omitempty" json:"whitelist_reason,omitempty"` Stage string `yaml:"Stage,omitempty" json:"Stage,omitempty"` Line Line `yaml:"Line,omitempty" json:"Line,omitempty"` Parsed map[string]string `yaml:"Parsed,omitempty" json:"Parsed,omitempty"` Enriched map[string]string `yaml:"Enriched,omitempty" json:"Enriched,omitempty"` Unmarshaled map[string]any `yaml:"Unmarshaled,omitempty" json:"Unmarshaled,omitempty"` Overflow RuntimeAlert `yaml:"Overflow,omitempty" json:"Alert,omitempty"` Time time.Time `yaml:"Time,omitempty" json:"Time,omitempty"` StrTime string `yaml:"StrTime,omitempty" json:"StrTime,omitempty"` StrTimeFormat string `yaml:"StrTimeFormat,omitempty" json:"StrTimeFormat,omitempty"` MarshaledTime string `yaml:"MarshaledTime,omitempty" json:"MarshaledTime,omitempty"` Process bool `yaml:"Process,omitempty" json:"Process,omitempty"` Meta map[string]string `yaml:"Meta,omitempty" json:"Meta,omitempty"` } func (e *Event) GetType() string { return "" } func (e *Event) GetMeta(key string) string { return "" } type Alert struct { Capacity *int32 `json:"capacity"` CreatedAt string `json:"created_at,omitempty"` Decisions []*Decision `json:"decisions"` Events []*Event `json:"events"` EventsCount *int32 `json:"events_count"` ID int64 `json:"id,omitempty"` Labels []string `json:"labels"` Leakspeed *string `json:"leakspeed"` MachineID string `json:"machine_id,omitempty"` Message *string `json:"message"` Meta Meta `json:"meta,omitempty"` Remediation bool `json:"remediation,omitempty"` Scenario *string `json:"scenario"` ScenarioHash *string `json:"scenario_hash"` ScenarioVersion *string `json:"scenario_version"` Simulated *bool `json:"simulated"` Source *Source `json:"source"` StartAt *string `json:"start_at"` StopAt *string `json:"stop_at"` UUID string `json:"uuid,omitempty"` Edges AlertEdges `json:"edges"` } func (a *Alert) HasRemediation() bool { return true } func (a *Alert) GetScope() string { return "" } func (a *Alert) GetValue() string { return "" } func (a *Alert) GetScenario() string { return "" } func (a *Alert) GetEventsCount() int32 { return 0 } func (a *Alert) GetMeta(_ string) string { return "" } func (s Source) GetValue() string { return *s.Value } func (s Source) GetScope() string { return *s.Scope } func (s Source) GetAsNumberName() string { return "" } type AlertEdges struct { Owner *Machine `json:"owner,omitempty"` Decisions []*Decision `json:"decisions,omitempty"` Events []*Event `json:"events,omitempty"` Metas []*Meta `json:"metas,omitempty"` } func (e AlertEdges) OwnerOrErr() (*Machine, error) { return nil, nil } func (e AlertEdges) DecisionsOrErr() ([]*Decision, error) { return nil, nil } func (e AlertEdges) EventsOrErr() ([]*Event, error) { return nil, nil } func (e AlertEdges) MetasOrErr() ([]*Meta, error) { return nil, nil } type Machine struct { ID int `json:"id,omitempty"` CreatedAt *time.Time `json:"created_at,omitempty"` UpdatedAt *time.Time `json:"updated_at,omitempty"` LastPush *time.Time `json:"last_push,omitempty"` LastHeartbeat *time.Time `json:"last_heartbeat,omitempty"` MachineId string `json:"machineId,omitempty"` Password string `json:"-"` IpAddress string `json:"ipAddress,omitempty"` Scenarios string `json:"scenarios,omitempty"` Version string `json:"version,omitempty"` IsValidated bool `json:"isValidated,omitempty"` Status string `json:"status,omitempty"` AuthType string `json:"auth_type"` Edges MachineEdges `json:"edges"` } type MachineEdges struct { Alerts []*Alert `json:"alerts,omitempty"` } type Decision struct { Duration *string `json:"duration"` ID int64 `json:"id,omitempty"` Origin *string `json:"origin"` Scenario *string `json:"scenario"` Scope *string `json:"scope"` Simulated *bool `json:"simulated,omitempty"` Type *string `json:"type"` Until string `json:"until,omitempty"` UUID string `json:"uuid,omitempty"` Value *string `json:"value"` } type Line struct { Raw string `yaml:"Raw,omitempty"` Src string `yaml:"Src,omitempty"` Time time.Time Labels map[string]string `yaml:"Labels,omitempty"` Process bool Module string `yaml:"Module,omitempty"` } type ScopeType struct { Scope string `yaml:"type"` Filter string `yaml:"expression"` } type RuntimeAlert struct { Mapkey string `yaml:"MapKey,omitempty" json:"MapKey,omitempty"` BucketId string `yaml:"BucketId,omitempty" json:"BucketId,omitempty"` Whitelisted bool `yaml:"Whitelisted,omitempty" json:"Whitelisted,omitempty"` Reprocess bool `yaml:"Reprocess,omitempty" json:"Reprocess,omitempty"` Sources map[string]Source `yaml:"Sources,omitempty" json:"Sources,omitempty"` Alert *Alert `yaml:"Alert,omitempty" json:"Alert,omitempty"` APIAlerts []Alert `yaml:"APIAlerts,omitempty" json:"APIAlerts,omitempty"` } func (r RuntimeAlert) GetSources() []string { return nil } type Source struct { AsName string `json:"as_name,omitempty"` AsNumber string `json:"as_number,omitempty"` Cn string `json:"cn,omitempty"` IP string `json:"ip,omitempty"` Latitude float32 `json:"latitude,omitempty"` Longitude float32 `json:"longitude,omitempty"` Range string `json:"range,omitempty"` Scope *string `json:"scope"` Value *string `json:"value"` } type Meta []*MetaItems0 type MetaItems0 struct { Key string `json:"key,omitempty"` Value string `json:"value,omitempty"` } ================================================ FILE: test/crowdsec/crowdsec_test.go ================================================ package crowdsec_test import ( "encoding/json" "os" "testing" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr" "github.com/expr-lang/expr/test/crowdsec" ) func TestCrowdsec(t *testing.T) { b, err := os.ReadFile("../../testdata/crowdsec.json") require.NoError(t, err) var examples []string err = json.Unmarshal(b, &examples) require.NoError(t, err) env := map[string]any{ "evt": &crowdsec.Event{}, } var opt = []expr.Option{ expr.Env(env), } for _, fn := range crowdsec.CustomFunctions { opt = append( opt, expr.Function( fn.Name, func(params ...any) (any, error) { return nil, nil }, fn.Func..., ), ) } for _, line := range examples { t.Run(line, func(t *testing.T) { _, err = expr.Compile(line, opt...) require.NoError(t, err) }) } } ================================================ FILE: test/crowdsec/funcs.go ================================================ package crowdsec import ( "time" ) var CustomFunctions = []struct { Name string Func []any }{ { Name: "Distance", Func: []any{ new(func(string, string, string, string) (float64, error)), }, }, { Name: "GetFromStash", Func: []any{ new(func(string, string) (string, error)), }, }, { Name: "Atof", Func: []any{ new(func(string) float64), }, }, { Name: "JsonExtract", Func: []any{ new(func(string, string) string), }, }, { Name: "JsonExtractUnescape", Func: []any{ new(func(string, ...string) string), }, }, { Name: "JsonExtractLib", Func: []any{ new(func(string, ...string) string), }, }, { Name: "JsonExtractSlice", Func: []any{ new(func(string, string) []any), }, }, { Name: "JsonExtractObject", Func: []any{ new(func(string, string) map[string]any), }, }, { Name: "ToJsonString", Func: []any{ new(func(any) string), }, }, { Name: "File", Func: []any{ new(func(string) []string), }, }, { Name: "RegexpInFile", Func: []any{ new(func(string, string) bool), }, }, { Name: "Upper", Func: []any{ new(func(string) string), }, }, { Name: "Lower", Func: []any{ new(func(string) string), }, }, { Name: "IpInRange", Func: []any{ new(func(string, string) bool), }, }, { Name: "TimeNow", Func: []any{ new(func() string), }, }, { Name: "ParseUri", Func: []any{ new(func(string) map[string][]string), }, }, { Name: "PathUnescape", Func: []any{ new(func(string) string), }, }, { Name: "QueryUnescape", Func: []any{ new(func(string) string), }, }, { Name: "PathEscape", Func: []any{ new(func(string) string), }, }, { Name: "QueryEscape", Func: []any{ new(func(string) string), }, }, { Name: "XMLGetAttributeValue", Func: []any{ new(func(string, string, string) string), }, }, { Name: "XMLGetNodeValue", Func: []any{ new(func(string, string) string), }, }, { Name: "IpToRange", Func: []any{ new(func(string, string) string), }, }, { Name: "IsIPV6", Func: []any{ new(func(string) bool), }, }, { Name: "IsIPV4", Func: []any{ new(func(string) bool), }, }, { Name: "IsIP", Func: []any{ new(func(string) bool), }, }, { Name: "LookupHost", Func: []any{ new(func(string) []string), }, }, { Name: "GetDecisionsCount", Func: []any{ new(func(string) int), }, }, { Name: "GetDecisionsSinceCount", Func: []any{ new(func(string, string) int), }, }, { Name: "Sprintf", Func: []any{ new(func(string, ...any) string), }, }, { Name: "ParseUnix", Func: []any{ new(func(string) string), }, }, { Name: "SetInStash", Func: []any{ new(func(string, string, string, *time.Duration) error), }, }, { Name: "Fields", Func: []any{ new(func(string) []string), }, }, { Name: "Index", Func: []any{ new(func(string, string) int), }, }, { Name: "IndexAny", Func: []any{ new(func(string, string) int), }, }, { Name: "Join", Func: []any{ new(func([]string, string) string), }, }, { Name: "Split", Func: []any{ new(func(string, string) []string), }, }, { Name: "SplitAfter", Func: []any{ new(func(string, string) []string), }, }, { Name: "SplitAfterN", Func: []any{ new(func(string, string, int) []string), }, }, { Name: "SplitN", Func: []any{ new(func(string, string, int) []string), }, }, { Name: "Replace", Func: []any{ new(func(string, string, string, int) string), }, }, { Name: "ReplaceAll", Func: []any{ new(func(string, string, string) string), }, }, { Name: "Trim", Func: []any{ new(func(string, string) string), }, }, { Name: "TrimLeft", Func: []any{ new(func(string, string) string), }, }, { Name: "TrimRight", Func: []any{ new(func(string, string) string), }, }, { Name: "TrimSpace", Func: []any{ new(func(string) string), }, }, { Name: "TrimPrefix", Func: []any{ new(func(string, string) string), }, }, { Name: "TrimSuffix", Func: []any{ new(func(string, string) string), }, }, { Name: "Get", Func: []any{ new(func([]string, int) string), }, }, { Name: "ToString", Func: []any{ new(func(any) string), }, }, { Name: "Match", Func: []any{ new(func(string, string) bool), }, }, { Name: "KeyExists", Func: []any{ new(func(string, map[string]any) bool), }, }, { Name: "LogInfo", Func: []any{ new(func(string, ...any) bool), }, }, { Name: "B64Decode", Func: []any{ new(func(string) string), }, }, { Name: "UnmarshalJSON", Func: []any{ new(func(string, map[string]any, string) error), }, }, { Name: "ParseKV", Func: []any{ new(func(string, map[string]any, string) error), }, }, { Name: "Hostname", Func: []any{ new(func() (string, error)), }, }, } ================================================ FILE: test/deref/deref_test.go ================================================ package deref_test import ( "context" "testing" "time" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr" ) func TestDeref_binary(t *testing.T) { i := 1 env := map[string]any{ "i": &i, "obj": map[string]any{ "i": &i, }, } t.Run("==", func(t *testing.T) { program, err := expr.Compile(`i == 1 && obj.i == 1`, expr.Env(env)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, true, out) }) t.Run("><", func(t *testing.T) { program, err := expr.Compile(`i > 0 && obj.i < 99`, expr.Env(env)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, true, out) }) t.Run("??+", func(t *testing.T) { program, err := expr.Compile(`(i ?? obj.i) + 1`, expr.Env(env)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, 2, out) }) } func TestDeref_unary(t *testing.T) { i := 1 ok := true env := map[string]any{ "i": &i, "obj": map[string]any{ "ok": &ok, }, } program, err := expr.Compile(`-i < 0 && !!obj.ok`, expr.Env(env)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, true, out) } func TestDeref_eval(t *testing.T) { i := 1 env := map[string]any{ "i": &i, "obj": map[string]any{ "i": &i, }, } out, err := expr.Eval(`i == 1 && obj.i == 1`, env) require.NoError(t, err) require.Equal(t, true, out) } func TestDeref_emptyCtx(t *testing.T) { program, err := expr.Compile(`ctx`) require.NoError(t, err) output, err := expr.Run(program, map[string]any{ "ctx": context.Background(), }) require.NoError(t, err) require.Implements(t, new(context.Context), output) } func TestDeref_emptyCtx_Eval(t *testing.T) { output, err := expr.Eval(`ctx`, map[string]any{ "ctx": context.Background(), }) require.NoError(t, err) require.Implements(t, new(context.Context), output) } func TestDeref_context_WithValue(t *testing.T) { program, err := expr.Compile(`ctxWithValue`) require.NoError(t, err) output, err := expr.Run(program, map[string]any{ "ctxWithValue": context.WithValue(context.Background(), "value", "test"), }) require.NoError(t, err) require.Implements(t, new(context.Context), output) } func TestDeref_method_on_int_pointer(t *testing.T) { output, err := expr.Eval(`foo.Bar()`, map[string]any{ "foo": new(foo), }) require.NoError(t, err) require.Equal(t, 42, output) } type foo int func (f *foo) Bar() int { return 42 } func TestDeref_multiple_pointers(t *testing.T) { a := 42 b := &a c := &b t.Run("returned as is", func(t *testing.T) { output, err := expr.Eval(`c`, map[string]any{ "c": c, }) require.NoError(t, err) require.Equal(t, c, output) require.IsType(t, (**int)(nil), output) }) t.Run("+ works", func(t *testing.T) { output, err := expr.Eval(`c+2`, map[string]any{ "c": c, }) require.NoError(t, err) require.Equal(t, 44, output) }) } func TestDeref_pointer_of_interface(t *testing.T) { v := 42 a := &v b := any(a) c := any(&b) t.Run("returned as is", func(t *testing.T) { output, err := expr.Eval(`c`, map[string]any{ "c": c, }) require.NoError(t, err) require.Equal(t, c, output) require.IsType(t, (*interface{})(nil), output) }) t.Run("+ works", func(t *testing.T) { output, err := expr.Eval(`c+2`, map[string]any{ "c": c, }) require.NoError(t, err) require.Equal(t, 44, output) }) } func TestDeref_nil(t *testing.T) { var b *int = nil c := &b t.Run("returned as is", func(t *testing.T) { output, err := expr.Eval(`c`, map[string]any{ "c": c, }) require.NoError(t, err) require.Equal(t, c, output) require.IsType(t, (**int)(nil), output) }) t.Run("== nil works", func(t *testing.T) { output, err := expr.Eval(`c == nil`, map[string]any{ "c": c, }) require.NoError(t, err) require.Equal(t, true, output) }) } func TestDeref_nil_in_pointer_of_interface(t *testing.T) { var a *int32 = nil b := any(a) c := any(&b) t.Run("returned as is", func(t *testing.T) { output, err := expr.Eval(`c`, map[string]any{ "c": c, }) require.NoError(t, err) require.Equal(t, c, output) require.IsType(t, (*interface{})(nil), output) }) t.Run("== nil works", func(t *testing.T) { output, err := expr.Eval(`c == nil`, map[string]any{ "c": c, }) require.NoError(t, err) require.Equal(t, true, output) }) } func TestDeref_commutative(t *testing.T) { a := "ok" b := "ok" type Env struct { A string B *string } env := Env{ A: a, B: &b, } tests := []struct { code string want bool }{ {`A == B`, true}, {`B == A`, true}, {`A != B`, false}, {`B != A`, false}, } for _, test := range tests { t.Run(test.code, func(t *testing.T) { program, err := expr.Compile(test.code, expr.Env(env)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, test.want, out) }) } } func TestDeref_fetch_from_interface_mix_pointer(t *testing.T) { type FooBar struct { Value string } foobar := &FooBar{"waldo"} var foobarAny any = foobar var foobarPtrAny any = &foobarAny res, err := expr.Eval("foo.Value", map[string]any{ "foo": foobarPtrAny, }) assert.NoError(t, err) assert.Equal(t, "waldo", res) } func TestDeref_func_args(t *testing.T) { i := 20 env := map[string]any{ "var": &i, "fn": func(p int) int { return p + 1 }, } program, err := expr.Compile(`fn(var) + fn(var + 0)`, expr.Env(env)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, 42, out) } func TestDeref_struct_func_args(t *testing.T) { n, _ := time.Parse(time.RFC3339, "2024-05-12T18:30:00+00:00") duration := 30 * time.Minute env := map[string]any{ "time": n, "duration": &duration, } program, err := expr.Compile(`time.Add(duration).Format('2006-01-02T15:04:05Z07:00')`, expr.Env(env)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, "2024-05-12T19:00:00Z", out) } func TestDeref_ignore_func_args(t *testing.T) { f := foo(1) env := map[string]any{ "foo": &f, "fn": func(f *foo) int { return f.Bar() }, } program, err := expr.Compile(`fn(foo)`, expr.Env(env)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, 42, out) } func TestDeref_ignore_struct_func_args(t *testing.T) { n := time.Now() location, _ := time.LoadLocation("UTC") env := map[string]any{ "time": n, "location": location, } program, err := expr.Compile(`time.In(location).Location().String()`, expr.Env(env)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, "UTC", out) } func TestDeref_keep_pointer_if_arg_in_interface(t *testing.T) { x := 42 env := map[string]any{ "x": &x, "fn": func(p any) int { return *p.(*int) + 1 }, } program, err := expr.Compile(`fn(x)`, expr.Env(env)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, 43, out) } ================================================ FILE: test/examples/examples_test.go ================================================ package main import ( "os" "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/internal/testify/require" ) var examples []CodeBlock func init() { b, err := os.ReadFile("../../testdata/examples.md") if err != nil { panic(err) } examples = extractCodeBlocksWithTitle(string(b)) } func TestExamples(t *testing.T) { for _, code := range examples { code := code t.Run(code.Title, func(t *testing.T) { program, err := expr.Compile(code.Content, expr.Env(nil)) require.NoError(t, err) _, err = expr.Run(program, nil) require.NoError(t, err) }) } } ================================================ FILE: test/examples/markdown.go ================================================ package main import ( "strings" ) // CodeBlock holds the optional title and content of a code block. type CodeBlock struct { Title string Content string } func extractCodeBlocksWithTitle(markdown string) []CodeBlock { var blocks []CodeBlock var currentBlock []string var currentTitle string inBlock := false // Split the markdown into lines. lines := strings.Split(markdown, "\n") for i, line := range lines { trimmed := strings.TrimSpace(line) // Check if the line starts with a code block fence. if strings.HasPrefix(trimmed, "```") { // If already inside a code block, this marks its end. if inBlock { blocks = append(blocks, CodeBlock{ Title: currentTitle, Content: strings.Join(currentBlock, "\n"), }) currentBlock = nil inBlock = false currentTitle = "" } else { // Not in a block: starting a new code block. // Look backwards for the closest non-empty line that is not a code fence. title := "" for j := i - 1; j >= 0; j-- { prev := strings.TrimSpace(lines[j]) if prev == "" || strings.HasPrefix(prev, "```") { continue } title = prev break } currentTitle = title inBlock = true } // Skip the fence line. continue } // If inside a code block, add the line. if inBlock { currentBlock = append(currentBlock, line) } } return blocks } ================================================ FILE: test/fuzz/fuzz_corpus.sh ================================================ #!/bin/bash inputfile=./fuzz_corpus.txt zipname=fuzz_expr_seed_corpus.zip if [ ! -f "$inputfile" ]; then echo "Error: File $inputfile not found!" exit 1 fi lineno=1 while IFS= read -r line; do echo "$line" >"file_${lineno}.txt" ((lineno++)) done <"$inputfile" zip "$zipname" file_*.txt rm file_*.txt echo "Done!" ================================================ FILE: test/fuzz/fuzz_corpus.txt ================================================ !!!false !!(1 <= f64) !!(1 > 0.5) !!(i64 != f64) !!all(array, ok) !!false !!ok !!true !("bar" != "bar") !("bar" != "foo") !("bar" != nil) !("bar" < "foo") !("bar" <= "foo") !("bar" == "bar") !("bar" == "foo") !("bar" == nil) !("bar" > "bar") !("bar" > "foo") !("bar" >= "bar") !("bar" >= "foo") !("bar" contains "bar") !("bar" contains "foo") !("bar" endsWith "bar") !("bar" endsWith "foo") !("bar" in foo) !("bar" matches "foo") !("bar" not contains "bar") !("bar" not endsWith "bar") !("bar" not endsWith "foo") !("bar" not in foo) !("bar" not matches "bar") !("bar" not startsWith "bar") !("bar" not startsWith "foo") !("bar" startsWith "bar") !("foo" != "bar") !("foo" != nil) !("foo" < "foo") !("foo" <= "bar") !("foo" <= "foo") !("foo" == "bar") !("foo" == nil) !("foo" > "bar") !("foo" > "foo") !("foo" >= "bar") !("foo" contains "bar") !("foo" contains "foo") !("foo" endsWith "foo") !("foo" in foo) !("foo" matches "bar") !("foo" matches "foo") !("foo" not contains "bar") !("foo" not contains "foo") !("foo" not endsWith "bar") !("foo" not matches "bar") !("foo" not matches "foo") !("foo" not startsWith "bar") !("foo" not startsWith "foo") !("foo" startsWith "bar") !("foo" startsWith "foo") !(-f32 < f32) !(-i < i32) !(-i32 >= i) !(0.5 != 0.5) !(0.5 != 1) !(0.5 != f32) !(0.5 != f64) !(0.5 != i) !(0.5 != i32) !(0.5 != i64) !(0.5 != nil) !(0.5 < 0.5) !(0.5 < 1) !(0.5 < f32) !(0.5 < f64) !(0.5 < i) !(0.5 < i32) !(0.5 < i64) !(0.5 <= 0.5) !(0.5 <= 1) !(0.5 <= f32) !(0.5 <= f64) !(0.5 <= i) !(0.5 <= i32) !(0.5 <= i64) !(0.5 == 0.5) !(0.5 == 1) !(0.5 == f32) !(0.5 == f64) !(0.5 == i) !(0.5 == i32) !(0.5 == i64) !(0.5 == nil) !(0.5 > 0.5) !(0.5 > 1) !(0.5 > f32) !(0.5 > f64) !(0.5 > i) !(0.5 > i32) !(0.5 > i64) !(0.5 >= 0.5) !(0.5 >= 1) !(0.5 >= f32) !(0.5 >= f64) !(0.5 >= i) !(0.5 >= i32) !(0.5 >= i64) !(0.5 in array) !(0.5 not in array) !(1 != 0.5) !(1 != 1) !(1 != f32) !(1 != f64) !(1 != i) !(1 != i32) !(1 != i64) !(1 != nil) !(1 / i64 == i64) !(1 < 0.5) !(1 < 1) !(1 < f32) !(1 < f64) !(1 < i) !(1 < i32) !(1 < i64) !(1 <= 0.5) !(1 <= 1) !(1 <= f32) !(1 <= f64) !(1 <= i) !(1 <= i32) !(1 <= i64) !(1 == 0.5) !(1 == 1) !(1 == f32) !(1 == f64) !(1 == i) !(1 == i32) !(1 == i64) !(1 == nil) !(1 > 0.5) !(1 > 1) !(1 > f32) !(1 > f64) !(1 > i) !(1 > i32) !(1 > i64) !(1 >= 0.5) !(1 >= 1) !(1 >= f32) !(1 >= f64) !(1 >= i) !(1 >= i32) !(1 >= i64) !(1 in array) !(1 not in array) !(add != add) !(add != div) !(add != nil) !(add == add) !(add == div) !(add == nil) !(array != array) !(array != list) !(array != nil) !(array == array) !(array == list) !(array == nil) !(div != add) !(div != div) !(div != nil) !(div == add) !(div == div) !(f32 != 0.5) !(f32 != 1) !(f32 != f32) !(f32 != f64) !(f32 != i) !(f32 != i32) !(f32 != i64) !(f32 != nil) !(f32 < 0.5) !(f32 < 1) !(f32 < f32) !(f32 < f64) !(f32 < i) !(f32 < i32) !(f32 < i64) !(f32 <= 0.5) !(f32 <= 1) !(f32 <= f32) !(f32 <= f64) !(f32 <= i32) !(f32 <= i64) !(f32 == 0.5) !(f32 == 1) !(f32 == f32) !(f32 == f64) !(f32 == i) !(f32 == i32) !(f32 == i64) !(f32 == nil) !(f32 > 0.5) !(f32 > 1) !(f32 > f32) !(f32 > f64) !(f32 > i) !(f32 > i32) !(f32 > i64) !(f32 >= 0.5) !(f32 >= 1) !(f32 >= f32) !(f32 >= i) !(f32 >= i32) !(f32 >= i64) !(f32 in array) !(f32 not in array) !(f64 != 0.5) !(f64 != 1) !(f64 != f32) !(f64 != f64) !(f64 != i) !(f64 != i32) !(f64 != i64) !(f64 != nil) !(f64 < 0.5 + 1) !(f64 < 0.5) !(f64 < 1) !(f64 < f64) !(f64 < i) !(f64 < i32) !(f64 < i64) !(f64 < max(1)) !(f64 <= 0.5) !(f64 <= 1) !(f64 <= i32) !(f64 <= i64) !(f64 == 0.5) !(f64 == 1) !(f64 == f32) !(f64 == f64) !(f64 == i) !(f64 == i32) !(f64 == i64) !(f64 == nil) !(f64 > 0.5) !(f64 > 1) !(f64 > f32) !(f64 > f64) !(f64 > i) !(f64 > i32) !(f64 > i64) !(f64 >= 0.5) !(f64 >= 1) !(f64 >= f32) !(f64 >= f64) !(f64 >= i) !(f64 >= i32) !(f64 >= i64) !(f64 in array) !(f64 not in array) !(false != false) !(false != nil) !(false != ok) !(false != true) !(false && false) !(false && ok) !(false && true) !(false == false) !(false == nil) !(false == ok) !(false == true) !(false and false) !(false and ok) !(false and true) !(false or false) !(false or ok) !(false || false) !(false || ok) !(false || true) !(foo != foo) !(foo != nil) !(foo == foo) !(foo == nil) !(foo == reduce(list, #)) !(foo in list) !(foo not in list) !(greet != greet) !(greet != nil) !(greet == greet) !(greet == nil) !(half != half) !(half != nil) !(half == half) !(half == nil) !(i != 0.5) !(i != 1) !(i != f32) !(i != f64) !(i != i) !(i != i32) !(i != i64) !(i != nil) !(i < 0.5) !(i < 1) !(i < f64) !(i < i) !(i < i32) !(i < i64) !(i <= 0.5) !(i <= 1) !(i <= f32) !(i <= f64) !(i <= i32) !(i == 0.5) !(i == 1) !(i == f32) !(i == f64) !(i == i) !(i == i32) !(i == i64) !(i == nil) !(i > 0.5) !(i > 1) !(i > f32) !(i > f64) !(i > i) !(i > i32) !(i > i64) !(i >= 0.5) !(i >= 1 * i64) !(i >= 1) !(i >= f32) !(i >= f64) !(i >= i) !(i >= i32) !(i >= i64) !(i in array) !(i not in array) !(i32 != 0.5) !(i32 != 1) !(i32 != f32) !(i32 != f64) !(i32 != i) !(i32 != i32) !(i32 != i64) !(i32 != nil) !(i32 < 0.5) !(i32 < 1) !(i32 < f32) !(i32 < f64) !(i32 < i) !(i32 < i32) !(i32 < i64) !(i32 <= 0.5) !(i32 <= 1) !(i32 <= f32) !(i32 <= f64) !(i32 <= i) !(i32 <= i32) !(i32 <= i64) !(i32 == 0.5) !(i32 == 1) !(i32 == f32) !(i32 == f64) !(i32 == i) !(i32 == i32) !(i32 == i64) !(i32 == nil) !(i32 > 0.5) !(i32 > 1) !(i32 > f32) !(i32 > f64) !(i32 > i) !(i32 > i32) !(i32 >= 0.5) !(i32 >= 1) !(i32 >= f32) !(i32 >= f64) !(i32 >= i) !(i32 >= i32) !(i32 >= i64) !(i32 in array) !(i32 not in array) !(i64 != 0.5) !(i64 != 1) !(i64 != f32) !(i64 != f64) !(i64 != i) !(i64 != i32) !(i64 != i64) !(i64 != nil) !(i64 < 0.5) !(i64 < 1) !(i64 < f32) !(i64 < f64) !(i64 < i) !(i64 < i32 + i64) !(i64 < i32) !(i64 < i64) !(i64 <= 0.5) !(i64 <= 1) !(i64 <= f32) !(i64 <= f64) !(i64 <= i) !(i64 <= i32) !(i64 <= i64) !(i64 == 0.5) !(i64 == 1) !(i64 == f32) !(i64 == f64) !(i64 == i32) !(i64 == i64) !(i64 == nil) !(i64 > 0.5) !(i64 > 1) !(i64 > f32) !(i64 > f64) !(i64 > i) !(i64 > i32) !(i64 > i64) !(i64 >= 0.5) !(i64 >= 1) !(i64 >= f32) !(i64 >= f64) !(i64 >= i) !(i64 >= i32) !(i64 >= i64) !(i64 in array) !(len("bar") <= i) !(list != array) !(list != list) !(list != nil) !(list == array) !(list == list) !(list == nil) !(nil != "bar") !(nil != "foo") !(nil != 0.5) !(nil != 1) !(nil != add) !(nil != array) !(nil != div) !(nil != f32) !(nil != f64) !(nil != false) !(nil != foo) !(nil != greet) !(nil != half) !(nil != i) !(nil != i32) !(nil != i64) !(nil != list) !(nil != nil) !(nil != ok) !(nil != score) !(nil != true) !(nil == "bar") !(nil == "foo") !(nil == 0.5) !(nil == 1) !(nil == add) !(nil == array) !(nil == div) !(nil == f32) !(nil == f64) !(nil == false) !(nil == foo) !(nil == greet) !(nil == half) !(nil == i) !(nil == i32) !(nil == i64) !(nil == list) !(nil == nil) !(nil == ok) !(nil == score) !(nil == true) !(nil in array) !(nil in list) !(nil not in array) !(nil not in list) !(ok != false) !(ok != nil) !(ok != ok) !(ok != true) !(ok && false) !(ok && ok) !(ok && true) !(ok == nil) !(ok == ok) !(ok == true) !(ok and ok) !(ok and true) !(ok or false) !(ok or ok) !(ok or true) !(ok || false) !(ok || ok) !(ok || true) !(score != nil) !(score != score) !(score == nil) !(score == score) !(true != false) !(true != nil) !(true != ok) !(true != true) !(true && false) !(true && ok) !(true && true) !(true == false) !(true == nil) !(true == ok) !(true == true) !(true and ok) !(true and true) !(true or ok) !(true or true) !(true || false) !(true || ok) !(true || true) !all(array, false) !all(array, ok) !all(array, true) !all(list, false) !all(list, ok) !all(list, true) !any(array, i == #) !any(array, ok) !any(array, true) !any(list, false) !any(list, ok) !any(list, true) !false != not true !false != ok !false && 0.5 == 1 !false == ok !false ? "foo" : 0.5 !false ? "foo" : f32 !false ? 0.5 : "foo" !false ? 0.5 : f32 !false ? 1 : half !false ? 1 : i !false ? add : f32 !false ? add : i64 !false ? array : add !false ? array : ok !false ? div : array !false ? div : greet !false ? div : half !false ? f32 : add !false ? f32 : false !false ? f64 : "foo" !false ? foo : "bar" !false ? half : 1 !false ? half : add !false ? half : list !false ? half : true !false ? i : nil !false ? i32 : list !false ? i64 : foo !false ? i64 : i64 !false ? nil : add !false ? nil : f64 !false ? nil : foo !false ? nil : half !false ? ok : 1 !false ? score : "bar" !false ? score : foo !false ? score : ok !false ? true : "foo" !false or 0.5 > i32 !false or ok !false || ok !hasPrefix("foo", "foo") !none(array, # > #) !none(array, # >= #) !none(array, false) !none(array, ok) !none(list, ok) !none(list, true) !not ("bar" == nil) !not (1 <= 1) !not (1 > 0.5) !not (greet == nil) !not (i32 == f64) !not false !not none(list, true) !not ok !not true !ok !ok != !true !ok != ok !ok && ok !ok == ok !ok ? "bar" : "foo" !ok ? "bar" : foo !ok ? "foo" : 0.5 !ok ? "foo" : list !ok ? 0.5 : 1 !ok ? 0.5 : i !ok ? 1 : array !ok ? 1 : div !ok ? 1 : f64 !ok ? 1 : list !ok ? 1 : ok !ok ? add : 0.5 !ok ? array : div !ok ? array : f32 !ok ? array : foo !ok ? array : i !ok ? array : i32 !ok ? div : "foo" !ok ? div : 1 !ok ? div : i !ok ? f32 : "bar" !ok ? f32 : add !ok ? f32 : false !ok ? f32 : greet !ok ? f64 : "bar" !ok ? f64 : "foo" !ok ? f64 : 0.5 !ok ? f64 : half !ok ? f64 : score !ok ? false : ok !ok ? foo : "foo" !ok ? foo : f32 !ok ? foo : false !ok ? foo : i32 !ok ? greet : div !ok ? greet : list !ok ? greet : nil !ok ? half : f64 !ok ? i : "bar" !ok ? i : array !ok ? i : div !ok ? i : foo !ok ? i32 : 0.5 !ok ? i32 : f32 !ok ? i32 : greet !ok ? i32 : nil !ok ? i64 : 0.5 !ok ? i64 : 1 !ok ? i64 : f32 !ok ? i64 : true !ok ? list : f32 !ok ? list : i !ok ? nil : 1 !ok ? nil : array !ok ? ok : f32 !ok ? ok : list !ok and ok !ok or f32 < i64 !ok or false or false !ok or ok !ok || ok !one(array, false) !one(array, ok) !one(array, true) !one(list, false) !one(list, ok) !one(list, true) !reduce(array, false) !reduce(array, ok) !reduce(array, true) !reduce(list, # != #) !reduce(list, false) !reduce(list, ok) !reduce(list, true) !true != all(array, ok) !true ? "bar" : "foo" !true ? "bar" : true !true ? "foo" : "foo" !true ? "foo" : 0.5 !true ? "foo" : i !true ? 1 : "foo" !true ? 1 : i64 !true ? add : 0.5 !true ? add : score !true ? array : f64 !true ? array : list !true ? div : add !true ? f32 : false !true ? f64 : f64 !true ? foo : 1 !true ? foo : array !true ? greet : ok !true ? greet : score !true ? greet : true !true ? half : f64 !true ? i : 1 !true ? i : add !true ? i : ok !true ? i32 : 1 !true ? i64 : false !true ? i64 : i64 !true ? i64 : list !true ? list : 0.5 !true ? list : nil !true ? list : score !true ? nil : 0.5 !true ? nil : false !true ? nil : ok !true ? ok : add !true ? ok : div !true ? score : false !true ? true : f32 !true ? true : half !true and foo != nil !true || ok "bar" != "bar" || ok "bar" != foo.Bar "bar" != foo?.Bar "bar" + "bar" not in foo "bar" + foo.Bar "bar" + foo?.Bar "bar" < foo.Bar "bar" < foo?.Bar "bar" < foo?.String() "bar" <= foo.Bar "bar" <= foo.String() "bar" <= foo?.Bar "bar" == foo.Bar "bar" == foo?.Bar "bar" == foo?.String() "bar" > "bar" or ok ? f32 : i64 "bar" > foo.Bar "bar" > foo?.String() "bar" >= foo.Bar "bar" >= foo.String() "bar" >= foo?.Bar "bar" contains foo.Bar "bar" contains foo.String() "bar" contains foo?.Bar "bar" endsWith foo.Bar "bar" endsWith foo?.Bar "bar" endsWith foo?.String() "bar" matches "bar" and ok "bar" matches foo.Bar "bar" matches foo.String() "bar" matches foo?.Bar "bar" matches foo?.String() "bar" not contains foo.Bar "bar" not contains foo?.Bar "bar" not endsWith foo.Bar "bar" not endsWith foo?.Bar "bar" not endsWith foo?.String() "bar" not matches foo.Bar "bar" not matches foo.String() "bar" not matches foo?.Bar "bar" not matches foo?.String() "bar" not startsWith foo.Bar "bar" not startsWith foo?.Bar "bar" not startsWith foo?.String() "bar" startsWith "foo" or list == array "bar" startsWith foo.Bar "bar" startsWith foo.String() "foo" != "foo" ? f64 : array "foo" != "foo" or ok "foo" != foo.Bar "foo" != foo.String() "foo" != foo?.Bar "foo" != foo?.String() "foo" + "bar" not in foo "foo" + foo.Bar "foo" + foo?.Bar "foo" + foo?.String() "foo" < "bar" and ok "foo" < foo.Bar "foo" < foo?.Bar "foo" < foo?.String() "foo" <= foo.Bar "foo" <= foo?.Bar "foo" == "bar" != ok "foo" == "bar" and ok "foo" == foo.Bar "foo" == foo?.Bar "foo" == foo?.String() "foo" > foo.Bar "foo" > foo.String() "foo" > foo?.Bar "foo" >= foo.Bar "foo" >= foo.String() "foo" >= foo?.Bar "foo" >= foo?.String() "foo" contains "bar" == ok "foo" contains foo?.Bar "foo" endsWith foo.Bar "foo" endsWith foo?.Bar "foo" matches "bar" ? add : div "foo" matches "foo" || true ? greet : "bar" "foo" matches foo.Bar "foo" matches foo.String() "foo" matches foo?.Bar "foo" not contains foo.Bar "foo" not contains foo?.Bar "foo" not contains foo?.String() "foo" not endsWith foo.Bar "foo" not endsWith foo?.Bar "foo" not matches foo.Bar "foo" not matches foo?.Bar "foo" not matches foo?.String() "foo" not startsWith foo.Bar "foo" not startsWith foo?.Bar "foo" not startsWith foo?.String() "foo" startsWith foo.Bar "foo" startsWith foo?.Bar ("bar" not endsWith "bar") != ok ("bar" not endsWith "foo") != ok ("bar" not endsWith "foo") && false != nil ("bar" not matches "foo") || reduce(list, ok) ("foo" not matches "bar") == ok (0.5 * 0.5) ** i (0.5 * 0.5) ^ f32 (0.5 * 1) ** f64 (0.5 * 1) ** i (0.5 * 1) ^ i32 (0.5 * f64) ^ f32 (0.5 * i) ^ i (0.5 + 0.5) * f32 (0.5 + 0.5) ^ i32 (0.5 + 1) ^ i (0.5 + f64) * f64 (0.5 + f64) / i32 (0.5 + i) ** i (0.5 + i) ^ i (0.5 + i64) ** f32 (0.5 + i64) / f32 (0.5 + i64) / i (0.5 - 0.5) * (i32 - 0.5) (0.5 - 0.5) * i64 (0.5 - 0.5) ** f32 (0.5 - 1) * i32 (0.5 - 1) ** f64 (0.5 - 1) ^ i64 (0.5 - f32) ** i (0.5 - f64) * i (0.5 - f64) / f32 (0.5 - f64) / f64 (0.5 - i) ^ f32 (0.5 - i32) ** (i32 * 1) (0.5 - i32) / f64 (0.5 - i32) ^ f32 (0.5 - i64) * i (0.5 - i64) / f64 (0.5 - i64) / i64 (0.5 / 0.5) ** f32 (0.5 / 0.5) ** i32 (0.5 / 0.5) ^ f64 (0.5 / 1) ^ f32 (0.5 / i) ** f64 (0.5 / i) ** i (0.5 / i32) ** i (0.5 / i32) ^ f32 (1 * 0.5) ** (f64 * 1) (1 * 0.5) ** i32 (1 * 0.5) ^ f64 (1 * 1) ^ -1 (1 * 1) ^ f32 (1 * f32) ^ i32 (1 * i) ** i32 (1 * i32) ^ i (1 * i64) ** i64 (1 + 0.5) ** i (1 + 1) * i64 (1 + 1) / i (1 + f32) ^ i (1 + f64) ^ i (1 + f64) ^ i32 (1 + i) ** f32 (1 + i) / f64 (1 + i) ^ i64 (1 + i32) * f64 (1 + i32) ^ f64 (1 - 0.5) * f32 ^ 1 (1 - 0.5) * i64 (1 - 0.5) / i (1 - 0.5) ^ min(f32) (1 - f32) * f32 (1 - f64) ** f64 (1 - i) * -i32 (1 - i32) ^ f32 (1 - i32) ^ i (1 - i64) ** f32 (1 - i64) / f64 (1 - i64) / i64 (1 / 0.5) ** f32 (1 / 0.5) ^ i32 (1 / 1) ** (f64 * 0.5) (1 / 1) ^ ceil(i64) (1 / 1) ^ max(0.5) (1 / f32) ^ f32 (1 / i) ^ f32 (1 / i32) ^ i (1 / i64) ** i64 (f32 * 0.5) ** f64 (f32 * 0.5) ^ i32 (f32 * f32) ^ -f32 (f32 * f32) ^ i (f32 * i) ^ -1 (f32 * i64) ** i (f32 + f64) * i (f32 + i) ^ f64 (f32 - 0.5) / f64 (f32 - 0.5) ^ f32 (f32 - 1) / f64 (f32 - 1) ^ f64 (f32 - f32) / i64 (f32 - i32) * i64 (f32 / 0.5) ^ f32 (f32 / i64) ^ f64 (f64 * 0.5) ** f32 (f64 * 0.5) ** i64 (f64 * f32) ** f64 (f64 * i64) ** f64 (f64 * i64) ** i32 (f64 + 0.5) * f32 (f64 + 0.5) * i64 (f64 + f32) ** get(array, i) (f64 + f32) ** i32 (f64 + f64) * (i64 - i64) (f64 + f64) ^ f64 (f64 + i) * (0.5 + i64) (f64 + i32) ^ i64 (f64 + i64) ^ i (f64 - 0.5) ** f64 (f64 - 1) ** i64 (f64 - 1) ^ i32 (f64 - f32) ** i (f64 - f32) ^ i64 (f64 - i) * i32 (f64 - i32) / i (f64 - i64) ** i (f64 - i64) / f32 (f64 - i64) / f64 (f64 / 1) ** i64 (f64 / f32) ^ i (f64 / f64) ** i32 (f64 / f64) ^ i32 ** 0.5 (false || ok) == ok (i % i) ^ i (i % i32) ^ (1 - i32) (i % i64) ^ f64 (i * 0.5) ** f32 (i * 1) ^ f64 (i * 1) ^ i (i * i64) ** f32 (i + 0.5) ** half(f64) (i + 1) % i64 (i + 1) / i64 (i + i) ^ i64 (i + i32) * i64 ^ f64 (i + i32) / i32 (i + i32) ^ f32 (i + i64) ^ i32 (i - 0.5) / i64 (i - 1) ^ i64 (i / 0.5) ** f32 (i / f32) ^ f64 (i32 % 1) ** f32 (i32 % i) ** f32 (i32 % i32) ** i32 (i32 % i32) ^ i32 (i32 * 0.5) ^ f32 (i32 * 1) ^ i32 (i32 + 0.5) ** i64 (i32 + f32) * i64 (i32 + f64) / i (i32 + i) / i (i32 + i32) ^ i32 (i32 - 0.5) * f64 (i32 - 0.5) / i64 (i32 - 1) ^ f64 (i32 - f32) / i64 (i32 - i) % i64 (i32 - i) / f32 (i32 - i32) ^ (i32 * i) (i32 - i64) * i32 (i32 - i64) * i32 * i64 (i32 / i) ** f32 (i32 / i) ^ i64 (i32 < f64 ? nil : i) .. i32 (i32 not in array) and ok (i64 % i) ** f32 (i64 * 0.5) ^ f64 (i64 * f32) ^ i64 (i64 * f64) ^ i32 (i64 * i) ** score(1) (i64 * i64) ** i ** 0.5 (i64 * i64) ^ i (i64 + 0.5) * f32 (i64 + 0.5) ** i64 (i64 + 1) % i (i64 + 1) ^ i (i64 + f32) * -i32 (i64 + f32) ** i32 (i64 + f32) / f64 (i64 + f32) / i (i64 + f32) / i32 (i64 + f64) * i32 (i64 + i) % i64 (i64 + i) / f64 (i64 + i32) * i64 (i64 + i64) / i64 (i64 - 0.5) / f64 (i64 - 0.5) ^ i64 (i64 - 1) ^ i32 (i64 - f32) ** f64 (i64 - f32) ^ i64 (i64 - i) ** i (i64 - i32) * i64 (i64 / 1) ** f32 (i64 / f64) ** i32 (nil not in array) || ok (ok || true) && (ok or true) -((i64 + 1) % i32) -(0.5 * 0.5) -(0.5 * 1) -(0.5 * f32) -(0.5 * f64) -(0.5 * i) -(0.5 * i32) -(0.5 * i64) -(0.5 ** 0.5) -(0.5 ** 1) -(0.5 ** f32) -(0.5 ** f64) -(0.5 ** i) -(0.5 ** i32) -(0.5 ** i64) -(0.5 + 0.5) -(0.5 + 1) -(0.5 + f32) -(0.5 + f64) -(0.5 + i) -(0.5 + i32) -(0.5 + i64) -(0.5 - 0.5) -(0.5 - 1) -(0.5 - f32) -(0.5 - f64) -(0.5 - i) -(0.5 - i32) -(0.5 - i64) -(0.5 / 0.5) -(0.5 / 1) -(0.5 / f32) -(0.5 / f64) -(0.5 / i) -(0.5 / i32) -(0.5 / i64) -(0.5 ^ 0.5) -(0.5 ^ 1) -(0.5 ^ f32) -(0.5 ^ f64) -(0.5 ^ i) -(0.5 ^ i32) -(0.5 ^ i64) -(1 % 1) -(1 % i) -(1 % i32) -(1 % i64) -(1 * 0.5) -(1 * 1) -(1 * f32) -(1 * f64) -(1 * i) -(1 * i32) -(1 * i64) -(1 ** 0.5) -(1 ** 1) -(1 ** f32) -(1 ** f64) -(1 ** i) -(1 ** i32) -(1 ** i64) -(1 + 0.5) -(1 + 1) -(1 + f32) -(1 + f64) -(1 + i) -(1 + i32) -(1 + i64) -(1 - 0.5) -(1 - 1) -(1 - f32) -(1 - f64) -(1 - i) -(1 - i32) -(1 - i64) -(1 / 0.5) -(1 / 1) -(1 / f32) -(1 / f64) -(1 / i) -(1 / i32) -(1 / i64) -(1 ^ 0.5) -(1 ^ 1) -(1 ^ f32) -(1 ^ f64) -(1 ^ i) -(1 ^ i32) -(1 ^ i64) -(f32 * 0.5) -(f32 * 1) -(f32 * f32) -(f32 * f64) -(f32 * i) -(f32 * i32) -(f32 * i64) -(f32 ** 0.5) -(f32 ** 1) -(f32 ** f32) -(f32 ** f64) -(f32 ** i) -(f32 ** i32) -(f32 ** i64) -(f32 + 0.5) -(f32 + 1) -(f32 + f32) -(f32 + f64) -(f32 + i) -(f32 + i64) -(f32 - 0.5) -(f32 - 1) -(f32 - f32) -(f32 - i) -(f32 - i32) -(f32 - i64) -(f32 / 0.5) -(f32 / 1) -(f32 / f32) -(f32 / f64) -(f32 / i) -(f32 / i32) -(f32 / i64) -(f32 ^ 0.5) -(f32 ^ 1) -(f32 ^ f32) -(f32 ^ f64) -(f32 ^ i) -(f32 ^ i32) -(f32 ^ i64) -(f64 * 0.5) -(f64 * 1) -(f64 * f32) -(f64 * f64) -(f64 * i) -(f64 * i32) -(f64 * i64) -(f64 ** 0.5) -(f64 ** 1) -(f64 ** f32) -(f64 ** f64) -(f64 ** i) -(f64 ** i32) -(f64 ** i64) -(f64 + 0.5) -(f64 + 1) -(f64 + f32) -(f64 + i) -(f64 + i32) -(f64 + i64) -(f64 - 0.5) -(f64 - 1) -(f64 - f32) -(f64 - f64) -(f64 - i) -(f64 - i64) -(f64 / 0.5) -(f64 / 1) -(f64 / f32) -(f64 / f64) -(f64 / i) -(f64 / i64) -(f64 ^ 0.5) -(f64 ^ 1) -(f64 ^ f32) -(f64 ^ f64) -(f64 ^ i) -(f64 ^ i32) -(f64 ^ i64) -(i % 1) -(i % i) -(i % i32) -(i % i64) -(i * 0.5) -(i * 1) -(i * f32) -(i * f64) -(i * i) -(i * i32) -(i * i64) -(i ** 0.5) -(i ** 1) -(i ** f64) -(i ** i) -(i ** i32) -(i ** i64) -(i + 0.5) -(i + 1) -(i + i32) -(i + i64) -(i - 0.5) -(i - 1) -(i - f32) -(i - f64) -(i - i ** 1) -(i - i) -(i - i32) -(i - i64) -(i / 0.5) -(i / 1) -(i / f32) -(i / f64) -(i / i) -(i / i32) -(i / i64) -(i ^ 0.5) -(i ^ 1) -(i ^ f32) -(i ^ f64) -(i ^ i) -(i ^ i32) -(i ^ i64) -(i32 % 1) -(i32 % i) -(i32 % i32) -(i32 % i64) -(i32 * 0.5) -(i32 * 1) -(i32 * f32) -(i32 * f64) -(i32 * i) -(i32 * i32) -(i32 * i64) -(i32 ** 0.5) -(i32 ** 1) -(i32 ** f32) -(i32 ** f64) -(i32 ** i) -(i32 ** i32) -(i32 ** i64) -(i32 + 0.5) -(i32 + 1) -(i32 + f32) -(i32 + f64) -(i32 + i) -(i32 + i32) -(i32 + i64) -(i32 - 0.5) -(i32 - 1) -(i32 - f32) -(i32 - f64) -(i32 - i) -(i32 - i32) -(i32 - i64) -(i32 / 0.5) -(i32 / 1) -(i32 / f64) -(i32 / i) -(i32 / i32) -(i32 / i64) -(i32 ^ 0.5) -(i32 ^ 1) -(i32 ^ f32) -(i32 ^ f64) -(i32 ^ i) -(i32 ^ i32) -(i32 ^ i64) -(i64 % 1) -(i64 % i) -(i64 % i32) -(i64 % i64) -(i64 * 0.5) -(i64 * 1) -(i64 * f32) -(i64 * f64) -(i64 * i) -(i64 * i32) -(i64 * i64) -(i64 ** 0.5) -(i64 ** 1) -(i64 ** f32) -(i64 ** f64) -(i64 ** i) -(i64 ** i32) -(i64 ** i64) -(i64 + 0.5) -(i64 + 1) -(i64 + f32) -(i64 + f64) -(i64 + i32) -(i64 + i64) -(i64 - 0.5) -(i64 - 1) -(i64 - f32) -(i64 - f64) -(i64 - i) -(i64 - i32) -(i64 - i64) -(i64 / 0.5) -(i64 / 1) -(i64 / f32) -(i64 / f64) -(i64 / i) -(i64 / i32) -(i64 / i64) -(i64 ^ 0.5) -(i64 ^ 1) -(i64 ^ f32) -(i64 ^ f64) -(i64 ^ i) -(i64 ^ i32) -(i64 ^ i64) -(max(f32) ^ i32) -(min(0.5) ^ i32) --(f64 ** 0.5) --(i64 ** i64) --0.5 --1 --ceil(1) --f32 --f64 --f64 ** i64 --float(f64) --i --i32 --i64 -0.5 != f32 -0.5 != i32 -0.5 * 1 ** 1 -0.5 * f32 -0.5 * f64 -0.5 * i32 -0.5 * i64 -0.5 ** -1 -0.5 ** ceil(i) -0.5 ** f32 -0.5 ** f64 -0.5 ** i -0.5 ** i32 -0.5 ** i64 -0.5 + f64 -0.5 + i -0.5 + i32 -0.5 + i64 -0.5 - abs(i) -0.5 - f32 -0.5 - f64 -0.5 - i -0.5 - i32 -0.5 - i64 -0.5 / f32 -0.5 / i -0.5 / i32 -0.5 < i32 -0.5 < i64 -0.5 <= 0.5 + 0.5 -0.5 <= f32 -0.5 <= i -0.5 <= i32 -0.5 <= i64 -0.5 == f32 -0.5 == f64 -0.5 == i -0.5 == i32 -0.5 == i32 ^ i32 -0.5 == i64 -0.5 > f32 -0.5 > i -0.5 >= f32 -0.5 >= f32 ? f32 : i32 -0.5 >= f64 -0.5 >= i -0.5 >= i32 -0.5 >= i64 -0.5 ^ f32 -0.5 ^ f64 -0.5 ^ float(f64) -0.5 ^ i32 -0.5 ^ i64 -0.5 in array -0.5 not in sort(array) -1 != -i -1 != f32 -1 != f64 -1 != i32 -1 != i64 -1 % i -1 % i32 -1 * array[i] -1 * f32 -1 * f64 -1 * i -1 * i32 -1 * i64 -1 ** (f32 + f32) -1 ** (i + i64) -1 ** ceil(0.5) -1 ** f32 -1 ** f64 -1 ** i -1 ** i64 ^ 1 -1 + -i32 -1 + f32 -1 + f64 -1 + i -1 + i32 -1 + i64 -1 + reduce(array, #) -1 + reduce(list, f32) -1 - f64 -1 - i -1 - i % i32 -1 - i32 -1 - i64 -1 .. i -1 .. i64 -1 / f32 -1 / f64 -1 / i -1 / i32 -1 < f64 -1 < i -1 < i64 -1 <= -1 -1 <= f64 -1 <= i -1 <= i32 -1 <= i64 -1 == f32 -1 == f64 -1 == floor(f64) -1 == i -1 == i32 -1 == i64 -1 > f32 -1 > i -1 > i64 -1 >= f32 * f32 -1 >= f64 -1 >= i32 -1 >= i64 -1 ^ f32 -1 ^ f64 -1 ^ i32 -1 ^ i64 -1 in array -1 not in array -abs(0.5) -abs(1) -abs(f32) -abs(f64) -abs(i) -abs(i32) -abs(i64) -add(i, 1) -add(i, i) -array[1] -array[i32] -array[i64] -array[i] -bitand(i64, i32) -bitnand(1, i) -bitnot(1) -bitnot(i) -bitnot(i32) -bitnot(i64) -bitor(1, i64) -bitor(i, i32) -bitshl(i, 1) -bitshl(i, i32) -bitshl(i, i64) -bitshl(i64, i32) -bitshr(i, i) -bitshr(i64, i32) -bitushr(i, i32) -bitxor(1, 1) -bitxor(i, i32) -ceil(0.5) -ceil(1) -ceil(f32) -ceil(f64) -ceil(i) -ceil(i32) -ceil(i64) -count(array, false) -count(array, ok) -count(array, true) -count(list, ok) -count(list, true) -div(1, 1) -f32 -f32 != i32 -f32 * i64 -f32 ** (i + 1) -f32 ** f32 -f32 ** f64 -f32 ** i -f32 ** i32 -f32 ** i64 -f32 + i32 -f32 - i -f32 - round(i) -f32 / f32 -f32 / f64 -f32 / i -f32 < f32 ** 0.5 -f32 < f64 -f32 < i -f32 < i32 -f32 <= f32 -f32 <= i -f32 <= i32 -f32 <= i64 -f32 == f32 -f32 == f64 -f32 > 0.5 ? f32 : "bar" -f32 > f32 -f32 > f64 -f32 >= f32 -f32 >= f64 -f32 >= i64 -f32 ^ i -f32 ^ i32 -f32 ^ i64 -f32 in array -f32 not in array -f64 -f64 != f32 -f64 != f64 -f64 != i -f64 != i32 -f64 * -1 -f64 * -f64 -f64 * f32 -f64 * f64 -f64 * i -f64 * i32 -f64 * i64 -f64 ** 0.5 ** f32 -f64 ** f32 -f64 ** i -f64 ** i32 -f64 + f32 -f64 + i64 -f64 - 0.5 / i64 -f64 - f32 -f64 - i -f64 - i32 -f64 - i64 -f64 - int(f64) -f64 / f32 -f64 / f64 -f64 / i -f64 / i32 -f64 / i64 -f64 < 0.5 ^ f32 -f64 < f64 -f64 < f64 ** 1 -f64 < half(0.5) -f64 < half(f64) -f64 < i -f64 < i ^ f32 -f64 < i32 -f64 < i64 -f64 <= f32 -f64 <= f64 -f64 == f64 -f64 == i -f64 == i32 -f64 == i64 -f64 > f32 -f64 > f32 ? false : array -f64 > f64 -f64 > i32 -f64 > i64 -f64 >= f32 -f64 >= f32 / f64 -f64 >= f64 -f64 >= i32 -f64 ^ f32 -f64 ^ f64 -f64 ^ i64 -f64 not in array -find(array, ok) -find(array, true) -findIndex(array, # <= #) -findIndex(array, ok) -findIndex(array, true) -findIndex(list, ok) -findIndex(list, true) -findLast(array, # <= #) -findLast(array, ok) -findLast(array, true) -findLastIndex(array, ok) -findLastIndex(array, true) -findLastIndex(list, ok) -findLastIndex(list, true) -first(array) -float(0.5 ** 0.5) -float(0.5 ^ 0.5) -float(0.5) -float(1) -float(bitnot(i64)) -float(f32) -float(f64) -float(i) -float(i32) -float(i64) -floor(0.5) -floor(1) -floor(f32) -floor(f64) -floor(i) -floor(i32) -floor(i64) -get(array, 1) -get(array, i) -get(array, i32) -get(array, i64) -half(-0.5) -half(-1) -half(0.5) -half(1) -half(f32 + i64) -half(f64) -half(median(array)) -i -i != f32 -i != f64 -i != f64 ? foo : 1 -i != i -i != i + f64 -i != i32 -i != i64 -i % i32 -i % i64 -i * abs(0.5) -i * f64 -i * i -i * i64 -i * reduce(array, 0.5) -i ** f32 -i ** f64 -i ** i -i + f32 -i + f64 -i + i32 -i + i64 * 1 -i - f32 -i - i64 -i .. i -i .. i64 -i / f32 -i / i64 -i < f32 -i < half(1) -i < i -i < i64 -i <= 0.5 ? half : "bar" -i <= 1 - 0.5 -i <= f32 -i <= i -i <= i32 -i <= i64 -i <= i64 ** 0.5 -i == f32 -i == f64 -i == f64 ^ f32 -i == i -i == i32 -i > f32 -i > i -i > i32 -i >= f32 -i >= f64 -i >= i -i >= i64 -i >= score(1) -i ^ 0.5 ** 0.5 -i ^ f32 -i ^ f32 ^ 0.5 -i ^ f64 -i ^ i -i ^ i64 -i in array -i not in array -i32 -i32 != f32 -i32 != i -i32 != i32 ** 1 -i32 != i64 -i32 % i -i32 % i32 -i32 % i64 -i32 * i -i32 * i32 -i32 * i64 -i32 ** f32 -i32 ** f64 -i32 ** i64 -i32 + f32 -i32 + i -i32 + i32 -i32 - f32 -i32 .. i32 -i32 / i32 -i32 / i64 -i32 < i -i32 < i32 -i32 < i64 -i32 < round(f64) -i32 <= f64 -i32 <= i -i32 <= i32 -i32 <= i64 -i32 == 1 % i -i32 == f32 -i32 == f64 -i32 == i64 -i32 == max(1) -i32 > f32 -i32 > f64 -i32 > i -i32 > i ** 0.5 -i32 > i32 -i32 > i64 -i32 >= f64 -i32 >= i -i32 >= i == nil -i32 >= i32 -i32 ^ f32 -i32 ^ i32 -i32 ^ i64 -i32 ^ score(1) -i32 in array -i64 -i64 != f32 -i64 != f64 -i64 != i32 -i64 != i64 -i64 != i64 ? score : foo -i64 * (1 + f64) -i64 * f32 -i64 * i -i64 * i32 -i64 * i64 -i64 * indexOf("foo", "bar") -i64 ** i -i64 ** i32 -i64 + f32 -i64 + i -i64 + i32 -i64 + i64 -i64 - f32 -i64 - i -i64 - i32 -i64 .. i -i64 .. i32 -i64 .. i64 -i64 / f64 -i64 / i32 -i64 < f32 -i64 < f64 -i64 < half(f64) -i64 < i32 -i64 < i64 -i64 <= i -i64 <= i32 -i64 == 1 ^ i64 -i64 == f32 -i64 == f64 -i64 == i -i64 == i32 -i64 > f32 -i64 > f64 -i64 > i -i64 > i32 -i64 >= f32 -i64 >= i -i64 >= i32 -i64 ^ f64 -i64 ^ float(i) -i64 ^ i -i64 ^ i32 -i64 ^ i64 -i64 in array -i64 not in array -int(0.5) -int(1) -int(f32) -int(f64) -int(i) -int(i32) -int(i64) -last(array) -len("bar") -len("foo") -len(array) -len(list) -max(0.5) -max(0.5, 0.5, f64) -max(1) -max(f32) -max(f64) -max(i) -max(i, 0.5) -max(i32 - 1) -max(i32) -max(i32, f32) -max(i64 * 0.5) -max(i64) -max(i64, f64) -max(i64, i) -mean(array) -median(array) -min(-1) -min(0.5) -min(1) -min(1, 0.5) -min(f32) -min(f32, 1) -min(f64) -min(float(0.5)) -min(i) -min(i, 1) -min(i32) -min(i32, 0.5) -min(i64) -min(i64, i, 0.5) -reduce(array, #) -reduce(array, -#) -reduce(array, 0.5) -reduce(array, 1) -reduce(array, 1) - f32 -reduce(array, f64) -reduce(array, i) -reduce(array, i32) -reduce(array, i64) -reduce(list, 0.5) -reduce(list, 1) -reduce(list, f32) -reduce(list, f64) -reduce(list, i) -reduce(list, i32) -round(0.5) -round(1) -round(f32) -round(f64) -round(i) -round(i32) -round(i64) -score(1) -score(1, 1) -score(1, i) -score(i) -score(i32 + i) -score(int(i)) -sum(array) -sum(i .. 1) 0.5 != 0.5 == ok 0.5 != f64 ? list : f32 0.5 != f64 and !true 0.5 != f64 and ok 0.5 != i == ok 0.5 != i32 && ok 0.5 != i32 == ok 0.5 != i32 ? ok : ok 0.5 != i32 and 1 > f64 0.5 != nil == ok 0.5 * 0.5 * f64 0.5 * 0.5 / f32 0.5 * 0.5 / f64 0.5 * 0.5 < f64 0.5 * 0.5 >= i64 0.5 * 1 * i64 0.5 * 1 <= f32 0.5 * 1 > i32 0.5 * 1 not in array 0.5 * f32 * f32 0.5 * f32 * i32 0.5 * f32 + f32 0.5 * f32 - f64 0.5 * f32 / half(1) 0.5 * f32 == i32 0.5 * f32 > i 0.5 * f64 != i64 0.5 * f64 < i 0.5 * f64 <= i 0.5 * i + i 0.5 * i + mean(array) 0.5 * i - i32 0.5 * i == 0.5 ? ok : ok 0.5 * i32 / f32 0.5 * i64 < f64 0.5 * i64 == 1 ** i64 0.5 ** 0.5 != i64 0.5 ** 0.5 * max(1) 0.5 ** 0.5 ** i64 0.5 ** 0.5 + -f32 0.5 ** 0.5 < f64 0.5 ** 0.5 == i 0.5 ** 0.5 ^ f32 0.5 ** 0.5 not in array 0.5 ** 1 != i 0.5 ** 1 != i32 0.5 ** 1 - f64 0.5 ** 1 / f64 0.5 ** 1 / i32 0.5 ** 1 ^ i64 0.5 ** f32 + f32 / i64 0.5 ** f32 <= f32 0.5 ** f32 ^ i 0.5 ** f64 * f64 0.5 ** f64 > f64 ? 1 : nil 0.5 ** f64 >= i64 0.5 ** i / i 0.5 ** i > i 0.5 ** i32 * i32 0.5 ** i32 > f64 0.5 ** i32 >= mean(array) 0.5 + 0.5 != i 0.5 + 0.5 == i32 0.5 + 0.5 > f32 0.5 + 1 != f64 0.5 + 1 + i32 0.5 + 1 - i32 0.5 + 1 < float(1) 0.5 + 1 == f32 0.5 + f32 - i64 0.5 + f32 <= ceil(f32) 0.5 + f32 <= i32 0.5 + f32 > f32 0.5 + f64 != i64 0.5 + f64 <= i32 0.5 + f64 == 1 / 0.5 0.5 + i + i 0.5 + i > i64 0.5 + i in array 0.5 + i32 - i64 0.5 + i32 <= f32 0.5 + i64 - i 0.5 + i64 > i64 * 0.5 0.5 - 0.5 - i32 0.5 - 0.5 >= f32 0.5 - 0.5 >= i 0.5 - 0.5 >= i32 0.5 - 1 + i 0.5 - 1 + i / i 0.5 - 1 <= f64 0.5 - f32 != i64 0.5 - f32 >= i64 0.5 - f64 - f32 0.5 - f64 < i 0.5 - f64 in array 0.5 - i != i64 0.5 - i + i 0.5 - i > f32 0.5 - i32 != f32 0.5 - i64 + -f64 0.5 - i64 == i 0.5 - i64 not in array 0.5 / 0.5 + i 0.5 / 0.5 - i 0.5 / 0.5 - i32 0.5 / 0.5 - i64 0.5 / 0.5 / half(0.5) 0.5 / 0.5 < i32 0.5 / 0.5 == i64 0.5 / 0.5 >= f32 0.5 / 0.5 >= f64 0.5 / 1 * i 0.5 / 1 / f64 0.5 / 1 < f64 0.5 / 1 == i 0.5 / 1 > f32 0.5 / 1 >= i32 0.5 / 1 not in array 0.5 / f32 * f64 0.5 / f64 + f64 0.5 / f64 - i 0.5 / f64 / f64 0.5 / f64 < i 0.5 / f64 == f32 0.5 / i != i64 0.5 / i * i64 0.5 / i / i32 0.5 / i <= i 0.5 / i32 + i64 0.5 / i32 > i ^ i 0.5 / i32 > i64 0.5 / i32 >= f64 0.5 / i64 != f64 0.5 / i64 != i 0.5 / i64 != min(f32) 0.5 / i64 * i32 0.5 < 0.5 ? f32 : array 0.5 < 0.5 ? foo : greet 0.5 < 1 == ok 0.5 < 1 || ok 0.5 < f32 && ok 0.5 < f32 || ok 0.5 <= f64 ? i : i64 0.5 <= f64 || ok 0.5 == 1 and ok 0.5 == 1 || ok 0.5 == array[ok ? 0.5 : score] 0.5 == f32 and i64 == i32 0.5 == f64 ? i : (false ? i : i64) 0.5 == f64 and i64 == 0.5 0.5 == i or ok 0.5 == i32 and ok 0.5 == i64 and ok 0.5 == nil or "foo" endsWith "bar" 0.5 == nil or ok 0.5 == nil || ok 0.5 > 0.5 == ok 0.5 > array[i64] 0.5 > f32 and ok 0.5 > i && 0.5 < i64 0.5 > i64 ? -i : array 0.5 >= 0.5 ? array[i64] : f32 0.5 >= 0.5 and ok 0.5 >= i && 1 < 0.5 0.5 >= i32 == ok 0.5 >= i32 and ok 0.5 ^ 0.5 == f64 0.5 ^ 0.5 >= i32 0.5 ^ 0.5 >= i64 0.5 ^ 1 ** i64 0.5 ^ 1 - f32 0.5 ^ 1 < f32 0.5 ^ 1 < i 0.5 ^ 1 <= i32 0.5 ^ 1 > f64 / 1 0.5 ^ 1 >= i 0.5 ^ f32 * i 0.5 ^ f32 ** i64 0.5 ^ f32 <= i32 0.5 ^ f32 > i64 0.5 ^ f32 >= i 0.5 ^ f64 - i64 0.5 ^ f64 / f32 0.5 ^ f64 < f32 0.5 ^ f64 > i32 0.5 ^ i != f64 0.5 ^ i * reduce(array, i) 0.5 ^ i ** floor(0.5) 0.5 ^ i / (0.5 + i32) 0.5 ^ i < -f64 0.5 ^ i <= i32 0.5 ^ i >= i64 0.5 ^ i32 * reduce(list, f64) 0.5 ^ i32 ** f32 0.5 ^ i32 < f32 ? ok : i32 0.5 ^ i32 == i64 0.5 ^ i32 ^ f64 0.5 ^ i32 in array 0.5 ^ i64 * i 0.5 ^ i64 ** i 0.5 ^ i64 ** i64 0.5 ^ i64 > i32 0.5 in array != ok 0.5 in array && ok 1 != 0.5 != ok 1 != 0.5 and 1 == 1 1 != 1 && ok 1 != 1 ? f64 : 0.5 > i 1 != 1 ? list : score 1 != f32 != ok 1 != f32 ? ok : half 1 != i or ok 1 != i64 ? add : div 1 != nil && ok 1 != nil == ok 1 != nil or not false 1 % 1 != i 1 % 1 != i32 1 % 1 % i 1 % 1 / f32 1 % 1 / i32 1 % 1 < f64 1 % 1 < i 1 % 1 == f64 1 % 1 == i ? nil : 0.5 1 % 1 == i32 1 % array[i32] 1 % array[i] 1 % i != -i64 1 % i != 1 != nil 1 % i - i64 1 % i < i32 1 % i >= f64 1 % i >= i 1 % i not in array 1 % i32 != i 1 % i32 <= f32 1 % i32 > i64 1 % i32 >= f64 1 % i64 - f32 1 % i64 < score(i) 1 % i64 > f32 1 * 0.5 + f64 1 * 0.5 + i32 1 * 0.5 + round(f64) 1 * 0.5 / i 1 * 0.5 / i64 1 * 0.5 < i64 1 * 0.5 == f32 1 * 0.5 >= f32 1 * 1 - i32 1 * 1 <= int(i) 1 * 1 >= f32 1 * f32 != f64 - 0.5 1 * f32 <= reduce(array, #) 1 * f32 >= f64 1 * f64 * i64 1 * f64 <= i64 1 * f64 > i 1 * f64 >= f64 1 * i * f32 1 * i - i32 1 * i / f64 1 * i < f32 1 * i > i32 1 * i not in array 1 * i32 + i32 1 * i32 - i 1 * i32 < i 1 * i64 * f32 1 * i64 + i 1 * i64 - f64 1 * i64 / f64 1 * i64 <= f64 1 * i64 in array 1 ** 0.5 * i 1 ** 0.5 ** f32 1 ** 0.5 ** f64 1 ** 0.5 ** i64 1 ** 0.5 - f32 1 ** 0.5 - i32 1 ** 0.5 - i64 1 ** 0.5 < -f32 1 ** 0.5 > i 1 ** 0.5 > i64 1 ** 0.5 ^ f64 1 ** 1 ** f64 1 ** 1 + f64 1 ** 1 + i64 1 ** 1 - round(0.5) 1 ** 1 / f64 1 ** 1 < f32 1 ** 1 == 0.5 + i32 1 ** 1 >= i 1 ** 1 >= i32 1 ** 1 ^ i 1 ** 1 ^ i32 1 ** 1 in array 1 ** array[i32] 1 ** f32 / i32 1 ** f32 / i64 1 ** f32 <= f32 1 ** f32 <= i64 1 ** f32 == i64 ? i32 : array 1 ** f32 >= f32 1 ** f32 >= i 1 ** f32 ^ f32 1 ** f32 ^ i64 1 ** i + i32 1 ** i >= i 1 ** i32 != i32 1 ** i32 + f32 1 ** i32 + i64 1 ** i64 <= f32 1 ** i64 <= f64 1 ** i64 <= i32 1 ** i64 > f32 1 + 0.5 != i32 1 + 0.5 + i 1 + 0.5 - i64 1 + 0.5 < f32 1 + 0.5 < i 1 + 0.5 == f64 1 + 0.5 == f64 != nil 1 + 0.5 > i64 1 + 0.5 not in array 1 + 1 != 0.5 ? 0.5 : half 1 + 1 - f32 1 + 1 - i 1 + 1 < i 1 + 1 == f64 * i64 1 + 1 > f32 1 + 1 >= half(0.5) 1 + 1 >= i 1 + f32 != i32 1 + f32 < i32 1 + f32 <= i 1 + f32 > i64 1 + f64 == i64 1 + f64 >= f64 1 + i .. i32 1 + i <= ceil(f32) 1 + i <= f64 1 + i >= min(i64) 1 + i32 != i32 1 + i32 - f64 1 + i32 < f32 1 + i32 < i32 1 + i32 <= f64 1 + i32 > reduce(array, #) 1 + i32 >= f64 1 + i64 != i32 1 + i64 != i64 1 + i64 < i32 1 + i64 <= i64 1 - 0.5 != f32 1 - 0.5 + i 1 - 0.5 - f32 1 - 0.5 <= i32 1 - 0.5 <= i64 1 - 1 < i64 ? 0.5 : "foo" 1 - 1 <= i32 + i64 1 - 1 == f64 1 - 1 > i32 / i32 1 - f32 != f32 1 - f32 <= i64 1 - f64 != f32 1 - f64 + f32 1 - f64 + i - 0.5 1 - f64 <= i 1 - f64 in array 1 - f64 not in array 1 - i > f64 1 - i > i 1 - i > i32 1 - i >= i64 1 - i not in array 1 - i32 < i32 1 - i32 < i64 1 - i32 == i32 1 - i64 <= i32 1 .. i != list 1 / 0.5 <= abs(f32) 1 / 0.5 <= i32 1 / 0.5 == f64 1 / 0.5 > f32 1 / 0.5 >= i 1 / 0.5 >= i - i 1 / 0.5 >= i32 1 / 1 != i32 1 / 1 * f32 1 / 1 <= f64 1 / 1 in array 1 / f32 != f64 1 / f32 / i64 1 / f32 <= f32 1 / f32 <= f64 1 / f32 == i32 1 / f32 == i32 / i 1 / f32 > f32 1 / f32 >= f64 1 / f64 + f64 1 / f64 < f32 1 / f64 == f64 1 / i * f32 1 / i / f64 1 / i < i 1 / i == f64 1 / i >= i32 1 / i in map(list, 1) 1 / i32 > f32 1 / i32 >= i64 1 / i64 * i 1 / i64 > f32 / f64 1 / i64 > f64 1 / i64 >= f64 1 < 1 == ok 1 < 1 and ok 1 < array[get(array, i32)] 1 < array[i32] 1 < f32 != not true 1 < f64 || ok 1 < i ? array : foo 1 < i32 || 1 >= f32 1 < i64 == ok 1 < i64 ? ok : list 1 <= 1 == ok 1 <= 1 || add == add 1 <= f32 && ok 1 <= f64 || ok 1 <= i32 ? foo : f32 1 == 0.5 ? i32 : greet 1 == 0.5 and ok 1 == 1 || ok 1 == f64 && 0.5 != nil 1 == f64 || ok 1 == i32 && ok 1 == i32 == ok 1 == i64 == ok 1 == nil ? ok : half 1 > 0.5 == ok 1 > array[i64] 1 > f32 && ok 1 > f32 == reduce(array, ok) 1 > f64 != ok 1 > i == ok 1 > i64 or i != 1 1 >= 1 != (nil not in list) 1 >= f32 ? i64 : half 1 >= f64 ? ok : half 1 >= i and ok 1 ^ 0.5 != f32 1 ^ 0.5 != i 1 ^ 0.5 ** f32 1 ^ 0.5 ** i32 1 ^ 0.5 - i32 1 ^ 0.5 < i32 1 ^ 0.5 <= f64 1 ^ 0.5 == i 1 ^ 0.5 ^ f32 1 ^ 0.5 ^ i64 1 ^ 1 != f64 1 ^ 1 != i64 1 ^ 1 ** i 1 ^ 1 + f64 1 ^ 1 / i 1 ^ 1 < i 1 ^ 1 < i64 1 ^ 1 >= i 1 ^ 1 >= i32 1 ^ f32 < i32 1 ^ f32 <= f64 1 ^ f64 / f64 1 ^ f64 == f32 1 ^ f64 > f32 1 ^ f64 >= 1 / f64 1 ^ i != i * f32 1 ^ i - i32 1 ^ i < i 1 ^ i32 * i32 1 ^ i32 ** i64 1 ^ i32 / i 1 ^ i32 >= i32 1 ^ i32 >= i64 1 ^ i64 * i64 1 ^ i64 ** reduce(list, 1) 1 ^ i64 - i64 1 ^ i64 / f64 1 ^ i64 > i 1 ^ i64 >= i32 + i32 1 in array ? f32 : foo [!false] [!ok] [!true] ["bar" + "foo"] ["bar" < "bar"] ["bar" not contains "bar"] [-0.5] [-1] [-f32] [-f64] [-i64] [0.5 != f32] [0.5 != i] [0.5 * 0.5] [0.5 * f32] [0.5 ** i] [0.5 - 0.5] [0.5 - i] [0.5 / i32] [0.5 <= i32, half] [0.5 > 1] [0.5 > f32] [0.5 > i64] [0.5 >= f64] [0.5 ^ 0.5] [1 != 1] [1 * 0.5] [1 ** 0.5] [1 + i64, add] [1 == i64] [1 == i] [[f32]] [add != nil] [add, add] [add, f32] [add, i] [add] [all(list, false)] [any(list, ok)] [array, add] [array, array] [array, f32] [array, greet] [array, i64] [array, i] [array, list] [array, ok, add] [array, string(nil)] [array] [bitnot(1)] [ceil(i32)] [div(1, 1)] [div, add] [div, foo] [div, i32] [div, i64, array] [div] [f32 * i] [f32 + f64] [f32 >= i] [f32, f64] [f32, foo, greet] [f32, greet] [f32, i32] [f32, list] [f32, ok] [f32, score] [f32] [f64 + f64] [f64 / f64] [f64 < 0.5] [f64 < f32] [f64 < i64] [f64 <= 1] [f64 in array] [f64, add] [f64, f64] [f64, half] [f64, i64] [f64] [f64] == array [find(array, true)] [findIndex(list, false)] [findLast(list, ok)] [float(0.5)] [float(1)] [foo, add] [foo, array] [foo, half] [foo, i] [foo, ok] [foo, reduce(array, #)] [foo.Bar] [foo.Qux] [foo?.Bar, f32, f64] [foo?.Bar, i32] [foo?.Bar] [foo?.Qux] [foo?.String()] [foo] [greet != nil] [greet, array] [greet, div] [greet, foo] [greet, greet] [greet, half] [greet, i64] [greet, list] [greet] [greet] == list [groupBy(array, "bar")] [groupBy(array, #), half] [groupBy(array, #)] [groupBy(array, f64)] [groupBy(list, #)?.Qux] [half(0.5)] [half(f64)] [half(i64 ^ 1)] [half, array] [half, div] [half, f64] [half, i64 < f64] [half, list] [half] [i != i64] [i .. 1] [i / i] [i < i64, score] [i <= 0.5] [i == i32] [i >= i32] [i ^ 1] [i, array, list] [i, array] [i, greet("bar")] [i, greet] [i, i32] [i, i] [i, list] [i32 < i] [i32 > 1] [i32, -1] [i32, div] [i32, f64] [i32, i32] [i32, list] [i32, type(greet)] [i32] [i64 != f64] [i64 + 0.5] [i64 / f64] [i64 <= i64] [i64 >= 1] [i64 ^ 1] [i64, div] [i64, foo] [i64, half] [i64, score] [i64] [i] [list != nil] [list, div] [list, f32] [list, greet] [list, half] [list, i] [list, ok] [list] [map(array, #)] [map(array, add)] [map(array, f64)] [map(array, foo)] [max(1)] [nil != 0.5] [not false] [ok ? 1 : greet] [ok, f32] [ok, half] [ok, i64] [ok, i] [ok, list, 0.5] == list [ok, ok] [ok] [reduce(array, foo)] [reduce(list, #)] [reduce(list, div)] [score == nil] [score, div] [score, f32] [score, f64] [score, greet] [score, half] [score, one(array, # > i32)] [score, score] [score] [string(0.5)] [string(1)] [string(foo)] [string(i)] [string(i64)] [toJSON(list)] [trimPrefix("bar")] [true ? add : f64] [true and ok] [true || ok] [type(1)] [type(add)] [type(div)] [type(greet)] [type(nil)] abs(-0.5) abs(-1) abs(-f32) abs(-f64) abs(-i) abs(-i32) abs(-i64) abs(0.5 * 0.5) abs(0.5 * 1) abs(0.5 * i) abs(0.5 * i64) abs(0.5 ** 0.5) abs(0.5 ** 1) abs(0.5 ** i32) abs(0.5 + 0.5) abs(0.5 + 1) abs(0.5 + f32) abs(0.5 + i) abs(0.5 + i64) abs(0.5 - 0.5) abs(0.5 - 1) abs(0.5 - i) abs(0.5 - i32) abs(0.5 - i64) abs(0.5 / 0.5) abs(0.5 / 1) abs(0.5 / f64) abs(0.5 ^ 0.5) abs(0.5 ^ 1) abs(0.5 ^ f32) abs(0.5) - i32 abs(0.5) / f32 abs(0.5) < f64 abs(0.5) < i32 abs(0.5) <= i64 abs(0.5) == -0.5 abs(0.5) == half(1) abs(0.5) > i32 abs(0.5) >= f64 abs(0.5) ^ i64 abs(0.5) not in array abs(1 * f32) abs(1 * f64) abs(1 * i32) abs(1 ** 0.5) abs(1 ** 1) abs(1 ** i) abs(1 + 1) abs(1 + i) abs(1 + i64) abs(1 - 0.5) abs(1 - 1) abs(1 - i64) abs(1 / 0.5) abs(1 / 1) abs(1 / i) abs(1 / i32) abs(1 ^ f32) abs(1 ^ i) abs(1 ^ i32) abs(1) - i32 abs(1) .. i abs(1) / f64 abs(1) / i64 abs(1) < i64 abs(1) <= i32 abs(1) == i32 abs(1) >= i abs(1) ^ f64 abs(abs(0.5)) abs(abs(1)) abs(abs(f64)) abs(abs(i32)) abs(abs(i64)) abs(add(i, 1)) abs(bitand(i64, i32)) abs(bitnand(i64, i)) abs(bitnot(1)) abs(bitnot(i)) abs(bitnot(i32)) abs(bitnot(i64)) abs(bitushr(1, 1)) abs(ceil(0.5)) abs(ceil(1)) abs(ceil(f32)) abs(ceil(i)) abs(ceil(i32)) abs(ceil(i64)) abs(count(array, ok)) abs(count(array, true)) abs(count(list, false)) abs(div(i, i)) abs(f32 * 0.5) abs(f32 ** 1) abs(f32 ** f32) abs(f32 ** i32) abs(f32 + 0.5) abs(f32 + 1) abs(f32 + i) abs(f32 + i32) abs(f32 - 0.5) abs(f32 - 1) abs(f32 - i32) abs(f32 - i64) abs(f32 / 0.5) abs(f32 / 1) abs(f32 / f32) abs(f32 / f64) abs(f32 / i32) abs(f32 ^ i) abs(f32 ^ i64) abs(f32) abs(f32) ** f32 abs(f32) ** i abs(f32) + i64 abs(f32) - i32 abs(f32) / f64 abs(f32) < f64 abs(f32) >= 0.5 / 1 abs(f32) ^ f32 abs(f64 * f32) abs(f64 * f64) abs(f64 ** 1) abs(f64 + 0.5) abs(f64 + 1) abs(f64 + f64) abs(f64 - 1) abs(f64 - f32) abs(f64 / 0.5) abs(f64 / 1) abs(f64 / f64) abs(f64 / i) abs(f64 ^ 0.5) abs(f64 ^ f32) abs(f64 ^ i) abs(f64 ^ i64) abs(f64) abs(f64) + f32 abs(f64) + f64 abs(f64) + i32 abs(f64) + i64 / i abs(f64) - i abs(f64) < i32 abs(f64) <= f64 abs(f64) > i64 abs(f64) ^ f32 abs(f64) ^ i64 abs(f64) in array abs(false ? f32 : 1) abs(false ? half : 0.5) abs(false ? list : 1) abs(find(array, ok)) abs(find(array, true)) abs(findIndex(list, ok)) abs(findIndex(list, true)) abs(findLastIndex(array, ok)) abs(first(array)) abs(float(0.5)) abs(float(1)) abs(float(f32)) abs(float(f64)) abs(float(i)) abs(float(i32)) abs(floor(0.5)) abs(floor(f32)) abs(floor(i32)) abs(get(array, 1)) abs(get(array, i)) abs(get(array, i32)) abs(get(array, i64)) abs(half(0.5)) abs(half(1)) abs(half(f64)) abs(i * 1) abs(i * f32) abs(i ** 1) abs(i ** f32) abs(i ** i32) abs(i + 0.5) abs(i + f64) abs(i - 0.5) abs(i - 1) abs(i - f32) abs(i - f64) abs(i - i32) abs(i / 0.5) abs(i / f64) abs(i / i) abs(i / i32) abs(i / i64) abs(i ^ 0.5) abs(i ^ f64) abs(i ^ i) abs(i ^ i32) abs(i ^ i64) abs(i) abs(i) % i abs(i) * i32 abs(i) ** f32 abs(i) + f64 abs(i) - f32 abs(i) .. i abs(i) .. i32 abs(i) / f32 abs(i) < f64 abs(i) <= i64 abs(i) == 0.5 / i abs(i) > i64 abs(i) ^ f64 abs(i) ^ half(1) abs(i) ^ i abs(i) ^ i32 abs(i32 % i32) abs(i32 % i64) abs(i32 * f64) abs(i32 * i32) abs(i32 ** 0.5) abs(i32 ** 1) abs(i32 ** i32) abs(i32 + 0.5) abs(i32 + 1) abs(i32 + f64) abs(i32 + i) abs(i32 + i32) abs(i32 - 0.5) abs(i32 - i64) abs(i32 / 0.5) abs(i32 / i) abs(i32 / i64) abs(i32) abs(i32) != f64 abs(i32) * f32 abs(i32) * i abs(i32) ** i abs(i32) - i32 abs(i32) / -1 abs(i32) / i32 ** f64 abs(i32) < i64 == false abs(i32) <= i abs(i32) <= i32 abs(i32) == i32 abs(i32) ^ i64 abs(i32) in array abs(i64 * 0.5) abs(i64 * f32) abs(i64 * i32) abs(i64 ** 0.5) abs(i64 ** f64) abs(i64 ** i64) abs(i64 + 0.5) abs(i64 + 1) abs(i64 + f32) abs(i64 + f64) abs(i64 + i) abs(i64 - 0.5) abs(i64 - i) abs(i64 / f32) abs(i64 / i32) abs(i64 ^ f64) abs(i64 ^ i) abs(i64 ^ i32) abs(i64) abs(i64) * i32 abs(i64) ** i abs(i64) + f32 abs(i64) / i abs(i64) > i32 abs(i64) ^ i32 abs(i64) not in array abs(int(0.5)) abs(int(1)) abs(int(i)) abs(int(i32)) abs(int(i64)) abs(last(array)) abs(len("foo")) abs(len(list)) abs(max(0.5)) abs(max(f32)) abs(max(f64)) abs(max(i32)) abs(max(i64)) abs(mean(array)) abs(median(array)) abs(min(0.5)) abs(min(1)) abs(min(f32)) abs(min(f64)) abs(min(i)) abs(min(i32)) abs(ok ? 1 : "foo") abs(ok ? f32 : 0.5) abs(ok ? f32 : nil) abs(ok ? f64 : ok) abs(ok ? i32 : foo) abs(reduce(array, #)) abs(reduce(array, i)) abs(reduce(list, 1)) abs(reduce(list, i32)) abs(round(0.5)) abs(round(1)) abs(round(f32)) abs(round(i)) abs(round(i64)) abs(score(1)) abs(score(i)) abs(sum(array)) abs(true ? 1 : ok) add add != add add != add == nil add != div add != div != false add != div == true add != nil ? f64 : i64 add != reduce(list, add) add == add add == add != nil add == add == nil add == add ? 1 : i64 add == div add == div ? f64 : list add == nil ? false : i32 add == nil ? greet : i32 add == nil ? nil : nil add in sort(array) add(1, i) < i add(i, 1) ** f32 add(i, i) add(i, i32 + 1) all(1 .. i64, ok) all(["bar"], # >= #) all(["foo"], # not matches #) all([false], # && false) all([false], #) all(array, !(# >= f64)) all(array, !ok) all(array, !true) all(array, "foo" < "bar") all(array, # != #) all(array, # != 1) all(array, # != f32) all(array, # != f64) all(array, # != i32) all(array, # != nil) all(array, # < #) all(array, # < 0.5) all(array, # < 1) all(array, # < f64) all(array, # < i) all(array, # < i64) all(array, # <= #) all(array, # <= 0.5) all(array, # <= i) all(array, # == # + #) all(array, # == #) all(array, # == 0.5) all(array, # == 1) all(array, # == f64) all(array, # == i) all(array, # == i32) all(array, # == i64) all(array, # > #) all(array, # > 0.5) all(array, # > 1) all(array, # > f64) all(array, # > i) all(array, # > i32) all(array, # > i64) all(array, # >= #) all(array, # >= 0.5) all(array, # >= f32) all(array, # >= f64) all(array, # >= i32) all(array, # >= i64) all(array, # in array) all(array, 0.5 != #) all(array, 0.5 < #) all(array, 0.5 < f32) all(array, 0.5 <= #) all(array, 0.5 <= f32) all(array, 0.5 <= i) all(array, 0.5 > f32) all(array, 0.5 > f64) all(array, 0.5 > i32) all(array, 0.5 >= #) all(array, 0.5 >= 0.5) all(array, 0.5 in array) all(array, 1 != #) all(array, 1 != f32) all(array, 1 < #) all(array, 1 < f32) all(array, 1 == #) all(array, 1 > #) all(array, 1 > i64) all(array, 1 >= #) all(array, 1 >= 1) all(array, 1 >= i64) all(array, f32 < #) all(array, f32 <= #) all(array, f32 <= f32) all(array, f32 > i) all(array, f32 >= #) all(array, f64 != #) all(array, f64 <= #) all(array, f64 <= f32) all(array, f64 == #) all(array, f64 == 0.5) all(array, f64 == i64) all(array, f64 >= i64) all(array, false && true) all(array, false ? 1 : true) all(array, i != 0.5) all(array, i <= 0.5) all(array, i <= f32) all(array, i <= i32) all(array, i == #) all(array, i32 != #) all(array, i32 != i64) all(array, i32 < i) all(array, i32 >= #) all(array, i64 != #) all(array, i64 != i64) all(array, i64 == i32) all(array, i64 > #) all(array, i64 > 0.5) all(array, i64 >= #) all(array, nil != "bar") all(array, nil != #) all(array, nil != list) all(array, nil != ok) all(array, nil == "foo") all(array, nil == i32) all(array, nil == list) all(array, none(list, true)) all(array, not false) all(array, not true) all(array, ok) all(false ? add : "bar", ok) all(filter(array, true), ok) all(groupBy(array, f32).score, 0.5 in #?.f64) all(groupBy(list, #).i, #?.half() not in # + #) all(i32 .. 1, ok) all(list, !false) all(list, "bar" in #) all(list, "bar" not in #) all(list, "foo" > "foo") all(list, # != #) all(list, # != nil) all(list, # == # || f64 != i64) all(list, # == #) all(list, # == foo) all(list, # in list) all(list, # not in list) all(list, 0.5 < f64) all(list, 0.5 < i64) all(list, 0.5 <= i64) all(list, 0.5 >= i) all(list, 0.5 >= i32) all(list, 1 != 1) all(list, 1 <= 1) all(list, 1 > i32) all(list, 1 >= f64) all(list, add == div) all(list, all(array, ok)) all(list, div != nil) all(list, f64 != 0.5) all(list, f64 != f32) all(list, f64 < i32) all(list, f64 > i64) all(list, false ? i : true) all(list, i < f32) all(list, i <= 1) all(list, i <= i32) all(list, i > f64) all(list, i > i32) all(list, i >= 1) all(list, i32 < 1) all(list, i32 <= 0.5) all(list, i32 == f32) all(list, i64 != nil) all(list, i64 <= 0.5) all(list, i64 > 1) all(list, list != nil) all(list, nil != 1) all(list, nil != i64) all(list, nil != nil) all(list, nil != score) all(list, nil == #) all(list, nil == score) all(list, nil in array) all(list, none(array, 1 > #)) all(list, not true) all(list, ok) all(list, reduce(array, true)) all(list, type(i) not endsWith .Bar) all(map(array, #), ok && false) all(map(array, #), ok) all(map(array, f32), !ok) all(map(array, false), #) all(map(array, score), # != #) all(map(array, score), ok) all(map(list, "bar" not in #), #) all(map(list, 0.5), 0.5 <= #) all(map(list, i), # == 0.5) all(map(list, list), 1 == 0.5) all(map(list, ok), #) all(reduce(array, array), # > #) all(reduce(array, list), ok) all(true ? list : false, not true) any(["bar"], # not endsWith #) any([greet], ok) any(array, !(i32 <= #)) any(array, "foo" >= "foo") any(array, "foo" not endsWith "bar") any(array, # != # or # > #) any(array, # != #) any(array, # != 0.5) any(array, # != f32) any(array, # != f64) any(array, # != i32) any(array, # != i64) any(array, # != nil) any(array, # < #) any(array, # < 0.5) any(array, # < 1) any(array, # < f32) any(array, # < f64) any(array, # < i) any(array, # < i32) any(array, # <= #) any(array, # <= 0.5) any(array, # <= 1) any(array, # <= f32) any(array, # <= i) any(array, # <= i32) any(array, # <= i64) any(array, # == #) any(array, # == 0.5) any(array, # == 1) any(array, # == i32) any(array, # == i64) any(array, # > #) any(array, # > 0.5) any(array, # > 1) any(array, # > f64) any(array, # > i32) any(array, # >= #) any(array, # >= 0.5) any(array, # >= 1) any(array, # >= f32) any(array, # >= i32) any(array, # >= i64) any(array, # in array) any(array, 0.5 != #) any(array, 0.5 == #) any(array, 0.5 == i32) any(array, 0.5 > #) any(array, 0.5 > f64) any(array, 0.5 >= #) any(array, 1 != i64) any(array, 1 < #) any(array, 1 < 0.5) any(array, 1 <= #) any(array, 1 == #) any(array, 1 > #) any(array, 1 > 1) any(array, 1 >= #) any(array, 1 >= f64) any(array, all(list, false)) any(array, f32 < i) any(array, f32 > #) any(array, f32 > 0.5) any(array, f32 >= #) any(array, f64 != #) any(array, f64 < i) any(array, f64 <= #) any(array, f64 == #) any(array, f64 > #) any(array, f64 > 0.5) any(array, false && false) any(array, greet == greet) any(array, i != #) any(array, i < #) any(array, i > #) any(array, i >= #) any(array, i32 > i64) any(array, i64 < #) any(array, i64 == f64) any(array, i64 >= #) any(array, nil != #) any(array, nil != 1) any(array, nil != i) any(array, nil != ok) any(array, nil == "foo") any(array, nil == #) any(array, nil == 1) any(array, ok != true) any(array, ok) any(array, one(array, # <= 0.5)) any(array, one(array, ok)) any(array, score == nil) any(i32 .. i, half == half) any(list, !ok) any(list, !true) any(list, "bar" < "foo") any(list, "bar" not in #) any(list, "bar" not startsWith "foo") any(list, "foo" not in foo) any(list, # != #) any(list, # == #) any(list, # == foo) any(list, # == nil) any(list, 0.5 != 1) any(list, 0.5 < 1) any(list, 0.5 < f64) any(list, 0.5 == i64) any(list, 1 >= f64) any(list, 1 >= i32) any(list, any(list, false)) any(list, any(list, ok)) any(list, array == nil) any(list, f32 < 1) any(list, f32 <= i64) any(list, f32 > 1) any(list, f32 > i64) any(list, f32 >= i32) any(list, f64 != i64) any(list, f64 >= 1) any(list, false) == (foo not in list) any(list, false) || false ? nil : add any(list, i > i64) any(list, i >= 0.5) any(list, i32 != 0.5) any(list, i64 <= 1) any(list, i64 == 0.5) any(list, i64 == i) any(list, i64 >= i32) any(list, i64 not in array) any(list, nil == false) any(list, nil == nil) any(list, none(array, false)) any(list, not ok) any(list, ok || # == #) any(list, ok) any(list, reduce(list, true)) any(list, true ? false : f64) any(map(array, #), # >= #) any(map(array, #), ok) any(map(array, false), #) any(map(array, ok), # and #) any(map(array, ok), #) any(map(list, #), nil == #) any(map(list, false), nil == i32) any(map(list, ok), #) any(ok ? "foo" : 1, ok) any(ok ? "foo" : f32, i > #) any(reduce(array, array), 1 == #) array array != array array != array ? 1 : false array != array ? score : i32 array != list array != list ? list : f64 array != map(array, #) array != map(array, 1) array != map(list, #) array != map(list, true) array != nil ? add : 0.5 array == array array == array ? half : false array == list array == map(array, score) array == map(list, #) array == nil ? list : float(f32) array not in sort(array) array[-i32] array[-i64] array[-i] array[1 % i64] array[1 + 1] array[1] * i32 array[1] * i64 array[1] - f64 array[1] / i32 array[1] == -i array[1] > i array[1] ^ i array[abs(1)] array[array[i32]] array[bitnot(1)] array[bitor(1, i)] array[count(list, ok)] array[get(array, 1)] array[i32 * 1] array[i32:i] array[i32] array[i32] != i array[i32] % i32 array[i32] * f64 array[i32] ** i32 array[i32] + i64 array[i32] - f64 array[i32] / f32 array[i32] == i32 array[i32] == i64 array[i32] > f64 array[i32] >= f32 array[i64:i64] array[i64] array[i64] .. i32 array[i64] == floor(0.5) array[i64] == i array[i64] > half(f64) array[i64] ^ f64 array[i:i32] array[i:i64] array[i] array[i] * f64 array[i] + f32 array[i] - f32 array[i] / f64 array[i] < round(i) array[i] == i32 array[i] > f64 array[i] >= 0.5 ** i array[max(1)] array[reduce(list, 1)] array[score(1):i] array[score(1)] array[score(i)] bitand(1 * i64, i) bitand(1, 1) != i bitand(1, i64) == f64 bitand(i, i) bitand(i, i32) bitand(i, i64) bitand(i32, 1) != f32 bitand(i32, i) bitand(i32, i) - i32 bitand(i32, i32 * i) bitand(i32, i32) bitand(i32, i64) bitand(i64, 1) <= i32 bitand(i64, i + i64) bitand(i64, i) bitand(i64, i) ^ f64 bitand(i64, i32) bitand(i64, i64) bitand(int(i32), i64) bitnand(1, i64) != int(i64) bitnand(i, i) bitnand(i, i32 + i32) bitnand(i, i32) bitnand(i, i64) bitnand(i32, bitnot(1)) bitnand(i32, i) bitnand(i32, i32) bitnand(i32, i64) bitnand(i64 + i, i32) bitnand(i64 + i64, i64) bitnand(i64, -1) bitnand(i64, 1) + i64 + 1 bitnand(i64, i) bitnand(i64, i32) bitnand(i64, i32) > f64 bitnand(i64, i64) bitnot(-1) bitnot(-i) bitnot(-i32) bitnot(-i64) bitnot(1 % 1) bitnot(1 % i32) bitnot(1 % i64) bitnot(1 * 1) bitnot(1 * i64) bitnot(1 + 1) bitnot(1 - i) bitnot(1 - i32) bitnot(1) * i % 1 bitnot(1) ** f32 bitnot(1) ** i bitnot(1) + i32 bitnot(1) - i bitnot(1) - i32 bitnot(1) / min(i) bitnot(1) < i32 bitnot(1) < i64 bitnot(1) == i32 bitnot(1) > f64 bitnot(1) >= i bitnot(1) >= i64 bitnot(abs(1)) bitnot(abs(i32)) bitnot(abs(i64)) bitnot(array[1]) bitnot(array[i64]) bitnot(array[i]) bitnot(bitnot(i)) bitnot(bitushr(1, 1)) bitnot(bitushr(i32, 1)) bitnot(bitxor(i, i64)) bitnot(count(array, false)) bitnot(findLast(array, ok)) bitnot(first(array)) bitnot(get(array, 1)) bitnot(get(array, i)) bitnot(i % i64) bitnot(i * i) bitnot(i * i32) bitnot(i + 1) bitnot(i - 1) bitnot(i - i64) bitnot(i) bitnot(i) % i32 bitnot(i) * i bitnot(i) + f64 bitnot(i) .. i64 bitnot(i) == 1 - i bitnot(i) > i bitnot(i) >= i32 bitnot(i) ^ f32 bitnot(i) ^ f64 bitnot(i) in array bitnot(i32 % 1) bitnot(i32 % i64) bitnot(i32 + i) bitnot(i32 + i32) bitnot(i32 - 1) bitnot(i32 - i32) bitnot(i32) bitnot(i32) != f64 bitnot(i32) != i32 bitnot(i32) * i bitnot(i32) * i64 bitnot(i32) ** f32 bitnot(i32) - i32 bitnot(i32) / f64 bitnot(i32) == i64 bitnot(i32) > 1 != true bitnot(i32) >= f32 bitnot(i64 % 1) bitnot(i64 % i) bitnot(i64 % i32) bitnot(i64 * 1) bitnot(i64 * i) bitnot(i64 * i32) bitnot(i64 * i64) bitnot(i64 - 1) bitnot(i64 - i) bitnot(i64 - i64) bitnot(i64) bitnot(i64) % i32 bitnot(i64) * f32 bitnot(i64) < f32 bitnot(i64) > f64 bitnot(i64) > i % i bitnot(i64) >= i32 ^ f32 bitnot(i64) ^ f64 bitnot(i64) not in array bitnot(int(f32)) bitnot(int(f64)) bitnot(int(i)) bitnot(int(i32)) bitnot(int(i64)) bitnot(last(array)) bitnot(len("bar")) bitnot(len("foo")) bitnot(len(list)) bitnot(max(1)) bitnot(max(1, i64)) bitnot(max(i)) bitnot(max(i32)) bitnot(min(1)) bitnot(min(i32)) bitnot(min(i64)) bitnot(ok ? 1 : array) bitnot(ok ? 1 : ok) bitnot(ok ? i : add) bitnot(reduce(array, #)) bitnot(reduce(array, 1)) bitnot(reduce(list, 1)) bitnot(score(1)) bitnot(score(i)) bitnot(sum(array)) bitor(1, 1) < i bitor(1, 1) == i bitor(1, i32) != i64 bitor(i, -i64) bitor(i, i) bitor(i, i64) bitor(i32, i) bitor(i32, i32) bitor(i32, i64) bitor(i64 % 1, i32) bitor(i64, i) bitor(i64, i32) bitor(i64, i64) bitor(min(i64), i) bitor(score(i), i64) bitshl(bitnot(i), i) bitshl(i, i) bitshl(i, i32) bitshl(i, i64) bitshl(i32, i) bitshl(i32, i32) bitshl(i32, i64) bitshl(i64, i32) bitshl(i64, i64) bitshl(len(array), i) bitshl(score(i), i32) bitshr(i % 1, i32) bitshr(i, 1) - i64 bitshr(i, i32) bitshr(i, i64) bitshr(i32, i) bitshr(i32, i) - f32 bitshr(i32, i32) bitshr(i32, i64) bitshr(i64, i32) bitshr(i64, i64) bitushr(-i64, i64) bitushr(1 % i, i) bitushr(1, i) * i bitushr(abs(1), i32) bitushr(i, i) bitushr(i, i) % i64 bitushr(i, i32) bitushr(i, i64) bitushr(i32, i) bitushr(i32, i32) bitushr(i32, i64) bitushr(i64, i) bitushr(i64, i32) bitushr(i64, i64) bitxor(-i, i64) bitxor(1, i) * i bitxor(bitnot(1), -i) bitxor(i, i32) bitxor(i, i64) bitxor(i32, 1) > i64 bitxor(i32, i) bitxor(i32, i) ** f64 bitxor(i32, i32) bitxor(i32, i64) bitxor(i32, i64) ** i32 bitxor(i64, i) bitxor(i64, i32) bitxor(i64, i64) bitxor(score(1), i) ceil(-0.5) ceil(-1) ceil(-f32) ceil(-f64) ceil(-i) ceil(-i32) ceil(-i64) ceil(0.5 * 0.5) ceil(0.5 * 1) ceil(0.5 * f64) ceil(0.5 * i) ceil(0.5 ** 1) ceil(0.5 ** f64) ceil(0.5 ** i) ceil(0.5 + 0.5) ceil(0.5 + 1) ceil(0.5 + f32) ceil(0.5 + f64) ceil(0.5 + i) ceil(0.5 + i32) ceil(0.5 + i64) ceil(0.5 - 0.5) ceil(0.5 - f64) ceil(0.5 - i) ceil(0.5 / 0.5) ceil(0.5 / 1) ceil(0.5 / f32) ceil(0.5 / i) ceil(0.5 / i32) ceil(0.5 ^ 1) ceil(0.5 ^ f32) ceil(0.5 ^ i32) ceil(0.5 ^ i64) ceil(0.5) != 0.5 * 0.5 ceil(0.5) != i ceil(0.5) != nil ? score : "foo" ceil(0.5) ** round(f32) ceil(0.5) - i ceil(0.5) < i ceil(0.5) == f32 ceil(0.5) == i ? div : half ceil(0.5) == i64 ceil(0.5) > f64 ceil(0.5) >= i ceil(0.5) >= i64 ceil(0.5) ^ i64 ceil(1 % i64) ceil(1 * 0.5) ceil(1 * 1) ceil(1 ** 1) ceil(1 + 0.5) ceil(1 + 1) ceil(1 + f64) ceil(1 + i) ceil(1 - 0.5) ceil(1 - f64) ceil(1 / 0.5) ceil(1 / 1) ceil(1 / f64) ceil(1 / i64) ceil(1 ^ f64) ceil(1 ^ i) ceil(1 ^ i64) ceil(1) ** f32 ceil(1) + i32 ceil(1) / i ceil(1) < f32 ^ i ceil(1) <= f32 ceil(1) <= i64 ceil(1) == f32 ceil(1) > f32 ceil(1) >= f32 ceil(1) >= i64 ** 0.5 ceil(1) ^ i ceil(abs(0.5)) ceil(abs(1)) ceil(abs(f32)) ceil(abs(f64)) ceil(abs(i32)) ceil(abs(i64)) ceil(add(1, 1)) ceil(array[1]) ceil(array[i64]) ceil(array[i]) ceil(bitnot(1)) ceil(bitnot(i)) ceil(ceil(0.5)) ceil(ceil(f64)) ceil(ceil(i)) ceil(ceil(i32)) ceil(count(list, ok)) ceil(f32 * 0.5) ceil(f32 * i) ceil(f32 * i32) ceil(f32 ** i) ceil(f32 ** i32) ceil(f32 + 1) ceil(f32 + i64) ceil(f32 - f32) ceil(f32 - i) ceil(f32 - i32) ceil(f32 - i64) ceil(f32 / 0.5) ceil(f32 / f64) ceil(f32 / i32) ceil(f32 ^ 0.5) ceil(f32 ^ 1) ceil(f32 ^ i64) ceil(f32) ceil(f32) != i64 ceil(f32) * i64 ceil(f32) ** -1 ceil(f32) ** i ceil(f32) + i ceil(f32) + i64 ceil(f32) - i32 ceil(f32) / i64 ceil(f32) < i ceil(f32) < i32 ceil(f64 * 1) ceil(f64 * i) ceil(f64 ** i) ceil(f64 ** i64) ceil(f64 + 1) ceil(f64 + f32) ceil(f64 - 0.5) ceil(f64 - f32) ceil(f64 - f64) ceil(f64 - i32) ceil(f64 / 0.5) ceil(f64 / f64) ceil(f64 / i32) ceil(f64 / i64) ceil(f64 ^ 0.5) ceil(f64 ^ f32) ceil(f64 ^ f64) ceil(f64 ^ i32) ceil(f64 ^ i64) ceil(f64) ceil(f64) != i ceil(f64) != i64 ceil(f64) * f32 ceil(f64) ** f32 ceil(f64) - i32 ceil(f64) / f64 ceil(f64) / i / i64 ceil(f64) in array ceil(false ? add : 0.5) ceil(find(array, ok)) ceil(findLast(array, true)) ceil(findLastIndex(list, ok)) ceil(findLastIndex(list, true)) ceil(first(array)) ceil(float(0.5)) ceil(float(1)) ceil(float(f64)) ceil(float(i)) ceil(float(i32)) ceil(float(i64)) ceil(floor(0.5)) ceil(floor(1)) ceil(floor(f64)) ceil(floor(i)) ceil(floor(i32)) ceil(floor(i64)) ceil(get(array, 1)) ceil(get(array, i)) ceil(half(0.5)) ceil(half(1)) ceil(half(f64)) ceil(i % i) ceil(i * 0.5) ceil(i * i) ceil(i ** f64) ceil(i ** i) ceil(i + 0.5) ceil(i + 1) ceil(i + f32) ceil(i + i64) ceil(i - i) ceil(i / f32) ceil(i / i) ceil(i / i64) ceil(i ^ i) ceil(i ^ i32) ceil(i) ceil(i) != i32 ceil(i) * f64 ceil(i) * i64 ceil(i) ** f64 ceil(i) + i ceil(i) - f32 ceil(i) / f32 ceil(i) <= f64 ceil(i) == i32 ceil(i) > i64 ceil(i32 * i) ceil(i32 * i32) ceil(i32 ** i32) ceil(i32 + 0.5) ceil(i32 + i32) ceil(i32 - 0.5) ceil(i32 - 1) ceil(i32 - i) ceil(i32 - i64) ceil(i32 / 0.5) ceil(i32 / f32) ceil(i32 / i) ceil(i32 / i32) ceil(i32 ^ 0.5) ceil(i32 ^ i64) ceil(i32) ceil(i32) * 1 ^ i32 ceil(i32) * i32 ceil(i32) ** max(i) ceil(i32) + f32 ceil(i32) + i ceil(i32) + i32 ceil(i32) <= i64 ceil(i32) not in array ceil(i64 % 1) ceil(i64 % i32) ceil(i64 * f32) ceil(i64 * f64) ceil(i64 ** i32) ceil(i64 ** i64) ceil(i64 + 0.5) ceil(i64 + f64) ceil(i64 + i32) ceil(i64 - 0.5) ceil(i64 - f64) ceil(i64 / 0.5) ceil(i64 / 1) ceil(i64 / f64) ceil(i64 ^ 0.5) ceil(i64 ^ i) ceil(i64 ^ i32) ceil(i64 ^ i64) ceil(i64) ceil(i64) - -1 ceil(i64) - f32 ceil(i64) - i32 ceil(i64) / (0.5 - f32) ceil(i64) >= f32 ceil(i64) ^ i32 ceil(int(0.5)) ceil(int(f32)) ceil(int(f64)) ceil(int(i)) ceil(int(i64)) ceil(len("bar")) ceil(len(array)) ceil(len(list)) ceil(max(1, i)) ceil(max(f32, 0.5)) ceil(max(f64)) ceil(max(i)) ceil(mean(array)) ceil(median(array)) ceil(min(0.5, f32)) ceil(min(1)) ceil(min(f32)) ceil(min(f64)) ceil(min(i)) ceil(min(i64)) ceil(ok ? f32 : nil) ceil(ok ? i32 : "bar") ceil(ok ? i32 : i64) ceil(reduce(array, #)) ceil(reduce(array, 0.5)) ceil(reduce(list, 1)) ceil(round(0.5)) ceil(round(1)) ceil(round(f32)) ceil(round(f64)) ceil(round(i)) ceil(round(i32)) ceil(round(i64)) ceil(score(1)) ceil(score(i)) ceil(true ? 1 : half) ceil(true ? 1 : nil) ceil(true ? f64 : nil) count(["bar", score, i], 1 != #) count(["bar"], # startsWith #) count([0.5], ok) count([greet], ok) count([i32], f32 != #) count([list, 0.5], # not in list) count([nil], ok) count(array, !ok) count(array, !true) count(array, "bar" <= "bar") count(array, "bar" not endsWith "bar") count(array, "foo" matches "foo") count(array, # != #) count(array, # != 0.5) count(array, # != i) count(array, # != i64) count(array, # != nil) count(array, # < #) count(array, # < i) count(array, # < i32) count(array, # <= #) count(array, # <= 0.5) count(array, # <= 1) count(array, # <= i) count(array, # <= i32) count(array, # == #) count(array, # == 0.5) count(array, # == 1) count(array, # == f32) count(array, # == i) count(array, # == i64) count(array, # == nil) count(array, # > #) count(array, # > 0.5) count(array, # > i) count(array, # > i64) count(array, # >= #) count(array, # >= 0.5) count(array, # >= 1) count(array, # >= f32) count(array, # >= i) count(array, # in array) count(array, # not in array) count(array, 0.5 != #) count(array, 0.5 < #) count(array, 0.5 <= #) count(array, 0.5 <= f32) count(array, 0.5 <= f64) count(array, 0.5 == #) count(array, 0.5 == f32) count(array, 0.5 == i) count(array, 0.5 > #) count(array, 1 != #) count(array, 1 != 0.5) count(array, 1 < #) count(array, 1 <= #) count(array, 1 == #) count(array, 1 >= #) count(array, any(array, true)) count(array, div(#, 1) >= #) count(array, f32 <= #) count(array, f32 == #) count(array, f64 < #) count(array, f64 < f32) count(array, f64 <= #) count(array, f64 <= 1) count(array, f64 == #) count(array, false) ** i32 count(array, false) + f32 count(array, false) - i64 count(array, false) / f64 count(array, false) > i64 * i64 count(array, foo in list) count(array, foo not in list) count(array, i != #) count(array, i < #) count(array, i < 0.5) count(array, i <= #) count(array, i == #) count(array, i > i64) count(array, i >= #) count(array, i32 != #) count(array, i32 != i) count(array, i32 < #) count(array, i32 < 1) count(array, i32 <= #) count(array, i32 <= f32) count(array, i32 == #) count(array, i32 == 0.5) count(array, i32 > #) count(array, i32 >= #) count(array, i32 >= f32) count(array, i32 >= i32) count(array, i64 != i32) count(array, i64 != i64) count(array, i64 < #) count(array, i64 <= #) count(array, i64 == #) count(array, i64 == i64) count(array, i64 > 1) count(array, list != array) count(array, list != nil) count(array, nil != "foo") count(array, nil != f64) count(array, nil == 1) count(array, nil == list) count(array, nil == nil) count(array, none(array, false)) count(array, not false) count(array, ok or false) count(array, ok) count(array, ok) * i32 count(array, ok) ^ i count(array, reduce(list, false)) count(array, true == ok) count(array, true) / f64 count(filter(list, true), ok) count(groupBy(list, #).String, .div?.array) count(i .. 1, # == i) count(i .. i, ok) count(i32 .. i, # >= #) count(i64 .. 1, nil != f32) count(list, !false) count(list, !true) count(list, "bar" not matches "bar") count(list, "foo" in #) count(list, # != #) count(list, # == #) count(list, # == nil) count(list, # in list) count(list, 0.5 < f32) count(list, 0.5 <= 0.5) count(list, 0.5 <= i64) count(list, 0.5 > 0.5) count(list, 0.5 > 1) count(list, 0.5 > f32) count(list, 1 != i) count(list, 1 >= 0.5) count(list, 1 >= f32) count(list, f32 == i64) count(list, f32 >= f32) count(list, false && false) count(list, false) + -1 count(list, false) / f64 count(list, false) > f32 count(list, foo == #) count(list, i != i64) count(list, i < 0.5) count(list, i <= i64) count(list, i > 1) count(list, i32 < f32) count(list, i32 < i64) count(list, i64 not in array) count(list, nil != #) count(list, nil != false) count(list, nil == list) count(list, not false) count(list, ok) count(list, ok) % i64 count(list, ok) / half(1) count(list, ok) / i count(list, ok) >= i32 count(list, ok) ^ i count(list, ok) ^ i64 count(list, true or ok) count(list, true || true) count(list, true) * f32 count(list, true) == i count(map(array, #), # == i32) count(map(array, #), not true) count(map(array, #), ok) count(map(array, false), #) count(map(array, i), ok) count(map(array, i32), 1 == #) count(map(array, i64), f64 != nil) count(map(array, ok), !#) count(map(list, 0.5), "bar" == "foo") count(map(list, div), ok) count(map(list, f32), # == #) count(map(list, greet), ok) count(map(list, i32), # != i64) count(map(list, ok), #) count(map(list, ok), 0.5 <= i64) count(ok ? array : i64, # > 0.5) count(sort(array), 1 <= #) div div != add div != add != nil div != add == ok div != div div != div != ok div != div && ok div != div ? "bar" : "foo" div != nil == ok div != nil || f32 < 0.5 div != reduce(array, div) div == add div == add ? 1 : ok div == div div == nil ? f32 : half div == nil ? false : 1 div(-i, array[i64]) div(-i, i) div(1, i) + i div(findLast(array, true), i) div(i, -1) div(i, i) div(last(array), 1 * i32) div(score(1), bitnot(1)) f32 f32 != -0.5 f32 != -1 f32 != -f32 f32 != 0.5 != false f32 != 0.5 * 1 f32 != 0.5 * i64 f32 != 0.5 ** f32 f32 != 0.5 + 1 f32 != 0.5 - i64 f32 != 0.5 / 0.5 f32 != 0.5 / i32 f32 != 0.5 == ok f32 != 0.5 == true f32 != 0.5 ? array : score f32 != 0.5 ? foo : f64 f32 != 0.5 ? true : i32 f32 != 0.5 ^ 1 f32 != 0.5 ^ f32 f32 != 1 && ok f32 != 1 * i f32 != 1 + i64 f32 != f32 f32 != f32 / 0.5 f32 != f32 / f32 f32 != f64 f32 != findLast(array, ok) f32 != findLastIndex(array, ok) f32 != floor(0.5) f32 != half(0.5) f32 != i f32 != i != true f32 != i % 1 f32 != i % i f32 != i ** i64 f32 != i / f64 f32 != i32 f32 != i32 % i f32 != i32 * i32 f32 != i32 + 0.5 f32 != i64 f32 != i64 != nil f32 != i64 != true f32 != i64 ? 0.5 : f64 f32 != i64 ^ i32 f32 != int(f32) f32 != int(i32) f32 != len(array) f32 != nil ? true : score f32 != nil || ok f32 != round(i) f32 != score(1) f32 != score(1, i) f32 * (0.5 + f64) f32 * (0.5 + i32) f32 * (0.5 - f32) f32 * (f64 + f64) f32 * (f64 + i64) f32 * (f64 - i) f32 * -0.5 f32 * -1 f32 * -f64 f32 * -i f32 * -i64 f32 * -len(array) f32 * 0.5 * 0.5 f32 * 0.5 * i f32 * 0.5 * i32 f32 * 0.5 - i32 f32 * 0.5 / i f32 * 0.5 <= i f32 * 0.5 ^ f32 f32 * 0.5 not in array f32 * 1 != f32 f32 * 1 * f64 f32 * 1 * i32 f32 * 1 ** 0.5 f32 * 1 + f64 f32 * 1 < i64 f32 * 1 >= i64 f32 * 1 ^ i64 f32 * ceil(i) f32 * f32 f32 * f32 * 0.5 f32 * f32 < i32 f32 * f32 <= i64 f32 * f32 > f32 - 1 f32 * f32 ^ 0.5 f32 * f32 in array f32 * f64 f32 * f64 + f64 f32 * f64 + i32 f32 * f64 / i64 f32 * f64 >= 1 - i f32 * float(i) f32 * float(i32) f32 * floor(0.5) f32 * floor(i) f32 * half(0.5) f32 * half(1) f32 * half(f64) f32 * i f32 * i != i32 f32 * i - i f32 * i / f64 f32 * i == i64 f32 * i32 f32 * i32 != max(i) f32 * i32 * i32 f32 * i32 ** 0.5 f32 * i32 >= i f32 * i64 f32 * i64 != f64 f32 * i64 ** i f32 * int(i64) f32 * min(i64) f32 * reduce(array, 1) f32 * reduce(list, 1) f32 * round(f64) f32 ** (0.5 + 0.5) f32 ** (0.5 - 1) f32 ** (0.5 / f32) f32 ** (1 / f64) f32 ** (f32 - 0.5) f32 ** (f64 - i64) f32 ** (i % 1) f32 ** (i64 * i32) f32 ** (i64 + 0.5) f32 ** (i64 - 1) f32 ** -0.5 f32 ** -f32 f32 ** -f64 f32 ** -i f32 ** 0.5 != f32 f32 ** 0.5 + f32 f32 ** 0.5 >= -i64 f32 ** 0.5 ^ (f32 / f64) f32 ** 0.5 ^ i64 f32 ** 1 + i64 f32 ** 1 / i f32 ** 1 < f64 f32 ** 1 < i64 f32 ** 1 <= i64 f32 ** ceil(i64) f32 ** f32 f32 ** f32 * f32 f32 ** f32 ** f32 f32 ** f32 < f64 f32 ** f32 ^ f32 f32 ** f32 ^ f64 f32 ** f64 f32 ** f64 ** 1 f32 ** f64 <= f64 f32 ** f64 >= i f32 ** float(f32) f32 ** float(f64) f32 ** half(0.5) f32 ** half(1) f32 ** i f32 ** i != half(1) f32 ** i ** f64 f32 ** i ** i32 f32 ** i <= i64 f32 ** i32 f32 ** i32 / i32 f32 ** i32 == f64 f32 ** i32 ^ f32 f32 ** i64 f32 ** i64 / f32 f32 ** i64 == i32 f32 ** i64 > i32 f32 ** int(f64) f32 ** len("foo") f32 ** max(f32) f32 ** max(i32) f32 ** median(array) f32 ** reduce(array, 0.5) f32 ** round(f64) f32 + -0.5 f32 + -1 f32 + -f32 f32 + -i f32 + 0.5 ** f32 f32 + 0.5 + i32 f32 + 0.5 - i f32 + 0.5 - i32 f32 + 0.5 / f32 f32 + 0.5 == i f32 + 0.5 > i64 f32 + 0.5 ^ 0.5 f32 + 1 * 0.5 f32 + 1 * 1 f32 + 1 + i f32 + 1 - f64 f32 + 1 - i64 f32 + 1 / f64 f32 + 1 < f32 f32 + 1 < i f32 + 1 >= ceil(0.5) f32 + bitnot(i64) f32 + ceil(-1) f32 + ceil(1) f32 + ceil(f32) f32 + f32 f32 + f32 * 0.5 f32 + f32 ** i64 f32 + f32 - i32 f32 + f32 / 1 f32 + f32 > i32 f32 + f32 ^ 0.5 f32 + f64 f32 + f64 in array f32 + findIndex(array, true) f32 + first(array) f32 + float(i) f32 + floor(1) f32 + floor(i64) f32 + half(1) f32 + half(f64) f32 + i f32 + i != i64 f32 + i + 1 f32 + i + i f32 + i - i32 f32 + i == f64 f32 + i32 f32 + i32 != f32 f32 + i32 % i f32 + i32 / f32 f32 + i32 <= i f32 + i32 ^ 0.5 f32 + i64 f32 + i64 != f32 f32 + i64 + 0.5 f32 + i64 < f32 f32 + i64 <= i32 f32 + i64 >= i f32 + i64 >= i32 f32 + int(1) f32 + int(f64) f32 + max(0.5) f32 + max(f64) f32 + reduce(array, #) f32 + round(1) f32 + round(i32) f32 + score(1) f32 + score(i) f32 - -1 f32 - -f64 f32 - -i f32 - 0.5 ** i64 f32 - 0.5 + 0.5 f32 - 0.5 + f64 f32 - 0.5 - i64 f32 - 0.5 < i f32 - 0.5 <= i32 f32 - 0.5 <= i64 f32 - 0.5 > f64 f32 - 1 % i64 f32 - 1 * i64 f32 - 1 + 1 f32 - 1 / 0.5 f32 - 1 < i32 f32 - 1 <= i32 f32 - 1 == f32 f32 - 1 >= f64 f32 - abs(i32) f32 - abs(i64) f32 - bitshl(i, i32) f32 - ceil(f64) f32 - f32 f32 - f32 ** i32 f32 - f32 + i f32 - f32 == i f32 - f64 f32 - f64 + f64 f32 - f64 - i f32 - f64 <= f32 f32 - i f32 - i >= f32 f32 - i32 f32 - i32 * 0.5 f32 - i32 * f64 f32 - i32 ** 1 f32 - i32 <= f32 f32 - i32 <= i32 f32 - i32 >= abs(0.5) f32 - i64 f32 - i64 ** 0.5 f32 - len(array) f32 - max(1) f32 - min(0.5) f32 - min(0.5, 0.5) f32 - reduce(array, #) f32 - score(1) f32 - score(i) f32 / (0.5 - i32) f32 / (1 + i) f32 / (f64 - 0.5) f32 / (i - i32) f32 / (i32 + 1) f32 / -1 f32 / -f64 f32 / -i64 f32 / 0.5 ** f64 f32 / 0.5 / i f32 / 0.5 <= i64 f32 / 0.5 ^ f64 f32 / 1 * i32 f32 / 1 <= f32 f32 / 1 >= 0.5 ? f64 : foo f32 / 1 >= f32 f32 / 1 >= i32 f32 / array[1] f32 / array[i32] f32 / bitnot(i) f32 / ceil(1) f32 / ceil(f32) f32 / count(list, false) f32 / f32 f32 / f32 / 0.5 f32 / f32 ^ 1 f32 / f64 f32 / f64 * i32 f32 / f64 + f32 f32 / f64 - i32 f32 / f64 / 1 f32 / f64 / f64 f32 / f64 / i64 f32 / f64 < i f32 / float(1) f32 / float(i32) f32 / float(i64) f32 / floor(i) f32 / half(0.5) f32 / half(1) f32 / half(f64) f32 / i f32 / i * 0.5 f32 / i / 0.5 f32 / i <= i f32 / i == i32 f32 / i > f64 f32 / i32 f32 / i32 * 1 f32 / i32 * f32 f32 / i32 ** f32 f32 / i32 + i f32 / i32 + i64 f32 / i32 < f64 + 0.5 f32 / i32 >= i32 f32 / i64 f32 / i64 - f64 f32 / i64 ^ 0.5 f32 / int(0.5) f32 / int(1 * i64) f32 / max(0.5) f32 / min(i32) f32 / reduce(array, #) f32 / reduce(list, 1) f32 / score(i) f32 < -0.5 f32 < -f64 f32 < -i f32 < -i64 f32 < 0.5 + 0.5 f32 < 0.5 + 1 f32 < 0.5 ^ f32 f32 < 0.5 ^ i64 f32 < 1 % 1 f32 < 1 + f64 f32 < 1 ? f64 : i f32 < 1 and ok f32 < abs(0.5) f32 < ceil(0.5) f32 < ceil(f64) f32 < count(array, ok) f32 < count(list, ok) f32 < f32 f32 < f32 / 1 f32 < f32 ^ f64 f32 < f64 f32 < f64 ** 1 f32 < f64 + 0.5 f32 < f64 + i f32 < f64 / i64 f32 < f64 ? 0.5 : array f32 < f64 ? div : i32 f32 < f64 and ok f32 < floor(0.5) f32 < floor(i) f32 < half(0.5) f32 < half(1) f32 < i f32 < i != ok f32 < i / 1 f32 < i ? 1 : i f32 < i32 f32 < i32 ** i64 f32 < i32 ? f64 : i f32 < i32 ? greet : i32 f32 < i32 or ok f32 < i64 f32 < i64 - i32 f32 < i64 / 0.5 f32 < i64 ? foo : i32 f32 < i64 ? foo?.Bar : div f32 < i64 ^ 0.5 f32 < max(i) f32 < max(i32, 1) f32 < min(0.5) f32 < reduce(array, #) f32 < reduce(list, 1) f32 < round(i64) f32 <= -0.5 f32 <= -1 f32 <= -f64 f32 <= -i64 f32 <= 0.5 != true f32 <= 0.5 * 0.5 f32 <= 0.5 + i f32 <= 0.5 / i64 f32 <= 0.5 ? i64 : i f32 <= 1 - 0.5 f32 <= 1 == nil f32 <= 1 ? f64 : add f32 <= 1 ? i64 : i64 % 1 f32 <= 1 ? list : div f32 <= 1 || ok f32 <= f32 f32 <= f32 * 1 f32 <= f32 + f64 f32 <= f32 + i f32 <= f32 ? greet : half f32 <= f64 f32 <= findIndex(list, ok) * f64 f32 <= float(1) f32 <= float(i) f32 <= float(i64) f32 <= float(toJSON(1)) f32 <= floor(0.5) f32 <= half(0.5) f32 <= half(1) f32 <= half(f64) f32 <= i f32 <= i == nil f32 <= i and i32 <= f32 f32 <= i32 f32 <= i32 ** i32 f32 <= i32 + 1 f32 <= i32 / 1 f32 <= i64 f32 <= i64 ** i64 f32 <= i64 - f32 f32 <= i64 ? f64 : f64 f32 <= i64 ^ i32 f32 <= i64 || nil in array f32 <= last(array) f32 <= min(0.5) f32 <= min(1) f32 <= min(f64) f32 <= round(0.5) f32 <= score(1) f32 == -0.5 f32 == -1 f32 == -f32 f32 == -i32 f32 == -i64 f32 == 0.5 != ok f32 == 0.5 * 0.5 f32 == 0.5 * 1 f32 == 0.5 ** i32 f32 == 0.5 + 1 f32 == 0.5 / i32 f32 == 0.5 / i64 f32 == 0.5 ? array : greet f32 == 0.5 ? true : score f32 == 0.5 ^ 0.5 f32 == 0.5 || f64 >= 1 f32 == 1 != nil f32 == 1 + f32 f32 == 1 - 1 f32 == 1 - i f32 == 1 == ok f32 == 1 ? foo : f32 f32 == 1 ? ok : add != nil f32 == add(i, 1) f32 == array[i32] f32 == bitnot(i) f32 == ceil(1) f32 == ceil(i32) f32 == ceil(i64) f32 == f32 f32 == f32 ? f32 : list f32 == f32 and ok f32 == f64 f32 == f64 + f64 f32 == f64 ^ 1 f32 == findLastIndex(array, ok) f32 == first(array) f32 == float(0.5) f32 == float(1) f32 == floor(f64) f32 == half(1) f32 == half(f64) f32 == i f32 == i != nil f32 == i - 0.5 f32 == i - i64 f32 == i32 f32 == i32 + i32 f32 == i32 ? 0.5 : array f32 == i32 ? i64 : i64 f32 == i32 ? true : half f32 == i32 ^ i32 f32 == i32 or ok f32 == i64 f32 == i64 * i64 f32 == i64 + 0.5 f32 == i64 - 0.5 f32 == i64 - 1 f32 == i64 ? div : 0.5 f32 == last(array) f32 == max(f64) f32 == min(0.5) f32 == min(f32) f32 == nil ? array : add f32 == nil ? i : div f32 == round(1) f32 == score(1) f32 == score(i) f32 > -(0.5 / 1) f32 > -0.5 f32 > -f32 f32 > -i32 f32 > 0.5 / f32 f32 > 0.5 / i32 f32 > 0.5 == true ? i32 : array f32 > 0.5 ? half : false f32 > 0.5 ^ f64 f32 > 1 ** i f32 > 1 ? 1 : false f32 > 1 ? list : "foo" f32 > abs(1) f32 > abs(f32) f32 > abs(f64) f32 > count(array, ok) f32 > f32 f32 > f32 + f32 f32 > f32 - f32 f32 > f32 == nil f32 > f64 f32 > f64 * i f32 > f64 ** 0.5 f32 > float(0.5) f32 > float(i32) f32 > floor(1) f32 > half(1) f32 > half(f64) f32 > i f32 > i != ok f32 > i * 1 f32 > i ? array : 1 f32 > i ? foo : list f32 > i32 f32 > i32 != nil f32 > i32 * f64 f32 > i32 ? 0.5 : greet f32 > i32 and ok f32 > i64 f32 > i64 % i64 f32 > i64 ** i f32 > i64 + 0.5 f32 > i64 - i64 f32 > i64 ? i : 0.5 f32 > mean(array) f32 > min(f32) f32 > min(i64) f32 > reduce(array, #) f32 > reduce(array, i64) f32 > reduce(list, f32) f32 > round(0.5) f32 > score(1, 1) f32 >= -0.5 f32 >= -f32 f32 >= -f64 f32 >= 0.5 * f64 f32 >= 0.5 / i64 f32 >= 0.5 ? i64 : nil f32 >= 0.5 ^ i64 f32 >= 1 == false f32 >= 1 == ok ? add : array f32 >= 1 ? i : 1 f32 >= abs(0.5) f32 >= abs(f32) f32 >= abs(i) f32 >= array[1] f32 >= array[i32] f32 >= bitnot(i32) f32 >= count(list, false) f32 >= f32 f32 >= f32 ** 1 f32 >= f32 - i64 f32 >= f32 ? half : greet f32 >= f32 or nil != ok f32 >= f64 f32 >= f64 && ok f32 >= f64 ** 0.5 f32 >= f64 ** i32 f32 >= f64 - f64 f32 >= f64 / i64 f32 >= f64 or ok f32 >= float(0.5) f32 >= half(f64) f32 >= i f32 >= i - f32 f32 >= i ? 1 : nil f32 >= i ^ i f32 >= i32 f32 >= i32 % i f32 >= i32 - f32 f32 >= i32 / i64 f32 >= i32 ? f32 : 0.5 f32 >= i32 or not ok f32 >= i64 f32 >= i64 * i32 f32 >= i64 + f64 f32 >= i64 / 1 f32 >= len("bar") f32 >= max(i) f32 >= max(i64) f32 >= reduce(array, #) f32 >= score(1) f32 >= sum(array) f32 ^ (0.5 * f64) f32 ^ (0.5 / 1) f32 ^ (0.5 / i) f32 ^ (1 * i) f32 ^ (1 + f64) f32 ^ (f32 * i64) f32 ^ (f64 * f64) f32 ^ (f64 - 1) f32 ^ (f64 / i) f32 ^ (i64 * f64) f32 ^ (i64 * i32) f32 ^ (i64 * i64) f32 ^ (i64 + i64) f32 ^ (i64 - f32) f32 ^ -0.5 f32 ^ -1 f32 ^ -i32 f32 ^ 0.5 ** i32 f32 ^ 0.5 - f32 f32 ^ 0.5 - i32 f32 ^ 0.5 == i64 f32 ^ 0.5 ^ 0.5 f32 ^ 1 != i64 f32 ^ 1 / f32 f32 ^ 1 >= -0.5 f32 ^ abs(1) f32 ^ abs(f32) f32 ^ array[i64] f32 ^ array[i] f32 ^ bitnot(1) f32 ^ bitor(1, i32) f32 ^ f32 f32 ^ f32 ^ 0.5 f32 ^ f32 in array f32 ^ f64 f32 ^ f64 ** f64 f32 ^ f64 / 1 * 1 f32 ^ f64 / f64 f32 ^ f64 == i64 f32 ^ f64 not in array f32 ^ floor(0.5) f32 ^ floor(1) f32 ^ half(1) f32 ^ half(f64) f32 ^ i f32 ^ i - f64 f32 ^ i <= i f32 ^ i >= f64 f32 ^ i ^ f32 f32 ^ i32 f32 ^ i32 ** i64 f32 ^ i64 f32 ^ i64 ** 1 f32 ^ i64 + i64 f32 ^ i64 - f32 f32 ^ i64 >= f64 f32 ^ i64 ^ f32 f32 ^ int(i32) f32 ^ len("foo") f32 ^ len(array) f32 ^ min(1) f32 ^ min(f64) f32 ^ min(i) f32 ^ reduce(array, 1) f32 ^ round(i) f32 ^ round(i32) f32 ^ score(i) f32 ^ score(reduce(array, #)) f32 in [i] f32 in [nil] f32 in array f32 in array == nil f32 in array ? 1 : i f32 in array ? false : 0.5 f32 in array ? nil : "bar" f32 in groupBy(array, #) f32 in groupBy(list, #) f32 in groupBy(list, ok) f32 in map(array, #) f32 not in [f32, "bar"] f32 not in array f32 not in array ? foo : i f32 not in array ? i32 : div f64 f64 != -0.5 f64 != -1 f64 != -f32 f64 != -i f64 != -i64 f64 != 0.5 != false f64 != 0.5 ** 1 f64 != 0.5 ** f64 f64 != 0.5 + f32 f64 != 0.5 ^ 0.5 f64 != 1 - 1 f64 != 1 / 0.5 f64 != 1 ? half : div f64 != 1 ^ i f64 != abs(i32) f64 != bitnot(i64) f64 != ceil(i) f64 != f32 f64 != f32 != nil f64 != f32 + 0.5 f64 != f32 + i32 f64 != f32 - i32 f64 != f32 ? array : nil f64 != f32 ? i32 : "bar" f64 != f32 ? ok : i f64 != f32 or greet == nil f64 != f64 f64 != f64 * f32 f64 != f64 ? f64 : true f64 != first(array) f64 != floor(1) f64 != half(0.5) f64 != half(1) f64 != i f64 != i * 0.5 f64 != i / 1 f64 != i / f32 f64 != i ^ f64 f64 != i32 f64 != i32 * f32 f64 != i32 == ok f64 != i32 ? f64 : ok f64 != i32 ? foo : ok f64 != i32 ^ i32 f64 != i64 f64 != i64 * f64 f64 != i64 - i32 f64 != i64 or ok f64 != int(i64) f64 != min(f64) f64 != nil != ok f64 != nil && f64 > 0.5 f64 != nil == true f64 != nil ? array : foo f64 != nil ? f64 : half f64 != nil ? i64 : 0.5 f64 != nil ? nil : half f64 != round(1) f64 * (0.5 - 1) f64 * (i64 + 0.5) f64 * -1 f64 * -f32 f64 * -f64 f64 * 0.5 * 1 f64 * 0.5 * i64 f64 * 0.5 ** 0.5 f64 * 0.5 / 0.5 f64 * 0.5 / f32 f64 * 0.5 / i32 f64 * 0.5 < f32 f64 * 0.5 <= i f64 * 0.5 == f64 f64 * 0.5 ^ 1 f64 * 1 * f64 f64 * 1 * i32 f64 * 1 ** 1 f64 * 1 + f64 f64 * 1 - i32 f64 * 1 <= 1 + 1 f64 * 1 == i64 f64 * 1 > f32 f64 * 1 > f64 f64 * 1 >= f64 f64 * bitnot(i64) f64 * ceil(i) f64 * ceil(i64) f64 * f32 f64 * f32 != i f64 * f32 / i64 f64 * f32 > f64 f64 * f32 > i f64 * f64 f64 * f64 * f64 f64 * f64 / 1 f64 * f64 <= f64 f64 * f64 > f64 f64 * f64 in array f64 * float(f32) f64 * floor(0.5) f64 * get(array, 1) f64 * half(f64) f64 * i f64 * i / f64 f64 * i32 f64 * i32 != i64 * f64 f64 * i32 - i32 f64 * i64 f64 * i64 ** i f64 * i64 == i f64 * i64 > i32 f64 * i64 ^ i32 f64 * median(array) f64 * min(1) f64 * min(f64) f64 * min(i) f64 * round(1) f64 * round(i64) f64 ** (0.5 - i) f64 ** (0.5 / i64) f64 ** (1 * i) f64 ** (f64 * i32) f64 ** (f64 / 1) f64 ** (i * 1) f64 ** (i * i64) f64 ** (i32 * i) f64 ** (i32 + i32) f64 ** (i32 - f64) f64 ** (i32 / i64) f64 ** (i64 % 1) f64 ** (i64 + 0.5) f64 ** (i64 + i64) f64 ** (i64 - i32) f64 ** (i64 / 0.5) f64 ** -0.5 f64 ** -1 f64 ** -i f64 ** 0.5 ** f32 f64 ** 0.5 == i32 f64 ** 1 + f64 f64 ** 1 / i f64 ** 1 < f32 f64 ** 1 > i32 f64 ** 1 ^ f32 f64 ** abs(i) f64 ** bitand(1, 1) f64 ** ceil(0.5) f64 ** ceil(f64) f64 ** f32 f64 ** f32 != f64 f64 ** f32 ** f64 f64 ** f32 > f64 f64 ** f64 f64 ** f64 - f32 f64 ** f64 / min(1) f64 ** f64 <= f32 f64 ** f64 <= i64 f64 ** f64 ^ 0.5 f64 ** half(0.5) f64 ** i f64 ** i * f64 f64 ** i ** i f64 ** i + -i32 f64 ** i + f32 f64 ** i32 f64 ** i32 != f64 f64 ** i32 > f64 f64 ** i64 f64 ** i64 + f32 f64 ** i64 <= f32 f64 ** i64 not in map(array, 0.5) f64 ** last(array) f64 ** len("bar") f64 ** max(i) f64 ** min(f32) f64 ** reduce(array, #) f64 ** reduce(list, i32) f64 ** score(i) f64 + -0.5 f64 + -1 f64 + -f64 f64 + -i f64 + -i32 f64 + 0.5 / f32 f64 + 0.5 < i32 f64 + 0.5 <= f64 f64 + 0.5 <= float(f32) f64 + 0.5 <= i f64 + 0.5 > f64 f64 + 0.5 ^ i f64 + 0.5 ^ i64 f64 + 1 % i f64 + 1 * 0.5 f64 + 1 * 1 f64 + 1 * f64 f64 + 1 ** 0.5 f64 + 1 + i32 f64 + 1 / i64 f64 + 1 ^ i f64 + 1 not in map(array, #) f64 + ceil(0.5) f64 + count(list, true) f64 + f32 f64 + f32 == i != true f64 + f64 f64 + f64 < f32 f64 + f64 <= i32 f64 + f64 ^ i32 f64 + float(f64) f64 + floor(f64) f64 + get(array, i32) f64 + half(0.5) f64 + half(1) f64 + i f64 + i + 0.5 f64 + i / 0.5 f64 + i / i32 f64 + i > 0.5 != true f64 + i > f64 f64 + i >= f64 f64 + i32 f64 + i32 != i64 f64 + i32 % i32 f64 + i32 ** 1 f64 + i32 > i64 f64 + i64 f64 + i64 + i64 f64 + i64 / f64 f64 + i64 > i32 / i f64 + i64 > i64 f64 + i64 ^ i32 f64 + reduce(array, #) f64 + reduce(list, f32) f64 + score(1) f64 - -0.5 f64 - -1 f64 - -f64 f64 - -i f64 - -i64 f64 - 0.5 - 0.5 f64 - 0.5 - 1 f64 - 0.5 - i32 f64 - 0.5 >= f64 f64 - 0.5 ^ i64 f64 - 1 * i32 f64 - 1 + i64 f64 - 1 - f64 f64 - 1 / i64 f64 - 1 < f32 f64 - 1 < f32 ? i64 : false f64 - 1 >= len(array) f64 - 1 ^ i64 f64 - f32 f64 - f32 != i64 f64 - f32 + f32 f64 - f32 < f64 f64 - f32 ^ f32 f64 - f64 f64 - f64 + -1 f64 - f64 < f64 f64 - float(f32) f64 - floor(1) f64 - half(1) f64 - i f64 - i + 0.5 f64 - i + 1 f64 - i + i32 f64 - i / i f64 - i ^ f32 f64 - i32 f64 - i32 / 0.5 f64 - i32 >= i64 f64 - i32 ^ 0.5 f64 - i64 f64 - i64 ** i32 f64 - int(i) f64 - int(i32) f64 - reduce(array, -#) f64 - round(1) f64 - score(i) f64 / (0.5 - 1) f64 / (0.5 - i64) f64 / (f32 + 1) f64 / (i + 0.5) f64 / (i32 + i64) f64 / -0.5 f64 / -1 f64 / -f64 f64 / -i f64 / -i32 f64 / -i64 f64 / 0.5 != f64 f64 / 0.5 * f32 f64 / 0.5 + f64 f64 / 0.5 / 1 f64 / 0.5 < i32 f64 / 0.5 == i32 f64 / 0.5 >= i64 f64 / 1 != i f64 / 1 * i32 f64 / 1 ** 1 f64 / 1 / i f64 / 1 <= i64 f64 / 1 ^ i f64 / abs(f64) f64 / array[1] f64 / array[i64] f64 / ceil(i32) f64 / f32 f64 / f32 * i f64 / f32 * i64 f64 / f32 / 0.5 f64 / f32 == f32 f64 / f32 ^ 0.5 f64 / f64 f64 / f64 / 0.5 f64 / f64 >= f64 f64 / f64 >= i32 f64 / f64 >= i64 f64 / float(1) f64 / float(f64) f64 / floor(i64) f64 / get(array, 1) f64 / get(array, i32) f64 / half(0.5) f64 / half(1) f64 / i f64 / i != f64 f64 / i ** 0.5 f64 / i ** f32 f64 / i + i32 f64 / i == i64 f64 / i >= i f64 / i32 f64 / i32 != 0.5 - i64 f64 / i32 == f64 ** i f64 / i32 == i32 f64 / i32 >= f32 f64 / i64 f64 / i64 < f64 f64 / int(f32) f64 / last(array) f64 / max(i) f64 / reduce(array, #) f64 / reduce(array, f64) f64 / reduce(list, f32) f64 / round(1) f64 / round(i64) f64 / score(1) f64 < -0.5 f64 < -i32 f64 < -i64 f64 < 0.5 + i64 f64 < 0.5 / 0.5 f64 < 0.5 / i f64 < 0.5 == true f64 < 0.5 ? f64 : array f64 < 1 % 1 f64 < 1 * 0.5 f64 < 1 ** i32 f64 < 1 / f32 f64 < 1 == false f64 < 1 ? i : "foo" f64 < abs(1) f64 < abs(f32) f64 < array[i64] f64 < bitnot(1) f64 < ceil(f64) f64 < count(array, false) f64 < f32 f64 < f32 * i f64 < f32 / i64 f64 < f32 ^ 1 f64 < f32 ^ f64 f64 < f64 f64 < f64 == ok f64 < floor(i64) f64 < get(array, i) f64 < i f64 < i && "bar" < "bar" f64 < i && ok f64 < i ** i32 f64 < i + 1 f64 < i ? 0.5 : "bar" f64 < i ? div : nil f64 < i32 f64 < i32 * f64 f64 < i32 * i f64 < i32 ** f32 f64 < i32 ** i64 f64 < i32 + f32 f64 < i32 + f64 f64 < i32 + i64 f64 < i32 ? false : ok f64 < i32 ? true : 1 f64 < i32 ^ 1 f64 < i32 ^ i32 f64 < i64 f64 < i64 * f64 f64 < i64 ^ i f64 < int(0.5) f64 < max(1) f64 < max(f64, i32) f64 < min(0.5, i64) f64 < min(f32) f64 < min(f64, f32) f64 < min(i32) f64 < round(0.5) f64 < score(1) f64 <= -0.5 f64 <= -1 f64 <= -i f64 <= -i32 f64 <= 0.5 != false f64 <= 0.5 + 0.5 f64 <= 0.5 / f32 f64 <= 0.5 ? greet : f64 f64 <= 0.5 ? score : array f64 <= 1 * i32 f64 <= 1 + 0.5 f64 <= 1 / i f64 <= 1 == nil f64 <= 1 ? "bar" : array f64 <= 1 ? half : list f64 <= 1 ^ f64 f64 <= abs(0.5) f64 <= abs(i) f64 <= array[i64] f64 <= ceil(i) f64 <= f32 f64 <= f32 ** 0.5 f64 <= f32 - i64 f64 <= f32 ? f64 : div f64 <= f32 ^ f32 f64 <= f64 f64 <= f64 != ok f64 <= f64 + f64 f64 <= f64 + i32 f64 <= f64 - 1 f64 <= f64 ^ i f64 <= float(i) f64 <= float(i64) f64 <= half(0.5) f64 <= half(1) f64 <= i f64 <= i * i64 f64 <= i - 1 f64 <= i - f32 f64 <= i ^ f64 f64 <= i32 f64 <= i32 ** 1 f64 <= i32 ? div : foo f64 <= i32 or all(list, ok) f64 <= i64 f64 <= i64 + 1 f64 <= i64 - 0.5 f64 <= int(f32) f64 <= max(i) f64 <= max(i64, i32) f64 <= min(i32) f64 <= min(i64) f64 <= reduce(array, #) f64 == -0.5 f64 == -1 f64 == -f32 f64 == -f64 f64 == -i f64 == -i64 f64 == 0.5 ** 0.5 f64 == 0.5 - i f64 == 0.5 ? 0.5 : i64 f64 == 0.5 ? 1 : 1 f64 == 1 != ok f64 == 1 % 1 f64 == 1 * i64 f64 == 1 ** 0.5 f64 == 1 == false f64 == abs(0.5) f64 == abs(i64) f64 == ceil(i) f64 == f32 f64 == f32 && ok f64 == f32 + len(array) f64 == f32 ? 0.5 : i f64 == f32 ^ i32 f64 == f64 f64 == f64 ** i f64 == f64 - f64 f64 == float(0.5) f64 == floor(0.5) f64 == half(0.5) f64 == half(f64) f64 == i f64 == i != false f64 == i * 1 f64 == i ? i32 : score f64 == i32 f64 == i32 == ok ? 1 : list f64 == i32 == true f64 == i32 || ok f64 == i64 f64 == i64 / i f64 == i64 ? 1 : 0.5 f64 == i64 ? greet : i32 f64 == int(f32) f64 == max(0.5) f64 == max(i) f64 == min(i32) f64 == nil && ok f64 == nil ? 0.5 : add f64 == nil ? foo : "foo" f64 == reduce(list, i32) f64 == round(i) f64 == score(i, 1) f64 > -0.5 f64 > -1 f64 > -f64 f64 > -i f64 > -i32 f64 > 0.5 ** f32 f64 > 0.5 / i f64 > 0.5 ^ i f64 > 0.5 or i <= 0.5 f64 > 1 + f32 f64 > 1 + i32 f64 > 1 ? div : i32 f64 > 1 ^ i32 f64 > array[i64] f64 > ceil(0.5) f64 > ceil(1) f64 > ceil(f32) f64 > f32 f64 > f32 / 1 f64 > f64 f64 > f64 - 0.5 f64 > float(0.5 * i64) f64 > floor(f64) f64 > get(array, 1) f64 > half(0.5) f64 > half(1) f64 > half(f64) f64 > i f64 > i - 0.5 f64 > i32 f64 > i32 == ok f64 > i32 ? f32 : array f64 > i32 ? list : half f64 > i32 ^ i32 f64 > i32 ^ i64 f64 > i64 f64 > i64 - 1 f64 > i64 ? array : half f64 > i64 ? list : div f64 > i64 || ok or ok f64 > int(f32) f64 > last(array) f64 > max(0.5) f64 > max(0.5, i64) f64 > max(f32) f64 > median(array) f64 > min(f32) f64 >= -0.5 f64 >= -1 f64 >= -i64 f64 >= 0.5 + i32 f64 >= 0.5 - 1 f64 >= 0.5 - f32 f64 >= 0.5 / i64 f64 >= 0.5 ? list : i32 f64 >= 0.5 ^ i64 f64 >= array[1] f64 >= f32 f64 >= f32 - i32 f64 >= f32 ^ 1 f64 >= f64 f64 >= f64 != nil f64 >= f64 != ok f64 >= findIndex(array, ok) f64 >= floor(f32) f64 >= floor(i) f64 >= half(0.5) f64 >= half(1) f64 >= i f64 >= i * 0.5 f64 >= i ** 0.5 f64 >= i ** i32 f64 >= i / i32 f64 >= i ^ 1 f64 >= i32 f64 >= i32 - f64 f64 >= i32 ? ok : add f64 >= i32 ^ 1 f64 >= i64 f64 >= i64 + f64 f64 >= i64 ? 0.5 : score f64 >= i64 ? 1 : f32 f64 >= max(1) f64 >= median(array) f64 >= reduce(array, #) f64 >= reduce(array, i32) f64 >= score(i) f64 ^ (0.5 * i) f64 ^ (0.5 + 1) f64 ^ (1 * f64) f64 ^ (1 - 1) f64 ^ (f32 + 1) f64 ^ (f32 - 0.5) f64 ^ (f32 - i) f64 ^ (f32 / -f64) f64 ^ (i32 - 1) f64 ^ (i32 / f32) f64 ^ (i64 - 1) f64 ^ -0.5 f64 ^ -i32 f64 ^ 0.5 * f64 f64 ^ 0.5 ** f32 f64 ^ 0.5 ** i32 f64 ^ 0.5 > ceil(f32) f64 ^ 0.5 > i f64 ^ 0.5 >= f64 f64 ^ 0.5 >= i32 f64 ^ 0.5 ^ i32 f64 ^ 0.5 not in array f64 ^ 1 ** i f64 ^ 1 ** i64 f64 ^ 1 ^ i f64 ^ abs(0.5) f64 ^ array[i64] f64 ^ f32 f64 ^ f32 ** 1 f64 ^ f32 < score(1) f64 ^ f32 >= i32 f64 ^ f64 f64 ^ f64 - -i f64 ^ f64 == i32 f64 ^ f64 > f64 f64 ^ f64 ^ i f64 ^ f64 ^ i64 f64 ^ findIndex(array, true) f64 ^ float(abs(i)) f64 ^ floor(f64) f64 ^ half(1) f64 ^ half(f64) f64 ^ i f64 ^ i ** 1 f64 ^ i + f32 f64 ^ i + i32 f64 ^ i <= i32 f64 ^ i ^ i64 f64 ^ i32 f64 ^ i32 / f64 f64 ^ i32 <= i32 f64 ^ i32 >= i f64 ^ i64 f64 ^ i64 ** i64 f64 ^ int(0.5) f64 ^ int(f64) f64 ^ last(array) f64 ^ len(list) f64 ^ min(1) f64 ^ reduce(array, #) f64 ^ round(i) f64 ^ score(1) f64 in array f64 in array != nil f64 in groupBy(list, i64) f64 not in array f64 not in array != ok f64 not in array != true f64 not in array == true f64 not in groupBy(array, #) f64 not in groupBy(array, bitnand(#, 1)) f64 not in i .. i32 f64 not in map(array, #) false != false ? foo : greet false && i not in array false && nil not in array false && nil not in list false == nil ? i32 : f64 false == nil ? i32 : i32 false ? "bar" : 0.5 - i false ? "foo" : f32 * i false ? "foo" : f32 / i32 false ? "foo" : foo.Qux false ? add : 1 / i ^ 0.5 false ? add : i64 - i false ? div : i64 ** i false ? f32 : foo.Qux false ? f64 : 0.5 != i32 false ? f64 : 0.5 ** i32 false ? f64 : 1 >= i false ? f64 : foo?.Qux false ? f64 : i ^ f32 false ? false : foo?.Qux false ? foo : i32 - i false ? half : 0.5 == f32 false ? half : i ^ i64 false ? i : foo?.Qux false ? i : nil in list false ? i32 : 1 <= i32 false ? i32 : foo.Qux false ? i64 : 1 <= f32 false ? i64 : foo.Qux false ? i64 : i64 ** i64 false ? list : list == list false ? nil : foo?.Qux false ? nil : i32 > i32 false ? ok : foo.String() false ? ok : i64 < i64 false and false || 0.5 > f32 false or 1 not in array false or true or ok false or true || ok filter(1 .. 1, # > i) filter(1 .. i, i >= #) filter([0.5], # > 0.5) filter([nil], # != false) filter(array, !true) filter(array, "bar" != "foo") filter(array, "foo" == nil) filter(array, # != #) filter(array, # != f32) filter(array, # != f64) filter(array, # != i) filter(array, # != i64) filter(array, # < #) filter(array, # < f64) filter(array, # <= #) filter(array, # <= 1) filter(array, # <= bitshr(#, #)) filter(array, # <= i) filter(array, # <= i64) filter(array, # == #) filter(array, # == 0.5) filter(array, # == f32) filter(array, # == f64) filter(array, # == i) filter(array, # == i32) filter(array, # == i64) filter(array, # == nil) filter(array, # > #) filter(array, # > 0.5) filter(array, # > 1) filter(array, # > i) filter(array, # > i32) filter(array, # >= #) filter(array, # >= 0.5) filter(array, # >= 1) filter(array, # >= f32) filter(array, # >= i) filter(array, # >= i32) filter(array, # >= i64) filter(array, 0.5 != #) filter(array, 0.5 != f64) filter(array, 0.5 != i) filter(array, 0.5 < #) filter(array, 0.5 < f64) filter(array, 0.5 < i32) filter(array, 0.5 <= #) filter(array, 0.5 <= i) filter(array, 0.5 <= i32) filter(array, 0.5 == #) filter(array, 0.5 == f64) filter(array, 0.5 > #) filter(array, 0.5 >= #) filter(array, 1 != #) filter(array, 1 < i) filter(array, 1 == #) filter(array, 1 == 0.5) filter(array, 1 == i) filter(array, 1 > i) filter(array, 1 >= #) filter(array, add == add) filter(array, add == nil) filter(array, any(list, ok)) filter(array, f32 != #) filter(array, f32 < #) filter(array, f32 <= #) filter(array, f32 == #) filter(array, f32 == i64) filter(array, f32 > #) filter(array, f32 >= #) filter(array, f64 < #) filter(array, f64 <= #) filter(array, f64 == i32) filter(array, f64 >= #) filter(array, half != nil) filter(array, half == half) filter(array, half(1) >= # ^ i) filter(array, i != #) filter(array, i != f64) filter(array, i <= i32) filter(array, i == #) filter(array, i > #) filter(array, i > f32) filter(array, i32 != i64) filter(array, i32 < 0.5) filter(array, i32 > #) filter(array, i64 < #) filter(array, i64 < i64) filter(array, i64 == #) filter(array, i64 == i32) filter(array, i64 >= #) filter(array, nil != #) filter(array, nil != greet) filter(array, nil == #) filter(array, nil == 1) filter(array, nil == i32) filter(array, not false) filter(array, not ok) filter(array, not true) filter(array, ok && true) filter(array, ok) filter(array, ok)[i64] filter(array, score == nil) filter(array, true == true) filter(array, true and true) filter(false ? ok : array, # == nil) filter(filter(list, true), ok) filter(groupBy(list, #).f64, # not matches #?.foo) filter(i .. i64, ok) filter(list, !ok) filter(list, !true) filter(list, "bar" < "foo") filter(list, "bar" not matches "foo") filter(list, "foo" == "foo") filter(list, "foo" in #) filter(list, "foo" not endsWith "bar") filter(list, "foo" startsWith "bar") filter(list, # != #) filter(list, # != foo) filter(list, # != nil) filter(list, # == #) filter(list, # == foo) filter(list, # in list) filter(list, 0.5 < 1) filter(list, 0.5 <= 0.5) filter(list, 0.5 >= 1) filter(list, 0.5 >= i) filter(list, 0.5 >= i64) filter(list, 1 < 1) filter(list, 1 <= f32) filter(list, any(array, ok)) filter(list, any(list, true)) filter(list, div != div) filter(list, f32 <= 1) filter(list, f32 == f64) filter(list, f32 > i) filter(list, f64 <= 1) filter(list, f64 == 0.5) filter(list, false != false) filter(list, false or ok) filter(list, foo == #) filter(list, i < 0.5) filter(list, i < f32) filter(list, i >= 0.5) filter(list, i64 > 0.5) filter(list, nil != "foo") filter(list, nil != #) filter(list, nil != #?.Bar) filter(list, nil != add) filter(list, nil != greet) filter(list, nil != i64) filter(list, nil == #) filter(list, nil == 0.5) filter(list, nil == f32) filter(list, nil == half) filter(list, nil == i32) filter(list, nil == score) filter(list, ok == nil) filter(list, ok and false) filter(list, ok) filter(list, ok)[i] filter(list, true == ok) filter(list, true || true) filter(list, true) == list filter(map(array, #), # == 1) filter(map(array, #), # > #) filter(map(array, 1), ok) filter(map(array, greet), ok) filter(map(array, i32), ok) filter(map(array, i64), nil == div) filter(map(array, ok), true || ok) filter(map(array, score), # != nil) filter(map(list, #), # == #) filter(map(list, #), half != nil) filter(map(list, #), ok) filter(map(list, array), # == #) filter(map(list, f32), # == #) filter(map(list, f32), ok) filter(map(list, false), #) filter(map(list, i32), i64 <= i32) filter(map(list, ok), #) filter(map(list, true), #) filter(ok ? "foo" : 0.5, # <= i64) filter(true ? list : score, # != #) find(1 .. i, ok) find([ok], #) find([score, score], # == #) find(array, !(# <= i32)) find(array, !ok) find(array, !true) find(array, "bar" not startsWith "foo") find(array, "foo" not contains "bar") find(array, # != #) find(array, # != 1) find(array, # != i) find(array, # != i32) find(array, # != nil) find(array, # - i != #) find(array, # < #) find(array, # < 0.5) find(array, # < 1) find(array, # < f32) find(array, # < i) find(array, # < i32) find(array, # < i64) find(array, # <= #) find(array, # <= 0.5) find(array, # <= 1) find(array, # <= i32) find(array, # == #) find(array, # == 0.5) find(array, # == 1) find(array, # == i) find(array, # == i64) find(array, # == nil) find(array, # > #) find(array, # > 1) find(array, # > i32) find(array, # > i64) find(array, # >= #) find(array, # >= 1) find(array, # >= f64) find(array, # >= i) find(array, # not in array) find(array, 0.5 != 1) find(array, 0.5 / i64 <= #) find(array, 0.5 < #) find(array, 0.5 < f64) find(array, 0.5 <= #) find(array, 0.5 >= #) find(array, 0.5 >= 0.5) find(array, 0.5 >= f64) find(array, 1 != #) find(array, 1 < #) find(array, 1 < i32) find(array, 1 < i64) find(array, 1 <= #) find(array, 1 <= i) find(array, 1 == #) find(array, 1 > #) find(array, 1 >= #) find(array, div != nil) find(array, f32 != #) find(array, f32 != f32) find(array, f32 < #) find(array, f32 <= #) find(array, f32 == #) find(array, f32 == i32) find(array, f32 > #) find(array, f32 >= #) find(array, f64 != #) find(array, f64 < #) find(array, f64 < 1) find(array, f64 <= #) find(array, f64 == #) find(array, f64 == i64) find(array, false ? # : false) find(array, false) != f64 find(array, floor(#) > #) find(array, greet != greet) find(array, i % # != f64) find(array, i < 0.5) find(array, i <= #) find(array, i > 0.5) find(array, i >= #) find(array, i >= 1) find(array, i32 != #) find(array, i32 != i32) find(array, i32 == #) find(array, i32 > #) find(array, i32 >= #) find(array, i64 != #) find(array, i64 != 1) find(array, i64 < #) find(array, i64 <= #) find(array, i64 == #) find(array, i64 > #) find(array, nil != nil) find(array, nil == #) find(array, nil == 0.5) find(array, nil == i32) find(array, none(array, true)) find(array, not (# == #)) find(array, ok == nil) find(array, ok and false) find(array, ok) find(array, ok) % i32 find(array, ok) ** i find(array, ok) >= i32 find(array, true) > f64 find(array, true) > i64 find(filter(list, false), i64 not in array) find(groupBy(array, #).Qux, .String?.f32) find(groupBy(array, #).ok, first(#[1])) find(i .. i64, ok) find(i64 .. i32, # != #) find(list, !false) find(list, !ok) find(list, "bar" not in #) find(list, "foo" contains "foo") find(list, # != #) find(list, # != nil) find(list, # == #) find(list, # == foo) find(list, # == nil) find(list, 0.5 != 1) find(list, 0.5 <= 0.5) find(list, 1 != 0.5) find(list, 1 < 1) find(list, 1 < i64) find(list, 1 == f64) find(list, 1 > 0.5) find(list, 1 > i) find(list, 1 > i64) find(list, f32 < 1) find(list, f32 <= 0.5) find(list, f32 <= i32) find(list, f32 == i64) find(list, f32 > f64) find(list, f32 not in array) find(list, f64 < f64) find(list, false && true) find(list, false)?.Bar find(list, foo != #) find(list, foo == #) find(list, i != 1) find(list, i != f64) find(list, i != i32) find(list, i32 != 1) find(list, i32 != f64) find(list, i32 < i) find(list, i32 == i32) find(list, nil != #) find(list, nil != ok) find(list, nil == array) find(list, nil == div) find(list, not false) find(list, ok != false) find(list, ok) find(list, ok).String find(list, ok).String() find(list, ok)?.Bar find(list, ok)?.Qux find(list, ok)?.String find(list, score == score) find(list, true != nil) find(list, true == true) find(list, true or false) find(list, true).Bar find(list, true).Qux find(list, true).String find(list, true)?.Bar find(list, true)?.String find(map(array, #), # != f32) find(map(array, #), # <= 1) find(map(array, #), # == 0.5) find(map(array, #), ok) find(map(array, false), #) find(map(array, foo), ok) find(map(array, ok), #) find(map(list, #), # != #) find(map(list, #), ok) find(map(list, 0.5), # != #) find(map(list, add), 0.5 >= i64) find(map(list, div), # == #) find(map(list, f32), # > 0.5) find(map(list, false), #) find(map(list, i), # == i64) find(map(list, ok), #) find(map(list, true), #) find(ok ? "foo" : f64, f32 >= #) findIndex(array, !ok) findIndex(array, "bar" == "foo") findIndex(array, "foo" > "foo") findIndex(array, "foo" in foo) findIndex(array, # != #) findIndex(array, # != 0.5) findIndex(array, # != f32) findIndex(array, # != f64) findIndex(array, # != i) findIndex(array, # != i64) findIndex(array, # != nil) findIndex(array, # < #) findIndex(array, # < 1) findIndex(array, # < i32) findIndex(array, # <= #) findIndex(array, # <= 0.5) findIndex(array, # <= 1) findIndex(array, # == #) findIndex(array, # == 0.5) findIndex(array, # == 1) findIndex(array, # == i32) findIndex(array, # == nil) findIndex(array, # > #) findIndex(array, # > 0.5) findIndex(array, # > 1) findIndex(array, # > f64) findIndex(array, # > i) findIndex(array, # > i64) findIndex(array, # >= #) findIndex(array, # >= 0.5) findIndex(array, # >= 1) findIndex(array, # >= f32) findIndex(array, # >= f64) findIndex(array, # >= i) findIndex(array, # >= i32) findIndex(array, # >= i64) findIndex(array, 0.5 != #) findIndex(array, 0.5 != 1) findIndex(array, 0.5 < 1) findIndex(array, 0.5 <= #) findIndex(array, 0.5 == #) findIndex(array, 0.5 == i64) findIndex(array, 0.5 > #) findIndex(array, 0.5 > 0.5) findIndex(array, 0.5 > i) findIndex(array, 0.5 > i32) findIndex(array, 0.5 >= 0.5) findIndex(array, 0.5 >= 1) findIndex(array, 0.5 not in array) findIndex(array, 1 != #) findIndex(array, 1 != i64) findIndex(array, 1 != nil) findIndex(array, 1 < #) findIndex(array, 1 <= #) findIndex(array, 1 > #) findIndex(array, 1 > i) findIndex(array, 1 >= #) findIndex(array, add != div) findIndex(array, add != nil) findIndex(array, f32 != #) findIndex(array, f32 != 1) findIndex(array, f32 < #) findIndex(array, f32 == #) findIndex(array, f32 >= #) findIndex(array, f32 >= i32) findIndex(array, f64 >= #) findIndex(array, f64 >= i32) findIndex(array, false) == -f64 findIndex(array, i != f64) findIndex(array, i < #) findIndex(array, i < i32) findIndex(array, i <= #) findIndex(array, i <= 0.5) findIndex(array, i == #) findIndex(array, i >= i) findIndex(array, i >= i32) findIndex(array, i32 != #) findIndex(array, i32 < #) findIndex(array, i32 == #) findIndex(array, i32 > f32) findIndex(array, i64 != #) findIndex(array, i64 != nil) findIndex(array, i64 < 0.5) findIndex(array, i64 <= #) findIndex(array, i64 <= i64) findIndex(array, i64 > #) findIndex(array, i64 >= #) findIndex(array, i64 >= f64) findIndex(array, i64 >= i32) findIndex(array, nil != half) findIndex(array, nil != ok) findIndex(array, nil == #) findIndex(array, nil == 1) findIndex(array, nil == nil) findIndex(array, not false) findIndex(array, ok) findIndex(array, ok) / f64 findIndex(array, ok) / i findIndex(array, ok) <= f32 findIndex(array, one(list, false)) findIndex(array, true) + f64 findIndex(array, true) - f64 findIndex(array, true) .. i findIndex(filter(array, false), # > 1) findIndex(filter(array, true), # not in array) findIndex(filter(list, false), 1 <= i64) findIndex(groupBy(array, #).f64, .Bar(half(add, half, div, greet, f64))) findIndex(groupBy(array, false).String, #?.i64()) findIndex(groupBy(array, foo).String, #) findIndex(groupBy(list, #).Qux, #) findIndex(i32 .. 1, # >= #) findIndex(list, !false) findIndex(list, !ok) findIndex(list, !true) findIndex(list, "bar" > "foo") findIndex(list, "bar" in #) findIndex(list, "bar" not in #) findIndex(list, # != #) findIndex(list, # != nil) findIndex(list, # == #) findIndex(list, # == foo) findIndex(list, # in list) findIndex(list, #?.Bar not in #) findIndex(list, 0.5 != i) findIndex(list, 0.5 > 1) findIndex(list, 0.5 >= i) findIndex(list, 1 != i32) findIndex(list, 1 < f64) findIndex(list, 1 < i32) findIndex(list, 1 == f32) findIndex(list, 1 > 0.5) findIndex(list, 1 > i32) findIndex(list, 1 >= 1) findIndex(list, 1 >= i) findIndex(list, f32 != f32) findIndex(list, f32 != i) findIndex(list, f32 < i32) findIndex(list, f32 == bitshl(i, i64)) findIndex(list, f32 > 1) findIndex(list, f64 != 0.5) findIndex(list, f64 < 1) findIndex(list, f64 < i) findIndex(list, f64 > 1) findIndex(list, f64 >= f64) findIndex(list, false != nil) findIndex(list, false || ok) findIndex(list, foo != #) findIndex(list, greet == nil) findIndex(list, i < 0.5) findIndex(list, i <= i32) findIndex(list, i32 == 1) findIndex(list, i32 >= i64) findIndex(list, i64 != f32) findIndex(list, nil != 0.5) findIndex(list, nil != f32) findIndex(list, nil != i64) findIndex(list, nil == "foo") findIndex(list, nil == f64) findIndex(list, not ok) findIndex(list, not true) findIndex(list, ok) findIndex(list, ok) * i findIndex(list, ok) ** i findIndex(list, ok) >= f64 findIndex(list, ok) ^ i32 findIndex(list, true ? ok : #) findIndex(list, true) % i64 findIndex(map(array, #), # < #) findIndex(map(array, #), # >= #) findIndex(map(array, #), i > #) findIndex(map(array, f32), i32 == #) findIndex(map(array, i), # != #) findIndex(map(array, i), ok) findIndex(map(list, #), # != #) findIndex(map(list, #), # == #) findIndex(map(list, i64), # == 0.5) findIndex(map(list, i64), i64 < #) findIndex(map(list, true), #) findIndex(map(list, true), ok) findIndex(ok ? "foo" : greet, !ok) findIndex(ok ? "foo" : i, # == #) findIndex(sort(array), i32 == #) findIndex(true ? "foo" : ok, # == greet) findLast(1 .. i, # <= #) findLast(1 .. i32, 1 >= #) findLast(1 .. i64, ok) findLast([false], #) findLast(array, !false) findLast(array, !ok) findLast(array, "foo" > "bar") findLast(array, # != #) findLast(array, # != 0.5) findLast(array, # != 1) findLast(array, # != f32) findLast(array, # != f64) findLast(array, # != i) findLast(array, # < #) findLast(array, # < 0.5) findLast(array, # < f32) findLast(array, # < f64) findLast(array, # < i + #) findLast(array, # <= #) findLast(array, # <= 0.5) findLast(array, # <= 1) findLast(array, # <= f32) findLast(array, # <= i64) findLast(array, # == #) findLast(array, # == 0.5) findLast(array, # == nil) findLast(array, # > #) findLast(array, # > 0.5) findLast(array, # > 1) findLast(array, # > i) findLast(array, # > i32) findLast(array, # > i64) findLast(array, # >= #) findLast(array, # >= 0.5) findLast(array, # >= 1) findLast(array, # >= f32) findLast(array, # >= i32) findLast(array, 0.5 <= #) findLast(array, 0.5 <= i64) findLast(array, 0.5 > #) findLast(array, 0.5 >= #) findLast(array, 0.5 >= 1) findLast(array, 1 != #) findLast(array, 1 <= #) findLast(array, 1 == #) findLast(array, f32 >= #) findLast(array, f64 != #) findLast(array, f64 != nil) findLast(array, f64 <= #) findLast(array, f64 <= 1) findLast(array, f64 == #) findLast(array, f64 == nil) findLast(array, f64 >= 1) findLast(array, f64 >= i64) findLast(array, false != true) findLast(array, false or true) findLast(array, greet != nil) findLast(array, i < #) findLast(array, i == i32) findLast(array, i > #) findLast(array, i >= 0.5) findLast(array, i32 < #) findLast(array, i32 == 0.5) findLast(array, i32 > #) findLast(array, i32 >= #) findLast(array, i32 >= i32) findLast(array, i64 != #) findLast(array, i64 < #) findLast(array, i64 <= #) findLast(array, i64 == #) findLast(array, i64 > 0.5) findLast(array, list != nil) findLast(array, nil != array) findLast(array, not (array == array)) findLast(array, not false) findLast(array, not ok) findLast(array, ok and true) findLast(array, ok) findLast(array, ok) == i64 findLast(array, reduce(list, ok)) findLast(array, score != nil) findLast(array, true) % i64 findLast(groupBy(array, #).i32, #) findLast(groupBy(list, "bar").div, #?.f32?.half()) findLast(groupBy(list, #)[ok], .ok) findLast(groupBy(list, f64).foo, .f32(#, #)?.Qux(#?.i64(add, nil))) findLast(i .. 1, # < #) findLast(i .. i32, # != i64) findLast(i .. i32, ok) findLast(i32 .. i64, # >= i) findLast(i64 .. 1, # < #) findLast(list, !false) findLast(list, !ok) findLast(list, "foo" in #) findLast(list, # != #) findLast(list, # != nil) findLast(list, # == #) findLast(list, # == foo) findLast(list, # in list) findLast(list, # not in list) findLast(list, 0.5 != i64) findLast(list, 0.5 <= 1) findLast(list, 0.5 == i64) findLast(list, 1 != f32) findLast(list, 1 != nil) findLast(list, 1 <= 1) findLast(list, 1 > f32) findLast(list, 1 >= f64) findLast(list, f32 != i) findLast(list, f32 > f32) findLast(list, f32 >= 1) findLast(list, f64 <= i) findLast(list, f64 in array) findLast(list, false)?.Bar findLast(list, foo != #) findLast(list, foo in list) findLast(list, i != i) findLast(list, i <= 1) findLast(list, i <= i) findLast(list, i == i32) findLast(list, i >= i) findLast(list, i32 != f32) findLast(list, i64 > f32) findLast(list, i64 > i) findLast(list, i64 >= 1) findLast(list, nil != #) findLast(list, nil not in array) findLast(list, nil not in list) findLast(list, none(array, ok)) findLast(list, not false) findLast(list, not true) findLast(list, ok or true) findLast(list, ok) findLast(list, ok) not in list findLast(list, ok).Bar findLast(list, ok).Qux findLast(list, ok).String findLast(list, ok)?.Bar findLast(list, ok)?.Qux findLast(list, ok)?.String findLast(list, true or ok) findLast(list, true).Bar findLast(list, true).Qux findLast(list, true).String findLast(list, true)?.Bar findLast(list, true)?.Qux findLast(list, true)?.String findLast(map(array, #), # < #) findLast(map(array, #), # < i32) findLast(map(array, #), # <= 1) findLast(map(array, #), # == f64) findLast(map(array, #), 0.5 != 0.5) findLast(map(array, #), i32 == #) findLast(map(array, #), ok) findLast(map(array, f64 * #), # + # > f32) findLast(map(array, score), ok) findLast(map(list, #), # == #) findLast(map(list, #), greet == nil) findLast(map(list, #), ok) findLast(map(list, ok), # ? # : #) findLastIndex(1 .. 1, i64 < #) findLastIndex([i64, half], ok) findLastIndex(array, "bar" not matches "foo") findLastIndex(array, "bar" startsWith "foo") findLastIndex(array, "foo" == nil) findLastIndex(array, "foo" >= "foo") findLastIndex(array, "foo" contains "foo") findLastIndex(array, # != #) findLastIndex(array, # != 1) findLastIndex(array, # != f32) findLastIndex(array, # != f64) findLastIndex(array, # != i32) findLastIndex(array, # != i64) findLastIndex(array, # != nil) findLastIndex(array, # < #) findLastIndex(array, # < 1) findLastIndex(array, # < f64) findLastIndex(array, # < i) findLastIndex(array, # < i64) findLastIndex(array, # <= #) findLastIndex(array, # <= 0.5) findLastIndex(array, # <= i64) findLastIndex(array, # == #) findLastIndex(array, # == 0.5) findLastIndex(array, # == 1) findLastIndex(array, # == f64) findLastIndex(array, # == i64) findLastIndex(array, # == nil) findLastIndex(array, # > #) findLastIndex(array, # > 0.5) findLastIndex(array, # > f32) findLastIndex(array, # > f64) findLastIndex(array, # > i) findLastIndex(array, # >= #) findLastIndex(array, # >= 0.5) findLastIndex(array, # >= 1) findLastIndex(array, # >= f32) findLastIndex(array, # >= i32) findLastIndex(array, # ^ # >= #) findLastIndex(array, # not in array) findLastIndex(array, 0.5 != #) findLastIndex(array, 0.5 != i64) findLastIndex(array, 0.5 < #) findLastIndex(array, 0.5 < i32) findLastIndex(array, 0.5 <= #) findLastIndex(array, 0.5 > #) findLastIndex(array, 0.5 >= 0.5) findLastIndex(array, 0.5 >= f64) findLastIndex(array, 1 != #) findLastIndex(array, 1 <= #) findLastIndex(array, 1 == #) findLastIndex(array, 1 == f64) findLastIndex(array, 1 >= i32) findLastIndex(array, array == nil) findLastIndex(array, f32 != #) findLastIndex(array, f32 != f32) findLastIndex(array, f32 < #) findLastIndex(array, f32 == #) findLastIndex(array, f32 == nil) findLastIndex(array, f32 > #) findLastIndex(array, f64 != #) findLastIndex(array, f64 < #) findLastIndex(array, f64 <= #) findLastIndex(array, f64 <= i32) findLastIndex(array, f64 == #) findLastIndex(array, f64 == 0.5) findLastIndex(array, f64 > #) findLastIndex(array, false ? # : false) findLastIndex(array, foo != foo) findLastIndex(array, greet == greet) findLastIndex(array, i - # >= #) findLastIndex(array, i < #) findLastIndex(array, i <= #) findLastIndex(array, i > 0.5) findLastIndex(array, i32 <= #) findLastIndex(array, i32 <= 1) findLastIndex(array, i32 <= f32) findLastIndex(array, i32 > 0.5) findLastIndex(array, i32 >= #) findLastIndex(array, i64 <= # + #) findLastIndex(array, i64 > #) findLastIndex(array, min(1, #) <= i32 + #) findLastIndex(array, nil != #) findLastIndex(array, nil != add) findLastIndex(array, nil != i32) findLastIndex(array, nil == #) findLastIndex(array, not (i32 != 0.5)) findLastIndex(array, not ok) findLastIndex(array, ok && true) findLastIndex(array, ok) findLastIndex(array, ok) % i64 findLastIndex(array, ok) + f64 findLastIndex(array, one(list, ok)) findLastIndex(array, score == nil) findLastIndex(array, true == false) findLastIndex(array, true) / f32 findLastIndex(array, true) not in array findLastIndex(filter(array, false), ok) findLastIndex(groupBy(list, #).ok, #) findLastIndex(groupBy(list, 0.5).Bar, #?.String endsWith .f32(list)) findLastIndex(i32 .. i32, ok) findLastIndex(i64 .. 1, ok) findLastIndex(list, !(nil != #)) findLastIndex(list, !false) findLastIndex(list, !ok) findLastIndex(list, !true) findLastIndex(list, "bar" in #) findLastIndex(list, "bar" matches "foo") findLastIndex(list, "bar" not endsWith "foo") findLastIndex(list, "bar" not matches "bar") findLastIndex(list, "foo" <= "bar") findLastIndex(list, "foo" not in #) findLastIndex(list, # != #) findLastIndex(list, # != foo) findLastIndex(list, # == #) findLastIndex(list, # == foo) findLastIndex(list, # == nil) findLastIndex(list, # in list) findLastIndex(list, # not in list) findLastIndex(list, 1 != f32) findLastIndex(list, 1 != nil) findLastIndex(list, 1 > 1) findLastIndex(list, 1 >= 0.5) findLastIndex(list, array != nil) findLastIndex(list, div != nil) findLastIndex(list, f32 != 1) findLastIndex(list, f32 != f64) findLastIndex(list, f64 > 0.5) findLastIndex(list, foo == #) findLastIndex(list, i <= 1) findLastIndex(list, i32 > 1) findLastIndex(list, i32 > f32) findLastIndex(list, i64 == i64) findLastIndex(list, i64 >= 0.5) findLastIndex(list, i64 not in array) findLastIndex(list, nil != "bar") findLastIndex(list, nil != #) findLastIndex(list, nil != f64) findLastIndex(list, nil == #) findLastIndex(list, nil == 1) findLastIndex(list, nil == half) findLastIndex(list, not false) findLastIndex(list, not true) findLastIndex(list, ok ? ok : 0.5) findLastIndex(list, ok and false) findLastIndex(list, ok) findLastIndex(list, ok) != i64 findLastIndex(list, ok) > f32 findLastIndex(list, ok) > i64 findLastIndex(list, one(array, true)) findLastIndex(list, true && ok) findLastIndex(list, true) * i32 findLastIndex(list, true) - i32 findLastIndex(list, true) < i64 findLastIndex(list, true) > i64 findLastIndex(list, true) ^ f64 findLastIndex(map(array, "bar"), # not endsWith #) findLastIndex(map(array, #), # < f64) findLastIndex(map(array, #), # <= #) findLastIndex(map(array, #), ok) findLastIndex(map(array, div), 0.5 <= 0.5) findLastIndex(map(array, f32), nil == nil) findLastIndex(map(array, list), ok) findLastIndex(map(array, ok), # and #) findLastIndex(map(list, "bar"), # >= #) findLastIndex(map(list, #), !true) findLastIndex(map(list, #), nil == 0.5) findLastIndex(map(list, false), #) findLastIndex(map(list, foo), ok) findLastIndex(map(list, i32), # >= #) findLastIndex(map(list, i64), ok) findLastIndex(ok ? "bar" : add, not false) findLastIndex(true ? "foo" : 1, # and false) first(1 .. 1) first(1 .. i64) first([f32]) first([foo]) first([ok]) first(array) first(array) * i first(array) * i64 first(array) + f32 first(array) <= i first(array) == f32 first(array) == f64 first(array) == i64 first(array) > 0.5 ** i first(array) > i64 first(array) ^ f64 first(array[1:1]) first(false ? foo : 1) first(false ? greet : foo) first(get(groupBy(array, #), i)) first(groupBy(array, #).greet) first(groupBy(list, #)?.div) first(i .. i) first(i64 .. i32) first(i64 .. i64) first(list) first(list) not in list first(list).Bar first(list).Qux first(list).String first(list).String() first(list)?.Bar first(list)?.Qux first(list)?.String first(list)?.String() first(map(array, #)) first(map(array, 0.5)) first(map(array, 1)) first(map(array, add)) first(map(array, array)) first(map(array, div)) first(map(array, half)) first(map(array, i)) first(map(array, i32)) first(map(array, i64)) first(map(array, ok)) first(map(list, #)) first(map(list, 0.5)) first(map(list, f32)) first(map(list, greet)) first(map(list, i)) first(map(list, list)) first(map(list, score)) first(ok ? 0.5 : false) first(ok ? array : add) first(ok ? greet : i64) first(ok ? list : ok) first(reduce(list, array)) first(sort(array)) first(true ? f32 : div) first(true ? greet : div) first(true ? score : div) float(-0.5) float(-1) float(-f32) float(-f64) float(-i) float(-i32) float(-i64) float(0.5 * 0.5) float(0.5 * 1) float(0.5 * f32) float(0.5 * i64) float(0.5 ** 0.5) float(0.5 ** f32) float(0.5 + 1) float(0.5 + i32) float(0.5 + i64) float(0.5 - 0.5) float(0.5 - 1) float(0.5 - i64) float(0.5 / 0.5) float(0.5 / i32) float(0.5 / i64) float(0.5 ^ 1) float(0.5 ^ i) float(0.5) != f32 float(0.5) != i32 float(0.5) * f32 float(0.5) * i32 float(0.5) * i64 float(0.5) ** f64 float(0.5) ** i float(0.5) ** i32 float(0.5) - i float(0.5) - i64 float(0.5) / f32 float(0.5) / f64 float(0.5) / i32 float(0.5) == i32 * 0.5 float(0.5) ^ i64 float(0.5) in array float(1 % i64) float(1 * 0.5) float(1 * f32) float(1 * i) float(1 * i64) float(1 ** 0.5) float(1 ** 1) float(1 ** f64) float(1 ** i) float(1 + f64) float(1 + i32) float(1 - 0.5) float(1 / 0.5) float(1 ^ f64) float(1) * f32 float(1) * i64 float(1) ** i float(1) ** i64 float(1) - f64 float(1) <= i64 float(1) == i64 float(1) > -0.5 float(1) > i64 float(1) >= f64 float(1) >= i float(abs(f32)) float(abs(f64)) float(abs(i)) float(abs(i32)) float(add(1, 1)) float(array[i32]) float(array[i64]) float(array[i]) float(bitnot(1)) float(bitnot(i)) float(bitnot(i32)) float(bitnot(i64)) float(ceil(0.5)) float(ceil(f32)) float(ceil(f64)) float(ceil(i32)) float(ceil(i64)) float(count(array, false)) float(count(array, ok)) float(count(list, i32 == 0.5)) float(f32 * f64) float(f32 * i) float(f32 * i32) float(f32 ** 1) float(f32 ** f32) float(f32 ** i) float(f32 ** i64) float(f32 + 0.5) float(f32 + 1) float(f32 + f64) float(f32 + i32) float(f32 + i64) float(f32 - 0.5) float(f32 - f64) float(f32 - i64) float(f32 / 0.5) float(f32 / 1) float(f32 / i) float(f32 ^ 0.5) float(f32 ^ 1) float(f32 ^ f32) float(f32 ^ i) float(f32 ^ i32) float(f32) float(f32) < i32 float(f32) <= f32 float(f32) <= f64 / f32 float(f32) <= i float(f32) > i float(f32) >= i64 float(f32) ^ f64 float(f32) ^ i64 float(f64 * 0.5) float(f64 * 1) float(f64 * f32) float(f64 * f64) float(f64 * i32) float(f64 ** f32) float(f64 + 1) float(f64 + i) float(f64 + i32) float(f64 - 1) float(f64 - i) float(f64 / 0.5) float(f64 / 1) float(f64 / i64) float(f64 ^ f32) float(f64) float(f64) * f32 float(f64) * i float(f64) / -i32 float(f64) / i float(f64) == f64 float(f64) > f64 float(f64) > i64 float(f64) >= f32 float(f64) >= i float(f64) >= i64 float(f64) ^ i64 float(false ? f64 : 0.5) float(false ? half : f64) float(false ? list : f64) float(find(array, ok)) float(findIndex(array, ok)) float(findLastIndex(array, ok)) float(findLastIndex(list, true)) float(first(array)) float(float(0.5)) float(float(1)) float(float(f32)) float(float(f64)) float(float(i)) float(float(i32)) float(floor(0.5)) float(floor(1)) float(floor(f32)) float(floor(f64)) float(floor(i32)) float(floor(i64)) float(get(array, 1)) float(get(array, i)) float(half(0.5)) float(half(1)) float(half(f64)) float(i % i32) float(i * 0.5) float(i * f64) float(i * i64) float(i ** f32) float(i ** i32) float(i + 0.5) float(i + 1) float(i + i64) float(i - 1) float(i - f64) float(i / 0.5) float(i / 1) float(i ^ 0.5) float(i ^ i32) float(i) float(i) != 1 ? nil : foo float(i) != f64 float(i) + f32 float(i) + f64 float(i) < i float(i) == f32 float(i) == i float(i) > f64 float(i32 % i) float(i32 % i64) float(i32 * f64) float(i32 * i32) float(i32 ** 1) float(i32 + f64) float(i32 + i64) float(i32 / 1) float(i32 / f32) float(i32 / i32) float(i32 ^ f64) float(i32 ^ i32) float(i32) float(i32) != f64 float(i32) ** f32 float(i32) ** i float(i32) > i32 float(i32) >= i float(i64 % i64) float(i64 * i64) float(i64 ** 1) float(i64 + f32) float(i64 + i) float(i64 - 0.5) float(i64 - 1) float(i64 - f32) float(i64 / 1) float(i64 ^ f32) float(i64) float(i64) != i float(i64) ** max(f64) float(i64) + i32 float(i64) - 0.5 ^ f32 float(i64) - f64 float(i64) / i32 float(i64) < i32 float(i64) == i float(i64) == i64 float(i64) > i float(i64) ^ f32 float(int(0.5)) float(int(1)) float(int(f32)) float(int(i)) float(int(i32)) float(last(array)) float(len("bar")) float(len(array)) float(len(list)) float(max(0.5)) float(max(0.5, i64)) float(max(1)) float(max(1, 1)) float(max(f32)) float(max(f64)) float(max(i)) float(max(i32)) float(max(i64)) float(mean(array)) float(min(1)) float(min(f64)) float(min(f64, i64)) float(min(i32)) float(min(i64)) float(ok ? 0.5 : foo) float(ok ? 0.5 : list) float(reduce(array, #)) float(reduce(array, 0.5)) float(reduce(array, f64)) float(reduce(array, i32)) float(reduce(list, i64)) float(round(0.5)) float(round(1)) float(round(i32)) float(round(i64)) float(score(1)) float(score(1, 1)) float(score(i)) float(string(0.5)) float(string(1)) float(string(f64 - 0.5)) float(string(i)) float(string(i32)) float(string(i64)) float(sum(array)) float(toJSON(0.5)) float(toJSON(1)) float(toJSON(f32)) float(toJSON(f64)) float(toJSON(i32)) float(toJSON(i64)) float(true ? f32 : "foo") floor(-0.5) floor(-1) floor(-f32) floor(-f64) floor(-i) floor(-i32) floor(-i64) floor(0.5 * 0.5) floor(0.5 * 1) floor(0.5 * i32) floor(0.5 ** 1) floor(0.5 ** f64) floor(0.5 ** i) floor(0.5 + 1) floor(0.5 + f32) floor(0.5 + i) floor(0.5 + i32) floor(0.5 + i64) floor(0.5 - 1) floor(0.5 - f32) floor(0.5 - i) floor(0.5 / 0.5) floor(0.5 / 1) floor(0.5 / i32) floor(0.5 ^ 0.5) floor(0.5 ^ 1) floor(0.5 ^ f32) floor(0.5 ^ f64) floor(0.5 ^ i) floor(0.5) != i64 floor(0.5) ** f32 floor(0.5) - i floor(0.5) - i64 floor(0.5) / i floor(0.5) <= i64 floor(0.5) > i32 floor(0.5) > i64 != ok floor(0.5) >= f32 floor(0.5) ^ i floor(1 % 1) floor(1 % i) floor(1 * 0.5) floor(1 * 1) floor(1 ** 1) floor(1 ** f64) floor(1 ** i32) floor(1 + 0.5) floor(1 + 1) floor(1 + f32) floor(1 + f64) floor(1 + i32) floor(1 - 0.5) floor(1 - 1) floor(1 - i) floor(1 - i32) floor(1 - i64) floor(1 / 0.5) floor(1 / 1) floor(1 / i) floor(1 / i64) floor(1 ^ i) floor(1 ^ i32) floor(1 ^ i64) floor(1) * i64 floor(1) - f32 floor(1) - i floor(1) <= f32 floor(1) >= half(0.5) floor(abs(0.5)) floor(abs(1)) floor(abs(f32)) floor(abs(f64)) floor(abs(i32)) floor(abs(i64)) floor(array[1]) floor(array[i32]) floor(array[i64]) floor(array[i]) floor(bitnot(1)) floor(bitnot(i)) floor(bitnot(i32)) floor(bitnot(i64)) floor(ceil(0.5)) floor(ceil(1)) floor(ceil(f64)) floor(ceil(i)) floor(ceil(i32)) floor(ceil(i64)) floor(count(array, false)) floor(count(array, ok)) floor(count(list, ok)) floor(f32 ** 1) floor(f32 ** f64) floor(f32 ** i32) floor(f32 + f32) floor(f32 + i32) floor(f32 + i64) floor(f32 - 0.5) floor(f32 - f64) floor(f32 / 0.5) floor(f32 / f64) floor(f32 / i) floor(f32 / i32) floor(f32 / i64) floor(f32 ^ 0.5) floor(f32 ^ f64) floor(f32 ^ i) floor(f32) floor(f32) != -i32 floor(f32) * i32 floor(f32) + f32 floor(f32) / f32 floor(f32) / f64 floor(f32) == i64 floor(f32) > i32 floor(f32) >= f32 floor(f32) >= i floor(f32) ^ f32 floor(f64 * f32) floor(f64 ** 0.5) floor(f64 ** 1) floor(f64 ** i32) floor(f64 + 0.5) floor(f64 + 1) floor(f64 + i32) floor(f64 - 0.5) floor(f64 - i32) floor(f64 / 0.5) floor(f64 / 1) floor(f64 / f32) floor(f64 / f64) floor(f64 / i) floor(f64 ^ 1) floor(f64) floor(f64) * i32 floor(f64) ** f64 floor(f64) / f32 floor(f64) < i32 floor(f64) <= f64 floor(f64) <= i64 floor(f64) == f64 ** i floor(f64) == i floor(f64) > i32 floor(f64) >= 1 * 1 floor(f64) >= f32 floor(false ? div : 0.5) floor(find(array, true)) floor(findIndex(array, ok)) floor(findLastIndex(array, ok)) floor(float(0.5)) floor(float(1)) floor(float(f64)) floor(float(i32)) floor(floor(0.5)) floor(floor(1)) floor(floor(f32)) floor(floor(f64)) floor(floor(i)) floor(floor(i32)) floor(floor(i64)) floor(get(array, 1)) floor(get(array, i)) floor(get(array, i64)) floor(half(0.5)) floor(half(1)) floor(half(f64)) floor(i % 1) floor(i % i) floor(i % i32) floor(i % i64) floor(i * 1) floor(i * f64) floor(i ** 0.5) floor(i ** f32) floor(i ** i32) floor(i ** i64) floor(i + 0.5) floor(i + f64) floor(i - 0.5) floor(i - f32) floor(i - i32) floor(i / 0.5) floor(i / 1) floor(i / f64) floor(i ^ i32) floor(i) floor(i) != i floor(i) * f64 floor(i) ^ i floor(i32 % i32) floor(i32 * 1) floor(i32 * f32) floor(i32 * f64) floor(i32 * i32) floor(i32 ** i) floor(i32 ** i64) floor(i32 + 0.5) floor(i32 + f64) floor(i32 - 1) floor(i32 - f32) floor(i32 - i) floor(i32 - i32) floor(i32 - i64) floor(i32 ^ 0.5) floor(i32 ^ 1) floor(i32 ^ f64) floor(i32 ^ i) floor(i32 ^ i32) floor(i32 ^ i64) floor(i32) floor(i32) != f32 floor(i32) * f64 floor(i32) * i floor(i32) * i64 floor(i32) > i32 floor(i32) > i64 floor(i32) >= i32 floor(i32) ^ i32 floor(i64 % i) floor(i64 * 0.5) floor(i64 * f32) floor(i64 * i) floor(i64 ** 0.5) floor(i64 ** 1) floor(i64 ** i) floor(i64 ** i32) floor(i64 + 0.5) floor(i64 + f64) floor(i64 + i64) floor(i64 - f64) floor(i64 - i) floor(i64 / f32) floor(i64 ^ 0.5) floor(i64 ^ f32) floor(i64 ^ i64) floor(i64) floor(i64) * i64 floor(i64) / (i64 - i) floor(i64) / f64 floor(i64) / i32 floor(i64) < f32 floor(i64) <= i64 floor(i64) ^ f32 floor(int(0.5)) floor(int(1)) floor(int(i32)) floor(int(i64)) floor(len("foo")) floor(len(array)) floor(len(list)) floor(max(0.5)) floor(max(1)) floor(max(f32)) floor(max(f64)) floor(max(i32)) floor(min(0.5)) floor(min(f64) ^ i64) floor(min(i, i64)) floor(min(i32)) floor(ok ? 1 : 1) floor(ok ? f32 : "foo") floor(ok ? i64 : f64) floor(reduce(array, #)) floor(reduce(array, i)) floor(reduce(array, i64)) floor(reduce(list, 1)) floor(reduce(list, f32)) floor(reduce(list, i64)) floor(round(0.5)) floor(round(f32)) floor(round(f64)) floor(round(i)) floor(round(i32)) floor(score(1)) floor(score(1, 1)) floor(score(i)) floor(true ? 0.5 : false) floor(true ? 1 : true) floor(true ? f64 : 0.5) floor(true ? f64 : array) foo foo != foo foo != nil != nil foo != reduce(list, #) foo == foo foo == foo and 0.5 != f64 foo == get(list, 1) foo == list[i] foo == nil ? i : i32 foo == nil ? i64 : i foo == reduce(list, #) foo in filter(list, false) foo in groupBy(array, #) foo in groupBy(list, #) foo in list foo in list != ok foo not in groupBy(array, #) foo not in groupBy(array, f64).foo foo not in groupBy(list, #).i foo not in groupBy(list, f32) foo not in groupBy(list, ok) foo not in list foo not in list and ok foo not in list or false foo not in map(list, #) foo.Bar foo.Bar <= foo.Bar foo.Bar matches foo.Bar foo.Bar matches trimPrefix("foo") foo.Qux foo.Qux("foo" + "foo") foo.Qux(foo.Bar) foo.Qux(foo.String()) foo.Qux(greet("foo")) foo.Qux(string("foo")) foo.Qux(toJSON(i)) foo.Qux(type("bar")) foo.Qux(type(f64)) foo.Qux(type(half)) foo.String foo.String() foo.String() != foo?.String() foo.String() in foo foo.String() not in foo foo?.Bar foo?.Bar != foo?.Bar foo?.Bar in foo foo?.Bar matches toJSON(f64) foo?.Bar not endsWith foo.Bar foo?.Bar not endsWith toJSON(foo) foo?.Qux foo?.Qux(foo?.Bar) foo?.Qux(string(i32)) foo?.Qux(toJSON(1)) foo?.Qux(toJSON(i32)) foo?.Qux(upper("bar")) foo?.String foo?.String() foo?.String() contains string("foo") fromBase64(string(ok)) fromBase64(toBase64("bar")) fromBase64(type(1 == 0.5)) fromBase64(type(add)) fromBase64(type(div)) fromBase64(type(false)) fromBase64(type(greet)) fromBase64(type(half)) fromBase64(type(ok)) fromBase64(type(score)) fromBase64(type(true)) fromJSON(string(1)) fromJSON(string(f32)) fromJSON(string(f64)) fromJSON(string(i)) fromJSON(string(i32)) fromJSON(string(i64)) fromJSON(string(ok)) fromJSON(string(true)) fromJSON(toJSON("bar")) fromJSON(toJSON(0.5)) fromJSON(toJSON(array)) fromJSON(toJSON(f64)) fromJSON(toJSON(false)) fromJSON(toJSON(foo)) fromJSON(toJSON(i)) fromJSON(toJSON(i32)) fromJSON(toJSON(list)) fromJSON(toJSON(nil)) fromJSON(toJSON(true)) fromPairs(filter(array, false)) fromPairs(filter(list, false)) fromPairs(groupBy(array, #).String) get(["foo"], i32) get(array, -1) get(array, -i32) get(array, -i64) get(array, -score(1)) get(array, 1 * 1) get(array, 1 * i) get(array, 1) ** f32 get(array, 1) < f32 get(array, 1) > i32 get(array, 1) > i64 get(array, bitnot(1)) get(array, count(array, ok)) get(array, false ? "foo" : 0.5) get(array, i) get(array, i) != f32 get(array, i) != i32 get(array, i) * i32 get(array, i) - i get(array, i) / i64 get(array, i) > f64 get(array, i) >= f64 get(array, i) >= i64 get(array, i) ^ half(0.5) get(array, i32 % i32) get(array, i32) get(array, i32) / f64 get(array, i32) < i get(array, i64 - 1) get(array, i64) get(array, i64) > f64 get(array, last(array)) get(array, min(i)) get(array, reduce(array, #)) get(array, reduce(list, i64)) get(array, score(1)) get(array, score(abs(1))) get(array, score(i)) get(array, sum(array)) get(false ? 0.5 : greet, list) get(false ? add : array, f64) get(false ? add : score, ok) get(false ? f64 : 1, ok) get(false ? f64 : score, add) get(false ? false : f32, i) get(false ? i32 : list, i64) get(false ? i64 : true, f64) get(false ? score : ok, trimSuffix("bar", "bar")) get(filter(list, true), i) get(groupBy(array, "bar"), i) get(groupBy(array, "bar"), ok) get(groupBy(array, #), f32) get(groupBy(array, #), f64) get(groupBy(array, #), foo) get(groupBy(array, #), i) get(groupBy(array, #), i64 * 0.5) get(groupBy(array, #), i64) get(groupBy(array, 0.5), ok) get(groupBy(array, 1), f32) get(groupBy(array, f64), i64) get(groupBy(array, false), findIndex(array, ok)) get(groupBy(array, i), ok) get(groupBy(array, true), i32) get(groupBy(list, "bar"), i32) get(groupBy(list, #), f32 <= f64) get(groupBy(list, #), f32) get(groupBy(list, #), foo) get(groupBy(list, #), i) get(groupBy(list, #), i32) get(groupBy(list, #), i64) get(groupBy(list, #), int(f32)) get(groupBy(list, #), reduce(array, foo)) get(groupBy(list, #), score(1)) get(groupBy(list, 0.5), ok) get(groupBy(list, 1), i32) get(groupBy(list, foo), i32) get(i .. 1, 1 * 1) get(i .. i32, i) get(i32 .. i, i64) get(i64 .. 1, i32) get(i64 .. i, i32) get(i64 .. i64, i64) get(list, -1) get(list, -i) get(list, -i64) get(list, 1 * 1) get(list, 1 - 1) get(list, 1 - i) get(list, 1) != foo get(list, 1).Bar get(list, 1).Qux get(list, 1).String get(list, 1).String() get(list, 1)?.Bar get(list, 1)?.Qux get(list, 1)?.String get(list, 1)?.String() get(list, bitshr(i, i32)) get(list, first(array)) get(list, get(array, 1)) get(list, get(array, i64)) get(list, i % 1) get(list, i) get(list, i).Bar get(list, i).Qux get(list, i).String get(list, i)?.Bar get(list, i)?.Qux get(list, i)?.String get(list, i)?.String() get(list, i32 * i32) get(list, i32 - i32) get(list, i32) get(list, i32).Bar get(list, i32).Qux get(list, i32).String get(list, i32)?.Bar get(list, i32)?.Qux get(list, i32)?.String get(list, i32)?.String() get(list, i64 * 1) get(list, i64 * i) get(list, i64 - 1) get(list, i64) get(list, i64).Bar get(list, i64).Qux get(list, i64).String get(list, i64)?.Bar get(list, i64)?.Qux get(list, i64)?.String get(list, i64)?.String() get(list, int(1)) get(list, max(i32)) get(list, min(i32)) get(list, min(i64)) get(list, ok ? 0.5 : "foo") get(list, reduce(list, i64)) get(list, score(1)) get(list, score(i)) get(list, true ? i : i32) get(list[i64:1], i) get(map(array, #), i) get(map(array, #), i32) get(map(array, #), i64) get(map(array, add), i32) get(map(array, array), i) get(map(array, greet), i64) get(map(array, half), i64) get(map(list, "foo"), i64) get(map(list, #), i) get(map(list, #), i64) get(map(list, 1), i32) get(map(list, array), i) get(map(list, i32), i64) get(map(list, i64), i64) get(ok ? 1 : "bar", f32) get(ok ? add : f32, array) get(ok ? f64 : div, i64) get(ok ? false : list, f32 > i) get(ok ? half : i32, i) get(ok ? half : ok, f64) get(ok ? i : 0.5, half) get(ok ? i32 : half, f64) get(ok ? i64 : foo, f32) get(ok ? list : i32, f32) get(ok ? ok : div, greet) get(ok ? score : f64, i) get(ok ? score : i64, foo) get(reduce(list, array), i32) get(sort(array), i32) get(take(list, i), i64) get(true ? "bar" : ok, score(i)) get(true ? 0.5 : i32, array) get(true ? f32 : 0.5, ok) get(true ? false : foo, i64 > 0.5) get(true ? greet : i32, score) get(true ? half : f32, greet) get(true ? half : list, add) get(true ? i64 : greet, i32) get(true ? score : true, half)?.half get(true ? true : i, f64) get({"foo": foo, "bar": false}, type(i)) greet greet != greet greet != greet != ok greet != nil ? "bar" : add greet != nil ? 0.5 : false greet != nil ? list : false greet == greet greet == greet ? 0.5 : "bar" greet == greet and ok greet == nil == ok greet == nil ? i64 : ok greet in groupBy(array, f64).f32 greet in groupBy(list, #).score greet not in sort(array) greet("bar" + "bar") greet("foo" + "foo") greet("foo") startsWith type(f64) greet(false ? i64 : "bar") greet(foo.Bar) greet(foo.Qux("foo")) greet(foo.String()) greet(foo?.Bar) greet(foo?.String()) greet(greet("bar")) greet(greet("foo")) greet(lower("bar")) greet(lower("foo")) greet(ok ? "bar" : 1) greet(ok ? "bar" : i64) greet(ok ? "foo" : 0.5) greet(ok ? "foo" : div) greet(ok ? "foo" : true) greet(reduce(array, "bar")) greet(reduce(array, "foo")) greet(reduce(list, "foo")) greet(repeat("bar", 1)) greet(repeat(foo?.String(), i32)) greet(string("bar")) greet(string("foo")) greet(string(0.5)) greet(string(1)) greet(string(add)) greet(string(array)) greet(string(div)) greet(string(f32)) greet(string(f64)) greet(string(false)) greet(string(foo)) greet(string(greet)) greet(string(half)) greet(string(i)) greet(string(i32)) greet(string(i64)) greet(string(list)) greet(string(nil)) greet(string(ok)) greet(string(score)) greet(string(true)) greet(toBase64("bar")) greet(toBase64(trimPrefix("bar"))) greet(toJSON("bar")) greet(toJSON("foo")) greet(toJSON(0.5)) greet(toJSON(1)) greet(toJSON(array)) greet(toJSON(f32)) greet(toJSON(f64)) greet(toJSON(false)) greet(toJSON(foo)) greet(toJSON(i)) greet(toJSON(i32)) greet(toJSON(i64)) greet(toJSON(list)) greet(toJSON(nil)) greet(toJSON(ok)) greet(toJSON(true)) greet(trim("bar")) greet(trim("foo")) greet(trimPrefix("bar")) greet(trimPrefix("foo")) greet(trimSuffix("bar")) greet(trimSuffix("foo")) greet(trimSuffix(foo.String())) greet(trimSuffix(foo?.Bar)) greet(true ? "bar" : i64) greet(true ? "bar" : ok) greet(true ? "foo" : foo) greet(type("bar")) greet(type("foo")) greet(type(0.5)) greet(type(1)) greet(type(add)) greet(type(array)) greet(type(div)) greet(type(f32)) greet(type(f64)) greet(type(false)) greet(type(foo)) greet(type(greet)) greet(type(half)) greet(type(i)) greet(type(i32)) greet(type(i64)) greet(type(list)) greet(type(nil)) greet(type(ok)) greet(type(score)) greet(type(true)) greet(upper("bar")) greet(upper("foo")) groupBy(1 .. 1, #).f64 groupBy(1 .. i, #) groupBy(1 .. i, i32)?.score groupBy(1 .. i32, #) groupBy(1 .. i32, ok) groupBy(1 .. i64, i32) groupBy([0.5, f64], nil == "foo") groupBy([1], # <= #) groupBy([f32 ^ i64], #) groupBy([f32], f64) groupBy([f64], # >= f32) groupBy([half], f32) groupBy([i32], array[#]) groupBy([nil], foo) groupBy([true], #) groupBy(array, !false) groupBy(array, !true) groupBy(array, "bar" in foo).String groupBy(array, "bar").Bar groupBy(array, "bar").Qux groupBy(array, "bar").String groupBy(array, "bar").add groupBy(array, "bar").array groupBy(array, "bar").div groupBy(array, "bar").f32 groupBy(array, "bar").f64 groupBy(array, "bar").foo groupBy(array, "bar").greet groupBy(array, "bar").half groupBy(array, "bar").i groupBy(array, "bar").i32 groupBy(array, "bar").i64 groupBy(array, "bar").list groupBy(array, "bar").ok groupBy(array, "bar").score groupBy(array, "bar")?.Bar groupBy(array, "bar")?.Qux groupBy(array, "bar")?.String groupBy(array, "bar")?.add groupBy(array, "bar")?.array groupBy(array, "bar")?.div groupBy(array, "bar")?.f32 groupBy(array, "bar")?.f64 groupBy(array, "bar")?.foo groupBy(array, "bar")?.greet groupBy(array, "bar")?.half groupBy(array, "bar")?.i groupBy(array, "bar")?.i64 groupBy(array, "bar")?.list groupBy(array, "bar")?.ok groupBy(array, "bar")?.score groupBy(array, "bar")[f32 > f32] groupBy(array, "foo").Bar groupBy(array, "foo").Qux groupBy(array, "foo").String groupBy(array, "foo").add groupBy(array, "foo").array groupBy(array, "foo").div groupBy(array, "foo").f32 groupBy(array, "foo").f64 groupBy(array, "foo").foo groupBy(array, "foo").greet groupBy(array, "foo").half groupBy(array, "foo").i groupBy(array, "foo").i32 groupBy(array, "foo").i64 groupBy(array, "foo").list groupBy(array, "foo").ok groupBy(array, "foo").score groupBy(array, "foo")?.Bar groupBy(array, "foo")?.String groupBy(array, "foo")?.add groupBy(array, "foo")?.array groupBy(array, "foo")?.div groupBy(array, "foo")?.f32 groupBy(array, "foo")?.f64 groupBy(array, "foo")?.foo groupBy(array, "foo")?.greet groupBy(array, "foo")?.half groupBy(array, "foo")?.i groupBy(array, "foo")?.i32 groupBy(array, "foo")?.i64 groupBy(array, "foo")?.list groupBy(array, "foo")?.ok groupBy(array, "foo")?.score groupBy(array, # != #) groupBy(array, # != #).Qux groupBy(array, # != #)?.array groupBy(array, # != 0.5) groupBy(array, # != 1) groupBy(array, # != f32) groupBy(array, # != f64) groupBy(array, # != f64)?.String groupBy(array, # != i64) groupBy(array, # != nil) groupBy(array, # % #) groupBy(array, # % 1) groupBy(array, # % i32) groupBy(array, # * #) groupBy(array, # * #)?.Qux groupBy(array, # * 0.5) groupBy(array, # * 1) groupBy(array, # * i) groupBy(array, # * i32) groupBy(array, # * i64) groupBy(array, # ** #) groupBy(array, # ** #).add groupBy(array, # ** 0.5) groupBy(array, # ** 0.5)?.foo groupBy(array, # ** 0.5)?.greet groupBy(array, # ** 1) groupBy(array, # ** f64) groupBy(array, # ** i) groupBy(array, # ** i32) groupBy(array, # ** i64) groupBy(array, # + #) groupBy(array, # + 1) groupBy(array, # + f32) groupBy(array, # + i) groupBy(array, # - #) groupBy(array, # - 0.5) groupBy(array, # - 1) groupBy(array, # - f32) groupBy(array, # - f64) groupBy(array, # - i) groupBy(array, # - i32) groupBy(array, # / #) groupBy(array, # / 0.5) groupBy(array, # / 0.5)?.foo groupBy(array, # / 1) groupBy(array, # / i) groupBy(array, # / i32) groupBy(array, # / i64) groupBy(array, # < # || 0.5 > f64) groupBy(array, # < #) groupBy(array, # < 0.5) groupBy(array, # < 1) groupBy(array, # < i32) groupBy(array, # < i64) groupBy(array, # <= #) groupBy(array, # <= #)?.Bar groupBy(array, # <= #)?.Qux groupBy(array, # <= 0.5) groupBy(array, # <= 1) groupBy(array, # <= f32) groupBy(array, # <= f64) groupBy(array, # <= i) groupBy(array, # <= i64) groupBy(array, # == #) groupBy(array, # == #).String groupBy(array, # == #)?.half groupBy(array, # == 0.5) groupBy(array, # == 1) groupBy(array, # == f32) groupBy(array, # == f32).half groupBy(array, # == f64) groupBy(array, # == i) groupBy(array, # == i64) groupBy(array, # == nil) groupBy(array, # > #) groupBy(array, # > 0.5) groupBy(array, # > 1) groupBy(array, # > 1).Bar groupBy(array, # > i)?.i64 groupBy(array, # > i64) groupBy(array, # >= #) groupBy(array, # >= f64) groupBy(array, # >= i) groupBy(array, # >= i32) groupBy(array, # >= i64) groupBy(array, # ^ #) groupBy(array, # ^ 0.5) groupBy(array, # ^ f32) groupBy(array, # ^ i) groupBy(array, # ^ i32) groupBy(array, # in array) groupBy(array, #) groupBy(array, #).Bar groupBy(array, #).Qux groupBy(array, #).String groupBy(array, #).add groupBy(array, #).array groupBy(array, #).div groupBy(array, #).f32 groupBy(array, #).f64 groupBy(array, #).foo groupBy(array, #).greet groupBy(array, #).half groupBy(array, #).i groupBy(array, #).i32 groupBy(array, #).i64 groupBy(array, #).list groupBy(array, #).ok groupBy(array, #).score groupBy(array, #)?.Bar groupBy(array, #)?.Qux groupBy(array, #)?.String groupBy(array, #)?.add groupBy(array, #)?.array groupBy(array, #)?.div groupBy(array, #)?.f32 groupBy(array, #)?.f64 groupBy(array, #)?.foo groupBy(array, #)?.greet groupBy(array, #)?.half groupBy(array, #)?.i groupBy(array, #)?.i32 groupBy(array, #)?.i64 groupBy(array, #)?.list groupBy(array, #)?.ok groupBy(array, #)?.score groupBy(array, #)[1 / i] groupBy(array, #)[f32] groupBy(array, #)[f64] groupBy(array, #)[foo] groupBy(array, #)[i32] groupBy(array, #)[i64] groupBy(array, #)[i] groupBy(array, #)[ok] groupBy(array, #)[reduce(list, #)] groupBy(array, -# * # * 0.5) groupBy(array, -#) groupBy(array, -#).Qux groupBy(array, -0.5) groupBy(array, -1) groupBy(array, -f32) groupBy(array, -i)?.score groupBy(array, -i32) groupBy(array, -i64) groupBy(array, 0.5 != #) groupBy(array, 0.5 * #) groupBy(array, 0.5 * 0.5) groupBy(array, 0.5 * f64) groupBy(array, 0.5 ** #) groupBy(array, 0.5 ** 1) groupBy(array, 0.5 ** i64) groupBy(array, 0.5 + #)?.score groupBy(array, 0.5 + f32) groupBy(array, 0.5 - 1) groupBy(array, 0.5 / #).array groupBy(array, 0.5 / f64) groupBy(array, 0.5 / i64) groupBy(array, 0.5 < 0.5) groupBy(array, 0.5 <= f32) groupBy(array, 0.5 == #) groupBy(array, 0.5 >= #) groupBy(array, 0.5 >= i32) groupBy(array, 0.5 >= i64) groupBy(array, 0.5 ^ f32) groupBy(array, 0.5 ^ i64) groupBy(array, 0.5).Bar groupBy(array, 0.5).Qux groupBy(array, 0.5).String groupBy(array, 0.5).add groupBy(array, 0.5).array groupBy(array, 0.5).div groupBy(array, 0.5).f32 groupBy(array, 0.5).f64 groupBy(array, 0.5).foo groupBy(array, 0.5).greet groupBy(array, 0.5).half groupBy(array, 0.5).i groupBy(array, 0.5).i32 groupBy(array, 0.5).i64 groupBy(array, 0.5).list groupBy(array, 0.5).ok groupBy(array, 0.5).score groupBy(array, 0.5)?.Bar groupBy(array, 0.5)?.Qux groupBy(array, 0.5)?.String groupBy(array, 0.5)?.add groupBy(array, 0.5)?.array groupBy(array, 0.5)?.div groupBy(array, 0.5)?.f32 groupBy(array, 0.5)?.f64 groupBy(array, 0.5)?.foo groupBy(array, 0.5)?.greet groupBy(array, 0.5)?.half groupBy(array, 0.5)?.i groupBy(array, 0.5)?.i32 groupBy(array, 0.5)?.i64 groupBy(array, 0.5)?.list groupBy(array, 0.5)?.ok groupBy(array, 0.5)?.score groupBy(array, 1 != #)?.String groupBy(array, 1 != 0.5) groupBy(array, 1 != f32) groupBy(array, 1 % #) groupBy(array, 1 % i) groupBy(array, 1 * 0.5) groupBy(array, 1 * i) groupBy(array, 1 + #) groupBy(array, 1 + 1) groupBy(array, 1 - #) groupBy(array, 1 - 1) groupBy(array, 1 / #) groupBy(array, 1 < #) groupBy(array, 1 < i32)?.array groupBy(array, 1 < i64)?.ok groupBy(array, 1 <= #) groupBy(array, 1 == #) groupBy(array, 1 == #).add groupBy(array, 1 == i32) groupBy(array, 1 == nil) groupBy(array, 1 > i) groupBy(array, 1 >= #) groupBy(array, 1 ^ #) groupBy(array, 1 not in array) groupBy(array, 1).Bar groupBy(array, 1).Qux groupBy(array, 1).String groupBy(array, 1).add groupBy(array, 1).array groupBy(array, 1).div groupBy(array, 1).f64 groupBy(array, 1).foo groupBy(array, 1).greet groupBy(array, 1).half groupBy(array, 1).i groupBy(array, 1).i32 groupBy(array, 1).i64 groupBy(array, 1).list groupBy(array, 1).ok groupBy(array, 1).score groupBy(array, 1)?.Bar groupBy(array, 1)?.Qux groupBy(array, 1)?.String groupBy(array, 1)?.add groupBy(array, 1)?.array groupBy(array, 1)?.div groupBy(array, 1)?.f32 groupBy(array, 1)?.f64 groupBy(array, 1)?.foo groupBy(array, 1)?.greet groupBy(array, 1)?.half groupBy(array, 1)?.i groupBy(array, 1)?.i32 groupBy(array, 1)?.i64 groupBy(array, 1)?.list groupBy(array, 1)?.ok groupBy(array, 1)?.score groupBy(array, abs(#)) groupBy(array, abs(0.5)) groupBy(array, abs(1)) groupBy(array, abs(f32)) groupBy(array, abs(f64)) groupBy(array, abs(i)) groupBy(array, abs(i64)) groupBy(array, add(#, #)) groupBy(array, add(#, 1))?.i64 groupBy(array, bitnand(1, #)) groupBy(array, bitnot(#)) groupBy(array, bitnot(1)) groupBy(array, bitor(#, #)) groupBy(array, bitor(1, #)) groupBy(array, bitor(i32, #)) groupBy(array, bitshl(1, #)) groupBy(array, bitshr(i, #)) groupBy(array, bitushr(#, #)) groupBy(array, ceil(#)) groupBy(array, ceil(i)) groupBy(array, ceil(i32)) groupBy(array, div(#, #)) groupBy(array, f32 != #) groupBy(array, f32 ** 0.5) groupBy(array, f32 - #) groupBy(array, f32 - f64) groupBy(array, f32 / #) groupBy(array, f32 < #) groupBy(array, f32 <= #) groupBy(array, f32 == #) groupBy(array, f32 > 0.5) groupBy(array, f32 > i32) groupBy(array, f32 ^ i) groupBy(array, f32) groupBy(array, f32).Bar groupBy(array, f32).Qux groupBy(array, f32).String groupBy(array, f32).add groupBy(array, f32).array groupBy(array, f32).div groupBy(array, f32).f64 groupBy(array, f32).greet groupBy(array, f32).half groupBy(array, f32).i groupBy(array, f32).i32 groupBy(array, f32).i64 groupBy(array, f32).list groupBy(array, f32).ok groupBy(array, f32).score groupBy(array, f32)?.Bar groupBy(array, f32)?.Qux groupBy(array, f32)?.String groupBy(array, f32)?.add groupBy(array, f32)?.array groupBy(array, f32)?.div groupBy(array, f32)?.f32 groupBy(array, f32)?.f64 groupBy(array, f32)?.greet groupBy(array, f32)?.half groupBy(array, f32)?.i32 groupBy(array, f32)?.i64 groupBy(array, f32)?.list groupBy(array, f32)?.ok groupBy(array, f32)?.score groupBy(array, f32)[foo] groupBy(array, f64 != #) groupBy(array, f64 != i64) groupBy(array, f64 ** #) groupBy(array, f64 - #) groupBy(array, f64 - #).i32 groupBy(array, f64 < #) groupBy(array, f64 == #) groupBy(array, f64 > #) groupBy(array, f64 >= #) groupBy(array, f64 >= 0.5) groupBy(array, f64) groupBy(array, f64).Bar groupBy(array, f64).Qux groupBy(array, f64).String groupBy(array, f64).add groupBy(array, f64).array groupBy(array, f64).div groupBy(array, f64).f32 groupBy(array, f64).f64 groupBy(array, f64).foo groupBy(array, f64).greet groupBy(array, f64).half groupBy(array, f64).i groupBy(array, f64).i32 groupBy(array, f64).i64 groupBy(array, f64).list groupBy(array, f64).ok groupBy(array, f64).score groupBy(array, f64)?.Bar groupBy(array, f64)?.Qux groupBy(array, f64)?.String groupBy(array, f64)?.add groupBy(array, f64)?.array groupBy(array, f64)?.div groupBy(array, f64)?.f32 groupBy(array, f64)?.f64 groupBy(array, f64)?.foo groupBy(array, f64)?.greet groupBy(array, f64)?.half groupBy(array, f64)?.i groupBy(array, f64)?.i32 groupBy(array, f64)?.i64 groupBy(array, f64)?.list groupBy(array, f64)?.ok groupBy(array, f64)?.score groupBy(array, f64)[i32] groupBy(array, false ? # : #) groupBy(array, false || ok) groupBy(array, false).Bar groupBy(array, false).Qux groupBy(array, false).String groupBy(array, false).add groupBy(array, false).array groupBy(array, false).div groupBy(array, false).f32 groupBy(array, false).f64 groupBy(array, false).greet groupBy(array, false).half groupBy(array, false).i groupBy(array, false).i32 groupBy(array, false).i64 groupBy(array, false).list groupBy(array, false).ok groupBy(array, false).score groupBy(array, false)?.Bar groupBy(array, false)?.Qux groupBy(array, false)?.String groupBy(array, false)?.add groupBy(array, false)?.array groupBy(array, false)?.div groupBy(array, false)?.f32 groupBy(array, false)?.f64 groupBy(array, false)?.foo groupBy(array, false)?.greet groupBy(array, false)?.half groupBy(array, false)?.i groupBy(array, false)?.i32 groupBy(array, false)?.i64 groupBy(array, false)?.list groupBy(array, false)?.ok groupBy(array, false)?.score groupBy(array, findLastIndex(list, true)) groupBy(array, float(#)) groupBy(array, floor(#)) groupBy(array, floor(i32)) groupBy(array, foo) groupBy(array, foo).Bar groupBy(array, foo).Qux groupBy(array, foo).String groupBy(array, foo).add groupBy(array, foo).array groupBy(array, foo).div groupBy(array, foo).f32 groupBy(array, foo).f64 groupBy(array, foo).foo groupBy(array, foo).greet groupBy(array, foo).half groupBy(array, foo).i groupBy(array, foo).i32 groupBy(array, foo).i64 groupBy(array, foo).list groupBy(array, foo).ok groupBy(array, foo).score groupBy(array, foo)?.Bar groupBy(array, foo)?.Qux groupBy(array, foo)?.String groupBy(array, foo)?.add groupBy(array, foo)?.array groupBy(array, foo)?.div groupBy(array, foo)?.f32 groupBy(array, foo)?.f64 groupBy(array, foo)?.foo groupBy(array, foo)?.greet groupBy(array, foo)?.half groupBy(array, foo)?.i groupBy(array, foo)?.i32 groupBy(array, foo)?.i64 groupBy(array, foo)?.list groupBy(array, foo)?.ok groupBy(array, foo)?.score groupBy(array, foo.Bar) groupBy(array, foo?.Bar) groupBy(array, get(array, #)) groupBy(array, get(list, #)) groupBy(array, get(list, i32)) groupBy(array, half(1)) groupBy(array, half(f64)) groupBy(array, half(f64))?.i64 groupBy(array, i != #) groupBy(array, i % #) groupBy(array, i * #) groupBy(array, i * #)?.f64 groupBy(array, i ** #) groupBy(array, i + #) groupBy(array, i - f64).array groupBy(array, i / #) groupBy(array, i < #) groupBy(array, i <= #) groupBy(array, i <= f64) groupBy(array, i > i) groupBy(array, i ^ #) groupBy(array, i ^ 0.5) groupBy(array, i) groupBy(array, i).Bar groupBy(array, i).Qux groupBy(array, i).String groupBy(array, i).add groupBy(array, i).array groupBy(array, i).div groupBy(array, i).f32 groupBy(array, i).f64 groupBy(array, i).foo groupBy(array, i).greet groupBy(array, i).half groupBy(array, i).i groupBy(array, i).i32 groupBy(array, i).i64 groupBy(array, i).list groupBy(array, i).ok groupBy(array, i).score groupBy(array, i)?.Bar groupBy(array, i)?.String groupBy(array, i)?.add groupBy(array, i)?.array groupBy(array, i)?.div groupBy(array, i)?.f32 groupBy(array, i)?.f64 groupBy(array, i)?.foo groupBy(array, i)?.greet groupBy(array, i)?.half groupBy(array, i)?.i groupBy(array, i)?.i32 groupBy(array, i)?.i64 groupBy(array, i)?.list groupBy(array, i)?.ok groupBy(array, i)?.score groupBy(array, i)[f64] groupBy(array, i)[false ? i32 : ok] groupBy(array, i32 * f64) groupBy(array, i32 ** # <= i32) groupBy(array, i32 ** f64) groupBy(array, i32 ** i) groupBy(array, i32 ** i64) groupBy(array, i32 + #) groupBy(array, i32 - 1)?.foo groupBy(array, i32 - i64) groupBy(array, i32 / #) groupBy(array, i32 / f32) groupBy(array, i32 < #) groupBy(array, i32 < f64) groupBy(array, i32 <= 1) groupBy(array, i32 == #) groupBy(array, i32 == i) groupBy(array, i32 > #) groupBy(array, i32 >= #).Bar groupBy(array, i32 ^ #) groupBy(array, i32) groupBy(array, i32).Bar groupBy(array, i32).Qux groupBy(array, i32).String groupBy(array, i32).add groupBy(array, i32).array groupBy(array, i32).div groupBy(array, i32).f32 groupBy(array, i32).f64 groupBy(array, i32).greet groupBy(array, i32).half groupBy(array, i32).i groupBy(array, i32).i32 groupBy(array, i32).i64 groupBy(array, i32).list groupBy(array, i32).ok groupBy(array, i32).score groupBy(array, i32)?.Bar groupBy(array, i32)?.Qux groupBy(array, i32)?.String groupBy(array, i32)?.add groupBy(array, i32)?.array groupBy(array, i32)?.div groupBy(array, i32)?.f32 groupBy(array, i32)?.f64 groupBy(array, i32)?.foo groupBy(array, i32)?.greet groupBy(array, i32)?.half groupBy(array, i32)?.i groupBy(array, i32)?.i32 groupBy(array, i32)?.i64 groupBy(array, i32)?.list groupBy(array, i32)?.ok groupBy(array, i32)?.score groupBy(array, i32)[i] groupBy(array, i64 != i) groupBy(array, i64 % #) groupBy(array, i64 * f32) groupBy(array, i64 ** #) groupBy(array, i64 ** i) groupBy(array, i64 + #) groupBy(array, i64 - #) groupBy(array, i64 / #)?.Qux groupBy(array, i64 / 0.5) groupBy(array, i64 < #) groupBy(array, i64 <= #).foo groupBy(array, i64 >= #) groupBy(array, i64 ^ #) groupBy(array, i64) groupBy(array, i64).Bar groupBy(array, i64).Qux groupBy(array, i64).String groupBy(array, i64).add groupBy(array, i64).array groupBy(array, i64).div groupBy(array, i64).f32 groupBy(array, i64).f64 groupBy(array, i64).foo groupBy(array, i64).greet groupBy(array, i64).half groupBy(array, i64).i groupBy(array, i64).i32 groupBy(array, i64).i64 groupBy(array, i64).list groupBy(array, i64).ok groupBy(array, i64).score groupBy(array, i64)?.Bar groupBy(array, i64)?.Qux groupBy(array, i64)?.String groupBy(array, i64)?.add groupBy(array, i64)?.array groupBy(array, i64)?.div groupBy(array, i64)?.f32 groupBy(array, i64)?.f64 groupBy(array, i64)?.foo groupBy(array, i64)?.greet groupBy(array, i64)?.half groupBy(array, i64)?.i groupBy(array, i64)?.i32 groupBy(array, i64)?.i64 groupBy(array, i64)?.list groupBy(array, i64)?.ok groupBy(array, i64)?.score groupBy(array, int(f64)).i32 groupBy(array, max(#)) groupBy(array, max(#, #, #)).ok groupBy(array, max(0.5, #)) groupBy(array, max(1)) groupBy(array, max(f64)) groupBy(array, min(#)) groupBy(array, min(0.5)) groupBy(array, min(f32)) groupBy(array, min(i, #, i32)) groupBy(array, nil != #) groupBy(array, nil != f64) groupBy(array, nil != foo) groupBy(array, nil != half) groupBy(array, nil == #) groupBy(array, nil == 0.5) groupBy(array, none(array, false)) groupBy(array, none(array, ok)) groupBy(array, not ok)?.Bar groupBy(array, not true) groupBy(array, ok == ok) groupBy(array, ok ? # : #) groupBy(array, ok) groupBy(array, ok).Bar groupBy(array, ok).Qux groupBy(array, ok).String groupBy(array, ok).add groupBy(array, ok).array groupBy(array, ok).div groupBy(array, ok).f32 groupBy(array, ok).f64 groupBy(array, ok).foo groupBy(array, ok).greet groupBy(array, ok).half groupBy(array, ok).i groupBy(array, ok).i32 groupBy(array, ok).i64 groupBy(array, ok).list groupBy(array, ok).ok groupBy(array, ok).score groupBy(array, ok)?.Bar groupBy(array, ok)?.Qux groupBy(array, ok)?.String groupBy(array, ok)?.array groupBy(array, ok)?.div groupBy(array, ok)?.f32 groupBy(array, ok)?.f64 groupBy(array, ok)?.foo groupBy(array, ok)?.greet groupBy(array, ok)?.half groupBy(array, ok)?.i32 groupBy(array, ok)?.i64 groupBy(array, ok)?.list groupBy(array, ok)?.ok groupBy(array, ok)?.score groupBy(array, one(array, ok)) groupBy(array, reduce(array, #)) groupBy(array, reduce(array, foo)) groupBy(array, reduce(list, #)) groupBy(array, round(#)) groupBy(array, score(#)) groupBy(array, score(#, #)) groupBy(array, score(#, #, #, 1)) groupBy(array, score(#, 1)).list groupBy(array, score(1)) groupBy(array, score(i)) groupBy(array, string(#)) groupBy(array, string(div)) groupBy(array, string(i32)) groupBy(array, toJSON("bar")) groupBy(array, toJSON(#)) groupBy(array, toJSON(1 .. i)) groupBy(array, toJSON(foo)) groupBy(array, trimPrefix("foo")) groupBy(array, true == nil) groupBy(array, true ? # : #) groupBy(array, true ? # : 1) groupBy(array, true ? nil : "foo") groupBy(array, true).Bar groupBy(array, true).Qux groupBy(array, true).add groupBy(array, true).div groupBy(array, true).f64 groupBy(array, true).foo groupBy(array, true).greet groupBy(array, true).half groupBy(array, true).i groupBy(array, true).i32 groupBy(array, true).i64 groupBy(array, true).list groupBy(array, true).ok groupBy(array, true).score groupBy(array, true)?.Bar groupBy(array, true)?.Qux groupBy(array, true)?.String groupBy(array, true)?.add groupBy(array, true)?.array groupBy(array, true)?.div groupBy(array, true)?.f32 groupBy(array, true)?.f64 groupBy(array, true)?.half groupBy(array, true)?.i groupBy(array, true)?.i32 groupBy(array, true)?.i64 groupBy(array, true)?.list groupBy(array, true)?.ok groupBy(array, true)?.score groupBy(array, true)[i32] groupBy(array, type(# <= #)) groupBy(array, type(#)).i64 groupBy(array, type(-f64)) groupBy(array, type(f32)) groupBy(false ? 0.5 : "bar", #) groupBy(filter(array, false), #) groupBy(filter(array, false), add) groupBy(filter(array, false), f32) groupBy(filter(array, false), nil == #) groupBy(filter(array, ok), half(1)) groupBy(filter(array, true), #) groupBy(filter(array, true), f64) groupBy(filter(list, ok), #) groupBy(groupBy(array, "foo").list, #) groupBy(groupBy(array, #).i32, add) groupBy(groupBy(array, ok).Bar, #?.array not matches #) groupBy(groupBy(array, true).f64, #[#]) groupBy(i .. 1, !ok)?.f64 groupBy(i .. 1, # % #) groupBy(i .. i, i64) groupBy(i .. i32, #) groupBy(i .. i32, f64 * #) groupBy(i .. i64, f64)?.score groupBy(i .. i64, foo) groupBy(i .. len(array), #) groupBy(i32 .. 1, # - #) groupBy(i32 .. 1, #)?.f32 groupBy(i32 .. i, #) groupBy(i32 .. i32, i) groupBy(i32 .. i32, i32) groupBy(i32 .. i32, i64) groupBy(i32 .. i32, list[i]) groupBy(i32 .. i32, ok) groupBy(i32 .. i64, #) groupBy(i32 .. i64, get(array, #)) groupBy(i64 .. 1, -0.5) groupBy(i64 .. 1, i) groupBy(i64 .. i, -#) groupBy(i64 .. i, i32) groupBy(i64 .. i32, i) groupBy(i64 .. i64, i32) groupBy(list, !("foo" in #)) groupBy(list, !false) groupBy(list, !ok) groupBy(list, !true) groupBy(list, "bar" contains "foo")?.ok groupBy(list, "bar" endsWith "bar") groupBy(list, "bar" not in #) groupBy(list, "bar").Bar groupBy(list, "bar").Qux groupBy(list, "bar").String groupBy(list, "bar").add groupBy(list, "bar").array groupBy(list, "bar").div groupBy(list, "bar").f32 groupBy(list, "bar").f64 groupBy(list, "bar").foo groupBy(list, "bar").greet groupBy(list, "bar").i groupBy(list, "bar").i32 groupBy(list, "bar").i64 groupBy(list, "bar").list groupBy(list, "bar").ok groupBy(list, "bar").score groupBy(list, "bar")?.Bar groupBy(list, "bar")?.Qux groupBy(list, "bar")?.String groupBy(list, "bar")?.add groupBy(list, "bar")?.array groupBy(list, "bar")?.div groupBy(list, "bar")?.f32 groupBy(list, "bar")?.f64 groupBy(list, "bar")?.foo groupBy(list, "bar")?.greet groupBy(list, "bar")?.half groupBy(list, "bar")?.i groupBy(list, "bar")?.i32 groupBy(list, "bar")?.i64 groupBy(list, "bar")?.list groupBy(list, "bar")?.ok groupBy(list, "bar")?.score groupBy(list, "foo" not in #)?.foo groupBy(list, "foo").Bar groupBy(list, "foo").Qux groupBy(list, "foo").String groupBy(list, "foo").add groupBy(list, "foo").array groupBy(list, "foo").div groupBy(list, "foo").f32 groupBy(list, "foo").f64 groupBy(list, "foo").foo groupBy(list, "foo").greet groupBy(list, "foo").half groupBy(list, "foo").i groupBy(list, "foo").i32 groupBy(list, "foo").i64 groupBy(list, "foo").list groupBy(list, "foo").ok groupBy(list, "foo").score groupBy(list, "foo")?.Bar groupBy(list, "foo")?.Qux groupBy(list, "foo")?.String groupBy(list, "foo")?.add groupBy(list, "foo")?.array groupBy(list, "foo")?.div groupBy(list, "foo")?.f32 groupBy(list, "foo")?.f64 groupBy(list, "foo")?.foo groupBy(list, "foo")?.greet groupBy(list, "foo")?.half groupBy(list, "foo")?.i groupBy(list, "foo")?.i32 groupBy(list, "foo")?.i64 groupBy(list, "foo")?.list groupBy(list, "foo")?.ok groupBy(list, "foo")?.score groupBy(list, # != #) groupBy(list, # != foo) groupBy(list, # != foo)?.i groupBy(list, # != nil) groupBy(list, # == #) groupBy(list, # == #).div groupBy(list, # in list) groupBy(list, # not in list) groupBy(list, #) groupBy(list, #).Bar groupBy(list, #).Qux groupBy(list, #).String groupBy(list, #).add groupBy(list, #).array groupBy(list, #).div groupBy(list, #).f32 groupBy(list, #).f64 groupBy(list, #).foo groupBy(list, #).greet groupBy(list, #).half groupBy(list, #).i groupBy(list, #).i32 groupBy(list, #).i64 groupBy(list, #).list groupBy(list, #).ok groupBy(list, #).score groupBy(list, #)?.Bar groupBy(list, #)?.Qux groupBy(list, #)?.String groupBy(list, #)?.add groupBy(list, #)?.array groupBy(list, #)?.div groupBy(list, #)?.f32 groupBy(list, #)?.f64 groupBy(list, #)?.foo groupBy(list, #)?.greet groupBy(list, #)?.half groupBy(list, #)?.i groupBy(list, #)?.i32 groupBy(list, #)?.i64 groupBy(list, #)?.list groupBy(list, #)?.ok groupBy(list, #)?.score groupBy(list, #)[-i64] groupBy(list, #)[1 == i32] groupBy(list, #)[f32] groupBy(list, #)[foo] groupBy(list, #)[i == i64] groupBy(list, #)[i32] groupBy(list, #)[i64] groupBy(list, #)[ok] groupBy(list, #?.Bar) groupBy(list, #?.String()) groupBy(list, #?.String())?.score groupBy(list, -0.5) groupBy(list, -1) groupBy(list, -f32) groupBy(list, -i) groupBy(list, .Bar) groupBy(list, .Bar).f32 groupBy(list, .String()) groupBy(list, .String())?.score groupBy(list, 0.5 != f32) groupBy(list, 0.5 != f64) groupBy(list, 0.5 * f32) groupBy(list, 0.5 ** i64) groupBy(list, 0.5 / i) groupBy(list, 0.5).Bar groupBy(list, 0.5).Qux groupBy(list, 0.5).String groupBy(list, 0.5).add groupBy(list, 0.5).array groupBy(list, 0.5).div groupBy(list, 0.5).f32 groupBy(list, 0.5).f64 groupBy(list, 0.5).greet groupBy(list, 0.5).half groupBy(list, 0.5).i groupBy(list, 0.5).i32 groupBy(list, 0.5).i64 groupBy(list, 0.5).list groupBy(list, 0.5).ok groupBy(list, 0.5).score groupBy(list, 0.5)?.Bar groupBy(list, 0.5)?.Qux groupBy(list, 0.5)?.String groupBy(list, 0.5)?.add groupBy(list, 0.5)?.array groupBy(list, 0.5)?.div groupBy(list, 0.5)?.f32 groupBy(list, 0.5)?.f64 groupBy(list, 0.5)?.foo groupBy(list, 0.5)?.greet groupBy(list, 0.5)?.half groupBy(list, 0.5)?.i groupBy(list, 0.5)?.i32 groupBy(list, 0.5)?.i64 groupBy(list, 0.5)?.list groupBy(list, 0.5)?.ok groupBy(list, 0.5)?.score groupBy(list, 1 * f64).f32 groupBy(list, 1 + i) groupBy(list, 1 - 0.5) groupBy(list, 1 ^ 0.5) groupBy(list, 1 ^ 1) groupBy(list, 1 ^ i) groupBy(list, 1).Bar groupBy(list, 1).Qux groupBy(list, 1).String groupBy(list, 1).add groupBy(list, 1).array groupBy(list, 1).div groupBy(list, 1).f32 groupBy(list, 1).f64 groupBy(list, 1).foo groupBy(list, 1).greet groupBy(list, 1).half groupBy(list, 1).i groupBy(list, 1).i32 groupBy(list, 1).i64 groupBy(list, 1).list groupBy(list, 1).ok groupBy(list, 1).score groupBy(list, 1)?.Bar groupBy(list, 1)?.Qux groupBy(list, 1)?.String groupBy(list, 1)?.add groupBy(list, 1)?.array groupBy(list, 1)?.div groupBy(list, 1)?.f32 groupBy(list, 1)?.f64 groupBy(list, 1)?.foo groupBy(list, 1)?.greet groupBy(list, 1)?.half groupBy(list, 1)?.i groupBy(list, 1)?.i32 groupBy(list, 1)?.i64 groupBy(list, 1)?.list groupBy(list, 1)?.ok groupBy(list, 1)?.score groupBy(list, 1)[i] groupBy(list, 1)[reduce(list, "foo")] groupBy(list, abs(1)) groupBy(list, abs(i)) groupBy(list, abs(i64)) groupBy(list, all(list, ok)) groupBy(list, ceil(0.5)) groupBy(list, ceil(f64)) groupBy(list, f32 ** 0.5) groupBy(list, f32 ** 1) groupBy(list, f32 < f32) groupBy(list, f32 == i64) groupBy(list, f32 >= 1) groupBy(list, f32) groupBy(list, f32).Bar groupBy(list, f32).Qux groupBy(list, f32).String groupBy(list, f32).add groupBy(list, f32).array groupBy(list, f32).div groupBy(list, f32).f32 groupBy(list, f32).f64 groupBy(list, f32).foo groupBy(list, f32).half groupBy(list, f32).i groupBy(list, f32).i32 groupBy(list, f32).i64 groupBy(list, f32).list groupBy(list, f32).ok groupBy(list, f32)?.Bar groupBy(list, f32)?.Qux groupBy(list, f32)?.String groupBy(list, f32)?.add groupBy(list, f32)?.array groupBy(list, f32)?.div groupBy(list, f32)?.f32 groupBy(list, f32)?.f64 groupBy(list, f32)?.foo groupBy(list, f32)?.greet groupBy(list, f32)?.half groupBy(list, f32)?.i groupBy(list, f32)?.i32 groupBy(list, f32)?.i64 groupBy(list, f32)?.list groupBy(list, f32)?.ok groupBy(list, f32)?.score groupBy(list, f32)[add == nil] groupBy(list, f32)[toJSON(true)] groupBy(list, f64 * 0.5) groupBy(list, f64 * 1) groupBy(list, f64 - 1) groupBy(list, f64 < f64) groupBy(list, f64) groupBy(list, f64).Bar groupBy(list, f64).Qux groupBy(list, f64).String groupBy(list, f64).add groupBy(list, f64).array groupBy(list, f64).div groupBy(list, f64).f32 groupBy(list, f64).f64 groupBy(list, f64).foo groupBy(list, f64).greet groupBy(list, f64).half groupBy(list, f64).i groupBy(list, f64).i32 groupBy(list, f64).i64 groupBy(list, f64).list groupBy(list, f64).ok groupBy(list, f64).score groupBy(list, f64)?.Bar groupBy(list, f64)?.Qux groupBy(list, f64)?.String groupBy(list, f64)?.add groupBy(list, f64)?.array groupBy(list, f64)?.div groupBy(list, f64)?.f32 groupBy(list, f64)?.f64 groupBy(list, f64)?.foo groupBy(list, f64)?.greet groupBy(list, f64)?.half groupBy(list, f64)?.i groupBy(list, f64)?.i32 groupBy(list, f64)?.i64 groupBy(list, f64)?.list groupBy(list, f64)?.ok groupBy(list, f64)?.score groupBy(list, false == ok) groupBy(list, false ? score : #) groupBy(list, false).Bar groupBy(list, false).add groupBy(list, false).array groupBy(list, false).div groupBy(list, false).f32 groupBy(list, false).foo groupBy(list, false).greet groupBy(list, false).half groupBy(list, false).i groupBy(list, false).i32 groupBy(list, false).i64 groupBy(list, false).list groupBy(list, false).ok groupBy(list, false)?.Bar groupBy(list, false)?.Qux groupBy(list, false)?.String groupBy(list, false)?.add groupBy(list, false)?.div groupBy(list, false)?.f32 groupBy(list, false)?.f64 groupBy(list, false)?.greet groupBy(list, false)?.half groupBy(list, false)?.i groupBy(list, false)?.i32 groupBy(list, false)?.i64 groupBy(list, false)?.list groupBy(list, false)?.ok groupBy(list, false)?.score groupBy(list, findLastIndex(array, ok)) groupBy(list, findLastIndex(list, false)) groupBy(list, first(array)) groupBy(list, float(-1)) groupBy(list, float(0.5)) groupBy(list, floor(i)) groupBy(list, floor(i64)) groupBy(list, foo != #) groupBy(list, foo) groupBy(list, foo).Bar groupBy(list, foo).Qux groupBy(list, foo).String groupBy(list, foo).add groupBy(list, foo).array groupBy(list, foo).div groupBy(list, foo).f32 groupBy(list, foo).f64 groupBy(list, foo).foo groupBy(list, foo).greet groupBy(list, foo).half groupBy(list, foo).i groupBy(list, foo).i32 groupBy(list, foo).i64 groupBy(list, foo).list groupBy(list, foo).ok groupBy(list, foo).score groupBy(list, foo)?.Bar groupBy(list, foo)?.Qux groupBy(list, foo)?.String groupBy(list, foo)?.add groupBy(list, foo)?.array groupBy(list, foo)?.div groupBy(list, foo)?.f32 groupBy(list, foo)?.f64 groupBy(list, foo)?.foo groupBy(list, foo)?.half groupBy(list, foo)?.i groupBy(list, foo)?.i32 groupBy(list, foo)?.i64 groupBy(list, foo)?.list groupBy(list, foo)?.ok groupBy(list, foo)?.score groupBy(list, foo)[i32] groupBy(list, foo.Bar) groupBy(list, foo.String()) groupBy(list, foo?.String()) groupBy(list, greet != greet) groupBy(list, greet("bar")) groupBy(list, i * i) groupBy(list, i / f64) groupBy(list, i <= i) groupBy(list, i ^ i) groupBy(list, i) groupBy(list, i).Bar groupBy(list, i).Qux groupBy(list, i).String groupBy(list, i).add groupBy(list, i).array groupBy(list, i).div groupBy(list, i).f32 groupBy(list, i).f64 groupBy(list, i).foo groupBy(list, i).half groupBy(list, i).i groupBy(list, i).i32 groupBy(list, i).i64 groupBy(list, i).list groupBy(list, i).ok groupBy(list, i).score groupBy(list, i)?.Bar groupBy(list, i)?.Qux groupBy(list, i)?.String groupBy(list, i)?.add groupBy(list, i)?.array groupBy(list, i)?.div groupBy(list, i)?.f32 groupBy(list, i)?.f64 groupBy(list, i)?.foo groupBy(list, i)?.greet groupBy(list, i)?.half groupBy(list, i)?.i groupBy(list, i)?.i32 groupBy(list, i)?.i64 groupBy(list, i)?.list groupBy(list, i)?.ok groupBy(list, i)?.score groupBy(list, i32 != f32)?.foo groupBy(list, i32 * 0.5) groupBy(list, i32 ** 0.5) groupBy(list, i32 ** f32) groupBy(list, i32 > i) groupBy(list, i32 ^ i) groupBy(list, i32) groupBy(list, i32).Bar groupBy(list, i32).Qux groupBy(list, i32).add groupBy(list, i32).array groupBy(list, i32).div groupBy(list, i32).f32 groupBy(list, i32).f64 groupBy(list, i32).foo groupBy(list, i32).greet groupBy(list, i32).half groupBy(list, i32).i groupBy(list, i32).i32 groupBy(list, i32).i64 groupBy(list, i32).list groupBy(list, i32).ok groupBy(list, i32).score groupBy(list, i32)?.Bar groupBy(list, i32)?.Qux groupBy(list, i32)?.String groupBy(list, i32)?.add groupBy(list, i32)?.array groupBy(list, i32)?.div groupBy(list, i32)?.f32 groupBy(list, i32)?.f64 groupBy(list, i32)?.foo groupBy(list, i32)?.greet groupBy(list, i32)?.half groupBy(list, i32)?.i groupBy(list, i32)?.i32 groupBy(list, i32)?.i64 groupBy(list, i32)?.list groupBy(list, i32)?.ok groupBy(list, i32)?.score groupBy(list, i64 != i32) groupBy(list, i64 != nil) groupBy(list, i64 - 0.5) groupBy(list, i64 < 1) groupBy(list, i64 <= 1) groupBy(list, i64 == 1) groupBy(list, i64 == nil) groupBy(list, i64) groupBy(list, i64).Bar groupBy(list, i64).Qux groupBy(list, i64).String groupBy(list, i64).add groupBy(list, i64).array groupBy(list, i64).div groupBy(list, i64).f32 groupBy(list, i64).f64 groupBy(list, i64).foo groupBy(list, i64).greet groupBy(list, i64).half groupBy(list, i64).i groupBy(list, i64).i32 groupBy(list, i64).list groupBy(list, i64).ok groupBy(list, i64).score groupBy(list, i64)?.Bar groupBy(list, i64)?.Qux groupBy(list, i64)?.String groupBy(list, i64)?.add groupBy(list, i64)?.array groupBy(list, i64)?.div groupBy(list, i64)?.f32 groupBy(list, i64)?.f64 groupBy(list, i64)?.foo groupBy(list, i64)?.greet groupBy(list, i64)?.half groupBy(list, i64)?.i groupBy(list, i64)?.i32 groupBy(list, i64)?.i64 groupBy(list, i64)?.list groupBy(list, i64)?.ok groupBy(list, i64)?.score groupBy(list, i64)[max(i)] groupBy(list, i64)[ok] groupBy(list, int(1)) groupBy(list, list == array) groupBy(list, lower("foo")) groupBy(list, max(f64)) groupBy(list, max(i)) groupBy(list, nil != #) groupBy(list, nil != div) groupBy(list, nil != true) groupBy(list, nil == #) groupBy(list, nil == #).i groupBy(list, nil in list) groupBy(list, not false) groupBy(list, not ok) groupBy(list, ok != false) groupBy(list, ok ? # : true) groupBy(list, ok) groupBy(list, ok).Bar groupBy(list, ok).Qux groupBy(list, ok).String groupBy(list, ok).add groupBy(list, ok).array groupBy(list, ok).div groupBy(list, ok).f32 groupBy(list, ok).f64 groupBy(list, ok).foo groupBy(list, ok).greet groupBy(list, ok).half groupBy(list, ok).i groupBy(list, ok).i32 groupBy(list, ok).i64 groupBy(list, ok).list groupBy(list, ok).ok groupBy(list, ok).score groupBy(list, ok)?.Bar groupBy(list, ok)?.Qux groupBy(list, ok)?.String groupBy(list, ok)?.add groupBy(list, ok)?.array groupBy(list, ok)?.div groupBy(list, ok)?.f32 groupBy(list, ok)?.f64 groupBy(list, ok)?.foo groupBy(list, ok)?.greet groupBy(list, ok)?.half groupBy(list, ok)?.i groupBy(list, ok)?.i32 groupBy(list, ok)?.i64 groupBy(list, ok)?.list groupBy(list, ok)?.ok groupBy(list, ok)?.score groupBy(list, reduce(array, #)) groupBy(list, reduce(list, #)).i32 groupBy(list, reduce(list, f64)) groupBy(list, reduce(list, i32)) groupBy(list, reduce(map(list, i64), #)) groupBy(list, round(0.5)) groupBy(list, round(1)) groupBy(list, round(f64)) groupBy(list, score(1)) groupBy(list, score(i)) groupBy(list, string(#)) groupBy(list, string(add)) groupBy(list, string(half)) groupBy(list, string(i32)) groupBy(list, string(true)) groupBy(list, toBase64("foo")) groupBy(list, toJSON(#)) groupBy(list, toJSON(1)) groupBy(list, toJSON(array)) groupBy(list, toJSON(foo)) groupBy(list, true && false) groupBy(list, true ? # : 1) groupBy(list, true ? 1 : #) groupBy(list, true).Qux groupBy(list, true).String groupBy(list, true).add groupBy(list, true).array groupBy(list, true).div groupBy(list, true).f32 groupBy(list, true).f64 groupBy(list, true).foo groupBy(list, true).greet groupBy(list, true).half groupBy(list, true).i groupBy(list, true).i32 groupBy(list, true).i64 groupBy(list, true).list groupBy(list, true).ok groupBy(list, true).score groupBy(list, true)?.Bar groupBy(list, true)?.Qux groupBy(list, true)?.String groupBy(list, true)?.add groupBy(list, true)?.array groupBy(list, true)?.div groupBy(list, true)?.f32 groupBy(list, true)?.f64 groupBy(list, true)?.foo groupBy(list, true)?.greet groupBy(list, true)?.half groupBy(list, true)?.i groupBy(list, true)?.i32 groupBy(list, true)?.i64 groupBy(list, true)?.list groupBy(list, true)?.ok groupBy(list, true)?.score groupBy(list, type("foo")) groupBy(list, type(#)) groupBy(list, type(false)) groupBy(list[i32:1], i64) groupBy(list[i32:i32], foo) groupBy(list[i64:1], i32) groupBy(list[i:1], f64) groupBy(map(array, #), # <= #) groupBy(map(array, #), # == #) groupBy(map(array, #), # >= #) groupBy(map(array, #), #) groupBy(map(array, #), 0.5 < 0.5) groupBy(map(array, #), foo) groupBy(map(array, #), i) groupBy(map(array, #), i64) groupBy(map(array, #), min(1)) groupBy(map(array, #), ok) groupBy(map(array, 0.5), # != 0.5) groupBy(map(array, 0.5), # / #) groupBy(map(array, 0.5), #) groupBy(map(array, 0.5), f64) groupBy(map(array, 1), 0.5 / #) groupBy(map(array, 1), f64) groupBy(map(array, 1), max(#)) groupBy(map(array, 1), ok) groupBy(map(array, div), div != #) groupBy(map(array, f32), # - 0.5) groupBy(map(array, f32), min(#)) groupBy(map(array, f64), #) groupBy(map(array, false), f64) groupBy(map(array, false), i) groupBy(map(array, foo), #).add groupBy(map(array, foo), i) groupBy(map(array, foo), ok) groupBy(map(array, i), #) groupBy(map(array, i32), # % i) groupBy(map(array, i32), #) groupBy(map(array, ok), i64) groupBy(map(list, "bar"), #) groupBy(map(list, "foo"), #) groupBy(map(list, #), "bar" == "bar") groupBy(map(list, #), #) groupBy(map(list, #), #)?.array groupBy(map(list, #), f32) groupBy(map(list, #), f64) groupBy(map(list, #), i32) groupBy(map(list, #), i64) groupBy(map(list, #), ok) groupBy(map(list, 0.5), # * i64) groupBy(map(list, 0.5), # ** #) groupBy(map(list, 0.5), #) groupBy(map(list, 0.5), i32) groupBy(map(list, 1), #) groupBy(map(list, 1), get(list, #)).i64 groupBy(map(list, 1), i64) groupBy(map(list, f32), # ** #).array groupBy(map(list, f64), #) groupBy(map(list, f64), #).half groupBy(map(list, f64), f32) groupBy(map(list, f64), i) groupBy(map(list, i), #) groupBy(map(list, i32), # == #) groupBy(map(list, i64), #)?.i32 groupBy(map(list, i64), i) groupBy(map(list, list), foo) groupBy(map(list, ok), #) groupBy(ok ? "foo" : greet, # <= #) groupBy(reduce(array, # .. i64), add) groupBy(reduce(array, array), foo) groupBy(reduce(array, array), i) groupBy(reduce(list, array), # / #) groupBy(reduce(list, array), true ? true : nil) groupBy(sort(array), #) groupBy(sort(array), foo) groupBy(true ? "foo" : 1, # > 0.5) groupBy(true ? "foo" : 1, foo) groupBy(true ? "foo" : false, # / #) groupBy(true ? "foo" : score, #) half half != half half != half != nil half != half and "bar" in foo half != nil == false half != nil ? "bar" : div half != nil ? "bar" : false half != nil ? true : div half != reduce(list, half) half == half half == nil && ok half == nil ? array : 0.5 half == nil ? foo : false half(-(0.5 + 1)) half(-(f64 + 1)) half(-(i64 - 0.5)) half(-0.5) half(-1) half(-f64) half(0.5 * 0.5) half(0.5 * 1) half(0.5 * f64) half(0.5 * i) half(0.5 * i32) half(0.5 * i64) half(0.5 ** 0.5) half(0.5 ** 1) half(0.5 ** f32) half(0.5 ** f64) half(0.5 ** i) half(0.5 ** i32) half(0.5 ** i64) half(0.5 + 0.5) half(0.5 + 1 + i64) half(0.5 + 1) half(0.5 + f32) half(0.5 + f64) half(0.5 + i) half(0.5 + i32) half(0.5 + i64) half(0.5 - 0.5) half(0.5 - 1) half(0.5 - f32) half(0.5 - f64) half(0.5 - i) half(0.5 - i32) half(0.5 - i64) half(0.5 / 0.5) half(0.5 / 1) half(0.5 / f32) half(0.5 / f64) half(0.5 / i) half(0.5 / i64) half(0.5 ^ 0.5) half(0.5 ^ 1) half(0.5 ^ f32) half(0.5 ^ f64) half(0.5 ^ i) half(0.5 ^ i32) half(0.5 ^ i64) half(0.5) != -i64 half(0.5) != 0.5 ^ i half(0.5) != i32 half(0.5) != i64 half(0.5) * f32 half(0.5) * i half(0.5) * i32 half(0.5) * i64 half(0.5) ** f32 half(0.5) ** i half(0.5) ** i32 half(0.5) ** i64 half(0.5) ** max(1) half(0.5) + 1 / 1 half(0.5) + f32 half(0.5) + f64 half(0.5) + i32 half(0.5) + i64 half(0.5) - i64 half(0.5) / -0.5 half(0.5) / f64 half(0.5) / i half(0.5) / i64 half(0.5) < f64 half(0.5) <= f32 ? f64 : 1 half(0.5) <= f64 half(0.5) <= i32 half(0.5) <= i64 + i32 half(0.5) <= int(0.5) half(0.5) == f32 half(0.5) == i32 / i half(0.5) == i64 half(0.5) > f32 half(0.5) > f64 half(0.5) > i half(0.5) > i64 half(0.5) >= i32 half(0.5) ^ (1 * i32) half(0.5) ^ f32 half(0.5) ^ f64 half(0.5) ^ i half(0.5) ^ i32 half(0.5) ^ i64 half(1 * 0.5) half(1 * 1) half(1 * f32) half(1 * f64) half(1 * i) half(1 * i32) half(1 * i64) half(1 ** 0.5) half(1 ** 1) half(1 ** f32) half(1 ** f64) half(1 ** i) half(1 ** i32) half(1 ** i64) half(1 + 0.5) half(1 + 1) half(1 + f32) half(1 + f64) half(1 + i) half(1 + i32) half(1 + i64) half(1 - 0.5) half(1 - 1) half(1 - f32) half(1 - f64) half(1 - i) half(1 - i32) half(1 - i64) half(1 / 0.5) half(1 / 1) half(1 / f32) half(1 / f64) half(1 / i) half(1 / i32) half(1 / i64) half(1 ^ 0.5) half(1 ^ 1) half(1 ^ f32) half(1 ^ f64) half(1 ^ i) half(1 ^ i32) half(1 ^ i64) half(1) != f32 half(1) != f64 half(1) != f64 ** f32 half(1) != f64 ^ 0.5 half(1) != i32 half(1) != i64 half(1) * i32 * i64 half(1) ** (i64 * f32) half(1) ** f32 half(1) ** i half(1) ** i32 half(1) ** i64 half(1) + f32 half(1) + f32 / 0.5 half(1) + i half(1) + i32 half(1) + i64 + i32 half(1) - f32 half(1) - i < i64 half(1) - i32 half(1) - i64 half(1) / -1 half(1) / 0.5 / i half(1) / i half(1) / i32 half(1) < f64 half(1) < i half(1) < i64 half(1) <= f32 half(1) <= i32 half(1) <= i64 half(1) == -1 half(1) == 1 ^ i64 half(1) == f32 half(1) == i32 half(1) > i half(1) > i32 half(1) > i64 half(1) >= f32 half(1) >= i half(1) >= i32 half(1) >= i64 half(1) >= max(1) half(1) >= mean(array) half(1) ^ f32 half(1) ^ findIndex(list, true) half(1) ^ i64 half(1) in array half(1) not in array half(abs(0.5)) half(abs(f64)) half(ceil(0.5)) half(ceil(1)) half(ceil(f32)) half(ceil(f64)) half(ceil(i)) half(ceil(i32)) half(ceil(i64)) half(f32 * 0.5) half(f32 * 1) half(f32 * f64) half(f32 * i) half(f32 * i32) half(f32 ** 0.5) half(f32 ** f32) half(f32 ** f64) half(f32 ** i64) half(f32 + 0.5) half(f32 + 1) half(f32 + f64) half(f32 + i32) half(f32 + i64) half(f32 - 0.5) half(f32 - 1) half(f32 - f64) half(f32 - i) half(f32 - i32) half(f32 - i64) half(f32 / 0.5) half(f32 / 1) half(f32 / f32) half(f32 / f64) half(f32 / i) half(f32 / i32) half(f32 / i64) half(f32 ^ 0.5) half(f32 ^ 1) half(f32 ^ f32) half(f32 ^ f64) half(f32 ^ i) half(f32 ^ i32) half(f32 ^ i64) half(f64 * 0.5) half(f64 * f32) half(f64 * f64) half(f64 * i) half(f64 * i32) half(f64 * i64) half(f64 ** 0.5) half(f64 ** 1) half(f64 ** f32) half(f64 ** i) half(f64 ** i32) half(f64 + 0.5) half(f64 + 1) half(f64 + f64) half(f64 + i) half(f64 + i64) half(f64 - 0.5) half(f64 - 1) half(f64 - f32) half(f64 - f64) half(f64 - i) half(f64 - i64) half(f64 / 0.5) half(f64 / 1) half(f64 / f32) half(f64 / f64) half(f64 / i) half(f64 / i32) half(f64 ^ 0.5) half(f64 ^ 1) half(f64 ^ f32) half(f64 ^ f64) half(f64 ^ i32) half(f64) half(f64) != f64 != false half(f64) != i32 half(f64) != i64 half(f64) ** f64 half(f64) ** i half(f64) ** i32 half(f64) + i32 half(f64) + i64 half(f64) - f64 half(f64) - i32 half(f64) / f64 half(f64) / i32 half(f64) < i half(f64) < i32 half(f64) <= f32 half(f64) <= i32 half(f64) == f32 half(f64) == f64 half(f64) == i half(f64) == i32 half(f64) == i64 half(f64) > f32 half(f64) > f64 half(f64) > i half(f64) > i32 half(f64) > i64 half(f64) >= i half(f64) >= i64 half(f64) ^ i half(f64) not in array half(false ? f64 : 0.5) half(false ? i32 : 0.5) half(false ? ok : 0.5) half(false ? score : 0.5) half(false ? true : f64) half(float(0.5)) half(float(1)) half(float(f32)) half(float(f64)) half(float(i)) half(float(i32)) half(float(i64)) half(floor(0.5)) half(floor(1)) half(floor(f32)) half(floor(f64)) half(floor(i)) half(floor(i32)) half(floor(i64)) half(half(0.5)) half(half(1)) half(half(ceil(i))) half(half(f64 - 0.5)) half(half(f64)) half(i * 0.5) half(i * 1) half(i * f64) half(i ** 0.5) half(i ** 1) half(i ** f32) half(i ** f64) half(i ** i) half(i ** i32) half(i ** i64) half(i + 0.5) half(i + 1) half(i + f32) half(i + f64) half(i - 1) half(i - f32) half(i - f64) half(i / 0.5) half(i / 1) half(i / f64) half(i / i) half(i / i32) half(i ^ 0.5) half(i ^ 1) half(i ^ i) half(i ^ i32) half(i ^ i64) half(i32 * 0.5) half(i32 * 1) half(i32 * f32) half(i32 * f64) half(i32 ** 0.5) half(i32 ** 1) half(i32 ** f64) half(i32 ** i) half(i32 ** i32) half(i32 ** i64) half(i32 + 0.5) half(i32 + 1) half(i32 + f32) half(i32 + f64) half(i32 - 0.5) half(i32 - 1) half(i32 - f32) half(i32 / 0.5) half(i32 / 1) half(i32 / f32) half(i32 / f64) half(i32 / i) half(i32 / i32 / f32 / f64) half(i32 / i32) half(i32 / i64) half(i32 ^ 0.5) half(i32 ^ 1) half(i32 ^ f32) half(i32 ^ f64) half(i32 ^ i) half(i32 ^ i32) half(i32 ^ i64 ^ i) half(i32 ^ i64) half(i64 != i ? true : 0.5) half(i64 * 0.5) half(i64 * 1) half(i64 * f64) half(i64 ** 0.5) half(i64 ** 1) half(i64 ** f64) half(i64 ** i) half(i64 ** i32) half(i64 ** i64) half(i64 + 0.5) half(i64 + f32) half(i64 + f64) half(i64 - 0.5) half(i64 - 1) half(i64 - f32) half(i64 - f64) half(i64 / 0.5) half(i64 / 1) half(i64 / f32) half(i64 / f64) half(i64 / i) half(i64 / i32) half(i64 ^ 0.5) half(i64 ^ 1) half(i64 ^ f32) half(i64 ^ f64) half(i64 ^ i) half(i64 ^ i32) half(max(0.5)) half(max(0.5)) ** i half(max(f64)) half(mean(array)) half(median(array)) half(min(0.5)) half(min(0.5, f32)) half(min(0.5, i32)) half(min(f64)) half(min(i, 0.5)) half(reduce(array, 0.5)) half(reduce(array, f64)) half(reduce(list, 0.5)) half(reduce(list, f64)) half(round(0.5)) half(round(1)) half(round(f32)) half(round(f64)) half(round(i)) half(round(i32)) half(round(i64)) half(score(1) ^ i64) half(true ? 0.5 : i64) half(true ? f64 : nil) i i != -0.5 i != -1 i != -f32 i != -f64 i != -i i != -i32 i != 0.5 + 0.5 i != 0.5 - 1 i != 0.5 / 1 i != 0.5 ? 1 : div i != 0.5 ? false : i32 i != 0.5 ^ 0.5 i != 0.5 ^ 1 i != 0.5 ^ f32 i != 1 != nil i != 1 / 1 i != 1 ? f64 : score i != ceil(1) i != ceil(f32) i != ceil(i64) i != f32 i != f32 ** i64 i != f32 + i64 i != f32 == ok i != f64 i != f64 + i32 i != f64 == true i != f64 ^ f32 i != f64 ^ i64 i != float(0.5) i != float(i) i != half(0.5) i != half(f64) i != i i != i * 1 i != i * i32 i != i - i32 i != i ? i : false i != i32 i != i32 != nil ? greet : score i != i32 * 0.5 i != i32 * f32 i != i32 and ok i != i64 i != i64 ** i i != i64 ? add : i64 i != i64 ? f32 : nil i != i64 ^ 1 i != int(1) i != min(i64) i != nil != ok i != nil ? ok : f64 i != reduce(array, #) i != reduce(array, 0.5) i != reduce(list, 1) i != round(f64) i != score(1) i != score(i) i != {"foo": score}?.f32 i % (1 + i32) i % (i32 + i32) i % (i64 + 1) i % -1 i % -i i % -i32 i % 1 % i32 i % 1 % i64 i % 1 * i32 i % 1 + i64 i % 1 .. i i % 1 / 0.5 i % 1 / f32 i % 1 <= i64 i % 1 >= i i % abs(1) i % abs(i) i % array[1] i % array[i64] i % i i % i / i i % i32 i % i32 != i32 i % i32 * 1 i % i32 * f64 i % i32 / i32 i % i32 <= f64 i % i64 i % i64 != i ? f64 : list i % i64 <= i i % min(1) i % min(i64) i % reduce(array, #) i % score(i) i * (1 + 1) i * (f32 + 0.5) i * (f32 + 1) i * (f64 + i) i * (f64 - i32) i * -i32 i * -i64 i * 0.5 * f64 i * 0.5 + i i * 0.5 / i i * 0.5 < i32 i * 0.5 > i32 * f32 i * 0.5 ^ 1 i * 1 % i64 i * 1 ** 1 i * 1 < f64 i * 1 < i32 i * 1 == i32 i * bitnand(i64, i64) i * bitnot(i64) i * ceil(1) i * f32 i * f32 <= f64 i * f32 ^ 0.5 i * f32 ^ 1 i * f32 ^ f32 i * f64 i * f64 != i i * f64 * f32 > i i * f64 * i i * f64 ** i32 i * float(f32) i * floor(f32) i * floor(i) i * floor(i32) i * floor(i64) i * half(0.5) i * half(1) i * half(f64) i * i i * i % i i * i * 0.5 i * i * f32 i * i ** 0.5 i * i - f32 i * i .. i i * i == f32 i * i32 i * i32 * i i * i32 .. i32 i * i32 / min(1) i * i32 == f32 i * i32 in array i * i64 i * i64 < f64 i * int(1) i * max(1) i * max(f64, f32) i * max(i) i * min(f64, i) i * reduce(array, #) i * score(1) i * score(i) i * sum(array) i ** (0.5 * f64) i ** (0.5 + 0.5) i ** (0.5 - 1) i ** (0.5 - f64) i ** (0.5 / i32) i ** (f32 + 0.5) i ** (f32 + f32) i ** (i * 0.5) i ** (i * 1) i ** (i + f64) i ** (i - i32 + i32) i ** (i32 - i64) i ** (i32 / 1) i ** (i64 - 0.5) i ** -0.5 i ** -1 i ** -f32 i ** -i32 i ** -i64 i ** 0.5 ** f32 i ** 0.5 ** reduce(array, #) i ** 0.5 < bitnot(i64) i ** 0.5 < f32 i ** 0.5 < f64 i ** 0.5 <= i64 i ** 0.5 ^ i i ** 0.5 ^ i64 i ** 1 ** 1 i ** 1 / i i ** 1 < -f32 i ** 1 >= f64 i ** 1 ^ i i ** 1 ^ i32 i ** abs(0.5) i ** array[i64] i ** bitnand(i32, 1) i ** bitshl(i64, i32) i ** ceil(1) i ** f32 i ** f32 * i32 i ** f32 ** 1 i ** f32 ^ f64 i ** f32 ^ i64 i ** f64 i ** f64 != i32 i ** f64 ** f64 i ** f64 > i64 ? 1 : ok i ** f64 >= i i ** first(array) i ** floor(f64) i ** half(1) i ** half(f64) i ** half(i + f32) i ** i i ** i != i == ok i ** i ^ 0.5 i ** i32 i ** i32 == f32 i ** i32 > i64 i ** i64 i ** i64 ** i i ** i64 < i i ** i64 == i32 i ** i64 >= i i ** i64 ^ i64 i ** i64 not in array i ** len("foo") i ** len(array) i ** min(1) i ** min(i32) i ** reduce(array, #) i ** score(1) i ** score(i) i + -0.5 i + -1 i + -f32 i + -f64 i + 0.5 ** 0.5 i + 0.5 + i i + 0.5 / 1 i + 1 + f32 i + 1 / f32 i + 1 > f64 i + 1 ^ 1 i + 1 ^ f32 i + abs(0.5) i + array[i64] i + array[i] i + count(list, true) i + f32 i + f32 ** i i + f32 / f64 i + f32 / i32 i + f32 < i64 i + f64 i + f64 - i32 i + f64 < i64 i + f64 == i32 i + f64 > f64 i + float(0.5) i + float(i32) i + get(array, i) i + half(1) i + half(f64) i + i i + i * i64 i + i ^ 1 i + i32 i + i32 .. -i64 i + i32 .. i i + i32 <= f32 i + i32 == i64 i + i32 > min(i) i + i32 >= i32 == nil i + i32 in array i + i64 i + i64 - f64 i + i64 / 0.5 i + i64 / f64 i + i64 > f32 i + int(f32) i + len("bar") i + reduce(array, #) i + reduce(array, f32) i + reduce(list, i32) i + score(i) i - -0.5 i - -1 i - -f32 i - -f64 i - -i64 i - 0.5 + i64 i - 0.5 - 1 i - 0.5 < f64 i - 0.5 > i i - 0.5 not in array i - 1 + i i - 1 - i64 i - 1 .. i64 i - 1 < i32 i - 1 <= f64 i - 1 <= i i - 1 > 0.5 - 0.5 i - 1 ^ 0.5 i - bitxor(i, i) i - ceil(f64) i - f32 i - f32 * f32 i - f32 - i32 i - f32 / i i - f32 ^ 0.5 i - f64 i - f64 + i32 i - f64 + i32 - f64 i - f64 / i32 i - f64 ^ i64 i - find(array, true) i - float(0.5) i - floor(1) i - half(f64) i - i i - i + f32 i - i32 i - i32 + 0.5 i - i32 - f32 i - i32 - i32 i - i64 i - i64 .. i32 i - i64 / i i - i64 <= i32 i - i64 ^ f32 i - i64 ^ f64 i - int(i32) i - max(i64) i - median(array) i - round(i32) i - score(1) i .. -i i .. -i32 i .. -i64 i .. abs(1) i .. i i .. i32 i .. i64 i .. i64 * 1 i .. i64 + 1 i .. int(0.5) i .. max(1) i .. max(i) i .. min(i) i .. reduce(list, i64) i .. score(1) i .. score(i) i / (0.5 + 1) i / (0.5 + f64) i / (0.5 + i) i / (0.5 - f32) i / (i + f32) i / -1 i / -f32 i / -f64 i / -i32 i / 0.5 * 1 i / 0.5 * f64 i / 0.5 / f64 i / 0.5 == nil != false i / 0.5 >= f32 i / 0.5 ^ i32 i / 1 ** i32 i / 1 <= i64 i / 1 > i i / abs(i) i / bitnot(i64) i / count(array, false) i / f32 i / f32 != i64 ? 1 : list i / f32 >= len(array) i / f64 i / f64 * f64 i / f64 ^ i32 i / float(0.5) i / float(1) i / float(f64) i / floor(1) i / floor(i32) i / i i / i ** 1 i / i / i i / i < i32 i / i ^ 1 i / i32 i / i32 / 1 i / i64 i / i64 * f32 i / i64 / f64 i / max(0.5) i / mean(array) i / min(f32) i / min(i64) i / score(1) i < -(f32 * 1) i < --f64 i < -i32 i < -i64 i < 0.5 != nil i < 0.5 + f64 i < 0.5 == ok i < 1 / 0.5 i < 1 == nil i < 1 ? array : score i < 1 ^ i64 i < abs(i32) i < f32 i < f32 && ok i < f32 * 0.5 i < f32 * i64 i < f32 ** i i < f32 ** i32 i < f32 + 1 i < f32 + array[i64] i < f32 / 0.5 i < f32 ? "bar" : div i < f32 || ok i < f64 i < f64 - 1 i < float(f64) i < floor(f32) i < half(0.5) i < half(1) i < half(f64) i < i i < i != true i < i ** 1 i < i / i64 i < i ? score : list i < i32 i < i32 * f32 i < i32 + 1 i < i64 i < i64 ^ f32 i < max(0.5) i < reduce(array, #) i <= -0.5 i <= -1 i <= -f64 i <= -i i <= -i32 i <= -i64 i <= 0.5 * f32 i <= 0.5 + 0.5 i <= 0.5 / 1 i <= 0.5 / f64 i <= 0.5 == ok i <= 0.5 ? i : ok i <= 0.5 ? nil : i32 i <= 0.5 ^ f32 i <= 1 != nil i <= 1 && ok i <= 1 * 0.5 i <= 1 ** i i <= 1 + f64 i <= 1 - f32 i <= 1 ? 0.5 : f32 i <= 1 ? 0.5 : list i <= 1 ? list : div i <= 1 ^ f32 i <= abs(0.5) i <= ceil(1) i <= f32 i <= f32 - 0.5 i <= f32 ? array : nil i <= f64 i <= float(0.5) i <= float(f32) i <= half(1) i <= half(f64) i <= i i <= i != nil i <= i * f32 i <= i ** f64 i <= i - 0.5 i <= i - 1 i <= i / i i <= i ^ 1 i <= i32 i <= i32 - f64 i <= i32 - i i <= i32 == ok i <= i32 ? array : false i <= i32 ? greet : foo i <= i32 || false ? f32 : i32 i <= i64 i <= i64 * i i <= i64 + f64 i <= len(list) i <= max(0.5) i <= max(f32, i32) i <= round(f32) i <= round(i32) i <= score(1) i == -f32 i == -f64 i == -i i == -i32 i == -i64 i == 0.5 ** f64 i == 0.5 == ok i == 0.5 ? "foo" : f64 i == 1 * 0.5 i == 1 ** i64 i == 1 / 0.5 i == 1 / f32 i == 1 ? f32 : 1 i == 1 ? f64 : f64 i == 1 ? greet : score i == abs(i64) i == bitnot(1) i == f32 i == f32 + i i == f32 == nil i == f32 ? foo : foo i == f32 ^ i32 i == f64 i == f64 + i32 i == f64 - i i == f64 ? i64 : div i == f64 ? score : foo i == f64 and ok i == findIndex(list, true) i == float(0.5) i == floor(f32) i == floor(i32) i == half(0.5) i == half(f64) i == i i == i + 0.5 i == i - i32 i == i == true i == i ? add : i32 i == i ? i32 : add i == i and ok i == i32 i == i32 * 0.5 i == i32 ** 0.5 i == i32 + 0.5 i == i32 + i64 i == i32 ^ f32 i == i64 i == i64 * 0.5 i == i64 * f32 i == i64 ** 0.5 i == i64 == nil i == i64 == ok i == i64 ? list : div i == len("bar") i == nil ? 0.5 : div i == nil ? div : i32 i == nil and add != nil i == reduce(array, #) i == reduce(array, 0.5) i == score(1) i == score(i) i > -f32 i > -f64 i > -i i > -i32 i > 0.5 - 0.5 i > 0.5 ^ i64 i > 0.5 or ok i > 0.5 || ok i > 1 != ok i > 1 % i64 i > 1 ** i32 i > 1 == ok i > 1 ? greet : nil i > 1 ? score : 0.5 i > 1 ? true : greet i > bitnot(1) i > bitor(1, i32) i > count(array, true) i > f32 i > f32 ** i32 i > f32 - f64 i > f32 ^ 1 i > f64 i > f64 != ok i > f64 * 1 i > f64 * f32 i > f64 ** i32 i > f64 ? foo : array i > f64 ? greet : "bar" i > first(array) i > floor(f64) i > i i > i % i32 i > i ** i i > i + i i > i ? f32 : i32 i > i32 i > i32 * 1 i > i32 * i32 i > i32 + 1 i > i32 == ok i > i64 i > i64 && f32 < 0.5 i > i64 + 0.5 i > i64 - 0.5 i > i64 - i i > int(f32) i > len("bar") i > reduce(list, i32) i >= -0.5 i >= -1 i >= -f32 i >= -i i >= -i32 i >= -i64 i >= 0.5 / 1 i >= 0.5 ? i64 : array i >= 0.5 ? nil : ok i >= 0.5 ^ i i >= 1 * i64 i >= 1 + f32 i >= 1 == nil i >= 1 ? f32 : nil i >= 1 ? ok : false i >= 1 ^ f64 i >= bitnot(i) i >= f32 i >= f32 ? f32 : i i >= f32 ? true : list i >= f64 i >= f64 * 0.5 i >= f64 - 1 i >= first(array) i >= float(0.5) i >= float(1) i >= get(array, i64) i >= half(f64) i >= i i >= i * 1 i >= i ** f32 i >= i ? foo : div i >= i32 i >= i32 ** i64 i >= i32 ? f32 : div i >= i32 ^ 1 i >= i64 i >= int(0.5) i >= min(0.5) i >= reduce(array, f64) i >= reduce(array, i) i >= reduce(list, 1) i >= round(1) i >= score(1) i >= score(i) i ^ (1 % i) i ^ (1 * f64) i ^ (1 - 0.5) i ^ (f32 - f64) i ^ (f64 - 1) i ^ (i + 0.5) i ^ (i + i64) i ^ (i - f32) i ^ (i32 * i32) i ^ (i32 + 1) i ^ (i32 / f32) i ^ (i32 / i) i ^ (i64 * 1) i ^ -1 i ^ -f32 i ^ -f64 i ^ -i i ^ 0.5 ** 0.5 i ^ 0.5 + i32 i ^ 0.5 < f64 i ^ 0.5 < i i ^ 0.5 <= i64 i ^ 0.5 > f64 i ^ 0.5 >= f32 i ^ 0.5 >= reduce(array, #) i ^ 0.5 ^ f32 i ^ 0.5 ^ i64 i ^ 1 * f64 i ^ 1 / i i ^ 1 >= f32 i ^ 1 ^ i i ^ 1 not in array i ^ bitnot(i64 + 1) i ^ bitnot(min(i)) i ^ ceil(0.5) i ^ f32 i ^ f32 ** 1 i ^ f32 < i i ^ f32 <= -f32 i ^ f64 i ^ f64 ** 0.5 i ^ f64 - f64 i ^ f64 / i32 i ^ f64 <= f32 i ^ f64 == i i ^ f64 > f32 i ^ find(array, ok) i ^ floor(i32) i ^ half(0.5) i ^ half(1) i ^ half(f64) i ^ i i ^ i * i i ^ i * i64 i ^ i ** i i ^ i / i i ^ i32 i ^ i32 / f64 i ^ i32 in array i ^ i64 i ^ i64 != f32 + 1 i ^ i64 ** f32 i ^ last(array) i ^ median(array) i ^ min(i32, 1) i ^ reduce(array, #) i ^ round(i32) i ^ score(1) i in 1 .. i i in array i in array != nil i in array ? nil : 1 i in groupBy(list, #) i in groupBy(list, foo) i in map(array, #) i in map(array, i64) i not in 1 .. 1 i not in array i not in groupBy(array, #) i not in groupBy(list, #) i not in i64 .. 1 i not in i64 .. i64 i not in map(array, #) i not in map(list, i32) i32 i32 != -0.5 i32 != -1 i32 != -f32 i32 != -i i32 != -i32 i32 != -i64 i32 != 0.5 - 0.5 i32 != 0.5 - i32 i32 != 0.5 / f32 i32 != 0.5 ^ 0.5 i32 != 0.5 ^ i64 i32 != 0.5 || ok i32 != 1 % i64 i32 != 1 && ok i32 != 1 * f32 i32 != 1 ? "foo" : array i32 != 1 ? greet : "foo" i32 != array[i64] i32 != bitnot(i) i32 != bitnot(i64) i32 != ceil(1) i32 != ceil(f64) i32 != count(array, false) i32 != f32 i32 != f32 == true i32 != f32 ? false : 0.5 i32 != f32 ? i : 0.5 i32 != f64 i32 != f64 ** i i32 != f64 - 1 i32 != f64 ? 1 : add i32 != findLastIndex(array, false) i32 != get(array, 1) i32 != half(1) i32 != i i32 != i + 1 i32 != i32 i32 != i32 ** 0.5 i32 != i32 + 0.5 i32 != i32 ^ i64 i32 != i64 i32 != i64 * i64 i32 != i64 / 0.5 i32 != i64 / f32 i32 != len(list) i32 != max(f64) i32 != min(1) i32 != min(i32) i32 != nil != false i32 != nil ? f64 : "foo" i32 != reduce(array, #) i32 != reduce(array, i) i32 != reduce(list, f32) i32 != round(1) i32 % -1 i32 % -i32 i32 % 1 % i32 i32 % 1 * f32 i32 % 1 * i i32 % 1 * i32 i32 % 1 .. i i32 % 1 / 0.5 i32 % 1 / i32 i32 % 1 > i i32 % array[i64] i32 % get(array, 1) i32 % i i32 % i != i i32 % i < i i32 % i32 i32 % i32 != f64 i32 % i32 * i64 i32 % i32 == i32 i32 % i32 >= i64 i32 % i64 i32 % i64 % i i32 % i64 * i64 i32 % i64 + i i32 % i64 .. i i32 % i64 / i i32 % i64 == f64 i32 % max(i32) i32 % reduce(array, #) i32 % score(1) i32 * (1 + f32) i32 * (1 + f64) i32 * (f32 + 1) i32 * (f32 - i) i32 * (f64 + 0.5) i32 * (f64 + i) i32 * (i - f32) i32 * (i32 + i64) i32 * (i32 - 1) i32 * (i32 - f64) i32 * -0.5 i32 * -1 i32 * -f32 i32 * -i32 i32 * -i64 i32 * 0.5 * 0.5 i32 * 0.5 / 0.5 i32 * 0.5 / 1 i32 * 0.5 / i32 i32 * 0.5 == f64 i32 * 0.5 == i64 i32 * 0.5 ^ f64 i32 * 0.5 ^ i32 i32 * 1 * i i32 * 1 ** i64 i32 * 1 + f64 i32 * 1 - i64 i32 * 1 > half(0.5) i32 * 1 ^ 1 i32 * abs(i32) i32 * bitnot(i32) i32 * ceil(1) i32 * f32 i32 * f32 + f32 i32 * f32 / i i32 * f32 <= f64 i32 * f32 <= i32 i32 * f32 ^ f32 i32 * f64 i32 * f64 * 1 i32 * f64 >= f32 i32 * first(array) i32 * float(f32) i32 * float(f64) i32 * floor(f64) i32 * half(0.5) i32 * half(1) i32 * i i32 * i / -i i32 * i / f32 i32 * i / i64 i32 * i < f32 i32 * i32 i32 * i32 != f64 i32 * i32 % i64 / i i32 * i32 / i64 i32 * i32 < i64 i32 * i32 >= f32 i32 * i64 i32 * i64 % 1 i32 * i64 % 1 % 1 i32 * i64 ** i64 i32 * i64 / f32 i32 * i64 < i i32 * len("foo") i32 * max(i32) i32 * max(i64) i32 * median(array) i32 * min(0.5) i32 * min(i) i32 * reduce(array, #) i32 * round(i) i32 * score(1) i32 * score(i) i32 ** (0.5 - i32) i32 ** (1 * i64) i32 ** (1 / 0.5) i32 ** (f32 * i64) i32 ** (i % i32) i32 ** (i - i) i32 ** (i - i32) i32 ** (i / 0.5) i32 ** (i32 / i64) i32 ** (i64 + 0.5) i32 ** (i64 - 1) i32 ** -1 i32 ** -f64 i32 ** -i i32 ** -i64 i32 ** 0.5 * i64 i32 ** 0.5 - f64 i32 ** 0.5 / reduce(array, #) i32 ** 0.5 ^ i i32 ** 1 ** i64 i32 ** 1 + f32 i32 ** 1 / i64 i32 ** 1 <= i i32 ** 1 ^ i64 i32 ** 1 in array i32 ** array[1] i32 ** array[i64] i32 ** bitnot(i64) i32 ** ceil(1) i32 ** ceil(f64) i32 ** f32 i32 ** f32 / score(1) i32 ** f32 < f32 i32 ** f32 <= i i32 ** f32 == f32 i32 ** f64 i32 ** f64 == f32 i32 ** f64 > i i32 ** find(array, ok) i32 ** float(i32) i32 ** half(0.5) i32 ** half(1) i32 ** half(f64) i32 ** i i32 ** i * f64 i32 ** i ** i i32 ** i ^ i i32 ** i32 i32 ** i32 ^ i64 i32 ** i64 i32 ** int(1) i32 ** int(i32) i32 ** len("foo") i32 ** len(list) i32 ** max(f32, i32) i32 ** min(0.5) i32 ** min(i64) i32 ** reduce(array, 1) i32 ** reduce(array, i64) i32 ** reduce(list, i64) i32 ** round(i64) i32 ** sum(array) i32 + -0.5 i32 + -1 i32 + -i i32 + -i32 i32 + -i64 i32 + 0.5 != f32 i32 + 0.5 != i32 i32 + 0.5 * i i32 + 0.5 + 0.5 i32 + 0.5 + 1 i32 + 0.5 + f32 i32 + 0.5 + f64 i32 + 0.5 + i i32 + 0.5 + i64 i32 + 0.5 / i64 i32 + 0.5 <= -f32 i32 + 1 % 1 i32 + 1 + i64 i32 + 1 - f32 i32 + 1 - i i32 + 1 - i64 i32 + 1 / i i32 + 1 ^ f32 i32 + abs(f32) i32 + array[i64] i32 + bitnot(i32) i32 + ceil(i) i32 + f32 i32 + f32 / i i32 + f32 < i32 i32 + f32 <= i64 i32 + f64 i32 + f64 * 1 i32 + f64 * i32 i32 + f64 > i32 i32 + f64 ^ 0.5 i32 + f64 ^ i32 i32 + findIndex(list, true) i32 + floor(0.5) i32 + floor(f64) i32 + i i32 + i + f64 i32 + i + i64 i32 + i - 0.5 i32 + i - i64 i32 + i <= i32 i32 + i > i64 i32 + i32 i32 + i32 + f64 i32 + i32 <= i + i64 i32 + i32 > i i32 + i32 > i32 i32 + i64 i32 + i64 % i32 i32 + i64 ** 1 i32 + i64 - 0.5 i32 + i64 - f32 i32 + i64 / 0.5 i32 + i64 ^ 1 i32 + int(i64) i32 + len("bar") i32 + min(i32) i32 + reduce(array, #) i32 + round(f32) i32 + round(i32) i32 + score(i) i32 - -0.5 i32 - -1 i32 - -f32 i32 - -i i32 - 0.5 * f32 i32 - 0.5 + half(0.5) i32 - 0.5 - i32 i32 - 0.5 <= f32 i32 - 0.5 ^ 0.5 i32 - 1 ** i i32 - 1 + 0.5 i32 - 1 > -i64 i32 - abs(i32) i32 - abs(i64) i32 - array[i] i32 - bitushr(i32, i64) i32 - div(1, i) i32 - div(i, i) i32 - f32 i32 - f32 * 0.5 i32 - f32 + i32 i32 - f32 - int(f64) i32 - f32 / i32 i32 - f32 < i64 i32 - f32 <= f32 i32 - f32 <= i32 i32 - f32 > i i32 - f32 >= f32 i32 - f64 i32 - f64 + f32 i32 - float(0.5) i32 - float(1) i32 - float(f64) i32 - floor(1) i32 - floor(f64) i32 - get(array, i) i32 - half(0.5) i32 - half(f64) i32 - i i32 - i ** i64 i32 - i + i32 i32 - i / 0.5 i32 - i == f32 i32 - i > f64 i32 - i > i i32 - i >= i64 i32 - i32 i32 - i32 != i64 i32 - i32 * 1 i32 - i32 * i32 i32 - i32 + 1 i32 - i32 < i32 i32 - i32 > i64 i32 - i32 > i64 / i i32 - i64 i32 - i64 != -f32 i32 - i64 / 1 i32 - i64 == f64 i32 - len(array) i32 - len(list) i32 - max(f32) i32 - score(1) i32 .. -i64 i32 .. abs(i64) i32 .. bitnot(i64) i32 .. bitushr(i, 1) i32 .. count(array, true) i32 .. div(i, 1) i32 .. i i32 .. i32 i32 .. i64 i32 .. int(f32) i32 .. len("foo") i32 .. max(1) i32 .. max(i32) i32 .. max(i32, 0.5) i32 .. score(i) i32 / (1 + 1) i32 / (1 + i64) i32 / (f64 - i64) i32 / (i32 + i64) i32 / (i64 + 0.5) i32 / -0.5 i32 / -f32 i32 / -i i32 / -i32 i32 / -i64 i32 / 0.5 * i i32 / 0.5 * i / 1 i32 / 0.5 + i64 i32 / 0.5 - i32 i32 / 0.5 / i32 i32 / 0.5 / i64 i32 / 0.5 >= i64 i32 / 0.5 ^ 1 i32 / 0.5 ^ f64 i32 / 1 != i i32 / 1 * i64 i32 / 1 ** 1 i32 / 1 ^ 0.5 i32 / abs(0.5) i32 / abs(1) i32 / abs(f64) i32 / abs(i32) i32 / array[1] i32 / ceil(i32) i32 / f32 i32 / f32 ** 1 i32 / f32 / i64 i32 / f32 <= i32 i32 / f32 <= i64 i32 / f32 >= i32 == false i32 / f64 i32 / f64 != f64 i32 / f64 != i64 i32 / f64 * 1 i32 / f64 - i32 i32 / f64 == i64 i32 / f64 >= f32 i32 / find(array, ok) i32 / float(f32) i32 / floor(1) i32 / floor(f64) i32 / half(0.5) i32 / i i32 / i * i32 i32 / i ^ i32 i32 / i32 i32 / i32 * f64 i32 / i32 / i64 i32 / i32 <= i64 i32 / i64 i32 / i64 ** f32 i32 / i64 ^ 0.5 i32 / int(1) i32 / len("foo") i32 / max(1) i32 / max(i) i32 / min(f32) i32 / reduce(array, #) i32 / score(i) i32 < -f32 i32 < -f64 i32 < -i32 i32 < 0.5 ** i32 i32 < 0.5 - 1 i32 < 0.5 - f32 i32 < 0.5 / 1 i32 < 0.5 == nil i32 < 0.5 ? "foo" : half i32 < 0.5 ? foo : 1 i32 < 0.5 or ok i32 < 0.5 || ok i32 < 1 * f32 i32 < 1 + i64 i32 < 1 / f32 i32 < 1 ^ i i32 < abs(f64) i32 < f32 i32 < f32 * i i32 < f32 - 0.5 i32 < f32 - 1 i32 < f64 i32 < f64 * i64 i32 < float(reduce(array, f32)) i32 < get(array, i32) i32 < get(array, i64) i32 < half(1) i32 < half(f64) i32 < i i32 < i ** i64 i32 < i + 0.5 i32 < i / i32 i32 < i ? score : score i32 < i32 i32 < i32 % i i32 < i32 ** 1 i32 < i32 - f32 i32 < i32 ^ i64 i32 < i64 i32 < i64 ** 0.5 i32 < i64 + f32 i32 < i64 / f64 i32 < int(0.5) i32 < last(array) i32 < min(1) i32 < min(f64) i32 < min(i32) i32 < score(1) i32 < score(i) i32 <= -0.5 i32 <= -f32 i32 <= -i i32 <= -i32 i32 <= -i64 i32 <= 0.5 - f64 i32 <= 0.5 == nil i32 <= 0.5 ? i32 : greet i32 <= 0.5 ? i32 : half i32 <= 0.5 ^ i64 i32 <= 0.5 and ok i32 <= 1 + i32 i32 <= 1 + i64 i32 <= 1 ^ 0.5 i32 <= 1 and ok i32 <= 1 || i32 >= i32 i32 <= abs(1) i32 <= f32 i32 <= f32 != ok i32 <= f64 i32 <= f64 != ok i32 <= f64 * i i32 <= f64 == ok i32 <= f64 ^ f64 i32 <= findIndex(array, true) i32 <= float(i32) i32 <= floor(0.5) i32 <= half(0.5) i32 <= half(1) i32 <= half(f64) i32 <= i i32 <= i * 1 i32 <= i * i64 i32 <= i - 0.5 i32 <= i32 i32 <= i32 != true i32 <= i64 i32 <= i64 / 1 i32 <= len("foo") i32 <= max(i64) i32 <= mean(array) i32 <= round(0.5) i32 <= score(1) i32 <= score(i) i32 == -0.5 i32 == -1 i32 == -f32 i32 == -f64 i32 == -i i32 == 0.5 != false i32 == 0.5 * f32 i32 == 0.5 / 0.5 i32 == 1 % 1 i32 == 1 + f32 i32 == 1 - i i32 == 1 ? div : div i32 == 1 ^ 0.5 i32 == 1 ^ f64 i32 == abs(f64) i32 == abs(i) i32 == bitnot(1) i32 == bitnot(i) i32 == ceil(1) i32 == count(list, ok) i32 == f32 i32 == f32 * i32 i32 == f32 ** 1 i32 == f32 - f32 i32 == f32 ? f64 : list i32 == f32 ? i64 : true i32 == f32 ? score : "bar" i32 == f64 i32 == f64 ** 0.5 i32 == find(array, 0.5 == i64) i32 == first(array) i32 == floor(f64) i32 == half(f64) i32 == i i32 == i ** f64 i32 == i ? half : 1 i32 == i ? i : "bar" i32 == i32 i32 == i32 && i == i i32 == i32 - 1 i32 == i32 - i64 i32 == i64 i32 == i64 * f32 i32 == i64 ? "foo" : 1 i32 == i64 or ok i32 == int(f64) i32 == int(i) i32 == nil ? f32 : 0.5 i32 == reduce(array, #) i32 == round(i32) i32 == round(i64) i32 == score(1) i32 > -0.5 i32 > -f64 i32 > -i32 i32 > 0.5 != true i32 > 0.5 * f64 i32 > 0.5 ** 0.5 i32 > 0.5 ** 1 i32 > 0.5 ** i i32 > 0.5 - i i32 > 0.5 / 1 i32 > 0.5 == ok i32 > 0.5 ^ 1 i32 > 0.5 || ok i32 > 1 * f64 i32 > 1 * i32 i32 > 1 + i64 i32 > 1 ? f32 : f64 i32 > 1 ? i : "bar" i32 > 1 ? i64 : div i32 > ceil(0.5) i32 > ceil(1) i32 > count(array, ok) i32 > f32 i32 > f32 * i64 i32 > f32 + 0.5 i32 > f32 + 1 i32 > f32 - f32 i32 > f32 - i32 i32 > f32 ^ 0.5 i32 > f64 i32 > f64 ** i32 i32 > f64 + f64 i32 > get(array, i32) i32 > half(1) i32 > half(half(1)) i32 > i i32 > i != ok i32 > i + f32 i32 > i ? i : i i32 > i ^ i32 i32 > i32 i32 > i32 - i i32 > i32 == nil ? score : i i32 > i32 ? score : 1 i32 > i32 ^ 1 i32 > i32 ^ i32 i32 > i64 i32 > i64 != false i32 > i64 ** f32 i32 > i64 / 1 i32 > i64 == ok i32 > i64 || ok i32 > int(1) i32 > int(i64) i32 > min(i32) i32 > reduce(array, #) i32 > round(i64) i32 > score(i) i32 >= -1 i32 >= -f32 i32 >= -f64 i32 >= -i i32 >= -i64 i32 >= 0.5 != not true i32 >= 0.5 == true i32 >= 0.5 ? 0.5 : half i32 >= 0.5 ^ 0.5 i32 >= 0.5 ^ i32 i32 >= 1 % i i32 >= 1 * 0.5 i32 >= 1 * i32 i32 >= 1 + i64 i32 >= 1 - 1 i32 >= 1 == ok i32 >= 1 ? 1 : false i32 >= 1 ? add : 1 i32 >= abs(0.5) i32 >= abs(f32) i32 >= bitnot(1 + i) i32 >= bitnot(i64) i32 >= ceil(1) i32 >= ceil(f32) i32 >= count(list, true) i32 >= f32 i32 >= f32 ** f32 i32 >= f32 ^ 1 i32 >= f64 i32 >= f64 != false i32 >= f64 ** f64 i32 >= f64 / i64 i32 >= f64 ? half : f64 i32 >= f64 ^ f64 i32 >= float(0.5) i32 >= floor(1) i32 >= floor(f32) i32 >= half(0.5) i32 >= i i32 >= i % 1 i32 >= i % i64 i32 >= i / i32 i32 >= i / i64 i32 >= i == ok i32 >= i32 i32 >= i32 ** i32 i32 >= i64 i32 >= i64 != false i32 >= i64 - i64 i32 >= i64 / i32 i32 >= i64 ? 0.5 : 0.5 i32 >= i64 ? div : half i32 >= i64 ? half : i64 i32 >= i64 and ok i32 >= int(i64) i32 >= last(array) i32 >= min(i32) i32 >= reduce(array, #) i32 >= reduce(array, i64) i32 >= reduce(list, i32) i32 >= round(f32) i32 >= score(1) i32 ^ (0.5 + 1) i32 ^ (1 - i) i32 ^ (i + 1) i32 ^ (i / f64) i32 ^ (i32 + 0.5) i32 ^ (i32 - f32) i32 ^ (i64 + i) i32 ^ -0.5 i32 ^ -1 i32 ^ -f64 i32 ^ -i i32 ^ -i32 i32 ^ -i64 i32 ^ 0.5 != f32 i32 ^ 0.5 != f64 i32 ^ 0.5 * i i32 ^ 0.5 ** i64 i32 ^ 0.5 - f32 i32 ^ 0.5 / i32 i32 ^ 0.5 == i64 i32 ^ 0.5 >= f64 i32 ^ 1 ** i32 i32 ^ 1 + i32 i32 ^ 1 - f64 i32 ^ 1 < f64 i32 ^ 1 ^ (1 + i64) i32 ^ 1 ^ f32 i32 ^ array[i64] i32 ^ f32 i32 ^ f32 / bitnot(1) i32 ^ f32 >= max(f64) i32 ^ f64 i32 ^ f64 + i i32 ^ find(array, true) i32 ^ first(array) i32 ^ float(i64) i32 ^ i i32 ^ i * f64 i32 ^ i + i64 i32 ^ i <= f32 i32 ^ i32 i32 ^ i32 * f64 i32 ^ i32 ** i i32 ^ i64 i32 ^ i64 == f64 i32 ^ i64 > -f64 i32 ^ len(list) i32 ^ mean(array) i32 ^ min(i) i32 ^ reduce(array, #) i32 ^ reduce(list, 1) i32 in [0.5] i32 in array i32 in array || ok i32 in groupBy(array, #) i32 in groupBy(array, f32) i32 in groupBy(list, #) i32 in groupBy(list, #?.Bar) i32 in groupBy(list, foo).i i32 in i32 .. 1 i32 in i32 .. i64 i32 in map(array, #) i32 in map(list, 0.5) i32 in map(list, i32) i32 not in 1 .. i i32 not in array i32 not in array ? array : array i32 not in filter(array, ok) i32 not in groupBy(list, #) i64 i64 != -1 i64 != -i i64 != -i64 i64 != 0.5 && ok i64 != 0.5 * 0.5 i64 != 0.5 * i i64 != 0.5 + 0.5 i64 != 0.5 + i i64 != 0.5 - 0.5 i64 != 0.5 / i64 i64 != 0.5 ? i : 1 i64 != 0.5 ^ i32 i64 != 1 * f64 i64 != 1 - 1 i64 != abs(f64) i64 != array[i64] i64 != bitnot(i32) i64 != f32 i64 != f32 + i64 i64 != f64 i64 != f64 * 1 i64 != f64 == true i64 != f64 or i64 <= f32 i64 != findIndex(array, ok) i64 != float(1) i64 != floor(i) i64 != get(array, i) i64 != half(0.5) i64 != half(1) i64 != i i64 != i % 1 i64 != i + 1 i64 != i / 0.5 i64 != i ? f32 : true i64 != i32 i64 != i32 ? 0.5 : nil i64 != i32 ? f64 : greet i64 != i32 ^ i i64 != i32 || ok i64 != i64 i64 != i64 - 0.5 i64 != len("bar") i64 != len(list) i64 != max(0.5) i64 != min(1) i64 != min(1, f32) i64 != min(f32) i64 != min(i) i64 != nil != ok i64 != nil ? div : 1 i64 != nil ? greet : i i64 != nil ? i : i i64 != nil ? i64 : false i64 != score(1) i64 != score(i) i64 % -i i64 % 1 % 1 i64 % 1 * i i64 % 1 < i32 i64 % 1 >= f64 i64 % 1 >= i32 i64 % abs(i32) i64 % array[i32] i64 % i i64 % i * i i64 % i >= i i64 % i32 i64 % i32 / f64 i64 % i32 <= f64 i64 % i64 i64 % i64 % 1 i64 % i64 .. i64 i64 % i64 == i64 i64 % int(i32) i64 % len("bar") i64 % max(i) i64 % min(1) i64 % score(1) i64 * (0.5 + f64) i64 * (1 - i64) i64 * (f32 - f32) i64 * (f64 + f32) i64 * (i + 0.5) i64 * (i + f64) i64 * (i32 + f64) i64 * -0.5 i64 * -1 i64 * -f32 i64 * -i32 i64 * 0.5 * i32 i64 * 0.5 ** 0.5 i64 * 0.5 - f32 i64 * 0.5 / 1 i64 * 0.5 >= f32 i64 * 1 % 1 i64 * 1 * 0.5 i64 * 1 * f64 i64 * 1 ** 1 i64 * 1 - i64 i64 * 1 .. i32 i64 * 1 / i64 i64 * 1 <= f64 i64 * 1 == 0.5 != true i64 * 1 == f32 i64 * 1 > 1 - i64 i64 * 1 > f64 i64 * 1 ^ i32 i64 * add(1, 1) i64 * ceil(1) i64 * ceil(i) i64 * ceil(i64) i64 * count(array, false) i64 * f32 i64 * f32 * f32 i64 * f32 ** 1 i64 * f32 / f32 i64 * f32 / i i64 * f32 / i32 i64 * f32 not in array i64 * f64 i64 * f64 + i32 i64 * f64 - f64 i64 * f64 / f64 i64 * f64 < f64 i64 * f64 > f64 i64 * f64 ^ i32 i64 * findIndex(array, ok) i64 * float(i) i64 * float(i64) i64 * half(0.5) i64 * i i64 * i - -f64 i64 * i <= f64 i64 * i32 i64 * i32 != i32 i64 * i32 * 1 i64 * i32 * i i64 * i32 / 0.5 i64 * i32 ^ i i64 * i64 i64 * i64 % i64 i64 * i64 * i64 i64 * i64 ** i i64 * i64 / f32 i64 * i64 > i32 i64 * int(1) i64 * int(i) i64 * max(1) i64 * max(i64) i64 * min(1) i64 * min(i32) i64 * reduce(array, #) i64 * reduce(list, 0.5) i64 * reduce(list, 1) i64 * round(i) i64 * score(1) i64 ** (0.5 + 0.5) i64 ** (0.5 / 1) i64 ** (1 % 1) i64 ** (1 * 1) i64 ** (1 - f32) i64 ** (f32 + 1) i64 ** (f32 / 0.5) i64 ** (f64 - 0.5) i64 ** (i * i64) i64 ** (i / 1) i64 ** (i64 % i) i64 ** (i64 / i) i64 ** -0.5 i64 ** -1 i64 ** -f32 i64 ** 0.5 != i32 i64 ** 0.5 <= f32 i64 ** 0.5 <= i i64 ** 1 + i32 i64 ** 1 - f32 i64 ** 1 / i64 i64 ** 1 >= f32 i64 ** bitnot(i32) i64 ** ceil(i32) i64 ** count(array, false) i64 ** f32 i64 ** f32 * min(0.5) i64 ** f64 i64 ** f64 ** f64 i64 ** f64 not in array i64 ** f64 not in array ? f32 : greet i64 ** floor(f32) i64 ** half(1) i64 ** i i64 ** i != f32 i64 ** i * f32 i64 ** i <= -i i64 ** i == f64 i64 ** i ^ f32 i64 ** i32 i64 ** i32 != i64 i64 ** i32 * i ^ i i64 ** i32 not in array i64 ** i64 i64 ** i64 - i64 i64 ** i64 in array i64 ** max(1) i64 ** min(0.5) i64 ** min(1) i64 ** min(i32, 1) i64 ** reduce(array, #) i64 + -1 i64 + -i i64 + -i64 i64 + 0.5 ** f32 i64 + 0.5 + i32 i64 + 0.5 + i64 i64 + 0.5 - f64 i64 + 0.5 <= bitnand(1, 1) i64 + 0.5 <= f64 i64 + 0.5 == f32 i64 + 1 != f64 i64 + 1 % i64 i64 + 1 + f64 i64 + 1 <= f32 i64 + array[i64] i64 + array[i] i64 + f32 i64 + f32 * f64 i64 + f32 / i64 i64 + f64 i64 + f64 * 0.5 i64 + f64 ** 0.5 i64 + f64 > f32 i64 + float(f32) i64 + float(i32) i64 + half(0.5) i64 + i i64 + i % 1 i64 + i * 0.5 i64 + i + f32 i64 + i - i32 i64 + i / i32 i64 + i == 0.5 - i32 i64 + i ^ f32 i64 + i ^ f64 i64 + i32 i64 + i32 % i64 i64 + i32 - 0.5 i64 + i32 == f64 i64 + i64 i64 + i64 - 0.5 i64 + reduce(array, #) i64 + score(i) i64 - -1 i64 - -f32 i64 - -i32 i64 - -i64 i64 - 0.5 + f32 i64 - 0.5 / i64 i64 - 0.5 <= i i64 - 0.5 ^ f32 i64 - 1 ** 1 i64 - 1 < i i64 - 1 == i32 i64 - 1 > f32 i64 - 1 >= i i64 - 1 not in array i64 - ceil(1) i64 - f32 i64 - f32 != f32 i64 - f32 - 1 i64 - f32 - i i64 - f32 / 1 i64 - f32 < i64 i64 - f32 >= f64 i64 - f64 i64 - f64 != i i64 - f64 ** f32 i64 - f64 ** i32 i64 - f64 + f32 i64 - f64 + i32 i64 - f64 >= f64 i64 - float(0.5) i64 - half(1) i64 - half(f64) i64 - i i64 - i * 1 i64 - i + i64 i64 - i - 1 i64 - i .. i64 i64 - i < i32 i64 - i > 1 - 0.5 i64 - i >= f64 i64 - i ^ i64 i64 - i not in array i64 - i32 i64 - i32 - i64 i64 - i32 .. i64 i64 - i32 > i i64 - i32 >= i i64 - i64 i64 - i64 > f32 i64 - int(i) i64 - len("foo") i64 - max(0.5) i64 - min(f32) i64 - min(f64) i64 - min(i) i64 - reduce(array, #) i64 - reduce(array, i64) i64 - round(1) i64 - score(1) i64 - score(i) i64 .. -1 i64 .. -i i64 .. -i32 i64 .. -i64 i64 .. 1 * i64 i64 .. 1 - 1 i64 .. 1 - i i64 .. 1 - i64 i64 .. abs(i) i64 .. bitnot(i32) i64 .. count(array, false) i64 .. get(array, 1) i64 .. i i64 .. i * i i64 .. i + 1 i64 .. i == list i64 .. i32 i64 .. i32 * 1 i64 .. i64 i64 .. i64 * i32 i64 .. i64 + i i64 .. i64 - i i64 .. int(0.5) i64 .. int(f32) i64 .. int(i64) i64 .. min(i32) i64 .. min(i64, 0.5) i64 .. reduce(array, #) i64 .. score(1) i64 / (f32 + i64) i64 / (f32 - i) i64 / (i + 1) i64 / (i32 + 0.5) i64 / (i64 - i) i64 / -0.5 i64 / -1 i64 / -f32 i64 / -f64 i64 / -i i64 / 0.5 * f64 i64 / 0.5 - i64 i64 / 0.5 / i i64 / 0.5 == i i64 / 1 ** i64 i64 / 1 / i32 i64 / 1 / i64 i64 / 1 < i i64 / 1 == f32 i64 / ceil(i) i64 / f32 i64 / f32 - i i64 / f32 / i64 i64 / f32 > i i64 / f32 ^ 1 i64 / f32 ^ i i64 / f64 i64 / f64 * i64 i64 / f64 - min(i64) i64 / f64 / f32 i64 / f64 / i * 0.5 i64 / f64 / i32 i64 / f64 in array i64 / float(1) i64 / get(array, i32) i64 / half(1) i64 / i i64 / i * i64 i64 / i - f64 i64 / i32 i64 / i32 != f32 i64 / i32 * f64 i64 / i32 == f64 i64 / i32 > 1 + 1 i64 / i32 >= f32 i64 / i32 >= f64 i64 / i32 ^ f32 i64 / i64 i64 / i64 + f64 i64 / i64 < i32 i64 / i64 <= f32 i64 / i64 == i32 i64 / int(1) i64 / len(list) i64 / max(1) i64 / reduce(array, #) i64 / reduce(array, 1) i64 / round(0.5) i64 / round(i) i64 / score(1) i64 / score(i) i64 < -0.5 i64 < -1 i64 < -f32 i64 < -f64 i64 < -i i64 < -i32 i64 < -i64 i64 < 0.5 * 0.5 i64 < 0.5 + i i64 < 0.5 - 1 i64 < 0.5 / 0.5 i64 < 0.5 / 1 i64 < 0.5 == ok i64 < 0.5 || false ? 1 : nil i64 < 1 * i32 i64 < 1 ** 0.5 i64 < 1 + 0.5 i64 < 1 + i64 i64 < 1 / f32 i64 < ceil(i64) i64 < f32 i64 < f32 * 0.5 i64 < f32 - i64 i64 < f32 ^ f32 i64 < f64 i64 < f64 && ok i64 < f64 - f64 i64 < f64 ? score : add i64 < float(0.5) i64 < float(i32) i64 < floor(0.5) i64 < floor(i32) i64 < half(1) i64 < i i64 < i % i64 i64 < i ^ 0.5 i64 < i || ok i64 < i32 i64 < i32 + 1 i64 < i32 + i32 i64 < i32 / f32 i64 < i32 ? foo : i i64 < i64 i64 < i64 != nil i64 < i64 * 1 i64 < i64 * i64 i64 < i64 / f32 i64 < i64 / i i64 < i64 ^ 1 i64 < i64 ^ i i64 < int(f64) i64 < len("bar") i64 < len("foo") i64 <= -0.5 i64 <= -1 i64 <= -f32 i64 <= -f64 i64 <= -i64 i64 <= 0.5 && ok i64 <= 0.5 * 0.5 i64 <= 0.5 + 1 i64 <= 0.5 ? i : i32 i64 <= 1 ** i32 i64 <= 1 + 1 i64 <= 1 - 0.5 i64 <= 1 - 1 i64 <= 1 / 1 i64 <= 1 == ok i64 <= 1 ? add : div i64 <= 1 ? f32 : greet i64 <= 1 ? i64 : true i64 <= 1 ^ 1 i64 <= array[i64] i64 <= array[i] i64 <= bitnot(1) i64 <= f32 i64 <= f32 ** i i64 <= f32 ** i64 i64 <= f32 == ok i64 <= f64 i64 <= f64 + 1 i64 <= f64 + f32 i64 <= f64 / 1 i64 <= f64 ? nil : i32 i64 <= float(1) i64 <= floor(i) i64 <= floor(i32) i64 <= half(min(0.5, 1, i64)) i64 <= i i64 <= i * 1 i64 <= i * f32 i64 <= i ** i32 i64 <= i ? greet : add i64 <= i32 i64 <= i32 ** i32 i64 <= i32 ? list : half i64 <= i32 ^ -1 i64 <= i64 i64 <= i64 * i i64 <= len(list) i64 <= max(f32) i64 <= min(0.5) i64 <= min(i32) i64 <= reduce(array, i32) i64 <= reduce(list, i64) i64 <= round(0.5) i64 == -1 i64 == -f32 i64 == -f64 i64 == -i i64 == -i32 i64 == 0.5 * 1 i64 == 0.5 - f64 i64 == 0.5 == ok i64 == 0.5 ? 0.5 : f64 i64 == 1 ** f64 i64 == 1 + 0.5 i64 == 1 / i i64 == 1 == ok i64 == 1 ? "foo" : i i64 == array[1] i64 == bitnot(i64) i64 == ceil(i64) i64 == f32 i64 == f32 != true i64 == f32 + i i64 == f32 - f32 i64 == f32 == ok i64 == f64 i64 == f64 * f64 i64 == f64 ? 1 : nil i64 == f64 ^ 0.5 i64 == f64 ^ f32 i64 == f64 and not true i64 == findIndex(list, f64 <= f64) i64 == floor(0.5) i64 == get(array, 1) i64 == half(1) i64 == i i64 == i != nil i64 == i + i32 i64 == i ? i64 : foo i64 == i32 i64 == i64 i64 == i64 * f32 i64 == i64 / i64 i64 == i64 ? add : 0.5 i64 == i64 ? add : greet i64 == int(0.5) i64 == int(1) i64 == int(i) i64 == len("foo") i64 == nil != nil i64 == reduce(array, #) i64 == score(1) i64 > -0.5 i64 > -f32 i64 > -f64 i64 > 0.5 + f32 i64 > 0.5 - f64 i64 > 0.5 - i32 i64 > 0.5 ? array : 1 i64 > 0.5 ? f32 : nil i64 > 0.5 ? ok : nil i64 > 0.5 ? score : foo i64 > 0.5 or ok i64 > 1 != true i64 > 1 ** 1 i64 > 1 == false i64 > 1 ? nil : 1 i64 > 1 ^ f32 i64 > 1 ^ i32 i64 > f32 i64 > f32 * 0.5 i64 > f32 + f64 i64 > f32 / f32 i64 > f32 ? "foo" : greet i64 > f32 ? 1 : i32 i64 > f64 i64 > f64 * i i64 > f64 - 0.5 i64 > f64 - f32 i64 > first(array) i64 > half(0.5) i64 > i i64 > i != nil i64 > i == true i64 > i32 i64 > i32 ? div : f32 i64 > i32 ^ f32 i64 > i64 i64 > i64 - i i64 > i64 - i32 i64 > i64 / f64 i64 > i64 == false i64 > len(list) i64 > max(0.5) i64 > min(1) i64 > min(i32) i64 > reduce(array, #) i64 > reduce(array, 1) i64 > round(0.5) i64 > round(i32) i64 > score(i) i64 >= -0.5 i64 >= -1 i64 >= -i i64 >= -i64 i64 >= 0.5 / i i64 >= 0.5 == nil i64 >= 0.5 ? 0.5 : f64 i64 >= 0.5 ^ i i64 >= 1 % i64 i64 >= 1 * f64 i64 >= 1 * i64 i64 >= abs(i64) i64 >= array[i32] i64 >= bitnot(1) i64 >= f32 i64 >= f32 + f32 i64 >= f32 - f32 i64 >= f32 ? array : i i64 >= f32 ? f32 : i32 i64 >= f32 ? list : f32 i64 >= f64 i64 >= f64 + 0.5 i64 >= first(array) i64 >= float(0.5) i64 >= float(f32) i64 >= floor(1) i64 >= floor(i64) i64 >= half(0.5) i64 >= half(half(f64)) i64 >= i i64 >= i / 0.5 i64 >= i ? true : i32 i64 >= i32 i64 >= i32 * i i64 >= i32 / f32 i64 >= i32 == false i64 >= i32 || f64 == 1 i64 >= i64 i64 >= i64 + 1 i64 >= i64 ? foo : foo i64 >= i64 or ok i64 >= int(f64) i64 >= last(array) i64 >= max(i64) i64 >= min(1) i64 >= min(f64) i64 >= round(1) i64 >= round(i) i64 >= score(1) i64 ^ (0.5 * i32) i64 ^ (0.5 / i64) i64 ^ (1 * f64) i64 ^ (1 - i) i64 ^ (f32 / 1) i64 ^ (i % i) i64 ^ (i32 * f64) i64 ^ (i32 - f64) i64 ^ (i64 + 0.5) i64 ^ (i64 + 1) i64 ^ (i64 - f32) i64 ^ -0.5 i64 ^ -1 i64 ^ -f32 i64 ^ -i64 i64 ^ 0.5 != i64 i64 ^ 0.5 ** 0.5 i64 ^ 0.5 / f32 i64 ^ 0.5 <= i64 i64 ^ 0.5 == i i64 ^ 0.5 ^ f32 i64 ^ 0.5 ^ i64 i64 ^ 1 * i64 i64 ^ 1 * round(0.5) i64 ^ 1 ** f64 i64 ^ 1 ** i32 i64 ^ 1 - f32 i64 ^ 1 < f64 i64 ^ 1 >= f32 i64 ^ 1 >= half(1) i64 ^ 1 ^ f32 i64 ^ 1 ^ i32 i64 ^ abs(1) i64 ^ array[i] i64 ^ f32 i64 ^ f32 * i32 i64 ^ f32 ** f64 i64 ^ f32 - f64 i64 ^ f32 / i - i32 i64 ^ f32 < f32 i64 ^ f32 <= i64 i64 ^ f32 ^ 1 i64 ^ f64 i64 ^ f64 * i i64 ^ f64 ** 1 i64 ^ f64 > i64 i64 ^ f64 ^ f32 i64 ^ float(i32) i64 ^ floor(i32) i64 ^ floor(i64) i64 ^ half(0.5) i64 ^ half(1) i64 ^ i i64 ^ i * i i64 ^ i ** i32 i64 ^ i + i % 1 i64 ^ i + i64 i64 ^ i - f32 ^ 1 i64 ^ i - f64 i64 ^ i / i i64 ^ i < f32 i64 ^ i ^ i32 i64 ^ i32 i64 ^ i32 * i i64 ^ i32 + i32 i64 ^ i32 + i64 i64 ^ i64 i64 ^ i64 * i64 i64 ^ i64 + i i64 ^ i64 == i64 i64 ^ i64 ^ 1 i64 ^ i64 in array i64 ^ int(1) i64 ^ max(0.5) i64 ^ reduce(array, #) i64 ^ round(i64) i64 ^ score(1) i64 in array i64 in array == ok i64 in groupBy(array, 0.5) i64 in groupBy(array, foo) i64 in groupBy(list, "bar") i64 in groupBy(list, i) i64 in i64 .. i32 i64 in map(array, #) i64 in map(list, 1) i64 in map(list, i) i64 not in 1 .. i i64 not in array i64 not in array ? f32 : i32 i64 not in array ? ok : f32 i64 not in map(array, #) i64 not in map(list, 0.5) int(-0.5) int(-1) int(-f32) int(-f64) int(-i) int(-i32) int(-i64) int(0.5 * 0.5) int(0.5 * f32) int(0.5 * f64) int(0.5 * i32) int(0.5 ** 0.5) int(0.5 ** 1) int(0.5 ** f32) int(0.5 ** f64) int(0.5 ** i32) int(0.5 + 0.5) int(0.5 + 1) int(0.5 + f64) int(0.5 + i32) int(0.5 + i64) int(0.5 - f32) int(0.5 - i) int(0.5 - i32) int(0.5 - i64) int(0.5 / i) int(0.5 / i64) int(0.5 ^ i) int(0.5 ^ i64) int(0.5) * -i int(0.5) ** f64 int(0.5) ** i32 int(0.5) + i int(0.5) / i32 int(0.5) < 0.5 * f64 int(0.5) <= i int(0.5) <= i32 int(0.5) == f32 int(0.5) > -i64 int(0.5) > i int(0.5) >= f32 int(0.5) >= i32 int(0.5) >= max(0.5) int(0.5) ^ i32 int(1 % i) int(1 * f32) int(1 * i) int(1 * i32) int(1 ** i) int(1 + 1) int(1 + f32) int(1 + f64) int(1 + i32) int(1 - 0.5) int(1 - f32) int(1 - f64) int(1 - i32) int(1 - i64) int(1 / 0.5) int(1 / 1) int(1 ^ 0.5) int(1 ^ i64) int(1) != i64 int(1) ** f32 int(1) ** i32 int(1) + f32 int(1) + i64 int(1) + reduce(array, #) int(1) - i int(1) < f64 int(1) < i64 * 0.5 int(1) == i32 int(1) ^ f64 int(abs(0.5)) int(abs(1)) int(abs(f64)) int(abs(i)) int(abs(i32)) int(abs(i64)) int(add(1, 1)) int(array[i64]) int(bitnot(1)) int(bitnot(i32)) int(bitnot(i64)) int(bitshl(1, i)) int(bitxor(1, i32) + i) int(bitxor(i32, i)) int(ceil(0.5)) int(ceil(1)) int(ceil(f32)) int(ceil(half(1))) int(ceil(i)) int(ceil(i32)) int(count(array, ok)) int(count(list, false)) int(f32 * 1) int(f32 * i) int(f32 ** 0.5) int(f32 ** i64) int(f32 + f32) int(f32 - 0.5) int(f32 - i64) int(f32 / 0.5) int(f32 / 1) int(f32 / f64) int(f32 / i32) int(f32 / i64) int(f32 ^ f32) int(f32 ^ i32) int(f32) int(f32) != i int(f32) != i64 int(f32) ** f64 int(f32) + i32 int(f32) - f32 int(f32) < i int(f32) <= i32 int(f32) == i ? list : add int(f64 * 0.5) int(f64 ** 1) int(f64 ** i) int(f64 ** i32) int(f64 + 0.5) int(f64 + 1) int(f64 + i) int(f64 - 0.5) int(f64 - f32) int(f64 / 0.5) int(f64 / i64) int(f64 ^ 0.5) int(f64 ^ 1) int(f64 ^ f64) int(f64 ^ i64) int(f64) int(f64) % i64 int(f64) * f64 int(f64) + f64 int(f64) < i32 int(f64) == f32 int(f64) == f64 int(f64) > i int(f64) > i64 int(false ? 0.5 : 0.5) int(false ? i : 0.5) int(findIndex(list, ok)) int(findLastIndex(list, ok)) int(first(array)) int(float(0.5)) int(float(1)) int(float(f32)) int(float(f64)) int(float(i32 ** i)) int(float(i32)) int(floor(f64)) int(floor(i)) int(floor(i32)) int(get(array, i64)) int(half(0.5)) int(half(1)) int(half(f64)) int(i % 1) int(i % i32) int(i % i64) int(i * 0.5) int(i * 1) int(i * f64) int(i ** f32) int(i ** f64) int(i ** i64) int(i + f32) int(i + f64) int(i + i) int(i - 0.5) int(i - f32) int(i - i32) int(i - i64) int(i / 0.5) int(i / 1) int(i / i) int(i / i32) int(i ^ 0.5) int(i ^ 1) int(i ^ i32) int(i) int(i) != i32 int(i) * f64 int(i) * i64 int(i) - i int(i) .. i64 int(i32 * 0.5) int(i32 * 1) int(i32 * i64) int(i32 ** 0.5) int(i32 ** 1) int(i32 + 0.5) int(i32 + 1) int(i32 + f64) int(i32 + i64) int(i32 - 1) int(i32 - i) int(i32 / 0.5) int(i32 / 1) int(i32 / f64) int(i32 ^ 0.5) int(i32 ^ f64) int(i32 ^ i32) int(i32) int(i32) != f32 int(i32) - i int(i32) / f32 int(i32) / i int(i32) / i64 int(i32) < i64 int(i32) > half(0.5) int(i64 * 1) int(i64 ** 0.5) int(i64 ** f64) int(i64 ** i64) int(i64 + i) int(i64 + i32) int(i64 - 0.5) int(i64 - f32) int(i64 - i) int(i64 - i64) int(i64 / 1) int(i64 ^ f64) int(i64 ^ i32) int(i64 ^ i64) int(i64) int(i64) != i64 int(i64) - i64 int(i64) .. i32 int(i64) / i int(i64) <= i int(i64) == f32 int(i64) > i64 int(i64) ^ i int(int(0.5)) int(int(1)) int(int(f64)) int(len("bar")) int(len(array)) int(max(0.5)) int(max(0.5, i64)) int(max(1)) int(max(f32)) int(max(f64)) int(max(i)) int(max(i64)) int(mean(array)) int(min(0.5)) int(min(1)) int(min(1, i64)) int(min(f32)) int(min(i)) int(min(i32)) int(min(i64)) int(ok ? i : div) int(ok ? i : i64) int(ok ? i64 : list) int(reduce(array, #)) int(reduce(array, f32)) int(reduce(array, i32)) int(reduce(list, 0.5)) int(reduce(list, 1)) int(reduce(list, i64)) int(round(0.5)) int(round(1)) int(round(f32)) int(round(f64)) int(round(i)) int(score(1)) int(score(1, i)) int(score(i)) int(string(1)) int(string(i)) int(string(i32)) int(string(i64)) int(sum(array)) int(toJSON(i)) int(toJSON(i32)) int(toJSON(i64)) int(true ? 1 : foo) int(true ? f64 : greet) join(map(array, "foo")) join(map(list, "foo")) keys(groupBy(array, "foo")) keys(groupBy(array, # ** 0.5)) keys(groupBy(array, #)) keys(groupBy(array, f32 != f64)) keys(groupBy(array, foo)) keys(groupBy(array, i32)) keys(groupBy(array, ok)) keys(groupBy(list, "bar")) keys(groupBy(list, #)) keys(groupBy(list, false)) keys(groupBy(list, i32)) keys({"bar": 1}) keys({"bar": array, "foo": "bar"}) keys({"bar": f32}) keys({"foo": array, "bar": f64}) keys({"foo": array}) last(1 .. 1) last(1 .. i) last([0.5]) last([f32, list]) last([list, list]) last(array) last(array) != int(i64) last(array) + f64 last(array) - f32 last(array) - i64 last(array) .. i32 last(array) / f32 last(array) <= i32 last(array) == f32 last(array) > f32 * i64 last(array) >= f64 last(false ? "foo" : true) last(false ? 0.5 : "bar") last(false ? 1 : foo)?.div last(false ? div : score) last(false ? f64 : false) last(filter(array, false)) last(filter(array, ok)) last(filter(list, true)) last(groupBy(array, foo).Qux) last(groupBy(array, i32).Qux) last(groupBy(list, #).list) last(groupBy(list, #)?.Qux) last(groupBy(list, #)?.ok) last(i32 .. 1) last(i32 .. i64) last(i64 .. 1) last(list) last(list).Bar last(list).Qux last(list).String last(list).String() last(list)?.Bar last(list)?.Qux last(list)?.String last(list)?.String() last(list[1:i64]) last(map(array, #)) last(map(array, 1)) last(map(array, array)) last(map(array, foo)) last(map(array, i)) last(map(list, "foo")) last(map(list, #)) last(map(list, 1)) last(map(list, false)) last(map(list, half)) last(map(list, i32)) last(map(list, i64)) last(map(list, ok)) last(ok ? "bar" : true) last(ok ? "foo" : f64) last(ok ? 0.5 : "foo") last(ok ? 0.5 : list) last(ok ? 1 : add) last(ok ? 1 : half) last(ok ? array : array) last(ok ? array : ok) last(ok ? f32 : 0.5) last(ok ? greet : 1) last(ok ? i32 : array) last(ok ? i64 : add) last(ok ? ok : 0.5) last(reduce(array, list)) last(reduce(list, array)) last(sort(array)) last(true ? "bar" : half) last(true ? add : list) last(true ? foo : 1) last(true ? greet : true) last(true ? ok : 1) len("bar") ** i64 len("bar") + i64 - i64 len("bar") / i64 len("bar") >= i len("bar") in array len("foo") ** i32 len("foo") ** i64 len("foo") - i len("foo") - i32 len("foo") >= i len(1 .. 1) len([f32]) len([foo]) len([half]) len(array) len(array) != f32 len(array) + i64 len(array) < f64 len(array) <= i32 len(array) == f32 len(array) >= f64 len(array) ^ i32 len(array) not in array len(filter(list, false)) len(filter(list, ok)) len(foo.Bar) len(foo.String()) len(foo?.Bar) len(foo?.Qux("bar")) len(foo?.String()) len(greet("bar")) len(greet("foo")) len(groupBy(array, #)) len(groupBy(array, 0.5)) len(groupBy(array, f32)) len(groupBy(array, false)) len(groupBy(array, i64)) len(groupBy(array, true)) len(groupBy(list, #)) len(groupBy(list, #).ok) len(groupBy(list, 0.5)) len(groupBy(list, false)) len(groupBy(list, foo).list) len(groupBy(list, i32)) len(groupBy(list, i64)) len(i64 .. 1) len(i64 .. i) len(list) len(list) % i32 len(list) % i64 len(list) .. i64 len(list) / i32 len(list) <= i len(list) > i len(list) ^ f64 len(list[1:i]) len(lower("bar")) len(lower("foo")) len(map(array, "bar")) len(map(array, #)) len(map(array, add)) len(map(array, f32)) len(map(array, greet)) len(map(array, i)) len(map(array, list)[i64]) len(map(array, score)) len(map(list, #)) len(map(list, 1)) len(map(list, f32)) len(map(list, f64)) len(map(list, foo)) len(map(list, i64)) len(map(list, ok)) len(map(list, true)) len(ok ? list : score) len(sort(array)) len(string("bar")) len(string("foo")) len(string(0.5)) len(string(1)) len(string(add)) len(string(f64)) len(string(foo)) len(string(half)) len(string(i)) len(string(i32)) len(string(i64)) len(string(list)) len(string(nil)) len(string(score)) len(string(string(list))) len(toJSON("bar")) len(toJSON("foo")) len(toJSON(0.5)) len(toJSON(1)) len(toJSON(array)) len(toJSON(f32)) len(toJSON(false)) len(toJSON(i)) len(toJSON(i32)) len(toJSON(list)) len(toJSON(nil)) len(toJSON(ok)) len(toJSON(true)) len(trim("foo")) len(trimPrefix("foo")) len(trimSuffix("bar")) len(type("foo")) len(type(0.5)) len(type(1)) len(type(add)) len(type(array)) len(type(div)) len(type(half)) len(type(i)) len(type(i32)) len(type(i64)) len(type(list)) len(type(nil)) len(type(ok)) len(type(score)) len(upper("bar")) len(upper("foo")) len({"bar": array}) len({"bar": f64}) len({"bar": score}) len({"foo": 1}) len({"foo": add, "foo": "foo"}) len({"foo": i64}) list list != 1 .. 1 list != ["foo"] list != [i, 0.5] list != [i] list != array list != filter(array, ok) list != filter(array, true) list != list list != list ? 0.5 : div list != list ? half : div list != map(array, #) list != map(list, 1) list != map(list, i64) list != nil && i32 <= 1 list != nil ? false : 1 list != nil ? i : 1 list != sort(array) list == [div, nil] list == [i] list == array list == array == nil list == list list == list != false list == list ? i32 : i list == map(list, #) list == nil && ok list == nil ? nil : "foo" list == nil or f64 == f64 list not in groupBy(list, #).i list[-1] list[-i32] list[-i64] list[-i] list[1 - 1] list[1] not in list list[1].Bar list[1].Qux list[1].String list[1].String() list[1]?.Bar list[1]?.Qux list[1]?.String list[1]?.String() list[bitnot(i)] list[bitshr(i32, i32)] list[findIndex(array, true)] list[first(array)] list[i * i64] list[i32:i32] list[i32:i] list[i32] list[i32] in list list[i32].Bar list[i32].Qux list[i32].String list[i32]?.Bar list[i32]?.Qux list[i32]?.String list[i32]?.String() list[i64:i32 - i] list[i64:i64] list[i64] list[i64] in list list[i64].Bar list[i64].Qux list[i64].String list[i64]?.Bar list[i64]?.Qux list[i64]?.String list[i:i32] list[i:i64] list[i:i64] == nil != nil list[i:i] list[i] list[i].Bar list[i].Qux list[i].String list[i].String() list[i]?.Bar list[i]?.Qux list[i]?.String list[i]?.String() list[int(f32)] list[int(f64)] list[int(i)] list[int(i64)] list[max(i64, 1)] list[min(i)] list[min(i32)] list[ok ? 1 : half] list[score(1)] list[score(i)] lower("bar" + "bar") lower("bar") == trimSuffix("bar") lower("foo" + "bar") lower(false ? foo : "bar") lower(foo.Bar) lower(foo.String()) lower(foo?.Bar) lower(foo?.String()) lower(greet("bar")) lower(greet("foo")) lower(lower("bar")) lower(lower("foo")) lower(reduce(array, "bar")) lower(reduce(list, "bar")) lower(string("foo")) lower(string(0.5)) lower(string(add)) lower(string(f32)) lower(string(f64)) lower(string(foo)) lower(string(greet)) lower(string(i)) lower(string(i32)) lower(string(i64)) lower(string(list)) lower(string(nil)) lower(string(score)) lower(toBase64("foo")) lower(toBase64(string(i))) lower(toJSON("bar")) lower(toJSON("foo")) lower(toJSON(0.5)) lower(toJSON(1)) lower(toJSON(f64)) lower(toJSON(foo)) lower(toJSON(list)) lower(toJSON(nil)) lower(toJSON(ok)) lower(toJSON(true)) lower(trim("bar")) lower(trim("foo")) lower(trimPrefix("bar")) lower(trimPrefix("foo")) lower(trimSuffix("bar")) lower(type("bar")) lower(type("foo")) lower(type(0.5)) lower(type(1)) lower(type(add)) lower(type(div)) lower(type(f32)) lower(type(half)) lower(type(i)) lower(type(i32)) lower(type(i64)) lower(type(list)) lower(type(ok)) lower(type(true)) lower(upper("bar")) lower(upper("foo")) map(1 .. 1, f32) map(1 .. 1, foo) map(1 .. 1, score) map(1 .. i, foo) map(1 .. i32, #) map(1 .. i32, 0.5 / f64) map(1 .. i32, div) map(1 .. i32, reduce(array, #)) map(1 .. i64, # ^ #) map(1 .. i64, #) map(1 .. i64, half) map(1 .. i64, i32) map([f64], half) map([false], ok) map([half], #) map([i * i32], score) map([i32, foo, score], #) map([i32], foo) map([i32], greet) map([i32], half) map([list, 1, foo], i32) map([nil], foo) map([score, "bar"], f32) map([true, i32, 1], #) map(array, !(# == #)) map(array, !(nil in list)) map(array, !ok) map(array, "bar" in foo) map(array, "foo" not endsWith "bar") map(array, "foo") == array map(array, # != #) map(array, # != 0.5) map(array, # != 1) map(array, # != f64) map(array, # != i32) map(array, # != nil) map(array, # % #) map(array, # % 1) map(array, # % i) map(array, # % i64) map(array, # * #) map(array, # * 0.5) map(array, # * 1) map(array, # * f32) map(array, # * f64) map(array, # * i) map(array, # ** #) map(array, # ** 1) map(array, # ** f32) map(array, # ** i) map(array, # ** i64) map(array, # + #) map(array, # + 0.5) map(array, # + 1) map(array, # + f32) map(array, # + i) map(array, # + i32) map(array, # - #) map(array, # - 0.5) map(array, # - 1) map(array, # - f32) map(array, # - f64) map(array, # - i) map(array, # - i32) map(array, # .. #) map(array, # .. 1) map(array, # / #) map(array, # / 0.5) map(array, # / 1) map(array, # / f32) map(array, # / f64) map(array, # / i) map(array, # / i64) map(array, # < #) map(array, # < 1) map(array, # < f32) map(array, # < i32) map(array, # < i64) map(array, # <= #) map(array, # <= f32) map(array, # <= i) map(array, # <= i32) map(array, # == #) map(array, # == f32) map(array, # == f64) map(array, # == nil) map(array, # > #) map(array, # > 0.5) map(array, # > 1) map(array, # > f32) map(array, # > f64) map(array, # >= #) map(array, # >= 1) map(array, # >= f32) map(array, # >= i32) map(array, # >= i64) map(array, # ^ #) map(array, # ^ 0.5) map(array, # ^ 1) map(array, # ^ i) map(array, # ^ i32) map(array, # not in array) map(array, #) map(array, #) != array map(array, #) != list map(array, #) == array map(array, #) == list map(array, #)[i64] map(array, #)[i] map(array, -#) map(array, --#) map(array, -0.5) map(array, -1) map(array, -f64) map(array, -i) map(array, -i32) map(array, -i64) map(array, 0.5 != #) map(array, 0.5 != 0.5) map(array, 0.5 * #) map(array, 0.5 * f64) map(array, 0.5 ** f32) map(array, 0.5 ** i64) map(array, 0.5 + #) map(array, 0.5 + 1) map(array, 0.5 - #) map(array, 0.5 - 0.5) map(array, 0.5 / i) map(array, 0.5 < #) map(array, 0.5 < i32) map(array, 0.5 > #) map(array, 0.5 > i64) map(array, 0.5 >= #) map(array, 0.5 ^ #) map(array, 0.5)[i] map(array, 1 != #) map(array, 1 != f32) map(array, 1 % #) map(array, 1 ** #) map(array, 1 ** i) map(array, 1 ** i64) map(array, 1 + #) map(array, 1 + f64) map(array, 1 - #) map(array, 1 .. #) map(array, 1 / #) map(array, 1 / i32) map(array, 1 < #) map(array, 1 <= #) map(array, 1 <= 1) map(array, 1 <= f32) map(array, 1 == #) map(array, 1 ^ #) map(array, abs(#)) map(array, abs(i64)) map(array, add == nil) map(array, add(#, #)) map(array, add(#, i)) map(array, add) map(array, array) map(array, array)[bitnot(i32)] map(array, array)[i64] map(array, array[#:#]) map(array, bitand(#, 1)) map(array, bitnand(#, 1)) map(array, bitnot(#)) map(array, bitnot(1)) map(array, bitshl(#, #)) map(array, bitshr(#, #)) map(array, bitshr(#, i64)) map(array, bitushr(1, #)) map(array, ceil(#)) map(array, ceil(0.5)) map(array, ceil(f32)) map(array, div(#, #)) map(array, div) map(array, f32 * #) map(array, f32 * f64) map(array, f32 ** #) map(array, f32 + #) map(array, f32 / #) map(array, f32 < #) map(array, f32 == #) map(array, f32 > #) map(array, f32 >= #) map(array, f32 >= i) map(array, f32 ^ #) map(array, f32) map(array, f32)[min(i32)] map(array, f64 != #) map(array, f64 != 0.5) map(array, f64 * #) map(array, f64 ** #) map(array, f64 ** 0.5) map(array, f64 / #) map(array, f64 < #) map(array, f64 < f64) map(array, f64 <= #) map(array, f64 == #) map(array, f64 >= #) map(array, f64 >= i32) map(array, f64 ^ #) map(array, f64) map(array, false && false) map(array, false ? # : f64) map(array, false ? greet : i) map(array, false)[i32] map(array, find(array, true)) map(array, findIndex(list, ok)) map(array, float(# + #)) map(array, float(#)) map(array, floor(#)) map(array, foo == foo) map(array, foo) map(array, foo.Bar) map(array, foo.Qux) map(array, foo.String()) map(array, foo.String) map(array, foo?.Bar) map(array, foo?.String) map(array, get(array, #)) map(array, greet("bar")) map(array, greet("foo")) map(array, greet) map(array, groupBy(array, #)) map(array, groupBy(array, f32)) map(array, groupBy(list, #)) map(array, groupBy(list, f64)) map(array, groupBy(list, i)) map(array, half != half) map(array, half != nil) map(array, half(0.5)) map(array, half(1)) map(array, half(f64)) map(array, half(i - 0.5)) map(array, half) map(array, i % #) map(array, i + #) map(array, i - i32) map(array, i / 0.5) map(array, i <= #) map(array, i <= f32) map(array, i <= f64) map(array, i == #) map(array, i == f64) map(array, i > i32) map(array, i >= #) map(array, i) map(array, i)[i] map(array, i32 * #) map(array, i32 ** #) map(array, i32 ** f64) map(array, i32 / f32) map(array, i32 < #) map(array, i32 < f64) map(array, i32 == #) map(array, i32 == 1) map(array, i32 > #) map(array, i32 ^ #) map(array, i32 not in array) map(array, i32) map(array, i32) == array map(array, i32) == list map(array, i64 != #) map(array, i64 % #) map(array, i64 * #) map(array, i64 * 0.5) map(array, i64 + 0.5) map(array, i64 - #) map(array, i64 .. #) map(array, i64 < #) map(array, i64 <= #) map(array, i64 <= f64) map(array, i64 <= i64) map(array, i64 > #) map(array, i64) map(array, int(#)) map(array, int(0.5)) map(array, len("foo")) map(array, list != array) map(array, list) map(array, map(array, f64)) map(array, map(list, greet)) map(array, max(#)) map(array, max(f32, 1)) map(array, max(f64)) map(array, mean(array)) map(array, min(#, #)) map(array, nil == #) map(array, nil == ok) map(array, nil not in list) map(array, not ok) map(array, not true) map(array, ok || ok) map(array, ok) map(array, ok)[i64] map(array, reduce(array, "bar")) map(array, reduce(array, #)) map(array, reduce(list, add)) map(array, reduce(list, half)) map(array, round(#)) map(array, score(#)) map(array, score(#, #)) map(array, score(1)) map(array, score) map(array, string(add)) map(array, string(foo)) map(array, string(i64)) map(array, take(array, #)) map(array, toBase64("foo")) map(array, toJSON(#)) map(array, toJSON(foo)) map(array, toJSON(list)) map(array, true != nil) map(array, true ? 0.5 : #) map(array, true ? 0.5 : 1) map(array, true ? f32 : div) map(array, true ? i : true) map(array, type(#)) map(array, type(f32)) map(array[1:i32], list) map(false ? i32 : list, ok) map(filter(array, false), foo) map(filter(array, ok), 1 * #) map(filter(list, # != #), #) map(filter(list, false), #) map(filter(list, ok), #) map(filter(list, ok), i) map(filter(list, true), i64) map(groupBy(array, #).String, i32) map(groupBy(array, #).greet, foo.Qux(.f32)) map(groupBy(array, #).greet, score) map(groupBy(array, #).score, #?.list()) map(groupBy(list, i32).i, #) map(i .. 1, -#) map(i .. 1, 0.5 ^ #) map(i .. 1, f32) map(i .. 1, i) map(i .. i, add(#, #)) map(i .. i, div) map(i .. i, i32) map(i .. i32, half) map(i .. i64, min(#, #, #)) map(i32 .. 1, half) map(i32 .. i, f32) map(i32 .. i32, array) map(i32 .. i64, div) map(i32 .. i64, list) map(i64 .. 1, #) map(i64 .. 1, 1 ^ #) map(i64 .. 1, array) map(i64 .. 1, f32) map(i64 .. 1, f64) map(i64 .. i32, #) map(i64 .. i64, # - #) map(i64 .. i64, #) map(list, !false) map(list, !ok) map(list, "bar" not matches "foo") map(list, "bar") != list map(list, "bar")[i64] map(list, "foo" not in foo) map(list, "foo" not matches #.Bar) map(list, # != #) map(list, # != nil) map(list, # == #) map(list, # in list) map(list, #) map(list, #) != array map(list, #) == list map(list, #)[i64] map(list, #)[i] map(list, #?.Bar) map(list, #?.Qux) map(list, #?.String()) map(list, #?.String) map(list, -0.5) map(list, -f32) map(list, -i) map(list, -i32) map(list, .Bar) map(list, .Qux) map(list, .String()) map(list, .String) map(list, 0.5 != 0.5) map(list, 0.5 != i64) map(list, 0.5 + i64) map(list, 0.5 - 0.5) map(list, 0.5 <= 0.5) map(list, 0.5 == i32) map(list, 0.5 in array) map(list, 0.5) != array map(list, 0.5) == array map(list, 1 % i) map(list, 1 ** 0.5) map(list, 1 ** f32) map(list, 1 + 1) map(list, 1 / f64) map(list, 1 / i64) map(list, 1 < 0.5) map(list, 1 <= i32) map(list, 1 ^ i32) map(list, [#]) map(list, [foo, 0.5, #]) map(list, [score]) map(list, abs(f32)) map(list, add) map(list, array) map(list, ceil(0.5)) map(list, count(array, true)) map(list, div) map(list, f32 != i32) map(list, f32 ** 1) map(list, f32 + i64) map(list, f32 < f32) map(list, f32 == 0.5) map(list, f32 > i64) map(list, f32 >= i) map(list, f32 >= i32) map(list, f32 ^ i) map(list, f32) map(list, f64 < 0.5) map(list, f64 < f32) map(list, f64 <= 1) map(list, f64 > 1) map(list, f64 >= 0.5) map(list, f64 >= f32) map(list, f64) map(list, f64)[i] map(list, false ? # : list) map(list, false) != array map(list, float(f64)) map(list, float(i)) map(list, float(i32)) map(list, foo == #) map(list, foo) map(list, foo.Qux) map(list, foo.String()) map(list, foo?.String) map(list, greet) map(list, groupBy(array, #)) map(list, groupBy(array, i)) map(list, groupBy(list, #)) map(list, half(0.5)) map(list, half(f64)) map(list, half) map(list, i ** 1) map(list, i + i64) map(list, i .. i) map(list, i < 0.5) map(list, i == 1) map(list, i) map(list, i)[i64] map(list, i32 % i64) map(list, i32 ** 0.5) map(list, i32 + f32) map(list, i32 - i32) map(list, i32 / f64) map(list, i32 < 1) map(list, i32 < i32) map(list, i32 <= 1) map(list, i32 >= 1) map(list, i32) map(list, i64 * i) map(list, i64 + i64) map(list, i64 <= i64) map(list, i64 == nil) map(list, i64) map(list, i64)[i64] map(list, i64)[i] map(list, last(array)) map(list, list) map(list, list)[i] map(list, map(array, #)) map(list, map(array, 1)) map(list, map(array, div)) map(list, map(array, i64)) map(list, map(list, "foo")) map(list, max(f32)) map(list, min(0.5)) map(list, min(f64)) map(list, nil != #) map(list, nil != i64) map(list, nil == #) map(list, nil == ok) map(list, nil not in list) map(list, none(array, true)) map(list, not ok) map(list, ok ? # : #) map(list, ok || ok) map(list, ok) map(list, reduce(array, half)) map(list, reduce(list, foo)) map(list, reduce(list, half)) map(list, score(1)) map(list, score) map(list, score)[i64] map(list, string(#)) map(list, string(1)) map(list, string(add)) map(list, string(i32)) map(list, toJSON(#)) map(list, toJSON([#])) map(list, toJSON(false)) map(list, toJSON(ok)) map(list, true ? i : f32) map(list, true ? i32 : #) map(list, true ? list : div) map(list, true)[i32] map(list, type("bar")) map(list, type(#)) map(list, type(i32)) map(list, type(true)) map(list[i64:i32], greet) map(map(array, #), # - i32) map(map(array, #), # == #) map(map(array, #), # >= #) map(map(array, #), #) map(map(array, #), add) map(map(array, #), bitand(#, #)) map(map(array, #), foo) map(map(array, #), greet) map(map(array, #), half) map(map(array, #), i % i64) map(map(array, #), i) map(map(array, #), i32) map(map(array, #), i64) map(map(array, #), list) map(map(array, 0.5), #) map(map(array, 0.5), ok) map(map(array, 1), greet) map(map(array, array), i32 ^ i32) map(map(array, array), i64) map(map(array, array), reduce(#, array)) map(map(array, div), i) map(map(array, div), list) map(map(array, f32), #) map(map(array, f32), array) map(map(array, f32), f64) map(map(array, f64), # > #) map(map(array, f64), f64) map(map(array, f64), greet) map(map(array, foo), div) map(map(array, greet), foo) map(map(array, greet), list) map(map(array, half), array) map(map(array, i), #) map(map(array, i32), #) map(map(array, i64), array) map(map(array, i64), f64) map(map(array, list), foo) map(map(array, ok), !#) map(map(array, ok), -f32) map(map(array, true), # != nil) map(map(array, true), i64) map(map(list, #), # != #) map(map(list, #), #) map(map(list, #), #?.Qux) map(map(list, #), .Bar) map(map(list, #), div) map(map(list, #), f32) map(map(list, #), f64) map(map(list, #), greet) map(map(list, #), half) map(map(list, #), list) map(map(list, #), ok) map(map(list, #), score) map(map(list, 0.5), #) map(map(list, 0.5), div) map(map(list, 1), # * #) map(map(list, 1), f32) map(map(list, add), #) map(map(list, add), i) map(map(list, array), f64) map(map(list, array), findIndex(#, ok)) map(map(list, f64), f32) map(map(list, f64), i32) map(map(list, false), 0.5 / f64) map(map(list, foo), #) map(map(list, foo), list) map(map(list, greet), "bar" <= "foo") map(map(list, i64), # >= f64) map(map(list, i64), #) map(map(list, i64), i64) map(map(list, list), #) map(map(list, ok), f64 > i64) map(map(list, ok), foo) map(map(list, true), f64) map(map(list, true), list) map(ok ? "bar" : i64, ok) map(ok ? "bar" : ok, i64) map(ok ? "bar" : score, 1 .. #) map(ok ? array : foo, foo) map(ok ? array : i64, list) map(ok ? list : i64, #) map(ok ? list : list, add) map(reduce(array, array), # <= #) map(reduce(array, array), #) map(reduce(list, array), -i32) map(reduce(list, array), foo) map(reduce(list, array), half) map(reduce(list, list), #) map(sort(array), # / 0.5) map(sort(array), #) map(sort(array), greet) map(split("foo", "bar"), #) map(true ? "foo" : 0.5, # * #) map(true ? array : "foo", f32 + #) map(true ? list : greet, greet) map(true ? list : list, #) max(-0.5) max(-1) max(-f32) max(-f64) max(-findIndex(array, ok)) max(-i) max(-i, f32) max(-i32) max(-i64) max(-reduce(array, #)) max(0.5 * f32) max(0.5 * i) max(0.5 * i64) max(0.5 ** 0.5) max(0.5 ** 1) max(0.5 ** f32) max(0.5 ** f64 ^ reduce(array, f64)) max(0.5 ** i) max(0.5 ** i32) max(0.5 + 1) max(0.5 - 0.5) max(0.5 - f32) max(0.5 - f64) max(0.5 / 0.5) max(0.5 / 1) max(0.5 / f64) max(0.5 / i32) max(0.5 / i64) max(0.5 ^ 0.5) max(0.5 ^ 1) max(0.5 ^ i) max(0.5 ^ i32) max(0.5 ^ i64) max(0.5) != f32 max(0.5) != i max(0.5) + f64 max(0.5) + i max(0.5) - i32 max(0.5) / i64 max(0.5) <= i max(0.5) > f64 max(0.5) > i max(0.5) > i64 max(0.5) >= i64 max(0.5, 0.5) != i max(0.5, i) ** i32 max(1 % 1) max(1 % i64) max(1 * 0.5) max(1 * 1) max(1 * f64) max(1 * i32) max(1 ** 0.5) max(1 ** 1) max(1 ** f32) max(1 ** i64) max(1 + f32) max(1 + i64) max(1 - f32) max(1 - f64) max(1 / 1) max(1 / f32) max(1 / f32, i64) max(1 / f64) max(1 / i) max(1 / i32) max(1 / i64) max(1 ^ 0.5) max(1 ^ 1) max(1 ^ f32) max(1 ^ f64) max(1 ^ i32) max(1 ^ i64) max(1) != 1 ? foo : "bar" max(1) + f32 max(1) - f64 max(1) .. i max(1) / i max(1) == i64 max(1) > f64 max(1) > i32 max(1, i) not in array max(abs(0.5)) max(abs(1)) max(abs(f32)) max(abs(f64)) max(abs(i)) max(abs(i32)) max(add(1, i)) max(array[1]) max(array[i64]) max(bitnand(i32, 1)) max(bitnot(1)) max(bitnot(i)) max(bitnot(i64)) max(bitshr(1, i32)) max(bitxor(1, 1)) max(ceil(0.5), f64 / i64) max(ceil(f32)) max(ceil(i32)) max(f32 * 1) max(f32 * f64) max(f32 * i64) max(f32 ** 1) max(f32 ** f64) max(f32 + 1) max(f32 + f64) max(f32 + i) max(f32 + i64) max(f32 - 1) max(f32 - i64) max(f32 / 0.5) max(f32 / f32) max(f32 ^ 1) max(f32 ^ f32) max(f32 ^ f64) max(f32 ^ i64) max(f32) max(f32) * i64 max(f32) ** i max(f32) + f32 max(f32) + f64 max(f32) - f64 max(f32) / i32 max(f32) < i max(f32) == i max(f32) ^ f32 max(f32, f32) max(f32, f64) max(f32, f64) in array max(f32, i) max(f32, i32) max(f32, i32) ** i64 max(f32, i64) max(f64 * 1) max(f64 * f64) max(f64 ** 0.5) max(f64 ** f64) max(f64 ** i) max(f64 + 1) max(f64 + f32) max(f64 + f64) max(f64 - 0.5) max(f64 - i) max(f64 ^ 0.5) max(f64 ^ 1) max(f64 ^ f32) max(f64 ^ f64) max(f64) max(f64) != f64 max(f64) < i32 max(f64) <= f32 max(f64) == f32 max(f64) == i max(f64) == round(i) max(f64) ^ f32 max(f64) ^ i64 max(f64, f32) max(f64, f32) <= int(f64) max(f64, f64) max(f64, i) max(f64, i) - 1 ^ i max(f64, i) < i max(f64, i) > f64 max(f64, i32) max(f64, i64) max(f64, i64) ^ f32 max(false ? 0.5 : array) max(false ? add : f64) max(false ? div : half) max(false ? div : i64) max(false ? ok : 0.5) max(find(array, false)) max(findIndex(list, false)) max(findIndex(list, ok)) max(findLast(array, false)) max(float(0.5)) max(float(1)) max(float(1), i) max(float(i32)) max(float(i64)) max(float(score(i))) max(floor(0.5)) max(floor(1)) max(floor(f32)) max(floor(i)) max(floor(i32)) max(floor(len(array))) max(get(array, 1)) max(get(array, i)) max(get(array, i32)) max(get(array, i64)) max(half(0.5)) max(half(1)) max(half(1), i64) max(half(f64)) max(i % 1) max(i * 0.5) max(i * f32) max(i * i) max(i * i64) max(i ** f64) max(i ** score(1)) max(i + 1) max(i - 1) max(i - i) max(i - i64) max(i ^ f64) max(i) max(i) != i32 max(i) != i64 max(i) % (i64 + i) max(i) % array[i32] max(i) ** (1 / i32) max(i) + f64 max(i) - i max(i) / f32 max(i) / i max(i) < 0.5 - f64 max(i) < f32 max(i) < i32 max(i) <= f64 max(i) == f64 max(i) >= i max(i, f32) max(i, f64) max(i, i) max(i, i32) max(i, i64) max(i, i64, i32) max(i32 % 1) max(i32 * 0.5) max(i32 * 1) max(i32 * f32) max(i32 * i) max(i32 * i64) max(i32 ** f32) max(i32 ** i) max(i32 ** i32) max(i32 + 0.5) max(i32 + i64) max(i32 - 0.5) max(i32 - 1) max(i32 - f64) max(i32 - i) max(i32 / 1) max(i32 ^ i) max(i32 ^ i, f32) max(i32) max(i32) * i32 max(i32) / f32 max(i32) / i max(i32) <= f32 max(i32) ^ f32 max(i32) in array max(i32, f32) max(i32, f64) max(i32, i) max(i32, i32) max(i32, i64) max(i64 % i) max(i64 * 0.5) max(i64 * i64) max(i64 ** 0.5) max(i64 ** f32) max(i64 ** i64) max(i64 + i) max(i64 + i64) max(i64 - 0.5) max(i64 - 1) max(i64 - f64) max(i64 / f64) max(i64 / i32) max(i64 / i64) max(i64 ^ 0.5) max(i64 ^ 1) max(i64 ^ i) max(i64) max(i64) ** (1 + 1) max(i64) ** f32 max(i64) + i32 max(i64) - i32 max(i64) - i64 max(i64) .. i32 max(i64) < f32 max(i64) >= f32 max(i64) ^ i max(i64, 0.5 + 1) max(i64, 0.5, i64) ** i32 max(i64, f32) max(i64, f64) max(i64, half(1)) max(i64, i) max(i64, i) + i32 max(i64, i32) max(i64, i32) == f64 max(i64, i64) max(int(0.5)) max(int(f32)) max(int(i32)) max(int(i64)) max(len("foo")) max(len(array)) max(len(list)) max(max(0.5)) max(max(0.5, f64)) max(max(1)) max(max(i)) max(max(i32)) max(max(i64)) max(mean(array)) max(median(array)) max(min(0.5, 0.5)) max(min(1)) max(min(1, f64)) max(min(f32, i64, i32)) max(min(i)) max(min(i32)) max(ok ? "foo" : f64) max(ok ? 0.5 : i64) max(ok ? 1 : i) max(ok ? array : true) max(ok ? foo : greet) max(ok ? half : f32) max(ok ? half : list) max(ok ? i : 1) max(ok ? i : nil) max(reduce(array, # % #)) max(reduce(array, #)) max(reduce(array, 1)) max(reduce(array, f32)) max(reduce(array, f64)) max(reduce(list, 0.5)) max(reduce(list, f32), i64) max(reduce(list, i64)) max(round(1)) max(round(f32)) max(round(f64)) max(round(i)) max(round(i32)) max(score(1)) max(score(i), i) max(true ? f32 : f32) max(true ? foo : array) max(true ? greet : 1) max({"bar": list}.String) max({"foo": array}?.f32) max({"foo": half}?.f32) mean(1 .. 1) mean(1 .. i) mean([f64, 0.5]) mean([i]) mean(array) mean(array) * i mean(array) + i mean(array) - min(i) mean(array) / i mean(array) / i64 mean(array) < f32 mean(array) < f64 mean(array) <= i64 mean(array) > f32 mean(array) >= f32 mean(array) >= i64 mean(array) ^ i mean(array) ^ i32 mean(filter(array, true)) mean(groupBy(array, i64).score) mean(i .. 1) mean(i .. i) mean(map(array, #)) mean(map(array, -#)) mean(map(array, f32)) mean(map(array, i)) mean(map(array, i32)) mean(map(list, 1)) mean(map(list, f32)) mean(map(list, i)) mean(map(list, i32)) mean(sort(array)) median(1 .. i) median(array) median(array) != f32 median(array) * 1 * f32 median(array) * i32 median(array) ** i64 median(array) + f32 median(array) >= i32 median(array) ^ i32 median(array) ^ i64 median(array) not in array median(array[1:1]) median(filter(array, ok)) median(groupBy(list, #).i32) median(i .. i) median(i .. i64) median(i64 .. i64) median(map(array, #)) median(map(array, 1)) median(map(list, 0.5)) median(map(list, f32)) median(map(list, i32)) median(reduce(array, array)) median(reduce(list, array)) median(sort(array)) min(-0.5) min(-0.5, i) min(-1) min(-f32) min(-f64) min(-half(0.5)) min(-i) min(-i32) min(-i64) min(0.5 * 0.5) min(0.5 * 1) min(0.5 * f32, i32 ** i32) min(0.5 * f64) min(0.5 * i32) min(0.5 * i64) min(0.5 ** i) min(0.5 ** i64) min(0.5 + f64) min(0.5 + i) min(0.5 + i32) min(0.5 - 0.5) min(0.5 - 1) min(0.5 - f32) min(0.5 - f64) min(0.5 - i) min(0.5 / 0.5) min(0.5 / i64) min(0.5 / i64, i64) min(0.5 ^ 0.5) min(0.5 ^ f32) min(0.5 ^ i) min(0.5 ^ i32) min(0.5) != i64 min(0.5) * i32 min(0.5) ** f64 min(0.5) ** i min(0.5) + f64 ^ i64 min(0.5) - f32 min(0.5) - f64 min(0.5) / i32 min(0.5) < i32 min(0.5) == f32 / f32 min(0.5) == i min(0.5) >= i64 min(0.5) ^ (f32 - i64) min(0.5, 0.5) < f32 + f64 min(1 % 1) min(1 % i) min(1 % i32) min(1 % i64) min(1 * 0.5) min(1 * 1) min(1 * f32) min(1 * i) min(1 * i32) min(1 ** i) min(1 + 0.5) min(1 + 1) min(1 + f32) min(1 + i64) min(1 - 1) min(1 - f64) min(1 - i) min(1 - i32) min(1 - i64) min(1 / 0.5) min(1 / f32) min(1 / i) min(1 / i32) min(1 / i64) min(1 ^ 0.5) min(1 ^ 1) min(1 ^ f32) min(1 ^ i) min(1 ^ i32) min(1 ^ i64) min(1) != i min(1) - i min(1) .. i32 min(1) <= f32 min(1) <= f64 min(1) > i64 min(1) >= i min(1) >= i64 min(1) ^ f64 min(abs(0.5)) min(abs(1)) min(abs(f32)) min(abs(f64)) min(abs(i)) min(abs(i32)) min(array[1]) min(array[i32]) min(array[i]) min(bitnand(1, i32)) min(bitnot(1)) min(bitnot(i)) min(bitnot(i32)) min(bitnot(i32), i64) min(bitnot(i64)) min(ceil(0.5)) min(ceil(1)) min(ceil(f32)) min(ceil(f64)) min(ceil(i)) min(count(array, false)) min(count(list, ok)) min(f32 * 1) min(f32 * i64) min(f32 ** 0.5) min(f32 - 0.5) min(f32 - 1) min(f32 - f64) min(f32 - i) min(f32 - i64) min(f32 / 1) min(f32 / i64) min(f32 ^ i32) min(f32) min(f32) * i64 min(f32) / f64 min(f32) / i32 min(f32) == i min(f32) >= f64 min(f32, -0.5) min(f32, ceil(1)) min(f32, f32) min(f32, f64) min(f32, i) min(f32, i32) min(f32, i64) min(f64 * 1) min(f64 * f64) min(f64 ** f32) min(f64 ** f64) min(f64 + 0.5) min(f64 + f32) min(f64 + i64) min(f64 - 1) min(f64 - i) min(f64 - i32) min(f64 / 0.5) min(f64 / f32) min(f64 / i) min(f64 / i64) min(f64 ^ 1) min(f64) min(f64) * f64 min(f64) * i32 min(f64) / i min(f64) >= f64 min(f64, 0.5 ** i64) min(f64, 0.5) == f64 min(f64, f32) min(f64, f64) min(f64, i) min(f64, i32) min(f64, i64) min(false ? foo : i32) min(false ? greet : f32) min(find(array, false)) min(find(array, ok)) min(findIndex(array, false)) min(findLastIndex(array, i32 > #)) min(findLastIndex(array, ok)) min(findLastIndex(array, true)) min(findLastIndex(list, ok)) min(first(array)) min(float(0.5)) min(float(1)) min(float(f32)) min(float(f64)) min(float(i)) min(float(i64), i) min(floor(0.5)) min(floor(1)) min(floor(f32)) min(floor(i)) min(floor(i32)) min(floor(i64)) min(half(0.5)) min(half(1)) min(half(1), -1) min(half(f64 - 0.5)) min(half(f64)) min(i % 1) min(i % i64) min(i * i) min(i ** 0.5) min(i ** i) min(i + 1) min(i - 0.5) min(i - f64) min(i - i32) min(i / 1) + f64 min(i / f64) min(i ^ f32) min(i ^ f64) min(i ^ i) min(i) min(i) * f32 min(i) ** i64 min(i) / f64 min(i) / i min(i) < f64 min(i) < i32 min(i) >= i32 min(i) ^ f32 min(i, f32) min(i, f32, i) + i32 min(i, f64) min(i, i) min(i, i32) min(i, i64) min(i, last(array)) min(i32 % 1) min(i32 * f32) min(i32 * i) min(i32 ** 0.5) min(i32 ** i32) min(i32 + i32) min(i32 + i64) min(i32 - 0.5) min(i32 - i64) min(i32 / 0.5) min(i32 / f64) min(i32 ^ 0.5) min(i32 ^ f32) min(i32 ^ f64) min(i32 ^ i64) min(i32) min(i32) - i min(i32) .. i32 min(i32) / i min(i32) < i min(i32) <= f32 min(i32) <= i min(i32) > f32 min(i32) > i64 + f64 min(i32) >= i min(i32) ^ f32 min(i32) ^ i64 min(i32, f32) min(i32, f64 * 0.5) min(i32, f64) min(i32, i) min(i32, i32) min(i32, i64) min(i64 % 1) min(i64 * 0.5) min(i64 * 1) min(i64 * bitnot(i64)) min(i64 * i) min(i64 * i32) min(i64 * i64) min(i64 ** 0.5) min(i64 ** f64) min(i64 ** i) min(i64 ** i32) min(i64 + f32) min(i64 - f64) min(i64 - i32) min(i64 / 1) min(i64 / f32) min(i64 / i) min(i64 / i32) min(i64 / i64) min(i64 ^ 0.5) min(i64 ^ 1) min(i64 ^ f64) min(i64 ^ i32) min(i64) min(i64) / f32 min(i64) < i32 min(i64) >= f64 min(i64) not in array min(i64, f32) min(i64, f64) min(i64, i) min(i64, i32) min(i64, i64) min(i64, i64) < i64 min(int(0.5)) min(int(1)) min(int(f32)) min(int(f64)) min(int(i)) min(int(i32)) min(int(i64)) min(last(1 .. 1)) min(last(array)) min(len(array)) min(len(list)) min(max(0.5)) min(max(1, 0.5)) min(max(f32)) min(max(f64)) min(max(i)) min(max(i64, 1)) min(mean(array)) min(min(1)) min(min(1, 1, 1)) min(min(1, i, f32)) min(min(i)) min(min(i32)) min(min(reduce(list, f32))) min(ok ? array : false) min(ok ? f64 : i) min(ok ? half : ok) min(ok ? i : f32) min(ok ? array : score) min(ok ? true : div) min(reduce(array, #)) min(reduce(array, 0.5)) min(reduce(array, 1)) min(reduce(list, 1)) min(round(0.5)) min(round(1)) min(round(f32)) min(round(i32)) min(round(i64)) min(score(1)) min(score(i)) min(sum(array)) min(true ? i : "foo") min(true ? i : i32) min(true ? i64 : "foo") nil != array != nil ? add : half nil != array && ok nil != div == reduce(array, ok) nil != f64 || ok || false nil != false && ok nil != false or i == nil nil != foo and ok nil != foo.Bar nil != foo.Qux nil != foo.String nil != foo.String() nil != foo?.Bar nil != foo?.Qux nil != foo?.String nil != foo?.String() nil != nil ? score : div nil != true || i < 1 nil == "foo" != ok nil == "foo" && 0.5 < f64 nil == 0.5 and reduce(list, true) nil == add && 0.5 >= 0.5 nil == add || f32 >= i64 nil == array and ok nil == array or ok nil == array[i64] nil == div ? f64 : ok nil == false && nil != true nil == false ? i64 : toBase64("bar") nil == foo.Bar nil == foo.Qux nil == foo.String nil == foo.String() nil == foo?.Bar nil == foo?.Qux nil == foo?.String nil == greet ? i : greet("bar") nil == list || f32 == i nil == list[i32] nil == nil and ok nil in array || score == nil nil in list != not false none(1 .. i, # < #) none(1 .. i32, # <= #) none([foo, list, 1 >= i], ok) none([greet], ok) none([true], #) none(array, !(i32 != i32)) none(array, !false) none(array, !true) none(array, "bar" endsWith "foo") none(array, # != #) none(array, # != 0.5) none(array, # != 1) none(array, # != f32) none(array, # != f64) none(array, # != i) none(array, # < #) none(array, # < 0.5) none(array, # < f32) none(array, # < i32) none(array, # < i64) none(array, # <= #) none(array, # <= 0.5) none(array, # <= 1) none(array, # <= f32) none(array, # <= i) none(array, # <= i32) none(array, # <= i64) none(array, # == #) none(array, # == 0.5) none(array, # == f32) none(array, # == i32) none(array, # == i64) none(array, # == nil) none(array, # > #) none(array, # > 0.5) none(array, # > i) none(array, # >= #) none(array, # >= 0.5) none(array, # >= 1) none(array, # >= f32) none(array, # >= f64) none(array, # >= i32) none(array, # >= i64) none(array, # in array) none(array, 0.5 != #) none(array, 0.5 != 1) none(array, 0.5 < #) none(array, 0.5 < i64) none(array, 0.5 <= #) none(array, 0.5 <= 1) none(array, 0.5 <= f64) none(array, 0.5 == #) none(array, 0.5 > 0.5) none(array, 0.5 > 1) none(array, 0.5 > f32) none(array, 0.5 >= #) none(array, 0.5 >= 1) none(array, 1 < #) none(array, 1 <= #) none(array, 1 == 1) none(array, 1 > #) none(array, any(array, true)) none(array, f32 != #) none(array, f32 < 0.5) none(array, f32 < 1) none(array, f32 == 1) none(array, f32 > #) none(array, f32 >= #) none(array, f32 >= 1) none(array, f32 >= f32) none(array, f64 != 1) none(array, f64 == #) none(array, f64 > #) none(array, f64 >= #) none(array, i != #) none(array, i < #) none(array, i < f64) none(array, i <= #) none(array, i > #) none(array, i >= #) none(array, i >= 0.5) none(array, i >= i32) none(array, i32 != #) none(array, i32 != i) none(array, i32 != nil) none(array, i32 < #) none(array, i32 > #) none(array, i64 != #) none(array, i64 != 0.5) none(array, i64 > i64) none(array, i64 >= #) none(array, nil != "bar") none(array, nil != #) none(array, nil != false) none(array, nil != greet) none(array, nil == #) none(array, nil == 1) none(array, nil == f32) none(array, nil == greet) none(array, nil == half) none(array, not (# == #)) none(array, not (# >= 1)) none(array, not false) none(array, ok) none(array, reduce(array, true)) none(filter(array, # >= f64), ok) none(groupBy(array, #).f64, # or #.Bar) none(groupBy(list, #).div, ok) none(groupBy(list, #).greet, #) none(groupBy(list, 0.5).i, ok) none(i .. i, ok) none(i .. i32, # <= #) none(list, !false) none(list, !ok) none(list, "bar" contains "bar") none(list, # != #) none(list, # != foo) none(list, # != nil) none(list, # == #) none(list, # == foo) none(list, # in list) none(list, # not in list) none(list, (0.5 not in array) || ok) none(list, 0.5 != i32) none(list, 0.5 > f64) none(list, 0.5 > i) none(list, 1 != i64) none(list, 1 != nil) none(list, 1 == f32) none(list, 1 > 0.5) none(list, all(array, ok)) none(list, f32 != 1 ** f64) none(list, f32 >= 0.5) none(list, f32 in array) none(list, f32 not in array) none(list, f64 <= i32) none(list, f64 >= 1) none(list, false) ? ok : half none(list, false) || ok none(list, foo != #) none(list, foo == foo) none(list, i != i) none(list, i != i64) none(list, i >= f32) none(list, i32 == f32) none(list, i32 > 1) none(list, i32 > i64) none(list, i32 not in array) none(list, i64 != 0.5) none(list, i64 > i64) none(list, nil != #) none(list, nil != greet) none(list, nil != i64) none(list, nil == #) none(list, nil == list) none(list, not false) none(list, ok) none(list, one(array, true)) none(list, true && ok) none(list, true) and ok none(map(array, #), ok) none(map(array, div), # != #) none(map(array, f64 == #), ok) none(map(list, "bar"), # endsWith #) none(map(list, #), nil == list) none(map(list, #), ok) none(map(list, 1), i > #) none(map(list, ok), # ? true : #) none(map(list, ok), #) none(map(list, score), ok) none(sort(filter(array, false)), #?.div > greet(#)) not !(0.5 != i64) not !(i < 1) not !(i >= 0.5) not !(i32 != i32) not !(nil != false) not !false not !not false not !ok not !true not ("bar" != "bar") not ("bar" != "foo") not ("bar" != nil) not ("bar" < "bar") not ("bar" < "foo") not ("bar" <= "bar") not ("bar" <= "foo") not ("bar" == "bar") not ("bar" == "foo") not ("bar" == nil) not ("bar" > "bar") not ("bar" > "foo") not ("bar" >= "bar") not ("bar" >= "foo") not ("bar" contains "bar") not ("bar" contains "foo") not ("bar" endsWith "bar") not ("bar" endsWith "foo") not ("bar" in foo) not ("bar" matches "bar") not ("bar" matches "foo") not ("bar" not contains "bar") not ("bar" not contains "foo") not ("bar" not endsWith "bar") not ("bar" not endsWith "foo") not ("bar" not in foo) not ("bar" not matches "bar") not ("bar" not matches "foo") not ("bar" not startsWith "bar") not ("bar" not startsWith "foo") not ("bar" startsWith "bar") not ("bar" startsWith "foo") not ("foo" != "bar") not ("foo" != "foo") not ("foo" != nil) not ("foo" < "bar") not ("foo" < "foo") not ("foo" <= "bar") not ("foo" <= "foo") not ("foo" == "bar") not ("foo" == "foo") not ("foo" == nil) not ("foo" > "bar") not ("foo" > "foo") not ("foo" >= "bar") not ("foo" >= "foo") not ("foo" contains "bar") not ("foo" contains "foo") not ("foo" endsWith "bar") not ("foo" endsWith "foo") not ("foo" in foo) not ("foo" matches "bar") not ("foo" matches "foo") not ("foo" not contains "bar") not ("foo" not contains "foo") not ("foo" not endsWith "bar") not ("foo" not endsWith "foo") not ("foo" not in foo) not ("foo" not matches "foo") not ("foo" not startsWith "foo") not ("foo" startsWith "bar") not ("foo" startsWith "foo") not (0.5 != 0.5) not (0.5 != 1) not (0.5 != f32) not (0.5 != f64) not (0.5 != i) not (0.5 != i32) not (0.5 != i64) not (0.5 != nil) not (0.5 < 0.5) not (0.5 < 1) not (0.5 < f32) not (0.5 < f64) not (0.5 < i) not (0.5 < i32) not (0.5 < i64) not (0.5 <= 0.5) not (0.5 <= 1) not (0.5 <= f32) not (0.5 <= f64) not (0.5 <= i) not (0.5 <= i32) not (0.5 <= i64) not (0.5 == 0.5) not (0.5 == 1) not (0.5 == f32) not (0.5 == f64) not (0.5 == i && i32 != i32) not (0.5 == i) not (0.5 == i32) not (0.5 == i64) not (0.5 == nil) not (0.5 > 0.5) not (0.5 > 1) not (0.5 > f32) not (0.5 > f64) not (0.5 > i) not (0.5 > i32) not (0.5 > i64) not (0.5 >= 0.5) not (0.5 >= 1) not (0.5 >= f32) not (0.5 >= f64) not (0.5 >= i) not (0.5 >= i32) not (0.5 >= i64) not (0.5 in array) not (0.5 not in array) not (1 != 0.5) not (1 != 1) not (1 != f32) not (1 != f64) not (1 != i) not (1 != i32) not (1 != i64) not (1 != nil) not (1 < 0.5) not (1 < 1) not (1 < f32) not (1 < f64) not (1 < i) not (1 < i32) not (1 < i64) not (1 <= 0.5) not (1 <= 1) not (1 <= f32) not (1 <= f64) not (1 <= i) not (1 <= i32) not (1 <= i64) not (1 == 0.5) not (1 == 1) not (1 == f32) not (1 == f64) not (1 == i) not (1 == i32) not (1 == i64) not (1 == nil) not (1 > 0.5) not (1 > 1) not (1 > f32) not (1 > f64) not (1 > i) not (1 > i32) not (1 > i64) not (1 >= 0.5) not (1 >= 1) not (1 >= f32) not (1 >= f64) not (1 >= i) not (1 >= i32) not (1 >= i64) not (1 in array) not (1 not in array) not (add != add) not (add != nil) not (add == div) not (add == nil) not (array != array) not (array != list) not (array != nil) not (array == array) not (array == list) not (array == nil) not (array[i32] > i64) not (div != add) not (div != div) not (div != nil) not (div == add) not (div == div) not (div == nil) not (f32 != 0.5) not (f32 != 1) not (f32 != f32) not (f32 != f64) not (f32 != i) not (f32 != i32) not (f32 != i64) not (f32 != nil) not (f32 < 0.5) not (f32 < 1) not (f32 < f32) not (f32 < f64) not (f32 < i) not (f32 < i32) not (f32 < i64) not (f32 <= 0.5) not (f32 <= 1) not (f32 <= f64) not (f32 <= i) not (f32 <= i32) not (f32 <= i64) not (f32 == 0.5) not (f32 == 1) not (f32 == f32) not (f32 == f64) not (f32 == i) not (f32 == i32) not (f32 == i64) not (f32 == nil) not (f32 > 0.5) not (f32 > 1) not (f32 > f32) not (f32 > f64) not (f32 > i) not (f32 > i32) not (f32 > i64) not (f32 >= 0.5) not (f32 >= 1) not (f32 >= f32) not (f32 >= f64) not (f32 >= i) not (f32 >= i32) not (f32 >= i64) not (f32 in array) not (f32 not in array) not (f64 != 0.5) not (f64 != 1) not (f64 != f32) not (f64 != f64) not (f64 != i) not (f64 != i32) not (f64 != i64) not (f64 != nil) not (f64 < 0.5) not (f64 < 1) not (f64 < f32) not (f64 < f64) not (f64 < i32) not (f64 < i64) not (f64 <= -0.5) not (f64 <= 0.5) not (f64 <= 1) not (f64 <= f32) not (f64 <= f64) not (f64 <= i) not (f64 <= i32) not (f64 <= i64) not (f64 == 0.5) not (f64 == 1) not (f64 == f64) not (f64 == i) not (f64 == i32) not (f64 == i64) not (f64 == nil) not (f64 > 0.5) not (f64 > 1) not (f64 > f32) not (f64 > f64) not (f64 > i) not (f64 > i32) not (f64 > i64) not (f64 >= 0.5) not (f64 >= 1) not (f64 >= f32) not (f64 >= f64) not (f64 >= i) not (f64 >= i32) not (f64 >= i64) not (f64 in array) not (f64 not in array) not (false != false) not (false != nil) not (false != ok) not (false != true) not (false && false) not (false && ok) not (false == nil) not (false == ok) not (false and false) not (false and ok) not (false and true) not (false or false) not (false or ok) not (false or true) not (false || false) not (false || ok) not (false || true) not (findIndex(list, ok) != i ^ f64) not (foo != foo) not (foo != nil) not (foo == foo) not (foo == nil) not (foo in list) not (foo not in list) not (greet != greet) not (greet != nil) not (greet == greet) not (greet == nil) not (half != half) not (half != nil) not (half == half) not (half == nil) not (i != 0.5) not (i != 1) not (i != f32) not (i != f64) not (i != i) not (i != i32) not (i != i64) not (i != nil) not (i < 0.5) not (i < 1) not (i < f32) not (i < f64) not (i < i) not (i < i32) not (i < i64) not (i <= 0.5) not (i <= 1) not (i <= f32) not (i <= f64) not (i <= i) not (i <= i32) not (i <= i64) not (i == 0.5) not (i == 1) not (i == ceil(f64)) not (i == f32) not (i == f64) not (i == i) not (i == i32) not (i == i64) not (i == nil) not (i > 0.5) not (i > 1) not (i > f32) not (i > f64) not (i > i) not (i > i32) not (i > i64) not (i >= 0.5) not (i >= 1) not (i >= f32) not (i >= f64) not (i >= i) not (i >= i32) not (i >= i64) not (i in array) not (i not in array) not (i32 != 0.5) not (i32 != 1) not (i32 != f32) not (i32 != f64) not (i32 != i) not (i32 != i32) not (i32 != i64) not (i32 != nil) not (i32 < 0.5) not (i32 < 1) not (i32 < f32 ** 0.5) not (i32 < f32) not (i32 < f64) not (i32 < i) not (i32 < i32) not (i32 < i64) not (i32 <= 0.5) not (i32 <= 1) not (i32 <= f32) not (i32 <= f64) not (i32 <= i) not (i32 <= i32) not (i32 <= i64) not (i32 == -i) not (i32 == 0.5) not (i32 == 1) not (i32 == f32) not (i32 == f64) not (i32 == i) not (i32 == i32) not (i32 == i64) not (i32 == nil) not (i32 > 0.5) not (i32 > 1) not (i32 > f32) not (i32 > f64) not (i32 > i) not (i32 > i32) not (i32 > i64) not (i32 >= 0.5) not (i32 >= 1) not (i32 >= f32) not (i32 >= f64) not (i32 >= i) not (i32 >= i32) not (i32 >= i64) not (i32 in array) not (i32 not in array) not (i64 != 0.5) not (i64 != 1) not (i64 != f32) not (i64 != f64) not (i64 != i) not (i64 != i32) not (i64 != i64) not (i64 != nil) not (i64 < 0.5) not (i64 < 1) not (i64 < f32) not (i64 < f64) not (i64 < i) not (i64 < i32) not (i64 < i64) not (i64 <= 0.5) not (i64 <= 1) not (i64 <= f32) not (i64 <= f64) not (i64 <= i) not (i64 <= i32) not (i64 <= i64) not (i64 == 0.5) not (i64 == 1) not (i64 == f32) not (i64 == f64) not (i64 == i) not (i64 == i32) not (i64 == i64) not (i64 == nil) not (i64 > 0.5) not (i64 > 1) not (i64 > f32) not (i64 > f64) not (i64 > i) not (i64 > i32) not (i64 > i64) not (i64 >= 0.5) not (i64 >= 1) not (i64 >= f32) not (i64 >= f64) not (i64 >= i) not (i64 >= i32) not (i64 >= i64) not (i64 not in array) not (list != array) not (list != list) not (list != nil) not (list == array) not (list == list) not (list == nil) not (nil != "bar") not (nil != "foo") not (nil != 0.5) not (nil != 1) not (nil != add) not (nil != array) not (nil != div) not (nil != f32) not (nil != f64) not (nil != false) not (nil != foo) not (nil != half) not (nil != i) not (nil != i32) not (nil != i64) not (nil != list) not (nil != nil) not (nil != ok) not (nil != score) not (nil != true) not (nil == "bar") not (nil == "foo") not (nil == 0.5) not (nil == 1) not (nil == add) not (nil == array) not (nil == div) not (nil == f32) not (nil == f64) not (nil == false) not (nil == foo) not (nil == greet) not (nil == half) not (nil == i) not (nil == i32) not (nil == i64) not (nil == list) not (nil == nil) not (nil == ok) not (nil == score) not (nil == true) not (nil in array) not (nil in list) not (nil not in array) not (nil not in list) not (ok != nil) not (ok != ok) not (ok != true) not (ok && false) not (ok && ok) not (ok && true) not (ok == false) not (ok == nil) not (ok == ok) not (ok == true) not (ok and false) not (ok and ok) not (ok and true) not (ok or false) not (ok or ok) not (ok or true) not (ok || ok) not (ok || true) not (score != nil) not (score != score) not (score == nil) not (score == score) not (true != false) not (true != nil) not (true != ok) not (true != true) not (true && false) not (true && true) not (true == false) not (true == nil) not (true == ok) not (true == true) not (true and false) not (true and ok) not (true and true) not (true or false) not (true or ok) not (true or true) not (true || false) not (true || ok) not (true || true) not all(array, false) not all(array, ok) not all(array, true) not all(list, nil == #) not all(list, ok) not all(list, true) not any(array, false) not any(array, ok) not any(array, true) not any(list, false) not any(list, ok) not any(list, true) not false && nil == f64 not false && ok not false == ok not false ? "foo" : "foo" not false ? 0.5 : "foo" not false ? 0.5 : array not false ? 0.5 : div not false ? 0.5 : foo not false ? 0.5 : i64 not false ? 0.5 : nil not false ? 1 : 0.5 not false ? add : array not false ? array : 0.5 not false ? array : 1 not false ? array : f64 not false ? array : i not false ? array : true not false ? div : 0.5 not false ? div : f64 not false ? f32 : 0.5 not false ? f32 : 1 not false ? f32 : i not false ? f32 : nil not false ? f32 : score not false ? f64 : "foo" not false ? f64 : f64 not false ? false : half not false ? false : list not false ? foo : f64 not false ? greet : 1 not false ? i : "bar" not false ? i : 1 not false ? i : array not false ? i : i not false ? i32 : greet not false ? i64 : list not false ? list : i not false ? list : true not false ? nil : f32 not false ? nil : half not false ? nil : ok not false ? ok : 1 not false ? score : ok not false ? true : f64 not false ? true : nil not false or false == false not false or ok not false || ok not none(array, # > f32) not none(array, false) not none(array, ok) not none(array, true) not none(list, false) not none(list, ok) not none(list, true) not not (f64 <= 1) not not (i32 < i64) not not (i64 >= f64) not not (nil != greet) not not (ok or ok) not not false not not ok not not true not ok not ok != ok not ok && 1 > 0.5 not ok && ok not ok ? "bar" : list not ok ? "foo" : 0.5 not ok ? "foo" : 1 not ok ? 0.5 : "bar" not ok ? 0.5 : 0.5 not ok ? 0.5 : i not ok ? 1 : f64 not ok ? 1 : nil not ok ? add : array not ok ? add : groupBy(array, #) not ok ? array : 1 not ok ? array : f32 not ok ? div : f64 not ok ? f32 : f32 not ok ? f64 : f64 not ok ? f64 : half not ok ? foo : foo not ok ? greet : 0.5 not ok ? half : half not ok ? i : 1 not ok ? i : add not ok ? i32 : 1 not ok ? i32 : i not ok ? i64 : f32 not ok ? i64 : f64 not ok ? nil : "bar" not ok ? nil : 0.5 not ok ? nil : foo not ok ? nil : greet not ok ? nil : i not ok ? ok : false not ok ? ok : list not ok ? score : "foo" not ok ? score : score not ok ? true : 1 not ok ? true : div not ok ? true : half not ok ? true : i64 not ok ? true : nil not ok and "foo" == "foo" not ok and i32 > 0.5 not ok and ok not ok or 1 != i not ok or ok not ok || array == list not ok || ok not one(array, false) not one(array, ok) not one(array, true) not one(list, false) not one(list, ok) not one(list, true) not reduce(array, false) not reduce(array, ok) not reduce(array, true) not reduce(list, false) not reduce(list, ok) not reduce(list, true) not true != ok not true && ok not true == ok not true ? "bar" : array not true ? "bar" : i32 not true ? "foo" : f32 not true ? "foo" : f64 not true ? 0.5 : foo not true ? 0.5 : greet not true ? 0.5 : i not true ? 0.5 : i64 not true ? 1 : f32 not true ? add : i32 not true ? add : ok not true ? array : nil not true ? f32 : 0.5 not true ? f32 : div not true ? f64 : 1 not true ? f64 : array not true ? foo : greet not true ? foo : ok not true ? greet : 1 not true ? greet : i64 not true ? greet : list not true ? greet : true not true ? half : half not true ? i : f64 not true ? i64 : "foo" not true ? i64 : array not true ? i64 : i64 not true ? list : "bar" not true ? list : f64 not true ? list : foo not true ? nil : div not true ? ok : nil not true ? score : f32 not true ? score : score not true ? true : 1 not true and ok ? i : half not true || ok ok ok != !ok ok != (0.5 not in array) ok != false != ok ok != false ? f32 : list ok != nil == nil ok != nil ? f32 : greet ok != nil ? nil : array ok != not ok ok != ok ok != ok ? false : "bar" ok && !false ok && !ok ok && "foo" matches "bar" ok && ("bar" not endsWith "bar") ok && (false || ok) ok && (ok or false) ok && (true || true) ok && 0.5 < 1 ok && 0.5 < f64 ok && 0.5 <= 1 ok && 0.5 == nil ok && 0.5 > i64 ok && 1 != 0.5 ok && 1 != i32 ok && 1 <= 1 ok && 1 <= f64 ok && 1 == 0.5 ok && 1 == nil ok && 1 >= f64 ok && f32 != i ok && f32 >= i64 ok && f64 <= 0.5 ok && false != ok ok && false ? i : list ok && false ? ok : ok ok && i < 0.5 ok && i < i64 ok && i == 0.5 ok && i > f64 ok && i32 > 0.5 ok && i32 >= i64 ok && i64 != i ok && i64 == 0.5 ok && nil != 0.5 ok && nil != 1 ok && nil == ok ok && not false ok && not true ok && ok ok && ok ? nil : div ok && ok and false ok && true != false ok && true && 1 >= i64 ok == !false ok == !true ok == ("bar" not endsWith "foo") ok == (0.5 not in array) ok == (false and ok) ok == (i32 not in array) ok == (nil not in list) ok == false ? f64 : 1 ok == false ? score : 1 ok == nil ? i64 : add ok == nil ? nil : f64 ok == none(array, true) ok == not false ok == ok ok == ok != false ok == true && ok ok ? "bar" : f64 <= f32 ok ? "foo" : foo.Bar ok ? -0.5 : add ok ? -f64 : list ok ? -i32 : i ok ? 0.5 / 0.5 : f64 ok ? 0.5 : i32 >= i64 ok ? 0.5 > 1 : 0.5 * i64 ok ? 1 + i : i32 ok ? 1 / i64 : greet ok ? 1 : foo.Bar ok ? 1 : foo?.Qux ok ? abs(i64) : i64 ok ? add : abs(f32) ok ? add : add ok ? add : array ok ? add : f64 ok ? add : foo ok ? add : foo?.String ok ? add : greet ok ? add : half ok ? add : i ok ? add : i64 ok ? add : list ok ? add : ok ok ? array : array ok ? array : f32 ok ? array : f64 + f64 ok ? array : foo ok ? array : foo.String ok ? array : foo?.String ok ? array : greet ok ? array : i ok ? array : i32 ok ? array : list ok ? array : ok ok ? array : score ok ? div : add ok ? div : array ok ? div : div ok ? div : f64 ok ? div : foo ok ? div : foo.Bar ok ? div : greet ok ? div : half ok ? div : i32 > reduce(array, #) ok ? div : nil == true ok ? div : ok ok ? div : score ok ? f32 != i32 : f32 ok ? f32 ** i64 : score ok ? f32 : -0.5 ok ? f32 : add ok ? f32 : array ok ? f32 : div ok ? f32 : f32 ok ? f32 : f64 ok ? f32 : foo ok ? f32 : half ok ? f32 : i32 ok ? f32 : i64 ok ? f32 : ok ok ? f32 : score ok ? f64 : add ok ? f64 : array ok ? f64 : div ok ? f64 : f64 - f64 ok ? f64 : false != true ok ? f64 : foo ok ? f64 : foo.String ok ? f64 : greet ok ? f64 : i32 ok ? f64 : i32 % i32 ok ? f64 : i32 >= -i64 ok ? f64 : ok ok ? f64 : score ok ? false : foo.Bar ok ? foo : div ok ? foo : f32 ok ? foo : foo ok ? foo : greet ok ? foo : half ok ? foo : i32 ok ? foo : i32 > i32 ok ? foo : i64 ok ? foo : list ok ? foo : ok ok ? foo : score ok ? foo.Qux : ok ok ? greet : 0.5 > i ok ? greet : 1 <= 0.5 ok ? greet : add ok ? greet : div ok ? greet : f32 ok ? greet : f64 ok ? greet : foo ok ? greet : half ok ? greet : i64 ok ? greet : list ok ? greet : map(list, i) ok ? greet : ok ok ? greet : score ok ? half : add ok ? half : f32 ok ? half : f64 ok ? half : foo ok ? half : foo?.Qux ok ? half : greet ok ? half : half ok ? half : list ok ? half : nil in list ok ? half : ok ok ? half : reduce(list, "bar") ok ? half : string(array) ok ? half(1) : add ok ? i : 1 / i64 ok ? i : add ok ? i : array ok ? i : f32 <= 0.5 ok ? i : foo ok ? i : half ok ? i : i ok ? i : i32 ok ? i : i64 ok ? i : list ok ? i : ok ok ? i : score ok ? i32 : 1 - f64 ok ? i32 : add ok ? i32 : div ok ? i32 : f32 ok ? i32 : f32 + 0.5 ok ? i32 : f64 ok ? i32 : foo ok ? i32 : foo.Qux ok ? i32 : greet ok ? i32 : i ok ? i32 : i32 ok ? i32 : i32 + i32 ok ? i32 : list ok ? i32 : ok ok ? i32 : score ok ? i64 : (ok ? list : half) ok ? i64 : div ok ? i64 : f32 ok ? i64 : foo ok ? i64 : foo.String ok ? i64 : half ok ? i64 : i ok ? i64 : i32 ok ? i64 : i64 ok ? i64 : list ok ? i64 : ok ok ? i64 ^ f32 : foo ok ? list : 0.5 * f64 ok ? list : add ok ? list : array ok ? list : div ok ? list : div(i64, 1) ok ? list : f32 ok ? list : foo.String ok ? list : greet ok ? list : half ok ? list : i ok ? list : i - f32 ok ? list : i64 ok ? list : list ok ? list : list != array ok ? list : not ok ok ? list : score ok ? map(list, #) : add ok ? nil : 0.5 <= f64 ok ? nil : foo.Qux ok ? nil : foo?.Bar ok ? not false : i32 ok ? ok : 0.5 ** i32 ok ? ok : add ok ? ok : array ok ? ok : div ok ? ok : f32 ok ? ok : f64 ** int(f64) ok ? ok : foo ok ? ok : foo.String ok ? ok : greet ok ? ok : half ok ? ok : i32 ok ? ok : i64 ok ? ok : list ok ? ok : ok ok ? reduce(array, false) : score ok ? reduce(list, #) : list ok ? score : 1 == i32 ok ? score : div ok ? score : f32 ok ? score : f64 ok ? score : greet ok ? score : half ok ? score : i ok ? score : i32 ok ? score : min(i64) ok ? score : score ok ? score : true == nil ok ? toJSON(i64) : div ok and !ok ok and "bar" < "foo" ok and ("foo" not contains "bar") ok and 1 < i64 ok and 1 == 1 ok and 1 == i64 ok and add == nil ok and f32 != 1 ok and f32 >= 1 ok and greet == greet ok and i == 0.5 ok and i32 < f32 ok and i32 <= i64 ok and i32 > i32 ok and i64 < i32 ok and i64 <= i64 ok and i64 > 1 ok and i64 >= i ok and i64 in array ok and list != nil ok and nil == array ok and nil == nil ok and nil in array ok and nil in list ok and nil not in array ok and not ok ok and not true ok and ok ok and ok && ok ok and true ? f64 : add ok and true ? greet : i ok in groupBy(array, "bar") ok in groupBy(list, #) ok in groupBy(list, i32) ok in {"bar": true}?.greet ok not in groupBy(array, # != i32) ok not in groupBy(array, 0.5) ok not in groupBy(array, f64) ok not in groupBy(list, #)?.f64 ok not in groupBy(list, f64)?.Bar ok or !ok ok or !true ok or "bar" endsWith "foo" ok or 0.5 != f32 ok or 0.5 != nil ok or 0.5 == i ok or 1 != f32 ok or 1 <= 1 ok or 1 <= i ok or div != nil ok or f32 != f32 ok or f32 == 0.5 ok or f32 == f32 ok or f64 <= 1 ok or false ? ok : 1 ok or false and false ok or foo != foo ok or i < 1 ok or i == 0.5 ok or i == f32 ok or i32 < 1 ok or i32 > f64 ok or i64 != i32 ok or i64 > i64 ok or i64 >= 0.5 ok or i64 not in array ok or nil != "foo" ok or nil != f64 ok or nil != foo ok or nil != greet ok or nil != ok ok or nil == div ok or not false ok or not ok ok or ok ok or ok == true ok or true || true ok or {"foo": false}.String ok || !ok ok || (nil not in list) ok || 0.5 < f32 ok || 0.5 > 0.5 ok || 0.5 > 1 ok || 0.5 >= f64 ok || 1 != nil ok || 1 < i32 ok || 1 == i ok || f32 >= 1 ok || f64 < 1 ok || f64 == i ok || f64 > f64 ok || f64 >= i64 ok || false ? half : i64 ok || foo == foo ok || i == i ok || i32 < f32 ok || i32 <= 0.5 ok || i32 == i ok || i32 > 0.5 ok || i32 >= i32 ok || i64 != i32 ok || i64 == 0.5 ok || list == list ok || nil == 0.5 ok || nil == array ok || nil == nil ok || nil not in array ok || not false ok || not ok ok || ok ok || ok ? f64 : i64 ok || ok ? ok : score ok || ok or ok ok || reduce(array, false) ok || true ? add : ok one(1 .. i64, ok) one([div], nil == i32) one([false], i64 != i32) one(array, !(# <= 0.5)) one(array, !false) one(array, !ok) one(array, !true) one(array, "bar" matches "bar") one(array, # != #) one(array, # != 0.5) one(array, # != 1) one(array, # != f32) one(array, # != f64) one(array, # != i) one(array, # != i32) one(array, # != nil) one(array, # / i >= f64) one(array, # < #) one(array, # < 0.5) one(array, # < 1) one(array, # < f32) one(array, # < i64) one(array, # <= #) one(array, # <= 0.5) one(array, # <= 1) one(array, # <= f32) one(array, # <= f64) one(array, # <= i32) one(array, # == #) one(array, # == 0.5) one(array, # == 1) one(array, # == nil) one(array, # > #) one(array, # > f32) one(array, # > f64) one(array, # > i32) one(array, # >= #) one(array, # >= 0.5) one(array, # >= 1) one(array, # >= f64) one(array, 0.5 != #) one(array, 0.5 != i64) one(array, 0.5 < #) one(array, 0.5 < 0.5) one(array, 0.5 <= #) one(array, 0.5 == #) one(array, 0.5 == 0.5) one(array, 0.5 > #) one(array, 0.5 > 1) one(array, 0.5 >= #) one(array, 1 != #) one(array, 1 != i64) one(array, 1 != nil) one(array, 1 < #) one(array, 1 < f64) one(array, 1 <= #) one(array, 1 > 0.5) one(array, 1 >= #) one(array, add == div) one(array, all(array, true)) one(array, f32 <= #) one(array, f32 <= 0.5) one(array, f32 >= #) one(array, f64 < #) one(array, f64 == #) one(array, f64 >= #) one(array, f64 >= 1) one(array, f64 >= i32) one(array, f64 in array) one(array, false || true) one(array, i < #) one(array, i > 0.5) one(array, i > f64) one(array, i32 != #) one(array, i32 < #) one(array, i32 <= #) one(array, i32 > #) one(array, i32 >= #) one(array, i64 != #) one(array, i64 < #) one(array, i64 == #) one(array, i64 == f32) one(array, i64 >= #) one(array, i64 >= f64) one(array, list != array) one(array, nil != #) one(array, nil != i64) one(array, not ok) one(array, ok) one(array, one(list, false)) one(array, true != false) one(array, true == nil) one(array, true) ? greet : add one(array, true) or 1 != nil one(false ? greet : "bar", f64 != #) one(groupBy(array, f64).array, .i(nil).ok) one(groupBy(list, ok).foo, .add?.array) one(i32 .. 1, # == #) one(i32 .. i32, not ok) one(i64 .. 1, # >= 1) one(i64 .. i32, # != #) one(i64 .. i32, # >= #) one(list, !(i64 != 1)) one(list, !false) one(list, !ok) one(list, "foo" < "bar") one(list, "foo" not endsWith "bar") one(list, "foo" not in #) one(list, "foo" startsWith "bar") one(list, # != #) one(list, # != foo) one(list, # == #) one(list, # in list) one(list, # not in list) one(list, 0.5 < 1) one(list, 0.5 <= 0.5) one(list, 0.5 == f64) one(list, 1 > i) one(list, add != nil) one(list, all(array, true)) one(list, any(list, true)) one(list, div != nil) one(list, f32 == nil) one(list, f32 > i) one(list, f32 >= 1) one(list, f64 >= 1) one(list, false == nil) one(list, foo != #) one(list, foo != nil) one(list, foo == #) one(list, greet == nil) one(list, half == nil) one(list, i <= i64) one(list, i > f64) one(list, i > i32) one(list, i32 != f32) one(list, i64 == 1) one(list, nil != #) one(list, nil != half) one(list, nil == #) one(list, nil == f64) one(list, ok or true) one(list, ok) one(list, ok) or 0.5 == nil one(list, score != nil) one(list, true == nil) one(list[i64:i32], i != i) one(map(array, "bar"), not false) one(map(array, #), # != #) one(map(array, #), # >= #) one(map(array, #), i32 == #) one(map(array, 1), ok) one(map(array, div), # == #) one(map(array, f64), # < 0.5) one(map(array, false), #) one(map(array, i), ok) one(map(array, list), ok) one(map(array, true), #) one(map(list, ok), #) one(map(list, score), # != #) one(ok ? "foo" : false, # > #) one(reduce(array, array), ok) one(true ? array : 1, # <= #) reduce(1 .. 1, #) reduce(1 .. 1, f32 >= i) reduce(1 .. i64, array) reduce(1 .. i64, greet) reduce(1 .. i64, half) reduce(["foo"], f32) reduce([0.5], f64) reduce([div, "foo"], i32) reduce([f32, f64], f32) reduce([foo], ok) reduce([i32], list) reduce([i64, half], "bar" not startsWith "foo") reduce([i], # < #) reduce([i], ok) reduce([list], f64) reduce([nil], # in array) reduce(array, !false) reduce(array, "foo" endsWith "foo") reduce(array, "foo") not in foo reduce(array, # != #) reduce(array, # != 1) reduce(array, # != i32) reduce(array, # != nil) reduce(array, # % #) reduce(array, # % i64) reduce(array, # * #) reduce(array, # * 0.5) reduce(array, # * 1) reduce(array, # * f32) reduce(array, # * i) reduce(array, # * i32) reduce(array, # * i64) reduce(array, # ** #) reduce(array, # ** f32) reduce(array, # ** i32) reduce(array, # + #) reduce(array, # + 0.5) reduce(array, # + 1) reduce(array, # + i) reduce(array, # + i64) reduce(array, # - #) reduce(array, # - 0.5) reduce(array, # - 1) reduce(array, # - i) reduce(array, # - i32) reduce(array, # - i64) reduce(array, # .. #) reduce(array, # .. i32) reduce(array, # / #) reduce(array, # / 0.5) reduce(array, # / 1) reduce(array, # / f32) reduce(array, # / i32) reduce(array, # < #) reduce(array, # < 0.5) reduce(array, # < 1) reduce(array, # < i32) reduce(array, # <= #) reduce(array, # <= 0.5) reduce(array, # <= f32) reduce(array, # <= i32) reduce(array, # == #) reduce(array, # == 0.5) reduce(array, # == 1) reduce(array, # == f32) reduce(array, # == i32) reduce(array, # == i64) reduce(array, # == nil) reduce(array, # > #) reduce(array, # > 1) reduce(array, # > f64) reduce(array, # > i) reduce(array, # >= #) reduce(array, # >= f32) reduce(array, # >= f64) reduce(array, # >= i32) reduce(array, # >= i64) reduce(array, # ^ #) reduce(array, # ^ 0.5) reduce(array, # ^ f32) reduce(array, # ^ f64) reduce(array, # ^ i64) reduce(array, # in array) reduce(array, # not in array) reduce(array, #) reduce(array, #) != 0.5 == true reduce(array, #) != 0.5 ? ok : nil reduce(array, #) != f32 reduce(array, #) != i32 reduce(array, #) != i64 reduce(array, #) % i reduce(array, #) % i32 reduce(array, #) % i64 reduce(array, #) * i reduce(array, #) * i32 reduce(array, #) * len("foo") reduce(array, #) ** f64 reduce(array, #) ** min(1, i32) reduce(array, #) + i reduce(array, #) + i64 reduce(array, #) + reduce(array, #) reduce(array, #) - f64 reduce(array, #) - i reduce(array, #) - max(f32) reduce(array, #) .. i reduce(array, #) .. i32 reduce(array, #) .. i64 reduce(array, #) / f32 reduce(array, #) / f64 reduce(array, #) / i32 reduce(array, #) / i64 reduce(array, #) < f32 reduce(array, #) < f32 / 0.5 reduce(array, #) < f64 reduce(array, #) < i reduce(array, #) <= -1 reduce(array, #) <= f32 reduce(array, #) <= f64 reduce(array, #) <= f64 * 0.5 reduce(array, #) <= i reduce(array, #) == f64 reduce(array, #) == i64 reduce(array, #) > i32 reduce(array, #) >= f32 reduce(array, #) >= f64 reduce(array, #) >= i32 reduce(array, #) >= i64 reduce(array, #) ^ f32 ** 0.5 reduce(array, #) ^ i32 reduce(array, #) not in array reduce(array, #) not in map(array, #) reduce(array, (0.5 + #) * f32) reduce(array, -#) reduce(array, -(# - #)) reduce(array, -0.5) reduce(array, -1) reduce(array, -f32) reduce(array, -f64) reduce(array, -i) reduce(array, -i32) reduce(array, -i64) reduce(array, 0.5 != #) reduce(array, 0.5 != 0.5) reduce(array, 0.5 * #) reduce(array, 0.5 ** #) reduce(array, 0.5 ** 1) reduce(array, 0.5 + #) reduce(array, 0.5 - #) reduce(array, 0.5 - i64) reduce(array, 0.5 / #) reduce(array, 0.5 / f32) reduce(array, 0.5 < #) reduce(array, 0.5 < 1) reduce(array, 0.5 <= #) reduce(array, 0.5 <= 1) reduce(array, 0.5 == #) reduce(array, 0.5 == f64) reduce(array, 0.5 == i64) reduce(array, 0.5 > #) reduce(array, 0.5 > 0.5) reduce(array, 0.5 >= 0.5) reduce(array, 0.5 >= 1) reduce(array, 0.5 ^ #) reduce(array, 0.5 ^ 0.5) reduce(array, 0.5) * f32 reduce(array, 0.5) - i reduce(array, 0.5) > i64 ? 1 : 0.5 reduce(array, 1 != #) reduce(array, 1 * f64) reduce(array, 1 ** #) reduce(array, 1 + #) reduce(array, 1 - #) reduce(array, 1 - 1) reduce(array, 1 / i32) reduce(array, 1 < #) reduce(array, 1 >= #) reduce(array, 1 ^ #) reduce(array, 1 ^ 0.5) reduce(array, 1 ^ i32) reduce(array, 1) % i32 reduce(array, 1) ** f32 reduce(array, 1) + f64 reduce(array, 1) / f64 reduce(array, 1) / i32 reduce(array, 1) <= i32 reduce(array, 1) ^ i reduce(array, 1) not in array reduce(array, [#]) reduce(array, abs(#)) reduce(array, abs(f64)) reduce(array, abs(i64)) reduce(array, add(#, #)) reduce(array, add) reduce(array, all(list, ok)) reduce(array, array) reduce(array, array)[i32] reduce(array, array[#:#]) reduce(array, array[i64:#]) reduce(array, bitand(i32, i32)) reduce(array, bitnot(#)) reduce(array, bitor(#, #)) reduce(array, bitshr(#, #)) reduce(array, bitushr(#, #)) reduce(array, ceil(#)) reduce(array, div(#, #)) reduce(array, div) reduce(array, f32 ** #) reduce(array, f32 + #) reduce(array, f32 / #) reduce(array, f32 <= #) reduce(array, f32 == #) reduce(array, f32 == i) reduce(array, f32 >= #) reduce(array, f32 >= 0.5) reduce(array, f32 ^ #) reduce(array, f32 ^ f32) reduce(array, f32 ^ i32) reduce(array, f32) reduce(array, f32) ** (0.5 * f64) reduce(array, f32) <= f32 reduce(array, f32) not in array reduce(array, f64 ** #) reduce(array, f64 + #) reduce(array, f64 + i32) reduce(array, f64 - #) reduce(array, f64 / 1) reduce(array, f64 < #) reduce(array, f64 == #) reduce(array, f64 ^ 1) reduce(array, f64) reduce(array, f64) != i32 reduce(array, f64) * i reduce(array, f64) / f64 reduce(array, f64) <= f32 reduce(array, f64) <= first(array) reduce(array, f64) == i reduce(array, f64) >= i reduce(array, f64) ^ f64 reduce(array, false ? f64 : #) reduce(array, false ? score : #) reduce(array, false) ? i64 : f32 reduce(array, false) || ok reduce(array, findLastIndex(list, false)) reduce(array, findLastIndex(list, reduce(array, true))) reduce(array, float(#)) reduce(array, floor(i64)) reduce(array, foo) reduce(array, foo).Bar reduce(array, foo).Qux reduce(array, foo).String reduce(array, foo).String() reduce(array, foo)?.Bar reduce(array, foo)?.Qux reduce(array, foo)?.String reduce(array, foo)?.String() reduce(array, foo.Bar) reduce(array, foo.String) reduce(array, foo?.String()) reduce(array, foo?.String) reduce(array, get(array, 1)) reduce(array, get(list, #)) reduce(array, greet("bar")) reduce(array, greet) reduce(array, groupBy(array, #)) reduce(array, groupBy(list, #)) reduce(array, groupBy(list, #)?.f32) reduce(array, half(1)) reduce(array, half) reduce(array, i != #) reduce(array, i % #) reduce(array, i * #) reduce(array, i ** f64) reduce(array, i + 0.5) reduce(array, i - #) reduce(array, i / #) reduce(array, i <= #) reduce(array, i <= i64) reduce(array, i > i32) reduce(array, i ^ #) reduce(array, i) reduce(array, i) % i32 reduce(array, i) + i32 reduce(array, i) - f32 reduce(array, i) == 0.5 ** 1 reduce(array, i32 != #) reduce(array, i32 != i32) reduce(array, i32 + 0.5) reduce(array, i32 - #) reduce(array, i32 .. #) reduce(array, i32 < #) reduce(array, i32 < 1) reduce(array, i32 > #) reduce(array, i32 >= #) reduce(array, i32) reduce(array, i32) * 1 * 0.5 reduce(array, i64 != #) reduce(array, i64 % i) reduce(array, i64 % i32) reduce(array, i64 * #) reduce(array, i64 + i32) reduce(array, i64 - #) reduce(array, i64 .. #) reduce(array, i64 .. 1) reduce(array, i64 / f64) reduce(array, i64 <= #) reduce(array, i64 == 1) reduce(array, i64 == nil) reduce(array, i64 ^ #) reduce(array, i64 ^ f64) reduce(array, i64) reduce(array, i64) + i reduce(array, i64) / f64 reduce(array, i64) < i reduce(array, i64) == f32 reduce(array, int(f64)) reduce(array, len(array)) reduce(array, list) reduce(array, list) != map(list, half) reduce(array, map(array, div)) reduce(array, map(array, score)) reduce(array, map(list, 1)) reduce(array, max(#, #, #)) reduce(array, max(0.5)) reduce(array, min(#)) reduce(array, min(#, #, 0.5)) reduce(array, min(0.5)) reduce(array, min(1, 1)) reduce(array, nil != "bar") reduce(array, nil != #) reduce(array, nil != 1) reduce(array, not ok) reduce(array, ok ? "foo" : "bar") reduce(array, ok ? # : array) reduce(array, ok ? # : i) reduce(array, ok || true) reduce(array, ok) reduce(array, ok) and ok reduce(array, reduce(array, 1)) reduce(array, reduce(list, 0.5)) reduce(array, round(0.5)) reduce(array, score(#)) reduce(array, score(1, #)) reduce(array, score) reduce(array, string(0.5)) reduce(array, string(1)) reduce(array, string(foo)) reduce(array, string(i32)) reduce(array, toJSON(i)) reduce(array, trimPrefix("bar")) reduce(array, true && true) reduce(array, true ? add : #) reduce(array, true) != ok reduce(array, true) and ok reduce(array, type(#)) reduce(array, type(1)) reduce(array, type(add)) reduce(array, type(greet)) reduce(array, type(score)) reduce(array, upper("bar")) reduce(false ? 0.5 : "bar", # and false) reduce(false ? i32 : array, toJSON(#)) reduce(false ? nil : list, #) reduce(filter(array, ok), foo) reduce(filter(list, ok), foo.Bar) reduce(filter(list, true), i) reduce(i .. 1, f64) reduce(i .. 1, score) reduce(i .. i, #) reduce(i .. i, foo) reduce(i .. i32, add) reduce(i32 .. 1, #) reduce(i32 .. 1, foo) reduce(i32 .. i, 0.5 - #) reduce(i32 .. i32, i64) reduce(i32 .. i64, abs(f64)) reduce(i64 .. 1, -#) reduce(i64 .. i, #) reduce(i64 .. i, -0.5) reduce(i64 .. i, false ? "bar" : #) reduce(i64 .. i, i) reduce(i64 .. i, ok) reduce(i64 .. i, round(i32)) reduce(i64 .. i64, i64) reduce(list, !true) reduce(list, "bar" <= "bar") reduce(list, "bar" in #) reduce(list, "foo" not in #) reduce(list, # != #) reduce(list, # != foo) reduce(list, # != nil) reduce(list, # == #) reduce(list, # == foo) reduce(list, # == nil) reduce(list, # in list) reduce(list, # not in list) reduce(list, #) reduce(list, #) != foo reduce(list, #) not in groupBy(array, i) reduce(list, #) not in list reduce(list, #).Bar reduce(list, #).Qux reduce(list, #).String reduce(list, #).String() reduce(list, #)?.Bar reduce(list, #)?.Qux reduce(list, #)?.String reduce(list, #)?.String() reduce(list, #?.Bar not in # ? # : #) reduce(list, #?.Bar) reduce(list, #?.Qux("foo")) reduce(list, #?.Qux) reduce(list, #?.String()) reduce(list, #?.String) reduce(list, -0.5) reduce(list, -f64) reduce(list, -i) reduce(list, -i32) reduce(list, .Bar) reduce(list, .Qux) reduce(list, .String()) reduce(list, .String) reduce(list, 0.5 != f64) reduce(list, 0.5 != nil) reduce(list, 0.5 == i64) reduce(list, 0.5 >= 0.5) reduce(list, 0.5) != i reduce(list, 0.5) / i64 reduce(list, 0.5) < f32 reduce(list, 0.5) < i reduce(list, 0.5) < i32 reduce(list, 0.5) < i64 reduce(list, 0.5) <= f32 reduce(list, 0.5) >= f64 reduce(list, 0.5) >= i64 reduce(list, 1 != nil) reduce(list, 1 + f64) reduce(list, 1 - 0.5) reduce(list, 1 / 0.5) reduce(list, 1 < f64) reduce(list, 1 <= 1) reduce(list, 1 == 0.5) reduce(list, 1 == nil) reduce(list, 1 ^ 1) reduce(list, 1) * f64 reduce(list, 1) + f32 reduce(list, 1) - i reduce(list, add) reduce(list, add) != div reduce(list, array != array) reduce(list, array) reduce(list, div) reduce(list, f32 / 0.5) reduce(list, f32 < i32) reduce(list, f32 <= f32) reduce(list, f32) reduce(list, f32) == f32 reduce(list, f64 != nil) reduce(list, f64 + 0.5) reduce(list, f64 + 1) reduce(list, f64 / i32) reduce(list, f64 <= i32) reduce(list, f64 == f32) reduce(list, f64 > f32) reduce(list, f64 >= 0.5) reduce(list, f64) reduce(list, f64) * i64 reduce(list, false == false) reduce(list, false ? "foo" : list) reduce(list, false ? # : #) reduce(list, false || true) reduce(list, filter(list, ok)) reduce(list, findIndex(array, true)) reduce(list, findLastIndex(list, false)) reduce(list, float(i)) reduce(list, floor(0.5)) reduce(list, foo != #) reduce(list, foo) reduce(list, foo) == foo reduce(list, foo).Bar reduce(list, foo).Qux reduce(list, foo).String reduce(list, foo).String() reduce(list, foo)?.Bar reduce(list, foo)?.Qux reduce(list, foo)?.String reduce(list, foo)?.String() reduce(list, foo.Bar) reduce(list, foo.String) reduce(list, foo?.Bar) reduce(list, foo?.Qux) reduce(list, foo?.String) reduce(list, get(list, i)) reduce(list, greet != nil) reduce(list, greet("bar")) reduce(list, greet) reduce(list, groupBy(array, 1)) reduce(list, groupBy(list, "bar")) reduce(list, groupBy(list, #)) reduce(list, half(1)) reduce(list, half) reduce(list, i * i64) reduce(list, i + 1) reduce(list, i - f64) reduce(list, i .. 1) reduce(list, i == 0.5) reduce(list, i > i64) reduce(list, i >= 0.5) reduce(list, i) reduce(list, i) * i64 reduce(list, i) .. 1 % 1 reduce(list, i) .. i reduce(list, i) / f64 reduce(list, i) / i32 reduce(list, i) < f32 reduce(list, i) == f32 reduce(list, i) > f32 reduce(list, i) ^ f32 reduce(list, i32 != nil) reduce(list, i32 - i32) reduce(list, i32 .. 1) reduce(list, i32 / 0.5) reduce(list, i32 < i) reduce(list, i32 <= i) reduce(list, i32 == f64) reduce(list, i32 >= f32) reduce(list, i32) reduce(list, i32) != f64 reduce(list, i32) % i reduce(list, i32) - f32 reduce(list, i32) >= i reduce(list, i64 .. 1) reduce(list, i64 < i64) reduce(list, i64 > i64) reduce(list, i64 >= 0.5) reduce(list, i64) reduce(list, i64) * f64 reduce(list, i64) ** i32 reduce(list, i64) <= i64 reduce(list, int(i64)) reduce(list, len(array)) reduce(list, list != nil) reduce(list, list == nil) reduce(list, list) reduce(list, map(array, "bar")) reduce(list, map(array, #)) reduce(list, map(list, 1)) reduce(list, max(0.5)) reduce(list, max(f32)) reduce(list, min(0.5)) reduce(list, min(1)) reduce(list, min(f32)) reduce(list, nil != #) reduce(list, nil != add) reduce(list, nil != half) reduce(list, nil == #) reduce(list, not false) reduce(list, not ok) reduce(list, not true) reduce(list, ok ? # : #) reduce(list, ok ? # : score) reduce(list, ok ? greet : add) reduce(list, ok ? score : #) reduce(list, ok) reduce(list, reduce(array, ok)) reduce(list, reduce(array, score)) reduce(list, reduce(list, #)) reduce(list, reduce(list, 1)) reduce(list, reduce(list, add)) reduce(list, reduce(list, i32)) reduce(list, score(i)) reduce(list, score) reduce(list, string(greet)) reduce(list, toBase64("bar")) reduce(list, toBase64("foo")) reduce(list, toJSON(array)) reduce(list, toJSON(list)) reduce(list, toJSON(nil)) reduce(list, true == nil) reduce(list, true ? foo : f64) reduce(list, type(#)) reduce(map(array, "bar"), # not endsWith #) reduce(map(array, "bar"), add) reduce(map(array, "foo"), half(f64)) reduce(map(array, #), # != i) reduce(map(array, #), # .. #) reduce(map(array, #), #) reduce(map(array, #), abs(#)) reduce(map(array, #), i) reduce(map(array, #), i32 * #) reduce(map(array, #), not ok) reduce(map(array, 0.5), add) reduce(map(array, 0.5), div) reduce(map(array, 0.5), f32) reduce(map(array, 1), # ^ 0.5) reduce(map(array, 1), #) reduce(map(array, 1), foo) reduce(map(array, add), #) reduce(map(array, add), f32) reduce(map(array, add), list) reduce(map(array, array), f64) reduce(map(array, div), #) reduce(map(array, div), div) reduce(map(array, div), i32 * i) reduce(map(array, f32), f32) reduce(map(array, f32), i) reduce(map(array, f32), i32) reduce(map(array, f64), #) reduce(map(array, f64), f32 < #) reduce(map(array, false), # and true) reduce(map(array, false), f32) reduce(map(array, foo), # == nil) reduce(map(array, i), # / 1) reduce(map(array, i), #) reduce(map(array, i), add) reduce(map(array, i), f64 + 1) reduce(map(array, i32), array) reduce(map(array, i32), list) reduce(map(array, i64), # <= #) reduce(map(array, i64), #) reduce(map(array, list), filter(#, false)) reduce(map(array, ok), i) reduce(map(array, score), i32) reduce(map(list, "bar"), #) reduce(map(list, "foo"), #) reduce(map(list, #), #) reduce(map(list, #), .Qux) reduce(map(list, #), add) reduce(map(list, #), array) reduce(map(list, #), f32) reduce(map(list, #), f64) reduce(map(list, #), half) reduce(map(list, #), i64) reduce(map(list, #), ok) reduce(map(list, 0.5), #) reduce(map(list, 0.5), foo) reduce(map(list, 1), # > #) reduce(map(list, 1), #) reduce(map(list, 1), list) reduce(map(list, array), div) reduce(map(list, div), add) reduce(map(list, f64), #) reduce(map(list, f64), ok) reduce(map(list, false), div) reduce(map(list, greet), #) reduce(map(list, i), #) reduce(map(list, i), [i32]) reduce(map(list, i), f32) reduce(map(list, i), score(#)) reduce(map(list, i32), #) reduce(map(list, i32), foo) reduce(map(list, i64), #) reduce(map(list, i64), i32) reduce(map(list, list), ok) reduce(map(list, score), #) reduce(map(list, score), f64) reduce(map(list, true), #) reduce(map(list, true), add) reduce(map(list, true), half) reduce(ok ? "bar" : i32, #) reduce(ok ? "foo" : list, #) reduce(ok ? array : half, f32) reduce(ok ? list : i, #) reduce(reduce(array, array), f64 != #) reduce(reduce(array, list), get(array, i32)) reduce(reduce(list, array), f64) reduce(sort(array), #) reduce(sort(array), foo) reduce(sort(array), greet) reduce(sort(array), ok) reduce(true ? array : 1, array) reduce(true ? array : array, #) repeat(type(ok), i) round(-0.5) round(-1) round(-f32) round(-f64) round(-i) round(-i32) round(-i64) round(0.5 * 1) round(0.5 * f64) round(0.5 * i32) round(0.5 ** 0.5) round(0.5 ** 1) round(0.5 ** i) round(0.5 ** i32) round(0.5 ** i64) round(0.5 + 1) round(0.5 + f64) round(0.5 + i) round(0.5 + i32) round(0.5 - 0.5) round(0.5 - 1) round(0.5 - i32) round(0.5 / 0.5) round(0.5 / 1) round(0.5 / f64) round(0.5 / i32) round(0.5 ^ f64) round(0.5 ^ i) round(0.5 ^ i64) round(0.5) * f32 round(0.5) ** i32 round(0.5) + -f32 round(0.5) - i64 ^ i round(0.5) < f64 round(0.5) <= i64 round(0.5) == i32 round(0.5) == i64 round(0.5) == max(i, i64) round(0.5) > -1 round(0.5) > i round(0.5) >= i round(0.5) in array round(1 % i) round(1 % i64) round(1 * 0.5) round(1 * f32) round(1 * i64) round(1 ** 0.5) round(1 ** 1) round(1 ** f32) round(1 ** f64) round(1 ** i) round(1 + 0.5) round(1 + 1) round(1 + i64) round(1 - 0.5) round(1 - 1) round(1 - i) round(1 - i32) round(1 - i64) round(1 / 0.5) round(1 / 1) round(1 / f32) round(1 / i) round(1 / i64) round(1 ^ 0.5) round(1 ^ 1) round(1 ^ f32) round(1 ^ i) round(1 ^ i64) round(1) != ceil(i32) round(1) * i32 round(1) + i64 round(1) - i64 round(1) / i32 round(1) / i64 round(1) < i64 round(1) <= i round(1) == i round(1) >= f64 round(1) >= i32 round(1) >= i64 round(1) ^ f64 round(1) not in array round(abs(0.5)) round(abs(1)) round(abs(f64)) round(abs(i)) round(abs(i64)) round(add(1, i)) round(array[1]) round(array[i32]) round(array[i64]) round(bitnot(i)) round(bitnot(i32)) round(bitnot(i64)) round(ceil(1)) round(ceil(f64)) round(ceil(i32)) round(ceil(i64)) round(count(list, true)) round(div(1, 1)) round(f32 * 0.5) round(f32 * 1) round(f32 * f64) round(f32 * i32 ^ f32) round(f32 * i64) round(f32 ** 0.5) round(f32 ** 1) round(f32 + f64) round(f32 + i32) round(f32 - 0.5) round(f32 - i) round(f32 / i32) round(f32 ^ 0.5) round(f32 ^ f32) round(f32 ^ i) round(f32 ^ i64) round(f32) round(f32) * i32 round(f32) - i32 round(f32) / f32 round(f32) == i32 round(f64 * 0.5) round(f64 * i) round(f64 ** 0.5) round(f64 ** 1) round(f64 ** f32) round(f64 ** i) round(f64 + f64) round(f64 + i) round(f64 + i32) round(f64 - 0.5) round(f64 - 1) round(f64 - i32) round(f64 / f64) round(f64 / i) round(f64 / i32) round(f64 / i64) round(f64 ^ 1) round(f64 ^ f64) round(f64) round(f64) * f32 round(f64) ** i32 round(f64) + f64 round(f64) <= f64 round(f64) > i round(f64) > i32 round(f64) >= i64 round(f64) not in array round(false ? f32 : f64) round(false ? f64 : 1) round(false ? nil : 1) round(findIndex(array, # <= #)) round(findIndex(list, ok)) round(findLast(array, ok)) round(findLast(array, true)) round(findLastIndex(array, ok)) round(findLastIndex(list, ok)) round(float(0.5)) round(float(1)) round(float(f32)) round(float(i)) round(floor(0.5)) round(floor(1)) round(floor(f64)) round(floor(i32)) round(floor(i64)) round(get(array, i)) round(get(array, i32)) round(get(array, i64)) round(half(-1)) round(half(0.5)) round(half(1)) round(half(f64)) round(i % i32) round(i % i64) round(i * 1) round(i * f64) round(i * i32) round(i ** 1) round(i ** i64) round(i + 0.5) round(i + 1) round(i + f64) round(i + i) round(i + i32) round(i + i64) round(i - i) round(i - i32) round(i / 1) round(i / i) round(i / i64) round(i ^ 0.5) > f32 round(i ^ 1) round(i ^ f32) round(i) round(i) * f32 round(i) * i round(i) / f64 round(i) < i round(i) < i32 round(i) > i round(i) > i64 != ok round(i) >= f32 round(i) >= i64 round(i) ^ i32 round(i32 % 1) round(i32 * 1) round(i32 ** 1) round(i32 ** f32) round(i32 ** f64) round(i32 + 0.5) round(i32 + 1) round(i32 + i32) round(i32 - 1) round(i32 - f32) round(i32 - f64) round(i32 / 0.5) round(i32 / 1) round(i32 ^ f64) round(i32) round(i32) != i round(i32) * f32 round(i32) ** f64 round(i32) - i round(i32) < i32 round(i32) <= ceil(1) round(i32) <= f64 round(i32) <= i64 round(i32) >= f64 round(i32) >= i32 round(i32) ^ f64 round(i64 % i) round(i64 % i32) round(i64 * 0.5) round(i64 * i) round(i64 ** 1) round(i64 ** f64) round(i64 ** i64) round(i64 + f32) round(i64 - 0.5) round(i64 - 1) round(i64 - i) round(i64 / 0.5) round(i64 / 1) round(i64 ^ 1) round(i64 ^ i32) round(i64 ^ i64) round(i64) round(i64) != f64 round(i64) * i64 round(i64) ** i32 round(i64) - bitnot(1) round(i64) - f32 round(i64) < f64 round(i64) ^ f64 round(int(0.5)) round(int(1)) round(int(f32)) round(int(f64)) round(int(i)) round(int(i32)) round(int(i64)) round(last(array)) round(len("bar")) round(len("foo")) round(len(array)) round(len(list)) round(max(0.5)) round(max(1)) round(max(i)) round(max(i32)) round(max(i64)) round(max(i64, f32)) round(mean(array)) round(median(array)) round(min(0.5)) round(min(1)) round(min(f32)) round(min(f64)) round(min(i32)) round(min(i64)) round(reduce(array, #)) round(reduce(array, 0.5)) round(reduce(array, 1)) round(reduce(array, i64)) round(reduce(list, 0.5)) round(reduce(list, f32)) round(round(0.5)) round(round(1)) round(round(f32)) round(round(f64)) round(round(i)) round(round(i32)) round(round(i64)) round(score(1)) round(score(i)) round(sum(array)) round(true ? i : ok) score score != nil != ok score != nil ? half : f64 score != nil or i32 > 0.5 score != nil || ok score != score score != score != ok score != score ? i32 : i32 score == nil != nil score == nil && ok score == nil ? 0.5 : "bar" score == score score == score == true score == score ? 0.5 : score score in groupBy(list, #)?.array score in sort(array) score(-1) score(-1, i) score(-get(array, i)) score(-i) score(-i, i) score(1 % 1) score(1 % i) score(1 % i32) score(1 % i64) score(1 * 1) score(1 * i) score(1 * i32) score(1 * i64) score(1 + 1) score(1 + i) score(1 + i32) score(1 + i64) score(1 - 1) score(1 - i) score(1 - i32) score(1) != -f32 score(1) != i score(1) != i32 score(1) % -1 score(1) % i score(1) % i64 score(1) * f32 score(1) * i score(1) * i64 score(1) ** i32 score(1) + f64 score(1) + i32 score(1) - f32 score(1) - i score(1) - i32 score(1) - int(0.5) score(1) .. i score(1) .. i32 score(1) .. i64 score(1) .. score(1) score(1) / f32 score(1) / i32 score(1) < i score(1) < i32 score(1) < i64 score(1) < i64 - 0.5 score(1) <= 0.5 * 1 score(1) <= i score(1) <= i64 score(1) == i32 score(1) == i64 score(1) > bitshr(i64, 1) score(1) > f32 score(1) > i64 score(1) >= 0.5 + f64 score(1) >= f32 score(1) >= i score(1) >= sum(array) score(1) ^ f64 score(1) ^ i score(1) ^ i32 score(1) in array score(1) not in groupBy(list, false) score(1, 1) < i score(1, i) < f64 score(1, i) ^ f32 score(abs(1)) score(abs(i)) score(add(1, i)) score(array[1]) score(array[i64]) score(array[i]) score(bitnand(1, i64)) score(bitnand(i64, i32)) score(bitnot(1)) score(bitnot(i)) score(bitnot(i32)) score(bitnot(i64)) score(bitshl(i32, i)) score(bitshr(1, i64)) score(bitshr(i32, i64)) score(bitushr(1, i)) score(count(array, false)) score(count(array, ok)) score(count(array, true)) score(count(list, ok)) score(false ? f64 : 1) score(false ? foo : 1) score(find(array, i != #)) score(find(array, ok)) score(find(array, true)) score(findIndex(array, ok)) score(findIndex(array, true)) score(findIndex(list, true)) score(findLast(array, true)) score(findLastIndex(array, true)) score(findLastIndex(list, ok)) score(findLastIndex(list, true)) score(first(array)) score(get(array, 1)) score(get(array, i)) score(get(array, i32)) score(get(array, i64)) score(i % 1) score(i % i) score(i % i64) score(i * 1 * i) score(i * 1) score(i * i) score(i * i32) score(i * i64) score(i + 1) score(i + i) score(i + i32) score(i - 1) score(i - i) score(i - i32) score(i) score(i) != f32 score(i) != f64 score(i) % i score(i) % i * f64 score(i) * f32 score(i) * i32 score(i) ** (0.5 / 0.5) score(i) ** -0.5 score(i) ** i32 score(i) ** i64 score(i) + f64 score(i) - f64 score(i) - i32 score(i) / i64 score(i) < 1 != ok score(i) < f32 score(i) < f64 / 0.5 score(i) < i32 score(i) < i64 score(i) <= 0.5 / f32 score(i) <= f32 score(i) <= f64 score(i) <= i score(i) <= i32 score(i) == f32 score(i) > f32 score(i) > i score(i) > i64 score(i) >= f32 score(i) >= f64 score(i) >= i score(i) >= i32 score(i) >= i64 score(i) ^ f32 score(i) ^ i32 score(i) ^ i64 score(i) ^ score(1) score(i, 1) + -1 score(i, 1) .. i64 score(i, 1) <= f32 score(i, i) score(i, i) ** f32 score(i32 % 1) score(i32 % i) score(i32 % i32) score(i32 * 1) score(i32 * i) score(i32 * i32) score(i32 * i64) score(i32 + 1) score(i32 + i) score(i32 + i32) score(i32 + i64) score(i32 - 1) score(i32 - i) score(i32 - i32) score(i32 - i64) score(i64 % 1) score(i64 % i) score(i64 % i32) score(i64 % i64) score(i64 * 1) score(i64 * i32) score(i64 * i64) score(i64 + 1) score(i64 + i) score(i64 + i32) score(i64 - 1) score(i64 - i64) score(int(0.5)) score(int(1)) score(int(f32)) score(int(f64)) score(int(float(0.5))) score(int(i)) score(int(i32)) score(int(i64)) score(last(array)) score(len("bar")) score(len("foo")) score(len(array)) score(len(list)) score(max(1)) score(max(1, i32, 0.5)) score(max(i)) score(max(i, i32)) score(min(1)) score(min(i)) score(min(i, i32)) score(ok ? 1 : "bar") score(ok ? 1 : list) score(reduce(array, #)) score(reduce(array, i)) score(reduce(list, 1)) score(reduce(list, i)) score(score(1)) score(score(i)) score(score(i32 + i)) score(sum(array)) sort(1 .. 1) sort(1 .. i) sort([add]) sort([greet]) sort([half]) sort([i64]) sort([list]) sort(array) sort(array) == array sort(false ? greet : array) sort(groupBy(list, #)?.foo) sort(groupBy(list, i32).half) sort(i .. i32) sort(i .. i64) sort(i32 .. 1) sort(i64 .. 1) sort(map(array, "bar")) sort(map(array, "foo")) sort(map(array, #)) sort(map(array, 1)) sort(map(array, f64)) sort(map(array, i)) sort(map(array, i64)) sort(reduce(array, array)) sortBy(array, string(true)) string(!!false) string(!false) string(!ok) string(!true) string("bar" != nil) string("bar" <= "bar") string("bar" == "bar") string("bar" > "foo") string("bar" >= "bar") string("bar" not endsWith "bar") string("bar" not matches "bar") string("bar" not startsWith "foo") string("bar" startsWith "foo") string("bar") > type(i64) string("bar") >= toJSON("bar") string("foo" != nil) string("foo" == "foo") string("foo" == nil) string("foo" > "bar") string("foo" in foo) string("foo" matches "bar") string("foo" not contains "bar") string("foo" not contains "foo") string("foo" not in foo) string(--i) string(-0.5) string(-1) string(-f32) string(-f64) string(-i) string(-i32) string(-i64) string(0.5 != 0.5) string(0.5 != f64) string(0.5 != i) string(0.5 != i32) string(0.5 * 0.5) string(0.5 * i) string(0.5 * i32) string(0.5 ** f32) string(0.5 ** i32) string(0.5 + f64) string(0.5 + i) string(0.5 + i64) string(0.5 - f32) string(0.5 - f64) string(0.5 / 0.5) string(0.5 / 1) string(0.5 / f32) string(0.5 / i) string(0.5 < 0.5) string(0.5 < 1) string(0.5 < i64) string(0.5 <= 0.5) string(0.5 <= f64) string(0.5 <= i) string(0.5 <= i32) string(0.5 == 0.5) string(0.5 == 1) string(0.5 == i64) string(0.5 == nil) string(0.5 > 0.5) string(0.5 > 1) string(0.5 > i) string(0.5 > i64) string(0.5 >= 0.5) string(0.5 >= 1) string(0.5 >= f32) string(0.5 >= i32) string(0.5 >= i64) string(0.5 ^ f32) string(0.5 ^ i) string(0.5 ^ i32) string(0.5 ^ i64) string(0.5 in array) string(0.5 not in array) string(1 != 0.5) string(1 != 1) string(1 != i) string(1 != i64) string(1 != nil) string(1 % 1) string(1 % i) string(1 % i32) string(1 * 0.5) string(1 * f32) string(1 * f64) string(1 ** 0.5) string(1 ** 1) string(1 ** i) string(1 ** i64) string(1 + 0.5) string(1 + 1) string(1 + f64) string(1 - 0.5) string(1 - f32) string(1 - i32) string(1 - i64) string(1 .. 1) string(1 .. i32) string(1 .. i64) string(1 / 0.5) string(1 / f64) string(1 / i) string(1 / i32) string(1 / i64) string(1 < 0.5) string(1 <= 1) string(1 <= f32) string(1 <= i) string(1 <= i32) string(1 <= i64) string(1 == 1) string(1 == f32) string(1 == i32) string(1 > 0.5) string(1 > 1) string(1 > i64) string(1 >= f32) string(1 >= i) string(1 ^ 0.5) string(1 ^ 1) string(1 ^ f32) string(1 ^ f64) string(1 ^ i64) string(1 not in array) string([0.5]) string([div]) string([f64]) string([list]) string([score]) string([true]) string(abs(0.5)) string(abs(1)) string(abs(f32)) string(abs(i)) string(abs(i32)) string(add != add) string(add != div) string(add == div) string(add == nil) string(add) string(add) in foo ? i64 : i32 string(add) not endsWith foo.Bar string(all(array, ok)) string(all(array, true)) string(any(array, ok)) string(any(list, false)) string(any(list, ok)) string(array != array) string(array != nil) string(array) string(array[i32]) string(bitnot(1)) string(bitnot(i32)) string(bitnot(i64)) string(ceil(0.5)) string(ceil(1)) string(ceil(f32)) string(ceil(f64)) string(ceil(i)) string(ceil(i64)) string(div != div) string(div != nil) string(div == add) string(div == div) string(div) string(f32 != 0.5) string(f32 != f64) string(f32 != i) string(f32 != nil) string(f32 * 0.5) string(f32 * 1) string(f32 * f64) string(f32 * i) string(f32 * i32) string(f32 ** 1) string(f32 ** f64) string(f32 + f32) string(f32 + f64) string(f32 + i32) string(f32 + i64) string(f32 - 0.5) string(f32 - 1) string(f32 - i64) string(f32 / 0.5) string(f32 / f64) string(f32 / i64) string(f32 < f32) string(f32 <= i) string(f32 <= i32) string(f32 == 0.5) string(f32 == i) string(f32 > 0.5) string(f32 > f64) string(f32) string(f32) in foo string(f64 != 1) string(f64 != i) string(f64 != nil) string(f64 * 0.5) string(f64 * i) string(f64 * i32) string(f64 * i64) string(f64 ** 0.5) string(f64 ** f64) string(f64 ** i) string(f64 + 0.5) string(f64 + 1) string(f64 + f32) string(f64 - 0.5) string(f64 - 1) string(f64 - i) string(f64 / 0.5) string(f64 < f32) string(f64 < i) string(f64 <= 1) string(f64 <= f32) string(f64 <= f64) string(f64 == 1) string(f64 == f32) string(f64 == i) string(f64 == i64) string(f64 > 1) string(f64 >= f32) string(f64 >= i) string(f64 ^ 0.5) string(f64 ^ f32) string(f64 ^ i) string(f64 in array) string(f64 not in array) string(f64) string(false != nil) string(false != ok) string(false != true) string(false ? array : 0.5) string(false ? f64 : i32) string(false ? false : i) string(false ? greet : f64) string(false ? half : "bar") string(false ? half : i) string(false ? i : i) string(false ? nil : nil) string(false and ok) string(false) endsWith toBase64("foo") string(filter(array, false)) string(filter(array, ok)) string(filter(array, true)) string(filter(list, false)) string(find(array, ok)) string(find(array, true)) string(find(list, ok)) string(findIndex(array, true)) string(findLast(array, false)) string(findLast(array, ok)) string(findLast(array, true)) string(findLastIndex(array, ok)) string(first(array)) string(first(list)) string(float(0.5)) string(float(1)) string(float(f64)) string(float(i)) string(float(i64)) string(floor(0.5)) string(floor(f32)) string(floor(f64)) string(floor(i)) string(floor(i32)) string(floor(i64)) string(foo == foo) string(foo == nil) string(foo not in list) string(foo) string(foo.Bar) string(foo.Qux) string(foo.String()) string(foo.String) string(foo?.Bar) string(foo?.Qux) string(foo?.String()) string(foo?.String) string(get(array, i)) string(get(array, i64)) string(get(list, 1)) string(get(list, i32)) string(get(list, i64)) string(greet != nil) string(greet == greet) string(greet == nil) string(greet("bar")) string(greet("foo")) string(greet) string(greet) == nil ? 0.5 : i string(groupBy(array, #)) string(groupBy(array, 1)) string(groupBy(array, f32)) string(groupBy(array, false)) string(groupBy(array, i32)) string(groupBy(list, #)) string(groupBy(list, 0.5)) string(groupBy(list, 1)) string(groupBy(list, f64)) string(groupBy(list, false)) string(groupBy(list, i)) string(half != nil) string(half == nil) string(half(0.5)) string(half(1)) string(half(f64)) string(half) string(i != 1) string(i != i64) string(i % 1) string(i % i32) string(i % i64) string(i * 1) string(i * f64) string(i ** f32) string(i ** f64) string(i ** i64) string(i + 0.5) string(i + i) string(i - f32) string(i .. 1) string(i .. i) string(i .. i32) string(i / 1) string(i / f32) string(i / f64) string(i / i32) string(i / i64) string(i < 0.5) string(i < 1) string(i < i32) string(i <= f32) string(i <= i) string(i == 1) string(i == i) string(i > 0.5) string(i > 1) string(i > f32) string(i >= 0.5) string(i >= i64) string(i ^ 1) string(i ^ f32) string(i ^ i) string(i ^ i64) string(i) string(i) in foo string(i32 != 0.5) string(i32 != 1) string(i32 != f64) string(i32 != i32) string(i32 != nil) string(i32 % 1) string(i32 % i) string(i32 % i64) string(i32 * 1) string(i32 * f32) string(i32 * f64) string(i32 * i) string(i32 ** 0.5) string(i32 ** f64) string(i32 + 0.5) string(i32 - 0.5) string(i32 - 1) string(i32 - f32) string(i32 - f64) string(i32 - i32) string(i32 - i64) string(i32 .. 1) string(i32 .. i) string(i32 / 0.5) string(i32 < 1) string(i32 < f64) string(i32 < i64) string(i32 == f32) string(i32 == i64) string(i32 == nil) string(i32 > 1) string(i32 > i) string(i32 >= 0.5) string(i32 >= 1) string(i32 >= i) string(i32 ^ f32) string(i32 ^ f64) string(i32 ^ i32) string(i32 in array) string(i32 not in array) string(i32) string(i32) not startsWith trimSuffix("foo") string(i64 != 1) string(i64 != i) string(i64 != i32) string(i64 != i64) string(i64 % i32) string(i64 * 1) string(i64 * f32) string(i64 * i) string(i64 ** 0.5) string(i64 + i64) string(i64 - i) string(i64 - i32) string(i64 - i64) string(i64 .. 1) string(i64 .. i) string(i64 .. i32) string(i64 / f64) string(i64 / i) string(i64 / i64) string(i64 < 0.5) string(i64 < i) string(i64 <= i64) string(i64 == 0.5) string(i64 == i) string(i64 > 0.5) string(i64 > i64) string(i64 >= 0.5) string(i64 >= 1) string(i64 ^ 0.5) string(i64 ^ f64) string(i64 in array) string(i64) string(i64) matches greet("bar") string(i64) not in foo string(int(0.5)) string(int(1)) string(int(i32)) string(int(i64)) string(last(array)) string(last(list).String()) string(len("bar")) string(len(array)) string(len(list)) string(list != nil) string(list == array) string(list == list) string(list == nil) string(list) string(list[1]) string(list[i32]) string(list[i64]) string(list[i]) string(map(array, #)) string(map(array, 0.5)) string(map(array, add)) string(map(array, div)) string(map(array, i)) string(map(array, i32)) string(map(array, true)) string(map(list, "bar")) string(map(list, "foo")) string(map(list, #)) string(map(list, 0.5)) string(map(list, 1)) string(map(list, array)) string(map(list, half)) string(map(list, i32)) string(map(list, i64)) string(max(0.5)) string(max(0.5, f32)) string(max(1)) string(max(f32)) string(max(f64)) string(max(i)) string(max(i64)) string(mean(array)) string(min(0.5)) string(min(f32)) string(min(i)) string(min(i32)) string(min(i64)) string(nil != "bar") string(nil != div) string(nil != false) string(nil != greet) string(nil != half) string(nil != i) string(nil != ok) string(nil == "bar") string(nil == 0.5) string(nil == 1) string(nil == div) string(nil == foo) string(nil == list) string(nil == nil) string(nil == ok) string(nil == score) string(nil in list) string(nil not in list) string(nil) <= list[i].Bar string(none(array, ok)) string(none(list, false)) string(none(list, ok)) string(not !false) string(not (i64 == 0.5)) string(not false) string(not ok) string(not true) string(ok != nil) string(ok != true) string(ok ? 0.5 : nil) string(ok ? 0.5 : true) string(ok ? 1 : array) string(ok ? 1 : f32) string(ok ? array : add) string(ok ? div : array) string(ok ? half : score) string(ok ? i : 1) string(ok ? nil : half) string(ok ? nil : list) string(ok or false) string(ok || false) string(ok) string(one(array, true)) string(one(list, true)) string(reduce(array, #)) string(reduce(array, 0.5)) string(reduce(array, 1)) string(reduce(array, f64)) string(reduce(array, greet)) string(reduce(array, half)) string(reduce(array, i64)) string(reduce(array, list)) string(reduce(array, score)) string(reduce(list, "bar")) string(reduce(list, #)) string(reduce(list, 1)) string(reduce(list, add)) string(reduce(list, div)) string(reduce(list, foo)) string(reduce(list, i)) string(reduce(list, i64)) string(reduce(list, list)) string(round(0.5)) string(round(1)) string(round(ceil(i32))) string(round(f64)) string(round(i64)) string(score != nil) string(score == nil) string(score(1 % 1)) string(score(1)) string(score(i)) string(score) string(sort(array)) string(sortBy(array, "foo")) string(string("bar")) string(string("foo")) string(string(0.5)) string(string(1)) string(string(array)) string(string(div)) string(string(f32)) string(string(f64)) string(string(false)) string(string(greet)) string(string(half)) string(string(i)) string(string(i64)) string(string(nil)) string(string(ok)) string(string(score)) string(sum(array)) string(toBase64("foo")) string(toJSON("bar")) string(toJSON(0.5)) string(toJSON(1)) string(toJSON(array)) string(toJSON(f32)) string(toJSON(f64)) string(toJSON(false)) string(toJSON(i)) string(toJSON(i32)) string(toJSON(i64)) string(toJSON(list)) string(toJSON(nil)) string(toJSON(ok)) string(toJSON(true)) string(trim("bar")) string(trim(type(nil))) string(trimPrefix("foo")) string(trimSuffix("foo")) string(true != false) string(true && ok) string(true == nil) string(true ? 0.5 : true) string(true ? f64 : score) string(true ? false : nil) string(true ? greet : i) string(true ? list : ok) string(true and false) string(true or false) string(true or ok) string(true || true) string(type("bar")) string(type("foo")) string(type(-i64)) string(type(0.5)) string(type(1)) string(type(array)) string(type(f32)) string(type(f64)) string(type(foo)) string(type(greet)) string(type(half)) string(type(i)) string(type(i32)) string(type(i64)) string(type(list)) string(type(nil)) string(type(ok)) string(type(score)) string(upper("foo")) string({"bar": "foo", "foo": half}) string({"bar": f32, "foo": i32}) string({"bar": f32}) string({"bar": true}) string({"foo": add}) string({"foo": array, "foo": list}) sum(1 .. 1) sum(1 .. i) sum(1 .. i32) sum(1 .. i64) sum([0.5]) sum([f32]) sum(array) sum(array) != f32 sum(array) % i sum(array) % i64 sum(array) - f32 sum(array) / -f64 sum(array) < i sum(array) == i64 - i sum(array) ^ f64 sum(array) not in array sum(filter(array, ok)) sum(groupBy(array, i32).String) sum(i32 .. 1) sum(i64 .. i32) sum(i64 .. i64) sum(list[i:1]) sum(map(array, #)) sum(map(array, f32)) sum(map(list, 0.5)) sum(map(list, f32)) sum(map(list, i32)) sum(ok ? array : i64) sum(reduce(array, array)) sum(reduce(list, array)) sum(sort(array)) sum(true ? array : i32) take(array, i) take(array, i32) take(array, i64) take(list, i) take(list, i32) take(list, i64) take(map(array, #), i) toBase64("bar" + "bar") toBase64("bar" + "foo") toBase64("bar") startsWith type(score) toBase64("foo" + "bar") toBase64(foo.Bar) toBase64(foo.String()) toBase64(foo?.Bar) toBase64(foo?.String()) toBase64(greet("bar")) toBase64(greet("foo")) toBase64(lower("bar")) toBase64(lower("foo")) toBase64(ok ? "bar" : f64) toBase64(reduce(list, "bar")) toBase64(string("foo")) toBase64(string(0.5)) toBase64(string(1)) toBase64(string(add)) toBase64(string(array)) toBase64(string(f32)) toBase64(string(f64)) toBase64(string(foo)) toBase64(string(greet)) toBase64(string(half)) toBase64(string(i)) toBase64(string(list)) toBase64(string(ok)) toBase64(toBase64("bar")) toBase64(toJSON("bar")) toBase64(toJSON(0.5)) toBase64(toJSON(1)) toBase64(toJSON(f32)) toBase64(toJSON(f64)) toBase64(toJSON(foo)) toBase64(toJSON(i64)) toBase64(toJSON(list)) toBase64(toJSON(nil)) toBase64(toJSON(ok)) toBase64(toJSON(true)) toBase64(trim("bar")) toBase64(trimPrefix("foo")) toBase64(trimSuffix("foo")) toBase64(type(0.5)) toBase64(type(1)) toBase64(type(add)) toBase64(type(div)) toBase64(type(f32)) toBase64(type(f64)) toBase64(type(false)) toBase64(type(foo)) toBase64(type(greet)) toBase64(type(half)) toBase64(type(i)) toBase64(type(i32)) toBase64(type(i64)) toBase64(type(list)) toBase64(type(nil)) toBase64(type(score)) toBase64(upper("foo")) toJSON(!false) toJSON(!ok) toJSON(!true) toJSON("bar" < "foo") toJSON("bar" >= "bar") toJSON("bar" endsWith "bar") toJSON("bar" matches "foo") toJSON("bar" not in foo) toJSON("bar" not matches "bar") toJSON("bar" not startsWith "foo") toJSON("bar" startsWith "bar") toJSON("bar") not in foo toJSON("foo" != "bar") toJSON("foo" != "foo") toJSON("foo" < "foo") toJSON("foo" == "bar") toJSON("foo" > "foo") toJSON("foo" >= "foo") toJSON("foo" startsWith "bar") toJSON(-0.5) toJSON(-1) toJSON(-f32) toJSON(-f64) toJSON(-i) toJSON(-i32) toJSON(-i64) toJSON(0.5 != 1) toJSON(0.5 != f64) toJSON(0.5 != nil) toJSON(0.5 * i) toJSON(0.5 * i32) toJSON(0.5 * i64) toJSON(0.5 ** 0.5) toJSON(0.5 ** 1) toJSON(0.5 ** f32) toJSON(0.5 ** f64) toJSON(0.5 ** i) toJSON(0.5 ** i32) toJSON(0.5 + 0.5) toJSON(0.5 + 1) toJSON(0.5 + f32) toJSON(0.5 - 0.5) toJSON(0.5 - 1) toJSON(0.5 - f32) toJSON(0.5 - f64) toJSON(0.5 - i) toJSON(0.5 - i32) toJSON(0.5 / 1) toJSON(0.5 / f32) toJSON(0.5 / f64) toJSON(0.5 / i32) toJSON(0.5 < 1) toJSON(0.5 < f32) toJSON(0.5 < f64) toJSON(0.5 < i) toJSON(0.5 <= 0.5) toJSON(0.5 <= 1) toJSON(0.5 <= f32) toJSON(0.5 <= i64) toJSON(0.5 == 0.5) toJSON(0.5 == f64) toJSON(0.5 == i) toJSON(0.5 == i32) toJSON(0.5 == i64) toJSON(0.5 >= 0.5) toJSON(0.5 >= 1) toJSON(0.5 >= f32) toJSON(0.5 ^ f32) toJSON(0.5 ^ i32) toJSON(0.5 ^ i64) toJSON(0.5) not in foo toJSON(1 != 0.5) toJSON(1 != f32) toJSON(1 != nil) toJSON(1 % 1) toJSON(1 % i) toJSON(1 % i32) toJSON(1 * f64) toJSON(1 * i32) toJSON(1 * i64) toJSON(1 ** 0.5) toJSON(1 ** 1) toJSON(1 ** i32) toJSON(1 + 0.5) toJSON(1 + 1) toJSON(1 + f64) toJSON(1 + i) toJSON(1 + i32) toJSON(1 - i) toJSON(1 - i32) toJSON(1 .. i32) toJSON(1 .. i64) toJSON(1 / 1) toJSON(1 / f64) toJSON(1 / i64) toJSON(1 < 0.5) toJSON(1 < 1) toJSON(1 < f64) toJSON(1 < i) toJSON(1 <= 0.5) toJSON(1 <= f32) toJSON(1 <= f64) toJSON(1 == 0.5) toJSON(1 == 1) toJSON(1 == f64) toJSON(1 == i) toJSON(1 == i32) toJSON(1 == nil) toJSON(1 > f32) toJSON(1 > i) toJSON(1 >= 1) toJSON(1 >= f32) toJSON(1 >= i32) toJSON(1 ^ 1) toJSON(1 ^ f32) toJSON(1 ^ i32) toJSON(1 ^ i64) toJSON(1) > reduce(list, "bar") toJSON(1) not contains string(true) toJSON([f64]) toJSON([false]) toJSON([foo]) toJSON([nil]) toJSON([true]) toJSON(abs(0.5)) toJSON(abs(1)) toJSON(abs(f32)) toJSON(abs(f64)) toJSON(abs(i)) toJSON(abs(i32)) toJSON(abs(i64)) toJSON(add == add) toJSON(any(array, false)) toJSON(array == array) toJSON(array == list) toJSON(array == nil) toJSON(array) toJSON(array[1:i64]) toJSON(array[1]) toJSON(array[i]) toJSON(bitnot(1)) toJSON(bitnot(i)) toJSON(bitnot(i32)) toJSON(bitnot(i64)) toJSON(bitshl(i, i32)) toJSON(ceil(1)) toJSON(ceil(f64)) toJSON(ceil(i)) toJSON(ceil(i32)) toJSON(ceil(i64)) toJSON(count(array, ok)) toJSON(div != div) toJSON(div == div) toJSON(f32 != 0.5) toJSON(f32 != 1 || ok) toJSON(f32 != f32) toJSON(f32 != i32) toJSON(f32 * f32) toJSON(f32 ** 0.5) toJSON(f32 ** 1) toJSON(f32 ** f64) toJSON(f32 ** i32) toJSON(f32 + 0.5) toJSON(f32 + f32) toJSON(f32 - 0.5) toJSON(f32 - f32) toJSON(f32 - f64) toJSON(f32 - i64) toJSON(f32 < 0.5) toJSON(f32 < i) toJSON(f32 < i64) toJSON(f32 <= 0.5) toJSON(f32 <= 1) toJSON(f32 <= i64) toJSON(f32 == f64) toJSON(f32 == i) toJSON(f32 == nil) toJSON(f32 > i) toJSON(f32 > i32) toJSON(f32 >= 0.5) toJSON(f32 ^ i64) toJSON(f32) toJSON(f32) in foo toJSON(f64 != 0.5) toJSON(f64 != f32) toJSON(f64 != i) toJSON(f64 != i32) toJSON(f64 != nil) toJSON(f64 * 1) toJSON(f64 * f64) toJSON(f64 * i64) toJSON(f64 ** 0.5) toJSON(f64 ** f32) toJSON(f64 + 0.5) toJSON(f64 + f32) toJSON(f64 + i32) toJSON(f64 - f64) toJSON(f64 - i) toJSON(f64 - i64) toJSON(f64 / 1) toJSON(f64 < f64) toJSON(f64 <= 0.5) toJSON(f64 == f64) toJSON(f64 >= 1) toJSON(f64 >= f64) toJSON(f64 ^ f32) toJSON(f64) toJSON(false != ok) toJSON(false ? 0.5 : "foo") toJSON(false ? add : f64) toJSON(false ? array : 1) toJSON(false ? false : foo) toJSON(false ? nil : ok) toJSON(false ? ok : i32) toJSON(filter(list, true)) toJSON(find(list, ok)) toJSON(findIndex(map(array, list), ok)) toJSON(first(array)) toJSON(first(list)) toJSON(float(0.5)) toJSON(float(1)) toJSON(float(f32)) toJSON(float(f64)) toJSON(float(i)) toJSON(float(i64)) toJSON(floor(0.5)) toJSON(floor(f64)) toJSON(floor(i)) toJSON(floor(i32)) toJSON(foo != nil) toJSON(foo in list) toJSON(foo) toJSON(foo.Bar) toJSON(foo.String()) toJSON(foo?.Bar) toJSON(foo?.String()) toJSON(get(array, i32)) toJSON(get(array, i64)) toJSON(get(list, 1)) toJSON(get(list, i)) toJSON(get(list, i32)) toJSON(get(list, i64)) toJSON(greet != nil) toJSON(greet == greet) toJSON(greet == nil) toJSON(greet("bar")) toJSON(greet("foo")) toJSON(groupBy(array, #)?.div) toJSON(groupBy(array, ok)?.foo) toJSON(groupBy(list, #)?.foo) toJSON(half(0.5)) toJSON(half(1)) toJSON(half(f64)) toJSON(i != 0.5) toJSON(i != 1) toJSON(i % i) toJSON(i % i32) toJSON(i * 0.5) toJSON(i * 1) toJSON(i * f32) toJSON(i * i) toJSON(i * i32) toJSON(i ** f32) toJSON(i ** i) toJSON(i + 0.5) toJSON(i + 1) toJSON(i + i) toJSON(i - 1) toJSON(i - f32) toJSON(i .. i) toJSON(i .. i32) toJSON(i / i64) toJSON(i < f32) toJSON(i < f64) toJSON(i < i) toJSON(i < i32) toJSON(i <= 1) toJSON(i <= f32) toJSON(i <= f64) toJSON(i <= i) toJSON(i <= i32) toJSON(i <= i64) toJSON(i == 0.5) toJSON(i == 1) toJSON(i == i32) toJSON(i == nil) toJSON(i > 0.5) toJSON(i > i) toJSON(i > i32) toJSON(i > i64) toJSON(i >= f64) toJSON(i >= i32) toJSON(i ^ i64) toJSON(i not in array) toJSON(i) toJSON(i) matches string("bar") toJSON(i32 != i) toJSON(i32 != i64) toJSON(i32 % 1) toJSON(i32 * 0.5) toJSON(i32 * i) toJSON(i32 * i32) toJSON(i32 * i64) toJSON(i32 ** f64) toJSON(i32 ** i64) toJSON(i32 + 0.5) toJSON(i32 + 1) toJSON(i32 + f64) toJSON(i32 .. i) toJSON(i32 .. i64) toJSON(i32 / 0.5) toJSON(i32 / f32) toJSON(i32 / f64) toJSON(i32 / i64) toJSON(i32 < 0.5) toJSON(i32 < 1) toJSON(i32 < i) toJSON(i32 < i32) toJSON(i32 <= 0.5) toJSON(i32 > f64) toJSON(i32 > i) toJSON(i32 > i32) toJSON(i32 >= f64) toJSON(i32 ^ 0.5) toJSON(i32 ^ f32) toJSON(i32 ^ f64) toJSON(i32 ^ i32) toJSON(i32 in array) toJSON(i32 not in array) toJSON(i32) toJSON(i32) contains foo.Bar toJSON(i64 != 1) toJSON(i64 != i) toJSON(i64 != i32) toJSON(i64 % i32) toJSON(i64 * 0.5) toJSON(i64 * f64) toJSON(i64 ** f64) toJSON(i64 ** i) toJSON(i64 ** i32) toJSON(i64 + 1) toJSON(i64 - i32) toJSON(i64 .. 1) toJSON(i64 .. i32) toJSON(i64 / f64) toJSON(i64 / i) toJSON(i64 / i64) toJSON(i64 < 1) toJSON(i64 < f64) toJSON(i64 < i32) toJSON(i64 <= 1) toJSON(i64 <= i64) toJSON(i64 == 0.5) toJSON(i64 > 0.5) toJSON(i64 > 1) toJSON(i64 > i) toJSON(i64 > i32) toJSON(i64 > i64) toJSON(i64 >= 1) toJSON(i64 >= i) toJSON(i64 >= i64) toJSON(i64 ^ 0.5) toJSON(i64 ^ f32) toJSON(i64 ^ i32) toJSON(i64 in array) toJSON(i64) toJSON(int(0.5)) toJSON(int(1)) toJSON(int(i)) toJSON(int(i32)) toJSON(int(i64)) toJSON(len("bar")) toJSON(len(array)) toJSON(len(greet("foo"))) toJSON(len(list)) toJSON(list != array) toJSON(list != nil) toJSON(list == array) toJSON(list == list) toJSON(list) toJSON(list[1]) toJSON(lower("bar")) toJSON(map(array, #)) toJSON(map(array, -#)) toJSON(map(array, array)) toJSON(map(array, false)) toJSON(map(array, i)) toJSON(map(array, i64)) toJSON(map(array, list)) toJSON(map(list, #)) toJSON(map(list, 0.5)) toJSON(map(list, 1)) toJSON(map(list, foo)) toJSON(map(list, i32)) toJSON(map(list, i64)) toJSON(map(list, list)) toJSON(map(list, ok)) toJSON(max(1)) toJSON(max(f32)) toJSON(max(f64)) toJSON(max(i32)) toJSON(mean(array)) toJSON(median(array)) toJSON(min(0.5)) toJSON(min(1)) toJSON(min(f32)) toJSON(min(f64)) toJSON(min(f64, f64)) toJSON(min(i)) toJSON(min(i32)) toJSON(min(i64)) toJSON(nil != 0.5) toJSON(nil != 1) toJSON(nil != add) toJSON(nil != array) toJSON(nil != f32) toJSON(nil != false) toJSON(nil != foo) toJSON(nil != greet) toJSON(nil != half) toJSON(nil == 0.5) toJSON(nil == 1) toJSON(nil == div) toJSON(nil == f64) toJSON(nil == half) toJSON(nil == i) toJSON(nil == i64) toJSON(nil == list) toJSON(nil == nil) toJSON(nil == ok) toJSON(nil in array) toJSON(nil) + foo.Bar toJSON(none(array, ok)) toJSON(none(array, true)) toJSON(none(list, false)) toJSON(none(list, ok)) toJSON(not ("foo" not in foo)) toJSON(not (f32 != 1)) toJSON(not false) toJSON(not ok) toJSON(not true) toJSON(ok != false) toJSON(ok && false) toJSON(ok && ok) toJSON(ok == nil) toJSON(ok == ok) toJSON(ok ? "foo" : f32) toJSON(ok ? 0.5 : f32) toJSON(ok ? f64 : 0.5) toJSON(ok ? i : false) toJSON(ok ? nil : i) toJSON(ok ? nil : true) toJSON(ok ? true : greet) toJSON(ok and ok) toJSON(ok or true) toJSON(ok) toJSON(one(array, false)) toJSON(one(array, true)) toJSON(reduce(array, #)) toJSON(reduce(array, 0.5)) toJSON(reduce(array, array)) toJSON(reduce(array, foo)) toJSON(reduce(array, i64)) toJSON(reduce(array, list)) toJSON(reduce(array, score(i32 * i64))) toJSON(reduce(list, #)) toJSON(reduce(list, 1)) toJSON(reduce(list, f32)) toJSON(reduce(list, false)) toJSON(reduce(list, i)) toJSON(reduce(list, i32)) toJSON(reduce(list, list)) toJSON(reduce(list, ok)) toJSON(reduce(list, true)) toJSON(round(1)) toJSON(round(f64)) toJSON(round(i32)) toJSON(score != score) toJSON(score(1)) toJSON(score(1, 1)) toJSON(score(i)) toJSON(sort(array)) toJSON(string("bar")) toJSON(string(0.5)) toJSON(string(1)) toJSON(string(array)) toJSON(string(f32)) toJSON(string(f64)) toJSON(string(false)) toJSON(string(foo)) toJSON(string(half)) toJSON(string(i)) toJSON(string(i32)) toJSON(string(i64)) toJSON(string(list)) toJSON(string(nil)) toJSON(string(ok)) toJSON(string(score)) toJSON(string(true)) toJSON(sum(array)) toJSON(take(array, i32)) toJSON(toBase64("bar")) toJSON(toJSON("bar")) toJSON(toJSON(array)) toJSON(toJSON(f32)) toJSON(toJSON(f64)) toJSON(toJSON(false)) toJSON(toJSON(foo)) toJSON(toJSON(i)) toJSON(toJSON(i32)) toJSON(toJSON(i64)) toJSON(toJSON(list)) toJSON(toJSON(nil)) toJSON(toJSON(ok)) toJSON(trim("bar")) toJSON(trimPrefix("foo")) toJSON(trimSuffix("bar")) toJSON(true != true) toJSON(true && ok) toJSON(true == ok) toJSON(true ? "bar" : "bar") toJSON(true ? nil : score) toJSON(true and false) toJSON(true and true) toJSON(true) in foo toJSON(type("foo")) toJSON(type(add)) toJSON(type(array)) toJSON(type(f32)) toJSON(type(f64)) toJSON(type(false)) toJSON(type(foo)) toJSON(type(i)) toJSON(type(i32)) toJSON(type(i64)) toJSON(type(list)) toJSON(type(ok)) toJSON(type(score)) toJSON(type(true)) toJSON(upper("bar")) toJSON({"bar": 1, "bar": array}) toJSON({"bar": 1}) toJSON({"bar": f64}) toJSON({"bar": list}) toJSON({"foo": i}) toJSON({"foo": nil}) toPairs(groupBy(array, # / #)) toPairs(groupBy(array, #)) toPairs(groupBy(array, 0.5)) toPairs(groupBy(array, 1)) toPairs(groupBy(array, false)) toPairs(groupBy(array, foo)) toPairs(groupBy(array, i)) toPairs(groupBy(array, i32)) toPairs(groupBy(array, ok)) toPairs(groupBy(array, true)) toPairs(groupBy(list, #)) toPairs(groupBy(list, 1)) toPairs(groupBy(list, f32)) toPairs(groupBy(list, i)) toPairs(groupBy(list, ok)) toPairs({"bar": f32}) toPairs({"foo": i32, "bar": score}) toPairs({"foo": nil}) trim("bar") not in foo trim(false ? "bar" : "bar") trim(foo.Bar) trim(foo.String()) trim(foo?.Bar) trim(foo?.String()) trim(greet("bar")) trim(greet("foo")) trim(lower("bar")) trim(lower("foo")) trim(reduce(list, "bar")) trim(string("bar")) trim(string(-f64)) trim(string(0.5)) trim(string(1)) trim(string(add)) trim(string(array)) trim(string(f32)) trim(string(foo)) trim(string(i64)) trim(string(list)) trim(string(nil)) trim(toJSON("bar")) trim(toJSON(1)) trim(toJSON(f32)) trim(toJSON(false)) trim(toJSON(foo)) trim(toJSON(i32)) trim(toJSON(i64)) trim(toJSON(ok)) trim(toJSON(true)) trim(trim("bar")) trim(trimPrefix("foo")) trim(trimSuffix("bar")) trim(true ? "foo" : greet) trim(type("bar")) trim(type("foo")) trim(type(0.5)) trim(type(1)) trim(type(add)) trim(type(div)) trim(type(f32)) trim(type(f64)) trim(type(greet)) trim(type(i)) trim(type(list)) trim(type(nil)) trim(type(ok)) trim(type(score)) trim(type(true)) trimPrefix("bar" + "foo") trimPrefix("foo" + "bar") trimPrefix(false ? 1 : "bar") trimPrefix(foo.Bar) trimPrefix(foo.String()) trimPrefix(foo?.Bar) trimPrefix(foo?.String()) trimPrefix(greet("bar")) trimPrefix(greet("foo")) trimPrefix(greet(type(0.5))) trimPrefix(lower("bar")) trimPrefix(string("foo")) trimPrefix(string(0.5)) trimPrefix(string(1)) trimPrefix(string(add)) trimPrefix(string(array)) trimPrefix(string(div)) trimPrefix(string(f32)) trimPrefix(string(f64)) trimPrefix(string(foo)) trimPrefix(string(greet)) trimPrefix(string(half)) trimPrefix(string(i)) trimPrefix(string(i32)) trimPrefix(string(i64)) trimPrefix(string(nil)) trimPrefix(string(score)) trimPrefix(string(true)) trimPrefix(string({"bar": greet})) trimPrefix(toBase64("bar")) trimPrefix(toJSON("foo")) trimPrefix(toJSON(1)) trimPrefix(toJSON(array)) trimPrefix(toJSON(f32)) trimPrefix(toJSON(foo)) trimPrefix(toJSON(i32)) trimPrefix(toJSON(i64)) trimPrefix(toJSON(list)) trimPrefix(toJSON(nil)) trimPrefix(toJSON(true)) trimPrefix(trimPrefix("foo")) trimPrefix(type("bar")) trimPrefix(type(0.5)) trimPrefix(type(1)) trimPrefix(type(array)) trimPrefix(type(f32)) trimPrefix(type(f64)) trimPrefix(type(greet)) trimPrefix(type(half)) trimPrefix(type(i)) trimPrefix(type(i32)) trimPrefix(type(i64)) trimPrefix(type(list)) trimPrefix(type(nil)) trimPrefix(type(ok)) trimPrefix(type(true)) trimPrefix(upper("bar")) trimPrefix(upper("foo")) trimSuffix("bar" + "foo") trimSuffix("bar") not contains reduce(list, "bar") trimSuffix("foo" + "bar") trimSuffix(false ? i64 : "foo") trimSuffix(foo.Bar) trimSuffix(foo.String()) trimSuffix(foo?.Bar) trimSuffix(foo?.String()) trimSuffix(greet("bar")) trimSuffix(greet("foo")) trimSuffix(lower("bar")) trimSuffix(reduce(array, "foo")) trimSuffix(reduce(list, #)?.Bar) trimSuffix(string("bar")) trimSuffix(string("foo")) trimSuffix(string(0.5)) trimSuffix(string(add)) trimSuffix(string(array)) trimSuffix(string(div)) trimSuffix(string(f64)) trimSuffix(string(false)) trimSuffix(string(foo)) trimSuffix(string(half)) trimSuffix(string(i)) trimSuffix(string(i32)) trimSuffix(string(i64)) trimSuffix(string(list)) trimSuffix(string(nil)) trimSuffix(string(ok)) trimSuffix(string(true)) trimSuffix(toBase64("bar")) trimSuffix(toBase64("foo")) trimSuffix(toJSON(1 > f64)) trimSuffix(toJSON(1)) trimSuffix(toJSON(f32)) trimSuffix(toJSON(f64)) trimSuffix(toJSON(false)) trimSuffix(toJSON(foo)) trimSuffix(toJSON(i)) trimSuffix(toJSON(i32)) trimSuffix(toJSON(i64)) trimSuffix(toJSON(list)) trimSuffix(toJSON(nil)) trimSuffix(toJSON(true)) trimSuffix(trim("bar")) trimSuffix(trim("foo")) trimSuffix(trimPrefix("bar")) trimSuffix(trimPrefix("foo")) trimSuffix(trimSuffix("bar")) trimSuffix(type(1)) trimSuffix(type(add)) trimSuffix(type(array)) trimSuffix(type(div)) trimSuffix(type(f32)) trimSuffix(type(foo)) trimSuffix(type(greet)) trimSuffix(type(half)) trimSuffix(type(i32)) trimSuffix(type(list)) trimSuffix(type(nil)) trimSuffix(type(ok)) trimSuffix(upper("foo")) true != nil || true == true true != ok != ok true == ok == ok true ? 0.5 : i <= f32 true ? 1 : foo?.Bar true ? 1 : ok or i64 == 0.5 true ? add : foo?.Bar true ? array : 0.5 >= i32 true ? array : foo.String true ? array : foo?.Bar true ? array : foo?.String true ? array : i32 ** f64 true ? div : i64 ** 1 ^ i32 true ? false : 0.5 > i true ? false : foo.Qux true ? foo : 0.5 + -1 true ? foo : foo.Bar true ? foo : i64 / f32 true ? greet : foo.Bar true ? greet : ok == ok true ? half : 0.5 / i32 true ? half : foo.String true ? i : 1 * i64 true ? i32 : i32 - f32 true ? i32 : i32 >= f32 true ? i64 : f64 != i true ? list : f32 != i true ? nil : foo.String true ? nil : foo?.String true ? nil : i32 != f64 + 1 true ? ok : foo.Qux true ? ok : foo?.String true ? score : ok or f64 < f32 true and nil not in list true and ok or ok true and true || ok true or 0.5 not in array true || f32 not in groupBy(list, #) true || false ? half : half type(!false) type(!ok) type(!true) type("bar" != "bar") type("bar" < "foo") type("bar" <= "bar") type("bar" == "foo") type("bar" >= "bar") type("bar" not endsWith "foo") type("bar" startsWith "bar") type("bar") startsWith greet("bar") type("foo" != nil) type("foo" + "bar") type("foo" not startsWith "bar") type("foo") not in foo type(-0.5) type(-1) type(-f32) type(-f64) type(-i) type(-i32) type(-i64) type(-int(f64)) type(0.5 != f64) type(0.5 != i32) type(0.5 != nil) type(0.5 * 0.5) type(0.5 * f32) type(0.5 * f64) type(0.5 * i64) type(0.5 ** 0.5) type(0.5 ** 1) type(0.5 ** f32) type(0.5 ** f64) type(0.5 ** i) type(0.5 ** i32) type(0.5 + 0.5) type(0.5 + 1) type(0.5 + f32) type(0.5 + f64) type(0.5 + i) type(0.5 + i64) type(0.5 - 1) type(0.5 - f64) type(0.5 - i32) type(0.5 / 1) type(0.5 / f32) type(0.5 / i) type(0.5 / i32) type(0.5 / i64) type(0.5 < 1) type(0.5 < f32) type(0.5 < i32) type(0.5 < i64) type(0.5 <= 1) type(0.5 <= f32) type(0.5 <= i64) type(0.5 == 0.5) type(0.5 == f32) type(0.5 == f64) type(0.5 == i32) type(0.5 > 0.5) type(0.5 > f32) type(0.5 > i) type(0.5 > i32) type(0.5 > i64) type(0.5 >= 0.5) type(0.5 >= i) type(0.5 >= i32) type(0.5 ^ 0.5) type(0.5 ^ i) type(0.5 ^ i32) type(0.5 ^ i64) type(0.5 not in array) type(0.5) in foo type(1 != i32) type(1 != nil) type(1 % 1) type(1 % i) type(1 * 0.5) type(1 * f32) type(1 * i) type(1 * i32) type(1 ** 0.5) type(1 ** f64) type(1 ** i) type(1 ** i64) type(1 + 0.5) type(1 + 1) type(1 + f32) type(1 + i64) type(1 - 0.5) type(1 - 1) type(1 - i64) type(1 .. 1) type(1 .. i64) type(1 / f64) type(1 / i) type(1 < i32) type(1 < i64) type(1 <= 0.5) type(1 <= 1) type(1 <= f64) type(1 <= i) type(1 == f32) type(1 == f64) type(1 == i) type(1 == i32) type(1 == i64) type(1 > i) type(1 >= 0.5) type(1 >= i) type(1 >= i64) type(1 ^ 1) type(1 ^ i) type(1 ^ i64) type(1) endsWith foo.Bar type(1) in reduce(list, #) type(1) not endsWith "bar" ? i64 : nil type(1) not startsWith string(0.5) type([div]) type([f32]) type(abs(0.5)) type(abs(f32)) type(abs(f64)) type(abs(i)) type(abs(i32)) type(abs(i64)) type(add) type(all(array, ok)) type(all(list, ok)) type(all(list, true)) type(any(array, false)) type(any(array, ok)) type(any(list, false)) type(array != list) type(array != nil) type(array == array) type(array) type(array) >= trimPrefix("foo") type(array[1]) type(array[i32]) type(array[i]) type(bitand(1, i)) type(bitnot(i)) type(bitnot(i32)) type(bitnot(i64)) type(bitxor(i64, 1)) type(ceil(0.5)) type(ceil(f32)) type(ceil(f64)) type(ceil(i64)) type(count(array, true)) type(div != div) type(div == div) type(div) type(f32 != 0.5) type(f32 != 1) type(f32 * 1) type(f32 * i) type(f32 * i32) type(f32 ** f32) type(f32 + 1) type(f32 + i) type(f32 - f32) type(f32 - i32) type(f32 / 1) type(f32 / f32) type(f32 < 1) type(f32 < f32) type(f32 <= f64) type(f32 == 0.5) type(f32 == f64) type(f32 == i) type(f32 == i32) type(f32 == i64) type(f32 > 1) type(f32 >= f32) type(f32 >= i) type(f32 >= i32) type(f32 ^ i64) type(f32 not in array) type(f32) type(f64 != 0.5) type(f64 != i) type(f64 * 0.5) type(f64 * 1) type(f64 * f32) type(f64 ** 1) type(f64 + f32) type(f64 + i32) type(f64 - 0.5) type(f64 - 1) type(f64 - f64) type(f64 - i) type(f64 / 1) type(f64 / f32) type(f64 / i64) type(f64 < 0.5) type(f64 < f32) type(f64 < f64) type(f64 < i32) type(f64 < i64) type(f64 <= 0.5) type(f64 <= f64) type(f64 <= i64) type(f64 == 0.5) type(f64 == f32) type(f64 == i64) type(f64 == nil) type(f64 > i) type(f64 > i32) type(f64 >= 0.5) type(f64 >= i) type(f64 ^ 0.5) type(f64 not in array) type(f64) type(false != nil) type(false != ok) type(false && true) type(false ? "bar" : score) type(false ? div : f64) type(false ? half : greet) type(false ? true : foo) type(false || true) type(false) startsWith "bar" ? ok : f32 type(find(array, false)) type(find(array, true)) type(find(list, true)) type(findIndex(array, ok)) type(findLast(array, false)) type(findLast(array, ok)) type(findLastIndex(array, false)) type(findLastIndex(list, false)) type(findLastIndex(list, ok)) type(findLastIndex(list, true)) type(first(list)) type(float(f32)) type(float(i32)) type(floor(0.5)) type(floor(1)) type(floor(f64)) type(floor(i64)) type(foo != foo) type(foo != nil) type(foo in list) type(foo) type(foo.Bar) type(foo.Qux) type(foo.String()) type(foo.String) type(foo?.Bar) type(foo?.Qux) type(foo?.String()) type(foo?.String) type(get(array, 1)) type(get(array, i64)) type(get(list, 1)) type(get(list, i)) type(get(list, i32)) type(get(list, i64)) type(greet("bar")) type(greet("foo")) type(greet) type(groupBy(array, #)) type(groupBy(array, #).score) type(groupBy(array, 0.5)) type(groupBy(array, false)?.add) type(groupBy(array, i)) type(groupBy(array, i32)) type(groupBy(array, i64)) type(groupBy(list, "bar")) type(groupBy(list, #)) type(groupBy(list, #)?.Bar) type(groupBy(list, 1)) type(groupBy(list, i64)) type(groupBy(list, true)) type(half(0.5)) type(half(1)) type(half(f64)) type(half) type(half) not in foo type(i % 1) type(i % i32) type(i * 0.5) type(i * i32) type(i ** f32) type(i ** f64) type(i ** i) type(i + i32) type(i - 0.5) type(i - 1) type(i - i) type(i - i64) type(i .. i) type(i / 0.5) type(i / i32) type(i < 0.5) type(i < 1) type(i <= 0.5) type(i <= 1) type(i == 1) type(i > 0.5) type(i > 1) type(i > f32) type(i > i64) type(i >= i32) type(i ^ 1) type(i ^ i) type(i ^ i32) type(i ^ i64) type(i) type(i) + foo.Bar type(i32 != 1) type(i32 != f64) type(i32 * 0.5) type(i32 * i) type(i32 ** 0.5) type(i32 ** f64) type(i32 ** i) type(i32 + 1) type(i32 - 1) type(i32 .. i32) type(i32 / 0.5) type(i32 / f64) type(i32 < 0.5) type(i32 <= 0.5) type(i32 <= f64) type(i32 <= i32) type(i32 == 1) type(i32 == nil) type(i32 > 0.5) type(i32 > f64) type(i32 > i64) type(i32 >= 1) type(i32 >= f32) type(i32 >= i64) type(i32 ^ 1) type(i32 ^ f32) type(i32 ^ f64) type(i32 ^ i) type(i32 not in array) type(i32) type(i32) in foo type(i32) not matches trim("foo") type(i64 != 1) type(i64 != f64) type(i64 % 1) type(i64 * f32) type(i64 * i64) type(i64 ** 0.5) type(i64 ** f64) type(i64 ** i32) type(i64 + 0.5) type(i64 + 1) type(i64 + i64) type(i64 - 0.5) type(i64 - f32) type(i64 - f64) type(i64 - i32) type(i64 .. i32) type(i64 / 0.5) type(i64 / f32) type(i64 / i64) type(i64 < 0.5) type(i64 < f32) type(i64 < f64) type(i64 < i) type(i64 < i64) type(i64 <= 0.5) type(i64 <= 1) type(i64 <= f32) type(i64 <= i) type(i64 == 1) type(i64 == f64) type(i64 > i64) type(i64 >= 1) type(i64 ^ f64) type(i64 ^ i) type(i64 not in array) type(i64) type(int(0.5)) type(int(f32)) type(int(f64)) type(int(i)) type(int(i32)) type(int(i64)) type(last(array)) type(last(list)) type(len(array)) type(len(list)) type(list != nil) type(list == array) type(list == nil) type(list) type(list[1]) type(list[i32]) type(list[i64]) type(list[i]) type(map(array, "bar")) type(map(array, "foo")) type(map(array, #)) type(map(array, 1)) type(map(array, div)) type(map(array, f32)) type(map(array, foo)) type(map(array, greet)) type(map(array, ok)) type(map(array, true)) type(map(list, "bar")) type(map(list, #)) type(map(list, array)) type(map(list, greet)) type(map(list, i64)) type(map(list, list)) type(map(list, ok)) type(max(0.5)) type(max(0.5, f64)) type(max(1)) type(max(1, i32)) type(max(f64)) type(max(i64)) type(median(array)) type(min(1)) type(min(f32)) type(min(i)) type(min(i32)) type(min(i64)) type(nil != "foo") type(nil != 0.5) type(nil != 1) type(nil != greet) type(nil != half) type(nil != i32) type(nil != i64) type(nil != nil) type(nil != score) type(nil == "foo") type(nil == array) type(nil == f32) type(nil == false) type(nil == foo) type(nil == greet) type(nil == nil) type(nil == score) type(nil in array) type(nil in list) type(nil not in array) type(nil not in list) type(none(list, ok)) type(none(list, true)) type(not (f64 <= i)) type(not false) type(not ok) type(not true) type(ok != false) type(ok != nil) type(ok != true) type(ok && false) type(ok == nil) type(ok ? "bar" : half) type(ok ? 1 : "bar") type(ok ? array : i64) type(ok ? array : score) type(ok ? i : "bar") type(ok ? i : nil) type(ok ? nil : 0.5) type(ok ? nil : div) type(ok and ok) type(ok or false) type(ok || false) type(ok) type(one(array, false)) type(one(array, true)) type(one(list, false)) type(one(list, true)) type(reduce(array, "bar")) type(reduce(array, #)) type(reduce(array, 1)) type(reduce(array, foo)) type(reduce(array, greet)) type(reduce(array, i)) type(reduce(array, ok)) type(reduce(list, "foo")) type(reduce(list, #)) type(reduce(list, array)) type(reduce(list, i64)) type(reduce(list, ok)) type(round(0.5)) type(round(1)) type(round(f64)) type(round(i)) type(round(i64)) type(score != score) type(score == nil) type(score(1)) type(score(1, 1)) type(score(i)) type(score) type(sort(array)) type(string(0.5)) type(string(1)) type(string(add)) type(string(div)) type(string(f32)) type(string(f64)) type(string(false)) type(string(greet)) type(string(i32)) type(string(i64)) type(string(list)) type(string(nil)) type(string(ok)) type(string(score)) type(toBase64("bar")) type(toJSON("bar")) type(toJSON("foo")) type(toJSON(0.5)) type(toJSON(1)) type(toJSON(array)) type(toJSON(false)) type(toJSON(i)) type(toJSON(i32)) type(toJSON(i64)) type(toJSON(list)) type(toJSON(nil)) type(trim("foo")) type(trimPrefix("bar")) type(true != nil) type(true == false) type(true == nil) type(true ? array : false) type(true ? array : half) type(true ? div : add) type(true ? f64 : i32) type(true ? ok : 1) type(true and false) type(true and true) type(true or true) type(true || ok) type(true || true) type(true) in foo type(true) matches string(list) type(type(0.5)) type(type(1)) type(type(add)) type(type(div)) type(type(foo)) type(type(greet)) type(type(half)) type(type(i)) type(type(i32)) type(type(i64)) type(type(nil)) type(type(ok)) type(type(true)) type(upper("foo")) type({"bar": 1}) type({"bar": array}) type({"foo": "foo"}) type({"foo": f64}) type({"foo": false, "foo": foo}.Bar) upper("bar") not in foo upper("foo" + "foo") upper("foo") == toJSON("bar") upper(foo.Bar) upper(foo.String()) upper(foo?.Bar) upper(foo?.String()) upper(greet("bar")) upper(greet("foo")) upper(last(list).Bar) upper(lower("bar")) upper(lower("foo")) upper(reduce(list, #)?.Bar) upper(string("foo")) upper(string(0.5)) upper(string(1)) upper(string(add)) upper(string(array)) upper(string(f32)) upper(string(i32)) upper(string(i64)) upper(string(list)) upper(string(nil)) upper(string(score)) upper(string(true)) upper(toBase64("bar")) upper(toBase64("foo")) upper(toJSON("foo")) upper(toJSON(1)) upper(toJSON(f32)) upper(toJSON(false)) upper(toJSON(foo)) upper(toJSON(i)) upper(toJSON(i32)) upper(toJSON(list)) upper(toJSON(nil)) upper(toJSON(true)) upper(trim("bar")) upper(trim("foo")) upper(trimSuffix("bar")) upper(trimSuffix("foo")) upper(type("bar")) upper(type("foo")) upper(type(array)) upper(type(div)) upper(type(f32)) upper(type(foo.Bar)) upper(type(greet)) upper(type(i)) upper(type(i32)) upper(type(list)) upper(type(nil)) upper(type(ok)) upper(type(score)) upper(type(true)) upper(upper("foo")) values(groupBy(array, "bar")) values(groupBy(array, "foo")) values(groupBy(array, #)) values(groupBy(array, 0.5)) values(groupBy(array, 1)) values(groupBy(array, foo)) values(groupBy(array, i)) values(groupBy(list, #)) values(groupBy(list, 1)) values(groupBy(list, i)) values(groupBy(list, i32)) values(groupBy(list, true)) values({"bar": "bar"}) values({"bar": array}) values({"foo": add, "bar": div}) values({"foo": ok}) {"bar": "bar" <= "foo"} {"bar": "bar", "bar": half}.add {"bar": "bar", "bar": i}.Qux {"bar": "bar", "bar": i}.String {"bar": "bar", "foo": 0.5}.i64 {"bar": "bar", "foo": i64}?.Qux {"bar": "bar", "foo": score}.f32 {"bar": "bar"}.String?.foo {"bar": "bar"}.array {"bar": "bar"}.f64 {"bar": "bar"}.greet {"bar": "bar"}.list {"bar": "bar"}.ok {"bar": "bar"}?.Qux {"bar": "bar"}?.array {"bar": "bar"}?.half {"bar": "bar"}?.list {"bar": "foo", "bar": div}.half {"bar": "foo", "foo": f32}.String {"bar": "foo", "foo": i64}.ok?.f64 {"bar": "foo", "foo": ok}?.i64 {"bar": "foo"}.Bar {"bar": "foo"}.f32 {"bar": "foo"}.foo {"bar": "foo"}.half {"bar": "foo"}.i {"bar": "foo"}.i64 {"bar": "foo"}?.String {"bar": "foo"}?.f32 {"bar": "foo"}?.foo {"bar": "foo"}?.greet {"bar": "foo"}?.i {"bar": "foo"}?.i32 {"bar": "foo"}?.i?.String() {"bar": "foo"}?.list {"bar": "foo"}?.ok {"bar": -0.5} {"bar": -f32} {"bar": -f64} {"bar": -i32} {"bar": 0.5 != nil} {"bar": 0.5 * 1}.foo {"bar": 0.5, "bar": 0.5}.half {"bar": 0.5, "bar": add, "foo": i32}.list {"bar": 0.5, "bar": i}?.add {"bar": 0.5, "bar": list}?.div {"bar": 0.5, "bar": nil, "bar": nil}.i32 {"bar": 0.5, "bar": ok, "foo": 1}?.String {"bar": 0.5, "bar": true}.score {"bar": 0.5, "foo": 0.5}?.f32 {"bar": 0.5, "foo": array}?.list {"bar": 0.5, "foo": f32}.i32?.Bar {"bar": 0.5, "foo": ok}?.array {"bar": 0.5}.Qux {"bar": 0.5}.String {"bar": 0.5}.add {"bar": 0.5}.array {"bar": 0.5}.f32 {"bar": 0.5}.f64 {"bar": 0.5}.half {"bar": 0.5}.i {"bar": 0.5}.i32 {"bar": 0.5}.i64 {"bar": 0.5}.ok {"bar": 0.5}?.Bar {"bar": 0.5}?.Qux {"bar": 0.5}?.String {"bar": 0.5}?.div {"bar": 0.5}?.foo {"bar": 0.5}?.greet {"bar": 0.5}?.half {"bar": 0.5}?.i {"bar": 0.5}?.i32 {"bar": 0.5}?.i64 {"bar": 0.5}?.list {"bar": 0.5}?.score {"bar": 1 * i} {"bar": 1 ** 0.5} {"bar": 1 / 0.5} {"bar": 1 / f32} {"bar": 1 ^ 1} {"bar": 1, "bar": add, "foo": "bar"}?.add {"bar": 1, "bar": add}.div {"bar": 1, "bar": f32}?.Bar {"bar": 1, "bar": f64, "foo": array}.ok {"bar": 1, "foo": "bar"}.half {"bar": 1, "foo": array, "bar": score}?.i {"bar": 1, "foo": i}?.list {"bar": 1, "foo": i}?.ok {"bar": 1, "foo": ok}?.f32 {"bar": 1, "foo": score}.f64 {"bar": 1}.String {"bar": 1}.add {"bar": 1}.f32 {"bar": 1}.foo {"bar": 1}.greet {"bar": 1}.half {"bar": 1}.i {"bar": 1}.i32 {"bar": 1}.list {"bar": 1}.score {"bar": 1}?.Qux {"bar": 1}?.add {"bar": 1}?.div {"bar": 1}?.f32 {"bar": 1}?.f64 {"bar": 1}?.i {"bar": 1}?.i32 {"bar": 1}?.i64 {"bar": 1}?.list {"bar": 1}?.ok {"bar": add, "bar": half}.div {"bar": add, "bar": i, "bar": ok}?.foo {"bar": add, "bar": list} {"bar": add, "bar": ok, "foo": 1}?.ok {"bar": add, "foo": "foo"}?.f64 {"bar": add} {"bar": add}.Qux {"bar": add}.String {"bar": add}.add {"bar": add}.array {"bar": add}.div {"bar": add}.half {"bar": add}?.Qux {"bar": add}?.String {"bar": add}?.add {"bar": add}?.array {"bar": add}?.div {"bar": add}?.f64 {"bar": add}?.f64 != half {"bar": add}?.half {"bar": add}?.ok {"bar": add}?.score?.div {"bar": array, "bar": "bar"}?.i {"bar": array, "bar": array}?.foo {"bar": array, "bar": f32} {"bar": array, "bar": nil}.i64 {"bar": array, "foo": f32}?.String {"bar": array, "foo": f64} {"bar": array, "foo": half}?.add {"bar": array, "foo": i32} {"bar": array, "foo": score} {"bar": array} {"bar": array}.Bar {"bar": array}.div {"bar": array}.div?.Qux {"bar": array}.greet {"bar": array}.i {"bar": array}.i64 {"bar": array}.list {"bar": array}.score {"bar": array}?.add?.ok {"bar": array}?.div {"bar": array}?.f64 {"bar": array}?.greet {"bar": array}?.half {"bar": array}?.i64 {"bar": array}?.ok {"bar": div, "bar": array, "bar": 0.5}.i64 {"bar": div, "bar": div}?.f32 {"bar": div, "bar": foo}.foo {"bar": div, "bar": ok} {"bar": div, "foo": 1, "bar": ok}.Qux {"bar": div, "foo": false}?.String {"bar": div, "foo": foo, "foo": score}.Bar {"bar": div, "foo": greet}.i {"bar": div, "foo": greet}?.ok {"bar": div, "foo": score} {"bar": div} {"bar": div}.array {"bar": div}.f32 {"bar": div}.f64 {"bar": div}.i64?.Qux {"bar": div}.list {"bar": div}.ok {"bar": div}?.Bar {"bar": div}?.array {"bar": div}?.f64 {"bar": div}?.greet {"bar": div}?.half {"bar": div}?.list {"bar": div}?.ok {"bar": div}?.score {"bar": f32 ** i} {"bar": f32 - 0.5} {"bar": f32 >= 0.5} {"bar": f32 ^ 1} {"bar": f32, "bar": "foo"}.add {"bar": f32, "bar": false}?.Bar {"bar": f32, "bar": true}?.String {"bar": f32, "foo": add, "foo": false}?.String {"bar": f32, "foo": f32}.ok {"bar": f32, "foo": f64} {"bar": f32, "foo": half, "foo": ok} {"bar": f32, "foo": half} {"bar": f32, "foo": list}?.f32 {"bar": f32, "foo": nil}?.f64?.foo {"bar": f32} {"bar": f32}.Qux {"bar": f32}.div {"bar": f32}.f64 {"bar": f32}.greet {"bar": f32}.i {"bar": f32}.i32 {"bar": f32}.i64 {"bar": f32}?.Bar {"bar": f32}?.String {"bar": f32}?.array {"bar": f32}?.f64 {"bar": f32}?.half {"bar": f32}?.list {"bar": f64 + 1} {"bar": f64 == i32} {"bar": f64 > 0.5} {"bar": f64 ^ i32} {"bar": f64, "bar": "bar"}.i {"bar": f64, "bar": foo}?.i {"bar": f64, "bar": i64}?.i64 {"bar": f64, "bar": i}.f64 {"bar": f64, "bar": true}?.i {"bar": f64, "foo": 0.5, "foo": score}.ok {"bar": f64, "foo": 1}.f32 {"bar": f64, "foo": f64}?.score {"bar": f64, "foo": i}?.Qux?.f64 {"bar": f64} {"bar": f64}.array {"bar": f64}.f32?.Bar {"bar": f64}.f64 {"bar": f64}.foo {"bar": f64}.i {"bar": f64}.i32 {"bar": f64}.ok {"bar": f64}?.Bar {"bar": f64}?.Bar?.Qux {"bar": f64}?.add {"bar": f64}?.div {"bar": f64}?.f32 {"bar": f64}?.foo {"bar": f64}?.i {"bar": f64}?.i64 {"bar": f64}?.list {"bar": f64}?.ok {"bar": false, "bar": array}?.list {"bar": false, "bar": i32}?.div {"bar": false, "bar": i}?.i64 {"bar": false, "bar": nil}.ok {"bar": false}.Bar {"bar": false}.Qux {"bar": false}.array {"bar": false}.f32 {"bar": false}.f64 {"bar": false}.half {"bar": false}.i {"bar": false}.i32 {"bar": false}.ok {"bar": false}.score {"bar": false}?.Bar {"bar": false}?.array {"bar": false}?.div {"bar": false}?.foo {"bar": false}?.half {"bar": false}?.i {"bar": false}?.list {"bar": false}?.ok {"bar": filter(list, ok)} {"bar": float(0.5)} {"bar": floor(0.5)}.score {"bar": floor(i32)} {"bar": foo != nil, "foo": array} {"bar": foo, "bar": "foo", "bar": score}?.score {"bar": foo, "bar": 1, "bar": score}?.ok {"bar": foo, "bar": greet} {"bar": foo, "bar": i}?.i {"bar": foo, "bar": score}?.ok {"bar": foo, "foo": 0.5, "foo": ok}?.half {"bar": foo, "foo": 0.5}.score {"bar": foo, "foo": 1, "foo": i}?.add {"bar": foo, "foo": f64} {"bar": foo, "foo": f64}.Bar {"bar": foo.Bar} {"bar": foo.String()} {"bar": foo?.Qux, "bar": f32} {"bar": foo?.String} {"bar": foo} {"bar": foo}.Bar {"bar": foo}.array {"bar": foo}.f32 {"bar": foo}.half {"bar": foo}.i {"bar": foo}.list {"bar": foo}.ok {"bar": foo}?.Bar {"bar": foo}?.add {"bar": foo}?.greet {"bar": foo}?.i {"bar": foo}?.i32 {"bar": foo}?.i64 {"bar": foo}?.list {"bar": foo}?.ok {"bar": foo}?.score {"bar": get(list, i32)} {"bar": greet("foo")} {"bar": greet, "bar": 0.5}.i32 {"bar": greet, "bar": 1}.Bar {"bar": greet, "bar": f32}.Bar {"bar": greet, "bar": i32} {"bar": greet, "bar": not ok} {"bar": greet, "foo": "bar"}.ok {"bar": greet, "foo": f64} {"bar": greet, "foo": false, "bar": ok}.i32 {"bar": greet, "foo": i32} {"bar": greet} {"bar": greet}.Bar {"bar": greet}.array {"bar": greet}.f32 {"bar": greet}.greet {"bar": greet}.half {"bar": greet}.list {"bar": greet}?.Qux {"bar": greet}?.div {"bar": greet}?.f32 {"bar": greet}?.f64 {"bar": greet}?.greet {"bar": greet}?.half {"bar": greet}?.i32 {"bar": greet}?.ok {"bar": greet}?.score {"bar": groupBy(array, f32)} {"bar": half == nil} {"bar": half(f64)} {"bar": half, "bar": add, "bar": f64}?.i32 {"bar": half, "bar": foo} {"bar": half, "bar": list} {"bar": half, "bar": score} {"bar": half, "foo": 1}?.i64 {"bar": half, "foo": list} {"bar": half, "foo": ok, "bar": i} {"bar": half, "foo": ok}.Qux {"bar": half, "foo": true}?.String {"bar": half} {"bar": half}.Bar?.i {"bar": half}.Qux {"bar": half}.String {"bar": half}.div?.i {"bar": half}.f32 {"bar": half}.foo {"bar": half}.half {"bar": half}.i32 {"bar": half}.list {"bar": half}.list?.String() {"bar": half}?.Bar {"bar": half}?.String {"bar": half}?.array {"bar": half}?.f32 {"bar": half}?.greet {"bar": half}?.i32 {"bar": half}?.list {"bar": i % i32} {"bar": i ** f64} {"bar": i < 1}?.half {"bar": i, "bar": 1}.add {"bar": i, "bar": 1}?.i64 {"bar": i, "bar": array}?.half {"bar": i, "bar": div}.ok {"bar": i, "bar": f64, "bar": "foo"}?.foo {"bar": i, "bar": f64, "bar": nil}.i32 {"bar": i, "bar": score} {"bar": i, "foo": half} {"bar": i, "foo": i32}?.score {"bar": i, "foo": nil}?.String {"bar": i32 ^ 0.5} {"bar": i32 ^ f64} {"bar": i32, "bar": list} {"bar": i32, "foo": "bar"}.i64 {"bar": i32, "foo": array}.div {"bar": i32, "foo": f64, "foo": add}.f64 {"bar": i32, "foo": foo}?.add {"bar": i32, "foo": ok}.ok {"bar": i32} {"bar": i32}.Qux {"bar": i32}.f64 {"bar": i32}.i {"bar": i32}.i32 {"bar": i32}.list {"bar": i32}.ok {"bar": i32}.score {"bar": i32}?.Qux {"bar": i32}?.add {"bar": i32}?.array {"bar": i32}?.div {"bar": i32}?.f32 {"bar": i32}?.i32 {"bar": i32}?.list {"bar": i32}?.ok {"bar": i64 + 1} {"bar": i64 <= 0.5} {"bar": i64 == 0.5} {"bar": i64 in array} {"bar": i64, "bar": !ok} {"bar": i64, "bar": 0.5}.f32 {"bar": i64, "bar": greet}.array {"bar": i64, "bar": score}.ok {"bar": i64, "foo": nil}?.i32 {"bar": i64, "foo": ok} {"bar": i64, "foo": ok}?.f32 {"bar": i64} {"bar": i64}.array?.Bar {"bar": i64}.div {"bar": i64}.f32 {"bar": i64}.f64 {"bar": i64}.i {"bar": i64}.list {"bar": i64}.ok {"bar": i64}.score {"bar": i64}?.div {"bar": i64}?.f32 {"bar": i64}?.f64 {"bar": i64}?.half {"bar": i64}?.i {"bar": i64}?.i32 {"bar": i64}?.i?.ok {"bar": i64}?.list {"bar": int(f64)} {"bar": i} {"bar": i}.add {"bar": i}.array {"bar": i}.div?.Qux.div {"bar": i}.f64 {"bar": i}.half {"bar": i}.i {"bar": i}.i64 {"bar": i}.list {"bar": i}?.String {"bar": i}?.array {"bar": i}?.f64 {"bar": i}?.foo {"bar": i}?.greet {"bar": i}?.i {"bar": i}?.i32 {"bar": i}?.i64 {"bar": i}?.score {"bar": list == nil} {"bar": list, "bar": half}?.Bar {"bar": list, "bar": score} {"bar": list, "foo": "foo"}.String {"bar": list, "foo": 1, "foo": nil}.score {"bar": list, "foo": 1, "foo": score}?.array {"bar": list, "foo": array}?.i64 {"bar": list, "foo": f64}.div?.Qux {"bar": list, "foo": f64}.list {"bar": list, "foo": half}?.f32 {"bar": list, "foo": i64}?.array {"bar": list, "foo": nil}.i64 {"bar": list[i32:i32]} {"bar": list} {"bar": list}.String {"bar": list}.add {"bar": list}.array {"bar": list}.array?.i64 {"bar": list}.f64 {"bar": list}.greet {"bar": list}.i {"bar": list}.list {"bar": list}?.Bar {"bar": list}?.Qux {"bar": list}?.add {"bar": list}?.div {"bar": list}?.f64 {"bar": list}?.i64 {"bar": list}?.score {"bar": lower("bar")} {"bar": map(array, #)} {"bar": map(array, i)} {"bar": map(list, #)} {"bar": nil != "bar"} {"bar": nil != nil} {"bar": nil == 0.5} {"bar": nil == nil} {"bar": nil, "bar": "bar"}?.i32 {"bar": nil, "bar": add, "bar": i}.add {"bar": nil, "bar": foo}?.list {"bar": nil, "foo": "foo"}.f64 {"bar": nil, "foo": 1, "foo": add}.ok {"bar": nil, "foo": foo}?.add {"bar": nil, "foo": i}?.f64 {"bar": nil, "foo": list}?.f32 {"bar": nil}.Bar {"bar": nil}.add {"bar": nil}.div {"bar": nil}.f32 {"bar": nil}.foo {"bar": nil}.greet {"bar": nil}.half {"bar": nil}.i {"bar": nil}.i32 {"bar": nil}.i32?.greet {"bar": nil}.i64 {"bar": nil}.i?.f64 {"bar": nil}.list {"bar": nil}.ok {"bar": nil}?.Qux {"bar": nil}?.String {"bar": nil}?.add {"bar": nil}?.div {"bar": nil}?.f32 {"bar": nil}?.f64 {"bar": nil}?.half {"bar": nil}?.i {"bar": nil}?.i32 {"bar": nil}?.list {"bar": nil}?.ok {"bar": none(list, ok)} {"bar": not true} {"bar": ok ? "bar" : i} {"bar": ok ? i32 : "foo"} {"bar": ok ? nil : greet} {"bar": ok, "bar": 1, "foo": f64}.half {"bar": ok, "bar": array} {"bar": ok, "bar": i64, "foo": 1}?.Qux {"bar": ok, "bar": i} {"bar": ok, "bar": list}?.div {"bar": ok, "bar": ok}.f32 {"bar": ok, "foo": 0.5}?.score {"bar": ok, "foo": 1}.i {"bar": ok, "foo": greet} {"bar": ok, "foo": half} {"bar": ok, "foo": list} {"bar": ok, "foo": list}?.f64 {"bar": ok, "foo": nil}?.i32 {"bar": ok, "foo": ok}.div {"bar": ok} {"bar": ok}.Bar {"bar": ok}.div {"bar": ok}.f32 {"bar": ok}.greet {"bar": ok}.i32 {"bar": ok}.i64 {"bar": ok}.list {"bar": ok}.ok {"bar": ok}.score {"bar": ok}?.Qux {"bar": ok}?.add {"bar": ok}?.f32 {"bar": ok}?.i32 {"bar": ok}?.i64 {"bar": ok}?.list {"bar": ok}?.score {"bar": one(list, false)} {"bar": reduce(array, i)}.i64 {"bar": reduce(list, half)} {"bar": score(i)} {"bar": score, "bar": "bar", "bar": "foo"}?.f32 {"bar": score, "bar": add}.String {"bar": score, "bar": i64}.f32 {"bar": score, "bar": nil}.i {"bar": score, "foo": div} {"bar": score, "foo": foo}.i {"bar": score, "foo": half, "foo": i}?.array {"bar": score, "foo": half} {"bar": score, "foo": score}?.greet {"bar": score} {"bar": score}.add {"bar": score}.array {"bar": score}.div {"bar": score}.f64 {"bar": score}.foo {"bar": score}.half {"bar": score}.list {"bar": score}?.String {"bar": score}?.array {"bar": score}?.f32 {"bar": score}?.foo {"bar": score}?.half {"bar": score}?.i {"bar": score}?.i32 {"bar": score}?.list {"bar": score}?.score {"bar": string(0.5)} {"bar": string(i64)} {"bar": string(ok)} {"bar": toJSON(list)} {"bar": true == false} {"bar": true, "bar": f64}?.score {"bar": true, "bar": i32}.array {"bar": true, "foo": nil}?.f32 {"bar": true}.Bar {"bar": true}.Qux {"bar": true}.String {"bar": true}.div {"bar": true}.half {"bar": true}.i32 {"bar": true}?.Bar {"bar": true}?.add {"bar": true}?.array {"bar": true}?.div {"bar": true}?.half {"bar": true}?.i32 {"bar": true}?.i64 {"bar": type(greet)}.Bar {"bar": type(half)} {"bar": type(score)} {"foo": !ok} {"foo": "bar" < "bar"} {"foo": "bar" > "bar"} {"foo": "bar", "bar": list}.div {"foo": "bar", "bar": nil}.f64 {"foo": "bar", "foo": 0.5}?.add {"foo": "bar", "foo": 0.5}?.list {"foo": "bar", "foo": array}?.f64?.list() {"foo": "bar", "foo": list}.list {"foo": "bar"}.Bar {"foo": "bar"}.Qux {"foo": "bar"}.String {"foo": "bar"}.foo {"foo": "bar"}.half {"foo": "bar"}.i {"foo": "bar"}.i64 {"foo": "bar"}?.Bar {"foo": "bar"}?.String {"foo": "bar"}?.add {"foo": "bar"}?.array {"foo": "bar"}?.div {"foo": "bar"}?.f32 {"foo": "bar"}?.f64 {"foo": "bar"}?.foo {"foo": "bar"}?.half {"foo": "bar"}?.i32 {"foo": "bar"}?.score {"foo": "foo" <= "foo"} {"foo": "foo" endsWith "foo"} {"foo": "foo", "bar": false}.greet {"foo": "foo", "bar": half}?.String {"foo": "foo", "bar": list, "bar": div}?.String {"foo": "foo", "foo": add}?.f32 {"foo": "foo"}.Qux {"foo": "foo"}.div {"foo": "foo"}.f32 {"foo": "foo"}.i {"foo": "foo"}.i32 {"foo": "foo"}.list {"foo": "foo"}?.div {"foo": "foo"}?.f32 {"foo": "foo"}?.foo {"foo": "foo"}?.i {"foo": "foo"}?.i32 {"foo": "foo"}?.score {"foo": -0.5} {"foo": -1} {"foo": -f64} {"foo": -i64} {"foo": 0.5 != 0.5} {"foo": 0.5 ** f64} {"foo": 0.5 < i64}.div {"foo": 0.5 <= 0.5} {"foo": 0.5, "bar": 0.5}.String {"foo": 0.5, "bar": 0.5}.foo {"foo": 0.5, "bar": 0.5}?.score {"foo": 0.5, "bar": 1}?.div {"foo": 0.5, "bar": i64}.i32 {"foo": 0.5, "bar": list}?.i64 {"foo": 0.5, "foo": 1}.Qux {"foo": 0.5, "foo": array}.i64 {"foo": 0.5, "foo": f64}.i {"foo": 0.5, "foo": false, "bar": list}.add {"foo": 0.5, "foo": greet}.i32 {"foo": 0.5, "foo": score}.foo {"foo": 0.5}.Qux?.half {"foo": 0.5}.String {"foo": 0.5}.add {"foo": 0.5}.array {"foo": 0.5}.div {"foo": 0.5}.f32 {"foo": 0.5}.half {"foo": 0.5}.i64 {"foo": 0.5}.list {"foo": 0.5}.score {"foo": 0.5}?.Bar {"foo": 0.5}?.String {"foo": 0.5}?.div {"foo": 0.5}?.f32 {"foo": 0.5}?.f64 {"foo": 0.5}?.half {"foo": 0.5}?.i {"foo": 0.5}?.list {"foo": 0.5}?.ok {"foo": 1 / i64} {"foo": 1 == f32} {"foo": 1, "bar": nil}?.add {"foo": 1, "bar": score}.greet {"foo": 1, "foo": 1}.f64 {"foo": 1, "foo": f64}.i {"foo": 1, "foo": false}?.f32 {"foo": 1, "foo": half}?.f32 {"foo": 1, "foo": ok}.Bar {"foo": 1, "foo": ok}.f32 {"foo": 1, "foo": ok}.i32 {"foo": 1, "foo": score}.half {"foo": 1}.Bar {"foo": 1}.add {"foo": 1}.div {"foo": 1}.f32 {"foo": 1}.f64 {"foo": 1}.foo {"foo": 1}.greet {"foo": 1}.half {"foo": 1}.i {"foo": 1}.i64 {"foo": 1}.list {"foo": 1}?.String {"foo": 1}?.add {"foo": 1}?.f64 {"foo": 1}?.greet {"foo": 1}?.half {"foo": 1}?.list {"foo": 1}?.ok {"foo": abs(i64)} {"foo": add, "bar": half} {"foo": add, "bar": nil}.i {"foo": add, "bar": nil}?.i {"foo": add, "bar": ok, "foo": array}?.i32 {"foo": add, "foo": 1, "bar": i32}.add {"foo": add, "foo": array}?.f32 {"foo": add, "foo": foo}?.i64 {"foo": add, "foo": half} {"foo": add, "foo": score, "bar": i32}.list {"foo": add} {"foo": add}.array {"foo": add}.div {"foo": add}.f32 {"foo": add}.foo {"foo": add}.half {"foo": add}.i {"foo": add}.i32 {"foo": add}.i?.score {"foo": add}.list {"foo": add}?.Bar {"foo": add}?.Qux {"foo": add}?.String {"foo": add}?.div {"foo": add}?.f32 {"foo": add}?.foo {"foo": add}?.greet {"foo": add}?.half {"foo": add}?.i {"foo": add}?.i64 {"foo": add}?.score {"foo": array, "bar": "bar"}.add {"foo": array, "bar": 0.5}?.div {"foo": array, "bar": add}.ok {"foo": array, "bar": array}.f32 {"foo": array, "bar": i64}?.add {"foo": array, "bar": list} {"foo": array, "bar": nil}.half {"foo": array, "bar": ok, "bar": i} {"foo": array, "foo": "foo"}.array {"foo": array, "foo": array} {"foo": array, "foo": f32, "foo": half}.ok {"foo": array, "foo": f64} {"foo": array, "foo": list} {"foo": array} {"foo": array}.Bar {"foo": array}.Qux {"foo": array}.f32 {"foo": array}.foo {"foo": array}.greet {"foo": array}.i {"foo": array}.i32 {"foo": array}.i64 {"foo": array}.score {"foo": array}?.Qux {"foo": array}?.add {"foo": array}?.array {"foo": array}?.greet {"foo": array}?.i64?.add {"foo": array}?.list {"foo": array}?.ok {"foo": div, "bar": "foo"}.array {"foo": div, "bar": array} {"foo": div, "bar": foo, "foo": true}?.i64 {"foo": div, "bar": half} {"foo": div, "bar": i64} {"foo": div, "foo": array} {"foo": div, "foo": f32} {"foo": div, "foo": greet}?.i64 {"foo": div} {"foo": div}.Qux {"foo": div}.array {"foo": div}.div {"foo": div}.f32 {"foo": div}.greet?.i {"foo": div}.i32 {"foo": div}.i64 {"foo": div}?.Bar {"foo": div}?.Qux {"foo": div}?.String {"foo": div}?.div {"foo": div}?.greet {"foo": div}?.half {"foo": div}?.i32 {"foo": div}?.i64 {"foo": div}?.list {"foo": div}?.score {"foo": f32 > 1} {"foo": f32 >= 1} {"foo": f32, "bar": 0.5}.list {"foo": f32, "bar": div} {"foo": f32, "bar": f32} {"foo": f32, "bar": f64} {"foo": f32, "bar": greet}.greet {"foo": f32, "bar": half} {"foo": f32, "bar": ok}?.add {"foo": f32, "bar": score}?.i64 {"foo": f32, "foo": "foo"}.ok {"foo": f32, "foo": add}?.half?.f64() {"foo": f32, "foo": foo}?.half {"foo": f32} {"foo": f32}.Qux {"foo": f32}.add {"foo": f32}.f32 {"foo": f32}.foo {"foo": f32}.greet {"foo": f32}.half {"foo": f32}.i {"foo": f32}.i32 {"foo": f32}.i64 {"foo": f32}.list {"foo": f32}.score?.greet {"foo": f32}?.Bar {"foo": f32}?.String {"foo": f32}?.array {"foo": f32}?.f64?.i {"foo": f32}?.i {"foo": f32}?.ok {"foo": f64 < f64} {"foo": f64 > f32} {"foo": f64 >= 0.5} {"foo": f64 >= f32} {"foo": f64 in array} {"foo": f64, "bar": 0.5}.greet {"foo": f64, "bar": add, "foo": greet}.Bar {"foo": f64, "bar": list}.i64 {"foo": f64, "bar": sum(array)} {"foo": f64, "bar": true}?.greet {"foo": f64, "foo": list, "foo": i}?.add {"foo": f64} {"foo": f64}.Bar {"foo": f64}.Qux {"foo": f64}.div {"foo": f64}.f32 {"foo": f64}.f64 {"foo": f64}.greet {"foo": f64}.i32 {"foo": f64}.list {"foo": f64}.ok {"foo": f64}?.String {"foo": f64}?.f32 {"foo": f64}?.f64 {"foo": f64}?.foo {"foo": f64}?.greet {"foo": f64}?.i32 {"foo": f64}?.i64 {"foo": f64}?.ok {"foo": f64}?.ok?.ok {"foo": f64}?.score {"foo": false or false}.array {"foo": false, "bar": 0.5, "foo": add}.score {"foo": false, "foo": foo, "bar": half}.array {"foo": false, "foo": score, "foo": nil}?.div {"foo": false, "foo": true}?.i32 {"foo": false}.array {"foo": false}.i {"foo": false}.ok {"foo": false}?.f32 {"foo": false}?.f64 {"foo": false}?.list {"foo": foo == nil} {"foo": foo, "bar": div} {"foo": foo, "bar": foo} {"foo": foo, "bar": ok}.i32 {"foo": foo, "bar": {"foo": 1}} {"foo": foo, "foo": add} {"foo": foo, "foo": half} {"foo": foo, "foo": i} {"foo": foo, "foo": ok} {"foo": foo, "foo": score, "foo": f64}.i {"foo": foo.Bar} {"foo": foo.String, "bar": foo} {"foo": foo.String} {"foo": foo?.Bar} {"foo": foo?.Qux} {"foo": foo?.String()} {"foo": foo?.String} {"foo": foo} {"foo": foo}.Bar?.Bar {"foo": foo}.Qux {"foo": foo}.String {"foo": foo}.String?.String {"foo": foo}.f32 {"foo": foo}.greet {"foo": foo}.half {"foo": foo}.i64 {"foo": foo}?.Qux {"foo": foo}?.add {"foo": foo}?.array {"foo": foo}?.array?.Bar {"foo": foo}?.f64 {"foo": foo}?.greet {"foo": foo}?.i32 {"foo": foo}?.list {"foo": foo}?.ok {"foo": greet("foo")} {"foo": greet, "bar": "bar"}?.i32 {"foo": greet, "bar": i64} {"foo": greet, "bar": i}.list {"foo": greet, "foo": add}.String {"foo": greet, "foo": nil}?.add {"foo": greet} {"foo": greet}.Bar {"foo": greet}.Qux {"foo": greet}.String {"foo": greet}.add {"foo": greet}.array {"foo": greet}.f32 {"foo": greet}.i {"foo": greet}.i32 {"foo": greet}.i64 {"foo": greet}.i64?.greet {"foo": greet}.ok {"foo": greet}.score {"foo": greet}?.Qux {"foo": greet}?.array {"foo": greet}?.div {"foo": greet}?.f32 {"foo": greet}?.f64 {"foo": greet}?.i32 {"foo": greet}?.i64 {"foo": greet}?.list {"foo": greet}?.ok {"foo": greet}?.score {"foo": groupBy(array, 1)} {"foo": groupBy(list, #)} {"foo": half, "bar": "foo"}?.half {"foo": half, "bar": add, "foo": true}?.array {"foo": half, "bar": array}.half {"foo": half, "bar": greet}?.half {"foo": half, "bar": half}?.i {"foo": half, "bar": list, "foo": 1}?.f64 {"foo": half, "bar": list} {"foo": half, "bar": true}?.Qux {"foo": half, "foo": 1}?.i32 {"foo": half, "foo": div, "foo": array}?.i32 {"foo": half, "foo": f64} {"foo": half, "foo": list, "foo": half}.half {"foo": half, "foo": score, "foo": list}.String {"foo": half} {"foo": half}.Bar {"foo": half}.String {"foo": half}.add {"foo": half}.div {"foo": half}.f32 {"foo": half}.foo {"foo": half}.half {"foo": half}.i {"foo": half}.i64 {"foo": half}.ok {"foo": half}.score {"foo": half}?.Bar {"foo": half}?.Qux {"foo": half}?.String {"foo": half}?.div {"foo": half}?.f32 {"foo": half}?.foo {"foo": half}?.i32 {"foo": half}?.i64 {"foo": half}?.score {"foo": i != 1} {"foo": i - f64} {"foo": i / 1} {"foo": i ^ 1} {"foo": i, "bar": 0.5}?.half {"foo": i, "bar": f32} {"foo": i, "bar": foo} {"foo": i, "bar": list}.foo {"foo": i, "foo": "bar"}?.div?.f32 {"foo": i, "foo": 1}.list {"foo": i, "foo": 1}?.list {"foo": i, "foo": add} {"foo": i, "foo": array, "bar": 0.5}?.f32 {"foo": i, "foo": half}?.list {"foo": i, "foo": score} {"foo": i, "foo": score}?.f32 {"foo": i32 != i} {"foo": i32 * 0.5} {"foo": i32 + 1} {"foo": i32 - f32}.foo {"foo": i32 - f64} {"foo": i32 / 1} {"foo": i32 < 1} {"foo": i32, "bar": 0.5, "bar": foo}.i64 {"foo": i32, "bar": foo}?.score {"foo": i32, "bar": nil}?.ok {"foo": i32, "foo": false, "bar": f32}?.foo {"foo": i32, "foo": greet}?.greet {"foo": i32} {"foo": i32}.i {"foo": i32}.ok {"foo": i32}?.Bar {"foo": i32}?.String {"foo": i32}?.add {"foo": i32}?.f32 {"foo": i32}?.f64 {"foo": i32}?.i {"foo": i32}?.i32 {"foo": i32}?.i64 {"foo": i32}?.list {"foo": i32}?.score {"foo": i64 % 1} {"foo": i64 * f32} {"foo": i64 .. i64} {"foo": i64, "bar": array} {"foo": i64, "foo": array}.f32 {"foo": i64, "foo": f32} {"foo": i64, "foo": i32}?.foo {"foo": i64, "foo": i64, "bar": f64}.foo {"foo": i64, "foo": i64} {"foo": i64, "foo": i64}.greet {"foo": i64, "foo": i64}?.foo {"foo": i64} {"foo": i64}.Bar {"foo": i64}.array {"foo": i64}.div {"foo": i64}.foo {"foo": i64}.greet {"foo": i64}.half {"foo": i64}.i {"foo": i64}.i32 {"foo": i64}.list {"foo": i64}?.Qux {"foo": i64}?.add {"foo": i64}?.array {"foo": i64}?.f32 {"foo": i64}?.f64 {"foo": i64}?.half {"foo": i64}?.i32 {"foo": i64}?.i32?.f32 {"foo": i64}?.i64 {"foo": i64}?.score?.list {"foo": int(i)} {"foo": int(i32)} {"foo": int(i64)} {"foo": i} {"foo": i}.Bar {"foo": i}.String {"foo": i}.add {"foo": i}.array {"foo": i}.f64 {"foo": i}.greet {"foo": i}.i {"foo": i}.ok {"foo": i}?.div {"foo": i}?.greet {"foo": i}?.i {"foo": i}?.i32 {"foo": i}?.i64 {"foo": i}?.score {"foo": last(list)} {"foo": len(list)} {"foo": list, "bar": add} {"foo": list, "bar": all(list, false)} {"foo": list, "bar": array} {"foo": list, "bar": f32}.f64 {"foo": list, "bar": half} {"foo": list, "bar": i32, "bar": score}.array {"foo": list, "bar": true}?.foo {"foo": list} {"foo": list}.Qux {"foo": list}.String {"foo": list}.add {"foo": list}.div {"foo": list}.f32 {"foo": list}.greet {"foo": list}.half {"foo": list}.i {"foo": list}.i32 {"foo": list}?.String {"foo": list}?.div {"foo": list}?.f32 {"foo": list}?.foo {"foo": list}?.i {"foo": list}?.i32 {"foo": list}?.i64 {"foo": list}?.ok {"foo": list}?.score {"foo": map(array, #)} {"foo": map(array, i64)} {"foo": nil, "bar": 0.5}.ok {"foo": nil, "bar": add, "bar": f32}?.list {"foo": nil, "bar": div, "bar": 1}.i64 {"foo": nil, "bar": f32}.score {"foo": nil, "bar": foo}?.String {"foo": nil, "bar": score}?.ok?.div {"foo": nil, "foo": "foo"}.Bar {"foo": nil, "foo": greet}.String {"foo": nil, "foo": half}.f64 {"foo": nil, "foo": i64, "bar": f64}?.list {"foo": nil, "foo": i}.div {"foo": nil, "foo": list}.add {"foo": nil, "foo": list}?.array {"foo": nil, "foo": nil}.ok {"foo": nil}.array?.half() {"foo": nil}.div {"foo": nil}.f32 {"foo": nil}.f64 {"foo": nil}.half {"foo": nil}.i {"foo": nil}.i32 {"foo": nil}.i64?.Bar() {"foo": nil}.list {"foo": nil}.ok {"foo": nil}.score {"foo": nil}?.Bar {"foo": nil}?.Bar?.score {"foo": nil}?.add {"foo": nil}?.array {"foo": nil}?.f64 {"foo": nil}?.foo {"foo": nil}?.half {"foo": nil}?.i32 {"foo": nil}?.i64 {"foo": nil}?.list {"foo": ok == false} {"foo": ok, "bar": "foo"}?.i64 {"foo": ok, "bar": add}.String {"foo": ok, "bar": f32} {"foo": ok, "foo": half}.ok {"foo": ok, "foo": list} {"foo": ok} {"foo": ok}.Bar {"foo": ok}.Bar?.i {"foo": ok}.String {"foo": ok}.array {"foo": ok}.div {"foo": ok}.f64 {"foo": ok}.foo {"foo": ok}.i32 {"foo": ok}.i64 {"foo": ok}.ok {"foo": ok}?.Qux {"foo": ok}?.String {"foo": ok}?.String?.Bar {"foo": ok}?.array {"foo": ok}?.f32 {"foo": ok}?.foo {"foo": ok}?.greet {"foo": ok}?.half {"foo": ok}?.i32 {"foo": ok}?.i64 {"foo": ok}?.list {"foo": reduce(array, "foo")} {"foo": reduce(array, #)} {"foo": reduce(list, #).String()} {"foo": reduce(list, #)} {"foo": reduce(list, #)}?.list {"foo": score, "bar": add}.add {"foo": score, "bar": div} {"foo": score, "bar": f64} {"foo": score, "bar": false}?.array {"foo": score, "bar": false}?.i {"foo": score, "bar": true}.div?.i {"foo": score, "foo": 0.5}?.String {"foo": score, "foo": 1}.array {"foo": score, "foo": add} {"foo": score, "foo": array}.array {"foo": score, "foo": f32} {"foo": score, "foo": greet} fromJSON('5e2482') ================================================ FILE: test/fuzz/fuzz_env.go ================================================ package fuzz import ( "fmt" "github.com/expr-lang/expr" ) func NewEnv() map[string]any { return map[string]any{ "ok": true, "f64": .5, "f32": float32(.5), "i": 1, "i64": int64(1), "i32": int32(1), "array": []int{1, 2, 3, 4, 5}, "list": []Foo{{"bar"}, {"baz"}}, "foo": Foo{"bar"}, "add": func(a, b int) int { return a + b }, "div": func(a, b int) int { return a / b }, "half": func(a float64) float64 { return a / 2 }, "score": func(a int, x ...int) int { s := a for _, n := range x { s += n } return s }, "greet": func(name string) string { return "Hello, " + name }, } } func Func() expr.Option { return expr.Function("fn", func(params ...any) (any, error) { return fmt.Sprintf("fn(%v)", params), nil }) } type Foo struct { Bar string } func (f Foo) String() string { return "foo" } func (f Foo) Qux(s string) string { return f.Bar + s } ================================================ FILE: test/fuzz/fuzz_expr.dict ================================================ "{" "}" "," "[" "]" "(" ")" ":" "'" "\"" "0.1" "1.2" "2.3" "-3.4" "-4.5" "-5.6" "1e2" "2e3" "-3e4" "-4e5" "0" "1" "2" "-3" "-4" "0x" "true" "false" "not" "nil" "String" "ok" "f64" "f32" "i" "i64" "i32" "array" "list" "foo" "add" "div" "half" "score" "greet" "Foo" "Bar" "Qux" "all" "none" "any" "one" "filter" "map" "count" "find" "findIndex" "findLast" "findLastIndex" "len" "type" "abs" "int" "float" "string" "trim" "trimPrefix" "trimSuffix" "upper" "lower" "split" "splitAfter" "replace" "repeat" "join" "indexOf" "lastIndexOf" "hasPrefix" "hasSuffix" "max" "min" "toJSON" "fromJSON" "toBase64" "fromBase64" "now" "duration" "date" "first" "last" "get" "keys" "values" "sort" "sortBy" ================================================ FILE: test/fuzz/fuzz_test.go ================================================ package fuzz import ( _ "embed" "regexp" "strings" "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/vm" ) //go:embed fuzz_corpus.txt var fuzzCorpus string func FuzzExpr(f *testing.F) { corpus := strings.Split(strings.TrimSpace(fuzzCorpus), "\n") for _, s := range corpus { f.Add(s) } skip := []*regexp.Regexp{ regexp.MustCompile(`cannot fetch .* from .*`), regexp.MustCompile(`cannot get .* from .*`), regexp.MustCompile(`cannot slice`), regexp.MustCompile(`slice index out of range`), regexp.MustCompile(`error parsing regexp`), regexp.MustCompile(`integer divide by zero`), regexp.MustCompile(`interface conversion`), regexp.MustCompile(`invalid argument`), regexp.MustCompile(`invalid character`), regexp.MustCompile(`invalid operation`), regexp.MustCompile(`invalid duration`), regexp.MustCompile(`time: missing unit in duration`), regexp.MustCompile(`time: unknown unit .* in duration`), regexp.MustCompile(`unknown time zone`), regexp.MustCompile(`invalid location name`), regexp.MustCompile(`json: unsupported value`), regexp.MustCompile(`json: unsupported type`), regexp.MustCompile(`json: cannot unmarshal .* into Go value of type .*`), regexp.MustCompile(`unexpected end of JSON input`), regexp.MustCompile(`memory budget exceeded`), regexp.MustCompile(`using interface \{} as type .*`), regexp.MustCompile(`reflect.Value.MapIndex: value of type .* is not assignable to type .*`), regexp.MustCompile(`reflect: Call using .* as type .*`), regexp.MustCompile(`reflect: cannot use .* as type .* in .*`), regexp.MustCompile(`reflect: Call with too few input arguments`), regexp.MustCompile(`invalid number of arguments`), regexp.MustCompile(`reflect: call of reflect.Value.Call on .* Value`), regexp.MustCompile(`reflect: call of reflect.Value.Index on map Value`), regexp.MustCompile(`reflect: call of reflect.Value.Len on .* Value`), regexp.MustCompile(`reflect: string index out of range`), regexp.MustCompile(`strings: negative Repeat count`), regexp.MustCompile(`strings: illegal bytes to escape`), regexp.MustCompile(`invalid date .*`), regexp.MustCompile(`parsing time .*`), regexp.MustCompile(`cannot parse .* as .*`), regexp.MustCompile(`operator "in" not defined on .*`), regexp.MustCompile(`cannot sum .*`), regexp.MustCompile(`index out of range: .* \(array length is .*\)`), regexp.MustCompile(`reduce of empty array with no initial value`), regexp.MustCompile(`cannot use as argument \(type .*\) to call .*`), regexp.MustCompile(`illegal base64 data at input byte .*`), regexp.MustCompile(`sort order argument must be a string`), regexp.MustCompile(`sortBy order argument must be a string`), regexp.MustCompile(`invalid order .*, expected asc or desc`), regexp.MustCompile(`unknown order, use asc or desc`), regexp.MustCompile(`cannot use .* as a key for groupBy: type is not comparable`), } env := NewEnv() fn := Func() f.Fuzz(func(t *testing.T, code string) { if len(code) > 1000 { t.Skip("too long code") } program, err := expr.Compile(code, expr.Env(env), fn) if err != nil { t.Skipf("compile error: %s", err) } v := vm.VM{MemoryBudget: 500000} _, err = v.Run(program, env) if err != nil { for _, r := range skip { if r.MatchString(err.Error()) { t.Skipf("skip error: %s", err) return } } t.Errorf("%s", err) } }) } ================================================ FILE: test/gen/env.go ================================================ package main var Env = map[string]any{ "ok": true, "i": 1, "str": "str", "f64": .5, "array": []int{1, 2, 3, 4, 5}, "foo": Foo{"foo"}, "list": []Foo{{"bar"}, {"baz"}}, "add": func(a, b int) int { return a + b }, "greet": func(name string) string { return "Hello, " + name }, } type Foo struct { Bar string } func (f Foo) String() string { return "foo" } ================================================ FILE: test/gen/gen.go ================================================ package main import ( "fmt" "reflect" "runtime" "runtime/debug" "strings" "sync" "github.com/expr-lang/expr" "github.com/expr-lang/expr/builtin" ) var ( dict []string predicates []string builtins []string operators = []string{ "or", "||", "and", "&&", "==", "!=", "<", ">", ">=", "<=", "..", "??", "+", "-", "*", "/", "%", "**", "^", "in", "matches", "contains", "startsWith", "endsWith", "not in", "not matches", "not contains", "not startsWith", "not endsWith", } ) func init() { for name, x := range Env { dict = append(dict, name) v := reflect.ValueOf(x) if v.Kind() == reflect.Struct { for i := 0; i < v.NumField(); i++ { dict = append(dict, v.Type().Field(i).Name) } for i := 0; i < v.NumMethod(); i++ { dict = append(dict, v.Type().Method(i).Name) } } if v.Kind() == reflect.Map { for _, key := range v.MapKeys() { dict = append(dict, fmt.Sprintf("%v", key.Interface())) } } } for _, b := range builtin.Builtins { if b.Predicate { predicates = append(predicates, b.Name) } else { builtins = append(builtins, b.Name) } } } func main() { runtime.GOMAXPROCS(runtime.NumCPU()) var corpus = make(map[string]struct{}) var corpusMutex sync.Mutex numWorkers := runtime.NumCPU() var wg sync.WaitGroup wg.Add(numWorkers) for i := 0; i < numWorkers; i++ { go func(workerID int) { defer func() { if r := recover(); r != nil { fmt.Printf("Worker %d recovered from panic: %v\n", workerID, r) debug.PrintStack() } }() defer wg.Done() for { var code string code = node(oneOf(list[int]{ {3, 100}, {4, 40}, {5, 50}, {6, 30}, {7, 20}, {8, 10}, {9, 5}, {10, 5}, })) program, err := expr.Compile(code, expr.Env(Env)) if err != nil { continue } _, err = expr.Run(program, Env) if err != nil { continue } corpusMutex.Lock() if _, exists := corpus[code]; exists { corpusMutex.Unlock() continue } corpus[code] = struct{}{} corpusMutex.Unlock() fmt.Println(code) } }(i) } wg.Wait() } type fn func(depth int) string func node(depth int) string { if depth <= 0 { return oneOf(list[fn]{ {nilNode, 1}, {envNode, 1}, {floatNode, 1}, {integerNode, 1}, {stringNode, 1}, {booleanNode, 1}, {identifierNode, 10}, {pointerNode, 10}, })(depth - 1) } return oneOf(list[fn]{ {sequenceNode, 1}, {variableNode, 1}, {arrayNode, 10}, {mapNode, 10}, {identifierNode, 1000}, {memberNode, 1500}, {unaryNode, 100}, {binaryNode, 2000}, {callNode, 2000}, {pipeNode, 1000}, {builtinNode, 500}, {predicateNode, 1000}, {pointerNode, 500}, {sliceNode, 100}, {conditionalNode, 100}, })(depth - 1) } func nilNode(_ int) string { return "nil" } func envNode(_ int) string { return "$env" } func floatNode(_ int) string { return "1.0" } func integerNode(_ int) string { return oneOf(list[string]{ {"1", 1}, {"0", 1}, }) } func stringNode(_ int) string { return "foo" } func booleanNode(_ int) string { return random([]string{"true", "false"}) } func identifierNode(_ int) string { if maybe() { return "foobar" } return random(dict) } func memberNode(depth int) string { dot := "." if maybe() { dot = "?." } prop := oneOf(list[fn]{ {func(_ int) string { return random(dict) }, 5}, {node, 1}, })(depth - 1) if maybe() { return fmt.Sprintf("%v%v%v", node(depth-1), dot, prop) } return fmt.Sprintf("%v%v[%v]", node(depth-1), dot, prop) } func unaryNode(depth int) string { op := random([]string{"-", "!", "not"}) // Use a simple formatting to ensure valid unary expression syntax if op == "not" { return fmt.Sprintf("not %v", node(depth-1)) } return fmt.Sprintf("%s%v", op, node(depth-1)) } func binaryNode(depth int) string { return fmt.Sprintf("%v %v %v", node(depth-1), random(operators), node(depth-1)) } func methodNode(depth int) string { dot := "." if maybe() { dot = "?." } method := random(dict) if maybe() { return fmt.Sprintf("%v%v%v", node(depth-1), dot, method) } return fmt.Sprintf("%v%v[%v]", node(depth-1), dot, method) } func funcNode(_ int) string { return random(dict) } func callNode(depth int) string { var args []string for i := 0; i < oneOf(list[int]{ {0, 100}, {1, 100}, {2, 50}, {3, 25}, {4, 10}, {5, 5}, }); i++ { args = append(args, node(depth-1)) } fn := oneOf(list[fn]{ {methodNode, 2}, {funcNode, 2}, })(depth - 1) return fmt.Sprintf("%v(%v)", fn, strings.Join(args, ", ")) } func pipeNode(depth int) string { a := node(depth - 1) b := oneOf(list[fn]{ {callNode, 2}, {builtinNode, 5}, {predicateNode, 10}, })(depth - 1) return fmt.Sprintf("%v | %v", a, b) } func builtinNode(depth int) string { var args []string for i := 0; i < oneOf(list[int]{ {1, 100}, {2, 50}, {3, 50}, {4, 10}, }); i++ { args = append(args, node(depth-1)) } return fmt.Sprintf("%v(%v)", random(builtins), strings.Join(args, ", ")) } func predicateNode(depth int) string { var args []string for i := 0; i < oneOf(list[int]{ {1, 100}, {2, 50}, {3, 50}, }); i++ { args = append(args, node(depth-1)) } return fmt.Sprintf("%v(%v)", random(predicates), strings.Join(args, ", ")) } func pointerNode(_ int) string { return oneOf(list[string]{ {"#", 100}, {"#." + random(dict), 100}, {"." + random(dict), 100}, {"#acc", 10}, {"#index", 10}, }) } func arrayNode(depth int) string { var items []string for i := 0; i < oneOf(list[int]{ {1, 100}, {2, 50}, {3, 25}, }); i++ { items = append(items, node(depth-1)) } return fmt.Sprintf("[%v]", strings.Join(items, ", ")) } func mapNode(depth int) string { var items []string for i := 0; i < oneOf(list[int]{ {1, 100}, {2, 50}, {3, 25}, }); i++ { items = append(items, fmt.Sprintf("%v: %v", stringNode(depth-1), node(depth-1))) } return fmt.Sprintf("{%v}", strings.Join(items, ", ")) } func sliceNode(depth int) string { return oneOf(list[string]{ {fmt.Sprintf("%v[%v:%v]", node(depth-1), node(depth-1), node(depth-1)), 100}, {fmt.Sprintf("%v[%v:]", node(depth-1), node(depth-1)), 100}, {fmt.Sprintf("%v[:%v]", node(depth-1), node(depth-1)), 100}, {fmt.Sprintf("%v[:]", node(depth-1)), 1}, }) } func conditionalNode(depth int) string { return oneOf(list[string]{ {fmt.Sprintf("if %v { %v } else { %v }", node(depth-1), node(depth-1), node(depth-1)), 100}, {fmt.Sprintf("if %v { %v } else %v", node(depth-1), node(depth-1), node(depth-1)), 100}, {fmt.Sprintf("%v ? %v : %v", node(depth-1), node(depth-1), node(depth-1)), 100}, {fmt.Sprintf("%v ?: %v", node(depth-1), node(depth-1)), 20}, }) } func sequenceNode(depth int) string { var items []string for i := 0; i < oneOf(list[int]{ {2, 50}, {3, 25}, }); i++ { items = append(items, node(depth-1)) } if maybe() { return strings.Join(items, "; ") } return fmt.Sprintf("(%v)", strings.Join(items, ", ")) } func variableNode(depth int) string { // Generate 1-3 variable declarations with diverse names and then make sure // at least one of them is used in the final expression. namesPool := []string{"x", "y", "z", "foo", "bar", "foobar", "tmp"} nDecls := oneOf(list[int]{ {1, 60}, {2, 30}, {3, 10}, }) var decls []string var chosen []string for i := 0; i < nDecls; i++ { name := random(namesPool) chosen = append(chosen, name) decls = append(decls, fmt.Sprintf("let %s = %v", name, node(depth-1))) } // Build a usage expression that references declared vars to guarantee coverage. use := oneOf(list[string]{ {chosen[0], 50}, {fmt.Sprintf("%s + %v", chosen[0], node(depth-1)), 30}, {fmt.Sprintf("%v + %s", node(depth-1), chosen[0]), 30}, {fmt.Sprintf("if %v { %s } else { %v }", node(depth-1), chosen[0], node(depth-1)), 20}, {fmt.Sprintf("%s ? %v : %v", chosen[0], node(depth-1), node(depth-1)), 10}, }) return fmt.Sprintf("%s; %s", strings.Join(decls, "; "), use) } ================================================ FILE: test/gen/gen_test.go ================================================ package main import ( "bufio" "flag" "os" "strings" "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/internal/testify/require" ) var updateFlag = flag.Bool("update", false, "Drop failing lines from examples.txt") func TestGenerated(t *testing.T) { flag.Parse() b, err := os.ReadFile("../../testdata/generated.txt") require.NoError(t, err) examples := strings.TrimSpace(string(b)) var validLines []string for _, line := range strings.Split(examples, "\n") { line := line t.Run(line, func(t *testing.T) { program, err := expr.Compile(line, expr.Env(Env)) if err != nil { if !*updateFlag { t.Errorf("Compilation failed: %v", err) } return } _, err = expr.Run(program, Env) if err != nil { if !*updateFlag { t.Errorf("Execution failed: %v", err) } return } validLines = append(validLines, line) }) } if *updateFlag { file, err := os.Create("../../testdata/examples.txt") if err != nil { t.Fatalf("Failed to update examples.txt: %v", err) } defer func(file *os.File) { _ = file.Close() }(file) writer := bufio.NewWriter(file) for _, line := range validLines { _, err := writer.WriteString(line + "\n") if err != nil { t.Fatalf("Failed to write to examples.txt: %v", err) } } _ = writer.Flush() } } ================================================ FILE: test/gen/utils.go ================================================ package main import ( "math/rand" ) func maybe() bool { return rand.Intn(2) == 0 } type list[T any] []element[T] type element[T any] struct { value T weight int } func oneOf[T any](cases []element[T]) T { total := 0 for _, c := range cases { total += c.weight } r := rand.Intn(total) for _, c := range cases { if r < c.weight { return c.value } r -= c.weight } return cases[0].value } func random[T any](array []T) T { return array[rand.Intn(len(array))] } ================================================ FILE: test/interface/interface_method_test.go ================================================ package interface_test import ( "testing" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr" ) type Bar interface { Bar() int } type FooImpl struct{} func (f FooImpl) Foo() Bar { return BarImpl{} } type BarImpl struct{} // Aba is a special method that is not part of the Bar interface, // but is used to test that the correct method is called. "Aba" name // is chosen to be before "Bar" in the alphabet. func (b BarImpl) Aba() bool { return true } func (b BarImpl) Bar() int { return 42 } func TestInterfaceMethod(t *testing.T) { require.True(t, BarImpl{}.Aba()) require.True(t, BarImpl{}.Bar() == 42) env := map[string]any{ "var": FooImpl{}, } p, err := expr.Compile(`var.Foo().Bar()`, expr.Env(env)) assert.NoError(t, err) out, err := expr.Run(p, env) assert.NoError(t, err) assert.Equal(t, 42, out) } ================================================ FILE: test/interface/interface_test.go ================================================ package interface_test import ( "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/internal/testify/assert" ) type StoreInterface interface { Get(string) int } type StoreImpt struct{} func (f StoreImpt) Get(s string) int { return 42 } func (f StoreImpt) Set(s string, i int) bool { return true } type Env struct { Store StoreInterface `expr:"store"` } func TestInterfaceHide(t *testing.T) { var env Env p, err := expr.Compile(`store.Get("foo")`, expr.Env(env)) assert.NoError(t, err) out, err := expr.Run(p, Env{Store: StoreImpt{}}) assert.NoError(t, err) assert.Equal(t, 42, out) _, err = expr.Compile(`store.Set("foo", 100)`, expr.Env(env)) assert.Error(t, err) assert.Contains(t, err.Error(), "type interface_test.StoreInterface has no method Set") } ================================================ FILE: test/issues/461/issue_test.go ================================================ package issue_test import ( "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/internal/testify/require" ) func TestIssue461(t *testing.T) { type EnvStr string type EnvField struct { S EnvStr Str string } type Env struct { S EnvStr Str string EnvField EnvField } var tests = []struct { input string env Env want bool err string }{ { input: "Str == S", env: Env{S: "string", Str: "string"}, err: "invalid operation: == (mismatched types string and issue_test.EnvStr)", }, { input: "Str == Str", env: Env{Str: "string"}, want: true, }, { input: "S == S", env: Env{Str: "string"}, want: true, }, { input: `Str == "string"`, env: Env{Str: "string"}, want: true, }, { input: `S == "string"`, env: Env{Str: "string"}, err: "invalid operation: == (mismatched types issue_test.EnvStr and string)", }, { input: "EnvField.Str == EnvField.S", env: Env{EnvField: EnvField{S: "string", Str: "string"}}, err: "invalid operation: == (mismatched types string and issue_test.EnvStr)", }, { input: "EnvField.Str == EnvField.Str", env: Env{EnvField: EnvField{Str: "string"}}, want: true, }, { input: "EnvField.S == EnvField.S", env: Env{EnvField: EnvField{Str: "string"}}, want: true, }, { input: `EnvField.Str == "string"`, env: Env{EnvField: EnvField{Str: "string"}}, want: true, }, { input: `EnvField.S == "string"`, env: Env{EnvField: EnvField{Str: "string"}}, err: "invalid operation: == (mismatched types issue_test.EnvStr and string)", }, } for _, tt := range tests { t.Run(tt.input, func(t *testing.T) { program, err := expr.Compile(tt.input, expr.Env(tt.env), expr.AsBool()) if tt.err != "" { require.Error(t, err) require.Contains(t, err.Error(), tt.err) } else { out, err := expr.Run(program, tt.env) require.NoError(t, err) require.Equal(t, tt.want, out) } }) } } ================================================ FILE: test/issues/567/issue_test.go ================================================ package expr_test import ( "bytes" "strings" "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/internal/testify/require" ) func TestIssue567(t *testing.T) { program, err := expr.Compile("concat(1..2, 3..4)") require.NoError(t, err) var buf bytes.Buffer program.DisassembleWriter(&buf) output := buf.String() // Check if "concat" is mentioned in the output require.True(t, strings.Contains(output, "concat"), "expected 'concat' in disassembly output") // It should appear as a pushed constant require.True(t, strings.Contains(output, "OpPush\t<4>\tconcat"), "expected 'OpPush <4> concat' in disassembly output") } ================================================ FILE: test/issues/688/issue_test.go ================================================ package issue_test import ( "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/internal/testify/require" ) type Foo interface { Add(a int, b *int) int } type FooImpl struct { } func (*FooImpl) Add(a int, b *int) int { return 0 } type Env struct { Foo Foo `expr:"foo"` } func (Env) Any(x any) any { return x } func TestNoInterfaceMethodWithNil(t *testing.T) { program, err := expr.Compile(`foo.Add(1, nil)`) require.NoError(t, err) _, err = expr.Run(program, Env{Foo: &FooImpl{}}) require.NoError(t, err) } func TestNoInterfaceMethodWithNil_with_env(t *testing.T) { program, err := expr.Compile(`foo.Add(1, nil)`, expr.Env(Env{})) require.NoError(t, err) _, err = expr.Run(program, Env{Foo: &FooImpl{}}) require.NoError(t, err) } func TestNoInterfaceMethodWithNil_with_any(t *testing.T) { program, err := expr.Compile(`Any(nil)`, expr.Env(Env{})) require.NoError(t, err) out, err := expr.Run(program, Env{Foo: &FooImpl{}}) require.NoError(t, err) require.Equal(t, nil, out) } ================================================ FILE: test/issues/723/issue_test.go ================================================ package issue_test import ( "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/internal/testify/require" ) func TestIssue723(t *testing.T) { emptyMap := make(map[string]string) env := map[string]interface{}{ "empty_map": emptyMap, } code := `get(empty_map, "non_existing_key")` program, err := expr.Compile(code, expr.Env(env)) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, nil, output) } ================================================ FILE: test/issues/730/issue_test.go ================================================ package issue_test import ( "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/internal/testify/require" ) type ModeEnum int const ( ModeEnumA ModeEnum = 1 ) type Env struct { Mode *ModeEnum } func TestIssue730(t *testing.T) { code := `int(Mode) == 1` tmp := ModeEnumA env := map[string]any{ "Mode": &tmp, } program, err := expr.Compile(code, expr.Env(env)) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) require.True(t, output.(bool)) } func TestIssue730_warn_about_different_types(t *testing.T) { code := `Mode == 1` _, err := expr.Compile(code, expr.Env(Env{})) require.Error(t, err) require.Contains(t, err.Error(), "invalid operation: == (mismatched types issue_test.ModeEnum and int)") } func TestIssue730_eval(t *testing.T) { code := `Mode == 1` tmp := ModeEnumA env := map[string]any{ "Mode": &tmp, } // Golang also does not allow this: // _ = ModeEnumA == int(1) // will not compile out, err := expr.Eval(code, env) require.NoError(t, err) require.False(t, out.(bool)) } ================================================ FILE: test/issues/739/issue_test.go ================================================ package issue_test import ( "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/internal/testify/require" ) func TestIssue739(t *testing.T) { jsonString := `{"Num": 1}` env := map[string]any{ "aJSONString": &jsonString, } result, err := expr.Eval("fromJSON(aJSONString)", env) require.NoError(t, err) require.Contains(t, result, "Num") } ================================================ FILE: test/issues/756/issue_test.go ================================================ package issue_test import ( "context" "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/internal/testify/require" ) type X struct{} func (x *X) HelloCtx(ctx context.Context, text string) error { return nil } func TestIssue756(t *testing.T) { env := map[string]any{ "_goctx_": context.TODO(), "_g_": map[string]*X{ "rpc": {}, }, "text": "еуче", } exprStr := `let v = _g_.rpc.HelloCtx(text); v` program, err := expr.Compile(exprStr, expr.Env(env), expr.WithContext("_goctx_")) require.NoError(t, err) _, err = expr.Run(program, env) require.NoError(t, err) } ================================================ FILE: test/issues/785/issue_test.go ================================================ package issue_test import ( "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/internal/testify/require" ) func TestIssue785(t *testing.T) { emptyMap := map[string]any{} env := map[string]interface{}{ "empty_map": emptyMap, } { code := `get(empty_map, "non_existing_key") | get("some_key") | get("another_key") | get("yet_another_key") | get("last_key")` program, err := expr.Compile(code, expr.Env(env)) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, nil, output) } { code := `{} | get("non_existing_key") | get("some_key") | get("another_key") | get("yet_another_key") | get("last_key")` program, err := expr.Compile(code, expr.Env(env)) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, nil, output) } } ================================================ FILE: test/issues/817/issue_test.go ================================================ package issue_test import ( "fmt" "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/internal/testify/require" ) func TestIssue817_1(t *testing.T) { out, err := expr.Eval( `sprintf("result: %v %v", 1, nil)`, map[string]any{ "sprintf": fmt.Sprintf, }, ) require.NoError(t, err) require.Equal(t, "result: 1 ", out) } func TestIssue817_2(t *testing.T) { out, err := expr.Eval( `thing(nil)`, map[string]any{ "thing": func(arg ...any) string { return fmt.Sprintf("result: (%T) %v", arg[0], arg[0]) }, }, ) require.NoError(t, err) require.Equal(t, "result: () ", out) } ================================================ FILE: test/issues/819/issue_test.go ================================================ package issue_test import ( "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/internal/testify/require" ) func TestIssue819(t *testing.T) { t.Run("case 1", func(t *testing.T) { program, err := expr.Compile(` let a = [1]; let b = type(a[0]) == 'array' ? a : [a]; b[0][0] `) require.NoError(t, err) out, err := expr.Run(program, nil) require.NoError(t, err) require.Equal(t, 1, out) }) t.Run("case 2", func(t *testing.T) { program, err := expr.Compile(` let range = [1,1000]; let arr = false ? range : [range]; map(arr, {len(#)}) `) require.NoError(t, err) out, err := expr.Run(program, nil) require.NoError(t, err) require.Equal(t, []interface{}{2}, out) }) } ================================================ FILE: test/issues/823/issue_test.go ================================================ package issue_test import ( "context" "testing" "time" "github.com/expr-lang/expr" "github.com/expr-lang/expr/internal/testify/require" ) type env struct { Ctx context.Context `expr:"ctx"` } // TestIssue823 verifies that WithContext injects context into nested custom // function calls. The bug was that date2() nested as an argument to After() // didn't receive the context because its callee type was unknown. func TestIssue823(t *testing.T) { now2Called := false date2Called := false p, err := expr.Compile( "now2().After(date2())", expr.Env(env{}), expr.WithContext("ctx"), expr.Function( "now2", func(params ...any) (any, error) { require.Len(t, params, 1, "now2 should receive context") _, ok := params[0].(context.Context) require.True(t, ok, "now2 first param should be context.Context") now2Called = true return time.Now(), nil }, new(func(context.Context) time.Time), ), expr.Function( "date2", func(params ...any) (any, error) { require.Len(t, params, 1, "date2 should receive context") _, ok := params[0].(context.Context) require.True(t, ok, "date2 first param should be context.Context") date2Called = true return time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC), nil }, new(func(context.Context) time.Time), ), ) require.NoError(t, err) r, err := expr.Run(p, &env{Ctx: context.Background()}) require.NoError(t, err) require.True(t, r.(bool)) require.True(t, now2Called, "now2 should have been called") require.True(t, date2Called, "date2 should have been called") } // envWithMethods tests that Env methods with context.Context work correctly // when nested in method chains (similar to TestIssue823 but with Env methods). type envWithMethods struct { Ctx context.Context `expr:"ctx"` } func (e *envWithMethods) Now2(ctx context.Context) time.Time { return time.Now() } func (e *envWithMethods) Date2(ctx context.Context) time.Time { return time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC) } func TestIssue823_EnvMethods(t *testing.T) { p, err := expr.Compile( "Now2().After(Date2())", expr.Env(&envWithMethods{}), expr.WithContext("ctx"), ) require.NoError(t, err) r, err := expr.Run(p, &envWithMethods{Ctx: context.Background()}) require.NoError(t, err) require.True(t, r.(bool)) } ================================================ FILE: test/issues/830/issue_test.go ================================================ package issues import ( "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr/internal/testify/require" ) func TestIssue830(t *testing.T) { program, err := expr.Compile("varNotExist", expr.AllowUndefinedVariables(), expr.AsBool()) require.NoError(t, err) output, err := expr.Run(program, map[string]interface{}{}) require.NoError(t, err) // The user expects output to be false (bool), but gets nil. assert.Equal(t, false, output) } ================================================ FILE: test/issues/836/issue_test.go ================================================ package issue_test import ( "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/internal/testify/require" ) type InputStruct struct { Enabled *bool `json:"enabled"` } func TestIssue836(t *testing.T) { str := "foo" ptrStr := &str b := true ptrBool := &b i := 1 ptrInt := &i env := map[string]interface{}{ "ptrStr": ptrStr, "ptrBool": ptrBool, "ptrInt": ptrInt, "arr": []int{1, 2, 3}, "mapPtr": map[*int]int{ptrInt: 42}, } t.Run("map access with pointer key", func(t *testing.T) { program, err := expr.Compile(`{"foo": "bar"}[ptrStr]`, expr.Env(env)) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, "bar", output) }) t.Run("conditional with pointer condition", func(t *testing.T) { program, err := expr.Compile(`ptrBool ? 1 : 0`, expr.Env(env)) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, 1, output) }) t.Run("get() with pointer key", func(t *testing.T) { program, err := expr.Compile(`get({"foo": "bar"}, ptrStr)`, expr.Env(env)) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, "bar", output) }) t.Run("struct field pointer check in ternary", func(t *testing.T) { var v InputStruct // v.Enabled is nil env := map[string]any{ "v": v, } code := `v.Enabled == nil ? 'default' : ( v.Enabled ? 'enabled' : 'disabled' )` program, err := expr.Compile(code, expr.Env(env)) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, "default", output) }) t.Run("struct field pointer check in ternary (enabled)", func(t *testing.T) { b := true v := InputStruct{Enabled: &b} env := map[string]any{ "v": v, } code := `v.Enabled == nil ? 'default' : ( v.Enabled ? 'enabled' : 'disabled' )` program, err := expr.Compile(code, expr.Env(env)) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, "enabled", output) }) t.Run("slice with pointer indices", func(t *testing.T) { program, err := expr.Compile(`arr[ptrInt:ptrInt]`, expr.Env(env)) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, []int{}, output) }) } ================================================ FILE: test/issues/840/issue_test.go ================================================ package issue_test import ( "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/internal/testify/require" ) func TestEnvFieldMethods(t *testing.T) { program, err := expr.Compile(`Func() + Int`, expr.Env(&Env{})) require.NoError(t, err) env := &Env{} env.Func = func() int { return 40 } env.EmbeddedEnv = &EmbeddedEnv{ Int: 2, } out, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, 42, out) } type Env struct { *EmbeddedEnv Func func() int } type EmbeddedEnv struct { Int int } ================================================ FILE: test/issues/844/issue_test.go ================================================ package main import ( "strings" "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/checker" "github.com/expr-lang/expr/conf" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr/parser" ) func TestIssue844(t *testing.T) { testCases := []struct { name string env any expression string shouldFail bool }{ { name: "exported env, exported field", env: ExportedEnv{}, expression: `ExportedEmbedded`, shouldFail: false, }, { name: "exported env, unexported field", env: ExportedEnv{}, expression: `unexportedEmbedded`, shouldFail: true, }, { name: "exported env, exported field inherited from exported field", env: ExportedEnv{}, expression: `Str`, shouldFail: false, }, { name: "exported env, unexported field inherited from exported field", env: ExportedEnv{}, expression: `str`, shouldFail: true, }, { name: "exported env, exported field inherited from exported field", env: ExportedEnv{}, expression: `Integer`, shouldFail: false, }, { name: "exported env, unexported field inherited from exported field", env: ExportedEnv{}, expression: `integer`, shouldFail: true, }, { name: "exported env, exported field directly accessed from exported field", env: ExportedEnv{}, expression: `ExportedEmbedded.Str`, shouldFail: false, }, { name: "exported env, unexported field directly accessed from exported field", env: ExportedEnv{}, expression: `ExportedEmbedded.str`, shouldFail: true, }, { name: "exported env, exported field directly accessed from exported field", env: ExportedEnv{}, expression: `unexportedEmbedded.Integer`, shouldFail: true, }, { name: "exported env, unexported field directly accessed from exported field", env: ExportedEnv{}, expression: `unexportedEmbedded.integer`, shouldFail: true, }, { name: "unexported env, exported field", env: unexportedEnv{}, expression: `ExportedEmbedded`, shouldFail: false, }, { name: "unexported env, unexported field", env: unexportedEnv{}, expression: `unexportedEmbedded`, shouldFail: true, }, { name: "unexported env, exported field inherited from exported field", env: unexportedEnv{}, expression: `Str`, shouldFail: false, }, { name: "unexported env, unexported field inherited from exported field", env: unexportedEnv{}, expression: `str`, shouldFail: true, }, { name: "unexported env, exported field inherited from exported field", env: unexportedEnv{}, expression: `Integer`, shouldFail: false, }, { name: "unexported env, unexported field inherited from exported field", env: unexportedEnv{}, expression: `integer`, shouldFail: true, }, { name: "unexported env, exported field directly accessed from exported field", env: unexportedEnv{}, expression: `ExportedEmbedded.Str`, shouldFail: false, }, { name: "unexported env, unexported field directly accessed from exported field", env: unexportedEnv{}, expression: `ExportedEmbedded.str`, shouldFail: true, }, { name: "unexported env, exported field directly accessed from exported field", env: unexportedEnv{}, expression: `unexportedEmbedded.Integer`, shouldFail: true, }, { name: "unexported env, unexported field directly accessed from exported field", env: unexportedEnv{}, expression: `unexportedEmbedded.integer`, shouldFail: true, }, } for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { config := conf.New(tc.env) tree, err := parser.ParseWithConfig(tc.expression, config) require.NoError(t, err) _, err = new(checker.Checker).PatchAndCheck(tree, config) if tc.shouldFail { require.Error(t, err) errStr := err.Error() if !strings.Contains(errStr, "unknown name") && !strings.Contains(errStr, " has no field ") { t.Fatalf("expected a different error, got: %v", err) } } else { require.NoError(t, err) } // We add this because the issue was actually not catching something // that sometimes failed with the error: // reflect.Value.Interface: cannot return value obtained from unexported field or method // This way, we test that everything we allow passing is also // allowed later _, err = expr.Eval(tc.expression, tc.env) if tc.shouldFail { require.Error(t, err) } else { require.NoError(t, err) } }) } } type ExportedEnv struct { ExportedEmbedded unexportedEmbedded } type unexportedEnv struct { ExportedEmbedded unexportedEmbedded } type ExportedEmbedded struct { Str string str string } type unexportedEmbedded struct { Integer int integer int } ================================================ FILE: test/issues/854/issue_test.go ================================================ package main import ( "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr/types" ) func TestIssue854(t *testing.T) { envType := types.Map{ "user": types.Map{ // If we do not specify `Profile` here, // this is a correct behavior to throw // on a missing property. }, } code := `user.Profile?.Address ?? "Unknown address"` _, err := expr.Compile(code, expr.Env(envType)) require.Error(t, err) } ================================================ FILE: test/issues/857/issue_test.go ================================================ package main import ( "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/internal/testify/require" ) func TestIssue857(t *testing.T) { foo := map[string]any{ "entry": map[string]any{ "alpha": "x", "beta": 1, }, } bar := map[string]any{ "entry": map[string]any{ "alpha": "x", "beta": 1, }, } env := map[string]any{ "foo": foo, "bar": bar, } code := ` foo | keys() | filter(# in bar) | filter(foo[#].alpha == bar[#].alpha) | filter(foo[#].beta == bar[#].beta) ` _, err := expr.Compile(code, expr.Env(env)) require.NoError(t, err) } ================================================ FILE: test/issues/888/issue_test.go ================================================ package main import ( "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/internal/testify/require" ) type Container struct { ID string List []string } func (c Container) IncludesAny(s ...string) bool { for _, l := range c.List { // Note: original issue used "slices.Contains" but // it is not available in the minimum Go version of expr (1.18). for _, v := range s { if v == l { return true } } } return false } func TestIssue888(t *testing.T) { env := map[string]any{ "Container": Container{ ID: "id", List: []string{"foo", "bar", "baz"}, }, } code := `Container.IncludesAny("nope", "nope again", "bar")` program, err := expr.Compile(code, expr.Env(env)) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, true, output) } ================================================ FILE: test/issues/924/issue_test.go ================================================ package issue_test import ( "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/internal/testify/require" ) func TestIssue924_allow_disabling_builtins_and_providing_fn_at_runtime(t *testing.T) { // We disable the builtin "upper", but do not env information, // but we can provide a function at runtime. program, err := expr.Compile(`upper(1)`, expr.DisableBuiltin("upper")) require.NoError(t, err) env := map[string]any{ "upper": func(a int) int { return a }, } out, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, 1, out) } ================================================ FILE: test/issues/934/issue_test.go ================================================ package issue934 import ( "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/internal/testify/require" ) type Env struct { Exported unexported } type Exported struct { Str string str string } type unexported struct { Integer int integer int } // TestIssue934 tests that accessing unexported fields on values whose type // is unknown at compile time (e.g., from a ternary with mixed types) yields // a descriptive error. // // OSS-Fuzz issue #486370271. func TestIssue934(t *testing.T) { env := map[string]any{ "v": Env{}, } // Accessing unexported fields like time.Time.loc // should produce a proper error. _, err := expr.Eval(`(true ? v : "string").str`, env) require.Error(t, err) require.Contains(t, err.Error(), "cannot fetch str") // Exported field access should still work. _, err = expr.Eval(`(true ? v : "string").Str`, env) require.NoError(t, err) // Access unexported field inherited from unexported embedded struct. _, err = expr.Eval(`(true ? v : "string").integer`, env) require.Error(t, err) require.Contains(t, err.Error(), "cannot fetch integer") // Access exported field inherited from unexported embedded struct should work. _, err = expr.Eval(`(true ? v : "string").Integer`, env) require.NoError(t, err) } ================================================ FILE: test/mock/mock.go ================================================ package mock import ( "fmt" "reflect" "strings" "time" "github.com/expr-lang/expr/ast" ) type Env struct { Embed Ambiguous string Any any Bool bool Float float64 Int64 int64 Int32 int32 Int, One, Two int Uint32 uint32 Uint64 uint64 Float32 float32 Float64 float64 String string BoolPtr *bool FloatPtr *float64 IntPtr *int IntPtrPtr **int StringPtr *string Foo Foo Abstract Abstract ArrayOfAny []any ArrayOfInt []int ArrayOfString []string ArrayOfFoo []*Foo MapOfFoo map[string]Foo MapOfAny map[string]any MapIntAny map[int]string FuncParam func(_ bool, _ int, _ string) bool FuncParamAny func(_ any) bool FuncTooManyReturns func() (int, int, error) FuncNamed MyFunc NilAny any NilInt *int NilFn func() NilStruct *Foo NilSlice []any Variadic func(_ int, _ ...int) bool Fast func(...any) any Time time.Time TimePlusDay time.Time Duration time.Duration } func (p Env) FuncFoo(_ Foo) int { return 0 } func (p Env) Func() int { return 0 } func (p Env) FuncTyped(_ string) int { return 2023 } func (p Env) FuncInt(_ int) int { return 0 } func (p Env) FuncUint(_ uint) int { return 0 } func (p Env) FuncInt8(_ float64) int { return 0 } func (p Env) FuncInt16(_ int16) int { return 0 } func (p Env) FuncInt32(_ int32) int { return 0 } func (p Env) FuncInt64(_ int64) int { return 0 } func (p Env) FuncUint8(_ uint8) int { return 0 } func (p Env) FuncUint16(_ uint16) int { return 0 } func (p Env) FuncUint32(_ uint32) int { return 0 } func (p Env) FuncUint64(_ uint64) int { return 0 } func (p Env) TimeEqualString(a time.Time, s string) bool { return a.Format("2006-01-02") == s } func (p Env) GetInt() int { return p.Int } func (Env) Add(a, b int) int { return a + b } func (Env) StringerStringEqual(f fmt.Stringer, s string) bool { return f.String() == s } func (Env) StringStringerEqual(s string, f fmt.Stringer) bool { return s == f.String() } func (Env) StringerStringerEqual(f fmt.Stringer, g fmt.Stringer) bool { return f.String() == g.String() } func (Env) NotStringerStringEqual(f fmt.Stringer, s string) bool { return f.String() != s } func (Env) NotStringStringerEqual(s string, f fmt.Stringer) bool { return s != f.String() } func (Env) NotStringerStringerEqual(f fmt.Stringer, g fmt.Stringer) bool { return f.String() != g.String() } type Embed struct { EmbedEmbed *EmbedPointerEmbed EmbedString string } func (p Embed) EmbedMethod(_ int) string { return "" } type EmbedPointerEmbed struct { EmbedPointerEmbedInt int } func (p EmbedPointerEmbed) EmbedPointerEmbedMethod(_ int) string { return "" } func (p *EmbedPointerEmbed) EmbedPointerEmbedPointerReceiverMethod(_ int) string { return "" } type EmbedEmbed struct { EmbedEmbedString string } type Foo struct { Value string Bar Bar } func (Foo) Method() Bar { return Bar{ Baz: "baz (from Foo.Method)", } } func (f Foo) MethodWithArgs(prefix string) string { return prefix + f.Value } func (Foo) String() string { return "Foo.String" } func (Foo) VariadicMethod(_ ...string) bool { return true } type Bar struct { Baz string } type Abstract interface { Method(int) int } type MyFunc func(string) int var stringer = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() type StringerPatcher struct{} func (*StringerPatcher) Visit(node *ast.Node) { t := (*node).Type() if t == nil { return } if t.Implements(stringer) { ast.Patch(node, &ast.CallNode{ Callee: &ast.MemberNode{ Node: *node, Property: &ast.StringNode{Value: "String"}, }, }) } } type MapStringStringEnv map[string]string func (m MapStringStringEnv) Split(s, sep string) []string { return strings.Split(s, sep) } type MapStringIntEnv map[string]int type Is struct{} func (Is) Nil(a any) bool { return a == nil } ================================================ FILE: test/operator/issues584/issues584_test.go ================================================ package issues584_test import ( "testing" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr" ) type Env struct{} type Program struct { } func (p *Program) Foo() Value { return func(e *Env) float64 { return 5 } } func (p *Program) Bar() Value { return func(e *Env) float64 { return 100 } } func (p *Program) AndCondition(a, b Condition) Conditions { return Conditions{a, b} } func (p *Program) AndConditions(a Conditions, b Condition) Conditions { return append(a, b) } func (p *Program) ValueGreaterThan_float(v Value, i float64) Condition { return func(e *Env) bool { realized := v(e) return realized > i } } func (p *Program) ValueLessThan_float(v Value, i float64) Condition { return func(e *Env) bool { realized := v(e) return realized < i } } type Condition func(e *Env) bool type Conditions []Condition type Value func(e *Env) float64 func TestIssue584(t *testing.T) { code := `Foo() > 1.5 and Bar() < 200.0` p := &Program{} opt := []expr.Option{ expr.Env(p), expr.Operator("and", "AndCondition", "AndConditions"), expr.Operator(">", "ValueGreaterThan_float"), expr.Operator("<", "ValueLessThan_float"), } program, err := expr.Compile(code, opt...) assert.Nil(t, err) state, err := expr.Run(program, p) assert.Nil(t, err) assert.NotNil(t, state) } ================================================ FILE: test/operator/operator_test.go ================================================ package operator_test import ( "fmt" "testing" "time" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr" "github.com/expr-lang/expr/test/mock" ) func TestOperator_struct(t *testing.T) { env := mock.Env{ Time: time.Date(2017, time.October, 23, 18, 30, 0, 0, time.UTC), } code := `Time == "2017-10-23"` program, err := expr.Compile(code, expr.Env(mock.Env{}), expr.Operator("==", "TimeEqualString")) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, true, output) } func TestOperator_no_env(t *testing.T) { code := `Time == "2017-10-23"` require.Panics(t, func() { _, _ = expr.Compile(code, expr.Operator("==", "TimeEqualString")) }) } func TestOperator_interface(t *testing.T) { env := mock.Env{} code := `Foo == "Foo.String" && "Foo.String" == Foo && Time != Foo && Time == Time` program, err := expr.Compile( code, expr.Env(mock.Env{}), expr.Operator("==", "StringerStringEqual", "StringStringerEqual", "StringerStringerEqual"), expr.Operator("!=", "NotStringerStringEqual", "NotStringStringerEqual", "NotStringerStringerEqual"), ) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, true, output) } type Value struct { Int int } func TestOperator_Function(t *testing.T) { env := map[string]interface{}{ "foo": Value{1}, "bar": Value{2}, } tests := []struct { input string want int }{ { input: `foo + bar`, want: 3, }, { input: `2 + 4`, want: 6, }, } for _, tt := range tests { t.Run(fmt.Sprintf(`operator function helper test %s`, tt.input), func(t *testing.T) { program, err := expr.Compile( tt.input, expr.Env(env), expr.Operator("+", "Add", "AddInt"), expr.Function("Add", func(args ...interface{}) (interface{}, error) { return args[0].(Value).Int + args[1].(Value).Int, nil }, new(func(_ Value, __ Value) int), ), expr.Function("AddInt", func(args ...interface{}) (interface{}, error) { return args[0].(int) + args[1].(int), nil }, new(func(_ int, __ int) int), ), ) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, tt.want, output) }) } } func TestOperator_Function_WithTypes(t *testing.T) { env := map[string]interface{}{ "foo": Value{1}, "bar": Value{2}, } assert.PanicsWithError(t, `function "Add" for "+" operator misses types`, func() { _, _ = expr.Compile( `foo + bar`, expr.Env(env), expr.Operator("+", "Add", "AddInt"), expr.Function("Add", func(args ...interface{}) (interface{}, error) { return args[0].(Value).Int + args[1].(Value).Int, nil }), ) }) assert.PanicsWithError(t, `function "Add" for "+" operator does not have a correct signature`, func() { _, _ = expr.Compile( `foo + bar`, expr.Env(env), expr.Operator("+", "Add", "AddInt"), expr.Function("Add", func(args ...interface{}) (interface{}, error) { return args[0].(Value).Int + args[1].(Value).Int, nil }, new(func(_ Value) int), ), ) }) } func TestOperator_FunctionOverTypesPrecedence(t *testing.T) { env := struct { Add func(a, b int) int }{ Add: func(a, b int) int { return a + b }, } program, err := expr.Compile( `1 + 2`, expr.Env(env), expr.Operator("+", "Add"), expr.Function("Add", func(args ...interface{}) (interface{}, error) { // Weird function that returns 100 + a + b for testing purposes. return args[0].(int) + args[1].(int) + 100, nil }, new(func(_ int, __ int) int), ), ) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, 103, output) } func TestOperator_CanBeDefinedEitherInTypesOrInFunctions(t *testing.T) { env := struct { Add func(a, b int) int }{ Add: func(a, b int) int { return a + b }, } program, err := expr.Compile( `1 + 2`, expr.Env(env), expr.Operator("+", "Add", "AddValues"), expr.Function("AddValues", func(args ...interface{}) (interface{}, error) { return args[0].(Value).Int + args[1].(Value).Int, nil }, new(func(_ Value, __ Value) int), ), ) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, 3, output) } func TestOperator_Polymorphic(t *testing.T) { env := struct { Add func(a, b int) int Foo Value Bar Value }{ Add: func(a, b int) int { return a + b }, Foo: Value{1}, Bar: Value{2}, } program, err := expr.Compile( `1 + 2 + (Foo + Bar)`, expr.Env(env), expr.Operator("+", "Add", "AddValues"), expr.Function("AddValues", func(args ...interface{}) (interface{}, error) { return args[0].(Value).Int + args[1].(Value).Int, nil }, new(func(_ Value, __ Value) int), ), ) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, 6, output) } func TestOperator_recursive_apply(t *testing.T) { type Decimal struct { Int int } env := map[string]any{ "add": func(a, b Decimal) Decimal { return Decimal{ Int: a.Int + b.Int, } }, "addInt": func(a Decimal, b int) Decimal { return Decimal{ Int: a.Int + b, } }, "a": Decimal{1}, "b": Decimal{2}, "c": Decimal{3}, "d": Decimal{4}, "e": Decimal{5}, } program, err := expr.Compile( `a + b + 100 + c + d + e`, expr.Env(env), expr.Operator("+", "add"), expr.Operator("+", "addInt"), ) require.NoError(t, err) require.Equal(t, `add(add(add(addInt(add(a, b), 100), c), d), e)`, program.Node().String()) output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, 115, output.(Decimal).Int) } ================================================ FILE: test/patch/change_ident_test.go ================================================ package patch_test import ( "testing" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr" "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/vm" "github.com/expr-lang/expr/vm/runtime" ) func TestPatch_change_ident(t *testing.T) { program, err := expr.Compile( `foo`, expr.Env(Env{}), expr.Patch(changeIdent{}), ) require.NoError(t, err) expected := &vm.Program{ Bytecode: []vm.Opcode{ vm.OpLoadField, }, Arguments: []int{ 0, }, Constants: []any{ &runtime.Field{ Path: []string{"bar"}, Index: []int{1}, }, }, } require.Equal(t, expected.Disassemble(), program.Disassemble()) } type Env struct { Foo int `expr:"foo"` Bar int `expr:"bar"` } type changeIdent struct{} func (changeIdent) Visit(node *ast.Node) { id, ok := (*node).(*ast.IdentifierNode) if !ok { return } if id.Value == "foo" { // A correct way to patch the node: // // newNode := &ast.IdentifierNode{Value: "bar"} // ast.Patch(node, newNode) // // But we can do it in a wrong way: id.Value = "bar" } } ================================================ FILE: test/patch/patch_count_test.go ================================================ package patch_test import ( "testing" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr" "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/test/mock" ) // This patcher tracks how many nodes it patches which can // be used to verify if it was run too many times or not at all type countingPatcher struct { PatchCount int } func (c *countingPatcher) Visit(node *ast.Node) { switch (*node).(type) { case *ast.IntegerNode: c.PatchCount++ } } // Test over a simple expression func TestPatch_Count(t *testing.T) { patcher := countingPatcher{} _, err := expr.Compile( `5 + 5`, expr.Env(mock.Env{}), expr.Patch(&patcher), ) require.NoError(t, err) require.Equal(t, 2, patcher.PatchCount, "Patcher run an unexpected number of times during compile") } // Test with operator overloading func TestPatchOperator_Count(t *testing.T) { patcher := countingPatcher{} _, err := expr.Compile( `5 + 5`, expr.Env(mock.Env{}), expr.Patch(&patcher), expr.Operator("+", "_intAdd"), expr.Function( "_intAdd", func(params ...any) (any, error) { return params[0].(int) + params[1].(int), nil }, new(func(int, int) int), ), ) require.NoError(t, err) require.Equal(t, 2, patcher.PatchCount, "Patcher run an unexpected number of times during compile") } ================================================ FILE: test/patch/patch_test.go ================================================ package patch_test import ( "testing" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr" "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/test/mock" ) type lengthPatcher struct{} func (p *lengthPatcher) Visit(node *ast.Node) { switch n := (*node).(type) { case *ast.MemberNode: if prop, ok := n.Property.(*ast.StringNode); ok && prop.Value == "length" { ast.Patch(node, &ast.BuiltinNode{ Name: "len", Arguments: []ast.Node{n.Node}, }) } } } func TestPatch_length(t *testing.T) { program, err := expr.Compile( `String.length == 5`, expr.Env(mock.Env{}), expr.Patch(&lengthPatcher{}), ) require.NoError(t, err) env := mock.Env{String: "hello"} output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, true, output) } ================================================ FILE: test/patch/set_type/set_type_test.go ================================================ package set_type_test import ( "reflect" "testing" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr" "github.com/expr-lang/expr/ast" ) func TestPatch_SetType(t *testing.T) { _, err := expr.Compile( `Value + "string"`, expr.Env(Env{}), expr.Function( "getValue", func(params ...any) (any, error) { return params[0].(Value).Int, nil }, // We can set function type right here, // but we want to check what SetType in // getValuePatcher will take an effect. ), expr.Patch(getValuePatcher{}), ) require.Error(t, err) } type Value struct { Int int } type Env struct { Value Value } var valueType = reflect.TypeOf((*Value)(nil)).Elem() type getValuePatcher struct{} func (getValuePatcher) Visit(node *ast.Node) { id, ok := (*node).(*ast.IdentifierNode) if !ok { return } if id.Type() == valueType { newNode := &ast.CallNode{ Callee: &ast.IdentifierNode{Value: "getValue"}, Arguments: []ast.Node{id}, } newNode.SetType(reflect.TypeOf(0)) ast.Patch(node, newNode) } } ================================================ FILE: test/pipes/pipes_test.go ================================================ package pipes_test import ( "fmt" "testing" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr" ) func TestPipes(t *testing.T) { env := map[string]any{ "sprintf": fmt.Sprintf, } tests := []struct { input string want any }{ { `-1 | abs()`, 1, }, { `"%s bar %d" | sprintf("foo", -42 | abs())`, "foo bar 42", }, { `[] | first() ?? "foo"`, "foo", }, { `"a" | upper() + "B" | lower()`, "ab", }, } for _, test := range tests { t.Run(test.input, func(t *testing.T) { program, err := expr.Compile(test.input, expr.Env(env)) require.NoError(t, err) out, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, test.want, out) }) } } func TestPipes_map_filter(t *testing.T) { program, err := expr.Compile(`1..9 | map(# + 1) | filter(# % 2 == 0)`) require.NoError(t, err) out, err := expr.Run(program, nil) require.NoError(t, err) require.Equal(t, []any{2, 4, 6, 8, 10}, out) } ================================================ FILE: test/playground/data.go ================================================ package playground import ( "fmt" "time" ) func ExampleData() Blog { profileJohn := UserProfile{ Birthday: time.Date(1990, 1, 1, 0, 0, 0, 0, time.UTC), Biography: "A passionate writer about Go.", Website: "https://johndoe.com", } profileJane := UserProfile{ Birthday: time.Date(1985, 2, 15, 0, 0, 0, 0, time.UTC), Biography: "A web developer and writer.", Website: "https://jane.com", } authorJohn := Author{ ID: 1, FirstName: "John", LastName: "Doe", Email: "john.doe@example.com", Profile: profileJohn, } authorJane := Author{ ID: 2, FirstName: "Jane", LastName: "Smith", Email: "jane.smith@example.com", Profile: profileJane, } posts := []Post{ { ID: 1, Title: "Understanding Golang", Content: "Go is an open-source programming language...", PublishDate: time.Now().AddDate(0, -1, 0), Author: authorJohn, Comments: generateComments(3), Tags: []string{"Go", "Programming"}, Likes: 100, }, { ID: 2, Title: "Exploring Python", Content: "Python is versatile...", PublishDate: time.Now().AddDate(0, -2, 0), Author: authorJane, Comments: generateComments(4), Tags: []string{"Python", "Development"}, Likes: 150, }, { ID: 3, Title: "Web Development Basics", Content: "The world of web development...", PublishDate: time.Now().AddDate(0, -3, 0), Author: authorJane, Comments: generateComments(5), Tags: []string{"Web", "HTML", "CSS"}, Likes: 125, }, { ID: 4, Title: "Machine Learning in a Nutshell", Content: "ML is revolutionizing industries...", PublishDate: time.Now().AddDate(0, -5, 0), Author: authorJohn, Comments: generateComments(6), Tags: []string{"ML", "AI"}, Likes: 200, }, { ID: 5, Title: "JavaScript: The Good Parts", Content: "JavaScript powers the web...", PublishDate: time.Now().AddDate(0, -4, 0), Author: authorJane, Comments: generateComments(3), Tags: []string{"JavaScript", "Web"}, Likes: 170, }, } blog := Blog{ Posts: make([]Post, len(posts)), Authors: map[int]Author{authorJohn.ID: authorJohn, authorJane.ID: authorJane}, TotalViews: 10000, TotalPosts: len(posts), TotalLikes: 0, } for i, post := range posts { blog.Posts[i] = post blog.TotalLikes += post.Likes } return blog } func generateComments(count int) []Comment { var comments []Comment for i := 1; i <= count; i++ { comment := Comment{ ID: i, AuthorName: fmt.Sprintf("Commenter %d", i), Content: fmt.Sprintf("This is comment %d!", i), CommentDate: time.Now().AddDate(0, 0, -i), Upvotes: i * 5, } comments = append(comments, comment) } return comments } ================================================ FILE: test/playground/env.go ================================================ package playground import ( "time" ) type UserProfile struct { Birthday time.Time Biography string Website string } func (u UserProfile) Age() int { return time.Now().Year() - u.Birthday.Year() } type Author struct { ID int FirstName string LastName string Email string Profile UserProfile } func (a Author) FullName() string { return a.FirstName + " " + a.LastName } func (a Author) IsAdmin() bool { return a.ID == 1 } type Post struct { ID int Title string Content string PublishDate time.Time Author Author Comments []Comment Tags []string Likes int } func (p Post) Published() bool { return !p.PublishDate.IsZero() } func (p Post) After(date time.Time) bool { return p.PublishDate.After(date) } func (p Post) Before(date time.Time) bool { return p.PublishDate.Before(date) } func (p Post) Compare(other Post) int { if p.PublishDate.Before(other.PublishDate) { return -1 } else if p.PublishDate.After(other.PublishDate) { return 1 } return 0 } func (p Post) Equal(other Post) bool { return p.Compare(other) == 0 } func (p Post) IsZero() bool { return p.ID == 0 && p.Title == "" && p.Content == "" && p.PublishDate.IsZero() } type Comment struct { ID int AuthorName string Content string CommentDate time.Time Upvotes int } func (c Comment) Upvoted() bool { return c.Upvotes > 0 } func (c Comment) AuthorEmail() string { return c.AuthorName + "@example.com" } type Blog struct { Posts []Post Authors map[int]Author TotalViews int TotalPosts int TotalLikes int } func (b Blog) RecentPosts() []Post { var posts []Post for _, post := range b.Posts { if post.Published() { posts = append(posts, post) } } return posts } func (b Blog) PopularPosts() []Post { var posts []Post for _, post := range b.Posts { if post.Likes > 150 { posts = append(posts, post) } } return posts } func (b Blog) TotalUpvotes() int { var upvotes int for _, post := range b.Posts { for _, comment := range post.Comments { upvotes += comment.Upvotes } } return upvotes } func (b Blog) TotalComments() int { var comments int for _, post := range b.Posts { comments += len(post.Comments) } return comments } func (Blog) Add(a, b float64) float64 { return a + b } func (Blog) Sub(a, b float64) float64 { return a - b } func (Blog) Title(post Post) string { return post.Title } func (Blog) HasTag(post Post, tag string) bool { for _, t := range post.Tags { if t == tag { return true } } return false } func (Blog) IsAdmin(author Author) bool { return author.IsAdmin() } func (Blog) IsZero(post Post) bool { return post.IsZero() } func (Blog) WithID(posts []Post, id int) Post { for _, post := range posts { if post.ID == id { return post } } return Post{} } ================================================ FILE: test/time/time_test.go ================================================ package time_test import ( "fmt" "testing" "time" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr" "github.com/expr-lang/expr/checker" "github.com/expr-lang/expr/compiler" "github.com/expr-lang/expr/conf" "github.com/expr-lang/expr/parser" "github.com/expr-lang/expr/vm" ) func TestTime(t *testing.T) { testTime := time.Date(2000, time.Month(1), 1, 0, 0, 0, 0, time.UTC) testDuration := time.Duration(1) tests := []struct { a any b any op string want any wantErr bool }{ {a: testTime, b: testTime, op: "<", wantErr: false, want: false}, {a: testTime, b: testTime, op: ">", wantErr: false, want: false}, {a: testTime, b: testTime, op: "<=", wantErr: false, want: true}, {a: testTime, b: testTime, op: ">=", wantErr: false, want: true}, {a: testTime, b: testTime, op: "==", wantErr: false, want: true}, {a: testTime, b: testTime, op: "!=", wantErr: false, want: false}, {a: testTime, b: testTime, op: "-", wantErr: false}, {a: testTime, b: testDuration, op: "+", wantErr: false}, {a: testTime, b: testDuration, op: "-", wantErr: false}, // error cases {a: testTime, b: int64(1), op: "<", wantErr: true}, {a: testTime, b: float64(1), op: "<", wantErr: true}, {a: testTime, b: testDuration, op: "<", wantErr: true}, {a: testTime, b: int64(1), op: ">", wantErr: true}, {a: testTime, b: float64(1), op: ">", wantErr: true}, {a: testTime, b: testDuration, op: ">", wantErr: true}, {a: testTime, b: int64(1), op: "<=", wantErr: true}, {a: testTime, b: float64(1), op: "<=", wantErr: true}, {a: testTime, b: testDuration, op: "<=", wantErr: true}, {a: testTime, b: int64(1), op: ">=", wantErr: true}, {a: testTime, b: float64(1), op: ">=", wantErr: true}, {a: testTime, b: testDuration, op: ">=", wantErr: true}, {a: testTime, b: int64(1), op: "==", wantErr: false, want: false}, {a: testTime, b: float64(1), op: "==", wantErr: false, want: false}, {a: testTime, b: testDuration, op: "==", wantErr: false, want: false}, {a: testTime, b: int64(1), op: "!=", wantErr: false, want: true}, {a: testTime, b: float64(1), op: "!=", wantErr: false, want: true}, {a: testTime, b: testDuration, op: "!=", wantErr: false, want: true}, {a: testTime, b: int64(1), op: "-", wantErr: true}, {a: testTime, b: float64(1), op: "-", wantErr: true}, {a: testTime, b: testTime, op: "+", wantErr: true}, {a: testTime, b: int64(1), op: "+", wantErr: true}, {a: testTime, b: float64(1), op: "+", wantErr: true}, {a: testDuration, b: testTime, op: "+", wantErr: false}, } for _, tt := range tests { t.Run(fmt.Sprintf("time helper test `%T %s %T`", tt.a, tt.op, tt.b), func(t *testing.T) { input := fmt.Sprintf("a %v b", tt.op) env := map[string]any{ "a": tt.a, "b": tt.b, } config := conf.CreateNew() tree, err := parser.Parse(input) require.NoError(t, err) _, err = checker.Check(tree, config) require.NoError(t, err) program, err := compiler.Compile(tree, config) require.NoError(t, err) got, err := vm.Run(program, env) if tt.wantErr { require.Error(t, err) } else { require.NoError(t, err) if tt.want != nil { require.Equal(t, tt.want, got) } } }) } } func TestTime_duration(t *testing.T) { env := map[string]any{ "foo": time.Date(2000, time.Month(1), 1, 0, 0, 0, 0, time.UTC), } program, err := expr.Compile(`now() - duration("1h") < now() && foo + duration("24h") < now()`, expr.Env(env)) require.NoError(t, err) output, err := expr.Run(program, env) require.NoError(t, err) require.Equal(t, true, output) } func TestTime_date(t *testing.T) { var tests = []struct { input string want time.Time }{ { `date('2017-10-23')`, time.Date(2017, 10, 23, 0, 0, 0, 0, time.UTC), }, { `date('24.11.1987 20:30', "02.01.2006 15:04", "Europe/Zurich")`, time.Date(1987, 11, 24, 20, 30, 0, 0, time.FixedZone("Europe/Zurich", 3600)), }, { `date('24.11.1987 20:30 MSK', "02.01.2006 15:04 MST", "Europe/Zurich")`, time.Date(1987, 11, 24, 20, 30, 0, 0, time.FixedZone("MSK", 0)), }, } for _, test := range tests { t.Run(test.input, func(t *testing.T) { program, err := expr.Compile(test.input) require.NoError(t, err) output, err := expr.Run(program, nil) require.NoError(t, err) require.Truef(t, test.want.Equal(output.(time.Time)), "want %v, got %v", test.want, output) }) } } ================================================ FILE: testdata/crowdsec.json ================================================ [ " {Jan:'01',Feb:'02',Mar:'03',Apr:'04',May:'05',Jun:'06',Jul:'07',Aug:'08',Sep:'09',Oct:'10',Nov:'11',Dec:'12'}[evt.Parsed.ts_m] + '/' + evt.Parsed.ts_d + '/' + evt.Parsed.ts_y + ' ' + evt.Parsed.ts_t", "\"20\" + evt.Parsed.year + \"/\" + evt.Parsed.month + \"/\" + evt.Parsed.day + \" \" + evt.Parsed.time", "'source_ip' in evt.Meta", "(\nUpper(evt.Meta.http_path) contains Upper('/service/extension/backup/mboximport?account-name=admin&ow=2&no-switch=1&append=1') ||\nUpper(evt.Meta.http_path) contains Upper('/service/extension/backup/mboximport?account-name=admin&account-status=1&ow=cmd') \n)\nand evt.Meta.http_status startsWith ('40') and\nUpper(evt.Meta.http_verb) == 'POST'\n", "GetFromStash(\"auditd_pid_progname\", evt.Unmarshaled.auditd.ppid)", "IpToRange(evt.Overflow.Alert.Source.IP, \"/64\")", "IsIP(evt.Unmarshaled.cloudtrail.sourceIPAddress) ? evt.Unmarshaled.cloudtrail.sourceIPAddress : \"\"\n", "JsonExtract(evt.Line.Raw, \"common_log\")", "JsonExtract(evt.Line.Raw, \"metric_name\")", "JsonExtract(evt.Line.Raw, \"path_info\")", "JsonExtract(evt.Line.Raw, \"request.headers.User-Agent\")", "JsonExtract(evt.Line.Raw, \"request.host\")", "JsonExtract(evt.Line.Raw, \"request.method\")", "JsonExtract(evt.Line.Raw, \"request.remote_addr\")", "JsonExtract(evt.Line.Raw, \"request.remote_ip\")", "JsonExtract(evt.Line.Raw, \"request.uri\")", "JsonExtract(evt.Line.Raw, \"request_ip\")", "JsonExtract(evt.Line.Raw, \"resp_headers.Date[0]\")", "JsonExtract(evt.Line.Raw, \"status\")", "JsonExtract(evt.Line.Raw, \"time\")", "JsonExtract(evt.Line.Raw, \"timestamp\")", "JsonExtract(evt.Line.Raw, \"user_agent\")", "JsonExtract(evt.Line.Raw, 'status') == '401' && JsonExtract(evt.Line.Raw, 'request.headers.Authorization[0]') startsWith 'Basic ' ? 'auth_fail' : ''", "JsonExtract(evt.Parsed.line, \"bouncer_agent\")", "JsonExtract(evt.Parsed.line, \"customer_id\")", "JsonExtract(evt.Parsed.line, \"ip\")", "JsonExtract(evt.Parsed.line, \"order_id\")", "JsonExtract(evt.Parsed.line, \"payment_method\")", "JsonExtract(evt.Parsed.line, \"product_id\")", "JsonExtract(evt.Parsed.line, \"quote_id\")", "JsonExtract(evt.Parsed.line, \"type\")", "JsonExtract(evt.Parsed.line, \"x-forwarded-for-ip\")", "JsonExtract(evt.Parsed.message, \"alert.rev\")", "JsonExtract(evt.Parsed.message, \"alert.severity\")", "JsonExtract(evt.Parsed.message, \"alert.signature\")", "JsonExtract(evt.Parsed.message, \"alert.signature_id\")", "JsonExtract(evt.Parsed.message, \"attr.authenticationDatabase\")", "JsonExtract(evt.Parsed.message, \"attr.principalName\")", "JsonExtract(evt.Parsed.message, \"attr.remote\")", "JsonExtract(evt.Parsed.message, \"client_ip\")", "JsonExtract(evt.Parsed.message, \"dest_ip\")", "JsonExtract(evt.Parsed.message, \"dest_port\")", "JsonExtract(evt.Parsed.message, \"eventAudience\")", "JsonExtract(evt.Parsed.message, \"eventData.eventConfidence\")", "JsonExtract(evt.Parsed.message, \"eventData.httpSourceId\")", "JsonExtract(evt.Parsed.message, \"eventData.matchedLocation\")", "JsonExtract(evt.Parsed.message, \"eventData.matchedParameter\")", "JsonExtract(evt.Parsed.message, \"eventData.matchedSample\")", "JsonExtract(evt.Parsed.message, \"eventData.securityAction\")", "JsonExtract(evt.Parsed.message, \"eventData.sourceIP\")", "JsonExtract(evt.Parsed.message, \"eventData.waapIncidentType\")", "JsonExtract(evt.Parsed.message, \"eventName\")", "JsonExtract(evt.Parsed.message, \"eventPriority\")", "JsonExtract(evt.Parsed.message, \"eventSeverity\")", "JsonExtract(evt.Parsed.message, \"eventTime\")", "JsonExtract(evt.Parsed.message, \"flow_id\")", "JsonExtract(evt.Parsed.message, \"message\")", "JsonExtract(evt.Parsed.message, \"msg\")", "JsonExtract(evt.Parsed.message, \"proto\")", "JsonExtract(evt.Parsed.message, \"remote_ip\")", "JsonExtract(evt.Parsed.message, \"request_method\")", "JsonExtract(evt.Parsed.message, \"request_referer\")", "JsonExtract(evt.Parsed.message, \"request_user_agent\")", "JsonExtract(evt.Parsed.message, \"response_body_size\")", "JsonExtract(evt.Parsed.message, \"response_status\")", "JsonExtract(evt.Parsed.message, \"src_ip\")", "JsonExtract(evt.Parsed.message, \"t.$date\")", "JsonExtract(evt.Parsed.message, \"time\")", "JsonExtract(evt.Parsed.message, \"timestamp\")", "JsonExtract(evt.Parsed.message, \"url\")", "JsonExtractUnescape(evt.Line.Raw, \"log\")", "Lower(evt.Meta.http_path) contains '/index.php' &&\nUpper(evt.Parsed.verb) == 'POST' &&\nevt.Meta.http_status == '302' &&\nLower(evt.Parsed.http_args) matches 'login=.*[$|%24][\\\\(|%28].*[\\\\)|%29]'\n", "Lower(evt.Unmarshaled.iptables.PROTO)", "ParseKV(evt.Parsed.message, evt.Unmarshaled, \"iptables\")", "RegexpInFile(evt.Enriched.reverse_dns, 'rdns_seo_bots.regex')", "Split(evt.Unmarshaled.traefik.ClientAddr, ':')[0]", "Split(evt.Unmarshaled.traefik.RequestProtocol, '/')[1]", "UnmarshalJSON(evt.Line.Raw, evt.Unmarshaled, \"k8s_audit\")", "UnmarshalJSON(evt.Line.Raw, evt.Unmarshaled, 'cloudtrail')", "Upper(PathUnescape(evt.Meta.http_path)) contains Upper('${script:javascript:java.lang.Runtime.getRuntime().exec(')\nor\nUpper(PathUnescape(evt.Meta.http_path)) contains Upper('${script:js:java.lang.Runtime.getRuntime().exec(')\nor\nUpper(PathUnescape(evt.Meta.http_path)) contains Upper('${url:UTF-8:') \nor\nUpper(PathUnescape(evt.Meta.http_path)) contains Upper('${dns:address|') \n", "Upper(PathUnescape(evt.Meta.http_path)) contains Upper('@java.lang.Runtime@getRuntime().exec(')", "Upper(evt.Meta.http_path) contains Upper('/autodiscover/autodiscover.json') &&\nUpper(evt.Parsed.http_args) contains Upper('powershell')\n", "Upper(evt.Meta.http_path) contains Upper('/ghost/api/admin/session') &&\nUpper(evt.Parsed.verb) == 'POST' &&\nevt.Meta.http_status == '404'\n", "Upper(evt.Meta.http_path) contains Upper('/remote_agent.php') &&\nUpper(evt.Parsed.verb) == 'GET' &&\nLower(evt.Parsed.http_args) contains 'action=polldata' &&\nLower(evt.Parsed.http_args) matches 'poller_id=.*(;|%3b)'\n", "Upper(evt.Meta.http_path) contains Upper('/remote_agent.php') &&\nUpper(evt.Parsed.verb) == 'GET' &&\nLower(evt.Parsed.http_args) contains 'host_id' &&\nLower(evt.Parsed.http_args) contains 'local_data_ids'\n", "Upper(evt.Meta.http_path) contains Upper('/vendor/htmlawed/htmlawed/htmLawedTest.php')", "Upper(evt.Parsed.file_ext) in ['.JPG', '.CSS', '.JS', '.JPEG', '.PNG', '.SVG', '.MAP', '.ICO', '.OTF', '.GIF', '.MP3', '.MP4', '.WOFF', '.WOFF2', '.TTF', '.OTF', '.EOT', '.WEBP', '.WAV', '.GZ', '.BROTLI', '.BVR', '.TS', '.BMP'] ? 'true' : 'false'", "Upper(evt.Parsed.program) == 'BAIKAL'", "Upper(evt.Parsed.program) == 'GITLAB'", "Upper(evt.Parsed.program) == 'MONGODB'", "Upper(evt.Parsed.program) == 'NAMED'", "Upper(evt.Parsed.program) == 'NEXTCLOUD'", "Upper(evt.Parsed.program) == 'PAPERLESS-NGX'", "Upper(evt.Parsed.program) == 'UPTIME-KUMA'", "Upper(evt.Parsed.program) == 'VAULTWARDEN'", "Upper(evt.Parsed.program) == 'WEBMIN'", "XMLGetAttributeValue(evt.Line.Raw, \"/Event/System[1]/Provider\", \"Name\")", "XMLGetAttributeValue(evt.Line.Raw, \"/Event/System[1]/Security\", \"UserID\")", "XMLGetAttributeValue(evt.Line.Raw, \"/Event/System[1]/TimeCreated\", \"SystemTime\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[1]\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[2]\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[3]\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='Archived']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='CallTrace']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='ClientInfo']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='CommandLine']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='Company']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='Configuration']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='ConfigurationFileHash']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='Consumer']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='CreationUtcTime']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='CurrentDirectory']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='Description']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='Destination']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='DestinationHostname']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='DestinationIp']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='DestinationIsIpv6']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='DestinationPort']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='DestinationPortName']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='Details']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='Device']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='EventNamespace']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='EventType']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='FileVersion']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='Filter']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='GrantedAccess']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='Hashes']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='Image']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='ImageLoaded']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='Initiated']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='IntegrityLevel']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='IpAddress']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='IsExecutable']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='LogonGuid']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='LogonId']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='Name']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='NewName']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='NewThreadId']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='Operation']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='OriginalFileName']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='ParentCommandLine']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='ParentImage']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='ParentProcessGuid']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='ParentProcessId']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='ParentUser']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='PipeName']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='ProcessGuid']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='ProcessId']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='Protocol']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='Query']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='QueryName']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='QueryResults']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='QueryStatus']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='RuleName']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='SchemaVersion']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='Session']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='Signature']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='SignatureStatus']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='Signed']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='SourceHostname']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='SourceImage']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='SourceIp']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='SourceIsIpv6']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='SourcePort']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='SourcePortName']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='SourceProcessGUID']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='SourceProcessGuid']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='SourceProcessId']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='SourceThreadId']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='StartAddress']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='StartFunction']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='StartModule']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='State']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='TargetFilename']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='TargetImage']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='TargetObject']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='TargetProcessGUID']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='TargetProcessGuid']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='TargetProcessId']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='TargetUserName']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='TerminalSessionId']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='Type']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='User']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='Version']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='c-ip']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='cs-method']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='cs-uri-query']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='cs-uri-stem']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='csUser-Agent']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='date']\") + \" \" + XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='time']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='s-sitename']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/EventData[1]/Data[@Name='sc-status']\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/System[1]/Channel\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/System[1]/Computer\")", "XMLGetNodeValue(evt.Line.Raw, \"/Event/System[1]/EventID\")", "all(evt.Overflow.Alert.Events, {.GetMeta('parent_progname') in ['/usr/bin/dpkg', '/usr/bin/dnf']})", "any(File('cloudflare_ip6s.txt'), { IpInRange(evt.Overflow.Alert.Source.IP ,#)})", "any(File('cloudflare_ips.txt'), { IpInRange(evt.Overflow.Alert.Source.IP ,#)})", "any(File('ip_seo_bots.txt'), { len(#) > 0 && IpInRange(evt.Overflow.Alert.Source.IP ,#)})", "any(File('rdns_seo_bots.txt'), { len(#) > 0 && evt.Enriched.reverse_dns endsWith #})", "any(['Authentication failure', 'Password mismatch', 'password mismatch', 'auth failed', 'unknown user'], {evt.Parsed.dovecot_login_message contains #}) ? 'auth_failed' : ''", "evt.Enriched.ASNNumber", "evt.Enriched.ASNOrg", "evt.Enriched.GeoCoords", "evt.Enriched.IsInEU", "evt.Enriched.IsoCode", "evt.Enriched.MarshaledTime", "evt.Enriched.SourceRange", "evt.Enriched.reverse_dns", "evt.Enriched.reverse_dns endsWith '.ptr.discord.com.'", "evt.GetType() == 'overflow' && evt.Overflow.Alert.Remediation == true", "evt.Line.Labels.external_format == 'fastly'", "evt.Line.Labels.program", "evt.Line.Labels.type", "evt.Line.Labels.type != 'syslog'", "evt.Line.Labels.type == 'aws-alb'", "evt.Line.Labels.type == 'containerd'", "evt.Line.Labels.type == 'docker'", "evt.Line.Labels.type == 'syslog'", "evt.Line.Labels.type == 'unifi'", "evt.Line.Module", "evt.Line.Module != 'wineventlog'", "evt.Line.Module == 'wineventlog'", "evt.Line.Raw", "evt.Line.Src", "evt.Meta.error in ['user_not_found', 'invalid_user_credentials']", "evt.Meta.http_path + '?' + evt.Parsed.http_args", "evt.Meta.http_status == '200' && evt.Parsed.static_ressource == 'false' && evt.Meta.http_verb == 'GET' && evt.Meta.http_path contains '/apps/photos/api/v1/preview' && evt.Parsed.http_args contains '&x=' && evt.Parsed.http_args contains '&y=' && evt.Parsed.http_args contains 'etag='", "evt.Meta.http_status == '403' && evt.Meta.http_verb == 'POST' && evt.Meta.http_path contains \"/Sessions/Playing/Progress\"", "evt.Meta.http_status == '404' && evt.Meta.http_verb == 'GET' && evt.Meta.http_path contains '/apps/files_trashbin/preview' && evt.Parsed.http_args contains 'fileId=' && evt.Parsed.http_args contains '&file='", "evt.Meta.http_status == '404' && evt.Meta.http_verb == 'GET' && evt.Meta.http_path contains '/apps/files_versions/preview' && evt.Parsed.http_args contains 'version'", "evt.Meta.http_status == '404' && evt.Meta.http_verb == 'GET' && evt.Meta.http_path contains '/apps/photos/api/v1/preview' && evt.Parsed.http_args contains 'x' && evt.Parsed.http_args contains 'y'", "evt.Meta.http_status == '404' && evt.Meta.http_verb == 'GET' && evt.Meta.http_path matches '\\\\/apps\\\\/files\\\\/api\\\\/v1\\\\/thumbnail\\\\/(\\\\d+)/(\\\\d+)'", "evt.Meta.http_status == '404' && evt.Meta.http_verb == 'GET' && evt.Meta.http_path startsWith '/apps/mail/api/avatars/url/'", "evt.Meta.http_status == '404' && evt.Meta.http_verb == 'GET' && evt.Parsed.file_ext == '.vcf' && evt.Parsed.http_args contains \"photo\"", "evt.Meta.http_status == '404' && evt.Meta.http_verb == 'GET' && evt.Parsed.request == '/ocs/v2.php/apps/text/workspace' && evt.Parsed.http_args contains 'path=%2F'", "evt.Meta.http_status == '404' && evt.Meta.http_verb == 'GET' && evt.Parsed.request contains '/core/preview' && evt.Parsed.http_args contains 'x=' && evt.Parsed.http_args contains 'y=' && evt.Parsed.http_args contains 'fileId='", "evt.Meta.http_status == '404' && evt.Meta.http_verb in ['PROPFIND', 'GET'] && evt.Meta.http_path matches '^/remote.php/(web)?dav/'", "evt.Meta.http_status in ['404', '403', '502'] ? 'false' : 'true'", "evt.Meta.log_subtype == 'zm_bad_password'", "evt.Meta.log_subtype == 'zm_bad_user'", "evt.Meta.log_type == 'gotify_failed_auth'", "evt.Meta.log_type == \"palo_alto\" && evt.Meta.severity in [\"medium\", \"high\", \"critical\"]", "evt.Meta.log_type == 'ADMIN_LOGIN_FAILED'", "evt.Meta.log_type == 'CVE-2021-4034-xpl'", "evt.Meta.log_type == 'PAYMENT_FAILED'", "evt.Meta.log_type == 'PAYMENT_FAILED' and evt.Meta.ASNNumber != '' ", "evt.Meta.log_type == 'PAYMENT_FAILED' and evt.Meta.IsoCode != '' ", "evt.Meta.log_type == 'adguardhome_failed_auth'", "evt.Meta.log_type == 'apache-guacamole_failed_auth'", "evt.Meta.log_type == 'asterisk_failed_auth'", "evt.Meta.log_type == 'auth_bf_attempt'", "evt.Meta.log_type == 'auth_bf_log'", "evt.Meta.log_type == 'aws-cloudtrail'", "evt.Meta.log_type == 'aws-cloudtrail' &&\n(\n (evt.Unmarshaled.cloudtrail.errorCode != nil && evt.Unmarshaled.cloudtrail.errorCode matches \".*UnauthorizedOperation$\") ||\n (evt.Unmarshaled.cloudtrail.errorCode != nil && evt.Unmarshaled.cloudtrail.errorCode matches \"^AccessDenied.*\")\n)\n", "evt.Meta.log_type == 'aws-cloudtrail' &&\n(\n evt.Meta.event_name == \"DeleteGroupPolicy\" ||\n evt.Meta.event_name == \"DeleteRolePolicy\" ||\n evt.Meta.event_name == \"DeleteUserPolicy\" ||\n evt.Meta.event_name == \"PutGroupPolicy\" ||\n evt.Meta.event_name == \"PutRolePolicy\" ||\n evt.Meta.event_name == \"PutUserPolicy\" ||\n evt.Meta.event_name == \"CreatePolicy\" ||\n evt.Meta.event_name == \"DeletePolicy\" ||\n evt.Meta.event_name == \"CreatePolicyVersion\" ||\n evt.Meta.event_name == \"DeletePolicyVersion\" ||\n evt.Meta.event_name == \"AttachRolePolicy\" ||\n evt.Meta.event_name == \"DetachRolePolicy\" ||\n evt.Meta.event_name == \"AttachUserPolicy\" ||\n evt.Meta.event_name == \"DetachUserPolicy\" ||\n evt.Meta.event_name == \"AttachGroupPolicy\" ||\n evt.Meta.event_name == \"DetachGroupPolicy\"\n)\n", "evt.Meta.log_type == 'aws-cloudtrail' &&\n(\nevt.Meta.event_name == \"AuthorizeSecurityGroupIngress\" ||\nevt.Meta.event_name == \"AuthorizeSecurityGroupEgress\" ||\nevt.Meta.event_name == \"RevokeSecurityGroupIngress\" ||\nevt.Meta.event_name == \"RevokeSecurityGroupEgress\" ||\nevt.Meta.event_name == \"CreateSecurityGroup\" ||\nevt.Meta.event_name == \"DeleteSecurityGroup\"\n)\n", "evt.Meta.log_type == 'aws-cloudtrail' &&\n(\nevt.Meta.event_name == \"CreateCustomerGateway\" ||\nevt.Meta.event_name == \"DeleteCustomerGateway\" ||\nevt.Meta.event_name == \"AttachInternetGateway\" ||\nevt.Meta.event_name == \"CreateInternetGateway\" ||\nevt.Meta.event_name == \"DeleteInternetGateway\" ||\nevt.Meta.event_name == \"DetachInternetGateway\"\n)\n", "evt.Meta.log_type == 'aws-cloudtrail' &&\n(\nevt.Meta.event_name == \"CreateNetworkAcl\" ||\nevt.Meta.event_name == \"CreateNetworkAclEntry\" ||\nevt.Meta.event_name == \"DeleteNetworkAcl\" ||\nevt.Meta.event_name == \"DeleteNetworkAclEntry\" ||\nevt.Meta.event_name == \"ReplaceNetworkAclEntry\" ||\nevt.Meta.event_name == \"ReplaceNetworkAclAssociation\"\n)\n", "evt.Meta.log_type == 'aws-cloudtrail' &&\n(\nevt.Meta.event_name == \"CreateRoute\" ||\nevt.Meta.event_name == \"CreateRouteTable\" ||\nevt.Meta.event_name == \"ReplaceRoute\" ||\nevt.Meta.event_name == \"ReplaceRouteTableAssociation\" ||\nevt.Meta.event_name == \"DeleteRouteTable\" ||\nevt.Meta.event_name == \"DeleteRoute\" ||\nevt.Meta.event_name == \"DisassociateRouteTable\"\n)\n", "evt.Meta.log_type == 'aws-cloudtrail' &&\n(\nevt.Meta.event_name == \"CreateTrail\" ||\nevt.Meta.event_name == \"UpdateTrail\" ||\nevt.Meta.event_name == \"DeleteTrail\" ||\nevt.Meta.event_name == \"StartLogging\" ||\nevt.Meta.event_name == \"StopLogging\"\n)\n", "evt.Meta.log_type == 'aws-cloudtrail' &&\n(\nevt.Meta.event_name == \"CreateVpc\" ||\nevt.Meta.event_name == \"DeleteVpc\" ||\nevt.Meta.event_name == \"ModifyVpcAttribute\" ||\nevt.Meta.event_name == \"AcceptVpcPeeringConnection\" ||\nevt.Meta.event_name == \"CreateVpcPeeringConnection\" ||\nevt.Meta.event_name == \"DeleteVpcPeeringConnection\" ||\nevt.Meta.event_name == \"RejectVpcPeeringConnection\" ||\nevt.Meta.event_name == \"AttachClassicLinkVpc\" ||\nevt.Meta.event_name == \"DetachClassicLinkVpc\" ||\nevt.Meta.event_name == \"DisableVpcClassicLink\" ||\nevt.Meta.event_name == \"EnableVpcClassicLink\"\n)\n", "evt.Meta.log_type == 'aws-cloudtrail' &&\n(evt.Meta.event_name == 'ConsoleLogin' || evt.Meta.event_name == 'GetSessionToken' || evt.Meta.event_name == 'GetFederationToken') &&\nevt.Unmarshaled.cloudtrail.responseElements?.ConsoleLogin == 'Success' &&\n(\n (evt.Time.Hour() >= 18 || evt.Time.Hour() < 6) || \n (evt.Time.Weekday().String() == 'Saturday' || evt.Time.Weekday().String() == 'Sunday')\n)\n", "evt.Meta.log_type == 'aws-cloudtrail' &&\nevt.Meta.event_name == \"ConsoleLogin\" &&\nevt.Unmarshaled.cloudtrail.additionalEventData.MFAUsed != \"Yes\" &&\nevt.Unmarshaled.cloudtrail.userIdentity.type == \"IAMUser\" &&\nevt.Unmarshaled.cloudtrail.responseElements.ConsoleLogin == \"Success\"\n", "evt.Meta.log_type == 'aws-cloudtrail' &&\nevt.Unmarshaled.cloudtrail.eventSource == \"kms.amazonaws.com\" &&\n(evt.Meta.event_name == \"DisableKey\" || evt.Meta.event_name == \"ScheduleKeyDeletion\")\n", "evt.Meta.log_type == 'aws-cloudtrail' &&\nevt.Unmarshaled.cloudtrail.eventSource == \"s3.amazonaws.com\" &&\n(\n evt.Meta.event_name == \"PutBucketAcl\" ||\n evt.Meta.event_name == \"PutBucketPolicy\" ||\n evt.Meta.event_name == \"PutBucketCors\" ||\n evt.Meta.event_name == \"PutBucketLifecycle\" ||\n evt.Meta.event_name == \"PutBucketReplication\" ||\n evt.Meta.event_name == \"DeleteBucketPolicy\" ||\n evt.Meta.event_name == \"DeleteBucketCors\" ||\n evt.Meta.event_name == \"DeleteBucketLifecycle\" ||\n evt.Meta.event_name == \"DeleteBucketReplication\"\n)\n", "evt.Meta.log_type == 'aws-cloudtrail' &&\nevt.Unmarshaled.cloudtrail.userIdentity.type == \"Root\" &&\nevt.Unmarshaled.cloudtrail.userIdentity.invokedBy == nil &&\nevt.Unmarshaled.cloudtrail.eventType != \"AwsServiceEvent\"\n", "evt.Meta.log_type == 'aws-cloudtrail' && \nevt.Meta.event_name == \"ConsoleLogin\" && \nevt.Unmarshaled.cloudtrail.errorMessage == \"Failed authentication\"\n", "evt.Meta.log_type == 'aws-cloudtrail' && \nevt.Unmarshaled.cloudtrail.eventSource == \"config.amazonaws.com\" &&\n(\n evt.Meta.event_name == \"StopConfigurationRecorder\" ||\n evt.Meta.event_name == \"DeleteDeliveryChannel\" ||\n evt.Meta.event_name == \"PutDeliveryChannel\" ||\n evt.Meta.event_name == \"PutConfigurationRecorder\"\n)\n", "evt.Meta.log_type == 'aws-cloudtrail' && (\n (evt.Meta.event_name == 'ConsoleLogin' && evt.Unmarshaled.cloudtrail.responseElements.ConsoleLogin == 'Failure') || \n (evt.Meta.event_name == 'GetSessionToken' && evt.Meta.error_code=='AccessDenied') || \n (evt.Meta.event_name == 'GetFederationToken' && evt.Meta.error_code=='AccessDenied')\n)\n", "evt.Meta.log_type == 'baikal_failed_auth'", "evt.Meta.log_type == 'bind9_denied'", "evt.Meta.log_type == 'cas_failed-auth'", "evt.Meta.log_type == 'dovecot_logs' && evt.Meta.dovecot_login_result == 'auth_failed'", "evt.Meta.log_type == 'emby_failed_auth'", "evt.Meta.log_type == 'endlessh_accept'", "evt.Meta.log_type == 'execve'", "evt.Meta.log_type == 'execve' && evt.Meta.exe == '/usr/bin/pgrep'", "evt.Meta.log_type == 'execve' && evt.Meta.exe in ['/usr/bin/rm', '/bin/rm']", "evt.Meta.log_type == 'execve' and ( evt.Meta.exe startsWith \"/tmp/\" or evt.Meta.exe contains \"/.\" )", "evt.Meta.log_type == 'exim_failed_auth'", "evt.Meta.log_type == 'ftp_failed_auth'", "evt.Meta.log_type == 'gitea_failed_auth'", "evt.Meta.log_type == 'gitlab_failed_password'", "evt.Meta.log_type == 'grafana_failed_auth'", "evt.Meta.log_type == 'harbor_failed_auth'", "evt.Meta.log_type == 'home-assistant_failed_auth'", "evt.Meta.log_type == 'http_access-log' && Upper(evt.Parsed.http_args) contains 'AUTHOR='", "evt.Meta.log_type == 'http_access-log' && evt.Meta.http_path startsWith '/apps/login' && evt.Parsed.verb == 'POST' && evt.Meta.http_status == '200'", "evt.Meta.log_type == 'http_access-log' && evt.Meta.http_status in ['400','405'] && (evt.Parsed.verb == 'CONNECT' || evt.Parsed.request matches '^http[s]?://')", "evt.Meta.log_type == 'http_access-log' && evt.Parsed.file_name == 'wp-login.php' && evt.Parsed.verb == 'POST' && evt.Meta.http_status == '200'", "evt.Meta.log_type == 'http_access-log' && evt.Parsed.file_name == 'xmlrpc.php' && evt.Parsed.verb == 'POST'", "evt.Meta.log_type == 'http_access-log' && evt.Parsed.file_name contains 'w00tw00t.at.ISC.SANS.DFind'", "evt.Meta.log_type == 'http_access-log' && evt.Parsed.file_name contains 'wp-config.php'", "evt.Meta.log_type == 'http_access-log' && evt.Parsed.verb == 'POST' && evt.Meta.http_status == '401'", "evt.Meta.log_type == 'http_access-log' && evt.Parsed.verb == 'POST' && evt.Meta.http_status == '403'", "evt.Meta.log_type == 'http_error-log' && evt.Parsed.program == 'nginx'", "evt.Meta.log_type == 'immich_failed_auth'", "evt.Meta.log_type == 'iptables_drop' && evt.Meta.service == 'tcp'", "evt.Meta.log_type == 'jellyfin_failed_auth'", "evt.Meta.log_type == 'jellyseerr_failed_auth'", "evt.Meta.log_type == 'k8s-audit' &&\n(\n (\n evt.Meta.datasource_type == \"k8s-audit\" &&\n evt.Unmarshaled.k8s_audit.ObjectRef?.Resource == 'pods' &&\n evt.Unmarshaled.k8s_audit.RequestObject != nil &&\n evt.Unmarshaled.k8s_audit.RequestObject.spec != nil &&\n evt.Unmarshaled.k8s_audit.RequestObject.spec.volumes != nil &&\n any(evt.Unmarshaled.k8s_audit.RequestObject.spec.volumes, { .hostPath != nil && .hostPath.path in [\"/proc\", \"/var/run/docker.sock\", \"/\", \"/etc\", \"/root\", \"/var/run/crio/crio.sock\", \"/home/admin\", \"/var/lib/kubelet\", \"/var/lib/kubelet/pki\", \"/etc/kubernetes\", \"/etc/kubernetes/manifests\"] })\n )\n ||\n (\n evt.Meta.datasource_type != \"k8s-audit\" &&\n evt.Unmarshaled.k8s_audit.objectRef?.resource == 'pods' &&\n evt.Unmarshaled.k8s_audit.requestObject != nil &&\n evt.Unmarshaled.k8s_audit.requestObject.spec != nil &&\n evt.Unmarshaled.k8s_audit.requestObject.spec.volumes != nil &&\n any(evt.Unmarshaled.k8s_audit.requestObject.spec.volumes, { .hostPath != nil && .hostPath.path in [\"/proc\", \"/var/run/docker.sock\", \"/\", \"/etc\", \"/root\", \"/var/run/crio/crio.sock\", \"/home/admin\", \"/var/lib/kubelet\", \"/var/lib/kubelet/pki\", \"/etc/kubernetes\", \"/etc/kubernetes/manifests\"] })\n )\n)\n", "evt.Meta.log_type == 'k8s-audit' &&\n(\n (\n evt.Meta.datasource_type == \"k8s-audit\" &&\n evt.Unmarshaled.k8s_audit.Verb == 'create' &&\n evt.Unmarshaled.k8s_audit.ObjectRef?.Resource == 'pods' &&\n evt.Unmarshaled.k8s_audit.RequestObject != nil &&\n evt.Unmarshaled.k8s_audit.RequestObject.spec != nil &&\n any(evt.Unmarshaled.k8s_audit.RequestObject.spec.containers, { .securityContext != nil && .securityContext.privileged == true })\n )\n ||\n (\n evt.Meta.datasource_type != \"k8s-audit\" &&\n evt.Unmarshaled.k8s_audit.verb == 'create' &&\n evt.Unmarshaled.k8s_audit.objectRef?.resource == 'pods' &&\n evt.Unmarshaled.k8s_audit.requestObject != nil &&\n evt.Unmarshaled.k8s_audit.requestObject.spec != nil &&\n any(evt.Unmarshaled.k8s_audit.requestObject.spec.containers, { .securityContext != nil && .securityContext.privileged == true })\n )\n)\n", "evt.Meta.log_type == 'k8s-audit' &&\n(\n (evt.Meta.datasource_type == \"k8s-audit\" && evt.Unmarshaled.k8s_audit.ObjectRef?.Resource == 'pods' && evt.Unmarshaled.k8s_audit.ObjectRef?.Subresource == 'exec')\n ||\n (evt.Meta.datasource_type != \"k8s-audit\" && evt.Unmarshaled.k8s_audit.objectRef?.resource == 'pods' && evt.Unmarshaled.k8s_audit.objectRef?.subresource == 'exec')\n)\n", "evt.Meta.log_type == 'k8s-audit' &&\n(\n (evt.Meta.datasource_type == \"k8s-audit\" && evt.Unmarshaled.k8s_audit.ObjectRef?.Resource not in [\"healthz\", \"livez\", \"readyz\"]) \n || \n (evt.Meta.datasource_type != \"k8s-audit\" && evt.Unmarshaled.k8s_audit.objectRef?.resource not in [\"healthz\", \"livez\", \"readyz\"])\n)\n&& evt.Meta.user in [\"system:anonymous\", \"system:unauthenticated\"]\n", "evt.Meta.log_type == 'k8s-audit' &&\n(\n (evt.Meta.datasource_type == \"k8s-audit\" && evt.Unmarshaled.k8s_audit.Verb == 'create' && evt.Unmarshaled.k8s_audit.ObjectRef?.Resource == 'pods' && evt.Unmarshaled.k8s_audit.RequestObject?.spec?.hostNetwork == true)\n ||\n (evt.Meta.datasource_type != \"k8s-audit\" && evt.Unmarshaled.k8s_audit.verb == 'create' && evt.Unmarshaled.k8s_audit.objectRef?.resource == 'pods' && evt.Unmarshaled.k8s_audit.requestObject?.spec?.hostNetwork == true)\n)\n", "evt.Meta.log_type == 'k8s-audit' &&\nevt.Meta.user startsWith \"system:serviceaccount:\" &&\n(\n (evt.Meta.datasource_type == \"k8s-audit\" && evt.Unmarshaled.k8s_audit.Annotations[\"authorization.k8s.io/decision\"] == \"forbid\")\n ||\n (evt.Meta.datasource_type != \"k8s-audit\" && evt.Unmarshaled.k8s_audit.annotations[\"authorization.k8s.io/decision\"] == \"forbid\")\n)\n", "evt.Meta.log_type == 'k8s-audit' && \n(\n (evt.Meta.datasource_type == \"k8s-audit\" && evt.Unmarshaled.k8s_audit.ResponseStatus.code in [401, 403])\n ||\n (evt.Meta.datasource_type != \"k8s-audit\" && evt.Unmarshaled.k8s_audit.responseStatus.code in [401, 403])\n)\n", "evt.Meta.log_type == 'mail_auth' && evt.Meta.sub_type == 'auth_fail'", "evt.Meta.log_type == 'mailu_admin_auth_attempt'", "evt.Meta.log_type == 'mariadb_failed_auth'", "evt.Meta.log_type == 'meshcentral_failed_auth'", "evt.Meta.log_type == 'mikrotik_drop' && evt.Meta.service == 'tcp_udp'", "evt.Meta.log_type == 'mikrotik_failed_auth'", "evt.Meta.log_type == 'modsecurity' && (evt.Parsed.ruleseverity == 'CRITICAL' || evt.Parsed.ruleseverity == '2')", "evt.Meta.log_type == 'mongodb_failed_auth'", "evt.Meta.log_type == 'mssql_failed_auth'", "evt.Meta.log_type == 'mysql_failed_auth'", "evt.Meta.log_type == 'nextcloud_domain_error'", "evt.Meta.log_type == 'nextcloud_failed_auth'", "evt.Meta.log_type == 'odoo_failed_auth'", "evt.Meta.log_type == 'ombi_auth_failed'", "evt.Meta.log_type == 'openappsec_security_log' and Lower(evt.Meta.security_action) in ['prevent', 'detect'] and Lower(evt.Meta.incident_type) contains 'bot protection'", "evt.Meta.log_type == 'openappsec_security_log' and Lower(evt.Meta.security_action) in ['prevent', 'detect'] and Lower(evt.Meta.incident_type) contains 'cross site redirect'", "evt.Meta.log_type == 'openappsec_security_log' and Lower(evt.Meta.security_action) in ['prevent', 'detect'] and Lower(evt.Meta.incident_type) contains 'cross site request forgery'", "evt.Meta.log_type == 'openappsec_security_log' and Lower(evt.Meta.security_action) in ['prevent', 'detect'] and Lower(evt.Meta.incident_type) contains 'cross site scripting'", "evt.Meta.log_type == 'openappsec_security_log' and Lower(evt.Meta.security_action) in ['prevent', 'detect'] and Lower(evt.Meta.incident_type) contains 'error disclosure'", "evt.Meta.log_type == 'openappsec_security_log' and Lower(evt.Meta.security_action) in ['prevent', 'detect'] and Lower(evt.Meta.incident_type) contains 'error limit'", "evt.Meta.log_type == 'openappsec_security_log' and Lower(evt.Meta.security_action) in ['prevent', 'detect'] and Lower(evt.Meta.incident_type) contains 'evasion techniques'", "evt.Meta.log_type == 'openappsec_security_log' and Lower(evt.Meta.security_action) in ['prevent', 'detect'] and Lower(evt.Meta.incident_type) contains 'general'", "evt.Meta.log_type == 'openappsec_security_log' and Lower(evt.Meta.security_action) in ['prevent', 'detect'] and Lower(evt.Meta.incident_type) contains 'http limit violation'", "evt.Meta.log_type == 'openappsec_security_log' and Lower(evt.Meta.security_action) in ['prevent', 'detect'] and Lower(evt.Meta.incident_type) contains 'illegal http method violation'", "evt.Meta.log_type == 'openappsec_security_log' and Lower(evt.Meta.security_action) in ['prevent', 'detect'] and Lower(evt.Meta.incident_type) contains 'ldap injection'", "evt.Meta.log_type == 'openappsec_security_log' and Lower(evt.Meta.security_action) in ['prevent', 'detect'] and Lower(evt.Meta.incident_type) contains 'open redirect'", "evt.Meta.log_type == 'openappsec_security_log' and Lower(evt.Meta.security_action) in ['prevent', 'detect'] and Lower(evt.Meta.incident_type) contains 'path traversal'", "evt.Meta.log_type == 'openappsec_security_log' and Lower(evt.Meta.security_action) in ['prevent', 'detect'] and Lower(evt.Meta.incident_type) contains 'remote code execution'", "evt.Meta.log_type == 'openappsec_security_log' and Lower(evt.Meta.security_action) in ['prevent', 'detect'] and Lower(evt.Meta.incident_type) contains 'request rate limit'", "evt.Meta.log_type == 'openappsec_security_log' and Lower(evt.Meta.security_action) in ['prevent', 'detect'] and Lower(evt.Meta.incident_type) contains 'schema validation'", "evt.Meta.log_type == 'openappsec_security_log' and Lower(evt.Meta.security_action) in ['prevent', 'detect'] and Lower(evt.Meta.incident_type) contains 'sql injection'", "evt.Meta.log_type == 'openappsec_security_log' and Lower(evt.Meta.security_action) in ['prevent', 'detect'] and Lower(evt.Meta.incident_type) contains 'url instead of file'", "evt.Meta.log_type == 'openappsec_security_log' and Lower(evt.Meta.security_action) in ['prevent', 'detect'] and Lower(evt.Meta.incident_type) contains 'vulnerability scanning'", "evt.Meta.log_type == 'openappsec_security_log' and Lower(evt.Meta.security_action) in ['prevent', 'detect'] and Lower(evt.Meta.incident_type) contains 'xml external entity'", "evt.Meta.log_type == 'opnsense-gui-failed-auth'", "evt.Meta.log_type == 'paperless_ngx_failed_auth'", "evt.Meta.log_type == 'pf' and evt.Parsed.action == 'block'", "evt.Meta.log_type == 'pf_drop' && evt.Meta.service == 'tcp_udp'", "evt.Meta.log_type == 'pftpd_failed-auth'", "evt.Meta.log_type == 'pgsql_failed_auth'", "evt.Meta.log_type == 'pterodactly_wings_invalid_format'", "evt.Meta.log_type == 'pterodactly_wings_invalid_username_or_password'", "evt.Meta.log_type == 'pve_failed-auth'", "evt.Meta.log_type == 'redmine_failed_auth'", "evt.Meta.log_type == 'smb_failed_auth'", "evt.Meta.log_type == 'spam-attempt' && evt.Meta.service == 'exim'", "evt.Meta.log_type == 'ssh_bad_keyexchange'", "evt.Meta.log_type == 'ssh_failed-auth'", "evt.Meta.log_type == 'sshesame_cmd'", "evt.Meta.log_type == 'sshesame_input'", "evt.Meta.log_type == 'sshesame_login'", "evt.Meta.log_type == 'suricata_alert' && evt.Parsed.proto == 'TCP' && evt.Meta.suricata_rule_severity == '1'", "evt.Meta.log_type == 'suricata_alert' && evt.Parsed.proto == 'TCP' && evt.Meta.suricata_rule_severity == '2'", "evt.Meta.log_type == 'synology-dsm_failed_auth'", "evt.Meta.log_type == 'telnet_new_session'", "evt.Meta.log_type == 'thehive_failed_auth'", "evt.Meta.log_type == 'ts3_fail_auth'", "evt.Meta.log_type == 'vaultwarden_failed_auth'", "evt.Meta.log_type == 'waf_naxsi-log' && len(evt.Parsed.naxsi_id) > 4", "evt.Meta.log_type == 'webmin_failed_auth_wrong_pass'", "evt.Meta.log_type == 'windows_failed_auth'", "evt.Meta.log_type == 'wireguard_failed_auth'", "evt.Meta.log_type == 'zimbra_auth_fail'", "evt.Meta.log_type in [\"http_access-log\", \"http_error-log\"]\nand \n (\n ( Upper(evt.Meta.http_verb) == \"POST\" and\n Upper(evt.Meta.http_path) matches Upper('^(?P/.*index.php)?.*(?Pfile=.*</td></tr(?P.*)>)')\n )\n or \n Upper(evt.Parsed.rawrequest) matches Upper('^(?PPOST) (?P/.*index.php)?.*(?Pfile=.*</td></tr(?P.*)>)')\n )\n", "evt.Meta.log_type in [\"http_access-log\", \"http_error-log\"]\nand \n(\n( Upper(evt.Meta.http_verb) == \"POST\" and\nUpper(evt.Meta.http_path) matches Upper('^(?P/.*index.php)?.*(?Pview=request|request=log|task=create)+.*(?Pview=request|request=log|task=create)+.*(?Pview=request|request=log|task=create)+.*')\n\n)\nor\nUpper(evt.Parsed.rawrequest) matches Upper('^(?PPOST) (?P/.*index.php)?.*(?Pview=request|request=log|task=create)+.*(?Pview=request|request=log|task=create)+.*(?Pview=request|request=log|task=create)+.*')\n)\n", "evt.Meta.log_type in [\"http_access-log\", \"http_error-log\"]\nand Upper(evt.Meta.http_verb) == \"GET\"\nand Upper(evt.Meta.http_path) matches Upper('.*action=.*')\n", "evt.Meta.log_type in [\"http_access-log\", \"http_error-log\"] && RegexpInFile(evt.Parsed.http_user_agent, \"bad_user_agents.regex.txt\")", "evt.Meta.log_type in [\"http_access-log\", \"http_error-log\"] and\n (Upper(evt.Meta.http_path) contains 'CLASS.MODULE.CLASSLOADER.')\n", "evt.Meta.log_type in [\"http_access-log\", \"http_error-log\"] and \n (\n Upper(evt.Meta.http_path) matches Upper('/tmui/login.jsp/..;/tmui/[^.]+.jsp\\\\?(fileName|command|directoryPath|tabId)=')\n or\n Upper(evt.Meta.http_path) matches Upper('/tmui/login.jsp/%2E%2E;/tmui/[^.]+.jsp\\\\?(fileName|command|directoryPath|tabId)=')\n )\n", "evt.Meta.log_type in [\"http_access-log\", \"http_error-log\"] and \n (Upper(evt.Meta.http_path) contains \"/.%2E/.%2E/\"\n or\n Upper(evt.Meta.http_path) contains \"/%2E%2E/%2E%2E\")\n", "evt.Meta.log_type in [\"http_access-log\", \"http_error-log\"] and \n (Upper(evt.Meta.http_path) matches '/PUBLIC/PLUGINS/[^/]+/../[./]+/'\n or\n Upper(evt.Meta.http_path) matches '/PUBLIC/PLUGINS/[^/]+/%2E%2E/[%2E/]+/')\n", "evt.Meta.log_type in [\"http_access-log\", \"http_error-log\"] and \n (Upper(evt.Meta.http_path) matches Upper('/dana-na/../dana/html5acc/guacamole/../../../../../../../[^?]+\\\\?/dana/html5acc/guacamole/')\n or\n Upper(evt.Meta.http_path) matches Upper('/dana-na/%2E%2E/dana/html5acc/guacamole/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/%2E%2E/[^?]+\\\\?/dana/html5acc/guacamole/'))\n", "evt.Meta.log_type in [\"http_access-log\", \"http_error-log\"] and \n Upper(evt.Meta.http_path) contains \"/%%32%65%%32%65/\"\n", "evt.Meta.log_type in [\"http_access-log\", \"http_error-log\"] and \n Upper(evt.Meta.http_path) contains Upper('/remote/fgt_lang?lang=/../../../..//////////dev/cmdb/sslvpn_websession')\n", "evt.Meta.log_type in [\"http_access-log\", \"http_error-log\"] and \n(\n any(File(\"log4j2_cve_2021_44228.txt\"), { Upper(evt.Meta.http_path) contains Upper(#)})\nor\n any(File(\"log4j2_cve_2021_44228.txt\"), { Upper(evt.Parsed.http_user_agent) contains Upper(#)})\nor\n any(File(\"log4j2_cve_2021_44228.txt\"), { Upper(evt.Parsed.http_referer) contains Upper(#)}) \n)\n", "evt.Meta.log_type in [\"http_access-log\", \"http_error-log\"] and \nUpper(evt.Meta.http_path) startsWith Upper('/api/v2/cmdb/system/admin/') and Lower(evt.Parsed.http_user_agent) == 'report runner'\n", "evt.Meta.log_type in [\"http_access-log\", \"http_error-log\"] and any(File(\"backdoors.txt\"), { evt.Parsed.file_name == #})", "evt.Meta.log_type in [\"http_access-log\", \"http_error-log\"] and any(File(\"jira_cve_2021-26086.txt\"), {Upper(evt.Meta.http_path) contains Upper(#)})\n", "evt.Meta.log_type in [\"http_access-log\", \"http_error-log\"] and any(File(\"sensitive_data.txt\"), { evt.Parsed.request endsWith #})", "evt.Meta.log_type in [\"http_access-log\", \"http_error-log\"] and any(File(\"thinkphp_cve_2018-20062.txt\"), {Upper(evt.Meta.http_path) matches Upper(#)})\n", "evt.Meta.log_type in ['authelia_failed_clf_auth', 'authelia_failed_json_auth']", "evt.Meta.log_type in ['baikal_failed_auth', 'baikal_failed_auth_no_user']", "evt.Meta.log_type in ['bitwarden_failed_auth','bitwarden_failed_auth_2fa']", "evt.Meta.log_type in ['gitlab_failed_password', 'gitlab_failed_totp']", "evt.Meta.log_type in ['http_access-log', 'http_error-log'] && Lower(QueryUnescape(evt.Meta.http_path)) startsWith Lower('/setup.cgi?next_file=netgear.cfg&todo=syscmd&cmd=')\n", "evt.Meta.log_type in ['http_access-log', 'http_error-log'] && Upper(QueryUnescape(evt.Meta.http_path)) startsWith Upper('/Telerik.Web.UI.WebResource.axd?type=rau')\n", "evt.Meta.log_type in ['http_access-log', 'http_error-log'] && Upper(QueryUnescape(evt.Meta.http_path)) startsWith Upper('/catalog-portal/ui/oauth/verify?error=&deviceUdid=${\"freemarker.template.utility.Execute\"?new()(')\n", "evt.Meta.log_type in ['http_access-log', 'http_error-log'] && any(File('http_path_traversal.txt'),{evt.Meta.http_path contains #})", "evt.Meta.log_type in ['http_access-log', 'http_error-log'] && any(File('sqli_probe_patterns.txt'), {Upper(evt.Parsed.http_args) contains Upper(#)})", "evt.Meta.log_type in ['http_access-log', 'http_error-log'] && any(File('xss_probe_patterns.txt'), {Upper(evt.Parsed.http_args) contains Upper(#)})", "evt.Meta.log_type in ['http_access-log', 'http_error-log'] && evt.Meta.http_path matches '/ui/vcav-bootstrap/rest/vcav-providers/provider-logo\\\\?url=(file|http)'\n", "evt.Meta.log_type in ['http_access-log', 'http_error-log'] && evt.Parsed.static_ressource == 'false' && evt.Parsed.verb in ['GET', 'HEAD']", "evt.Meta.log_type in ['nextcloud_failed_auth', 'nextcloud_bruteforce_attempt']", "evt.Meta.log_type in ['prowlarr_failed_authentication']", "evt.Meta.log_type in ['radarr_failed_authentication']", "evt.Meta.log_type in ['sonarr_failed_authentication']", "evt.Meta.log_type in ['uptime_kuma_failed_password', 'uptime_kuma_failed_totp']", "evt.Meta.log_type in ['vaultwarden_failed_auth', 'vaultwarden_failed_admin_auth', 'vaultwarden_failed_totp']", "evt.Meta.log_type_enh == 'spam-attempt' || evt.Meta.log_type == 'postfix' && evt.Meta.action == 'reject'", "evt.Meta.metric_name in ['account.login.failed_invalid_user', 'account.login.failed_invalid_password']", "evt.Meta.ppid", "evt.Meta.service == 'exchange' && evt.Meta.sub_type == 'auth_fail'", "evt.Meta.service == 'freeswitch' && evt.Meta.sub_type == 'acl_reject'", "evt.Meta.service == 'freeswitch' && evt.Meta.sub_type == 'auth_failure'", "evt.Meta.service == 'freeswitch' && evt.Meta.sub_type == 'user_enumeration'", "evt.Meta.service == 'http' && evt.Meta.http_status in ['404', '403', '400'] && evt.Parsed.static_ressource == 'false'", "evt.Meta.service == 'http' && evt.Meta.log_type in ['http_access-log', 'http_error-log']", "evt.Meta.service == 'http' && evt.Meta.sub_type == 'auth_fail'", "evt.Meta.service == 'http' && evt.Meta.sub_type == 'litespeed_admin_auth_fail'", "evt.Meta.service == 'llng' and evt.Meta.log_type == 'llng_auth_fail'", "evt.Meta.service == 'postscreen' && evt.Meta.pregreet == 'PREGREET'", "evt.Meta.service == 'sysmon' && evt.Parsed.EventID == '1' &&\nevt.Parsed.ParentImage endsWith \"\\\\svchost.exe\" &&\nevt.Parsed.Image endsWith \"\\\\rundll32.exe\" &&\nevt.Parsed.CommandLine contains \"C:\\\\windows\\\\system32\\\\davclnt.dll,DavSetCookie\" &&\nevt.Parsed.CommandLine matches '://\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}\\\\.\\\\d{1,3}' &&\n(not (evt.Parsed.CommandLine contains \"://10.\" ||\n evt.Parsed.CommandLine contains \"://192.168.\" ||\n evt.Parsed.CommandLine contains \"://172.16.\" ||\n evt.Parsed.CommandLine contains \"://172.17.\" ||\n evt.Parsed.CommandLine contains \"://172.18.\" ||\n evt.Parsed.CommandLine contains \"://172.19.\" ||\n evt.Parsed.CommandLine contains \"://172.20.\" ||\n evt.Parsed.CommandLine contains \"://172.21.\" ||\n evt.Parsed.CommandLine contains \"://172.22.\" ||\n evt.Parsed.CommandLine contains \"://172.23.\" ||\n evt.Parsed.CommandLine contains \"://172.24.\" ||\n evt.Parsed.CommandLine contains \"://172.25.\" ||\n evt.Parsed.CommandLine contains \"://172.26.\" ||\n evt.Parsed.CommandLine contains \"://172.27.\" ||\n evt.Parsed.CommandLine contains \"://172.28.\" ||\n evt.Parsed.CommandLine contains \"://172.29.\" ||\n evt.Parsed.CommandLine contains \"://172.30.\" ||\n evt.Parsed.CommandLine contains \"://172.31.\" ||\n evt.Parsed.CommandLine contains \"://127.\" ||\n evt.Parsed.CommandLine contains \"://169.254.\"))\n", "evt.Meta.service == 'sysmon' && evt.Parsed.EventID == '1' && \nUpper(evt.Parsed.Image) endsWith 'MSDT.EXE' && \nUpper(evt.Parsed.ParentImage) endsWith 'WINWORD.EXE' &&\n(Upper(evt.Parsed.CommandLine) contains 'PCWDIAGNOSTIC' && Upper(evt.Parsed.CommandLine) contains 'IT_REBROWSEFORFILE' && Upper(evt.Parsed.CommandLine) contains 'IT_BROWSEFORFILE')\n", "evt.Meta.service in [\"tcp\", \"udp\"] && evt.Unmarshaled.iptables.OUT == \"\" ? \"iptables_drop\" : \"\"", "evt.Meta.source_ip", "evt.Meta.sub_type == 'req_limit_exceeded'", "evt.Meta.target_user", "evt.Meta.user_arn", "evt.Overflow.Alert.GetScenario() == 'crowdsecurity/auditd-sus-exec' && all(evt.Overflow.Alert.Events, {.GetMeta('exe') matches '\\\\.nvm\\\\/versions\\\\/node\\\\/v(\\\\d+)\\\\.(\\\\d+)\\\\.(\\\\d+)\\\\/bin\\\\/node$'})", "evt.Overflow.Alert.Remediation == true && IsIPV6(evt.Overflow.Alert.Source.IP)", "evt.Overflow.Alert.Remediation == true && evt.Overflow.Alert.GetScope() == 'Ip'", "evt.Overflow.Alert.Source.IP", "evt.Parsed.Channel == 'Application' && evt.Parsed.Source == 'MSSQLSERVER' && evt.Parsed.EventID == '18456'", "evt.Parsed.Channel == 'Microsoft-Windows-Sysmon/Operational'", "evt.Parsed.Channel == 'Security' && evt.Parsed.EventID == '4625'", "evt.Parsed.User", "evt.Parsed.action", "evt.Parsed.app", "evt.Parsed.asterisk_service", "evt.Parsed.asterisk_session_id", "evt.Parsed.auth_method", "evt.Parsed.auth_result", "evt.Parsed.cas_client_ip", "evt.Parsed.cas_invalid_user", "evt.Parsed.client", "evt.Parsed.client_ip", "evt.Parsed.clientip", "evt.Parsed.cri_timestamp", "evt.Parsed.date", "evt.Parsed.date + ' ' + evt.Parsed.time", "evt.Parsed.datetime", "evt.Parsed.day + \" \" + evt.Parsed.month + \" \" + evt.Parsed.monthday + \" \" + evt.Parsed.time + \".000000\" + \" \" + evt.Parsed.year", "evt.Parsed.db_name", "evt.Parsed.dest_ip", "evt.Parsed.dest_port", "evt.Parsed.dovecot_remote_ip", "evt.Parsed.dst_country", "evt.Parsed.dst_port", "evt.Parsed.elb_status_code", "evt.Parsed.email", "evt.Parsed.error", "evt.Parsed.event_inc_id", "evt.Parsed.fastly_timestamp + \".00+\" + evt.Parsed.tz_part1 + \":\" + evt.Parsed.tz_part2", "evt.Parsed.file_frag + evt.Parsed.file_ext", "evt.Parsed.haproxy_monthday + '/' + evt.Parsed.haproxy_month + '/' + evt.Parsed.haproxy_year + ':' + evt.Parsed.haproxy_hour + ':' + evt.Parsed.haproxy_minute + ':' + evt.Parsed.haproxy_second[0:2] + ' -0000'", "evt.Parsed.http_path", "evt.Parsed.http_request", "evt.Parsed.http_status_code", "evt.Parsed.http_user_agent", "evt.Parsed.http_verb", "evt.Parsed.invalid_user", "evt.Parsed.ipAddress", "evt.Parsed.ip_source", "evt.Parsed.log_level", "evt.Parsed.logsource", "evt.Parsed.message contains 'PVEFW-reject' or evt.Parsed.message contains 'DROP' or evt.Parsed.message contains 'REJECT'", "evt.Parsed.method", "evt.Parsed.naxsi_src_ip", "evt.Parsed.pgsql_dbname", "evt.Parsed.pgsql_target_user", "evt.Parsed.pregreet", "evt.Parsed.program == \"gotify\"", "evt.Parsed.program == \"suricata-evelogs\" && JsonExtract(evt.Parsed.message, \"event_type\") == \"alert\"\n", "evt.Parsed.program == \"zoneminder\"", "evt.Parsed.program == 'Prowlarr'", "evt.Parsed.program == 'Radarr'", "evt.Parsed.program == 'adguardhome'", "evt.Parsed.program == 'apache-guacamole'", "evt.Parsed.program == 'asterisk'", "evt.Parsed.program == 'audit'", "evt.Parsed.program == 'auditd'", "evt.Parsed.program == 'authelia'", "evt.Parsed.program == 'aws-cloudtrail'", "evt.Parsed.program == 'bitwarden'", "evt.Parsed.program == 'cas'", "evt.Parsed.program == 'cowrie'", "evt.Parsed.program == 'cpanel'", "evt.Parsed.program == 'dovecot'", "evt.Parsed.program == 'dropbear'", "evt.Parsed.program == 'emby'", "evt.Parsed.program == 'endlessh'", "evt.Parsed.program == 'exchange-imap'", "evt.Parsed.program == 'exchange-pop'", "evt.Parsed.program == 'exchange-smtp'", "evt.Parsed.program == 'exim'", "evt.Parsed.program == 'filterlog' or evt.Parsed.message matches '^filterlog:'", "evt.Parsed.program == 'gitea'", "evt.Parsed.program == 'grafana'", "evt.Parsed.program == 'harbor'", "evt.Parsed.program == 'home-assistant' or evt.Parsed.program endsWith 'homeassistant'", "evt.Parsed.program == 'iis'", "evt.Parsed.program == 'immich'", "evt.Parsed.program == 'jellyfin'", "evt.Parsed.program == 'jellyseerr'", "evt.Parsed.program == 'k8s-audit'", "evt.Parsed.program == 'kernel' and evt.Parsed.message contains 'IN=' and not (evt.Parsed.message contains 'ACCEPT')", "evt.Parsed.program == 'kernel' and evt.Parsed.message contains 'wireguard:'", "evt.Parsed.program == 'keycloak'", "evt.Parsed.program == 'laurel'", "evt.Parsed.program == 'litespeed'", "evt.Parsed.program == 'magento-extension'", "evt.Parsed.program == 'mailu-admin'", "evt.Parsed.program == 'meshcentral'", "evt.Parsed.program == 'mikrotik'", "evt.Parsed.program == 'modsecurity'", "evt.Parsed.program == 'mssql'", "evt.Parsed.program == 'mysql'", "evt.Parsed.program == 'odoo'", "evt.Parsed.program == 'ombi'", "evt.Parsed.program == 'openappsec' && JsonExtract(evt.Parsed.message, 'eventAudience') == 'Security' && Lower(JsonExtract(evt.Parsed.message, 'eventSeverity')) in ['critical', 'high'] && Lower(JsonExtract(evt.Parsed.message, 'eventData.practiceSubType')) in ['web application','web api']", "evt.Parsed.program == 'palo-alto-threat'", "evt.Parsed.program == 'pkexec'", "evt.Parsed.program == 'postgres'", "evt.Parsed.program == 'proftpd'", "evt.Parsed.program == 'pterodactyl'", "evt.Parsed.program == 'pure-ftpd'", "evt.Parsed.program == 'pvedaemon'", "evt.Parsed.program == 'redmine'", "evt.Parsed.program == 'smb'", "evt.Parsed.program == 'sshd'", "evt.Parsed.program == 'sshesame'", "evt.Parsed.program == 'sudo'", "evt.Parsed.program == 'suricata-fastlogs'", "evt.Parsed.program == 'tcpdump'", "evt.Parsed.program == 'thehive'", "evt.Parsed.program == 'ts3'", "evt.Parsed.program == 'vsftpd'", "evt.Parsed.program == 'windows-firewall' and evt.Parsed.message contains ' DROP TCP ' and evt.Parsed.message contains ' RECEIVE'", "evt.Parsed.program in ['LLNG','lemonldap-ng']", "evt.Parsed.program in ['mono', 'Sonarr']", "evt.Parsed.program in ['postfix/postscreen', 'haproxy/postscreen']", "evt.Parsed.program in ['postfix/smtpd','postfix/smtps/smtpd','postfix/submission/smtpd', 'postfix/smtps-haproxy/smtpd', 'postfix/submission-haproxy/smtpd']", "evt.Parsed.program matches 'synoscgi_SYNO.API.Auth_[1-9]([0-9])?_login'", "evt.Parsed.program startsWith 'apache2'", "evt.Parsed.program startsWith 'caddy'", "evt.Parsed.program startsWith 'freeswitch'", "evt.Parsed.program startsWith 'haproxy'", "evt.Parsed.program startsWith 'kasm'", "evt.Parsed.program startsWith 'mariadb'", "evt.Parsed.program startsWith 'nginx'", "evt.Parsed.program startsWith 'nginx-proxy-manager'", "evt.Parsed.program startsWith 'traefik'", "evt.Parsed.program startsWith 'zimbra'", "evt.Parsed.rbl_url", "evt.Parsed.remote_addr", "evt.Parsed.remote_host", "evt.Parsed.remote_ip", "evt.Parsed.remote_user", "evt.Parsed.request", "evt.Parsed.request_creation_time", "evt.Parsed.response", "evt.Parsed.rule", "evt.Parsed.rule_id", "evt.Parsed.ruledata", "evt.Parsed.ruleid", "evt.Parsed.rulemessage", "evt.Parsed.severity", "evt.Parsed.smtp_message", "evt.Parsed.source_dns", "evt.Parsed.source_helo", "evt.Parsed.source_ip", "evt.Parsed.source_rdns", "evt.Parsed.source_user", "evt.Parsed.sourcehost", "evt.Parsed.src_country", "evt.Parsed.src_ip", "evt.Parsed.sshd_client_ip", "evt.Parsed.sshd_invalid_user", "evt.Parsed.sshesame_cmd", "evt.Parsed.sshesame_input", "evt.Parsed.sshesame_user", "evt.Parsed.status", "evt.Parsed.suricata_rule_severity", "evt.Parsed.syslog_timestamp", "evt.Parsed.target_fqdn", "evt.Parsed.target_ip", "evt.Parsed.target_port", "evt.Parsed.target_uri", "evt.Parsed.target_user", "evt.Parsed.tcpflags contains 'S' ? 'true' : 'false'", "evt.Parsed.telnet_session", "evt.Parsed.threat_id", "evt.Parsed.time", "evt.Parsed.time + 'Z'", "evt.Parsed.time_local", "evt.Parsed.timestamp", "evt.Parsed.timestamp + \"Z\"", "evt.Parsed.timestamp8601", "evt.Parsed.traefik_router_name", "evt.Parsed.unix_epoch", "evt.Parsed.user", "evt.Parsed.user_agent", "evt.Parsed.username", "evt.Parsed.verb", "evt.Parsed.year+ \"/\" + evt.Parsed.month + \"/\" + evt.Parsed.day + \" \" + evt.Parsed.time", "evt.StrTime", "evt.StrTime != ''", "evt.Unmarshaled.auditd.auid", "evt.Unmarshaled.auditd.exe", "evt.Unmarshaled.auditd.msg", "evt.Unmarshaled.auditd.ppid", "evt.Unmarshaled.auditd.tty", "evt.Unmarshaled.auditd.uid", "evt.Unmarshaled.cloudtrail.awsRegion", "evt.Unmarshaled.cloudtrail.errorCode", "evt.Unmarshaled.cloudtrail.eventID", "evt.Unmarshaled.cloudtrail.eventName", "evt.Unmarshaled.cloudtrail.eventSource", "evt.Unmarshaled.cloudtrail.eventTime", "evt.Unmarshaled.cloudtrail.userAgent", "evt.Unmarshaled.cloudtrail.userIdentity.accountId", "evt.Unmarshaled.cloudtrail.userIdentity.type", "evt.Unmarshaled.cloudtrail.userIdentity?.arn ?? evt.Unmarshaled.cloudtrail.userIdentity.userName\n", "evt.Unmarshaled.iptables.CODE", "evt.Unmarshaled.iptables.DPT", "evt.Unmarshaled.iptables.DST", "evt.Unmarshaled.iptables.IN", "evt.Unmarshaled.iptables.LEN", "evt.Unmarshaled.iptables.PROTO", "evt.Unmarshaled.iptables.SPT", "evt.Unmarshaled.iptables.SRC", "evt.Unmarshaled.iptables.TYPE", "evt.Unmarshaled.k8s_audit.ObjectRef?.Name", "evt.Unmarshaled.k8s_audit.ObjectRef?.Namespace", "evt.Unmarshaled.k8s_audit.RequestObject?.kind", "evt.Unmarshaled.k8s_audit.RequestReceivedTimestamp", "evt.Unmarshaled.k8s_audit.SourceIPs[0]", "evt.Unmarshaled.k8s_audit.User.username", "evt.Unmarshaled.k8s_audit.objectRef?.name", "evt.Unmarshaled.k8s_audit.objectRef?.namespace", "evt.Unmarshaled.k8s_audit.requestObject?.kind", "evt.Unmarshaled.k8s_audit.requestReceivedTimestamp", "evt.Unmarshaled.k8s_audit.sourceIPs[0]", "evt.Unmarshaled.k8s_audit.user.username", "evt.Unmarshaled.laurel.ID", "evt.Unmarshaled.laurel.SYSCALL.PPID.exe", "evt.Unmarshaled.laurel.SYSCALL.SYSCALL", "evt.Unmarshaled.laurel.SYSCALL.exe", "evt.Unmarshaled.laurel.SYSCALL.tty", "evt.Unmarshaled.traefik.ClientHost", "evt.Unmarshaled.traefik.DownstreamContentSize != nil ? int(evt.Unmarshaled.traefik.DownstreamContentSize) : nil", "evt.Unmarshaled.traefik.RequestAddr", "evt.Unmarshaled.traefik.RequestMethod", "evt.Unmarshaled.traefik.RequestPath", "evt.Unmarshaled.traefik.RouterName", "evt.Unmarshaled.traefik.ServiceAddr != nil ? Split(evt.Unmarshaled.traefik.ServiceAddr, ':')[0] : nil", "evt.Unmarshaled.traefik.time", "evt.Unmarshaled.traefik[\"request_User-Agent\"]", "filter(JsonExtractSlice(evt.Parsed.message, \"params\"), {.key == 'user' && .value.login != ''})[0]['value']['login']", "int(evt.Unmarshaled.laurel.SYSCALL.auid)", "int(evt.Unmarshaled.laurel.SYSCALL.ppid)", "int(evt.Unmarshaled.laurel.SYSCALL.uid)", "int(evt.Unmarshaled.traefik.DownstreamStatus)", "int(evt.Unmarshaled.traefik.Duration)", "len(evt.Parsed.http_args)" ] ================================================ FILE: testdata/examples.md ================================================ # Examples Character Frequency Grouping ``` let char = "0"; 1..100000 | map(string(#)) | groupBy(split(#, char) | len() - 1) | toPairs() | map({{ count: #[0], len: len(#[1]), examples: [first(#[1]), last(#[1])], }}) | sortBy(.len, 'desc') ``` Log Filtering and Aggregation ``` let logs = [ {timestamp: date("2023-08-14 08:30:00"), message: "User logged in", level: "info"}, {timestamp: date("2023-08-14 09:00:00"), message: "Error processing payment", level: "error"}, {timestamp: date("2023-08-14 10:15:00"), message: "User logged out", level: "info"}, {timestamp: date("2023-08-14 11:00:00"), message: "Error connecting to database", level: "error"} ]; logs | filter(.level == "error") | map({{ time: string(.timestamp), detail: .message }}) | sortBy(.time) ``` Financial Data Analysis and Summary ``` let accounts = [ {name: "Alice", balance: 1234.56, transactions: [100, -50, 200]}, {name: "Bob", balance: 2345.67, transactions: [-200, 300, -150]}, {name: "Charlie", balance: 3456.78, transactions: [400, -100, 50]} ]; { totalBalance: sum(accounts, .balance), averageBalance: mean(map(accounts, .balance)), totalTransactions: reduce(accounts, #acc + len(.transactions), 0), accounts: map(accounts, {{ name: .name, final: .balance + sum(.transactions), transactionCount: len(.transactions) }}) } ``` Bitwise Operations and Flags Decoding ``` let flags = [ {name: "read", value: 0b0001}, {name: "write", value: 0b0010}, {name: "execute", value: 0b0100}, {name: "admin", value: 0b1000} ]; let userPermissions = 0b1011; flags | filter(userPermissions | bitand(.value) != 0) | map(.name) ``` Nested Predicates with Optional Chaining ``` let users = [ {id: 1, name: "Alice", posts: [{title: "Hello World", content: "Short post"}, {title: "Another Post", content: "This is a bit longer post"}]}, {id: 2, name: "Bob", posts: nil}, {id: 3, name: "Charlie", posts: [{title: "Quick Update", content: "Update content"}]} ]; users | filter( // Check if any post has content length greater than 10. any(.posts ?? [], len(.content) > 10) ) | map({{name: .name, postCount: len(.posts ?? [])}}) ``` String Manipulation and Validation ``` " Apple, banana, Apple, orange, banana, kiwi " | trim() | split(",") | map(trim(#)) | map(lower(#)) | uniq() | sort() | join(", ") ``` Date Difference ``` let startDate = date("2023-01-01"); let endDate = date("2023-12-31"); let diff = endDate - startDate; { daysBetween: diff.Hours() / 24, hoursBetween: diff.Hours() } ``` Phone number filtering ``` let phone = filter(split("123-456-78901", ""), # in map(0..9, string(#)))[:10]; join(concat(["("], phone[:3], [")"], phone[3:6], ["-"], phone[6:])) ``` Prime numbers ``` 2..1000 | filter(let N = #; none(2..N-1, N % # == 0)) ``` ================================================ FILE: testdata/generated.txt ================================================ !!!ok !!$env?.ok !!false !!not false !!ok !!ok ?? 1 !!true !$env && false !$env and !true !$env and false !$env or true !$env || true !$env.ok !$env.ok ?? foo !$env?.ok !all($env, false) !all($env, true) !all(array, false) !all(array, true) !all(list, true) !any($env, false) !any($env, ok) !any($env, true) !any(array, false) !any(array, ok ?? #) !any(array, ok) !any(array, true) !any(list, ok) !false != $env !false != 0 ?? false !false != false !false != nil !false != ok !false != true !false && $env !false && false !false && ok !false && true !false == $env !false == false !false == nil !false == ok !false == ok == ok !false == true !false ? 0 : f64 !false ? 0 : nil !false ? 1 : ok !false ? 1.0 : 0 !false ? add : array !false ? add : foo !false ? array : $env !false ? array : nil !false ? f64 : true !false ? false : foo !false ? false : greet !false ? false : true !false ? foo : $env !false ? foo : foo !false ? foo : greet !false ? str : $env !false ?: $env !false ?: 1.0 !false ?: bitnand(i, 1) !false ?: foo !false ?: list !false ?: nil !false ?: true !false ?? $env !false ?? $env?.String !false ?? 0 !false ?? 1 !false ?? 1.0 !false ?? add !false ?? array !false ?? f64 !false ?? false !false ?? foo !false ?? greet !false ?? i !false ?? list !false ?? nil !false ?? ok !false ?? sortBy($env, $env) !false ?? str !false ?? true !false and $env !false and 1.0 != f64 !false and 1.0 ?? list !false and false !false and false == $env !false and ok !false and true !false or $env !false or 1.0 != f64 !false or false !false or ok !false or true !false || $env !false || $env?.[$env] !false || $env?.[greet()] !false || $env?.[greet] !false || false !false || ok !false || true !false; foo !nil ?? false !nil ?? false || true !nil ?? ok !nil ?? true !none($env, false) !none($env, ok) !none($env, true) !none(array, ok) !none(array, true) !none(list, ok) !not !false !not !ok !not $env.ok !not false !not not false !not ok !not true !ok !ok != $env !ok != false !ok != nil !ok != ok !ok != true !ok && $env !ok && $env?.Bar !ok && $env?.[i] !ok && false !ok && list not in $env !ok && ok !ok && true !ok == $env !ok == false !ok == nil !ok == nil == nil !ok == ok !ok == true !ok ? $env : $env !ok ? $env : 0 !ok ? $env : str !ok ? 1 : str !ok ? 1.0 : 1.0 !ok ? 1.0 : str !ok ? add : ok !ok ? array : false !ok ? foo : 1 !ok ? foo : foo !ok ? list : foo !ok ? nil : 1.0 !ok ? nil : true !ok ?: $env !ok ?: $env?.f64 !ok ?: i !ok ?: ok !ok ?: str !ok ?? $env !ok ?? $env?.add !ok ?? 0 !ok ?? 1 !ok ?? 1.0 !ok ?? add !ok ?? array !ok ?? f64 !ok ?? false !ok ?? foo !ok ?? foo?.String !ok ?? greet !ok ?? i !ok ?? list !ok ?? nil !ok ?? ok !ok ?? str !ok ?? true !ok and $env !ok and $env ?? ok !ok and false !ok and ok !ok and true !ok not in $env?.[Bar] !ok or $env !ok or $env?.Bar !ok or false !ok or ok !ok or true !ok || $env !ok || $env ?? f64 !ok || false !ok || foo ?? i !ok || greet == $env !ok || ok !ok || true !one($env, false) !one($env, ok) !one($env, true) !one(array, false) !one(array, true) !one(list, ok) !reduce($env, false, foo) !reduce([true], $env != nil) !reduce(array, false, list) !reduce(array, ok) !reduce(array, ok, $env) !reduce(array, true) !reduce(list, false) !reduce(list, ok) !reduce(list, true) !true != $env !true != $env?.[foobar] !true != false !true != nil !true != ok !true != true !true && $env !true && $env?.[Bar] !true && 1 ?? foo !true && 1.0 != nil !true && false !true && not $env !true && ok !true && true !true == $env !true == $env?.String !true == false !true == nil !true == ok !true == true !true ? 1 : false !true ? 1.0 : 1.0 !true ? 1.0 : str !true ? add : 1.0 !true ? array : 0 !true ? f64 : f64 !true ? nil : false !true ? str : 1.0 !true ? str : add !true ? str : nil !true ? str : str !true ?: array !true ?: false !true ?: foo !true ?: i !true ?: nil !true ?: ok !true ?: str !true ?? $env !true ?? $env?.array !true ?? 0 !true ?? 1 !true ?? 1.0 !true ?? add !true ?? array !true ?? date($env, foo) !true ?? f64 !true ?? false !true ?? foo !true ?? greet !true ?? i !true ?? list !true ?? nil !true ?? ok !true ?? str !true ?? true !true and $env !true and false !true and nil ?? $env !true and ok !true and true !true not in [$env] !true or $env !true or $env == foo !true or false !true or ok !true or true !true || $env !true || false !true || ok !true || true $env != $env == ok $env != $env ?: greet $env != $env or f64 ?? foo $env != $env.add $env != $env.array $env != $env.f64 $env != $env.foo $env != $env.greet $env != $env.i $env != $env.list $env != $env.ok $env != $env.str $env != $env?.Bar $env != $env?.Bar?.add $env != $env?.Bar?.list $env != $env?.String $env != $env?.String?.String $env != $env?.[Bar] $env != $env?.[Bar]?.Bar $env != $env?.[Bar]?.sum(foobar matches Bar) $env != $env?.[String] $env != $env?.[String]?.[array] $env != $env?.[String]?.greet $env != $env?.[foobar] $env != $env?.[str] $env != $env?.add $env != $env?.array $env != $env?.f64 $env != $env?.foo $env != $env?.foobar $env != $env?.foobar?.greet $env != $env?.foobar?.ok $env != $env?.greet $env != $env?.i $env != $env?.list $env != $env?.ok $env != $env?.str $env != 0 != ok $env != 0 && 1.0 != nil $env != 0 ?: $env?.[f64] $env != 0 ?? add $env != 0 ?? ok $env != 1 != $env?.[str] $env != 1 / f64 $env != 1.0 != $env.ok $env != 1.0 * $env.i $env != 1.0 * f64 $env != 1.0 * i $env != 1.0 ** i && false $env != 1.0 + f64 $env != 1.0 - f64 $env != 1.0 / i $env != 1.0 == $env?.false $env != 1.0 ?? foo $env != 1.0 ?? ok $env != 1.0 or ok $env != 1.0 || abs($env) $env != add ? add : ok ?: array $env != add || $env + $env $env != add || 1.0 not in $env $env != array or ok $env != array?.[i] $env != f64 && ok $env != f64 + i $env != f64 / f64 $env != f64 ? $env?.ok : foo $env != f64 and ok $env != false != ok $env != foo != greet ?? 1 $env != foo && add ?? foo $env != foo == $env?.[String] $env != foo == ok $env != foo ?? add $env != foo ?? ok $env != foo ?? str $env != foo and ok $env != foo.Bar $env != foo.String $env != foo.String() $env != foo?.Bar $env != foo?.String $env != foo?.String() $env != greet ?? add $env != greet ?? f64 $env != i ?? f64 ?? foo $env != i ?? i $env != i ?? list $env != i not in toPairs($env) $env != i or one($env, true) $env != i || ok $env != list ?? flatten($env) $env != list ?? list $env != list and ok $env != list or ok $env != list?.[i] $env != nil != ok $env != nil ?? array $env != nil ?? i $env != nil ?? ok $env != ok ?? add $env != str && ok $env != str + str $env != str in $env?.[String] $env != str || 1 in $env $env != true ?? list $env != true ?? ok $env != true and nil != nil $env && false && 1.0 == 1.0 $env && false and $env matches $env $env && false or ok $env * 1 || true == true $env - 1.0 not startsWith $env && false $env .. $env in $env || true $env == $env && nil in list $env == $env && ok $env == $env ?: i != $env $env == $env ?? $env?.[ok] $env == $env ?? f64 $env == $env and ok $env == $env or $env?.Bar() $env == $env or ok $env == $env.add $env == $env.array $env == $env.f64 $env == $env.foo $env == $env.greet $env == $env.i $env == $env.list $env == $env.list?.[i] $env == $env.ok $env == $env.str $env == $env?.$env?.[list] $env == $env?.Bar $env == $env?.String $env == $env?.String?.foo $env == $env?.String?.foobar?.[array] $env == $env?.String?.list $env == $env?.[Bar] $env == $env?.[Bar]?.[i] $env == $env?.[Bar]?.[ok]?.[array] $env == $env?.[Bar]?.foo $env == $env?.[Bar]?.i $env == $env?.[String] $env == $env?.[foobar?.Bar] $env == $env?.[foobar] $env == $env?.[str] $env == $env?.add $env == $env?.array $env == $env?.f64 $env == $env?.f64 / i $env == $env?.foo $env == $env?.foo.Bar $env == $env?.foobar $env == $env?.greet $env == $env?.i $env == $env?.list $env == $env?.ok $env == $env?.str $env == 0 ?? list $env == 0 ?? ok == ok $env == 0 ^ f64 $env == 0 and take($env, 0) $env == 1 && ok $env == 1 * f64 $env == 1 .. i $env == 1 ?: array $env == 1.0 && $env != greet $env == 1.0 && map($env, false)?.[i] $env == 1.0 ** 1 ?: 1 $env == 1.0 ** f64 $env == 1.0 - f64 $env == 1.0 / $env?.i $env == 1.0 == $env?.Bar $env == 1.0 == none(array, true) $env == 1.0 ?: $env?.greet $env == 1.0 ?? i $env == 1.0 ?? ok $env == 1.0 ^ $env?.f64 $env == 1.0 ^ f64 $env == 1.0 and add != add $env == 1.0 or foo ?? str $env == add ?? array $env == add and $env[foo:] $env == add or nil != foo $env == array ?? -1.0 $env == array ?? add $env == array and ok $env == array?.[i] $env == f64 * f64 $env == f64 - f64 $env == f64 - i $env == f64 == ok $env == false == ok $env == false not in $env?.[Bar] $env == false not in $env?.[String] $env == foo != !ok $env == foo && ok $env == foo == $env ?? 1.0 $env == foo ?? add $env == foo ?? list $env == foo ?? ok $env == foo || ok $env == foo.Bar $env == foo.String $env == foo.String() $env == foo?.Bar $env == foo?.String $env == foo?.String() $env == greet ?? $env?.[str] $env == i ** f64 $env == i || ok $env == list && $env not in list $env == list && findLast($env, .array) $env == list or ok $env == list?.[i] $env == list[i:] $env == nil != ok $env == nil && 1.0 > i $env == nil ?? type(foo) $env == nil or all($env, false) $env == ok ?? ok $env == ok and $env in foo $env == ok and not $env?.String $env == str && ok or $env $env == str ?? 1 and ok $env == str ?? add $env == str ?? lastIndexOf($env, str) $env == str || ok $env == true && f64 ?? 1 $env == true ?? !true $env == true ?? list $env == true || ok $env >= 1.0 == $env or true $env ?? $env ?? timezone($env) $env ?? $env | map($env) $env ?? $env | map(i) $env ?? $env | map(str) $env ?? $env | reduce(true, true) $env ?? $env.add $env ?? $env.array $env ?? $env.f64 $env ?? $env.foo $env ?? $env.foo?.String $env ?? $env.greet $env ?? $env.i $env ?? $env.list $env ?? $env.ok $env ?? $env.str $env ?? $env?.$env?.[add] $env ?? $env?.$env?.array $env ?? $env?.Bar $env ?? $env?.Bar() $env ?? $env?.Bar()?.add $env ?? $env?.Bar(String(foobar) | float(String)) $env ?? $env?.Bar?.add $env ?? $env?.Bar?.f64 $env ?? $env?.String $env ?? $env?.String() $env ?? $env?.String(String ?? not foobar) $env ?? $env?.String.f64 $env ?? $env?.String.greet $env ?? $env?.String?.i(foo) $env ?? $env?.[Bar] $env ?? $env?.[String] $env ?? $env?.[add] $env ?? $env?.[array] $env ?? $env?.[f64] $env ?? $env?.[foo?.add] $env ?? $env?.[foo] $env ?? $env?.[foobar | sortBy(1)] $env ?? $env?.[foobar.foobar] $env ?? $env?.[foobar?.[f64]] $env ?? $env?.[foobar] $env ?? $env?.[greet || false] $env ?? $env?.[greet?.f64] $env ?? $env?.[greet] $env ?? $env?.[greet] | any(ok) $env ?? $env?.[greet]?.f64 $env ?? $env?.[i] $env ?? $env?.[i].foo() $env ?? $env?.[list] $env ?? $env?.[ok()] $env ?? $env?.[ok?.[str]] $env ?? $env?.[ok] $env ?? $env?.[str] $env ?? $env?.[str].i $env ?? $env?.add $env ?? $env?.array $env ?? $env?.f64 $env ?? $env?.findLast(ok) $env ?? $env?.foo $env ?? $env?.foobar $env ?? $env?.greet $env ?? $env?.i $env ?? $env?.list $env ?? $env?.ok $env ?? $env?.str $env ?? $env[:1 not endsWith foobar] $env ?? $env[:Bar()] $env ?? $env[:f64()] $env ?? $env[:f64(foobar)] $env ?? $env[:filter(foobar, #)] $env ?? $env[:foo.foo] $env ?? $env[:foobar not startsWith greet].f64 $env ?? $env[:foobar] $env ?? $env[:nil | any(array)]?.[i] $env ?? $env[:str | foo(0)] $env ?? $env[String(String):] $env ?? $env[String(i):$env?.array(foo, false)] $env ?? $env[array():] $env ?? $env[filter(foobar, #):] $env ?? $env[foo:String] $env ?? $env[foobar | groupBy(1.0):] $env ?? $env[foobar || Bar:] $env ?? $env[foobar:] $env ?? $env[foobar[foobar:0]:foobar] $env ?? $env[list():true <= 1.0] $env ?? $env[list:foobar] $env ?? $env[str | groupBy(#.list):] $env ?? 0 | filter(false) $env ?? 0 | find(false) $env ?? 0 | map(array) $env ?? 0 | map(false) $env ?? 0 | map(str) $env ?? 0 | none(true) $env ?? 1 | map(#index) $env ?? 1 | sum(f64) $env ?? 1.0 ?? array $env ?? 1.0 ?? greet $env ?? 1.0 | findIndex(ok) $env ?? 1.0 | map($env) $env ?? 1.0 | map(ok) $env ?? 1.0 | sum(0) $env ?? 1.0 | sum(i) $env ?? add | any(false) $env ?? add | reduce(foo, nil) $env ?? array | map($env) $env ?? array | map(foo) $env ?? array | map(true) $env ?? array | reduce(i, 1.0) $env ?? array | sum(1.0) $env ?? array?.[i] $env ?? f64 ?? f64 $env ?? f64 | find(false) $env ?? f64 | findLastIndex(ok) $env ?? f64 | map(add) $env ?? f64 | map(str) $env ?? false | all(false) $env ?? false | none(true) $env ?? false | sum(1.0) $env ?? foo ?? $env?.[str] $env ?? foo ?? array $env ?? foo ?? f64 $env ?? foo ?? i $env ?? foo | any(false) $env ?? foo | count(true) $env ?? foo | map(1.0) $env ?? foo | none(ok) $env ?? foo | one(ok) $env ?? foo | reduce(f64, $env) $env ?? foo | sum(1.0) $env ?? foo | sum(i) $env ?? foo.Bar $env ?? foo.String $env ?? foo.String() $env ?? foo?.Bar $env ?? foo?.String $env ?? foo?.String() $env ?? greet ?? i $env ?? greet | map($env) $env ?? greet | none(true) $env ?? greet | sum(1.0) $env ?? i ?? array $env ?? i | map(0) $env ?? i | sum(0) $env ?? list | any(false) $env ?? list?.[i] $env ?? nil ?? false | map(foo) $env ?? nil ?? i $env ?? nil ?? str $env ?? nil | all(ok) $env ?? nil | any(true) $env ?? nil | filter(0 >= 1) $env ?? nil | findLastIndex(true) $env ?? nil | none(false) $env ?? nil | none(true) $env ?? nil | reduce(str, true) $env ?? nil | sum(1) $env ?? ok ?? ok $env ?? ok | map(true) $env ?? ok | none(ok) $env ?? str ?? $env?.add $env ?? str | map(foo) $env ?? str | map(ok) $env ?? str | none(true) $env ?? str | sum(0) $env ?? true | all(true) $env ?? true | findLastIndex(true) $env ?? true | none(ok) $env and false or 1.0 != f64 $env contains $env?.Bar $env contains $env?.Bar?.str $env contains $env?.String $env contains $env?.String?.foo $env contains $env?.String?.list $env contains $env?.[Bar] $env contains $env?.[Bar]?.Bar $env contains $env?.[Bar]?.[f64] $env contains $env?.[String] $env contains $env?.[String]?.[foo] $env contains $env?.[foobar] $env contains $env?.[str[:1.0]] $env contains $env?.foobar $env contains $env?.nil?.[list] $env endsWith $env?.Bar $env endsWith $env?.Bar?.[foo] $env endsWith $env?.String $env endsWith $env?.String?.[array] $env endsWith $env?.[Bar] $env endsWith $env?.[Bar]?.[f64] $env endsWith $env?.[Bar]?.[foo].i $env endsWith $env?.[Bar]?.str $env endsWith $env?.[String?.array] $env endsWith $env?.[String] $env endsWith $env?.[foobar?.[add]] $env endsWith $env?.[foobar] $env endsWith $env?.foobar $env in $env.array $env in $env.list $env in $env?.Bar $env in $env?.Bar?.foo $env in $env?.String $env in $env?.String?.list $env in $env?.[Bar?.ok()] $env in $env?.[Bar] $env in $env?.[Bar]?.add?.[i] $env in $env?.[String?.[str]] $env in $env?.[String] $env in $env?.[String]?.foo(foo) $env in $env?.[foobar] $env in $env?.array $env in $env?.foo || true $env in $env?.foobar $env in $env?.foobar?.foo $env in $env?.foobar?.list(foo) $env in $env?.list $env in $env?.true?.f64(foobar) $env in 0 .. i $env in 1 .. i $env in 1..i $env in array ?: ok $env in array ?? greet $env in array or ok $env in array[:] $env in array[:i] $env in i .. $env.i $env in list && $env and $env $env in list and $env?.[f64] $env in list and max($env) $env in nil ?? list $env matches $env && ok or true $env matches $env?.$env?.add $env matches $env?.Bar $env matches $env?.String $env matches $env?.[Bar] $env matches $env?.[Bar]?.[f64] $env matches $env?.[String?.[foobar]] $env matches $env?.[String] $env matches $env?.[String]?.ok() $env matches $env?.[foobar] $env matches $env?.[last(foo)] $env matches $env?.foobar $env matches $env?.foobar?.Bar(foobar, foobar) $env matches $env?.foobar?.greet() $env matches $env?.foobar?.greet(foobar, 1) $env not contains $env?.Bar $env not contains $env?.String $env not contains $env?.String?.[str] $env not contains $env?.String?.array $env not contains $env?.[Bar] $env not contains $env?.[Bar]?.add() $env not contains $env?.[Bar]?.ok $env not contains $env?.[String?.str] $env not contains $env?.[String] $env not contains $env?.[first(foobar, greet)] $env not contains $env?.[foobar?.array()] $env not contains $env?.[foobar] $env not contains $env?.[toJSON(foobar)] $env not contains $env?.foobar $env not contains $env?.foobar?.[ok] $env not contains $env?.foobar?.greet() $env not contains $env?.foobar?.i $env not contains $env?.nil?.f64 $env not endsWith $env?.Bar $env not endsWith $env?.Bar?.[list] $env not endsWith $env?.String $env not endsWith $env?.String?.[greet] $env not endsWith $env?.[Bar] $env not endsWith $env?.[String] $env not endsWith $env?.[foobar] $env not endsWith $env?.foobar $env not endsWith $env?.nil?.add() $env not in $env.array $env not in $env.list $env not in $env?.Bar $env not in $env?.Bar?.[ok] $env not in $env?.String $env not in $env?.String?.f64 $env not in $env?.[Bar] $env not in $env?.[String] $env not in $env?.[foobar?.list] $env not in $env?.[foobar] $env not in $env?.array $env not in $env?.foobar $env not in $env?.foobar?.[foo] $env not in $env?.foobar?.foobar $env not in $env?.list $env not in 1 .. 1 ?? add $env not in 1..i $env not in array && ok $env not in array == $env || false $env not in array == $env?.[String] $env not in array || i ?? false $env not in array[:i] $env not in list and 1 <= f64 $env not in list and greet == greet $env not in list or ok $env not in nil ?? list $env not matches $env?.Bar $env not matches $env?.Bar?.[add] $env not matches $env?.Bar?.array $env not matches $env?.String $env not matches $env?.String?.[add] $env not matches $env?.String?.[ok] $env not matches $env?.String?.array $env not matches $env?.[Bar] $env not matches $env?.[Bar]?.[str] $env not matches $env?.[String?.[Bar]] $env not matches $env?.[String] $env not matches $env?.[String]?.[add] $env not matches $env?.[foobar?.[0]] $env not matches $env?.[foobar] $env not matches $env?.foobar $env not startsWith $env?.Bar $env not startsWith $env?.Bar?.[greet] $env not startsWith $env?.String $env not startsWith $env?.[Bar] $env not startsWith $env?.[Bar]?.Bar $env not startsWith $env?.[Bar]?.f64 $env not startsWith $env?.[String] $env not startsWith $env?.[String]?.[f64] $env not startsWith $env?.[foobar] $env not startsWith $env?.foobar $env not startsWith $env?.foobar?.[foo] $env not startsWith $env?.foobar?.add $env or nil != nil || true $env or nil == list and false $env or true ?: greet $env startsWith $env?.Bar $env startsWith $env?.Bar?.Bar $env startsWith $env?.Bar?.add $env startsWith $env?.String $env startsWith $env?.[Bar] $env startsWith $env?.[String] $env startsWith $env?.[String]?.greet $env startsWith $env?.[foobar] $env startsWith $env?.[foobar]?.[i] $env startsWith $env?.foobar $env startsWith $env?.foobar?.Bar() $env | all(false) && $env?.[f64] $env | all(ok) && ok $env | all(ok) or -$env $env | any(false) != ok $env | any(false) ?? str $env | any(ok) != ok $env | any(ok) == ok $env | count(ok) | min(0) $env | count(true) .. -i $env | filter(#) | filter(false) $env | filter(#.f64) | filter(false) $env | filter(false) | all(#.str()) $env | filter(false) | all($env) $env | filter(false) | all(true) $env | filter(false) | any(#) $env | filter(false) | any(.list) $env | filter(false) | count($env) $env | filter(false) | count(.i.greet) $env | filter(false) | filter(.str) $env | filter(false) | find($env) $env | filter(false) | findIndex(#.ok) $env | filter(false) | findIndex(.String) $env | filter(false) | findIndex(.foo) $env | filter(false) | findLast(.greet) $env | filter(false) | findLast(.ok) $env | filter(false) | findLastIndex(.i) $env | filter(false) | groupBy(#.f64) $env | filter(false) | groupBy(str) $env | filter(false) | map(#) $env | filter(false) | one(#) $env | filter(false) | one(.foo) $env | filter(false) | sum(#) $env | filter(false) | sum(.greet) $env | filter(true) | map($env) $env | filter(true) | map(1.0) $env | find(.add) startsWith str || true $env | find(false) ?? $env?.String $env | findIndex(false) not in array $env | findIndex(ok) <= i $env | findIndex(true) ?? f64 $env | findLast(false) == str or true $env | findLast(false) | get(nil) $env | findLastIndex(false) in sort($env) $env | findLastIndex(true) + f64 $env | findLastIndex(true) - i $env | findLastIndex(true) > i $env | get(str) | groupBy(foo) $env | map(#index) != array $env | map(#index) | findIndex(true) $env | map(#index) | groupBy(f64) $env | map(#index) | map(i) $env | map(#index) | reduce(f64, nil) $env | map(#index) | sortBy(f64) $env | map($env) | count(ok) $env | map($env) | find(#.ok) $env | map($env) | findIndex(false) $env | map($env) | map(#.ok) $env | map($env) | map(.array) $env | map($env) | map(list) $env | map($env) | map(true) $env | map($env) | reduce(add) $env | map($env) | reduce(true) $env | map($env) | sortBy(#.i) $env | map($env) | sortBy(.i) $env | map($env) | sortBy(i) $env | map(0) == list $env | map(0) | all(ok) $env | map(0) | groupBy(1) $env | map(0) | map(ok) $env | map(0) | sortBy(#) $env | map(0) | sortBy(1.0) $env | map(0) | sum(#) $env | map(0) | sum(1.0) $env | map(1) | groupBy(#) $env | map(1) | map($env) $env | map(1) | sum(#) $env | map(1) | sum(f64) $env | map(1.0) | filter(true) $env | map(1.0) | findLastIndex(ok) $env | map(1.0) | groupBy(foo) $env | map(1.0) | mean(0) $env | map(1.0) | none(ok) $env | map(1.0) | none(true) $env | map(1.0) | reduce(#) $env | map(1.0) | reduce(1.0) $env | map(1.0) | reduce(false, list) $env | map(1.0) | sortBy(#) $env | map(add) | count(true) $env | map(add) | reduce(#, 1.0) $env | map(array) ?? i $env | map(array) | findIndex(ok) $env | map(array) | map(add) $env | map(array) | one(false) $env | map(f64) | map(#) $env | map(false) | groupBy(1) $env | map(false) | map(f64) $env | map(false) | reduce(foo, i) $env | map(false) | reduce(str) $env | map(foo) ?? array $env | map(foo) | any(false) $env | map(foo) | findIndex(true) $env | map(foo) | groupBy(#) $env | map(foo) | groupBy(1) $env | map(foo) | map(#) $env | map(foo) | map(list) $env | map(foo) | none(ok) $env | map(foo) | reduce(#acc) $env | map(foo) | reduce($env, $env) $env | map(foo) | sum(1) $env | map(greet) | map(array) $env | map(greet) | map(greet) $env | map(greet) | reduce(foo) $env | map(i) ?? greet $env | map(i) | count(false) $env | map(i) | groupBy(1.0) $env | map(list) ?? list $env | map(list) | any(false) $env | map(list) | any(ok) $env | map(list) | reduce(ok) $env | map(list) | reduce(true) $env | map(ok) ?? ok $env | map(ok) | findLast(ok) $env | map(ok) | map($env) $env | map(ok) | none(#) $env | map(ok) | one(#) $env | map(ok) | reduce(0) $env | map(ok) | reduce(false) $env | map(str) != list $env | map(str) | findIndex(ok) $env | map(str) | groupBy(foo) $env | map(str) | map(1) $env | map(str) | map(foo) $env | map(str) | reduce(#) $env | map(str) | sortBy(str) $env | map(true) ?? array $env | map(true) ?? str $env | map(true) | all(#) $env | map(true) | count(#) $env | map(true) | filter(#) $env | map(true) | find(false) $env | map(true) | findLastIndex(#) $env | map(true) | groupBy(foo) $env | map(true) | map(#) $env | map(true) | map($env) $env | median(1.0) or true || true $env | none(true) && ok $env | one(ok) || ok $env | reduce(#, nil) > $env and false $env | reduce($env, $env) | count(ok) $env | reduce($env, 1) | sum(0) $env | reduce(0, false) | max(1.0, f64) $env | reduce(1.0, 1) <= f64 $env | reduce(false, $env); list $env | reduce(greet, array) ?? foo $env | reduce(ok, 1) ?: greet $env | reduce(str, foo) not startsWith str $env | sum(#) not endsWith $env or true $env | sum(1.0) <= i $env | sum(1.0) in array $env | sum(f64) > f64 $env | sum(f64) ?? ok $env | sum(i) / bitnot(i) $env || false and $env?.Bar() $env || true || $env < 1 $env.add != $env?.add $env.add == $env.add $env.add == $env?.add $env.add == add $env.add ?? !false $env.add ?? $env?.foo $env.add ?? [i] $env.add ?? add $env.add ?? array $env.add ?? count(array) $env.add ?? foo $env.add ?? greet $env.add ?? groupBy(array, $env) $env.add ?? i $env.add ?? list $env.add ?? list ?? nil $env.add ?? ok $env.add ?? str $env.add ?? sum($env) $env.add not in [nil, false] $env.add(1, 1) < f64 && ok $env.array != array $env.array != list $env.array == $env?.array $env.array == array $env.array == list $env.array ?? !true $env.array ?? $env | groupBy(#) $env.array ?? $env?.Bar $env.array ?? $env?.[String] $env.array ?? $env?.add $env.array ?? [nil] $env.array ?? add $env.array ?? array $env.array ?? f64 $env.array ?? foo | findLastIndex(false) $env.array ?? greet $env.array ?? list $env.array ?? ok $env.array | all(false) $env.array | all(ok) $env.array | all(true) $env.array | any($env?.ok) $env.array | any(false) $env.array | any(nil == #) $env.array | any(ok) $env.array | concat(array) $env.array | concat(list) $env.array | count(false) $env.array | count(true) $env.array | filter(false) $env.array | filter(ok) $env.array | filter(true) $env.array | find(false) $env.array | find(ok) $env.array | find(true) $env.array | findIndex(false) $env.array | findIndex(nil == list) $env.array | findIndex(ok) $env.array | findIndex(true) $env.array | findLast(false) $env.array | findLast(ok) $env.array | findLast(true) $env.array | findLastIndex(false) $env.array | findLastIndex(ok) $env.array | findLastIndex(true) $env.array | groupBy(#) $env.array | groupBy(0) $env.array | groupBy(1) $env.array | groupBy(1.0) $env.array | groupBy(f64) $env.array | groupBy(false) $env.array | groupBy(foo) $env.array | groupBy(i) $env.array | groupBy(ok) $env.array | map(#) $env.array | map(#index) $env.array | map($env) $env.array | map($env?.[String]) $env.array | map(1) $env.array | map(1.0) $env.array | map(array) $env.array | map(f64) $env.array | map(false) $env.array | map(float(1.0)) $env.array | map(foo) $env.array | map(greet) $env.array | map(i) $env.array | map(list) $env.array | map(ok) $env.array | map(str) $env.array | map(true) $env.array | mean(1.0) $env.array | mean(f64) $env.array | mean(i) $env.array | median(0, array) $env.array | median(1) $env.array | median(1.0) $env.array | median(i) $env.array | min(0) $env.array | min(1) $env.array | none(ok) $env.array | none(true) $env.array | one(false) $env.array | one(ok) $env.array | one(true) $env.array | reduce(# ^ #) $env.array | reduce(#) $env.array | reduce(#, $env) $env.array | reduce(#, 0) $env.array | reduce(#, 1) $env.array | reduce(#, false) $env.array | reduce(#, foo) $env.array | reduce(#, greet) $env.array | reduce(#index) $env.array | reduce($env) $env.array | reduce($env, 1.0) $env.array | reduce(0) $env.array | reduce(1) $env.array | reduce(1.0) $env.array | reduce(1.0, f64) $env.array | reduce(1.0, greet) $env.array | reduce(add) $env.array | reduce(add, greet) $env.array | reduce(add, true) $env.array | reduce(array) $env.array | reduce(f64) $env.array | reduce(f64, 0) $env.array | reduce(f64, i) $env.array | reduce(false) $env.array | reduce(foo) $env.array | reduce(foo, 1) $env.array | reduce(foo, 1.0) $env.array | reduce(foo, array) $env.array | reduce(foo, i) $env.array | reduce(greet) $env.array | reduce(i) $env.array | reduce(i, true) $env.array | reduce(list) $env.array | reduce(not false) $env.array | reduce(ok) $env.array | reduce(str) $env.array | reduce(str, false) $env.array | reduce(true) $env.array | reduce(true, false) $env.array | reduce(true, true) $env.array | sortBy(#) $env.array | sortBy(0) $env.array | sortBy(1) $env.array | sortBy(1.0) $env.array | sortBy(f64) $env.array | sortBy(i) $env.array | sortBy(str) $env.array | sum(#) $env.array | sum(0) $env.array | sum(1) $env.array | sum(1.0) $env.array | sum(i) $env.array | take(0) $env.array | take(1) $env.array | take(i) $env.array?.[i] $env.array[:] $env.array[:i] $env.f64 != $env.i $env.f64 != -1.0 $env.f64 != 0 % i $env.f64 != abs(f64) $env.f64 != f64 $env.f64 != i $env.f64 != sum(array) $env.f64 * 0 >= 1.0 $env.f64 * array?.[i] $env.f64 * f64 $env.f64 * i $env.f64 * i ?? str $env.f64 ** f64 $env.f64 ** i $env.f64 ** sum(array) $env.f64 + $env.i $env.f64 + f64 $env.f64 + f64 == 1 $env.f64 + i $env.f64 - 1 >= f64 $env.f64 - 1.0 > 0 $env.f64 - f64 $env.f64 - i $env.f64 - i ^ 0 $env.f64 / 0.0 $env.f64 / f64 $env.f64 / i $env.f64 < 1.0 ?: list $env.f64 < 1.0 || ok $env.f64 < f64 $env.f64 < i $env.f64 <= $env.i $env.f64 <= 1.0 != false $env.f64 <= f64 $env.f64 <= i $env.f64 <= i ?? foo $env.f64 == $env.f64 $env.f64 == f64 $env.f64 == i $env.f64 > $env.f64 $env.f64 > bitushr(0, i) $env.f64 > f64 $env.f64 > i $env.f64 > sum($env, f64) $env.f64 >= 1.0 - 1.0 $env.f64 >= abs(1.0) $env.f64 >= i $env.f64 ?? !true $env.f64 ?? add $env.f64 ?? f64 $env.f64 ?? foo $env.f64 ?? greet $env.f64 ?? i $env.f64 ?? list $env.f64 ?? list?.[i] $env.f64 ?? ok $env.f64 ?? sortBy(list, f64) $env.f64 ?? str $env.f64 ^ 0 / 0 $env.f64 ^ f64 $env.f64 ^ i $env.f64 ^ i != $env $env.f64 in array $env.f64 in array and ok $env.f64 not in array ? i : $env $env.f64 not in first($env) $env.f64 | max(1.0) $env.f64 | max(f64) $env.f64 | max(i, 1.0) $env.f64 | mean(0) $env.f64 | mean(1) $env.f64 | mean(f64) $env.f64 | median(i) $env.f64 | min(0) $env.f64 | min(array) $env.f64 | min(i) $env.foo != $env.foo $env.foo != $env?.foo $env.foo != foo $env.foo != {foo: list, foo: true, foo: $env}?.foo $env.foo == $env?.foo $env.foo == foo $env.foo == nil == $env $env.foo == nil and ok $env.foo ?? $env.array $env.foo ?? $env?.[add] $env.foo ?? add $env.foo ?? all($env, true) $env.foo ?? array $env.foo ?? array?.[i] $env.foo ?? foo $env.foo ?? greet $env.foo ?? greet(str) $env.foo ?? i $env.foo ?? last(array) $env.foo ?? list $env.foo ?? ok $env.foo ?? str $env.foo ?? sum($env, 1.0) $env.foo in list $env.foo not in list $env.foo.Bar $env.foo.String $env.foo.String() $env.foo?.Bar $env.foo?.Bar > str $env.foo?.String $env.foo?.String() $env.greet != $env && $env $env.greet != $env.greet $env.greet != greet $env.greet == $env?.foobar?.[list] $env.greet == greet $env.greet ?? $env?.[list] $env.greet ?? $env?.list $env.greet ?? array $env.greet ?? f64 $env.greet ?? foo $env.greet ?? greet $env.greet ?? greet(str) $env.greet ?? list $env.greet ?? ok $env.greet ?? reduce(list, str) $env.greet ?? str $env.greet($env.str) $env.greet($env?.[str]) $env.greet($env?.str) $env.greet(foo.Bar) $env.greet(foo.String()) $env.greet(foo?.Bar) $env.greet(foo?.String()) $env.greet(greet(str)) $env.greet(str) $env.greet(string($env)) $env.greet(string(1.0)) $env.greet(toJSON(list)) $env.greet(trimPrefix(str)) $env.greet(type(0)) $env.i != $env?.Bar $env.i != $env?.[Bar]?.foo() $env.i != 1 / 1 $env.i != 1.0 + 1.0 $env.i != f64 $env.i != i $env.i % i $env.i % i != $env $env.i % i <= 0 $env.i * -i $env.i * f64 $env.i * i $env.i * min(0) $env.i ** f64 $env.i ** i $env.i ** mean(1.0) $env.i + f64 $env.i + i $env.i - -0 $env.i - -1.0 $env.i - 1 == 1.0 $env.i - ceil(1) $env.i - f64 $env.i - i $env.i .. i $env.i / $env.f64 $env.i / f64 $env.i / find(array, true) $env.i / i $env.i / i - 0 $env.i < $env.i $env.i < 1.0 != $env $env.i < 1.0 or $env $env.i < f64 $env.i < f64 ^ f64 $env.i < i $env.i < i / i $env.i <= 1.0 > 1.0 $env.i <= f64 $env.i <= i $env.i == $env?.f64 $env.i == f64 $env.i == i $env.i > $env.i $env.i > f64 $env.i > i $env.i >= $env?.i $env.i >= f64 $env.i >= f64 / f64 $env.i >= i $env.i ?? $env?.[str] $env.i ?? add $env.i ?? array $env.i ?? f64 $env.i ?? foo?.Bar $env.i ?? foo?.String $env.i ?? greet $env.i ?? i $env.i ?? ok $env.i ?? str $env.i ?? sum(array) $env.i ?? toJSON(f64) $env.i ^ f64 $env.i ^ i $env.i in $env?.[Bar] $env.i in array $env.i in array != nil $env.i in take(array, 0) $env.i not in $env?.[String] $env.i not in $env?.array $env.i not in array $env.i | add(i) $env.i | bitnand(i) $env.i | bitor(0) $env.i | bitor(1) $env.i | bitshl(0) $env.i | bitshl(1) $env.i | bitshr(i) $env.i | bitushr(1) $env.i | bitushr(i) $env.i | bitxor(0) $env.i | max(1.0) $env.i | mean(i) $env.i | median(1) $env.list != array $env.list != list $env.list == $env?.Bar $env.list == array $env.list == list $env.list == nil || $env $env.list ?? $env?.[greet] $env.list ?? $env?.i $env.list ?? -0 $env.list ?? add $env.list ?? f64 $env.list ?? false | sortBy(#.Bar) $env.list ?? foo $env.list ?? i $env.list ?? list $env.list | all(false) $env.list | all(ok) $env.list | all(true) $env.list | any(false) $env.list | any(ok) $env.list | any(true) $env.list | concat(array) $env.list | count(false) $env.list | count(ok) $env.list | count(true) $env.list | filter(false) $env.list | filter(ok) $env.list | filter(true) $env.list | find(false) $env.list | find(nil not in list) $env.list | find(ok) $env.list | find(true) $env.list | findIndex(false) $env.list | findIndex(ok) $env.list | findIndex(true) $env.list | findLast(false) $env.list | findLast(ok) $env.list | findLast(true) $env.list | findLastIndex(ok) $env.list | findLastIndex(true) $env.list | groupBy(#) $env.list | groupBy(#.Bar) $env.list | groupBy(.Bar) $env.list | groupBy(0) $env.list | groupBy(1) $env.list | groupBy(1.0) $env.list | groupBy(f64) $env.list | groupBy(false != false) $env.list | groupBy(false) $env.list | groupBy(foo) $env.list | groupBy(ok) $env.list | groupBy(true) $env.list | map(#) $env.list | map(#.Bar) $env.list | map(#.String) $env.list | map(#index) $env.list | map($env) $env.list | map(.Bar) $env.list | map(0) $env.list | map(1) $env.list | map(1.0) $env.list | map(add) $env.list | map(array) $env.list | map(f64) $env.list | map(false) $env.list | map(foo) $env.list | map(greet) $env.list | map(i) $env.list | map(list) $env.list | map(ok) $env.list | map(str) $env.list | map(true) $env.list | none(false) $env.list | none(ok) $env.list | none(true) $env.list | one(false) $env.list | one(foo != $env) $env.list | one(ok) $env.list | one(true) $env.list | reduce(#) $env.list | reduce(#, $env) $env.list | reduce(#, 0) $env.list | reduce(#, 1.0) $env.list | reduce(#, nil) $env.list | reduce(#, true) $env.list | reduce(#.Bar) $env.list | reduce(#.String) $env.list | reduce(#acc) $env.list | reduce(#acc, $env) $env.list | reduce(#index) $env.list | reduce($env) $env.list | reduce(.Bar, 1) $env.list | reduce(.Bar, 1.0) $env.list | reduce(.String) $env.list | reduce(0) $env.list | reduce(1) $env.list | reduce(1, $env) $env.list | reduce(1.0) $env.list | reduce(1.0, f64) $env.list | reduce(1.0, false) $env.list | reduce(add) $env.list | reduce(add, nil) $env.list | reduce(array) $env.list | reduce(array, 0) $env.list | reduce(f64) $env.list | reduce(false) $env.list | reduce(false, i) $env.list | reduce(false, str) $env.list | reduce(foo == #) $env.list | reduce(foo) $env.list | reduce(foo, 0) $env.list | reduce(foo, foo) $env.list | reduce(foo, i) $env.list | reduce(foo, nil) $env.list | reduce(foo, str) $env.list | reduce(greet) $env.list | reduce(greet, foo) $env.list | reduce(i) $env.list | reduce(i, 1.0) $env.list | reduce(list) $env.list | reduce(str) $env.list | reduce(str, false) $env.list | reduce(true) $env.list | reduce(true, 1) $env.list | sortBy(#.Bar) $env.list | sortBy(.Bar) $env.list | sortBy(0) $env.list | sortBy(1) $env.list | sortBy(1.0) $env.list | sortBy(f64) $env.list | sortBy(i) $env.list | sortBy(str) $env.list | sum(0) $env.list | sum(1) $env.list | sum(1.0) $env.list | sum(f64) $env.list | sum(i) $env.list?.[$env?.i] $env.list?.[i] $env.list?.[i].Bar $env.list?.[i].String() $env.list[:] $env.list[:sum(array, #)] $env.list[i:] $env.ok != list ?? foo $env.ok != ok $env.ok && $env?.$env $env.ok && $env?.[nil] $env.ok && $env?.[str] $env.ok && array ?? i $env.ok && f64 == nil $env.ok && ok $env.ok == $env ?? ok $env.ok == nil || true $env.ok == ok $env.ok ? list : date(1) $env.ok ?: array $env.ok ?: f64 $env.ok ?? add $env.ok ?? array $env.ok ?? foo.String $env.ok ?? i $env.ok ?? ok $env.ok ?? str $env.ok and $env?.[foobar] $env.ok and $env?.[nil] $env.ok and f64 < 1.0 $env.ok and ok $env.ok in $env?.[nil] $env.ok in keys($env) $env.ok not in $env?.$env $env.ok not in [false] $env.ok or $env?.String.String $env.ok or $env?.[String] $env.ok or $env?.ok $env.ok or not $env $env.ok or ok $env.ok || $env?.foobar $env.ok || array ?? i $env.ok || ok $env.str != str $env.str + $env.str $env.str + str $env.str + type($env) $env.str + type(nil) $env.str < $env?.[str] $env.str < foo.Bar $env.str < str $env.str <= str $env.str <= toJSON(ok) $env.str == $env?.[Bar] $env.str == str $env.str > str $env.str > type(nil) $env.str >= greet(str) $env.str >= str $env.str ?? $env.foo $env.str ?? add $env.str ?? array $env.str ?? f64 $env.str ?? foo $env.str ?? greet $env.str ?? greet($env) $env.str ?? i $env.str ?? list $env.str ?? ok $env.str ?? str $env.str contains $env?.String $env.str contains $env?.[Bar] $env.str contains str $env.str contains toJSON(foo) $env.str endsWith str $env.str endsWith str[:i] $env.str in foo $env.str matches str $env.str matches str ?: 1.0 $env.str matches string(1.0) $env.str not contains $env.str $env.str not contains $env?.[str] $env.str not contains foo.String() $env.str not contains str $env.str not endsWith str $env.str not in $env ? foo : 0 $env.str not in foo $env.str not matches foo?.Bar $env.str not matches str $env.str not startsWith foo?.Bar $env.str not startsWith str $env.str startsWith str $env.str | greet() $env.str | hasPrefix(str) $env.str | hasSuffix(str) $env.str | split(str) $env.str[:] $env.str[i:] $env; $env.add $env; $env.i $env; $env?.[Bar] $env; $env?.foo $env; $env?.i $env; $env?.ok $env; $env?.str $env; false; $env?.foo $env; list?.[i] $env?.$env != $env.array $env?.$env != foo $env?.$env != i $env?.$env != str $env?.$env == add $env?.$env == foo?.String() $env?.$env ?? $env ?? greet $env?.$env ?? array $env?.$env ?? greet $env?.$env and $env || true $env?.$env in foo || true $env?.$env in list $env?.$env not contains str $env?.$env not endsWith str $env?.$env?.Bar $env?.$env?.Bar() $env?.$env?.Bar()?.[foo] $env?.$env?.Bar?.foo $env?.$env?.String $env?.$env?.String() $env?.$env?.String(foobar) $env?.$env?.String(greet) $env?.$env?.[add] $env?.$env?.[array] $env?.$env?.[f64] $env?.$env?.[f64].list.greet $env?.$env?.[f64]?.str $env?.$env?.[foo] $env?.$env?.[foo].ok $env?.$env?.[greet] $env?.$env?.[greet].i $env?.$env?.[i] $env?.$env?.[i].f64 $env?.$env?.[i].foo $env?.$env?.[i].str $env?.$env?.[i]?.[greet]?.greet() $env?.$env?.[i]?.[ok] $env?.$env?.[i]?.f64 $env?.$env?.[list] $env?.$env?.[ok] $env?.$env?.[str] $env?.$env?.[str]?.[foo]?.str $env?.$env?.add $env?.$env?.add() $env?.$env?.add().Bar $env?.$env?.add(foobar?.[str]) $env?.$env?.add(nil == Bar, add) $env?.$env?.add?.ok $env?.$env?.array $env?.$env?.array() $env?.$env?.array(foobar) $env?.$env?.array.i $env?.$env?.array?.[list] $env?.$env?.array?.[ok] $env?.$env?.array?.[str] $env?.$env?.array?.list $env?.$env?.count(String, foobar) $env?.$env?.f64 $env?.$env?.f64() $env?.$env?.f64(foobar) $env?.$env?.f64.String $env?.$env?.filter(1.0, foo) $env?.$env?.findLast(i, i) $env?.$env?.foo $env?.$env?.foo.greet $env?.$env?.foobar.Bar $env?.$env?.foobar.i(foo) $env?.$env?.greet $env?.$env?.greet() $env?.$env?.greet.foo() $env?.$env?.greet.i $env?.$env?.greet?.i() $env?.$env?.i $env?.$env?.i() $env?.$env?.i()?.list $env?.$env?.i(foobar?.[f64])?.String $env?.$env?.i(str, foobar?.f64) $env?.$env?.i?.greet $env?.$env?.keys(Bar, foobar) $env?.$env?.list $env?.$env?.list() $env?.$env?.list.String $env?.$env?.list.list $env?.$env?.list?.foo $env?.$env?.list?.list $env?.$env?.ok $env?.$env?.ok() $env?.$env?.ok(String) $env?.$env?.ok.first(0)?.list $env?.$env?.ok?.String $env?.$env?.ok?.ok $env?.$env?.str $env?.$env?.str() $env?.$env?.str()?.[add] $env?.$env?.str(foobar) $env?.$env?.sum(0, list) $env?.$env?.uniq(foobar) $env?.Bar != $env.add $env?.Bar != add $env?.Bar != array $env?.Bar != f64 $env?.Bar != filter(array, true) $env?.Bar != foo $env?.Bar != foo && true $env?.Bar != greet $env?.Bar != i $env?.Bar != list $env?.Bar != min(1) $env?.Bar != ok $env?.Bar != str $env?.Bar != type(1.0) $env?.Bar + 1.0 or true $env?.Bar == $env?.f64 $env?.Bar == $env?.foobar $env?.Bar == 1.0 / f64 $env?.Bar == add $env?.Bar == array $env?.Bar == f64 $env?.Bar == foo $env?.Bar == foo.Bar $env?.Bar == greet $env?.Bar == greet(str) $env?.Bar == i $env?.Bar == list $env?.Bar == map(array, #) $env?.Bar == map(list, 1.0) $env?.Bar == nil ?? 1.0 $env?.Bar == ok $env?.Bar == ok or true $env?.Bar == str $env?.Bar == string(list) $env?.Bar ?? $env?.str $env?.Bar ?? -f64 $env?.Bar ?? [foo] $env?.Bar ?? add $env?.Bar ?? array $env?.Bar ?? f64 $env?.Bar ?? foo $env?.Bar ?? greet $env?.Bar ?? i $env?.Bar ?? list $env?.Bar ?? not ok $env?.Bar ?? ok $env?.Bar ?? str $env?.Bar ?? type(array) $env?.Bar contains $env?.$env $env?.Bar contains str $env?.Bar endsWith $env?.String $env?.Bar endsWith str $env?.Bar endsWith str ? foo : 1 $env?.Bar endsWith toJSON(0) $env?.Bar in array $env?.Bar matches $env?.[String] $env?.Bar matches str $env?.Bar matches string(i) $env?.Bar not contains mean(array) $env?.Bar not contains str $env?.Bar not endsWith $env.str $env?.Bar not endsWith foo.Bar $env?.Bar not in $env?.String $env?.Bar not in $env?.list $env?.Bar not in [f64, $env] $env?.Bar not in array $env?.Bar not in array ?? array $env?.Bar not in list $env?.Bar not in list and $env $env?.Bar not matches greet(str) $env?.Bar not matches str $env?.Bar not startsWith $env?.str $env?.Bar not startsWith 0 ?? array $env?.Bar not startsWith str $env?.Bar not startsWith str ?? $env $env?.Bar startsWith $env ?? foo $env?.Bar startsWith $env?.[String] $env?.Bar startsWith 1.0 ?? 0 $env?.Bar startsWith str $env?.Bar | get(1.0) $env?.Bar | get(list) $env?.Bar | get(nil) $env?.Bar | get(true) $env?.Bar().foobar or true $env?.Bar(foobar)?.foobar && false $env?.Bar; array $env?.Bar?.$env?.ok() $env?.Bar?.Bar $env?.Bar?.Bar() $env?.Bar?.Bar() != !ok $env?.Bar?.Bar().Bar $env?.Bar?.Bar()?.[f64] $env?.Bar?.Bar(Bar) $env?.Bar?.Bar(String) $env?.Bar?.Bar(f64) $env?.Bar?.Bar(foo != foobar) $env?.Bar?.Bar(foobar) $env?.Bar?.Bar(foobar?.String) $env?.Bar?.Bar(foobar?.[greet]) $env?.Bar?.Bar(foobar?.greet()) $env?.Bar?.Bar(i) $env?.Bar?.Bar(list) $env?.Bar?.Bar.String $env?.Bar?.Bar.add $env?.Bar?.Bar.i $env?.Bar?.Bar.list() $env?.Bar?.Bar.ok $env?.Bar?.Bar.str() $env?.Bar?.Bar?.Bar $env?.Bar?.Bar?.Bar().greet $env?.Bar?.Bar?.String $env?.Bar?.Bar?.[f64] $env?.Bar?.Bar?.[i] $env?.Bar?.Bar?.[list] $env?.Bar?.Bar?.i $env?.Bar?.Bar?.list $env?.Bar?.Bar?.ok $env?.Bar?.Bar?.str $env?.Bar?.String $env?.Bar?.String() $env?.Bar?.String()?.[foo] $env?.Bar?.String(add(foobar, foobar)) $env?.Bar?.String(foo) $env?.Bar?.String(foobar) $env?.Bar?.String(foobar)?.[add] $env?.Bar?.String(foobar)?.[ok]?.[str] $env?.Bar?.String(foobar)?.str $env?.Bar?.String(foobar?.Bar?.[f64]) $env?.Bar?.String(foobar?.[true]) $env?.Bar?.String(foobar?.f64(foobar)) $env?.Bar?.String(greet(Bar))?.foobar $env?.Bar?.String(greet) $env?.Bar?.String(i) $env?.Bar?.String(str | toBase64(foobar), foobar) $env?.Bar?.String.f64 $env?.Bar?.String.foo $env?.Bar?.String.i $env?.Bar?.String.ok $env?.Bar?.String?.String $env?.Bar?.String?.[array] $env?.Bar?.String?.[f64] $env?.Bar?.String?.[i] $env?.Bar?.String?.[str] $env?.Bar?.String?.add() $env?.Bar?.String?.date(foo) $env?.Bar?.String?.foo $env?.Bar?.String?.str() $env?.Bar?.[$env.i] $env?.Bar?.[$env?.Bar] $env?.Bar?.[$env?.[String]] $env?.Bar?.[$env?.[add]].Bar $env?.Bar?.[$env?.f64] $env?.Bar?.[add] $env?.Bar?.[add].Bar $env?.Bar?.[add].String $env?.Bar?.[add].add $env?.Bar?.[add].foo $env?.Bar?.[add].i $env?.Bar?.[add]?.Bar?.str $env?.Bar?.[add]?.[greet] $env?.Bar?.[add]?.[i] $env?.Bar?.[add]?.f64 $env?.Bar?.[add]?.foo $env?.Bar?.[add]?.greet $env?.Bar?.[add]?.list $env?.Bar?.[add]?.ok $env?.Bar?.[add]?.str $env?.Bar?.[array] $env?.Bar?.[array].ok $env?.Bar?.[array].ok() $env?.Bar?.[array]?.Bar $env?.Bar?.[array]?.String $env?.Bar?.[array]?.[greet] $env?.Bar?.[array]?.[list] $env?.Bar?.[array]?.add $env?.Bar?.[array]?.foo $env?.Bar?.[array]?.list $env?.Bar?.[count($env)] $env?.Bar?.[f64] $env?.Bar?.[f64].Bar $env?.Bar?.[f64].f64 $env?.Bar?.[f64].list $env?.Bar?.[f64].ok $env?.Bar?.[f64]?.Bar $env?.Bar?.[f64]?.[greet] $env?.Bar?.[f64]?.[list] $env?.Bar?.[f64]?.add() $env?.Bar?.[f64]?.array() $env?.Bar?.[f64]?.str(foobar) $env?.Bar?.[false != $env] $env?.Bar?.[foo?.String] $env?.Bar?.[foo] $env?.Bar?.[foo].add $env?.Bar?.[foo].array() $env?.Bar?.[foo].f64 $env?.Bar?.[foo].greet $env?.Bar?.[foo].str $env?.Bar?.[foo]?.Bar $env?.Bar?.[foo]?.String $env?.Bar?.[foo]?.[array] $env?.Bar?.[foo]?.[greet] $env?.Bar?.[foo]?.[i] $env?.Bar?.[foo]?.[ok] $env?.Bar?.[foo]?.add $env?.Bar?.[foo]?.array(i) $env?.Bar?.[foo]?.f64 $env?.Bar?.[foo]?.list $env?.Bar?.[foo]?.str $env?.Bar?.[greet] $env?.Bar?.[greet].Bar $env?.Bar?.[greet].Bar(add)?.greet $env?.Bar?.[greet].add $env?.Bar?.[greet].f64 $env?.Bar?.[greet].foo $env?.Bar?.[greet].i $env?.Bar?.[greet].list $env?.Bar?.[greet].ok $env?.Bar?.[greet]?.Bar $env?.Bar?.[greet]?.[add] $env?.Bar?.[greet]?.[f64] $env?.Bar?.[greet]?.[i] $env?.Bar?.[greet]?.array $env?.Bar?.[greet]?.f64 $env?.Bar?.[greet]?.foo() $env?.Bar?.[greet]?.greet $env?.Bar?.[greet]?.list.String $env?.Bar?.[groupBy(list, #)] $env?.Bar?.[i] $env?.Bar?.[i].Bar(foo, false, greet).array $env?.Bar?.[i].add $env?.Bar?.[i].foo $env?.Bar?.[i].list $env?.Bar?.[i].ok $env?.Bar?.[i]?.Bar $env?.Bar?.[i]?.String $env?.Bar?.[i]?.[add] $env?.Bar?.[i]?.[array] $env?.Bar?.[i]?.[greet] $env?.Bar?.[i]?.[i] $env?.Bar?.[i]?.[list] $env?.Bar?.[i]?.[ok] $env?.Bar?.[i]?.add $env?.Bar?.[i]?.f64 $env?.Bar?.[i]?.foo $env?.Bar?.[i]?.ok $env?.Bar?.[i]?.str() $env?.Bar?.[list?.[i]] $env?.Bar?.[list] $env?.Bar?.[list].Bar $env?.Bar?.[list].add $env?.Bar?.[list].array() $env?.Bar?.[list].f64 $env?.Bar?.[list].greet $env?.Bar?.[list].i(foobar) $env?.Bar?.[list].ok $env?.Bar?.[list].str $env?.Bar?.[list].str() $env?.Bar?.[list]?.String $env?.Bar?.[list]?.[add] $env?.Bar?.[list]?.[array] $env?.Bar?.[list]?.[f64] $env?.Bar?.[list]?.[foo] $env?.Bar?.[list]?.[i] $env?.Bar?.[list]?.[ok] $env?.Bar?.[list]?.[str] $env?.Bar?.[list]?.array.list $env?.Bar?.[list]?.f64 $env?.Bar?.[list]?.list $env?.Bar?.[list]?.list() $env?.Bar?.[list]?.str() $env?.Bar?.[median(0)] $env?.Bar?.[nil | date(array)] $env?.Bar?.[none($env, #.i)] $env?.Bar?.[ok] $env?.Bar?.[ok] == greet $env?.Bar?.[ok].Bar $env?.Bar?.[ok].String $env?.Bar?.[ok].f64 $env?.Bar?.[ok].i $env?.Bar?.[ok].ok() $env?.Bar?.[ok].str $env?.Bar?.[ok]?.Bar $env?.Bar?.[ok]?.String $env?.Bar?.[ok]?.[greet] $env?.Bar?.[ok]?.[i] $env?.Bar?.[ok]?.[str] $env?.Bar?.[ok]?.add $env?.Bar?.[ok]?.array $env?.Bar?.[ok]?.array() $env?.Bar?.[ok]?.f64() $env?.Bar?.[ok]?.foo $env?.Bar?.[ok]?.greet() $env?.Bar?.[ok]?.greet.array(foobar?.[str]) $env?.Bar?.[ok]?.i()?.[ok] $env?.Bar?.[ok]?.ok $env?.Bar?.[ok]?.str $env?.Bar?.[str] $env?.Bar?.[str].f64 $env?.Bar?.[str].foo() $env?.Bar?.[str].i $env?.Bar?.[str].list $env?.Bar?.[str].ok(foobar) $env?.Bar?.[str].str $env?.Bar?.[str]?.[array] $env?.Bar?.[str]?.[foo] $env?.Bar?.[str]?.[greet] $env?.Bar?.[str]?.[i] $env?.Bar?.[str]?.[ok]?.greet $env?.Bar?.[str]?.add $env?.Bar?.[str]?.array $env?.Bar?.[str]?.f64 $env?.Bar?.add $env?.Bar?.add not contains $env $env?.Bar?.add($env.foo).String $env?.Bar?.add() $env?.Bar?.add().f64 $env?.Bar?.add().f64(foobar) $env?.Bar?.add()?.[array] $env?.Bar?.add()?.greet() $env?.Bar?.add()?.i() $env?.Bar?.add(Bar) $env?.Bar?.add(add) $env?.Bar?.add(f64) $env?.Bar?.add(foo) $env?.Bar?.add(foobar != 1) $env?.Bar?.add(foobar) $env?.Bar?.add(foobar?.Bar?.[list]) $env?.Bar?.add(list) $env?.Bar?.add(ok) $env?.Bar?.add.Bar $env?.Bar?.add.f64() $env?.Bar?.add.foo $env?.Bar?.add.greet $env?.Bar?.add.i $env?.Bar?.add.list $env?.Bar?.add.ok $env?.Bar?.add.ok() $env?.Bar?.add?.Bar $env?.Bar?.add?.String $env?.Bar?.add?.[add] $env?.Bar?.add?.[foo] $env?.Bar?.add?.[greet] $env?.Bar?.add?.[list] $env?.Bar?.add?.[str] $env?.Bar?.add?.array $env?.Bar?.add?.greet $env?.Bar?.all(greet) $env?.Bar?.any(foo) $env?.Bar?.any(str) $env?.Bar?.array $env?.Bar?.array($env) $env?.Bar?.array() $env?.Bar?.array().f64 $env?.Bar?.array()?.[str] $env?.Bar?.array(array) $env?.Bar?.array(f64) $env?.Bar?.array(foobar) $env?.Bar?.array(foobar?.foo).ok $env?.Bar?.array(list) $env?.Bar?.array(ok) $env?.Bar?.array(reduce(list, foobar))?.Bar $env?.Bar?.array(str) $env?.Bar?.array.Bar $env?.Bar?.array.array $env?.Bar?.array.i?.foo $env?.Bar?.array.list $env?.Bar?.array.list(string(list) endsWith foobar?.String) $env?.Bar?.array.str $env?.Bar?.array?.[add] $env?.Bar?.array?.[array] $env?.Bar?.array?.[f64] $env?.Bar?.array?.[foo] $env?.Bar?.array?.[str] $env?.Bar?.array?.array $env?.Bar?.array?.f64 $env?.Bar?.array?.foo $env?.Bar?.array?.ok $env?.Bar?.array?.str $env?.Bar?.array?.str?.[array] $env?.Bar?.bitand(foobar) $env?.Bar?.bitnand(i, f64) $env?.Bar?.bitshl(str, foobar) $env?.Bar?.bitshr(foobar) $env?.Bar?.bitushr(Bar, str) $env?.Bar?.count(nil, nil) $env?.Bar?.f64 $env?.Bar?.f64() $env?.Bar?.f64().add() $env?.Bar?.f64(1) $env?.Bar?.f64(Bar?.[ok]) $env?.Bar?.f64(f64) $env?.Bar?.f64(foobar) $env?.Bar?.f64(foobar, foobar?.str()) $env?.Bar?.f64(i == foobar not in nil) $env?.Bar?.f64(list) $env?.Bar?.f64(ok, foobar) $env?.Bar?.f64(str, foobar) $env?.Bar?.f64.Bar(0) $env?.Bar?.f64.array() $env?.Bar?.f64.list $env?.Bar?.f64?.Bar() $env?.Bar?.f64?.[f64] $env?.Bar?.f64?.[greet] $env?.Bar?.f64?.[i] $env?.Bar?.f64?.f64 $env?.Bar?.f64?.list() $env?.Bar?.f64?.str $env?.Bar?.false?.[foo] $env?.Bar?.false?.list $env?.Bar?.filter(Bar) $env?.Bar?.filter(Bar, foobar) $env?.Bar?.filter(foo) $env?.Bar?.find(false) $env?.Bar?.find(foobar) $env?.Bar?.findIndex($env, foobar) $env?.Bar?.findIndex(false) $env?.Bar?.findLast($env) $env?.Bar?.findLastIndex(1, foobar) $env?.Bar?.findLastIndex(foo, foo) $env?.Bar?.findLastIndex(foobar, ok) $env?.Bar?.floor(ok, 1.0) $env?.Bar?.foo $env?.Bar?.foo not contains $env $env?.Bar?.foo($env matches foobar) $env?.Bar?.foo() $env?.Bar?.foo().greet.str $env?.Bar?.foo().i $env?.Bar?.foo()?.[add] $env?.Bar?.foo(Bar not matches foobar) $env?.Bar?.foo(f64) $env?.Bar?.foo(foobar) $env?.Bar?.foo(foobar, foobar) $env?.Bar?.foo(foobar?.list(foobar, array)) $env?.Bar?.foo(i) $env?.Bar?.foo(list) $env?.Bar?.foo(str) $env?.Bar?.foo.Bar $env?.Bar?.foo.add $env?.Bar?.foo.array $env?.Bar?.foo.f64 $env?.Bar?.foo.greet(greet) $env?.Bar?.foo.greet.i $env?.Bar?.foo.i $env?.Bar?.foo.list $env?.Bar?.foo?.Bar $env?.Bar?.foo?.[array] $env?.Bar?.foo?.[foo] $env?.Bar?.foo?.[i] $env?.Bar?.foo?.[ok] $env?.Bar?.foo?.add $env?.Bar?.foo?.i $env?.Bar?.foo?.str $env?.Bar?.foobar $env?.Bar?.foobar ?? foo $env?.Bar?.foobar.String.greet?.ok $env?.Bar?.foobar.add $env?.Bar?.foobar.add(foobar) $env?.Bar?.foobar.array $env?.Bar?.foobar.f64 $env?.Bar?.foobar.foobar $env?.Bar?.foobar.i $env?.Bar?.foobar.i() $env?.Bar?.foobar.list $env?.Bar?.foobar.ok $env?.Bar?.foobar.str()?.ok $env?.Bar?.foobar?.Bar(Bar) $env?.Bar?.foobar?.String $env?.Bar?.foobar?.[f64] $env?.Bar?.foobar?.[foo] $env?.Bar?.foobar?.[i].String $env?.Bar?.foobar?.[list] $env?.Bar?.foobar?.array $env?.Bar?.foobar?.array(foobar) $env?.Bar?.foobar?.foo $env?.Bar?.foobar?.i $env?.Bar?.foobar?.list $env?.Bar?.foobar?.str $env?.Bar?.fromBase64(ok) $env?.Bar?.fromPairs(0) $env?.Bar?.greet $env?.Bar?.greet() $env?.Bar?.greet()?.String $env?.Bar?.greet(String not contains foo, foo) $env?.Bar?.greet(String) $env?.Bar?.greet(array) $env?.Bar?.greet(foo) $env?.Bar?.greet(foobar ?? String) $env?.Bar?.greet(foobar startsWith foobar) $env?.Bar?.greet(foobar | greet()) $env?.Bar?.greet(foobar) $env?.Bar?.greet(foobar?.ok()) $env?.Bar?.greet(ok) $env?.Bar?.greet(str) $env?.Bar?.greet.add() $env?.Bar?.greet.f64 $env?.Bar?.greet.foo $env?.Bar?.greet.greet $env?.Bar?.greet?.[add] $env?.Bar?.greet?.[array] $env?.Bar?.greet?.[f64] $env?.Bar?.greet?.[i] $env?.Bar?.greet?.[i]?.f64 $env?.Bar?.greet?.[ok] $env?.Bar?.greet?.add $env?.Bar?.greet?.array $env?.Bar?.greet?.foo $env?.Bar?.greet?.foo(foobar)?.str $env?.Bar?.greet?.greet() $env?.Bar?.greet?.i() $env?.Bar?.greet?.list $env?.Bar?.groupBy(add) $env?.Bar?.groupBy(true, foo) $env?.Bar?.i $env?.Bar?.i == 1.0 $env?.Bar?.i() $env?.Bar?.i().foo $env?.Bar?.i()?.array $env?.Bar?.i(Bar, ok) $env?.Bar?.i(String) $env?.Bar?.i(foo.Bar) $env?.Bar?.i(foobar) $env?.Bar?.i(foobar?.[str]) $env?.Bar?.i(foobar?.str().str) $env?.Bar?.i(list) $env?.Bar?.i(nil matches foobar) $env?.Bar?.i(nil, false) $env?.Bar?.i.Bar(1, nil) $env?.Bar?.i.array() $env?.Bar?.i.i $env?.Bar?.i.ok $env?.Bar?.i?.String $env?.Bar?.i?.String(foobar) $env?.Bar?.i?.[add] $env?.Bar?.i?.[greet]?.[array] $env?.Bar?.i?.[ok] $env?.Bar?.i?.array $env?.Bar?.i?.foo $env?.Bar?.i?.foo() $env?.Bar?.i?.ok $env?.Bar?.last(foobar) $env?.Bar?.len(add) $env?.Bar?.len(greet) $env?.Bar?.list $env?.Bar?.list() $env?.Bar?.list().ok $env?.Bar?.list()?.ok $env?.Bar?.list(1.0 startsWith foobar, foobar?.list) $env?.Bar?.list(Bar | type(nil)) $env?.Bar?.list(f64) $env?.Bar?.list(foobar) $env?.Bar?.list(foobar?.i) $env?.Bar?.list(list)?.str $env?.Bar?.list(nil) $env?.Bar?.list(type(foobar)) $env?.Bar?.list.Bar $env?.Bar?.list.String $env?.Bar?.list.array $env?.Bar?.list.f64() $env?.Bar?.list.foobar $env?.Bar?.list?.Bar $env?.Bar?.list?.String $env?.Bar?.list?.[array] $env?.Bar?.list?.[foo]?.String()?.list $env?.Bar?.list?.[greet] $env?.Bar?.list?.[list] $env?.Bar?.list?.add $env?.Bar?.list?.f64 $env?.Bar?.list?.foo $env?.Bar?.list?.i $env?.Bar?.list?.str $env?.Bar?.map(foobar) $env?.Bar?.map(foobar, greet, String) $env?.Bar?.median(true, $env) $env?.Bar?.nil.array() $env?.Bar?.nil?.ok() $env?.Bar?.none(false, foobar) $env?.Bar?.none(foo) $env?.Bar?.none(foobar) $env?.Bar?.ok $env?.Bar?.ok() $env?.Bar?.ok().array $env?.Bar?.ok().greet $env?.Bar?.ok()?.f64 $env?.Bar?.ok()?.list $env?.Bar?.ok(add) $env?.Bar?.ok(f64) $env?.Bar?.ok(foobar) $env?.Bar?.ok(foobar?.[array]) $env?.Bar?.ok(foobar?.[f64]) $env?.Bar?.ok(foobar?.foo) $env?.Bar?.ok(greet) $env?.Bar?.ok(list) $env?.Bar?.ok(str) $env?.Bar?.ok.String() $env?.Bar?.ok.f64 $env?.Bar?.ok.f64(foobar?.[add]?.f64()) $env?.Bar?.ok.greet $env?.Bar?.ok.i(add) $env?.Bar?.ok.list $env?.Bar?.ok.ok $env?.Bar?.ok.str $env?.Bar?.ok?.Bar $env?.Bar?.ok?.String $env?.Bar?.ok?.[add] $env?.Bar?.ok?.[array] $env?.Bar?.ok?.[f64] $env?.Bar?.ok?.[foo] $env?.Bar?.ok?.add $env?.Bar?.ok?.f64 $env?.Bar?.ok?.foo $env?.Bar?.ok?.greet $env?.Bar?.ok?.i $env?.Bar?.ok?.str $env?.Bar?.one(array) $env?.Bar?.one(list) $env?.Bar?.reduce(foobar, foobar) $env?.Bar?.reduce(str) $env?.Bar?.reduce(true) $env?.Bar?.replace(str) $env?.Bar?.round(array) $env?.Bar?.round(foobar) $env?.Bar?.round(foobar, nil) $env?.Bar?.sort(list)?.Bar $env?.Bar?.sortBy($env, false) $env?.Bar?.sortBy(nil) $env?.Bar?.split(false) $env?.Bar?.str $env?.Bar?.str != ok $env?.Bar?.str() $env?.Bar?.str() endsWith str $env?.Bar?.str()?.[str] $env?.Bar?.str()?.f64 $env?.Bar?.str()?.greet $env?.Bar?.str(1, foobar) $env?.Bar?.str(Bar) $env?.Bar?.str(add) $env?.Bar?.str(f64 in nil) $env?.Bar?.str(foobar) $env?.Bar?.str(foobar?.[foobar]) $env?.Bar?.str(foobar?.array(String)) $env?.Bar?.str(greet) $env?.Bar?.str(ok) $env?.Bar?.str.f64 $env?.Bar?.str.foo $env?.Bar?.str.i $env?.Bar?.str.list $env?.Bar?.str?.Bar $env?.Bar?.str?.Bar() $env?.Bar?.str?.[foo] $env?.Bar?.str?.[greet] $env?.Bar?.str?.[ok] $env?.Bar?.str?.[str] $env?.Bar?.str?.[str]?.Bar $env?.Bar?.str?.[str]?.array $env?.Bar?.str?.array $env?.Bar?.str?.greet(foobar) $env?.Bar?.str?.i() $env?.Bar?.str?.list $env?.Bar?.str?.str() $env?.Bar?.string(foobar) $env?.Bar?.sum(f64) $env?.Bar?.sum(false) $env?.Bar?.toJSON(true) $env?.Bar?.true?.add $env?.Bar?.type(i) $env?.String != $env ? ok : true $env?.String != add $env?.String != array $env?.String != f64 $env?.String != float(i) $env?.String != foo $env?.String != foo?.String $env?.String != greet $env?.String != i $env?.String != list $env?.String != list != true $env?.String != ok $env?.String != str $env?.String == $env?.list $env?.String == -1.0 $env?.String == add $env?.String == array $env?.String == f64 $env?.String == foo $env?.String == greet $env?.String == i $env?.String == list $env?.String == str $env?.String ?? add $env?.String ?? array $env?.String ?? foo $env?.String ?? greet $env?.String ?? list $env?.String ?? str $env?.String ?? toJSON(1.0) $env?.String contains 0 ?? greet $env?.String contains str $env?.String endsWith $env && $env $env?.String endsWith str $env?.String in $env ? 1 : true $env?.String in $env ?? greet $env?.String in array $env?.String in list $env?.String matches $env ?: foo $env?.String matches $env?.nil $env?.String matches str $env?.String not contains str $env?.String not endsWith $env and $env $env?.String not endsWith $env.str $env?.String not endsWith str $env?.String not in $env?.Bar?.array $env?.String not in array $env?.String not in list $env?.String not in values($env) $env?.String not matches $env?.[String] $env?.String not matches foo.String() $env?.String not matches str $env?.String not startsWith str $env?.String startsWith str $env?.String startsWith toJSON(foo) $env?.String | get(1.0) $env?.String | get(false) $env?.String() == 1 || true $env?.String?.$env != true $env?.String?.$env.foo $env?.String?.Bar $env?.String?.Bar() $env?.String?.Bar(String) $env?.String?.Bar(add) $env?.String?.Bar(f64) $env?.String?.Bar(foo, ok) $env?.String?.Bar(foobar) $env?.String?.Bar(greet != foobar) $env?.String?.Bar(ok) $env?.String?.Bar.String $env?.String?.Bar.add $env?.String?.Bar.add() $env?.String?.Bar.i $env?.String?.Bar.list $env?.String?.Bar.ok $env?.String?.Bar.str $env?.String?.Bar?.Bar?.[ok] $env?.String?.Bar?.String $env?.String?.Bar?.[f64] $env?.String?.Bar?.[greet] $env?.String?.Bar?.[list] $env?.String?.Bar?.[ok] $env?.String?.Bar?.add $env?.String?.Bar?.greet $env?.String?.Bar?.greet() $env?.String?.Bar?.i $env?.String?.Bar?.ok $env?.String?.Bar?.str $env?.String?.String $env?.String?.String() $env?.String?.String().array $env?.String?.String(foobar not matches Bar) $env?.String?.String(foobar) $env?.String?.String(foobar, foobar) $env?.String?.String(i) $env?.String?.String(str) $env?.String?.String.add.f64 $env?.String?.String.f64 $env?.String?.String.i $env?.String?.String.list $env?.String?.String.ok $env?.String?.String?.[foo] $env?.String?.String?.[greet] $env?.String?.String?.[i] $env?.String?.String?.[list].ok $env?.String?.String?.add $env?.String?.String?.f64 $env?.String?.String?.foo $env?.String?.String?.greet $env?.String?.String?.list $env?.String?.String?.one(foobar?.list) $env?.String?.[$env or $env] $env?.String?.[$env | count(true)] $env?.String?.[$env.f64] $env?.String?.[$env?.[f64]] $env?.String?.[add] $env?.String?.[add] != greet $env?.String?.[add].Bar $env?.String?.[add].array $env?.String?.[add].greet $env?.String?.[add].i $env?.String?.[add].ok $env?.String?.[add]?.Bar?.array $env?.String?.[add]?.[f64] $env?.String?.[add]?.[foo] $env?.String?.[add]?.[i] $env?.String?.[add]?.[list] $env?.String?.[array] $env?.String?.[array].Bar $env?.String?.[array].f64 $env?.String?.[array].f64() $env?.String?.[array].greet $env?.String?.[array].str $env?.String?.[array]?.Bar $env?.String?.[array]?.String $env?.String?.[array]?.[add] $env?.String?.[array]?.[array] $env?.String?.[array]?.[f64] $env?.String?.[array]?.[list] $env?.String?.[array]?.add $env?.String?.[array]?.array $env?.String?.[array]?.foo $env?.String?.[array]?.foo() $env?.String?.[f64] $env?.String?.[f64].add $env?.String?.[f64].array $env?.String?.[f64].foobar $env?.String?.[f64].greet $env?.String?.[f64].i() $env?.String?.[f64]?.Bar $env?.String?.[f64]?.String $env?.String?.[f64]?.[f64] $env?.String?.[f64]?.[list] $env?.String?.[f64]?.[str] $env?.String?.[f64]?.array $env?.String?.[f64]?.greet $env?.String?.[f64]?.list $env?.String?.[f64]?.list() $env?.String?.[f64]?.ok $env?.String?.[f64]?.str() $env?.String?.[findLast($env, .list)] $env?.String?.[foo] $env?.String?.[foo].array $env?.String?.[foo].f64 $env?.String?.[foo].f64() $env?.String?.[foo].i $env?.String?.[foo]?.String $env?.String?.[foo]?.[foo] $env?.String?.[foo]?.[i] $env?.String?.[foo]?.add $env?.String?.[foo]?.foo $env?.String?.[foo]?.i $env?.String?.[foo]?.list $env?.String?.[foo]?.ok $env?.String?.[foo]?.ok() $env?.String?.[foo]?.str $env?.String?.[greet] $env?.String?.[greet] not in array $env?.String?.[greet].add $env?.String?.[greet].any(foobar).str $env?.String?.[greet].array $env?.String?.[greet]?.[add] $env?.String?.[greet]?.[list] $env?.String?.[greet]?.f64 $env?.String?.[greet]?.greet() $env?.String?.[greet]?.list $env?.String?.[greet]?.ok $env?.String?.[i] $env?.String?.[i].Bar $env?.String?.[i].f64 $env?.String?.[i].f64() $env?.String?.[i].foo $env?.String?.[i].list $env?.String?.[i]?.String $env?.String?.[i]?.[array] $env?.String?.[i]?.[foo] $env?.String?.[i]?.[greet] $env?.String?.[i]?.add $env?.String?.[i]?.array $env?.String?.[i]?.foo $env?.String?.[i]?.list $env?.String?.[i]?.str $env?.String?.[i]?.str() $env?.String?.[list] $env?.String?.[list].array $env?.String?.[list].f64 $env?.String?.[list].foo $env?.String?.[list].list $env?.String?.[list].ok $env?.String?.[list].ok() $env?.String?.[list].str $env?.String?.[list]?.[list] $env?.String?.[list]?.[str] $env?.String?.[list]?.add $env?.String?.[list]?.list(foobar) $env?.String?.[list]?.ok $env?.String?.[ok] $env?.String?.[ok].Bar $env?.String?.[ok].add $env?.String?.[ok].list() $env?.String?.[ok]?.Bar $env?.String?.[ok]?.Bar.str $env?.String?.[ok]?.[array] $env?.String?.[ok]?.[f64]?.foo $env?.String?.[ok]?.[i] $env?.String?.[ok]?.[ok] $env?.String?.[ok]?.[str] $env?.String?.[ok]?.add $env?.String?.[ok]?.add() $env?.String?.[ok]?.foo() $env?.String?.[ok]?.greet $env?.String?.[ok]?.ok $env?.String?.[str] $env?.String?.[str] != lower(str) $env?.String?.[str].foo $env?.String?.[str].str() $env?.String?.[str]?.[array] $env?.String?.[str]?.[list] $env?.String?.[str]?.array $env?.String?.[str]?.f64 $env?.String?.[str]?.foo() $env?.String?.[str]?.str(str) $env?.String?.[sum($env)] $env?.String?.abs(1.0) $env?.String?.add $env?.String?.add() $env?.String?.add()?.[i] $env?.String?.add(Bar) $env?.String?.add(f64 not endsWith nil) $env?.String?.add(f64) $env?.String?.add(foobar) $env?.String?.add(foobar).i $env?.String?.add(foobar, ceil(abs(foobar, 1))) $env?.String?.add(ok) $env?.String?.add(str) $env?.String?.add.f64 $env?.String?.add.ok $env?.String?.add.ok() $env?.String?.add?.Bar $env?.String?.add?.[array] $env?.String?.add?.[f64] $env?.String?.add?.[greet] $env?.String?.add?.[ok] $env?.String?.add?.[str] $env?.String?.add?.add $env?.String?.add?.array $env?.String?.add?.f64 $env?.String?.add?.greet $env?.String?.add?.i(f64) $env?.String?.add?.list $env?.String?.add?.ok $env?.String?.add?.str?.array $env?.String?.all(1.0, true) $env?.String?.all(foobar) $env?.String?.all(nil, nil) $env?.String?.all(ok, nil) $env?.String?.any(f64)?.[foo] $env?.String?.any(foo) $env?.String?.any(foobar, foobar, foobar) $env?.String?.array $env?.String?.array not endsWith str $env?.String?.array() $env?.String?.array()?.[f64] $env?.String?.array(String) $env?.String?.array(add) $env?.String?.array(array matches nil) $env?.String?.array(foo) $env?.String?.array(foobar and true) $env?.String?.array(foobar) $env?.String?.array(i) $env?.String?.array(str not in String) $env?.String?.array.Bar $env?.String?.array.String $env?.String?.array.add $env?.String?.array.array $env?.String?.array.f64 $env?.String?.array.foo $env?.String?.array.list $env?.String?.array.ok $env?.String?.array?.Bar $env?.String?.array?.Bar?.list $env?.String?.array?.String $env?.String?.array?.[array] $env?.String?.array?.[str] $env?.String?.array?.array() $env?.String?.array?.f64 $env?.String?.array?.f64.list() $env?.String?.array?.i.foo $env?.String?.array?.ok $env?.String?.bitshl(String) $env?.String?.bitshr(nil, f64) $env?.String?.bitushr(str, foobar) $env?.String?.bitxor(String) $env?.String?.date(foobar, foobar) $env?.String?.duration(foobar) $env?.String?.f64 $env?.String?.f64 == i $env?.String?.f64() $env?.String?.f64().f64 $env?.String?.f64()?.String $env?.String?.f64()?.[i] $env?.String?.f64()?.[str] $env?.String?.f64(1.0 ?? nil) $env?.String?.f64(String) $env?.String?.f64(foobar) $env?.String?.f64(foobar)?.greet $env?.String?.f64(foobar, foobar) $env?.String?.f64(foobar?.[0]) $env?.String?.f64(i) $env?.String?.f64(list) $env?.String?.f64(nil == f64) $env?.String?.f64.String?.greet $env?.String?.f64.f64 $env?.String?.f64.greet $env?.String?.f64.list $env?.String?.f64.list() $env?.String?.f64.ok $env?.String?.f64.str(foobar, foobar)?.[add] $env?.String?.f64?.String $env?.String?.f64?.[array] $env?.String?.f64?.[greet] $env?.String?.f64?.[ok] $env?.String?.f64?.add $env?.String?.f64?.list?.[str] $env?.String?.f64?.ok $env?.String?.false?.add() $env?.String?.filter(str) $env?.String?.findIndex($env) $env?.String?.findIndex(f64, foobar) $env?.String?.findIndex(foobar) $env?.String?.findIndex(nil) $env?.String?.findLast(greet, nil) $env?.String?.flatten(f64) $env?.String?.flatten(foobar, foobar) $env?.String?.float($env) $env?.String?.foo $env?.String?.foo($env) $env?.String?.foo() $env?.String?.foo()?.[i] $env?.String?.foo(add) $env?.String?.foo(f64) $env?.String?.foo(false ?? add) $env?.String?.foo(foo) $env?.String?.foo(foobar) $env?.String?.foo(foobar?.greet) $env?.String?.foo(greet) $env?.String?.foo(list, 1) $env?.String?.foo(ok) $env?.String?.foo.array $env?.String?.foo.i $env?.String?.foo.ok() $env?.String?.foo?.Bar $env?.String?.foo?.[f64] $env?.String?.foo?.[i] $env?.String?.foo?.[ok] $env?.String?.foo?.[ok].f64() $env?.String?.foo?.[str] $env?.String?.foo?.add $env?.String?.foo?.f64 $env?.String?.foo?.greet $env?.String?.foo?.i $env?.String?.foobar $env?.String?.foobar ?? add $env?.String?.foobar in array $env?.String?.foobar.String(greet) $env?.String?.foobar.add $env?.String?.foobar.f64 $env?.String?.foobar.foo $env?.String?.foobar.greet $env?.String?.foobar.str() $env?.String?.foobar?.[add] $env?.String?.foobar?.[array] $env?.String?.foobar?.[list] $env?.String?.foobar?.add() $env?.String?.foobar?.foo() $env?.String?.foobar?.foo(i) $env?.String?.get(nil) $env?.String?.greet $env?.String?.greet($env) $env?.String?.greet() $env?.String?.greet().Bar $env?.String?.greet().foo $env?.String?.greet()?.String $env?.String?.greet()?.[i] $env?.String?.greet(0) $env?.String?.greet(String) $env?.String?.greet(foobar == String) $env?.String?.greet(foobar and true) $env?.String?.greet(foobar or true) $env?.String?.greet(foobar) $env?.String?.greet(foobar?.String) $env?.String?.greet(i) $env?.String?.greet(nil) $env?.String?.greet(ok) $env?.String?.greet(str) $env?.String?.greet.add $env?.String?.greet.i $env?.String?.greet?.[array] $env?.String?.greet?.[list] $env?.String?.greet?.[ok] $env?.String?.greet?.foo $env?.String?.greet?.greet() $env?.String?.greet?.i $env?.String?.greet?.list $env?.String?.groupBy(nil) $env?.String?.groupBy(str, foobar) $env?.String?.i $env?.String?.i() $env?.String?.i().add $env?.String?.i()?.add $env?.String?.i()?.i $env?.String?.i(0).f64 $env?.String?.i(1) $env?.String?.i(Bar)?.[array] $env?.String?.i(String?.$env) $env?.String?.i(array) $env?.String?.i(f64) $env?.String?.i(foobar) $env?.String?.i.Bar $env?.String?.i.add $env?.String?.i.foo $env?.String?.i.foobar $env?.String?.i.str $env?.String?.i?.Bar $env?.String?.i?.String $env?.String?.i?.[f64] $env?.String?.i?.add $env?.String?.i?.foo $env?.String?.i?.ok $env?.String?.int(add, foobar, greet) $env?.String?.join(true, f64) $env?.String?.keys(0, 0) $env?.String?.last(foo) $env?.String?.list $env?.String?.list() $env?.String?.list()?.[i] $env?.String?.list(1.0, foobar, greet) $env?.String?.list(false) $env?.String?.list(foobar not endsWith greet) $env?.String?.list(foobar?.f64()) $env?.String?.list(ok) $env?.String?.list.String() $env?.String?.list.array() $env?.String?.list.str $env?.String?.list?.[add] $env?.String?.list?.[i] $env?.String?.list?.[list] $env?.String?.list?.[str] $env?.String?.list?.add $env?.String?.list?.f64 $env?.String?.list?.list $env?.String?.list?.str $env?.String?.lower(0) $env?.String?.map($env) $env?.String?.map(false) $env?.String?.map(foo) $env?.String?.map(nil, String) $env?.String?.mean(add) $env?.String?.nil endsWith str $env?.String?.nil?.foo $env?.String?.not $env?.String?.not .array $env?.String?.ok $env?.String?.ok() $env?.String?.ok()?.Bar $env?.String?.ok(array) $env?.String?.ok(foo) $env?.String?.ok(foobar not endsWith add) $env?.String?.ok(foobar) $env?.String?.ok(foobar?.[foo]) $env?.String?.ok(nil) $env?.String?.ok.Bar() $env?.String?.ok.array $env?.String?.ok.f64 $env?.String?.ok.foo $env?.String?.ok.foo() $env?.String?.ok.greet $env?.String?.ok.list $env?.String?.ok?.Bar $env?.String?.ok?.[array] $env?.String?.ok?.[list] $env?.String?.ok?.[ok] $env?.String?.ok?.[str] $env?.String?.ok?.f64 $env?.String?.ok?.i $env?.String?.ok?.i(foobar) $env?.String?.ok?.str $env?.String?.reverse(greet) $env?.String?.round(foobar, foobar) $env?.String?.sortBy(foobar) $env?.String?.sortBy(true) $env?.String?.str $env?.String?.str($env) $env?.String?.str() $env?.String?.str().String $env?.String?.str()?.[f64] $env?.String?.str()?.add $env?.String?.str()?.ok $env?.String?.str(foo?.String) $env?.String?.str(foobar) $env?.String?.str(i) $env?.String?.str.Bar $env?.String?.str.add() $env?.String?.str.greet(foobar, foobar) $env?.String?.str.list $env?.String?.str.str $env?.String?.str?.Bar $env?.String?.str?.String $env?.String?.str?.[greet] $env?.String?.str?.[str] $env?.String?.str?.f64 $env?.String?.str?.greet $env?.String?.str?.greet() $env?.String?.str?.i $env?.String?.str?.ok $env?.String?.sum(1.0) $env?.String?.toPairs(Bar) $env?.String?.true.array $env?.String?.true?.[list] $env?.[1.0]?.foobar and false $env?.[Bar] != $env.i $env?.[Bar] != $env?.list $env?.[Bar] != 1.0 && $env $env?.[Bar] != 1.0 + 1.0 $env?.[Bar] != add $env?.[Bar] != array $env?.[Bar] != f64 $env?.[Bar] != foo $env?.[Bar] != foo.Bar $env?.[Bar] != greet $env?.[Bar] != i $env?.[Bar] != i - 1.0 $env?.[Bar] != list $env?.[Bar] != min(f64) $env?.[Bar] != not true $env?.[Bar] != ok $env?.[Bar] != str $env?.[Bar] != str != true $env?.[Bar] != string(false) $env?.[Bar] < i || true $env?.[Bar] == $env.array $env?.[Bar] == $env?.[str] $env?.[Bar] == add $env?.[Bar] == array $env?.[Bar] == count(array, ok) $env?.[Bar] == f64 $env?.[Bar] == foo $env?.[Bar] == foo?.Bar $env?.[Bar] == greet ? 0 : true $env?.[Bar] == greet or ok $env?.[Bar] == i $env?.[Bar] == list $env?.[Bar] == ok $env?.[Bar] == str $env?.[Bar] ?? add $env?.[Bar] ?? array $env?.[Bar] ?? f64 $env?.[Bar] ?? foo $env?.[Bar] ?? foo?.Bar $env?.[Bar] ?? greet ?? str $env?.[Bar] ?? i $env?.[Bar] ?? list $env?.[Bar] ?? ok $env?.[Bar] ?? str $env?.[Bar] and true and false $env?.[Bar] contains $env ?? nil $env?.[Bar] contains foo.Bar $env?.[Bar] contains last($env) $env?.[Bar] contains nil ?? $env $env?.[Bar] contains str $env?.[Bar] endsWith str $env?.[Bar] in $env?.nil?.add $env?.[Bar] in array $env?.[Bar] in list $env?.[Bar] matches $env?.str $env?.[Bar] matches str $env?.[Bar] not contains $env.str $env?.[Bar] not contains $env?.Bar $env?.[Bar] not contains $env?.String $env?.[Bar] not contains greet(str) $env?.[Bar] not contains str $env?.[Bar] not endsWith $env || false $env?.[Bar] not endsWith greet(str) $env?.[Bar] not endsWith str $env?.[Bar] not in $env?.[foobar] $env?.[Bar] not in array $env?.[Bar] not in list $env?.[Bar] not matches foo.Bar $env?.[Bar] not matches str $env?.[Bar] not matches string(1.0) $env?.[Bar] not startsWith $env?.[String] $env?.[Bar] not startsWith foo.Bar $env?.[Bar] not startsWith str $env?.[Bar] not startsWith str != nil $env?.[Bar] startsWith str $env?.[Bar] | get($env) $env?.[Bar] | get(1.0) $env?.[Bar] | get(list) $env?.[Bar]?.$env?.[f64] $env?.[Bar]?.$env?.[foo].Bar $env?.[Bar]?.$env?.array() $env?.[Bar]?.$env?.str $env?.[Bar]?.Bar $env?.[Bar]?.Bar($env) $env?.[Bar]?.Bar() $env?.[Bar]?.Bar().ok $env?.[Bar]?.Bar()?.[i] $env?.[Bar]?.Bar()?.greet() $env?.[Bar]?.Bar(0)?.foo $env?.[Bar]?.Bar(Bar not contains f64) $env?.[Bar]?.Bar(Bar?.ok) $env?.[Bar]?.Bar(String?.ok(foobar)) $env?.[Bar]?.Bar(add) $env?.[Bar]?.Bar(foo) $env?.[Bar]?.Bar(foo, foobar) $env?.[Bar]?.Bar(foobar) $env?.[Bar]?.Bar(greet) $env?.[Bar]?.Bar(nil) $env?.[Bar]?.Bar(ok) $env?.[Bar]?.Bar.add $env?.[Bar]?.Bar.greet $env?.[Bar]?.Bar.str $env?.[Bar]?.Bar?.[add] $env?.[Bar]?.Bar?.[array] $env?.[Bar]?.Bar?.[list]?.array $env?.[Bar]?.Bar?.f64 $env?.[Bar]?.Bar?.foo $env?.[Bar]?.Bar?.i $env?.[Bar]?.Bar?.list $env?.[Bar]?.Bar?.str $env?.[Bar]?.String $env?.[Bar]?.String() $env?.[Bar]?.String().foo $env?.[Bar]?.String().ok $env?.[Bar]?.String(f64) $env?.[Bar]?.String(foobar not contains foobar?.String) $env?.[Bar]?.String(foobar) $env?.[Bar]?.String(str) $env?.[Bar]?.String(str).i $env?.[Bar]?.String.foobar $env?.[Bar]?.String.greet $env?.[Bar]?.String.i $env?.[Bar]?.String?.Bar $env?.[Bar]?.String?.[f64] $env?.[Bar]?.String?.[foo] $env?.[Bar]?.String?.[greet] $env?.[Bar]?.String?.[str] $env?.[Bar]?.String?.add $env?.[Bar]?.String?.add(foobar) $env?.[Bar]?.String?.array $env?.[Bar]?.String?.foo $env?.[Bar]?.String?.greet?.String(foobar)?.greet $env?.[Bar]?.String?.i() $env?.[Bar]?.String?.i(false) $env?.[Bar]?.String?.list $env?.[Bar]?.String?.ok $env?.[Bar]?.String?.str $env?.[Bar]?.[$env % 1]?.[f64] $env?.[Bar]?.[$env | none(.array)] $env?.[Bar]?.[$env?.array] $env?.[Bar]?.[add ?? 1] $env?.[Bar]?.[add] $env?.[Bar]?.[add].Bar $env?.[Bar]?.[add].Bar() $env?.[Bar]?.[add].Bar()?.[list] $env?.[Bar]?.[add].f64 $env?.[Bar]?.[add].foo $env?.[Bar]?.[add].greet $env?.[Bar]?.[add].list $env?.[Bar]?.[add].ok $env?.[Bar]?.[add].str $env?.[Bar]?.[add]?.[list] $env?.[Bar]?.[add]?.[ok] $env?.[Bar]?.[add]?.array $env?.[Bar]?.[add]?.i $env?.[Bar]?.[add]?.list $env?.[Bar]?.[add]?.ok $env?.[Bar]?.[array] $env?.[Bar]?.[array].Bar $env?.[Bar]?.[array].String $env?.[Bar]?.[array].String() $env?.[Bar]?.[array].add() $env?.[Bar]?.[array].f64 $env?.[Bar]?.[array].f64() $env?.[Bar]?.[array].foo $env?.[Bar]?.[array].greet $env?.[Bar]?.[array].i $env?.[Bar]?.[array]?.Bar $env?.[Bar]?.[array]?.[array] $env?.[Bar]?.[array]?.[i] $env?.[Bar]?.[array]?.[ok] $env?.[Bar]?.[array]?.f64 $env?.[Bar]?.[array]?.foo $env?.[Bar]?.[count($env)] $env?.[Bar]?.[count(list)] $env?.[Bar]?.[date(ok, false)] $env?.[Bar]?.[f64] $env?.[Bar]?.[f64] != i $env?.[Bar]?.[f64].Bar $env?.[Bar]?.[f64].array $env?.[Bar]?.[f64].array()?.list $env?.[Bar]?.[f64].f64 $env?.[Bar]?.[f64].greet $env?.[Bar]?.[f64].str $env?.[Bar]?.[f64]?.Bar $env?.[Bar]?.[f64]?.[add] $env?.[Bar]?.[f64]?.[ok] $env?.[Bar]?.[f64]?.add(foobar, Bar) $env?.[Bar]?.[f64]?.array $env?.[Bar]?.[f64]?.f64() $env?.[Bar]?.[f64]?.foo() $env?.[Bar]?.[f64]?.i?.[f64] $env?.[Bar]?.[f64]?.none(foobar) $env?.[Bar]?.[f64]?.ok $env?.[Bar]?.[f64]?.str $env?.[Bar]?.[foo == foo] $env?.[Bar]?.[foo] $env?.[Bar]?.[foo].String $env?.[Bar]?.[foo].foo() $env?.[Bar]?.[foo].greet $env?.[Bar]?.[foo].i $env?.[Bar]?.[foo].ok $env?.[Bar]?.[foo]?.Bar(f64) $env?.[Bar]?.[foo]?.[f64] $env?.[Bar]?.[foo]?.[foo] $env?.[Bar]?.[foo]?.[list] $env?.[Bar]?.[foo]?.[list].greet $env?.[Bar]?.[foo]?.f64 $env?.[Bar]?.[foo]?.findLast(list, foobar) $env?.[Bar]?.[foo]?.ok() $env?.[Bar]?.[foo]?.str $env?.[Bar]?.[greet] $env?.[Bar]?.[greet] == str $env?.[Bar]?.[greet].array $env?.[Bar]?.[greet].array() $env?.[Bar]?.[greet].i $env?.[Bar]?.[greet].i() $env?.[Bar]?.[greet].list $env?.[Bar]?.[greet].ok $env?.[Bar]?.[greet].str $env?.[Bar]?.[greet]?.String $env?.[Bar]?.[greet]?.[f64] $env?.[Bar]?.[greet]?.[str] $env?.[Bar]?.[greet]?.add() $env?.[Bar]?.[greet]?.array() $env?.[Bar]?.[greet]?.foo $env?.[Bar]?.[greet]?.i $env?.[Bar]?.[greet]?.str $env?.[Bar]?.[greet]?.str() $env?.[Bar]?.[groupBy($env, #)]?.[str] $env?.[Bar]?.[i] $env?.[Bar]?.[i].Bar $env?.[Bar]?.[i].Bar() $env?.[Bar]?.[i].array $env?.[Bar]?.[i].greet $env?.[Bar]?.[i].i() $env?.[Bar]?.[i].list $env?.[Bar]?.[i].str $env?.[Bar]?.[i]?.String $env?.[Bar]?.[i]?.[i] $env?.[Bar]?.[i]?.[list] $env?.[Bar]?.[i]?.[ok] $env?.[Bar]?.[i]?.array $env?.[Bar]?.[i]?.f64 $env?.[Bar]?.[i]?.foo $env?.[Bar]?.[i]?.i $env?.[Bar]?.[i]?.str $env?.[Bar]?.[list] $env?.[Bar]?.[list] in list $env?.[Bar]?.[list].String $env?.[Bar]?.[list].add() $env?.[Bar]?.[list].array $env?.[Bar]?.[list].foo $env?.[Bar]?.[list].greet $env?.[Bar]?.[list].ok $env?.[Bar]?.[list].ok() $env?.[Bar]?.[list].str(foobar) $env?.[Bar]?.[list]?.String $env?.[Bar]?.[list]?.[array] $env?.[Bar]?.[list]?.[greet]?.list $env?.[Bar]?.[list]?.[i] $env?.[Bar]?.[list]?.[list] $env?.[Bar]?.[list]?.[ok] $env?.[Bar]?.[list]?.add() $env?.[Bar]?.[list]?.f64 $env?.[Bar]?.[list]?.foo $env?.[Bar]?.[list]?.i $env?.[Bar]?.[list]?.str() $env?.[Bar]?.[nil != 0] $env?.[Bar]?.[ok] $env?.[Bar]?.[ok].f64 $env?.[Bar]?.[ok].foo() $env?.[Bar]?.[ok]?.[greet] $env?.[Bar]?.[ok]?.[i] $env?.[Bar]?.[ok]?.foo $env?.[Bar]?.[ok]?.foo() $env?.[Bar]?.[ok]?.i $env?.[Bar]?.[ok]?.ok $env?.[Bar]?.[ok]?.str $env?.[Bar]?.[str] $env?.[Bar]?.[str].Bar $env?.[Bar]?.[str].String $env?.[Bar]?.[str].greet() $env?.[Bar]?.[str].i $env?.[Bar]?.[str].ok $env?.[Bar]?.[str]?.[array] $env?.[Bar]?.[str]?.[f64] $env?.[Bar]?.[str]?.[foo]?.ok $env?.[Bar]?.[str]?.i() $env?.[Bar]?.[str]?.ok() $env?.[Bar]?.[sum($env, str)] $env?.[Bar]?.abs(nil, ok)?.[ok] $env?.[Bar]?.add $env?.[Bar]?.add() $env?.[Bar]?.add() == add $env?.[Bar]?.add().str $env?.[Bar]?.add()?.[f64] $env?.[Bar]?.add(1) $env?.[Bar]?.add(Bar) $env?.[Bar]?.add(String, foo, 1.0 | int(String, 1.0)) $env?.[Bar]?.add(add) $env?.[Bar]?.add(array) $env?.[Bar]?.add(foo) $env?.[Bar]?.add(foobar) $env?.[Bar]?.add(foobar?.[add]) $env?.[Bar]?.add(list) $env?.[Bar]?.add(str == foobar?.greet(foobar)) $env?.[Bar]?.add.Bar $env?.[Bar]?.add.String() $env?.[Bar]?.add.add $env?.[Bar]?.add.get(foobar?.str()) $env?.[Bar]?.add.greet $env?.[Bar]?.add.i $env?.[Bar]?.add.not $env?.[Bar]?.add.ok $env?.[Bar]?.add.str $env?.[Bar]?.add?.Bar() $env?.[Bar]?.add?.[add] $env?.[Bar]?.add?.[foo] $env?.[Bar]?.add?.[ok] $env?.[Bar]?.add?.array $env?.[Bar]?.add?.join(foobar, str) $env?.[Bar]?.all($env) $env?.[Bar]?.any(foo) $env?.[Bar]?.any(foobar, foobar) $env?.[Bar]?.array $env?.[Bar]?.array() $env?.[Bar]?.array().ok $env?.[Bar]?.array()?.list $env?.[Bar]?.array(1 != foo) $env?.[Bar]?.array(Bar, array) $env?.[Bar]?.array(add) == greet $env?.[Bar]?.array(add, foobar) $env?.[Bar]?.array(f64) $env?.[Bar]?.array(foo) $env?.[Bar]?.array(foobar endsWith 1.0) $env?.[Bar]?.array(foobar) $env?.[Bar]?.array(foobar, f64, i) $env?.[Bar]?.array(foobar?.ok) $env?.[Bar]?.array(greet) $env?.[Bar]?.array(sort(foobar)) $env?.[Bar]?.array.Bar $env?.[Bar]?.array.String() $env?.[Bar]?.array.add $env?.[Bar]?.array.f64 $env?.[Bar]?.array.list() $env?.[Bar]?.array?.[add] $env?.[Bar]?.array?.[add]?.foo $env?.[Bar]?.array?.[array] $env?.[Bar]?.array?.[greet] $env?.[Bar]?.array?.[list] $env?.[Bar]?.array?.list $env?.[Bar]?.bitxor(ok) $env?.[Bar]?.concat(i, 0) $env?.[Bar]?.f64 $env?.[Bar]?.f64() $env?.[Bar]?.f64().array $env?.[Bar]?.f64()?.f64?.[greet] $env?.[Bar]?.f64()?.ok $env?.[Bar]?.f64(1.0 != foo) $env?.[Bar]?.f64(Bar?.ok?.greet) $env?.[Bar]?.f64(add) $env?.[Bar]?.f64(foo) $env?.[Bar]?.f64(foobar in foobar)?.[add] $env?.[Bar]?.f64(foobar, ok) $env?.[Bar]?.f64(greet) $env?.[Bar]?.f64.String $env?.[Bar]?.f64.foo $env?.[Bar]?.f64.foo() $env?.[Bar]?.f64.greet $env?.[Bar]?.f64.i $env?.[Bar]?.f64.i() $env?.[Bar]?.f64.list $env?.[Bar]?.f64?.[add] $env?.[Bar]?.f64?.[greet] $env?.[Bar]?.f64?.[str] $env?.[Bar]?.f64?.f64 $env?.[Bar]?.f64?.i $env?.[Bar]?.f64?.list() $env?.[Bar]?.false.foo $env?.[Bar]?.find($env, foo) $env?.[Bar]?.find(Bar) $env?.[Bar]?.findIndex(true) $env?.[Bar]?.findLast(1) $env?.[Bar]?.findLast(1, i) $env?.[Bar]?.findLastIndex(nil) $env?.[Bar]?.foo $env?.[Bar]?.foo($env) $env?.[Bar]?.foo() $env?.[Bar]?.foo().list $env?.[Bar]?.foo()?.[i] $env?.[Bar]?.foo(foobar) $env?.[Bar]?.foo(foobar)?.foo $env?.[Bar]?.foo(foobar, foobar) $env?.[Bar]?.foo(foobar?.true startsWith foobar contains foobar) $env?.[Bar]?.foo(let bar = array; let z = ok; let z = 1.0; bar)?.[f64] $env?.[Bar]?.foo.add $env?.[Bar]?.foo.array $env?.[Bar]?.foo.greet $env?.[Bar]?.foo.greet?.greet(foobar) $env?.[Bar]?.foo.i $env?.[Bar]?.foo.ok $env?.[Bar]?.foo.ok() $env?.[Bar]?.foo.str $env?.[Bar]?.foo?.Bar $env?.[Bar]?.foo?.String $env?.[Bar]?.foo?.[add] $env?.[Bar]?.foo?.[array] $env?.[Bar]?.foo?.[greet].list() $env?.[Bar]?.foo?.[i] $env?.[Bar]?.foo?.[list] $env?.[Bar]?.foo?.array $env?.[Bar]?.foo?.f64 $env?.[Bar]?.foo?.foo() $env?.[Bar]?.foo?.greet $env?.[Bar]?.foo?.list $env?.[Bar]?.foo?.ok $env?.[Bar]?.foobar $env?.[Bar]?.foobar == add $env?.[Bar]?.foobar endsWith $env $env?.[Bar]?.foobar not endsWith str $env?.[Bar]?.foobar || false $env?.[Bar]?.foobar.String $env?.[Bar]?.foobar.String?.Bar $env?.[Bar]?.foobar.array $env?.[Bar]?.foobar.foo $env?.[Bar]?.foobar.list(nil) $env?.[Bar]?.foobar.str $env?.[Bar]?.foobar?.String $env?.[Bar]?.foobar?.[f64] $env?.[Bar]?.foobar?.[foo] $env?.[Bar]?.foobar?.[i] $env?.[Bar]?.foobar?.[ok] $env?.[Bar]?.foobar?.ok $env?.[Bar]?.fromPairs(foobar, foo) $env?.[Bar]?.greet $env?.[Bar]?.greet == ok $env?.[Bar]?.greet($env endsWith foobar) $env?.[Bar]?.greet() $env?.[Bar]?.greet().add $env?.[Bar]?.greet()?.[foo] $env?.[Bar]?.greet()?.[i] $env?.[Bar]?.greet()?.f64 $env?.[Bar]?.greet(0) $env?.[Bar]?.greet(array) $env?.[Bar]?.greet(f64, foobar) $env?.[Bar]?.greet(foo endsWith foobar?.[String]).Bar $env?.[Bar]?.greet(foo) $env?.[Bar]?.greet(foobar) $env?.[Bar]?.greet(foobar)?.String $env?.[Bar]?.greet(foobar, str) $env?.[Bar]?.greet(greet) $env?.[Bar]?.greet(list) $env?.[Bar]?.greet(str) $env?.[Bar]?.greet.Bar() $env?.[Bar]?.greet.add $env?.[Bar]?.greet.array() $env?.[Bar]?.greet.f64 $env?.[Bar]?.greet.f64(foobar) $env?.[Bar]?.greet?.[add] $env?.[Bar]?.greet?.[f64] $env?.[Bar]?.greet?.[i] $env?.[Bar]?.greet?.[list] $env?.[Bar]?.greet?.array $env?.[Bar]?.greet?.f64 $env?.[Bar]?.greet?.i $env?.[Bar]?.greet?.ok $env?.[Bar]?.groupBy(0, $env, foobar) $env?.[Bar]?.i $env?.[Bar]?.i($env not matches foobar, Bar)?.foo $env?.[Bar]?.i($env) $env?.[Bar]?.i() $env?.[Bar]?.i()?.str $env?.[Bar]?.i(0 < i) $env?.[Bar]?.i(foobar) $env?.[Bar]?.i(foobar, str | reduce($env, f64)) $env?.[Bar]?.i(greet, foobar) $env?.[Bar]?.i(list, foobar) $env?.[Bar]?.i.add $env?.[Bar]?.i.array() $env?.[Bar]?.i.ok $env?.[Bar]?.i.str $env?.[Bar]?.i?.Bar $env?.[Bar]?.i?.[add] $env?.[Bar]?.i?.[foo] $env?.[Bar]?.i?.[greet] $env?.[Bar]?.i?.add $env?.[Bar]?.i?.array $env?.[Bar]?.i?.foo() $env?.[Bar]?.i?.greet $env?.[Bar]?.i?.i $env?.[Bar]?.i?.i() $env?.[Bar]?.i?.ok() $env?.[Bar]?.i?.str $env?.[Bar]?.indexOf(nil, 1.0) $env?.[Bar]?.keys(Bar, false) $env?.[Bar]?.len(foo) $env?.[Bar]?.list $env?.[Bar]?.list() $env?.[Bar]?.list()?.[array] $env?.[Bar]?.list()?.[ok] $env?.[Bar]?.list()?.ok $env?.[Bar]?.list()?.str $env?.[Bar]?.list(array) $env?.[Bar]?.list(foo.String) $env?.[Bar]?.list(foobar ?? list) $env?.[Bar]?.list(foobar) $env?.[Bar]?.list(foobar).f64 $env?.[Bar]?.list(foobar)?.[str] $env?.[Bar]?.list(foobar?.list) $env?.[Bar]?.list.Bar $env?.[Bar]?.list.String $env?.[Bar]?.list.add $env?.[Bar]?.list.f64 $env?.[Bar]?.list.foobar $env?.[Bar]?.list.str $env?.[Bar]?.list?.Bar(foo, f64) $env?.[Bar]?.list?.[foo] $env?.[Bar]?.list?.[greet] $env?.[Bar]?.list?.[list] $env?.[Bar]?.list?.foo $env?.[Bar]?.list?.i $env?.[Bar]?.list?.str $env?.[Bar]?.list?.str() $env?.[Bar]?.lower(nil) $env?.[Bar]?.map(nil) $env?.[Bar]?.nil.str(Bar) $env?.[Bar]?.nil?.[ok] $env?.[Bar]?.nil?.i?.f64 $env?.[Bar]?.none(list) $env?.[Bar]?.none(ok) $env?.[Bar]?.not .str $env?.[Bar]?.not.ok $env?.[Bar]?.now(f64, foo) $env?.[Bar]?.now(foobar, foobar, $env) $env?.[Bar]?.ok $env?.[Bar]?.ok() $env?.[Bar]?.ok().list $env?.[Bar]?.ok()?.add $env?.[Bar]?.ok(Bar) $env?.[Bar]?.ok(add) $env?.[Bar]?.ok(array) $env?.[Bar]?.ok(f64) $env?.[Bar]?.ok(foobar?.[f64]) $env?.[Bar]?.ok(greet) $env?.[Bar]?.ok.String $env?.[Bar]?.ok.add $env?.[Bar]?.ok.f64 $env?.[Bar]?.ok.foo $env?.[Bar]?.ok.list $env?.[Bar]?.ok.ok $env?.[Bar]?.ok?.[array] $env?.[Bar]?.ok?.[greet] $env?.[Bar]?.ok?.foo $env?.[Bar]?.ok?.list $env?.[Bar]?.one(foobar, foobar)?.[str] $env?.[Bar]?.reduce(1.0) $env?.[Bar]?.str $env?.[Bar]?.str($env == foobar) $env?.[Bar]?.str($env) $env?.[Bar]?.str() $env?.[Bar]?.str().add.i $env?.[Bar]?.str()?.[list] $env?.[Bar]?.str(0) $env?.[Bar]?.str(Bar) $env?.[Bar]?.str(f64) $env?.[Bar]?.str(f64, array) $env?.[Bar]?.str(foobar) $env?.[Bar]?.str(greet) $env?.[Bar]?.str(list | first(true, foobar)) $env?.[Bar]?.str(list) $env?.[Bar]?.str(nil) $env?.[Bar]?.str.Bar $env?.[Bar]?.str.String $env?.[Bar]?.str.array $env?.[Bar]?.str.foo $env?.[Bar]?.str.greet $env?.[Bar]?.str.ok $env?.[Bar]?.str?.Bar $env?.[Bar]?.str?.[add] $env?.[Bar]?.str?.[array] $env?.[Bar]?.str?.[foo] $env?.[Bar]?.str?.[list] $env?.[Bar]?.str?.[str] $env?.[Bar]?.str?.f64 $env?.[Bar]?.str?.i(greet) $env?.[Bar]?.str?.list $env?.[Bar]?.sum(foobar) $env?.[Bar]?.sum(list).ok $env?.[Bar]?.sum(ok) $env?.[Bar]?.toBase64(1.0) $env?.[Bar]?.true not contains $env $env?.[Bar]?.true?.[ok] $env?.[Bar]?.uniq(array, $env) $env?.[Bar]?.uniq(foobar, foo) $env?.[Bar]?.values(foobar, foobar) $env?.[String] != $env.ok $env?.[String] != 1 ? f64 : f64 $env?.[String] != add $env?.[String] != array $env?.[String] != f64 $env?.[String] != foo $env?.[String] != foo ? foo : 0 $env?.[String] != i $env?.[String] != len(list) $env?.[String] != list $env?.[String] != nil ? add : foo $env?.[String] != ok $env?.[String] != str $env?.[String] == $env.i $env?.[String] == 0 != $env $env?.[String] == 1.0 / 1 $env?.[String] == add $env?.[String] == array $env?.[String] == f64 $env?.[String] == foo $env?.[String] == foo == $env $env?.[String] == foo?.Bar $env?.[String] == greet $env?.[String] == i $env?.[String] == i && $env $env?.[String] == list $env?.[String] == str $env?.[String] ?? -0 $env?.[String] ?? add $env?.[String] ?? array $env?.[String] ?? f64 $env?.[String] ?? foo $env?.[String] ?? i $env?.[String] ?? list $env?.[String] ?? str $env?.[String] contains $env?.[String] $env?.[String] contains $env?.[str] $env?.[String] contains 1.0 ?? greet $env?.[String] contains add ?? list $env?.[String] contains str $env?.[String] endsWith $env?.String $env?.[String] endsWith $env?.[str] $env?.[String] endsWith str $env?.[String] in [1] $env?.[String] in array $env?.[String] in list $env?.[String] matches str $env?.[String] not contains $env?.Bar $env?.[String] not contains false ?? greet $env?.[String] not contains str $env?.[String] not endsWith 1 ?? greet $env?.[String] not endsWith str $env?.[String] not in $env?.array $env?.[String] not in 0 .. 0 $env?.[String] not in array $env?.[String] not in list $env?.[String] not matches str $env?.[String] not startsWith str $env?.[String] startsWith $env?.[Bar] $env?.[String] startsWith foo ?? add $env?.[String] startsWith min($env) $env?.[String] startsWith str $env?.[String] | get(i) $env?.[String]?.$env.list $env?.[String]?.$env?.[foo] $env?.[String]?.$env?.[ok] $env?.[String]?.$env?.array $env?.[String]?.Bar $env?.[String]?.Bar() $env?.[String]?.Bar().foo $env?.[String]?.Bar()?.str $env?.[String]?.Bar(1.0).String $env?.[String]?.Bar(array) $env?.[String]?.Bar(f64) $env?.[String]?.Bar(foo contains String)?.[foo] $env?.[String]?.Bar(foobar) $env?.[String]?.Bar(greet) $env?.[String]?.Bar.String $env?.[String]?.Bar.greet $env?.[String]?.Bar.i(ok) $env?.[String]?.Bar.ok() $env?.[String]?.Bar.ok?.[ok] $env?.[String]?.Bar.str $env?.[String]?.Bar?.Bar() $env?.[String]?.Bar?.[add] $env?.[String]?.Bar?.[foo] $env?.[String]?.Bar?.[greet] $env?.[String]?.Bar?.[str] $env?.[String]?.Bar?.add $env?.[String]?.Bar?.i $env?.[String]?.Bar?.list() $env?.[String]?.Bar?.str.f64 $env?.[String]?.String $env?.[String]?.String($env) $env?.[String]?.String() $env?.[String]?.String().list $env?.[String]?.String().list(String) $env?.[String]?.String()?.add $env?.[String]?.String(String) $env?.[String]?.String(add) $env?.[String]?.String(foo) $env?.[String]?.String(foobar) $env?.[String]?.String(foobar, $env) $env?.[String]?.String(foobar?.[list])?.str() $env?.[String]?.String(greet) $env?.[String]?.String(last($env, String)) $env?.[String]?.String(ok && foobar) $env?.[String]?.String.add $env?.[String]?.String.split(false, add).str.array $env?.[String]?.String?.Bar $env?.[String]?.String?.Bar?.greet $env?.[String]?.String?.String $env?.[String]?.String?.[$env] $env?.[String]?.String?.[foo] $env?.[String]?.String?.[greet] $env?.[String]?.String?.[i] $env?.[String]?.String?.[list] $env?.[String]?.String?.[ok] $env?.[String]?.String?.array $env?.[String]?.String?.f64(false) $env?.[String]?.String?.foo $env?.[String]?.String?.foo(foobar) $env?.[String]?.String?.foo?.foo $env?.[String]?.String?.greet.greet $env?.[String]?.String?.list $env?.[String]?.String?.str?.ok $env?.[String]?.[$env == true] $env?.[String]?.[$env | none($env)] $env?.[String]?.[$env.foo] $env?.[String]?.[$env?.[greet]] $env?.[String]?.[$env?.array] $env?.[String]?.[add] $env?.[String]?.[add].String $env?.[String]?.[add].foo $env?.[String]?.[add].greet $env?.[String]?.[add].str $env?.[String]?.[add]?.String $env?.[String]?.[add]?.[add] $env?.[String]?.[add]?.[list] $env?.[String]?.[add]?.[ok] $env?.[String]?.[add]?.add $env?.[String]?.[add]?.add(foo) $env?.[String]?.[add]?.greet $env?.[String]?.[add]?.list?.Bar $env?.[String]?.[array | reduce(#)] $env?.[String]?.[array] $env?.[String]?.[array] == list $env?.[String]?.[array].Bar $env?.[String]?.[array].String $env?.[String]?.[array].String() $env?.[String]?.[array].array $env?.[String]?.[array].foo $env?.[String]?.[array].i $env?.[String]?.[array].ok $env?.[String]?.[array]?.Bar() $env?.[String]?.[array]?.[add] $env?.[String]?.[array]?.[foo] $env?.[String]?.[array]?.[list] $env?.[String]?.[array]?.[ok] $env?.[String]?.[array]?.[str] $env?.[String]?.[array]?.add $env?.[String]?.[array]?.array() $env?.[String]?.[array]?.f64 $env?.[String]?.[array]?.list?.[add] $env?.[String]?.[array]?.ok $env?.[String]?.[array]?.str $env?.[String]?.[f64] $env?.[String]?.[f64].add $env?.[String]?.[f64].foo $env?.[String]?.[f64].list $env?.[String]?.[f64].list() $env?.[String]?.[f64].ok $env?.[String]?.[f64].str $env?.[String]?.[f64]?.Bar $env?.[String]?.[f64]?.Bar() $env?.[String]?.[f64]?.[f64] $env?.[String]?.[f64]?.[foo] $env?.[String]?.[f64]?.[greet] $env?.[String]?.[f64]?.[i] $env?.[String]?.[f64]?.[str] $env?.[String]?.[f64]?.array() $env?.[String]?.[f64]?.greet $env?.[String]?.[f64]?.greet().foo $env?.[String]?.[f64]?.ok $env?.[String]?.[foo != nil] $env?.[String]?.[foo] $env?.[String]?.[foo].String $env?.[String]?.[foo].f64 $env?.[String]?.[foo].foo $env?.[String]?.[foo].i $env?.[String]?.[foo].str.add?.[i] $env?.[String]?.[foo]?.String $env?.[String]?.[foo]?.[foo] $env?.[String]?.[foo]?.[ok] $env?.[String]?.[foo]?.[ok]?.[f64] $env?.[String]?.[foo]?.[str] $env?.[String]?.[foo]?.add $env?.[String]?.[foo]?.f64() $env?.[String]?.[foo]?.foo $env?.[String]?.[greet] $env?.[String]?.[greet].String $env?.[String]?.[greet].array $env?.[String]?.[greet].str $env?.[String]?.[greet]?.Bar $env?.[String]?.[greet]?.[greet] $env?.[String]?.[greet]?.[ok] $env?.[String]?.[greet]?.foo $env?.[String]?.[greet]?.i $env?.[String]?.[greet]?.list(foobar) $env?.[String]?.[greet]?.ok $env?.[String]?.[greet]?.str $env?.[String]?.[i | mean(1.0)] $env?.[String]?.[i] $env?.[String]?.[i].Bar $env?.[String]?.[i].add({foo: str}) $env?.[String]?.[i].f64 $env?.[String]?.[i].foo $env?.[String]?.[i].i $env?.[String]?.[i].list $env?.[String]?.[i].ok $env?.[String]?.[i]?.[add] $env?.[String]?.[i]?.[array] $env?.[String]?.[i]?.[foo] $env?.[String]?.[i]?.[greet] $env?.[String]?.[i]?.array $env?.[String]?.[i]?.greet $env?.[String]?.[i]?.ok $env?.[String]?.[list] $env?.[String]?.[list].array $env?.[String]?.[list].array() $env?.[String]?.[list].foobar $env?.[String]?.[list].greet $env?.[String]?.[list].i $env?.[String]?.[list].ok $env?.[String]?.[list].str $env?.[String]?.[list]?.String $env?.[String]?.[list]?.String() $env?.[String]?.[list]?.[add] $env?.[String]?.[list]?.[i] $env?.[String]?.[list]?.array() $env?.[String]?.[list]?.f64 $env?.[String]?.[list]?.greet $env?.[String]?.[list]?.ok $env?.[String]?.[nil ?? array] $env?.[String]?.[ok and ok] $env?.[String]?.[ok not in $env] $env?.[String]?.[ok] $env?.[String]?.[ok].add $env?.[String]?.[ok].add?.array $env?.[String]?.[ok].f64 $env?.[String]?.[ok].ok $env?.[String]?.[ok]?.Bar $env?.[String]?.[ok]?.[f64] $env?.[String]?.[ok]?.[list] $env?.[String]?.[ok]?.greet $env?.[String]?.[ok]?.i $env?.[String]?.[str matches str] $env?.[String]?.[str not endsWith $env] $env?.[String]?.[str] $env?.[String]?.[str] != f64 $env?.[String]?.[str].array $env?.[String]?.[str].f64 $env?.[String]?.[str].i.add $env?.[String]?.[str]?.Bar $env?.[String]?.[str]?.String $env?.[String]?.[str]?.[f64] $env?.[String]?.[str]?.[i] $env?.[String]?.[str]?.[ok] $env?.[String]?.[str]?.add $env?.[String]?.[str]?.array $env?.[String]?.[str]?.foo $env?.[String]?.add $env?.[String]?.add($env) $env?.[String]?.add() $env?.[String]?.add()?.[foo] $env?.[String]?.add()?.f64() $env?.[String]?.add()?.greet $env?.[String]?.add(1) $env?.[String]?.add(1.0, foobar) $env?.[String]?.add(foobar) $env?.[String]?.add(i == true) $env?.[String]?.add(str) $env?.[String]?.add.Bar $env?.[String]?.add.String $env?.[String]?.add.array() $env?.[String]?.add.greet $env?.[String]?.add.i $env?.[String]?.add.list() $env?.[String]?.add?.Bar $env?.[String]?.add?.String $env?.[String]?.add?.[add] $env?.[String]?.add?.[foo] $env?.[String]?.add?.[greet] $env?.[String]?.add?.[list] $env?.[String]?.add?.array $env?.[String]?.add?.f64 $env?.[String]?.add?.foo $env?.[String]?.add?.greet $env?.[String]?.add?.greet() $env?.[String]?.add?.ok() $env?.[String]?.all(ok) $env?.[String]?.any(foobar, ok) $env?.[String]?.array $env?.[String]?.array() $env?.[String]?.array().array $env?.[String]?.array()?.[foo] $env?.[String]?.array()?.f64(list) $env?.[String]?.array(Bar?.foo()) $env?.[String]?.array(String) $env?.[String]?.array(add) $env?.[String]?.array(f64) $env?.[String]?.array(foo) $env?.[String]?.array(foobar not startsWith foo) $env?.[String]?.array(foobar) $env?.[String]?.array(foobar?.[String].add) $env?.[String]?.array(i) $env?.[String]?.array(str) $env?.[String]?.array(toJSON(foobar)) $env?.[String]?.array.String $env?.[String]?.array.array(String, foo) $env?.[String]?.array.f64 $env?.[String]?.array.i $env?.[String]?.array.i() $env?.[String]?.array.list(foobar) $env?.[String]?.array.list.array $env?.[String]?.array.ok $env?.[String]?.array?.Bar $env?.[String]?.array?.Bar(list) $env?.[String]?.array?.[greet] $env?.[String]?.array?.f64 $env?.[String]?.array?.foo $env?.[String]?.array?.greet $env?.[String]?.array?.i $env?.[String]?.array?.list(i) $env?.[String]?.bitor(foobar, 0) $env?.[String]?.bitshl(foobar) $env?.[String]?.bitshr(nil) $env?.[String]?.bitushr(foobar) $env?.[String]?.ceil(nil) $env?.[String]?.concat(1.0) $env?.[String]?.duration(foobar) $env?.[String]?.f64 $env?.[String]?.f64() $env?.[String]?.f64().Bar $env?.[String]?.f64().Bar() $env?.[String]?.f64()?.f64 $env?.[String]?.f64(String?.[array]) $env?.[String]?.f64(foo.Bar) $env?.[String]?.f64(foobar) $env?.[String]?.f64(min(foobar)) $env?.[String]?.f64.Bar $env?.[String]?.f64.Bar() $env?.[String]?.f64.add() $env?.[String]?.f64.greet.str $env?.[String]?.f64.i $env?.[String]?.f64.ok $env?.[String]?.f64?.String $env?.[String]?.f64?.[add] $env?.[String]?.f64?.[ok]?.str $env?.[String]?.f64?.foo() $env?.[String]?.f64?.greet() $env?.[String]?.f64?.i $env?.[String]?.f64?.ok() $env?.[String]?.f64?.str $env?.[String]?.false?.str $env?.[String]?.filter(1) $env?.[String]?.find(foobar) $env?.[String]?.findLastIndex(add, f64) $env?.[String]?.foo $env?.[String]?.foo() $env?.[String]?.foo().foo $env?.[String]?.foo().list $env?.[String]?.foo()?.foo $env?.[String]?.foo()?.str $env?.[String]?.foo(f64, foobar) $env?.[String]?.foo(foobar) $env?.[String]?.foo(true) $env?.[String]?.foo.String $env?.[String]?.foo.add $env?.[String]?.foo.add() $env?.[String]?.foo.add?.greet $env?.[String]?.foo.array() $env?.[String]?.foo.f64 $env?.[String]?.foo.foo $env?.[String]?.foo.greet $env?.[String]?.foo.i $env?.[String]?.foo.ok $env?.[String]?.foo.str $env?.[String]?.foo?.Bar $env?.[String]?.foo?.String $env?.[String]?.foo?.[add] $env?.[String]?.foo?.[array] $env?.[String]?.foo?.[f64] $env?.[String]?.foo?.[foo] $env?.[String]?.foo?.add $env?.[String]?.foo?.array $env?.[String]?.foo?.greet $env?.[String]?.foo?.i $env?.[String]?.foo?.list $env?.[String]?.foo?.str $env?.[String]?.foo?.str() $env?.[String]?.foobar $env?.[String]?.foobar.Bar $env?.[String]?.foobar.array $env?.[String]?.foobar.f64 $env?.[String]?.foobar.foo $env?.[String]?.foobar.i $env?.[String]?.foobar.list(foobar, add) $env?.[String]?.foobar.str $env?.[String]?.foobar.str() $env?.[String]?.foobar?.Bar $env?.[String]?.foobar?.[foo] $env?.[String]?.foobar?.[i] $env?.[String]?.foobar?.[list] $env?.[String]?.foobar?.[ok] $env?.[String]?.foobar?.array $env?.[String]?.foobar?.foo $env?.[String]?.foobar?.i $env?.[String]?.foobar?.i() $env?.[String]?.foobar?.ok() $env?.[String]?.fromJSON(foobar) $env?.[String]?.fromPairs(false) $env?.[String]?.get(String) $env?.[String]?.get(str) $env?.[String]?.greet $env?.[String]?.greet != str $env?.[String]?.greet() $env?.[String]?.greet().Bar $env?.[String]?.greet()?.[list] $env?.[String]?.greet()?.[str] $env?.[String]?.greet(add) $env?.[String]?.greet(foobar != str) $env?.[String]?.greet(foobar) $env?.[String]?.greet(greet) $env?.[String]?.greet.Bar $env?.[String]?.greet.add $env?.[String]?.greet.array() $env?.[String]?.greet.f64 $env?.[String]?.greet.foo $env?.[String]?.greet.foobar $env?.[String]?.greet.i $env?.[String]?.greet.i() $env?.[String]?.greet.list $env?.[String]?.greet.ok $env?.[String]?.greet.ok() $env?.[String]?.greet?.Bar $env?.[String]?.greet?.[array] $env?.[String]?.greet?.[list] $env?.[String]?.greet?.[str] $env?.[String]?.greet?.array $env?.[String]?.greet?.f64 $env?.[String]?.greet?.foo $env?.[String]?.greet?.greet() $env?.[String]?.greet?.list.str $env?.[String]?.groupBy(1.0) $env?.[String]?.groupBy(f64, foobar, array)?.[ok] $env?.[String]?.groupBy(foobar) $env?.[String]?.groupBy(str) $env?.[String]?.hasPrefix(nil)?.String $env?.[String]?.i $env?.[String]?.i in array $env?.[String]?.i() $env?.[String]?.i().ok $env?.[String]?.i()?.[add] $env?.[String]?.i()?.[array] $env?.[String]?.i()?.[greet] $env?.[String]?.i()?.f64 $env?.[String]?.i(add) $env?.[String]?.i(array) $env?.[String]?.i(foo) $env?.[String]?.i(foobar ?? array) $env?.[String]?.i(foobar) $env?.[String]?.i(i) $env?.[String]?.i(ok) $env?.[String]?.i(str) $env?.[String]?.i(true) $env?.[String]?.i.Bar $env?.[String]?.i.String $env?.[String]?.i.f64(f64) $env?.[String]?.i.greet $env?.[String]?.i.list $env?.[String]?.i?.[array] $env?.[String]?.i?.[greet] $env?.[String]?.i?.[list] $env?.[String]?.i?.[ok] $env?.[String]?.i?.[str] $env?.[String]?.i?.add $env?.[String]?.i?.array $env?.[String]?.i?.f64?.String $env?.[String]?.i?.foo $env?.[String]?.i?.foo() $env?.[String]?.i?.greet $env?.[String]?.i?.list $env?.[String]?.i?.ok.f64 $env?.[String]?.int(foo) $env?.[String]?.lastIndexOf(true, foobar, foo) $env?.[String]?.len(false) $env?.[String]?.list $env?.[String]?.list($env) $env?.[String]?.list() $env?.[String]?.list().i $env?.[String]?.list(0) $env?.[String]?.list(1.0) $env?.[String]?.list(Bar) $env?.[String]?.list(foo).f64 $env?.[String]?.list(foobar) $env?.[String]?.list(foobar).greet $env?.[String]?.list(greet) $env?.[String]?.list(nil in foobar or foobar) $env?.[String]?.list(ok) $env?.[String]?.list(true, true) $env?.[String]?.list.add() $env?.[String]?.list.foo $env?.[String]?.list.foo($env) $env?.[String]?.list.list $env?.[String]?.list?.String() $env?.[String]?.list?.[array] $env?.[String]?.list?.[foo] $env?.[String]?.list?.[greet] $env?.[String]?.list?.[list]?.Bar $env?.[String]?.list?.[ok] $env?.[String]?.list?.add?.list $env?.[String]?.list?.array $env?.[String]?.list?.foo(0) $env?.[String]?.list?.foobar $env?.[String]?.list?.i $env?.[String]?.list?.list $env?.[String]?.map($env) $env?.[String]?.map($env, foo).add $env?.[String]?.map(String, foobar) $env?.[String]?.nil.String $env?.[String]?.nil.list $env?.[String]?.nil?.f64 $env?.[String]?.nil?.ok() $env?.[String]?.none($env) $env?.[String]?.none(array) $env?.[String]?.none(foobar) $env?.[String]?.not $env?.[String]?.ok $env?.[String]?.ok() $env?.[String]?.ok().add $env?.[String]?.ok()?.[add] $env?.[String]?.ok()?.list $env?.[String]?.ok()?.str() == f64 $env?.[String]?.ok(array) $env?.[String]?.ok(f64, foobar) $env?.[String]?.ok(foo contains foobar) $env?.[String]?.ok(foo) $env?.[String]?.ok(foobar) $env?.[String]?.ok(foobar?.[1.0]) $env?.[String]?.ok(foobar?.[list]) $env?.[String]?.ok(nil startsWith ok) $env?.[String]?.ok(toJSON(foo)).f64 $env?.[String]?.ok.add $env?.[String]?.ok.f64 $env?.[String]?.ok.foo $env?.[String]?.ok.i $env?.[String]?.ok.ok $env?.[String]?.ok.str $env?.[String]?.ok?.[array] $env?.[String]?.ok?.[f64] $env?.[String]?.ok?.[f64].list $env?.[String]?.ok?.[foo] $env?.[String]?.ok?.[list] $env?.[String]?.ok?.[ok] $env?.[String]?.ok?.add $env?.[String]?.ok?.f64 $env?.[String]?.ok?.foo $env?.[String]?.ok?.ok $env?.[String]?.one($env) $env?.[String]?.one(array) $env?.[String]?.one(foobar)?.[f64] $env?.[String]?.reduce(1.0) $env?.[String]?.reduce(foobar) $env?.[String]?.sortBy(add) $env?.[String]?.splitAfter(true) $env?.[String]?.str $env?.[String]?.str not endsWith $env $env?.[String]?.str not startsWith str $env?.[String]?.str() $env?.[String]?.str().list $env?.[String]?.str().list?.[list] $env?.[String]?.str()?.array $env?.[String]?.str(add) $env?.[String]?.str(foo) $env?.[String]?.str(foobar) $env?.[String]?.str(foobar?.array) $env?.[String]?.str.String $env?.[String]?.str.add $env?.[String]?.str.array $env?.[String]?.str.foo $env?.[String]?.str.ok $env?.[String]?.str?.Bar $env?.[String]?.str?.String $env?.[String]?.str?.[add] $env?.[String]?.str?.[i] $env?.[String]?.str?.add $env?.[String]?.str?.f64() $env?.[String]?.str?.f64(false)?.greet $env?.[String]?.str?.list() $env?.[String]?.str?.str $env?.[String]?.string(foobar, foobar) $env?.[String]?.sum(String, foobar) $env?.[String]?.sum(add) $env?.[String]?.sum(foobar, foobar) $env?.[String]?.take(String)?.str $env?.[String]?.trimPrefix(add) $env?.[String]?.trimPrefix(foobar) $env?.[String]?.true not in array $env?.[String]?.true.foo $env?.[String]?.true?.[1] $env?.[String]?.true?.foobar $env?.[add] != 1.0 && false $env?.[add] * f64 && false $env?.[add] == nil and false $env?.[f64] == list || true $env?.[false] and not true $env?.[foo] != 1.0 || true $env?.[foo] endsWith $env && false $env?.[foobar] != $env.i $env?.[foobar] != $env.list $env?.[foobar] != f64 $env?.[foobar] != foo $env?.[foobar] != greet $env?.[foobar] != i $env?.[foobar] != i ? true : $env $env?.[foobar] != list $env?.[foobar] != str $env?.[foobar] == add $env?.[foobar] == array $env?.[foobar] == f64 $env?.[foobar] == foo $env?.[foobar] == greet $env?.[foobar] == list $env?.[foobar] == list != $env $env?.[foobar] == ok $env?.[foobar] ?? f64 $env?.[foobar] ?? greet $env?.[foobar] ?? ok $env?.[foobar] contains str $env?.[foobar] endsWith $env?.[str] $env?.[foobar] endsWith str $env?.[foobar] in $env?.[String] $env?.[foobar] in list $env?.[foobar] in reverse(array) $env?.[foobar] matches str $env?.[foobar] not contains str $env?.[foobar] not endsWith str $env?.[foobar] not in array $env?.[foobar] not in list $env?.[foobar] not matches str $env?.[foobar] not startsWith foo?.String() $env?.[foobar] not startsWith str $env?.[foobar] not startsWith trim(str) $env?.[foobar] startsWith $env or $env $env?.[foobar] startsWith $env?.[str] $env?.[foobar] | get($env) $env?.[foobar] | get(foo) $env?.[foobar]?.$env == nil $env?.[foobar]?.$env.greet $env?.[foobar]?.Bar $env?.[foobar]?.Bar() $env?.[foobar]?.Bar().str $env?.[foobar]?.Bar()?.foobar $env?.[foobar]?.Bar(add) $env?.[foobar]?.Bar(foobar) $env?.[foobar]?.Bar(list) $env?.[foobar]?.Bar.foo() $env?.[foobar]?.Bar.foobar $env?.[foobar]?.Bar.i $env?.[foobar]?.Bar.str(foobar) $env?.[foobar]?.Bar?.[f64] $env?.[foobar]?.Bar?.[i] $env?.[foobar]?.Bar?.[str] $env?.[foobar]?.Bar?.[str]?.array $env?.[foobar]?.Bar?.f64 $env?.[foobar]?.Bar?.foo $env?.[foobar]?.String $env?.[foobar]?.String() $env?.[foobar]?.String(Bar) $env?.[foobar]?.String(add).String $env?.[foobar]?.String(foobar) $env?.[foobar]?.String(foobar?.f64, Bar?.[foobar]) $env?.[foobar]?.String(nil == foobar) $env?.[foobar]?.String.Bar $env?.[foobar]?.String.ok $env?.[foobar]?.String.str $env?.[foobar]?.String?.[i] $env?.[foobar]?.String?.[str] $env?.[foobar]?.String?.[str]?.[f64]?.ok $env?.[foobar]?.String?.array $env?.[foobar]?.String?.i $env?.[foobar]?.String?.list $env?.[foobar]?.String?.ok() $env?.[foobar]?.[!false] $env?.[foobar]?.[$env | groupBy(i)] $env?.[foobar]?.[$env[nil:]] $env?.[foobar]?.[add] $env?.[foobar]?.[add].f64 $env?.[foobar]?.[add].greet $env?.[foobar]?.[add].i $env?.[foobar]?.[add]?.Bar $env?.[foobar]?.[add]?.[add] $env?.[foobar]?.[add]?.[foo] $env?.[foobar]?.[add]?.[greet] $env?.[foobar]?.[add]?.f64 $env?.[foobar]?.[array] $env?.[foobar]?.[array].i $env?.[foobar]?.[array]?.Bar $env?.[foobar]?.[array]?.Bar() $env?.[foobar]?.[array]?.[i] $env?.[foobar]?.[array]?.[ok] $env?.[foobar]?.[array]?.add $env?.[foobar]?.[array]?.f64 $env?.[foobar]?.[array]?.f64() $env?.[foobar]?.[array]?.foo $env?.[foobar]?.[array]?.list()?.[add] $env?.[foobar]?.[f64 ^ 1.0] $env?.[foobar]?.[f64] $env?.[foobar]?.[f64].array $env?.[foobar]?.[f64].f64 $env?.[foobar]?.[f64].f64() $env?.[foobar]?.[f64].greet $env?.[foobar]?.[f64].ok() $env?.[foobar]?.[f64]?.[i] $env?.[foobar]?.[f64]?.[str] $env?.[foobar]?.[f64]?.greet $env?.[foobar]?.[foo] $env?.[foobar]?.[foo].Bar $env?.[foobar]?.[foo].String $env?.[foobar]?.[foo].String() $env?.[foobar]?.[foo].add() $env?.[foobar]?.[foo]?.[str] $env?.[foobar]?.[foo]?.i $env?.[foobar]?.[greet ?? 1.0] $env?.[foobar]?.[greet] $env?.[foobar]?.[greet].array.array $env?.[foobar]?.[greet].f64 $env?.[foobar]?.[greet]?.[add] $env?.[foobar]?.[greet]?.[i].array $env?.[foobar]?.[greet]?.[ok] $env?.[foobar]?.[greet]?.str $env?.[foobar]?.[i] $env?.[foobar]?.[i].Bar $env?.[foobar]?.[i].array $env?.[foobar]?.[i].greet $env?.[foobar]?.[i].str $env?.[foobar]?.[i]?.[list] $env?.[foobar]?.[i]?.[ok] $env?.[foobar]?.[i]?.ok $env?.[foobar]?.[list] $env?.[foobar]?.[list].f64() $env?.[foobar]?.[list].foo $env?.[foobar]?.[list].ok $env?.[foobar]?.[list]?.[f64] $env?.[foobar]?.[list]?.[str] $env?.[foobar]?.[list]?.f64() $env?.[foobar]?.[list]?.ok $env?.[foobar]?.[ok] $env?.[foobar]?.[ok].Bar $env?.[foobar]?.[ok].list $env?.[foobar]?.[ok].str $env?.[foobar]?.[ok]?.[add] $env?.[foobar]?.[ok]?.[f64] $env?.[foobar]?.[ok]?.f64 $env?.[foobar]?.[ok]?.ok $env?.[foobar]?.[sortBy($env, f64)] $env?.[foobar]?.[str] $env?.[foobar]?.[str].Bar $env?.[foobar]?.[str].foo?.[add] $env?.[foobar]?.[str].i $env?.[foobar]?.[str]?.[f64] $env?.[foobar]?.add $env?.[foobar]?.add() $env?.[foobar]?.add()?.[array] $env?.[foobar]?.add(foobar) $env?.[foobar]?.add(toJSON(foo), Bar) $env?.[foobar]?.add.add() $env?.[foobar]?.add.greet(foo) $env?.[foobar]?.add?.[add] $env?.[foobar]?.add?.array() $env?.[foobar]?.add?.greet $env?.[foobar]?.add?.i $env?.[foobar]?.all(foobar, greet, $env) $env?.[foobar]?.any(1, foobar) $env?.[foobar]?.any(f64, nil) $env?.[foobar]?.any(i).f64 $env?.[foobar]?.array $env?.[foobar]?.array contains str $env?.[foobar]?.array() $env?.[foobar]?.array(foobar) $env?.[foobar]?.array.Bar $env?.[foobar]?.array.f64 $env?.[foobar]?.array.f64() $env?.[foobar]?.array?.[add] $env?.[foobar]?.array?.[f64] $env?.[foobar]?.array?.[i] $env?.[foobar]?.array?.add() $env?.[foobar]?.array?.i $env?.[foobar]?.bitand(false) $env?.[foobar]?.count(0) $env?.[foobar]?.f64 $env?.[foobar]?.f64() $env?.[foobar]?.f64()?.[ok] $env?.[foobar]?.f64()?.array $env?.[foobar]?.f64(String) $env?.[foobar]?.f64(foobar endsWith String)?.[greet] $env?.[foobar]?.f64(foobar) $env?.[foobar]?.f64(i) $env?.[foobar]?.f64.ok $env?.[foobar]?.f64?.Bar $env?.[foobar]?.f64?.[i] $env?.[foobar]?.f64?.list() $env?.[foobar]?.f64?.ok $env?.[foobar]?.false?.[add] $env?.[foobar]?.filter(foo) $env?.[foobar]?.find(foobar, 1) $env?.[foobar]?.findLast(foo).String() $env?.[foobar]?.foo $env?.[foobar]?.foo() $env?.[foobar]?.foo()?.array $env?.[foobar]?.foo()?.f64 $env?.[foobar]?.foo(Bar) $env?.[foobar]?.foo(foobar) $env?.[foobar]?.foo(foobar, foobar) $env?.[foobar]?.foo.foobar $env?.[foobar]?.foo?.String $env?.[foobar]?.foo?.[array] $env?.[foobar]?.foo?.[foo] $env?.[foobar]?.foo?.[i] $env?.[foobar]?.foo?.foo $env?.[foobar]?.foo?.foo?.array $env?.[foobar]?.foobar $env?.[foobar]?.foobar not in $env $env?.[foobar]?.foobar.str $env?.[foobar]?.foobar?.[foo] $env?.[foobar]?.foobar?.greet $env?.[foobar]?.foobar?.ok(list, foobar) $env?.[foobar]?.foobar?.str $env?.[foobar]?.greet $env?.[foobar]?.greet == foo $env?.[foobar]?.greet() $env?.[foobar]?.greet()?.String $env?.[foobar]?.greet(Bar) $env?.[foobar]?.greet(String) $env?.[foobar]?.greet(foobar) $env?.[foobar]?.greet(foobar, foo) $env?.[foobar]?.greet(foobar?.list(), array) $env?.[foobar]?.greet(greet) $env?.[foobar]?.greet(list, Bar) $env?.[foobar]?.greet.foo $env?.[foobar]?.greet.i $env?.[foobar]?.greet?.add $env?.[foobar]?.greet?.add(nil) $env?.[foobar]?.greet?.array $env?.[foobar]?.greet?.ok $env?.[foobar]?.i $env?.[foobar]?.i() $env?.[foobar]?.i()?.greet $env?.[foobar]?.i(Bar) $env?.[foobar]?.i(foo) $env?.[foobar]?.i(foobar) $env?.[foobar]?.i.Bar $env?.[foobar]?.i.String $env?.[foobar]?.i.array $env?.[foobar]?.i.foo $env?.[foobar]?.i?.[array] $env?.[foobar]?.i?.[foo] $env?.[foobar]?.i?.[greet] $env?.[foobar]?.i?.f64 $env?.[foobar]?.i?.ok $env?.[foobar]?.join(greet, nil) $env?.[foobar]?.lastIndexOf(nil, foobar) $env?.[foobar]?.list $env?.[foobar]?.list() $env?.[foobar]?.list(1) $env?.[foobar]?.list(f64) $env?.[foobar]?.list(foobar) $env?.[foobar]?.list(str) $env?.[foobar]?.list.i $env?.[foobar]?.list.i() $env?.[foobar]?.list.list $env?.[foobar]?.list.ok(foobar) $env?.[foobar]?.list?.[array] $env?.[foobar]?.list?.[i] $env?.[foobar]?.list?.[list] $env?.[foobar]?.list?.f64 $env?.[foobar]?.list?.ok() $env?.[foobar]?.max(1, ok) $env?.[foobar]?.max(foo) $env?.[foobar]?.nil?.[foo] $env?.[foobar]?.nil?.str(foo, foobar) $env?.[foobar]?.none(foobar) $env?.[foobar]?.none(nil, foobar) $env?.[foobar]?.not .String $env?.[foobar]?.now(1) $env?.[foobar]?.ok $env?.[foobar]?.ok() $env?.[foobar]?.ok()?.i $env?.[foobar]?.ok(Bar?.[greet])?.greet $env?.[foobar]?.ok(foo not startsWith foobar) $env?.[foobar]?.ok(foo) $env?.[foobar]?.ok(list) $env?.[foobar]?.ok.add $env?.[foobar]?.ok.add() $env?.[foobar]?.ok.i $env?.[foobar]?.ok?.[greet] $env?.[foobar]?.ok?.greet() $env?.[foobar]?.ok?.i $env?.[foobar]?.reduce(nil, 1.0) $env?.[foobar]?.sortBy(foo, 0, foobar) $env?.[foobar]?.str $env?.[foobar]?.str($env) $env?.[foobar]?.str() $env?.[foobar]?.str()?.str $env?.[foobar]?.str(foobar) $env?.[foobar]?.str(foobar?.greet(nil)) $env?.[foobar]?.str(i) $env?.[foobar]?.str.ok $env?.[foobar]?.str?.String $env?.[foobar]?.str?.[f64] $env?.[foobar]?.str?.[list] $env?.[foobar]?.str?.foo $env?.[foobar]?.str?.i $env?.[foobar]?.str?.i() $env?.[foobar]?.str?.list $env?.[foobar]?.sum($env) $env?.[foobar]?.trimSuffix(f64, foobar) $env?.[foobar]?.true?.ok $env?.[greet]?.foobar or true $env?.[i] and !true $env?.[i].i and false $env?.[list] contains str && false $env?.[list] || false or true $env?.[nil] != array $env?.[nil] != ok $env?.[nil] == array?.[0] $env?.[nil] == ok $env?.[nil] == str $env?.[nil] ?? add $env?.[nil] ?? map($env, foo) $env?.[nil] endsWith str $env?.[nil] in $env?.[String] $env?.[nil] not endsWith str $env?.[nil] not startsWith str $env?.[nil] | get(nil) $env?.[nil]?.Bar $env?.[nil]?.Bar() $env?.[nil]?.Bar?.[add] $env?.[nil]?.Bar?.[str] $env?.[nil]?.String $env?.[nil]?.String() $env?.[nil]?.String(Bar?.[str]) $env?.[nil]?.String(f64) $env?.[nil]?.String(false ?? foobar) $env?.[nil]?.String.greet $env?.[nil]?.String?.[add] $env?.[nil]?.String?.[list] $env?.[nil]?.[add] $env?.[nil]?.[add].Bar $env?.[nil]?.[add]?.[add] $env?.[nil]?.[add]?.array $env?.[nil]?.[array] $env?.[nil]?.[array].count(i) $env?.[nil]?.[array]?.f64() $env?.[nil]?.[f64] $env?.[nil]?.[f64].list $env?.[nil]?.[f64]?.Bar $env?.[nil]?.[foo] $env?.[nil]?.[foo]?.i() $env?.[nil]?.[greet] $env?.[nil]?.[greet]?.Bar $env?.[nil]?.[greet]?.array() $env?.[nil]?.[i] $env?.[nil]?.[list] $env?.[nil]?.[ok] $env?.[nil]?.[str] $env?.[nil]?.[str]?.[array] $env?.[nil]?.[{foo: 1}] $env?.[nil]?.add $env?.[nil]?.add() $env?.[nil]?.array $env?.[nil]?.array() $env?.[nil]?.array(add) $env?.[nil]?.array(list) $env?.[nil]?.array?.[foo] $env?.[nil]?.array?.add $env?.[nil]?.f64 $env?.[nil]?.f64() $env?.[nil]?.f64.add $env?.[nil]?.f64.f64 $env?.[nil]?.f64.foo() $env?.[nil]?.f64.i $env?.[nil]?.flatten(0) $env?.[nil]?.foo $env?.[nil]?.foo() $env?.[nil]?.foo?.String $env?.[nil]?.foobar $env?.[nil]?.foobar.String() $env?.[nil]?.foobar.str $env?.[nil]?.foobar?.i $env?.[nil]?.greet $env?.[nil]?.greet() $env?.[nil]?.greet(foobar) $env?.[nil]?.greet.f64 $env?.[nil]?.greet?.f64 $env?.[nil]?.i $env?.[nil]?.i() $env?.[nil]?.i(true or $env >= ok) $env?.[nil]?.i?.f64 $env?.[nil]?.list $env?.[nil]?.list($env?.foo) $env?.[nil]?.list() $env?.[nil]?.list?.array $env?.[nil]?.list?.f64 $env?.[nil]?.list?.i $env?.[nil]?.map(foo) $env?.[nil]?.ok $env?.[nil]?.ok() $env?.[nil]?.ok(f64) $env?.[nil]?.ok?.[str] $env?.[nil]?.ok?.f64 $env?.[nil]?.str $env?.[nil]?.str() $env?.[nil]?.str(String) $env?.[nil]?.str(foobar) $env?.[nil]?.str(str)?.[f64] $env?.[nil]?.str?.greet() $env?.[ok] - 1 or true $env?.[str] != 1 and false $env?.[str] != add $env?.[str] != add != $env $env?.[str] != array $env?.[str] != f64 $env?.[str] != foo $env?.[str] != foo.Bar $env?.[str] != foo?.String() $env?.[str] != greet $env?.[str] != i $env?.[str] != list $env?.[str] != ok $env?.[str] != str $env?.[str] != string(1.0) $env?.[str] != type(str) $env?.[str] + str $env?.[str] < foo?.Bar $env?.[str] < foo?.String() $env?.[str] < str $env?.[str] <= $env.str $env?.[str] <= str $env?.[str] == 1.0 == $env $env?.[str] == add $env?.[str] == array $env?.[str] == f64 $env?.[str] == first($env) $env?.[str] == foo $env?.[str] == greet $env?.[str] == i $env?.[str] == ok $env?.[str] == str $env?.[str] > str $env?.[str] >= str $env?.[str] ?? $env[:foobar] $env?.[str] ?? add $env?.[str] ?? array $env?.[str] ?? foo $env?.[str] ?? greet $env?.[str] ?? i $env?.[str] ?? list $env?.[str] ?? ok $env?.[str] ?? str $env?.[str] contains foo?.Bar $env?.[str] contains str $env?.[str] contains type(greet) $env?.[str] endsWith $env?.str $env?.[str] endsWith str $env?.[str] in $env.foo $env?.[str] in $env.list $env?.[str] in array $env?.[str] in list $env?.[str] matches foo?.Bar $env?.[str] matches str $env?.[str] not contains str $env?.[str] not endsWith str $env?.[str] not in $env == ok $env?.[str] not in $env.list $env?.[str] not in $env?.[Bar] $env?.[str] not in $env?.array $env?.[str] not in array $env?.[str] not in list $env?.[str] not in {foo: 1} $env?.[str] not matches $env?.[Bar] $env?.[str] not matches foo?.String() $env?.[str] not matches str $env?.[str] not startsWith str $env?.[str] startsWith $env?.[String] $env?.[str] startsWith foo?.Bar $env?.[str] startsWith str $env?.[str] | all(false) $env?.[str] | all(ok) $env?.[str] | all(true) $env?.[str] | any(any(list, true)) $env?.[str] | any(false) $env?.[str] | any(ok) $env?.[str] | any(true) $env?.[str] | count(false) $env?.[str] | count(i != 0) $env?.[str] | count(ok) $env?.[str] | count(true) $env?.[str] | date(str) $env?.[str] | filter(false) $env?.[str] | filter(true != false) $env?.[str] | filter(true) $env?.[str] | find(0 >= #) $env?.[str] | find(false) $env?.[str] | find(ok) $env?.[str] | find(true) $env?.[str] | findIndex(1 != 0) $env?.[str] | findIndex(add != #) $env?.[str] | findIndex(false) $env?.[str] | findIndex(ok) $env?.[str] | findIndex(true) $env?.[str] | findLast(false) $env?.[str] | findLast(ok) $env?.[str] | findLast(true) $env?.[str] | findLastIndex(false) $env?.[str] | findLastIndex(true) $env?.[str] | greet() $env?.[str] | groupBy(#) $env?.[str] | groupBy(0) $env?.[str] | groupBy(1) $env?.[str] | groupBy(1.0) $env?.[str] | groupBy(f64) $env?.[str] | groupBy(false) $env?.[str] | groupBy(foo) $env?.[str] | groupBy(i) $env?.[str] | groupBy(ok) $env?.[str] | groupBy(str) $env?.[str] | groupBy(true) $env?.[str] | hasPrefix(str) $env?.[str] | indexOf(str) $env?.[str] | map(#) $env?.[str] | map($env) $env?.[str] | map(0) $env?.[str] | map(1) $env?.[str] | map(1.0) $env?.[str] | map(add) $env?.[str] | map(false) $env?.[str] | map(foo) $env?.[str] | map(greet) $env?.[str] | map(i) $env?.[str] | map(list) $env?.[str] | map(ok) $env?.[str] | map(str) $env?.[str] | map(true) $env?.[str] | none(false) $env?.[str] | none(ok) $env?.[str] | none(true) $env?.[str] | one(false) $env?.[str] | one(ok) $env?.[str] | one(true) $env?.[str] | reduce(#) $env?.[str] | reduce(#, add) $env?.[str] | reduce(#, array) $env?.[str] | reduce(#, false) $env?.[str] | reduce(#, ok) $env?.[str] | reduce(#, str) $env?.[str] | reduce(#acc) $env?.[str] | reduce($env) $env?.[str] | reduce($env, ok) $env?.[str] | reduce($env, true) $env?.[str] | reduce(0) $env?.[str] | reduce(0, nil) $env?.[str] | reduce(1, 1.0) $env?.[str] | reduce(1.0) $env?.[str] | reduce(1.0, $env) $env?.[str] | reduce(1.0, nil) $env?.[str] | reduce(add) $env?.[str] | reduce(add, nil) $env?.[str] | reduce(array) $env?.[str] | reduce(f64) $env?.[str] | reduce(false) $env?.[str] | reduce(false, greet) $env?.[str] | reduce(foo) $env?.[str] | reduce(foo, true) $env?.[str] | reduce(greet) $env?.[str] | reduce(greet, add) $env?.[str] | reduce(greet, foo) $env?.[str] | reduce(i) $env?.[str] | reduce(list) $env?.[str] | reduce(list, true) $env?.[str] | reduce(ok) $env?.[str] | reduce(ok, $env) $env?.[str] | reduce(str) $env?.[str] | reduce(true) $env?.[str] | reduce(true, f64) $env?.[str] | repeat(1) $env?.[str] | sortBy(#) $env?.[str] | sortBy(0) $env?.[str] | sortBy(1) $env?.[str] | sortBy(1.0) $env?.[str] | sortBy(f64) $env?.[str] | sortBy(i) $env?.[str] | sortBy(str) $env?.[str] | sum(#) $env?.[str] | sum(1) $env?.[str] | sum(1.0) $env?.[str] | sum(f64) $env?.[str] | sum(i) $env?.[str] | trimSuffix(str) $env?.[str].Bar or true $env?.[str]?.[-1.0] $env?.[str]?.[f64] $env?.[str]?.[f64] * f64 $env?.[str]?.[i] $env?.[str][:-1] $env?.[str][:] $env?.[str][:f64] $env?.[str][:i] $env?.[str][array?.[f64]:] $env?.[str][f64:] $env?.add != 1.0 ?? 1 $env?.add != add $env?.add == $env || ok $env?.add == add $env?.add ?? $env.i $env?.add ?? add $env?.add ?? array $env?.add ?? f64 $env?.add ?? foo?.Bar $env?.add ?? greet $env?.add ?? i $env?.add ?? join($env) $env?.add ?? list $env?.add ?? ok $env?.add ?? reverse($env) $env?.add ?? str $env?.add ?? sum($env) $env?.add in $env?.Bar $env?.add not in $env?.[Bar] $env?.array != array $env?.array != array || $env $env?.array != list $env?.array == array $env?.array == list $env?.array ?? $env?.[add] $env?.array ?? ceil(1.0) $env?.array ?? f64 $env?.array ?? false | groupBy(foo) $env?.array ?? fromBase64(str) $env?.array ?? i $env?.array ?? list $env?.array ?? ok $env?.array ?? str $env?.array ?? true | map(add) $env?.array in $env?.[Bar] $env?.array in sort($env) $env?.array | all(false) $env?.array | all(ok) $env?.array | all(true) $env?.array | any(# == 0) $env?.array | any(false) $env?.array | any(ok) $env?.array | any(true) $env?.array | count(ok) $env?.array | count(true) $env?.array | filter(false) $env?.array | filter(ok) $env?.array | filter(true) $env?.array | find(false) $env?.array | find(ok) $env?.array | find(true) $env?.array | findIndex(ok) $env?.array | findIndex(true) $env?.array | findLast(false ?? nil) $env?.array | findLast(false) $env?.array | findLast(ok) $env?.array | findLast(true) $env?.array | findLastIndex(false) $env?.array | findLastIndex(ok) $env?.array | findLastIndex(true) $env?.array | get(1) $env?.array | groupBy(#) $env?.array | groupBy(0) $env?.array | groupBy(1) $env?.array | groupBy(1.0) $env?.array | groupBy(false) $env?.array | groupBy(foo) $env?.array | groupBy(mean(1)) $env?.array | groupBy(ok) $env?.array | groupBy(str) $env?.array | groupBy(true) $env?.array | map(#) $env?.array | map(#index) $env?.array | map($env) $env?.array | map(0) $env?.array | map(1) $env?.array | map(1.0) $env?.array | map(add) $env?.array | map(array) $env?.array | map(f64) $env?.array | map(false) $env?.array | map(foo) $env?.array | map(i) $env?.array | map(list) $env?.array | map(ok) $env?.array | map(str) $env?.array | map(true) $env?.array | mean(1) $env?.array | mean(1.0) $env?.array | mean(f64) $env?.array | min(array) $env?.array | min(i) $env?.array | none(false) $env?.array | none(ok) $env?.array | none(true) $env?.array | one(f64 != nil) $env?.array | one(false) $env?.array | one(ok) $env?.array | one(true) $env?.array | reduce(#) $env?.array | reduce(#, $env) $env?.array | reduce(#, 1) $env?.array | reduce(#, array) $env?.array | reduce(#, f64) $env?.array | reduce(#, foo) $env?.array | reduce(#, true) $env?.array | reduce(#acc) $env?.array | reduce(#index) $env?.array | reduce($env) $env?.array | reduce($env, $env) $env?.array | reduce($env, add) $env?.array | reduce($env, greet) $env?.array | reduce($env, nil) $env?.array | reduce(0) $env?.array | reduce(0, foo) $env?.array | reduce(1 == #) $env?.array | reduce(1) $env?.array | reduce(1, 1) $env?.array | reduce(1, list) $env?.array | reduce(1.0) $env?.array | reduce(1.0, array) $env?.array | reduce(add) $env?.array | reduce(add, 1.0) $env?.array | reduce(add, nil) $env?.array | reduce(array) $env?.array | reduce(f64) $env?.array | reduce(false) $env?.array | reduce(foo) $env?.array | reduce(foo, foo) $env?.array | reduce(greet, str) $env?.array | reduce(i) $env?.array | reduce(i, 1.0) $env?.array | reduce(ok) $env?.array | reduce(ok, true) $env?.array | reduce(str) $env?.array | reduce(true) $env?.array | reduce(true, 0) $env?.array | sortBy(#) $env?.array | sortBy(0) $env?.array | sortBy(1) $env?.array | sortBy(1.0) $env?.array | sortBy(f64) $env?.array | sortBy(i) $env?.array | sortBy(str) $env?.array | sum(#) $env?.array | sum(1) $env?.array | sum(1.0) $env?.array | sum(f64) $env?.array | sum(i) $env?.array | take(0) $env?.array; i $env?.array?.[-0] $env?.array?.[-1] $env?.array?.[first(array)] $env?.array?.[i] $env?.array[:$env.i] $env?.array[:] $env?.array[:i] $env?.f64 != $env?.String $env?.f64 != f64 $env?.f64 != i $env?.f64 != nil ?? 1.0 $env?.f64 * 1.0 == 1.0 $env?.f64 * f64 $env?.f64 * i $env?.f64 ** $env.f64 $env?.f64 ** 0 / f64 $env?.f64 ** f64 $env?.f64 ** i $env?.f64 ** int(f64) $env?.f64 + 0 < 1.0 $env?.f64 + 1 * 0 $env?.f64 + f64 $env?.f64 + i $env?.f64 - 1 / f64 $env?.f64 - 1.0 == 1.0 $env?.f64 - 1.0 > 0 $env?.f64 - f64 $env?.f64 / f64 $env?.f64 / i $env?.f64 / len($env) $env?.f64 < 0 % i $env?.f64 < 1.0 - 1 $env?.f64 < 1.0 - 1.0 $env?.f64 < f64 $env?.f64 < i $env?.f64 <= f64 $env?.f64 <= i $env?.f64 == $env?.[Bar] $env?.f64 == $env?.[str] $env?.f64 == f64 $env?.f64 == i $env?.f64 == max(array, 1.0) $env?.f64 > f64 $env?.f64 > i $env?.f64 >= -1 $env?.f64 >= f64 $env?.f64 >= i $env?.f64 >= i == false $env?.f64 >= round(f64) $env?.f64 ?? 1.0 ?? i $env?.f64 ?? add $env?.f64 ?? array $env?.f64 ?? foo $env?.f64 ?? foo.String $env?.f64 ?? greet $env?.f64 ?? list $env?.f64 ?? list ?? foo $env?.f64 ?? ok $env?.f64 ?? str $env?.f64 ?? upper($env) $env?.f64 ^ $env?.f64 $env?.f64 ^ f64 $env?.f64 ^ i $env?.f64 in $env.array $env?.f64 in array $env?.f64 not in $env?.String $env?.f64 not in array $env?.f64 | max(1.0) $env?.f64 | mean(0) $env?.f64 | mean(1.0) $env?.f64 | median(0) $env?.f64 | median(1.0, f64) $env?.f64 | median(f64) $env?.f64 | min(1.0, 1.0) $env?.false != add $env?.false != ok $env?.false == add $env?.false ?? array $env?.false contains $env?.String $env?.false endsWith str $env?.false in list $env?.false?.Bar $env?.false?.Bar() $env?.false?.Bar()?.[i] $env?.false?.Bar.String $env?.false?.String $env?.false?.String([foobar contains String]) $env?.false?.String?.list $env?.false?.[add] $env?.false?.[add].String() $env?.false?.[add].i $env?.false?.[array] $env?.false?.[array].String() $env?.false?.[array]?.String $env?.false?.[f64] $env?.false?.[foo] $env?.false?.[foo].String?.list $env?.false?.[greet] $env?.false?.[i] $env?.false?.[list] $env?.false?.[list]?.array() $env?.false?.[ok] $env?.false?.[ok]?.[foo] $env?.false?.[str] $env?.false?.add $env?.false?.add() $env?.false?.add?.[f64] $env?.false?.add?.[greet] $env?.false?.array $env?.false?.array() $env?.false?.array(f64) $env?.false?.array(foobar) $env?.false?.array?.array $env?.false?.f64 $env?.false?.f64() $env?.false?.foo $env?.false?.foo() $env?.false?.foo(foobar, i .. f64) $env?.false?.foobar $env?.false?.foobar.array $env?.false?.foobar?.array() $env?.false?.foobar?.str $env?.false?.greet $env?.false?.greet() $env?.false?.groupBy(str) $env?.false?.i $env?.false?.i.str $env?.false?.list $env?.false?.list() $env?.false?.list(String == foobar?.[str]) $env?.false?.list?.Bar $env?.false?.list?.[foo] $env?.false?.ok $env?.false?.ok() $env?.false?.ok?.[list] $env?.false?.ok?.foobar.foo $env?.false?.sortBy($env) $env?.false?.str $env?.false?.str() $env?.false?.str.foo $env?.false?.str?.add $env?.foo == foo $env?.foo ?? $env?.String $env?.foo ?? $env?.[f64] $env?.foo ?? array $env?.foo ?? f64 $env?.foo ?? foo $env?.foo ?? ok $env?.foo ?? str $env?.foo ?? {foo: i} $env?.foo in $env?.[Bar] $env?.foo in list $env?.foo not in $env?.[String] $env?.foo not in [$env] $env?.foo not in list $env?.foo.Bar $env?.foo.String $env?.foo.String() $env?.foo?.Bar $env?.foo?.String $env?.foo?.String() $env?.foobar != -f64 $env?.foobar != f64 $env?.foobar != greet $env?.foobar != str $env?.foobar == $env.i $env?.foobar == $env.str $env?.foobar == $env?.add $env?.foobar == [1.0] $env?.foobar == add $env?.foobar == array $env?.foobar == f64 $env?.foobar == foo $env?.foobar == greet $env?.foobar == list $env?.foobar == ok $env?.foobar == reduce(list, false) $env?.foobar == str $env?.foobar ?? $env?.[String] $env?.foobar ?? i $env?.foobar ?? list $env?.foobar ?? ok $env?.foobar contains greet(str) $env?.foobar contains str $env?.foobar endsWith str $env?.foobar in array $env?.foobar in groupBy(array, 1.0) $env?.foobar in list $env?.foobar matches str $env?.foobar not contains str $env?.foobar not endsWith str $env?.foobar not in array $env?.foobar not in array == $env $env?.foobar not matches str $env?.foobar startsWith str $env?.foobar | get(add) $env?.foobar | get(ok) $env?.foobar?.$env.array(foo) $env?.foobar?.$env?.[f64] $env?.foobar?.Bar $env?.foobar?.Bar() $env?.foobar?.Bar().str $env?.foobar?.Bar()?.[str] $env?.foobar?.Bar(foobar) $env?.foobar?.Bar(greet) $env?.foobar?.Bar(list) $env?.foobar?.Bar.str $env?.foobar?.Bar?.[list] $env?.foobar?.Bar?.list() $env?.foobar?.String $env?.foobar?.String() $env?.foobar?.String()?.Bar $env?.foobar?.String(array) $env?.foobar?.String(foo) $env?.foobar?.String(foobar) $env?.foobar?.String.i $env?.foobar?.String.ok $env?.foobar?.String?.[greet] $env?.foobar?.String?.add $env?.foobar?.[add] $env?.foobar?.[add].list $env?.foobar?.[add]?.[array] $env?.foobar?.[add]?.[f64] $env?.foobar?.[add]?.f64 $env?.foobar?.[add]?.foo $env?.foobar?.[add]?.greet() $env?.foobar?.[array] $env?.foobar?.[array] in list $env?.foobar?.[array].ok() $env?.foobar?.[array].str $env?.foobar?.[array]?.[f64] $env?.foobar?.[array]?.[f64]?.list?.[i] $env?.foobar?.[array]?.i?.f64 $env?.foobar?.[count($env)] $env?.foobar?.[f64] $env?.foobar?.[f64].add $env?.foobar?.[f64]?.Bar $env?.foobar?.[f64]?.[foo] $env?.foobar?.[f64]?.[i] $env?.foobar?.[f64]?.[list] $env?.foobar?.[f64]?.add $env?.foobar?.[f64]?.f64(foobar) $env?.foobar?.[f64]?.foo $env?.foobar?.[f64]?.greet $env?.foobar?.[f64]?.i $env?.foobar?.[foo] $env?.foobar?.[foo].Bar $env?.foobar?.[foo].str $env?.foobar?.[foo]?.[i] $env?.foobar?.[foo]?.[str] $env?.foobar?.[foo]?.ok $env?.foobar?.[greet] $env?.foobar?.[greet].ok().array $env?.foobar?.[greet].str $env?.foobar?.[greet]?.[greet] $env?.foobar?.[greet]?.add $env?.foobar?.[greet]?.array $env?.foobar?.[greet]?.ok $env?.foobar?.[i] $env?.foobar?.[i].add $env?.foobar?.[i].str() $env?.foobar?.[i]?.Bar $env?.foobar?.[i]?.[list] $env?.foobar?.[i]?.[ok] $env?.foobar?.[i]?.foo() $env?.foobar?.[i]?.i $env?.foobar?.[i]?.list $env?.foobar?.[i]?.ok $env?.foobar?.[list] $env?.foobar?.[list] != ok $env?.foobar?.[list].Bar $env?.foobar?.[list].greet() $env?.foobar?.[list].list $env?.foobar?.[list]?.[f64] $env?.foobar?.[list]?.add $env?.foobar?.[list]?.i $env?.foobar?.[nil ?? list] $env?.foobar?.[ok] $env?.foobar?.[ok].ok $env?.foobar?.[ok]?.ok $env?.foobar?.[ok]?.ok() $env?.foobar?.[ok]?.str $env?.foobar?.[str] $env?.foobar?.[str].String $env?.foobar?.[str].array $env?.foobar?.[str].foo $env?.foobar?.[str].list(foobar?.[i].ok) $env?.foobar?.[str].ok $env?.foobar?.[str]?.f64 $env?.foobar?.[str]?.i $env?.foobar?.[str]?.list $env?.foobar?.add $env?.foobar?.add($env) $env?.foobar?.add() $env?.foobar?.add().f64() $env?.foobar?.add(1.0) $env?.foobar?.add(foobar) $env?.foobar?.add(foobar?.[add]) $env?.foobar?.add.Bar() $env?.foobar?.add.add() $env?.foobar?.add.array $env?.foobar?.add.foo $env?.foobar?.add.ok $env?.foobar?.add.str $env?.foobar?.add?.[greet] $env?.foobar?.add?.[greet]?.foo $env?.foobar?.add?.[i] $env?.foobar?.add?.[str] $env?.foobar?.add?.add $env?.foobar?.add?.f64 $env?.foobar?.add?.foo $env?.foobar?.add?.greet() $env?.foobar?.add?.i $env?.foobar?.add?.ok $env?.foobar?.all(str) $env?.foobar?.array $env?.foobar?.array() $env?.foobar?.array().list $env?.foobar?.array()?.foo $env?.foobar?.array(Bar) $env?.foobar?.array(foo) $env?.foobar?.array(foobar) $env?.foobar?.array(foobar, ok) $env?.foobar?.array(i) $env?.foobar?.array.array() $env?.foobar?.array.foo $env?.foobar?.array.list() $env?.foobar?.array.ok $env?.foobar?.array.str $env?.foobar?.array?.String(i) $env?.foobar?.array?.[add] $env?.foobar?.array?.array $env?.foobar?.array?.list $env?.foobar?.count($env) $env?.foobar?.count(foo, foo) $env?.foobar?.f64 $env?.foobar?.f64 not matches $env $env?.foobar?.f64() $env?.foobar?.f64()?.greet $env?.foobar?.f64(add)?.String(list) $env?.foobar?.f64(false ? foobar : foobar) $env?.foobar?.f64(foobar) $env?.foobar?.f64(foobar?.[String]) $env?.foobar?.f64.f64 $env?.foobar?.f64.i $env?.foobar?.f64?.[array].Bar $env?.foobar?.f64?.[foo]?.[greet] $env?.foobar?.f64?.[i] $env?.foobar?.f64?.[ok] $env?.foobar?.f64?.array $env?.foobar?.f64?.array() $env?.foobar?.f64?.foo $env?.foobar?.false?.i() $env?.foobar?.filter(f64) $env?.foobar?.findIndex(array) $env?.foobar?.findLast($env, $env) $env?.foobar?.findLastIndex(foo, f64, array) $env?.foobar?.findLastIndex(true) $env?.foobar?.foo $env?.foobar?.foo() $env?.foobar?.foo(array) $env?.foobar?.foo(ceil(Bar, 1), foobar?.Bar()) $env?.foobar?.foo(foobar | string($env)) $env?.foobar?.foo(foobar)?.[i] $env?.foobar?.foo(i) $env?.foobar?.foo.f64 $env?.foobar?.foo.ok $env?.foobar?.foo?.String $env?.foobar?.foo?.[add] $env?.foobar?.foo?.[foo] $env?.foobar?.foo?.[greet] $env?.foobar?.foo?.ok(str) $env?.foobar?.foo?.str $env?.foobar?.foobar $env?.foobar?.foobar?.[f64] $env?.foobar?.foobar?.[foo] $env?.foobar?.foobar?.[greet] $env?.foobar?.foobar?.[ok] $env?.foobar?.greet $env?.foobar?.greet() $env?.foobar?.greet(array) $env?.foobar?.greet(foobar) $env?.foobar?.greet(list) $env?.foobar?.greet.Bar $env?.foobar?.greet.array $env?.foobar?.greet?.add $env?.foobar?.greet?.array() $env?.foobar?.greet?.foo $env?.foobar?.i $env?.foobar?.i() $env?.foobar?.i(foobar) $env?.foobar?.i(list not endsWith foobar) $env?.foobar?.i.array $env?.foobar?.i?.Bar $env?.foobar?.i?.f64 $env?.foobar?.i?.greet $env?.foobar?.i?.ok $env?.foobar?.list $env?.foobar?.list() $env?.foobar?.list().ok $env?.foobar?.list()?.f64 $env?.foobar?.list(foobar) $env?.foobar?.list?.[greet] $env?.foobar?.list?.[list] $env?.foobar?.list?.foo $env?.foobar?.min(foobar, 1.0) $env?.foobar?.nil.foobar $env?.foobar?.none(1) $env?.foobar?.none(array) $env?.foobar?.not $env?.foobar?.not?.[ok] $env?.foobar?.ok $env?.foobar?.ok() $env?.foobar?.ok().String() $env?.foobar?.ok(foobar not contains foobar) $env?.foobar?.ok(foobar) $env?.foobar?.ok(ok) $env?.foobar?.ok(str, $env) $env?.foobar?.ok.array $env?.foobar?.ok.f64() $env?.foobar?.ok?.[array] $env?.foobar?.ok?.[f64] $env?.foobar?.ok?.[greet] $env?.foobar?.ok?.[str] $env?.foobar?.ok?.i $env?.foobar?.ok?.ok $env?.foobar?.one(foobar) $env?.foobar?.one(i) $env?.foobar?.reduce(1.0) $env?.foobar?.repeat(foobar) $env?.foobar?.replace(str) $env?.foobar?.reverse($env) $env?.foobar?.round(foo) $env?.foobar?.split(1.0) $env?.foobar?.str $env?.foobar?.str() $env?.foobar?.str().String $env?.foobar?.str()?.[foo] $env?.foobar?.str(1 ?? foobar) $env?.foobar?.str(String?.[i]) $env?.foobar?.str(foo) $env?.foobar?.str(foobar) $env?.foobar?.str.array $env?.foobar?.str.i $env?.foobar?.str.str $env?.foobar?.str?.[f64] $env?.foobar?.str?.[i] $env?.foobar?.str?.[str] $env?.foobar?.str?.add $env?.foobar?.str?.i $env?.foobar?.string($env) $env?.foobar?.timezone(str) $env?.foobar?.trimSuffix(list, i) $env?.foobar?.true?.$env $env?.foobar?.true?.str $env?.foobar?.uniq(foobar).add $env?.foobar?.upper(list) $env?.greet != greet $env?.greet == $env?.[Bar] $env?.greet == find($env, false) $env?.greet == greet $env?.greet == list ?? 1.0 $env?.greet ?? $env?.Bar(true) $env?.greet ?? $env?.[String] $env?.greet ?? add $env?.greet ?? array $env?.greet ?? f64 $env?.greet ?? foo $env?.greet ?? greet $env?.greet ?? i $env?.greet ?? list $env?.greet ?? nil ?? foo $env?.greet ?? ok ?? foo $env?.greet ?? str $env?.greet($env?.[str]) $env?.greet($env?.str) $env?.greet(foo.Bar) $env?.greet(foo.String()) $env?.greet(foo?.Bar) $env?.greet(foo?.String()) $env?.greet(greet(str)) $env?.greet(str ?? str) $env?.greet(str) $env?.greet(str) startsWith str $env?.greet(str[:]) $env?.greet(string(0)) $env?.greet(toJSON(1.0)) $env?.greet(toJSON(array)) $env?.greet(toJSON(false)) $env?.greet(toJSON(str)) $env?.greet(trim(str)) $env?.greet(type(greet)) $env?.greet(type(ok)) $env?.greet(type(true)) $env?.greet(upper(str)) $env?.i != $env?.foobar $env?.i != 1.0 ** i $env?.i != f64 $env?.i != i $env?.i % $env.i $env?.i % 1 ?? foo $env?.i % i $env?.i * 1 != $env $env?.i * f64 $env?.i * i $env?.i ** 1.0 >= i $env?.i ** f64 $env?.i ** i $env?.i ** int(1.0) $env?.i + $env?.f64 $env?.i + f64 $env?.i + findIndex($env, ok) $env?.i + i $env?.i - ceil(i) $env?.i - i $env?.i .. 1 | groupBy(f64) $env?.i .. i $env?.i / 1.0 <= i $env?.i / f64 $env?.i / i $env?.i / len(list) $env?.i / max(1.0) $env?.i < 1.0 - 0 $env?.i < f64 $env?.i < i $env?.i < i + 1 $env?.i <= 0 ^ 1.0 $env?.i <= f64 $env?.i <= i $env?.i == 1 - 0 $env?.i == f64 $env?.i == first($env) $env?.i == i $env?.i == len($env) $env?.i == len(list) $env?.i == max($env) $env?.i > 0 * 1.0 $env?.i > 1 ?? nil $env?.i > f64 $env?.i > i $env?.i > i != true $env?.i >= $env?.f64 $env?.i >= 0 or $env $env?.i >= 1.0 ** 1 $env?.i >= f64 $env?.i >= floor(1.0) $env?.i >= i $env?.i ?? add $env?.i ?? f64 $env?.i ?? filter($env, #.f64) $env?.i ?? foo $env?.i ?? greet $env?.i ?? i $env?.i ?? str $env?.i ?? str ?? str $env?.i ?? sum($env) $env?.i ^ 1.0 * 1 $env?.i ^ i $env?.i ^ i not in array $env?.i in array $env?.i not in $env?.String $env?.i not in $env?.[Bar] $env?.i not in array $env?.i | add(0) $env?.i | add(1) $env?.i | bitand(i) $env?.i | bitnand(0) $env?.i | bitnand(1) $env?.i | bitor(i) $env?.i | bitshl(0) $env?.i | bitushr(i) $env?.i | max(1.0) $env?.i | max(array) $env?.i | mean(i) $env?.i | median(0) $env?.i | median(1) $env?.i | median(1.0) $env?.i | median(f64) $env?.i | median(i) $env?.i | min(1, f64) $env?.i | min(f64, 1) $env?.i..i $env?.list != [1.0] $env?.list != array $env?.list != list $env?.list == [foo, 0] $env?.list == array $env?.list == list $env?.list == nil || $env $env?.list ?? $env?.add $env?.list ?? add $env?.list ?? array $env?.list ?? f64 $env?.list ?? foo $env?.list ?? greet $env?.list ?? i $env?.list ?? nil ?? ok $env?.list ?? nil | groupBy(#) $env?.list ?? ok $env?.list ?? str $env?.list ?? toJSON(add) $env?.list ?? toPairs($env) $env?.list | all(false) $env?.list | all(nil == 1) $env?.list | all(ok) $env?.list | all(true) $env?.list | any(f64 >= f64) $env?.list | any(false) $env?.list | any(ok) $env?.list | any(true) $env?.list | concat(list) $env?.list | count(false) $env?.list | count(ok) $env?.list | count(true) $env?.list | filter(ok) $env?.list | filter(true) $env?.list | find(false) $env?.list | find(ok) $env?.list | find(true) $env?.list | findIndex(!ok) $env?.list | findIndex(false) $env?.list | findIndex(ok) $env?.list | findIndex(true) $env?.list | findIndex(true) not in array $env?.list | findLast(false) $env?.list | findLast(ok) $env?.list | findLast(true) $env?.list | findLastIndex(#.Bar in #) $env?.list | findLastIndex(false) $env?.list | findLastIndex(ok) $env?.list | findLastIndex(true) $env?.list | groupBy(#) $env?.list | groupBy(#.Bar) $env?.list | groupBy(.Bar) $env?.list | groupBy(0) $env?.list | groupBy(1) $env?.list | groupBy(1.0) $env?.list | groupBy(f64) $env?.list | groupBy(false) $env?.list | groupBy(foo) $env?.list | groupBy(i) $env?.list | groupBy(ok) $env?.list | groupBy(str) $env?.list | groupBy(true) $env?.list | map(#) $env?.list | map(#.Bar) $env?.list | map(#.String) $env?.list | map(#index) $env?.list | map($env) $env?.list | map(.Bar) $env?.list | map(.String) $env?.list | map(0) $env?.list | map(1) $env?.list | map(1.0) $env?.list | map(add) $env?.list | map(array) $env?.list | map(false) $env?.list | map(foo) $env?.list | map(greet) $env?.list | map(i) $env?.list | map(list) $env?.list | map(ok) $env?.list | map(str) $env?.list | map(true) $env?.list | none(.Bar not startsWith #.Bar) $env?.list | none(false) $env?.list | none(ok) $env?.list | none(true) $env?.list | one(false) $env?.list | one(ok) $env?.list | reduce(#) $env?.list | reduce(#, f64) $env?.list | reduce(#, false) $env?.list | reduce(#, foo) $env?.list | reduce(#, i) $env?.list | reduce(#.Bar) $env?.list | reduce(#.Bar, 0) $env?.list | reduce(#.String, $env) $env?.list | reduce(#acc) $env?.list | reduce(#acc, 1) $env?.list | reduce(#acc, true) $env?.list | reduce(#index) $env?.list | reduce($env) $env?.list | reduce($env, greet) $env?.list | reduce($env, true) $env?.list | reduce(.Bar) $env?.list | reduce(.String, $env) $env?.list | reduce(0) $env?.list | reduce(1) $env?.list | reduce(1.0) $env?.list | reduce(1.0, list) $env?.list | reduce(add) $env?.list | reduce(array) $env?.list | reduce(array, $env) $env?.list | reduce(f64 == 1) $env?.list | reduce(f64, $env) $env?.list | reduce(false) $env?.list | reduce(foo) $env?.list | reduce(foo, nil) $env?.list | reduce(foo, ok) $env?.list | reduce(foo, str) $env?.list | reduce(greet) $env?.list | reduce(greet, ok) $env?.list | reduce(list) $env?.list | reduce(ok) $env?.list | reduce(str) $env?.list | reduce(str, nil) $env?.list | reduce(true) $env?.list | reduce(true, i) $env?.list | sortBy(#.Bar) $env?.list | sortBy(.Bar) $env?.list | sortBy(0) $env?.list | sortBy(1) $env?.list | sortBy(1.0) $env?.list | sortBy(str) $env?.list | sum(0) $env?.list | sum(1) $env?.list | sum(1.0) $env?.list | sum(f64) $env?.list | sum(i) $env?.list | take(1) $env?.list?.[i] $env?.list?.[i].Bar $env?.list?.[i].String $env?.list[:] $env?.list[:i] $env?.list[i:] $env?.nil != $env?.[String] $env?.nil != array $env?.nil != greet $env?.nil == array $env?.nil == foo.Bar $env?.nil ?? foo.String $env?.nil ?? str $env?.nil contains $env?.[nil] $env?.nil in list $env?.nil matches str $env?.nil not in array $env?.nil startsWith str $env?.nil.Bar || true $env?.nil?.$env.foo $env?.nil?.Bar $env?.nil?.Bar() $env?.nil?.Bar(list) $env?.nil?.Bar?.String(Bar) $env?.nil?.Bar?.[i] $env?.nil?.Bar?.[list] $env?.nil?.String $env?.nil?.String() $env?.nil?.String(i) $env?.nil?.String.i $env?.nil?.String?.ok() $env?.nil?.[add] $env?.nil?.[add]?.[greet] $env?.nil?.[add]?.str $env?.nil?.[array] $env?.nil?.[array].Bar $env?.nil?.[array]?.String $env?.nil?.[f64] $env?.nil?.[f64]?.f64 $env?.nil?.[foo] $env?.nil?.[foo]?.ok $env?.nil?.[greet] $env?.nil?.[greet]?.ok $env?.nil?.[i] $env?.nil?.[i]?.Bar $env?.nil?.[i]?.[foo] $env?.nil?.[list] $env?.nil?.[ok] $env?.nil?.[ok]?.str $env?.nil?.[str] $env?.nil?.[str]?.i $env?.nil?.[str]?.str $env?.nil?.add $env?.nil?.add() $env?.nil?.add(foobar) $env?.nil?.array $env?.nil?.array() $env?.nil?.array(str) $env?.nil?.array?.foo $env?.nil?.array?.list $env?.nil?.f64 $env?.nil?.f64() $env?.nil?.f64(foobar != i) $env?.nil?.f64?.true?.greet?.foo $env?.nil?.filter(0) $env?.nil?.filter(1.0) $env?.nil?.findIndex(str) $env?.nil?.findLast(false) $env?.nil?.foo $env?.nil?.foo() $env?.nil?.foo.foo $env?.nil?.foo.i $env?.nil?.foo.str $env?.nil?.foo?.[add].array $env?.nil?.foo?.[f64] $env?.nil?.foo?.f64(Bar) $env?.nil?.foobar $env?.nil?.foobar.ok $env?.nil?.foobar?.Bar(foobar, $env) $env?.nil?.foobar?.i $env?.nil?.greet $env?.nil?.greet() $env?.nil?.greet?.array $env?.nil?.i $env?.nil?.i($env.foo) $env?.nil?.i() $env?.nil?.list $env?.nil?.list() $env?.nil?.map(foobar) $env?.nil?.median(foobar) $env?.nil?.ok $env?.nil?.ok() $env?.nil?.ok(add) $env?.nil?.ok(foobar?.[String].add) $env?.nil?.ok.add $env?.nil?.one(foobar, foobar) $env?.nil?.round(1.0) $env?.nil?.str $env?.nil?.str() $env?.nil?.str(foobar) $env?.ok && $env?.Bar $env?.ok && $env?.[str] $env?.ok && $env?.ok $env?.ok && nil not in $env $env?.ok && ok $env?.ok == ok $env?.ok ? add : foo $env?.ok ? foo == nil : i $env?.ok ?: array $env?.ok ?: foo $env?.ok ?? $env?.[Bar] $env?.ok ?? $env?.[add] $env?.ok ?? add $env?.ok ?? array $env?.ok ?? f64 $env?.ok ?? foo $env?.ok ?? greet $env?.ok ?? i $env?.ok ?? keys($env) $env?.ok ?? list $env?.ok ?? str $env?.ok ?? str ?? $env $env?.ok and $env?.[String] $env?.ok and 1.0 == i $env?.ok and foo != foo $env?.ok and ok $env?.ok not in $env && false $env?.ok or !true $env?.ok or $env != $env $env?.ok or $env in str $env?.ok or i != 1.0 $env?.ok or nil not in $env $env?.ok or ok $env?.ok || $env?.Bar() $env?.ok || ok $env?.ok || sum($env) $env?.str != 1.0 ?? foo $env?.str + str $env?.str < foo.Bar $env?.str < str $env?.str < type(add) $env?.str <= $env?.str $env?.str <= foo.Bar $env?.str <= str $env?.str <= string(str) $env?.str == str $env?.str > str $env?.str > str == nil $env?.str > toJSON(nil) $env?.str >= foo?.Bar $env?.str ?? $env.ok $env?.str ?? $env?.String() $env?.str ?? add $env?.str ?? array $env?.str ?? f64 $env?.str ?? foo $env?.str ?? greet $env?.str ?? list $env?.str ?? not ok $env?.str ?? ok $env?.str ?? str $env?.str contains $env?.[Bar] $env?.str contains foo?.Bar $env?.str contains str $env?.str endsWith $env and false $env?.str endsWith str $env?.str endsWith toJSON(foo) $env?.str in $env ? 1.0 : nil $env?.str in $env?.[String] $env?.str in foo $env?.str matches $env?.[String] $env?.str matches str $env?.str not contains str $env?.str not endsWith str $env?.str not in $env?.[String] $env?.str not in foo $env?.str not in {foo: greet, foo: nil} $env?.str not matches foo.Bar $env?.str not matches str $env?.str not startsWith $env.str $env?.str not startsWith foo?.Bar $env?.str not startsWith str $env?.str startsWith $env?.Bar $env?.str | date(str) $env?.str | greet() $env?.str | trim(str) $env?.str | trimPrefix(str) $env?.str[:0 ?? false] $env?.str[:] $env?.str[:i] $env?.str[i:] $env?.true != i $env?.true != ok $env?.true == foo $env?.true == i $env?.true ?? foo.Bar $env?.true not endsWith str $env?.true not matches str $env?.true | get(array) $env?.true?.Bar $env?.true?.Bar() $env?.true?.Bar(false) $env?.true?.String $env?.true?.String() $env?.true?.String().add $env?.true?.String.foo(foobar) $env?.true?.String?.Bar.str $env?.true?.[add] $env?.true?.[array] $env?.true?.[array].Bar $env?.true?.[array].add() $env?.true?.[f64] $env?.true?.[f64]?.String() $env?.true?.[f64]?.[list] $env?.true?.[foo] $env?.true?.[greet] $env?.true?.[greet].Bar $env?.true?.[greet]?.ok $env?.true?.[i] $env?.true?.[list] $env?.true?.[ok] $env?.true?.[ok]?.[ok] $env?.true?.[str] $env?.true?.[str].foo $env?.true?.add $env?.true?.add(foobar matches foo) $env?.true?.add.foo $env?.true?.array $env?.true?.array() $env?.true?.f64 $env?.true?.f64() $env?.true?.f64(foobar) $env?.true?.find(foobar, foobar) $env?.true?.foo $env?.true?.foo() $env?.true?.foo?.[ok] $env?.true?.foobar $env?.true?.foobar?.str $env?.true?.greet $env?.true?.greet() $env?.true?.greet().i $env?.true?.greet?.ok $env?.true?.i $env?.true?.i() $env?.true?.list $env?.true?.list() $env?.true?.list.foo $env?.true?.ok $env?.true?.ok() $env?.true?.reduce(array) $env?.true?.str $env?.true?.str() $env?.true?.true?.array $env[$env:] - f64 and false $env[:str] not in foo || true - + $env || true - + $env.f64 - + $env.i - + $env?.f64 - + $env?.i - + 1 != f64 - + 1 < 1.0 - + 1 ^ 1 - + 1.0 != 1.0 - + abs(i) - + ceil(0) - + f64 - + f64 + f64 - + f64 - 1.0 - + f64 > 0 - + i - + i < 1 - + i in $env.array - + int(0) - + median(f64) - + min(f64) - + sum(array) - + {foo: 1}.foo - - $env?.f64 - - $env?.i - - 0 <= 1.0 - - 0 >= 1.0 - - 0 ^ 0 - - 0 ^ 1 - - 1 == 1.0 - - 1.0 != nil - - 1.0 ** 1.0 - - 1.0 < 1 - - 1.0 == 0 - - abs(1) - - array?.[i] - - ceil(1.0) - - f64 - - i - - i != $env - - len($env) - - max(1.0) - - sum(array) -$env && false -$env and false -$env in str && false -$env not in foo || true -$env or true -$env || true -$env.f64 -$env.f64 - i -$env.f64 ?? i -$env.i -$env.i / i -$env.i ?? add -$env?.[str]?.[f64] -$env?.array?.[i] -$env?.f64 -$env?.i -$env?.i != $env -$env?.i == f64 --$env.f64 --$env?.f64 --$env?.i --0 --0 .. i --0 ?? array --1 --1 < 1.0 --1.0 --1.0 - 1.0 --bitnot(0) --f64 --f64 / f64 --i --sum(array) -.0 ** 0 -.0 / 1 -0 != $env -0 != 0 -0 != 1 -0 != 1.0 -0 != f64 -0 != i -0 != mean(f64) -0 != min($env) -0 != nil -0 % 1 -0 % i -0 % i + f64 -0 * 0 -0 * 1 -0 * 1.0 -0 * f64 -0 * i -0 ** 0 -0 ** 1 -0 ** 1.0 -0 ** 1.0 < i -0 ** 1.0 ?? list -0 ** i -0 + -f64 -0 + 0 -0 + 1 -0 + 1.0 -0 + f64 -0 + f64 != 1.0 -0 + i -0 - 0 -0 - 1 -0 - 1.0 -0 - f64 -0 - floor(f64) -0 - i -0 .. 0 -0 .. 1 -0 .. i -0 / 0 -0 / 1 -0 / 1.0 -0 / f64 -0 / i -0 < 0 -0 < 1 -0 < 1.0 -0 < f64 -0 < i -0 <= 0 -0 <= 1 -0 <= 1.0 -0 <= f64 -0 <= i -0 == $env -0 == $env?.Bar -0 == $env?.[Bar] -0 == 0 -0 == 1 -0 == 1.0 -0 == f64 -0 == i -0 == mean(1.0) -0 == nil -0 > 0 -0 > 1 -0 > 1.0 -0 > f64 -0 > i -0 >= 0 -0 >= 0 || false -0 >= 1 -0 >= 1.0 -0 >= f64 -0 >= i -0 ?? $env -0 ?? 0 -0 ?? 1 -0 ?? 1.0 -0 ?? add -0 ?? array -0 ?? f64 -0 ?? false -0 ?? foo -0 ?? foo.Bar -0 ?? foo?.Bar -0 ?? greet -0 ?? i -0 ?? list -0 ?? min(0, i) -0 ?? nil -0 ?? ok -0 ?? str -0 ?? true -0 ^ 0 -0 ^ 0 | max(1) -0 ^ 1 -0 ^ 1.0 -0 ^ 1.0 <= 1 -0 ^ f64 -0 ^ i -0 in $env?.array -0 in array -0 not in array -0 | bitshl(i) -0 | bitushr(1) -0 | max(array) -0 | mean(0) -0 | mean(1.0) -0 | median(1.0) -0 | median(i) -0.0 -0.1 -1 != $env -1 != 0 -1 != 1 -1 != 1.0 -1 != 1.0 || true -1 != f64 -1 != i -1 != mean(array) -1 != nil -1 % 1 -1 % i -1 * 0 -1 * 1 -1 * 1.0 -1 * 1.0 - i -1 * f64 -1 * i -1 ** 0 -1 ** 1 -1 ** 1.0 -1 ** f64 -1 ** i -1 + 0 -1 + 1 -1 + 1 ^ f64 -1 + 1.0 -1 + f64 -1 + float(i) -1 + i -1 - 0 -1 - 1 -1 - 1.0 -1 - f64 -1 - i -1 .. 0 -1 .. 1 -1 .. i -1 / 0 -1 / 1 -1 / 1.0 -1 / f64 -1 / i -1 < 0 -1 < 1 -1 < 1.0 -1 < f64 -1 < i -1 <= -0 -1 <= 0 -1 <= 1 -1 <= 1.0 -1 <= f64 -1 <= i -1 == $env -1 == 0 -1 == 1 -1 == 1.0 -1 == 1.0 * 1 -1 == f64 -1 == i -1 == nil -1 == nil != false -1 > 0 -1 > 1 -1 > 1.0 -1 > f64 -1 > i -1 >= 0 -1 >= 0 + i -1 >= 1 -1 >= 1.0 -1 >= f64 -1 >= i -1 ?? $env -1 ?? $env.ok -1 ?? $env?.greet -1 ?? 0 -1 ?? 1 -1 ?? 1.0 -1 ?? add -1 ?? array -1 ?? array ?? $env -1 ?? f64 -1 ?? false -1 ?? foo -1 ?? greet -1 ?? i -1 ?? list -1 ?? nil -1 ?? ok -1 ?? str -1 ?? str && false -1 ?? sum($env, list) -1 ?? true -1 ?? type(i) -1 ^ $env?.i -1 ^ 0 -1 ^ 1 -1 ^ 1.0 -1 ^ f64 -1 ^ i -1 ^ i <= 1 -1 in array -1 not in $env.array -1 not in array -1 | bitnand(0) -1 | bitnand(1) -1 | bitor(1) -1 | bitshr(1) -1 | bitushr(i) -1 | bitxor(i) -1 | max(1.0) -1 | max(array) -1 | mean(0) -1 | mean(1) -1 | mean(1.0) -1 | mean(f64) -1 | median(1, 0) -1 | min(f64) -1..i -1.0 -1.0 != $env -1.0 != $env?.[Bar] -1.0 != $env?.i -1.0 != 0 -1.0 != 1 -1.0 != 1.0 -1.0 != 1.0 == $env?.[String] -1.0 != f64 -1.0 != i -1.0 != nil -1.0 * $env?.i -1.0 * -1 -1.0 * 0 -1.0 * 1 -1.0 * 1.0 -1.0 * f64 -1.0 * i -1.0 ** 0 -1.0 ** 1 -1.0 ** 1.0 -1.0 ** f64 -1.0 ** i -1.0 + 0 -1.0 + 1 -1.0 + 1.0 -1.0 + f64 -1.0 + i -1.0 + i != 1.0 -1.0 - $env?.i -1.0 - 0 -1.0 - 1 -1.0 - 1.0 -1.0 - f64 -1.0 - i -1.0 / $env.i -1.0 / 0 -1.0 / 1 -1.0 / 1.0 -1.0 / f64 -1.0 / i -1.0 < 0 -1.0 < 0 ** 1.0 -1.0 < 1 -1.0 < 1.0 -1.0 < f64 -1.0 < i -1.0 < mean(i, 1.0) -1.0 <= 0 -1.0 <= 1 -1.0 <= 1.0 -1.0 <= f64 -1.0 <= f64 != $env -1.0 <= i -1.0 == $env -1.0 == $env?.[String] -1.0 == $env?.[str] -1.0 == 0 -1.0 == 1 -1.0 == 1 && false -1.0 == 1.0 -1.0 == f64 -1.0 == f64 ?? add -1.0 == i -1.0 == nil -1.0 > 0 -1.0 > 1 -1.0 > 1.0 -1.0 > f64 -1.0 > i -1.0 >= -f64 -1.0 >= 0 -1.0 >= 1 -1.0 >= 1.0 -1.0 >= 1.0 >= 1 -1.0 >= f64 -1.0 >= i -1.0 ?? !true -1.0 ?? $env -1.0 ?? $env?.add -1.0 ?? -f64 -1.0 ?? 0 -1.0 ?? 1 -1.0 ?? 1.0 -1.0 ?? add -1.0 ?? array -1.0 ?? f64 -1.0 ?? false -1.0 ?? foo -1.0 ?? greet -1.0 ?? i -1.0 ?? list -1.0 ?? nil -1.0 ?? ok -1.0 ?? str -1.0 ?? true -1.0 ^ 0 -1.0 ^ 1 -1.0 ^ 1.0 -1.0 ^ 1.0 <= 1.0 -1.0 ^ array?.[i] -1.0 ^ f64 -1.0 ^ i -1.0 in array -1.0 not in $env?.Bar -1.0 not in array -1.0 | max(f64) -1.0 | mean(1) -1.0 | mean(1.0, f64) -1.0 | median(1.0) -1.0 | median(i) -1.0 | min(0) -1.0 | min(1) -1.0 | min(1.0) -1.0 | min(array) -1.0 | min(array, 1.0) -1.0; false -1.1 -abs(0) -abs(1 * i) -abs(1) -abs(1.0) -abs(f64) -abs(i) -abs(reduce(array, 0)) -add(0, 1) -add(1, 1) -add(i, 0) -add(i, 1) -array?.[0] -array?.[1] -array?.[i] -bitnand(0, 1) -bitnand(1, i) -bitnot(0) -bitnot(1) -bitnot(i) -bitnot(min(array)) -bitnot(sum(array)) -bitshl(0, i) -bitshl(1, i) -bitshl(i, i) -bitshr(1, 0) -bitshr(1, i) -bitshr(i, 1) -bitxor(1, 1) -ceil(0) -ceil(1) -ceil(1.0) -ceil(f64) -ceil(i) -count($env, ok) -count($env, true) -count(array, false) -count(array, ok) -count(list, false) -count(list, ok) -count(list, true) -f64 -f64 != $env -f64 != 0 -f64 != 1 -f64 != 1.0 -f64 != f64 -f64 != i -f64 != int(1) -f64 != nil -f64 * 0 -f64 * 1 -f64 * 1.0 -f64 * f64 -f64 * i -f64 ** 0 -f64 ** 1 -f64 ** 1.0 -f64 ** f64 -f64 ** i -f64 + 0 -f64 + 1 -f64 + 1.0 -f64 + 1.0 / 1 -f64 + f64 -f64 + i -f64 + sum(array) -f64 - 0 -f64 - 1 -f64 - 1.0 -f64 - f64 -f64 - i -f64 / 1 -f64 / 1.0 -f64 / 1.0 ?? false -f64 / f64 -f64 / i -f64 / i ** 0 -f64 < 0 -f64 < 1 -f64 < 1.0 -f64 < f64 -f64 < i -f64 <= 0 -f64 <= 1 -f64 <= 1.0 -f64 <= f64 -f64 <= i -f64 == $env -f64 == 0 -f64 == 1 -f64 == 1.0 -f64 == 1.0 || $env -f64 == f64 -f64 == i -f64 == max(0) -f64 == nil -f64 > 0 -f64 > 1 -f64 > 1.0 -f64 > f64 -f64 > f64 <= f64 -f64 > i -f64 >= $env?.i -f64 >= 0 -f64 >= 0 > 0 -f64 >= 1 -f64 >= 1.0 -f64 >= f64 -f64 >= float(1.0) -f64 >= i -f64 ?? $env -f64 ?? 0 -f64 ?? 1 -f64 ?? 1.0 -f64 ?? add -f64 ?? array -f64 ?? false -f64 ?? foo -f64 ?? greet -f64 ?? i -f64 ?? list -f64 ?? nil -f64 ?? nil ?? nil -f64 ?? ok -f64 ?? str -f64 ?? string(nil) -f64 ?? true -f64 ^ 1 -f64 ^ 1.0 -f64 ^ f64 -f64 ^ i -f64 in array -f64 not in array -f64 | mean(0) -find(array, ok) -find(array, true) -findIndex($env, ok) -findIndex(list, true) -findLast(array, ok) -findLastIndex($env, ok) -findLastIndex($env, true) -findLastIndex(array, ok) -findLastIndex(array, true) -findLastIndex(list, true) -first($env | map(#index)) -first(array) -float(0) -float(1) -float(1.0 ?? nil) -float(1.0) -float(f64) -float(i) -floor($env.i) -floor(0) -floor(1) -floor(1.0) -floor(f64) -floor(i) -i -i != $env -i != 0 -i != 1 -i != 1.0 -i != ceil(f64) -i != f64 -i != i -i != nil -i % 1 -i % i -i * 1 -i * 1.0 -i * f64 -i * i -i * nil ?? 1.0 -i ** 0 -i ** 1.0 -i ** 1.0 ** f64 -i ** 1.0 == nil -i ** f64 -i ** i -i + 0 -i + 1 -i + 1.0 -i + f64 -i + i -i + median(1.0) -i - 0 -i - 1 -i - 1.0 -i - array?.[i] -i - f64 -i - i -i .. 0 -i .. 1 -i .. i -i .. min(1) -i / 0 -i / 1 -i / 1.0 -i / f64 -i / i -i < 0 -i < 1 -i < 1 and false -i < 1.0 -i < f64 -i < i -i < sum(array) -i <= 0 -i <= 1 -i <= 1.0 -i <= f64 -i <= i -i == $env -i == 0 -i == 1.0 -i == 1.0 * i -i == f64 -i == i -i == nil -i > 0 -i > 1 -i > 1.0 -i > f64 -i > i -i >= 1 -i >= 1.0 -i >= 1.0 ?? foo -i >= f64 -i >= i -i >= i || $env -i ?? $env -i ?? $env.array -i ?? $env?.String?.i -i ?? $env?.[i] -i ?? $env?.add -i ?? $env?.i -i ?? 0 -i ?? 1 -i ?? 1.0 -i ?? add -i ?? array -i ?? f64 -i ?? false -i ?? foo -i ?? foo?.Bar -i ?? greet -i ?? i -i ?? list -i ?? nil -i ?? ok -i ?? str -i ?? true -i ^ 0 -i ^ 0 ?? foo -i ^ 1 -i ^ 1.0 -i ^ f64 -i ^ i -i ^ i > 1.0 -i in array -i not in array -i | add(i) -i | bitand(0) -i | bitor(0) -i | bitshr(1) -i | bitxor(1) -i | bitxor(i) -i | max(1) -i | max(f64) -i | min(1.0) -i..i -int($env?.i) -int(0) -int(1) -int(1.0) -int(array | max(1)) -int(f64) -int(i) -last(array) -len($env) -len(array) -len(foo?.Bar) -len(list) -len(str) -max($env).i -max(0 * 1) -max(0) -max(1) -max(1, 1.0) -max(1, array) -max(1.0) -max(1.0, 0) -max(1.0, 1.0) -max(array) -max(array, 0) -max(array, i) -max(f64) -max(f64, 1.0) -max(i) -max(i, 0) -max(i, 1) -max(i, array) -mean(0) -mean(0, f64) -mean(1) -mean(1, 1) -mean(1, f64) -mean(1.0) -mean(1.0, 0, array) -mean(1.0, 1) -mean(1.0, 1.0) -mean(1.0, i) -mean(array) -mean(f64) -mean(f64, 1) -mean(i) -mean(i) > f64 -mean(i, f64) -median(0) -median(1) -median(1) < i -median(1.0) -median(array) -median(array, 1.0) -median(f64) -median(f64, f64) -median(i) -median(i, 1) -median(min(0)) -min(0) -min(0, 1) -min(1) -min(1.0) -min(1.0, i) -min(array) -min(array, 0, array) -min(array, i, 1.0) -min(f64) -min(f64, 0, 1.0) -min(i) -min(i, 1) -min(i, 1.0) -min(i, 1.0) + f64 -nil ?? -f64 -nil ?? 0 -nil ?? 1 -nil ?? 1 != nil -nil ?? 1.0 -nil ?? f64 -nil ?? i -nil ?? i / 0 -reduce($env, 0, nil) -reduce($env, i, str) -reduce(array, #) -reduce(array, #acc) -reduce(array, #index, $env) -reduce(array, 0) -reduce(array, 1) -reduce(array, 1, f64) -reduce(array, 1.0) -reduce(array, f64) -reduce(array, i) -reduce(list, 1) -reduce(list, 1.0) -round(0) -round(1) -round(1.0) -round(f64) -round(i) -sum($env, 0) -sum($env, 1) -sum($env, 1.0) -sum($env, f64) -sum($env.array) -sum(array) -sum(array); str -sum(array, #) -sum(array, 0) -sum(array, 1) -sum(array, 1.0) -sum(array, i) -sum(list | reduce(array, greet)) -sum(list, 0) -sum(list, 1) -sum(list, 1.0) -sum(list, f64) -sum(str ?? 0) 0 != $env ?: $env?.[i]?.ok 0 != $env ?: ok 0 != $env ?? add 0 != $env ?? array 0 != $env.f64 0 != $env.i 0 != $env?.Bar 0 != $env?.Bar?.foo() 0 != $env?.String 0 != $env?.[Bar] 0 != $env?.[String] 0 != $env?.[foobar] 0 != $env?.[str] 0 != $env?.f64 0 != $env?.foobar?.foo 0 != $env?.i 0 != $env?.not 0 != 0 % sum(array) 0 != 0 && $env == foo 0 != 0 - i 0 != 0 ?: array 0 != 0 ?? f64 0 != 0 ^ 1.0 ^ 1 0 != 0 or 0 != f64 0 != 1.0 && ok ?? greet 0 != 1.0 * $env.f64 0 != 1.0 * i 0 != 1.0 + f64 ** 1.0 0 != 1.0 / i * 1.0 0 != 1.0 ?? ok 0 != 1.0 || $env - i 0 != array?.[i] 0 != f64 - $env?.i 0 != f64 / f64 0 != f64 == $env?.Bar 0 != f64 ^ 1.0 or $env 0 != f64 || $env?.[ok] 0 != f64 || nil == str 0 != f64 || ok 0 != foo ?? list 0 != i ** i 0 != i ^ f64 0 != nil != ok 0 != nil || $env?.[String] 0 != ok ?? $env?.Bar 0 != ok ?? i 0 != true ?? foo?.Bar 0 % $env.i 0 % $env?.i 0 % 1 * i 0 % 1 + i >= 0 0 % 1 < array?.[i] 0 % 1 > -1 0 % 1 > count(array, false) 0 % 1 >= i 0 % 1 in array != $env 0 % 1 | median(f64) 0 % array?.[i] 0 % i * i 0 % i <= f64 0 % i | mean(f64) 0 * $env.f64 0 * $env.i 0 * $env?.f64 0 * $env?.i 0 * 0 != f64 0 * 0 == i 0 * 0 ?? foo 0 * 1 != i 0 * 1 + f64 0 * 1 < f64 0 * 1 | bitshl(0) 0 * 1.0 != i 0 * 1.0 != nil or ok 0 * 1.0 ** i 0 * 1.0 < f64 0 * array?.[i] 0 * f64 + i 0 * f64 <= f64 0 * f64 == f64 || ok 0 * i != i 0 * i ^ f64 0 * i not in groupBy(array, foo) 0 * i | max(0) 0 ** $env.f64 0 ** $env.i 0 ** $env?.f64 0 ** $env?.i 0 ** 0 != $env?.i 0 ** 0 + $env.i 0 ** 0 >= i 0 ** 0 | max(1.0) 0 ** 1 > i 0 ** 1 | max(1) 0 ** 1.0 ** f64 0 ** 1.0 / f64 0 ** 1.0 < i 0 ** 1.0 == i 0 ** 1.0 > i 0 ** 1.0 >= floor(i) 0 ** 1.0 ?? f64 0 ** 1.0 ^ i 0 ** 1.0 | max(f64) 0 ** array?.[i] 0 ** f64 == nil || false 0 ** f64 >= $env?.f64 0 ** i != f64 0 ** i ?? ok 0 ** i ^ $env?.f64 0 + $env.f64 0 + $env.i 0 + $env?.[str]?.[i] 0 + $env?.f64 0 + $env?.i 0 + 0 != f64 0 + 0 - f64 0 + 0 / i 0 + 0 >= f64 <= $env 0 + 0 ^ i 0 + 0 in array 0 + 1 + i 0 + 1 <= $env.i 0 + 1 <= f64 0 + 1 == $env.f64 0 + 1 | min(0) 0 + 1.0 + i 0 + 1.0 <= f64 0 + 1.0 > f64 0 + 1.0 >= i 0 + 1.0 ?? i 0 + 1.0 ^ f64 0 + array?.[i] 0 + f64 > i 0 + i != f64 0 + i * f64 0 + i ** i 0 + i < $env?.f64 0 - $env.f64 0 - $env.i 0 - $env?.f64 0 - $env?.i 0 - 0 != bitand(0, i) 0 - 0 < f64 0 - 0 == i 0 - 1 ** f64 0 - 1 + f64 0 - 1 < $env.i 0 - 1 < sum(array) 0 - 1 >= -f64 0 - 1 ?? array 0 - 1 ?? str 0 - 1.0 + i 0 - array?.[i] 0 - f64 <= f64 0 - f64 > f64 0 - f64 >= f64 * i 0 - f64 >= i 0 - i ?? f64 0 - i ?? foo 0 - nil ?? i 0 .. $env.i 0 .. $env?.i 0 .. 0 ?? toJSON(i) 0 .. 0 | find(ok) 0 .. 0 | map(#) 0 .. 0 | map(#index) 0 .. 0 | map(true) 0 .. 0 | max(1.0) 0 .. 0 | reduce(#) 0 .. 0 | reduce(str) 0 .. 1 | get(1) 0 .. 1 | map(#) 0 .. 1 | map(array) 0 .. 1 | map(foo) 0 .. 1 | reduce(#) 0 .. 1 | reduce($env) 0 .. 1 | reduce(add) 0 .. 1 | sortBy(#) 0 .. 1 | sum(#) 0 .. 1.0 ?? foo 0 .. array?.[i] 0 .. i | any(false) 0 .. i | groupBy(foo) 0 .. i | map(str) 0 .. i | median(f64) 0 .. i | one(false) 0 .. i | reduce(list, add) 0 .. i | sortBy(1) 0 / $env != 1 and false 0 / $env.f64 0 / $env.f64 ** f64 0 / $env.i 0 / $env?.f64 0 / $env?.i 0 / 0 * i 0 / 0 + ceil(1.0) 0 / 0 / i 0 / 0 > f64 0 / 1 / f64 0 / 1 == $env?.String 0 / 1.0 * f64 0 / 1.0 + $env.i 0 / 1.0 > f64 0 / 1.0 ?? $env ?? i 0 / 1.0 ?? date(nil, foo) 0 / 1.0 ?? foo 0 / 1.0 ?? list ?? 1.0 0 / array?.[i] 0 / f64 - f64 0 / f64 <= f64 0 / f64 | median(f64) 0 / i + i 0 / i / 1.0 ?? 0 0 / i <= 0 != nil 0 / i == f64 0 / i > f64 0 / i ?? i 0 / i not in concat(list) 0 < $env.f64 0 < $env.i 0 < $env?.[str]?.[f64] 0 < $env?.f64 0 < $env?.i 0 < 0 != ok 0 < 0 + len(str) 0 < 0 ?? date(1) 0 < 0 ?? ok 0 < 1 % i 0 < 1 - i 0 < 1 >= i 0 < 1 ^ median(1.0) 0 < 1 and foo ?? 1.0 0 < 1.0 * 1 != false 0 < 1.0 - f64 0 < 1.0 / i 0 < 1.0 <= i 0 < 1.0 > i 0 < array?.[i] 0 < f64 + i 0 < f64 - f64 0 < f64 ? array : list 0 < f64 ?? array 0 < f64 ^ 0 / i 0 < f64 || $env?.ok 0 < i + i 0 < i < i 0 < i <= reduce(array, #) 0 <= $env.f64 0 <= $env.i 0 <= $env?.f64 0 <= $env?.i 0 <= 0 ?? ok 0 <= 1 * i 0 <= 1 <= f64 0 <= 1 ^ f64 0 <= 1 or $env != 1 0 <= 1.0 * f64 0 <= array?.[i] 0 <= f64 - f64 or $env 0 <= f64 > f64 0 <= f64 ?? add 0 <= f64 or !$env 0 <= i % i 0 <= i ^ 1.0 <= 1.0 0 <= i || ok 0 <= nil ?? f64 0 == $env == 0 ?? 1.0 0 == $env or $env.ok 0 == $env or ok 0 == $env || ok 0 == $env.f64 0 == $env.i 0 == $env?.Bar 0 == $env?.Bar?.foo 0 == $env?.String 0 == $env?.String?.str 0 == $env?.[Bar | get(foo)] 0 == $env?.[Bar] 0 == $env?.[String] 0 == $env?.[first(0, ok)] 0 == $env?.[foobar] 0 == $env?.[foobar]?.add 0 == $env?.[str] 0 == $env?.f64 0 == $env?.i 0 == 0 * f64 0 == 0 * i 0 == 0 not in $env?.foobar 0 == 1.0 && f64 + $env 0 == 1.0 / i 0 == add ?? f64 0 == array?.[i] 0 == f64 - 1 and false 0 == f64 ?: add 0 == f64 ?? ok 0 == false ?? str 0 == foo ?? $env?.add 0 == i and $env?.[foo] 0 == nil and $env matches str 0 == str ?? greet 0 == true ?? list 0 > $env.f64 0 > $env.i 0 > $env?.[str]?.[f64] 0 > $env?.f64 0 > $env?.i 0 > 0 * f64 0 > 0 / i 0 > 0 == ok 0 > 0 > ceil($env) 0 > 0 or foo == nil 0 > 1 - i 0 > 1.0 != str ?? i 0 > 1.0 ** f64 0 > 1.0 / f64 0 > 1.0 >= f64 or ok 0 > 1.0 ^ f64 0 > array?.[i] 0 > f64 > $env?.[Bar] 0 > f64 > f64 0 > f64 ?? f64 0 > f64 and $env?.[greet] 0 > i > i 0 > i and foo == nil 0 >= $env.f64 0 >= $env.i 0 >= $env?.f64 0 >= $env?.i 0 >= 0 ** i 0 >= 0 ?? list 0 >= 0 or str != nil 0 >= 1 >= i 0 >= 1 ?? add 0 >= 1 ?? i 0 >= 1.0 ** i 0 >= 1.0 / 1 ** 1 0 >= 1.0 ?? list 0 >= 1.0 ?? ok 0 >= 1.0 ^ i 0 >= 1.0 and ok 0 >= 1.0 or ok 0 >= array?.[i] 0 >= f64 ** f64 0 >= f64 + f64 0 >= f64 <= $env?.i 0 >= f64 >= $env?.[foo] 0 >= i > i 0 >= i >= 1.0 - $env 0 >= nil ?? f64 0 ?? $env ?? str 0 ?? $env | max(1.0) 0 ?? $env.add 0 ?? $env.array 0 ?? $env.foo 0 ?? $env.greet 0 ?? $env.i 0 ?? $env.list 0 ?? $env.ok 0 ?? $env.str 0 ?? $env?.Bar 0 ?? $env?.String 0 ?? $env?.String() 0 ?? $env?.String(greet()) 0 ?? $env?.[Bar] 0 ?? $env?.[String] 0 ?? $env?.[String].String 0 ?? $env?.[add(0)] 0 ?? $env?.[add] 0 ?? $env?.[add]?.[array] 0 ?? $env?.[array] 0 ?? $env?.[date($env)] 0 ?? $env?.[f64] 0 ?? $env?.[foo] 0 ?? $env?.[greet] 0 ?? $env?.[i] 0 ?? $env?.[list] 0 ?? $env?.[nil | date(1, foobar)] 0 ?? $env?.[ok] 0 ?? $env?.[str] 0 ?? $env?.add 0 ?? $env?.array 0 ?? $env?.f64 0 ?? $env?.foo 0 ?? $env?.foobar 0 ?? $env?.greet 0 ?? $env?.i 0 ?? $env?.list 0 ?? $env?.ok 0 ?? $env?.str 0 ?? $env[:String matches $env] 0 ?? $env[:add(greet, str)] 0 ?? $env[:count(foo)] 0 ?? $env[:foo] 0 ?? $env[:foobar and foobar] 0 ?? $env[:foobar | filter(#.i)] 0 ?? $env[:foobar.add] 0 ?? $env[:greet.ok] 0 ?? $env[String():add(list)] 0 ?? $env[i:foobar] 0 ?? 1 ?? i 0 ?? 1 ?? str 0 ?? 1.0 ?? i 0 ?? add ?? i 0 ?? array?.[array?.[i]] 0 ?? array?.[i] 0 ?? f64 | mean(0) 0 ?? foo | get(foo) 0 ?? foo.Bar 0 ?? foo.String 0 ?? foo.String() 0 ?? foo?.Bar 0 ?? foo?.String 0 ?? foo?.String() 0 ?? i ?? foo 0 ?? list ?? greet 0 ?? list?.[i] 0 ?? ok ?? i 0 ?? true ?? foo 0 ^ $env.f64 0 ^ $env.i 0 ^ $env?.f64 0 ^ $env?.i 0 ^ 1 * i 0 ^ 1 ** i 0 ^ 1 / f64 0 ^ 1.0 != $env?.f64 0 ^ 1.0 != i 0 ^ 1.0 + f64 0 ^ 1.0 / f64 0 ^ 1.0 >= f64 0 ^ 1.0 ?? $env.ok 0 ^ 1.0 ?? 1.0 > f64 0 ^ 1.0 in array 0 ^ array?.[i] 0 ^ f64 == i 0 ^ i == i 0 ^ i ?? i 0 in $env.array 0 in $env?.Bar 0 in $env?.Bar?.greet 0 in $env?.String 0 in $env?.[Bar] 0 in $env?.[String] 0 in $env?.[String]?.array 0 in $env?.array 0 in array != ok 0 in nil ?? array 0 not in $env.array 0 not in $env?.Bar 0 not in $env?.String 0 not in $env?.String?.[array] 0 not in $env?.[Bar] 0 not in $env?.[String] 0 not in $env?.[foobar] 0 not in $env?.array 0 not in $env?.foobar 0 | add(0) ^ f64 0 | bitnand(0) > i 0 | bitor($env) == 1 and false 0 | bitshl(1) / f64 0 | bitshr(0); array; greet 0 | bitxor(0) in array 0 | max(0) in array 0 | max(array, 1.0) - floor(i) 0 | mean(i) ?? f64 0 | min(0) | mean(1) 0 | min(1) ** f64 0..array?.[i] 0..i | count(true) 0..i | groupBy(#) 0..i | groupBy(f64) 0..i | map(1.0) 0..i | map(list) 0.0 != f64 0.0 + 0 == $env 0.1 != floor(1.0) 0.1 | mean(f64) 0.1 | min(1.0) 0; $env.add 0; $env?.add 1 != $env not in [true] 1 != $env.f64 1 != $env.i 1 != $env?.Bar 1 != $env?.Bar?.array 1 != $env?.String 1 != $env?.String?.f64 1 != $env?.[Bar] 1 != $env?.[Bar]?.f64 1 != $env?.[Bar]?.greet 1 != $env?.[String] 1 != $env?.[foobar] 1 != $env?.[str] 1 != $env?.f64 1 != $env?.foobar 1 != $env?.i 1 != 0 * f64 1 != 0 ?? list 1 != 1 - f64 1 != 1 ?? list 1 != 1 ?? ok 1 != 1.0 && 0 == 1.0 1 != 1.0 + i 1 != 1.0 ^ f64 1 != array ?? list 1 != array?.[i] 1 != f64 && $env?.[str] 1 != f64 ** f64 1 != f64 || $env?.[ok] 1 != f64 || ok 1 != false ?? foo 1 != foo ?? f64 1 != i != ok 1 != i + f64 1 != i - f64 1 != i ?? greet 1 != i ^ f64 1 != list ?? array ?: list 1 != nil or ok 1 % $env.i 1 % $env?.i 1 % 1 > f64 1 % 1 ?? list 1 % array?.[i] 1 % i + f64 1 % i < f64 1 % i >= i 1 * $env.f64 1 * $env.i 1 * $env.i + f64 1 * $env?.f64 1 * $env?.i 1 * 0 / f64 1 * 0 < f64 1 * 0 == {foo: 1.0}?.array 1 * 0 not in $env?.[Bar] 1 * 0 | bitushr(0) 1 * 1 == i 1 * 1 | bitnand(0) 1 * 1 | min(f64) 1 * 1.0 * 1.0 * i 1 * 1.0 ** $env.i 1 * 1.0 < f64 1 * 1.0 <= ceil(0) 1 * 1.0 <= f64 1 * 1.0 ?? foo 1 * array?.[i] 1 * f64 * f64 1 * f64 * i 1 * f64 / min(0) 1 * f64 ^ f64 - 1 1 * f64 | mean(1) 1 * i + bitnot(0) 1 * i - f64 1 * i / i 1 * i | bitxor(i) 1 * nil ?? $env?.f64 1 ** $env.f64 1 ** $env.i 1 ** $env?.f64 1 ** $env?.f64 ?? list 1 ** $env?.i 1 ** 0 ** i 1 ** 0 / i 1 ** 0 == ceil(1) 1 ** 0 > f64 1 ** 0 ?? list 1 ** 1 != i 1 ** 1 ** i 1 ** 1.0 != f64 1 ** 1.0 ?? $env == f64 1 ** 1.0 ?? groupBy(list, ok) 1 ** 1.0 in array 1 ** 1.0 | mean(array) 1 ** array?.[i] 1 ** f64 - array?.[i] 1 ** f64 | median(i) 1 ** i + f64 1 ** i < 1.0 + 0 1 ** i <= i 1 ** nil ?? i 1 ** nil ?? mean(0) 1 + $env.f64 1 + $env.i 1 + $env?.f64 1 + $env?.i 1 + 0 ** i 1 + 0 | bitor(i) 1 + 1 % i 1 + 1 >= f64 ^ 0 1 + 1 not in array 1 + 1.0 != i 1 + 1.0 * f64 1 + 1.0 - i 1 + 1.0 < f64 1 + 1.0 ?? foo 1 + 1.0 ?? greet > f64 1 + 1.0 ?? ok 1 + 1.0 ^ i 1 + 1.0 | max(1) 1 + f64 ?? greet 1 + f64 ^ i ** 1 1 + f64 in array 1 + f64 | max(array) 1 + f64 | median(array) 1 + i < f64 1 + i < i 1 + i..i 1 - $env.f64 1 - $env.i 1 - $env?.f64 1 - $env?.i 1 - 0 > i 1 - 0 ?? list 1 - 1 == f64 1 - 1 | median(1, 1.0) 1 - 1.0 ** f64 1 - 1.0 + f64 1 - 1.0 / i 1 - 1.0 == 1.0 == $env 1 - 1.0 ?? i 1 - 1.0 ?? not true 1 - 1.0 in array 1 - 1.0 not in array 1 - array?.[i] 1 - f64 / i 1 - f64 > f64 1 - f64 >= 1.0 < 1 1 - f64 ?? add 1 - f64 ^ f64 1 - f64 | min(array) 1 - i / f64 1 - i > i 1 - i ^ i 1 - i | min(1.0) 1 .. $env.i 1 .. $env?.i 1 .. 0 | all($env) 1 .. 0 | filter(true) 1 .. 0 | groupBy(#) 1 .. 0 | groupBy(foo) 1 .. 0 | one($env) 1 .. 0 | sortBy(#) 1 .. 0 | sortBy($env) 1 .. 0 | sortBy(str) 1 .. 0 | sum(greet) 1 .. 1 ?? array 1 .. 1 | filter(ok) 1 .. 1 | findLast(true) 1 .. 1 | map(#) 1 .. 1 | map($env) 1 .. 1 | map(foo) 1 .. 1 | sum(1.0) 1 .. array?.[i] 1 .. i - i 1 .. i ?? i 1 .. i ?? ok 1 .. i | groupBy(#) 1 .. i | groupBy(foo) 1 .. i | groupBy(ok) 1 .. i | reduce(foo) 1 / $env.array?.[i] 1 / $env.f64 1 / $env.i 1 / $env?.f64 1 / $env?.i 1 / 0 ?? foo 1 / 1 * f64 1 / 1 > f64 1 / 1 ^ i 1 / 1 in [nil] 1 / 1.0 * $env?.f64 1 / 1.0 ** i 1 / 1.0 <= f64 1 / 1.0 == i || ok 1 / 1.0 > 1.0 != nil 1 / 1.0 ?? f64 1 / array?.[i] 1 / f64 - f64 1 / f64 >= f64 1 / i != i 1 / i + 1.0 / 1 1 / i + i 1 / i ?? i 1 < $env.f64 1 < $env.i 1 < $env?.f64 1 < $env?.f64 && ok 1 < $env?.i 1 < 0 && ok 1 < 0 - f64 1 < 0 - f64 ?? foo 1 < 0 <= $env?.[str] 1 < 0 ?? i 1 < 0 ^ i ** 1.0 1 < 1 * f64 1 < 1 < f64 1 < 1 ?: array 1 < 1 ?? f64 1 < 1 ?? i 1 < 1 ^ sum(array) 1 < 1.0 < i 1 < 1.0 > $env?.[false] 1 < 1.0 ?? add 1 < 1.0 ?? greet 1 < 1.0 ?? str 1 < array?.[i] 1 < f64 / f64 1 < f64 > 0 ** i 1 < f64 >= $env?.i 1 < i > i 1 < i ? ok : ok 1 < i ?? f64 1 < i or min($env) 1 <= $env.f64 1 <= $env.i 1 <= $env?.f64 1 <= $env?.i 1 <= 0 - i 1 <= 0 ?: greet 1 <= 0 and ok 1 <= 1 * i 1 <= 1 / f64 1 <= 1 == true or true 1 <= 1.0 == $env?.[Bar] 1 <= 1.0 >= f64 1 <= 1.0 ?? array 1 <= array?.[i] 1 <= f64 + i 1 <= f64 - f64 1 <= f64 or ok 1 <= i / i 1 <= i ^ i 1 == $env || ok 1 == $env.f64 1 == $env.i 1 == $env?.Bar 1 == $env?.Bar?.Bar 1 == $env?.String 1 == $env?.String?.[greet] 1 == $env?.[Bar] 1 == $env?.[String] 1 == $env?.[foobar] 1 == $env?.[foobar]?.[greet] 1 == $env?.[str] 1 == $env?.f64 1 == $env?.i 1 == $env?.not 1 == 1 ^ i 1 == 1.0 - $env.i 1 == 1.0 - f64 1 == 1.0 - i 1 == 1.0 ?? 1.0 ?? ok 1 == 1.0 and ok 1 == 1.0 or $env[:foobar] 1 == array?.[i] 1 == f64 && list == $env 1 == f64 * f64 ** 1.0 1 == f64 ?: greet 1 == f64 ?? -$env 1 == f64 ^ f64 1 == foo ?? list 1 == foo ?? str 1 == i != $env?.String 1 == i - f64 1 == i || $env?.[add] 1 == nil != ok 1 == ok ?? foo 1 == str ?? array 1 > $env.f64 1 > $env.i 1 > $env?.f64 1 > $env?.i 1 > 0 != ok 1 > 0 * f64 1 > 0 <= i or $env 1 > 0 ?? foo 1 > 1 or nil != str 1 > 1.0 / i 1 > 1.0 <= -$env 1 > 1.0 <= array?.[i] 1 > 1.0 <= i 1 > 1.0 >= $env.i 1 > 1.0 >= $env[true:1] 1 > 1.0 ^ min(array) 1 > array?.[i] 1 > f64 ** i 1 > i % i 1 > i - i 1 > i / i 1 > i <= f64 1 > i ?? i 1 >= $env.f64 1 >= $env.i 1 >= $env?.f64 1 >= $env?.i 1 >= 0 && $env?.String 1 >= 0 * i 1 >= 0 == ok 1 >= 0 >= f64 1 >= 1 <= f64 1 >= 1 <= i 1 >= 1 ?? greet 1 >= 1.0 ** f64 1 >= 1.0 > float(1) 1 >= 1.0 >= i 1 >= 1.0 ?: list 1 >= 1.0 or $env.ok 1 >= array?.[i] 1 >= f64 > sum($env, 1) 1 >= f64 ?? array 1 >= i ** i 1 >= i >= i 1 ?? $env | get(ok) 1 ?? $env | max(1.0) 1 ?? $env.add 1 ?? $env.array 1 ?? $env.array?.[i] 1 ?? $env.f64 1 ?? $env.foo 1 ?? $env.greet 1 ?? $env.i 1 ?? $env.list 1 ?? $env.ok 1 ?? $env.str 1 ?? $env?.Bar 1 ?? $env?.Bar() 1 ?? $env?.Bar?.[f64] 1 ?? $env?.String 1 ?? $env?.String() 1 ?? $env?.String(nil) 1 ?? $env?.[Bar] 1 ?? $env?.[Bar]?.[add] 1 ?? $env?.[String] 1 ?? $env?.[add] 1 ?? $env?.[array] 1 ?? $env?.[f64()] 1 ?? $env?.[f64] 1 ?? $env?.[f64].f64.greet 1 ?? $env?.[foo(true)] 1 ?? $env?.[foo] 1 ?? $env?.[greet] 1 ?? $env?.[greet]?.[str] 1 ?? $env?.[i] 1 ?? $env?.[i]?.[foo] 1 ?? $env?.[list] 1 ?? $env?.[list]?.Bar 1 ?? $env?.[ok] 1 ?? $env?.[ok].str 1 ?? $env?.[ok]?.[str] 1 ?? $env?.[str] 1 ?? $env?.[str].Bar 1 ?? $env?.add 1 ?? $env?.array 1 ?? $env?.f64 1 ?? $env?.foo 1 ?? $env?.foobar 1 ?? $env?.foobar.greet 1 ?? $env?.foobar?.[f64]?.array() 1 ?? $env?.foobar?.list() 1 ?? $env?.greet 1 ?? $env?.i 1 ?? $env?.list 1 ?? $env?.ok 1 ?? $env?.round(foobar) 1 ?? $env?.str 1 ?? $env[:String | ceil(foobar)] 1 ?? $env[:foobar == foobar].foo 1 ?? $env[:foobar?.array(foobar)] 1 ?? $env[:str] 1 ?? $env[String <= false:foobar < foo] 1 ?? $env[String():]?.list 1 ?? $env[list():] 1 ?? $env[ok(foobar):] 1 ?? $env[reverse(0):] 1 ?? 1 ?? array 1 ?? 1.0 ?? greet 1 ?? 1.0 | bitnand(i) 1 ?? 1.0 | mean(f64) 1 ?? add ?? f64 1 ?? array ?? f64 1 ?? false ?? f64 1 ?? foo ?? array 1 ?? foo ?? str 1 ?? foo | max(1) 1 ?? foo.Bar 1 ?? foo.String 1 ?? foo.String() 1 ?? foo?.Bar 1 ?? foo?.String 1 ?? foo?.String() 1 ?? i ?? array 1 ?? list?.[i] 1 ?? ok | get(true) 1 ^ $env.f64 1 ^ $env.i 1 ^ $env?.f64 1 ^ $env?.i 1 ^ 0 ** i 1 ^ 0 >= i 1 ^ 1 - i 1 ^ 1 > f64 1 ^ 1 ?? foo?.String 1 ^ 1 in $env.array 1 ^ 1 in array 1 ^ 1 not in array 1 ^ 1.0 + f64 1 ^ 1.0 + i - 0 1 ^ 1.0 == f64 ?? 1.0 1 ^ 1.0 == i 1 ^ 1.0 > i 1 ^ 1.0 ?? array 1 ^ 1.0 ?? foo 1 ^ 1.0 ?? list 1 ^ 1.0 ?? {foo: foo} 1 ^ 1.0 ^ f64 1 ^ 1.0 ^ int(1.0) 1 ^ 1.0 ^ round(0) 1 ^ array?.[i] 1 ^ f64 != $env.f64 1 ^ f64 - ceil(1.0) 1 ^ f64 | min(1) 1 ^ i ** i 1 in $env.array 1 in $env?.Bar 1 in $env?.String 1 in $env?.[Bar] 1 in $env?.[Bar]?.[array] 1 in $env?.[Bar]?.f64 1 in $env?.[String] 1 in $env?.array 1 in $env?.foobar 1 in array ?? foo 1 in array || false ? 1 : foo 1 in array || ok 1 not in $env.array 1 not in $env?.$env?.list 1 not in $env?.Bar 1 not in $env?.Bar?.[i] 1 not in $env?.Bar?.add 1 not in $env?.String 1 not in $env?.String?.[foo] 1 not in $env?.[Bar] 1 not in $env?.[String] 1 not in $env?.[String]?.f64 1 not in $env?.[foobar] 1 not in $env?.array 1 not in $env?.foobar 1 not in $env?.foobar?.String(foobar) 1 not in $env?.foobar?.[array] 1 not in list ?? add 1 not in nil ?? array 1 | bitand(i) ?? $env?.[foo] 1 | bitshl(0) != f64 1 | bitshl(1) != f64 1 | bitxor(1) >= i 1 | mean(1) < 0 ?? 1.0 1 | min(1.0) + i 1..array?.[i] 1..i != array 1..i | all(true) 1..i | map(#) 1..i | map(0) 1..i | reduce(array) 1.0 != $env ?? foo 1.0 != $env.f64 1.0 != $env.i 1.0 != $env?.Bar 1.0 != $env?.Bar?.[array] 1.0 != $env?.Bar?.str 1.0 != $env?.String 1.0 != $env?.String?.[add] 1.0 != $env?.String?.[i] 1.0 != $env?.String?.[ok] 1.0 != $env?.[Bar] 1.0 != $env?.[String] 1.0 != $env?.[String]?.greet() 1.0 != $env?.[foobar?.add($env)]?.greet 1.0 != $env?.[foobar?.add] 1.0 != $env?.[foobar] 1.0 != $env?.[foobar]?.[array] 1.0 != $env?.[str] 1.0 != $env?.f64 1.0 != $env?.foobar 1.0 != $env?.foobar?.list 1.0 != $env?.i 1.0 != $env?.not 1.0 != 0 != ok 1.0 != 0 - f64 1.0 != 0 / abs(1.0) 1.0 != 0 ?? add 1.0 != 0 ?? str 1.0 != 0.-1.0 1.0 != 1 != ok 1.0 != 1 / i 1.0 != 1 ?: foo 1.0 != 1.0 ** i 1.0 != 1.0 / abs(1.0) 1.0 != 1.0 == ok 1.0 != 1.0 ^ $env.f64 1.0 != 1.0 ^ f64 1.0 != 1.0 and $env not endsWith $env 1.0 != add ?? greet 1.0 != add ?? {foo: 1} 1.0 != array?.[i] 1.0 != f64 && ok 1.0 != false ?? $env?.[list] 1.0 != foo ?? array?.[i] 1.0 != foo ?? count($env, false) 1.0 != foo ?? greet 1.0 != i % i 1.0 != i * f64 1.0 != i / i 1.0 != i ^ f64 1.0 != i or ok 1.0 != list ?? array 1.0 != nil ?? 1 ?? foo 1.0 != nil or reduce($env, #.str)?.[str] 1.0 != str ?? array 1.0 != true ?? $env.add 1.0 != true ?? array 1.0 != true ?? f64 1.0 * $env.array?.[i] 1.0 * $env.f64 1.0 * $env.i 1.0 * $env?.f64 1.0 * $env?.i 1.0 * 0 + f64 1.0 * 0 / f64 != nil 1.0 * 0 <= f64 1.0 * 0 == f64 1.0 * 0 >= i 1.0 * 0 ^ f64 1.0 * 1 != i 1.0 * 1 != max($env) 1.0 * 1 ** i 1.0 * 1 ?? add 1.0 * 1 ?? list 1.0 * 1 ?? ok 1.0 * 1 | max(f64) 1.0 * 1.0 != i 1.0 * 1.0 / f64 1.0 * 1.0 <= f64 1.0 * 1.0 > f64 1.0 * 1.0 > i 1.0 * 1.0 >= 0 == nil 1.0 * 1.0 >= i 1.0 * 1.0 ?? f64 1.0 * 1.0 | mean(array) 1.0 * 1.0 | median(1.0) 1.0 * 1.0 | min(1.0) 1.0 * array?.[i] 1.0 * f64 * i 1.0 * f64 - i 1.0 * f64 - max(1, array) 1.0 * f64 == f64 1.0 * f64 == sum(array) 1.0 * f64 ?? f64 1.0 * f64 ?? greet 1.0 * f64 | max(1.0) 1.0 * i + f64 1.0 * i >= 1.0 ^ 1 1.0 * i ?? ok 1.0 * i not in array 1.0 * i | median(1.0) 1.0 ** $env.f64 1.0 ** $env.i 1.0 ** $env?.f64 1.0 ** $env?.i 1.0 ** 0 - 1.0 in array 1.0 ** 0 - i 1.0 ** 0 / i 1.0 ** 0 < i 1.0 ** 0 <= f64 1.0 ** 0 == f64 1.0 ** 0 == i 1.0 ** 0 > i 1.0 ** 0 ?? str 1.0 ** 0 ^ 0 ** 0 1.0 ** 0 | median(1) 1.0 ** 1 ** $env.i 1.0 ** 1 / 1.0 ?? foo 1.0 ** 1 ^ i 1.0 ** 1.0 != i 1.0 ** 1.0 * i 1.0 ** 1.0 ** -1.0 1.0 ** 1.0 < 0 != false 1.0 ** 1.0 < i 1.0 ** 1.0 ?? array 1.0 ** 1.0 ?? foo 1.0 ** 1.0 ?? greet 1.0 ** 1.0 ?? list 1.0 ** 1.0 ?? nil ?? foo 1.0 ** 1.0 ?? upper($env) 1.0 ** 1.0 | median(1.0) 1.0 ** array?.[i] 1.0 ** f64 1.0 ** f64 != f64 1.0 ** f64 * f64 1.0 ** f64 * i 1.0 ** f64 - f64 1.0 ** f64 / i 1.0 ** f64 >= f64 1.0 ** f64 ?? ok 1.0 ** f64 | median(i) 1.0 ** f64 | min(1) 1.0 ** i - -0 1.0 ** i - float(f64) 1.0 ** i / f64 1.0 ** i <= i * 1.0 1.0 ** nil ?? f64 1.0 + $env.f64 1.0 + $env.i 1.0 + $env?.f64 1.0 + $env?.i 1.0 + 0 != i 1.0 + 0 + f64 1.0 + 0 / reduce(array, i) 1.0 + 0 < round(1) 1.0 + 0 ?? add 1.0 + 1 ?? f64 1.0 + 1 not in array 1.0 + 1 | median(1.0) 1.0 + 1.0 + i 1.0 + 1.0 - i 1.0 + 1.0 <= i 1.0 + 1.0 ?? add 1.0 + 1.0 ^ f64 1.0 + 1.0 ^ i 1.0 + 1.0 in $env?.Bar 1.0 + 1.0 not in array 1.0 + 1.0 | mean(1) 1.0 + 1.0 | median(1.0) 1.0 + array?.[i] 1.0 + f64 / f64 1.0 + f64 / i 1.0 + f64 < i 1.0 + f64 == i 1.0 + f64 >= f64 1.0 + i / f64 1.0 + i < f64 1.0 + i > i 1.0 + i >= i 1.0 + i ?? greet == foo 1.0 - $env.f64 1.0 - $env.i 1.0 - $env?.f64 1.0 - $env?.f64 == 1.0 1.0 - $env?.i 1.0 - 0 != f64 1.0 - 0 * f64 1.0 - 0 >= f64 1.0 - 0 ?? str 1.0 - 1 + 1.0 == nil 1.0 - 1 - i 1.0 - 1 - min(1.0) 1.0 - 1 / i 1.0 - 1 > i and $env 1.0 - 1 not in array 1.0 - 1.0 != f64 1.0 - 1.0 ** f64 1.0 - 1.0 + f64 1.0 - 1.0 < f64 1.0 - 1.0 <= i 1.0 - 1.0 == f64 1.0 - 1.0 == i 1.0 - 1.0 > f64 1.0 - 1.0 >= f64 1.0 - 1.0 ?? ok 1.0 - 1.0 in array 1.0 - 1.0 in array ?: i 1.0 - 1.0 | median(0) 1.0 - array?.[i] 1.0 - f64 != f64 1.0 - f64 * i 1.0 - f64 - f64 1.0 - f64 / i 1.0 - f64 in array 1.0 - i * $env.i 1.0 - i ** -i 1.0 - i < i 1.0 - i ^ f64 1.0 - i ^ i 1.0 / $env.f64 1.0 / $env.i 1.0 / $env?.f64 1.0 / $env?.i 1.0 / 0 != i 1.0 / 0 * $env?.f64 1.0 / 0 + f64 1.0 / 0 - i 1.0 / 0 < i 1.0 / 0 <= 1 + f64 1.0 / 0 == f64 1.0 / 0 == i 1.0 / 0 > $env?.f64 1.0 / 0 ?? list 1.0 / 0 | median(f64, i) 1.0 / 0 | min(1.0) 1.0 / 1 != find($env, false) 1.0 / 1 * f64 1.0 / 1 ** i 1.0 / 1 > f64 1.0 / 1 >= f64 1.0 / 1.0 != f64 1.0 / 1.0 + i 1.0 / 1.0 + min(0) 1.0 / 1.0 - f64 1.0 / 1.0 / f64 1.0 / 1.0 <= f64 1.0 / 1.0 == i 1.0 / 1.0 > f64 1.0 / 1.0 > i 1.0 / 1.0 >= f64 1.0 / 1.0 ?? 0 + 1 1.0 / 1.0 ?? i 1.0 / 1.0 ^ f64 1.0 / 1.0 ^ i 1.0 / array?.[i] 1.0 / f64 * i 1.0 / f64 <= f64 || true 1.0 / f64 ?? one($env, #.foo) 1.0 / f64 ^ i 1.0 / f64 in array 1.0 / i ** i 1.0 / i / i != nil 1.0 / i < f64 1.0 / i <= i 1.0 / i == i 1.0 < $env.add(0, i) 1.0 < $env.f64 1.0 < $env.i 1.0 < $env?.f64 1.0 < $env?.i 1.0 < 1 <= f64 1.0 < 1 > $env?.[greet] 1.0 < 1 > f64 1.0 < 1 >= i 1.0 < 1 ?? ok 1.0 < 1.0 != ok 1.0 < 1.0 && $env?.String(foobar, i) 1.0 < 1.0 && $env?.[ok] 1.0 < 1.0 ** f64 1.0 < 1.0 - i 1.0 < 1.0 / round(1.0) 1.0 < 1.0 <= $env?.String 1.0 < 1.0 <= i 1.0 < 1.0 == $env && true 1.0 < 1.0 == ok 1.0 < 1.0 > round($env) 1.0 < 1.0 >= 1.0 == ok 1.0 < 1.0 ? foo != nil : str 1.0 < 1.0 ?? $env?.[greet] 1.0 < 1.0 ?? f64 1.0 < 1.0 ?? foo 1.0 < 1.0 ^ f64 1.0 < 1.0 ^ i 1.0 < 1.0 || ok 1.0 < array?.[i] 1.0 < f64 + $env.i 1.0 < f64 + i 1.0 < f64 - f64 1.0 < f64 - i ?? add 1.0 < f64 < $env?.[ok] 1.0 < f64 ?: i 1.0 < f64 ^ f64 1.0 < i != ok 1.0 < i / f64 1.0 < i > f64 1.0 < i > i 1.0 < i >= -1.0 1.0 < i >= i 1.0 < i ?: 1 == i 1.0 < i ?: list 1.0 < i ^ f64 1.0 <= $env.f64 1.0 <= $env.i 1.0 <= $env?.f64 1.0 <= $env?.i 1.0 <= 0 % i 1.0 <= 0 - f64 1.0 <= 0 / f64 1.0 <= 0 / i 1.0 <= 0 < f64 <= f64 1.0 <= 0 >= i 1.0 <= 0 ? f64 : greet 1.0 <= 0 ?? array 1.0 <= 0 ?? duration($env) 1.0 <= 0 or ok 1.0 <= 1 ** f64 ^ 1 1.0 <= 1 ** i 1.0 <= 1 / $env?.i 1.0 <= 1 / i 1.0 <= 1 < -i 1.0 <= 1 < f64 < f64 1.0 <= 1 or none($env, $env) 1.0 <= 1.0 != ok 1.0 <= 1.0 && $env?.Bar 1.0 <= 1.0 * f64 1.0 <= 1.0 * i 1.0 <= 1.0 ** 1 and false 1.0 <= 1.0 - f64 1.0 <= 1.0 / mean(f64) 1.0 <= 1.0 < f64 1.0 <= 1.0 <= i 1.0 <= 1.0 == ok == $env 1.0 <= 1.0 > i 1.0 <= 1.0 >= f64 1.0 <= 1.0 or ok 1.0 <= 1.0 || ok 1.0 <= array?.[i] 1.0 <= f64 1.0 <= f64 != ok 1.0 <= f64 && ok 1.0 <= f64 ** 1 ? 1.0 : ok 1.0 <= f64 < $env.f64 1.0 <= f64 < -0 1.0 <= f64 <= f64 1.0 <= f64 >= f64 1.0 <= f64 ?? add 1.0 <= i * $env.f64 1.0 <= i * i 1.0 <= i / i 1.0 <= i or 1 != f64 1.0 <= i or ok != false 1.0 == $env && ok != false 1.0 == $env ?? array 1.0 == $env ^ $env or true 1.0 == $env or ok 1.0 == $env or true ?? nil 1.0 == $env.f64 1.0 == $env.i 1.0 == $env?.Bar 1.0 == $env?.String 1.0 == $env?.[Bar] 1.0 == $env?.[Bar]?.foo 1.0 == $env?.[String] 1.0 == $env?.[String]?.[array] 1.0 == $env?.[String]?.[ok].greet 1.0 == $env?.[foobar?.[f64]] 1.0 == $env?.[foobar] 1.0 == $env?.[greet(Bar)] 1.0 == $env?.[str] 1.0 == $env?.f64 1.0 == $env?.foobar 1.0 == $env?.foobar?.[ok] 1.0 == $env?.i 1.0 == $env?.true != $env 1.0 == 0 != $env || false 1.0 == 0 ?? -0 1.0 == 0 ^ f64 1.0 == 0 or $env?.ok 1.0 == 1 != ok 1.0 == 1 % i 1.0 == 1 * f64 1.0 == 1 - f64 1.0 == 1 - i 1.0 == 1 == ok 1.0 == 1.0 != ok 1.0 == 1.0 * f64 1.0 == 1.0 ** i 1.0 == 1.0 - i 1.0 == 1.0 / f64 1.0 == 1.0 ?? i 1.0 == 1.0 and ok 1.0 == 1.0 in [nil, 1] 1.0 == 1.0 || any($env, true) 1.0 == 1.0 || ok 1.0 == array?.[i] 1.0 == f64 != ok 1.0 == f64 * 0 ?? 0 1.0 == false ?? uniq(array) 1.0 == foo ?? count(array) 1.0 == foo ?? ok 1.0 == i != ok 1.0 == i != ok; nil 1.0 == i * i 1.0 == i + f64 1.0 == i + sum(list, 1.0) 1.0 == i / i 1.0 == i ?? i 1.0 == nil ?: array 1.0 == nil and $env.ok 1.0 == nil or ok 1.0 == ok ?? f64 1.0 == str ?? foo 1.0 > $env * 1.0 || true 1.0 > $env.f64 1.0 > $env.i 1.0 > $env?.f64 1.0 > $env?.i 1.0 > 0 / i 1.0 > 0 < 1 ^ f64 1.0 > 0 < f64 1.0 > 0 < i 1.0 > 0 >= last(array) 1.0 > 0 || ok 1.0 > 1 > find($env, #) 1.0 > 1 >= $env?.[ok] 1.0 > 1 ?: {foo: add, foo: ok}?.foo 1.0 > 1 ?? $env?.str 1.0 > 1 ?? f64 1.0 > 1 ?? nil && $env 1.0 > 1 ^ i 1.0 > 1.0 * array?.[i] 1.0 > 1.0 <= f64 1.0 > 1.0 == ok 1.0 > 1.0 > i 1.0 > 1.0 >= len(str) 1.0 > 1.0 ?? array 1.0 > 1.0 ?? list 1.0 > array?.[i] 1.0 > f64 * f64 1.0 > f64 ** i 1.0 > f64 + f64 1.0 > f64 / i 1.0 > f64 < f64 1.0 > f64 > round(1.0) 1.0 > f64 ?? greet 1.0 > f64 ?? map(list, true) 1.0 > f64 or none($env, .f64) 1.0 > i != str ?? foo 1.0 > i && median($env, foo) 1.0 > i && ok 1.0 > i + 1.0 1.0 > i >= $env?.[String] 1.0 >= $env.f64 1.0 >= $env.i 1.0 >= $env?.[str]?.[f64] 1.0 >= $env?.f64 1.0 >= $env?.i 1.0 >= 0 / i 1.0 >= 1 <= f64 1.0 >= 1 > i 1.0 >= 1 > i >= i 1.0 >= 1 ?? array < 0 1.0 >= 1 in $env?.Bar 1.0 >= 1.0 * f64 1.0 >= 1.0 * f64 or ok 1.0 >= 1.0 + f64 1.0 >= 1.0 / i 1.0 >= 1.0 / sum(array) 1.0 >= 1.0 < f64 1.0 >= 1.0 <= f64 1.0 >= 1.0 == {foo: $env, foo: $env}.foo 1.0 >= 1.0 > i 1.0 >= 1.0 ?: list 1.0 >= 1.0 ?? greet 1.0 >= 1.0 ?? list 1.0 >= 1.0 ^ f64 1.0 >= 1.0 and f64 ?? foo 1.0 >= array?.[i] 1.0 >= f64 ** $env?.i 1.0 >= f64 ** 0 > 1.0 1.0 >= f64 + i 1.0 >= f64 - i 1.0 >= f64 / i 1.0 >= f64 > f64 1.0 >= f64 not in $env?.[String] 1.0 >= i * f64 1.0 >= i * i 1.0 >= i + 1.0 >= $env 1.0 >= i - i 1.0 >= i < $env?.i 1.0 >= i == $env?.[Bar] 1.0 >= i == not false 1.0 >= i ?? array 1.0 >= i and not ok 1.0 ?? $env ?? list 1.0 ?? $env.add 1.0 ?? $env.array 1.0 ?? $env.f64 1.0 ?? $env.foo 1.0 ?? $env.greet 1.0 ?? $env.i 1.0 ?? $env.list 1.0 ?? $env.ok 1.0 ?? $env.str 1.0 ?? $env?.$env?.$env 1.0 ?? $env?.$env?.array 1.0 ?? $env?.Bar 1.0 ?? $env?.Bar() 1.0 ?? $env?.String 1.0 ?? $env?.String() 1.0 ?? $env?.String?.f64 1.0 ?? $env?.String?.ok() 1.0 ?? $env?.[$env?.[foobar]] 1.0 ?? $env?.[1.0 >= list] 1.0 ?? $env?.[1.0 not in array] 1.0 ?? $env?.[Bar] 1.0 ?? $env?.[Bar]?.[list] 1.0 ?? $env?.[String] 1.0 ?? $env?.[String]?.[add] 1.0 ?? $env?.[String]?.ok 1.0 ?? $env?.[add] 1.0 ?? $env?.[add].str 1.0 ?? $env?.[array < array] 1.0 ?? $env?.[array] 1.0 ?? $env?.[array].greet 1.0 ?? $env?.[count(1)] 1.0 ?? $env?.[f64(ok)] 1.0 ?? $env?.[f64] 1.0 ?? $env?.[filter(foobar, foobar)] 1.0 ?? $env?.[findIndex(ok, #acc)] 1.0 ?? $env?.[flatten(add)] 1.0 ?? $env?.[foo | floor(foobar)] 1.0 ?? $env?.[foo?.str] 1.0 ?? $env?.[foo] 1.0 ?? $env?.[foobar | ok()] 1.0 ?? $env?.[foobar?.add(foobar)] 1.0 ?? $env?.[foobar?.add] 1.0 ?? $env?.[foobar] 1.0 ?? $env?.[greet startsWith String] 1.0 ?? $env?.[greet()] 1.0 ?? $env?.[greet?.add] 1.0 ?? $env?.[greet] 1.0 ?? $env?.[i] 1.0 ?? $env?.[list(Bar)]?.[i] 1.0 ?? $env?.[list] 1.0 ?? $env?.[ok] 1.0 ?? $env?.[str] 1.0 ?? $env?.[str].foo 1.0 ?? $env?.[str]?.[f64] 1.0 ?? $env?.add 1.0 ?? $env?.array 1.0 ?? $env?.f64 1.0 ?? $env?.false?.[f64] 1.0 ?? $env?.foo 1.0 ?? $env?.foo?.String 1.0 ?? $env?.foobar.array 1.0 ?? $env?.greet 1.0 ?? $env?.i 1.0 ?? $env?.list 1.0 ?? $env?.ok 1.0 ?? $env?.str 1.0 ?? $env[$env || foobar:foobar ** f64] 1.0 ?? $env[1.0 || true:] 1.0 ?? $env[:$env && add] 1.0 ?? $env[:$env | hasSuffix(false)] 1.0 ?? $env[:findIndex(foobar, foobar)] 1.0 ?? $env[:foobar?.[array]] 1.0 ?? $env[:foobar] 1.0 ?? $env[add not startsWith greet:] 1.0 ?? $env[array():] 1.0 ?? $env[f64 and ok:0 or 1.0] 1.0 ?? $env[foo($env):str(foobar)] 1.0 ?? $env[foo?.foo():] 1.0 ?? $env[foobar | f64():] 1.0 ?? $env[foobar:greet()] 1.0 ?? $env[reduce(true, nil, foobar):foo and foobar] 1.0 ?? 1.0 ?? f64 1.0 ?? 1.0 ?? list 1.0 ?? array ?? ok 1.0 ?? array | mean(0) 1.0 ?? array?.[i] 1.0 ?? array[:$env ?? f64] 1.0 ?? array[:i] 1.0 ?? f64 | max(1.0) 1.0 ?? foo.Bar 1.0 ?? foo.String 1.0 ?? foo.String() 1.0 ?? foo?.Bar 1.0 ?? foo?.String 1.0 ?? foo?.String() 1.0 ?? greet ?? add 1.0 ?? greet ?? ok 1.0 ?? list ?? greet 1.0 ?? list?.[i] 1.0 ?? nil | median(array) 1.0 ?? ok ?? list 1.0 ?? str ?? [true] 1.0 ?? true ?? add 1.0 ^ $env.f64 1.0 ^ $env.i 1.0 ^ $env?.f64 1.0 ^ $env?.i 1.0 ^ 0 - i 1.0 ^ 0 / -i 1.0 ^ 0 < f64 1.0 ^ 0 <= i 1.0 ^ 0 == $env ?? 1.0 1.0 ^ 0 > i ? array : foo 1.0 ^ 0 ?? f64 1.0 ^ 0 ?? foo 1.0 ^ 0 ^ f64 1.0 ^ 1 * i 1.0 ^ 1 ** f64 1.0 ^ 1 - f64 1.0 ^ 1 - sum(array) 1.0 ^ 1 == i 1.0 ^ 1 >= 1 || false 1.0 ^ 1 ?? add 1.0 ^ 1 ?? f64 1.0 ^ 1 ?? foo 1.0 ^ 1.0 * f64 1.0 ^ 1.0 ** f64 1.0 ^ 1.0 ** i 1.0 ^ 1.0 + 1.0 in array 1.0 ^ 1.0 == $env?.i 1.0 ^ 1.0 > i 1.0 ^ 1.0 >= f64 1.0 ^ 1.0 ?? f64 1.0 ^ 1.0 ?? foo 1.0 ^ 1.0 ?? ok 1.0 ^ 1.0 ^ i 1.0 ^ 1.0 not in array 1.0 ^ 1.0 | min(1.0 ?? $env) 1.0 ^ 1.0 | min(f64) 1.0 ^ array?.[i] 1.0 ^ f64 * i 1.0 ^ f64 <= f64 1.0 ^ f64 <= i and $env 1.0 ^ f64 == f64 1.0 ^ f64 ^ i 1.0 ^ i * i 1.0 ^ i - i 1.0 ^ i < f64 < 1.0 1.0 ^ i <= int(1.0) 1.0 ^ i > i 1.0 ^ i ?? greet 1.0 ^ i in array 1.0 ^ i not in array 1.0 in $env.array 1.0 in $env?.Bar 1.0 in $env?.String 1.0 in $env?.String?.array 1.0 in $env?.String?.f64 1.0 in $env?.[Bar] 1.0 in $env?.[Bar]?.[add] 1.0 in $env?.[Bar]?.array 1.0 in $env?.[String] 1.0 in $env?.[String]?.[i] 1.0 in $env?.[String]?.[str] 1.0 in $env?.[foobar?.[foo]] 1.0 in $env?.[foobar] 1.0 in $env?.array 1.0 in $env?.foobar 1.0 in $env?.foobar?.Bar() 1.0 in 0 .. i 1.0 in array != ok 1.0 in array == ok 1.0 in array ?? i 1.0 in array or ok 1.0 in i..i 1.0 not in $env.array 1.0 not in $env?.Bar 1.0 not in $env?.String 1.0 not in $env?.[Bar] 1.0 not in $env?.[String] 1.0 not in $env?.[String]?.[array] 1.0 not in $env?.[foobar?.str] 1.0 not in $env?.[foobar] 1.0 not in $env?.[foobar]?.list 1.0 not in $env?.array 1.0 not in $env?.foobar 1.0 not in $env?.nil?.[list].array() 1.0 not in array && ok 1.0 not in array ?? $env?.[list] 1.0 | max(1.0, f64) < f64 1.0 | max(array) <= i 1.0 | max(f64) != i 1.0 | max(i) == f64 1.0 | mean(1.0) * 1 ?? false 1.0 | mean(f64) != i 1.0 | median(0) ^ i 1.0 | median(array) | get(foo) 1.0 | min(1.0) != i 1.0 | min(1.0) ** i 1.0; $env.i 1.0; $env?.Bar 1.0; $env?.i 1.0; $env?.list 1.0; 1.0 < f64 1.0; array | reduce(#) 1.0; foo?.Bar 1.1 * f64 1.1 < i 1.1 >= f64 1; $env.i 1; $env?.foo 1; $env?.foobar 1; $env?.i 1; 1 ?? $env.array 1; add ?? date(i) 1; f64 < i [!false, -0] [!false, foo] [!false] [!ok, foo] [!ok, greet] [!ok] [!true, array] [!true] [$env != $env] [$env != 0] [$env != 1, f64] [$env != 1.0] [$env != 1] [$env != add] [$env != f64] [$env != false] [$env != foo] [$env != greet] [$env != i] [$env != list] [$env != nil] [$env != ok] [$env != str] [$env && false] [$env && true] [$env == $env, foo != foo] [$env == $env.add] [$env == $env] [$env == 0] [$env == 1.0] [$env == 1] [$env == add] [$env == false] [$env == foo, ok] [$env == foo] [$env == greet] [$env == i, f64] [$env == i] [$env == list] [$env == nil] [$env == ok] [$env == str] [$env == true] [$env ?? $env] [$env ?? 0] [$env ?? 1.0] [$env ?? 1] [$env ?? add] [$env ?? array] [$env ?? false] [$env ?? foo] [$env ?? i] [$env ?? nil] [$env ?? str] [$env ?? true] [$env and false] [$env and true] [$env in list] [$env not in array] [$env not in list, f64] [$env not in list] [$env or false, list] [$env or false] [$env | all(false)] [$env | all(true)] [$env | any(false)] [$env | any(ok)] [$env | any(true)] [$env | filter(false), f64] [$env | find(false)] [$env | findIndex(true)] [$env | findLast(false)] [$env | findLastIndex(false)] [$env | map(#index)] [$env | map(1.0)] [$env | map(add)] [$env | map(array)] [$env | map(false)] [$env | map(foo)] [$env | map(greet)] [$env | map(i)] [$env | map(list)] [$env | map(ok)] [$env | map(str)] [$env | map(true)] [$env | none(false)] [$env | one(false)] [$env | one(ok)] [$env | reduce(list, 0)] [$env | reduce(true, foo)] [$env | sum(0)] [$env | sum(1)] [$env | sum(1.0)] [$env | sum(f64)] [$env || false] [$env || true] [$env, $env]?.[i] [$env, 0] | any(.ok) [$env, 1.0] | find(true) [$env, 1.0] | map(#) [$env, 1.0] | map(true) [$env, 1.0]?.[i] [$env, 1] | reduce(i, nil) [$env, false, i]?.[i] [$env, false] | reduce(#) [$env, foo] | groupBy(f64) [$env, foo] | reduce($env) [$env, foo]?.[i] [$env, greet] | reduce(1) [$env, i] | reduce(false, $env) [$env, nil]?.[i] [$env, ok, $env]?.[i] [$env, ok] | findLastIndex(#) [$env, ok] | findLastIndex(false) [$env, ok] | reduce(f64) [$env, ok]?.[i] [$env, true] | groupBy(foo) [$env, true] | map(foo) [$env.add, foo] [$env.add, list] [$env.add] [$env.array, i] [$env.array?.[i]] [$env.array] [$env.f64, greet] [$env.f64, ok] [$env.f64, round(1.0)] [$env.f64, string($env)] [$env.f64] [$env.foo, foo] [$env.foo?.String()] [$env.foo] [$env.greet, 1 >= 1] [$env.greet, foo] [$env.greet] [$env.i, $env.i] [$env.i, greet] [$env.i, str] [$env.i] [$env.list, add] [$env.list] [$env.ok, foo] [$env.ok, i] [$env.ok, list] [$env.ok] [$env.str, max(1.0)] [$env.str, str] [$env.str] [$env?.$env] [$env?.Bar] [$env?.String, add] [$env?.String, f64] [$env?.String?.f64] [$env?.String] [$env?.[Bar], array] [$env?.[Bar], foo] [$env?.[Bar]?.f64] [$env?.[Bar]] [$env?.[String] == list] [$env?.[String], foo] [$env?.[String], list] [$env?.[String], str] [$env?.[String]?.[foo]] [$env?.[String]?.[list]] [$env?.[String]] [$env?.[foobar], i] [$env?.[foobar]?.add?.add] [$env?.[foobar]?.greet] [$env?.[foobar]] [$env?.[nil]?.add()] [$env?.[nil]] [$env?.[str] | groupBy(#)] [$env?.[str], f64] [$env?.[str]?.[i]] [$env?.[str]] [$env?.add, foo] [$env?.add, ok] [$env?.add] [$env?.array | map(str)] [$env?.array, $env?.list] [$env?.array, [true]] [$env?.array, add] [$env?.array, array != $env] [$env?.array, str] [$env?.array] [$env?.f64] [$env?.false] [$env?.foo] [$env?.foobar, $env.add] [$env?.foobar?.ok] [$env?.foobar] [$env?.greet, add] [$env?.greet, array] [$env?.greet] [$env?.i, i < f64] [$env?.i, ok] [$env?.i] [$env?.list | map(#)] [$env?.list] [$env?.nil] [$env?.ok] [$env?.str, str] [$env?.str] [$env] != list [$env] == 0 .. 1 [$env] ?? duration($env) [$env] ?? str [$env] | all(false) [$env] | any(#.ok) [$env] | any(.ok) [$env] | any(false) [$env] | any(true) [$env] | concat(array) [$env] | count(#.ok) [$env] | count(ok) [$env] | filter(.ok) [$env] | filter(false) [$env] | filter(ok) [$env] | find(#.ok != .Bar) [$env] | find(#.ok) [$env] | findLast(ok) [$env] | findLast(true) [$env] | findLastIndex(#.ok) [$env] | findLastIndex(false) [$env] | groupBy(#.f64) [$env] | groupBy(.add == ok) [$env] | groupBy(1) [$env] | groupBy(i) [$env] | map(#.String) [$env] | map(#.ok) [$env] | map($env) [$env] | map(.greet) [$env] | map(.list) [$env] | map(.str) [$env] | map(1) [$env] | map(1.0) [$env] | map(array) [$env] | map(false) [$env] | map(foo) [$env] | map(true) [$env] | one(.ok) [$env] | reduce(#) [$env] | reduce(#.Bar) [$env] | reduce(#.add) [$env] | reduce(#.add?.[false]) [$env] | reduce(#.f64 | map(#.str)) [$env] | reduce(#.greet, greet) [$env] | reduce(#.greet?.[foo]) [$env] | reduce(#.ok) [$env] | reduce(#index) [$env] | reduce($env) [$env] | reduce(.Bar) [$env] | reduce(.Bar, 0) [$env] | reduce(.String) [$env] | reduce(0) [$env] | reduce(1) [$env] | reduce(1.0) [$env] | reduce(array) [$env] | reduce(f64) [$env] | reduce(false) [$env] | reduce(false, 1.0) [$env] | reduce(foo) [$env] | reduce(greet, true) [$env] | reduce(i) [$env] | reduce(list, i) [$env] | reduce(ok) [$env] | reduce(str) [$env] | sortBy(#.list) [$env] | sortBy(#?.[.String]) [$env] | sortBy(.array) [$env] | sortBy(.foo) [$env] | sortBy(1) [$env] | sortBy(array) [$env] | sortBy(false) [$env] | sortBy(foo) [$env] | sortBy(greet) [$env] | sortBy(list) [$env] | sum(#.f64) [$env] | sum(#.i) [$env] | sum(.f64) [$env] | sum(1) [$env] | sum(1.0) [$env]; i [$env][len(list):] [-$env.f64] [--1.0] [-0, list] [-0, ok] [-0] [-1.0, i ?? foo] [-1.0] [-1] [-f64] [-i, add] [-i, f64] [-i] [0 != $env] [0 != 0] [0 != 1.0] [0 != f64] [0 != i] [0 != nil] [0 % i] [0 * 0] [0 * 1.0] [0 * 1] [0 * f64] [0 ** 0] [0 ** 1.0, f64] [0 ** 1.0] [0 ** 1] [0 + 1.0] [0 + f64] [0 + i] [0 - 0] [0 - 1.0] [0 - 1] [0 - i] [0 .. 0] [0 .. i] [0 / 0] [0 / f64] [0 / i] [0 < 0] [0 < 1.0] [0 < 1] [0 < f64] [0 < i] [0 <= 0] [0 <= f64] [0 <= i] [0 == $env] [0 == 0] [0 == 1.0] [0 == 1] [0 == i] [0 == nil] [0 > 0] [0 > 1] [0 > f64] [0 > i] [0 >= 1.0] [0 >= 1] [0 >= f64] [0 ?? 0] [0 ?? 1.0] [0 ?? array] [0 ?? foo] [0 ?? greet] [0 ?? i] [0 ?? nil] [0 ?? ok] [0 ?? true] [0 ^ 1.0] [0 ^ 1] [0 ^ i] [0 in array] [0 not in array] [0 | bitor(1), list] [0 | median(1.0)] [0, $env] | count(false || true) [0, $env] | map(1) [0, $env] | reduce(str, 1.0) [0, $env] | sortBy(1.0) [0, $env]?.[i] [0, 0] | reduce(1.0, $env) [0, 1.0] | map(array) [0, 1.0]?.[i] [0, 1]?.[i] [0, add] | findLastIndex(ok) [0, add]?.[i] [0, false]?.[i] [0, foo] | findLast(true) [0, foo] | reduce(#, 1) [0, foo]?.[i] [0, foo][:] [0, greet]?.[i] [0, i] | any(false) [0, i]?.[i] [0, list, true] | map(#) [0, list] | sortBy(f64) [0, list]?.[i] [0, nil] | map(#) [0, nil]?.[i] [0, ok]?.[i] [0, str] | map(#) [0, true] ?? str [0, true]?.[i] [0.0] [0.1] [0] ?? $env?.String [0] ?? groupBy($env, .Bar) [0] | all(false) [0] | any(false) [0] | count(ok) [0] | findIndex(ok) [0] | groupBy(i) [0] | groupBy(true) [0] | map(#) [0] | map(array) [0] | map(f64) [0] | map(foo) [0] | map(greet) [0] | map(true) [0] | none(false) [0] | one(ok) [0] | one(true) [0] | reduce(#) [0] | reduce(0, nil) [0] | reduce(1) [0] | reduce(false) [0] | reduce(foo, $env) [0] | reduce(i) [0] | sortBy(#) [0] | sortBy(0) [0] | sortBy(1.0) [0] | sortBy(foo) [0] | sortBy(str) [0] | sum(#) [0] | sum(i) [1 != $env] [1 != 0] [1 != 1.0] [1 != 1] [1 != f64] [1 != i] [1 != nil] [1 % i] [1 * 0] [1 * 1.0] [1 * 1] [1 * f64] [1 ** 1.0] [1 ** 1] [1 ** f64] [1 ** i] [1 + 0] [1 + 1.0] [1 + 1] [1 + f64] [1 + i] [1 - 0] [1 - 1.0] [1 - f64] [1 - i] [1 .. 1] [1 / 1.0] [1 / f64] [1 / i] [1 < 0] [1 < 1.0, foo] [1 < 1.0] [1 < 1] [1 < f64] [1 <= 1.0] [1 <= 1] [1 <= i] [1 == $env] [1 == 1.0] [1 == 1] [1 == f64] [1 == i] [1 == nil] [1 > 1.0] [1 > 1] [1 > i] [1 >= 1.0] [1 >= 1] [1 >= i] [1 ?? 1, i] [1 ?? 1.0] [1 ?? 1] [1 ?? add] [1 ?? array] [1 ?? foo] [1 ?? list, greet] [1 ?? list] [1 ?? nil] [1 ?? str] [1 ?? true] [1 ^ f64] [1 ^ i] [1 | max(1.0)] [1 | median(1.0)] [1, $env]?.[i] [1, 1.0] | one(ok) [1, 1.0]?.[i] [1, 1] | reduce(true) [1, 1]?.[i] [1, false] | all(false) [1, false] | groupBy(true) [1, foo] | count(true) [1, foo]?.[i] [1, greet] | reduce(#, foo) [1, greet] | reduce(#acc, 0) [1, greet]?.[i] [1, nil] | reduce(add, array) [1, str, 0] | findLastIndex($env?.ok) [1, true] | findLastIndex(#) [1.0 != $env] [1.0 != $env] | all(ok) [1.0 != 0] [1.0 != 1.0] [1.0 != 1] [1.0 != f64] [1.0 != i] [1.0 != nil] [1.0 * 0] [1.0 * 1.0] [1.0 * 1] [1.0 * i] [1.0 ** 0] [1.0 ** 1, ok] [1.0 ** 1.0] [1.0 ** 1] [1.0 ** f64] [1.0 ** i] [1.0 + 0] [1.0 + 1.0] [1.0 + 1] [1.0 + f64] [1.0 + i] [1.0 - 0] [1.0 - 1.0] [1.0 - 1] [1.0 - i] [1.0 / 0] [1.0 / 1.0] [1.0 / 1] [1.0 / f64] [1.0 / i] [1.0 < 0] [1.0 < 1.0] [1.0 < 1] [1.0 < f64] [1.0 < i] [1.0 <= 0] [1.0 <= 1.0, foo] [1.0 <= 1.0] [1.0 <= 1] [1.0 <= f64] [1.0 <= i] [1.0 == $env] [1.0 == 0] [1.0 == 1.0] [1.0 == 1] [1.0 == f64] [1.0 == i] [1.0 == nil] [1.0 > 0] [1.0 > 1.0] [1.0 > 1] [1.0 > f64] [1.0 > i] [1.0 >= 0] [1.0 >= 1.0] [1.0 >= 1] [1.0 >= f64] [1.0 >= i] [1.0 ?? $env] [1.0 ?? 0] [1.0 ?? 1.0] [1.0 ?? add] [1.0 ?? array] [1.0 ?? f64] [1.0 ?? foo] [1.0 ?? greet] [1.0 ?? list] [1.0 ?? nil] [1.0 ?? str] [1.0 ^ 0] [1.0 ^ 1.0] [1.0 ^ 1] [1.0 ^ f64] [1.0 ^ i] [1.0 in array, list] [1.0 not in array] [1.0 | max(f64)] [1.0 | mean(array)] [1.0 | mean(f64)] [1.0 | min(1)] [1.0 | min(1.0, i)] [1.0, $env] | map(add) [1.0, $env] | map(str) [1.0, $env] | reduce(array) [1.0, $env]?.[i] [1.0, 0] | groupBy(#) [1.0, 0] | map(#) [1.0, 1.0] | findLast(true) [1.0, 1.0] | mean(i) [1.0, 1.0] | reduce(str) [1.0, 1.0] | sortBy(#) [1.0, 1.0]?.[i] [1.0, 1]?.[i] [1.0, add] | any(ok) [1.0, f64] | reduce(#) [1.0, f64]?.[i] [1.0, foo]?.[i] [1.0, greet] | reduce($env, list) [1.0, greet]?.[i] [1.0, i]?.[i] [1.0, list] ?? ok [1.0, nil] | reduce(true) [1.0, nil] | sortBy(1) [1.0, nil] | sum(f64) [1.0, ok] | findLastIndex(true) [1.0, ok]?.[i] [1.0, str] | map(array) [1.0, str] | reduce(greet) [1.0, true] | map($env) [1.0, true]?.[i] [1.0] [1.0] != array [1.0] != nil || ok [1.0] == list [1.0] ?? array [1.0] ?? count($env, $env) [1.0] ?? f64 [1.0] | all(true) [1.0] | any(true) [1.0] | filter(ok) [1.0] | filter(true) [1.0] | find(false) [1.0] | findLastIndex(false) [1.0] | get(0) [1.0] | groupBy(#) [1.0] | groupBy(0) [1.0] | groupBy(1) [1.0] | groupBy(1.0) [1.0] | groupBy(f64) [1.0] | groupBy(foo) [1.0] | map(#) [1.0] | map(#index) [1.0] | map($env) [1.0] | map(1) [1.0] | map(1.0) [1.0] | map(add) [1.0] | map(array) [1.0] | map(foo) [1.0] | map(greet) [1.0] | map(i) [1.0] | map(str) [1.0] | median(1.0) [1.0] | one(false) [1.0] | one(ok) [1.0] | one(true) [1.0] | reduce(#) [1.0] | reduce(#acc) [1.0] | reduce(#acc, foo) [1.0] | reduce($env) [1.0] | reduce(0) [1.0] | reduce(1, foo) [1.0] | reduce(1.0) [1.0] | reduce(add) [1.0] | reduce(array) [1.0] | reduce(f64) [1.0] | reduce(false) [1.0] | reduce(greet) [1.0] | sortBy(0) [1.0] | sortBy(1) [1.0] | sortBy(false) [1.0] | sortBy(greet) [1.0] | sortBy(list) [1.0] | sum(0) [1.0] | sum(1.0) [1.0][:] [1.1] [1] != [1] [1] ?? f64 [1] ?? ok [1] | all(true) [1] | filter(false) [1] | findIndex(ok) [1] | findIndex(true) [1] | findLast(ok) [1] | groupBy(#) [1] | groupBy(f64) [1] | groupBy(foo) [1] | groupBy(str) [1] | map(#) [1] | map($env) [1] | map(1.0) [1] | map(foo) [1] | mean(1.0) [1] | one(ok) [1] | reduce(#) [1] | reduce(#, foo) [1] | reduce(1.0, true) [1] | reduce(f64, foo) [1] | reduce(list) [1] | sortBy(#) [1] | sortBy($env) [1] | sortBy(1.0) [1] | sortBy(array) [1] | sortBy(true) [1] | sum(#) [1] | sum(1.0) [1] | sum(f64) [1]?.[f64 ?? $env] [[$env, greet, i]] [[$env, i, 1.0]] [[$env]] [[0]] [[1, add]] [[1, foo], greet] [[1, ok]] [[1, true, true]] [[1.0, foo]] [[1.0, true]] [[1.0], 1 / 1.0] [[1.0], foo] [[1.0], greet] [[1.0]] [[1]] [[add, ok]] [[add]] [[array, $env]] [[array]] [[f64, array]] [[f64, foo]] [[f64]] [[false, add]] [[false]] [[foo, 1]] [[foo, array]] [[foo, f64]] [[foo, true]] [[foo], i] [[foo]] [[greet], $env?.String] [[greet], add] [[greet]] [[i, foo]] [[i]] [[list, nil, foo]] [[list, nil]] [[list, ok, foo]] [[list]] [[nil, $env]] [[nil, ok]] [[nil], f64] [[nil], i] [[nil]] [[ok, 0]] [[ok, add]] [[ok]] [[str]] [[true]] [[{foo: false, foo: add}]] [abs(0)] [abs(1)] [abs(1.0)] [abs(f64)] [abs(i)] [add != $env] [add != nil] [add == $env] [add == nil] [add ?? $env] [add ?? 0] [add ?? 1.0] [add ?? array] [add ?? f64] [add ?? foo] [add ?? list] [add ?? nil] [add ?? str] [add ?? true] [add(1, i)] [add(i, 1)] [add(i, i)] [add, $env != 1] [add, $env.foo] [add, $env?.[String]] [add, $env?.[str]] [add, $env?.greet] [add, -1.0] [add, 0] | map(add) [add, 1.0, i] | count(true) [add, 1.0]?.[i] [add, 1] | reduce(true, nil) [add, [$env]] [add, add] [add, array] [add, f64] [add, f64]?.[i] [add, false]?.[i] [add, foo, list] [add, foo.Bar] [add, foo?.String] [add, foo] [add, foo] | groupBy(foo) [add, foo] | reduce(#index) [add, foo] | reduce(f64) [add, foo] | reduce(foo) [add, foo] | sortBy(i) [add, greet] [add, greet] | reduce(i, foo) [add, i] [add, list] [add, ok] [add, ok] | groupBy(foo) [add, ok] | none(ok) [add, ok]?.[i] [add, str] [add, str] | groupBy(f64) [add, string(i)] [add, toJSON(true)] [add, true]?.[i] [add] [add] ?? greet [add] ?? ok [add] | all(false) [add] | all(true) [add] | any(false) [add] | any(ok) [add] | findLast(ok) [add] | findLastIndex(false) [add] | groupBy(0) [add] | groupBy(true) [add] | map(#) [add] | map($env) [add] | map(0) [add] | map(1.0) [add] | map(add) [add] | map(greet) [add] | map(ok) [add] | none(ok) [add] | reduce(#) [add] | reduce(#, add) [add] | reduce(#acc) [add] | reduce(1) [add] | reduce(foo, foo) [add] | reduce(ok) [add] | sortBy($env) [add] | sortBy(list) [add] | sum(1) [add] | sum(1.0) [add][i:] [all($env, ok)] [all($env, true)] [all(array, false)] [all(list, ok)] [any(list, false)] [array != $env] [array != array] [array != list] [array != nil] [array == $env] [array == array] [array == list] [array == nil] [array ?? 1.0] [array ?? f64] [array ?? false] [array ?? foo] [array ?? greet] [array ?? true] [array | all(ok)] [array | findIndex(ok)] [array | findLast(false)] [array | groupBy(#)] [array | groupBy(foo)] [array | map(#)] [array | map($env)] [array | map(0)] [array | map(1)] [array | map(1.0)] [array | map(add)] [array | map(foo)] [array | map(i)] [array | map(ok)] [array | mean(1.0)] [array | one(false)] [array | one(true)] [array | reduce(#)] [array | reduce(#, false)] [array | reduce(#index)] [array | reduce($env)] [array | reduce(0)] [array | reduce(1.0)] [array | reduce(add)] [array | reduce(array)] [array | reduce(f64)] [array | reduce(false)] [array | reduce(foo)] [array | reduce(foo, true)] [array | reduce(ok)] [array | sortBy(#)] [array | sortBy(1)] [array | sortBy(1.0)] [array | sortBy(f64)] [array | sum(#), foo] [array | sum(#)] [array | sum(1)] [array | sum(1.0)] [array | sum(i)] [array, !ok] [array, !true] [array, $env.array] [array, $env?.[Bar]] [array, 0 == $env] [array, 1.0 == 1] [array, 1.0]?.[i] [array, 1] | findIndex(ok) [array, add, add] [array, add] [array, array] [array, array]?.[i] [array, f64] [array, f64] | findIndex(ok) [array, f64] | reduce(str) [array, f64]?.[i] [array, false, ok] | findLastIndex(#) [array, false] | sum(f64) [array, foo] [array, foo]?.[i] [array, greet] [array, greet] | reduce(foo) [array, i] [array, i]?.[i] [array, len($env)] [array, list] [array, nil] | map(#) [array, nil] | sum(0) [array, ok] [array, ok] | filter(false) [array, ok] | reduce(true) [array, ok]?.[i] [array, str, ok] [array, str] [array, str] | reduce(1.0) [array, true] ?? $env?.[str] [array, {foo: list}] [array?.[1]] [array?.[i]] [array[:1]] [array[i:]] [array] [array] ?? add [array] ?? f64 [array] ?? ok [array] | all(false) [array] | any(false) [array] | count(false) [array] | count(ok) [array] | find(true) [array] | findLastIndex(true) [array] | groupBy(ok) [array] | map(#) [array] | map($env) [array] | map(1.0) [array] | map(greet) [array] | map(ok) [array] | map(str) [array] | mean(i) [array] | reduce(#) [array] | reduce(#, 1.0) [array] | reduce($env) [array] | reduce($env, 1.0) [array] | reduce(0) [array] | reduce(1.0) [array] | reduce(ok) [array] | sortBy(#) [array] | sortBy($env) [array] | sortBy(i) [array] | sum(0) [array] | sum(1) [array] | sum(1.0) [array][:i] [bitnot(0)] [bitnot(1)] [bitnot(i)] [ceil(0)] [ceil(1)] [ceil(1.0)] [ceil(f64), add] [ceil(f64)] [ceil(i)] [concat(array), i] [concat(array)] [concat(list)] [count($env, false)] [count(list, false)] [f64 != $env] [f64 != 0] [f64 != 1.0] [f64 != i] [f64 != nil] [f64 * 1.0] [f64 * 1] [f64 * f64] [f64 * i] [f64 ** 0] [f64 ** 1.0] [f64 ** 1] [f64 ** i] [f64 + 1.0] [f64 - 0] [f64 - 1] [f64 - f64] [f64 / 1.0] [f64 / 1] [f64 / f64] [f64 < 0] [f64 < 1.0] [f64 < 1] [f64 < f64] [f64 < i] [f64 <= 1.0] [f64 <= 1] [f64 <= f64] [f64 == $env] [f64 == 0] [f64 == 1.0] [f64 == 1] [f64 == f64] [f64 == i] [f64 == nil] [f64 > 1.0] [f64 > f64] [f64 > i] [f64 >= 0] [f64 >= 1.0] [f64 >= i] [f64 ?? $env] [f64 ?? array] [f64 ?? foo] [f64 ?? greet] [f64 ?? nil] [f64 ^ 0] [f64 ^ 1] [f64 ^ f64] [f64 not in array] [f64 | median(1.0)] [f64, $env == 1.0] [f64, $env.add] [f64, $env.foo] [f64, $env.list] [f64, $env?.String] [f64, $env] | map(ok) [f64, 1.0 ^ i] [f64, 1.0] | map(0) [f64, abs(f64)] [f64, add] [f64, array] [f64, f64] [f64, foo] [f64, foo] | reduce(#) [f64, foo]?.[i] [f64, greet] [f64, i ?? 1] [f64, i] [f64, i] | findLast(false) [f64, i] | groupBy(1) [f64, i] | take(i) [f64, list] [f64, nil != foo] [f64, nil]?.[i] [f64, not true] [f64, ok] [f64, str] [f64, str] | findLast(ok) [f64, {foo: 0}] [f64] [f64] | count(ok) [f64] | findLast(ok) [f64] | findLast(true) [f64] | groupBy(#) [f64] | groupBy(str) [f64] | map(#) [f64] | map(#index) [f64] | map(1) [f64] | map(1.0) [f64] | map(add) [f64] | map(false) [f64] | map(foo) [f64] | map(greet) [f64] | none(false) [f64] | reduce(#) [f64] | reduce(1) [f64] | reduce(1.0) [f64] | reduce(f64) [f64] | reduce(false) [f64] | reduce(greet, true) [f64] | reduce(true, foo) [f64] | sortBy($env) [f64] | sortBy(0) [f64] | sortBy(add) [f64] | sum(#) [f64] | sum(1.0) [f64] | sum(i) [f64][:] [false != $env] [false != false] [false != nil] [false != true] [false && $env] [false && false] [false && true] [false == $env] [false == false] [false == nil] [false == ok] [false == true] [false ? 1.0 : foo] [false ? foo : 1.0] [false ?: 1.0] [false ?: foo] [false ?? $env] [false ?? 0, greet] [false ?? 0] [false ?? 1.0] [false ?? false, greet] [false ?? false] [false ?? foo] [false ?? greet] [false ?? nil] [false ?? ok] [false ?? true] [false and $env] [false and ok] [false and true] [false or $env] [false or false] [false or true] [false || $env?.[Bar]] [false || $env] [false || false, list] [false || ok] [false || true] [false, $env] | findIndex(true) [false, $env] | groupBy(1.0) [false, $env]?.[i] [false, 0] | map(#) [false, 1.0]?.[i] [false, 1] != nil ? 1.0 : $env[add(false) == greet():] [false, 1] | groupBy(#) [false, 1]?.[i] [false, add] | all(false) [false, array] | reduce(0) [false, f64]?.[i] [false, foo]?.[i] [false, greet]?.[i] [false, i] | map(#) [false, i]?.[i] [false, str] | groupBy(foo) [false, true]?.[i] [false] == $env?.Bar [false] ?? f64 [false] ?? foo [false] | all(#) [false] | all(true) [false] | any(#) [false] | count(false) [false] | find(#) [false] | findIndex(#) [false] | findLast(true) [false] | findLastIndex(#) [false] | findLastIndex(false) [false] | groupBy(#) [false] | groupBy(1.0) [false] | groupBy(foo) [false] | groupBy(i) [false] | map(#) [false] | map($env) [false] | map(foo) [false] | map(list) [false] | none(#) [false] | one(#) [false] | one(false) [false] | reduce(false, add) [false] | reduce(foo) [false] | reduce(greet) [false] | reduce(list, foo) [false] | reduce(true) [false] | sortBy(#) [false] | sortBy($env) [false] | sortBy(1.0) [false] | sortBy(array) [false] | sortBy(false) [false] | sortBy(true) [false] | sum(1) [false] | sum(1.0) [false][:] [false][i:] [filter($env, false)] [filter(array, false)] [find(array, false)] [find(array, true)] [find(list, false)] [find(list, true)] [findIndex($env, true)] [findIndex(array, false)] [findIndex(list, ok)] [findIndex(list, true)] [findLast(array, true)] [findLast(list, false), i] [findLastIndex($env, ok)] [findLastIndex(array, true)] [findLastIndex(list, true)] [first($env)] [first(array)] [first(list), string(foo)] [first(list)] [flatten(array)] [flatten(list)] [float(0)] [float(1)] [float(1.0)] [float(f64), ok] [float(f64)] [float(i)] [floor(0)] [floor(1), f64] [floor(1)] [floor(1.0)] [floor(f64)] [floor(i)] [foo != $env.foo] [foo != $env] [foo != foo, add] [foo != foo] [foo != nil] [foo == $env, list] [foo == $env] [foo == foo] [foo == nil] [foo ?? $env?.String()] [foo ?? $env] [foo ?? 0] [foo ?? 1.0] [foo ?? 1] [foo ?? add] [foo ?? array] [foo ?? f64] [foo ?? false] [foo ?? foo] [foo ?? i] [foo ?? list] [foo ?? str] [foo ?? true] [foo in list] [foo not in list] [foo, $env?.[str]] [foo, $env?.f64] [foo, $env?.false] [foo, $env?.ok] [foo, $env] | find(ok) [foo, $env] | map(1.0) [foo, $env] | sortBy(f64) [foo, $env]?.[i] [foo, -f64] [foo, 0] | groupBy(1.0) [foo, 0] | map(#) [foo, 1.0, $env]?.[i] [foo, 1.0] | groupBy(1) [foo, 1.0] | map(foo) [foo, 1.0] | one(ok) [foo, 1.0]?.[i] [foo, 1] | map(list) [foo, 1]?.[i] [foo, 1]?.[i] != greet [foo, abs(1.0)] [foo, add, $env] | findLastIndex(ok) [foo, add, f64] [foo, add] [foo, add]?.[i] [foo, array] [foo, array] | reduce(i) [foo, array]?.[i] [foo, f64, greet] | sortBy(1.0) [foo, f64] [foo, f64] | count(false) [foo, f64]?.[i] [foo, false, add] | none(true) [foo, false] | map(#) [foo, false]?.[i] [foo, foo != $env] [foo, foo.String] [foo, foo] [foo, foo] != list [foo, foo] | groupBy(1.0) [foo, foo] | reduce(1.0) [foo, foo]?.[i] [foo, greet(str)] [foo, greet] [foo, i, greet] [foo, i] [foo, i]?.[i] [foo, int(0)] [foo, list, foo] | reduce(list) [foo, list] [foo, list] != array [foo, list] | groupBy(f64) [foo, list]?.[i] [foo, mean(1)] [foo, nil != str] [foo, nil, list] | map(#) [foo, nil] | map(0) [foo, nil]?.[i] [foo, ok] [foo, ok] | all(true) [foo, round(1)] [foo, str] [foo, str] ?? f64 [foo, str]?.[i] [foo, true]?.[i] [foo, values($env)] [foo.Bar, [foo]] [foo.Bar, greet] [foo.Bar, ok] [foo.Bar] [foo.String()] [foo.String, f64] [foo.String, list] [foo.String] [foo?.Bar] [foo?.String(), ok] [foo?.String()] [foo?.String, $env?.String] [foo?.String] [foo] [foo] != array [foo] == $env?.[Bar] [foo] ?? add [foo] ?? array [foo] ?? greet [foo] ?? list [foo] ?? ok [foo] in [nil] [foo] | all(ok) [foo] | all(true) [foo] | any(ok) [foo] | any(true) [foo] | count(false) [foo] | count(ok) [foo] | count(true) [foo] | filter(ok) [foo] | filter(true) [foo] | find(false) [foo] | find(ok) [foo] | findLast(false) [foo] | findLastIndex(ok) [foo] | groupBy(#) [foo] | groupBy(#.Bar) [foo] | groupBy(f64) [foo] | groupBy(false) [foo] | groupBy(foo) [foo] | groupBy(ok) [foo] | map(#) [foo] | map(.String) [foo] | map(1) [foo] | map(add) [foo] | map(f64) [foo] | map(foo) [foo] | map(i) [foo] | map(list) [foo] | map(ok) [foo] | none(!true) [foo] | none(ok) [foo] | none(true) [foo] | one(false) [foo] | one(ok) [foo] | reduce(#) [foo] | reduce(#, ok) [foo] | reduce(#.String, 0) [foo] | reduce(#index) [foo] | reduce(.Bar, 0) [foo] | reduce(.Bar, nil) [foo] | reduce(0) [foo] | reduce(1) [foo] | reduce(1, 1.0) [foo] | reduce(1.0) [foo] | reduce(1.0, foo) [foo] | reduce(add) [foo] | reduce(array) [foo] | reduce(false) [foo] | reduce(foo) [foo] | reduce(foo, list) [foo] | reduce(greet) [foo] | reduce(i, 0) [foo] | reduce(list) [foo] | reduce(ok) [foo] | reduce(true) [foo] | sortBy(#) [foo] | sortBy(#.String) [foo] | sortBy($env) [foo] | sortBy(.Bar) [foo] | sortBy(1) [foo] | sortBy(add) [foo] | sortBy(f64) [foo] | sortBy(false) [foo] | sortBy(greet) [foo] | sortBy(i) [foo] | sortBy(str) [foo] | sum(i) [foo][:] [foo][:i] [get($env, nil)] [get($env, str)] [greet != $env] [greet != nil] [greet == $env] [greet == nil, array] [greet == nil] [greet ?? 1.0, list] [greet ?? 1] [greet ?? f64] [greet ?? foo, foo] [greet ?? foo] [greet ?? i] [greet(str), array] [greet(str), greet] [greet(str)] [greet, $env.array] [greet, $env.greet] [greet, $env.i] [greet, $env?.greet] [greet, $env?.nil] [greet, $env] | none(false) [greet, $env] | reduce(true) [greet, $env]?.[i] [greet, -i] [greet, 0]?.[i] [greet, 1.0]?.[i] [greet, [array]] [greet, abs(1.0)] [greet, add] [greet, add] | reduce($env) [greet, array] [greet, array] | map(i) [greet, f64] [greet, f64] | reduce(f64) [greet, foo == $env] [greet, foo ?? $env] [greet, foo] [greet, foo] | none(true) [greet, foo]?.[i] [greet, greet] [greet, greet] | reduce(#) [greet, i] [greet, int(1)] [greet, list] [greet, list] | reduce(add) [greet, nil]?.[i] [greet, ok] [greet, str, f64] [greet, str] [greet, true]?.[i] [greet] [greet] == $env.array [greet] ?? add [greet] ?? array [greet] ?? false ?? i [greet] ?? i [greet] ?? list [greet] ?? median(1.0) [greet] ?? str [greet] | all(ok) [greet] | any(false) [greet] | count(false) [greet] | find(false) [greet] | find(ok) [greet] | groupBy(1) [greet] | groupBy(foo) [greet] | groupBy(true) [greet] | map($env) [greet] | map(1) [greet] | map(add) [greet] | map(i) [greet] | map(str) [greet] | reduce(#, array) [greet] | reduce(false, nil) [greet] | reduce(foo, $env) [greet] | reduce(greet) [greet] | reduce(ok) [greet] | sortBy(#) [greet] | sortBy(array) [greet] | sortBy(i) [greet] | sortBy(str) [greet] | sum(f64) [greet][:i] [greet][i:] [groupBy(array, #)] [groupBy(array, foo)] [groupBy(list, #)?.[foo]] [groupBy(list, #)] [groupBy(list, 1.0)?.[i]] [groupBy(list, f64)] [groupBy(list, false)] [groupBy(list, foo)] [i != $env] [i != 0, str] [i != 0] [i != 1.0] [i != 1] [i != f64] [i != i] [i != nil] [i % 1] [i % i] [i * 0] [i * 1.0] [i * 1] [i * i] [i ** 0] [i ** 1.0] [i ** 1] [i ** f64] [i + 1.0] [i + 1] [i + f64] [i - 1.0] [i - 1] [i - f64] [i .. 0] [i .. i] [i / 1.0 ?? $env] [i / 1.0] [i / 1] [i < 1.0] [i < 1] [i <= 1.0] [i <= 1] [i <= f64] [i == $env] [i == 0] [i == 1.0] [i == 1] [i == f64] [i == nil] [i > 1.0] [i > f64] [i >= 1.0] [i >= 1] [i >= f64] [i ?? $env] [i ?? array] [i ?? f64] [i ?? false] [i ?? foo] [i ?? true] [i ^ 1.0] [i ^ 1] [i | max(array, i)] [i | min(0)] [i, $env in list] [i, $env?.String] [i, $env?.[String]] [i, $env?.foobar] [i, -1.0] [i, 1.0 >= 1.0] [i, 1.0] | sortBy(1) [i, 1.0] | sum(#) [i, 1.0]?.[i] [i, 1]?.[i] [i, add] [i, array?.[i]] [i, array] [i, f64 > i] [i, f64 ?? str] [i, f64] [i, f64] != array [i, foo?.String] [i, foo] [i, foo] | groupBy(1.0) [i, greet] [i, i] [i, list] [i, nil ?? 1.0] [i, nil in $env] [i, nil] | filter(true) [i, nil] | groupBy(1.0) [i, nil]?.[i] [i, ok] [i, ok]?.[i] [i, str] [i, sum(array)] [i, toJSON(0)] [i, true] | groupBy(true) [i..i] [i] [i] != list [i] == array [i] == list [i] ?? $env?.[foo] [i] ?? f64 [i] ?? greet [i] ?? i [i] ?? ok [i] | any(ok) [i] | find(false) [i] | findLast(ok) [i] | findLast(true) [i] | groupBy(1) [i] | groupBy(1.0) [i] | groupBy(foo) [i] | groupBy(ok) [i] | map(#) [i] | map(add) [i] | map(false) [i] | reduce(add, i) [i] | reduce(f64) [i] | reduce(foo) [i] | reduce(ok, nil) [i] | reduce(ok, true) [i] | reduce(str) [i] | reduce(str, str) [i] | sortBy(#) [i] | sortBy($env) [i] | sortBy(0) [i] | sortBy(1.0) [i] | sortBy(greet) [i] | sortBy(list) [i] | sortBy(str) [i] | sortBy(true) [i] | sum(#) [i] | sum(1.0) [i] | sum(f64) [i][i:] [if false { $env } else { 1.0 }] [if false { $env } else { greet }] [if false { 1.0 } else { true }] [if false { foo } else { 1 }] [if false { foo } else { true }] [if false { nil } else { $env }] [if false { true } else { false }] [if ok { 1.0 } else { foo }] [if ok { false } else { 1.0 }] [if ok { foo } else { $env }] [if ok { greet } else { nil }] [if ok { nil } else { nil }] [if ok { true } else { 1.0 }, $env.f64] [if true { $env } else { false }, list] [if true { 0 } else { ok }] [if true { 1 } else { 0 }] [if true { f64 } else { 1 }] [if true { foo } else { 1 }] [if true { foo } else { add }] [if true { foo } else { nil }] [if true { foo } else { ok }] [if true { nil } else { 1 }] [if true { nil } else { array }] [int(0), ok] [int(0)] [int(1)] [int(1.0)] [int(f64), foo] [int(f64)] [int(i)] [keys($env)] [last($env)] [last($env?.list)] [last(array)] [last(list), array] [last(list)] [len($env)] [len([nil, list])] [len(array), str] [len(array)] [len(list)] [len(str)] [len({foo: list})] [let foobar = $env; foobar] [let foobar = 1.0; foobar] [let z = 1.0; 0 + z] [list != $env] [list != array] [list != list] [list != nil] [list == $env] [list == nil] [list ?? 1.0] [list ?? add] [list ?? array] [list ?? foo] [list ?? greet] [list ?? i] [list ?? nil] [list ?? ok] [list | all(true)] [list | any(ok)] [list | find(false)] [list | findLast(false)] [list | groupBy(#)] [list | groupBy(1.0)] [list | groupBy(f64)] [list | groupBy(i)] [list | groupBy(str)] [list | map(#)] [list | map(foo)] [list | map(i), i] [list | reduce(#)] [list | reduce(#, 0)] [list | reduce(#, i)] [list | reduce(#, nil)] [list | reduce(#.String)] [list | reduce(#acc)] [list | reduce(#index)] [list | reduce(#index, greet)] [list | reduce($env)] [list | reduce($env, foo)] [list | reduce(1.0)] [list | reduce(1.0, greet)] [list | reduce(array)] [list | reduce(foo)] [list | reduce(i)] [list | reduce(list)] [list | sortBy(.Bar)] [list | sortBy(1)] [list | sortBy(1.0)] [list, $env, 1.0] | filter(ok) [list, $env.foo] [list, $env.i] [list, $env?.String] [list, $env?.list] [list, $env] | one(false) [list, 0 * i] [list, 0 ^ 1.0] [list, 0] | find(false) [list, 1.0 + 1.0] [list, 1.0]?.[i] [list, add] [list, add] | map(#) [list, add]?.[i] [list, array] [list, f64, ok] [list, f64] [list, f64]?.[i] [list, false, 1] | reduce(foo) [list, foo.String()] [list, foo] [list, foo] | groupBy(foo) [list, foo] | sum(1) [list, foo]?.[i] [list, greet] [list, greet] | map(#) [list, i ^ 1.0] [list, i, greet] [list, i] [list, list] [list, nil] | groupBy(foo) [list, ok] [list, ok]?.[i] [list, round(i)] [list, str, str] [list, str] [list, toJSON(nil)] [list, true != $env] [list, true] | reduce(f64) [list, true] | reduce(foo, ok) [list?.[0]] [list?.[i], add] [list?.[i]] [list[:1]] [list[i:]] [list] [list] != list [list] == $env?.String [list] == array [list] | filter(ok) [list] | findIndex(ok) [list] | findLast(false) [list] | findLastIndex(ok) [list] | get(i) [list] | groupBy($env.foo) [list] | map(#) [list] | map(1.0) [list] | map(add) [list] | map(i) [list] | map(ok) [list] | map(true) [list] | none(ok) [list] | one(true) [list] | reduce(1) [list] | reduce(foo) [list] | reduce(foo, false) [list] | reduce(foo, ok) [list] | sortBy(#) [list] | sortBy(add) [list] | sortBy(false) [list] | sortBy(foo) [list] | sortBy(i) [list] | sortBy(str) [list] | sum(1.0) [lower(str)] [map($env, #index)] [map($env, $env)] [map($env, 1.0)] [map($env, array)] [map($env, foo)] [map($env, greet)] [map($env, list)] [map($env, str)] [map(array, #)] [map(array, $env)] [map(array, 1)] [map(array, 1.0), foo] [map(array, 1.0)] [map(array, array)] [map(array, f64)] [map(array, false)] [map(array, foo)] [map(array, str), ok] [map(array, str)] [map(array, true)] [map(list, #)] [map(list, #index)] [map(list, $env)] [map(list, 0)] [map(list, f64)] [map(list, foo)] [map(list, list)] [map(list, ok)] [map(list, str)] [max($env), f64] [max($env)] [max(0)] [max(0, 1.0)] [max(1)] [max(1.0)] [max(1.0, 1)] [max(array) ^ f64] [max(array)] [max(array, 1.0)] [max(f64)] [max(i)] [mean(0)] [mean(1)] [mean(1, 1.0)] [mean(1.0)] [mean(array)] [mean(f64)] [mean(i)] [median(0)] [median(1)] [median(1, 1.0)] [median(1.0)] [median(1.0, 1.0)] [median(array)] [median(f64)] [median(floor(0))] [median(i)] [min($env ?? foo)] [min($env)] [min(0)] [min(1)] [min(1.0)] [min(array)] [min(f64)] [min(i)] [nil != $env?.f64] [nil != $env] [nil != 0] [nil != 1.0] [nil != add] [nil != array] [nil != f64] [nil != foo, greet] [nil != foo] [nil != greet] [nil != i] [nil != list, add] [nil != list] [nil != nil, ok] [nil != nil] [nil != ok] [nil != str] [nil != true] [nil == $env, foo] [nil == $env] [nil == 0] [nil == 1.0] [nil == add] [nil == array] [nil == f64] [nil == false, str] [nil == false] [nil == foo] [nil == greet] [nil == list, f64] [nil == list] [nil == nil] [nil == ok] [nil == str] [nil == true] [nil ?? $env] [nil ?? 1] [nil ?? add] [nil ?? false] [nil ?? foo, greet] [nil ?? foo] [nil ?? greet] [nil ?? list] [nil ?? nil] [nil ?? str] [nil in $env] [nil in list] [nil not in $env] [nil not in array] [nil not in list] [nil, $env] | reduce(0) [nil, $env]?.[i] [nil, 0] | reduce(i, greet) [nil, 0]?.[i] [nil, 1.0, 0] | all(true) [nil, 1.0] ?? add [nil, 1.0] | none(true) [nil, 1.0] | reduce(#) [nil, 1.0] | sum(f64) [nil, 1.0]?.[i] [nil, 1]?.[i] [nil, add] | none(false) [nil, add]?.[i] [nil, f64] | groupBy(str) [nil, false] | map($env) [nil, foo] | findLast(ok) [nil, foo] | map(ok) [nil, foo]?.[i] [nil, i] | filter(true) [nil, i]?.[i] [nil, nil, $env]?.[i] [nil, nil, array]?.[i] [nil, str, 1.0] | map(#) [nil, true]?.[i] [nil] == array [nil] == list [nil] == nil ? 1 : foo [nil] ?? i [nil] ?? ok [nil] | count(ok) [nil] | count(true) [nil] | filter(false) [nil] | filter(ok) [nil] | find(false) [nil] | find(true) [nil] | findIndex(true) [nil] | findLast(false) [nil] | findLastIndex(false) [nil] | findLastIndex(true) [nil] | groupBy(0) [nil] | groupBy(1) [nil] | groupBy(str) [nil] | groupBy(string(nil)) [nil] | groupBy(true) [nil] | map($env) [nil] | map(1.0) [nil] | map(f64) [nil] | map(foo) [nil] | map(greet) [nil] | map(i) [nil] | map(true) [nil] | one(ok) [nil] | reduce(#index) [nil] | reduce(0) [nil] | reduce(array) [nil] | reduce(array, array) [nil] | reduce(false) [nil] | reduce(foo) [nil] | reduce(i) [nil] | reduce(ok) [nil] | reduce(true) [nil] | sortBy($env) [nil] | sortBy(0) [nil] | sortBy(false) [nil] | sortBy(foo) [nil] | sortBy(true) [nil] | sum(1) [nil] | sum(1.0) [nil] | sum(i) [nil][:] [nil][i:] [none($env, false)] [none($env, true)] [none(array, false)] [not false, add] [not false] [not ok] [not ok] != array [not true] [ok != $env] [ok != nil] [ok != true] [ok && $env] [ok && false, foo?.Bar] [ok && ok] [ok && true] [ok == $env] [ok == false] [ok == nil] [ok == true] [ok ? 0 : false] [ok ? 1 : greet] [ok ? str : i, add] [ok ?: 0] [ok ?: nil] [ok ?? $env] [ok ?? 0] [ok ?? 1.0] [ok ?? add] [ok ?? array] [ok ?? foo] [ok ?? greet] [ok ?? nil, $env in array] [ok ?? nil] [ok ?? true] [ok and $env] [ok and false] [ok and ok, ok] [ok and ok] [ok and true] [ok or $env] [ok or false] [ok or ok] [ok or true] [ok || $env] [ok || false] [ok, $env.greet] [ok, $env?.[foobar]] [ok, $env?.[str]] [ok, $env?.i] [ok, $env?.str] [ok, $env] | find(#) [ok, $env] | map(false) [ok, $env]?.[i] [ok, 0]?.[i] [ok, 1 / 0] [ok, 1.0 == 1.0] [ok, 1] == array [ok, 1] | groupBy(#) [ok, 1] | map(1.0) [ok, add] [ok, array] [ok, array]?.[i] [ok, f64] [ok, false] not in uniq(list) [ok, false] | map(foo) [ok, floor(0)] [ok, foo not in list] [ok, foo?.String] [ok, foo] [ok, foo] | any(#) [ok, foo] | map(f64) [ok, foo]?.[i] [ok, greet] [ok, i] [ok, int(f64)] [ok, list] [ok, list] | findIndex(false) [ok, list]?.[i] [ok, nil == 1.0] [ok, nil] | find(#) [ok, nil]?.[i] [ok, ok] [ok, ok]?.[i] [ok, reduce(list, str)] [ok, str] [ok, str] | reduce(foo) [ok, string(add)] [ok] [ok] != $env?.list [ok] != array [ok] != list [ok] == nil and ok [ok] ?? f64 [ok] ?? foo [ok] | all(#) [ok] | any(#) [ok] | count(#) [ok] | filter(#) [ok] | findIndex(#) [ok] | findLast(#) [ok] | findLast(false) [ok] | groupBy(#) [ok] | groupBy(1) [ok] | groupBy(foo) [ok] | groupBy(true) [ok] | map(#) [ok] | map(0) [ok] | map(str) [ok] | none(#) [ok] | none(false) [ok] | one(#) [ok] | reduce($env) [ok] | reduce(1.0) [ok] | reduce(foo) [ok] | reduce(string(greet)) [ok] | sortBy(#) [ok] | sortBy($env) [ok] | sortBy(array) [ok] | sortBy(f64) [ok] | sortBy(foo) [ok] | sortBy(greet) [ok] | sortBy(str) [ok] | sum(1.0) [ok] | sum(f64) [one($env, false)] [one($env, ok)] [one(array, ok)] [one(list, true)] [reduce(array, #)] [reduce(array, $env), add] [reduce(array, $env)] [reduce(array, $env, f64)] [reduce(array, 1.0)] [reduce(array, add)] [reduce(array, array)] [reduce(array, false)] [reduce(array, foo)] [reduce(array, i)] [reduce(array, true)] [reduce(list, #.String)] [reduce(list, .String)] [reduce(list, add)] [reduce(list, f64)] [reduce(list, foo)] [reduce(list, greet)] [reduce(list, i)] [reduce(list, list)] [reverse(array)] [reverse(list)] [round(0), ok] [round(0)] [round(1)] [round(1.0)] [round(f64)] [round(i)] [sort($env)?.[i], foo] [sort($env)] [sort(array)] [sort(last($env)), list] [sortBy(array, #)] [sortBy(array, 1.0)] [sortBy(array, i)] [sortBy(list, .Bar)] [sortBy(list, 1)] [sortBy(list, 1.0)] [sortBy(list, i)] [str != nil] [str < str] [str <= str] [str == nil] [str >= str] [str ?? $env] [str ?? 1.0] [str ?? 1] [str ?? array] [str ?? f64] [str ?? false] [str ?? foo] [str ?? nil, ok] [str ?? str] [str ?? true] [str contains str] [str in $env] [str in foo, foo] [str in foo] [str matches str] [str not contains str] [str not endsWith str] [str not in $env] [str not in foo] [str not matches str] [str not startsWith str] [str startsWith str] [str | greet()] [str | splitAfter(str)] [str, $env == false] [str, $env ?? foo] [str, $env | count(true)] [str, $env.f64] [str, $env.str] [str, $env?.[Bar]] [str, $env?.[str]] [str, $env?.array] [str, $env?.nil] [str, $env?.ok] [str, $env] | map(add) [str, 0] | reduce(false, foo) [str, 1.0] | map(#) [str, 1]?.[i] [str, add] [str, array] [str, f64 ** 1] [str, f64 > i] [str, f64] [str, false != nil] [str, false]?.[i] [str, foo.Bar] [str, foo] [str, foo] | findIndex(ok) [str, foo] | map(greet) [str, greet] [str, i, array] | reduce(1.0) [str, i] [str, list | findLastIndex(true)] [str, list] [str, list] | any(false) [str, map(list, $env)] [str, nil in array] [str, nil] | map(str) [str, nil]?.[i] [str, ok, greet] [str, ok] [str, str, 0]?.[i] [str, str] [str, str]?.[i] [str[1:]] [str[:i]] [str] [str] == array [str] ?? f64 [str] ?? i [str] ?? str [str] | all(false) [str] | all(ok) [str] | any(ok) [str] | count(true) [str] | filter(ok) [str] | find(false) [str] | findLast(ok) [str] | findLastIndex(false) [str] | groupBy(#) [str] | groupBy(false) [str] | map(1) [str] | map(false) [str] | map(foo) [str] | none(false) [str] | one(ok) [str] | one(true) [str] | reduce(#) [str] | reduce(#acc) [str] | reduce(1.0, ok) [str] | reduce(false) [str] | reduce(str, i) [str] | sortBy(#) [str] | sortBy($env) [str] | sortBy(1.0) [str] | sortBy(add) [str] | sortBy(array) [str] | sortBy(foo) [str] | sum(abs(0)) [str][i:] [string($env)] [string($env.f64)] [string($env.greet)] [string(0)] [string(1)] [string(1.0)] [string(add)] [string(array), any(array, true)] [string(array), str] [string(array)] [string(f64)] [string(false)] [string(floor(0))] [string(foo), add] [string(foo), f64] [string(foo), foo] [string(foo)] [string(greet)] [string(i)] [string(list) not in $env?.foobar] [string(list)] [string(nil)] [string(str)] [string(true)] [sum($env, 1)] [sum($env.array)] [sum($env?.[str])] [sum([i])] [sum(array) - i] [sum(array), i] [sum(array)] [sum(array, #)] [sum(array, 1)] [sum(array, 1.0)] [sum(array, f64)] [sum(array, i)] [sum(list, 0)] [sum(list, 1.0)] [toBase64(str)] [toBase64(string(1.0))] [toJSON($env.foo)] [toJSON($env?.[String])] [toJSON(0)] [toJSON(1)] [toJSON(1.0)] [toJSON(array)] [toJSON(f64)] [toJSON(false), str] [toJSON(false)] [toJSON(foo)] [toJSON(foo?.Bar)] [toJSON(i)] [toJSON(list)] [toJSON(nil), foo.Bar] [toJSON(nil)] [toJSON(ok), array] [toJSON(ok)] [toJSON(true)] [toPairs($env)] [trim(str)] [trimPrefix(str)] [true != $env] [true != false] [true != nil] [true && $env, list] [true && $env] [true && false, array] [true && false] [true && true] [true == $env] [true == false] [true == nil] [true == true] [true ? $env : 1.0] [true ? f64 : foo] [true ? i : false, list] [true ?: 1] [true ?: array] [true ?: f64] [true ?: list] [true ?: ok] [true ?? $env?.i] [true ?? $env] [true ?? 0] [true ?? 1.0] [true ?? 1] [true ?? array, sum(array)] [true ?? f64] [true ?? foo] [true ?? list] [true ?? true] [true and $env] [true and false] [true and ok] [true and true] [true or true] [true || $env] [true || ok] [true || true] [true, $env] | groupBy(foo) [true, $env] | map(foo) [true, 0] | map(ok) [true, 1.0]?.[i] [true, 1] == $env?.array [true, 1] | any(ok) [true, add, foo] | findLastIndex(false) [true, add] | findLast(true) [true, add] | reduce(array, greet) [true, add]?.[i] [true, f64]?.[i] [true, false] == list [true, foo] | find(#) [true, foo] | groupBy(foo) [true, foo] | sum(1.0) [true, foo]?.[i] [true, list]?.[i] [true, nil, greet]?.[i]?.foo [true, nil] | none(#) [true, nil] | reduce(f64) [true, nil]?.[i] [true, ok] | find(true) [true, ok]?.[i] [true, str] ?? add [true, str] | groupBy(1.0) [true, str][i:] [true] != [array] [true] != array [true] ?? i [true] in $env?.foobar [true] | all(#) [true] | all(ok) [true] | any(#) [true] | any(false) [true] | count(#) [true] | filter(#) [true] | findIndex(#) [true] | findLastIndex(#) [true] | findLastIndex(false) [true] | groupBy(#) [true] | groupBy($env != $env) [true] | groupBy(1.0) [true] | groupBy(foo) [true] | groupBy(str) [true] | groupBy(true) [true] | map(#) [true] | map(1.0) [true] | map(true) [true] | none(true) [true] | one(#) [true] | one(false) [true] | reduce(#) [true] | reduce($env) [true] | reduce($env, str) [true] | reduce(1.0) [true] | reduce(true, $env) [true] | sortBy(#) [true] | sortBy($env) [true] | sortBy(0) [true] | sortBy(foo) [true] | sortBy(greet) [true] | sortBy(true) [true] | sum(1) [true] | sum(1.0) [true][:0 ?? str] [type($env)] [type(0)] [type(1)] [type(1.0), $env?.foo] [type(1.0)] [type(add)] [type(array)] [type(f64)] [type(false), str] [type(false)] [type(foo)] [type(greet)] [type(i)] [type(list), array] [type(list)] [type(nil)] [type(ok) not endsWith str, ok] [type(ok)] [type(str), foo]?.[i] [type(str)] [type(true)] [uniq(array)] [uniq(list)] [upper(str)] [values($env)] [{foo: $env, foo: 1.0, foo: 0}] [{foo: $env, foo: nil}] [{foo: $env}] [{foo: 0, foo: 1.0}] [{foo: 0, foo: nil}] [{foo: 0, foo: true}] [{foo: 0}] [{foo: 1.0, foo: 0}] [{foo: 1.0}.add] [{foo: 1.0}?.str] [{foo: 1.0}] [{foo: 1}] [{foo: add, foo: i}] [{foo: add, foo: str}] [{foo: add}] [{foo: array, foo: nil}] [{foo: array}] [{foo: f64, foo: foo}] [{foo: f64}?.f64] [{foo: f64}] [{foo: false, foo: 0}] [{foo: false}] [{foo: foo, foo: $env}.String] [{foo: foo, foo: false}] [{foo: foo, foo: nil}] [{foo: foo}] [{foo: greet, foo: f64, foo: 0}] [{foo: greet, foo: foo}] [{foo: greet}] [{foo: i, foo: $env}] [{foo: i, foo: greet, foo: foo}] [{foo: i}] [{foo: list, foo: foo}] [{foo: list}?.Bar] [{foo: list}] [{foo: nil, foo: 1.0}] [{foo: nil, foo: i}] [{foo: nil, foo: nil}] [{foo: nil, foo: str}] [{foo: nil}] [{foo: ok}?.foo] [{foo: ok}] [{foo: str, foo: true}] [{foo: str}] [{foo: true}] abs($env | count(ok)) abs($env | count(true)) abs($env | findLastIndex(ok)) abs($env | sum(1)) abs($env | sum(1.0)) abs($env.f64) abs($env.i) abs($env?.f64) abs($env?.i) abs(-0) abs(-1) abs(-1.0) abs(-f64) abs(-i) abs(0 % i) abs(0 * 1.0) abs(0 ** 1.0) abs(0 ** f64) abs(0 ** i) abs(0 + 0) abs(0 + 1.0) abs(0 + i) abs(0 - 0) abs(0 - 1) abs(0 - 1.0) abs(0 - f64) abs(0 - i) abs(0 / 0) abs(0 / 1) abs(0 / 1.0) abs(0 / f64) abs(0 ?? 1) abs(0 ?? add) abs(0 ?? array) abs(0 ?? false) abs(0 ?? foo) abs(0 ?? i) abs(0 ?? nil) abs(0 ^ 1.0) abs(0 ^ i) abs(0 | mean(i, i)) abs(0 | min(f64)) abs(0) * f64 abs(0) ** $env?.i abs(0) - f64 abs(0) - i abs(0) / f64 abs(0) ?? add abs(0) ?? array abs(0) ^ f64 abs(0) in array abs(0.1) abs(1 % 1) abs(1 % i) abs(1 * f64) abs(1 ** 1) abs(1 ** 1.0) abs(1 ** f64) abs(1 + 0) abs(1 + 1.0) abs(1 - 1) abs(1 - 1.0) abs(1 - f64) abs(1 / 1) abs(1 / 1.0) abs(1 / i) abs(1 ?? 1.0) abs(1 ?? add) abs(1 ?? f64) abs(1 ?? false) abs(1 ?? foo) abs(1 ?? greet) abs(1 ?? i) abs(1 ^ 0) abs(1 ^ 1) abs(1 ^ f64) abs(1 ^ i) abs(1 | bitshr(i)) abs(1 | max(array)) abs(1) != i abs(1) * i abs(1) + f64 abs(1) < f64 abs(1) < i abs(1) <= nil ?? i abs(1) >= i abs(1) ?? array abs(1) ^ float(1.0) abs(1) not in $env?.foobar abs(1) | mean(i) abs(1.0 * 0) abs(1.0 * 1) abs(1.0 * 1.0) abs(1.0 * f64) abs(1.0 * i) abs(1.0 ** 0) abs(1.0 ** 1) abs(1.0 ** 1.0) abs(1.0 ** i) abs(1.0 + 0) abs(1.0 + 1) abs(1.0 + 1.0) abs(1.0 + f64) abs(1.0 + i) abs(1.0 - 1) abs(1.0 - 1.0) abs(1.0 - f64) abs(1.0 - i) abs(1.0 / 0) abs(1.0 / 1) abs(1.0 / 1.0) abs(1.0 ?? $env[count(foobar):findLast(str, .list)]) abs(1.0 ?? 1) abs(1.0 ?? 1.0) abs(1.0 ?? f64) abs(1.0 ?? foo) abs(1.0 ?? list) abs(1.0 ?? nil) abs(1.0 ?? true) abs(1.0 ^ 0) abs(1.0 ^ 1) abs(1.0 ^ 1.0) abs(1.0 ^ f64) abs(1.0 ^ i) abs(1.0 | mean(array)) abs(1.0 | min(f64)) abs(1.0) abs(1.0) != $env?.[Bar] abs(1.0) != f64 abs(1.0) * i abs(1.0) ** f64 abs(1.0) + count(list, false) abs(1.0) - f64 abs(1.0) / 0 in array abs(1.0) / f64 abs(1.0) < 1.0 ?? 1 abs(1.0) <= reduce(array, #) abs(1.0) == i abs(1.0) > i abs(1.0) ?? f64 abs(1.0) ^ f64 > 0 abs(1.0) ^ i abs(1.0) in $env?.[String] abs(1.0) in array abs(1.0) | max(0) abs(1.0) | median(array) abs(1.1) abs(abs(1)) abs(abs(1.0)) abs(abs(f64)) abs(abs(i)) abs(abs(int(1.0))) abs(add(1, 1)) abs(array | count(true)) abs(array | find(ok)) abs(array | findLast(true)) abs(array | findLastIndex(ok)) abs(array | reduce(#)) abs(array | reduce(#acc)) abs(array | reduce(#index)) abs(array | reduce(0)) abs(array | reduce(0, array)) abs(array | reduce(1, nil)) abs(array | reduce(1.0)) abs(array | reduce(1.0, foo)) abs(array | sum(1.0)) abs(array?.[1]) abs(array?.[i]) abs(bitnot(0)) abs(bitnot(1)) abs(bitnot(i)) abs(bitor(0, 0)) abs(ceil(0)) abs(ceil(1)) abs(ceil(1.0)) abs(ceil(f64)) abs(ceil(i)) abs(count($env, false)) abs(count($env, true)) abs(f64 * 1) abs(f64 * 1.0) abs(f64 * f64) abs(f64 * i) abs(f64 ** 0) abs(f64 ** 1) abs(f64 ** 1.0) abs(f64 + 0) abs(f64 + 1) abs(f64 + 1.0) abs(f64 + f64) abs(f64 - 1) abs(f64 - i) abs(f64 / 1) abs(f64 / 1.0) abs(f64 / f64) abs(f64 ?? 0) abs(f64 ?? 1) abs(f64 ?? add) abs(f64 ?? foo) abs(f64 ?? nil) abs(f64 ^ 0) abs(f64 ^ 1) abs(f64 ^ 1.0) abs(f64 ^ i) abs(f64) abs(f64) != f64 abs(f64) != i abs(f64) ** i abs(f64) + i abs(f64) - f64 abs(f64) - i abs(f64) / i abs(f64) == f64 abs(f64) > f64 abs(f64) ?? array abs(f64) ?? f64 abs(f64) ?? i abs(f64) ?? str abs(findIndex($env, true)) abs(findIndex(array, true)) abs(findLastIndex($env, true)) abs(findLastIndex(list, true)) abs(first(array)) abs(float(0)) abs(float(1)) abs(float(1.0)) abs(float(f64)) abs(float(i)) abs(floor(0)) abs(floor(1)) abs(floor(1.0)) abs(floor(f64)) abs(floor(i)) abs(i % i) abs(i * 0) abs(i * 1) abs(i * 1.0) abs(i * f64) abs(i * i) abs(i ** 0) abs(i ** 1.0) abs(i ** i) abs(i + 0) abs(i + 1) abs(i + i) abs(i - 1.0) abs(i - f64) abs(i - i) abs(i / 1.0) abs(i / i) abs(i ?? $env) abs(i ?? 1.0) abs(i ?? add) abs(i ?? i) abs(i ?? list) abs(i ?? true) abs(i ^ 1) abs(i ^ 1.0) abs(i ^ i) abs(i | bitshl(0)) abs(i | bitushr(0)) abs(i) abs(i) * i abs(i) + f64 abs(i) < i abs(i) ^ i abs(i) not in array abs(i) | bitshr(0) abs(if false { array } else { 1 }) abs(if false { array } else { i }) abs(if ok { 1.0 } else { i }) abs(if true { f64 } else { list }) abs(if true { i } else { i }) abs(int(0)) abs(int(1)) abs(int(1.0)) abs(int(i)) abs(last(array)) abs(len($env)) abs(len(str)) abs(list | findIndex(ok)) abs(list | findIndex(true)) abs(list | reduce(1)) abs(list | sum(1.0)) abs(max($env)?.f64) abs(max(0)) abs(max(1)) abs(max(1.0)) abs(max(array)) abs(max(f64)) abs(max(f64, f64)) abs(max(i)) abs(mean(0)) abs(mean(1)) abs(mean(1.0)) abs(mean(1.0, i)) abs(mean(array)) abs(mean(array, 0)) abs(mean(f64)) abs(mean(f64, array)) abs(mean(i)) abs(median(0)) abs(median(0, 1.0)) abs(median(1)) abs(median(1, 0)) abs(median(1.0)) abs(median(1.0, 1.0)) abs(median(array)) abs(median(f64)) abs(median(f64, array)) abs(median(i)) abs(min(0)) abs(min(1)) abs(min(1.0)) abs(min(array)) abs(min(f64)) abs(min(i)) abs(nil ?? 0) abs(nil ?? 1) abs(nil ?? 1.0) abs(nil ?? f64) abs(reduce(array, #)) abs(reduce(array, #, nil)) abs(reduce(array, i)) abs(reduce(list, 0)) abs(reduce(list, 1)) abs(round(0)) abs(round(1)) abs(round(1.0)) abs(round(f64)) abs(round(i)) abs(round(median(f64))) abs(sum($env, 1.0)) abs(sum($env, i)) abs(sum(array)) abs(sum(array, #)) abs(sum(array, 0)) abs(sum(array, f64)) abs(sum(list, 1)) abs(sum(list, 1.0)) abs(sum(list, f64)) abs(sum(list, i)) add add != $env && $env?.ok add != $env && ok add != $env == $env add != $env ?? f64 add != $env ?? false add != $env ?? list add != $env ?? str add != $env and ok add != $env or $env?.[array] add != $env or ok add != $env.add add != $env?.$env?.greet add != $env?.Bar add != $env?.Bar?.ok add != $env?.String add != $env?.String?.str(foo) add != $env?.[Bar] add != $env?.[String] add != $env?.[String]?.[array] add != $env?.[String]?.str() add != $env?.[foobar?.[foobar]] add != $env?.[foobar?.f64] add != $env?.[foobar] add != $env?.[str] add != $env?.add add != $env?.add ?: foo add != $env?.foobar add != $env?.foobar?.[array] add != 1 ?? foo add != 1.0 ?? foo add != add add != add ?? count(array) add != add ?? true add != array ?? 1 add != array ?? 1.0 add != f64 ?? ok add != false ?? list add != foo ?? $env add != i ?? foo add != list ?? greet add != max(array) add != min($env) add != nil && $env add != nil == true add != nil ?: 1 add != nil ?: false add != nil and false add != nil || ok add != nil || true add != ok ?? str add == $env == false add == $env ? 0 : 1 add == $env ? array : ok add == $env ?? foo add == $env ?? greet add == $env or false add == $env or true add == $env.add add == $env?.Bar add == $env?.Bar?.[str] add == $env?.String add == $env?.String?.ok() add == $env?.[Bar] add == $env?.[String] add == $env?.[foobar] add == $env?.[str] add == $env?.add add == $env?.foobar add == $env?.foobar?.[greet] add == 0 ?? $env add == 0 ?? array add == 1 ?? foo add == 1 ?? str add == 1.0 ?? foo add == 1.0 ?? greet add == 1.0 ?? i add == 1.0 ?? str add == add add == add && $env add == add == true add == add ?? 1.0 add == add and $env?.[foo] add == add or $env add == false ?? 0 add == foo ?? 1 add == foo ?? array add == foo ?? f64 add == foo ?? i add == greet ?? $env add == i ?? str add == last($env) add == max($env) add == mean(array) add == nil != $env?.[Bar] add == nil && $env[foobar:foobar] add == nil == ok add == nil ?? add add == nil || $env add == nil || false add == str ?? list add == str ?? ok add ?? !false add ?? $env ?? nil add ?? $env.add add ?? $env.array add ?? $env.f64 add ?? $env.foo add ?? $env.greet add ?? $env.i add ?? $env.list add ?? $env.ok add ?? $env.str add ?? $env?.Bar add ?? $env?.Bar() add ?? $env?.Bar(f64 not endsWith foobar ^ true) add ?? $env?.Bar(foobar?.[i]) add ?? $env?.String add ?? $env?.String() add ?? $env?.String(add) add ?? $env?.String(array.i()) add ?? $env?.String?.f64 add ?? $env?.[Bar] add ?? $env?.[String] add ?? $env?.[add] add ?? $env?.[array] add ?? $env?.[array]?.[str] add ?? $env?.[array]?.foo add ?? $env?.[f64] add ?? $env?.[f64]?.[str] add ?? $env?.[f64]?.greet add ?? $env?.[foo] add ?? $env?.[foobar and String] add ?? $env?.[foobar] add ?? $env?.[greet] add ?? $env?.[i] add ?? $env?.[last(Bar, foobar, foobar)] add ?? $env?.[list] add ?? $env?.[list].String add ?? $env?.[ok] add ?? $env?.[str] add ?? $env?.add add ?? $env?.array add ?? $env?.f64 add ?? $env?.findIndex(foobar) add ?? $env?.foo add ?? $env?.greet add ?? $env?.i add ?? $env?.list add ?? $env?.ok add ?? $env?.str add ?? $env[$env != list:] add ?? $env[:String?.add] add ?? $env[:foobar] add ?? $env[f64(Bar):] add ?? $env[foo.ok():] add ?? $env[foobar != 1.0:] add ?? $env[foobar:1.0] add ?? $env[greet && Bar:foobar] add ?? -$env add ?? -0 add ?? -1 add ?? -f64 add ?? -i add ?? 0 ?? array add ?? 1 ?? i add ?? 1 ?? str add ?? 1.0 ?? add add ?? [1] add ?? [add] add ?? [foo] add ?? [i] add ?? [ok] add ?? abs(0) add ?? add add ?? add ?? foo add ?? add ?? true add ?? array add ?? array?.[i] add ?? bitnot(0) add ?? ceil(0) add ?? ceil(1) add ?? ceil(f64) add ?? count($env) add ?? count(array) add ?? count(list) add ?? date(false) add ?? date(nil) add ?? duration($env) add ?? duration(str) add ?? f64 add ?? false ?? foo add ?? false ?? i add ?? filter($env, #) add ?? filter($env, true) add ?? findIndex($env, #.array) add ?? findIndex($env, #.foo) add ?? findLast($env, #) add ?? findLast($env, false) add ?? findLast(list, true) add ?? flatten(array) add ?? float(1.0) add ?? floor(0) add ?? foo add ?? foo ?? f64 add ?? foo ?? foo add ?? foo ?? nil add ?? foo ?? true add ?? foo.Bar add ?? foo.String add ?? foo.String() add ?? foo?.Bar add ?? foo?.String add ?? foo?.String() add ?? fromBase64(str) add ?? fromPairs(list) add ?? greet add ?? greet ?? 1.0 add ?? greet($env) add ?? groupBy($env, 1) add ?? groupBy($env, foo) add ?? i add ?? i ?? $env add ?? i ?? $env?.Bar() add ?? int(1) add ?? list add ?? list ?? greet add ?? list ?? ok add ?? list | get(ok) add ?? list?.[i] add ?? list[:bitshr($env, i)] add ?? list[:i] add ?? lower($env) add ?? map($env, #index) add ?? map($env, greet) add ?? max($env) add ?? max(i) add ?? mean(1.0) add ?? mean(array) add ?? nil ?? false add ?? nil ?? foo add ?? nil ?? ok add ?? not $env add ?? not ok add ?? not true add ?? ok add ?? reduce($env, #) add ?? reduce($env, .Bar)?.array add ?? reverse(array) add ?? sortBy($env, $env).list(i) add ?? sortBy(array, #) add ?? sortBy(array, foo) add ?? str add ?? str ?? max(array) add ?? string(1.0) add ?? string(foo) add ?? string(greet) add ?? string(nil) add ?? sum($env) add ?? sum($env, 1) add ?? sum($env, array) add ?? sum($env, str) add ?? sum(array, f64) add ?? sum(list) add ?? timezone(str) add ?? toBase64($env) add ?? trim($env) add ?? true ?? 1.0 add ?? true | get(foo) add ?? type(1.0) add ?? type(array) add ?? upper($env) add ?? values($env) add ?? {foo: foo, foo: greet} add ?? {foo: foo} add ?? {foo: str} add in $env?.Bar add in $env?.Bar?.[f64] add in $env?.String add in $env?.[Bar] add in $env?.[String] add in $env?.[String]?.add add in $env?.[String]?.array add in $env?.[foobar] add in $env?.foobar add in $env?.foobar?.str()?.greet add in [$env, $env] add in keys($env) add in list ?? add add in map(array, $env) add in values($env) add in {foo: add}?.add add not in $env?.$env add not in $env?.Bar add not in $env?.Bar?.Bar add not in $env?.String add not in $env?.[Bar] add not in $env?.[String] add not in $env?.[foobar] add not in $env?.[nil] add not in $env?.foobar add not in $env?.foobar == false add not in $env?.foobar?.[str] add not in $env?.true?.[greet] add not in [array, foo] add not in [foo, nil] add not in [nil] add not in find($env, false) add not in first($env) add not in keys($env) add not in list ?? false add not in list ?? str add not in reverse(list) add not in toPairs($env) add not in {foo: 1}?.array add($env.i, i) add($env?.i, i) add(-i, i) add(0, 0) != i add(0, 0) ** ceil(i) add(0, 1) * f64 add(0, i) ?? array add(abs(1), sum(array, #)) add(i, -i) add(i, 1) >= f64 > i add(i, array?.[i]) add(i, i) add(i, list | sum(i)) add(int(0), i) add(min(0, i), i) add(sum(array), i) add; $env.add add; $env.array add; add add; add ?? f64 add; array add; greet add; list add; ok add; {foo: f64} all($env | filter(false), #[.ok:$env]) all($env, false) and $env?.[add].f64 all($env, false) and f64 <= 0 all($env, ok) ?? add all($env, ok) ?? str all($env, true) ?: greet all($env, true) and ok all($env.array, 1 > #) all($env.list, # != foo) all($env.list, $env == #) all($env?.[str], str != #) all($env?.array, ok) all($env?.list, nil == $env) all($env?.list, ok) all([$env], ok) all([add], ok) all([false], #) all([list], 1.0 < 1.0) all([ok], #) all(array, # != $env) all(array, # < #) all(array, # < f64) all(array, # <= #) all(array, # <= i) all(array, # == #) all(array, # == $env) all(array, # == 0) all(array, # == 1.0) all(array, # > #) all(array, # >= #) all(array, $env != #) all(array, $env != f64) all(array, $env == #) all(array, 0 == i) all(array, 1 <= 1.0) all(array, 1 == 0) all(array, 1.0 <= #) all(array, 1.0 > 0) all(array, add == $env) all(array, f64 | min(#, 1.0) >= #) all(array, false and ok) all(array, false) or 1.0 ?? i all(array, foo == nil) all(array, i >= 0) all(array, i >= 1) all(array, list | one(true)) all(array, nil != #) all(array, nil != nil) all(array, nil == 1) all(array, nil == true) all(array, ok ?? $env) all(array, ok) all(array, ok) || $env?.Bar all(array, str == nil) all(array, str startsWith str) all(array, true or $env) all(array, true) ?? greet all(list | map(true), #) all(list, !false) all(list, # != #) all(list, # in list) all(list, #.Bar >= str) all(list, $env != #) all(list, $env != 0) all(list, $env == #) all(list, $env?.ok) all(list, 0 < 1.0) all(list, 0 <= 1.0) all(list, 1.0 <= 0) all(list, add != $env) all(list, array | any(ok)) all(list, f64 != $env) all(list, f64 <= 1.0) all(list, false != false) all(list, false) != ok all(list, false) == $env == nil all(list, foo != #) all(list, foo == #) all(list, nil == nil) all(list, nil not in $env) all(list, not true) all(list, ok) all(list, true && ok) all(list, true and ok) all(list, true or true) all(map(list, 1.0), i < 1.0) all(nil ?? $env, ok) all(sort($env), #) all(sort($env), #.foo) all(sort($env), .f64 | reduce(#, foo)) all(sort($env), .f64) all(sort($env), .ok) all(sort($env), .ok?.array) all(sort($env), .str <= #) all(sort($env), 1.0 >= #) all(sort($env), sortBy(#, ok)) all(sort($env), str == #) all(toPairs($env), ok) all(uniq(list), ok) any($env ?? 1.0, ok) any($env, false) or $env?.[String] any($env, ok) || $env == foo any($env, true) ?? f64 any($env, true) || $env?.[str] any($env.list, ok) any($env?.[str], true and true) any($env?.array, # == #) any($env?.array, ok) any($env?.list, ok) any([$env], ok) any([0], foo == nil) any([1.0], not true) any(array ?? $env, true or #) any(array, # != #) any(array, # != $env) any(array, # < 0) any(array, # <= #) any(array, # > #) any(array, # >= 1) any(array, $env != #) any(array, $env != add) any(array, $env == 0) any(array, $env | all(true)) any(array, $env.ok) any(array, $env?.ok) any(array, 0 <= 1) any(array, 0 == #) any(array, 1 == 1.0) any(array, 1.0 != 0) any(array, 1.0 <= #) any(array, array == array) any(array, f64 != f64) any(array, false) ?? list any(array, false) || $env != 0 any(array, foo == nil) any(array, i != #) any(array, i <= i) any(array, nil != #) any(array, nil == greet) any(array, ok != ok) any(array, ok ?? $env) any(array, ok ?? 0) any(array, ok or $env) any(array, ok) any(array, str >= str) any(filter(list, false), ok) any(keys($env), ok) any(list ?? list, ok) any(list, !true) any(list, # != #) any(list, # == #) any(list, # in list) any(list, $env != false) any(list, $env && false) any(list, $env == 1.0) any(list, $env == list) any(list, $env == ok) any(list, $env == str) any(list, $env.ok) any(list, $env?.ok) any(list, 0 <= 1.0) any(list, 1 < 0) any(list, 1.0 < 1.0) any(list, false && true) any(list, false) && 1.0 ?? $env any(list, foo != #) any(list, foo == nil) any(list, i ^ i == 1.0) any(list, list != array) any(list, nil != 1) any(list, nil == nil) any(list, not true) any(list, ok or $env) any(list, ok) any(map(array, add), ok) any(nil ?? $env, ok) any(sort($env), #) any(sort($env), -#) any(sort($env), .String) any(sort($env), .list) any(sort($env), f64 == #) any(sort(array), # == ok) any(sortBy(list, i), ok) any(values($env), # != 1.0) array array != $env != $env array != $env && false array != $env == false array != $env == ok array != $env ?: str array != $env and $env array != $env and $env?.[Bar] array != $env or true array != $env.array array != $env.list array != $env?.Bar array != $env?.Bar?.i array != $env?.String array != $env?.String?.foo() array != $env?.[Bar] array != $env?.[String] array != $env?.[String]?.[greet] array != $env?.[foobar] array != $env?.[str] array != $env?.array array != $env?.foobar array != $env?.list array != $env?.true array != 0 ?? $env array != 0 ?? list array != 1.0 ?? array array != [1.0 + f64] array != [f64] array != [foo] array != [list] array != [median(1.0)] array != [true] array != array array != array != nil array != array && ok array != array && true array != array ?? false array != array or ok array != false ?? $env array != false ?? f64 array != false ?? greet array != flatten(array) array != foo ?? f64 array != i .. 1 array != i ?? foo array != list array != list != false array != list != true array != list && 1.0 > 0 array != list || ok array != map($env, 1.0) array != map(array, $env) array != map(list, #) array != map(list, 1.0) array != min($env) array != nil == $env array != nil ? list : greet array != nil and ok array != nil and true array != nil or $env array != nil or false array != nil or ok array != str ?? greet array != values($env) array != {foo: $env}?.str array != {foo: 0}.add array == $env != ok array == $env && false array == $env ?? i array == $env ?? nil array == $env ?? str array == $env and $env array == $env or $env?.Bar array == $env or false array == $env.array array == $env.list array == $env?.Bar array == $env?.Bar?.ok array == $env?.String array == $env?.String?.[greet] array == $env?.String?.greet array == $env?.[Bar] array == $env?.[Bar]?.[add] array == $env?.[Bar]?.add array == $env?.[String] array == $env?.[foobar] array == $env?.[greet(nil)] array == $env?.[str] array == $env?.array array == $env?.foobar array == $env?.list array == 0 ?? array array == 1.0 ?? find($env, #.list) array == [$env] array == [1.0] array == [1] array == [foo] array == [nil] array == [ok, 1.0] array == [ok] array == [str] array == [true] array == add ?? foo array == array array == array != ok array == f64 ?? $env array == false ?? $env array == false ?? i array == foo ?? add array == foo ?? true array == greet ?? array array == greet ?? ok array == keys($env) array == list array == list != $env array == list != false array == list[:] array == map(array, #) array == map(list, true) array == max($env)?.greet array == min($env) array == min(array) array == nil != nil array == nil != ok array == nil && $env array == nil && foo == $env array == nil == $env array == nil ?? nil array == ok ?? foo array == ok ?? list array ?? !$env array ?? !false array ?? !ok array ?? $env ?? foo array ?? $env ?? i array ?? $env | count(true) array ?? $env | findLast(ok) array ?? $env | groupBy(false) array ?? $env | map(f64) array ?? $env | map(foo) array ?? $env | map(ok) array ?? $env | median(i, f64) array ?? $env | reduce(#) array ?? $env | reduce(add) array ?? $env | reduce(foo) array ?? $env | sortBy(1.0) array ?? $env.add array ?? $env.array array ?? $env.f64 array ?? $env.foo array ?? $env.greet array ?? $env.i array ?? $env.list array ?? $env.ok array ?? $env.str array ?? $env?.Bar array ?? $env?.Bar() array ?? $env?.Bar(foobar) array ?? $env?.String array ?? $env?.String() array ?? $env?.String(Bar, 0) array ?? $env?.[Bar] array ?? $env?.[String] array ?? $env?.[add] array ?? $env?.[add].str array ?? $env?.[array] array ?? $env?.[f64] array ?? $env?.[f64]?.[add] array ?? $env?.[f64]?.greet() array ?? $env?.[foo?.[array]] array ?? $env?.[foo] array ?? $env?.[foobar.Bar] array ?? $env?.[foobar] array ?? $env?.[greet()] array ?? $env?.[greet] array ?? $env?.[i] array ?? $env?.[list | fromJSON(nil)] array ?? $env?.[list] array ?? $env?.[list]?.f64 array ?? $env?.[list]?.foo array ?? $env?.[nil or $env] array ?? $env?.[ok] array ?? $env?.[ok].foo() array ?? $env?.[str] array ?? $env?.[str].str array ?? $env?.add array ?? $env?.array array ?? $env?.f64 array ?? $env?.foo array ?? $env?.greet array ?? $env?.i array ?? $env?.list array ?? $env?.ok array ?? $env?.sort(foobar, nil) array ?? $env?.str array ?? $env[1.0:foobar] array ?? $env[:1.0] array ?? $env[:foobar] array ?? $env[:fromPairs(ok)] array ?? $env[:str .. false] array ?? $env[f64():] array ?? $env[findLastIndex(foo, greet):] array ?? $env[foobar .. foobar:] array ?? $env[foobar:] array ?? $env[str:] array ?? $env[true != foobar:] array ?? -$env array ?? -0 array ?? -1 array ?? -1.0 array ?? -1.0 ^ 1.0 | map(foo) array ?? 0 ?? f64 array ?? 0 | filter(false) array ?? 0 | map(#) array ?? 0 | map(add) array ?? 0 | one(false) array ?? 0 | one(ok) array ?? 0 | reduce(#) array ?? 0 | sum(i) array ?? 1 | map(1) array ?? 1 | map(false) array ?? 1 | reduce($env, $env) array ?? 1 | reduce(greet) array ?? 1 | reduce(i) array ?? 1.0 ?? add array ?? 1.0 ?? foo array ?? 1.0 | findLast(false) array ?? 1.0 | groupBy(1) array ?? 1.0 | map(#) array ?? 1.0 | sortBy(#) array ?? 1.0 | sortBy(1.0) array ?? 1.0 | sum(#) array ?? [1] array ?? [add] array ?? [list] array ?? [ok, add] array ?? abs(1.0) array ?? abs(f64) array ?? add array ?? add | findLastIndex(ok) array ?? add | groupBy(true) array ?? add | map(#) array ?? add | reduce($env) array ?? add | reduce(i) array ?? add($env, 1) array ?? array array ?? array ?? 0 array ?? array ?? f64 array ?? array | map(true) array ?? array | one(true) array ?? array | reduce($env) array ?? array | reduce(str) array ?? array?.[i] array ?? bitnot(1) array ?? bitushr($env, 0) array ?? ceil(1.0) array ?? concat(list) array ?? count($env) array ?? count($env, #) array ?? count(list) array ?? count(str ?? 1.0) array ?? date(foo) array ?? date(i) array ?? date(str) array ?? duration($env) array ?? f64 array ?? f64 ?? 1.0 array ?? f64 | map(#) array ?? f64 | map(foo) array ?? f64 | sortBy(f64) array ?? f64 | sum(#) array ?? false ?? false array ?? false | findLastIndex(true) array ?? false | groupBy(#) array ?? false | map($env) array ?? false | one(ok) array ?? filter($env, .str) array ?? findIndex($env, #) array ?? findLast($env, #.String) array ?? findLast($env, .add) array ?? findLastIndex($env, #) array ?? findLastIndex($env, #.i) array ?? floor(1.0) array ?? foo array ?? foo | all(ok) array ?? foo | all(true) array ?? foo | any(false) array ?? foo | filter(true) array ?? foo | groupBy(1) array ?? foo | map(#) array ?? foo | map(1.0) array ?? foo | map(foo) array ?? foo | reduce(#) array ?? foo | reduce(#acc, true) array ?? foo | reduce(#index * #) array ?? foo | reduce(1) array ?? foo | reduce(1.0) array ?? foo | reduce(foo) array ?? foo | reduce(foo, true) array ?? foo | sortBy(1) array ?? foo | sortBy(str) array ?? foo | sum(1.0) array ?? foo.Bar array ?? foo.String array ?? foo.String() array ?? foo?.Bar array ?? foo?.String array ?? foo?.String() array ?? fromBase64(str) array ?? greet array ?? greet ?? $env array ?? greet | all(ok) array ?? greet | map(true) array ?? greet | reduce(foo) array ?? greet | sortBy(f64) array ?? greet | sum(0) array ?? greet($env) array ?? i array ?? i ?? add array ?? i | map(#) array ?? i | max(0) array ?? i | sortBy(#) array ?? i | sum(1) array ?? last($env)?.Bar array ?? list array ?? list ?? str array ?? list | find(true) array ?? list | findIndex(ok) array ?? list | findIndex(true) array ?? list | map($env) array ?? list | map(foo) array ?? list?.[i] array ?? list[:] array ?? map($env, array) array ?? map($env?.[String], bitshr(#, #)) array ?? max(f64) array ?? mean(f64) array ?? min(i) array ?? nil ?? $env?.f64 array ?? nil ?? add array ?? nil ?? f64 array ?? nil ?? i array ?? nil | filter(false) array ?? nil | map(#) array ?? nil | map(false) array ?? nil | reduce(#) array ?? nil | reduce(foo, $env) array ?? nil | reduce(foo, foo) array ?? nil | sortBy(#) array ?? not ok array ?? not true array ?? ok array ?? ok | findIndex(ok) array ?? ok | findLastIndex(true) array ?? ok | map(i) array ?? ok | reduce(i, 1.0) array ?? ok | sum(#) array ?? one($env, #) array ?? reduce($env, #.greet) array ?? reduce($env, list) array ?? round(1) array ?? round(i) array ?? sortBy($env, 0) array ?? sortBy($env, 1) array ?? sortBy($env, foo) array ?? str array ?? str | map(foo) array ?? str | none(false) array ?? str | reduce(#, f64) array ?? str | sortBy(#) array ?? str | sum(#) array ?? string($env) array ?? string(array) array ?? string(nil) array ?? string(ok) array ?? sum($env) array ?? sum($env, list) array ?? sum(array) array ?? sum(array, true) array ?? toJSON(add) array ?? true | groupBy(ok) array ?? true | reduce(0) array ?? true | reduce(foo) array ?? true | sum(#) array ?? type(array) array ?? type(foo) array ?? type(list) array ?? uniq($env) array ?? uniq(array) array ?? {foo: 1} array ?? {foo: add} array ?? {foo: i} array in $env?.Bar array in $env?.Bar?.[array] array in $env?.String array in $env?.String?.array array in $env?.String?.foo array in $env?.[Bar] array in $env?.[String] array in $env?.[String]?.[greet] array in $env?.[String]?.list array in $env?.[foobar] array in $env?.[foobar]?.[i] array in $env?.foobar array in [$env?.foobar] array in [array] array in [f64, list] array in [list] array in [nil] array in [str, $env] array in array ?? add array in array ?? greet array in flatten(array) array in keys($env) array in last($env) array in reverse(list) array in uniq(array) array in values($env) array not in $env and false array not in $env?.Bar array not in $env?.String array not in $env?.[Bar] array not in $env?.[Bar]?.add array not in $env?.[String] array not in $env?.[String]?.[add] array not in $env?.[String]?.f64 array not in $env?.[String]?.list array not in $env?.[foobar?.String] array not in $env?.[foobar] array not in $env?.false array not in $env?.foobar array not in [1, 1.0] array not in [array] array not in [list] array not in first($env) array not in last($env) array not in list ?? none($env, #.Bar) array not in map(array, array) array not in toPairs($env) array not in uniq(array) array not in uniq(list) array not in {foo: foo}.add array | all(# != #) array | all(# != nil) array | all(# <= 1.0) array | all(# == f64) array | all(# >= i) array | all($env == #) array | all($env == $env) array | all($env == foo) array | all(0 < 1.0) array | all(0 == #) array | all(1.0 != nil) array | all(1.0 <= #) array | all(f64 < #) array | all(false) array | all(foo == foo) array | all(foo not in list) array | all(i != f64) array | all(i > #) array | all(ok) array | all(one(list, true)) array | all(true && true) array | all(true) array | any(# != #) array | any(# < #) array | any(# <= #) array | any(# == $env.i) array | any(# > #) array | any(# >= f64) array | any($env != #) array | any($env != nil) array | any($env == foo) array | any($env?.ok) array | any(1 < #) array | any(1.0 <= 1) array | any(false) array | any(i <= #) array | any(not ok) array | any(ok ?: nil) array | any(ok) array | any(true) array | concat(array) array | concat(array) | find(ok) array | concat(array) | sortBy(1) array | concat(array, array) array | concat(list) array | concat(list) | reduce(f64) array | count(# != #) array | count(# != $env) array | count(# != nil) array | count(# <= 0) array | count(# > #) array | count($env != foo) array | count($env == #) array | count($env == array) array | count($env.ok) array | count($env?.ok) array | count(0 < 1) array | count(0 <= #) array | count(0 > #) array | count(1.0 == #) array | count(false) array | count(i >= #) array | count(nil not in $env) array | count(not true) array | count(ok) array | count(ok) not in array array | count(true) array | count(true) ** i array | filter(!true) array | filter(# < 1.0) array | filter(# <= #) array | filter(# <= f64) array | filter(# >= #) array | filter(# >= 0) array | filter($env == #) array | filter($env == i) array | filter($env == ok) array | filter($env == str) array | filter($env.ok) array | filter(1 != #) array | filter(f64 < #) array | filter(f64 == #) array | filter(false) array | filter(false) | map(#) array | filter(false) | map(array) array | filter(false) | sortBy(#) array | filter(false) | sortBy(foo) array | filter(foo != foo) array | filter(foo != nil) array | filter(greet == $env) array | filter(nil == #) array | filter(nil == foo) array | filter(ok) array | filter(ok) | find(1.0 > #) array | filter(ok) | map(foo) array | filter(ok) | mean(1.0) array | filter(ok) | sum(1) array | filter(true) array | filter(true) != list array | filter(true) | groupBy(#) array | filter(true) | take(0) array | find(# < #) array | find(# >= 1.0) array | find($env != $env) array | find($env == i) array | find($env not in array) array | find($env not in list) array | find(-1 < #) array | find(0 < 1) array | find(1.0 != 1.0) array | find(1.0 < #) array | find(1.0 == 0) array | find(1.0 == 1.0) array | find(false) array | find(foo in list) array | find(i == i) array | find(ok) array | find(true) array | find(true) == i array | find(true) >= float(f64) array | find(true) ?? ok array | find(true) | mean(1.0) array | find(type(true) contains str[0:]) array | findIndex(!false) array | findIndex(# != 0) array | findIndex(# == #) array | findIndex(# > 1.0) array | findIndex(# > f64) array | findIndex(# >= 1.0) array | findIndex($env != false) array | findIndex($env != nil) array | findIndex($env.ok) array | findIndex($env?.ok) array | findIndex(0 != #) array | findIndex(1 not in array) array | findIndex(1.0 < 1.0) array | findIndex(1.0 <= #) array | findIndex(f64 == $env) array | findIndex(f64 >= 1.0) array | findIndex(false and false) array | findIndex(false) array | findIndex(i != $env) array | findIndex(ok ?? ok) array | findIndex(ok) array | findIndex(true) array | findIndex(true) + i array | findIndex(true) | bitshl(0) array | findLast(# <= i) array | findLast(# > #) array | findLast(# >= 1.0) array | findLast($env or true) array | findLast(0 >= #) array | findLast(1.0 < #) array | findLast(1.0 >= i) array | findLast(f64 + f64 != nil) array | findLast(f64 <= #) array | findLast(f64 >= #) array | findLast(false) array | findLast(greet != nil) array | findLast(nil != #) array | findLast(nil not in $env) array | findLast(none($env, true)) array | findLast(ok) array | findLast(ok) ?? $env[false:] array | findLast(ok) | mean(i) array | findLast(true ?: add) array | findLast(true) array | findLastIndex(!true) array | findLastIndex(# != $env) array | findLastIndex(# < #) array | findLastIndex(# <= #) array | findLastIndex($env != 0) array | findLastIndex($env != 1.0) array | findLastIndex($env | any(false)) array | findLastIndex(0 <= 0) array | findLastIndex(1 <= i) array | findLastIndex(1.0 < #) array | findLastIndex(1.0 <= #) array | findLastIndex(1.0 <= 1.0) array | findLastIndex(false ?: ok) array | findLastIndex(false) array | findLastIndex(foo in list) array | findLastIndex(nil == nil) array | findLastIndex(nil ?? true) array | findLastIndex(ok) array | findLastIndex(ok) < f64 array | findLastIndex(ok) ?? i array | findLastIndex(str endsWith str) array | findLastIndex(true) array | findLastIndex(true) - i array | get(0) array | get(1) array | get(i) array | get(mean(1.0, array)) array | get(sum(array)) array | groupBy(# != #) array | groupBy(# - #) array | groupBy(# / 1.0) array | groupBy(# / i) array | groupBy(# == #) array | groupBy(# == nil) array | groupBy(# > #) array | groupBy(# >= #) array | groupBy(# ^ #) array | groupBy(#) array | groupBy($env != 0) array | groupBy($env && false) array | groupBy($env.foo) array | groupBy($env?.[Bar]) array | groupBy($env?.[String]) array | groupBy($env?.[str]) array | groupBy($env?.foo) array | groupBy($env?.foobar) array | groupBy($env?.str) array | groupBy(-#) array | groupBy(0 ** 1.0) array | groupBy(0) array | groupBy(1) array | groupBy(1.0 != #) array | groupBy(1.0 != f64) array | groupBy(1.0 ** 1) array | groupBy(1.0 ** f64) array | groupBy(1.0 == 1.0) array | groupBy(1.0 ?? foo) array | groupBy(1.0 ^ #) array | groupBy(1.0) array | groupBy(add(#, 0)) array | groupBy(array?.[i]) array | groupBy(bitnot(i)) array | groupBy(f64) array | groupBy(false != false) array | groupBy(false ?? false) array | groupBy(false) array | groupBy(first(array)) array | groupBy(foo) array | groupBy(foo.Bar) array | groupBy(foo.String()) array | groupBy(i) array | groupBy(len(list)) array | groupBy(list?.[i]) array | groupBy(mean(1.0 ?? 1.0)) array | groupBy(not false) array | groupBy(ok ?? str) array | groupBy(ok) array | groupBy(round(#)) array | groupBy(round(0)) array | groupBy(round(1.0)) array | groupBy(str) array | groupBy(str[0:]) array | groupBy(string(1)) array | groupBy(sum(array)) array | groupBy(trimPrefix(str)) array | groupBy(true) array | map(!ok) array | map(# != 0) array | map(# * #) array | map(# ** i) array | map(# + #) array | map(# - #) array | map(# .. #index) array | map(# < #) array | map(# == 0) array | map(# > #) array | map(# >= #) array | map(# >= i) array | map(# ?? #) array | map(# ?? 0) array | map(# ^ #) array | map(#) array | map(#) | any(ok) array | map(#) | groupBy(foo) array | map(#) | map($env?.foobar) array | map(#) | map(1.0) array | map(#) | map(foo) array | map(#) | map(ok) array | map(#) | one(ok) array | map(#) | one(true) array | map(#) | reduce(#) array | map(#) | reduce(foo) array | map(#) | reduce(ok) array | map(#) | sum(1.0) array | map(#) | take(0) array | map(#index % i) array | map(#index - 1.0) array | map(#index / #) array | map(#index) array | map(#index) | filter(ok) array | map(#index) | groupBy(#) array | map(#index) | map(false) array | map(#index) | map(list) array | map($env != str) array | map($env) array | map($env) | any(.ok) array | map($env) | map(#) array | map($env.foo) array | map($env.greet) array | map($env.i) array | map($env.list) array | map($env.ok) array | map($env.str) array | map($env?.Bar) array | map($env?.[Bar]) array | map($env?.[foobar]) array | map($env?.i) array | map($env?.list) array | map($env?.str) array | map(-1) array | map(0 - i) array | map(0) array | map(0) | reduce(#) array | map(0) | sum(#) array | map(0) | sum(f64) array | map(1 ** #) array | map(1 >= 1) array | map(1) array | map(1) ?? greet array | map(1) | find(ok) array | map(1) | groupBy(#) array | map(1) | map(list) array | map(1) | one(ok) array | map(1) | reduce($env, array) array | map(1.0 ** #) array | map(1.0 + #index) array | map(1.0 - 1.0) array | map(1.0 <= #) array | map(1.0 > #) array | map(1.0) array | map(1.0) | groupBy(false) array | map(1.0) | groupBy(foo) array | map(1.0) | map(0) array | map(1.0) | reduce(foo) array | map(1.0) | sortBy(#) array | map([#]) array | map([$env]) array | map([foo]) array | map([list]) array | map(add(#, #)) array | map(add) array | map(add) | map(greet) array | map(add) | reduce(#) array | map(array | findLast(true)) array | map(array) array | map(array) == array array | map(array) | any(false) array | map(array) | findIndex(true) array | map(bitshl(#, #)) array | map(f64 < 1.0) array | map(f64 ^ #) array | map(f64) array | map(f64) ?? $env?.f64 array | map(f64) | findLastIndex(false) array | map(f64) | one(array == $env) array | map(f64) | reduce(#) array | map(f64) | reduce(foo) array | map(f64) | reduce(str, ok) array | map(f64) | sortBy(i) array | map(false && true) array | map(false) array | map(false) != list array | map(false) | none(#) array | map(foo) array | map(foo) != array array | map(foo) ?? greet array | map(foo) | map(#) array | map(foo) | reduce(#) array | map(foo) | reduce(1.0) array | map(foo) | sum(1.0) array | map(foo.Bar) array | map(foo.String) array | map(foo?.Bar) array | map(foo?.String()) array | map(foo?.String) array | map(greet) array | map(greet) | groupBy(true) array | map(greet) | map(#) array | map(i != $env) array | map(i <= 1) array | map(i ^ #) array | map(i) array | map(i) | filter(ok) array | map(i) | groupBy(f64) array | map(i) | reduce(add) array | map(i) | sum(#) array | map(if false { 0 } else { foo }) array | map(len($env)) array | map(let foobar = greet; foobar) array | map(list) array | map(list) | get(i) array | map(max(#)) array | map(mean(#)) array | map(median(#)) array | map(nil == greet) array | map(ok) array | map(ok) | all(ok) array | map(ok) | any(#) array | map(ok) | groupBy(ok) array | map(str) array | map(str) | groupBy(#) array | map(str) | map(#) array | map(sum(array)) array | map(toJSON(f64)) array | map(toJSON(foo)) array | map(true != nil) array | map(true ?? nil) array | map(true) array | map(true) | findLastIndex(#) array | map(true) | reduce(foo) array | map(type(foo)) array | max($env.f64) array | max(0) array | max(0, 0) array | max(0, 1) array | max(0, 1.0) array | max(1) array | max(1, 0) array | max(1, 1.0) array | max(1.0) array | max(array) array | max(f64) array | max(f64, 1.0) array | max(f64, f64) array | max(i) array | max(i, i) array | max(map($env, #index)) array | mean(-1.0) array | mean(0 / 1) array | mean(0) array | mean(0, 1.0, array) array | mean(1) array | mean(1, 0) array | mean(1, 1) array | mean(1, 1.0) array | mean(1.0) array | mean(1.0) * f64 array | mean(1.0, 1) array | mean(1.0, 1.0) array | mean(array) array | mean(array, 0) <= i array | mean(array, array) array | mean(f64) array | mean(f64, 1) array | mean(f64, 1.0) array | mean(i) array | mean(i, 0) array | mean(i, f64) array | median($env.array) array | median($env?.array) array | median(0) array | median(0, i) array | median(1 - 1.0) array | median(1) array | median(1, 1) array | median(1.0) array | median(1.0, 1.0) array | median(1.0, 1.0) ** f64 array | median(1.0, f64) array | median([array]) array | median(array) array | median(f64) array | median(f64) == $env?.ok array | median(f64, 1.0) array | median(i) array | min(-0) array | min(0) array | min(0, 1.0) array | min(0, array) array | min(0, f64) array | min(1) array | min(1, 1) array | min(1.0) array | min(1.0, 1.0) array | min(1.0, i) array | min(array) array | min(array, i) array | min(f64 ?? f64) array | min(f64) array | min(f64) | max(1.0, f64) array | min(f64, 0) array | min(i) array | min(i, 1.0) array | min(i, i) array | min(list | map(#index)) array | none(!true) array | none(# != $env) array | none(# != 1) array | none(# != 1.0) array | none(# != nil) array | none(# < #) array | none(# <= #) array | none(# == #) array | none(# == $env) array | none(# == nil) array | none($env != 1.0) array | none($env.ok) array | none(1 in array) array | none(1.0 < #) array | none(1.0 == i) array | none(1.0 > #) array | none(false ?? foo) array | none(false) array | none(i == #) array | none(ok) array | none(true == $env) array | none(true) array | one(# == #) array | one(# > #) array | one(# > 1.0) array | one(# not in array) array | one($env != $env) array | one($env != foo) array | one($env.ok) array | one(false != false) array | one(false) array | one(false) || ok array | one(i == nil) array | one(list | reduce(true, ok)) array | one(nil != f64) array | one(nil == #) array | one(nil == 1) array | one(nil == foo) array | one(ok) array | one(true) array | one(true) ?? f64 array | reduce(# != #) array | reduce(# * #) array | reduce(# * i) array | reduce(# + #) array | reduce(# - f64) array | reduce(# / #acc) array | reduce(# == 1) array | reduce(# == 1.0) array | reduce(# > #index) array | reduce(# >= 1.0) array | reduce(# | bitshl(0)) array | reduce(#) array | reduce(#) != f64 array | reduce(#) / f64 array | reduce(#) > f64 array | reduce(#) ?? array array | reduce(#) ^ f64 array | reduce(#, $env) array | reduce(#, 0 ^ 0) array | reduce(#, 0) array | reduce(#, 1 / 0) array | reduce(#, 1) array | reduce(#, 1.0) array | reduce(#, add) array | reduce(#, array) array | reduce(#, f64) array | reduce(#, false) array | reduce(#, foo) array | reduce(#, foo) > i array | reduce(#, greet) array | reduce(#, i) array | reduce(#, list) array | reduce(#, nil) array | reduce(#, ok) array | reduce(#, str) array | reduce(#, true) array | reduce(#acc != 1) array | reduce(#acc * 1) array | reduce(#acc ?? nil) array | reduce(#acc) array | reduce(#acc) - f64 array | reduce(#acc) == greet array | reduce(#acc) == {foo: f64, foo: 1} array | reduce(#acc, $env) array | reduce(#acc, 0) array | reduce(#acc, 1.0) in [str, foo] array | reduce(#acc, add) array | reduce(#acc, array) array | reduce(#acc, f64) array | reduce(#acc, foo) array | reduce(#acc, greet) array | reduce(#acc, i) array | reduce(#acc, nil) array | reduce(#acc, true) array | reduce(#index <= f64) array | reduce(#index >= 1) array | reduce(#index) array | reduce(#index, $env) array | reduce(#index, array) array | reduce(#index, f64) array | reduce(#index, false) array | reduce(#index, foo) array | reduce(#index, greet) >= i array | reduce(#index, i) array | reduce(#index, list) array | reduce(#index, nil) array | reduce(#index, ok) array | reduce(#index, str) array | reduce($env != #) array | reduce($env != array) array | reduce($env == greet) array | reduce($env) array | reduce($env) | findLastIndex(true) array | reduce($env) | reduce($env, nil) array | reduce($env, $env) array | reduce($env, 0) array | reduce($env, 1) array | reduce($env, 1.0) array | reduce($env, add) array | reduce($env, array) array | reduce($env, f64) array | reduce($env, false) array | reduce($env, foo) array | reduce($env, greet) array | reduce($env, i) array | reduce($env, list) array | reduce($env, nil) array | reduce($env, ok) array | reduce($env, ok) | map(array) array | reduce($env, str) array | reduce($env, true) array | reduce($env.ok) array | reduce($env?.Bar) array | reduce($env?.[Bar]) array | reduce($env?.[String]) array | reduce($env?.[String]?.foo()) array | reduce($env?.array) array | reduce($env?.f64) array | reduce($env?.foo) array | reduce($env?.i) array | reduce($env?.list, foo?.String) array | reduce(-#) array | reduce(-1.0, str) array | reduce(0 + i) array | reduce(0 .. #) array | reduce(0 <= #index) array | reduce(0 == #) array | reduce(0 > #) array | reduce(0) array | reduce(0) ?? add array | reduce(0, $env) array | reduce(0, 0) array | reduce(0, 1.0) array | reduce(0, array) array | reduce(0, foo) array | reduce(0, i) array | reduce(0, list) array | reduce(0, ok) array | reduce(0, str) array | reduce(0, true) array | reduce(1 ** #acc) array | reduce(1 ?? str) array | reduce(1) array | reduce(1, 0) array | reduce(1, 1) array | reduce(1, 1.0) array | reduce(1, add) array | reduce(1, array) array | reduce(1, f64) array | reduce(1, false) array | reduce(1, foo) array | reduce(1, greet) array | reduce(1, nil) array | reduce(1, ok) array | reduce(1, str) array | reduce(1.0 * 1) array | reduce(1.0 ** #) array | reduce(1.0 > 1.0) array | reduce(1.0 ?? $env) array | reduce(1.0) array | reduce(1.0) != f64 array | reduce(1.0) / f64 array | reduce(1.0) < i <= f64 array | reduce(1.0, $env) array | reduce(1.0, 0) array | reduce(1.0, 1) array | reduce(1.0, 1.0) array | reduce(1.0, array) array | reduce(1.0, f64) array | reduce(1.0, false) array | reduce(1.0, foo) array | reduce(1.0, greet) array | reduce(1.0, i) array | reduce(1.0, list) array | reduce(1.0, nil) array | reduce(1.0, ok) array | reduce(1.0, str) array | reduce(1.0, true) array | reduce(add) array | reduce(add, $env) array | reduce(add, 0) array | reduce(add, 1.0) array | reduce(add, array) array | reduce(add, f64) array | reduce(add, false) array | reduce(add, foo) array | reduce(add, greet) array | reduce(add, i) array | reduce(add, list) array | reduce(add, nil) array | reduce(add, ok) array | reduce(add, str) array | reduce(all($env, true)) array | reduce(array) array | reduce(array) | map(#) array | reduce(array) | none(true) array | reduce(array) | reduce(false) array | reduce(array) | sortBy(#) array | reduce(array, $env) array | reduce(array, 0) array | reduce(array, 1) array | reduce(array, 1.0) array | reduce(array, f64) array | reduce(array, false) array | reduce(array, foo) array | reduce(array, greet) array | reduce(array, list) array | reduce(array, nil) array | reduce(array, ok) array | reduce(bitnot(#)) array | reduce(concat(list), $env.greet) array | reduce(f64 ^ 0) array | reduce(f64) array | reduce(f64, $env) array | reduce(f64, 0) array | reduce(f64, 1) array | reduce(f64, 1.0) array | reduce(f64, array) array | reduce(f64, f64) array | reduce(f64, false) array | reduce(f64, foo) array | reduce(f64, i) array | reduce(f64, list) array | reduce(f64, nil) array | reduce(f64, true) array | reduce(false) array | reduce(false, $env) array | reduce(false, 0) array | reduce(false, 1) array | reduce(false, 1.0) array | reduce(false, add) array | reduce(false, false) array | reduce(false, foo) array | reduce(false, greet) array | reduce(false, i) array | reduce(false, list) array | reduce(false, nil) array | reduce(false, ok) array | reduce(false, true) array | reduce(foo) array | reduce(foo) ?? list array | reduce(foo, $env) array | reduce(foo, 0) array | reduce(foo, 1) array | reduce(foo, 1.0) array | reduce(foo, add) array | reduce(foo, array) array | reduce(foo, f64) array | reduce(foo, false) array | reduce(foo, foo) array | reduce(foo, i) array | reduce(foo, list) array | reduce(foo, nil) array | reduce(foo, ok) array | reduce(foo, str) array | reduce(foo, true) array | reduce(foo.String, $env?.[Bar]) array | reduce(foo?.Bar) array | reduce(greet != $env) array | reduce(greet(str), int(1.0)) array | reduce(greet) array | reduce(greet, $env) array | reduce(greet, 0) array | reduce(greet, 1) array | reduce(greet, 1.0) array | reduce(greet, add) array | reduce(greet, array) array | reduce(greet, f64) array | reduce(greet, false) array | reduce(greet, foo) array | reduce(greet, greet) array | reduce(greet, i) array | reduce(greet, nil) array | reduce(greet, str) array | reduce(greet, true) array | reduce(i * #) array | reduce(i > 1) array | reduce(i >= 1) array | reduce(i) array | reduce(i, $env) array | reduce(i, 0) array | reduce(i, 1) array | reduce(i, 1.0) array | reduce(i, array) array | reduce(i, false) array | reduce(i, foo) array | reduce(i, greet) array | reduce(i, i) array | reduce(i, list) array | reduce(i, nil) array | reduce(i, ok) array | reduce(i, true) array | reduce(int(#)) array | reduce(list) array | reduce(list, $env) array | reduce(list, 0) array | reduce(list, 1) array | reduce(list, 1.0) array | reduce(list, add) array | reduce(list, array) array | reduce(list, false) array | reduce(list, foo) array | reduce(list, greet) array | reduce(list, i) array | reduce(list, list) array | reduce(list, nil) array | reduce(list, ok) array | reduce(list, ok) | all(true) array | reduce(list, true) array | reduce(median(#)) array | reduce(median(0)) array | reduce(nil != #) array | reduce(not false) array | reduce(not true) array | reduce(ok ?? 1.0) array | reduce(ok) array | reduce(ok) ?? array array | reduce(ok, $env) array | reduce(ok, 0) array | reduce(ok, 1.0) array | reduce(ok, add) array | reduce(ok, array) array | reduce(ok, false) array | reduce(ok, foo) array | reduce(ok, greet) array | reduce(ok, i) array | reduce(ok, list) array | reduce(ok, nil) array | reduce(ok, true) array | reduce(str) array | reduce(str) | greet() array | reduce(str, $env) array | reduce(str, -1.0) array | reduce(str, 1) array | reduce(str, 1.0) array | reduce(str, abs(1)) array | reduce(str, add) array | reduce(str, array) array | reduce(str, false) array | reduce(str, foo) array | reduce(str, greet) array | reduce(str, i) array | reduce(str, list) array | reduce(str, nil) array | reduce(str, ok) array | reduce(string(1.0)) array | reduce(string(add)) array | reduce(toJSON(array)) array | reduce(true and true) array | reduce(true) array | reduce(true, $env) array | reduce(true, 0) array | reduce(true, 1) array | reduce(true, 1.0) array | reduce(true, add) array | reduce(true, array) array | reduce(true, foo) array | reduce(true, i) array | reduce(true, nil) array | reduce(true, ok) array | reduce(true, str) array | reduce(true, true) array | reduce(type(greet)) array | sortBy(# + #) array | sortBy(# + 1.0) array | sortBy(# + i) array | sortBy(# / #) array | sortBy(# / 1.0) array | sortBy(# ?? ok) array | sortBy(# ^ 1.0) array | sortBy(# ^ f64) array | sortBy(# | bitushr(#)) array | sortBy(#) array | sortBy(#) ?? [0, $env] array | sortBy(#) | all(ok) array | sortBy(#) | groupBy(#) array | sortBy(#) | groupBy(f64) array | sortBy(#) | map(#) array | sortBy(#) | map(#index) array | sortBy(#) | map(foo) array | sortBy(#) | reduce(#) array | sortBy(#) | reduce(1.0) array | sortBy(#) | reduce(ok) array | sortBy(#) | sum(1) array | sortBy($env.add(#, 1)) array | sortBy($env?.[str]) array | sortBy($env?.i) array | sortBy(-#) array | sortBy(-0) array | sortBy(0 / #) array | sortBy(0 ^ #) array | sortBy(0) array | sortBy(0) | median(1.0) array | sortBy(0) | reduce(0) array | sortBy(0) | reduce(foo, foo) array | sortBy(1) array | sortBy(1.0 ^ #) array | sortBy(1.0) array | sortBy(1.0) != list array | sortBy(1.0) ?? i array | sortBy(1.0) | findLastIndex(ok) array | sortBy(1.0) | one(true) array | sortBy(1.0) | reduce($env) array | sortBy(1.0) | sortBy(#) array | sortBy(array | reduce(1.0)) array | sortBy(array?.[i]) array | sortBy(bitnot(i)) array | sortBy(f64) array | sortBy(f64) | map(#) array | sortBy(f64) | sortBy(1.0) array | sortBy(f64) | sortBy(i) array | sortBy(floor(#)) array | sortBy(foo.String()) array | sortBy(i - 1) array | sortBy(i) array | sortBy(i) | sortBy(#) array | sortBy(max(#)) array | sortBy(mean(#)) array | sortBy(median(#)) array | sortBy(reduce(array, str, foo)) array | sortBy(str + str) array | sortBy(str) array | sortBy(str) | reduce(#) array | sortBy(sum(array)) array | sortBy(true ? # : $env) array | sortBy(type(f64)) array | sortBy(type(true)) array | sum(# ** #) array | sum(# + #) array | sum(# - #) array | sum(# ?? 0) array | sum(# ^ 1) array | sum(# ^ i) array | sum(#) array | sum(#) < 1.0 ^ 1.0 array | sum(#) <= f64 array | sum(#) ^ f64 array | sum($env.f64) array | sum($env.i) array | sum(-0) array | sum(-1) array | sum(-i) array | sum(0 ** 1.0) array | sum(0) array | sum(0.1) array | sum(1 * f64) array | sum(1 + 1.0) array | sum(1 | max(1.0)) array | sum(1) array | sum(1) not in array array | sum(1.0 * #) array | sum(1.0 ** #) array | sum(1.0 - 1.0) array | sum(1.0) array | sum(1.0) < i array | sum(1.0) > 1.0 ^ i array | sum(array?.[i]) array | sum(bitnot(1)) array | sum(bitshl(#, #)) array | sum(ceil(#)) array | sum(f64) array | sum(f64) ?? str array | sum(float(f64)) array | sum(i + 0) array | sum(i | bitshr(1)) array | sum(i) array | sum(i) > -0 array | sum(int(#)) array | sum(max(#, 1)) array | sum(median(#)) array | sum(round(1.0)) array | take(0) array | take(0) | one(ok) array | take(1) array | take(i) array; $env.ok array; add array; array array; f64 array; f64; array array; foo array; foo.String array; greet array; i array; list array; ok array?.[$env.i] array?.[$env?.i] array?.[-0] array?.[-i] array?.[0 % i] array?.[1.0 ?? foo] array?.[1] % i array?.[1] .. i array?.[1] / f64 array?.[array?.[i]] array?.[bitnot(i)] array?.[i] array?.[i] != 1.0 ?: 1.0 array?.[i] != f64 array?.[i] != i * 1.0 array?.[i] != i ?? f64 array?.[i] % i array?.[i] * f64 array?.[i] * i array?.[i] ** 0 ?? ok array?.[i] ** i array?.[i] + f64 array?.[i] - f64 array?.[i] - i array?.[i] .. i array?.[i] .. i ?? 1.0 array?.[i] / ceil(f64) array?.[i] / f64 array?.[i] / float(0) array?.[i] / i array?.[i] < 0 + 1.0 array?.[i] < f64 array?.[i] < i array?.[i] <= 1.0 <= $env array?.[i] <= f64 array?.[i] <= i array?.[i] == $env.i array?.[i] == -f64 array?.[i] == array ?? $env array?.[i] == f64 array?.[i] == i array?.[i] > f64 array?.[i] > i array?.[i] >= f64 array?.[i] >= i array?.[i] ?? $env?.Bar.greet array?.[i] ?? f64 array?.[i] ?? foo?.String() array?.[i] ?? greet array?.[i] ?? ok array?.[i] ?? str array?.[i] ^ f64 array?.[i] ^ f64 <= 1 array?.[i] ^ i array?.[i] in array array?.[i] not in array array?.[i] | add(i) array?.[i] | bitand(1) array?.[i] | bitshr(0) array?.[i] | max(1) array?.[i] | mean(1) array?.[i] | min(0) array?.[i] | min(array) array?.[int(1.0)] array?.[len(list)] array?.[list | count(ok)] array?.[max(0)] array?.[mean(1)] array?.[mean(i)] array?.[median(1)] array[$env | count(true):] array[$env.i:] array[$env?.i:] array[-i:] array[0:] | any(ok) array[0:] | map(greet) array[0:] | reduce(#) array[0:] | reduce(add) array[0:] | reduce(str) array[0:] | sortBy(#) array[0:]?.[i] array[1:] == list array[1:] | any(ok) array[1:] | findLast(false) array[1:] | reduce(#) array[1:] | reduce(foo) array[1:] | reduce(list, nil) array[1:] | sum(#) array[1:] | sum(1.0) array[1:]?.[i] array[:$env.i] array[:-1] array[:-i] array[:0 ?? foo] array[:0] ?? ok array[:0] | groupBy(str) array[:0] | sortBy(#) array[:0] | sum(str) array[:1 ?? 0] array[:1 ?? false] array[:1 ?? greet] array[:1] | findLastIndex(false) array[:1] | sortBy(#) array[:1] | sum(#) array[:] array[:] | map(f64) array[:] | reduce(f64) array[:]?.[i] array[:i] array[:i] ?? !ok array[:i] | map(#) array[:i] | map(f64) array[:i] | reduce($env) array[:i] | reduce(0) array[:i] | sortBy(array) array[:i] | sortBy(ok) array[:int(1.0)] array[:max(i)] array[:nil ?? 0] array[:reduce(array, 1)] array[:sum(array)] array[array?.[i]:] array[bitnot(1):] array[i % 1:] array[i:] array[i:] ?? list array[i:] | findIndex(false) array[i:] | groupBy(1) array[i:]?.[i] array[int(1):] array[len($env):] array[max(0):] array[sum(array):] bitand($env.i, i) bitand(1, 1) | median(0) bitand(1, i) * i bitand(i, 0) + f64 bitand(i, 0) > i bitand(i, i) bitand(i, sum(array)) bitnand($env.i, i) bitnand(-i, i) bitnand(i + i, i) bitnand(i, i) bitnand(i, i) % i bitnand(sum(array), i) bitnot($env | findIndex(true)) bitnot($env | findLastIndex(ok)) bitnot($env | findLastIndex(true)) bitnot($env.i) bitnot($env?.[str]?.[i]) bitnot($env?.i) bitnot(-$env.i) bitnot(-0 ?? 1) bitnot(-0) bitnot(-1) bitnot(-i) bitnot(-min(array, 1.0)) bitnot(0 * 1) bitnot(0 * i) bitnot(0 + 1) bitnot(0 - 0) bitnot(0 - 1) bitnot(0 - i) bitnot(0 ?? $env) bitnot(0 ?? 1.0) bitnot(0 ?? foo) bitnot(0 ?? greet) bitnot(0 ?? i) bitnot(0 ?? str) bitnot(0 | min(0)) bitnot(0) + f64 bitnot(0) + i bitnot(0) - $env.i bitnot(0) < f64 bitnot(0) <= f64 bitnot(0) == $env?.[Bar] bitnot(0) > $env?.i bitnot(0) ?? array bitnot(0) ?? ok bitnot(0) in array bitnot(0) not in array bitnot(0) | min(array, 0) bitnot(1 % 1) bitnot(1 % i) bitnot(1 * 0) bitnot(1 + 1) bitnot(1 - i) bitnot(1 ?? $env) bitnot(1 ?? 0) bitnot(1 ?? 1) bitnot(1 ?? foo) bitnot(1 ?? list) bitnot(1 ?? ok) bitnot(1 ?? true) bitnot(1 | bitshr(i)) bitnot(1 | min(i)) bitnot(1) != i bitnot(1) != i && false bitnot(1) * i bitnot(1) - f64 bitnot(1) == f64 bitnot(1) > i bitnot(1) ?? list bitnot(1) ^ f64 bitnot(1) | bitand(1) bitnot(abs(0)) bitnot(abs(1)) bitnot(abs(i)) bitnot(array | count(false)) bitnot(array | count(ok)) bitnot(array | findIndex(ok)) bitnot(array | findLast(true)) bitnot(array | reduce(#)) bitnot(array | reduce(i)) bitnot(array | sum(#)) bitnot(array | sum(i)) bitnot(array?.[0]) bitnot(array?.[i]) bitnot(bitand(1, 0)) bitnot(bitnot(0 ?? foo)) bitnot(bitnot(0)) bitnot(bitnot(1)) bitnot(bitnot(i)) bitnot(count(array, false)) bitnot(count(array, true)) bitnot(count(list, false)) bitnot(count(list, ok)) bitnot(false ? nil : 1) bitnot(false ?: 1) bitnot(findIndex($env, ok)) bitnot(findIndex(array, ok)) bitnot(findIndex(list, ok)) bitnot(findLastIndex(array, true)) bitnot(findLastIndex(list, ok)) bitnot(first(array)) bitnot(i % i) bitnot(i * 0) bitnot(i * 1) bitnot(i + 0) bitnot(i - 0) bitnot(i - 1) bitnot(i ?? $env) bitnot(i ?? 0) bitnot(i ?? array) bitnot(i ?? foo) bitnot(i ?? list) bitnot(i ?? ok) bitnot(i ?? str) bitnot(i ?? true) bitnot(i | add(i)) bitnot(i | min(1.0)) bitnot(i) bitnot(i) != f64 bitnot(i) != i bitnot(i) * -1.0 bitnot(i) + i bitnot(i) - i bitnot(i) > f64 bitnot(i) ?? $env.str bitnot(i) ?? ok bitnot(i) | bitshr(0) bitnot(i) | median(array) bitnot(if false { f64 } else { 0 }) bitnot(if true { 1 } else { 0 }) bitnot(if true { 1 } else { foo }) bitnot(int(0)) bitnot(int(1)) bitnot(int(1.0)) bitnot(int(f64)) bitnot(int(f64)) ** i bitnot(int(i)) bitnot(last(array)) bitnot(len($env)) bitnot(len(array)) bitnot(len(list)) bitnot(len(str)) bitnot(list | count(true)) bitnot(list | findIndex(ok)) bitnot(list | findLastIndex(ok)) bitnot(list | findLastIndex(true)) bitnot(list | reduce(1)) bitnot(list | sum(1)) bitnot(max(0)) bitnot(max(1)) bitnot(max(1, 0)) bitnot(max(array)) bitnot(max(array, 0)) bitnot(max(i)) bitnot(min(0)) bitnot(min(1)) bitnot(min(array)) bitnot(min(i)) bitnot(min(i, 0)) bitnot(nil ?? 1) bitnot(nil ?? i) bitnot(reduce(array, #)) bitnot(reduce(array, 0)) bitnot(reduce(list, i)) bitnot(reduce(reverse(list), #index)) bitnot(sum($env, 0)) bitnot(sum($env, 1)) bitnot(sum(array)) bitnot(sum(array, #)) bitnot(sum(list, 0)) bitnot(sum(list, 1)) bitnot(sum(list, i)) bitor($env.i, i) bitor(1, i) > f64 bitor(i, 1) ?? add bitor(i, array?.[i]) bitor(i, i) bitor(i, len(list)) bitor(i, list | count(true)) bitshl(i, $env?.i) bitshl(i, i) bitshl(int(f64), i) bitshr(0, 1) + f64 bitshr(1, 0) + i bitshr(i, $env?.i) bitshr(i, i) bitshr(i, sum(array)) bitushr(1, 0) .. i bitushr(array | count(ok), i) bitushr(i, $env?.i) bitushr(i, i) bitxor(i, 1 ?? array) bitxor(i, i) bitxor(i, i) ?? $env?.f64 ceil($env | findIndex(true)) ceil($env | reduce(1.0, nil)) ceil($env | sum(0)) ceil($env | sum(1)) ceil($env | sum(1.0)) ceil($env | sum(f64)) ceil($env | sum(i)) ceil($env.f64) ceil($env.f64) not in array ceil($env.i) ceil($env?.[str] | sum(1.0)) ceil($env?.array | findLast(ok)) ceil($env?.array?.[i]) ceil($env?.f64) ceil($env?.i) ceil($env?.i) < f64 ceil(--i) ceil(-0) ceil(-1) ceil(-1.0) ceil(-f64) ceil(-i) ceil(0 * 0) ceil(0 * 1) ceil(0 * 1.0) ceil(0 * f64) ceil(0 ** 1) ceil(0 ** 1.0) ceil(0 ** f64) ceil(0 + 0) ceil(0 + 1) ceil(0 + 1.0) ceil(0 + i) ceil(0 - 0) ceil(0 - 1.0) ceil(0 - f64) ceil(0 - i) ceil(0 / 0) ceil(0 / 1) ceil(0 / 1.0) ceil(0 / f64) ceil(0 / i) ceil(0 ?? $env) ceil(0 ?? 0) ceil(0 ?? 1) ceil(0 ?? array) ceil(0 ?? f64) ceil(0 ?? false) ceil(0 ?? foo) ceil(0 ?? greet) ceil(0 ?? list) ceil(0 ?? nil) ceil(0 ?? ok) ceil(0 ?? true) ceil(0 ^ 0) ceil(0 ^ 1.0) ceil(0 ^ f64) ceil(0 ^ i) ceil(0 | add(i)) ceil(0 | bitshl(i)) ceil(0 | median(1.0)) ceil(0) != $env?.[String] ceil(0) != f64 ceil(0) * f64 ceil(0) ** 0 ^ 1.0 ceil(0) ** i ceil(0) / i ceil(0) <= f64 ceil(0) ?? list ceil(0) ?? type(1.0) ceil(0) in {foo: greet}?.str ceil(0.0) ceil(0.1) ceil(1 % 1) ceil(1 * 0) ceil(1 * f64) ceil(1 ** 1) ceil(1 ** 1.0) ceil(1 ** f64) ceil(1 + 0) ceil(1 + 1.0) ceil(1 + f64) ceil(1 + i) ceil(1 - 0) ceil(1 - 1.0) ceil(1 / 1.0) ceil(1 ?? $env) ceil(1 ?? f64) ceil(1 ?? greet) ceil(1 ?? i) ceil(1 ?? nil) ceil(1 ?? true) ceil(1 ^ 1.0) ceil(1 ^ i) ceil(1 | bitor(0)) ceil(1 | min(1.0)) ceil(1) != i ceil(1) - i ceil(1) / i ceil(1) > f64 ceil(1) ?? i ceil(1) ^ i ceil(1) | median(1.0, 1) ceil(1) | min(array) ceil(1); f64 ceil(1.0 * 0) ceil(1.0 * 1) ceil(1.0 * 1.0) ceil(1.0 * f64) ceil(1.0 * i) ceil(1.0 ** 1) ceil(1.0 ** 1.0) ceil(1.0 ** i) ceil(1.0 + 0) ceil(1.0 + 1) ceil(1.0 + 1.0) ceil(1.0 + f64) ceil(1.0 + i) ceil(1.0 - 0) ceil(1.0 - 1) ceil(1.0 - 1.0) ceil(1.0 - f64) ceil(1.0 - i) ceil(1.0 / 0) ceil(1.0 / 1) ceil(1.0 / 1.0) ceil(1.0 / f64) ceil(1.0 ?? $env) ceil(1.0 ?? 0) ceil(1.0 ?? 1) ceil(1.0 ?? add) ceil(1.0 ?? array) ceil(1.0 ?? f64) ceil(1.0 ?? false) ceil(1.0 ?? foo) ceil(1.0 ?? greet) ceil(1.0 ?? i) ceil(1.0 ?? list) ceil(1.0 ?? nil) ceil(1.0 ?? ok) ceil(1.0 ?? true) ceil(1.0 ^ 0) ceil(1.0 ^ 1) ceil(1.0 ^ 1.0) ceil(1.0 ^ f64) ceil(1.0 ^ i) ceil(1.0 | max(array)) ceil(1.0 | mean(1, 1.0)) ceil(1.0 | mean(1.0)) ceil(1.0 | median(array)) ceil(1.0 | min(1)) ceil(1.0) != $env or $env ceil(1.0) != f64 ceil(1.0) ** f64 ceil(1.0) <= f64 ceil(1.0) <= i ceil(1.0) == nil ? foo : str ceil(1.0) > i ceil(1.0) >= f64 ceil(1.0) ?? add ceil(1.0) ?? list ceil(1.0) not in array ceil(1.0) | mean(1) ceil(1.1) ceil(abs(0)) ceil(abs(1.0)) ceil(abs(f64)) ceil(abs(i)) ceil(array | count(ok)) ceil(array | mean(1.0)) ceil(array | reduce(#)) ceil(array | reduce(#, greet)) ceil(array | reduce(i, f64)) ceil(array | sum(#)) ceil(array | sum(0)) ceil(array | sum(f64)) ceil(array?.[0]) ceil(array?.[i]) ceil(bitnot(0)) ceil(bitnot(1)) ceil(ceil(0)) ceil(ceil(1)) ceil(ceil(1.0)) ceil(ceil(f64)) ceil(ceil(i)) ceil(count($env, false)) ceil(count($env, true)) ceil(f64 * 0) ceil(f64 * 1) ceil(f64 * 1.0) ceil(f64 * f64) ceil(f64 ** 0) ceil(f64 ** 1) ceil(f64 ** 1.0) ceil(f64 ** i) ceil(f64 + 1) ceil(f64 + 1.0) ceil(f64 + f64) ceil(f64 - 1) ceil(f64 - 1.0) ceil(f64 / 0) ceil(f64 / 1) ceil(f64 / 1.0) ceil(f64 / f64) ceil(f64 / i) ceil(f64 ?? $env) ceil(f64 ?? 0) ceil(f64 ?? 1.0) ceil(f64 ?? array) ceil(f64 ?? f64) ceil(f64 ?? false) ceil(f64 ?? greet) ceil(f64 ?? i) ceil(f64 ?? true) ceil(f64 ^ 0) ceil(f64 ^ 1.0) ceil(f64 ^ i) ceil(f64 | max(1)) ceil(f64 | median(1)) ceil(f64 | min(1.0)) ceil(f64) ceil(f64) != -f64 ceil(f64) != i ceil(f64) * f64 ceil(f64) * i ceil(f64) - i ceil(f64) / 1 + i ceil(f64) == f64 ceil(f64) == i ceil(f64) ^ f64 ceil(f64) ^ i ceil(f64) | median(1) ceil(f64) | median(1.0, i, i) ceil(false ? 1.0 : 1) ceil(false ?: 0) ceil(false ?: 1) ceil(false ?: i) ceil(findIndex($env, true)) ceil(findIndex(array, true)) ceil(findLast(array, ok)) ceil(findLastIndex($env, true)) ceil(findLastIndex(array, true)) ceil(first(array)) ceil(float(0)) ceil(float(1)) ceil(float(1.0)) ceil(float(f64)) ceil(float(i)) ceil(floor(0)) ceil(floor(1)) ceil(floor(1.0)) ceil(floor(f64)) ceil(floor(f64)) ?? list ceil(floor(i)) ceil(i % 1) not in array ceil(i % i) ceil(i * 1) ceil(i * 1.0) ceil(i * i) ceil(i ** 0) ceil(i ** 1) ceil(i ** 1.0) ceil(i ** f64) ceil(i + 1) ceil(i + 1.0) ceil(i + i) ceil(i - 0) ceil(i - 1.0) ceil(i - i) ceil(i / 0) ceil(i / 1) ceil(i / 1.0) ceil(i / f64) ceil(i / i) ceil(i ?? 0) ceil(i ?? add) ceil(i ?? array) ceil(i ?? foo) ceil(i ?? true) ceil(i ^ 0) ceil(i ^ 1) ceil(i ^ 1.0) ceil(i ^ f64) ceil(i ^ i) ceil(i | min(0)) ceil(i | min(1.0)) ceil(i | min(array)) ceil(i) ceil(i) != 0 ?: 1.0 ceil(i) != i ceil(i) - i ceil(i) == i ceil(i) > i ceil(i) >= f64 ceil(i) >= min(1) ceil(i) ?? -1.0 ceil(if false { false } else { f64 }) ceil(if false { str } else { 1.0 }) ceil(if false { true } else { 0 }) ceil(if ok { 0 } else { 0 }) ceil(if true { 1.0 } else { 1.0 }) ceil(if true { 1.0 } else { f64 }) ceil(if true { i } else { foo }) ceil(indexOf(str, str)) ceil(int(0)) ceil(int(1)) ceil(int(1.0)) ceil(int(f64)) ceil(int(i)) ceil(last(array)) ceil(len($env)) ceil(len(array)) ceil(len(list)) ceil(len(str)) ceil(let foobar = 1.0; foobar) ceil(let foobar = f64; foobar + foobar) ceil(list | reduce(0)) ceil(list | reduce(0, 1.0)) ceil(list | reduce(f64)) ceil(list | sum(i)) ceil(max(0)) ceil(max(1)) ceil(max(1.0)) ceil(max(array)) ceil(max(array, 1.0)) ceil(max(f64)) ceil(max(f64, f64)) ceil(max(i)) ceil(mean(0)) ceil(mean(1)) ceil(mean(1.0 ^ 1.0)) ceil(mean(1.0)) ceil(mean(array)) ceil(mean(f64)) ceil(mean(f64, 1)) ceil(mean(i)) ceil(mean(i, i, 0)) ceil(mean(mean(1.0))) ceil(median(0)) ceil(median(1)) ceil(median(1.0)) ceil(median(1.0, 0)) ceil(median(1.0, array)) ceil(median(1.0, i)) ceil(median(array)) ceil(median(f64)) ceil(median(i)) ceil(median(i, 1.0)) ceil(min(0)) ceil(min(1)) ceil(min(1.0)) ceil(min(1.0, f64)) ceil(min(1.0, i)) ceil(min(array)) ceil(min(f64)) ceil(min(i)) ceil(nil ?? 1) ceil(nil ?? i) ceil(reduce($env, 1, $env)) ceil(reduce(array, #)) ceil(reduce(array, #acc)) ceil(reduce(array, 1.0)) ceil(reduce(array, f64)) ceil(reduce(list, 0)) ceil(reduce(list, 1)) ceil(round(0)) ceil(round(1)) ceil(round(1.0)) ceil(round(f64)) ceil(round(i)) ceil(sum($env, f64)) ceil(sum($env.array)) ceil(sum(array)) ceil(sum(array, #)) ceil(sum(list, 1.0)) ceil(sum(list, f64)) ceil({foo: 1.0}?.foo) concat($env | map(1.0)) concat($env | map(1.0))[:i] concat($env | map(add)) concat($env | map(array)) concat($env | map(foo)) concat($env | map(greet)) concat($env.array) concat($env.list) concat($env?.array | sortBy(#)) concat($env?.array) concat($env?.list) concat(0 .. 1) concat(0 .. i) concat(1 .. 0) concat(1 .. 1) concat(1 .. i) concat(1..i) concat([$env, $env]) concat([$env, 1]) concat([$env, add]) concat([$env, nil]) concat([$env]) concat([0]) concat([1, foo]) concat([1.0 - 1.0]) concat([1.0, $env]) concat([1.0]) concat([1]) concat([add, $env]) concat([add]) concat([array, 1.0]) concat([array, 1]) concat([array]) concat([f64, foo]) concat([f64]) concat([false, $env]) concat([false]) concat([foo, 1.0]) concat([foo, array]) concat([foo]) concat([greet, 0]) concat([greet]) concat([i, 1.0]) concat([i]) concat([list]) concat([nil]) concat([ok, $env]) concat([ok]) concat([str]) concat([true, list]) concat([true, str]) concat([true]) concat([true], array) concat(array ?? $env) concat(array ?? 1) concat(array ?? add) concat(array ?? f64) concat(array ?? greet) concat(array ?? nil) concat(array ?? true) concat(array | map(#)) concat(array | map($env)) concat(array | map(foo)) concat(array | sortBy(#)) concat(array | sortBy(f64)) concat(array | sortBy(i)) concat(array | take(0)) concat(array) concat(array) == array concat(array) == list concat(array) | all(ok) concat(array) | any(false) concat(array) | any(ok) concat(array) | count(1.0 >= f64) concat(array) | count(ok) concat(array) | groupBy(#) concat(array) | groupBy(0) concat(array) | groupBy(1.0) concat(array) | groupBy(true) concat(array) | map(0) concat(array) | map(1.0) concat(array) | map(f64) concat(array) | map(list) concat(array) | map(ok) concat(array) | max(1.0) concat(array) | reduce(#) concat(array) | reduce(1, foo) concat(array) | reduce(str) concat(array) | sortBy(f64) concat(array) | sum(#) concat(array)?.[i] concat(array, [greet]) concat(array, array) concat(array, array)?.[i] concat(array, array, [list]) concat(array, list) concat(array[0:]) concat(array[1:]) concat(array[:0]) concat(array[:1]) concat(array[:]) concat(array[i:]) concat(concat(array)) concat(concat(array, array)) concat(concat(list)) concat(false ?: array) concat(false ?: list) concat(filter($env, false)) concat(flatten($env.array)) concat(flatten(array)) concat(flatten(list)) concat(i .. 0) concat(i..i) concat(keys($env)) concat(keys({foo: array, foo: i})) concat(list ?? $env) concat(list ?? 1) concat(list ?? 1.0) concat(list ?? foo) concat(list ?? i) concat(list ?? str) concat(list ?? true) concat(list | filter(ok)) concat(list | map(#)) concat(list | map($env)) concat(list | map(.String)) concat(list | map(1)) concat(list | map(1.0)) concat(list | map(foo)) concat(list | map(list), array) concat(list | sortBy(1.0)) concat(list | sortBy(i)) concat(list) concat(list) == [1, str] concat(list) | any(ok) concat(list) | count(false) concat(list) | findIndex(true) concat(list) | groupBy(#) concat(list) | groupBy(0) concat(list) | groupBy(1) concat(list) | groupBy(1.0) concat(list) | groupBy(foo) concat(list) | map(0) concat(list) | map(add) concat(list) | map(f64) concat(list) | map(foo) concat(list) | none(ok) concat(list) | reduce(#) concat(list) | reduce(1.0, foo) concat(list) | reduce(f64) concat(list) | reduce(foo) concat(list) | reduce(i, str) concat(list) | sum(1) concat(list) | sum(i) concat(list)?.[i] concat(list, $env.array) concat(list, array) concat(list, array)?.[i] concat(list, list | sortBy(i)) concat(list, list) concat(list, list) | any(true) concat(list, list)?.[i] concat(list[1:]) concat(map($env, #index)) concat(map($env, $env)) concat(map($env, 1.0)) concat(map($env, array)) concat(map($env, array), list) concat(map($env, f64)) concat(map($env, foo)) concat(map($env, list)) concat(map($env, ok)) concat(map(array, #)) concat(map(array, $env)) concat(map(array, 1)) concat(map(array, 1.0)) concat(map(array, f64)) concat(map(array, foo)) concat(map(list, #)) concat(map(list, $env)) concat(map(list, 0)) concat(map(list, 1.0)) concat(map(list, add)) concat(map(list, greet)) concat(map(list, i)) concat(map(list, str)) concat(reduce(list, array)) concat(reverse(array)) concat(reverse(list)) concat(sort($env)) concat(sort(array)) concat(sortBy(array, #)) concat(sortBy(array, 1.0)) concat(sortBy(list, 1.0)) concat(sortBy(list, i)) concat(toPairs($env)) concat(toPairs({foo: false, foo: add})) concat(uniq(array)) concat(values($env)) count($env ?? f64, .greet and false) count($env | filter(false)) count($env | map(false)) count($env | map(foo), ok) count($env | map(ok)) count($env | map(true)) count($env, false) ^ i count($env, ok) | bitushr(0) count($env, true) ** i count($env, true) <= 1.0 == $env count($env, true) <= f64 count($env, true) > i count($env.list, foo != foo) count($env.list, ok) count($env?.[str], true != nil) count($env?.array, ok) count($env?.list, ok) count(0 .. 0, $env == list) count(1 .. 0) count([$env && false]) count([$env, true], 1 == $env) count([false, false]) count([false, true]) count([false]) count([false], #) count([foo] | filter(false)) count([nil], 1.0 >= 1.0) count([ok]) count([ok], #) count([true]) count(array ?? 0, 1.0 not in array) count(array | filter(false)) count(array | filter(nil == #)) count(array | map(false)) count(array | map(ok)) count(array, !false) count(array, # != #) count(array, # != i) count(array, # <= #) count(array, # == nil) count(array, # > #) count(array, # >= 1) count(array, # >= f64) count(array, # >= i) count(array, # not in array) count(array, $env != #) count(array, $env.ok) count(array, $env?.false != nil and ok) count(array, 0 <= 1.0) count(array, 0 == #) count(array, 0 == $env) count(array, 1 != nil) count(array, 1 == f64) count(array, 1 > #) count(array, 1.0 != #) count(array, 1.0 != nil) count(array, 1.0 == $env) count(array, 1.0 == nil) count(array, array | none(true)) count(array, f64 < #) count(array, false and $env) count(array, false) <= 1 ^ i count(array, false) ^ f64 count(array, foo in list) count(array, i >= #) count(array, nil == $env) count(array, nil == 1.0) count(array, nil == nil) count(array, nil ?? false) count(array, ok != false) count(array, ok) count(array, ok) ?? ok count(array, ok) ^ f64 count(array, true == ok) count(array, true) in array count(array[:0]) count(filter($env, false)) count(filter(list, # != #)) count(filter(list, false)) count(groupBy(list, 1.0).str) count(i .. 0) count(keys($env), ok || #) count(list ?? $env, $env?.ok) count(list | filter(false)) count(list | map(false)) count(list | map(true)) count(list, # != foo) count(list, # != nil) count(list, # == foo) count(list, #.Bar == nil) count(list, #.Bar matches .Bar) count(list, $env == $env) count(list, $env in array) count(list, $env?.ok) count(list, 0 != nil) count(list, 0 <= f64) count(list, 0 == i) count(list, 1 < i) count(list, 1.0 < 1.0) count(list, 1.0 == nil) count(list, [#] | all(true)) count(list, add == $env) count(list, f64 == nil) count(list, false) ?? i count(list, foo != $env) count(list, greet != $env) count(list, i == nil) count(list, nil != 1.0) count(list, nil != true) count(list, not ok) count(list, ok ?: .String) count(list, ok) count(list, ok) .. 1 | take(1) count(list, str != $env) count(list, true != nil) count(list, true) >= f64 count(list[:0]) count(list[:i], ok) count(list[array?.[i]:]) count(map($env, $env), ok == $env) count(map($env, false)) count(map($env, ok)) count(map($env, true)) count(map($env, true)) >= f64 count(map(array, false)) count(map(array, ok)) count(map(list, false)) count(map(list, ok)) count(map(list, true)) count(sort($env)) count(sort($env), # < #.str) count(sort($env), #) count(sort($env), #.str && #) count(sort($env), -#.add) count(sort($env), .greet?.[greet]) count(toPairs($env), 0 in #) date(str, str) duration(string(0)) duration(toJSON(0)) f64 f64 != $env == false f64 != $env ?: false f64 != $env ?? f64 f64 != $env ?? foo f64 != $env and $env f64 != $env or $env f64 != $env or ok f64 != $env || $env f64 != $env || false f64 != $env.f64 f64 != $env.i f64 != $env?.$env f64 != $env?.Bar f64 != $env?.Bar?.String f64 != $env?.Bar?.[ok] f64 != $env?.Bar?.list() f64 != $env?.String f64 != $env?.[Bar] f64 != $env?.[Bar]?.String f64 != $env?.[Bar]?.add f64 != $env?.[String] f64 != $env?.[foobar] f64 != $env?.[str] f64 != $env?.f64 f64 != $env?.foobar f64 != $env?.i f64 != $env?.nil f64 != $env?.true f64 != -0 f64 != -1.0 f64 != 0 != nil f64 != 0 != ok f64 != 0 != true f64 != 0 ** i f64 != 0 + i f64 != 0 - i f64 != 0 == $env f64 != 0 == false f64 != 0 == nil f64 != 0 ?: 1.0 f64 != 0 || $env f64 != 1 ** i f64 != 1 + 1.0 f64 != 1 / i f64 != 1 == $env f64 != 1 ?? $env f64 != 1 and $env f64 != 1 || $env f64 != 1.0 != $env f64 != 1.0 != nil f64 != 1.0 * 1.0 f64 != 1.0 ** 0 f64 != 1.0 ** i f64 != 1.0 + 1.0 f64 != 1.0 - 0 f64 != 1.0 - 1 f64 != 1.0 - i f64 != 1.0 == true f64 != 1.0 ?: add f64 != 1.0 ?? $env?.[greet] f64 != 1.0 ?? i f64 != 1.0 ^ 1.0 f64 != 1.0 ^ i f64 != 1.0 and $env f64 != 1.0 and false f64 != 1.0 or $env f64 != 1.0 or true f64 != abs(1.0) f64 != abs(i) f64 != array?.[i] f64 != bitxor(i, i) f64 != f64 f64 != f64 != $env f64 != f64 && $env f64 != f64 + 0 f64 != f64 == ok f64 != f64 ?? foo f64 != f64 ?? greet f64 != f64 ^ f64 && false f64 != f64 and true f64 != false ?? foo f64 != false ?? list f64 != findIndex(list, true) f64 != first($env) f64 != float(i) f64 != floor(f64) f64 != floor(i) f64 != foo ?? 0 f64 != greet ?? 1 f64 != greet ?? foo f64 != greet ?? true f64 != i f64 != i != false f64 != i && $env f64 != i * f64 f64 != i + 1 f64 != i / 1 f64 != i == nil f64 != i ?? 0 f64 != i ?? f64 f64 != i ^ 0 f64 != i ^ f64 f64 != i and $env f64 != i and nil not in array f64 != i and true f64 != i or ok f64 != int(1.0) f64 != last($env) f64 != last(array) f64 != len($env) f64 != len(array) f64 != max(f64) f64 != max(i) f64 != mean(0) f64 != mean(1.0) f64 != mean(array) f64 != mean(f64) f64 != median(1.0) f64 != median(array) f64 != median(f64) f64 != min(0) f64 != min(1.0) f64 != min(array, 1) f64 != nil != $env f64 != nil != false f64 != nil != nil f64 != nil && $env f64 != nil ?: greet f64 != nil ?? 1.0 f64 != nil ?? nil f64 != nil or $env f64 != nil || false f64 != ok ?? $env f64 != round(1) f64 != round(1.0) f64 != str ?? $env f64 != sum($env, 0) f64 != sum(array) f64 * $env.f64 f64 * $env.i f64 * $env?.f64 f64 * $env?.i f64 * -f64 f64 * -i f64 * 0 * 1.0 f64 * 0 + 1 f64 * 0 - 1.0 f64 * 0 - f64 f64 * 0 == $env f64 * 0 ?? str f64 * 0 ^ f64 f64 * 0 ^ max(i) f64 * 0 in array f64 * 1 != nil f64 * 1 * 0 f64 * 1 * i f64 * 1 < 1.0 f64 * 1 <= 0 f64 * 1 <= i f64 * 1 == nil f64 * 1 ?? $env?.String f64 * 1 ?? false f64 * 1 ?? i f64 * 1 in array f64 * 1.0 f64 * 1.0 != $env f64 * 1.0 != i f64 * 1.0 * 1.0 f64 * 1.0 * f64 f64 * 1.0 ** f64 f64 * 1.0 < 0 f64 * 1.0 < 1 f64 * 1.0 <= f64 f64 * 1.0 == $env f64 * 1.0 == 1 f64 * 1.0 == nil f64 * 1.0 > 0 f64 * 1.0 ?? str f64 * 1.0 ^ f64 f64 * 1.0 | max(0) f64 * abs(1.0) f64 * array?.[1] f64 * array?.[i] f64 * bitnot(0) f64 * ceil(1.0) f64 * ceil(f64) f64 * f64 f64 * f64 * i f64 * f64 + $env.f64 f64 * f64 - f64 f64 * f64 / i f64 * f64 > 1 f64 * f64 ?? true f64 * f64 ^ 1.0 f64 * float(0) f64 * float(f64) f64 * float(i) f64 * floor(f64) f64 * i f64 * i != $env?.i f64 * i != sum(array) f64 * i ** 1.0 f64 * i == i f64 * i == nil f64 * i > $env?.f64 f64 * i ?? $env f64 * i ?? groupBy($env, .greet) f64 * i ?? str f64 * i | max(array) f64 * int(0) f64 * int(1) f64 * int(1.0) f64 * int(i) f64 * len($env) f64 * len(foo.Bar) f64 * len(str) f64 * max(map(array, #)) f64 * median(1.0) f64 * median(f64) f64 * min(1.0, 0) f64 * min(array) f64 * reduce(array, #) f64 * round(1.0) f64 * sum($env, 1) f64 * sum(array | sortBy(#)) f64 * sum(array) f64 ** $env.f64 f64 ** $env.i f64 ** $env?.array?.[i] f64 ** $env?.f64 f64 ** $env?.i f64 ** -1 f64 ** -1.0 f64 ** -f64 f64 ** -i f64 ** 0 * i f64 ** 0 ** f64 f64 ** 0 < f64 f64 ** 0 <= i f64 ** 0 > i f64 ** 0 >= 1.0 f64 ** 0 ?? i f64 ** 0 ?? list / 0 f64 ** 0 ?? ok f64 ** 1 != nil f64 ** 1 - i f64 ** 1 / 0 f64 ** 1 < f64 f64 ** 1 == i f64 ** 1 > len($env) f64 ** 1 ^ 1 f64 ** 1.0 != $env f64 ** 1.0 != f64 f64 ** 1.0 * 1.0 f64 ** 1.0 + 0 f64 ** 1.0 / i f64 ** 1.0 > 1 f64 ** 1.0 > 1.0 f64 ** 1.0 >= 1.0 f64 ** 1.0 ?? f64 f64 ** 1.0 ?? list f64 ** 1.0 ^ 1.0 f64 ** 1.0 ^ f64 f64 ** 1.0 not in array f64 ** abs(mean(1.0)) f64 ** array?.[i] f64 ** bitnot(0) f64 ** f64 f64 ** f64 != $env || $env f64 ** f64 * 0 f64 ** f64 * i f64 ** f64 + 1.0 f64 ** f64 - 1.0 f64 ** f64 ?? $env?.[i] f64 ** f64 ^ i f64 ** f64 | median(0) f64 ** float(0) f64 ** float(1.0) f64 ** floor(1.0) f64 ** floor(i) f64 ** i f64 ** i + $env?.f64 f64 ** i == nil f64 ** i >= i f64 ** i ?? $env f64 ** i ?? true f64 ** i ^ i f64 ** int(i) f64 ** mean(1.0) f64 ** mean(f64) f64 ** min(1.0) f64 ** min(f64) f64 ** round(f64) f64 ** sum(array) f64 + $env or true f64 + $env.f64 f64 + $env.i f64 + $env?.f64 f64 + $env?.i f64 + -0 f64 + -1 f64 + -1.0 f64 + -f64 f64 + -i f64 + 0 * f64 f64 + 0 + array?.[i] f64 + 0 - 1.0 f64 + 0 - f64 f64 + 0 ?? !false f64 + 0 ^ 1.0 f64 + 0 ^ f64 f64 + 0.1 f64 + 1 * 0 f64 + 1 * f64 f64 + 1 * i f64 + 1 ** 1.0 f64 + 1 / 1.0 f64 + 1 < 1.0 f64 + 1 <= 1.0 f64 + 1 > $env and false f64 + 1 > 0 f64 + 1 ?? foo f64 + 1 ^ f64 f64 + 1.0 != f64 f64 + 1.0 - f64 f64 + 1.0 < 1.0 f64 + 1.0 < int(0) f64 + 1.0 <= $env.i f64 + 1.0 <= 0 f64 + 1.0 <= 1.0 f64 + 1.0 == 0 f64 + 1.0 == i f64 + 1.0 == nil f64 + 1.0 > 0 f64 + 1.0 > i f64 + 1.0 >= 1 f64 + 1.0 ?? 1 f64 + 1.0 ^ 0 f64 + 1.0 ^ 1.0 f64 + 1.0 not in array f64 + 1.0 | max(1.0) f64 + abs(f64) f64 + abs(i) f64 + array?.[i] f64 + bitnot(i) f64 + ceil(0) f64 + ceil(1) f64 + ceil(1.0) f64 + count($env, true) f64 + f64 f64 + f64 ** 1.0 f64 + f64 ?? 1 f64 + f64 ^ i f64 + floor(0) f64 + floor(i) f64 + i f64 + i != 0 f64 + i ** 1 f64 + i - 1 f64 + i / i f64 + i == f64 f64 + i == i f64 + i > 1.0 f64 + i > f64 f64 + i in array f64 + i not in array f64 + int(i) f64 + mean(1.0) f64 + median(f64) f64 + min(f64) f64 + min(i) f64 + nil ?? i ?? greet f64 + round(1.0) f64 + sum(array) f64 + sum(list, 1) f64 - $env.f64 f64 - $env.i f64 - $env?.f64 f64 - $env?.i f64 - -0 f64 - -1 f64 - -1.0 f64 - -i f64 - 0 % i f64 - 0 ** 1.0 f64 - 0 / 1 f64 - 0 / f64 f64 - 0 < 0 f64 - 0 < 1 f64 - 0 > 0 f64 - 0 > f64 f64 - 0 in array f64 - 1 != $env f64 - 1 * $env.f64 f64 - 1 <= -1 f64 - 1 <= 1 f64 - 1 <= 1 + f64 f64 - 1 > i f64 - 1 ?? $env.ok f64 - 1 ^ i f64 - 1 not in $env?.[Bar] f64 - 1 | mean(1.0) f64 - 1.0 * 1 f64 - 1.0 ** i f64 - 1.0 - 0 f64 - 1.0 - 1 f64 - 1.0 - 1.0 f64 - 1.0 / i f64 - 1.0 < f64 + 0 f64 - 1.0 <= i f64 - 1.0 == f64 f64 - 1.0 == nil f64 - 1.0 > 1 f64 - 1.0 ?? list f64 - 1.0 ^ f64 f64 - 1.0 | mean(array) f64 - abs(0) f64 - array?.[i] f64 - bitnot(i) f64 - bitxor(i, i) f64 - ceil(f64) f64 - count(list, true) f64 - f64 f64 - f64 < i f64 - f64 <= f64 f64 - f64 > 0 f64 - float(1.0) f64 - floor(0) f64 - floor(f64) f64 - floor(i) f64 - i f64 - i % 1 f64 - i >= 1 f64 - i >= i f64 - i ^ 1.0 f64 - i | median(1.0) f64 - int(0) f64 - int(1.0) f64 - last(array) f64 - len(str) f64 - max(array) f64 - max(f64) f64 - median(1.0) f64 - median(array) f64 - min(1.0, array) f64 - reduce(array, i) f64 - sum(array) f64 / $env.f64 f64 / $env.i f64 / $env?.f64 f64 / $env?.i f64 / -0 f64 / -1 f64 / -1.0 f64 / -i f64 / 0 != 1.0 f64 / 0 + i f64 / 0 - 1.0 f64 / 0 < f64 f64 / 0 ^ $env?.i f64 / 0 ^ 1.0 f64 / 0 not in array f64 / 1 * f64 f64 / 1 * i ?? 1.0 f64 / 1 / 1.0 f64 / 1 / i f64 / 1 <= 0 f64 / 1 == 0 f64 / 1 == int(f64) f64 / 1 ?? array f64 / 1.0 != 1 f64 / 1.0 != f64 f64 / 1.0 ** 1.0 f64 / 1.0 - 1 f64 / 1.0 / $env?.i f64 / 1.0 / 1.0 f64 / 1.0 <= 1.0 f64 / 1.0 == 1.0 f64 / 1.0 > 1 f64 / 1.0 >= 0 f64 / 1.0 >= 1.0 f64 / 1.0 ?? list f64 / 1.0 ?? nil + 1.0 f64 / 1.0 ?? true >= 1.0 f64 / 1.0 ^ 1.0 f64 / 1.0 ^ f64 f64 / 1.0 ^ i f64 / abs(1.0) f64 / abs(i) f64 / add(i, 1) f64 / array?.[i] f64 / ceil(1.0) f64 / f64 f64 / f64 != 1 f64 / f64 ** i f64 / f64 + 0 f64 / f64 / 1.0 f64 / f64 <= f64 f64 / f64 ?? 0 f64 / f64 ?? ok f64 / f64 not in array f64 / first(array) f64 / float(1.0) f64 / i f64 / i * i f64 / i - sum(array) f64 / i == 0 f64 / i >= 1.0 f64 / i ?? i f64 / i ?? nil f64 / i ^ 0 * 1.0 f64 / i ^ 1.0 f64 / int(f64) f64 / len($env) f64 / len(array) f64 / max(1) f64 / max(f64, f64) f64 / max(i) f64 / mean(0) f64 / mean(1) f64 / mean(1.0) f64 / mean(1.0, array) f64 / mean(array) f64 / min(array) f64 / nil ?? 1.0 f64 / reduce(list, i) f64 / round(1.0) f64 / sum(array) f64 / sum(array, 0) f64 < $env.f64 f64 < $env.i f64 < $env?.f64 f64 < $env?.i f64 < -1.0 f64 < -f64 f64 < 0 % 1 f64 < 0 * 1 f64 < 0 ** f64 f64 < 0 + 0 f64 < 0 + 1 f64 < 0 + 1.0 f64 < 0 + i f64 < 0 < $env > $env f64 < 0 <= $env?.[array] f64 < 0 == false f64 < 0 == true f64 < 0 ?? array f64 < 0 ?? nil f64 < 0 ?? str f64 < 0 or true f64 < 1 % 1 f64 < 1 ** 1.0 f64 < 1 / 0 f64 < 1 / 1.0 f64 < 1 <= f64 f64 < 1 > 1.0 f64 < 1 >= 1 f64 < 1 >= 1.0 f64 < 1 ?? i f64 < 1 or ok f64 < 1 or true f64 < 1.0 != true f64 < 1.0 && $env f64 < 1.0 * 1.0 f64 < 1.0 * i f64 < 1.0 ** 0 f64 < 1.0 + f64 f64 < 1.0 - 1.0 f64 < 1.0 - f64 f64 < 1.0 / 1 f64 < 1.0 / 1.0 f64 < 1.0 / f64 f64 < 1.0 < 1.0 f64 < 1.0 <= i f64 < 1.0 == false f64 < 1.0 >= 1.0 == true f64 < 1.0 >= i f64 < 1.0 ?: true f64 < 1.0 ?? ok f64 < 1.0 and false f64 < abs(1) f64 < abs(1.0) f64 < array?.[i] f64 < bitnot(i) f64 < ceil(1.0) f64 < count(list, true) f64 < f64 f64 < f64 < 1.0 f64 < f64 <= 1.0 f64 < f64 > 0 f64 < f64 >= 1.0 f64 < f64 ?: ok f64 < f64 ?? 1.0 f64 < f64 ?? greet f64 < f64 and $env f64 < f64 in $env?.String f64 < findIndex($env, ok) f64 < float(1) f64 < float(f64) f64 < floor(1) f64 < floor(f64) f64 < i f64 < i != nil f64 < i % 1 f64 < i % i f64 < i && $env f64 < i < $env.i f64 < i < max(0) f64 < i == nil f64 < i >= f64 f64 < i ?? f64 f64 < i ?? greet f64 < i || true f64 < len($env) f64 < max(array) f64 < max(f64) f64 < mean(f64) f64 < median(array) f64 < min(0) f64 < min(1.0) f64 < min(i) f64 < nil ?? i f64 < round(1.0) f64 < sum($env, 1) f64 < sum(array) f64 <= $env.f64 f64 <= $env.i f64 <= $env?.f64 f64 <= $env?.i f64 <= -0 f64 <= 0 ** 1.0 f64 <= 0 - f64 f64 <= 0 <= 1.0 f64 <= 0 > i f64 <= 0 >= mean(1.0) f64 <= 0.1 f64 <= 1 != true and $env f64 <= 1 && true f64 <= 1 * i f64 <= 1 - i f64 <= 1 / 1 f64 <= 1 / f64 f64 <= 1 >= 1.0 f64 <= 1 >= f64 f64 <= 1 ?? $env.f64 f64 <= 1 ?? foo f64 <= 1 ^ 0 f64 <= 1 ^ i f64 <= 1 or true f64 <= 1 || $env f64 <= 1.0 f64 <= 1.0 != nil f64 <= 1.0 != true f64 <= 1.0 && $env f64 <= 1.0 && true f64 <= 1.0 * $env?.i f64 <= 1.0 * min(i) f64 <= 1.0 + 1.0 f64 <= 1.0 / 1.0 f64 <= 1.0 < 1.0 ^ i f64 <= 1.0 <= f64 f64 <= 1.0 <= i f64 <= 1.0 <= mean(1.0) f64 <= 1.0 > 1 f64 <= 1.0 > i f64 <= 1.0 ?? add f64 <= 1.0 ?? greet f64 <= 1.0 ?? str f64 <= 1.0 ^ 0 f64 <= 1.0 ^ 1.0 f64 <= 1.0 ^ f64 f64 <= 1.0 and $env f64 <= 1.0 and ok f64 <= 1.0 || true f64 <= 1.1 <= 1 f64 <= abs(0) f64 <= abs(1) f64 <= abs(f64) f64 <= add(i, i) f64 <= array?.[i] f64 <= bitnand(i, 1) f64 <= f64 f64 <= f64 && $env f64 <= f64 * i f64 <= f64 - 0 f64 <= f64 == false f64 <= f64 ?? $env f64 <= f64 and $env f64 <= f64 || $env f64 <= findIndex(list, ok) f64 <= floor(1.0) f64 <= i f64 <= i + f64 f64 <= i - 0 f64 <= i == $env?.Bar f64 <= i > i f64 <= i ?? ok f64 <= int(1.0) f64 <= last(array) f64 <= len(list) f64 <= mean(1) f64 <= mean(1.0) f64 <= mean(i) f64 <= median(1.0) f64 <= median(f64) f64 <= min(f64) f64 <= reduce(array, 1.0, true) f64 <= sum(array) f64 <= sum(array, #) f64 == $env && true f64 == $env == $env f64 == $env ? add : $env f64 == $env ?? add f64 == $env ?? greet f64 == $env or $env f64 == $env or ok f64 == $env.f64 f64 == $env.i f64 == $env?.Bar f64 == $env?.String f64 == $env?.[Bar] f64 == $env?.[String] f64 == $env?.[String]?.[greet] f64 == $env?.[foobar] f64 == $env?.[str] f64 == $env?.f64 f64 == $env?.foobar f64 == $env?.foobar?.str f64 == $env?.i f64 == -1 f64 == -1.0 f64 == 0 % i f64 == 0 && $env?.[add] f64 == 0 && 0 == nil f64 == 0 && sum($env) f64 == 0 ** 1.0 f64 == 0 - 1.0 f64 == 0 / $env.i f64 == 0 == nil f64 == 0 or ok f64 == 1 != ok f64 == 1 * i f64 == 1 + 1.0 f64 == 1 - 1.0 f64 == 1 - f64 f64 == 1 ?: 1.0 f64 == 1 ?? f64 f64 == 1 || i <= 0 f64 == 1.0 != false f64 == 1.0 ** 0 f64 == 1.0 + f64 f64 == 1.0 == nil f64 == 1.0 == ok f64 == 1.0 ?: nil f64 == 1.0 ?? 1 f64 == 1.0 ?? ok f64 == 1.0 ^ 1.0 f64 == 1.0 and ok f64 == 1.0 and true f64 == 1.0 || $env f64 == abs(1.0) f64 == abs(i) f64 == add ?? false f64 == add ?? greet f64 == add ?? list f64 == array ?? greet f64 == array?.[i] f64 == bitnot(i) f64 == bitor(i, 1) f64 == ceil(1) f64 == ceil(1.0) f64 == count(array, ok) f64 == f64 f64 == f64 * 1 f64 == f64 * f64 f64 == f64 / 0 f64 == f64 ?? false f64 == f64 ^ i f64 == f64 || false f64 == findLastIndex($env, true) f64 == floor(1) f64 == foo ?? f64 f64 == foo ?? list f64 == greet ?? add f64 == i f64 == i % 1 f64 == i - i f64 == i / f64 f64 == i / i f64 == i ?? [foo] f64 == i ?? any($env, false) f64 == i ^ 0 f64 == i or ok f64 == i || false f64 == int(f64) f64 == len(string(nil)) f64 == list ?? $env f64 == list ?? array f64 == max(0) f64 == mean(1.0) f64 == median(1.0) f64 == median(i) f64 == min($env) f64 == min(1.0) f64 == nil != nil f64 == nil != ok f64 == nil ?: list f64 == nil or $env f64 == nil || max(array) f64 == nil || true f64 == ok ?? foo f64 == ok ?? str f64 == round(f64) f64 == str ?? 0 f64 == str ?? i f64 == sum(array) f64 > $env.f64 f64 > $env.i f64 > $env?.[str]?.[f64] f64 > $env?.f64 f64 > $env?.i f64 > -0 f64 > -1 f64 > -1.0 f64 > 0 + 1.0 f64 > 0 / 1.0 f64 > 0 / i f64 > 0 >= 0 f64 > 0 >= 1.0 f64 > 0 ? 1 : 1.0 f64 > 0 ?? $env.f64 f64 > 0 ?? false f64 > 0 ?? foo f64 > 0 and $env?.String f64 > 0 or true f64 > 0 || $env f64 > 1 != ok f64 > 1 && $env f64 > 1 * i f64 > 1 ** i f64 > 1 / 1.0 f64 > 1 / f64 f64 > 1 / i f64 > 1 <= i f64 > 1 >= f64 f64 > 1 >= i f64 > 1 ? array : false f64 > 1 ?? list f64 > 1 or true f64 > 1.0 != nil f64 > 1.0 != ok f64 > 1.0 && $env f64 > 1.0 * 1.0 f64 > 1.0 * i f64 > 1.0 ** f64 f64 > 1.0 - nil ?? i f64 > 1.0 / 0 f64 > 1.0 <= f64 f64 > 1.0 <= i f64 > 1.0 == true f64 > 1.0 > $env f64 > 1.0 > median(list, 1) f64 > 1.0 ? i : false f64 > 1.0 ?? 1.0 f64 > 1.0 ?? add f64 > 1.0 ?? foo f64 > 1.0 ^ f64 f64 > 1.0 and true f64 > 1.0 or ok f64 > 1.0 || $env?.[Bar] f64 > array?.[i] f64 > bitnot(1) f64 > ceil(0) f64 > ceil(f64) f64 > ceil(i) f64 > f64 f64 > f64 != true f64 > f64 * f64 f64 > f64 - 1 f64 > f64 >= 1.0 f64 > f64 and true f64 > f64 or ok f64 > first(array) f64 > float(1.0) f64 > i f64 > i - f64 f64 > i < f64 ?: $env f64 > i == $env f64 > i >= max($env) f64 > i ^ 1 f64 > i and ok f64 > max(array) f64 > mean(1) f64 > mean(1.0) f64 > median(f64) f64 > round(1) f64 > round(1.0) f64 > round(i) f64 > sum($env | filter(false)) f64 > sum($env, f64) f64 >= $env && false f64 >= $env ^ 1 and false f64 >= $env or true f64 >= $env || true f64 >= $env.f64 f64 >= $env.i f64 >= $env?.f64 f64 >= $env?.i f64 >= -1.0 f64 >= -i f64 >= 0 != $env f64 >= 0 - 0 f64 >= 0 == true f64 >= 0 >= f64 f64 >= 0 ? add : 0 f64 >= 0 ? greet : 1 f64 >= 0 ?? i f64 >= 0 || ok f64 >= 1 != nil f64 >= 1 != true f64 >= 1 / f64 f64 >= 1 < i f64 >= 1 == false f64 >= 1 >= f64 f64 >= 1 ? 0 : foo f64 >= 1 ? foo : str f64 >= 1 ^ 1.0 f64 >= 1.0 != add ?? foo f64 >= 1.0 != nil f64 >= 1.0 && ok f64 >= 1.0 ** i < f64 f64 >= 1.0 + $env.f64 f64 >= 1.0 + 1.0 f64 >= 1.0 / i f64 >= 1.0 > i f64 >= 1.0 ?: greet f64 >= 1.0 ?: list f64 >= 1.0 ?? nil f64 >= 1.0 and $env in str f64 >= 1.0 and $env?.[str] f64 >= 1.0 and not ok f64 >= 1.0 || ok f64 >= 1.1 f64 >= array?.[i] f64 >= bitnot(i) f64 >= ceil(0) f64 >= ceil(i) f64 >= f64 f64 >= f64 * 1.0 f64 >= f64 == ok f64 >= f64 >= i f64 >= f64 ?? str f64 >= f64 ^ f64 f64 >= f64 || 1.0 == 1.0 f64 >= f64 || true f64 >= float(0) f64 >= float(1) f64 >= float(1.0) f64 >= floor(-0) f64 >= floor(1.0) f64 >= floor(f64) f64 >= floor(i) f64 >= i f64 >= i != $env f64 >= i * f64 f64 >= i + 1.0 f64 >= i / f64 f64 >= i < f64 f64 >= i ?: true f64 >= i ?? $env f64 >= i ?? $env.list f64 >= i ?? false f64 >= i || $env f64 >= int(1.0) f64 >= mean(0) f64 >= mean(1) f64 >= mean(1.0) f64 >= min(0) f64 >= min(i) f64 >= nil ?? f64 f64 >= nil ?? i f64 >= round(1) f64 >= sum(array) f64 ?? !$env f64 ?? !false f64 ?? !ok f64 ?? $env ?? $env f64 ?? $env ?? add f64 ?? $env ?? f64 f64 ?? $env ?? nil f64 ?? $env ?? ok f64 ?? $env | get(greet) f64 ?? $env | max(1) f64 ?? $env.add f64 ?? $env.array f64 ?? $env.f64 f64 ?? $env.foo f64 ?? $env.greet f64 ?? $env.i f64 ?? $env.list f64 ?? $env.ok f64 ?? $env.str f64 ?? $env?.Bar f64 ?? $env?.Bar($env < 1.0) f64 ?? $env?.Bar() f64 ?? $env?.String f64 ?? $env?.String() f64 ?? $env?.[$env?.String()] f64 ?? $env?.[Bar] f64 ?? $env?.[String] f64 ?? $env?.[String].str() f64 ?? $env?.[add] f64 ?? $env?.[add]?.[greet] f64 ?? $env?.[array] f64 ?? $env?.[array].list() f64 ?? $env?.[f64] f64 ?? $env?.[false - 1] f64 ?? $env?.[foo] f64 ?? $env?.[foobar.Bar] f64 ?? $env?.[foobar?.[f64]] f64 ?? $env?.[foobar] f64 ?? $env?.[greet(foo)] f64 ?? $env?.[greet] f64 ?? $env?.[greet].array() f64 ?? $env?.[i] f64 ?? $env?.[i]?.[str] f64 ?? $env?.[list] f64 ?? $env?.[not foo] f64 ?? $env?.[ok] f64 ?? $env?.[ok].array() f64 ?? $env?.[str] f64 ?? $env?.[str][:i(i < foobar)] f64 ?? $env?.add f64 ?? $env?.all(foobar) f64 ?? $env?.array f64 ?? $env?.f64 f64 ?? $env?.foo f64 ?? $env?.foobar f64 ?? $env?.foobar?.list f64 ?? $env?.greet f64 ?? $env?.i f64 ?? $env?.list f64 ?? $env?.ok f64 ?? $env?.str f64 ?? $env[0:foobar] f64 ?? $env[:1] f64 ?? $env[:add[:]] f64 ?? $env[:foo] f64 ?? $env[:foobar] f64 ?? $env[:nil] f64 ?? $env[:sum(0, foobar)].ok f64 ?? $env[Bar | none(#):] f64 ?? $env[Bar():i(1)] f64 ?? $env[f64 / foo:] f64 ?? $env[f64:replace(foobar, 1.0)] f64 ?? $env[false > Bar:] f64 ?? $env[foo - 1:foobar].ok f64 ?? $env[foobar:] f64 ?? $env[foobar:foobar and array] f64 ?? $env[list:greet] f64 ?? -$env f64 ?? -$env?.[1] f64 ?? -0 f64 ?? -1 f64 ?? -1.0 f64 ?? -f64 f64 ?? 0 ?? $env?.nil f64 ?? 0 ?? [1.0] f64 ?? 0 ?? true f64 ?? 1 ?? foo f64 ?? 1.0 ?? date(f64) f64 ?? [$env] f64 ?? [f64, f64] f64 ?? abs(1.0) f64 ?? add f64 ?? add(i, $env) f64 ?? array f64 ?? array ?? array f64 ?? array ?? true f64 ?? array | mean(1.0) f64 ?? array?.[i] f64 ?? bitnot(i) f64 ?? count($env | map(#.add)) f64 ?? count($env) f64 ?? count($env, #) f64 ?? count($env?.[i]) f64 ?? count(array) f64 ?? count(list) f64 ?? date($env, 1) f64 ?? date(foo) f64 ?? date(sum(list)) f64 ?? f64 f64 ?? f64 ?? ok f64 ?? false ?? 1.0 f64 ?? false | max(0) f64 ?? findLast($env, #.f64) f64 ?? findLast(array, false) f64 ?? first($env)?.ok() f64 ?? floor($env) f64 ?? foo f64 ?? foo ?? $env f64 ?? foo ?? foo f64 ?? foo | get(1.0) f64 ?? foo | max(0) f64 ?? foo.Bar f64 ?? foo.String f64 ?? foo.String() f64 ?? foo?.Bar f64 ?? foo?.String f64 ?? foo?.String() f64 ?? fromBase64($env) f64 ?? greet f64 ?? greet($env) f64 ?? groupBy($env, #) f64 ?? groupBy($env, true) f64 ?? groupBy(list, #) f64 ?? i f64 ?? i ?? add f64 ?? int(1) f64 ?? int(f64) f64 ?? int(str) f64 ?? len(str) f64 ?? list f64 ?? list?.[i] f64 ?? lower($env) f64 ?? map($env, #) f64 ?? map($env, #.Bar) f64 ?? map(array, #index) f64 ?? max(1.0) f64 ?? mean($env) f64 ?? median(1.0) f64 ?? min($env?.[add]) f64 ?? min(0) f64 ?? min(list) f64 ?? nil ?? 0 f64 ?? not $env f64 ?? not ok f64 ?? not true f64 ?? ok f64 ?? ok ?? 1.0 f64 ?? ok ?? greet f64 ?? reduce($env, add) f64 ?? reduce($env, foo) f64 ?? reduce(array, #, $env) f64 ?? reduce(list, str) f64 ?? reverse($env) f64 ?? reverse(array) f64 ?? round(i) f64 ?? sortBy(list, ok) f64 ?? str f64 ?? str[$env:i] f64 ?? string(f64) f64 ?? string(str) f64 ?? string(true) f64 ?? sum($env, #.foo) f64 ?? sum($env, .str) f64 ?? sum($env, foo) f64 ?? sum($env?.[list]) f64 ?? sum(array) f64 ?? toJSON(0) f64 ?? toJSON(1.0) f64 ?? true ?? 0 f64 ?? type(1) f64 ?? uniq($env) f64 ?? {foo: 1.0, foo: list} f64 ?? {foo: 1} f64 ?? {foo: greet} f64 ?? {foo: i, foo: str} f64 ?? {foo: list} f64 ^ $env.f64 f64 ^ $env.i f64 ^ $env?.f64 f64 ^ $env?.i f64 ^ -1 f64 ^ -1.0 f64 ^ -f64 f64 ^ 0 - 1.0 f64 ^ 0 - i f64 ^ 0 / i f64 ^ 0 < 0 f64 ^ 0 >= 1.0 ?: greet f64 ^ 1 != 1 f64 ^ 1 * 1.0 f64 ^ 1 + 1 f64 ^ 1 + 1.0 f64 ^ 1 + f64 f64 ^ 1 > 1 f64 ^ 1 > f64 f64 ^ 1 ?? nil f64 ^ 1 in [1.0] f64 ^ 1.0 f64 ^ 1.0 != $env f64 ^ 1.0 != 1.0 f64 ^ 1.0 != f64 f64 ^ 1.0 != i f64 ^ 1.0 ** 1.0 f64 ^ 1.0 / i f64 ^ 1.0 > 1 f64 ^ 1.0 >= i f64 ^ 1.0 ?? str f64 ^ array?.[i] f64 ^ bitand(0, 0) f64 ^ bitnot(1) f64 ^ ceil(0) f64 ^ f64 f64 ^ f64 != $env f64 ^ f64 != 0 f64 ^ f64 != 1 f64 ^ f64 * 1.0 f64 ^ f64 ** i f64 ^ f64 + 1.0 f64 ^ f64 == i f64 ^ f64 > f64 f64 ^ f64 ?? greet f64 ^ f64 ^ f64 f64 ^ f64 in array f64 ^ find(array, ok) f64 ^ float(i) f64 ^ floor(i) f64 ^ i f64 ^ i ** 1.0 f64 ^ i ** i f64 ^ i / $env.i f64 ^ i <= 1.0 f64 ^ i >= 0 || $env f64 ^ i not in array f64 ^ int(0) f64 ^ int(1.0) f64 ^ int(f64) f64 ^ len($env) f64 ^ mean(0) f64 ^ mean(i) f64 ^ median(0) f64 ^ min(0) f64 ^ nil ?? 1 f64 ^ round(1.0) f64 ^ sum(array) f64 in $env && false f64 in $env.array f64 in $env?.Bar f64 in $env?.Bar?.[str] f64 in $env?.String f64 in $env?.[$env?.[String]] f64 in $env?.[Bar] f64 in $env?.[String] f64 in $env?.[foobar] f64 in $env?.array f64 in $env?.foobar f64 in $env?.foobar?.[add] f64 in $env?.nil f64 in [1.0] f64 in [foo, 1.0] f64 in [foo, i] f64 in [foo, nil] f64 in [i] f64 in [list, 1.0] f64 in [nil] f64 in [true, $env] f64 in array f64 in array != nil f64 in array ? foo : foo f64 in array ? type(false) : foo f64 in array ?? 0 f64 in array ?? nil f64 in array and $env f64 in array or false f64 in last($env) f64 in list ?? foo f64 in list ?? i f64 in reverse(array) f64 in sort($env) f64 in uniq(array) f64 in uniq(list) f64 not in $env or true f64 not in $env.array f64 not in $env?.Bar f64 not in $env?.String f64 not in $env?.[Bar] f64 not in $env?.[String] f64 not in $env?.[String]?.foo f64 not in $env?.[foobar] f64 not in $env?.array f64 not in $env?.foobar f64 not in $env?.foobar?.String f64 not in 0..i f64 not in [$env] f64 not in [1.0] f64 not in [array | groupBy(#), i] f64 not in array f64 not in array ?? 0 f64 not in array ?? foo or false f64 not in array || sum($env) f64 not in i .. i f64 not in keys($env) f64 not in list ?? str f64 not in map($env, $env) f64 not in map(array, 1) f64 | max(0) f64 | max(0, 1) f64 | max(1) f64 | max(1, array) f64 | max(1.0) f64 | max(1.0, 1) f64 | max(1.0, 1.0) f64 | max(1.0, f64) f64 | max(1.0, i) f64 | max([1.0]) f64 | max(array) f64 | max(array, 0) f64 | max(array, 1) f64 | max(bitnot(1)) f64 | max(f64) f64 | max(f64, i) f64 | max(i) f64 | max(i, 1) f64 | max(i, 1.0) f64 | max(i, i) f64 | max(sortBy(array, #)) f64 | mean($env?.i) f64 | mean(0) f64 | mean(0, 0) f64 | mean(0, 1.0) f64 | mean(0, array) f64 | mean(1) f64 | mean(1) > f64 f64 | mean(1.0 ?? 1.0) f64 | mean(1.0) f64 | mean(1.0, 0) f64 | mean(1.0, 1.0) f64 | mean(1.0, array) f64 | mean(array) f64 | mean(array, 0) f64 | mean(f64) f64 | mean(f64, 1.0) f64 | mean(f64, array) f64 | mean(f64, array) != add f64 | mean(f64, f64) f64 | mean(f64, i) f64 | mean(i) f64 | mean(i, 1) f64 | median($env?.i) f64 | median(-i) f64 | median(0) f64 | median(0, 0) f64 | median(0, array) f64 | median(0, i) f64 | median(1) f64 | median(1.0) f64 | median(1.0, 1) f64 | median(1.0, 1.0) f64 | median(array) f64 | median(array) >= f64 f64 | median(array, 0) f64 | median(array, 1.0) f64 | median(array, i) f64 | median(f64) f64 | median(f64, 1.0) f64 | median(i) f64 | median(i, 1.0) f64 | min($env?.array) f64 | min($env?.f64) f64 | min(0) f64 | min(0, 1) f64 | min(0, i) f64 | min(1) f64 | min(1, f64) f64 | min(1, i, 1.0, 1.0) f64 | min(1.0) f64 | min(1.0, 0) f64 | min(array) f64 | min(array, 1) f64 | min(array, array) f64 | min(array, i) f64 | min(f64) f64 | min(f64, 1.0) f64 | min(i) f64 | min(i, i) f64 | min(mean(f64)) f64; $env?.list f64; array f64; f64 f64; foo?.String f64; greet f64; i f64; min(foo ?? true) f64; ok f64; str false != $env ?? -1 false != $env and ok false != $env.ok false != $env?.Bar false != $env?.Bar?.greet() false != $env?.String false != $env?.[Bar] false != $env?.[String] false != $env?.[foobar] false != $env?.[str] false != $env?.foobar false != $env?.ok false != $env?.true?.[list].i false != 0 ?? str false != 1.0 ?? i false != add ?? f64 ?: foo false != array ?? list false != greet ?? $env?.[ok] false != greet ?? str false != i ?? array false != nil == nil ?: list false != nil == ok false != nil ?: add false != nil ?: f64 != $env false != nil or sum($env) false != str ?? filter($env, true) false && $env + i false && $env == add false && $env == count(array) false && $env > findLastIndex($env, #) false && $env >= sum($env)?.[array] false && $env ?? ok false && $env ^ f64 <= 1 false && $env contains array ?? list false && $env in list false && $env in str false && $env not contains str false && $env not in list false && $env or ok false && $env.ok false && $env?.Bar false && $env?.Bar() false && $env?.Bar(ok(), f64(), foobar)[foobar?.add.str:] false && $env?.Bar.add() false && $env?.String false && $env?.String() false && $env?.String(foobar.Bar) false && $env?.String?.[str] false && $env?.[0 in foobar] false && $env?.[Bar] false && $env?.[Bar]?.[f64] false && $env?.[String] false && $env?.[add] false && $env?.[add].array false && $env?.[array()] false && $env?.[array] false && $env?.[array]?.[ok] false && $env?.[f64 > str] false && $env?.[f64()] false && $env?.[f64] false && $env?.[f64]?.array false && $env?.[findLastIndex(greet, #.ok)] false && $env?.[foo] false && $env?.[foobar - foobar] false && $env?.[foobar >= foobar] false && $env?.[foobar.add] false && $env?.[foobar] false && $env?.[greet] false && $env?.[greet].i false && $env?.[i] false && $env?.[i].foo false && $env?.[list] false && $env?.[ok] false && $env?.[ok].add false && $env?.[str] false && $env?.[str].String false && $env?.[str]?.list() false && $env?.[type($env, foobar, 1)] false && $env?.foobar false && $env?.min(foobar) false && $env?.ok false && $env[:$env | toPairs(foobar)] false && $env[:Bar < 0] false && $env[:Bar()] false && $env[:add(1.0)] false && $env[:ok()] false && $env[:trimPrefix(foobar)] false && $env[String():str(foobar)] false && $env[count(foo):] false && $env[foobar < true:] false && $env[foobar | toPairs(foobar, false):] false && $env[foobar.list(foobar):ok endsWith foobar] false && $env[foobar:Bar] false && $env[foobar:foobar?.[String]] false && $env[foobar?.ok(foobar):] false && $env[hasPrefix(i):foobar[$env:true]].ok false && $env[i:-foobar] false && $env[i:] false && $env[i?.str:] false && $env[ok.String:all(foobar, #.foo)] false && 0 >= i false && 0 not in map($env, i) false && 1 - findLast($env, #) false && 1 == 1 ** $env false && 1 > 1.0 ** $env false && 1.0 <= f64 > $env false && 1.0 == i false && 1.0 == int(1) false && 1.0 > $env[:ok] false && 1.0 > i false && 1.0 >= f64 false && 1.0 >= false ?? 1.0 false && array == [$env] false && f64 - $env?.[foobar] false && f64 < i false && false ?? ok false && foo != foo false && foo ?? array false && foo ?? greet false && greet ?? array false && i < f64 false && i in $env.array false && i in array false && nil != greet false && nil == add false && nil == greet false && nil == ok false && nil in reduce($env, #) false && ok || ok false && str ?? ok false && true ?? foo false == $env && ok false == $env ?? reverse($env) false == $env.ok false == $env?.Bar false == $env?.String false == $env?.String?.list false == $env?.[Bar] false == $env?.[String] false == $env?.[String]?.[f64] false == $env?.[String]?.greet false == $env?.[foobar] false == $env?.[foobar]?.[str] false == $env?.[str] false == $env?.[str]?.[f64] false == $env?.ok false == 1.0 ?? $env?.foo false == 1.0 ?? add false == false && $env == str false == foo ?? i false == i ?? ok false == nil && ok false == nil and foo in $env false == nil || $env in list false == true ? $env | map(.array) : array false == true ?? greet false == true ?? list false ? $env : $env | map($env) false ? $env : $env.array false ? $env : $env.greet false ? $env : $env.list false ? $env : $env?.[str] false ? $env : $env?.add false ? $env : $env?.f64 false ? $env : foo.Bar false ? $env : foo?.Bar false ? 0 : array?.[i] false ? 0 : foo?.Bar false ? 1 : $env.foo false ? 1 : $env.list false ? 1 : $env?.f64 false ? 1 : $env?.i false ? 1 : $env?.ok false ? 1.0 : $env.greet false ? 1.0 : $env?.[Bar] false ? 1.0 : $env?.greet false ? 1.0 : $env?.list false ? 1.0 : $env?.ok false ? 1.0 : foo.Bar false ? 1.0 : foo?.Bar false ? 1.0 : foo?.String() false ? 1.0 : str contains str false ? add : $env not matches $env?.String false ? add : $env.array false ? add : $env?.String false ? add : foo.Bar false ? add : list | map($env.add) false ? add : list | reduce(true) false ? add : list?.[i] false ? add : nil not in array false ? array : $env.f64 false ? array : $env?.f64 false ? array : $env?.foo false ? array : $env?.list false ? array : 1 * f64 false ? array : nil != str false ? f64 : $env.array false ? f64 : $env.f64 false ? f64 : $env.list false ? f64 : $env.ok false ? f64 : $env.str false ? f64 : $env?.[String] false ? f64 : $env?.greet false ? f64 : $env?.str false ? f64 : foo.Bar false ? f64 : list | groupBy(#) false ? false : $env?.list false ? false : foo ?? greet false ? false : foo?.Bar false ? foo : $env?.String false ? foo : $env?.[Bar] false ? foo : $env?.[String] false ? foo : $env?.add false ? foo : $env?.f64 false ? foo : $env?.i false ? foo : $env?.list false ? foo : $env?.ok false ? foo : array | map(0) false ? foo : array?.[i] false ? foo : foo.Bar false ? foo : foo.String false ? foo : foo?.Bar false ? foo : foo?.String false ? foo : i ^ i false ? greet : $env | map(1.0) false ? greet : $env?.greet false ? greet : foo.String false ? i : $env.str false ? i : $env?.[String] false ? i : $env?.foo false ? i : foo.Bar false ? list : $env ?? list false ? list : $env.array false ? list : $env.i false ? list : $env?.foo false ? list : foo.Bar false ? nil : $env.f64 false ? nil : $env.foo false ? nil : $env.ok false ? nil : $env?.Bar false ? nil : $env?.[foobar] false ? nil : $env?.greet false ? nil : $env?.ok false ? nil : $env?.str false ? nil : 1.0 / f64 false ? nil : foo.String false ? nil : foo.String() false ? ok : $env.str false ? ok : $env?.[Bar] false ? ok : $env?.array false ? ok : list | groupBy(i) false ? str : $env != str false ? str : $env | map(add) false ? str : $env.add false ? str : $env.f64 false ? str : $env.list false ? str : $env?.Bar false ? str : foo?.Bar false ? true : $env.add false ? true : $env.i false ? true : $env?.String false ? true : foo.Bar false ? true : foo?.Bar false ? true : list != $env?.[str] false ?: $env.add false ?: $env.foo false ?: $env.greet false ?: $env.i false ?: $env.ok false ?: $env.str false ?: $env?.Bar false ?: $env?.String false ?: $env?.[foobar] false ?: $env?.add false ?: $env?.array false ?: $env?.f64 false ?: $env?.foo false ?: $env?.i false ?: $env?.list false ?: $env?.str false ?: array | sum(1.0) false ?: array?.[i] false ?: f64 - i false ?: foo.Bar false ?: foo.String false ?: foo?.Bar false ?: foo?.String false ?: foo?.String() false ?: i | mean(1) false ?: list | map(foo) false ?? $env ?? $env?.[foo] false ?? $env.add false ?? $env.array false ?? $env.f64 false ?? $env.foo false ?? $env.greet false ?? $env.i false ?? $env.list false ?? $env.ok false ?? $env.str false ?? $env?.Bar false ?? $env?.Bar().String false ?? $env?.String false ?? $env?.String() false ?? $env?.String?.ok false ?? $env?.[!String] false ?? $env?.[0 .. greet] false ?? $env?.[1.0 | any(String)] false ?? $env?.[Bar] false ?? $env?.[String] false ?? $env?.[add | groupBy(1)] false ?? $env?.[add] false ?? $env?.[add]?.[f64]?.[foo] false ?? $env?.[array] false ?? $env?.[f64] false ?? $env?.[foo] false ?? $env?.[foobar.list] false ?? $env?.[greet] false ?? $env?.[greet]?.add() false ?? $env?.[greet]?.f64 false ?? $env?.[i != foobar] false ?? $env?.[i] false ?? $env?.[list()] false ?? $env?.[list] false ?? $env?.[list]?.[i] false ?? $env?.[ok] false ?? $env?.[str ^ String] false ?? $env?.[str] false ?? $env?.add false ?? $env?.all(array) false ?? $env?.array false ?? $env?.f64 false ?? $env?.foo false ?? $env?.foobar false ?? $env?.foobar?.f64 false ?? $env?.greet false ?? $env?.i false ?? $env?.list false ?? $env?.none(i) false ?? $env?.ok false ?? $env?.str false ?? $env[1.0 | trimPrefix(1):foobar < true] false ?? $env[:String.f64] false ?? $env[:array || foo] false ?? $env[:array()] false ?? $env[:foo?.str] false ?? $env[Bar matches foobar:] false ?? $env[date(str, true):] false ?? 1.0 ?: f64 false ?? array?.[i] false ?? foo ?? ok ?: greet false ?? foo.Bar false ?? foo.String false ?? foo.String() false ?? foo?.Bar false ?? foo?.String false ?? foo?.String() false ?? nil ?? [$env, 1.0] false ?? nil ?? list false ?? nil ?? ok false ?? ok ?? foo false ?? true ?? $env?.String false and $env != f64 false and $env + $env?.[f64] false and $env + str false and $env <= $env[foobar:foobar] false and $env == add false and $env == str false and $env >= str false and $env ?? $env?.[Bar] false and $env not contains str false and $env not in array false and $env not in foo || true false and $env || ok false and $env.ok false and $env?.$env.Bar false and $env?.$env?.ok false and $env?.Bar false and $env?.Bar != foo false and $env?.Bar() false and $env?.Bar(1 | filter(list)) || ok false and $env?.Bar(array, foobar) false and $env?.Bar.f64() false and $env?.String false and $env?.String() false and $env?.String?.greet(str) false and $env?.[Bar] false and $env?.[Bar]?.[add] false and $env?.[String] false and $env?.[add] false and $env?.[array] false and $env?.[array]?.[array] false and $env?.[f64()] not matches str false and $env?.[f64] false and $env?.[findLast(String, $env)] false and $env?.[foo.list] false and $env?.[foo] false and $env?.[foo].greet false and $env?.[foobar?.[add]] false and $env?.[foobar] false and $env?.[greet] false and $env?.[i] false and $env?.[i].array false and $env?.[i]?.list false and $env?.[len(foo, Bar, foo)] false and $env?.[list] false and $env?.[list].array false and $env?.[ok(foobar)] false and $env?.[ok] false and $env?.[str] false and $env?.[str]?.[f64].array false and $env?.[str]?.list(filter(String / foobar, f64 >= 1.0)) false and $env?.[trim(foobar)] false and $env?.[true | findLast(foobar)] false and $env?.all(foobar, foo) false and $env?.concat(Bar, 1, foobar) false and $env?.foobar false and $env?.none(foobar) false and $env?.ok false and $env?.repeat(nil) false and $env?.type(foobar, str) false and $env[$env .. add:foo ? true : foobar]?.greet false and $env[$env[array:foo]:] false and $env[:Bar] false and $env[:String($env, ok)] false and $env[:add()] false and $env[:false > nil]?.[greet] false and $env[:foo.foobar] false and $env[:foo]?.list(first(foobar ?? String), array && foobar >= String, foobar && list?.[1]) false and $env[:foobar?.Bar] false and $env[Bar(foo):] false and $env[array():] false and $env[bitshr(foobar, array):foobar | reduce(.String)] false and $env[foobar:] false and $env[greet(str):true in list] false and $env[i():] false and $env[i:nil ^ 1.0] false and 0 == i false and 0 > count(array, false) false and 0 >= -1 false and 0 ?? $env[:nil] false and 1 != f64 false and 1 <= f64 false and 1 not in $env?.array false and 1.0 ** 1.0 == nil false and 1.0 + $env?.Bar false and 1.0 <= f64 false and 1.0 <= f64 / f64 false and 1.0 == i false and 1.0 > 0 ?? 0 false and 1.0 > sum($env) false and 1.0 ?? greet false and f64 >= i false and f64 in array false and false != $env?.[i] false and foo != foo false and foo ?? greet false and foo ?? i false and greet ?? ok false and greet not in $env?.[Bar] false and i != $env?.[add] false and i == median(list) false and nil == str false and ok and ok false and str > str false and str >= foo?.Bar false and str not in foo false and true ?: add false and true ?? sum($env) false and true || ok false in $env?.Bar false in $env?.String false in $env?.[Bar] false in $env?.[String] false in $env?.[foobar?.[foo]] false in $env?.[foobar] false in $env?.[foobar]?.[array] false in $env?.foobar false in $env?.foobar?.String false in list ?? foo false not in $env?.Bar false not in $env?.String false not in $env?.[Bar] false not in $env?.[String] false not in $env?.[String]?.Bar false not in $env?.[String]?.String false not in $env?.[String]?.[list] false not in $env?.[first(foobar)] false not in $env?.[foobar?.list] false not in $env?.[foobar] false not in $env?.foobar false not in array ?? {foo: $env} false or $env in $env?.[foobar] false or $env startsWith $env?.[Bar] false or $env.ok false or $env?.Bar false or $env?.Bar?.[i] false or $env?.String false or $env?.[Bar] false or $env?.[Bar]?.list false or $env?.[String] false or $env?.[String]?.[list] false or $env?.[foobar | toJSON(nil)] false or $env?.[foobar?.[0]] false or $env?.[foobar] false or $env?.[str] false or $env?.foobar false or $env?.ok false or 0 < 1.0 ^ 1 false or 0 == i false or 0 >= i || true false or 0 not in array false or 1 > i false or 1 ?? list false or 1 in array false or 1.0 >= i false or 1.0 ?? foo false or array == list false or f64 ?? $env?.ok false or false ?: ok false or false ?? foo false or foo ?? i false or foo ?? ok false or foo in list false or greet == greet false or i == i false or i ?? foo false or i ?? list false or list ?? ok false or nil != array false or nil != f64 false or nil == array false or nil == foo false or ok == ok false or str != str false or str >= string(0) false or str in foo == $env false or str not matches str false || $env != f64 and $env false || $env == [foo] false || $env == array ? foo : foo false || $env == i false || $env ?? f64 false || $env in list false || $env.ok false || $env?.Bar false || $env?.Bar?.[ok] false || $env?.Bar?.foo false || $env?.String false || $env?.String?.foo() false || $env?.[Bar] false || $env?.[String] false || $env?.[str] false || $env?.false?.array false || $env?.foobar false || $env?.ok false || 0 != $env?.String false || 1 == $env?.[foobar] false || 1 == array?.[i] false || 1 > f64 false || 1 in array false || 1.0 <= 1.0 ?: 1 false || 1.0 <= i false || 1.0 >= f64 false || 1.0 ?? array false || add != add false || array != list false || f64 != i false || false ?? foo false || foo ?? array false || foo ?? str false || foo in list false || foo.Bar matches str false || i == i false || i > median(f64) false || i >= i false || i ?? greet($env) false || i ?? str false || nil != f64 false || nil != i false || nil == greet false || str not endsWith str false || true == ok false; $env?.Bar false; $env?.String false; $env?.[Bar] false; $env?.foo filter($env | map(0), !true) filter($env, #.list) | filter(false) filter($env, .f64) | filter(false) filter($env, .ok) | filter(false) filter($env, .str) | filter(false) filter($env, false) | all(#) filter($env, false) | all(#.str not matches .str) filter($env, false) | all(false) filter($env, false) | find(#) filter($env, false) | find(true) filter($env, false) | findIndex(#) filter($env, false) | findLastIndex(.f64 not contains #) filter($env, false) | groupBy(#) filter($env, false) | reduce(#.list, str) filter($env, false) | reduce(true, nil) filter($env, false) | sortBy(foo) filter($env, false) | sum(.Bar) filter($env, false) | sum(.i) filter($env, false) | sum(foo) filter($env, false) | sum(greet) filter($env, ok) | map(foo) filter($env.array, foo != foo) filter($env.array, i == 1) filter($env.array, ok) filter($env.list, ok) filter($env.list, true || true) filter($env?.[str], false && $env) filter($env?.[str], ok) filter($env?.array, # <= #) filter($env?.array, ok) filter($env?.list, ok) filter([0], ok) filter([1], # != 1.0) filter([greet], ok) filter([i], ok) filter([true, $env], 1 < 1) filter(array, !ok) filter(array, # != #) filter(array, # != 1) filter(array, # < #) filter(array, # <= #) filter(array, # not in array) filter(array, $env != $env) filter(array, $env == $env) filter(array, $env and false) filter(array, $env.ok) filter(array, 0 <= #) filter(array, 1 != f64) filter(array, 1 <= #) filter(array, 1 >= #) filter(array, 1.0 != #) filter(array, 1.0 <= f64) filter(array, 1.0 == $env) filter(array, 1.0 > #) filter(array, 1.0 > 1.0) filter(array, f64 <= #) filter(array, false != $env) filter(array, false) | all($env[1.0:]) filter(array, false) | groupBy(#) filter(array, false) | sortBy($env) filter(array, false) | sortBy(add) filter(array, false) | sum(f64) filter(array, foo == foo) filter(array, i > #) filter(array, list == nil) filter(array, nil != #) filter(array, nil != list) filter(array, nil ?? false) filter(array, not true) filter(array, ok && i != #) filter(array, ok ?? i) filter(array, ok and true) filter(array, ok) filter(array, ok) | findIndex(false) filter(array, ok) | groupBy(foo) filter(array, ok) | sortBy(0) filter(array, ok)?.[i] filter(array, str in foo) filter(array, true) | findLast(ok) filter(array, true) | map(foo) filter(array, true) | none(true) filter(array, true)?.[i] filter(concat(array), #.greet || true) filter(keys($env), ok) filter(list | map($env), ok == nil) filter(list, !false) filter(list, # != #) filter(list, # == $env) filter(list, # not in list) filter(list, #.Bar in #) filter(list, #.Bar not in foo) filter(list, $env != #) filter(list, $env != str) filter(list, $env == #) filter(list, $env == str) filter(list, $env?.ok) filter(list, 1 > 1.0) filter(list, 1.0 < 1) filter(list, 1.0 == nil) filter(list, 1.0 > f64) filter(list, 1.0 not in array) filter(list, array != array) filter(list, f64 <= 1.0) filter(list, false != nil) filter(list, false && $env) filter(list, false ?? 1.0) filter(list, false) | groupBy(#) filter(list, false) | groupBy(ok) filter(list, false) | map(array) filter(list, false) | sum($env) filter(list, false) | sum(foo) filter(list, foo != nil) filter(list, greet == nil) filter(list, nil == nil) filter(list, nil in $env) filter(list, not true) filter(list, ok) filter(list, ok) | findIndex(true) filter(list, ok) | reduce(add) filter(list, ok)?.[i] filter(list, one(array, true)) filter(list, str != $env) filter(list, true) | all(true) filter(list, true) | groupBy(#) filter(list, true) | groupBy(1.0) filter(list, true) | reduce(#acc) filter(list, true) | reduce(i) filter(list, true)?.[i] filter(map($env, foo), # != #) filter(sort($env), #.String?.list) filter(sort($env), #.foo?.String) filter(sort($env), #.i || #) filter(sort($env), nil not in .list) find($env ?? ok, $env == 1.0) find($env | filter(false), # endsWith .Bar) find($env | map(greet), not true) find($env, false) != f64 find($env, false) ?? ok find($env, false)?.Bar find($env, false)?.Bar() find($env, false)?.String find($env, false)?.String?.foo find($env, false)?.[add] find($env, false)?.[array] find($env, false)?.[f64] find($env, false)?.[foo] find($env, false)?.[greet] find($env, false)?.[greet].i() find($env, false)?.[greet].str find($env, false)?.[i] find($env, false)?.[i]?.foo find($env, false)?.[list] find($env, false)?.[ok] find($env, false)?.[str] find($env, false)?.[str]?.greet find($env, false)?.[{foo: false}] find($env, false)?.add find($env, false)?.array find($env, false)?.bitxor(ok, nil, 1) find($env, false)?.f64 find($env, false)?.f64?.[array] find($env, false)?.foo find($env, false)?.foo() find($env, false)?.greet find($env, false)?.greet() find($env, false)?.greet(foobar) find($env, false)?.i find($env, false)?.i() find($env, false)?.list find($env, false)?.ok find($env, false)?.ok() find($env, false)?.str find($env.array, # > #) find($env.array, $env.ok) find($env.array, i != 1.0) find($env.array, ok) find($env.list, $env != .String) find($env.list, ok) find($env?.[str], 1 > 0) find($env?.[str], ok or .ok) find($env?.[str], ok) find($env?.list, f64 != 0) find($env?.list, ok) find([$env], .ok) find([1, greet], f64 < 1.0) find([array], nil in $env) find([array], ok) find([false], #) find([ok], #) find([str, true], ok) find([str], ok) find(array, !false) find(array, # != 0) find(array, # != nil) find(array, # < #) find(array, # < 0) find(array, # <= #) find(array, # <= 0) find(array, # <= i) find(array, # == 1) find(array, # > #) find(array, $env != $env) find(array, $env == foo) find(array, $env | any(false)) find(array, $env.ok) find(array, $env?.ok) find(array, 0 != f64) find(array, 0 <= 1) find(array, 0 >= #) find(array, 1 != f64) find(array, 1 > i) find(array, 1.0 != #) find(array, 1.0 != nil) find(array, 1.0 <= #) find(array, 1.0 == nil) find(array, 1.0 >= 1.0) find(array, array != list) find(array, array | one(true)) find(array, f64 != #) find(array, false == nil) find(array, i != nil) find(array, nil != ok) find(array, nil != true) find(array, not false) find(array, ok or false) find(array, ok) find(array, str not contains str) find(array, true ?? #) find(array, true ?? 1) find(array, true) - i find(array, true) | max(array) find(filter($env, false), .list in #.list) find(list ?? list, ok) find(list, # != #) find(list, #.String == .String) find(list, $env != list) find(list, $env == nil) find(list, $env == ok) find(list, $env not in array) find(list, $env.ok) find(list, $env?.ok) find(list, 0 > i) find(list, 1 == 1.0) find(list, 1.0 != 1) find(list, 1.0 <= i) find(list, 1.0 > f64) find(list, array != $env) find(list, array == list) find(list, false != nil) find(list, false) ?? list find(list, false)?.Bar find(list, foo != #) find(list, foo != $env) find(list, foo != nil) find(list, nil != #.Bar) find(list, nil == str) find(list, nil == true) find(list, ok) find(list, ok).Bar find(list, ok).String find(list, ok)?.Bar find(list, ok)?.String find(list, str == $env) find(list, true ?? $env) find(list, true).Bar find(list, true).String find(list, true)?.Bar find(list, true)?.String find(map($env, $env), foo == #) find(map(array, 1.0), i != 1.0) find(map(list, #), ok) find(map(list, 0), ok) find(max($env), $env == i) find(nil ?? array, # > #) find(nil ?? list, # == #) find(sort($env), #.array.f64) find(sort($env), #.f64 not startsWith .String) find(sort($env), #.foo) find(sort($env), .foo?.[greet]) find(sort($env), .greet.Bar) find(sort($env), .list?.foobar) find(sort($env), .str?.ok)?.[ok] find(toPairs($env), $env.ok) find(toPairs($env), ok) find(values($env), ok ?? 1) findIndex($env | map(i), # > f64) findIndex($env, ok) > -f64 findIndex($env, ok) >= f64 findIndex($env, ok) ?? f64 findIndex($env, ok) ?? foo findIndex($env, true) <= f64 findIndex($env, true) ?? 1.0 ?? $env findIndex($env.array, ok) findIndex($env.list, ok) findIndex($env?.[str], 1.0 == nil) findIndex($env?.array, # < #) findIndex($env?.array, nil == greet) findIndex($env?.list, ok) findIndex([0], # <= 1) findIndex([1.0, foo], not ok) findIndex([1.0], # > 1.0) findIndex([add], ok) findIndex([array], ok) findIndex([f64], ok) findIndex([false], #) findIndex([false], ok) findIndex([foo], ok) findIndex([list], $env == add) findIndex([ok], #) findIndex([str], $env?.ok) findIndex([true], #) findIndex(array | sortBy(1.0), ok) findIndex(array, !false) findIndex(array, !true) findIndex(array, # != #) findIndex(array, # != nil) findIndex(array, # <= #) findIndex(array, # == 1.0) findIndex(array, # > #) findIndex(array, # >= #) findIndex(array, $env != $env) findIndex(array, $env != 0) findIndex(array, $env != true) findIndex(array, $env == #) findIndex(array, $env.ok) findIndex(array, $env?.ok) findIndex(array, 0 == #) findIndex(array, 0 == i) findIndex(array, 1 <= #) findIndex(array, 1.0 != $env) findIndex(array, 1.0 < #) findIndex(array, 1.0 == $env) findIndex(array, 1.0 >= #) findIndex(array, add == nil) findIndex(array, f64 > f64) findIndex(array, false || ok) findIndex(array, foo == nil) findIndex(array, nil != #) findIndex(array, nil != foo) findIndex(array, not true) findIndex(array, ok) findIndex(array, ok) ^ f64 findIndex(array, reduce(list, true)) findIndex(array, true || $env) findIndex(array, true || false) findIndex(array, true) / i findIndex(array, true) == $env != nil findIndex(array, true) | min(array) findIndex(filter($env, false), #.list(foobar)) findIndex(flatten(list), # != list) findIndex(flatten(list), .String != ok) findIndex(list | map(add), not ok) findIndex(list, !ok) findIndex(list, !true) findIndex(list, # != nil) findIndex(list, # == #) findIndex(list, # == nil) findIndex(list, $env != .String) findIndex(list, $env != true) findIndex(list, $env == false) findIndex(list, $env == i) findIndex(list, .Bar == $env) findIndex(list, all($env, true)) findIndex(list, f64 <= f64) findIndex(list, f64 == 1.0) findIndex(list, foo != $env) findIndex(list, foo == foo) findIndex(list, greet == nil) findIndex(list, nil != $env) findIndex(list, none(array, ok)) findIndex(list, not false) findIndex(list, ok ?? ok) findIndex(list, ok) findIndex(list, ok) * f64 findIndex(list, str in #) findIndex(list, str not contains str) findIndex(list, true) | min(1.0) findIndex(map($env, $env), #.String contains #) findIndex(map($env, $env), ok) ?? add findIndex(max($env), i > f64) findIndex(nil ?? $env, ok) findIndex(sort($env), #.String?.list(foobar)) findIndex(sort($env), #.f64 - #.i) findIndex(sort($env), #.str && #.f64) findIndex(sort($env), .array) findIndex(sort($env), list not in .Bar) findIndex(sort(array), # == false) findIndex(values($env), 1 != 1.0) findLast($env, false) == greet findLast($env, false)?.Bar findLast($env, false)?.String findLast($env, false)?.String?.str findLast($env, false)?.[add] findLast($env, false)?.[array] findLast($env, false)?.[f64] findLast($env, false)?.[foo] findLast($env, false)?.[greet] findLast($env, false)?.[greet]?.Bar findLast($env, false)?.[i] findLast($env, false)?.[i].array findLast($env, false)?.[list] findLast($env, false)?.[ok] findLast($env, false)?.[str] findLast($env, false)?.add() findLast($env, false)?.array findLast($env, false)?.array() findLast($env, false)?.f64 findLast($env, false)?.f64() findLast($env, false)?.f64?.[str] findLast($env, false)?.foo findLast($env, false)?.fromPairs(i) findLast($env, false)?.greet findLast($env, false)?.greet() findLast($env, false)?.i findLast($env, false)?.i() findLast($env, false)?.list findLast($env, false)?.list() findLast($env, false)?.list(foobar?.f64) findLast($env, false)?.ok findLast($env, false)?.ok() findLast($env, false)?.reduce(String) findLast($env, false)?.str findLast($env.array, # >= #) findLast($env.array, ok) findLast($env.array, str in $env) findLast($env.list, !false) findLast($env.list, ok) findLast($env?.[str], # not in array) findLast($env?.[str], 1 == 1.0) findLast($env?.[str], false == #) findLast($env?.array, $env.ok) findLast($env?.array, i in array) findLast($env?.array, ok) findLast($env?.list, ok) findLast([$env], $env != nil).array findLast([$env], .Bar != str) findLast([1.0], ok) findLast([f64, true], if # { # } else { # }) findLast([f64], 1 != $env) findLast([false], $env | none(true)) findLast([foo], ok) findLast([list], ok) findLast([ok], #) findLast([ok], ok) findLast([true], ok) findLast(array ?? 0, # != 1.0) findLast(array | map(#index), ok) findLast(array | sortBy(0), 1 < 1) findLast(array, # != #) findLast(array, # < #) findLast(array, # < f64) findLast(array, # <= #) findLast(array, # > 1) findLast(array, # > 1.0) findLast(array, # >= #) findLast(array, # >= 1.0) findLast(array, # >= i) findLast(array, $env != 1) findLast(array, $env == $env) findLast(array, $env == true) findLast(array, $env?.ok) findLast(array, 0 >= 1.0) findLast(array, 0 in array) findLast(array, 1 != #) findLast(array, 1 < 1) findLast(array, 1 > 1.0) findLast(array, 1.0 == nil) findLast(array, 1.0 >= 1.0) findLast(array, f64 < 0) findLast(array, f64 < 1.0) findLast(array, f64 < f64) findLast(array, f64 > #) findLast(array, f64 >= 1.0) findLast(array, f64 >= i) findLast(array, false || true) findLast(array, i < #) findLast(array, nil != #) findLast(array, nil != nil) findLast(array, none($env, false)) findLast(array, not ok) findLast(array, ok ?: 1.0) findLast(array, ok ?? #) findLast(array, ok) findLast(array, ok) + i findLast(array, ok) >= f64 findLast(array, ok) in array findLast(array, str not in foo) findLast(concat(list), !true) findLast(filter(list, false), $env?.[array]) findLast(flatten(array), true ?? .ok) findLast(flatten(list), ok) findLast(keys($env), foo == foo) findLast(list ?? list, ok) findLast(list | sortBy(0), # == #) findLast(list, # != #) findLast(list, # != $env) findLast(list, # != nil) findLast(list, # == $env) findLast(list, # == foo) findLast(list, #.Bar in #) findLast(list, #.String != nil) findLast(list, $env != nil) findLast(list, $env != true) findLast(list, $env == false) findLast(list, $env == foo.String()) findLast(list, $env or true) findLast(list, $env.ok) findLast(list, .Bar matches str) findLast(list, 0 != 1.0) findLast(list, 1 != f64) findLast(list, 1 >= 1.0) findLast(list, 1.0 <= f64) findLast(list, 1.0 == 1) findLast(list, 1.0 >= 1.0) findLast(list, f64 == f64) findLast(list, f64 > i) findLast(list, false)?.Bar findLast(list, foo != #) findLast(list, foo == #) findLast(list, i == $env) findLast(list, i > 0) findLast(list, nil == #) findLast(list, nil == greet) findLast(list, ok) findLast(list, ok).Bar findLast(list, ok).String findLast(list, ok).String() findLast(list, ok)?.Bar findLast(list, str != nil) findLast(list, str not contains str) findLast(list, str startsWith str) findLast(list, true && false) findLast(list, true ?? add) findLast(list, true) ?? i findLast(list, true).Bar findLast(list, true).String findLast(list, true).String() findLast(list, true)?.Bar findLast(map(list, ok), #) findLast(min($env), .array and false) findLast(sort($env), #) findLast(sort($env), .array) findLast(sort($env), .f64 != #.i) findLast(sort($env), .greet.array)?.list findLast(sort($env), .list?.list) findLast(sort($env), 1.0 != #.list) findLast(uniq(array), ok) findLast(values($env), # != foo) findLast(values($env), ok) findLastIndex($env ?? 1, true || #) findLastIndex($env ?? foo, ok) findLastIndex($env | filter(false), #.add) findLastIndex($env, ok) > i findLastIndex($env, ok) ^ f64 findLastIndex($env, true) + i findLastIndex($env, true) <= f64 findLastIndex($env, true) ^ i findLastIndex($env, true) | bitor(1) findLastIndex($env, true) | bitshl(1) findLastIndex($env.array, # >= 1) findLastIndex($env.array, ok) findLastIndex($env.array, true == ok) findLastIndex($env?.[str], 1.0 > #) findLastIndex($env?.[str], ok) findLastIndex($env?.array, # != #) findLastIndex($env?.array, $env != $env) findLastIndex($env?.array, ok) findLastIndex([$env], #.f64 == true) findLastIndex([$env], #.f64 not endsWith .String) findLastIndex([false, 0], ok) findLastIndex([false, true, $env], #.greet != true) findLastIndex([list], foo not in #) findLastIndex([true], #) findLastIndex([true], str < str) findLastIndex(array ?? 1.0, ok) findLastIndex(array ?? foo, ok) findLastIndex(array, !false) findLastIndex(array, # != 0) findLastIndex(array, # < #) findLastIndex(array, # < i) findLastIndex(array, # <= #) findLastIndex(array, # == $env) findLastIndex(array, # == f64) findLastIndex(array, # > #) findLastIndex(array, $env != false) findLastIndex(array, $env == 1.0) findLastIndex(array, $env.ok) findLastIndex(array, $env?.ok) findLastIndex(array, 0 == $env) findLastIndex(array, 1 >= 1.0) findLastIndex(array, 1.0 == #) findLastIndex(array, add == nil) findLastIndex(array, any($env, false)) findLastIndex(array, false && $env) findLastIndex(array, false) != 1.0 + 1.0 findLastIndex(array, i >= # != false) findLastIndex(array, nil != 1.0) findLastIndex(array, nil != array) findLastIndex(array, nil == ok) findLastIndex(array, not false) findLastIndex(array, ok ?? false) findLastIndex(array, ok) findLastIndex(array, str in foo) findLastIndex(array, str not in $env) findLastIndex(array, true ?? ok) findLastIndex(array, true || $env) findLastIndex(array, true) * 1.0 + 1 findLastIndex(array, true) * f64 findLastIndex(array, true) ?? sortBy(array, 1.0) findLastIndex(array, true) | bitushr(i) findLastIndex(false ? nil : $env, ok) findLastIndex(flatten(array), ok) findLastIndex(flatten(list), ok) findLastIndex(list, !true) findLastIndex(list, # == #) findLastIndex(list, #.Bar == nil) findLastIndex(list, #.Bar matches str) findLastIndex(list, $env.ok) findLastIndex(list, .Bar in foo) findLastIndex(list, 0 != 1) findLastIndex(list, 0 > 1.0) findLastIndex(list, 0 >= 1.0) findLastIndex(list, 1.0 >= f64) findLastIndex(list, false ? foo : ok) findLastIndex(list, foo != #) findLastIndex(list, foo != $env) findLastIndex(list, foo == #) findLastIndex(list, foo not in list) findLastIndex(list, i > f64) findLastIndex(list, nil != #) findLastIndex(list, nil != foo) findLastIndex(list, nil != nil) findLastIndex(list, nil == 1) findLastIndex(list, nil in $env) findLastIndex(list, not false) findLastIndex(list, ok != false) findLastIndex(list, ok) findLastIndex(list, ok) < i findLastIndex(list, one(list, false)) findLastIndex(list, str == $env) findLastIndex(list, str not in #) findLastIndex(list, str not startsWith .Bar) findLastIndex(list, true) > f64 findLastIndex(list, true) ?? greet findLastIndex(map($env, str), ok) findLastIndex(map(array, ok), #) findLastIndex(map(list, add), ok) findLastIndex(sort($env), # contains #) findLastIndex(sort($env), #.foo?.greet) findLastIndex(sort($env), $env ?: #.i) findLastIndex(sort($env), ok) first($env ?? $env) first($env ?? 0) first($env ?? 1) first($env ?? 1.0) first($env ?? foo) first($env ?? foo) not in list first($env ?? greet) first($env ?? i) first($env ?? str) first($env ?? true) first($env ?? true)?.i first($env | findLast(false)) first($env | map(#index)) first($env | map($env)) first($env | map($env))?.foo first($env | map(1)) first($env) != $env?.f64 first($env) != foo first($env) != i first($env) == i first($env) == str first($env) ?? array first($env) ?? list first($env) not contains str first($env) not in array first($env) not matches str first($env) not startsWith str first($env) startsWith str first($env) | get(1.0) first($env)?.$env?.array() first($env)?.Bar first($env)?.Bar() first($env)?.Bar(add) first($env)?.Bar?.add first($env)?.String first($env)?.String() first($env)?.String?.array first($env)?.String?.foo first($env)?.[add] first($env)?.[add].list() first($env)?.[add]?.[foo] first($env)?.[add]?.i first($env)?.[array] first($env)?.[f64] first($env)?.[f64].String first($env)?.[f64].list first($env)?.[f64]?.String first($env)?.[foo] first($env)?.[foo]?.[greet].String first($env)?.[greet] first($env)?.[greet]?.[greet] first($env)?.[greet]?.f64 first($env)?.[greet]?.str first($env)?.[i] first($env)?.[i]?.String first($env)?.[i]?.[foo] first($env)?.[i]?.add first($env)?.[i]?.i first($env)?.[i]?.str first($env)?.[list] first($env)?.[list].Bar?.str().ok?.[str] first($env)?.[list].list first($env)?.[ok] first($env)?.[ok].add() first($env)?.[ok].list first($env)?.[str] first($env)?.[str].String first($env)?.[str].f64 first($env)?.[str]?.[str] first($env)?.[str]?.f64 first($env)?.[str]?.ok first($env)?.[str]?.str first($env)?.add first($env)?.add() first($env)?.add()?.add() first($env)?.add.String first($env)?.add.f64 first($env)?.add.greet() first($env)?.add?.String first($env)?.add?.[greet] first($env)?.add?.[i] first($env)?.add?.[list] first($env)?.any(foobar) first($env)?.any(foobar, ok) first($env)?.array first($env)?.array() first($env)?.array(foobar) first($env)?.array.ok first($env)?.f64 first($env)?.f64() first($env)?.f64(f64) first($env)?.f64(foobar) first($env)?.f64.String first($env)?.findIndex(add) first($env)?.foo first($env)?.foo() first($env)?.foo()?.Bar first($env)?.foo(foo)?.[list] first($env)?.foo(foobar not contains foobar) first($env)?.foo(foobar) first($env)?.foo?.[greet] first($env)?.foobar first($env)?.foobar not in $env first($env)?.foobar.greet first($env)?.foobar.list first($env)?.foobar?.[greet] first($env)?.greet first($env)?.greet() first($env)?.greet(foobar not startsWith foobar) first($env)?.greet(foobar, foobar) first($env)?.greet(true) first($env)?.greet?.Bar first($env)?.greet?.[f64] first($env)?.greet?.[i] first($env)?.greet?.[str] first($env)?.greet?.str first($env)?.i first($env)?.i() first($env)?.i.i first($env)?.i?.add first($env)?.indexOf(foobar) first($env)?.list first($env)?.list() first($env)?.list().Bar first($env)?.list(Bar) first($env)?.list(foo) first($env)?.list(foobar) first($env)?.list(foobar).String first($env)?.list(foobar?.[Bar]) first($env)?.list.str first($env)?.list?.[foo] first($env)?.list?.[str] first($env)?.list?.add first($env)?.map(add) first($env)?.ok first($env)?.ok() first($env)?.ok()?.[ok] first($env)?.ok(foobar) first($env)?.str first($env)?.str() first($env)?.str(f64) first($env)?.toJSON(String) first($env.array) first($env.list) first($env?.$env) first($env?.$env?.f64) first($env?.Bar) first($env?.Bar)?.array first($env?.Bar?.[array]) first($env?.Bar?.[foo]) first($env?.Bar?.f64) first($env?.String) first($env?.String)?.String first($env?.String)?.String() first($env?.String)?.i first($env?.[Bar]) first($env?.[Bar])?.[i] first($env?.[Bar])?.[str] first($env?.[Bar])?.str first($env?.[Bar]?.String) first($env?.[Bar]?.f64) first($env?.[String]) first($env?.[String])?.String() first($env?.[String])?.str first($env?.[String]?.f64) first($env?.[String]?.foo) first($env?.[foobar]) first($env?.[foobar])?.Bar first($env?.[nil]) first($env?.[nil]?.ok) first($env?.[str]) first($env?.array) first($env?.false) first($env?.foobar) first($env?.foobar)?.Bar() first($env?.foobar)?.i() first($env?.foobar?.str) first($env?.greet ?? ok) first($env?.list) first($env?.nil) first($env?.nil)?.f64 first($env?.true) first(0 .. 0) first(0 .. i) first(0 ?? $env) first(0 ?? array) first(0 ?? false) first(0 ?? foo) first(0 ?? greet) first(0 ?? str) first(0 ?? true) first(0..i) first(1 .. 0) first(1 .. i) first(1 ?? $env) first(1 ?? 1.0) first(1 ?? foo) first(1 ?? ok) first(1 ?? true) first(1 | median(array)) first(1.0 ?? $env) first(1.0 ?? $env.list) first(1.0 ?? 0) first(1.0 ?? 1) first(1.0 ?? add) first(1.0 ?? false) first(1.0 ?? foo) first(1.0 ?? greet) first(1.0 ?? i) first(1.0 ?? list) first(1.0 | min(array)) first([$env, array]) first([$env?.array]) first([$env]) first([0, array]) first([0]) first([1 > 1.0]) first([1, add]) first([1.0, 1.0]) first([1.0]) first([1]) first([add, $env, greet]) first([add]) first([array]) first([f64]) first([false, $env]) first([false, str]) first([false]) first([floor(f64)]) first([foo ?? foo]) first([foo]) first([greet]) first([i]) first([list]) first([nil, array]) first([nil]) first([ok]) first([str]) first([true]) first([type(greet)]) first(add ?? $env)?.f64 first(add ?? 0) first(add ?? 1) first(add ?? foo) first(add ?? list) first(add ?? str) first(add ?? true) first(array ?? $env) first(array ?? add) first(array ?? array) first(array ?? i) first(array ?? nil) first(array ?? ok) first(array | map(#)) first(array | map($env)) first(array | map(0)) first(array | map(1.0)) first(array | map(foo)) first(array | reduce($env, foo)) first(array | reduce(list, nil)) first(array | sortBy(#)) first(array | sortBy(1.0)) first(array | take(1)) first(array) first(array) != i first(array) * $env?.i first(array) / i != nil first(array) == i first(array) > 1.0 > $env first(array) > f64 first(array) >= $env.f64 first(array) ?? $env?.String() first(array) ?? foo first(array) ?? list first(array) | bitand(1) first(array) | bitshr(1) first(array[:0]) first(array[:1]) first(concat(array) | reduce(#)) first(concat(array)) first(concat(list)) first(f64 ?? $env)?.[foo] first(f64 ?? 1) first(f64 ?? array) first(f64 ?? greet) first(f64 ?? i) first(f64 ?? list) first(f64 ?? str) first(f64 | mean(array, 1)) first(false ? i : list) first(false ?? $env) first(false ?? 1) first(false ?? 1.0) first(false ?? add) first(false ?? foo) first(false ?? str) first(filter($env, false)) first(filter(list, ok)) first(find($env, false)) first(find($env, false))?.foo first(first($env)) first(first($env))?.[add] first(flatten(array)) first(flatten(list)) first(foo ?? $env) first(foo ?? $env.add) first(foo ?? 0) first(foo ?? 1) first(foo ?? 1.0) first(foo ?? add) first(foo ?? array) first(foo ?? f64) first(foo ?? false) first(foo ?? greet) first(foo ?? i) first(foo ?? list) first(foo ?? ok) first(foo ?? str) first(foo ?? true) first(greet ?? 1) first(greet ?? 1.0) first(greet ?? f64) first(greet ?? foo.Bar) first(greet ?? i) first(greet ?? list) first(greet ?? true) first(i .. 1) first(i ?? $env) first(i ?? f64) first(i ?? false) first(i ?? greet) first(i ?? ok) first(i..i) first(if false { 0 } else { foo }) first(if false { foo } else { greet }) first(if false { foo } else { str }) first(if ok { foo } else { false }) first(if true { 0 } else { foo })?.add first(if true { ok } else { 1 }) first(if true { ok } else { 1.0 }) first(keys($env)) first(last($env)) first(let foobar = list; foobar) first(list ?? add) first(list ?? f64) first(list ?? false) first(list ?? str) first(list | map(#)) first(list | map(#.Bar)) first(list | map(0)) first(list | map(add)) first(list | map(false)) first(list | map(true)) first(list | reduce(list)) first(list | sortBy(#.Bar)) first(list) first(list) == $env?.String first(list) ?? $env?.[add] first(list) ?? f64 first(list) ?? foo first(list) ?? greet first(list).Bar first(list).String first(list).String() first(list)?.Bar first(list)?.String first(list)?.String() first(list[:0]) first(list[:1]) first(list[:i]) first(map($env, $env)) first(map($env, 0)) first(map($env, 1)) first(map($env, array)) first(map($env, f64)) first(map($env, false)) first(map($env, i)) first(map($env, ok)) first(map(array, #)) first(map(array, #index)) first(map(array, $env)) first(map(array, 0)) first(map(array, 1)) first(map(array, 1.0)) first(map(array, false)) first(map(array, greet)) first(map(array, list)) first(map(array, str)) first(map(array, true)) first(map(list, #)) first(map(list, $env) | findLast(true)) first(map(list, 0)) first(map(list, array)) first(map(list, f64)) first(map(list, foo)) first(max($env)) first(max(array)) first(mean(array)) first(median(array)) first(min($env)) first(min($env))?.add first(min($env)?.f64) first(min(array)) first(min(array, 1, 1)) first(nil ?? $env) first(nil ?? array) first(ok ? 0 : 1.0) first(ok ? add : false) first(ok ? ok : $env) first(ok ?: $env) first(ok ?: add) first(ok ?: list) first(ok ?? $env) first(ok ?? 0) first(ok ?? 1.0) first(ok ?? foo) first(ok ?? foo)?.[list] first(ok ?? greet) first(reduce(array, $env)) first(reduce(list, list, $env)) first(reverse(array)) first(reverse(list)) first(sort($env)) first(sort(array)) first(sortBy(array, #)) first(sortBy(array, 1)) first(sortBy(array, f64)) first(sortBy(list, .Bar)) first(str ?? 0) first(str ?? 1) first(str ?? 1.0) first(str ?? add) first(str ?? i) first(str ?? ok) first(take(array, i)) first(toPairs($env)) first(true ? 1.0 : foo) first(true ?: 1.0)?.str first(true ?: str) first(true ?? add) first(true ?? foo) first(true ?? list) first(uniq(array)) first(uniq(list)) first(values($env)) first({foo: 1.0}.f64) first({foo: greet, foo: nil}.ok) first({foo: i, foo: f64}.String) flatten($env | map($env)) flatten($env | map(1.0)) flatten($env | map(add)) flatten($env | map(array)) flatten($env | map(foo)) flatten($env | map(i)) flatten($env | map(list)) flatten($env.array) flatten($env.list) flatten($env?.array) flatten($env?.list) flatten($env?.list)?.[i] flatten(0 .. i) flatten(1 .. 0) flatten(1 .. 1) flatten(1 .. i) flatten([$env]) flatten([0 <= 1]) flatten([0, 1.0]) flatten([0]) flatten([1.0, foo]) flatten([1.0]) flatten([1]) flatten([add, greet]) flatten([add, i]) flatten([add]) flatten([array, f64]) flatten([array, ok]) flatten([array]) flatten([f64, $env, 1]) flatten([f64, nil]) flatten([f64]) flatten([false, list]) flatten([false]) flatten([foo, 0]) flatten([foo, 1.0]) flatten([foo, str]) flatten([foo]) flatten([greet, foo]) flatten([greet]) flatten([i, list]) flatten([i]) flatten([list]) flatten([nil == ok]) flatten([nil]) flatten([ok, array]) flatten([ok, true]) flatten([ok]) flatten([str, list]) flatten([str]) flatten([true]) flatten(array ?? 0) flatten(array ?? 1) flatten(array ?? add) flatten(array ?? f64) flatten(array ?? foo) flatten(array ?? list) flatten(array ?? nil) flatten(array ?? true) flatten(array | map(#)) flatten(array | map(1.0)) flatten(array | map(array)) flatten(array | map(false)) flatten(array | reduce(array, false)) flatten(array | sortBy(#)) flatten(array | sortBy(1.0)) flatten(array | sortBy(i)) flatten(array) flatten(array) != array flatten(array) == array flatten(array) == list flatten(array) ?? greet flatten(array) ?? i flatten(array) | filter(ok) flatten(array) | groupBy(#) flatten(array) | groupBy(1.0) flatten(array) | groupBy(f64) flatten(array) | map(#) flatten(array) | map(ok) flatten(array) | min(1.0) flatten(array) | one(true) flatten(array) | reduce(#) flatten(array) | reduce(1.0) flatten(array) | reduce(foo) flatten(array) | reduce(true) flatten(array) | sum(#) flatten(array)?.[i] flatten(array)[i:] flatten(array[0:]) flatten(array[:1]) flatten(concat(array)) flatten(concat(list)) flatten(filter(list, false)) flatten(flatten(array)) flatten(flatten(list)) flatten(groupBy(array, #).String) flatten(groupBy(list, #).i) flatten(i .. 0) flatten(i..i) flatten(if ok { array } else { foo }) flatten(if ok { list } else { array }) flatten(if true { array } else { add }) flatten(keys($env)) flatten(let z = array; z) flatten(list ?? $env) flatten(list ?? 1) flatten(list ?? 1.0) flatten(list ?? nil) flatten(list | map(#)) flatten(list | map(i)) flatten(list | sortBy(0)) flatten(list | sortBy(f64)) flatten(list | sortBy(str)) flatten(list) flatten(list) == list flatten(list) | filter(true) flatten(list) | findLast(ok) flatten(list) | findLastIndex(false) flatten(list) | groupBy(!ok) flatten(list) | groupBy(#) flatten(list) | groupBy(foo) flatten(list) | groupBy(i) flatten(list) | map(1.0) flatten(list) | map(add) flatten(list) | map(f64) flatten(list) | map(false) flatten(list) | map(foo) flatten(list) | map(ok) flatten(list) | none(true) flatten(list) | reduce(#) flatten(list) | reduce($env, $env) flatten(list) | reduce(1.0) flatten(list) | sortBy(0) flatten(list) | sortBy(1.0) flatten(list) | sortBy(str) flatten(list) | sum(1) flatten(list)?.[i] flatten(list)[:] flatten(list[0:]) flatten(list[1:]) flatten(list[:]) flatten(map($env, $env)) flatten(map($env, 0)) flatten(map($env, 1.0)) flatten(map($env, f64)) flatten(map($env, false)) flatten(map(array, f64)) flatten(map(array, i)) flatten(map(array, true)) flatten(map(list, #)) flatten(map(list, $env)) flatten(map(list, .Bar)) flatten(map(list, f64)) flatten(map(list, ok)) flatten(nil ?? array) flatten(nil ?? list) flatten(reduce(array, array)) flatten(reverse(array)) flatten(reverse(list)) flatten(sort($env)) flatten(sort(array)) flatten(sortBy(array, #)) flatten(sortBy(array, 1)) flatten(sortBy(array, 1.0)) flatten(sortBy(array, f64)) flatten(sortBy(list, 1.0)) flatten(sortBy(list, i)) flatten(toPairs($env)) flatten(true ? list : list) flatten(uniq(array)) flatten(uniq(list)) flatten(values($env)) float($env | findIndex(true)) float($env | findLastIndex(ok)) float($env | findLastIndex(true)) float($env | sum(0)) float($env | sum(1.0)) float($env | sum(f64)) float($env | sum(i)) float($env.f64) float($env.i) float($env?.f64) float($env?.i) float(-0) float(-1) float(-1.0) float(-f64) float(-i) float(0 % 1) float(0 % i) float(0 * 1) float(0 * 1.0) float(0 * f64) float(0 ** 1) float(0 ** 1.0) float(0 ** f64) float(0 ** i) float(0 + 1) float(0 + i) float(0 - 1) float(0 - 1.0) float(0 - i) float(0 / 0) float(0 / 1.0) float(0 / f64) float(0 / i) float(0 ?? $env) float(0 ?? $env?.[i]) float(0 ?? false) float(0 ?? greet) float(0 ?? nil) float(0 ?? true) float(0 ^ 0) float(0 ^ 1) float(0 ^ 1.0) float(0 ^ f64) float(0 ^ i) float(0 | median(1.0)) float(0) != $env && ok float(0) != 1.0 && false float(0) ** f64 float(0) + $env?.f64 float(0) - float(0) float(0) > f64 float(0) > i float(0) >= -1 float(0) ^ f64 float(1 % 1) float(1 % i) float(1 * 1) float(1 * 1.0) float(1 * f64) float(1 * i) float(1 ** 1) float(1 ** 1.0) float(1 ** f64) float(1 ** i) float(1 + 1) float(1 + 1.0) float(1 + i) float(1 - 1.0) float(1 - f64) float(1 / 0) float(1 / 1) float(1 / 1.0) float(1 ?? $env) float(1 ?? $env?.array) float(1 ?? 0) float(1 ?? 1.0) float(1 ?? add) float(1 ?? nil) float(1 ?? ok) float(1 ^ 0) float(1 ^ 1) float(1 ^ 1.0) float(1 ^ i) float(1) + i float(1) - f64 float(1) < f64 float(1) == f64 float(1) == i float(1) ?? f64 float(1) ?? foo ?? $env float(1) ?? str float(1) ^ i float(1) in [add, true] float(1.0 * 0) float(1.0 * 1) float(1.0 * 1.0) float(1.0 * f64) float(1.0 * i) float(1.0 ** 0) float(1.0 ** 1) float(1.0 ** 1.0) float(1.0 ** f64) float(1.0 ** i) float(1.0 + 0) float(1.0 + 1.0) float(1.0 + f64) float(1.0 + i) float(1.0 - 0) float(1.0 - 1) float(1.0 - 1.0) float(1.0 - f64) float(1.0 - i) float(1.0 / 0) float(1.0 / 1) float(1.0 / 1.0) float(1.0 / f64) float(1.0 / i) float(1.0 ?? $env) float(1.0 ?? 0) float(1.0 ?? 1) float(1.0 ?? 1.0) float(1.0 ?? add) float(1.0 ?? array) float(1.0 ?? f64) float(1.0 ?? false) float(1.0 ?? foo) float(1.0 ?? i) float(1.0 ?? list) float(1.0 ?? nil) float(1.0 ?? str) float(1.0 ^ 0) float(1.0 ^ 1) float(1.0 ^ 1.0) float(1.0 ^ f64) float(1.0 ^ i) float(1.0 | min(f64)) float(1.0) != $env?.[str] float(1.0) * max(f64) float(1.0) ** i float(1.0) - f64 float(1.0) - i float(1.0) / i float(1.0) < i float(1.0) <= i float(1.0) == 0 % 1 float(1.0) == i float(1.0) == i != false float(1.0) > f64 float(1.0) >= last(array) float(1.0) | median(1.0) float(abs(0)) float(abs(1)) float(abs(1.0)) float(abs(f64)) float(abs(i)) float(add(0, i)) float(add(1, 1)) float(array | findLastIndex(true)) float(array | max(1)) float(array | reduce(#acc)) float(array | reduce(#index, 1.0)) float(array | reduce(1)) float(array | sum(#)) float(array | sum(0)) float(array | sum(1.0)) float(array?.[i]) float(bitand(0, i)) float(bitnot(0)) float(bitnot(1)) float(bitnot(i)) float(bitor(0, i)) float(bitshl(i, 0)) float(bitshr(0, 0)) float(bitshr(i, 1)) float(ceil(0)) float(ceil(1)) float(ceil(1.0)) float(ceil(f64)) float(ceil(i)) float(count($env, false)) float(count($env, ok)) float(count(array, true)) float(count(list, false)) float(count(list, ok)) float(f64 * 1) float(f64 * 1.0) float(f64 * f64) float(f64 ** 0) float(f64 ** 1) float(f64 ** 1.0) float(f64 + 0) float(f64 + 1.0) float(f64 + f64) float(f64 + i) float(f64 - 1.0) float(f64 / 0) float(f64 / 1) float(f64 / 1.0) float(f64 / f64) float(f64 / i) float(f64 ?? 1) float(f64 ?? 1.0) float(f64 ?? add) float(f64 ?? f64) float(f64 ?? greet) float(f64 ?? true) float(f64 ^ 0) float(f64 ^ 1) float(f64 ^ 1.0) float(f64) float(f64) != f64 float(f64) * 1.0 ** i float(f64) ** f64 float(f64) / max(1) float(f64) == i float(f64) ?? greet float(f64) ?? upper(str) float(false ? i : 1.0) float(false ? str : 1.0) float(false ?: 1.0) float(false ?: i) float(findIndex($env, ok)) float(findIndex(array, true)) float(findLastIndex($env, ok)) float(findLastIndex($env, true)) float(findLastIndex(array, ok)) float(first(array)) float(float(0)) float(float(1)) float(float(1.0)) float(float(f64)) float(float(i)) float(floor(0)) float(floor(1)) float(floor(1.0)) float(floor(f64)) float(floor(i)) float(i % 1) float(i * 0) float(i * 1.0) float(i * f64) float(i ** 1.0) float(i ** i) float(i + 0) float(i + 1) float(i + 1.0) float(i - 0) float(i - 1) float(i - 1.0) float(i - f64) float(i - i) float(i / 0) float(i / 1) float(i / 1.0) float(i ?? $env) float(i ?? 1) float(i ?? 1.0) float(i ?? add) float(i ?? foo) float(i ?? nil) float(i ?? true) float(i ^ i) float(i | bitor(0)) float(i) float(i) + first(array) float(i) == i float(i) > f64 float(i) in $env?.[String] float(i) | max(f64) float(if false { 1.0 } else { 1 }) float(if false { greet } else { 1 }) float(if false { greet } else { 1.0 }) float(if false { ok } else { 1.0 }) float(if true { 0 } else { $env }) float(if true { 1.0 } else { $env }) float(if true { 1.0 } else { i }) float(int(0)) float(int(1)) float(int(1.0)) float(int(f64)) float(int(i)) float(last(array)) float(lastIndexOf(str, str)) float(len($env)) float(len(array)) float(len(list)) float(len(str)) float(let foobar = i; foobar) float(list | findIndex(ok)) float(list | reduce(i)) float(list | sum(1.0)) float(list | sum(f64)) float(max($env?.f64)) float(max(0)) float(max(1)) float(max(1.0)) float(max(f64, 1)) float(max(f64, 1.0)) float(max(i)) float(mean(0)) float(mean(1)) float(mean(1.0 - 1.0)) float(mean(1.0)) float(mean(array)) float(mean(f64)) float(mean(f64, 1)) float(mean(i)) float(median(0)) float(median(1)) float(median(1.0)) float(median(1.0, 0, 0)) float(median(1.0, i)) float(median(array)) float(median(array, f64)) float(median(f64)) float(median(i)) float(min($env).f64) float(min($env?.array)) float(min(0)) float(min(0, 1)) float(min(1)) float(min(1.0)) float(min(array)) float(min(f64)) float(min(i)) float(nil ?? 1.0) float(reduce($env, 1.0, 1.0)) float(reduce(array, #)) float(reduce(list, 0)) float(reduce(list, 1)) float(reduce(list, i)) float(round(0)) float(round(1)) float(round(1.0)) float(round(f64)) float(round(i)) float(string(0)) float(string(1)) float(string(1.0)) float(string(f64)) float(string(i)) float(sum($env, 0)) float(sum($env, 1)) float(sum($env, 1.0)) float(sum($env.array)) float(sum($env?.array)) float(sum(array)) float(sum(array, #)) float(sum(array, 1)) float(sum(array, i)) float(sum(list, 1)) float(toJSON(0)) float(toJSON(1)) float(toJSON(1.0)) float(toJSON(f64)) float(toJSON(i)) float(toJSON(min(1.0))) float(true ? 1.0 : ok) float(true ? f64 : foo) float(true ? f64 : str) floor($env | count(true)) floor($env | findIndex(ok)) floor($env | findLastIndex(true)) floor($env | reduce(f64, f64)) floor($env.array?.[i]) floor($env.f64) floor($env.i) floor($env?.add(i, 1)) floor($env?.f64) floor($env?.i ^ f64) floor($env?.i) floor(-0) floor(-1) floor(-1.0) floor(-f64) floor(-i) floor(0 % i) floor(0 * 1) floor(0 * 1.0) floor(0 * f64) floor(0 * i) floor(0 ** 0) floor(0 ** 1.0) floor(0 ** f64) floor(0 ** i) floor(0 + 1.0) floor(0 + f64) floor(0 - 0) floor(0 - 1) floor(0 - 1.0) floor(0 - f64) floor(0 - i) floor(0 / 0) floor(0 / 1) floor(0 / f64) floor(0 / i) floor(0 ?? add) floor(0 ?? array) floor(0 ?? foo) floor(0 ?? greet) floor(0 ?? i) floor(0 ?? str) floor(0 ?? true) floor(0 ^ 0) floor(0 ^ 1.0) floor(0 ^ f64) floor(0 | bitxor(i)) floor(0 | min(1.0)) floor(0) * i floor(0) * reduce(array, #) floor(0) < array?.[i] floor(0) < f64 floor(0) < i floor(0) <= f64 floor(0) >= i floor(0) ?? f64 floor(0) ?? greet(str) floor(0) ?? list floor(0.0) floor(1 % 1) floor(1 % i) floor(1 * 1) floor(1 * 1.0) floor(1 * f64) floor(1 * i) floor(1 ** 0) floor(1 ** 1) floor(1 ** 1.0) floor(1 ** i) floor(1 + 1) floor(1 + 1.0) floor(1 + f64) floor(1 + i) floor(1 - 1) floor(1 - i) floor(1 / 0) floor(1 / 1.0) floor(1 / f64) floor(1 ?? $env?.[array]) floor(1 ?? 0) floor(1 ?? 1) floor(1 ?? false) floor(1 ?? foo) floor(1 ?? greet) floor(1 ?? i) floor(1 ?? nil) floor(1 ?? str) floor(1 ?? true) floor(1 ^ 0) floor(1 ^ 1.0) floor(1 ^ f64) floor(1 ^ i) floor(1) != f64 floor(1) * f64 floor(1) * i floor(1) ** f64 floor(1) + $env?.f64 floor(1) - i floor(1) <= i floor(1) ?? str floor(1) in array floor(1) | mean(1.0) floor(1) | min(1.0) floor(1.0 * 0) floor(1.0 * 1) floor(1.0 * 1.0) floor(1.0 * f64) floor(1.0 * i) floor(1.0 ** 0) floor(1.0 ** 1) floor(1.0 ** 1.0) floor(1.0 ** f64) floor(1.0 ** i) floor(1.0 + 0) floor(1.0 + 1) floor(1.0 + 1.0) floor(1.0 + f64) floor(1.0 - 0) floor(1.0 - 1.0) floor(1.0 - f64) floor(1.0 - i) floor(1.0 / 0) floor(1.0 / 1) floor(1.0 / 1.0) floor(1.0 / f64) floor(1.0 ?? $env) floor(1.0 ?? 0) floor(1.0 ?? 1) floor(1.0 ?? 1.0) floor(1.0 ?? add) floor(1.0 ?? false) floor(1.0 ?? foo) floor(1.0 ?? greet) floor(1.0 ?? i) floor(1.0 ?? nil) floor(1.0 ?? str) floor(1.0 ^ 0) floor(1.0 ^ 1.0) floor(1.0 ^ i) floor(1.0 | max(f64)) floor(1.0 | mean(array)) floor(1.0 | min(f64)) floor(1.0) != $env?.f64 floor(1.0) + f64 floor(1.0) - $env.i floor(1.0) <= i floor(1.0) == f64 floor(1.0) > i floor(1.0) ?? array floor(1.0) | mean(1.0) floor(1.0) | median(0) floor(1.0) | min(f64) floor(abs(0)) floor(abs(1)) floor(abs(1.0)) floor(abs(f64)) floor(abs(i)) floor(add(i, i)) floor(array | findLast(ok)) floor(array | findLastIndex(ok)) floor(array | findLastIndex(true)) floor(array | mean(1)) floor(array | mean(f64)) floor(array | reduce(#)) floor(array | reduce(#index)) floor(array | sum(#)) floor(array | sum(f64)) floor(array | sum(i)) floor(array?.[0]) floor(array?.[1]) floor(array?.[i]) floor(bitand(i, 1)) floor(bitnot(-0)) floor(bitnot(0)) floor(bitnot(1)) floor(bitnot(i)) floor(bitshr(1, i)) floor(bitxor(0, 1)) floor(ceil(0)) floor(ceil(1)) floor(ceil(1.0)) floor(ceil(f64 + 0)) floor(ceil(f64)) floor(ceil(i)) floor(count($env, true)) floor(count(list, ok)) floor(f64 * 1) floor(f64 * 1.0) floor(f64 * i) floor(f64 ** 1.0) floor(f64 ** i) floor(f64 + 0) floor(f64 + 1) floor(f64 + 1.0) floor(f64 + f64) floor(f64 + i) floor(f64 - 1) floor(f64 - 1.0) floor(f64 - f64) floor(f64 - i) floor(f64 / 1.0) floor(f64 / f64) floor(f64 ?? $env) floor(f64 ?? 0) floor(f64 ?? 1) floor(f64 ?? 1.0) floor(f64 ?? foo) floor(f64 ?? greet) floor(f64 ^ 0) floor(f64 ^ 1.0) floor(f64 ^ i) floor(f64) floor(f64) ** f64 floor(f64) / i floor(f64) < f64 floor(f64) >= f64 floor(f64) >= i ^ f64 floor(f64) in array floor(false ? $env : i) floor(false ?: 1) floor(findIndex($env, ok)) floor(findIndex(list, true)) floor(findLast(array, ok)) floor(findLastIndex(array, true)) floor(findLastIndex(list, ok)) floor(first(array)) floor(float(0)) floor(float(1)) floor(float(1.0)) floor(float(f64)) floor(float(i)) floor(floor(0)) floor(floor(1)) floor(floor(1.0)) floor(floor(f64)) floor(floor(i)) floor(i * 1.0) floor(i * i) floor(i ** 0) floor(i ** 1) floor(i ** 1.0) floor(i ** f64) floor(i ** i) floor(i + 1) floor(i + 1.0) floor(i + i) floor(i - 0) floor(i - 1.0) floor(i - f64) floor(i / 0) floor(i / 1) floor(i / 1.0) floor(i / f64) floor(i ?? 0) floor(i ?? foo) floor(i ?? greet) floor(i ?? i) floor(i ?? ok) floor(i ?? str) floor(i ?? true) floor(i ^ 0) floor(i ^ 1) floor(i ^ 1.0) floor(i ^ f64) floor(i ^ i) floor(i | add(1)) floor(i | median(array)) floor(i | min(0)) floor(i) floor(i) * f64 < 1.0 floor(i) ** 1.0 >= 1.0 floor(i) ** i floor(i) - f64 floor(i) / 1.0 >= 1.0 floor(i) / sum(array) floor(i) == $env != ok floor(i) == f64 floor(i) == i floor(i) > f64 floor(i) ^ f64 floor(i) | max(1.0) floor(if ok { f64 } else { nil }) floor(if ok { i } else { $env }) floor(if true { 1.0 } else { f64 }) floor(int(0)) floor(int(1)) floor(int(1.0)) floor(int(f64)) floor(int(i)) floor(last(array)) floor(len($env)) floor(len(array)) floor(len(list)) floor(len(str)) floor(let foobar = 1.0; foobar) floor(let x = f64; x) floor(list | sum(1)) floor(max(0 ^ 0)) floor(max(0)) floor(max(1)) floor(max(1.0)) floor(max(f64)) floor(max(i)) floor(mean(0)) floor(mean(0, 1.0)) floor(mean(1)) floor(mean(1, 1)) floor(mean(1.0)) floor(mean(array)) floor(mean(f64)) floor(mean(i)) floor(median(0)) floor(median(0, 1.0)) floor(median(1)) floor(median(1.0)) floor(median(array)) floor(median(f64)) floor(median(i)) floor(min(0)) floor(min(1)) floor(min(1.0)) floor(min(1.0, 0)) floor(min(array)) floor(min(array, 1)) floor(min(f64)) floor(min(i)) floor(nil ?? 0) floor(nil ?? 1.0) floor(nil ?? f64) floor(ok ? 1.0 : nil) floor(ok ? i : greet) floor(reduce(array, #)) floor(reduce(array, #, list)) floor(reduce(array, 1)) floor(reduce(list, 1)) floor(reduce(list, f64)) floor(round(0)) floor(round(1)) floor(round(1.0)) floor(round(add(0, i))) floor(round(f64)) floor(round(i)) floor(sum($env, 0)) floor(sum($env, 1.0)) floor(sum(array)) floor(sum(array, #)) floor(sum(array, 1.0)) floor(sum(list, 0)) floor(sum(list, 1.0)) foo foo != $env != ok foo != $env && ok and ok foo != $env == ok foo != $env == true foo != $env ? $env : nil foo != $env ?? greet foo != $env ?? list foo != $env and ok foo != $env or $env[foobar:] foo != $env || false foo != $env || ok foo != $env.foo foo != $env?.Bar foo != $env?.Bar?.[i] foo != $env?.Bar?.array foo != $env?.Bar?.list foo != $env?.String foo != $env?.String?.[greet] foo != $env?.String?.array foo != $env?.String?.greet foo != $env?.[Bar?.[greet]] foo != $env?.[Bar] foo != $env?.[String] foo != $env?.[String]?.add foo != $env?.[String]?.list foo != $env?.[foobar?.[foo]] foo != $env?.[foobar] foo != $env?.[str] foo != $env?.foo foo != $env?.foobar foo != $env?.not foo != 0 ?? ok foo != 1 ?? f64 foo != 1.0 ?? add foo != 1.0 ?? greet foo != 1.0 ?? ok foo != add ?? array foo != array ?? ok foo != array ?? str foo != first($env) foo != first(list) foo != foo foo != foo != $env foo != foo && $env.ok foo != foo && f64 == 0 foo != foo && get($env, 1) foo != foo == $env || false foo != foo == false foo != foo == true foo != foo ?: i foo != foo ?? $env.array foo != foo ?? add foo != foo ?? foo foo != foo ?? list foo != foo ?? nil foo != foo and find($env, .f64) foo != foo and true foo != foo or 0 ?? false foo != foo or ok foo != foo || ok foo != greet ?? add foo != greet ?? false foo != i ?? false foo != i ?? ok foo != last(list) foo != list ?? $env foo != list ?? greet(str) foo != list?.[i] foo != mean(array) foo != nil != $env foo != nil == $env.ok foo != nil ? 1.0 : $env foo != nil ? str : foo foo != nil ?: $env foo != nil ?? foo foo != nil || sum($env, $env) foo != str ?? f64 foo == $env != nil foo == $env != ok foo == $env && ok foo == $env ?: $env | map(foo) foo == $env ?? array foo == $env ?? greet foo == $env and $env foo == $env in $env?.foobar foo == $env or $env.ok foo == $env || $env foo == $env.foo foo == $env?.Bar foo == $env?.Bar?.[i] foo == $env?.Bar?.[list] foo == $env?.String foo == $env?.String?.[array] foo == $env?.[Bar] foo == $env?.[String] foo == $env?.[String]?.[f64] foo == $env?.[foo?.Bar] foo == $env?.[foobar?.[foobar]] foo == $env?.[foobar?.greet] foo == $env?.[foobar] foo == $env?.[str] foo == $env?.foo foo == $env?.foobar foo == $env?.foobar?.array() foo == $env?.foobar?.ok foo == $env?.nil foo == $env?.not foo == 0 ?? foo?.String foo == 0 ?? i ?? $env foo == 1 ?? f64 foo == 1.0 ?? $env foo == 1.0 ?? false foo == 1.0 ?? foo == false foo == add ?? 0 foo == add ?? 1 foo == array ?? foo foo == f64 ?? str foo == false ?? 1.0 foo == false ?? i foo == foo foo == foo != ok foo == foo && 0 ?? true foo == foo == false foo == foo == ok foo == foo ? $env : $env foo == foo ?: f64 foo == foo ?: i foo == foo ?? 0 foo == foo ?? 1.0 foo == foo ?? greet foo == foo ?? ok foo == foo ?? str foo == foo or $env?.[greet] foo == foo or ok foo == foo || $env?.[array] foo == foo || false foo == foo || ok foo == i ?? add foo == last($env) foo == last(list) foo == list?.[i] foo == nil != $env foo == nil != nil foo == nil && $env or $env foo == nil && f64 >= 1.0 foo == nil && nil != foo foo == nil == $env foo == nil ? foo : i foo == nil ? true : i foo == nil ?: str foo == nil and ok foo == nil || false foo == ok ?? $env?.[foo] foo == ok ?? f64 foo == ok ?? foo foo == true ?? foo foo == true ?? str foo ?? !$env foo ?? !ok foo ?? $env ?? f64 foo ?? $env ?? foo foo ?? $env ?? list foo ?? $env ?? str foo ?? $env.add foo ?? $env.array foo ?? $env.f64 foo ?? $env.foo foo ?? $env.greet foo ?? $env.i foo ?? $env.list foo ?? $env.ok foo ?? $env.str foo ?? $env?.Bar foo ?? $env?.Bar() foo ?? $env?.Bar()?.list foo ?? $env?.Bar.Bar() foo ?? $env?.String foo ?? $env?.String() foo ?? $env?.[$env?.list()] foo ?? $env?.[$env][:Bar].list foo ?? $env?.[Bar] foo ?? $env?.[String] foo ?? $env?.[String].String foo ?? $env?.[add(ok)] foo ?? $env?.[add?.f64] foo ?? $env?.[add] foo ?? $env?.[add]?.ok foo ?? $env?.[array] foo ?? $env?.[array]?.[array] foo ?? $env?.[f64] foo ?? $env?.[f64]?.[i] foo ?? $env?.[f64]?.count(foobar)?.foobar?.i() foo ?? $env?.[f64]?.i() foo ?? $env?.[foo ?? nil] foo ?? $env?.[foo] foo ?? $env?.[foo]?.str foo ?? $env?.[foobar not contains ok] foo ?? $env?.[foobar | none(#)] foo ?? $env?.[foobar.str()] foo ?? $env?.[foobar?.i] foo ?? $env?.[foobar] foo ?? $env?.[foobar]?.array foo ?? $env?.[greet] foo ?? $env?.[i] foo ?? $env?.[i]?.ok() foo ?? $env?.[lastIndexOf(foo)] foo ?? $env?.[list] foo ?? $env?.[list].array(foobar) foo ?? $env?.[nil | sortBy(.Bar, foo)] foo ?? $env?.[nil] foo ?? $env?.[ok] foo ?? $env?.[ok]?.String foo ?? $env?.[one(f64, foo)] foo ?? $env?.[sort($env, list)] foo ?? $env?.[str] foo ?? $env?.[str]?.[str] foo ?? $env?.[str]?.array foo ?? $env?.[str]?.foo foo ?? $env?.add foo ?? $env?.array foo ?? $env?.f64 foo ?? $env?.foo foo ?? $env?.foobar foo ?? $env?.greet foo ?? $env?.groupBy(nil, str, nil)?.i foo ?? $env?.i foo ?? $env?.list foo ?? $env?.nil foo ?? $env?.nil?.[greet] foo ?? $env?.ok foo ?? $env?.str foo ?? $env[$env < ok:] foo ?? $env[:$env] foo ?? $env[:array] foo ?? $env[:false].array foo ?? $env[:foo] foo ?? $env[:foobar] foo ?? $env[:i] foo ?? $env[:list] foo ?? $env[Bar?.str(foobar):] foo ?? $env[add:] foo ?? $env[foo.greet(ok):add | find(0)] foo ?? $env[foobar - true:] foo ?? $env[foobar.ok(foo):foobar?.foo] foo ?? $env[foobar:] foo ?? $env[foobar:true] foo ?? $env[get(greet, foobar):] foo ?? $env[i || nil:i($env, 1.0)] foo ?? $env[sortBy(foo, .greet):] foo ?? -$env foo ?? -1 foo ?? -1.0 foo ?? -i foo ?? 1 ?? add foo ?? 1.0 ?? sortBy(array, 1) foo ?? [0] foo ?? [1] foo ?? [f64] foo ?? [foo, str] foo ?? [i] foo ?? [true, foo] foo ?? add foo ?? add ?? add foo ?? add ?? str foo ?? all($env, #) foo ?? all($env, #.Bar) foo ?? any($env, $env) foo ?? array foo ?? array ?? f64 foo ?? array ?? greet foo ?? array?.[i] foo ?? array[:0] foo ?? array[:] foo ?? array[:count($env)] foo ?? concat(list) foo ?? concat(map(list, str))?.[i] foo ?? count($env) foo ?? count(array) foo ?? count(list) foo ?? date(1) foo ?? date(array) foo ?? date(array, list, ok) foo ?? date(foo) foo ?? date(true) foo ?? duration(str) foo ?? f64 foo ?? f64 ?? add foo ?? false ?? list foo ?? false ?? nil foo ?? filter($env, #) foo ?? find($env, #.add) foo ?? findLastIndex($env, .add) foo ?? findLastIndex(list, $env) foo ?? float(1.0) foo ?? floor(0) foo ?? floor(i) foo ?? foo foo ?? foo ?? 1.0 foo ?? foo ?? add foo ?? foo ?? f64 foo ?? foo ?? foo foo ?? foo ?? greet foo ?? foo ?? i foo ?? foo ?? list foo ?? foo ?? str foo ?? foo.Bar foo ?? foo.String foo ?? foo.String() foo ?? foo?.Bar foo ?? foo?.String foo ?? foo?.String() foo ?? fromPairs($env) foo ?? greet foo ?? greet($env) foo ?? greet(str) foo ?? groupBy($env, #.add) foo ?? groupBy(array, i) foo ?? i foo ?? i ?? i foo ?? int(1) foo ?? list foo ?? list?.[1] foo ?? list?.[i] foo ?? lower($env) foo ?? map($env, i) foo ?? mean(array) foo ?? mean(i) foo ?? mean(list, str) foo ?? median($env .. $env) foo ?? median(0) foo ?? median(array) foo ?? median(f64) foo ?? min(array, 1.0) foo ?? nil ?? 1.0 foo ?? nil ?? add foo ?? nil ?? array foo ?? nil ?? str foo ?? not $env foo ?? not false foo ?? not ok foo ?? ok foo ?? ok ?? foo?.String foo ?? ok ?? i foo ?? reduce($env, #.i) foo ?? reduce($env, .array) foo ?? reverse(list) foo ?? sort($env) foo ?? sortBy(array, ok) foo ?? str foo ?? string($env) foo ?? string(add) foo ?? string(greet) foo ?? sum($env ?? foo).ok foo ?? sum($env).array foo ?? sum($env, true) foo ?? sum(list) foo ?? toJSON(1) foo ?? toJSON(array) foo ?? trimPrefix(str) foo ?? true ?? list foo ?? type(false) foo ?? uniq($env) foo ?? {foo: 0, foo: foo} foo ?? {foo: array} foo ?? {foo: f64} foo ?? {foo: foo} foo ?? {foo: ok} foo in $env and false foo in $env.list foo in $env?.Bar foo in $env?.Bar?.[add]?.[str] foo in $env?.String foo in $env?.String?.[greet] foo in $env?.String?.[i] foo in $env?.String?.[ok] foo in $env?.String?.add foo in $env?.String?.ok() foo in $env?.[Bar] foo in $env?.[Bar]?.[i] foo in $env?.[String] foo in $env?.[String]?.[array] foo in $env?.[String]?.[foo] foo in $env?.[String]?.i foo in $env?.[foobar?.foo] foo in $env?.[foobar] foo in $env?.[foobar]?.i foo in $env?.[foobar]?.list foo in $env?.foobar foo in $env?.foobar?.list() foo in $env?.list foo in $env?.true?.[greet] foo in [foo, 0] foo in [foo] foo in [list, 1] foo in [nil] foo in array ?? 0 foo in array ?? 1.0 != nil foo in array ?? f64 foo in flatten(array) foo in keys($env) foo in list foo in list != nil && $env foo in list != ok foo in list == $env?.ok foo in list ?? add foo in list ?? greet foo in list or $env foo in list || false foo in list[0:] foo in map(list, foo) foo in nil ?? list foo in toPairs($env) foo in uniq(list) foo in values($env) foo in {foo: 1.0}.f64 foo not in $env.list foo not in $env?.Bar foo not in $env?.String foo not in $env?.String?.[greet] foo not in $env?.[Bar] foo not in $env?.[Bar]?.String foo not in $env?.[String] foo not in $env?.[String]?.[list] foo not in $env?.[String]?.greet foo not in $env?.[foobar?.[add]] foo not in $env?.[foobar?.f64] foo not in $env?.[foobar?.foo] foo not in $env?.[foobar] foo not in $env?.[foobar]?.[greet] foo not in $env?.[nil | last(foobar)] foo not in $env?.[nil] foo not in $env?.foobar foo not in $env?.foobar?.greet(foobar) foo not in $env?.list foo not in $env?.nil?.[ok] foo not in [$env] foo not in [foo] foo not in [nil] foo not in array ?? foo foo not in find($env, false)?.[i] foo not in first($env) foo not in flatten(array) foo not in groupBy(list, #) foo not in keys($env) foo not in list foo not in list != false foo not in list && ok foo not in list ?? 1 foo not in list ?? foo foo not in list || ok foo not in toPairs($env) foo not in {foo: 1}?.array foo not in {foo: str}.str foo.Bar foo.Bar != $env == nil foo.Bar != foo?.Bar foo.Bar != str foo.Bar + str foo.Bar < foo.Bar foo.Bar < str foo.Bar <= str foo.Bar == $env ?? 0 foo.Bar == $env.str foo.Bar == $env?.Bar foo.Bar == foo?.Bar foo.Bar == str foo.Bar > foo.String() foo.Bar > str foo.Bar >= str foo.Bar >= string(foo) foo.Bar >= type(ok) foo.Bar ?? $env ?? true foo.Bar ?? $env?.Bar foo.Bar ?? $env?.f64 foo.Bar ?? add foo.Bar ?? array foo.Bar ?? foo foo.Bar ?? greet foo.Bar ?? i foo.Bar ?? list foo.Bar ?? round(f64) foo.Bar ?? str foo.Bar ?? {foo: foo} foo.Bar contains $env?.String foo.Bar contains $env?.[str] foo.Bar contains str foo.Bar endsWith $env?.Bar foo.Bar endsWith str foo.Bar in $env foo.Bar in $env?.String foo.Bar in foo foo.Bar matches foo.Bar foo.Bar matches greet(str) foo.Bar matches str foo.Bar not contains $env?.Bar foo.Bar not contains str foo.Bar not contains type(0) foo.Bar not endsWith str foo.Bar not endsWith type(list) foo.Bar not in foo foo.Bar not in foo == $env foo.Bar not in {foo: nil, foo: 1} foo.Bar not matches str foo.Bar not matches toJSON(i) foo.Bar not startsWith foo?.Bar foo.Bar not startsWith foo?.String() foo.Bar not startsWith str foo.Bar startsWith $env?.String?.f64() foo.Bar startsWith $env?.[Bar] foo.Bar startsWith str foo.Bar | greet() foo.Bar | hasPrefix(str) foo.Bar | indexOf(str) foo.Bar | lastIndexOf(str) foo.Bar | repeat(0) foo.Bar | split($env?.str) foo.Bar | trimSuffix(str) foo.Bar[:] foo.Bar[:i] foo.Bar[:int(1)] foo.Bar[i:] foo.String foo.String != $env?.foobar foo.String != ok ?? $env foo.String == $env?.[String] foo.String ?? $env?.[Bar] foo.String ?? $env?.array foo.String ?? $env?.list foo.String ?? add foo.String ?? array foo.String ?? ceil(f64) foo.String ?? first(list) foo.String ?? foo foo.String ?? greet foo.String ?? i foo.String ?? len(array) foo.String ?? ok foo.String ?? str foo.String() foo.String() != max(array) foo.String() != str foo.String() + str foo.String() < $env.str foo.String() < str foo.String() <= $env.str foo.String() <= str foo.String() <= type(0 != 1.0) foo.String() == str foo.String() > foo.Bar foo.String() > str foo.String() >= $env?.[str] foo.String() >= str foo.String() ?? $env.i foo.String() ?? add foo.String() ?? array foo.String() ?? f64 foo.String() ?? foo foo.String() ?? greet foo.String() ?? i foo.String() contains str foo.String() endsWith str foo.String() in $env?.[Bar] foo.String() in foo foo.String() matches str foo.String() not contains str foo.String() not in foo foo.String() not in foo == false foo.String() not startsWith str foo.String() startsWith str foo.String() | greet() foo.String() | lastIndexOf(str) foo.String() | trimPrefix(str) foo.String()[0 ?? 1.0:] foo.String()[:] foo.String()[i:] foo; $env?.foo foo; $env?.ok foo; $env?.str foo; 1.0; $env?.add foo; 1.0; $env?.ok foo; array foo; f64 foo; foo; nil != ok foo; foo?.Bar foo; greet foo; i foo; list foo; str foo?.Bar foo?.Bar != list ?? 0 foo?.Bar != nil == $env foo?.Bar != str foo?.Bar != type(f64) foo?.Bar + foo.Bar foo?.Bar + str foo?.Bar + string(foo) foo?.Bar + toJSON(1) foo?.Bar + type(i) foo?.Bar < $env?.str foo?.Bar < str foo?.Bar < string(0) foo?.Bar <= str foo?.Bar == $env.str foo?.Bar == foo?.Bar foo?.Bar == nil and false foo?.Bar == str foo?.Bar > str foo?.Bar > trimPrefix(str) foo?.Bar > type(false) foo?.Bar > type(list) foo?.Bar >= $env.str foo?.Bar >= str foo?.Bar >= toJSON(foo) foo?.Bar ?? !true foo?.Bar ?? $env?.[add].greet foo?.Bar ?? $env?.[str] foo?.Bar ?? $env[foobar:] foo?.Bar ?? add foo?.Bar ?? array foo?.Bar ?? f64 foo?.Bar ?? flatten(array) foo?.Bar ?? foo foo?.Bar ?? greet foo?.Bar ?? i foo?.Bar ?? list foo?.Bar ?? map($env, 0) foo?.Bar ?? ok foo?.Bar ?? str foo?.Bar ?? toJSON(f64) foo?.Bar contains $env?.Bar foo?.Bar contains $env?.[Bar] foo?.Bar contains str foo?.Bar contains str ?? list foo?.Bar endsWith $env?.String foo?.Bar endsWith first($env) foo?.Bar endsWith str foo?.Bar in $env?.[Bar] foo?.Bar in foo foo?.Bar in list?.[i] foo?.Bar in uniq(list) foo?.Bar in {foo: array} foo?.Bar in {foo: str} foo?.Bar matches $env.str foo?.Bar matches str foo?.Bar matches str and true foo?.Bar matches toJSON(array) foo?.Bar not contains str foo?.Bar not contains type(nil) foo?.Bar not endsWith $env?.[String] foo?.Bar not endsWith $env?.foobar foo?.Bar not endsWith str foo?.Bar not in $env foo?.Bar not in $env?.[Bar] foo?.Bar not in foo foo?.Bar not matches $env?.[foobar] foo?.Bar not matches $env?.[str] foo?.Bar not matches str foo?.Bar not startsWith $env.str foo?.Bar not startsWith $env?.Bar foo?.Bar not startsWith str foo?.Bar not startsWith toJSON(0) foo?.Bar not startsWith toJSON(nil) foo?.Bar not startsWith type(str) foo?.Bar startsWith $env?.[Bar] foo?.Bar startsWith str foo?.Bar | greet() foo?.Bar | hasSuffix(str) foo?.Bar | lastIndexOf(str) foo?.Bar | repeat(i) foo?.Bar | splitAfter(str) foo?.Bar[:] foo?.Bar[i:] foo?.String foo?.String != $env && $env foo?.String != $env?.[Bar] foo?.String != $env?.[str] foo?.String != nil && $env foo?.String == $env or $env foo?.String == $env?.[String] foo?.String == nil || true foo?.String ?? $env?.list foo?.String ?? -$env foo?.String ?? add foo?.String ?? array foo?.String ?? f64 foo?.String ?? findLast($env, #) foo?.String ?? foo foo?.String ?? greet foo?.String ?? groupBy($env, 0) foo?.String ?? i foo?.String ?? list foo?.String ?? ok foo?.String ?? str foo?.String ?? str ?? foo foo?.String ?? string(foo) foo?.String() foo?.String() != str foo?.String() + foo.String() foo?.String() < str foo?.String() == str foo?.String() > foo?.Bar foo?.String() > str foo?.String() >= str foo?.String() >= toJSON(f64) foo?.String() ?? foo foo?.String() ?? greet foo?.String() ?? keys($env) foo?.String() ?? list foo?.String() ?? reverse($env) foo?.String() ?? str foo?.String() contains str foo?.String() endsWith str foo?.String() in foo foo?.String() matches str foo?.String() not contains $env?.[str] foo?.String() not contains str foo?.String() not endsWith $env?.Bar foo?.String() not endsWith $env?.[foobar] foo?.String() not in foo foo?.String() not startsWith str foo?.String() not startsWith type(foo) foo?.String() | greet() foo?.String() | hasSuffix(str) foo?.String()[:] fromBase64(string(ok)) fromBase64(string(true)) fromBase64(toBase64(str)) fromBase64(toJSON(nil)) fromBase64(toJSON(ok)) fromBase64(toJSON(true)) fromBase64(type(add)) fromBase64(type(false)) fromBase64(type(greet)) fromBase64(type(ok)) fromBase64(type(true)) fromJSON(string(0)) fromJSON(string(1)) fromJSON(string(1.0)) fromJSON(string(f64)) fromJSON(string(false)) fromJSON(string(i)) fromJSON(string(ok)) fromJSON(string(true)) fromJSON(toJSON(0)) fromJSON(toJSON(1)) fromJSON(toJSON(1.0)) fromJSON(toJSON(array)) fromJSON(toJSON(f64)) fromJSON(toJSON(false)) fromJSON(toJSON(foo)) fromJSON(toJSON(foo)).add fromJSON(toJSON(i)) fromJSON(toJSON(list)) fromJSON(toJSON(nil)) fromJSON(toJSON(nil))?.[i].i() fromJSON(toJSON(ok)) fromJSON(toJSON(str)) fromJSON(toJSON(str)) contains str fromJSON(toJSON(true)) fromJSON(toJSON(type(ok))) fromPairs($env).true && false fromPairs([list]) fromPairs(array | take(0)) fromPairs(array[:0]) fromPairs(filter($env, false)) fromPairs(filter(list, false)) fromPairs(list[:0]) fromPairs(map($env, list)) fromPairs(sort($env)) fromPairs(take(array, 0)) fromPairs(toPairs($env)) fromPairs(toPairs($env)).ok fromPairs(toPairs($env))?.[f64] get($env, nil) != array get($env, nil) == add get($env, nil)?.String get($env, nil)?.[add] get($env, nil)?.[add].add get($env, nil)?.[array] get($env, nil)?.[f64] get($env, nil)?.[foo] get($env, nil)?.[i] get($env, nil)?.[ok] get($env, nil)?.[str] get($env, nil)?.add get($env, nil)?.array() get($env, nil)?.f64 get($env, nil)?.foo get($env, nil)?.foo(foobar) get($env, nil)?.greet().add get($env, nil)?.list() get($env, nil)?.ok get($env, nil)?.ok(foobar) get($env, nil)?.str() get($env, str) | reduce($env) get($env, str)?.[f64] get($env?.[Bar], foo) get($env?.[String], foo.String) get(0 ?? list, add) get(1.0 ?? $env, false ?? list) get(add ?? f64, add) get(add ?? str, i) get(array, $env.i) get(array, i) get(array, i) < i get(false ? false : add, foo) get(i ?? $env, foo ?? $env) get(if ok { i } else { array }, list) get(list ?? add, i) get(list, -0) get(list, 1)?.String get(list, i) get(list, i).String get(mean(array), foo.String) get(median(array), true && $env) get(str ?? $env, i) greet greet != $env != nil greet != $env && $env greet != $env == nil greet != $env ?: add greet != $env ?? array greet != $env ?? list greet != $env and $env greet != $env or sum(array, true) greet != $env || ok greet != $env || true greet != $env.greet greet != $env?.Bar greet != $env?.String greet != $env?.String?.add() greet != $env?.[Bar] greet != $env?.[String] greet != $env?.[String]?.[greet] greet != $env?.[foobar?.String($env)] greet != $env?.[foobar] greet != $env?.[str] greet != $env?.foobar greet != $env?.greet greet != $env?.true greet != 0 ?? 1.0 greet != 0 ?? greet greet != 1 ?? str greet != 1.0 ?? add greet != array ?? !true greet != array ?? ok greet != first($env) greet != foo ?? array greet != foo ?? f64 greet != foo ?? list greet != get($env, str) greet != greet greet != greet != nil greet != greet != ok greet != greet && true greet != greet ?: greet greet != greet or ok greet != greet || $env greet != greet || false greet != max($env) greet != nil == nil greet != nil ? foo : true greet != nil ?? $env greet != nil and $env greet != nil || $env?.[i] greet != ok ?? i greet != ok ?? str greet != reduce(array, $env, 0) greet != str ?? $env greet != {foo: nil}.Bar?.list greet != {foo: str}.foobar greet != {foo: true}?.list greet == $env && $env greet == $env ?? foo greet == $env ?? true greet == $env and false greet == $env or ok greet == $env.greet greet == $env?.Bar greet == $env?.Bar?.array() greet == $env?.String greet == $env?.[Bar] greet == $env?.[Bar]?.[foo] greet == $env?.[String] greet == $env?.[String]?.ok greet == $env?.[foobar] greet == $env?.[str] greet == $env?.foobar greet == $env?.foobar?.String greet == $env?.greet greet == 0 ?? f64 greet == 1.0 ?? array greet == 1.0 ?? i greet == add ?? f64 greet == array ?? add greet == foo ?? 1.0 greet == foo ?? true greet == greet greet == greet && $env greet == greet == ok greet == greet ? 1.0 : foo greet == greet and $env greet == min($env) greet == nil != nil greet == nil != ok greet == nil == true greet == nil or $env greet == nil or ok greet == nil || true greet == ok ?? 1.0 greet == str ?? greet greet == str ?? true greet ?? !$env greet ?? !false greet ?? !ok greet ?? !true greet ?? $env ?? f64 greet ?? $env ?? foo greet ?? $env ?? str greet ?? $env.add greet ?? $env.array greet ?? $env.f64 greet ?? $env.foo greet ?? $env.greet greet ?? $env.i greet ?? $env.list greet ?? $env.ok greet ?? $env.str greet ?? $env?.Bar greet ?? $env?.Bar() greet ?? $env?.Bar()?.i greet ?? $env?.Bar(foobar) greet ?? $env?.Bar.array greet ?? $env?.Bar?.foo greet ?? $env?.String greet ?? $env?.String() greet ?? $env?.String?.[array] greet ?? $env?.String?.[i] greet ?? $env?.String?.greet greet ?? $env?.[Bar] greet ?? $env?.[String not in foobar] greet ?? $env?.[String] greet ?? $env?.[add] greet ?? $env?.[add]?.[add] greet ?? $env?.[array] greet ?? $env?.[f64] greet ?? $env?.[foo.f64()].filter(get(foobar)) greet ?? $env?.[foo.f64] greet ?? $env?.[foo] greet ?? $env?.[foobar.f64] greet ?? $env?.[foobar] greet ?? $env?.[greet] greet ?? $env?.[i] greet ?? $env?.[list] greet ?? $env?.[ok()] greet ?? $env?.[ok] greet ?? $env?.[str] greet ?? $env?.[str]?.[add] greet ?? $env?.add greet ?? $env?.array greet ?? $env?.f64 greet ?? $env?.foo greet ?? $env?.foobar greet ?? $env?.greet greet ?? $env?.i greet ?? $env?.list greet ?? $env?.nil?.String greet ?? $env?.ok greet ?? $env?.str greet ?? $env[$env:] greet ?? $env[:bitor(f64)] greet ?? $env[:foobar?.[add]] greet ?? $env[:foobar] greet ?? $env[:foobar].i() greet ?? $env[Bar(list):count(foobar)] greet ?? $env[array():] greet ?? $env[foo ^ foo:] greet ?? $env[foobar < foo:] greet ?? $env[foobar?.list:String] greet ?? $env[list(0):foo[:$env]] greet ?? -$env greet ?? -0 greet ?? -i greet ?? 0 ?? 1 greet ?? 0 ?? str greet ?? [1] greet ?? [false] greet ?? [list] greet ?? [true] greet ?? abs($env) greet ?? abs(i) greet ?? add greet ?? array greet ?? array ?? add greet ?? array ?? true greet ?? array?.[i] greet ?? count($env) greet ?? date($env) greet ?? date(false) greet ?? date(foo) greet ?? f64 greet ?? f64 ?? foo greet ?? findLast($env, #.foo) greet ?? findLastIndex(list, ok) greet ?? flatten($env) greet ?? float(i) greet ?? foo greet ?? foo ?? $env greet ?? foo ?? array greet ?? foo ?? greet greet ?? foo ?? i greet ?? foo | get(array) greet ?? foo | get(foo) greet ?? foo.Bar greet ?? foo.String greet ?? foo.String() greet ?? foo?.Bar greet ?? foo?.String greet ?? foo?.String() greet ?? fromJSON($env) greet ?? fromPairs(list) greet ?? greet greet ?? greet ?? array greet ?? groupBy($env, add) greet ?? groupBy(list, $env) greet ?? groupBy(list, list) greet ?? i greet ?? i ?? foo greet ?? i ?? list greet ?? int(1.0) greet ?? int(f64) greet ?? keys($env) greet ?? list greet ?? list ?? 0 greet ?? list ?? array greet ?? list ?? str greet ?? list?.[i] greet ?? lower($env) greet ?? map($env, #.ok) greet ?? map(list, #index * 1.0) greet ?? map(list, #index) greet ?? max(1.0, $env) greet ?? mean(1.0) greet ?? median(0) greet ?? min($env) greet ?? min(1.0) greet ?? min(i) greet ?? nil ?? 1.0 greet ?? nil ?? add greet ?? not false greet ?? not true greet ?? ok greet ?? one($env, .str) greet ?? reduce($env, true) greet ?? round(i) greet ?? sortBy(list, #) greet ?? str greet ?? str[:$env] greet ?? string($env) greet ?? string(array) greet ?? string(nil) greet ?? sum($env) greet ?? sum($env, #.ok) greet ?? sum(array) greet ?? sum(list) greet ?? sum(list, $env) greet ?? toJSON(add) greet ?? toJSON(foo) greet ?? toJSON(list) greet ?? toPairs($env) greet ?? trimSuffix($env) greet ?? type(1.0) greet ?? type(add) greet ?? type(str) greet ?? type(true) greet ?? {foo: foo}.i() greet in $env?.Bar greet in $env?.String greet in $env?.[Bar] greet in $env?.[Bar] && ok greet in $env?.[String] greet in $env?.[foobar?.[f64]] greet in $env?.[foobar?.[i]] greet in $env?.[foobar] greet in $env?.foobar greet in $env?.foobar?.[foo] greet in $env?.nil greet in $env?.true greet in [$env, foo] greet in [nil] greet in array ?? foo greet in first($env) greet in flatten(list) greet in list ?? $env?.[array] greet in list ?? $env?.[i] greet in map($env, $env) greet in reverse(list) greet in sort($env) greet in toPairs($env) greet in uniq(list) greet not in $env and false greet not in $env?.Bar greet not in $env?.String greet not in $env?.String?.str greet not in $env?.[Bar] greet not in $env?.[Bar]?.list() greet not in $env?.[String] greet not in $env?.[foobar?.[add]] greet not in $env?.[foobar] greet not in $env?.foobar greet not in [foo, 1.0] greet not in array ?? add greet not in array ?? i greet not in first($env) greet not in flatten(array) greet not in flatten(list) greet not in last($env) greet not in list ?? str greet not in toPairs($env) greet not in {foo: foo}.list and ok greet($env) != $env or true greet($env.foo?.Bar) greet($env.greet(str)) greet($env.str) greet($env?.[foobar] ?? str) greet($env?.[str]) greet($env?.foo?.Bar) greet($env?.greet(str)) greet($env?.str) greet(false ? foo : str) greet(foo.Bar) greet(foo.String()) greet(foo?.Bar) greet(foo?.Bar) not endsWith str greet(foo?.Bar) | repeat(nil ?? i) greet(foo?.String()) greet(get($env, str)) greet(greet($env?.[str])) greet(greet(foo.String())) greet(greet(greet(str))) greet(greet(str ?? foo?.Bar)) greet(greet(str)) greet(greet(str[:i])) greet(greet(string($env))) greet(greet(string(0))) greet(greet(type($env))) greet(greet(type(add))) greet(greet(type(true))) greet(if false { 1.0 } else { str }) greet(if ok { str } else { nil }) greet(if true { str } else { $env }) greet(join($env | map(str))) greet(keys($env)?.[i]) greet(last(list).Bar) greet(let x = str; x) greet(list | reduce(#.Bar)) greet(list | reduce(str)) greet(list | reduce(str, str)) greet(list?.[i].Bar) greet(list?.[i].String()) greet(lower(greet(str))) greet(lower(str)) greet(min($env)?.str) greet(nil ?? str) greet(ok ? str : 1) greet(reduce(array, str)) greet(reduce(list, str)) greet(str + str) greet(str ?? $env) greet(str ?? 0) greet(str ?? 1) greet(str ?? 1.0) greet(str ?? add) greet(str ?? array) greet(str ?? f64) greet(str ?? false) greet(str ?? foo) greet(str ?? greet) greet(str ?? i) greet(str ?? list) greet(str ?? nil) greet(str ?? ok) greet(str ?? str) greet(str ?? true) greet(str | greet()) greet(str | repeat(0)) greet(str | trim(str)) greet(str | trimPrefix(str)) greet(str) greet(str) != $env && $env greet(str) != list ?? 0 greet(str) != str greet(str) + str greet(str) < lower(str) greet(str) < str greet(str) <= $env?.str greet(str) <= str greet(str) <= type(i) greet(str) == nil ? foo : nil greet(str) == str greet(str) > str greet(str) > type(0) greet(str) >= $env.str greet(str) >= foo?.String() greet(str) >= str greet(str) ?? [array] greet(str) ?? f64 greet(str) ?? list greet(str) ?? str greet(str) contains str greet(str) contains string(true) greet(str) endsWith $env?.[str] greet(str) endsWith str greet(str) in $env == $env greet(str) in foo greet(str) matches str greet(str) not contains str greet(str) not endsWith $env?.str greet(str) not endsWith string(foo) greet(str) not endsWith type(nil) greet(str) not in foo greet(str) not matches str greet(str) not startsWith $env?.Bar greet(str) not startsWith $env?.String greet(str) not startsWith foo.Bar greet(str) not startsWith str greet(str) startsWith foo.Bar greet(str) startsWith str greet(str) startsWith toJSON(1) greet(str) | greet() greet(str)[:] greet(str)[:i] greet(str)[i:] greet(str[0:]) greet(str[1:0]) greet(str[1:]) greet(str[:0]) greet(str[:1]) greet(str[:]) greet(str[:i]) greet(str[i:1]) greet(str[i:]) greet(str[i:i]) greet(string($env)) greet(string($env?.Bar)) greet(string($env?.i)) greet(string(0)) greet(string(1)) greet(string(1.0 * f64)) greet(string(1.0)) greet(string(abs(0))) greet(string(add)) greet(string(array | sortBy(str))) greet(string(array)) greet(string(f64)) greet(string(false)) greet(string(foo)) greet(string(greet)) greet(string(groupBy(list, ok))) greet(string(i)) greet(string(last(array))) greet(string(list)) greet(string(nil != add)) greet(string(nil)) greet(string(ok)) greet(string(str)) greet(string(true)) greet(toBase64(str)) greet(toJSON($env.array)) greet(toJSON($env.foo)) greet(toJSON(0)) greet(toJSON(1)) greet(toJSON(1.0 + 1.0)) greet(toJSON(1.0)) greet(toJSON(array | sum(#))) greet(toJSON(array)) greet(toJSON(f64)) greet(toJSON(false)) greet(toJSON(foo) | greet()) greet(toJSON(foo)) greet(toJSON(foo?.Bar)) greet(toJSON(i % i)) greet(toJSON(i)) greet(toJSON(list)) greet(toJSON(max(0))) greet(toJSON(nil)) greet(toJSON(ok)) greet(toJSON(str)) greet(toJSON(true)) greet(trim(str)) greet(trim(trimSuffix(str))) greet(trimPrefix(str ?? nil)) greet(trimPrefix(str)) greet(trimSuffix(foo.String())) greet(trimSuffix(str)) greet(trimSuffix(str, str)) greet(true ? str : add) greet(true ? str : i) greet(true ? str : nil) greet(true ? str : ok) greet(type($env != 1.0)) greet(type($env)) greet(type($env.ok)) greet(type($env?.foo)) greet(type(0)) greet(type(1)) greet(type(1.0)) greet(type([list])) greet(type([ok])) greet(type(add)) greet(type(array)) greet(type(f64)) greet(type(false)) greet(type(foo)) greet(type(foo.String)) greet(type(greet)) greet(type(i * f64)) greet(type(i)) greet(type(list)) greet(type(map(array, ok))) greet(type(nil == f64)) greet(type(nil)) greet(type(not ok)) greet(type(ok)) greet(type(str)) greet(type(true)) greet(upper(str)) greet; $env?.[Bar] greet; $env?.add greet; $env?.foobar greet; add greet; array greet; array | sum(0) greet; f64 greet; float(f64) greet; foo greet; foo; i greet; greet greet; i greet; ok greet; ok ?? i greet; {foo: nil} groupBy($env | map(false), i)?.ok groupBy($env | map(i), ok) groupBy($env.array, # >= #) groupBy($env.array, #) groupBy($env.array, -#)?.f64 groupBy($env.array, 0 * 1.0) groupBy($env.array, f64) groupBy($env.array, foo) groupBy($env.array, i / #) groupBy($env.list, #) groupBy($env.list, f64) groupBy($env.list, foo) groupBy($env.list, i) groupBy($env.list, nil != #.String) groupBy($env.list, not ok) groupBy($env.list, str) groupBy($env?.[str], #) groupBy($env?.[str], 1.0 <= i) groupBy($env?.[str], 1.0 > 1.0) groupBy($env?.[str], any($env, true)) groupBy($env?.[str], f64) groupBy($env?.[str], i) groupBy($env?.[str], mean(#)) groupBy($env?.[str], ok) groupBy($env?.[str], ok)?.add groupBy($env?.[str], str) groupBy($env?.array, #) groupBy($env?.array, #)?.[i] groupBy($env?.array, $env?.i) groupBy($env?.array, -#) groupBy($env?.array, 0 <= #) groupBy($env?.array, f64) groupBy($env?.array, foo)?.ok groupBy($env?.array, i) groupBy($env?.array, ok) groupBy($env?.array, str) groupBy($env?.list, #) groupBy($env?.list, #.Bar) groupBy($env?.list, $env?.i) groupBy($env?.list, 0 == $env) groupBy($env?.list, int(1.0)) groupBy($env?.list, ok) groupBy($env?.list, str) groupBy(1 .. 0, #) groupBy(1 .. 1, ok) groupBy([$env], .String startsWith .str) groupBy([$env], i) groupBy([0, 0], #) groupBy([0], #) groupBy([1.0], # / f64) groupBy([1.0], #) groupBy([1.0], foo) groupBy([1.0], ok) groupBy([1], #) groupBy([1], i) groupBy([f64], ok) groupBy([f64], str) groupBy([false, str], ok) groupBy([false], #) groupBy([foo], .Bar not matches #.Bar) groupBy([foo], 0 >= i) groupBy([foo], foo)?.[ok] groupBy([foo], i) groupBy([greet], i) groupBy([i], foo) groupBy([list], abs(1.0)) groupBy([ok], #) groupBy([str], str) groupBy(array ?? $env, foo) groupBy(array ?? add, 1.0 ?? foo) groupBy(array ?? array, foo) groupBy(array ?? foo, str == #) groupBy(array ?? greet, #) groupBy(array ?? greet, ok) groupBy(array | filter(false), greet) groupBy(array | map(#), ok) groupBy(array | map($env), #.ok) groupBy(array | map(0), str) groupBy(array | map(1), #) groupBy(array | sortBy(#), 1 + #) groupBy(array | sortBy(1.0), #) groupBy(array, !false) groupBy(array, # != 1.0) groupBy(array, # % #) groupBy(array, # % #)?.[str] groupBy(array, # * i) groupBy(array, # ** 0) groupBy(array, # + #) groupBy(array, # - 1.0) groupBy(array, # / #) groupBy(array, # < 1) groupBy(array, # <= f64) groupBy(array, # == #) groupBy(array, # > #) groupBy(array, # >= #).String groupBy(array, # >= 0) groupBy(array, # >= f64) groupBy(array, # ?? 1.0) groupBy(array, # ?? array) groupBy(array, # ?? nil) groupBy(array, # ?? str) groupBy(array, # ^ #) groupBy(array, # ^ 1.0) groupBy(array, # | bitor(#)) groupBy(array, #) groupBy(array, #).Bar groupBy(array, #).String groupBy(array, #).add groupBy(array, #).array groupBy(array, #).f64 groupBy(array, #).foo groupBy(array, #).foobar groupBy(array, #).foobar | any(true) groupBy(array, #).greet groupBy(array, #).i groupBy(array, #).i | any(#.ok.array) groupBy(array, #).list groupBy(array, #).ok groupBy(array, #).str groupBy(array, #)?.Bar groupBy(array, #)?.String groupBy(array, #)?.[f64] groupBy(array, #)?.[foo] groupBy(array, #)?.[i] groupBy(array, #)?.[ok] groupBy(array, #)?.[str] groupBy(array, #)?.add groupBy(array, #)?.array groupBy(array, #)?.f64 groupBy(array, #)?.foo groupBy(array, #)?.foobar groupBy(array, #)?.greet groupBy(array, #)?.i groupBy(array, #)?.list groupBy(array, #)?.ok groupBy(array, #)?.str groupBy(array, $env != i)?.[ok] groupBy(array, $env == array).str groupBy(array, $env == foo) groupBy(array, $env | sum(1.0)) groupBy(array, $env.f64) groupBy(array, $env.foo) groupBy(array, $env.i) groupBy(array, $env.ok) groupBy(array, $env.str) groupBy(array, $env?.[String]) groupBy(array, $env?.[foobar]) groupBy(array, $env?.[str]) groupBy(array, $env?.f64) groupBy(array, $env?.i) groupBy(array, $env?.nil) groupBy(array, $env?.ok) groupBy(array, $env?.str) groupBy(array, -#) groupBy(array, -#)?.str groupBy(array, -0) groupBy(array, -1.0) groupBy(array, -i) groupBy(array, 0 + #) groupBy(array, 0 == 1.0) groupBy(array, 0) ?? foo groupBy(array, 0).Bar groupBy(array, 0).String groupBy(array, 0).add groupBy(array, 0).array groupBy(array, 0).foo groupBy(array, 0).foobar groupBy(array, 0).greet groupBy(array, 0).i groupBy(array, 0).list groupBy(array, 0).str groupBy(array, 0)?.Bar groupBy(array, 0)?.String groupBy(array, 0)?.[f64] groupBy(array, 0)?.[foo] groupBy(array, 0)?.[i] groupBy(array, 0)?.[str] groupBy(array, 0)?.add groupBy(array, 0)?.array groupBy(array, 0)?.f64 groupBy(array, 0)?.foo groupBy(array, 0)?.foobar groupBy(array, 0)?.greet groupBy(array, 0)?.i groupBy(array, 0)?.list groupBy(array, 0)?.str groupBy(array, 1 >= #) groupBy(array, 1).Bar groupBy(array, 1).String groupBy(array, 1).add groupBy(array, 1).array groupBy(array, 1).f64 groupBy(array, 1).foo groupBy(array, 1).greet groupBy(array, 1).i groupBy(array, 1).list groupBy(array, 1)?.Bar groupBy(array, 1)?.String groupBy(array, 1)?.[foo] groupBy(array, 1)?.[i] groupBy(array, 1)?.[ok] groupBy(array, 1)?.[str] groupBy(array, 1)?.add groupBy(array, 1)?.array groupBy(array, 1)?.f64 groupBy(array, 1)?.foo groupBy(array, 1)?.greet groupBy(array, 1)?.i groupBy(array, 1)?.list groupBy(array, 1)?.ok groupBy(array, 1)?.str groupBy(array, 1.0 != $env) groupBy(array, 1.0 != 1.0) groupBy(array, 1.0 ** #) groupBy(array, 1.0 - 1.0) groupBy(array, 1.0 < #) groupBy(array, 1.0 < 0)?.ok groupBy(array, 1.0 <= 0) groupBy(array, 1.0 <= f64) groupBy(array, 1.0 ?? str) groupBy(array, 1.0 ^ #) groupBy(array, 1.0) == $env?.Bar groupBy(array, 1.0).Bar groupBy(array, 1.0).add groupBy(array, 1.0).array groupBy(array, 1.0).f64 groupBy(array, 1.0).foo groupBy(array, 1.0).foobar groupBy(array, 1.0).greet groupBy(array, 1.0).i groupBy(array, 1.0).list groupBy(array, 1.0).ok groupBy(array, 1.0).ok?.[i] groupBy(array, 1.0).str groupBy(array, 1.0)?.Bar groupBy(array, 1.0)?.String groupBy(array, 1.0)?.[f64] groupBy(array, 1.0)?.[foo] groupBy(array, 1.0)?.[i] groupBy(array, 1.0)?.[ok] groupBy(array, 1.0)?.[str] groupBy(array, 1.0)?.add groupBy(array, 1.0)?.array groupBy(array, 1.0)?.f64 groupBy(array, 1.0)?.foo groupBy(array, 1.0)?.greet groupBy(array, 1.0)?.i groupBy(array, 1.0)?.list groupBy(array, 1.0)?.ok groupBy(array, 1.0)?.str groupBy(array, abs(#)) groupBy(array, array | sum(#)) groupBy(array, bitand(#, #)) groupBy(array, bitshr(#, 0)) groupBy(array, ceil(#)) groupBy(array, ceil(floor(1.0))) groupBy(array, f64 ** i) groupBy(array, f64 - 1) groupBy(array, f64 / #) groupBy(array, f64 < #) groupBy(array, f64 >= #) groupBy(array, f64 ?? #) groupBy(array, f64) groupBy(array, f64).Bar groupBy(array, f64).String groupBy(array, f64).add groupBy(array, f64).array groupBy(array, f64).f64 groupBy(array, f64).foo groupBy(array, f64).foobar groupBy(array, f64).greet groupBy(array, f64).i groupBy(array, f64).list groupBy(array, f64).ok groupBy(array, f64).str groupBy(array, f64)?.Bar groupBy(array, f64)?.String groupBy(array, f64)?.[f64] groupBy(array, f64)?.[foo] groupBy(array, f64)?.[i] groupBy(array, f64)?.[ok] groupBy(array, f64)?.[str] groupBy(array, f64)?.add groupBy(array, f64)?.array groupBy(array, f64)?.foo groupBy(array, f64)?.greet groupBy(array, f64)?.i groupBy(array, f64)?.list groupBy(array, f64)?.ok groupBy(array, f64)?.str groupBy(array, false and $env) groupBy(array, false or true) groupBy(array, false).Bar groupBy(array, false).String groupBy(array, false).add groupBy(array, false).f64 groupBy(array, false).foo groupBy(array, false).greet groupBy(array, false).i groupBy(array, false).list groupBy(array, false).ok groupBy(array, false).str groupBy(array, false)?.Bar groupBy(array, false)?.String groupBy(array, false)?.[f64] groupBy(array, false)?.[foo] groupBy(array, false)?.[i] groupBy(array, false)?.[ok] groupBy(array, false)?.[str] groupBy(array, false)?.add groupBy(array, false)?.array groupBy(array, false)?.f64 groupBy(array, false)?.foo groupBy(array, false)?.greet groupBy(array, false)?.i groupBy(array, false)?.list groupBy(array, false)?.ok groupBy(array, false)?.str groupBy(array, float(1.0)) groupBy(array, float(i)) groupBy(array, floor(#)) groupBy(array, foo == $env) groupBy(array, foo ?? #) groupBy(array, foo in list) groupBy(array, foo not in list) groupBy(array, foo) groupBy(array, foo) ?? ok groupBy(array, foo).Bar groupBy(array, foo).String groupBy(array, foo).add groupBy(array, foo).array groupBy(array, foo).f64 groupBy(array, foo).foo groupBy(array, foo).foobar groupBy(array, foo).foobar | groupBy(0) groupBy(array, foo).greet groupBy(array, foo).i groupBy(array, foo).list groupBy(array, foo).ok groupBy(array, foo).str groupBy(array, foo)?.Bar groupBy(array, foo)?.String groupBy(array, foo)?.[f64] groupBy(array, foo)?.[foo] groupBy(array, foo)?.[i] groupBy(array, foo)?.[ok] groupBy(array, foo)?.[str] groupBy(array, foo)?.add groupBy(array, foo)?.array groupBy(array, foo)?.f64 groupBy(array, foo)?.foo groupBy(array, foo)?.greet groupBy(array, foo)?.i groupBy(array, foo)?.list groupBy(array, foo)?.ok groupBy(array, foo)?.str groupBy(array, foo.Bar) groupBy(array, greet == $env) groupBy(array, greet(str)) groupBy(array, i - 1.0) groupBy(array, i / 1.0) groupBy(array, i > #) groupBy(array, i ^ #) groupBy(array, i | bitand(#))?.list groupBy(array, i) groupBy(array, i) ?? $env.f64 groupBy(array, i).Bar groupBy(array, i).add groupBy(array, i).array groupBy(array, i).f64 groupBy(array, i).foo groupBy(array, i).greet groupBy(array, i).i groupBy(array, i).ok groupBy(array, i).str groupBy(array, i)?.Bar groupBy(array, i)?.String groupBy(array, i)?.[f64] groupBy(array, i)?.[foo] groupBy(array, i)?.[ok] groupBy(array, i)?.[str] groupBy(array, i)?.add groupBy(array, i)?.array groupBy(array, i)?.f64 groupBy(array, i)?.foo groupBy(array, i)?.foobar groupBy(array, i)?.greet groupBy(array, i)?.i groupBy(array, i)?.list groupBy(array, i)?.ok groupBy(array, i)?.str groupBy(array, if true { nil } else { f64 }) groupBy(array, max(#)) groupBy(array, max(i)) groupBy(array, mean(1.0)) groupBy(array, nil == $env) groupBy(array, nil == 0) groupBy(array, not false) groupBy(array, not ok) groupBy(array, ok ?? #) groupBy(array, ok or true) groupBy(array, ok) groupBy(array, ok).Bar groupBy(array, ok).String groupBy(array, ok).add groupBy(array, ok).array groupBy(array, ok).f64 groupBy(array, ok).foo groupBy(array, ok).greet groupBy(array, ok).i groupBy(array, ok).list groupBy(array, ok).str groupBy(array, ok)?.Bar groupBy(array, ok)?.String groupBy(array, ok)?.[f64] groupBy(array, ok)?.[foo] groupBy(array, ok)?.[i] groupBy(array, ok)?.[ok] groupBy(array, ok)?.[str] groupBy(array, ok)?.add groupBy(array, ok)?.array groupBy(array, ok)?.foo groupBy(array, ok)?.list groupBy(array, ok)?.ok groupBy(array, ok)?.str groupBy(array, one(array, true)) groupBy(array, round(i)) groupBy(array, str endsWith str) groupBy(array, str) groupBy(array, str).Bar groupBy(array, str).String groupBy(array, str).add groupBy(array, str).array groupBy(array, str).foo groupBy(array, str).greet groupBy(array, str).i groupBy(array, str).list groupBy(array, str).ok groupBy(array, str).str groupBy(array, str)?.Bar groupBy(array, str)?.String groupBy(array, str)?.[f64] groupBy(array, str)?.[i] groupBy(array, str)?.[ok] groupBy(array, str)?.[str] groupBy(array, str)?.add groupBy(array, str)?.array groupBy(array, str)?.f64 groupBy(array, str)?.foo groupBy(array, str)?.greet groupBy(array, str)?.i groupBy(array, str)?.list groupBy(array, str)?.not groupBy(array, str)?.ok groupBy(array, str)?.str groupBy(array, sum(array)) groupBy(array, toJSON(array)) groupBy(array, toJSON(nil)) groupBy(array, toJSON(ok)) groupBy(array, true && true) groupBy(array, true || ok) groupBy(array, true).Bar groupBy(array, true).String groupBy(array, true).add groupBy(array, true).array groupBy(array, true).f64 groupBy(array, true).foo groupBy(array, true).greet groupBy(array, true).i groupBy(array, true).list groupBy(array, true).ok groupBy(array, true).str groupBy(array, true)?.Bar groupBy(array, true)?.[f64] groupBy(array, true)?.[foo] groupBy(array, true)?.[i] groupBy(array, true)?.[ok] groupBy(array, true)?.[str] groupBy(array, true)?.add groupBy(array, true)?.array groupBy(array, true)?.f64 groupBy(array, true)?.foo groupBy(array, true)?.i groupBy(array, true)?.list groupBy(array, true)?.ok groupBy(array, true)?.str groupBy(array, type(#)) groupBy(array, type(i)) groupBy(array, type(nil)) groupBy(concat(array), #) groupBy(concat(list), true ?? #).array groupBy(false ? nil : array, f64) groupBy(filter($env, false), .ok.greet()) groupBy(filter(array, false), #) groupBy(flatten(array), #) groupBy(flatten(list), #) groupBy(flatten(list), .Bar) groupBy(groupBy(array, ok).i, #?.[ok][.f64:]) groupBy(i..i, #) groupBy(if false { ok } else { list }, ok) groupBy(keys($env), #) groupBy(list | map(#), f64) groupBy(list | map(#), ok) groupBy(list | map(array), $env?.f64) groupBy(list | map(false), #) groupBy(list | map(list), ok) groupBy(list, # != foo) groupBy(list, # == #) groupBy(list, # ?? nil) groupBy(list, #) groupBy(list, #) ?? foo groupBy(list, #) ?? str groupBy(list, #).Bar groupBy(list, #).String groupBy(list, #).add groupBy(list, #).array groupBy(list, #).f64 groupBy(list, #).foo groupBy(list, #).foobar groupBy(list, #).greet groupBy(list, #).i groupBy(list, #).list groupBy(list, #).ok groupBy(list, #).str groupBy(list, #)?.Bar groupBy(list, #)?.String groupBy(list, #)?.[$env?.[str]] groupBy(list, #)?.[f64] groupBy(list, #)?.[foo] groupBy(list, #)?.[i] groupBy(list, #)?.[ok] groupBy(list, #)?.[str] groupBy(list, #)?.add groupBy(list, #)?.array groupBy(list, #)?.f64 groupBy(list, #)?.foo groupBy(list, #)?.greet groupBy(list, #)?.i groupBy(list, #)?.list groupBy(list, #)?.ok groupBy(list, #)?.str groupBy(list, #.Bar not in $env) groupBy(list, #.Bar) groupBy(list, #.Bar).Bar groupBy(list, #.Bar).array groupBy(list, #.Bar).f64 groupBy(list, #.Bar).foo groupBy(list, #.Bar).list groupBy(list, #.Bar).ok groupBy(list, #.Bar).str groupBy(list, #.Bar)?.String groupBy(list, #.Bar)?.[f64] groupBy(list, #.Bar)?.[ok] groupBy(list, #.Bar)?.add groupBy(list, #.Bar)?.array groupBy(list, #.Bar)?.f64 groupBy(list, #.Bar)?.foo groupBy(list, #.Bar)?.greet groupBy(list, #.Bar)?.i groupBy(list, #.Bar)?.list groupBy(list, #.Bar)?.ok groupBy(list, #.String == $env) groupBy(list, #?.Bar) groupBy(list, #?.Bar)?.[f64] groupBy(list, #?.String()) groupBy(list, $env != f64) groupBy(list, $env != greet) groupBy(list, $env != true) groupBy(list, $env == add) groupBy(list, $env == greet) groupBy(list, $env.f64) groupBy(list, $env.foo) groupBy(list, $env.i) groupBy(list, $env.str) groupBy(list, $env?.[String]) groupBy(list, $env?.[str]) groupBy(list, $env?.f64) groupBy(list, $env?.foo) groupBy(list, $env?.foobar) groupBy(list, $env?.nil) groupBy(list, $env?.str) groupBy(list, -i) groupBy(list, .Bar) groupBy(list, .Bar) ?? str groupBy(list, .Bar).Bar groupBy(list, .Bar).String groupBy(list, .Bar).add groupBy(list, .Bar).array groupBy(list, .Bar).f64 groupBy(list, .Bar).greet groupBy(list, .Bar).i groupBy(list, .Bar).list groupBy(list, .Bar)?.Bar groupBy(list, .Bar)?.[f64] groupBy(list, .Bar)?.[foo] groupBy(list, .Bar)?.[ok] groupBy(list, .Bar)?.[str] groupBy(list, .Bar)?.f64 groupBy(list, .Bar)?.greet groupBy(list, .Bar)?.i groupBy(list, .Bar)?.ok groupBy(list, .Bar)?.str groupBy(list, 0 + 1) groupBy(list, 0 == 1) groupBy(list, 0).Bar groupBy(list, 0).String groupBy(list, 0).f64 groupBy(list, 0).foo groupBy(list, 0).greet groupBy(list, 0).i groupBy(list, 0).list groupBy(list, 0).str groupBy(list, 0)?.Bar groupBy(list, 0)?.String groupBy(list, 0)?.[f64] groupBy(list, 0)?.[foo] groupBy(list, 0)?.[i] groupBy(list, 0)?.[str] groupBy(list, 0)?.add groupBy(list, 0)?.array groupBy(list, 0)?.f64 groupBy(list, 0)?.foo groupBy(list, 0)?.greet groupBy(list, 0)?.i groupBy(list, 0)?.list groupBy(list, 0)?.ok groupBy(list, 0)?.str groupBy(list, 0.1) groupBy(list, 1 * 0) groupBy(list, 1 * i) groupBy(list, 1 not in array) groupBy(list, 1).Bar groupBy(list, 1).String groupBy(list, 1).add groupBy(list, 1).array groupBy(list, 1).f64 groupBy(list, 1).foo groupBy(list, 1).foobar groupBy(list, 1).greet groupBy(list, 1).i groupBy(list, 1).str groupBy(list, 1)?.Bar groupBy(list, 1)?.String groupBy(list, 1)?.[f64] groupBy(list, 1)?.[foo] groupBy(list, 1)?.[ok] groupBy(list, 1)?.[str] groupBy(list, 1)?.add groupBy(list, 1)?.array groupBy(list, 1)?.f64 groupBy(list, 1)?.foo groupBy(list, 1)?.greet groupBy(list, 1)?.i groupBy(list, 1.0 > 1.0)?.[f64] groupBy(list, 1.0 >= f64) groupBy(list, 1.0 ?? foo) groupBy(list, 1.0 ^ 1.0) groupBy(list, 1.0) ?? list groupBy(list, 1.0) | get(1) groupBy(list, 1.0).String groupBy(list, 1.0).add groupBy(list, 1.0).array groupBy(list, 1.0).f64 groupBy(list, 1.0).foo groupBy(list, 1.0).foobar groupBy(list, 1.0).greet groupBy(list, 1.0).i groupBy(list, 1.0).list groupBy(list, 1.0).ok groupBy(list, 1.0).str groupBy(list, 1.0)?.Bar groupBy(list, 1.0)?.String groupBy(list, 1.0)?.[f64] groupBy(list, 1.0)?.[foo] groupBy(list, 1.0)?.[i] groupBy(list, 1.0)?.[ok] groupBy(list, 1.0)?.[str] groupBy(list, 1.0)?.add groupBy(list, 1.0)?.array groupBy(list, 1.0)?.f64 groupBy(list, 1.0)?.foo groupBy(list, 1.0)?.greet groupBy(list, 1.0)?.i groupBy(list, 1.0)?.list groupBy(list, 1.0)?.ok groupBy(list, 1.0)?.str groupBy(list, abs(1)) groupBy(list, add != add) groupBy(list, array | sum(1)) groupBy(list, bitor(i, i)) groupBy(list, ceil(0)) groupBy(list, f64 - 1.0) groupBy(list, f64) groupBy(list, f64).Bar groupBy(list, f64).String groupBy(list, f64).add groupBy(list, f64).array groupBy(list, f64).f64 groupBy(list, f64).foo groupBy(list, f64).greet groupBy(list, f64).i groupBy(list, f64).list groupBy(list, f64).ok groupBy(list, f64)?.Bar groupBy(list, f64)?.[f64] groupBy(list, f64)?.[foo] groupBy(list, f64)?.[i] groupBy(list, f64)?.[ok] groupBy(list, f64)?.[str] groupBy(list, f64)?.add groupBy(list, f64)?.array groupBy(list, f64)?.f64 groupBy(list, f64)?.foo groupBy(list, f64)?.greet groupBy(list, f64)?.i groupBy(list, f64)?.list groupBy(list, f64)?.ok groupBy(list, f64)?.str groupBy(list, false).Bar groupBy(list, false).String groupBy(list, false).add groupBy(list, false).array groupBy(list, false).f64 groupBy(list, false).foo groupBy(list, false).foobar groupBy(list, false).greet groupBy(list, false).i groupBy(list, false).list groupBy(list, false).str groupBy(list, false)?.String groupBy(list, false)?.[f64] groupBy(list, false)?.[i] groupBy(list, false)?.[i]?.[i] groupBy(list, false)?.[ok] groupBy(list, false)?.[str] groupBy(list, false)?.add groupBy(list, false)?.array groupBy(list, false)?.f64 groupBy(list, false)?.greet groupBy(list, false)?.i groupBy(list, false)?.list groupBy(list, false)?.ok groupBy(list, false)?.str groupBy(list, float(0)) groupBy(list, foo != foo) groupBy(list, foo != nil) groupBy(list, foo == #) groupBy(list, foo == foo) groupBy(list, foo ?? #) groupBy(list, foo) groupBy(list, foo).Bar groupBy(list, foo).String groupBy(list, foo).add groupBy(list, foo).array groupBy(list, foo).f64 groupBy(list, foo).foo groupBy(list, foo).foobar groupBy(list, foo).greet groupBy(list, foo).i groupBy(list, foo).list groupBy(list, foo).ok groupBy(list, foo).str groupBy(list, foo)?.Bar groupBy(list, foo)?.String groupBy(list, foo)?.[f64] groupBy(list, foo)?.[foo] groupBy(list, foo)?.[i] groupBy(list, foo)?.[ok] groupBy(list, foo)?.[str] groupBy(list, foo)?.add groupBy(list, foo)?.array groupBy(list, foo)?.f64 groupBy(list, foo)?.foo groupBy(list, foo)?.greet groupBy(list, foo)?.i groupBy(list, foo)?.list groupBy(list, foo)?.ok groupBy(list, foo)?.str groupBy(list, foo.Bar) groupBy(list, foo?.Bar) groupBy(list, foo?.String()) groupBy(list, greet(.Bar)) groupBy(list, i + i) groupBy(list, i == i) groupBy(list, i) groupBy(list, i).Bar groupBy(list, i).String groupBy(list, i).add groupBy(list, i).array groupBy(list, i).f64 groupBy(list, i).foo groupBy(list, i).i groupBy(list, i).list groupBy(list, i).ok groupBy(list, i).str groupBy(list, i)?.Bar groupBy(list, i)?.String groupBy(list, i)?.[f64] groupBy(list, i)?.[foo] groupBy(list, i)?.[i] groupBy(list, i)?.[ok] groupBy(list, i)?.[str] groupBy(list, i)?.add groupBy(list, i)?.array groupBy(list, i)?.f64 groupBy(list, i)?.foo groupBy(list, i)?.greet groupBy(list, i)?.i groupBy(list, i)?.list groupBy(list, i)?.ok groupBy(list, i)?.str groupBy(list, if false { # } else { #.Bar }) groupBy(list, if true { # } else { false }) groupBy(list, nil != 0) groupBy(list, nil == $env) groupBy(list, nil == 1.0) groupBy(list, nil == true) groupBy(list, nil ?? #) groupBy(list, none($env, true)) groupBy(list, ok and ok) groupBy(list, ok) groupBy(list, ok).String groupBy(list, ok).add groupBy(list, ok).array groupBy(list, ok).f64 groupBy(list, ok).foo groupBy(list, ok).i groupBy(list, ok).list groupBy(list, ok).ok groupBy(list, ok).ok?.[i] groupBy(list, ok).str groupBy(list, ok)?.Bar groupBy(list, ok)?.String groupBy(list, ok)?.[f64] groupBy(list, ok)?.[foo] groupBy(list, ok)?.[i] groupBy(list, ok)?.[ok] groupBy(list, ok)?.add groupBy(list, ok)?.f64 groupBy(list, ok)?.foo groupBy(list, ok)?.greet groupBy(list, ok)?.i groupBy(list, ok)?.list groupBy(list, ok)?.ok groupBy(list, ok)?.str groupBy(list, reduce(list, false)).ok groupBy(list, str == nil) groupBy(list, str ?? true) groupBy(list, str) groupBy(list, str).Bar groupBy(list, str).String groupBy(list, str).add groupBy(list, str).array groupBy(list, str).f64 groupBy(list, str).foo groupBy(list, str).greet groupBy(list, str).i groupBy(list, str).list groupBy(list, str).ok groupBy(list, str).str groupBy(list, str)?.Bar groupBy(list, str)?.String groupBy(list, str)?.[f64] groupBy(list, str)?.[foo] groupBy(list, str)?.[i] groupBy(list, str)?.[ok] groupBy(list, str)?.[str] groupBy(list, str)?.add groupBy(list, str)?.f64 groupBy(list, str)?.foo groupBy(list, str)?.foobar groupBy(list, str)?.greet groupBy(list, str)?.i groupBy(list, str)?.list groupBy(list, str)?.ok groupBy(list, string(#)) groupBy(list, string(add)).str groupBy(list, string(false)) groupBy(list, sum(array)) groupBy(list, toJSON(list)) groupBy(list, toJSON(ok)) groupBy(list, trimSuffix(str)) groupBy(list, true ?? str) groupBy(list, true).Bar groupBy(list, true).String groupBy(list, true).add groupBy(list, true).array groupBy(list, true).f64 groupBy(list, true).foo groupBy(list, true).greet groupBy(list, true).i groupBy(list, true).list groupBy(list, true).ok groupBy(list, true)?.Bar groupBy(list, true)?.String groupBy(list, true)?.[f64] groupBy(list, true)?.[i] groupBy(list, true)?.[ok] groupBy(list, true)?.[str] groupBy(list, true)?.add groupBy(list, true)?.array groupBy(list, true)?.f64 groupBy(list, true)?.greet groupBy(list, true)?.list groupBy(list, true)?.ok groupBy(list, true)?.str groupBy(list, type(0)) groupBy(list, type(1.0))?.i groupBy(list, type(foo)) groupBy(map($env, 1.0), f64) groupBy(map($env, 1.0), sum(array)) groupBy(map($env, foo), min(1.0)) groupBy(map(array, list), $env?.[str]) groupBy(map(list, #index), #) groupBy(reverse(array), # <= 1) groupBy(reverse(array), foo) groupBy(reverse(array), i + f64) groupBy(reverse(array), ok) groupBy(sort($env), # != .array) groupBy(sort($env), #.Bar) groupBy(sort($env), #.add not contains str) groupBy(sort($env), #.foo.str) groupBy(sort($env), #.greet) groupBy(sort($env), #.greet?.[i]) groupBy(sort($env), #.list.Bar(1.0)) groupBy(sort($env), 1.0 <= .array) groupBy(sort($env), 1.0 | min(#.f64, str)) groupBy(sort($env), i) groupBy(sort($env), max(#)) groupBy(sort(array), foo) groupBy(str ?? $env, toJSON(false)) groupBy(str ?? 1, foo) groupBy(str ?? add, str) groupBy(str ?? f64, # ^ #) groupBy(str ?? foo, str) groupBy(str ?? i, f64) groupBy(toPairs($env), 1 <= 1.0) groupBy(values($env), foo) groupBy(values($env), i) groupBy(values($env), str) hasPrefix(str, foo?.String()) hasPrefix(str, str) hasPrefix(str, string(i)) hasSuffix(foo.Bar, str) hasSuffix(foo.String(), str) hasSuffix(str, greet(str)) hasSuffix(str, str) hasSuffix(string(1), str) hasSuffix(string(nil), foo?.Bar) i i != $env != $env i != $env != true i != $env && false i != $env ?? 1.0 i != $env ?? f64 i != $env ?? str i != $env and false i != $env || $env i != $env.f64 i != $env.i i != $env?.$env?.list(add, nil) i != $env?.Bar i != $env?.Bar?.[f64] i != $env?.Bar?.[greet] i != $env?.String i != $env?.[Bar] i != $env?.[Bar]?.[i] i != $env?.[String] i != $env?.[String]?.[array] i != $env?.[foobar] i != $env?.[str] i != $env?.f64 i != $env?.foobar i != $env?.i i != $env?.true i != $env?.true?.str() i != -0 i != -1.0 i != -f64 i != 0 != $env i != 0 - 1.0 + 1.0 i != 0 == ok i != 0 == true != true i != 0 ?? i i != 0 ^ 0 i != 0 or $env i != 0 or ok i != 0 or true i != 0 || $env i != 1 && ok i != 1 / 1 i != 1 == nil i != 1 ?? list i != 1 ^ f64 i != 1 or ok i != 1.0 != $env i != 1.0 && str not endsWith str i != 1.0 * 1.0 i != 1.0 * array?.[i] i != 1.0 ** 0 i != 1.0 ** 1.0 i != 1.0 + 1.0 i != 1.0 + i i != 1.0 - 1.0 i != 1.0 == false i != 1.0 == nil i != 1.0 == ok i != 1.0 == true i != 1.0 ?: $env i != 1.0 ?? false i != 1.0 ?? nil i != 1.0 ^ i i != 1.0 and false i != 1.0 or $env i != 1.0 || $env i != abs(f64) i != abs(i) i != add ?? [foo] i != add ?? i i != array?.[i] i != f64 i != f64 && $env i != f64 && false i != f64 && true i != f64 + 1.0 i != f64 + f64 i != f64 ^ i i != f64 and $env i != false ?? list i != first($env) i != float(1.0) i != floor(0) i != floor(1) i != floor(1.0) i != floor(i) i != foo ?? greet i != foo ?? list i != i i != i != $env.ok i != i * f64 i != i ?: greet i != i ?? 1.0 i != i ^ 0 || true i != int(i) i != last($env) i != len($env) i != list ?? str i != max(1.0) i != mean(f64) i != median(1.0) i != min($env) i != min(0) i != min(i) i != nil != $env i != nil != false i != nil != ok i != nil && ok i != nil or ok i != sum(array) i != {foo: foo}.foo i % $env.i i % $env?.i i % -1 i % -i i % 1 != 1.0 i % 1 * f64 i % 1 - 1 i % 1 <= i i % 1 == i i % 1 > 0 i % add(i, i) i % array?.[i] i % i i % i != $env i % i - 1 i % i < i i % i <= 1 i % i <= 1.0 i % i == i ^ i i % i > 1.0 i % len(str) i % min(i) i % nil ?? i i % sum(array) i * $env or true i * $env || true i * $env.f64 i * $env.i i * $env?.f64 i * $env?.i i * - - f64 i * -1 i * -1.0 i * -i i * 0 != f64 i * 0 != nil i * 0 + i i * 0 - i i * 0 == i i * 0 ?? i i * 0 | min(array) i * 1 != 0 i * 1 != 1.0 i * 1 % i i * 1 - i i * 1 < f64 i * 1 | bitshl(i) i * 1.0 != 1.0 i * 1.0 != nil i * 1.0 * 1.0 i * 1.0 * f64 i * 1.0 * i i * 1.0 + 1.0 i * 1.0 + f64 i * 1.0 - i i * 1.0 < 1 i * 1.0 < i / 0 i * 1.0 <= 0 i * 1.0 <= 1.0 i * 1.0 == $env?.[String] i * 1.0 == 0 i * 1.0 ?? str i * 1.0 | min(i) i * abs(i) i * array?.[i] i * f64 i * f64 ** 1 i * f64 + f64 i * f64 / f64 i * f64 == i i * f64 ?? nil i * f64 ^ f64 i * f64 ^ i i * floor(0) i * floor(f64) i * i i * i != i i * i % i i * i ** 1.0 i * i / 1.0 i * i / i i * i <= i i * i == $env i * i == 0 i * i > i i * i ?? list i * i in array i * i | median(1) i * int(0) i * int(1.0) i * len(array) i * len(str) i * max(i) i * mean(array) i * mean(i) i * median(f64) i * median(i) i * min(0, f64) i * min(i) i * round(1.0) i * sum($env, 0) i * sum(array) i ** $env.f64 i ** $env.i i ** $env?.f64 i ** $env?.i i ** -0 i ** -1.0 i ** -f64 i ** -i i ** 0 != nil i ** 0 - abs(i) i ** 0 in array i ** 1 != $env i ** 1 + i i ** 1 <= 1 i ** 1 > 1.0 i ** 1 ?? true i ** 1 ^ 1.0 i ** 1.0 != i i ** 1.0 ** i i ** 1.0 + 1.0 i ** 1.0 - 1 i ** 1.0 - i i ** 1.0 / i i ** 1.0 == $env i ** 1.0 == nil i ** 1.0 >= f64 <= f64 i ** 1.0 ?? foo i ** 1.0 ?? list i ** 1.0 ^ 1 i ** 1.0 ^ i i ** 1.0 | max(1) i ** abs(1.0) i ** array?.[i] i ** bitshl(1, 0) i ** ceil(f64) i ** count($env, true) i ** f64 i ** f64 * 1.0 i ** f64 + 0 i ** f64 < 1 i ** f64 == nil i ** f64 ^ i i ** float(1.0) i ** float(i) i ** floor(f64) i ** i i ** i ** 1.0 i ** i + f64 i ** i / 1.0 i ** i < 1 i ** i == 1.0 i ** i > 0 i ** i >= i i ** i ^ 1 i ** i | max(array, i) i ** int(i) i ** len($env) i ** len(list) i ** max(0) i ** max(1) i ** mean(1, array) i ** min(0) i ** min(1) i ** min(1.0) i ** min(1.0, array) i ** min(array) i ** min(f64) i ** nil ?? 1 i ** sum($env, 1.0) i ** sum($env?.[str]) i ** sum(array) i + $env != str || true i + $env.f64 i + $env.i i + $env?.f64 i + $env?.i i + -1 i + -i i + 0 ** f64 i + 0 - 0 i + 0 - i i + 0 / 1 i + 0 <= 1.0 i + 0 ?? i i + 0 ?? ok i + 0 ?? true i + 1 != 1 i + 1 != 1.0 i + 1 - 1.0 i + 1 .. i i + 1 < 0 i + 1 ^ $env.f64 i + 1 in array i + 1 | min(1.0, 1.0) i + 1.0 != nil i + 1.0 * len(array) i + 1.0 ** f64 i + 1.0 - 1 i + 1.0 < f64 i + 1.0 < i i + 1.0 <= 1.0 i + 1.0 == f64 i + 1.0 > 1.0 i + 1.0 >= 1.0 && $env i + 1.0 ?? $env i + 1.0 ?? false i + 1.0 ?? nil i + abs(1) i + abs(1.0) i + abs(i) i + array?.[i] i + bitnot(0) i + ceil($env.i) i + ceil(0) i + f64 i + f64 != nil i + f64 ** i i + f64 <= i i + f64 > 1.0 i + f64 ?? nil < 1.0 i + first(array) i + float(1) i + float(1.0) i + floor(1.0) i + floor(i) i + i i + i ** f64 i + i .. i i + i / 0 i + i <= i i + i == $env i + i > 1.0 i + i > i <= 0 i + i | add(1) i + i | bitand(0) i + len($env) i + len(str) i + max(1) i + max(array) i + max(array, array) i + max(f64) i + max(i) i + mean(0) i + mean(1) i + mean(1.0) i + mean(i) i + reduce(list, 1.0) i + sum(array) i + sum(list, 0) i - $env and false and ok i - $env.f64 i - $env.i i - $env?.f64 i - $env?.i i - -0 i - -1.0 i - -f64 i - -i i - 0 != 1.0 i - 0 % i i - 0 * 1.0 i - 0 ** 1 i - 0 ** 1.0 i - 0 ** f64 i - 0 ** i i - 0 / 1.0 i - 0 == f64 i - 0 >= 0 i - 0 | mean(1.0) i - 1 ** 1.0 ^ 1 i - 1 / f64 i - 1 < i i - 1 ?? array i - 1 ?? nil i - 1 ^ f64 i - 1 in array i - 1.0 != $env?.String i - 1.0 != 1.0 i - 1.0 * 0 i - 1.0 ** 1.0 i - 1.0 ** i i - 1.0 + 1 i - 1.0 - 1.0 i - 1.0 < 0 i - 1.0 < f64 i - 1.0 <= 0 i - 1.0 <= f64 i - 1.0 == $env i - 1.0 == i i - 1.0 > f64 i - 1.0 >= 1 i - 1.0 >= f64 i - 1.0 ?? list i - 1.0 ^ i i - 1.0 ^ round(f64) i - 1.0 not in array i - 1.0 | min(1.0) i - array?.[0] i - array?.[i] i - ceil(0) i - ceil(1) i - ceil(1.0) i - f64 i - f64 != 1 i - f64 != 1.0 i - f64 - i i - f64 >= f64 i - f64 >= i i - f64 ^ 1.0 == 0 i - f64 in array i - float(f64) i - floor(1.0) i - floor(f64) i - floor(i) i - i i - i != 1.0 i - i != i i - i % i < 0 i - i ** i i - i + i i - i / i i - i < f64 i - i == 1.0 i - i > 0 i - i >= i i - i ?? $env i - i ?? array i - i ^ 1.0 i - i not in $env?.String i - i | min(array) i - i..i i - int(0) i - int(1.0) i - len(array) i - len(list) i - max(1.0) i - max(array) i - mean(1.0) i - median(array, 1) i - min(0) i - min(1) i - min(1.0) i - min(f64) i - min(i) i - nil ?? f64 i - reduce($env, #acc, i) i - reduce(array, #index) i - sum($env, f64) i .. $env.i i .. $env?.i i .. -i i .. 0 != $env i .. 0 * i i .. 0 == list i .. 0 ?? $env i .. 0 ?? list i .. 0 | all($env[.Bar:]) i .. 0 | count($env) i .. 0 | groupBy($env) i .. 0 | groupBy(greet) i .. 0 | map(#) i .. 0 | median(f64) i .. 0 | reduce(#, $env) i .. 0 | sum(1) i .. 0 | sum(foo) i .. 0 | sum(str) i .. 1 - i i .. 1 ?? f64 i .. 1 | filter(false) i .. 1 | groupBy(#) i .. 1 | groupBy(1.0) i .. 1 | map(#) i .. 1 | reduce(true) i .. 1 | sortBy(#) i .. 1 | sortBy(1) i .. 1 | sortBy(foo.Bar) i .. 1.0 ?? i i .. 1.0 ?? list i .. abs(i) i .. array?.[i] i .. bitnot(1) i .. f64 * 1.0 ?? 0 i .. f64 ?? array i .. f64 ?? true i .. i i .. i != nil i .. i % 1 i .. i ?? 1.0 i .. i | filter(ok) i .. i | groupBy(#) i .. i | map(#) i .. i | reduce(#) i .. i | reduce($env) i .. i | reduce(1.0) i .. i | reduce(false) i .. i | reduce(foo) i .. i | sortBy(1) i .. i | sortBy(false) i .. int(0) i .. len(array) i .. max(0) i .. max(i) i .. median(i) i .. min(1) i .. sum(array) i / $env.f64 i / $env.i i / $env?.f64 i / $env?.i i / -0 i / -1 i / -1.0 i / -f64 i / -i i / 0 + f64 == i i / 0 - f64 i / 0 < 1 i / 0 <= i i / 0 == 1.0 i / 0 not in array i / 1 != i i / 1 * i i / 1 ** f64 i / 1 + f64 i / 1 / 1 i / 1 ?? foo i / 1 not in array i / 1 | median(f64, 1.0) i / 1.0 != 1 i / 1.0 != 1.0 i / 1.0 * ceil(1.0) i / 1.0 ** i i / 1.0 + f64 i / 1.0 - 0 i / 1.0 - f64 i / 1.0 / i i / 1.0 < 0 i / 1.0 < i i / 1.0 <= 1.0 i / 1.0 > 1.0 i / 1.0 ?? 1 i / 1.0 ?? add i / 1.0 ?? foo i / 1.0 ?? greet i / 1.0 ?? list i / 1.0 ?? str i / 1.0 in array i / abs(1.0) i / array?.[i] i / bitnot(0) i / ceil(0) i / count(array, false) i / f64 i / f64 * 1.0 i / f64 / 1.0 i / f64 < 1.0 i / f64 == $env i / f64 > i i / f64 ?? 1 i / f64 ^ i i / f64 in list ?? str i / float(1) i / floor(1.0) i / i i / i ** f64 i / i + 1.0 i / i < 0 i / i < f64 ?? foo i / i <= 0 i / i == 1.0 i / i == i i / i == nil i / i ?? add i / i in array i / len($env) i / mean(1.0, 1.0) i / median(1) i / median(1.0) i / min(i) i / nil ?? i i / reduce(array, 0) i / sum(array) i / sum(list, f64) i < $env && false i < $env || true i < $env.f64 i < $env.i i < $env?.f64 i < $env?.i i < -0 i < -f64 i < -i i < 0 != ok i < 0 && false i < 0 / i i < 0 < i i < 0 <= f64 i < 0 > 0 i < 0 ?? $env?.[Bar] i < 0 and ok i < 0 || $env i < 1 != $env i < 1 ** i i < 1 + 1.0 i < 1 / 1.0 i < 1 < f64 i < 1 <= $env?.[foo] i < 1 <= 1 i < 1 <= sum($env, #) i < 1 ? array : add i < 1 ?? foo i < 1 ?? i i < 1 ?? nil i < 1 || $env i < 1.0 != nil i < 1.0 != ok i < 1.0 * f64 i < 1.0 ** 0 i < 1.0 / i i < 1.0 < $env?.f64 i < 1.0 < 0 i < 1.0 < 1.0 i < 1.0 < i i < 1.0 <= 1 i < 1.0 <= 1.0 i < 1.0 <= f64 i < 1.0 == $env i < 1.0 == nil i < 1.0 == true i < 1.0 > 1.0 i < 1.0 ?? 0 i < 1.0 ?? greet i < 1.0 || ok i < abs(1) i < abs(1.0) i < abs(i) i < array?.[i] i < bitnot(i) i < ceil(1.0) i < ceil(f64) i < f64 i < f64 != ok i < f64 != true i < f64 ** ceil(1.0) i < f64 + 1.0 i < f64 < 0 i < f64 < f64 < i i < f64 == $env i < f64 >= $env i < f64 ? 1 : foo i < f64 or $env i < f64 || true i < findIndex($env, ok) i < first(array) i < float(0) i < float(i) i < floor(0) i < floor(f64) i < i i < i + i i < i / 0 i < i <= i i < i == $env i < i >= i i < i ^ 0 i < i || $env i < int(0) i < len($env) i < max(array) i < max(f64) i < mean(0, array) i < min(1.0) i < reduce(array, 1.0) i < round(1.0) i < sum(array) i < sum(array, 1.0) i <= $env.f64 i <= $env.i i <= $env?.f64 i <= $env?.i i <= -0 i <= -1.0 i <= -f64 i <= 0 && $env i <= 0 * i i <= 0 + f64 i <= 0 < $env i <= 0 >= 0 i <= 0 >= f64 i <= 0 ?? 0 i <= 0 ?? nil i <= 0 and $env i <= 0 or false i <= 1 / 1 i <= 1 / 1.0 i <= 1 == nil i <= 1 >= 1 i <= 1 || ok i <= 1.0 && ok i <= 1.0 * i i <= 1.0 - 1.0 i <= 1.0 / f64 i <= 1.0 / i i <= 1.0 < 0 i <= 1.0 < f64 i <= 1.0 <= 1 i <= 1.0 == nil i <= 1.0 > 1.0 i <= 1.0 > i i <= 1.0 ?? greet i <= 1.0 ^ i i <= 1.0 or $env i <= 1.0 or ok i <= 1.0 || $env.ok i <= 1.0 || ok i <= abs(f64) i <= array?.[i] i <= bitnot(1) i <= ceil(1.0) i <= f64 i <= f64 * 1.0 i <= f64 < 1.0 i <= f64 > $env i <= f64 and false i <= f64 and true i <= f64 in $env?.String i <= f64 || $env i <= float(i) i <= floor(0) i <= floor(1) i <= floor(1.0) i <= i i <= i && true i <= i + i i <= i - 0 i <= i / 1 i <= i <= 1 i <= i == nil i <= i >= i i <= i ?: add i <= i ?? f64 i <= i ^ i i <= len(array) i <= max(1) i <= max(1.0) i <= max(array) i <= mean(1.0) i <= mean(i) i <= mean(i, i) i <= median(1.0) i <= median(array) i <= nil ?? 1.0 i <= round(0) i <= sum(array, #) i == $env != $env i == $env != ok i == $env && ok i == $env == $env i == $env ? array : array i == $env ?: 1.0 i == $env ?: f64 i == $env ?? 0 ?? array i == $env ?? array i == $env and $env?.[String] i == $env and nil == 1.0 i == $env || false i == $env.f64 i == $env.i i == $env?.Bar i == $env?.String i == $env?.String?.[f64]?.foo i == $env?.[Bar] i == $env?.[Bar]?.String() i == $env?.[Bar]?.add i == $env?.[String] i == $env?.[foobar] i == $env?.[str] i == $env?.f64 i == $env?.false?.[str] i == $env?.foobar i == $env?.i i == -0 ** 0 i == -1 i == -1.0 i == -i i == 0 != ok i == 0 ** i i == 0 + i i == 0 - 1.0 i == 0 - f64 && false i == 0 ?: $env i == 0 or $env i == 0 or ok i == 0 || $env i == 1 != false i == 1 && true i == 1 * 0 i == 1 ** 1.0 i == 1 - 1.0 i == 1 / f64 i == 1 / max(array) i == 1 == false i == 1 ?? 0 i == 1 ?? true i == 1 ^ i i == 1 and true i == 1 || ok i == 1.0 != $env i == 1.0 != ok ?: foo i == 1.0 != true i == 1.0 * 1.0 i == 1.0 ** 1.0 i == 1.0 + 1.0 i == 1.0 - 1 i == 1.0 == nil i == 1.0 == true i == 1.0 ?? 1.0 i == 1.0 ?? foo i == 1.0 ?? nil i == 1.0 ^ 1 i == 1.0 ^ 1.0 i == 1.0 || $env i == 1.0 || max($env) i == abs(f64) i == abs(i) i == add ?? ok i == array?.[i] i == bitnot(1) i == bitor(1, 0) i == ceil(1.0) i == count(list, false) i == f64 i == f64 != $env i == f64 && $env i == f64 * 0 i == f64 * 1 i == f64 * f64 i == f64 / f64 i == f64 ? f64 : foo i == f64 ?: array i == f64 ?? foo i == float(1.0) i == floor(1) i == floor(i) i == foo ?? 1 i == foo ?? ok i == i i == i + $env?.i i == i + 0 i == i + f64 i == i == $env i == i == nil i == i ?? 1.0 i == i ?? false i == i ^ 0 i == i ^ 1.0 i == i or $env i == int(1.0) i == int(i) i == len(array) i == len(list) i == len(str) i == list ?? 1 i == list ?? str i == max(array) i == max(i) i == mean(1.0) i == median(f64) i == min($env) i == min(f64) i == nil == $env i == nil ? $env?.[i] : list i == nil ?: foo i == nil ?? $env i == nil ?? 1 i == nil or false i == nil || $env i == ok ?? 0 i == round(1) i == round(f64) i == sum(array) i == sum(array, 1.0) i == true ?? add i > $env.f64 i > $env.i i > $env?.f64 i > $env?.i i > -1.0 i > 0 + 1 i > 0 + i i > 0 / f64 i > 0 <= 1.0 i > 0 == nil i > 0 > 1.0 i > 0 > f64 i > 0 ?: ok i > 0 and $env i > 0 or false i > 0.0 i > 1 && ok i > 1 * 0 i > 1 * f64 i > 1 - 0 i > 1 - 1.0 i > 1 < 1.0 i > 1 == ok i > 1 >= $env i > 1 >= $env[:0] i > 1 >= 0 i > 1 ?? 1.0 i > 1 or ok i > 1 || $env i > 1.0 i > 1.0 ** 0 i > 1.0 ** f64 i > 1.0 - $env?.i i > 1.0 - 1 i > 1.0 / 1 i > 1.0 / i i > 1.0 < $env i > 1.0 < $env == nil i > 1.0 < -$env i > 1.0 == $env i > 1.0 == ok i > 1.0 > $env i > 1.0 > 1.0 i > 1.0 >= 1.0 i > 1.0 ?: array i > 1.0 ?? f64 i > 1.0 ?? nil i > 1.0 or $env i > 1.0 or ok i > abs(i) i > array?.[i] i > ceil(1) i > ceil(1.0) i > f64 i > f64 != nil i > f64 != ok i > f64 && $env i > f64 ** i i > f64 + 1 i > f64 / 1.0 i > f64 <= i i > f64 >= 1 i > f64 >= 1.0 i > f64 ?? $env.foo i > f64 ?? i i > find(array, ok) i > float(0) i > floor(1) i > floor(1.0) i > get(array, 0) i > i i > i ** f64 i > i + 0 i > i - 1.0 i > i <= 1 i > i ?? greet i > i and $env i > last(array) i > len($env) i > max(1.0) i > max(i) i > mean(1.0) i > median(f64) i > min(0) i > min(i) i > round(-1.0) i > sum(array) i >= $env or true i >= $env || true i >= $env.f64 i >= $env.i i >= $env?.f64 i >= $env?.i i >= -1 i >= -f64 i >= -i i >= 0 != nil i >= 0 != ok i >= 0 - f64 i >= 0 - i i >= 0 / max(1.0) i >= 0 <= i i >= 0 >= 1 i >= 0 >= f64 i >= 0 >= i i >= 0 ^ 1 i >= 0 ^ f64 i >= 0 or $env i >= 0 || $env i >= 0.0 i >= 1 && ok i >= 1 ** f64 i >= 1 - 1.0 i >= 1 < f64 i >= 1 > 1.0 i >= 1 ?? $env?.[add] i >= 1 and $env i >= 1 and $env?.[str] i >= 1.0 != $env i >= 1.0 != nil i >= 1.0 && true i >= 1.0 * 0 i >= 1.0 ** i i >= 1.0 + 1.0 i >= 1.0 + i i >= 1.0 - sum($env, 0) i >= 1.0 ?? 1.0 i >= 1.0 ^ i i >= 1.0 and $env i >= 1.0 or $env i >= 1.0 or false i >= abs(1) i >= array?.[i] i >= ceil(0) i >= f64 i >= f64 != $env i >= f64 * 0 i >= f64 * 1 i >= f64 * 1.0 i >= f64 ** f64 i >= f64 ** i i >= f64 + 1 i >= f64 - 0 i >= f64 < i i >= f64 > 1.0 i >= f64 ?? foo i >= f64 ?? ok i >= f64 and $env i >= f64 || $env i >= float(1) i >= float(1.0) i >= float(f64) i >= floor(i) i >= i i >= i != $env i >= i != ok i >= i * 0 i >= i ** 0 i >= i - i i >= i / 1.0 i >= i ?? list i >= i ?? nil == nil i >= i || $env i >= i || false i >= int(1) i >= int(1.0) i >= last(array) i >= max(array) i >= mean(1.0) i >= mean(f64) i >= median(0) i >= median(1.0) i >= median(array) i >= min(1) i >= min(1.0) i >= min(array) i >= reduce($env, 0, 0) i >= round(f64) i >= round(i) i >= sum(array) i ?? !$env i ?? !ok i ?? !true i ?? $env.add i ?? $env.array i ?? $env.f64 i ?? $env.foo i ?? $env.greet i ?? $env.i i ?? $env.list i ?? $env.ok i ?? $env.str i ?? $env?.Bar i ?? $env?.Bar() i ?? $env?.String i ?? $env?.String() i ?? $env?.String(foobar, foobar startsWith foobar?.list) i ?? $env?.String?.[i] i ?? $env?.[Bar] i ?? $env?.[String] i ?? $env?.[add] i ?? $env?.[array] i ?? $env?.[f64] i ?? $env?.[f64].str i ?? $env?.[foo] i ?? $env?.[foobar and foobar] i ?? $env?.[foobar] i ?? $env?.[greet] i ?? $env?.[i.f64] i ?? $env?.[i] i ?? $env?.[i].Bar() i ?? $env?.[list | median(true)] i ?? $env?.[list] i ?? $env?.[list]?.[list] i ?? $env?.[list]?.str() i ?? $env?.[ok] i ?? $env?.[str] i ?? $env?.add i ?? $env?.array i ?? $env?.f64 i ?? $env?.foo i ?? $env?.foobar i ?? $env?.foobar?.[list] i ?? $env?.i i ?? $env?.list i ?? $env?.ok i ?? $env?.str i ?? $env?.true.foobar i ?? $env[$env.greet():] i ?? $env[:find(i, #acc)] i ?? $env[:foobar] i ?? $env[add:] i ?? $env[any(foo, i):] i ?? $env[f64?.String():] i ?? $env[false:foobar] i ?? $env[find(f64, 1.0):]?.[f64] i ?? $env[foo:foobar] i ?? $env[foobar:] i ?? $env[nil:1] i ?? -$env i ?? -0 i ?? -1.0 i ?? -abs($env?.String(foobar))?.ok i ?? -i i ?? 0 ?? foo i ?? 0 ?? nil i ?? 1.0 ?? $env.greet i ?? 1.0 ?? ok i ?? 1.0 ?? str i ?? 1.0 | bitand(0) i ?? 1.0 | max(0) i ?? [1.0] i ?? [false] i ?? [nil] i ?? [ok] i ?? abs($env - $env)?.[f64] i ?? abs($env) i ?? add i ?? add ?? 1 i ?? all($env, #.add) i ?? array i ?? array ?? ok i ?? array?.[i] i ?? bitand(i, $env) i ?? ceil(i) i ?? count(array) i ?? count(list) i ?? date(false) i ?? date(foo) i ?? date(foo, array) i ?? date(nil) i ?? date(true, true) i ?? f64 i ?? f64 ?? nil i ?? false ?? str i ?? findLast($env, .f64) i ?? findLastIndex($env, #) i ?? findLastIndex($env, $env) i ?? first($env) i ?? first(array) i ?? foo i ?? foo ?? foo i ?? foo | bitshl(0) i ?? foo | get(true) i ?? foo.Bar i ?? foo.String i ?? foo.String() i ?? foo?.Bar i ?? foo?.String i ?? foo?.String() i ?? fromBase64(str) i ?? fromJSON($env) i ?? fromPairs($env) i ?? greet i ?? greet ?? f64 i ?? greet($env - 1.0) i ?? greet($env) i ?? greet(str) i ?? groupBy($env, i) i ?? hasSuffix($env, $env) i ?? i i ?? i ?? add i ?? join($env) i ?? list i ?? list ?? f64 i ?? list ?? ok i ?? list?.[i] i ?? map($env, 0) i ?? map($env, 1) i ?? max($env) i ?? max(1.0) i ?? max(array) i ?? max(array)?.[f64] i ?? median(f64) i ?? median(list, list) i ?? min($env) i ?? nil ?? $env i ?? not $env i ?? not $env?.String(false) i ?? not $env?.[greet] i ?? not false i ?? not true i ?? ok i ?? ok ?? greet i ?? reduce(array, #acc) i ?? reduce(array, ok) i ?? round(0) i ?? sort(array) i ?? sortBy(list, #) i ?? str i ?? string(1) i ?? string(1.0) i ?? string(list) i ?? string(str) i ?? sum($env) i ?? sum($env, #.greet) i ?? sum($env, array) i ?? sum(array, #) i ?? sum(array, $env) i ?? sum(list) i ?? sum(list)?.String i ?? toBase64(str) i ?? toJSON(1.0) i ?? toJSON(ok) i ?? true ?? i i ?? true | get(0) i ?? type(greet) i ?? upper($env) i ?? {foo: 0} i ?? {foo: 1, foo: nil, foo: nil} i ?? {foo: 1.0} i ?? {foo: array} i ?? {foo: foo, foo: greet}.Bar i ?? {foo: foo} i ?? {foo: list} i ?? {foo: nil, foo: str} i ?? {foo: true} i ^ $env.f64 i ^ $env.i i ^ $env?.f64 i ^ $env?.i i ^ -1 i ^ -1.0 i ^ -f64 i ^ -i i ^ 0 != 1.0 i ^ 0 * abs(1) i ^ 0 + 1 i ^ 0 < 1.0 i ^ 0 < i i ^ 0 > f64 i ^ 0 not in array i ^ 1 != $env i ^ 1 - f64 i ^ 1 < i i ^ 1 == 0 i ^ 1 >= i i ^ 1 | median(1, i, 0) i ^ 1.-0 i ^ 1.0 != $env i ^ 1.0 != i i ^ 1.0 != nil i ^ 1.0 - 0 i ^ 1.0 - 1 i ^ 1.0 / i i ^ 1.0 < 1 i ^ 1.0 < 1.0 i ^ 1.0 < f64 i ^ 1.0 <= 0 i ^ 1.0 == 0 i ^ 1.0 > 0 i ^ 1.0 > 1.0 i ^ 1.0 > f64 i ^ 1.0 > i i ^ 1.0 > max(0) i ^ 1.0 ?? 1.0 i ^ 1.0 ?? add i ^ 1.0 | max(0) i ^ abs(0) i ^ array?.[i] i ^ bitnot(1) i ^ ceil(1) i ^ ceil(1.0) i ^ count($env, false) i ^ f64 i ^ f64 * 0 i ^ f64 ** f64 i ^ f64 + i i ^ f64 == $env i ^ f64 == 1 i ^ f64 == float(1.0) i ^ f64 >= 1 i ^ f64 ?? 1 i ^ f64 ^ 1.0 i ^ findIndex($env, true) i ^ findIndex(array, true) i ^ first(array) i ^ float(1.0) i ^ floor(1) i ^ floor(1.0) i ^ i i ^ i != f64 i ^ i * i i ^ i / f64 i ^ i < i i ^ i == nil i ^ i > f64 i ^ i >= i i ^ i ?? $env?.i i ^ i ?? array i ^ i ^ 0 ?? list i ^ i ^ 1.0 i ^ i in array i ^ i not in array i ^ int(1) i ^ int(1.0) i ^ int(i) i ^ len($env) i ^ max(array) i ^ mean(1.0) i ^ mean(array) i ^ mean(f64) i ^ median(1.0) i ^ min(0) i ^ min(1.0) i ^ min(i) i ^ sum(array) i in $env and false i in $env.array i in $env?.Bar i in $env?.Bar?.[list] i in $env?.String i in $env?.[Bar] i in $env?.[String] i in $env?.[String]?.foo i in $env?.[foobar?.[list]] i in $env?.array i in $env?.nil i in [0] i in array i in array != $env i in array ?? ok i in array and $env i in array and ok i in array or ok i in concat(array) i in concat(list, list) i in flatten(list) i in groupBy(list, #)?.i i in i .. 0 i in last($env) i in list ?? str i in map($env, f64) i in sort(array) i in toPairs($env) i in {foo: 1.0}.greet i in {foo: nil}?.greet i not in $env or true i not in $env.array i not in $env?.Bar i not in $env?.String i not in $env?.[Bar] i not in $env?.[Bar]?.array i not in $env?.[String] i not in $env?.[String]?.[list] i not in $env?.[String]?.str i not in $env?.[foobar] i not in $env?.array i not in $env?.foobar?.[i] i not in $env?.nil?.[add] i not in 1 .. i i not in [1.0] i not in [1] i not in [true, nil] i not in array i not in array == ok i not in array == true i not in concat(array) i not in flatten(array) i not in flatten(list) i not in groupBy(array, #) i not in groupBy(list, i) i not in last($env) i not in map(list, 1) i not in map(list, f64) i not in values($env) i | add(0) i | add(0) ?? foo i | add(1) i | add(i) i | bitand(0) i | bitand(1) i | bitand(1) + i i | bitand(i) i | bitnand(0) i | bitnand(1) i | bitnand(array?.[i]) i | bitnand(i) i | bitor(0) i | bitor(1 % 1) i | bitor(1) i | bitor(i) i | bitor(sum(array)) i | bitshl($env.i) i | bitshl(0) i | bitshl(1) i | bitshl(i) i | bitshl(sum(array)) i | bitshr(0) i | bitshr(0) != 1.0 || false i | bitshr(1) i | bitshr(i) i | bitushr(0) i | bitushr(1) i | bitushr(i) i | bitxor(0) i | bitxor(1) i | bitxor(i) i | max($env.i) i | max(0) i | max(0, 1.0) i | max(1) i | max(1.0) i | max(1.0, array) i | max(1.0, f64) i | max(array) i | max(array, 0) i | max(array, 1) i | max(f64) i | max(f64, 0) i | max(f64, f64) i | max(i) i | max(i, array) i | mean(0 / 1.0) i | mean(0) i | mean(0, array, 0) i | mean(1) i | mean(1, array) i | mean(1.0) i | mean(array) i | mean(f64 * 1) i | mean(f64) i | mean(f64, 1) i | mean(i) i | mean(i, f64) i | median(0) i | median(0, 0) i | median(0, 1.0) i | median(0, array, array) i | median(1) i | median(1) / f64 i | median(1, 1) i | median(1, f64) i | median(1.0) i | median(1.0, 0) i | median(1.0, 1) i | median(1.0, i) i | median(array) i | median(f64) i | median(i) i | median(i) != f64 i | median(i, 1.0) i | median(i, i) i | min(0) i | min(0) <= i i | min(0) | median(1.0) i | min(0, array) i | min(0, f64) i | min(1) i | min(1.0 ?? add) i | min(1.0) i | min(1.0, 0) i | min(array) i | min(array, f64) i | min(array, i, f64) i | min(f64) i | min(f64, 1) i | min(f64, array) i | min(i) i | min(i, 1) i | min(i, 1.0) i..array?.[i] i..i i..i - 0 i..i == $env i..i == nil i..i | map(#) i..i | map(ok) i..i | reduce(foo) i..i | sortBy(ok) i; 1.0; $env.foo i; add i; array i; ceil(1.0) i; f64 i; foo i; greet i; i i; i; greet(str) i; list i; str i; {foo: false} if $env != f64 { add } else { foo } if $env != foo { greet } else { str } if $env == 1.0 { list } else { add } if $env?.ok { foo?.String } else { greet } if $env?.ok { greet } else { foo } if 0 > 1 { list } else { false ? ok : ok } if 0 > f64 { f64 } else { array } if 1.0 != $env { ok } else { $env <= $env } if 1.0 >= 0 { foo } else { ok } if array == $env { i } else { median(0) } if f64 > 1.0 { array } else { round(1.0) } if f64 not in array { map(list, list) } else { add } if foo == foo { true != true } else { list | groupBy(1) } if i < 0 { str } else { str } if i > $env?.i { greet } else { list } if nil != nil { $env | bitshl(i) } else { 0 != $env } if nil != str { greet } else { array } if nil == nil { greet } else { array } if nil == ok { ok } else { greet } if nil not in list { array } else { f64 } if ok or false { str } else { greet } if ok { $env.foo } else { foo.Bar } if ok { 0 != i } else { ok } if ok { 1 > 1.0 } else { f64 } if ok { 1.0 ?? 0 } else { $env != $env } if ok { add } else { add } if ok { add } else { array } if ok { add } else { f64 } if ok { add } else { foo != $env } if ok { add } else { foo } if ok { add } else { greet } if ok { add } else { i } if ok { add } else { ok } if ok { array } else { foo } if ok { array } else { foo?.Bar } if ok { array } else { i } if ok { array } else { str } if ok { ceil(i) } else { list } if ok { f64 } else { array } if ok { f64 } else { f64 } if ok { f64 } else { findLastIndex($env, $env) } if ok { f64 } else { foo } if ok { f64 } else { list } if ok { f64 } else { ok } if ok { false && true } else { false == nil } if ok { foo } else { $env ?: f64 } if ok { foo } else { $env?.str } if ok { foo } else { f64 } if ok { foo } else { foo } if ok { foo } else { greet } if ok { foo } else { i } if ok { foo } else { ok } if ok { foo.Bar } else { 1 == 1.0 } if ok { greet } else { array } if ok { greet } else { f64 } if ok { greet } else { greet } if ok { greet } else { i } if ok { greet } else { str } if ok { i } else { $env | filter($env) } if ok { i } else { add } if ok { i } else { array } if ok { i } else { date($env) } if ok { i } else { str } if ok { i } else { type(nil) } if ok { list } else { i } if ok { list } else { nil == true } if ok { list } else { ok } if ok { list } else { str } if ok { nil == false } else { greet } if ok { ok } else { $env.add } if ok { ok } else { add } if ok { ok } else { array } if ok { ok } else { date(1.0) } if ok { ok } else { foo } if ok { ok } else { greet } if ok { ok } else { ok } if ok { str } else { array } if ok { str } else { foo } if ok { str } else { i } if ok { str } else { list } if ok { str } else { ok } if ok { str } else { str } if ok { type(f64) } else { foo } if str == $env { foo?.String() } else { $env.foo } if str > str { str } else { find(array, ok) } if true != true { i } else { array } if true && ok { array } else { greet } indexOf($env?.[str], str) indexOf($env?.str, $env?.str) indexOf(str, str) indexOf(toJSON(1.0), toJSON(true)) int($env | count(ok)) int($env | findIndex(ok)) int($env | findIndex(true)) int($env | findLastIndex(true)) int($env | reduce(1, f64)) int($env | sum(f64)) int($env | sum(i)) int($env.f64) int($env.i) int($env?.f64) int($env?.i) int(-$env?.i) int(-0) int(-1) int(-1.0) int(-f64) int(-i) int(0 % 1) int(0 % i) int(0 * 1) int(0 * 1.0) int(0 * f64) int(0 * i) int(0 ** 0) int(0 ** 1) int(0 ** 1.0) int(0 + 1) int(0 + 1.0) int(0 + f64) int(0 - $env.i) int(0 - 1.0) int(0 - f64) int(0 - i) int(0 / 0) int(0 / 1) int(0 / 1.0) int(0 / i) int(0 ?? 0) int(0 ?? 1) int(0 ?? 1.0) int(0 ?? array) int(0 ?? list) int(0 ?? true) int(0 ^ 0) int(0 ^ 1.0) int(0 ^ i) int(0 | bitshl(0)) int(0 | bitshr(i)) int(0 | bitxor(i)) int(0 | min(1.0, 1)) int(0) % count(array, true) int(0) * i int(0) + i int(0) - i int(0) .. i int(0) == i int(0) > 0 + i int(0) > 1.0 > 1 int(0) ^ i int(0) | bitshl(0) int(0) | mean(i) int(0) | median(array) int(0)..i int(0.0) int(1 % 1) int(1 * 0) int(1 * 1.0) int(1 * i) int(1 ** 1.0) int(1 ** f64) int(1 ** i) int(1 + f64) int(1 - 0) int(1 - 1) int(1 - 1.0) int(1 - f64) int(1 - i) int(1 / 1.0) int(1 / f64) int(1 ?? 1) int(1 ?? 1.0) int(1 ?? add) int(1 ?? false) int(1 ?? foo) int(1 ?? ok) int(1 ?? true) int(1 ^ 0) int(1 ^ 1.0) int(1 ^ f64) int(1 ^ i) int(1 | bitxor(i)) int(1 | max(i)) int(1 | median(f64)) int(1) != i int(1) * f64 int(1) - f64 int(1) <= f64 int(1) == f64 int(1) == i int(1) ?? add int(1) ?? str int(1) ^ f64 int(1) not in array int(1.0 * 1) int(1.0 * 1.0) int(1.0 * f64) int(1.0 ** 0) int(1.0 ** 1.0) int(1.0 ** f64) int(1.0 ** i) int(1.0 + 0) int(1.0 + 1) int(1.0 + 1.0) int(1.0 + f64) int(1.0 + i) int(1.0 - 0) int(1.0 - 1) int(1.0 - 1.0) int(1.0 - f64) int(1.0 / 0) int(1.0 / 1) int(1.0 / 1.0) int(1.0 / f64) int(1.0 / i) int(1.0 ?? $env) int(1.0 ?? 0) int(1.0 ?? 1.0) int(1.0 ?? add) int(1.0 ?? array) int(1.0 ?? f64) int(1.0 ?? foo) int(1.0 ?? foo?.Bar) int(1.0 ?? i) int(1.0 ?? list) int(1.0 ?? nil) int(1.0 ?? ok) int(1.0 ?? str) int(1.0 ?? true) int(1.0 ^ 0) int(1.0 ^ 1) int(1.0 ^ 1.0) int(1.0 ^ f64) int(1.0 ^ i) int(1.0 | median(1)) int(1.0 | min(f64)) int(1.0) int(1.0) != 1.0 ^ i int(1.0) != f64 int(1.0) != i int(1.0) * f64 int(1.0) * i int(1.0) ** f64 int(1.0) ** i int(1.0) + i / 1 int(1.0) .. i int(1.0) / i int(1.0) < f64 int(1.0) == f64 int(1.0) == i int(1.0) > 1 > 1.0 int(1.0) >= f64 int(1.0) ?? foo int(1.0) ?? greet int(1.0) ?? greet($env) int(1.0) in array int(1.0) | bitushr(i) int(1.0) | median(array) int(1.0)..i int(abs(0)) int(abs(1)) int(abs(1.0)) int(abs(f64)) int(abs(i)) int(array | count(false)) int(array | count(ok)) int(array | find(not false)) int(array | max(f64, array, 0)) int(array | median(f64, i)) int(array | min(1.0)) int(array | reduce(#)) int(array | reduce(#index)) int(array | reduce(0)) int(array | sum(#)) int(array | sum(0)) int(array?.[1]) int(array?.[i]) int(bitnot(0)) int(bitnot(1)) int(bitnot(i)) int(bitshr(0, i)) int(ceil($env?.i)) int(ceil(0)) int(ceil(1)) int(ceil(1.0)) int(ceil(f64)) int(ceil(i)) int(count($env, true)) int(count(list, false)) int(count(list, ok)) int(f64 * 0) int(f64 * 1) int(f64 * 1.0) int(f64 * f64) int(f64 ** 1) int(f64 ** i) int(f64 + 1.0) int(f64 + i) int(f64 - 0) int(f64 - 1) int(f64 - 1.0) int(f64 - f64) int(f64 - i) int(f64 / 0) int(f64 / 1) int(f64 / 1.0) int(f64 ?? $env) int(f64 ?? 0) int(f64 ?? 1.0) int(f64 ?? false) int(f64 ?? foo) int(f64 ?? i) int(f64 ^ 0) int(f64 ^ 1.0) int(f64 ^ f64) int(f64 ^ i) int(f64 | mean(i)) int(f64 | min(1.0)) int(f64) int(f64) != f64 int(f64) / i int(f64) <= ceil(1.0) int(f64) <= f64 int(f64) == i int(f64) in array int(f64) not in array ?? nil int(f64)..i int(false ?: 1.0) int(findIndex(array, true)) int(findIndex(list, ok)) int(findLast(array, true)) int(findLastIndex($env, ok)) int(findLastIndex(list, true)) int(first(array)) int(float(0)) int(float(1)) int(float(1.0)) int(float(f64)) int(float(i)) int(floor(1)) int(floor(1.0)) int(floor(f64)) int(floor(i)) int(i % i) int(i * i) int(i ** 1) int(i ** 1.0) int(i ** i) int(i + 0) int(i + 1) int(i + 1.0) int(i + f64) int(i - 1) int(i - 1.0) int(i - f64) int(i - i) int(i / 0) int(i / 1.0) int(i / i) int(i ?? 1.0) int(i ?? add) int(i ?? false) int(i ?? foo) int(i ?? i) int(i ?? nil) int(i ^ 1.0) int(i | bitxor(1)) int(i) int(i) != f64 int(i) * i int(i) ** f64 int(i) .. i int(i) < i int(i) == sum(array) int(i) ?? array int(i) ?? foo int(i) ?? foo ?? list int(i) | min(array) int(if ok { 1 } else { f64 }) int(if true { 1.0 } else { $env }) int(int(0)) int(int(1)) int(int(1.0)) int(int(f64)) int(int(i)) int(last(array)) int(len($env)) int(len(0 .. i)) int(len(array)) int(len(list)) int(len(str)) int(let foobar = 1.0; foobar) int(list | findLastIndex(ok)) int(list | reduce(#index)) int(list | reduce(0)) int(list | reduce(1, false)) int(list | reduce(1.0)) int(list | reduce(i)) int(list | sum(1)) int(list | sum(f64)) int(max(0)) int(max(1)) int(max(1.0)) int(max(array)) int(max(f64)) int(max(i)) int(mean(0)) int(mean(1)) int(mean(1.0)) int(mean(1.0, f64)) int(mean(array)) int(median(0)) int(median(1)) int(median(1.0)) int(median(array)) int(median(f64)) int(median(i)) int(min(0)) int(min(1)) int(min(1.0)) int(min(1.0, i)) int(min(array)) int(min(f64)) int(min(i)) int(min(i, array)) int(nil ?? 0) int(nil ?? 1.0) int(nil ?? i) int(ok ? 1.0 : greet) int(ok ? f64 : list) int(reduce($env, 1.0, i)) int(reduce(array, #)) int(reduce(array, f64)) int(reduce(list, 1.0)) int(round(1)) int(round(1.0)) int(round(f64)) int(round(i)) int(string(0)) int(string(1)) int(string(1.0)) int(string(i)) int(sum($env, 0)) int(sum($env, 1)) int(sum($env, i)) int(sum(array)) int(sum(array, #)) int(sum(array, f64)) int(toJSON(0)) int(toJSON(1)) int(toJSON(1.0)) int(toJSON(i)) int(toPairs($env) | reduce(i)) int(true ? 1 : array) int(true ? 1.0 : $env) int(true ? f64 : foo) int(true ? i : nil) join($env | filter(false)) join([str]) join(array | map(str)) join(keys($env)) join(list | map(str)) join(map(list, #.Bar)) join(sort($env)) keys($env ?? 0) keys($env ?? 1) keys($env ?? 1.0) keys($env ?? array) keys($env ?? f64) keys($env ?? false) keys($env ?? foo) keys($env ?? greet) keys($env ?? nil) keys($env ?? true) keys($env | reduce($env, add)) keys($env) != array keys($env) != foo ?? 1.0 keys($env) == foo ?? f64 keys($env) == list keys($env) == nil && true keys($env) | any(ok) keys($env) | count(ok) keys($env) | count(true) keys($env) | filter(true) keys($env) | find(false) keys($env) | findLast(true) keys($env) | findLastIndex(false) keys($env) | groupBy(#) keys($env) | groupBy($env?.i) keys($env) | groupBy(sum(#)) keys($env) | map(#) keys($env) | map(1) keys($env) | map(1.0) keys($env) | map(add) keys($env) | map(f64) keys($env) | map(greet) keys($env) | map(str) keys($env) | none(false) keys($env) | one(false) keys($env) | one(ok) keys($env) | one(true) keys($env) | reduce(#) keys($env) | reduce(#index) keys($env) | reduce($env) keys($env) | reduce(1.0) keys($env) | reduce(f64, ok) keys($env) | reduce(greet, $env) keys($env) | reduce(i) keys($env) | reduce(ok) keys($env) | sortBy(#) keys($env) | sortBy(str) keys($env)?.[i] keys(array | reduce($env)) keys(groupBy(array, #)) keys(groupBy(array, 1)) keys(groupBy(array, 1.0)) keys(groupBy(array, false)) keys(groupBy(array, foo)) keys(groupBy(list, #)) keys(groupBy(list, #.Bar)) keys(groupBy(list, foo)) keys(groupBy(list, ok)) keys(if true { $env } else { str }) keys(list | groupBy(#)) keys(list | groupBy(1)) keys(max($env)) keys(min($env)) keys(nil ?? $env) keys(reduce(list, $env)) keys({foo: $env}) keys({foo: 0}) keys({foo: 1, foo: 0}) keys({foo: 1, foo: false}) keys({foo: 1, foo: i}) keys({foo: 1.0}) keys({foo: 1}) keys({foo: add}) keys({foo: array, foo: i}) keys({foo: array}) keys({foo: f64}) keys({foo: false}) keys({foo: foo, foo: $env?.f64}) keys({foo: foo, foo: 0}) keys({foo: foo, foo: 1.0}) keys({foo: foo, foo: i}) keys({foo: foo}) keys({foo: greet, foo: $env}) keys({foo: greet}) keys({foo: i, foo: true}) keys({foo: i}) keys({foo: list}) keys({foo: nil, foo: 0}) keys({foo: nil}) keys({foo: ok, foo: str}) keys({foo: ok}) keys({foo: str, foo: $env}) keys({foo: str, foo: f64}) keys({foo: str, foo: nil}) keys({foo: str}) keys({foo: true, foo: $env}) keys({foo: true, foo: list}) keys({foo: true}) last($env ?? $env) last($env ?? $env.greet) last($env ?? 1) last($env ?? 1.0) last($env ?? false) last($env ?? foo) last($env ?? greet) last($env ?? i) last($env ?? nil) last($env ?? str) last($env | map(#index)) last($env | map(1)) last($env | map(add)) last($env | map(array)) last($env | map(f64)) last($env | map(foo)) last($env | map(greet)) last($env | map(ok)) last($env | reduce($env, add)) last($env) != array last($env) != list last($env) == i last($env) == ok last($env) contains foo.Bar last($env) contains str last($env) in array last($env) matches foo?.Bar last($env) not contains foo.Bar last($env) not in array last($env) not matches str last($env) not startsWith str last($env) startsWith str last($env)?.Bar last($env)?.Bar() last($env)?.Bar()?.[f64] last($env)?.Bar()?.foo last($env)?.Bar()?.str() last($env)?.Bar(foobar) last($env)?.Bar?.[array] last($env)?.Bar?.[i] last($env)?.Bar?.greet last($env)?.String last($env)?.String() last($env)?.String().add last($env)?.String()?.ok last($env)?.String(foobar) last($env)?.String(greet) last($env)?.String?.[add] last($env)?.String?.[array] last($env)?.[add] last($env)?.[add].Bar last($env)?.[add]?.String last($env)?.[array] last($env)?.[array].foo last($env)?.[array].i last($env)?.[f64] last($env)?.[f64] == i last($env)?.[f64].add() last($env)?.[f64]?.[list] last($env)?.[f64]?.f64(foobar, greet) last($env)?.[f64]?.foo() last($env)?.[foo] last($env)?.[foo].Bar last($env)?.[foo].list last($env)?.[foo]?.foo last($env)?.[greet] last($env)?.[greet]?.[i] last($env)?.[greet]?.[ok] last($env)?.[greet]?.list last($env)?.[i] last($env)?.[list] last($env)?.[list].greet last($env)?.[list].ok last($env)?.[ok] last($env)?.[ok] != i last($env)?.[ok].ok() last($env)?.[str] last($env)?.[str]?.[foo] last($env)?.[str]?.i last($env)?.[str]?.ok last($env)?.[{foo: add}] last($env)?.add last($env)?.add() last($env)?.add(f64) last($env)?.add(foobar) last($env)?.add.add() last($env)?.add.i last($env)?.add?.[ok] last($env)?.add?.f64 last($env)?.array last($env)?.array() last($env)?.array.list() last($env)?.array?.[add] last($env)?.array?.[greet] last($env)?.f64 last($env)?.f64($env?.[String]) last($env)?.f64() last($env)?.f64() == array last($env)?.f64(greet(foobar)) last($env)?.f64(list) last($env)?.f64?.[list] last($env)?.f64?.greet last($env)?.false != 0 last($env)?.findLast(foo, foobar) last($env)?.foo last($env)?.foo() last($env)?.foo()?.greet() last($env)?.foo(String, foobar?.greet) last($env)?.foo(add) last($env)?.foo.String last($env)?.foo?.[foo] last($env)?.foo?.[greet] last($env)?.foo?.array last($env)?.foobar last($env)?.foobar.str() last($env)?.foobar?.[str] last($env)?.foobar?.ok() last($env)?.fromPairs(foobar, foobar) last($env)?.greet last($env)?.greet() last($env)?.greet?.Bar last($env)?.greet?.[add] last($env)?.greet?.[foo].foo() last($env)?.greet?.array last($env)?.greet?.i last($env)?.i last($env)?.i() last($env)?.i(foobar endsWith add) last($env)?.i.Bar(foobar) last($env)?.i.foo last($env)?.i.foo(foobar, f64) last($env)?.i?.greet last($env)?.i?.i last($env)?.int(String) last($env)?.join(1.0) last($env)?.list last($env)?.list() last($env)?.list(foobar) last($env)?.list.array last($env)?.list?.[list] last($env)?.none(foobar)?.String() last($env)?.ok last($env)?.ok() last($env)?.ok?.add last($env)?.str last($env)?.str() last($env)?.str(foobar) last($env)?.str?.[list] last($env)?.str?.array?.[ok] last($env)?.str?.foo last($env)?.toJSON(str) last($env.array) last($env.list) last($env?.$env) last($env?.Bar) last($env?.Bar)?.[add] last($env?.Bar)?.[f64] last($env?.Bar)?.[ok] last($env?.Bar)?.add last($env?.Bar)?.add() last($env?.Bar?.String) last($env?.Bar?.[list]) last($env?.Bar?.[ok]) last($env?.String) last($env?.String)?.[ok] last($env?.String)?.greet() last($env?.String?.[add]) last($env?.String?.[f64]) last($env?.[Bar]) last($env?.[Bar])?.foo.add last($env?.[Bar]?.[foo]) last($env?.[Bar]?.[str]) last($env?.[Bar]?.array) last($env?.[String]) last($env?.[String])?.Bar last($env?.[String])?.[add] last($env?.[String])?.[foo] last($env?.[String]?.[foo]) last($env?.[String]?.ok) last($env?.[foobar]) last($env?.[foobar])?.String last($env?.[foobar])?.[f64] last($env?.[foobar])?.f64() last($env?.[foobar]?.str) last($env?.[nil]) last($env?.[str]) last($env?.array) last($env?.false) last($env?.false)?.[greet] last($env?.foobar) last($env?.foobar)?.ok last($env?.foobar?.[greet]) last($env?.list) last($env?.nil) last($env?.true) last(0 .. 0) last(0 .. 1) last(0 ?? 1.0) last(0 ?? false) last(0 ?? greet) last(0 ?? str) last(0 ?? true) last(0..i) last(1 .. 0) last(1 .. 1) last(1 .. i) last(1 ?? foo) last(1 ?? greet) last(1.0 ?? $env) last(1.0 ?? $env?.i) last(1.0 ?? 0) last(1.0 ?? array) last(1.0 ?? false) last(1.0 ?? foo) last(1.0 ?? greet) last(1.0 ?? true) last(1.0 | min(array)) last([$env, true]) last([$env.ok, array]) last([$env]) last([$env]).i last([0]) last([1, 0]) last([1, add]) last([1, nil]) last([1.0, str]) last([1.0]) last([1]) last([add, $env]) last([add, 1]) last([add]) last([array, 0]) last([array, false]) last([array]) last([f64]) last([false, 0]) last([false, foo]) last([false]) last([foo, $env]) last([foo, str]) last([foo]) last([greet, 1]) last([greet, false]) last([greet, nil]) last([greet]) last([i]) last([list]) last([nil]) last([ok]) last([str, $env]) last([str]) last([true, 1.0]) last(add ?? 1) last(add ?? 1.0) last(add ?? foo) last(add ?? foo)?.add last(add ?? true) last(array ?? 0) last(array ?? 1) last(array ?? array) last(array ?? greet) last(array ?? i) last(array ?? nil) last(array ?? str) last(array | map(#)) last(array | map(f64)) last(array | map(false)) last(array | map(foo)) last(array | map(list)) last(array | min(1.0)) last(array | reduce(#acc)) last(array | sortBy(1.0)) last(array) last(array) != i last(array) % i last(array) >= i last(array) ?? -0 last(array) ?? add last(array) in array != false last(array) | mean(1.0) last(array[:]) last(array[:i]) last(concat(array)) last(concat(list)) last(f64 ?? $env) last(f64 ?? add)?.f64() last(f64 ?? false) last(f64 ?? i) last(f64 ?? list) last(f64 ?? str) last(false ? $env : $env) last(false ? $env : greet) last(false ? add : greet) last(false ? false : 1) last(false ? foo : greet) last(false ?: $env) last(false ?: add) last(false ?? $env?.f64) last(false ?? 1.0) last(false ?? array)?.list() last(false ?? str) last(filter($env, false)) last(filter(array, true)) last(filter(list, false)) last(filter(list, true)) last(first($env)) last(first($env)?.[list]) last(first({foo: greet}?.list)) last(flatten(array)) last(flatten(list)) last(foo ?? $env) last(foo ?? $env.greet) last(foo ?? 0) last(foo ?? 1.0) last(foo ?? add) last(foo ?? add)?.[array] last(foo ?? array) last(foo ?? f64) last(foo ?? false) last(foo ?? greet) last(foo ?? i) last(foo ?? ok) last(foo ?? str) last(foo ?? true) last(greet ?? 1.0) last(greet ?? foo) last(greet ?? str) last(greet ?? true) last(groupBy(list, f64)?.[ok]) last(i ?? $env) last(i ?? foo) last(i ?? ok) last(if false { $env } else { i }) last(if false { nil } else { list }) last(if ok { $env } else { 1 }) last(if ok { false } else { $env }) last(if ok { foo } else { true }) last(if ok { list } else { $env }) last(if ok { list } else { true }) last(if true { $env } else { 1.0 }) last(if true { 1.0 } else { 1 }) last(if true { add } else { ok }) last(if true { list } else { array }) last(if true { ok } else { 1.0 }) last(keys($env)) last(keys($env)) | all(ok) last(last($env)) last(last($env)?.[list]) last(list ?? array) last(list ?? greet) last(list ?? true) last(list | map(#)) last(list | map(#.Bar)) last(list | map(foo)) last(list | map(greet)) last(list | map(list)) last(list | map(ok)) last(list | map(str)) last(list | reduce(array)) last(list | reduce(array, foo)) last(list | sortBy(0)) last(list) last(list) != $env != ok last(list) == foo last(list) ?? foo last(list) in list last(list).Bar last(list).String last(list).String() last(list)?.Bar last(list)?.String last(list)?.String() last(list[1:]) last(list[:1]) last(map($env, $env)) last(map($env, $env)).ok last(map($env, 1)) last(map($env, 1.0)) last(map($env, f64)) last(map($env, foo)) last(map($env, greet)) last(map($env, str)) last(map(array, #)) last(map(array, false)) last(map(array, foo)) last(map(array, true)) last(map(list, #)) last(map(list, 1)) last(map(list, 1.0)) last(map(list, array)) last(map(list, foo)) last(map(list, i)) last(max($env)) last(max($env?.Bar)) last(max(0, array)) last(max(array)) last(mean(array)) last(median(array)) last(median(i, array)) last(min($env)) last(min(array)) last(min(array, 1.0)) last(min(if true { $env } else { f64 })) last(nil ?? $env) last(nil ?? array) last(ok ? list : ok) last(ok ? true : list) last(ok ?? $env) last(ok ?? 1) last(ok ?? array) last(ok ?? foo) last(ok ?? i) last(ok ?? str) last(reduce(list, #acc)) last(reduce(list, $env)) last(reduce(list, list, foo)) last(reverse(array)) last(reverse(list)) last(sort($env)) last(sort(array)) last(sortBy(array, #)) last(sortBy(array, 0)) last(sortBy(array, f64)) last(sortBy(list, .Bar)) last(sortBy(list, 1.0)) last(sortBy(list, str)) last(str ?? 0) last(str ?? false) last(str ?? foo) last(str ?? i) last(toPairs($env)) last(true ? 1.0 : greet) last(true ? array : 0) last(true ? foo : array) last(true ? list : 1) last(true ? str : 1.0) last(true ? true : array) last(true ?: greet) last(true ?? 0) last(true ?? array) last(true ?? f64) last(true ?? foo) last(true ?? list) last(uniq(array)) last(uniq(list)) last(values($env)) last({foo: $env}.str) last({foo: $env}?.foobar?.add) last({foo: f64, foo: str}.foo) last({foo: foo, foo: 1}?.[str]) last({foo: foo}.greet) last({foo: ok, foo: foo}?.str) last({foo: str}?.f64) lastIndexOf(foo.Bar, str) lastIndexOf(foo?.Bar, str) lastIndexOf(str, false ? $env : str) lastIndexOf(str, str) lastIndexOf(str, str) ?? ok len($env ?? 0) len($env ?? 1) len($env ?? 1.0) len($env ?? add) len($env ?? false) len($env ?? foo) len($env ?? greet) len($env ?? list) len($env ?? nil) len($env ?? ok) len($env ?? str) len($env | filter(false)) len($env | filter(ok)) len($env | filter(true)) len($env | get(str)) len($env | map(0)) len($env | map(1.0)) len($env | map(false)) len($env | map(foo)) len($env | map(i)) len($env | map(true)) len($env | reduce(str, i)) len($env) != f64 len($env) * i len($env) ** int(f64) len($env) + i len($env) == $env || $env len($env) == add ?? false len($env) >= i len($env) ?? add len($env) ?? list len($env) ^ 1.0 < f64 len($env) ^ max(f64) len($env) ^ min(f64) len($env) not in array len($env) | bitand(1) len($env.array | groupBy(1)) len($env.array) len($env.list) len($env.str) len($env?.[str] | map(add)) len($env?.[str]) len($env?.array) len($env?.list) len($env?.str) len(0 .. 0) len(0 .. i) len(1 .. 0) len([$env, 1.0]) len([$env, add]) len([$env]) len([0, str]) len([0]) len([1.0, false, f64]) len([1.0]) len([1]) len([add, i]) len([add]) len([array, foo]) len([array]) len([f64, 0]) len([f64]) len([false]) len([foo, 1.0]) len([foo, 1]) len([foo, array]) len([foo, foo]) len([foo, i]) len([foo]) len([greet]) len([i, foo]) len([i]) len([list, f64]) len([list]) len([nil, 1]) len([nil, foo, add]) len([nil, nil]) len([nil]) len([ok, 1.0]) len([ok]) len([str, nil]) len([str]) len([true, list]) len([true]) len(array ?? 1) len(array ?? 1.0) len(array ?? array) len(array ?? greet) len(array ?? nil) len(array | filter(false)) len(array | groupBy(#)) len(array | groupBy(1)) len(array | groupBy(1.0)) len(array | groupBy(false)) len(array | groupBy(true)) len(array | map(#)) len(array | map(1.0)) len(array | map(array)) len(array | map(f64)) len(array | map(foo)) len(array | reduce($env)) len(array | reduce(array, 0)) len(array | sortBy(#)) len(array) len(array) % i len(array) * i len(array) - i len(array) .. i len(array) == nil && false len(array) > findIndex(list, true) len(array) | bitshr(1) len(array[0:]) len(array[1:]) len(array[:0]) len(array[:1]) len(array[:i]) len(concat(array)) len(concat(list)) len(false ? array : list) len(false ?: str) len(filter($env, ok)) len(flatten(array)) len(flatten(list)) len(flatten(map($env, $env))) len(foo.Bar) len(foo.String()) len(foo?.Bar) len(foo?.String()) len(greet(foo?.Bar)) len(greet(greet(str))) len(greet(str)) len(groupBy(array, 0)) len(groupBy(array, 1.0)) len(groupBy(array, f64)) len(groupBy(array, false)) len(groupBy(array, foo)) len(groupBy(array, i)) len(groupBy(array, true)) len(groupBy(list, #)) len(groupBy(list, .Bar)) len(groupBy(list, foo)) len(groupBy(list, str)) len(i .. 0) len(if true { str } else { nil }) len(keys($env)) len(let y = $env; y) len(list ?? $env) len(list ?? array) len(list ?? f64) len(list ?? foo) len(list ?? list) len(list ?? nil) len(list ?? ok) len(list ?? true) len(list | filter(false)) len(list | filter(true)) len(list | groupBy(#)) len(list | groupBy(foo)) len(list | groupBy(str)) len(list | map(#)) len(list | map(#.String)) len(list | map($env)) len(list | map(1)) len(list | map(1.0)) len(list | map(false)) len(list | map(foo)) len(list | map(list)) len(list | map(str)) len(list | reduce(#.Bar)) len(list | reduce(.Bar)) len(list) len(list) % i len(list) ** i len(list) < 1 and true len(list) < i len(list) <= i len(list) == f64 len(list) > i len(list) ^ f64 len(list) in $env?.array len(list)..i len(list[:0]) len(list[:1]) len(list[:]) len(lower(str)) len(map($env, #index)) len(map($env, 1)) len(map($env, 1.0)) len(map($env, add)) len(map($env, array)) len(map($env, f64)) len(map($env, foo)) len(map($env, greet)) len(map($env, i)) len(map($env, list)) len(map($env, str)) len(map(array, #)) len(map(array, $env)) len(map(array, 1)) len(map(array, foo)) len(map(array, list)) len(map(list, #)) len(map(list, #.String)) len(map(list, #index)) len(map(list, add)) len(map(list, f64)) len(map(list, true)) len(max($env)) len(min($env)) len(nil ?? array) len(nil ?? str) len(ok ? list : $env) len(reduce($env, $env, 1)) len(reduce($env, array, 0)) len(reduce(array, $env)) len(reduce(array, array)) len(reduce(list, $env, foo)) len(reduce(list, list)) len(reduce(list, str, f64)) len(reverse(array)) len(reverse(list)) len(sort($env)) len(sort(array)) len(sortBy(list, #.Bar)) len(sortBy(list, .Bar)) len(sortBy(list, 1)) len(sortBy(list, i)) len(sortBy(list, str)) len(str ?? $env) len(str ?? 1.0) len(str ?? greet) len(str ?? i) len(str ?? list) len(str ?? nil) len(str ?? ok) len(str ?? true) len(str | trimSuffix(str)) len(str) len(str) * i len(str) + 1.0 - i len(str) .. 0 | find($env) len(str) .. i len(str) / f64 ^ f64 len(str) <= i len(str) == i len(str) >= f64 len(str) ?? add len(str) ^ f64 len(str) | bitnand(1) len(str) | bitor(1) len(str) | mean(i) len(str) | median(1.0) len(str) | min(1.0) len(str[0:]) len(str[1:]) len(str[:1]) len(string($env)) len(string(0)) len(string(1)) len(string(1.0)) len(string(add)) len(string(array)) len(string(f64)) len(string(false)) len(string(foo)) len(string(greet)) len(string(i)) len(string(list)) len(string(nil)) len(string(ok)) len(string(str)) len(string(true)) len(toBase64(str)) len(toJSON($env.ok)) len(toJSON(0)) len(toJSON(1)) len(toJSON(1.0)) len(toJSON(array)) len(toJSON(f64)) len(toJSON(false)) len(toJSON(foo)) len(toJSON(i)) len(toJSON(list)) len(toJSON(nil)) len(toJSON(ok)) len(toJSON(str)) len(toJSON(true != false)) len(toJSON(true)) len(toPairs($env)) len(trim(str)) len(trimPrefix(str)) len(trimSuffix(str)) len(type($env)) len(type(0)) len(type(1)) len(type(1.0)) len(type(add)) len(type(array)) len(type(f64)) len(type(false)) len(type(foo)) len(type(greet)) len(type(i)) len(type(list)) len(type(nil)) len(type(ok)) len(type(str)) len(type(true)) len(uniq(array)) len(uniq(list)) len(upper(str)) len(values($env)) len({foo: $env ?? $env}) len({foo: $env, foo: $env}) len({foo: $env, foo: 0}) len({foo: $env, foo: 1.0}) len({foo: $env, foo: true}) len({foo: $env}) len({foo: 0, foo: nil}) len({foo: 0, foo: str, foo: str}) len({foo: 0}) len({foo: 1, foo: false}) len({foo: 1, foo: nil}) len({foo: 1.0, foo: f64}) len({foo: 1.0}) len({foo: 1}) len({foo: add}) len({foo: array, foo: 1.0}) len({foo: array, foo: greet}) len({foo: array, foo: str}) len({foo: array}) len({foo: f64}) len({foo: false}) len({foo: foo, foo: $env}) len({foo: foo, foo: 1.0}) len({foo: foo, foo: foo}) len({foo: foo, foo: nil}) len({foo: foo, foo: ok}) len({foo: foo}) len({foo: greet, foo: str}) len({foo: greet}) len({foo: i, foo: $env}) len({foo: i}) len({foo: list, foo: foo}) len({foo: list}) len({foo: nil, foo: 1.0}) len({foo: nil, foo: add}) len({foo: nil, foo: array}) len({foo: nil}) len({foo: ok, foo: $env}) len({foo: ok}) len({foo: str, foo: $env}) len({foo: str, foo: f64, foo: f64}) len({foo: str, foo: greet}) len({foo: str, foo: str}) len({foo: str}) len({foo: true}) let bar = $env == f64; bar let bar = $env.f64; bar let bar = $env.str; bar let bar = $env; bar.array let bar = $env; bar.foo let bar = $env?.list; bar let bar = 0 == $env; bar let bar = 1 == $env; bar let bar = [1.0]; bar let bar = add; bar let bar = array == list; bar let bar = array ?? foo; bar let bar = array; bar let bar = f64; bar let bar = f64; bar + f64 let bar = f64; let tmp = add; bar let bar = foo ?? f64; bar let bar = foo.Bar; bar let bar = foo.Bar; let x = add; bar let bar = foo.String(); bar let bar = foo; bar let bar = foo; bar.String let bar = greet ?? i; bar let bar = greet; bar let bar = i; bar let bar = i; let z = !ok; bar let bar = list; bar let bar = list; let foobar = greet; bar let bar = list[1:]; bar let bar = nil != add; bar let bar = ok == true; bar let bar = ok; bar let bar = str; bar let bar = str; let foobar = greet; bar let bar = string($env); bar let bar = type(f64); bar let foobar = $env not in array; foobar let foobar = $env.f64; i < foobar let foobar = $env.list; foobar let foobar = $env.str; foobar let foobar = $env; foobar == foobar let foobar = $env; foobar.Bar let foobar = $env; foobar.String let foobar = $env; foobar.add let foobar = $env; foobar.foo let foobar = $env; foobar.greet let foobar = $env; foobar.list let foobar = $env; foobar.ok let foobar = $env; foobar.str let foobar = $env; foobar?.[str] let foobar = $env; foobar?.add let foobar = $env; foobar?.foobar let foobar = $env; foobar?.greet let foobar = $env; foobar?.i let foobar = $env; foobar?.list let foobar = $env; foobar?.str let foobar = $env?.Bar; foobar let foobar = $env?.String; foobar let foobar = $env?.[Bar]; foobar?.list let foobar = $env?.[String]; foobar let foobar = $env?.[String]; foobar?.[str] let foobar = $env?.[str]; foobar let foobar = $env?.f64; foobar > foobar let foobar = $env?.true; foobar let foobar = 0 + f64; foobar let foobar = 0; foobar != foobar let foobar = 0; foobar <= foobar let foobar = 1 * 1.0; foobar let foobar = 1.0 != 1.0; foobar let foobar = 1.0; foobar * foobar let foobar = 1; foobar != f64 let foobar = 1; foobar % foobar let foobar = 1; foobar < float(foobar) let foobar = add; $env != foobar let foobar = add; foobar let foobar = array | sortBy(1.0); foobar let foobar = array; foobar let foobar = array; foobar?.[0] let foobar = array; foobar?.[i] let foobar = array; let bar = foobar; foobar let foobar = array?.[i]; f64 + foobar let foobar = f64 ?? nil; foobar let foobar = f64; foobar let foobar = f64; foobar ** f64 let foobar = f64; foobar + foobar let foobar = f64; foobar == foobar let foobar = false; foobar != foobar let foobar = false; foobar == $env and foobar let foobar = flatten(list); foobar let foobar = foo != nil; foobar || false let foobar = foo; foobar let foobar = foo; foobar.Bar let foobar = foo; foobar?.Bar let foobar = foo; foobar?.String let foobar = foo?.Bar; foobar let foobar = foo?.String; foobar let foobar = greet; foobar let foobar = greet; let z = foobar; foobar let foobar = greet; {foo: foobar} let foobar = i <= i; foobar let foobar = i; 1.0 == foobar let foobar = i; floor(foobar) + foobar let foobar = i; foobar let foobar = i; foobar != 0 let foobar = i; foobar % foobar let foobar = i; foobar ** foobar / foobar let foobar = i; foobar + foobar let foobar = i; foobar == f64 let foobar = i; foobar ^ foobar let foobar = i; {foo: foobar, foo: nil} let foobar = last(array); foobar let foobar = len(array); foobar let foobar = list; foobar let foobar = list; foobar != list let foobar = list; foobar?.[i] let foobar = list; reduce(foobar, foobar, $env) let foobar = map($env, 1); foobar let foobar = nil != nil; foobar let foobar = not true; foobar let foobar = ok ? nil : $env; foobar?.Bar let foobar = ok; foobar let foobar = ok; foobar == foobar let foobar = ok; let bar = foo; foobar let foobar = str != $env; foobar let foobar = str != nil; foobar let foobar = str; foobar let foobar = str; {foo: foobar} let foobar = sum(array); foobar let foobar = toPairs($env); foobar let foobar = trimSuffix(str); foobar let foobar = {foo: 0}; foobar.ok let foobar = {foo: nil}; foobar let tmp = $env.add; tmp let tmp = $env; tmp.greet let tmp = $env; tmp.str let tmp = $env?.array; tmp let tmp = 1.0 < 1; tmp let tmp = [$env]; tmp let tmp = add; tmp let tmp = array; tmp let tmp = f64 ?? $env; tmp let tmp = f64; tmp let tmp = foo; let y = foo; tmp let tmp = foo; tmp let tmp = greet; tmp let tmp = i; tmp let tmp = list; tmp let tmp = min(i, f64); tmp let tmp = ok; let y = foo; tmp let tmp = ok; tmp let tmp = str endsWith $env?.String; tmp let tmp = str; tmp let x = $env != true; x let x = $env; let tmp = 1.0; x?.ok let x = $env; x.add let x = $env; x.str let x = $env; x?.add let x = $env; x?.f64 let x = $env; x?.str let x = $env?.[foobar]; x let x = add; x let x = array; x let x = f64; x let x = foo.Bar; x let x = foo; x let x = foo; x.Bar let x = foo; x?.String let x = greet; x let x = i; let y = ok; x let x = i; x let x = list; let bar = foo; x let x = list; x let x = ok and $env; x let x = ok; x let x = str; x let x = trimSuffix(str); x let x = {foo: 1.0}; x let y = $env ?? $env; y let y = $env.array; y let y = $env; let tmp = i; y?.[str] let y = $env; y.greet let y = $env; y.list let y = $env; y?.String let y = $env; y?.add let y = $env; y?.greet let y = $env?.[String]; y let y = $env?.add; y let y = -1.0; y let y = 1.0 * i; y let y = add; y let y = array; y let y = concat(list); y let y = f64; y let y = false != ok; y let y = findLastIndex($env, true); y let y = foo.Bar; y let y = foo; y let y = foo?.String; y let y = greet; y let y = i; let bar = foo; y let y = i; y let y = list; y let y = nil ?? false; y let y = not false; y let y = ok; y let y = sort($env); y let y = str; y let z = $env != nil; z let z = $env == greet; z let z = $env.i; z let z = $env.ok; z let z = $env; z.Bar let z = $env; z.String let z = $env; z.array let z = $env; z.f64 let z = $env; z.greet let z = $env; z?.greet let z = $env?.ok; z let z = [foo]; z let z = add; z let z = array == list; z let z = array; z let z = array; z | groupBy(foo) let z = f64 != $env; z let z = f64; z let z = foo.String; z let z = foo; z let z = greet; z let z = i; z let z = list; let x = f64; z let z = list; z let z = map($env, add); z let z = ok or true; z let z = ok; z let z = str != $env; z let z = str; let tmp = array; z let z = str; z let z = {foo: ok, foo: nil}; z list list != $env != false list != $env != nil list != $env && ok list != $env ? list : i list != $env ?? $env?.add list != $env ?? 1 list != $env ?? f64 list != $env ?? i list != $env and ok list != $env or 1.0 > f64 list != $env or false list != $env or ok list != $env.array list != $env.list list != $env?.Bar list != $env?.String list != $env?.[Bar] list != $env?.[Bar]?.list list != $env?.[String] list != $env?.[foobar?.[foo]] list != $env?.[foobar] list != $env?.[str] list != $env?.array list != $env?.foobar list != $env?.list list != $env?.nil list != 0 ?? ok list != 1 ?? false list != 1..i list != 1.0 ?? add list != 1.0 ?? foo list != [0] list != [foo] list != [nil] list != [str] list != array list != array and ok list != array or $env list != array or false list != array || $env list != false ?? foo list != flatten(list) list != foo ?? f64 list != foo ?? ok list != foo ?? true list != greet ?? list list != i .. i list != i ?? foo list != keys($env) list != list list != list != ok list != list && $env list != list && true list != list == false list != list ?? 0 list != list ?? date(list) list != list ?? greet list != list and false list != list or false list != map(list, #) list != map(list, str) list != max($env) list != median(array) list != min(array) list != nil ? 1.0 : f64 list != nil ? ok : 1.0 list != nil ?: list list != nil ?? nil list != nil || false list != nil || true list != ok ?? 1.0 list != reverse($env.list) list != reverse(array) list != str ?? ok list != true ?? str list == $env == nil list == $env == ok list == $env == true list == $env ? foo : i list == $env ?: list == nil list == $env ?? 0 list == $env ?? f64 list == $env ?? i list == $env and false list == $env || $env list == $env.array list == $env.list list == $env?.$env list == $env?.Bar list == $env?.Bar?.add list == $env?.String list == $env?.[Bar] list == $env?.[String] list == $env?.[foobar?.list] list == $env?.[foobar?.str()] list == $env?.[foobar] list == $env?.[nil] list == $env?.[str] list == $env?.array list == $env?.foobar list == $env?.list list == 0 .. 1 list == 0 ?? foo list == 1 ?? add list == 1.0 ?? $env list == 1.0 ?? $env && $env list == 1.0 ?? greet list == 1.0 ?? str list == [$env] list == [0] list == [add] list == [false] list == [foo] list == [greet, 0] list == [greet] list == [list] list == [nil] list == [str] list == [true] list == add ?? array list == add ?? false list == array list == array == $env == true list == array == nil list == array ? nil : foo list == array ?: list list == array or ok list == array[:i] list == concat(array) list == f64 ?? $env ?? 1.0 list == false ?? greet list == flatten(array) list == foo ?? true list == i ?? f64 list == keys($env) list == list list == list != $env list == list != nil list == list == true list == list and true list == list[:i] list == map($env, str) list == map(list, $env) list == nil != false list == nil && false list == nil == nil list == nil ? add : $env list == nil ?: $env list == nil ?: nil list == nil or $env list == ok ?? greet list == ok ?? str list == reverse(array) list == str ?? array list == toPairs($env) list == values($env) list ?? !$env list ?? !false list ?? !true list ?? $env ?? $env list ?? $env ?? add list ?? $env ?? nil list ?? $env | count(ok) list ?? $env | filter(true) list ?? $env | findIndex(false) list ?? $env | findLast(false) list ?? $env | groupBy(1) list ?? $env | map(0) list ?? $env | reduce(#) list ?? $env | reduce($env) list ?? $env | reduce(.String) list ?? $env | reduce(ok) list ?? $env | sortBy(1) list ?? $env.add list ?? $env.array list ?? $env.f64 list ?? $env.foo list ?? $env.greet list ?? $env.i list ?? $env.list list ?? $env.ok list ?? $env.str list ?? $env?.Bar list ?? $env?.Bar() list ?? $env?.Bar()?.[list] list ?? $env?.String list ?? $env?.String() list ?? $env?.String(foobar)?.ok() list ?? $env?.String(ok | filter(String)) list ?? $env?.[$env] list ?? $env?.[Bar] list ?? $env?.[Bar].foo() list ?? $env?.[Bar]?.[array] list ?? $env?.[String] list ?? $env?.[add] list ?? $env?.[add].Bar list ?? $env?.[array] list ?? $env?.[f64] list ?? $env?.[f64]?.add() list ?? $env?.[foo] list ?? $env?.[foobar | keys(foobar)] list ?? $env?.[foobar] list ?? $env?.[greet] list ?? $env?.[i] list ?? $env?.[list] list ?? $env?.[list]?.[ok] list ?? $env?.[list]?.i()?.String list ?? $env?.[ok] list ?? $env?.[ok][add:foobar] list ?? $env?.[str] list ?? $env?.[true] list ?? $env?.add list ?? $env?.array list ?? $env?.f64 list ?? $env?.foo list ?? $env?.foobar list ?? $env?.greet list ?? $env?.i list ?? $env?.list list ?? $env?.nil list ?? $env?.ok list ?? $env?.str list ?? $env[:count(1.0)] list ?? $env[:foo.foo] list ?? $env[:str(nil)] list ?? $env[foobar:] list ?? -$env?.[nil] list ?? --1.0 list ?? -f64 list ?? 0 ?? $env list ?? 0 ?? array list ?? 0 | map(foo) list ?? 0 | none(true) list ?? 0 | sortBy(0) list ?? 0 | sortBy(str) list ?? 1 | groupBy(foo) list ?? 1 | map(1.0) list ?? 1.0 list ?? 1.0 ?? foo list ?? 1.0 | count(true) list ?? 1.0 | groupBy(0) list ?? 1.0 | groupBy(str) list ?? 1.0 | map(0) list ?? 1.0 | one(true) list ?? 1.0 | reduce(.Bar) list ?? [array] list ?? [list] list ?? [ok] list ?? [str] list ?? abs($env).greet list ?? add list ?? add | groupBy(#) list ?? add | groupBy(ok) list ?? add | reduce(1.0) list ?? add | sum(0) list ?? any($env, #) list ?? any($env, $env) list ?? array list ?? array ?? $env?.[greet] list ?? array | reduce($env) list ?? array?.[i] list ?? bitnot($env) list ?? bitshr($env, $env) list ?? ceil($env) list ?? count($env) list ?? count(array) list ?? count(foo ?? $env) list ?? date(greet) list ?? date(list) list ?? date(nil) list ?? f64 list ?? f64 ?? str list ?? f64 | count(true) list ?? f64 | groupBy(foo) list ?? f64 | map(#) list ?? f64 | map(ok) list ?? f64 | reduce(#, i) list ?? f64 | reduce(#acc, $env) list ?? false ?? greet list ?? false | filter(ok) list ?? false | find(true) list ?? false | map(1.0) list ?? false | map(false) list ?? false | map(foo) list ?? false | reduce(i) list ?? false | sortBy(1) list ?? filter(list, false) list ?? find($env, .add) list ?? find(array, ok) list ?? findIndex($env, .i) list ?? findLast($env, #) list ?? findLastIndex($env, #.ok) list ?? flatten($env) list ?? float(1.0) list ?? foo list ?? foo ?? foo list ?? foo ?? sortBy($env, 0) list ?? foo | all(false) list ?? foo | any(true) list ?? foo | findIndex(ok) list ?? foo | groupBy(i) list ?? foo | map(#) list ?? foo | map(#index) list ?? foo | map(ok) list ?? foo | reduce(#) list ?? foo | reduce(#) ?? foo list ?? foo | reduce($env) list ?? foo | reduce(1.0) list ?? foo | sum(0) list ?? foo | sum(1) list ?? foo.Bar list ?? foo.String list ?? foo.String() list ?? foo?.Bar list ?? foo?.String list ?? foo?.String() list ?? fromBase64($env) list ?? greet list ?? greet ?? list list ?? greet | all(false) list ?? greet | any(true) list ?? greet | findLastIndex(true) list ?? greet | map(#) list ?? greet | map(1) list ?? greet | reduce(foo, foo) list ?? greet | sum(1.0) list ?? greet($env) list ?? greet(str) list ?? i list ?? i | groupBy(1.0) list ?? i | groupBy(false) list ?? i | reduce($env) list ?? i | reduce(.Bar) list ?? int($env) list ?? len($env) list ?? list list ?? list | one(true) list ?? list | sum(1) list ?? map($env, $env) list ?? max($env) list ?? max(1, $env)?.list list ?? max(list) list ?? mean(1.0) list ?? mean(array) list ?? mean(i) list ?? median($env) list ?? min(f64) list ?? nil ?? str list ?? nil | all(true) list ?? nil | count(ok) list ?? nil | groupBy(#) list ?? nil | groupBy(1.0) list ?? nil | groupBy(foo) list ?? nil | map(#) list ?? nil | map(#index) list ?? nil | reduce(str) list ?? nil | reduce(true) list ?? nil | sortBy(f64) list ?? nil | sum(0) list ?? not $env list ?? not $env?.[array] list ?? not foo ?? str list ?? ok list ?? ok ?? 0 list ?? ok ?? false list ?? ok ?? i list ?? ok | all(true) list ?? ok | findLastIndex(ok) list ?? ok | map(#) list ?? ok | none(true) list ?? ok | reduce(list) list ?? ok | sortBy(str) list ?? ok | sum(i) list ?? one($env, #.Bar) list ?? reduce($env, #.String, add) list ?? reduce($env?.String(false, 1.0), #.foo[str:]) list ?? repeat($env, i) list ?? reverse($env) list ?? reverse(list) list ?? round($env) list ?? sortBy($env, .add) list ?? str list ?? str | any(true) list ?? str | findLast(true) list ?? str | map(foo) list ?? str | reduce(#) list ?? str | reduce(1.0) list ?? string($env) list ?? string(1) list ?? string(i) list ?? string(nil) list ?? sum($env) list ?? sum($env)?.[add] list ?? sum(array) list ?? sum(array, $env) list ?? sum(list) list ?? sum(list, add) list ?? toJSON(add) list ?? true ?? $env?.array list ?? true | count(false) list ?? true | groupBy(#) list ?? true | map(#) list ?? true | map(str) list ?? true | reduce(#) list ?? type(1) list ?? type(nil) list ?? upper($env) list ?? {foo: 1.0} list ?? {foo: 1} list ?? {foo: add} list in $env?.Bar list in $env?.String list in $env?.String?.[foo] list in $env?.String?.f64 list in $env?.[Bar] list in $env?.[Bar]?.Bar list in $env?.[Bar]?.[array] list in $env?.[String] list in $env?.[String]?.[ok] list in $env?.[String]?.[str] list in $env?.[foobar?.[Bar]] list in $env?.[foobar] list in $env?.foobar list in [$env, 1.0] list in [$env, nil] list in [array] list in [nil, $env] list in [nil] list in array ?? $env list in array ?? i list in concat(list) list in last($env) list in sort($env) list in {foo: 0}.array list not in $env?.$env?.list list not in $env?.Bar list not in $env?.String list not in $env?.String?.[add] list not in $env?.String?.add list not in $env?.[Bar] list not in $env?.[String] list not in $env?.[foobar?.[ok]] list not in $env?.[foobar] list not in $env?.foobar list not in [array, true] list not in [list] list not in array ?? 1 list not in last($env) list not in list ?? $env?.[f64] list not in list ?? array list not in list ?? i list not in toPairs($env) list | all(!true) list | all(# != $env) list | all(# == nil) list | all($env | any(true)) list | all($env?.ok) list | all(.Bar not in #) list | all(0 == nil) list | all(1.0 != f64) list | all(false && $env) list | all(false or false) list | all(false) list | all(false) ?: f64 list | all(foo != #) list | all(list != array) list | all(nil != 1.0) list | all(ok) list | all(ok) ?? f64 list | all(str >= .Bar) list | all(true) list | any(# == $env) list | any($env != #) list | any($env != 1.0) list | any($env == $env) list | any($env == foo) list | any($env.ok) list | any($env?.ok) list | any(.Bar in foo) list | any(array | any(ok)) list | any(f64 != 1.0) list | any(false) list | any(false) ?? list list | any(i == nil) list | any(i >= 1.0) list | any(nil == i) list | any(ok != nil) list | any(ok) list | any(true ?: nil) list | any(true) list | concat(array) list | concat(array) ?? i list | concat(i .. i) list | concat(list) list | concat(list) | any(true) list | concat(sortBy(array, #)) list | count(!false) list | count(# != nil) list | count($env != foo) list | count($env == #) list | count($env.ok) list | count(1.0 != $env) list | count(1.0 != nil) list | count(1.0 <= i) list | count(false) list | count(false) | bitxor(i) list | count(nil != ok) list | count(ok) list | count(ok) ?? $env?.String?.Bar list | count(ok) | median(f64) list | count(true != true) list | count(true and false) list | count(true or false) list | count(true) list | filter(!ok) list | filter(# != $env) list | filter(# == #) list | filter(#.String != nil) list | filter($env != false) list | filter($env.ok) list | filter(0 <= 1) list | filter(1.0 > 0) list | filter(false) list | filter(false) | find(true) list | filter(false) | findLast(true) list | filter(false) | map(1.0) list | filter(i <= 1) list | filter(list == $env) list | filter(nil != #.String) list | filter(nil == foo) list | filter(not false) list | filter(ok == nil) list | filter(ok) list | filter(ok) | reduce(1.0) list | filter(ok) | sum(1.0) list | filter(str not startsWith .Bar) list | filter(true) list | filter(true) ?? !$env list | filter(true) | groupBy(foo) list | filter(true) | groupBy(ok) list | filter(true) | map(#) list | filter(true) | sum(1.0) list | find(# != $env) list | find(# == #) list | find(# == $env) list | find($env != i) list | find(0 < 0) list | find(1.0 > 0) list | find(array | one(true)) list | find(f64 == 0) list | find(f64 > 1.0) list | find(false) list | find(foo == #) list | find(foo == $env) list | find(foo == foo) list | find(nil != $env?.f64) list | find(nil != foo) list | find(nil == foo) list | find(not ok) list | find(ok) list | find(true) list | findIndex(!ok) list | findIndex(# != #) list | findIndex(# != foo) list | findIndex(#.Bar in #) list | findIndex(#.String != $env) list | findIndex($env.ok) list | findIndex(1.0 >= 1) list | findIndex(false && $env) list | findIndex(false) list | findIndex(list != nil) list | findIndex(nil != greet) list | findIndex(nil == .Bar) list | findIndex(nil not in $env) list | findIndex(ok == true) list | findIndex(ok) list | findIndex(ok) ?? foo list | findIndex(ok) not in array list | findIndex(true == ok) list | findIndex(true) list | findLast(# == #) list | findLast($env == $env) list | findLast($env == 0) list | findLast($env.ok) list | findLast(.Bar in foo) list | findLast(0 > 1.0) list | findLast(1.0 <= 1) list | findLast(f64 < 0) list | findLast(false) list | findLast(nil != str) list | findLast(not false) list | findLast(ok ?? .String) list | findLast(ok) list | findLast(ok) ?? foo list | findLast(true) list | findLastIndex(!false) list | findLastIndex(!true) list | findLastIndex(# == #) list | findLastIndex(# == $env) list | findLastIndex(#.Bar == #.Bar) list | findLastIndex($env != nil) list | findLastIndex(all(array, true)) list | findLastIndex(array == $env) list | findLastIndex(false or true) list | findLastIndex(false) list | findLastIndex(foo == #) list | findLastIndex(greet != $env) list | findLastIndex(i <= 0) list | findLastIndex(nil not in list) list | findLastIndex(ok) list | findLastIndex(true) list | get(0) list | get(1) list | get(1.0 ?? $env) list | get(i) list | groupBy(# != #) list | groupBy(# != nil) list | groupBy(# == #) list | groupBy(# == nil) list | groupBy(# in list) list | groupBy(#) list | groupBy(#.Bar) list | groupBy(#.String()) list | groupBy($env != #) list | groupBy($env != 0) list | groupBy($env == 0) list | groupBy($env.f64) list | groupBy($env.i) list | groupBy($env.ok) list | groupBy($env?.Bar) list | groupBy($env?.String) list | groupBy($env?.f64) list | groupBy($env?.i) list | groupBy(-0) list | groupBy(.Bar) list | groupBy(0 > i) list | groupBy(0 ?? $env) list | groupBy(0) list | groupBy(1 ** 1.0) list | groupBy(1 / 1.0) list | groupBy(1) list | groupBy(1.0 != $env) list | groupBy(1.0 + i) list | groupBy(1.0 <= 1.0) list | groupBy(1.0 >= 1.0) list | groupBy(1.0 in array) list | groupBy(1.0) list | groupBy(f64 + 1) list | groupBy(f64) list | groupBy(false && $env) list | groupBy(false ?? #) list | groupBy(false) list | groupBy(foo) list | groupBy(foo.Bar) list | groupBy(greet(.Bar)) list | groupBy(i) list | groupBy(i) | get(true) list | groupBy(let foobar = true; foobar) list | groupBy(list?.[i]) list | groupBy(mean(f64)) list | groupBy(nil != #) list | groupBy(nil != $env) list | groupBy(ok) list | groupBy(ok) | get(str) list | groupBy(str) list | groupBy(string(#)) list | groupBy(string(str)) list | groupBy(toJSON(array)) list | groupBy(toJSON(foo)) list | groupBy(true && ok) list | groupBy(true && true) list | groupBy(true) list | groupBy(type(#)) list | groupBy(type(#?.Bar)) list | groupBy(type(1.0)) list | map(# != foo) list | map(# != nil) list | map(# == #) list | map(#) list | map(#) == array list | map(#) | all(true) list | map(#) | findIndex(false) list | map(#) | get(0) list | map(#) | groupBy(#) list | map(#) | groupBy(foo) list | map(#) | map(#) list | map(#) | map(#.Bar) list | map(#) | map(foo) list | map(#) | map(greet) list | map(#) | none(ok) list | map(#) | one(false) list | map(#) | reduce(#) list | map(#.Bar) list | map(#.Bar) | reduce(#, nil) list | map(#.Bar) | sortBy(#) list | map(#.String()) list | map(#.String) list | map(#.String) | reduce(#) list | map(#?.Bar) list | map(#?.String()) list | map(#?.String) list | map(#index) list | map($env) list | map($env) == list list | map($env) | all(#.ok) list | map($env) | all(.ok) list | map($env) | any(true) list | map($env) | findLastIndex(#.ok) list | map($env) | groupBy(0) list | map($env) | map(#.i) list | map($env) | map(.ok) list | map($env) | map(0) list | map($env) | reduce(greet(.str)) list | map($env) | reduce(str) list | map($env.ok) list | map($env?.Bar) list | map($env?.String) list | map($env?.[Bar]) list | map($env?.[String]) list | map($env?.f64) list | map($env?.i) list | map($env?.list) list | map($env?.nil) list | map($env?.str) list | map(-0) list | map(-i) list | map(.Bar) list | map(.Bar) ?? i list | map(.String) list | map(.String) == array list | map(0) list | map(0) ?? list list | map(0) | all(ok) list | map(0) | map(array) list | map(0) | none(ok) list | map(0) | reduce(#) list | map(0) | reduce(0) list | map(1 > 1) list | map(1 >= 0) list | map(1) list | map(1.0 * f64) list | map(1.0 + 1) list | map(1.0) list | map(1.0) | any(true) list | map(1.0) | findLastIndex(true) list | map(1.0) | map(str) list | map(1.0) | reduce(1.0) list | map(1.0) | reduce(foo) list | map(1.0) | sortBy(#) list | map([#]) list | map([.Bar, str]) list | map([false]) list | map(add) list | map(add) | find(ok) list | map(add) | reduce(add) list | map(array == nil) list | map(array) list | map(array) == array list | map(bitnot(i)) list | map(concat(list)) list | map(f64 < 1.0) list | map(f64) list | map(f64) | sum(#) list | map(f64); f64 list | map(false or $env) list | map(false) list | map(false) ?? greet list | map(false) | all(#) list | map(false) | map(#) list | map(false) | reduce(0) list | map(false) | sortBy(str) list | map(false) | sum(f64) list | map(foo == #) list | map(foo == $env) list | map(foo ?? 0) list | map(foo ?? i) list | map(foo) list | map(foo) != list list | map(foo) | count(ok) list | map(foo) | groupBy(#) list | map(foo) | groupBy(true) list | map(foo) | reduce(#acc) list | map(foo.Bar) list | map(foo?.String) list | map(get($env, str)) list | map(greet(.Bar)) list | map(greet) list | map(greet) != array list | map(greet) | sortBy(i) list | map(i != 1.0) list | map(i / f64) list | map(i) list | map(if true { 1.0 } else { # }) list | map(last($env)) list | map(let foobar = str; foobar) list | map(let x = array; x) list | map(list ?? 0) list | map(list) list | map(list) | map(#) list | map(list) | none(ok) list | map(map(array, list)) list | map(nil != 1) list | map(nil != nil) list | map(nil ?? $env) list | map(not true) list | map(ok or $env) list | map(ok) list | map(ok) | findLast(ok) list | map(ok) | reduce(1.0, 0) list | map(sortBy(array, #)) list | map(str <= .Bar) list | map(str) list | map(str) | groupBy(foo) list | map(str) | sortBy(f64) list | map(string(#.Bar)) list | map(string(greet)) list | map(true || ok) list | map(true) list | map(true) | find(true) list | map(true) | groupBy(0) list | map(type(#)) list | map(type(.String)) list | map(type(ok)) list | none(# != #) list | none(# == $env) list | none(#.Bar in foo) list | none($env != $env) list | none($env == #) list | none($env == i) list | none($env.ok) list | none($env?.f64 <= f64) list | none($env?.ok) list | none(.String == .String) list | none(1 < 0) list | none(1.0 <= 1) list | none(all(array, true)) list | none(f64 <= f64) list | none(false) list | none(false) || ok list | none(foo != #) list | none(foo == #) list | none(i == 0) list | none(list | any(ok)) list | none(nil == add) list | none(ok == $env) list | none(ok) list | none(true == nil) list | none(true) list | one(# != foo) list | one(# != nil) list | one(# == foo) list | one($env == $env) list | one($env == false) list | one($env.ok) list | one($env?.ok) list | one(.Bar not endsWith str) list | one(0 != 1.0) list | one(1 >= 1) list | one(add != nil) list | one(add == nil) list | one(f64 != 0) list | one(false) list | one(foo == $env) list | one(i == i) list | one(nil ?? false) list | one(ok ?: 0) list | one(ok) list | one(str == str) list | one(true) list | reduce(!ok) list | reduce(# ?? #) list | reduce(# ?? $env) list | reduce(# ?? 1.0) list | reduce(#) list | reduce(#, $env) list | reduce(#, 0) list | reduce(#, 1) list | reduce(#, 1.0) list | reduce(#, add) list | reduce(#, array) list | reduce(#, f64) list | reduce(#, false) list | reduce(#, foo ?? array) list | reduce(#, foo) list | reduce(#, greet) list | reduce(#, i) list | reduce(#, list) list | reduce(#, nil) list | reduce(#, ok) list | reduce(#, str) list | reduce(#, true) list | reduce(#.Bar) list | reduce(#.Bar, $env) list | reduce(#.Bar, 0) list | reduce(#.Bar, 1) list | reduce(#.Bar, add) list | reduce(#.Bar, array) list | reduce(#.Bar, f64) list | reduce(#.Bar, foo) list | reduce(#.Bar, greet) list | reduce(#.Bar, i) list | reduce(#.Bar, list) list | reduce(#.Bar, nil) list | reduce(#.Bar, ok) list | reduce(#.String == nil) list | reduce(#.String ?? nil) list | reduce(#.String) list | reduce(#.String, $env) list | reduce(#.String, 1) list | reduce(#.String, 1.0) list | reduce(#.String, f64) list | reduce(#.String, foo) list | reduce(#.String, greet) list | reduce(#.String, i) list | reduce(#.String, nil) list | reduce(#.String, true) list | reduce(#?.Bar) list | reduce(#?.String) list | reduce(#acc) list | reduce(#acc, $env) list | reduce(#acc, 1) list | reduce(#acc, 1.0) list | reduce(#acc, add) list | reduce(#acc, array) list | reduce(#acc, array) | map($env) list | reduce(#acc, f64) list | reduce(#acc, foo) list | reduce(#acc, i) list | reduce(#acc, nil) list | reduce(#acc, str) list | reduce(#acc, true) list | reduce(#index - 0) list | reduce(#index <= 1) list | reduce(#index) list | reduce(#index, $env) list | reduce(#index, 1.0) list | reduce(#index, add) list | reduce(#index, false) list | reduce(#index, foo) list | reduce(#index, list) list | reduce(#index, nil) list | reduce(#index, ok) list | reduce(#index, str) list | reduce(#index, true) list | reduce($env != #) list | reduce($env == #.Bar) list | reduce($env not in array) list | reduce($env) list | reduce($env, $env) list | reduce($env, 0) list | reduce($env, 1) list | reduce($env, 1.0) list | reduce($env, add) list | reduce($env, array) list | reduce($env, f64) list | reduce($env, false) list | reduce($env, foo) list | reduce($env, greet) list | reduce($env, i) list | reduce($env, list) list | reduce($env, nil) list | reduce($env, ok) list | reduce($env, str) list | reduce($env, true) list | reduce($env.i) list | reduce($env.ok) list | reduce($env?.String) list | reduce($env?.[Bar]) list | reduce($env?.[String]) list | reduce($env?.[foobar]) list | reduce($env?.[str]) list | reduce($env?.add) list | reduce($env?.add, ok) list | reduce($env?.greet, max(1)) list | reduce(-1) list | reduce(.Bar not in $env) list | reduce(.Bar) list | reduce(.Bar, $env) list | reduce(.Bar, 0) list | reduce(.Bar, 1.0) list | reduce(.Bar, add) list | reduce(.Bar, array) list | reduce(.Bar, i) list | reduce(.Bar, nil) list | reduce(.Bar, ok) list | reduce(.Bar, true) list | reduce(.String) list | reduce(.String, $env) list | reduce(.String, 0) list | reduce(.String, 1) list | reduce(.String, 1.0) list | reduce(.String, array) list | reduce(.String, f64) list | reduce(.String, foo) list | reduce(.String, greet) list | reduce(.String, i) list | reduce(.String, list) list | reduce(.String, nil) list | reduce(.String, ok) list | reduce(0 == f64) list | reduce(0) list | reduce(0) == sum(array) list | reduce(0) ^ f64 list | reduce(0) | median(1.0) list | reduce(0, $env) list | reduce(0, 1.0) list | reduce(0, add) list | reduce(0, array) list | reduce(0, false) list | reduce(0, foo) list | reduce(0, i) list | reduce(0, list) list | reduce(0, nil) list | reduce(0, ok) list | reduce(0, true) list | reduce(1 ** #index) <= i list | reduce(1) list | reduce(1, $env) list | reduce(1, 1) list | reduce(1, 1.0) list | reduce(1, add) list | reduce(1, array) list | reduce(1, false) list | reduce(1, foo) list | reduce(1, foo) | max(array) list | reduce(1, greet) list | reduce(1, i) list | reduce(1, list) list | reduce(1, nil) list | reduce(1, ok) list | reduce(1, str) list | reduce(1, true) list | reduce(1.0 <= i) list | reduce(1.0 == 0) list | reduce(1.0) list | reduce(1.0, $env) list | reduce(1.0, 0) list | reduce(1.0, 1) list | reduce(1.0, 1.0) list | reduce(1.0, add) list | reduce(1.0, array) list | reduce(1.0, f64) list | reduce(1.0, false) list | reduce(1.0, foo) list | reduce(1.0, greet) list | reduce(1.0, i) list | reduce(1.0, list) list | reduce(1.0, nil) list | reduce(1.0, ok) list | reduce(1.0, str) list | reduce(1.0, true) list | reduce([1.0]) list | reduce([ok, foo]) list | reduce([true, #]) list | reduce(add ?? #) list | reduce(add) list | reduce(add, $env) list | reduce(add, 1) list | reduce(add, 1.0) list | reduce(add, add) list | reduce(add, array) list | reduce(add, f64) list | reduce(add, false) list | reduce(add, foo) list | reduce(add, nil) list | reduce(add, ok) list | reduce(array ?? .String) list | reduce(array) list | reduce(array) | groupBy(0) list | reduce(array) | groupBy(ok) list | reduce(array) | map(#) list | reduce(array) | map($env) list | reduce(array) | none(ok) list | reduce(array) | reduce(0, list) list | reduce(array) | reduce(array) list | reduce(array, $env) list | reduce(array, 0) list | reduce(array, 1) list | reduce(array, 1.0) list | reduce(array, add) list | reduce(array, array) list | reduce(array, f64) list | reduce(array, false) list | reduce(array, foo) list | reduce(array, greet) list | reduce(array, i) list | reduce(array, list) list | reduce(array, nil) list | reduce(array, ok) list | reduce(array, str) list | reduce(array, true) list | reduce(f64 != $env) list | reduce(f64 != nil) list | reduce(f64 <= 1.0) list | reduce(f64) list | reduce(f64) < f64 list | reduce(f64) ?? $env?.foo list | reduce(f64, $env) list | reduce(f64, 0) list | reduce(f64, 1) list | reduce(f64, 1.0) list | reduce(f64, add) list | reduce(f64, array) list | reduce(f64, f64) list | reduce(f64, false) list | reduce(f64, foo) list | reduce(f64, greet) list | reduce(f64, list) list | reduce(f64, nil) list | reduce(f64, str) list | reduce(false != nil) list | reduce(false ? # : foo) list | reduce(false || $env) list | reduce(false) list | reduce(false, $env) list | reduce(false, 0) list | reduce(false, 1) list | reduce(false, 1.0) list | reduce(false, array) list | reduce(false, f64) list | reduce(false, false) list | reduce(false, foo) list | reduce(false, greet) list | reduce(false, i) list | reduce(false, nil) list | reduce(false, ok) list | reduce(false, true) list | reduce(first($env)) list | reduce(float(1.0)) list | reduce(foo == foo) list | reduce(foo ?? #) list | reduce(foo ?? 1) list | reduce(foo) list | reduce(foo, $env) list | reduce(foo, $env.array) list | reduce(foo, 0) list | reduce(foo, 1) list | reduce(foo, 1.0) list | reduce(foo, add) list | reduce(foo, array) list | reduce(foo, f64) list | reduce(foo, foo) list | reduce(foo, greet) list | reduce(foo, i) list | reduce(foo, list) list | reduce(foo, nil) list | reduce(foo, ok) list | reduce(foo, str) list | reduce(foo, true) list | reduce(foo.Bar) list | reduce(foo?.Bar) list | reduce(greet ?? 1) list | reduce(greet) list | reduce(greet) != greet list | reduce(greet, $env) list | reduce(greet, 1.0) list | reduce(greet, add) list | reduce(greet, array) list | reduce(greet, f64) list | reduce(greet, false) list | reduce(greet, foo) list | reduce(greet, greet) list | reduce(greet, i) list | reduce(greet, list) list | reduce(greet, nil) list | reduce(greet, str) list | reduce(greet, true) list | reduce(groupBy(list, f64)?.[foo]) list | reduce(i ^ i) list | reduce(i) list | reduce(i, 0) list | reduce(i, 1.0) list | reduce(i, add) list | reduce(i, array) list | reduce(i, f64) list | reduce(i, false) list | reduce(i, foo) list | reduce(i, greet) list | reduce(i, i) list | reduce(i, list) list | reduce(i, list) != $env?.String list | reduce(i, nil) list | reduce(i, ok) list | reduce(i, str) list | reduce(i, true) list | reduce(list) list | reduce(list) ?? not $env list | reduce(list) | groupBy(0) list | reduce(list, $env) list | reduce(list, 1.0) list | reduce(list, add) list | reduce(list, array) list | reduce(list, false) list | reduce(list, foo) list | reduce(list, greet) list | reduce(list, i) list | reduce(list, nil) list | reduce(list, ok) list | reduce(list, str) list | reduce(map(list, greet)) list | reduce(mean([1])) list | reduce(nil ?? foo) list | reduce(ok and #acc) list | reduce(ok) list | reduce(ok) == ok list | reduce(ok, $env) list | reduce(ok, add) list | reduce(ok, array) list | reduce(ok, false) list | reduce(ok, foo) list | reduce(ok, i) list | reduce(ok, list) list | reduce(ok, nil) list | reduce(ok, ok) list | reduce(ok, true) list | reduce(reduce(list, .Bar), ok) list | reduce(str) list | reduce(str) >= foo.Bar list | reduce(str) contains str list | reduce(str, $env) list | reduce(str, 0) list | reduce(str, 1) list | reduce(str, 1.0) list | reduce(str, add) list | reduce(str, array) list | reduce(str, f64) list | reduce(str, false) list | reduce(str, foo) list | reduce(str, i) list | reduce(str, list) list | reduce(str, nil) list | reduce(str, ok) list | reduce(str, str) list | reduce(str, true) list | reduce(trim(str)) list | reduce(true ?? #index) list | reduce(true and ok) list | reduce(true) list | reduce(true, $env) list | reduce(true, 0) list | reduce(true, array) list | reduce(true, f64) list | reduce(true, false) list | reduce(true, foo) list | reduce(true, greet) list | reduce(true, i) list | reduce(true, ok) list | reduce(true, str) list | reduce(type(#)) list | reduce(values($env)) list | sortBy(#.Bar) list | sortBy(#.Bar) | groupBy(foo) list | sortBy(#.String()) list | sortBy(#?.Bar) list | sortBy($env?.i) list | sortBy(-0) list | sortBy(-1.0) list | sortBy(-i) list | sortBy(.Bar) list | sortBy(.Bar) | groupBy(f64) list | sortBy(.Bar) | reduce($env) list | sortBy(0) list | sortBy(0) | one(ok) list | sortBy(0) | sortBy(str) list | sortBy(1) list | sortBy(1) | map(greet) list | sortBy(1) | map(str) list | sortBy(1) | sum(0) list | sortBy(1.0 ** 0) list | sortBy(1.0) list | sortBy(1.0) ?? i list | sortBy(1.0) | filter(false) list | sortBy(1.0) | groupBy(true) list | sortBy(1.0) | map(.String) list | sortBy(1.0) | reduce($env) list | sortBy(1.0) | sum(i) list | sortBy(ceil(1.0)) list | sortBy(f64 ** 0) list | sortBy(f64) list | sortBy(f64) == array list | sortBy(float(1)) list | sortBy(foo.String()) list | sortBy(foo?.Bar) list | sortBy(greet(.Bar)) list | sortBy(i) list | sortBy(i) | groupBy(0) list | sortBy(last(array)) list | sortBy(str) list | sortBy(str) | count(ok) list | sortBy(str) | reduce(ok, true) list | sortBy(string(true)) list | sum($env.i) list | sum($env?.f64) list | sum(-f64) list | sum(-i) list | sum(0 * 0) list | sum(0 - 1.0) list | sum(0) list | sum(0) != i list | sum(0) >= 1.0 == false list | sum(0) >= bitnot(i) list | sum(1) list | sum(1) / 0 ** 1 list | sum(1) <= f64 list | sum(1) | median(array) list | sum(1.0 ^ 1) list | sum(1.0) list | sum(array | findLastIndex(true)) list | sum(ceil(1.0)) list | sum(f64 * 1.0) list | sum(f64) list | sum(f64) ?? i list | sum(f64) in array list | sum(i) list | sum(int(i)) list | sum(round(1)) list | take(0) list | take(0) | sortBy(#) list | take(1) list | take(1) | sum(0) list | take(i) list; $env.i list; $env; $env?.ok list; $env?.ok list; add list; f64 list; foo list; foo; $env.array list; foo?.Bar list; foo?.String list; greet list; i list; list list; nil == nil list; nil; foo?.String list; ok list; str list; toJSON(i) list?.[$env | count(false)] list?.[$env.i] list?.[$env?.i] list?.[-0] list?.[-1] list?.[-i] list?.[0 % 1] list?.[0 ?? nil] list?.[0] list?.[0].Bar list?.[0].String list?.[0]?.Bar list?.[0]?.String list?.[1 + 0] list?.[1 ?? 1.0] list?.[1 ?? foo] list?.[1.0 ?? greet] list?.[1] list?.[1] != f64 ?? ok list?.[1].Bar list?.[1].String list?.[1].String() list?.[1]?.Bar list?.[1]?.String list?.[1]?.String() list?.[array?.[0]] list?.[f64 ?? $env?.[add]] list?.[i ?? add] list?.[i ?? f64] list?.[i] list?.[i] != foo list?.[i] != foo && $env list?.[i] == foo list?.[i] == nil && $env list?.[i] ?? $env?.ok list?.[i] ?? add list?.[i] ?? array list?.[i] ?? f64 list?.[i] ?? greet list?.[i] ?? ok list?.[i] ?? str list?.[i] ?? type(foo) list?.[i] not in list list?.[i] not in list ?? f64 list?.[i].Bar list?.[i].Bar ?? foo list?.[i].String list?.[i].String() list?.[i]?.Bar list?.[i]?.String list?.[i]?.String() list?.[int(1.0)] list?.[max(i)] list?.[mean(i)] list?.[median(0)] list[$env.i:] list[$env?.i:] list[-1:] list[-i:] list[0:] | map(foo) list[0:] | reduce(#.Bar) list[0:] | reduce(1.0) list[0:] | reduce(str) list[0:]?.[i] list[1 + 0:] list[1 ?? 0:] list[1:] | findLast(true) list[1:] | map(0) list[1:] | map(ok) list[1:] | reduce(foo) list[1:][:i] list[:$env.i] list[:$env?.i] list[:-i] list[:0 * 0] list[:0] | findIndex(nil != foo) list[:0] | map(str) list[:1] ?? list list[:1] | groupBy(ok) list[:1] | one(ok) list[:1] | sortBy(foo) list[:] list[:] | map(#index) list[:]?.[i] list[:array?.[i]] list[:bitnot(1)] list[:bitnot(i)] list[:count(array, ok)] list[:i] list[:i] | any(ok) list[:i] | filter(true) list[:i] | groupBy(ok) list[:i] | sum(f64) list[:mean(i)] list[:median(0)] list[:median(array)] list[:min(i)] list[:sum(array)] list[add(1, 0):] list[array?.[i]:] list[f64 ?? false:] list[i:] list[i:] ?? greet list[i:] | findIndex(ok) list[i:] | groupBy(true) list[i:] | sortBy(0) list[i:i] list[int(1.0):] list[len($env):] list[min(array):] list[sum(array):] lower($env | reduce(str, 1.0)) lower($env.str) lower($env?.[str]) lower($env?.str) lower(false ? array : str) lower(foo.Bar) lower(foo.String()) lower(foo?.Bar) lower(foo?.String()) lower(greet($env?.str)) lower(greet(str)) lower(greet(string(nil))) lower(greet(toJSON(array))) lower(list?.[i]?.Bar) lower(lower(str)) lower(reduce(array, str)) lower(repeat(str, 0)) lower(str + str) lower(str ?? $env) lower(str ?? 0) lower(str ?? 1.0) lower(str ?? array) lower(str ?? f64) lower(str ?? foo) lower(str ?? foo?.Bar) lower(str ?? ok) lower(str ?? true) lower(str | greet()) lower(str) lower(str) < str lower(str) == $env != false lower(str) == str lower(str) > str lower(str) ?? add lower(str) ?? f64 lower(str) ?? trim(str) lower(str) endsWith str lower(str) | greet() lower(str[1:]) lower(string($env)) lower(string(0)) lower(string(1)) lower(string(1.0)) lower(string(add)) lower(string(array)) lower(string(f64)) lower(string(false)) lower(string(foo)) lower(string(i)) lower(string(list)) lower(string(nil)) lower(string(ok)) lower(string(str)) lower(string(true)) lower(toBase64(str)) lower(toJSON(0)) lower(toJSON(1.0)) lower(toJSON(array)) lower(toJSON(f64)) lower(toJSON(false)) lower(toJSON(foo)) lower(toJSON(i)) lower(toJSON(list)) lower(toJSON(nil)) lower(toJSON(ok)) lower(toJSON(str)) lower(toJSON(true)) lower(trim(foo?.Bar)) lower(trim(str)) lower(trimPrefix(str)) lower(trimSuffix(str)) lower(type($env)) lower(type(0)) lower(type(1)) lower(type(1.0)) lower(type(add)) lower(type(array)) lower(type(f64)) lower(type(false)) lower(type(foo)) lower(type(greet)) lower(type(i)) lower(type(list)) lower(type(nil)) lower(type(ok)) lower(type(str)) lower(type(true)) lower(upper(str)) map($env ?? $env, ok) map($env ?? 1.0, ok) map($env | filter(false), #.add) map($env | filter(false), $env - #.str) map($env | map(#index), f64) map($env | map(foo), #.String) map($env, #index) | filter(false) map($env, #index) | map(greet) map($env, #index) | reduce($env) map($env, #index) | reduce(0, $env) map($env, #index)?.[i] map($env, $env) ?? timezone(str) map($env, $env) in last($env) map($env, $env) | any(f64 == .foo) map($env, $env) | count(ok) map($env, $env) | findLast(ok) map($env, $env) | map(array) map($env, $env) | map(foo) map($env, $env) | reduce($env) map($env, $env) | reduce(.f64, false) map($env, $env) | reduce(0) map($env, $env) | sum(1) map($env, $env)?.[i] map($env, 0) != i .. 0 map($env, 0) ?? greet map($env, 0) ?? list map($env, 0) | map($env) map($env, 0) | map(str) map($env, 0) | reduce(ok, i) map($env, 0) | sortBy(1.0) map($env, 0)?.[i] map($env, 1) | any(ok) map($env, 1) | count(ok) map($env, 1) | groupBy(foo) map($env, 1) | map(#) map($env, 1) | none(ok) map($env, 1) | reduce(foo) map($env, 1) | sum(#) map($env, 1)?.[i] map($env, 1.0) ?? f64 map($env, 1.0) | all(true) map($env, 1.0) | filter(ok) map($env, 1.0) | find(true) map($env, 1.0) | groupBy(#) map($env, 1.0) | map(str) map($env, 1.0) | reduce(ok, add) map($env, 1.0)?.[i] map($env, add) | groupBy(i) map($env, add) | map(false) map($env, add) | reduce(1.0) map($env, add) | reduce(add, false) map($env, add) | sum(f64) map($env, add)?.[i] map($env, array) | findIndex(ok) map($env, array) | map(0) map($env, array) | reduce(f64) map($env, array)?.[i] map($env, f64) | count(ok) map($env, f64) | count(true) map($env, f64) | groupBy(#) map($env, f64) | reduce(#) map($env, f64) | reduce(foo) map($env, f64) | reduce(greet) map($env, f64) | sortBy(#) map($env, f64) | sortBy(i) map($env, f64) | sum(#) map($env, f64)?.[i] map($env, f64)[:] map($env, false) | filter(false) map($env, false) | find(#) map($env, false) | map(#) map($env, false) | map(1.0) map($env, false) | map(greet) map($env, false) | reduce(str, nil) map($env, false)?.[i] map($env, foo) == list map($env, foo) ?? list map($env, foo) ?? str map($env, foo) not in [add, f64] map($env, foo) | all(.Bar not startsWith .Bar) map($env, foo) | findLastIndex(true) map($env, foo) | get(1) map($env, foo) | groupBy(#) map($env, foo) | map($env) map($env, foo) | map(f64) map($env, foo) | map(foo) map($env, foo) | map(greet) map($env, foo) | map(list) map($env, foo) | none(true) map($env, foo) | reduce(#) map($env, foo) | reduce(list) map($env, foo) | sortBy(.Bar) map($env, foo) | sortBy(str) map($env, foo)?.[i] map($env, greet) ?? list map($env, greet) | all(ok) map($env, greet) | findLast(false) map($env, greet) | map(1) map($env, greet) | map(greet) map($env, greet) | reduce(list) map($env, greet) | sortBy(i) map($env, greet)?.[i] map($env, i) == list map($env, i) | any(true) map($env, i) | groupBy(f64) map($env, i) | one(ok) map($env, i) | sortBy(1.0) map($env, i)?.[i] map($env, list) ?? str map($env, list) | filter(false) map($env, list) | map($env) map($env, list) | map(greet) map($env, list) | map(str) map($env, list) | reduce(1.0) map($env, list) | reduce(foo) map($env, list) | reduce(list) map($env, list)?.[i] map($env, ok) | findLastIndex(#) map($env, ok) | findLastIndex(false) map($env, ok) | one(1.0 == nil) map($env, ok) | reduce(false) map($env, ok)?.[i] map($env, str) | find(ok) map($env, str) | find(true) map($env, str) | findIndex(false) map($env, str) | groupBy(#) map($env, str) | map(1) map($env, str) | sortBy(str) map($env, str)?.[i] map($env, true) ?? ok map($env, true) | any(#) map($env, true) | filter(true) map($env, true) | find(#) map($env, true) | groupBy(0) map($env, true) | map(#) map($env, true) | map(f64) map($env, true) | reduce(foo) map($env, true) | sortBy(1.0) map($env, true)?.[i] map($env.array, #) map($env.array, #index - 1.0) map($env.array, #index) map($env.array, add) map($env.array, foo) map($env.array, list) map($env.array, mean(0)) map($env.array, not true) map($env.array, ok) map($env.array, str) map($env.list, #) map($env.list, #index) map($env.list, .String) map($env.list, 0 >= 1.0) map($env.list, array) map($env.list, f64 ^ f64) map($env.list, greet) map($env.list, i) map($env.list, list) map($env.list, ok) map($env.list, sortBy(array, 1.0))?.[i] map($env.list, str) map($env?.[str], # ** #) map($env?.[str], #) map($env?.[str], #index != #) map($env?.[str], #index) map($env?.[str], 0 <= 1.0) map($env?.[str], array) map($env?.[str], f64 - 1.0) map($env?.[str], foo ?? #.array) map($env?.[str], foo) map($env?.[str], greet) map($env?.[str], i != f64) map($env?.[str], i) map($env?.[str], list) map($env?.[str], median(0)) map($env?.[str], nil != false) map($env?.[str], ok) map($env?.[str], str) map($env?.array, #) map($env?.array, $env?.i) map($env?.array, add) map($env?.array, all(list, true)) map($env?.array, array) map($env?.array, f64) map($env?.array, foo) map($env?.array, greet == greet) map($env?.array, list) map($env?.array, str) map($env?.list, # != $env) map($env?.list, #) map($env?.list, $env?.[String]) map($env?.list, add) map($env?.list, count($env, false)) map($env?.list, foo) map($env?.list, greet) map($env?.list, i) map($env?.list, list[1:]) map($env?.list, median(i)) map($env?.list, ok) map($env?.list, trimSuffix(str)) map(1 .. 1, list) map([$env], #) map([$env], #.Bar not in #.array) map([$env], #?.f64) map([$env], 1 ^ 1.0) map([$env], add) map([$env], false != #) map([$env], greet) map([$env], true || .array) map([0], #) map([1.0], #) map([1.0], greet) map([1.0], ok) map([1], greet) map([add, i], array) map([array], #) map([false], -1) map([false], list) map([false], ok) map([foo, 1.0], #index) map([foo, true], #) map([foo], #) map([foo], #?.Bar) map([foo], .String) map([foo], 1.0 < 0) map([foo], add) map([foo], f64) map([foo], foo) map([foo], str) map([greet], #) map([greet], array) map([greet], foo) map([i / 1.0], #) map([i, 1.0], #) map([i], #) map([i], ok) map([i], str) map([list], array) map([list], f64 + 1.0) map([list], f64) map([nil], 1.0 <= 1) map([nil], foo) map([nil], list) map([nil], ok) map([nil], str ?? f64) map([ok], #) map([ok], array) map([str], greet) map([true], #) map([true], foo) map([true], i ^ 1.0) map(array ?? 1, i) map(array ?? 1, ok) map(array ?? 1.0, false ? #.add : #) map(array ?? array, add) map(array ?? foo, # > #) map(array ?? foo, add) map(array | map(#), 1.1) map(array | reduce($env), list) map(array | sortBy(#), ok) map(array, !false) map(array, !true) map(array, # != #) map(array, # % i) map(array, # ** #) map(array, # ** 1.0) map(array, # + #) map(array, # + 1) map(array, # .. #) map(array, # .. 0) map(array, # < f64) map(array, # <= #) map(array, # <= 1.0) map(array, # == #) map(array, # > #) map(array, # > 0) map(array, # >= #) map(array, # >= 0) map(array, # ?? #) map(array, # ?? i) map(array, # ^ #) map(array, # ^ 1.0) map(array, # | bitshr(#)) map(array, #) map(array, #) ?? add map(array, #) ?? greet map(array, #) | filter(false) map(array, #) | findLastIndex(ok) map(array, #) | findLastIndex(true) map(array, #) | groupBy(#) map(array, #) | map($env) map(array, #) | map(bitnot(1)) map(array, #) | map(foo) map(array, #) | map(greet) map(array, #) | reduce($env?.foobar) map(array, #) | reduce(1.0) map(array, #) | sortBy(#) map(array, #)?.[i] map(array, #..i) map(array, #index < 1.0) map(array, #index) map(array, #index) | groupBy(ok) map(array, #index)?.[i] map(array, $env && true) map(array, $env == #) map(array, $env == true) map(array, $env) | all(#.list || true) map(array, $env) | count(#.ok) map(array, $env) | none(.String matches #) map(array, $env) | reduce(1.0) map(array, $env) | reduce(add) map(array, $env) | sortBy(1) map(array, $env)?.[i] map(array, $env.array) map(array, $env.f64) map(array, $env.foo) map(array, $env.greet) map(array, $env.list) map(array, $env.str) map(array, $env?.String) map(array, $env?.[String]) map(array, $env?.[foobar]) map(array, $env?.[str]) map(array, $env?.add) map(array, $env?.array) map(array, $env?.f64) map(array, $env?.greet) map(array, $env?.list) map(array, $env?.ok) map(array, -1) map(array, -1.0) map(array, -f64) map(array, -i) map(array, 0 != #) map(array, 0 % #) map(array, 0 - #) map(array, 0 - 1) map(array, 0 <= #) map(array, 0 | bitxor(#)) map(array, 0) | find(false) map(array, 0) | map(array) map(array, 0) | reduce(#) map(array, 0) | sortBy(f64) map(array, 0)?.[i] map(array, 1 != #) map(array, 1 - #) map(array, 1 ^ #) map(array, 1) | map(1) map(array, 1) | one(ok) map(array, 1) | reduce($env) map(array, 1)?.[i] map(array, 1.0 != #) map(array, 1.0 != 1.0) map(array, 1.0 ** #) map(array, 1.0 + #) map(array, 1.0 + 1.0) map(array, 1.0 / 0) map(array, 1.0 <= #) map(array, 1.0 == #) map(array, 1.0 == nil) map(array, 1.0 ?? nil) map(array, 1.0 ^ f64) map(array, 1.0) != array map(array, 1.0) != f64 ?? greet map(array, 1.0) == list map(array, 1.0) | groupBy(#) map(array, 1.0) | groupBy(1.0) map(array, 1.0) | groupBy(ok) map(array, 1.0) | map(#) map(array, 1.0) | map(foo) map(array, 1.0) | reduce($env) map(array, 1.0) | reduce(1.0) map(array, 1.0) | reduce(true) map(array, 1.0) | take(1) map(array, 1.0)?.[i] map(array, [#]) map(array, [0, $env]) map(array, [f64]) map(array, [i]) map(array, [nil]) map(array, add) map(array, add) | groupBy(foo) map(array, add)?.[i] map(array, array | map(1.0)) map(array, array) map(array, array) | all(true) map(array, array) | sum(i) map(array, array)?.[i] map(array, array?.[1]) map(array, bitnot(#)) map(array, f64 - 1.0) map(array, f64 <= f64) map(array, f64 >= i) map(array, f64) map(array, f64) != list map(array, f64) ?? -1.0 map(array, f64) | groupBy(foo) map(array, f64) | reduce(#) map(array, f64)?.[i] map(array, false) | any(#) map(array, false) | count(false) map(array, false) | reduce(greet) map(array, false) | sortBy(str) map(array, false)?.[i] map(array, findIndex($env, ok)) map(array, flatten(array)) map(array, flatten(list)) map(array, float(#)) map(array, float(1)) map(array, foo != $env) map(array, foo != foo) map(array, foo == foo) map(array, foo ?? ok) map(array, foo) map(array, foo) != array map(array, foo) | count(true) map(array, foo) | findLastIndex(false) map(array, foo) | map(#.Bar) map(array, foo) | map(ok) map(array, foo) | reduce(#) map(array, foo) | reduce(list) map(array, foo) | reduce(str, f64) map(array, foo) | reduce(true) map(array, foo) | sum(0 + 1) map(array, foo)?.[i] map(array, foo)[:] map(array, foo.Bar) map(array, foo.String) map(array, foo?.Bar) map(array, foo?.String) map(array, greet) map(array, greet) | sum(f64) map(array, greet)?.[i] map(array, i * f64) map(array, i < 0) map(array, i == #index) map(array, i) map(array, i) | find(ok) map(array, i)?.[i] map(array, if ok { $env } else { i }) map(array, int(#index)) map(array, len($env)) map(array, list == $env) map(array, list == list) map(array, list) map(array, list)?.[i] map(array, list?.[i]) map(array, median(#)) map(array, median(1.0)) map(array, min(0)) map(array, nil != 1.0) map(array, nil != array) map(array, nil == 1.0) map(array, nil ?? list) map(array, not false) map(array, not true) map(array, ok != true) map(array, ok == nil) map(array, ok ?? str) map(array, ok || false) map(array, ok) map(array, ok) ?? float($env) map(array, ok) | count(1 >= 1.0) map(array, ok) | map(1) map(array, ok) | one(true) map(array, ok) | sum(1.0) map(array, ok)?.[i] map(array, reduce(array, foo, #index)) map(array, reverse(list)) map(array, round(1)) map(array, sort(array)) map(array, str == nil) map(array, str in foo) map(array, str) map(array, str) == list map(array, str) | groupBy(#) map(array, str) | map(list) map(array, str) | reduce(#) map(array, str)?.[i] map(array, sum(array)) map(array, true ? 1 : #) map(array, true ?? #) map(array, true ?? foo) map(array, true) != array map(array, true) | findLast(#) map(array, true)?.[i] map(array, type(1.0)) map(array, type(list)) map(array[i:], $env?.ok) map(concat(array), # == f64) map(concat(array), greet) map(concat(list), foo) map(false ? foo : list, $env.ok) map(filter(array, true), greet) map(flatten(array), #) map(flatten(array), i) map(flatten(array), str) map(i .. i, array) map(if false { $env } else { list }, #index) map(keys($env), #) map(keys($env), str) map(list ?? 0, # == str) map(list ?? false, f64) map(list ?? true, list) map(list | map($env), #) map(list | map(.Bar), #) map(list | map(.Bar), greet) map(list | sortBy(1.0), .String) map(list | sortBy(1.0), string(#)) map(list | sortBy(str), f64) map(list, # != #) map(list, # == #) map(list, # == foo) map(list, # ?? #) map(list, # ?? #index) map(list, # ?? $env) map(list, # ?? .Bar) map(list, # ?? greet) map(list, #) map(list, #) == array map(list, #) ?? greet map(list, #) | any(false) map(list, #) | any(ok) map(list, #) | findIndex(ok) map(list, #) | findIndex(true) map(list, #) | findLastIndex(ok) map(list, #) | groupBy(#) map(list, #) | groupBy(1.0) map(list, #) | groupBy(foo) map(list, #) | map(#) map(list, #) | map(1.0) map(list, #) | map(true) map(list, #) | one(false) map(list, #) | one(true) map(list, #) | reduce(#.String, foo) map(list, #) | reduce(#acc, 1) map(list, #) | reduce(1.0, nil) map(list, #) | reduce(f64, list) map(list, #) | sortBy(1.0) map(list, #) | take(1) map(list, #)?.[i] map(list, #.Bar <= #.Bar) map(list, #.Bar) map(list, #.String) map(list, #.String) ?? i map(list, #.String)?.[i] map(list, #?.Bar) map(list, #?.String) map(list, #index + i) map(list, #index - 1) map(list, #index | add(i)) map(list, #index) map(list, #index) ?? $env ?? nil map(list, #index)?.[i] map(list, $env != #) map(list, $env != foo) map(list, $env != greet) map(list, $env != nil) map(list, $env ?? 1.0) map(list, $env) ?? $env.ok map(list, $env) ?? array map(list, $env) | findIndex(.ok) map(list, $env) | findLastIndex(#.foo != #) map(list, $env) | map(1.0) map(list, $env) | map(foo) map(list, $env) | reduce(#.ok) map(list, $env) | reduce(1.0) map(list, $env)?.[i] map(list, $env.add) map(list, $env.f64) map(list, $env.foo) map(list, $env.greet) map(list, $env?.[.Bar]) map(list, $env?.[Bar]) map(list, $env?.[String]) map(list, $env?.[str]) map(list, $env?.add) map(list, $env?.array) map(list, $env?.f64) map(list, $env?.foo) map(list, $env?.foobar) map(list, $env?.greet) map(list, $env?.i) map(list, $env?.ok) map(list, $env?.str) map(list, -#index) map(list, .Bar) map(list, .Bar) | sum(1) map(list, .String) map(list, .String) | filter(true) map(list, .String) | map(#) map(list, .String) | sum(i) map(list, .String)?.[i] map(list, 0 <= 1.0) map(list, 0 > 1) map(list, 0) | groupBy(foo) map(list, 0) | sortBy(#) map(list, 0) | sum(#) map(list, 1 == 1.0) map(list, 1) | all(false) map(list, 1) | groupBy(#) map(list, 1) | map(list) map(list, 1)?.[i] map(list, 1.0 / i) map(list, 1.0 >= 1.0) map(list, 1.0 ?? #.Bar) map(list, 1.0 ?? list) map(list, 1.0) != array map(list, 1.0) ?? array map(list, 1.0) | any(# < i) map(list, 1.0) | findLast(true) map(list, 1.0) | groupBy(#) map(list, 1.0) | reduce(foo) map(list, 1.0) | sortBy(#) map(list, 1.0)?.[i] map(list, [$env, nil, add]) map(list, [foo]) map(list, [ok]) map(list, abs(1)) map(list, abs(1.0)) map(list, add ?? #) map(list, add ?? list) map(list, add) map(list, add)?.[i] map(list, array) map(list, array) ?? list map(list, array) | one(ok) map(list, array) | one(true) map(list, array)?.[i] map(list, array?.[i]) map(list, bitnot(0)) map(list, bitnot(i)) map(list, ceil(1.0)) map(list, f64 != 1.0) map(list, f64 * 0) map(list, f64 / 1.0) map(list, f64) map(list, f64) | groupBy(#) map(list, f64) | map($env) map(list, f64) | none(true) map(list, f64) | reduce(1) map(list, false ?? foo) map(list, false) | groupBy(foo) map(list, false) | map(#) map(list, float(0)) map(list, floor(1.0)) map(list, foo == #) map(list, foo ?? #) map(list, foo ?? foo) map(list, foo not in list) map(list, foo) map(list, foo) ?? f64 map(list, foo) | none(false) map(list, foo) | reduce(#, add) map(list, foo) | reduce(#.String) map(list, foo) | reduce(1) map(list, foo) | reduce(array) map(list, foo) | sum(0) map(list, foo)?.[i] map(list, foo.Bar) map(list, foo.String) map(list, foo?.Bar) map(list, foo?.String()) map(list, greet ?? nil) map(list, greet(#.Bar)) map(list, greet(str)) map(list, greet) map(list, greet) | findIndex(true) map(list, greet)?.[i] map(list, i == $env) map(list, i >= 0) map(list, i) map(list, i) != list map(list, i) != nil or true map(list, i) | groupBy(# < #) map(list, i) | reduce(#) map(list, i) | sortBy(#) map(list, i)?.[i] map(list, list) map(list, list) | map(str) map(list, list) | sum(f64) map(list, list)?.[i] map(list, max(1)) map(list, max(f64)) map(list, mean(array)) map(list, nil != add) map(list, nil ?? #) map(list, nil in $env) map(list, none($env, true)) map(list, not true) map(list, ok ? str : foo) map(list, ok ?? 0) map(list, ok or ok) map(list, ok) map(list, ok) | map(false) map(list, ok)?.[i] map(list, reverse(list)) map(list, round(f64)) map(list, sort(array)) map(list, str ?? 0) map(list, str not in #) map(list, str) map(list, str) | findLast(false) map(list, str) | map(#) map(list, str) | reduce(#) map(list, string(#)) map(list, string(f64)) map(list, sum(array)) map(list, toJSON(1)) map(list, trim(str)) map(list, true ? array : f64) map(list, true ?? #index) map(list, true)?.[i] map(list, type(#)) map(list, type($env)) map(list, upper(#.Bar)) map(list[:1], f64) map(map($env, $env), greet) map(map($env, 0), str == str) map(map(array, #), #) map(map(array, array), greet) map(map(array, list), str) map(map(list, 1), list) map(map(list, f64), ok) map(map(list, str), map($env, 1.0)) map(max($env), greet) map(min($env), f64) map(nil ?? $env, str) map(nil ?? array, 1.0 != 1.0) map(reduce($env, list, $env), foo) map(reduce(array, $env), foo.String()) map(reverse(array), str) map(sort($env), #.String contains #.list) map(sort($env), #.String.i) map(sort($env), #.array.greet) map(sort($env), #.greet.foo) map(sort($env), #.greet?.Bar(Bar)) map(sort($env), add) map(sort($env), array?.[#]) map(sort($env), lower(#)) map(sort($env), ok) map(sort($env), str not matches $env) map(sort($env), str) map(sort(array), list?.[i]) map(sort(array), ok) map(sortBy(array, 1.0), #) map(sortBy(array, str), # >= #index) map(str ?? foo, #) map(str ?? foo, f64) map(str ?? foo, i) map(toPairs($env), f64) map(toPairs($env), list | sortBy(1)) map(true ? array : false, $env?.greet) map(uniq(list), ok) map(uniq(list), reduce(list, foo)) map(values($env), #) max($env ?? $env) max($env ?? 1) max($env ?? add) max($env ?? array) max($env ?? f64) max($env ?? foo) max($env ?? list) max($env ?? nil) max($env ?? str) max($env ?? true) max($env | count(ok)) max($env | count(true)) max($env | find(false)) max($env | findIndex(ok)) max($env | findLast(false)) max($env | findLastIndex(false)) max($env | findLastIndex(ok)) max($env | findLastIndex(true)) max($env | map(#index)) max($env | map(0)) max($env | map(1)) max($env | sum(i)) max($env) != $env?.array max($env) != greet max($env) == $env?.foo max($env) == f64 max($env) == list max($env) == ok max($env) ?? i max($env) ?? list max($env) not in list max($env) | all(ok) max($env) | count($env.ok) max($env) | count(false) max($env) | count(true) max($env) | find(false) max($env) | map(1.0) max($env) | map(add) max($env) | map(f64) max($env) | map(greet) max($env) | map(i) max($env) | map(str) max($env) | none(ok) max($env) | sum(0) max($env) | sum(1.0) max($env).Bar max($env).Bar?.i().str max($env).Bar?.str max($env).String max($env).String?.[array] max($env).String?.[str] max($env).add max($env).array max($env).f64 max($env).foo max($env).foobar max($env).foobar?.[add] max($env).foobar?.[greet] max($env).foobar?.foo max($env).foobar?.str max($env).greet max($env).greet(foobar) max($env).i max($env).list max($env).not max($env).ok max($env).str max($env)?.$env?.Bar max($env)?.$env?.foo(1.0) max($env)?.Bar max($env)?.String max($env)?.String?.[str] max($env)?.[str] max($env)?.[str]?.[i] max($env)?.add max($env)?.array max($env)?.array not in list max($env)?.f64 max($env)?.foo max($env)?.foobar?.[add] max($env)?.foobar?.[greet] max($env)?.greet max($env)?.greet(foobar) max($env)?.i max($env)?.list max($env)?.list?.[f64] max($env)?.not max($env)?.ok max($env)?.str max($env)?.str?.[f64] max($env.array ?? array) max($env.array) max($env.array, array) max($env.f64) max($env.f64, sum(array)) max($env.i) max($env?.$env) max($env?.Bar) max($env?.Bar)?.[foo] max($env?.Bar)?.foo max($env?.Bar)?.list max($env?.String) max($env?.String)?.[foo] max($env?.String)?.[i] max($env?.String?.[array]) max($env?.String?.foo()) max($env?.String?.i()) max($env?.[Bar]) max($env?.[Bar])?.[ok] max($env?.[String]) max($env?.[String])?.[i] max($env?.[String])?.foo max($env?.[String]?.[f64]) max($env?.[String]?.[str]) max($env?.[String]?.ok) max($env?.[foobar]) max($env?.[nil]) max($env?.[str]) max($env?.[str]) | reduce(ceil(#)) max($env?.[str]?.[f64]) max($env?.array) max($env?.f64 ^ i) max($env?.f64) max($env?.f64, i) max($env?.false) max($env?.foobar) max($env?.i) max($env?.nil) max($env?.true) max(-0) max(-1) max(-1.0) max(-f64) max(-i) max(-median(1, 0)) max(0 % 1) max(0 % i) max(0 * 0) max(0 * 1) max(0 * 1.0) max(0 ** 1) max(0 ** f64) max(0 + 0) max(0 + 1) max(0 + 1.0) max(0 + f64) max(0 - 0) max(0 - 1) max(0 - 1.0) max(0 - f64) max(0 - i) max(0 .. 1) max(0 .. 1, i) max(0 .. i) max(0 / 0) max(0 / 1) max(0 ?? $env) max(0 ?? 1) max(0 ?? add) max(0 ?? array) max(0 ?? f64) max(0 ?? false) max(0 ?? greet) max(0 ?? ok) max(0 ^ 0) max(0 ^ 1) max(0 ^ 1.0) max(0 ^ f64) max(0 ^ i) max(0 | min(1.0, 1.0)) max(0) != 0 || ok max(0) - i max(0) < i max(0) == f64 max(0) ?? -f64 max(0) ?? f64 max(0) not in array max(0..i) max(0.0) max(0.1) max(1 * 0) max(1 * 1.0) max(1 * i) max(1 ** 0) max(1 ** 1.0) max(1 + 0) max(1 + 1) max(1 + f64) max(1 + i) max(1 - 1) max(1 - 1.0) max(1 - f64) max(1 - i) max(1 .. 1) max(1 / 1.0) max(1 / f64) max(1 / i) max(1 ?? 1.0) max(1 ?? f64) max(1 ?? false) max(1 ?? foo) max(1 ?? list) max(1 ?? list, array) max(1 ?? ok) max(1 ^ $env?.i) max(1 ^ 0) max(1 ^ 1.0) max(1 ^ i) max(1 | bitshr(1)) max(1 | max(1.0)) max(1) * i max(1) ** f64 max(1) ** i max(1) .. i max(1) / i max(1) < f64 max(1) < i max(1) ?? $env.ok max(1, 1.0) < f64 max(1, 1.0) in array max(1.0 * 0) max(1.0 * 1) max(1.0 * 1.0) max(1.0 * f64) max(1.0 * i) max(1.0 ** 0) max(1.0 ** 1) max(1.0 ** 1.0) max(1.0 ** f64) max(1.0 ** i) max(1.0 + 0) max(1.0 + 1) max(1.0 + 1.0) max(1.0 + f64) max(1.0 + i) max(1.0 - 0) max(1.0 - 1) max(1.0 - 1.0) max(1.0 - f64) max(1.0 - i) max(1.0 / 0) max(1.0 / 1.0) max(1.0 / i) max(1.0 ?? $env) max(1.0 ?? 1.0) max(1.0 ?? array) max(1.0 ?? f64) max(1.0 ?? false) max(1.0 ?? false, i) max(1.0 ?? foo) max(1.0 ?? greet) max(1.0 ?? i) max(1.0 ?? nil) max(1.0 ?? ok) max(1.0 ^ 0) max(1.0 ^ 1) max(1.0 ^ 1.0) max(1.0 ^ f64) max(1.0 ^ i) max(1.0) max(1.0) ** i max(1.0) - i max(1.0) < i max(1.0) <= $env.f64 max(1.0) <= i max(1.0) > 1 - i max(1.0) > f64 max(1.0) >= i max(1.0) ?? i max(1.0) ?? list max(1.0) ?? ok max(1.0) ^ f64 max(1.0) | min(array) max(1.0, 1.0) ?? greet max(1.0, array) >= floor(1.0) max([0]) max([1.0]) max([1]) max([array, 1.0]) max([array]) max([f64, 1.0] ?? add) max([f64]) max([i]) max(abs(0)) max(abs(1)) max(abs(1.0)) max(abs(f64)) max(abs(i)) max(add ?? $env) max(add ?? f64) max(add ?? i) max(add(0, 0)) max(array ?? false) max(array ?? greet) max(array ?? i) max(array | find(false)) max(array | findLast(ok)) max(array | findLast(true)) max(array | get(i)) max(array | map(1.0)) max(array | map(i)) max(array | reduce(#index)) max(array | reduce($env)) max(array | reduce($env, 0)) max(array | reduce(0)) max(array | reduce(1.0, foo)) max(array | reduce(i)) max(array | sortBy(#)) max(array | sortBy(0)) max(array | sortBy(1)) max(array | sortBy(1.0)) max(array | sortBy(f64)) max(array | sum(0)) max(array | sum(i)) max(array) max(array) != array max(array) != i max(array) ** f64 max(array) ** i max(array) - f64 max(array) / median(1) max(array) == i max(array) == str max(array) > f64 max(array) ?? greet max(array) ?? ok max(array, abs(i)) max(array, array) max(array, f64) max(array, i) max(array, int(0)) max(array?.[1]) max(array?.[i]) max(array[:]) max(bitnand(i, i)) max(bitnot(0)) max(bitnot(1)) max(bitnot(i)) max(bitor(1, 1)) max(bitushr(0, 1)) max(bitxor(0, 0)) max(bitxor(1, 0)) max(ceil(0)) max(ceil(1)) max(ceil(1.0)) max(ceil(f64)) max(ceil(i)) max(concat(array)) max(count(array, true)) max(count(list, false)) max(count(list, ok)) max(f64 * 1.0) max(f64 * f64) max(f64 * i) max(f64 ** 0) max(f64 ** 1) max(f64 ** 1.0) max(f64 ** i) max(f64 + 0) max(f64 + 1) max(f64 + 1.0) max(f64 - 1.0) max(f64 - i) max(f64 / 0) max(f64 / 1) max(f64 / 1.0) max(f64 ?? $env) max(f64 ?? 0) max(f64 ?? 1.0) max(f64 ?? foo) max(f64 ?? greet) max(f64 ?? i) max(f64 ?? nil) max(f64 ?? ok) max(f64 ^ 1) max(f64 ^ 1.0) max(f64 ^ i) max(f64) max(f64) != f64 max(f64) ** f64 max(f64) / f64 max(f64) < i max(f64) <= 0 * f64 max(f64) <= f64 max(f64) == f64 max(f64) >= f64 max(f64) ?? add max(f64) ^ f64 max(f64) not in array max(f64, $env?.array) max(f64, 1.0 ** 1.0) max(f64, array) max(f64, array, array) max(f64, f64) max(f64, i) max(f64, median(0)) max(f64, min(1, 1)) max(false ? foo : 0) max(false ? nil : $env) max(false ? nil : array) max(false ? str : 0) max(false ?: foo) max(false ?? $env) max(false ?? 1.0) max(false ?? foo) max(findLast($env, false)) max(findLastIndex($env, true)) max(findLastIndex(array, false)) max(findLastIndex(array, ok)) max(findLastIndex(array, true)) max(findLastIndex(list, false)) max(first($env)) max(first(array)) max(first(array), array) max(flatten(array)) max(float(0)) max(float(1)) max(float(1.0)) max(float(f64)) max(float(i)) max(floor(1)) max(floor(1.0)) max(floor(i)) max(foo ?? $env) max(foo ?? $env[foo:]) max(foo ?? 0) max(foo ?? 1) max(foo ?? 1.0) max(foo ?? add) max(foo ?? array) max(foo ?? f64) max(foo ?? false) max(foo ?? greet) max(foo ?? i) max(foo ?? list) max(foo ?? ok) max(foo ?? true) max(get($env, nil)) max(greet ?? $env) max(greet ?? 0) max(greet ?? 1) max(greet ?? add) max(greet ?? array) max(greet ?? false) max(greet ?? foo) max(greet ?? list) max(i % 1) max(i % i) max(i * 0) max(i * 1) max(i * 1.0) max(i * i, i) max(i ** 0) max(i ** 1) max(i ** 1.0) max(i ** f64) max(i ** i) max(i + 0) max(i + 1.0) max(i + f64) max(i - 1) max(i - 1.0) max(i - i) max(i .. 0) max(i .. 1) max(i / 1) max(i / 1.0) max(i / i) max(i ?? 0) max(i ?? 1.0) max(i ?? add) max(i ?? list) max(i ?? nil) max(i ?? ok) max(i ?? true) max(i ^ 0) max(i ^ i) max(i | bitor(i)) max(i | bitshl(0)) max(i | max(1)) max(i | min(f64)) max(i) max(i) + f64 max(i) - f64 max(i) < f64 max(i) <= f64 max(i) >= i max(i) ?? str max(i) not in array max(i) | bitushr(i) max(i) | bitxor(0) max(i) | min(1.0) max(i, array) max(i, array, i) max(i, f64) max(i, i) max(i, min(1.0)) max(i..i) max(if false { 0 } else { nil }) max(if false { array } else { nil }) max(if false { ok } else { 1.0 }) max(if ok { $env } else { 1.0 }) max(if ok { foo } else { 1.0 }) max(if ok { ok } else { 0 }) max(if true { $env } else { f64 }) max(int(0)) max(int(1)) max(int(1.0)) max(int(f64)) max(int(i)) max(int(sum(array, 1.0))) max(last($env)) max(last($env)?.ok) max(last(array)) max(len($env)) max(len(array)) max(len(list)) max(len(str)) max(let foobar = f64; foobar) max(let tmp = $env; tmp) max(list | count(ok)) max(list | count(true)) max(list | filter(false)) max(list | map(f64)) max(list | reduce($env)) max(list) startsWith str and false max(map($env, #index)) max(map($env, 0)) max(map($env, 1.0)) max(map($env, array)) max(map(array, #index)) max(map(array, 1)) max(map(array, array)) max(map(array, f64)) max(map(list, 1)) max(map(list, i)) max(max($env)) max(max($env.array)) max(max($env?.Bar)) max(max(0)) max(max(1)) max(max(1.0)) max(max(array)) max(max(array?.[i])) max(max(f64)) max(max(f64, 1)) max(max(i)) max(mean(0)) max(mean(0, f64)) max(mean(1)) max(mean(1.0)) max(mean(1.0, 1.0)) max(mean(array)) max(mean(f64)) max(mean(i)) max(mean(i), array) max(median(0)) max(median(1)) max(median(1.0)) max(median(1.0, array)) max(median(array)) max(median(array, 1)) max(median(f64)) max(median(i)) max(min($env)) max(min(0)) max(min(1)) max(min(1.0)) max(min(1.0, array)) max(min(1.0, f64, i)) max(min(array)) max(min(f64)) max(min(i)) max(nil ?? $env) max(nil ?? 0) max(nil ?? 1) max(nil ?? 1.0) max(nil ?? f64) max(ok ? 1 : nil) max(ok ? 1.0 : 1) max(ok ? 1.0 : nil) max(ok ? add : $env) max(ok ? f64 : $env) max(ok ?? 1.0) max(ok ?? f64) max(ok ?? foo) max(ok ?? i) max(reduce($env, i, foo)) max(reduce(array, #)) max(reduce(array, #acc)) max(reduce(array, $env)) max(reduce(array, $env).String) max(reduce(array, 1.0)) max(reduce(list, 0)) max(reduce(list, 1.0)) max(reduce(list, f64)) max(reverse(array)) max(round(0)) max(round(1)) max(round(1.0)) max(round(f64)) max(round(i)) max(sort($env)) max(sort(array)) max(sortBy(array, #)) max(sortBy(array, 1)) max(str ?? 0) max(str ?? 1.0) max(str ?? array) max(str ?? foo) max(str ?? i) max(str ?? list) max(sum($env, 1)) max(sum($env, 1), i) max(sum($env, 1.0)) max(sum($env, f64)) max(sum($env?.[str])) max(sum(array)) max(sum(array, #)) max(sum(array, 1.0)) max(sum(list, f64)) max(sum(list, i)) max(true ? array : false) max(true ?: list) max(true ?? $env?.[str]) max(true ?? 1) max(true ?? add) max(true ?? foo) max(uniq(array)) max({foo: $env}?.add) max({foo: true, foo: str}?.list) mean($env | count(ok)) mean($env | filter(false)) mean($env | map(0)) mean($env | map(1.0)) mean($env | reduce(1, 1.0)) mean($env | reduce(1.0, greet)) mean($env | reduce(array, foo)) mean($env | reduce(i, nil)) mean($env | sum(0)) mean($env.array) mean($env.array, median(0)) mean($env.f64) mean($env.i) mean($env.i, i) mean($env.i, sort(array)) mean($env?.array) mean($env?.f64) mean($env?.f64, array) mean($env?.f64, f64) mean($env?.i) mean($env?.i, mean(f64)) mean(-0) mean(-1) mean(-1.0) mean(-f64) mean(-i) mean(0 % 1) mean(0 * 0) mean(0 * 1) mean(0 * 1.0) mean(0 * i) mean(0 ** 0) mean(0 ** 1) mean(0 ** f64) mean(0 ** f64, i) mean(0 + 0) mean(0 + f64) mean(0 + i) mean(0 - 0) mean(0 - 1.0) mean(0 - f64) mean(0 .. 0) mean(0 / 0) mean(0 / 1) mean(0 / 1, i) mean(0 / 1.0) mean(0 / i) mean(0 ?? $env) mean(0 ?? 0) mean(0 ?? 1) mean(0 ?? add) mean(0 ?? foo) mean(0 ?? foo, $env?.array) mean(0 ?? i) mean(0 ^ 0) mean(0 ^ f64) mean(0 ^ i) mean(0 | bitand(0)) mean(0) * f64 mean(0) .. i mean(0) / f64 mean(0) <= i mean(0) == f64 mean(0) | max(f64) mean(0, 1.0) >= 1 == nil mean(0..i) mean(0.1) mean(1 % 1) mean(1 % i) mean(1 * 0) mean(1 * 1.0, i) mean(1 * i) mean(1 ** 0) mean(1 + 1) mean(1 + 1.0) mean(1 + f64) mean(1 + i) mean(1 - i) mean(1 .. 0) mean(1 / 0) mean(1 / 1) mean(1 / 1.0) mean(1 / i) mean(1 ?? $env) mean(1 ?? 0) mean(1 ?? 1) mean(1 ?? 1.0) mean(1 ?? add) mean(1 ?? f64) mean(1 ?? false) mean(1 ?? foo) mean(1 ?? ok) mean(1 ?? str) mean(1 ?? true) mean(1 ^ 1) mean(1 ^ 1.0) mean(1 ^ f64) mean(1 ^ i) mean(1) * 1.0 ?? add mean(1) * i mean(1) ** i mean(1) <= f64 mean(1) == f64 mean(1) == i + 0 ^ f64 mean(1) ?? array mean(1) ?? i mean(1) ?? ok mean(1) ^ bitnot(1) mean(1) not in array mean(1, 1) * f64 mean(1, 1.0) < i mean(1, f64) / f64 mean(1..i) mean(1.0 * 0) mean(1.0 * 1) mean(1.0 * 1.0) mean(1.0 * i) mean(1.0 ** 0) mean(1.0 ** 1) mean(1.0 ** 1.0) mean(1.0 ** f64) mean(1.0 ** i) mean(1.0 + 1) mean(1.0 + 1.0) mean(1.0 + f64) mean(1.0 + i) mean(1.0 - 0) mean(1.0 - 1) mean(1.0 - 1.0) mean(1.0 - i) mean(1.0 / 1) mean(1.0 / 1.0) mean(1.0 / f64) mean(1.0 / i) mean(1.0 ?? $env) mean(1.0 ?? 1.0) mean(1.0 ?? add) mean(1.0 ?? array) mean(1.0 ?? false) mean(1.0 ?? foo) mean(1.0 ?? i) mean(1.0 ?? list) mean(1.0 ?? nil) mean(1.0 ?? str) mean(1.0 ^ 0) mean(1.0 ^ 1) mean(1.0 ^ 1.0) mean(1.0 ^ f64) mean(1.0 ^ i) mean(1.0 | max(1.0)) mean(1.0 | median(array)) mean(1.0) mean(1.0) * i mean(1.0) + i mean(1.0) / f64 mean(1.0) == $env or $env mean(1.0) > f64 mean(1.0) >= i mean(1.0) >= i || true mean(1.0) ?? findIndex($env, $env) mean(1.0) ?? greet mean(1.0) ?? list mean(1.0) ^ i mean(1.0) | max(1.0) mean(1.0) | max(array) mean(1.0, 1.0) < f64 mean(1.0, 1.0) ?? i mean(1.1) mean([0, 1.0]) mean([0, array]) mean([0]) mean([1.0]) mean([1]) mean([array, 0]) mean([array]) mean([f64, i]) mean([f64]) mean([i, 1.0]) mean([i]) mean(abs(-f64)) mean(abs(0)) mean(abs(1)) mean(abs(1.0)) mean(abs(f64)) mean(abs(i)) mean(abs(i), f64) mean(array ?? $env) mean(array ?? f64) mean(array ?? f64, array) mean(array ?? foo) mean(array ?? nil) mean(array | count(false)) mean(array | count(true)) mean(array | filter(ok)) mean(array | findLastIndex(ok)) mean(array | map(#index)) mean(array | map(array)) mean(array | map(i)) mean(array | max(0)) mean(array | max(1.0)) mean(array | mean(array)) mean(array | sortBy(#)) mean(array | sortBy(1)) mean(array | sum(#)) mean(array | sum(1.0)) mean(array) mean(array) != add mean(array) * f64 mean(array) .. i mean(array) < f64 mean(array) <= f64 mean(array) == list mean(array) >= f64 mean(array) >= f64 or ok mean(array) ?? i mean(array) not in array mean(array) | median(array) mean(array, -1.0) mean(array, array) mean(array, f64) mean(array, f64, i) mean(array, i) mean(array, int(1.0)) mean(array?.[0]) mean(array?.[1]) mean(array?.[i]) mean(array?.[i], i) mean(array[:0]) mean(array[i:0]) mean(bitand(0, i)) mean(bitnot(0)) mean(bitnot(1)) mean(bitnot(1)) ** f64 mean(bitnot(i)) mean(bitor(0, 0)) mean(bitushr(1, 1)) mean(ceil(0)) mean(ceil(1)) mean(ceil(1.0)) mean(ceil(abs(f64))) mean(ceil(f64)) mean(ceil(i)) mean(concat(array)) mean(f64 * 0) mean(f64 * 1) mean(f64 * 1.0) mean(f64 * i) mean(f64 ** 0) mean(f64 ** 1.0) mean(f64 ** i) mean(f64 + 1.0) mean(f64 + f64) mean(f64 - 1.0) mean(f64 - i) mean(f64 / 1.0) mean(f64 / f64) mean(f64 / i) mean(f64 ?? $env) mean(f64 ?? 1.0) mean(f64 ?? greet) mean(f64 ?? list) mean(f64 ^ 0) mean(f64 ^ 1.0) mean(f64 | min(1.0)) mean(f64) mean(f64) * i mean(f64) ** f64 mean(f64) - f64 mean(f64) > f64 mean(f64) > i mean(f64) in $env?.array mean(f64, 0) | median(1) mean(f64, 1) <= f64 mean(f64, array) mean(f64, f64) mean(f64, i) mean(f64, reduce(array, 1.0, nil)) mean(f64, round(i)) mean(f64, sum(array)) mean(false ? add : 1.0) mean(false ? i : f64) mean(false ?: 1) mean(filter($env, false)) mean(filter(array, ok)) mean(find(array, ok)) mean(findIndex($env, true)) mean(findIndex(array, true)) mean(findLastIndex($env, ok)) mean(findLastIndex($env, true)) mean(findLastIndex(array, true)) mean(findLastIndex(list, ok)) mean(first(array)) mean(first(array), i * i) mean(flatten(array)) mean(float(0)) mean(float(1)) mean(float(1.0)) mean(float(f64)) mean(float(float(f64))) mean(float(i)) mean(floor(0)) mean(floor(1)) mean(floor(1.0)) mean(floor(f64)) mean(floor(i)) mean(floor(len(str))) mean(i % 1) mean(i * 1) mean(i * 1.0) mean(i ** 0) mean(i ** 1.0) mean(i ** f64) mean(i ** i) mean(i + 0) mean(i + 1) mean(i + 1.0) mean(i + i) mean(i - 1.0) mean(i - f64) mean(i .. $env?.i) mean(i .. 1) mean(i .. i) mean(i / 1) mean(i / f64) mean(i / i) mean(i ?? $env) mean(i ?? 1.0) mean(i ?? array) mean(i ?? f64, i) mean(i ?? foo) mean(i ?? greet) mean(i ?? list) mean(i ?? nil) mean(i ?? str) mean(i ?? true) mean(i ^ 1.0) mean(i | bitxor(i)) mean(i | max(1, 1.0)) mean(i | mean(1.0)) mean(i) mean(i) / 1.0 ^ 1.0 mean(i) <= f64 mean(i) >= i mean(i) ?? $env?.[String] mean(i) ^ $env?.i mean(i) ^ f64 mean(i) in array mean(i, $env.f64) mean(i, -1.0) mean(i, 0) + f64 mean(i, 1 ** f64) mean(i, array) mean(i, f64) mean(i, float(f64)) mean(i, i) mean(i, int(0)) mean(if false { 1 } else { 0 }) mean(if ok { 0 } else { foo }) mean(if ok { 0 } else { nil }) mean(if ok { f64 } else { 1.0 }) mean(if true { 1.0 } else { foo }) mean(if true { f64 } else { false }) mean(int(0)) mean(int(1)) mean(int(1.0)) mean(int(f64)) mean(int(i)) mean(last(array)) mean(lastIndexOf(str, str)) mean(len($env)) mean(len(array)) mean(len(list)) mean(let z = f64; 1.0 + z) mean(let z = f64; z) mean(list | filter(false)) mean(list | map(1.0)) mean(list | reduce(1)) mean(list | reduce(array)) mean(list | reduce(f64)) mean(list | sum(1)) mean(map($env, 1)) mean(map($env, 1.0)) mean(map($env, array)) mean(map($env, f64)) mean(map(array, #)) mean(map(array, 0)) mean(map(array, f64)) mean(map(list, 0)) mean(map(list, array)) mean(map(list, f64)) mean(max(0)) mean(max(1.0)) mean(max(array)) mean(max(f64)) mean(max(i)) mean(max(i), i) mean(mean(0)) mean(mean(1)) mean(mean(1.0)) mean(mean(1.0, 0)) mean(mean(1.0, f64, i)) mean(mean(array)) mean(mean(f64)) mean(mean(f64, f64)) mean(mean(i)) mean(median(0)) mean(median(0, f64)) mean(median(1)) mean(median(1, 0)) mean(median(1, 1.0)) mean(median(1.0)) mean(median(1.0, f64)) mean(median(array)) mean(median(array, 0)) mean(median(array, 1)) mean(median(array, f64)) mean(median(f64)) mean(median(i)) mean(min(0)) mean(min(1)) mean(min(1, 1.0)) mean(min(1.0)) mean(min(1.0, array)) mean(min(array)) mean(min(f64)) mean(min(f64, array)) mean(min(i)) mean(nil ?? 0) mean(nil ?? 1) mean(nil ?? 1.0) mean(nil ?? array) mean(nil ?? f64) mean(reduce($env, 1.0, 1.0)) mean(reduce($env, i, greet)) mean(reduce(array, #)) mean(reduce(array, 1.0)) mean(reduce(array, array)) mean(reduce(array, f64, array)) mean(reduce(list, 1)) mean(reduce(list, array)) mean(reverse(array)) mean(round(0)) mean(round(1)) mean(round(1.0)) mean(round(f64)) mean(round(i)) mean(sort($env)) mean(sort(array)) mean(sortBy(array, #)) mean(sortBy(array, 0)) mean(sortBy(array, 1.0)) mean(sum($env, 1)) mean(sum($env, 1.0)) mean(sum($env, f64)) mean(sum(array)) mean(sum(array, #)) mean(sum(array, 0)) mean(sum(array, 1.0)) mean(true ? 0 : ok) mean(true ? 0 : str) mean(true ? 1.0 : 1) mean(uniq(array ?? 1.0)) mean(uniq(array)) median($env | count(false)) median($env | findIndex(true)) median($env | findLastIndex(ok)) median($env | map(1)) median($env | map(1.0)) median($env | map(i)) median($env | reduce(f64, greet)) median($env | sum(0)) median($env | sum(1.0)) median($env.array) median($env.array, f64) median($env.f64) median($env.f64, i) median($env.i) median($env.i, i) median($env?.array) median($env?.array, array) median($env?.f64) median($env?.i) median($env?.i, $env.i) median(-0) median(-1) median(-1.0 ?? true) median(-1.0) median(-f64) median(-i ?? {foo: foo}) median(-i) median(0 % 1) median(0 % i) median(0 * 0) median(0 * 1) median(0 * 1.0) median(0 * f64) median(0 * i) median(0 ** 0) median(0 ** 1.0) median(0 ** i) median(0 + 1) median(0 + 1.0) median(0 + i) median(0 - 0) median(0 - 1) median(0 - 1.0) median(0 .. 0) median(0 .. 1) median(0 .. i) median(0 / 0) median(0 / 1.0) median(0 / i) median(0 ?? $env) median(0 ?? f64) median(0 ?? false) median(0 ?? foo) median(0 ?? greet) median(0 ?? list) median(0 ?? nil) median(0 ^ $env.i) median(0 ^ 1) median(0 ^ 1.0) median(0 | max(1)) median(0) * i median(0) - f64 median(0) / f64 median(0) == f64 median(0) >= f64 median(0) >= i median(0) ?? trim($env) median(0) not in [nil] median(0, 0) ?? i median(0.0) median(0.1) median(1 % 1) median(1 * 0) median(1 * 1) median(1 * 1.0) median(1 * i) median(1 ** 0) median(1 ** 1) median(1 ** 1.0) median(1 ** i) median(1 + 0) median(1 + 1) median(1 + 1.0) median(1 + f64) median(1 + i) median(1 - 0) median(1 - 1) median(1 - 1.0) median(1 - f64) median(1 .. 0) median(1 / 1.0) median(1 / f64) median(1 / i) median(1 ?? $env) median(1 ?? array) median(1 ?? f64) median(1 ?? false) median(1 ?? foo) median(1 ?? greet) median(1 ?? str) median(1 ^ 0) median(1 ^ 0, f64) median(1 ^ 1.0) median(1 ^ f64) median(1 ^ i) median(1 | max(array), i) median(1 | min(array)) median(1) != 1.0 && ok median(1) != f64 median(1) ^ $env?.f64 median(1.0 * 0) median(1.0 * 1) median(1.0 * 1.0) median(1.0 * f64) median(1.0 * f64, array | sortBy(1)) median(1.0 * i) median(1.0 ** 0) median(1.0 ** 1.0) median(1.0 ** f64) median(1.0 ** i) median(1.0 + 0) median(1.0 + 1) median(1.0 + 1.0) median(1.0 + f64) median(1.0 + i) median(1.0 - 1) median(1.0 - 1.0) median(1.0 - f64) median(1.0 - i) median(1.0 / 0) median(1.0 / 1) median(1.0 / 1.0) median(1.0 / f64) median(1.0 / i) median(1.0 ?? $env) median(1.0 ?? 0, 1.0) median(1.0 ?? 1) median(1.0 ?? 1.0) median(1.0 ?? add) median(1.0 ?? false) median(1.0 ?? foo) median(1.0 ?? greet) median(1.0 ?? nil) median(1.0 ?? str) median(1.0 ^ 1) median(1.0 ^ f64) median(1.0 ^ i) median(1.0 | mean(i)) median(1.0) * 0 ?? nil median(1.0) * 1 + 1 median(1.0) * f64 median(1.0) ** f64 median(1.0) + 1.0 != f64 median(1.0) + i median(1.0) - f64 median(1.0) / f64 median(1.0) / i median(1.0) <= f64 median(1.0) <= i median(1.0) <= i / 0 median(1.0) == $env == false median(1.0) > 1.0 ? greet : list median(1.0) >= f64 median(1.0) ?? $env.ok median(1.0) ?? 1 ?? true median(1.0) ?? add median(1.0) ?? foo median(1.0) ?? greet median(1.0) ?? str median(1.0) in array median(1.0) not in array median(1.0) | max(f64) median(1.0) | max(i) median(1.0, 0) ** f64 median(1.0, 0) ** i median(1.0, 1.0) | mean(i, 0) median(1.1) median([0]) median([1 % i]) median([1, 1.0]) median([1.0]) median([1]) median([1], $env.f64) median([array]) median([f64]) median([i, 1.0]) median([i]) median(abs(0)) median(abs(1)) median(abs(1.0)) median(abs(f64)) median(abs(i)) median(add(1, 0)) median(array ?? add) median(array ?? array) median(array ?? f64) median(array ?? false) median(array ?? foo) median(array ?? nil) median(array ?? str) median(array | find(ok)) median(array | findLast(true)) median(array | map(#)) median(array | map(1.0)) median(array | reduce(1.0)) median(array | reduce(i, 1.0)) median(array | reduce(i, foo)) median(array | sortBy(#)) median(array | sortBy(i)) median(array | sum(#)) median(array) median(array) != add median(array) != ok median(array) ** f64 median(array) ** i median(array) + i median(array) - 1.0 + i median(array) / f64 median(array) < 0 >= 1.0 median(array) < i median(array) >= i median(array) ?? f64 median(array) ?? not ok median(array) ?? ok median(array) ^ f64 median(array) | get(nil) median(array, $env?.i) median(array, -0) median(array, -i) median(array, 1 ^ 1) median(array, array) median(array, array) not endsWith $env?.[Bar] median(array, f64) median(array, i % i) median(array, i .. 0) median(array, i) median(array?.[i]) median(array[0:]) median(array[1:]) median(bitand(1, 1)) median(bitnot(0)) median(bitnot(1)) median(bitnot(i)) median(bitxor(0, 0)) median(ceil($env.i)) median(ceil(0)) median(ceil(1.0)) median(ceil(f64)) median(ceil(i)) median(concat(array)) median(count($env, false)) median(count(array, ok)) median(count(array[0:0])) median(count(list, ok)) median(f64 * $env?.f64) median(f64 * 1.0) median(f64 * f64) median(f64 ** $env?.i) median(f64 ** 0) median(f64 ** 1) median(f64 ** 1.0) median(f64 + 0) median(f64 + 1.0) median(f64 + f64) median(f64 + i) median(f64 - 0) median(f64 - 1) median(f64 - 1.0) median(f64 - i) median(f64 / 0) median(f64 / 1.0) median(f64 / f64) median(f64 / i) median(f64 ?? 1) median(f64 ?? 1.0) median(f64 ?? array) median(f64 ?? date(foo)) median(f64 ?? false) median(f64 ?? i) median(f64 ?? str) median(f64 ^ 0) median(f64 ^ 1) median(f64 ^ 1.0) median(f64 ^ f64) median(f64 ^ i) median(f64 | min(1.0)) median(f64) median(f64) + i median(f64) < f64 median(f64) == 1.0 and ok median(f64) > i median(f64) ?? array median(f64, array) median(f64, array) / 0 == 0 median(f64, f64) median(f64, i) median(f64, i) + i median(f64, i, 1 - 0) median(f64, list | sum(i)) median(f64, min(f64)) median(filter(list, false)) median(find(array, ok)) median(findIndex($env, true)) median(findLastIndex($env, ok)) median(findLastIndex($env, true)) median(findLastIndex(list, true)) median(first(array)) median(flatten(array)) median(float(0)) median(float(1)) median(float(1.0)) median(float(f64)) median(float(i)) median(floor(0)) median(floor(1)) median(floor(1.0)) median(floor(f64)) median(floor(i)) median(i % i) median(i * 0) median(i * 1) median(i * 1.0) median(i * f64) median(i * i) median(i ** 0) median(i ** 1.0) median(i ** i) median(i + 0) median(i + 1) median(i - 1.0) median(i - i) median(i .. i) median(i / 0) median(i / 1.0) median(i ?? $env?.ok) median(i ?? 0) median(i ?? 1.0) median(i ?? foo?.Bar) median(i ?? i) median(i ?? ok) median(i ?? str) median(i ^ 0) median(i ^ 1.0) median(i ^ f64) median(i ^ i) median(i | bitnand(i)) median(i | bitshr(1)) median(i | min(f64)) median(i) median(i) * i median(i) ?? f64 median(i) ?? list median(i) ^ i median(i) in $env?.array median(i) | mean(array) median(i) | median(array) median(i) | min(f64) median(i, $env.i) median(i, -i) median(i, 1.0) < i median(i, array) median(i, f64) median(i, floor(1)) median(i, i) median(i..i) median(if false { $env } else { 1 }) median(if false { 1.0 } else { i }) median(if false { str } else { i }) median(int(1)) median(int(1.0)) median(int(1.0), array) median(int(f64)) median(int(i)) median(last(array)) median(len($env)) median(len(list)) median(len(str)) median(let bar = 1.0; let foobar = 0; bar) median(let bar = 1; bar) median(let foobar = 0; foobar) median(let z = 1; z) median(list | count(ok)) median(list | map(#index)) median(list | map(array)) median(list | reduce(i)) median(list | sum(0)) median(map($env, 0)) median(map($env, 1)) median(map($env, 1.0)) median(map($env, f64)) median(map(array, 1)) median(map(list, 0)) median(map(list, 1.0)) median(max(0)) median(max(1)) median(max(1.0)) median(max(1.0, i)) median(max(array)) median(max(i)) median(max(i), array) median(mean(0)) median(mean(1)) median(mean(1.0)) median(mean(1.0, i)) median(mean(array)) median(mean(f64)) median(mean(i)) median(median(0)) median(median(1)) median(median(1, 1.0)) median(median(1.0)) median(median(array)) median(median(f64)) median(median(f64, i)) median(median(i)) median(min(0 * 1)) median(min(0)) median(min(1)) median(min(1.0, array, 1)) median(min(array)) median(min(f64)) median(min(f64, 1.0)) median(min(i)) median(nil ?? 0) median(nil ?? 1) median(nil ?? 1.0) median(nil ?? f64) median(ok ? 1.0 : greet) median(reduce(array, #)) median(reduce(array, #index)) median(reduce(array, i)) median(reduce(list, #index)) median(reduce(list, 1.0)) median(reverse(array)) median(round(0)) median(round(1)) median(round(1.0)) median(round(f64)) median(round(i)) median(sort($env)) median(sort(array)) median(sortBy(array, 1)) median(sortBy(array, f64)) median(sum($env, 0)) median(sum($env, 1.0)) median(sum($env, f64)) median(sum($env, i)) median(sum(array)) median(sum(array), f64) median(sum(array), i) median(sum(array, #)) median(sum(array, 1.0)) median(sum(list, i)) median(true ? 0 : 1.0, f64) median(true ? 0 : ok) median(true ? i : foo) median(uniq(array)) median({foo: 1.0}?.foo) min($env ?? 0) min($env ?? 1)?.ok min($env ?? add) min($env ?? f64) min($env ?? false) min($env ?? foo) min($env ?? greet) min($env ?? i) min($env ?? ok) min($env ?? true) min($env | filter(false)) min($env | findIndex(false)) min($env | findIndex(true)) min($env | findLast(false)) min($env | get(str)) min($env | map(0)) min($env | map(1)) min($env | map(1.0)) min($env | reduce(array, 1)) min($env | sum(1.0)) min($env | sum(f64)) min($env | sum(i)) min($env) != array min($env) == greet min($env) == i min($env) == ok min($env) ?? uniq($env) min($env) matches $env?.foobar min($env) not contains $env || true min($env) not in list min($env) | all(false) min($env) | any(false) min($env) | count(ok) min($env) | map(1) min($env) | map(add) min($env) | map(f64) min($env) | map(false) min($env) | map(foo) min($env) | map(ok) min($env) | reduce(0, 1) min($env) | reduce(1.0, $env) min($env) | sum(0) min($env) | sum(1.0) min($env).Bar min($env).Bar?.greet() min($env).String min($env).String?.[greet] min($env).add min($env).array min($env).f64 min($env).false?.add min($env).false?.f64 min($env).foo min($env).foobar min($env).foobar?.i(foobar, foobar) min($env).foobar?.ok min($env).greet min($env).i min($env).i && false min($env).list min($env).nil?.foobar min($env).ok min($env).str min($env)?.$env?.Bar() min($env)?.Bar min($env)?.Bar?.foobar.foo().list min($env)?.String min($env)?.String?.foo min($env)?.[str] min($env)?.[str] not startsWith str min($env)?.add min($env)?.array min($env)?.f64 min($env)?.foo min($env)?.foobar min($env)?.foobar?.String() min($env)?.foobar?.foo.i min($env)?.foobar?.list min($env)?.foobar?.str min($env)?.greet min($env)?.greet(foobar) min($env)?.i min($env)?.list min($env)?.not min($env)?.ok min($env)?.str min($env)?.true?.f64(foobar) min($env.array) min($env.array, sum(array)) min($env.f64) min($env.i) min($env.i, i) min($env?.$env) min($env?.Bar) min($env?.Bar?.array()) min($env?.Bar?.foo) min($env?.Bar?.greet()) min($env?.String) min($env?.String)?.[i] min($env?.String?.list) min($env?.[Bar]) min($env?.[Bar])?.add() min($env?.[Bar]?.Bar) min($env?.[Bar]?.[greet]) min($env?.[Bar]?.i()) min($env?.[String]) min($env?.[String])?.f64 min($env?.[foobar]) min($env?.[foobar])?.[str] min($env?.[nil]) min($env?.[str]) min($env?.array) min($env?.f64) min($env?.f64, i) min($env?.false) min($env?.foobar) min($env?.i) min($env?.nil) min($env?.true) min(-0) min(-1) min(-1.0 ** 1) min(-1.0 + i) min(-1.0) min(-f64) min(-i) min(0 % 1) min(0 % i) min(0 * 0) min(0 * 1) min(0 * 1.0) min(0 * f64) min(0 * i) min(0 ** 0) min(0 ** 1.0) min(0 ** i) min(0 + 1) min(0 + 1.0) min(0 + f64) min(0 - 1) min(0 - 1.0) min(0 - f64) min(0 - i) min(0 .. 0) min(0 .. 1) min(0 .. i) min(0 / 0) min(0 / 1) min(0 ?? 1.0) min(0 ?? false) min(0 ?? foo) min(0 ?? true) min(0 ^ 0) min(0 ^ 1) min(0 | bitshl(1)) min(0 | median(1)) min(0) != $env?.i min(0) * 0 < f64 min(0) * f64 min(0) ** f64 min(0) + i min(0) - ceil(i) min(0) / f64 min(0) ^ f64 min(0) in array min(0) | max(0) min(0, array) != str min(0.0) min(1 % 1) min(1 * 1) min(1 * 1.0) min(1 ** 0) min(1 ** 1) min(1 ** 1.0) min(1 ** f64) min(1 ** i) min(1 + 0) min(1 + 1.0) min(1 - 1) min(1 - f64) min(1 .. i) min(1 / 0) min(1 / 1) min(1 / 1.0) min(1 / i) min(1 ?? 0) min(1 ?? 1.0) min(1 ?? add) min(1 ?? foo) min(1 ?? greet) min(1 ?? nil) min(1 ?? ok) min(1 ^ 0) min(1 ^ 1.0) min(1 ^ i) min(1 | min(1.0)) min(1) % i min(1) + f64 min(1) - i min(1) < f64 min(1) < i min(1) <= i min(1) ?? i min(1) not in array min(1) | median(array) min(1, 1) - i min(1, 1.0) in array min(1, array) | get(ok) min(1..i) min(1.0 * 0) min(1.0 * 1) min(1.0 * 1.0) min(1.0 * f64) min(1.0 ** 0) min(1.0 ** 1) min(1.0 ** 1.0) min(1.0 ** i) min(1.0 + 0) min(1.0 + 1) min(1.0 + 1.0) min(1.0 + i) min(1.0 - 0) min(1.0 - 1) min(1.0 - f64) min(1.0 - i) min(1.0 / 1) min(1.0 / 1.0) min(1.0 / f64) min(1.0 ?? $env?.[greet]) min(1.0 ?? 0) min(1.0 ?? 1) min(1.0 ?? add) min(1.0 ?? array) min(1.0 ?? f64) min(1.0 ?? foo) min(1.0 ?? list) min(1.0 ?? nil) min(1.0 ?? ok) min(1.0 ?? ok, array) min(1.0 ?? str) min(1.0 ?? true) min(1.0 ^ 0) min(1.0 ^ 1) min(1.0 ^ 1.0) min(1.0 ^ f64) min(1.0 ^ i) min(1.0 | max(0)) min(1.0 | max(1)) min(1.0 | max(array)) min(1.0 | mean(1.0)) min(1.0 | min(1.0)) min(1.0) * bitand(i, i) min(1.0) * f64 min(1.0) ** f64 min(1.0) ** i min(1.0) - f64 min(1.0) <= 1.0 + 0 min(1.0) > i min(1.0) >= i min(1.0) ?? add min(1.0) ?? f64 min(1.0) ?? greet min(1.0) ?? list min(1.0) ?? str min(1.0) ^ i min(1.0) not in array min(1.0) | max(array, 1.0) min(1.0) | median(array) min(1.0, 0) + i min(1.0, 0) ?? ok min(1.0, 1) - f64 min(1.0, 1.0) ** f64 ?? true min(1.0, 1.0) + i min(1.0, 1.0) - 0 < 1.0 min(1.0, 1.0) ^ f64 min(1.1) min([$env] | reduce(.f64)) min([0]) min([1.0]) min([1]) min([array]) min([f64, 0]) min([f64]) min([i]) min(abs(0)) min(abs(1)) min(abs(1.0)) min(abs(f64)) min(abs(i)) min(add ?? 1.0) min(add ?? array) min(add ?? f64) min(add ?? foo) min(add(0, 0)) min(add(1, 1)) min(array ?? $env?.[greet(f64)]) min(array ?? 0) min(array ?? nil) min(array | count(true)) min(array | filter(true)) min(array | find(ok)) min(array | findIndex(false)) min(array | findIndex(ok)) min(array | map(#)) min(array | map(i)) min(array | max(1.0, 0)) min(array | reduce(#)) min(array | reduce(0)) min(array | reduce(1.0)) min(array | sortBy(0)) min(array | sortBy(1.0)) min(array | sum(#)) min(array | sum(1.0)) min(array | sum(f64)) min(array) min(array) + f64 min(array) - i min(array) .. i min(array) / i min(array) < 1.0 - i min(array) == i min(array) ?? f64 min(array) ?? ok min(array) | bitushr(0) min(array) | get(0) min(array) | get(str) min(array) | median(0) min(array, 1 - 0) min(array, 1.0 ?? 0) min(array, array) min(array, array, 1) == f64 min(array, ceil(0)) min(array, f64 * i) min(array, f64) min(array, float(1.0)) min(array, i ?? 1.0) min(array, i) min(array, int(0)) min(array, sortBy(array, #)) min(array?.[0]) min(array?.[1]) min(array?.[i]) min(array[0:]) min(array[:0])?.[greet] min(array[min(1):]) min(bitnot(0)) min(bitnot(1)) min(bitnot(i)) min(ceil(0)) min(ceil(1)) min(ceil(1.0)) min(ceil(f64)) min(ceil(i)) min(ceil(sum(array)), i) min(count($env, false)) min(count($env, ok)) min(count([true])) min(count(array, false)) min(f64 * 0) min(f64 * 1) min(f64 * f64) min(f64 * i) min(f64 ** 1) min(f64 ** 1.0) min(f64 ** f64) min(f64 ** i) min(f64 + 0) min(f64 + 1.0) min(f64 + f64) min(f64 - 0) min(f64 - 1.0) min(f64 - i) min(f64 / 0) min(f64 / 1) min(f64 / 1.0) min(f64 ?? $env) min(f64 ?? 1) min(f64 ?? 1.0) min(f64 ?? add, i) min(f64 ?? array) min(f64 ?? false) min(f64 ?? foo) min(f64 ?? ok) min(f64 ?? true) min(f64 ^ 0) min(f64 ^ 1) min(f64 ^ 1.0) min(f64 ^ f64) min(f64 ^ i) min(f64 | min(0)) min(f64) min(f64) * i min(f64) / f64 min(f64) < i min(f64) <= $env.i min(f64) >= i min(f64) ?? greet min(f64) not in array min(f64) | median(1.0) min(f64, $env.array) min(f64, $env.f64) min(f64, -1) min(f64, 0) == f64 min(f64, 1.0 / 1.0) min(f64, abs(f64)) min(f64, array) min(f64, f64) min(f64, i) min(f64, min(1.0)) min(false ? 0 : greet) min(false ? 0 : nil) min(false ? 1 : 1.0) min(false ? array : nil) min(false ? foo : $env).i min(false ? greet : foo) min(false ?: 0) min(false ?? 1.0) min(false ?? add) min(false ?? array) min(false ?? list) min(findIndex($env, false)) min(findIndex($env, true)) min(findIndex(array, true)) min(findIndex(list, false)) min(findLast(array, false)) min(findLast(array, true)) min(findLastIndex($env, false)) min(findLastIndex($env, true)) min(first($env)) min(first(array)) min(first(str ?? add)) min(flatten(array)) min(flatten(array), f64) min(float(0)) min(float(1)) min(float(1.0)) min(float(f64)) min(float(i)) min(floor(1.0 + i)) min(floor(1.0)) min(floor(f64)) min(floor(i)) min(foo ?? $env) min(foo ?? 0) min(foo ?? 1) min(foo ?? add) min(foo ?? f64) min(foo ?? false) min(foo ?? greet) min(foo ?? list) min(foo ?? ok) min(foo ?? str) min(foo ?? true) min(greet ?? 1.0) min(greet ?? add) min(greet ?? f64) min(greet ?? foo) min(groupBy(array, #)?.array) min(i % 1) min(i % i) min(i * 0) min(i * f64) min(i * i) min(i + 1.0) min(i + f64) min(i + i) min(i - 0) min(i - 1.0) min(i - f64) min(i - i) min(i .. 0) min(i / 1.0) min(i ?? $env) min(i ?? f64) min(i ?? false) min(i ?? foo) min(i ?? ok) min(i ?? str) min(i ?? true) min(i ^ 1.0) min(i ^ i) min(i | bitor(0)) min(i | bitshr(1)) min(i | min(0)) min(i) min(i) != $env?.i min(i) != f64 min(i) % i min(i) < f64 min(i) < i min(i) <= f64 min(i) == f64 min(i) ?? [0] min(i) ?? foo min(i) ?? foo.Bar min(i) ?? foo?.Bar min(i, $env.i) min(i, 1 ?? 0) min(i, [1]) min(i, array) min(i, array) .. i min(i, array) ^ i <= 1.0 min(i, f64 ** 1) min(i, f64 / i) min(i, f64) min(i, i) min(i, max(sum(array))) min(if false { nil } else { 0 }) min(if false { ok } else { array }) min(if true { 1 } else { $env }) min(if true { 1.0 } else { true }) min(if true { false } else { foo }) min(if true { greet } else { 1.0 }) min(int(0)) min(int(1)) min(int(1.0)) min(int(f64)) min(int(i)) min(last($env)) min(last(array)) min(len($env)) min(len(array)) min(len(list)) min(len(str)) min(list | count(false)) min(list | count(true)) min(list | findIndex(false)) min(list | map(1)) min(list | map(1.0)) min(list | map(i)) min(list | reduce($env)) min(list | reduce(1)) min(list | reduce(1.0)) min(list | reduce(array)) min(list | sum(1)) min(list[1:1]) min(map($env, 0)) min(map($env, 1.0)) min(map($env, array)) min(map(array, #)) min(map(array, #index)) min(map(array, 1.0)) min(map(list, #index)) min(map(list, f64)) min(max($env)) min(max(0)) min(max(0, 1)) min(max(0, 1.0, 0)) min(max(0, i)) min(max(1)) min(max(1.0)) min(max(1.0, 1.0)) min(max(array)) min(max(f64)) min(max(i)) min(mean(0)) min(mean(1)) min(mean(1.0)) min(mean(1.0, 1.0)) min(mean(array)) min(mean(f64)) min(mean(i)) min(median(0)) min(median(1)) min(median(1.0)) min(median(array)) min(median(f64)) min(median(i)) min(min($env)) min(min(0)) min(min(1)) min(min(1.0)) min(min(1.0, 1)) min(min(f64)) min(min(f64, 1.0)) min(min(f64, 1.0, 1.0)) min(min(i)) min(nil ?? $env) min(nil ?? f64) min(nil ?? i) min(ok ? array : true) min(ok ?: 1.0) min(ok ?? 1) min(ok ?? i) min(ok ?? toJSON(list)) min(reduce(array, #)) min(reduce(array, $env))?.str min(reduce(array, 1.0)) min(reduce(array, i)) min(reduce(list, 1.0)) min(reduce(list, f64)) min(reduce(list, f64), $env?.array) min(reverse(array)) min(round(0)) min(round(0), array) min(round(1)) min(round(1.0)) min(round(f64)) min(round(i)) min(sort($env)) min(sort(array)) min(sortBy(array, #)) min(sortBy(array, 1)) min(sortBy(array, f64)) min(sortBy(array, str), i) min(sortBy(array, toJSON(foo))) min(str ?? $env) min(str ?? 1.0) min(str ?? false) min(str ?? foo) min(str ?? i) min(str ?? list) min(sum($env, 1)) min(sum($env, 1.0)) min(sum($env?.array)) min(sum(array)) min(sum(array), array) min(sum(array, #)) min(sum(array, 1.0)) min(sum(list, 1)) min(sum(list, f64)) min(true ? 0 : foo) min(true ? 1.0 : str) min(true ? nil : $env) min(true ? nil : i) min(true ?: add) min(true ?: foo) min(true ?? 1) min(true ?? foo) min(true ?? list) min(true ?? str) min(uniq(array)) min({foo: 0}.foo) min({foo: 1.0}.array) min({foo: add}.i) min({foo: i}?.i) min({foo: nil}?.i) min({foo: str}?.list) min({foo: sum(array)}.array) nil != $env ?? add nil != $env.add nil != $env.array nil != $env.f64 nil != $env.foo nil != $env.greet nil != $env.i nil != $env.list nil != $env.ok nil != $env.str nil != $env?.Bar nil != $env?.Bar?.[i] nil != $env?.Bar?.list() nil != $env?.Bar?.str() nil != $env?.String nil != $env?.String?.[i] nil != $env?.[1.0 | first(nil)] nil != $env?.[Bar] nil != $env?.[Bar]?.Bar nil != $env?.[String] nil != $env?.[String]?.foo nil != $env?.[foobar] nil != $env?.[greet(foobar)] nil != $env?.[str] nil != $env?.add nil != $env?.array nil != $env?.array && true nil != $env?.f64 nil != $env?.false?.[str] nil != $env?.foo nil != $env?.foobar nil != $env?.foobar?.greet(1.0) nil != $env?.greet nil != $env?.i nil != $env?.list nil != $env?.ok nil != $env?.str nil != 0 && ok nil != 0 ** i nil != 0 - i nil != 0 / f64 nil != 0 ?: array nil != 0 ^ $env?.i nil != 1 % i nil != 1 + f64 nil != 1 + i nil != 1 ?? foo nil != 1 ^ i nil != 1.0 && ok nil != 1.0 + f64 nil != 1.0 - f64 nil != 1.0 ?: reduce($env, #.String, true) nil != 1.0 ?? ok nil != 1.0 ^ f64 nil != 1.0 and ok nil != 1.0 or 1.0 == 1 nil != add ?? ok nil != add and ok nil != array ?: i ^ 1.0 nil != array ?? i nil != array?.[i] nil != f64 + i nil != f64 - f64 == nil nil != f64 / f64 && ok nil != f64 ?? -1 nil != f64 ?? foo nil != f64 not in $env?.String nil != f64 or i == i nil != false == ok nil != false ?? add nil != false ?? foo nil != false || $env > $env nil != foo == ok nil != foo ?: greet nil != foo ?: list nil != foo ?? foo nil != foo or $env?.[add] nil != foo || 1 == $env?.[ok] nil != foo || i == f64 nil != foo.Bar nil != foo.String nil != foo.String() nil != foo?.Bar nil != foo?.String nil != foo?.String() nil != greet && false != nil nil != greet == ok nil != greet ?: i nil != greet ?? add nil != i && f64 < 1.0 nil != i + i nil != i .. $env?.i nil != i ?? greet nil != list or one($env, #.f64) nil != list?.[-i] nil != list?.[i] nil != list?.[i]?.Bar nil != list?.[i]?.String nil != list[:] nil != nil && $env?.[array] nil != nil && ok nil != nil ?? array nil != nil ?? i nil != nil ?? str nil != ok || abs($env) nil != str && get($env, nil) nil != str ?? foo nil != str or $env * i nil != str[:] nil != true ?? i nil != true || $env == 1.0 nil == $env ?? add nil == $env ?? array nil == $env ?? ok nil == $env ?? str == false nil == $env or f64 < 1.0 nil == $env.add nil == $env.array nil == $env.f64 nil == $env.foo nil == $env.greet nil == $env.i nil == $env.list nil == $env.ok nil == $env.str nil == $env?.Bar nil == $env?.String nil == $env?.String?.[list] nil == $env?.String?.ok nil == $env?.[Bar] nil == $env?.[String] nil == $env?.[foo.Bar] nil == $env?.[foobar?.[i]] nil == $env?.[foobar?.array] nil == $env?.[foobar] nil == $env?.[str] nil == $env?.add nil == $env?.array nil == $env?.f64 nil == $env?.foo nil == $env?.foobar nil == $env?.foobar?.add(foobar, foobar) nil == $env?.foobar?.i nil == $env?.greet nil == $env?.i nil == $env?.list nil == $env?.nil?.[foo] nil == $env?.ok nil == $env?.str nil == 0 != foo ?? greet nil == 0 ** 1.0 ? nil : nil nil == 0 ?? $env?.add nil == 0 || ok nil == 1 * i nil == 1 + f64 nil == 1 / i nil == 1 and find($env, #.add)?.[i] nil == 1 || 0 > i nil == 1..i nil == 1.0 ** f64 nil == 1.0 + f64 nil == 1.0 ?: i nil == 1.0 ?: str nil == 1.0 ?? string(nil) nil == 1.0 ^ f64 nil == 1.0 and ok nil == add ?: i nil == add and ok nil == add or foo ?? f64 nil == array ?? add nil == array?.[i] nil == f64 * f64 nil == f64 + f64 nil == f64 - f64 nil == f64 ?: ok nil == f64 ?? greet nil == false && list != $env nil == false ?? array nil == foo != foo ?? greet nil == foo != ok nil == foo ?: i nil == foo ?? 1.0 ?? true nil == foo ?? add nil == foo ?? greet($env) nil == foo and ok nil == foo.Bar nil == foo.String nil == foo.String() nil == foo?.Bar nil == foo?.String nil == foo?.String() nil == greet != $env?.Bar nil == greet ?? map($env, #.f64) nil == greet and $env?.[list] nil == greet or ok nil == i != ok nil == i + i nil == i and ok nil == i in $env?.[String] nil == list ?? list nil == list?.[i] nil == list[:] nil == nil != $env?.[String] nil == nil != nil || false nil == nil and ok nil == ok != ok nil == str != false || true nil == str ?? add nil == true ?? ok nil ?? $env ?? $env?.[array][foobar:] nil ?? $env ?? str nil ?? $env | findLastIndex(true) nil ?? $env | map(0) nil ?? $env | map(1) nil ?? $env | map(1.0) nil ?? $env | map(add) nil ?? $env | map(list) nil ?? $env | one(ok) nil ?? $env | sum(f64) nil ?? $env.add nil ?? $env.array nil ?? $env.f64 nil ?? $env.foo nil ?? $env.greet nil ?? $env.i nil ?? $env.list nil ?? $env.ok nil ?? $env.str nil ?? $env?.Bar nil ?? $env?.String nil ?? $env?.[Bar] nil ?? $env?.[String] nil ?? $env?.[foobar] nil ?? $env?.[str] nil ?? $env?.add nil ?? $env?.array nil ?? $env?.f64 nil ?? $env?.foo nil ?? $env?.foobar nil ?? $env?.foobar?.i nil ?? $env?.greet nil ?? $env?.i nil ?? $env?.list nil ?? $env?.ok nil ?? $env?.str nil ?? 0 | min(1.0) nil ?? 1 ?? array nil ?? 1.0 ?? trimSuffix(str) nil ?? array ?? str nil ?? array | groupBy(1.0) nil ?? array | map(#) nil ?? array | map(true) nil ?? array | one(ok) nil ?? array | reduce(#, false) nil ?? array | reduce(greet, $env) nil ?? array | reduce(list) nil ?? array | sortBy(1.0) nil ?? array | sum(i) nil ?? array?.[i] nil ?? f64 ?? i nil ?? foo ?? $env.list nil ?? foo.Bar nil ?? foo.String nil ?? foo.String() nil ?? foo?.Bar nil ?? foo?.String nil ?? foo?.String() nil ?? greet ?? add nil ?? i | median(f64) nil ?? list ?? add nil ?? list ?? {foo: foo} nil ?? list | groupBy(#) nil ?? list | groupBy(ok) nil ?? list | groupBy(true) nil ?? list | map(f64) nil ?? list | map(str) nil ?? list | reduce(#acc) nil ?? list | reduce(1.0, $env) nil ?? list | sortBy(.Bar) nil ?? list | sum(0) nil ?? list?.[i] nil ?? nil ?? foo nil ?? ok ?? ok nil ?? str ?? str nil ?? str | repeat(0) nil in $env != ok nil in $env ?? str nil in $env or ok nil in $env.array nil in $env.list nil in $env?.Bar nil in $env?.Bar?.[greet] nil in $env?.String nil in $env?.[Bar] nil in $env?.[Bar]?.[array] nil in $env?.[String] nil in $env?.[String]?.list nil in $env?.[foobar?.f64] nil in $env?.[foobar] nil in $env?.array nil in $env?.foobar?.i(false) nil in $env?.list nil in array ?? greet nil in array ?? toJSON(str) nil in list && ok nil in list and $env == foo nil in list and ok nil in list or ok nil not in $env ?: str nil not in $env or ok nil not in $env || 0 <= $env nil not in $env.array nil not in $env.list nil not in $env?.$env?.ok nil not in $env?.Bar nil not in $env?.Bar?.str nil not in $env?.String nil not in $env?.String?.greet nil not in $env?.[Bar] nil not in $env?.[String] nil not in $env?.[foobar] nil not in $env?.array nil not in $env?.foobar?.[list] nil not in $env?.foobar?.add(nil, f64) nil not in $env?.list nil not in array != ok nil not in array ?: i nil not in list[i:] nil; $env.greet nil; $env.ok nil; array | reduce(1.0, 1.0) none($env | map($env), .f64 != foo) none($env, false) != ok none($env, false) && ok == true none($env.array, # == 1.0) none($env.array, str not in $env) none($env.list, 1.0 <= 1.0) none($env?.[str], 1 > f64) none($env?.[str], ok) none($env?.list, f64 == $env) none($env?.list, ok) none(1 .. 0, $env < $env) none(1 .. 0, $env | all(ok)) none(1 .. i, !false) none([$env, foo], false != #) none([$env], .f64 in #.String) none([1.0], ok) none([array, false], true and ok) none([f64, nil], ok) none([false], #) none([greet, 1.0], ok) none([nil, foo], ok) none(array | map(0), ok) none(array, !true) none(array, # != #) none(array, # != 0) none(array, # != nil) none(array, # < #) none(array, # < 1) none(array, # <= #) none(array, # == 0) none(array, # == nil) none(array, # > #) none(array, # >= #) none(array, # >= f64) none(array, # >= i) none(array, $env == foo) none(array, $env || true) none(array, $env.ok) none(array, 0 <= 0) none(array, 1 == #) none(array, 1.0 != 1.0) none(array, 1.0 < #) none(array, 1.0 <= #) none(array, 1.0 == $env) none(array, add == add) none(array, f64 == #) none(array, false ?? add) none(array, foo != nil) none(array, i != #) none(array, i != nil) none(array, i < #) none(array, i >= #) none(array, nil != 1) none(array, nil == add) none(array, nil == false) none(array, nil == i) none(array, not false) none(array, ok && false) none(array, ok ?? i) none(array, ok) none(concat(array), f64 >= #) none(flatten(array), ok) none(if true { list } else { greet }, list != list) none(list ?? ok, ok) none(list | map($env), #.ok) none(list | map(str), ok) none(list, # != foo) none(list, # == #) none(list, $env != $env) none(list, $env != i) none(list, $env != nil) none(list, $env.ok) none(list, $env?.ok) none(list, .Bar not in #) none(list, .Bar startsWith str) none(list, 1 == f64) none(list, 1.0 > 1.0) none(list, array == $env) none(list, f64 != $env) none(list, f64 == 1.0) none(list, false != true) none(list, false ?? #) none(list, false and false) none(list, foo != #) none(list, foo != foo) none(list, foo == #) none(list, foo == foo) none(list, i == 1) none(list, nil == list) none(list, not true) none(list, ok == $env) none(list, ok) none(list, ok) || ok none(list, str < .Bar) none(list, true == $env) none(list, true || true) ?? i none(list, true) != ok none(map($env, 1.0), ok) none(map(list, $env), ok) none(reverse(array), not false) none(sort($env), #.add?.greet(foo)) none(sort($env), #.f64 != 1.0) none(sort($env), #.ok not in #) none(sort($env), not #.f64) none(sort($env), sortBy(.Bar, #.greet)) none(str ?? $env, ok) none(str ?? ok, f64 >= #) none(toPairs($env), # in #) not !$env.ok not !false not !ok not !true not !true or true not $env && false not $env and false not $env or true not $env || true not $env.ok not $env?.ok not all($env, false) not all($env, ok) not all($env, true) not all(array, false) not all(array, true) not all(list, ok) not all(list, true) not any($env, false) not any($env, ok) not any($env, true) not any(array, ok) not any(array, true) not any(list, ok) not false != $env not false != false not false != nil not false != ok not false != true not false && $env not false && false not false && ok not false && true not false == $env not false == false not false == nil not false == true not false ? 0 / 1 : ok not false ? 1.0 : foo not false ? add : foo not false ? foo : foo not false ? greet : nil not false ? list : 1.0 not false ? nil : 1.0 not false ? ok : i not false ? ok : nil not false ?: 1.0 not false ?: add not false ?: nil not false ?: ok not false ?? $env not false ?? 0 not false ?? 1 not false ?? 1.0 not false ?? add not false ?? array not false ?? f64 not false ?? false not false ?? findLastIndex($env, #.foo) not false ?? foo not false ?? greet not false ?? i not false ?? list not false ?? nil not false ?? not $env not false ?? ok not false ?? one(list, ok) not false ?? str not false ?? true not false and $env not false and false not false and ok not false not in $env or true not false not in $env?.Bar not false or $env not false or false not false or false != $env not false or not true not false or ok not false or true not false || $env not false || false not false || last($env) not false || ok not false || true not max($env).ok not nil ?? false not nil ?? ok not nil ?? true not none($env, false) not none($env, ok) not none($env, true) not none(array, false) not none(array, ok) not none(array, true) not none(list, false) not none(list, ok) not not !false not not $env.ok not not $env?.ok not not false not not not false not not ok not not ok != false not not true not not true and ok not ok not ok != $env not ok != 1.0 ?? i not ok != false not ok != nil not ok != ok not ok != true not ok && $env not ok && $env?.[list] not ok && 1.0 ?? split($env, str) not ok && false not ok && ok not ok && true not ok == $env not ok == false not ok == false != $env not ok == foo ?? $env not ok == nil not ok == ok not ok == true not ok ? $env : str not ok ? 1 : $env not ok ? 1.0 : 1.0 not ok ? 1.0 : add not ok ? 1.0 : foo not ok ? 1.0 : ok not ok ? f64 : 1.0 not ok ? f64 : foo not ok ? foo : nil not ok ? i : 1.0 not ok ? list : 1 not ok ? nil : 0 not ok ? nil : array not ok ? nil : foo not ok ? ok : $env not ok ? ok : $env?.add not ok ? ok : foo not ok ? true : $env not ok ? true : 0 not ok ?: $env not ok ?: 1.0 not ok ?: array not ok ?: foo not ok ?: list not ok ?? $env.f64 not ok ?? $env?.[foo] not ok ?? 0 not ok ?? 0 == $env not ok ?? 1 not ok ?? 1.0 not ok ?? [$env, list] not ok ?? add not ok ?? array not ok ?? f64 not ok ?? f64 ?: greet not ok ?? false not ok ?? foo not ok ?? foo.String not ok ?? greet not ok ?? i not ok ?? list not ok ?? nil not ok ?? nil || ok not ok ?? ok not ok ?? str not ok ?? true not ok and $env not ok and false not ok and foo in list not ok and ok not ok and true not ok not in $env?.[String] not ok or $env not ok or $env?.[str] not ok or false not ok or ok not ok or true not ok || $env not ok || false not ok || ok not ok || true not ok; nil not one($env, false) not one($env, ok) not one($env, true) not one(array, false) not one(array, true) not one(list, false) not one(list, ok) not one(list, true) not reduce(array, false) not reduce(array, ok) not reduce(array, true) not reduce(list, true) not true != $env not true != false not true != nil not true != nil or $env not true != ok not true != true not true && $env not true && $env == $env not true && 0 * $env not true && false not true && not true not true && ok not true && true not true == $env not true == false not true == nil not true == ok not true == true not true ? 0 : foo not true ? 1.0 : $env not true ? 1.0 : nil not true ? f64 : 1 not true ? greet : list not true ? str : array not true ?: $env not true ?: 0 not true ?: 1 not true ?: 1.0 not true ?: add not true ?: greet not true ?: nil not true ?: ok not true ?? $env not true ?? $env.add not true ?? $env.list not true ?? $env?.[Bar] not true ?? $env?.ok not true ?? $env[:$env | now(greet)] not true ?? $env[:foobar].i not true ?? 0 not true ?? 1 not true ?? 1.0 not true ?? add not true ?? array not true ?? f64 not true ?? false not true ?? floor($env) not true ?? foo not true ?? greet not true ?? i not true ?? list not true ?? nil not true ?? ok not true ?? str not true ?? str && true not true ?? true not true and $env not true and false not true and ok not true and true not true in $env?.[foobar] not true or $env not true or $env?.String not true or $env?.[Bar] not true or false not true or ok not true or true not true || $env not true || $env?.String not true || $env?.[String] not true || false not true || ok not true || true ok ok != !false ok != !ok ok != !true ok != $env != $env ok != $env != ok ok != $env && $env ok != $env == ok ok != $env ?? foo ok != $env ?? ok ok != $env and $env ok != $env or nil not in $env ok != $env.ok ok != $env?.Bar ok != $env?.String ok != $env?.String?.[i] ok != $env?.[Bar] ok != $env?.[String] ok != $env?.[foobar] ok != $env?.[nil] ok != $env?.[str] ok != $env?.foobar ok != $env?.foobar?.greet ok != $env?.ok ok != any($env, ok) ok != any(array, false) ok != array ?? f64 ok != false && $env ok != false ? 1.0 : foo ok != false ? list : 0 ok != false ?? findLastIndex($env, #) ok != false or false ok != false or true ok != false; false ok != greet ?? foo ok != i ?? sum($env, #) ok != nil && ok ok != nil == ok ok != nil == ok and ok ok != nil ? f64 : 1 ok != nil ?? false ok != nil ?? true ok != nil and $env ok != nil and 1 <= 1 ok != nil or false ok != not false ok != not true ok != ok ok != ok != nil ok != ok == nil ok != ok ? str : str ok != reduce(list, ok) ok != str ?? f64 ok != str ?? i ok != sum($env?.[str]) ok != true != nil ok != true != true ok != true && $env ok != true && ok ok != true == $env ok != true ? 1.0 : $env ok != true ?? foo ok != true and $env?.Bar ok && !true ok && $env != $env ok && $env != array ok && $env != nil ok && $env != str ok && $env == foo ok && $env == greet ok && $env ?? greet ok && $env ?? ok ok && $env not in $env?.array ok && $env not in array ok && $env.ok ok && $env?.Bar ok && $env?.String ok && $env?.String?.String ok && $env?.String?.list ok && $env?.[Bar] ok && $env?.[Bar]?.[array] ok && $env?.[Bar]?.add ok && $env?.[String] ok && $env?.[String]?.foo ok && $env?.[foobar?.Bar] ok && $env?.[foobar] ok && $env?.[str] ok && $env?.foobar ok && $env?.ok ok && 0 < 0 ok && 0 < 1 ok && 0 == 0 ok && 0 >= f64 ok && 0 ?? add ok && 1 != i ok && 1 <= 1.0 ok && 1 == 1 ok && 1 == f64 ok && 1 ?? foo ok && 1.0 != $env ok && 1.0 != 1.0 ok && 1.0 != f64 ok && 1.0 < f64 ok && 1.0 == f64 ok && 1.0 > 1 ok && 1.0 >= f64 ok && 1.0 ?? 0 ok && 1.0 ?? foo ok && 1.0 ?? list ok && add != $env ok && add != $env?.String ok && add == nil ok && add ?? list ok && add ?? true ok && all(list, false) ok && array == array ok && array ?? !$env ok && array ?? f64 ok && array ?? false ok && array ?? greet ok && f64 != nil ok && f64 > 1 or $env ok && f64 > 1.0 ok && foo != foo ok && foo != nil ok && foo == $env ok && foo ?? $env ok && foo ?? i ok && foo ?? ok ok && greet == nil ok && i < 1 ok && i <= f64 ok && i == i ok && i >= 1 ok && i not in array ok && list == $env ok && list ?? greet ok && max($env) ok && max(array) ok && mean(array) ok && median(array) ok && min(array) ok && nil != $env ok && nil != add ok && nil == i ok && nil == nil ok && nil == true ok && nil ?? $env ok && nil in array ok && not $env?.ok ok && not true ok && ok ok && ok && $env?.[str] ok && ok == $env ok && ok == ok ok && ok == true ok && ok ?? 1.0 ok && ok and $env ok && ok or false ok && ok || false ok && one(list, false) ok && str == nil ok && str endsWith str ok && str not in $env ok && str not startsWith str ok && str startsWith str ok && true != ok ok && true ?? 0 ok && true ?? foo ok && true ?? max(i, 1.0) ok && true ?? true ok && true or false ok && true || $env?.String ok == !true ok == $env && $env ok == $env && ok ok == $env ? nil : foo ok == $env ?? 0 ok == $env ?? 1 ok == $env ?? 1.0 == false ok == $env ?? ok ok == $env and ok ok == $env and true ok == $env || false ok == $env || ok ok == $env.ok ok == $env?.Bar ok == $env?.Bar?.[str] ok == $env?.String ok == $env?.String?.[greet] ok == $env?.[Bar] ok == $env?.[Bar]?.[array] ok == $env?.[String] ok == $env?.[foobar] ok == $env?.[str] ok == $env?.false ok == $env?.foobar ok == $env?.nil ok == $env?.ok ok == 1.0 ?? $env ok == 1.0 ?? array ok == any($env, false) ok == array ?? $env ok == array ?? 0 ok == f64 ?? array ok == f64 ?? i ok == false != nil ok == first($env) ok == foo ?? i ok == foo ?? ok ok == i ?? f64 ok == i ?? min($env) ok == list ?? greet ok == list ?? ok ok == max(array) ok == mean(array) ok == min($env) ok == nil != false ok == nil != ok ok == nil != true ok == nil == nil ok == nil ? 1.0 : $env ok == not false ok == not ok ok == not true ok == ok ok == ok != $env ok == ok ? nil : $env ok == ok || true ok == str ?? true ok == true != ok ok == true && $env ok == true == $env ok == true ?? false ok == true and ok ok == true in find($env, false) ok ? $env : $env * $env | map(i) ok ? $env : $env >= 1.0 | date(ok, true) ok ? $env : $env | find(.f64) ok ? $env : $env | map(1.0) ok ? $env : $env?.Bar ok ? $env : $env?.String() ok ? $env : $env?.[Bar] ok ? $env : $env?.[String] ok ? $env : $env?.[add] ok ? $env : $env?.[str] ok ? $env : $env?.array ok ? $env : $env?.ok ok ? $env : 0 not in array ok ? $env : foo.Bar ok ? $env : foo?.Bar ok ? $env?.String : str ok ? $env?.[String] : add ok ? 0 : $env.list ok ? 0 : $env?.f64 ok ? 0 : $env?.foo ok ? 0 : $env?.ok ok ? 0 : foo?.Bar ok ? 1 : $env.add ok ? 1 : $env?.[f64] ok ? 1 : $env[timezone(array):] ok ? 1.0 : $env | groupBy(#.str) ok ? 1.0 : $env.add ok ? 1.0 : $env.array ok ? 1.0 : $env.list ok ? 1.0 : $env?.Bar ok ? 1.0 : $env?.[array] ok ? 1.0 : $env?.array ok ? 1.0 : $env?.greet ok ? 1.0 : $env?.i ok ? 1.0 : $env?.list ok ? 1.0 : 1.0 * f64 ok ? 1.0 : f64 ?? list ok ? 1.0 : list | groupBy($env) ok ? add : $env | groupBy(#.list) ok ? add : $env | map(foo) ok ? add : $env | none(#) ok ? add : $env.array ok ? add : $env.f64 ok ? add : $env.greet ok ? add : $env?.Bar() ok ? add : $env?.[String] ok ? add : $env?.[greet] ok ? add : $env?.ok ok ? add : add ok ? add : array | reduce(1.0) ok ? add : f64 ok ? add : foo.Bar ok ? add : foo?.String ok ? add : greet ok ? add : i ok ? add : list | find($env?.Bar) ok ? add : list | reduce(#) ok ? add : nil in -$env ok ? add : nil in array ok ? add : str ok ? array : $env | sum(#) ok ? array : $env?.add ok ? array : add ok ? array : foo ok ? array : list | min(i) ok ? array : ok ok ? array : sum(array) ok ? f64 - 0 : $env not contains $env ok ? f64 : $env.foo ok ? f64 : $env.i ok ? f64 : $env.ok ok ? f64 : $env[bitxor(foobar):] ok ? f64 : f64 ok ? f64 : foo ok ? f64 : foo?.String ok ? f64 : foo?.String() ok ? f64 : keys($env) ok ? f64 : list ?? str ok ? f64 : str ok ? f64 : uniq($env) ok ? false : $env.foo ok ? false : $env?.[Bar] ok ? false : $env?.[add] ok ? false : $env?.[i] ok ? false : $env?.list ok ? false : foo.Bar ok ? false : list?.[i] ok ? foo : $env endsWith str ok ? foo : $env not endsWith $env?.true ok ? foo : $env | groupBy(.list) ok ? foo : $env | groupBy(i) ok ? foo : $env | sum(#.foo) ok ? foo : $env.add ok ? foo : $env.greet ok ? foo : $env.i ok ? foo : $env?.Bar() ok ? foo : $env?.String ok ? foo : $env?.[f64] ok ? foo : $env?.[find(foobar, .f64)] ok ? foo : $env?.[foo] ok ? foo : $env?.add ok ? foo : $env?.array ok ? foo : $env?.foobar?.String() ok ? foo : $env?.greet ok ? foo : add ok ? foo : array ok ? foo : array | reduce(false) ok ? foo : array?.[i] ok ? foo : foo ok ? foo : foo?.Bar ok ? foo : foo?.String ok ? foo : list ok ? foo not in list : array ok ? foo.String : str ok ? greet : $env.str ok ? greet : $env?.f64 ok ? greet : array ok ? greet : f64 ok ? greet : foo ok ? greet : foo?.String() ok ? greet : groupBy($env, greet)?.[i] ok ? greet : i ok ? greet : list | mean(nil) ok ? greet : sortBy($env, 1) ok ? greet : str ok ? greet : string($env) ok ? greet : {foo: true} ok ? i : $env?.[greet] ok ? i : $env?.i ok ? i : foo ok ? i : foo.Bar ok ? i : list ok ? i : list?.[i] ok ? i : str ok ? list : $env.i ok ? list : $env[fromBase64(foo, foo):] ok ? list : add ok ? list : f64 ok ? list : foo ok ? list : foo.String ok ? list : i ok ? list : nil ?? list ok ? list : ok ok ? list : str ok ? nil != $env : str ok ? nil : $env not matches $env?.[i] ok ? nil : $env | mean($env) ok ? nil : $env.foo ok ? nil : $env.ok ok ? nil : $env?.String ok ? nil : $env?.[String] ok ? nil : $env?.[f64] ok ? nil : $env?.[greet] ok ? nil : $env?.[list] ok ? nil : $env?.[ok] ok ? nil : $env?.greet ok ? nil : $env?.i ok ? nil : $env?.ok ok ? nil : $env?.str ok ? nil : foo.Bar ok ? nil : foo.String ok ? ok != $env : 1 < 1.0 ok ? ok : $env | filter(one(array, ok)) ok ? ok : $env.list ok ? ok : $env?.[array] ok ? ok : $env?.greet ok ? ok : false and ok ok ? ok : foo ok ? ok : foo | date(list) ok ? ok : foo?.String ok ? ok : i ok ? ok : list?.[i] ok ? ok : ok ok ? reduce($env, $env, true) : foo?.Bar ok ? str : $env | findLastIndex(#) ok ? str : $env?.String(i)?.ok ok ? str : $env?.[Bar] ok ? str : $env?.foo ok ? str : $env?.ok ok ? str : add ok ? str : f64 ok ? str : foo ok ? str : ok ok ? true : $env | groupBy(sortBy(#, 1)) ok ? true : array?.[i] ok ? true : foo?.String ok ? true : foo?.String() ok ? true ?: 0 : str ok ?: $env ?? $env ok ?: $env not endsWith str ok ?: $env not matches $env ok ?: $env | any(.Bar) ok ?: $env | filter(.Bar) ok ?: $env | find(#.str) ok ?: $env | map(#.Bar) ok ?: $env | max(add) ok ?: $env | one(#.Bar) ok ?: $env | reduce(#) ok ?: $env | sortBy(.i != #) ok ?: $env | sortBy(foo) ok ?: $env.add ok ?: $env.array ok ?: $env.f64 ok ?: $env.foo ok ?: $env.ok ok ?: $env.str ok ?: $env?.Bar ok ?: $env?.[Bar] ok ?: $env?.[Bar]?.str ok ?: $env?.[String] ok ?: $env?.[add] ok ?: $env?.[array] ok ?: $env?.[f64] ok ?: $env?.[foo] ok ?: $env?.[greet] ok ?: $env?.[i] ok ?: $env?.[ok] ok ?: $env?.[str] ok ?: $env?.add ok ?: $env?.array ok ?: $env?.f64 ok ?: $env?.foo ok ?: $env?.greet ok ?: $env?.i ok ?: $env?.list ok ?: $env?.str ok ?: $env[foobar not in list:] ok ?: $env[foobar:] ok ?: 1 % 1 ok ?: 1.0 | date($env) ok ?: 1.0 | date(1) ok ?: add ok ?: all($env, .f64) ok ?: array ok ?: array | sum(greet) ok ?: array?.[i] ok ?: ceil(f64) ok ?: count($env) ok ?: count(array) ok ?: count(list) ok ?: date(array) ok ?: date(false) ok ?: date(list) ok ?: f64 ok ?: foo ok ?: foo not in $env ok ?: foo?.Bar ok ?: foo?.String ok ?: foo?.String() ok ?: fromJSON(str) ok ?: greet ok ?: greet($env) ok ?: i ok ?: i == 1 ok ?: i >= i ok ?: int(1.0) ok ?: list ok ?: list | findIndex($env) ok ?: list | none(true) ok ?: max(list) ok ?: nil != str ok ?: nil in $env ok ?: ok ok ?: ok | date(add, f64) ok ?: str ok ?: str matches findLast($env, #) ok ?: str startsWith $env ok ?: sum($env) ok ?: sum(array, 0) ok ?: {foo: list} ok ?? !$env ok ?? !false ok ?? !ok ok ?? !true ok ?? $env ?: list | min(add, add) ok ?? $env ?? f64 ok ?? $env ?? true ok ?? $env | get(f64) ok ?? $env.add ok ?? $env.array ok ?? $env.f64 ok ?? $env.foo ok ?? $env.greet ok ?? $env.i ok ?? $env.list ok ?? $env.ok ok ?? $env.str ok ?? $env?.Bar ok ?? $env?.Bar() ok ?? $env?.String ok ?? $env?.String($env) ok ?? $env?.String(str) ok ?? $env?.String.Bar ok ?? $env?.String.add ok ?? $env?.String?.[ok] ok ?? $env?.String?.list() ok ?? $env?.[0 + foo] ok ?? $env?.[1 ** foobar] ok ?? $env?.[1.0 < list] ok ?? $env?.[Bar] ok ?? $env?.[Bar]?.array ok ?? $env?.[String] ok ?? $env?.[String].f64 ok ?? $env?.[String].ok ok ?? $env?.[String]?.ok ok ?? $env?.[add] ok ?? $env?.[array] ok ?? $env?.[array]?.f64 ok ?? $env?.[f64] ok ?? $env?.[foo and i] ok ?? $env?.[foo] ok ?? $env?.[foo]?.[i] ok ?? $env?.[foobar?.[greet]] ok ?? $env?.[foobar?.array()] ok ?? $env?.[greet] ok ?? $env?.[i] ok ?? $env?.[list] ok ?? $env?.[list]?.ok ok ?? $env?.[ok] ok ?? $env?.[ok]?.[i] ok ?? $env?.[str] ok ?? $env?.[true ** 0] ok ?? $env?.add ok ?? $env?.all(foobar, nil, list) ok ?? $env?.array ok ?? $env?.f64 ok ?? $env?.foo ok ?? $env?.greet ok ?? $env?.i ok ?? $env?.list ok ?? $env?.ok ok ?? $env?.str ok ?? $env[:f64] ok ?? $env[array not matches foobar:] ok ?? $env[array.list:foo(String)] ok ?? $env[foobar not matches false:foobar] ok ?? $env[foobar.ok:] ok ?? $env[greet:foobar?.[greet]] ok ?? $env[i:] ok ?? $env[nil:Bar] ok ?? $env[str():] ok ?? $env[str(foobar):] ok ?? -$env ok ?? -$env?.[ok] ok ?? -0 ok ?? -1 ok ?? -1.0 ok ?? -f64 ok ?? -i ok ?? 0 ?? $env ok ?? 0 ?? foo ok ?? 1 ?: f64 ok ?? 1 ?? $env ok ?? 1.0 ?? $env.add ok ?? 1.0 ?? ok ok ?? 1.0 | get($env) ok ?? [1.0] ok ?? add ok ?? add ?? i ok ?? add(i, 1) ok ?? all($env, #.str) ok ?? all($env, .Bar) ok ?? any($env, .str) ok ?? array ok ?? array ?? str ok ?? bitnot($env) ok ?? bitnot(i) ok ?? ceil(1.0) ok ?? concat($env) ok ?? count($env) ok ?? count($env, #.add) ok ?? count(array) ok ?? count(list) ok ?? date(1.0) ok ?? date(ok) ok ?? f64 ok ?? f64 ?? false ok ?? f64 ?? i ok ?? false ? $env : f64 ok ?? find($env, #.foo) ok ?? find($env, .ok) ok ?? find(array, ok) ok ?? findIndex($env, .array) ok ?? findLastIndex($env, #) ok ?? findLastIndex($env, #.list) ok ?? findLastIndex($env, .list) ok ?? first($env) ok ?? flatten($env) ok ?? float(0) ok ?? float(1.0) ok ?? float(str) ok ?? foo ok ?? foo ?? $env?.Bar() ok ?? foo ?? array ok ?? foo ?? list ok ?? foo ?? lower($env) ok ?? foo.Bar ok ?? foo.String ok ?? foo.String() ok ?? foo?.Bar ok ?? foo?.String ok ?? foo?.String() ok ?? greet ok ?? greet ? greet : greet ok ?? greet ?? nil ok ?? greet ?? str ok ?? greet($env) ok ?? greet(str) ok ?? groupBy($env, $env)?.i ok ?? groupBy($env, .foo) ok ?? groupBy($env, .greet) ok ?? groupBy($env, .list) ok ?? groupBy($env, i) ok ?? groupBy(array, #) ok ?? groupBy(array, foo) ok ?? i ok ?? i ?? ok ok ?? i ?? str ok ?? int(i) ok ?? len(list) ok ?? list ok ?? list ? ok : 1.0 ok ?? list?.[i] ok ?? max(0, $env)?.[add] ok ?? min(array) ok ?? nil ? false : foo ok ?? nil ?? 1 ok ?? nil ?? add ok ?? nil ?? array ok ?? none($env, #) ok ?? none(list, $env) ok ?? not $env ok ?? not 1.0 ?? foo ok ?? not false ok ?? not ok ok ?? not true ok ?? ok ok ?? round($env) ok ?? sort($env) ok ?? sortBy($env, #) ok ?? sortBy(array, #) ok ?? str ok ?? str ?? array ok ?? str ?? f64 ok ?? str ?? ok ok ?? str | get(false) ok ?? string(add) ok ?? string(ok) ok ?? sum($env) ok ?? sum($env, #) ok ?? sum($env, #.f64)?.[add] ok ?? sum(array) ok ?? sum(list) ok ?? sum(uniq($env)) ok ?? timezone($env) ok ?? toBase64($env) ok ?? toJSON(0) ok ?? toJSON(1.0) ok ?? toJSON(foo) ok ?? toJSON(true) ok ?? toPairs($env) ok ?? trimPrefix($env) ok ?? true ?? list ok ?? type($env) ok ?? type(f64) ok ?? type(greet) ok ?? type(ok) ok ?? {foo: 1} ok ?? {foo: i} ok ?? {foo: nil} ok ?? {foo: ok} ok and !true ok and $env != 0 ok and $env != 1.0 ok and $env != false ok and $env != list ok and $env == f64 ok and $env == list ok and $env ?? f64 ok and $env in array ok and $env || false ok and $env.ok ok and $env?.Bar ok and $env?.Bar?.f64 ok and $env?.Bar?.foobar ok and $env?.String ok and $env?.[Bar] ok and $env?.[Bar]?.[foo] ok and $env?.[Bar]?.array ok and $env?.[String] ok and $env?.[String]?.[add] ok and $env?.[foobar] ok and $env?.[str] ok and $env?.foobar ok and $env?.foobar?.[foo] ok and $env?.nil?.f64 ok and $env?.ok ok and 0 != nil ok and 0 < i ok and 0 <= f64 ok and 1 < 1.0 ok and 1 < i ok and 1 <= f64 ok and 1.0 != f64 ok and 1.0 != i ok and 1.0 <= i ok and 1.0 ?? $env ok and 1.0 ?? $env.foo ok and 1.0 not in array ok and add == $env ok and array != array ok and array ?? f64 ok and f64 not in array ok and false && $env ok and false == $env ok and false ? $env : $env ok and false ?? 1.0 ok and first($env) ok and foo != foo ok and foo == nil ok and foo ?? $env.ok ok and foo ?? $env?.String() ok and foo ?? true ok and greet == nil ok and greet not in $env?.[Bar] ok and i < i ok and i == f64 ok and i >= 1.0 ok and i ?? add ok and i ^ 1 != 1.0 ok and last($env) ok and list ?? [i] ok and list ?? foo ok and nil != false ok and nil != foo ok and nil != ok ok and nil == $env ok and nil == add ok and nil == f64 ok and nil == true ok and nil not in array ok and not ok ok and not true ok and ok ok and ok ? add : i ok and ok ?? $env ok and one(list, ok) ok and str == string(foo) ok and str matches toJSON(1.0) ok and str not endsWith str ok and str not startsWith str ok and true != false ok and true && $env ok and true ?? add ok and true ?? str ok and true and $env ok and true || $env.ok ok and {foo: i}?.foo ok in $env && false ok in $env?.Bar ok in $env?.String ok in $env?.[Bar] ok in $env?.[String] ok in $env?.[foobar] ok in $env?.foobar ok in $env?.foobar?.[add] ok in [$env, 1] ok in [false] ok in [ok] ok in concat(array) ok in first($env) ok in flatten(array) ok in last($env) ok in sort(array) ok not in $env || true ok not in $env?.Bar ok not in $env?.Bar?.list ok not in $env?.String ok not in $env?.String?.greet ok not in $env?.[Bar] ok not in $env?.[Bar]?.[foo] ok not in $env?.[Bar]?.ok() ok not in $env?.[String] ok not in $env?.[String]?.String ok not in $env?.[foobar] ok not in $env?.false?.[i] ok not in $env?.foobar?.[array] ok not in $env?.foobar?.[list] ok not in $env?.true || false ok not in [0, nil] ok not in [false] ok not in [ok] ok not in [true] ok not in array ?? greet ok not in groupBy(list, i) ok not in last($env) ok not in list ?? add ok not in list ?? greet ok not in map($env, false) ok not in values($env) ok or !false ok or !ok ok or !true ok or $env != 1 ok or $env != nil ok or $env * 1.0 ok or $env * f64 ok or $env + $env?.str ok or $env - $env ok or $env - 1 ok or $env - 1.0 ok or $env < i ok or $env <= $env.f64 ok or $env <= $env?.[f64] ok or $env == $env ok or $env == $env?.foo ok or $env == 1 ok or $env == array ok or $env == list ok or $env == ok ok or $env > str ok or $env >= i ok or $env >= str ok or $env ?: ok ok or $env and $env?.String ok or $env and 1 != $env ok or $env endsWith str ok or $env in $env ok or $env in list ok or $env not in foo ok or $env not in str ok or $env not startsWith str ok or $env or $env ok or $env or ok ok or $env || true ok or $env.ok ok or $env?.Bar ok or $env?.Bar() ok or $env?.Bar(list()) ok or $env?.Bar(list) ok or $env?.Bar(one(foobar, false)) ok or $env?.String ok or $env?.String() ok or $env?.String(1, f64) ok or $env?.String(1.0, i)?.f64 ok or $env?.[$env]?.ok(foobar?.str) ok or $env?.[1.0 not matches f64] ok or $env?.[1] ok or $env?.[Bar] ok or $env?.[Bar].array ok or $env?.[Bar]?.[list] ok or $env?.[Bar]?.greet ok or $env?.[String] ok or $env?.[String].list ok or $env?.[add] ok or $env?.[add]?.array ok or $env?.[add]?.ok ok or $env?.[array($env)] ok or $env?.[array] ok or $env?.[array].ok ok or $env?.[f64] ok or $env?.[f64].i ok or $env?.[foo not in foobar] ok or $env?.[foo] ok or $env?.[foobar or 1] ok or $env?.[foobar] ok or $env?.[foobar]?.add ok or $env?.[greet()] ok or $env?.[greet] ok or $env?.[greet] < str ok or $env?.[i] ok or $env?.[i].String ok or $env?.[list] ok or $env?.[list]?.add() ok or $env?.[ok | reduce(foo)] ok or $env?.[ok()] ok or $env?.[ok] ok or $env?.[ok]?.add ok or $env?.[sortBy(foobar, $env)] ok or $env?.[str] ok or $env?.[str]?.[f64] ok or $env?.[str]?.list ok or $env?.ok ok or $env?.upper(1.0, 0, foo) ok or $env[$env:foobar]?.[foo]?.[foo] ok or $env[:1.0 ^ false].str ok or $env[:foo?.list] ok or $env[:foo] ok or $env[:greet?.f64] ok or $env[:indexOf(greet)] ok or $env[:nil .. add] ok or $env[:str] ok or $env[add.Bar():] ok or $env[foo:] ok or $env[foobar.foo(nil):f64?.[foo]] ok or $env[foobar:] ok or $env[list:] ok or $env[nil matches i:foobar not startsWith foobar] ok or $env[not foobar:ok] ok or $env[ok():] ok or $env[ok:] ok or -$env ok or -i ?? add ok or 0 < $env ok or 0 == nil ok or 0 == nil ? 0 : array ok or 0 >= $env?.[array] ok or 0 >= 1.0 ok or 1 + $env?.[i] ok or 1 <= 1.0 ok or 1 <= i ok or 1 > $env?.[String] ok or 1 > 0 ok or 1 >= 1.0 ok or 1 ?? ok ok or 1.0 != $env ok or 1.0 != nil ok or 1.0 < 0 ok or 1.0 < 1.0 ok or 1.0 < f64 ok or 1.0 <= $env ok or 1.0 <= f64 ok or 1.0 <= f64 + 1 ok or 1.0 == $env ok or 1.0 >= $env ok or 1.0 >= 1 ok or 1.0 ?? 1 ok or 1.0 ?? list ok or 1.0 in $env ok or abs($env) ok or add == $env.add ok or add ?? array ok or array != nil ok or array ?? 0 ok or f64 < 1 ok or f64 <= i ok or f64 == nil ok or f64 > $env ok or f64 > $env?.[array] ok or f64 > 1 ok or f64 > f64 ok or f64 >= 0 ok or f64 ?? $env ok or false && ok ok or false ? foo : foo ok or false ?: foo ok or false ?? 1.0 ok or false or ok ok or false || false ok or find($env, #) ok or find($env, .greet) ok or find($env, .str) ok or foo != $env.foo ok or foo != foo ok or foo == foo ok or foo ?? $env ok or foo ?? list ok or foo in $env ok or foo in list ok or foo in sum($env) ok or foo not in groupBy($env, 1) ok or fromJSON($env) ok or fromJSON(str) ok or greet != $env ok or greet == $env ok or greet not in $env ok or i != nil ok or i < i ok or i == nil ok or i ?? foo ok or last($env) ok or list ?? true ok or mean(array) ok or nil != $env ok or nil != add ok or nil != foo ok or nil != i ok or nil != str ok or nil == add ok or nil == array ok or nil == str ok or nil in array ok or nil not in $env?.[Bar] ok or none($env, #) ok or not $env ok or not $env?.Bar()?.String ok or not $env?.[str] ok or not ok ok or ok ok or ok != true ok or ok == false ok or ok ?? nil ok or ok ?? not ok ok or ok or ok ok or reduce($env, ok) ok or sortBy($env, 1.0) ok or sortBy($env, true)?.array?.[array] ok or str + $env ok or str == $env ok or str == $env?.[str]?.String ok or str not endsWith $env ok or str not in foo ok or sum($env) ok or true && false ok or true == $env?.[String] ok or true == nil ok or true ?? $env ok or true ?? list ok or true ?? true ok or true or $env?.String(i) ok or true || ok ok or {foo: nil}?.i ok || !$env ok || !false ok || !ok ok || !true ok || $env != f64 ok || $env != false ok || $env != i ok || $env != nil ? foo : array ok || $env && $env ok || $env + 1.0 ok || $env + i ok || $env < $env ok || $env < -1.0 ok || $env < false ?? 1.0 ok || $env <= 0 ok || $env <= i ok || $env == $env ok || $env == 1.0 ok || $env == list ok || $env >= $env.f64 ok || $env >= str ok || $env contains $env?.[Bar].Bar ok || $env contains str ok || $env endsWith $env?.[list] ok || $env matches $env ok || $env matches str ok || $env not contains str ok || $env not in str ok || $env not matches $env ok || $env or false ok || $env || $env ok || $env || ok ok || $env.ok ok || $env?.$env ok || $env?.$env.str ok || $env?.Bar ok || $env?.Bar() ok || $env?.String ok || $env?.String() ok || $env?.String()[:ok]?.foo ok || $env?.String(all(foobar, #.list)) ok || $env?.String(first(foobar)) ok || $env?.String(foo()) ok || $env?.String.greet ok || $env?.String?.ok()?.array ok || $env?.[Bar] ok || $env?.[String?.Bar] ok || $env?.[String] ok || $env?.[String]?.Bar ok || $env?.[add] ok || $env?.[add]?.[i] ok || $env?.[add]?.i ok || $env?.[all(foobar, foobar)] ok || $env?.[array] ok || $env?.[array].list ok || $env?.[f64] ok || $env?.[f64].str(list?.[ok]) ok || $env?.[findLastIndex(i, .String)] ok || $env?.[foo] ok || $env?.[foo].f64 ok || $env?.[foo]?.str ok || $env?.[foobar startsWith foobar] ok || $env?.[foobar | take(foobar)] ok || $env?.[foobar?.i] ok || $env?.[foobar] ok || $env?.[greet] ok || $env?.[greet]?.String ok || $env?.[greet]?.f64 ok || $env?.[i] ok || $env?.[i].str ok || $env?.[i]?.[foo] ok || $env?.[list] ok || $env?.[list].add ok || $env?.[list]?.[greet] ok || $env?.[nil endsWith list] ok || $env?.[ok] ok || $env?.[str()] ok || $env?.[str] ok || $env?.[str].list ok || $env?.foobar ok || $env?.foobar.String ok || $env?.ok ok || $env?.sortBy(nil) ok || $env?.toPairs(add, true) ok || $env[$env:Bar] ok || $env[1.0:] ok || $env[:String()] ok || $env[:add()] ok || $env[:array | none(false)] ok || $env[:foo] ok || $env[:foobar] ok || $env[Bar(foo):add and foobar] ok || $env[Bar?.[str]:date($env)] ok || $env[add():] ok || $env[add:foobar] ok || $env[f64.ok:array(foobar, foobar, String)] ok || $env[f64:ok(true)] ok || $env[false .. String:] ok || $env[foo:foobar] ok || $env[foobar:] ok || $env[foobar?.list:] ok || $env[greet:$env?.Bar] ok || $env[i(foobar):Bar .. foo] ok || $env[map(foo, foobar):] ok || $env[str?.add:groupBy(i, foobar)] ok || 0 - $env ok || 0 == $env ok || 0 == 1 ok || 0 == 1.0 ok || 0 > 1.0 ok || 0 ?? $env[:String()] ok || 0 ?? ok ok || 1 < findLast($env, #.ok) ok || 1 > 1 ok || 1 >= $env?.[foo] ok || 1.0 != 1.0 ok || 1.0 != f64 ok || 1.0 * $env ok || 1.0 - $env?.[ok] ok || 1.0 <= 0 ok || 1.0 <= 1 ok || 1.0 <= i ok || 1.0 == 1 ok || 1.0 == 1.0 ok || 1.0 ?? add ok || 1.0 ?? array ok || 1.0 ?? i ok || 1.0 in $env ok || 1.0 in $env?.String ok || add == $env?.[foo] ok || add ?? str ok || add not in $env ok || any($env, #) ok || any($env, .list) ok || any($env, false) ok || array != nil ok || array ?? 1.0 ok || f64 != $env ok || f64 != f64 ok || f64 + $env ok || f64 < $env ok || f64 < 1.0 ok || f64 < i ok || f64 <= 1 ok || f64 == f64 ok || f64 > $env ok || f64 > 1 ok || false ?: foo ok || false and false ok || false not in sum(list, $env) ok || findLast($env, #.String) ok || findLast($env, $env) ok || foo != nil ok || foo == $env ok || foo == $env[:false] ok || foo == foo ok || foo == nil ok || foo ?? array ok || foo ?? list ok || foo ?? not true ok || foo not in list ok || fromJSON($env) ok || greet != nil ok || greet == $env ok || greet ?? array ok || greet ?? i ok || i * $env ok || i + $env ok || i < f64 ok || i == 1 ok || i > i ok || i >= $env ok || i >= 1.0 ok || last($env) ok || list != list ok || list ?? i ok || list ?? str ok || max(i, list) ok || max(list, greet) ok || mean(list | sortBy(greet)) ok || mean(list) ok || median($env)?.greet ok || median(array) ok || median(array, 1) ok || median(array, str) ok || min($env) ok || nil != -1.0 ok || nil != 1 ok || nil != add ok || nil != greet ok || nil != i ok || nil != nil ok || nil != true ok || nil == $env.array ok || nil == 1.0 ok || nil == false ok || nil == nil ?? 1 ok || nil ?? $env?.[f64] ok || nil in $env?.String ok || nil in array ok || nil not in array ok || none(array, $env) ok || not $env ok || not ok ok || ok ok || ok == nil ok || ok == ok ok || ok ?: foo ok || ok ?? [nil] ok || ok || $env ok || one($env, .add) ok || reduce($env, .foo) ok || sortBy($env, array).str ok || sortBy($env, i, str) ok || str != $env ok || str != nil ok || str != str ok || str + $env ok || str <= str ok || str ?? array ok || str contains $env ok || str contains str ok || str endsWith $env ok || str endsWith str ok || str in $env ok || str matches $env ok || str not in foo ok || sum($env) ok || sum($env, .list) ok || true != nil ok || true && $env ok || true ?? add ok || true and $env ok || true and true ok || true || $env?.[greet] ok || {foo: nil}?.add ok; 0 ?? 1 ok; add ok; f64 ok; foo ok; foo.String ok; foo?.String; groupBy(list, #) ok; greet ok; list ok; list | sortBy(i) ok; list?.[i] ok; ok ok; str ok; true != $env one($env ?? nil, false == $env) one($env | map(true), ok) one($env, true) ?: greet one($env, true) || $env?.Bar one($env.array, nil != true) one($env?.[str], # in list) one($env?.[str], list == #) one($env?.[str], ok) one($env?.array, $env == #) one($env?.array, ok) one($env?.list, 0 <= 1.0) one($env?.list, ok) one([$env], #.ok) one([$env], .array != add) one([false], 0 <= f64) one([foo], ok) one([i], ok) one([ok], #) one([str], none($env, false)) one([true, foo], ok) one(array ?? nil, ok) one(array, !ok) one(array, # != #) one(array, # < #) one(array, # <= 0) one(array, # <= 1) one(array, # == 1) one(array, # > #) one(array, # > 0) one(array, # >= #) one(array, # not in array) one(array, $env != #) one(array, $env != ok) one(array, $env && false) one(array, $env == list) one(array, $env.ok) one(array, $env?.ok) one(array, 0 == 0) one(array, 0 >= 0) one(array, 1 == 1.0) one(array, 1 >= #) one(array, 1.0 < #) one(array, 1.0 <= #) one(array, 1.0 > #) one(array, 1.0 >= #) one(array, f64 != nil) one(array, f64 == i) one(array, false and $env?.[ok]) one(array, false) != $env?.ok one(array, false) != ok one(array, foo == foo) one(array, greet == nil) one(array, i != $env) one(array, i <= f64) one(array, list != $env) one(array, nil != #) one(array, nil != add) one(array, nil in $env) one(array, nil not in list) one(array, ok) one(array, ok) and $env[greet:] one(array, ok) or ok one(array, str == str) one(array, str > str) one(array, true ?? i) one(array, true and true) one(array, true or $env) one(array, true) == ok one(if ok { $env } else { add }, ok) one(list ?? ok, ok) one(list, # != $env) one(list, # != foo) one(list, # == #) one(list, # == $env) one(list, # == foo) one(list, $env != .String) one(list, $env != i) one(list, $env == foo) one(list, $env == nil) one(list, $env.ok) one(list, $env?.ok) one(list, .Bar in foo) one(list, 1 <= f64) one(list, 1 > 1.0) one(list, 1.0 != i) one(list, 1.0 < i) one(list, 1.0 == $env) one(list, 1.0 >= 0) one(list, any(list, ok)) one(list, f64 == 1) one(list, f64 > 1.0) one(list, false and ok) one(list, foo != #) one(list, greet == nil) one(list, i == 0) one(list, list != $env) one(list, nil != 1.0) one(list, nil == #) one(list, nil == list) one(list, nil not in $env) one(list, none(list, false)) one(list, not ok) one(list, ok) one(list, ok) and ok one(list, str < #.Bar) one(list, str >= str) one(list, true != $env) one(list, true ?? foo) one(min($env), ok) one(sort($env), $env == nil) one(sort($env), .String.list(nil)) one(sort($env), .greet[:.i]) one(sort($env), .list?.array(foobar)) one(sort($env), 1.0 != $env) one(sort($env), i >= .f64) one(sort($env), ok) one(uniq(array), ok) reduce($env | map($env), #.foo) reduce($env | map(0), str) reduce($env | map(1.0), str) reduce($env | map(f64), #) reduce($env | map(foo), greet) reduce($env | map(str), str) reduce($env, #.list) == 1 && false reduce($env, $env, $env).foo reduce($env, $env, $env).greet reduce($env, $env, $env)?.add reduce($env, $env, $env)?.f64 reduce($env, $env, $env)?.greet reduce($env, $env, $env)?.ok reduce($env, $env, 1)?.f64 reduce($env, $env, 1.0)?.add reduce($env, $env, 1.0)?.greet reduce($env, $env, 1.0)?.list reduce($env, $env, add).ok reduce($env, $env, array)?.i reduce($env, $env, false).str reduce($env, $env, foo)?.Bar reduce($env, $env, foo)?.str reduce($env, $env, greet).String reduce($env, $env, greet).greet reduce($env, $env, greet)?.String reduce($env, $env, greet)?.greet reduce($env, $env, i)?.[str] reduce($env, $env, i)?.f64 reduce($env, $env, list).foo reduce($env, $env, list).ok reduce($env, $env, list)?.add reduce($env, $env, nil).Bar reduce($env, $env, nil)?.str reduce($env, $env, true)?.list reduce($env, 1.0, false) ?? array reduce($env, array, $env) | reduce(str) reduce($env, array, 1.0) | all(false) reduce($env, array, false)?.[i] reduce($env, foo, 1).Bar reduce($env, foo, add)?.Bar reduce($env, foo, false).Bar reduce($env, foo, nil)?.Bar reduce($env, foo, ok).String reduce($env, foo, ok)?.String() reduce($env, i, 1.0) ?? add reduce($env, list, 1.0)?.[i] reduce($env, str, false) ?? array reduce($env.array, #) reduce($env.array, #index / #) reduce($env.array, add) reduce($env.array, f64) reduce($env.array, greet) reduce($env.array, i) reduce($env.array, last($env)) reduce($env.array, list) reduce($env.array, mean(f64, #)) reduce($env.array, ok) reduce($env.array, str) reduce($env.list, #) reduce($env.list, #.Bar) reduce($env.list, #?.Bar) reduce($env.list, #acc) reduce($env.list, 1.0 + 1.0) reduce($env.list, [#, 1]) reduce($env.list, [nil]) reduce($env.list, add) reduce($env.list, array) reduce($env.list, f64 ^ 1) reduce($env.list, greet ?? $env, str ?? add) reduce($env.list, greet) reduce($env.list, list) reduce($env.list, ok) reduce($env.list, ok, {foo: nil}) reduce($env.list, str) reduce($env?.[str], # != foo) reduce($env?.[str], #) reduce($env?.[str], #acc) reduce($env?.[str], #index != #) reduce($env?.[str], #index == #) reduce($env?.[str], -0) reduce($env?.[str], 1 <= 1) reduce($env?.[str], f64) reduce($env?.[str], foo) reduce($env?.[str], greet) reduce($env?.[str], list) reduce($env?.[str], nil != list) reduce($env?.[str], ok) reduce($env?.[str], str) reduce($env?.array, # != f64) reduce($env?.array, # < #) reduce($env?.array, # >= 1.0) reduce($env?.array, #) reduce($env?.array, #acc ** #) reduce($env?.array, #acc) reduce($env?.array, $env.greet) reduce($env?.array, add) reduce($env?.array, array) reduce($env?.array, f64) reduce($env?.array, foo) reduce($env?.array, greet) reduce($env?.array, i != #) reduce($env?.array, i) reduce($env?.array, list | groupBy(foo)) reduce($env?.array, list) reduce($env?.array, ok) reduce($env?.array, str) reduce($env?.list, #) reduce($env?.list, #.String) reduce($env?.list, #.String, array) reduce($env?.list, #acc) reduce($env?.list, .Bar in #) reduce($env?.list, .Bar) reduce($env?.list, add) reduce($env?.list, f64) reduce($env?.list, false != ok) reduce($env?.list, foo) reduce($env?.list, foo, $env?.i) reduce($env?.list, foo?.Bar) reduce($env?.list, greet) reduce($env?.list, i ^ 0) reduce($env?.list, i in array) reduce($env?.list, i) reduce($env?.list, ok) reduce(1 .. 1, #acc?.[foo]) reduce([$env], #) reduce([$env], #.Bar) reduce([$env], #.String != $env) reduce([$env], #.add < #.greet) reduce([$env], #.foo?.[list]) reduce([$env], #acc) reduce([$env], .Bar) reduce([$env], .str) reduce([$env], add) reduce([$env], f64 <= #.f64) reduce([$env], foo) reduce([$env], greet) reduce([$env], i) reduce([$env], if true { .greet } else { foo }) reduce([$env], round($env)) reduce([$env], upper(.foo)) reduce([0, $env], array) reduce([0], #) reduce([0], array) reduce([1, greet], add) reduce([1.0, 1], # - #) reduce([1.0, foo], #) reduce([1.0], # - 1) reduce([1.0], #) reduce([1.0], $env[:#]) reduce([1.0], list) reduce([1], add) reduce([1], foo) reduce([add], $env[foobar:]) reduce([f64, add], #) reduce([f64], i) reduce([false, add], i) reduce([false], #acc) reduce([false], foo) reduce([foo, add], #) reduce([foo], #) reduce([foo], #.Bar + #acc) reduce([foo], #index) reduce([foo], $env?.[f64]) reduce([foo], foo).String reduce([foo], greet) reduce([foo], ok) reduce([greet, greet], str) reduce([greet], f64) reduce([i, 1.0], # != #) reduce([i, i], foo) reduce([i], list) reduce([list], #) reduce([list], add) reduce([list], greet) reduce([nil != true], list) reduce([nil, add], foo) reduce([nil, foo], # ?? .add) reduce([nil], array) reduce([nil], i) reduce([ok], #) reduce([ok], add) reduce([ok], foo) reduce([str, 1.0], $env.i) reduce([str], i) reduce([true, greet], #) reduce([true], foo.Bar) reduce(array ?? add, str) reduce(array ?? str, #index) reduce(array | map(#), f64) reduce(array | map(#), foo) reduce(array | map($env), #index) reduce(array | map(foo), f64) reduce(array | sortBy(#), ok) reduce(array | sortBy(1), #acc) reduce(array, # != #) reduce(array, # != i) reduce(array, # % #) reduce(array, # % i) reduce(array, # * #) reduce(array, # + #) reduce(array, # + 0) reduce(array, # - #acc) reduce(array, # .. #) reduce(array, # / #) reduce(array, # / 0) reduce(array, # < #) reduce(array, # <= #) reduce(array, # <= 1) reduce(array, # == #) reduce(array, # == 0) reduce(array, # > i) reduce(array, # >= #) reduce(array, # >= 0) reduce(array, # ?? foo) reduce(array, # ^ #) reduce(array, # in array) reduce(array, #) reduce(array, #) * f64 reduce(array, #, add) reduce(array, #, array) reduce(array, #, greet) reduce(array, #, i) reduce(array, #, i) | mean(array) reduce(array, #, ok) reduce(array, #..i) reduce(array, #acc) reduce(array, #acc, nil)?.[greet] reduce(array, #acc, nil)?.i reduce(array, #acc, nil)?.list reduce(array, #index != f64) reduce(array, #index ** 1.0) reduce(array, #index ** f64) reduce(array, #index == 1.0) reduce(array, #index ?? foo) reduce(array, #index ^ #) reduce(array, #index) reduce(array, #index, foo) reduce(array, $env != foo) reduce(array, $env != ok) reduce(array, $env == #) reduce(array, $env == ok) reduce(array, $env ?? ok) reduce(array, $env and true) reduce(array, $env) == ok reduce(array, $env) | count(false) reduce(array, $env) | find(false) reduce(array, $env) | map(false) reduce(array, $env).Bar reduce(array, $env).String reduce(array, $env).add reduce(array, $env).array reduce(array, $env).f64 reduce(array, $env).foo reduce(array, $env).foobar reduce(array, $env).greet reduce(array, $env).greet(foobar) reduce(array, $env).i reduce(array, $env).list reduce(array, $env).str reduce(array, $env)?.Bar reduce(array, $env)?.String reduce(array, $env)?.String?.str reduce(array, $env)?.[str] reduce(array, $env)?.add reduce(array, $env)?.array reduce(array, $env)?.f64 reduce(array, $env)?.false?.foo reduce(array, $env)?.foo reduce(array, $env)?.foobar reduce(array, $env)?.greet reduce(array, $env)?.i reduce(array, $env)?.list reduce(array, $env)?.ok reduce(array, $env)?.str reduce(array, $env, $env) | sum(1) reduce(array, $env, $env)?.str reduce(array, $env, 0)?.String reduce(array, $env, 1.0).Bar reduce(array, $env, f64)?.[str] reduce(array, $env, f64)?.list reduce(array, $env, foo)?.ok reduce(array, $env, ok)?.Bar reduce(array, $env, str)?.greet reduce(array, $env, true).array reduce(array, $env.array) reduce(array, $env.f64) reduce(array, $env.foo) reduce(array, $env.greet) reduce(array, $env.i) reduce(array, $env.list) reduce(array, $env.ok) reduce(array, $env.str) reduce(array, $env?.add) reduce(array, $env?.array) reduce(array, $env?.f64) reduce(array, $env?.foo) reduce(array, $env?.foo.Bar) reduce(array, $env?.greet) reduce(array, $env?.i) reduce(array, $env?.list, greet) reduce(array, $env?.str) reduce(array, -#) reduce(array, -0) reduce(array, -1) reduce(array, 0 * 1) reduce(array, 0) ^ i reduce(array, 0) | min(1.0) reduce(array, 1 != $env) reduce(array, 1 != nil) reduce(array, 1 | max(#acc)) reduce(array, 1) ** f64 reduce(array, 1.0 != #) reduce(array, 1.0 != 1) reduce(array, 1.0 * #) reduce(array, 1.0 ** #) reduce(array, 1.0 ** #index) reduce(array, 1.0 ** 1.0) reduce(array, 1.0 - #acc) reduce(array, 1.0 - f64) reduce(array, 1.0 - i) reduce(array, 1.0 / #) reduce(array, 1.0 < #) reduce(array, 1.0 == i) reduce(array, 1.0 > #) reduce(array, 1.0 >= f64) reduce(array, 1.0 ?? #) reduce(array, 1.0 ?? $env) reduce(array, 1.0 ^ #) reduce(array, 1.0) / $env?.i reduce(array, 1.0) == $env?.[str] reduce(array, 1.0) ^ $env?.f64 reduce(array, [#]) reduce(array, [1.0]) reduce(array, [add]) reduce(array, [flatten(list)]) reduce(array, [foo]) reduce(array, abs(#)) reduce(array, add == nil) reduce(array, add) reduce(array, add, f64) reduce(array, array | reduce($env)) reduce(array, array) reduce(array, array) | mean(1, i) reduce(array, array)?.[i] reduce(array, array, foo) reduce(array, array, i) reduce(array, array?.[i]) reduce(array, array[1:]) reduce(array, bitnand(1, #acc)) reduce(array, bitnot(#)) reduce(array, bitnot(#)) % i reduce(array, bitnot(i)) reduce(array, bitor(i, #)) reduce(array, ceil(#)) reduce(array, concat(list)) reduce(array, f64 + #) reduce(array, f64) reduce(array, f64) ?? f64 reduce(array, false ?? #) reduce(array, false) == $env?.String reduce(array, false) and ok reduce(array, float(#)) reduce(array, float(i)) reduce(array, foo == $env) reduce(array, foo ?? $env) reduce(array, foo) reduce(array, foo).Bar reduce(array, foo).String reduce(array, foo).String() reduce(array, foo)?.Bar reduce(array, foo)?.String reduce(array, foo)?.String() reduce(array, foo, 1.0).Bar reduce(array, foo, array) reduce(array, foo, foo).String reduce(array, foo, greet)?.String() reduce(array, foo, i).Bar reduce(array, foo, list).Bar reduce(array, foo, str) reduce(array, foo, str).Bar reduce(array, foo.Bar) reduce(array, foo.String()) reduce(array, foo.String) reduce(array, foo?.Bar) reduce(array, foo?.String()) reduce(array, foo?.String) reduce(array, greet(str)) reduce(array, greet) reduce(array, greet, [array]) reduce(array, greet, foo) reduce(array, i ** #acc) reduce(array, i .. #, greet) reduce(array, i <= #) reduce(array, i ^ #acc) reduce(array, i) reduce(array, i) != i reduce(array, i, array) % i reduce(array, i, f64) not in $env?.array reduce(array, i, list) reduce(array, keys($env)) reduce(array, list ?? #, i) reduce(array, list ?? str) reduce(array, list) reduce(array, list)?.[i] reduce(array, list, {foo: nil}) reduce(array, list[:#]) reduce(array, mean(#)) reduce(array, median(#)) reduce(array, median(0)) reduce(array, ok ? ok : #index) reduce(array, ok) reduce(array, ok, $env.ok) reduce(array, ok, 1.0) == ok reduce(array, reduce(array, #)) reduce(array, reduce(array, #, i)) reduce(array, round(#)) reduce(array, round(1)) reduce(array, str ?? 1.0) reduce(array, str not in foo) reduce(array, str) reduce(array, str) + str reduce(array, str) | greet() reduce(array, str, $env.f64) reduce(array, str, array) not in foo reduce(array, str, f64) reduce(array, string(#)) reduce(array, string(i)) reduce(array, sum(array, 1.0)) reduce(array, toJSON(#)) reduce(array, toJSON(1.0)) reduce(array, true and ok) reduce(array, true or $env) reduce(array, true) ?? add reduce(array, type(#)) reduce(array, type(true)) reduce(array, uniq(list)) reduce(array[0:], list) reduce(concat(list), #) reduce(flatten(array), array) reduce(flatten(array), foo) reduce(flatten(list), #) reduce(keys($env), #acc) reduce(keys($env), $env?.[String]) reduce(keys($env), abs(0)) reduce(keys($env), greet) reduce(keys($env), max(#)) reduce(keys($env), sum(#)) reduce(let foobar = array; foobar, #) reduce(list ?? 1.0, foo) reduce(list ?? array, #) reduce(list | map(1), $env?.f64) reduce(list | map(1.0), array) reduce(list | map(false), true != #) reduce(list | reduce(array), #) reduce(list | sortBy(1.0), greet) reduce(list, # == #) reduce(list, # == $env) reduce(list, # ?? false) reduce(list, # ?? foo) reduce(list, # in list) reduce(list, #) reduce(list, #) ?? foo reduce(list, #).Bar reduce(list, #).String reduce(list, #).String() reduce(list, #)?.Bar reduce(list, #)?.String reduce(list, #)?.String() reduce(list, #, 1.0)?.Bar reduce(list, #, 1.0)?.String reduce(list, #, add) reduce(list, #, array)?.String reduce(list, #, f64).String reduce(list, #, nil).String reduce(list, #, ok)?.Bar reduce(list, #.Bar != nil) reduce(list, #.Bar >= .Bar) reduce(list, #.Bar) reduce(list, #.String()) reduce(list, #.String) reduce(list, #?.Bar) reduce(list, #?.String()) reduce(list, #?.String) reduce(list, #acc == 0) reduce(list, #acc ?? $env) reduce(list, #acc ?? 1) reduce(list, #acc) reduce(list, #acc).Bar reduce(list, #acc)?.Bar reduce(list, #acc, foo).String reduce(list, #index) reduce(list, $env && true) reduce(list, $env == ok) reduce(list, $env ?? array) reduce(list, $env and true) reduce(list, $env | map(add)) reduce(list, $env) | map(i) reduce(list, $env).Bar reduce(list, $env).String reduce(list, $env).add reduce(list, $env).array reduce(list, $env).array?.[i] reduce(list, $env).f64 reduce(list, $env).foo reduce(list, $env).greet reduce(list, $env).i reduce(list, $env).list reduce(list, $env).ok reduce(list, $env).str reduce(list, $env)?.Bar reduce(list, $env)?.String reduce(list, $env)?.[str] reduce(list, $env)?.add reduce(list, $env)?.f64 reduce(list, $env)?.foo reduce(list, $env)?.foobar reduce(list, $env)?.foobar?.i reduce(list, $env)?.greet reduce(list, $env)?.i reduce(list, $env)?.list reduce(list, $env)?.ok reduce(list, $env)?.str reduce(list, $env, $env)?.i reduce(list, $env, add).array reduce(list, $env, add).foo reduce(list, $env, add)?.list reduce(list, $env, array)?.greet reduce(list, $env, false).f64 reduce(list, $env, false).ok reduce(list, $env, foo).ok reduce(list, $env, greet)?.Bar?.str reduce(list, $env, i).ok reduce(list, $env, nil)?.greet reduce(list, $env.add) reduce(list, $env.f64) reduce(list, $env.list) reduce(list, $env.str) reduce(list, $env?.[#.Bar]) reduce(list, $env?.[String]) reduce(list, $env?.[foobar]) reduce(list, $env?.add) reduce(list, $env?.f64) reduce(list, $env?.foo) reduce(list, $env?.list) reduce(list, $env?.nil?.[greet]) reduce(list, $env?.ok) reduce(list, $env?.str) reduce(list, -i) reduce(list, .Bar not contains str) reduce(list, .Bar not in foo, {foo: str}) reduce(list, .Bar) reduce(list, .String ?? foo) reduce(list, .String) reduce(list, .String, greet) reduce(list, 0 .. 0) reduce(list, 0 == 1) reduce(list, 0) != i reduce(list, 0) | mean(1.0) reduce(list, 1 <= 1) reduce(list, 1) * i reduce(list, 1) / i reduce(list, 1.0 * f64) reduce(list, 1.0 * i) reduce(list, 1.0 + 1) reduce(list, 1.0 <= 1.0) reduce(list, 1.0) * i reduce(list, 1.0) == i reduce(list, 1.0, array) <= i reduce(list, [$env, 0]) reduce(list, [f64, false]) reduce(list, [foo]) reduce(list, [nil, #]) reduce(list, [str]) reduce(list, abs(#index)) reduce(list, add == $env) reduce(list, add) reduce(list, add, foo) reduce(list, add, ok) reduce(list, array != array) reduce(list, array | one(ok)) reduce(list, array) reduce(list, array) | map(foo) reduce(list, array) | sum(#) reduce(list, array)?.[i] reduce(list, array, add) reduce(list, bitnot(1)) reduce(list, f64 != $env) reduce(list, f64 * #index) reduce(list, f64 * f64) reduce(list, f64 / f64) reduce(list, f64 >= 1) reduce(list, f64) reduce(list, f64, f64) reduce(list, f64, str) reduce(list, false == ok) reduce(list, false ?: foo) reduce(list, false) ? f64 : [false] reduce(list, false) in uniq(list) reduce(list, first(#acc)) reduce(list, foo != foo) reduce(list, foo ?? f64) reduce(list, foo ?? nil) reduce(list, foo) reduce(list, foo).Bar reduce(list, foo).String reduce(list, foo).String() reduce(list, foo)?.Bar reduce(list, foo)?.String reduce(list, foo)?.String() reduce(list, foo, $env) not in list reduce(list, foo, array).String reduce(list, foo, foo) reduce(list, foo, i)?.String reduce(list, foo, str) reduce(list, foo.Bar, list) reduce(list, foo.String) reduce(list, foo?.String()) reduce(list, foo?.String) reduce(list, greet == #acc) reduce(list, greet ?? $env) reduce(list, greet(#.Bar)) reduce(list, greet(.Bar)) reduce(list, greet) reduce(list, greet) ?? greet reduce(list, greet, greet) reduce(list, i / 1.0) reduce(list, i ^ 0) reduce(list, i) reduce(list, i, $env?.list[:]) reduce(list, i, 1.0) == i reduce(list, i, list) reduce(list, i, ok) reduce(list, int(#index)) reduce(list, int(0)) reduce(list, len($env)) reduce(list, list | any(ok)) reduce(list, list | map($env)) reduce(list, list) reduce(list, list)?.[i] reduce(list, list, f64) | map(array) reduce(list, list, i) reduce(list, list?.[i]) reduce(list, max(f64)) reduce(list, mean(1.0)) reduce(list, median(i)) reduce(list, nil != $env) reduce(list, nil != 0) reduce(list, nil == $env) reduce(list, ok == false) reduce(list, ok ?? #) reduce(list, ok ?? #acc) reduce(list, ok ?? $env) reduce(list, ok) reduce(list, ok) || $env?.[greet] reduce(list, ok, $env.foo) reduce(list, ok, 1 * i) reduce(list, ok, f64) reduce(list, reduce(array, greet, foo)) reduce(list, sort($env), ok) reduce(list, str > #.Bar) reduce(list, str ?? f64) reduce(list, str) reduce(list, str) == str reduce(list, string(ok)) reduce(list, sum(list, 1.0)) reduce(list, toBase64(#.Bar)) reduce(list, trimSuffix(#.Bar)) reduce(list, trimSuffix(.Bar)) reduce(list, true != $env) reduce(list, true != ok) reduce(list, true ? # : false) reduce(list, true || false) reduce(list, true || true) reduce(list, true) and ok reduce(list, type($env)) reduce(list, type(i)) reduce(list, type(list)) reduce(list[:1], [$env]) reduce(list[:1], str) reduce(list[:], greet) reduce(map($env, 1.0), #) reduce(map($env, false), i) reduce(map($env, foo), str) reduce(map($env, greet), #) reduce(map($env, greet), i) reduce(map($env, list), $env.str) reduce(map(array, foo), foo?.Bar) reduce(map(array, list), list) reduce(map(array, ok), greet) reduce(map(list, #), #) reduce(map(list, #), $env?.add) reduce(map(list, .Bar), list) reduce(map(list, i), #) reduce(max($env).array, ok) reduce(nil ?? list, add) reduce(reduce(array, list), #index) reduce(reduce(list, array), i) reduce(reverse(array), $env.ok) reduce(reverse(array), $env?.ok) reduce(reverse(list), str) reduce(sort(array), str) reduce(sortBy(array, #), #) reduce(sortBy(array, #), array) reduce(sortBy(array, 1.0), ok) reduce(sortBy(list, 1.0), i) reduce(str ?? $env, #) reduce(uniq(array), greet) reduce(values($env), # == $env) reduce(values($env), #) repeat(nil ?? str, i) repeat(str, 0 ?? false) repeat(str, i) repeat(str, i) not startsWith str repeat(str, max(1.0, array)) repeat(type(1), i) reverse($env | filter(false)) reverse($env | map($env)) reverse($env | map(0)) reverse($env | map(1.0)) reverse($env | map(false)) reverse($env | map(foo)) reverse($env | map(ok)) reverse($env | map(true)) reverse($env.array) reverse($env.list) reverse($env?.array) reverse($env?.list) reverse(0 .. 1) reverse(0 .. i) reverse(1 .. 0) reverse(1 .. 1) reverse(1 .. i) reverse([$env, 0]) reverse([$env, f64]) reverse([$env, ok]) reverse([$env]) reverse([0, $env, foo]) reverse([0, foo]) reverse([0, nil]) reverse([0]) reverse([1 .. 1]) reverse([1, true]) reverse([1.0, list]) reverse([1.0]) reverse([1]) reverse([add, list]) reverse([add]) reverse([array, array]) reverse([array, greet]) reverse([array]) reverse([f64, nil]) reverse([f64]) reverse([false, true]) reverse([false]) reverse([foo, 1.0]) reverse([foo, array]) reverse([foo, f64]) reverse([foo, list]) reverse([foo, str]) reverse([foo]) reverse([greet]) reverse([i, 1]) reverse([i]) reverse([list]) reverse([nil, 1]) reverse([nil, i]) reverse([nil, list]) reverse([nil, nil]) reverse([nil, true]) reverse([nil]) reverse([ok]) reverse([str, ok]) reverse([str]) reverse([true]) reverse(array ?? 1) reverse(array ?? 1.0) reverse(array ?? add) reverse(array ?? f64) reverse(array ?? foo) reverse(array | map(#)) reverse(array | map($env)) reverse(array | map(1.0)) reverse(array | map(ok)) reverse(array | map(str)) reverse(array | reduce(array, foo)) reverse(array | sortBy(1)) reverse(array) reverse(array) ?? list reverse(array) not in sort(array) reverse(array) | findIndex(ok) reverse(array) | findLastIndex(false) reverse(array) | groupBy(#) reverse(array) | groupBy(0) reverse(array) | groupBy(i) reverse(array) | map(#) reverse(array) | map($env) reverse(array) | one(ok) reverse(array) | reduce(#) reverse(array) | reduce(#, greet) reverse(array) | reduce($env) reverse(array) | reduce(array) reverse(array) | reduce(foo) reverse(array) | reduce(str) reverse(array) | sortBy(1) reverse(array) | sortBy(i) reverse(array) | sum(#) reverse(array) | sum(f64) reverse(array)?.[i] reverse(array[i:1]) reverse(concat(array)) reverse(concat(list)) reverse(false ? array : list) reverse(filter($env, false)) reverse(filter(list, ok)) reverse(flatten(array)) reverse(flatten(list)) reverse(i .. i) reverse(if false { $env } else { array }) reverse(if false { 1.0 } else { list }) reverse(keys($env)) reverse(let foobar = array; foobar) reverse(let foobar = list; foobar) reverse(list ?? 1.0) reverse(list ?? add) reverse(list ?? f64) reverse(list ?? false) reverse(list ?? foo) reverse(list ?? ok) reverse(list ?? str) reverse(list ?? true) reverse(list | filter(true)) reverse(list | map(#)) reverse(list | map(1.0)) reverse(list | map(array)) reverse(list | map(foo)) reverse(list | map(i)) reverse(list | map(ok)) reverse(list | map(str)) reverse(list | map(true)) reverse(list | sortBy(0)) reverse(list | sortBy(1.0)) reverse(list | sortBy(str)) reverse(list) reverse(list) != list reverse(list) == array reverse(list) ?? list reverse(list) | any(true) reverse(list) | count(true) reverse(list) | find(false) reverse(list) | findIndex(false) reverse(list) | groupBy(#) reverse(list) | groupBy(foo) reverse(list) | groupBy(true) reverse(list) | map(#index) reverse(list) | map(list) reverse(list) | one(false) reverse(list) | reduce(#, false) reverse(list) | reduce(0) reverse(list) | reduce(1.0) reverse(list) | reduce(f64) reverse(list) | reduce(foo) reverse(list) | reduce(greet) reverse(list) | reduce(ok) reverse(list) | reduce(true) reverse(list) | sum(f64) reverse(list)?.[i] reverse(list[:i]) reverse(map($env, $env)) reverse(map($env, 0)) reverse(map($env, 1.0)) reverse(map($env, add)) reverse(map($env, array)) reverse(map($env, f64)) reverse(map($env, foo)) reverse(map($env, list)) reverse(map($env, str)) reverse(map($env, true)) reverse(map(array, #)) reverse(map(array, #index)) reverse(map(array, 1.0)) reverse(map(array, foo)) reverse(map(array, i)) reverse(map(list, #)) reverse(map(list, #.Bar)) reverse(map(list, $env)) reverse(reduce(array, list)) reverse(reduce(list, list, ok)) reverse(reverse(array)) reverse(reverse(list)) reverse(sort($env)) reverse(sort(array)) reverse(sortBy(array, #)) reverse(sortBy(array, 1.0)) reverse(sortBy(array, str)) reverse(sortBy(list, 1.0)) reverse(sortBy(list, i)) reverse(toPairs($env)) reverse(uniq(array)) reverse(uniq(list)) reverse(values($env)) round($env | count(ok)) round($env | findIndex(true)) round($env | reduce(0, foo)) round($env | reduce(1.0, f64)) round($env | sum(1.0)) round($env | sum(f64)) round($env.f64) round($env.f64) != i round($env.i) round($env?.f64) round($env?.f64) - f64 round($env?.i) round(-0) round(-1) round(-1.0) round(-f64) round(-i) round(0 * 0) round(0 * 1.0) round(0 * f64) round(0 ** 0) round(0 ** 1) round(0 ** 1.0) round(0 ** f64) round(0 ** i) round(0 + 0) round(0 + 1) round(0 + 1.0) round(0 + i) round(0 - 0) round(0 - 1) round(0 - f64) round(0 / 0) round(0 / 1.0) round(0 / f64) round(0 / i) round(0 ?? f64) round(0 ?? false) round(0 ?? true) round(0 ^ 1.0) round(0 ^ f64) round(0 | max(array)) round(0) != i round(0) - i round(0) / f64 round(0) < i round(0) == max($env) round(0) ?? foo round(0) ^ f64 round(0) ^ i round(0.1) round(1 % i) round(1 * 0) round(1 * 1) round(1 ** 0) round(1 ** 1) round(1 ** 1.0) round(1 ** i) round(1 + 0) round(1 + 1) round(1 + 1.0) round(1 + i) round(1 - 0) round(1 - 1) round(1 - 1.0) round(1 - i) round(1 / 1) round(1 / f64) round(1 / i) round(1 ?? 0) round(1 ?? 1.0) round(1 ?? array) round(1 ?? f64) round(1 ?? foo) round(1 ?? i) round(1 ?? nil) round(1 ^ 0) round(1 ^ 1) round(1 ^ 1.0) round(1 ^ f64) round(1 ^ i) round(1 | bitnand(0)) round(1) * f64 round(1) * i round(1) / f64 round(1) ?? array ?? foo round(1) ?? greet round(1) ?? ok round(1) ^ sum(array) round(1) not in array round(1.0 * 0) round(1.0 * 1) round(1.0 * 1.0) round(1.0 * f64) round(1.0 * i) round(1.0 ** 0) round(1.0 ** 1) round(1.0 ** 1.0) round(1.0 ** f64) round(1.0 ** i) round(1.0 + 0) round(1.0 + 1.0) round(1.0 + f64) round(1.0 + i) round(1.0 - 0) round(1.0 - 1) round(1.0 - 1.0) round(1.0 - f64) round(1.0 - i) round(1.0 / 0) round(1.0 / 1) round(1.0 / 1.0) round(1.0 / f64) round(1.0 / i) round(1.0 ?? $env) round(1.0 ?? 0) round(1.0 ?? 1) round(1.0 ?? add) round(1.0 ?? f64) round(1.0 ?? false) round(1.0 ?? foo) round(1.0 ?? i) round(1.0 ?? list) round(1.0 ?? nil) round(1.0 ?? ok) round(1.0 ?? str) round(1.0 ^ $env.i) round(1.0 ^ 0) round(1.0 ^ 1) round(1.0 ^ 1.0) round(1.0 ^ f64) round(1.0 ^ i) round(1.0 | max(i)) round(1.0 | mean(0)) round(1.0) round(1.0) != f64 round(1.0) * $env and false round(1.0) * f64 round(1.0) ** 1.0 != 1 round(1.0) ** 1.0 / f64 round(1.0) ** f64 round(1.0) + f64 round(1.0) + mean(1.0, f64) round(1.0) + min(1.0) round(1.0) - f64 round(1.0) / i round(1.0) / int(1.0) round(1.0) <= i round(1.0) == 1 / i round(1.0) == i round(1.0) > i round(1.0) >= f64 round(1.0) >= i round(1.0) ?? f64 round(1.0) ?? foo round(1.0) ^ f64 round(1.0) ^ i round(1.0) ^ sum($env, 1) round(1.0) in $env.array round(1.0) | median(array) round(1.0) | median(f64) round(1.1) round(abs(-1.0)) round(abs(1.0)) round(abs(f64)) round(abs(i)) round(array | max(array)) round(array | median(1.0)) round(array | reduce(#)) round(array | sum(#)) round(array | sum(0)) round(array | sum(1)) round(array | sum(f64)) round(array?.[0]) round(array?.[i]) round(bitand(0, i)) round(bitnand(1, 1)) round(bitnand(i, 1)) round(bitnot(0)) round(bitnot(1)) round(bitnot(i)) round(ceil(0)) round(ceil(1)) round(ceil(1.0)) round(ceil(f64)) round(ceil(i)) round(count($env, ok)) round(count($env, true)) round(f64 * 0) round(f64 * 1) round(f64 * 1.0) round(f64 * i) round(f64 ** $env.f64) round(f64 ** 0) round(f64 + 0) round(f64 + 1.0) round(f64 - 0) round(f64 - 1.0) round(f64 - f64) round(f64 - i) round(f64 / 0) round(f64 / 1.0) round(f64 / f64) round(f64 ?? $env) round(f64 ?? 0) round(f64 ?? add) round(f64 ?? array) round(f64 ?? foo) round(f64 ?? greet) round(f64 ?? list) round(f64 ?? nil) round(f64 ?? ok) round(f64 ^ 1) round(f64 ^ 1.0) round(f64 ^ f64) round(f64 ^ i) round(f64 | median(0)) round(f64) round(f64) != $env?.f64 round(f64) != f64 round(f64) + f64 round(f64) + f64 < 0 round(f64) < i round(f64) <= i round(f64) >= i round(false ? 0 : 1.0) round(false ?: 1) round(find(array, true)) round(findIndex(array, true)) round(findIndex(list, ok)) round(findLast(array, ok)) round(findLastIndex($env, true)) round(findLastIndex(array, ok)) round(first(array)) round(float(0)) round(float(1)) round(float(1.0)) round(float(f64)) round(float(i)) round(floor(0)) round(floor(1)) round(floor(1.0)) round(floor(f64)) round(floor(i)) round(i % 1) round(i * 1) round(i * 1.0) round(i * i) round(i ** 0) round(i ** 1) round(i ** 1.0) round(i + 1) round(i + f64) round(i - 0) round(i - 1) round(i - 1.0) round(i - f64) round(i / 1) round(i / 1.0) round(i / f64) round(i / i) round(i ?? $env) round(i ?? 1.0) round(i ?? add) round(i ?? false) round(i ?? list) round(i ?? nil) round(i ^ 0) round(i ^ 1) round(i ^ 1.0) round(i ^ f64) round(i) round(i) ** i round(i) + i round(i) / i round(i) < 1.0 != $env round(i) <= 1.0 ? foo : add round(i) == i round(i) > $env?.i round(i) > f64 round(i) ?? add round(i) ?? f64 round(i) ?? foo round(i) ?? str round(i) ^ i round(i) | median(f64) round(if false { foo } else { 0 }) round(if true { 0 } else { greet }) round(int(0)) round(int(1)) round(int(1.0)) round(int(f64)) round(int(i)) round(int(string(1.0))) round(last(array)) round(len($env)) round(len(array)) round(len(list)) round(len(str)) round(list | count(ok)) round(list | reduce(1)) round(list | reduce(1.0, $env)) round(list | reduce(1.0, 1.0)) round(list | reduce(f64)) round(map(list, 1.0) | max(1)) round(max(0)) round(max(1)) round(max(1.0 * 0)) round(max(1.0)) round(max(array)) round(max(array, array)) round(max(f64)) round(max(i)) round(mean(0)) round(mean(1)) round(mean(1, 1.0)) round(mean(1.0)) round(mean(array)) round(mean(array, i, array)) round(mean(f64)) round(mean(f64, f64)) round(mean(i)) round(median($env.array)) round(median(0)) round(median(1)) round(median(1.0)) round(median(array)) round(median(array, 1.0)) round(median(f64)) round(median(f64, i)) round(median(i)) round(min(0)) round(min(1)) round(min(1.0)) round(min(1.0, 1.0)) round(min(array)) round(min(array, 0)) round(min(array, array, array)) round(min(f64)) round(min(i)) round(nil ?? 1) round(nil ?? 1.0) round(nil ?? f64) round(ok ? i : 0) round(reduce(array, #)) round(reduce(array, #, nil)) round(reduce(array, 1.0)) round(reduce(array, i)) round(reduce(list, #index, nil)) round(round(0)) round(round(1)) round(round(1.0)) round(sum($env, 0)) round(sum($env, 1)) round(sum($env, f64)) round(sum($env, i)) round(sum(array)) sort($env ?? $env) sort($env ?? add) sort($env ?? array) sort($env ?? f64) sort($env ?? false) sort($env ?? foo) sort($env ?? greet) sort($env ?? list) sort($env ?? nil) sort($env ?? ok) sort($env | filter(false)) sort($env | find(false)) sort($env | map(#index)) sort($env | map(0)) sort($env) != $env?.String sort($env) != array sort($env) ?? $env?.array sort($env) ?? greet sort($env) ?? type(list) sort($env) | all(#) sort($env) | all(#.Bar) sort($env) | all(#.String) sort($env) | all(#.add) sort($env) | all(#.array) sort($env) | all(#.foo?.Bar) sort($env) | all(#.ok) sort($env) | all($env) sort($env) | all(.foo?.[array]) sort($env) | all(.str) sort($env) | all(true) sort($env) | any(#) sort($env) | any(#.f64) sort($env) | any(#.i) sort($env) | any(.String) sort($env) | any(.array) sort($env) | concat(list) sort($env) | count(#) sort($env) | count(#.Bar) sort($env) | count(#.foo) sort($env) | count(#.i == 0) sort($env) | count($env) sort($env) | count(.f64) sort($env) | count(false) sort($env) | filter(#) sort($env) | filter(#.String) sort($env) | filter(#.i) sort($env) | filter(#.list) sort($env) | find(#) sort($env) | find(#.Bar) sort($env) | find(#.list) sort($env) | find($env) sort($env) | find(.String[#.array:true]) sort($env) | find(.array) sort($env) | find(.i) sort($env) | find(false) sort($env) | findIndex(#) sort($env) | findIndex(#.add) sort($env) | findIndex(#.array) sort($env) | findIndex(.String) sort($env) | findIndex(.array) sort($env) | findIndex(.foo) sort($env) | findIndex(.ok) sort($env) | findIndex(false) sort($env) | findIndex(ok) sort($env) | findLast(#) sort($env) | findLast(#.array) sort($env) | findLast(#.list?.foo(#)) sort($env) | findLast(#.str) sort($env) | findLast(false) sort($env) | findLastIndex(#) sort($env) | findLastIndex(#.add) sort($env) | findLastIndex(#.list) sort($env) | findLastIndex($env) sort($env) | findLastIndex(.Bar) sort($env) | findLastIndex(.foo) sort($env) | groupBy(#) sort($env) | groupBy(#.Bar) sort($env) | groupBy(#.add) sort($env) | groupBy(#.greet / #) sort($env) | groupBy(#.greet) sort($env) | groupBy(#?.foo(i)) sort($env) | groupBy(.array) sort($env) | groupBy(.greet) sort($env) | groupBy(0) sort($env) | groupBy(1.0) sort($env) | groupBy(add) sort($env) | groupBy(f64) sort($env) | groupBy(i) sort($env) | groupBy(list) sort($env) | groupBy(ok) sort($env) | map(#) sort($env) | map(#.Bar) sort($env) | map(#.f64) sort($env) | map($env) sort($env) | map(.array) sort($env) | map(.foo) sort($env) | map(.list) sort($env) | map(1) sort($env) | map(1.0) sort($env) | map(f64 ?? 0) sort($env) | map(foo) sort($env) | map(i) sort($env) | map(true) sort($env) | mean(1.0) sort($env) | none(#) sort($env) | none(#.add[foobar:]) sort($env) | none(#.list) sort($env) | none(#.ok) sort($env) | none($env) sort($env) | none(.String) sort($env) | none(.add) sort($env) | none(.array) sort($env) | none(.foo) sort($env) | none(.list) sort($env) | one(#.add) sort($env) | one(#.f64) sort($env) | one(#.greet) sort($env) | one(#.list) sort($env) | one(#.ok) sort($env) | one(#.ok.nil) sort($env) | one(#.str) sort($env) | one($env) sort($env) | one(.Bar) sort($env) | one(.f64) sort($env) | one(.f64?.[.greet]) sort($env) | one(.list) sort($env) | one(false) sort($env) | one(ok) sort($env) | reduce(#.String, nil) sort($env) | reduce(#.greet, str) sort($env) | reduce(false, 0) sort($env) | reduce(foo, foo) sort($env) | sortBy(#) sort($env) | sortBy(#.String) sort($env) | sortBy(.add) sort($env) | sortBy(.f64) sort($env) | sortBy(1.0) sort($env) | sortBy(foo) sort($env) | sortBy(i) sort($env) | sortBy(str) sort($env) | sum(#.foo) sort($env) | sum(#.greet) sort($env) | sum(#.str?.String) sort($env) | sum($env) sort($env) | sum(.array) sort($env) | sum(1.0) sort($env) | sum(array) sort($env) | sum(false) sort($env) | sum(foo) sort($env) | sum(not #.array) sort($env)?.[i] sort($env)?.[i].add() sort($env)?.[i]?.[array] sort($env)[:] sort($env.array) sort($env?.$env) sort($env?.Bar) sort($env?.Bar?.[ok]) sort($env?.Bar?.greet) sort($env?.String) sort($env?.String) | one(.str.add(foobar)) sort($env?.[Bar]) sort($env?.[Bar]) ?? array sort($env?.[Bar]?.[array]) sort($env?.[Bar]?.foo()) sort($env?.[String]) sort($env?.[foobar]) sort($env?.[foobar]?.[add]) sort($env?.[nil]) sort($env?.[nil]?.String().array) sort($env?.[str]) sort($env?.array) sort($env?.false) sort($env?.foobar) sort($env?.foobar?.greet) sort($env?.list | reduce(#acc)) sort($env?.nil) sort(0 .. i) sort(0 ?? 1.0) sort(0 ?? foo) sort(0 ?? foo.Bar) sort(0 ?? ok) sort(1 .. 1) sort(1 ?? 1.0) sort(1 ?? array) sort(1 ?? false) sort(1 ?? foo) sort(1 ?? greet) sort(1 ?? ok) sort(1..i) sort(1.0 ?? $env) sort(1.0 ?? 0) sort(1.0 ?? false) sort(1.0 ?? foo) sort(1.0 ?? greet) sort(1.0 ?? i) sort(1.0 ?? ok) sort(1.0 ?? str) sort(1.0 ?? true) sort([$env]) sort([0 .. 0]) sort([0]) sort([1 ?? 0]) sort([1.0]) sort([1]) sort([add]) sort([array]) sort([f64]) sort([false]) sort([foo]) sort([greet]) sort([i]) sort([list]) sort([nil]) sort([ok]) sort([str]) sort([true]) sort(add ?? $env) sort(add ?? 0) sort(add ?? 1.0) sort(add ?? array) sort(add ?? greet) sort(add ?? i) sort(add ?? ok) sort(array ?? 0) sort(array ?? array) sort(array ?? foo) sort(array ?? nil) sort(array ?? true) sort(array | filter(ok)) sort(array | map(#)) sort(array | map(1)) sort(array | mean(1)) sort(array | median(1, i)) sort(array | sortBy(#)) sort(array | sortBy(f64)) sort(array | sortBy(str)) sort(array | sum(#)..i) sort(array) sort(array) != list sort(array) == list sort(array) ?? mean(f64) sort(array) ?? not ok sort(array) | filter(true) sort(array) | find(true) sort(array) | findIndex($env?.ok) sort(array) | findLast(ok) sort(array) | findLastIndex(false) sort(array) | get(i) sort(array) | groupBy(#) sort(array) | groupBy(foo) sort(array) | groupBy(str) sort(array) | map(#) sort(array) | map(0) sort(array) | map(1.0) sort(array) | map(foo) sort(array) | map(list) sort(array) | map(ok) sort(array) | one(false) sort(array) | reduce(#) sort(array) | reduce(#index) sort(array) | reduce($env) sort(array) | reduce(foo) sort(array) | reduce(list, greet) sort(array) | reduce(true, 1.0) sort(array) | sortBy(#) sort(array) | sortBy(1) sort(array)?.[i] sort(array[0:]) sort(array[:0]) sort(concat(array)) sort(f64 ?? $env) sort(f64 ?? foo) sort(false ? true : 0) sort(false ?: $env) sort(false ?: 1.0) sort(false ?: i) sort(false ?: list) sort(false ?? $env) sort(false ?? add) sort(false ?? array) sort(false ?? foo) sort(false ?? greet) sort(false ?? list) sort(filter($env, false)) sort(filter(list, false)) sort(first($env)) sort(flatten(array)) sort(foo ?? $env) sort(foo ?? 0) sort(foo ?? 1) sort(foo ?? 1.0) sort(foo ?? add) sort(foo ?? array) sort(foo ?? f64) sort(foo ?? false) sort(foo ?? i) sort(foo ?? ok) sort(foo ?? true) sort(greet ?? $env) sort(greet ?? foo) sort(i .. 0) sort(i .. 1) sort(i ?? $env) sort(i ?? 1.0) sort(i ?? f64) sort(i ?? list) sort(if false { 1 } else { 1.0 }) sort(if false { 1.0 } else { 1 }) sort(if false { false } else { f64 }) sort(if false { foo } else { 1.0 }) sort(if false { nil } else { $env }) sort(if ok { ok } else { 1.0 }) sort(if true { add } else { str }) sort(if true { array } else { i }) sort(if true { f64 } else { $env }) sort(if true { foo } else { 1.0 }) sort(if true { greet } else { 1 }) sort(keys($env)) sort(last($env)) sort(list ?? 1) sort(list ?? 1.0) sort(list ?? add) sort(list ?? str) sort(list ?? true) sort(list | map(#.Bar)) sort(list | reduce(array)) sort(map($env, #index)) sort(map($env, i)) sort(map(array, #)) sort(map(array, 0)) sort(map(array, 1.0)) sort(map(list, #.Bar)) sort(map(list, 1.0)) sort(map(list, str)) sort(max($env)) sort(max(array)) sort(max(array, 1.0)) sort(mean(array)) sort(median(array)) sort(min($env)) sort(min(array)) sort(min(array, 1.0)) sort(nil ?? $env) sort(ok ? 1.0 : $env) sort(ok ? list : str) sort(ok ?: 1.0) sort(ok ?: list) sort(ok ?? 0) sort(ok ?? add) sort(ok ?? f64) sort(ok ?? foo) sort(ok ?? list) sort(reduce(array, $env)) sort(reduce(array, array)) sort(reduce(list, $env)) sort(reverse(array)) sort(sort($env)) sort(sort([str])) sort(sort(array)) sort(sortBy(array, 1.0)) sort(str ?? $env) sort(str ?? $env.list) sort(str ?? 0) sort(str ?? 1.0) sort(str ?? foo) sort(str ?? greet) sort(str ?? true) sort(toPairs($env)) sort(true ? 0 : $env) sort(true ? i : 1.0) sort(true ? list : 1) sort(true ?? 1.0) sort(true ?? f64) sort(true ?? foo) sort(true ?? greet) sort(true ?? str) sort({foo: 1.0}.add) sort({foo: foo, foo: add}.Bar) sort({foo: nil, foo: foo}.add) sort({foo: nil}.i) sort({foo: str}.greet) sort({foo: true}.Bar) sortBy($env, #) == $env || true sortBy($env.array, #) sortBy($env.array, f64) sortBy($env.array, str) sortBy($env.list, #.Bar) sortBy($env.list, f64) sortBy($env.list, i) sortBy($env.list, str) sortBy($env?.[str], #) sortBy($env?.[str], $env?.i) sortBy($env?.[str], f64) sortBy($env?.[str], str) sortBy($env?.array, #) sortBy($env?.array, str) sortBy($env?.list, .Bar) sortBy($env?.list, f64) sortBy($env?.list, i) sortBy(0 .. 0, #) sortBy(0 .. 0, str) sortBy(0 .. 1, #) sortBy(0 .. i, # ^ i) sortBy([$env], #) sortBy([$env], #.String?.[foo]) sortBy([$env], #?.add) sortBy([$env], .list) sortBy([$env], f64 ?? .array) sortBy([$env], greet) sortBy([$env], str) sortBy([0], $env.ok) sortBy([0], $env?.Bar) sortBy([0], add) sortBy([0], greet) sortBy([1.0], $env?.ok) sortBy([1.0], f64) sortBy([1], 0 >= #) sortBy([array], f64) sortBy([f64], # + #) sortBy([f64], add) sortBy([f64], array) sortBy([f64], f64) sortBy([f64], i) sortBy([false], list) sortBy([foo], #) sortBy([foo], #?.Bar) sortBy([foo], add) sortBy([foo], array) sortBy([foo], foo) sortBy([greet], #) sortBy([groupBy(array, #)], #) sortBy([i], array) sortBy([list], #) sortBy([nil], add) sortBy([nil], array) sortBy([ok], add) sortBy([str], #) sortBy([str], findIndex(list, ok)) sortBy([true], f64) sortBy([true], i) sortBy(array ?? 1.0, #) sortBy(array ?? f64, f64) sortBy(array | sortBy(#), #) sortBy(array, # * #) sortBy(array, # ** #) sortBy(array, # + #) sortBy(array, # - 1) sortBy(array, # / #) sortBy(array, # / f64) sortBy(array, # ?? #) sortBy(array, # ?? foo) sortBy(array, # ?? str) sortBy(array, # ^ #) sortBy(array, # ^ 1) sortBy(array, # | bitshl(#)) sortBy(array, # | mean(#, #)) sortBy(array, #) sortBy(array, #) | any(ok) sortBy(array, #) | findIndex(false) sortBy(array, #) | groupBy(true) sortBy(array, #) | map(#) sortBy(array, #) | map($env) sortBy(array, #) | map(0) sortBy(array, #) | map(foo) sortBy(array, #) | min(array, 1) sortBy(array, #) | reduce(#) sortBy(array, #) | reduce(#, 1) sortBy(array, #) | reduce($env) sortBy(array, #) | reduce(1.0, nil) sortBy(array, #) | reduce(true, 1.0) sortBy(array, #)?.[i] sortBy(array, $env.f64) sortBy(array, $env.i) sortBy(array, $env.str) sortBy(array, $env?.[str]) sortBy(array, $env?.i) sortBy(array, -#) sortBy(array, -0) sortBy(array, -1.0) sortBy(array, 0 * #) sortBy(array, 0 ** #) sortBy(array, 0 - 1) sortBy(array, 0) | map(#) sortBy(array, 0) | sortBy(#) sortBy(array, 0)?.[i] sortBy(array, 1 ** f64) sortBy(array, 1 + #) sortBy(array, 1 / #) sortBy(array, 1 ?? false) sortBy(array, 1 ^ #) sortBy(array, 1) | all(ok) sortBy(array, 1) | groupBy(#) sortBy(array, 1) | reduce($env) sortBy(array, 1) | reduce(foo) sortBy(array, 1)?.[i] sortBy(array, 1.0 ^ #) sortBy(array, 1.0) | findLast(false) sortBy(array, 1.0) | max(1.0) sortBy(array, 1.0)?.[i] sortBy(array, abs(#)) sortBy(array, bitnand(#, #)) sortBy(array, bitnot(#)) sortBy(array, f64 ** #) sortBy(array, f64) sortBy(array, f64) | groupBy(1.0) sortBy(array, f64) | reduce(#, 1.0) sortBy(array, f64)?.[i] sortBy(array, findLast(array, ok)) sortBy(array, findLastIndex($env, ok)) sortBy(array, float(1)) sortBy(array, foo.Bar) sortBy(array, foo?.Bar) sortBy(array, i ** #) sortBy(array, i + 1) sortBy(array, i - #) sortBy(array, i) sortBy(array, i) | find(false) sortBy(array, i) | map(list) sortBy(array, i)?.[i] sortBy(array, max(#)) sortBy(array, mean(#)) sortBy(array, median(1.0)) sortBy(array, min(#)) sortBy(array, round(#)) sortBy(array, round(i)) sortBy(array, str) sortBy(array, str) | groupBy(1.0) sortBy(array, str) | map(list) sortBy(array, str) | none(ok) sortBy(array, str) | reduce(#) sortBy(array, str) | reduce(ok) sortBy(array, str) | sortBy(0) sortBy(array, str)?.[i] sortBy(array, string(1.0)) sortBy(array, toJSON(f64)) sortBy(array, toJSON(foo)) sortBy(array, toJSON(nil)) sortBy(array[:i], str) sortBy(concat(array), #) sortBy(concat(array), round(i)) sortBy(filter($env, false), #.foo) sortBy(filter($env, false), .add) sortBy(filter($env, false), findLast($env, #.greet)) sortBy(flatten(array), #) sortBy(flatten(list), f64) sortBy(flatten(list), str) sortBy(let foobar = array; foobar, # * 1.0) sortBy(list | map(i), # ^ #) sortBy(list, #.Bar) sortBy(list, #.Bar) | map(#) sortBy(list, #.Bar)?.[i] sortBy(list, #.String()) sortBy(list, #?.Bar) sortBy(list, $env.f64) sortBy(list, $env.i) sortBy(list, $env.str) sortBy(list, $env?.[str]) sortBy(list, $env?.i) sortBy(list, -0) sortBy(list, -1.0) sortBy(list, -f64) sortBy(list, .Bar) sortBy(list, .Bar) != list sortBy(list, .Bar) | sum(f64) sortBy(list, 0 ^ 0) sortBy(list, 0) ?? greet sortBy(list, 0)?.[i] sortBy(list, 1 ?? #) sortBy(list, 1 ?? greet) sortBy(list, 1)?.[i] sortBy(list, 1.0 ** f64) sortBy(list, 1.0 + i) sortBy(list, 1.0) | groupBy(true) sortBy(list, 1.0) | map(list) sortBy(list, 1.0) | reduce(greet) sortBy(list, 1.0) | sortBy(i) sortBy(list, 1.0)?.[$env?.i] sortBy(list, 1.0)?.[i] sortBy(list, abs(0)) sortBy(list, abs(f64)) sortBy(list, bitnand(0, 1)) sortBy(list, bitnot(1)) sortBy(list, f64) sortBy(list, f64) | filter(true) sortBy(list, f64) | map($env) sortBy(list, f64) | reduce(#) sortBy(list, f64) | sum(0) sortBy(list, f64)?.[i] sortBy(list, foo.String()) sortBy(list, foo?.Bar) sortBy(list, greet(#.Bar)) sortBy(list, greet(.Bar)) sortBy(list, greet(str)) sortBy(list, i ?? #) sortBy(list, i ?? $env) sortBy(list, i) sortBy(list, i) == list sortBy(list, i) | one(false) sortBy(list, i) | reduce($env) sortBy(list, i) | reduce(add) sortBy(list, i)?.[i] sortBy(list, len(#.Bar)) sortBy(list, len(list)) sortBy(list, reduce(array, i)) sortBy(list, round(1)) sortBy(list, round(1.0)) sortBy(list, str) sortBy(list, str) | map(0) sortBy(list, str) | map(array) sortBy(list, str) | reduce(true) sortBy(list, str)?.[i] sortBy(list, string(#.Bar)) sortBy(list, string(1.0)) sortBy(list, string(greet)) sortBy(list, string(ok)) sortBy(list, sum(array)) sortBy(list, toBase64(#.Bar)) sortBy(list, toBase64(str)) sortBy(list, toJSON(#.Bar)) sortBy(list, toJSON(i)) sortBy(list, trimPrefix(str)) sortBy(list, type(1.0)) sortBy(list, type(add)) sortBy(list, type(false)) sortBy(list, type(list)) sortBy(map($env, greet), type(f64)) sortBy(map(array, #), #) sortBy(map(array, add), bitnot(1)) sortBy(sort($env), #) sortBy(sort($env), #.array .. .f64) sortBy(sort($env), f64) sortBy(sort($env), map(#.list, array)) sortBy(sort($env), ok) sortBy(sortBy(array, i), #) sortBy(take(list, 1), #) sortBy(uniq(array), #) split($env.str, str) split(str, $env?.[str]) split(str, $env?.str) split(str, str) split(str, str)?.[i] split(str, string($env)) split(str, toBase64(str)) splitAfter(foo?.Bar, str) splitAfter(str, foo?.String()) splitAfter(str, str) splitAfter(str, toJSON(nil)) str str != $env == $env str != $env ? 1.0 : $env str != $env ?? $env str != $env ?? 1.0 str != $env ?? i str != $env and false str != $env and ok str != $env or $env str != $env or false str != $env.str str != $env?.Bar str != $env?.String str != $env?.[Bar] str != $env?.[String] str != $env?.[foobar] str != $env?.[nil] str != $env?.[str] str != $env?.foobar str != $env?.foobar?.[greet] str != $env?.str str != 0 ?? array str != 1 ?? f64 str != 1 ?? foo str != 1.0 ?? 1 str != 1.0 ?? concat($env, $env) str != 1.0 ?? list str != add ?? foo str != array ?? $env?.[String] str != f64 ?? array str != first($env) str != foo ?? $env?.greet str != foo ?? 1.0 str != foo ?? array str != foo ?? f64 str != foo ?? false str != foo ?? greet str != foo ?? greet and $env str != foo.Bar str != foo.String() str != foo?.Bar str != foo?.String() str != greet ?? $env?.[String] str != greet ?? array str != greet ?? ok str != greet(str) str != i ?? array str != list ?? 1 str != list ?? false str != list ?? true str != lower(str) str != median(array) str != min(array, array) str != nil != nil str != nil && $env str != nil == true str != nil ? foo : f64 str != nil ?? $env str != nil or $env str != nil or $env?.[Bar] str != nil or ok str != nil || $env str != nil || false str != nil || ok str != ok ?? 1 str != reduce(array, #acc, foo) str != reduce(list, .Bar, false) str != str str != str != false str != str && $env?.String.i() str != str && true str != str ? 0 : 1.0 str != str ? foo : true str != str ?? 1.0 str != str ?? i str != str ?? ok str != str and $env str != str || $env str != str || false str != string(1.0) str != string(f64) str != string(false) str != string(list) str != toJSON(1.0) str != toJSON(false) str != toJSON(foo) str != trim(str) str != true ?? f64 str != true ?? str str != type($env) str != type(false) str != type(foo) str != type(str) str + $env not endsWith $env and false str + $env.str str + $env?.[str] str + $env?.str str + foo.Bar str + foo.String() str + foo?.Bar str + foo?.String() str + greet(str) str + repeat(str, 1) str + str str + str != $env str + str ?? foo str + str in max($env) str + str not in $env str + string($env) str + string(add) str + string(f64) str + string(list) str + string(nil) str + string(str) str + toBase64(str) str + toJSON(1.0) str + toJSON(false) str + toJSON(i) str + toJSON(list) str + toJSON(nil) str + toJSON(ok) str + toJSON(str) str + type($env) str + type(foo) str < $env && false str < $env.str str < $env?.[str] str < $env?.str str < -$env or true str < foo.Bar str < foo.String() str < foo?.Bar str < foo?.String() str < greet(str) str < nil ?? str str < str str < str && false str < str and ok str < str || ok str < string($env) str < string(add) str < string(foo) str < string(greet) str < string(str) str < toJSON(foo) str < type(array) str < type(nil) str < type(str) str < type(true) str <= $env or true str <= $env.str str <= $env?.[str] str <= $env?.foobar and false str <= $env?.str str <= foo.Bar str <= foo.String() str <= foo?.Bar str <= foo?.String() str <= greet(str) str <= str str <= str != $env str <= str != nil str <= str ?: str str <= str ?? f64 str <= str[:i] str <= string($env) str <= string(0) str <= string(i) str <= string(list) str <= string(nil) str <= string(true) str <= toJSON(1.0) str <= toJSON(f64) str <= toJSON(foo) str <= toJSON(nil) str <= toJSON(ok) str <= type(1.0) str <= type(add) str <= type(foo) str <= type(list) str <= type(str) str <= type(true) str == $env != nil str == $env && ok str == $env ?? 1 str == $env or $env str == $env || $env?.[Bar] str == $env.str str == $env?.Bar str == $env?.String str == $env?.[Bar] str == $env?.[Bar]?.[array] str == $env?.[Bar]?.[list] str == $env?.[String] str == $env?.[String]?.add str == $env?.[String]?.array str == $env?.[foobar] str == $env?.[str] str == $env?.foo.Bar str == $env?.foobar str == $env?.foobar?.String str == $env?.not str == $env?.str str == $env?.true str == 0 ?? 1.0 str == 1 ?? add str == 1.0 ?? foo str == add ?? list str == f64 ?? 0 str == false ?? str str == first($env) str == foo ?? add str == foo ?? str str == foo.Bar str == foo.String() str == foo?.Bar str == foo?.String() str == greet(str) str == i ?? array str == list ?? foo str == max($env) str == nil == ok str == nil ?: list str == nil or true || $env str == reduce(array, str) str == str str == str || $env[true:] str == str || true str == string(add) str == string(foo) str == string(ok) str == toBase64(str | repeat(0)) str == toJSON(0) str == toJSON(1.0) str == toJSON(f64) str == toJSON(nil) str == trim(str) str == true ?? foo str == type(add) str == type(foo) str == type(greet) str == upper(str) str == {foo: 1}.array str > $env or true str > $env || true str > $env.str str > $env?.[str] str > $env?.foo?.String() str > $env?.str str > foo.Bar str > foo.Bar < foo.Bar str > foo.String() str > foo?.Bar str > foo?.String() str > str str > str + $env.str str > str + str str > str < $env?.str str > str > $env?.Bar str > str > $env?.[list] str > str ?: 1 str > str ?: str str > str and true str > str[1:] str > str[int(0):] str > string($env) str > string(nil) str > string(true) str > toJSON(1.0) str > toJSON(foo) str > toJSON(ok) str > trimSuffix(str) str > type(1) str > type(1.0) str > type(add) str > type(false) str > type(nil) str > upper(toJSON(false)) str >= $env && false str >= $env or true str >= $env.str str >= $env?.[str] str >= $env?.[str] ?? list str >= $env?.foo.Bar str >= $env?.str str >= foo.Bar str >= foo.String() str >= foo?.Bar str >= foo?.String() str >= greet(str) str >= str str >= str != $env str >= str ?? nil str >= string(1) str >= string(1.0) str >= string(add) str >= string(str) str >= toJSON(false) str >= toJSON(str) str >= type(1) str >= type(list) str ?? !$env str ?? !ok str ?? $env ?? f64 str ?? $env ?? foo str ?? $env ?? foo?.String str ?? $env ?? list str ?? $env ?? ok str ?? $env ?? str str ?? $env | any(false) str ?? $env | greet() str ?? $env | groupBy(#) str ?? $env | map(#) str ?? $env | reduce(#) str ?? $env | reduce($env, false) str ?? $env | reduce(0) str ?? $env | reduce(foo, foo) str ?? $env | reduce(true, 1.0) str ?? $env | sum(#) str ?? $env.add str ?? $env.array str ?? $env.f64 str ?? $env.foo str ?? $env.greet str ?? $env.i str ?? $env.list str ?? $env.ok str ?? $env.str str ?? $env?.Bar str ?? $env?.Bar() str ?? $env?.Bar(foo) str ?? $env?.Bar(list) str ?? $env?.String str ?? $env?.String() str ?? $env?.String(foo contains foobar) str ?? $env?.[1.0] str ?? $env?.[Bar | any(1)] str ?? $env?.[Bar()] str ?? $env?.[Bar] str ?? $env?.[Bar].String() str ?? $env?.[String] str ?? $env?.[String].list str ?? $env?.[[foo]] str ?? $env?.[add] str ?? $env?.[add].greet str ?? $env?.[add]?.[f64] str ?? $env?.[array] str ?? $env?.[array].f64() str ?? $env?.[f64] str ?? $env?.[f64].f64 str ?? $env?.[foo] str ?? $env?.[foobar] str ?? $env?.[greet] str ?? $env?.[i] str ?? $env?.[i]?.foo str ?? $env?.[list] str ?? $env?.[list]?.add?.[array] str ?? $env?.[list]?.i str ?? $env?.[nil] str ?? $env?.[ok] str ?? $env?.[ok]?.Bar str ?? $env?.[str] str ?? $env?.add str ?? $env?.array str ?? $env?.f64 str ?? $env?.foo str ?? $env?.foobar str ?? $env?.greet str ?? $env?.i str ?? $env?.list str ?? $env?.nil str ?? $env?.ok str ?? $env?.str str ?? $env[:foobar] str ?? $env[:list?.f64()] str ?? $env[f64:] str ?? $env[ok:] str ?? -$env str ?? -0 str ?? -1 str ?? -1.0 str ?? -i str ?? 0 | all(false) str ?? 0 | groupBy(foo) str ?? 0 | map(greet) str ?? 0 | map(ok) str ?? 0 | sum(f64) str ?? 1 ?? foo str ?? 1 | greet() str ?? 1 | map(foo) str ?? 1 | map(i) str ?? 1.0 ?? foo str ?? 1.0 | findLast(true) str ?? 1.0 | findLastIndex(ok) str ?? 1.0 | groupBy(#) str ?? 1.0 | groupBy(0) str ?? 1.0 | map(#) str ?? 1.0 | map(1) str ?? 1.0 | map(1.0) str ?? 1.0 | reduce(#) str ?? 1.0 | reduce(false == #) str ?? 1.0 | sum(#) str ?? [0, i] str ?? [1.0] str ?? [f64] str ?? [foo] str ?? [nil] str ?? [true] str ?? add str ?? add ?? $env str ?? add | count(true) str ?? add | map(add) str ?? add | reduce(foo) str ?? add | reduce(greet) str ?? all($env, #) str ?? all(list, $env) str ?? array str ?? array | findIndex(true) str ?? array | map(array) str ?? array | none(true) str ?? array?.[i] str ?? concat(array) str ?? count($env) str ?? date(array) str ?? date(greet) str ?? date(ok, foo) str ?? duration(str) str ?? f64 str ?? f64 | groupBy(#) str ?? false | count(false) str ?? false | findLastIndex(# not in list) str ?? false | groupBy(#) str ?? false | map(0) str ?? false | map(foo) str ?? false | reduce(#) str ?? findIndex($env, #) str ?? first($env) str ?? float(1.0) str ?? floor(1) str ?? foo str ?? foo ?? $env str ?? foo ?? 1.0 str ?? foo ?? f64 str ?? foo ?? list str ?? foo ?? nil str ?? foo ?? ok str ?? foo ?? str str ?? foo | any(ok) str ?? foo | count(ok) str ?? foo | findLastIndex(false) str ?? foo | findLastIndex(ok) str ?? foo | groupBy(1.0) str ?? foo | map(#) str ?? foo | map(ok) str ?? foo | none(ok) str ?? foo | none(true) str ?? foo | one(false) str ?? foo | reduce(#, 1) str ?? foo | reduce(add) str ?? foo | reduce(greet, foo) str ?? foo | reduce(i, nil) str ?? foo | sortBy(0) str ?? foo | sum(#) str ?? foo.Bar str ?? foo.String str ?? foo.String() str ?? foo?.Bar str ?? foo?.String str ?? fromJSON($env) str ?? greet str ?? greet | greet() str ?? greet | groupBy(1.0) str ?? greet | groupBy(i) str ?? greet | groupBy(ok) str ?? greet | none(true) str ?? greet | reduce(#) str ?? greet | reduce(str) str ?? greet($env) str ?? greet(str) str ?? groupBy($env, 1.0) str ?? i str ?? i ?? 1 str ?? i ?? ok str ?? i | map(true) str ?? i | reduce(#) str ?? i | reduce($env) str ?? i | reduce($env, greet) str ?? i | reduce(false) str ?? i | sortBy(#) str ?? i | sum(#) str ?? indexOf($env, str) str ?? len(list) str ?? list str ?? list ?? $env | reduce(#) str ?? list ?? true str ?? list | any(ok) str ?? list | map(list) str ?? list | map(str) str ?? list | sortBy(f64) str ?? list?.[i] str ?? map($env, add) str ?? map(array, 1) str ?? max($env) str ?? max(0, 1) str ?? max(1.0) str ?? mean(array).i() str ?? min(1.0) str ?? min(list) str ?? nil ?? list str ?? nil | greet() str ?? not $env str ?? not false str ?? not true str ?? ok str ?? ok ?? array str ?? ok ?? toJSON(1) str ?? ok | all(ok) str ?? ok | find(ok) str ?? ok | findIndex(false) str ?? ok | groupBy(foo) str ?? ok | map(#) str ?? ok | map($env) str ?? ok | map(list) str ?? one($env, .greet) str ?? reduce($env, #) str ?? round(0) str ?? sortBy(array, f64) str ?? str str ?? str ?? str str ?? str[:sum(array)] str ?? string(1) str ?? string(array) str ?? string(true) str ?? sum($env) str ?? sum($env, #.f64) str ?? sum($env, .String) str ?? sum(array, foo) str ?? toJSON(0) str ?? toJSON(foo) str ?? toJSON(nil) str ?? toJSON(str) str ?? toPairs($env) str ?? toPairs($env?.String) str ?? trim($env) str ?? trimSuffix($env) str ?? true ?? greet str ?? true | all(true) str ?? true | find(false) str ?? true | greet() str ?? true | reduce(#) str ?? true | reduce($env) str ?? true | sum(1.0) str ?? type(1) str ?? type(1.0) str ?? type(nil) str ?? {foo: 1.0} str ?? {foo: 1} str ?? {foo: array} str ?? {foo: nil} str ?? {foo: true} str contains $env.str str contains $env?.Bar str contains $env?.String str contains $env?.String?.[i] str contains $env?.String?.list str contains $env?.[Bar] str contains $env?.[Bar]?.foo str contains $env?.[String] str contains $env?.[String]?.[i] str contains $env?.[foobar] str contains $env?.[str] str contains $env?.false str contains $env?.foobar str contains $env?.str str contains foo.Bar str contains foo.String() str contains foo?.Bar str contains foo?.String() str contains greet(str) str contains last($env) str contains str str contains str && ok str contains str == ok str contains str ?? $env str contains str ?? list str contains str ?? str str contains str or $env?.[foo] str contains str[:i] str contains string(greet) str contains string(ok) str contains string(str) str contains toJSON(f64) str contains toJSON(foo) str contains toJSON(nil) str contains toJSON(ok) str contains trimSuffix(str) str contains type(foo) str contains type(nil) str contains type(ok) str endsWith $env.str str endsWith $env?.Bar str endsWith $env?.Bar?.foo(foo) str endsWith $env?.String str endsWith $env?.[Bar] str endsWith $env?.[Bar]?.add str endsWith $env?.[String] str endsWith $env?.[String]?.[add] str endsWith $env?.[foobar] str endsWith $env?.[str] str endsWith $env?.foobar str endsWith $env?.str str endsWith first($env) str endsWith foo.Bar str endsWith foo.String() str endsWith foo?.Bar str endsWith foo?.String() str endsWith greet(str) str endsWith str str endsWith str == nil str endsWith str ?? foo str endsWith str ?? ok str endsWith string(foo) str endsWith string(nil) str endsWith string(ok) str endsWith toJSON(0) str endsWith toJSON(foo) str endsWith toJSON(i) str endsWith toJSON(nil) str endsWith toJSON(str) str endsWith toJSON(true) str endsWith trimPrefix($env.str) str endsWith trimSuffix(str) str endsWith type($env) str endsWith type(add) str endsWith type(i) str endsWith type(list) str endsWith type(str) str endsWith {foo: f64}.f64 str endsWith {foo: nil, foo: $env}?.f64 str in $env != $env str in $env && $env str in $env == ok str in $env ?? $env?.[i] str in $env ?? str str in $env and $env str in $env and false str in $env and ok str in $env || $env str in $env || ok str in $env.foo str in $env?.Bar str in $env?.String str in $env?.String?.[f64] str in $env?.[Bar] str in $env?.[Bar]?.[ok] str in $env?.[Bar]?.[str] str in $env?.[String] str in $env?.[String]?.str() str in $env?.[foobar?.[str]] str in $env?.[foobar] str in $env?.foo str in $env?.foobar str in $env?.foobar?.greet str in [$env, nil] str in [nil] str in array ?? foo str in concat(array) str in find($env, false) str in find(list, true) str in foo str in foo != false str in foo ?? greet str in foo and array != array str in foo and false str in foo || $env str in list?.[i] str in min($env) str in sort(array) str in {foo: $env?.[Bar]} str in {foo: 1} str in {foo: f64} str in {foo: foo} str in {foo: i, foo: 1} str in {foo: nil, foo: 1.0} str in {foo: nil} str matches $env and false str matches $env.str str matches $env?.Bar str matches $env?.String str matches $env?.String?.list str matches $env?.[Bar] str matches $env?.[Bar]?.f64 str matches $env?.[String] str matches $env?.[foobar] str matches $env?.[foobar]?.str str matches $env?.[str] str matches $env?.foobar str matches $env?.foobar?.[ok] str matches $env?.str str matches foo.Bar str matches foo.String() str matches foo?.Bar str matches foo?.String() str matches last($env) str matches lower(str) str matches str str matches str == nil str matches str ?? 1.0 str matches str ?? foo str matches str ?? i str matches str || $env str matches string($env) str matches string($env?.[String]) str matches string(1) str matches string(1.0) str matches string(add) str matches toBase64(str) str matches toJSON(1.0) str matches toJSON(nil) str matches toJSON(ok) str matches trimSuffix(str) str matches type(0) str matches type(1) str matches type(f64) str matches type(foo) str matches type(greet) str matches type(i) str matches type(str) str matches type(true) str matches {foo: i}?.foobar str not contains $env.str str not contains $env?.Bar str not contains $env?.Bar?.[f64] str not contains $env?.String str not contains $env?.String?.String str not contains $env?.[Bar] str not contains $env?.[Bar]?.Bar() str not contains $env?.[String] str not contains $env?.[foobar] str not contains $env?.[nil] str not contains $env?.[str] str not contains $env?.foobar str not contains $env?.nil str not contains $env?.str str not contains $env?.true?.[greet] str not contains foo.Bar str not contains foo.String() str not contains foo?.Bar str not contains foo?.String() str not contains greet(str) str not contains last($env) str not contains last($env)?.add str not contains lower(str) str not contains str str not contains str && $env str not contains str + str str not contains str[:1] str not contains string($env) str not contains string(add) str not contains string(nil) str not contains string(str) str not contains toJSON(0) str not contains toJSON(array) str not contains trim(str) str not contains trimPrefix(str) str not contains trimSuffix(str) str not contains type(0) str not contains type(foo) str not contains type(greet) str not contains type(list) str not contains type(str) str not contains upper(str) str not contains {foo: foo}.String str not endsWith $env and false str not endsWith $env.str str not endsWith $env?.Bar str not endsWith $env?.Bar?.[list] str not endsWith $env?.String str not endsWith $env?.[Bar] str not endsWith $env?.[Bar]?.String str not endsWith $env?.[String] str not endsWith $env?.[String]?.String str not endsWith $env?.[String]?.[add]?.[add] str not endsWith $env?.[String]?.[greet] str not endsWith $env?.[foobar?.foo($env)] str not endsWith $env?.[str] str not endsWith $env?.false str not endsWith $env?.foobar str not endsWith $env?.greet(str) str not endsWith $env?.not str not endsWith $env?.str str not endsWith first($env) str not endsWith first($env)?.[greet] str not endsWith foo.Bar str not endsWith foo.String() str not endsWith foo?.Bar str not endsWith foo?.String() str not endsWith greet(str) str not endsWith str str not endsWith str && $env?.String str not endsWith str ?? array str not endsWith str ?? nil str not endsWith str || $env.ok str not endsWith str || true str not endsWith string(1) str not endsWith toBase64(str) str not endsWith toJSON(foo) str not endsWith trimSuffix(str) str not endsWith type(i) str not endsWith type(list) str not endsWith upper(foo?.String()) str not endsWith {foo: foo}.i str not in $env && $env str not in $env == $env str not in $env ? $env : $env str not in $env ? 1.0 : false str not in $env ?? list str not in $env and false str not in $env.foo str not in $env?.Bar str not in $env?.Bar?.add str not in $env?.String str not in $env?.String?.[ok] str not in $env?.[Bar] str not in $env?.[Bar]?.String str not in $env?.[Bar]?.list str not in $env?.[String] str not in $env?.[String]?.[array] str not in $env?.[String]?.add() str not in $env?.[foobar] str not in $env?.[foobar]?.[ok] str not in $env?.[foobar]?.ok str not in $env?.[nil] str not in $env?.foo str not in $env?.foobar str not in $env?.foobar?.[ok] str not in [greet, $env] str not in [nil, add] str not in [nil, greet] str not in [nil] str not in array ?? 1 str not in foo str not in foo != false str not in foo && $env str not in foo && $env || true str not in foo && false str not in foo ? 1.0 : i str not in foo ?? $env str not in foo ?? f64 str not in foo ?? foo str not in foo and false str not in foo and ok str not in foo or $env?.[f64] str not in foo || $env str not in foo || ok str not in foo || true str not in groupBy(array, 1) str not in groupBy(list, #) str not in list ?? foo str not in list?.[i] str not in map(list, #.Bar) str not in nil ?? $env str not in reduce($env, $env, list) str not in reverse(array) str not in reverse(list) str not in toPairs($env) str not in {foo: $env} str not in {foo: 0, foo: add} str not in {foo: 1.0} str not in {foo: add} str not in {foo: array} str not in {foo: foo, foo: list, foo: $env} str not in {foo: foo} str not in {foo: nil} str not matches $env.str str not matches $env?.Bar str not matches $env?.String str not matches $env?.[Bar] str not matches $env?.[String] str not matches $env?.[foobar] str not matches $env?.[str] str not matches $env?.foobar str not matches $env?.foobar?.[str] str not matches $env?.nil str not matches $env?.str str not matches foo.Bar str not matches foo.String() str not matches foo?.Bar str not matches foo?.String() str not matches greet(str) str not matches lower(str) str not matches str str not matches str == $env str not matches str ?: {foo: $env} str not matches str || ok str not matches string(1) str not matches string(foo) str not matches toJSON(1.0) str not matches toJSON(f64) str not matches toJSON(foo) str not matches toJSON(i) str not matches toJSON(nil) str not matches toJSON(ok) str not matches trimSuffix(str) str not matches type(false) str not matches type(true) str not startsWith $env.str str not startsWith $env?.$env?.[add] str not startsWith $env?.Bar str not startsWith $env?.String str not startsWith $env?.[Bar] str not startsWith $env?.[Bar]?.[i] str not startsWith $env?.[Bar]?.i str not startsWith $env?.[String] str not startsWith $env?.[String]?.list str not startsWith $env?.[foobar]?.[str] str not startsWith $env?.[nil] str not startsWith $env?.[str] str not startsWith $env?.false?.[add] str not startsWith $env?.nil str not startsWith $env?.str str not startsWith findLast($env, false) str not startsWith foo.Bar str not startsWith foo.String() str not startsWith foo?.Bar str not startsWith foo?.String() str not startsWith greet(str) str not startsWith last($env) str not startsWith lower(str) str not startsWith str str not startsWith str ?: 1.0 str not startsWith str ?: ok str not startsWith str and $env str not startsWith string(false) str not startsWith string(foo) str not startsWith string(i) str not startsWith string(nil) str not startsWith string(ok) str not startsWith toJSON(foo) str not startsWith toJSON(true) str not startsWith trimSuffix(string(foo)) str not startsWith type(0) str not startsWith type(add) str not startsWith type(f64) str not startsWith type(i) str not startsWith type(ok) str not startsWith {foo: i}?.greet str startsWith $env.str str startsWith $env?.Bar str startsWith $env?.String str startsWith $env?.String?.[greet] str startsWith $env?.String?.array str startsWith $env?.[Bar] str startsWith $env?.[String] str startsWith $env?.[foobar] str startsWith $env?.[str] str startsWith $env?.foobar str startsWith $env?.str str startsWith first($env) str startsWith foo.Bar str startsWith foo.String() str startsWith foo?.Bar str startsWith foo?.String() str startsWith greet(str) str startsWith lower(type(array)) str startsWith str str startsWith str && ok str startsWith str ?? nil str startsWith str[1:] str startsWith string($env) str startsWith string(1.0) str startsWith string(add) str startsWith toBase64(str) str startsWith toJSON(1.0) str startsWith toJSON(foo) str startsWith toJSON(list) str startsWith toJSON(true) str startsWith type($env) str startsWith type(add) str startsWith type(foo) str startsWith type(i) str startsWith type(true) str | date(str) str | greet() str | greet() != $env?.$env str | greet() < str str | greet() not in foo str | hasPrefix($env?.[str]) str | hasPrefix(str) str | hasSuffix(str) str | indexOf(str) str | indexOf(toJSON(foo)) str | lastIndexOf(str) str | repeat(0) str | repeat(1) str | repeat(i) str | split(str) str | split(str, i) str | splitAfter($env?.[str]) str | splitAfter($env?.str) str | splitAfter(foo?.Bar) str | splitAfter(str) str | splitAfter(str, 1) str | trim(nil ?? str) str | trim(str) str | trim(type(1.0)) str | trimPrefix(str) str | trimPrefix(toJSON(ok)) str | trimPrefix(type(i)) str | trimSuffix(str) str; $env | count(false) str; $env?.[Bar] str; $env?.add str; $env?.ok str; add str; array str; f64 str; foo str; greet str; i str; ok str; str str; uniq(array) str[$env?.i:] str[-0:] str[-1:] str[0:] + str ?? i str[1 ?? add:] str[1.0 ?? foo:] str[1:] endsWith str str[1:] not contains str str[1:] | greet() str[:$env.i] str[:$env?.i] str[:-1] str[:-i] str[:0 % i] str[:0] matches str str[:] str[:] <= str str[:array | reduce(#)] str[:array?.[i]] str[:i] str[:int(i)] str[:last(array)] str[:median(1, 1.0)] str[:min(0)] str[:nil ?? 0] str[:sum(array)] str[f64 ?? str:] str[first(array):] str[i:] str[i:] endsWith str str[i:] not endsWith str str[i:i] str[len(str):] str[nil ?? 0:] str[sum(array):] string(!false) string(!ok) string(!true) string($env != 0) string($env != 1) string($env != 1.0) string($env != add) string($env != f64) string($env != false) string($env != foo) string($env != foo?.String()) string($env != greet) string($env != i) string($env != nil) string($env != ok) string($env != str) string($env != true) string($env && false) string($env && true) string($env == $env) string($env == 1.0) string($env == array) string($env == f64) string($env == false) string($env == foo) string($env == greet) string($env == nil) string($env == str) string($env ?? $env) string($env ?? 1) string($env ?? 1.0) string($env ?? add) string($env ?? f64) string($env ?? false) string($env ?? foo) string($env ?? list) string($env ?? nil) string($env ?? ok) string($env ?? true) string($env and true) string($env in $env?.[Bar]) string($env in array) string($env in list) string($env not in array) string($env or true) string($env | all(false)) string($env | all(ok)) string($env | count(false)) string($env | count(ok)) string($env | count(true)) string($env | findIndex(ok)) string($env | findIndex(true)) string($env | findLastIndex(true)) string($env | map(#index)) string($env | map($env)) string($env | map(1)) string($env | map(array)) string($env | map(greet)) string($env | map(true)) string($env | none(ok)) string($env | one(ok)) string($env | one(true)) string($env | reduce($env, ok)) string($env | reduce(1, array)) string($env | reduce(f64, 1.0)) string($env | sum(0)) string($env | sum(1)) string($env | sum(1.0)) string($env | sum(f64)) string($env || false) string($env || true) string($env) ?? f64 string($env) ?? i string($env) matches str string($env) not in foo string($env) not matches $env?.Bar string($env) not matches str string($env) not startsWith str string($env) | greet() string($env) | trimPrefix(str) string($env)[:] string($env)[i:] string($env.add) string($env.array) string($env.f64) string($env.foo) string($env.greet) string($env.i) string($env.list) string($env.ok) string($env.str) string($env?.$env) string($env?.Bar) string($env?.Bar?.[list]) string($env?.Bar?.[str]) string($env?.Bar?.greet) string($env?.String) string($env?.String?.Bar) string($env?.String?.String) string($env?.String?.list) string($env?.[Bar]) string($env?.[Bar]?.Bar) string($env?.[Bar]?.[i]) string($env?.[Bar]?.foobar) string($env?.[String]) string($env?.[String]?.array) string($env?.[String]?.str) string($env?.[foobar]) string($env?.[nil]) string($env?.[str]) string($env?.add) string($env?.array) string($env?.f64) string($env?.false) string($env?.foo) string($env?.foobar) string($env?.greet) string($env?.i) string($env?.list) string($env?.nil) string($env?.ok) string($env?.str) string($env?.str[:]) string($env?.true) string(-0) string(-1 == nil) string(-1) string(-1.0) string(-f64) string(-i) string(0 != 0) string(0 != 1.0) string(0 != i) string(0 != nil) string(0 % 1) string(0 * 0) string(0 * 1) string(0 * f64) string(0 * i) string(0 ** 0) string(0 ** 1) string(0 ** 1.0) string(0 ** f64) string(0 ** i) string(0 + 0) string(0 + 1.0) string(0 - 1) string(0 - i) string(0 .. 0) string(0 .. i) string(0 / $env.f64) string(0 / 1) string(0 < 0) string(0 < 1) string(0 < 1.0) string(0 < f64) string(0 <= 0) string(0 <= 1.0) string(0 <= f64) string(0 <= i) string(0 == $env) string(0 == 1) string(0 == f64) string(0 == i) string(0 == nil) string(0 > 1) string(0 > f64) string(0 > i) string(0 >= 1) string(0 >= 1.0) string(0 >= f64) string(0 >= i) string(0 ?? 1) string(0 ?? 1.0) string(0 ?? array) string(0 ?? f64) string(0 ?? foo) string(0 ?? i) string(0 ?? list) string(0 ?? str) string(0 ?? true) string(0 ^ i) string(0 | mean(f64)) string(0) >= str string(0) ?? $env?.list string(0) ?? 0 | find(true) string(0) contains string(str) string(0) not startsWith str string(0) | greet() string(0)[:] string(0)[i:] string(0..i) string(1 != 1) string(1 != 1.0) string(1 != f64) string(1 != nil) string(1 % 1) string(1 * 0) string(1 * 0) ?? add string(1 * 1.0) string(1 * f64) string(1 * i) string(1 ** 0) string(1 ** 1) string(1 ** 1.0) string(1 ** f64) string(1 ** i) string(1 + 1) string(1 + i) string(1 - 0) string(1 - 1) string(1 - 1.0) string(1 - f64) string(1 .. 0) string(1 .. 1) string(1 .. i) string(1 / 0) string(1 / 1) string(1 / 1.0) string(1 / f64) string(1 < 0) string(1 < 1.0) string(1 < i) string(1 <= 1.0) string(1 <= f64) string(1 <= i) string(1 == $env) string(1 == i) string(1 == nil) string(1 > $env?.i) string(1 > 0) string(1 > 1) string(1 >= 1) string(1 >= 1.0) string(1 >= f64) string(1 >= i) string(1 ?? $env) string(1 ?? 0) string(1 ?? 1.0) string(1 ?? array) string(1 ?? f64) string(1 ?? false) string(1 ?? foo) string(1 ?? i) string(1 ?? nil) string(1 ?? str) string(1 ^ 1) string(1 ^ 1.0) string(1 ^ i) string(1 not in array) string(1 | min(1.0)) string(1) != str string(1) + str string(1) < foo?.Bar string(1) == $env?.[Bar] string(1) > foo?.Bar string(1) ?? i string(1) ?? list string(1) ?? str string(1) matches toJSON(false) string(1) not in foo string(1) not startsWith toJSON(1) string(1) | greet() string(1..i) string(1.0 != $env) string(1.0 != 0) string(1.0 != 1.0) string(1.0 != f64) string(1.0 != nil) string(1.0 * 0) string(1.0 * 1) string(1.0 * 1.0) string(1.0 * f64) string(1.0 * i) string(1.0 ** 0) string(1.0 ** 1) string(1.0 ** 1.0) string(1.0 ** f64) string(1.0 ** i) string(1.0 + 0) string(1.0 + 1) string(1.0 + 1.0) string(1.0 + f64) string(1.0 + i) string(1.0 - 0) string(1.0 - 1) string(1.0 - 1.0) string(1.0 - f64) string(1.0 - i) string(1.0 / 0) string(1.0 / 1) string(1.0 / 1.0) string(1.0 / f64) string(1.0 / i) string(1.0 < 0) string(1.0 < 1) string(1.0 < 1.0) string(1.0 <= 0) string(1.0 <= 1) string(1.0 <= 1.0) string(1.0 <= i) string(1.0 == $env) string(1.0 == 0) string(1.0 == 1) string(1.0 == 1.0) string(1.0 == f64) string(1.0 == i) string(1.0 == nil) string(1.0 > 0) string(1.0 > 1) string(1.0 > 1.0) string(1.0 > f64) string(1.0 > i) string(1.0 >= 0) string(1.0 >= 1) string(1.0 >= 1.0) string(1.0 >= i) string(1.0 ?? $env) string(1.0 ?? 0) string(1.0 ?? 1.0) string(1.0 ?? array) string(1.0 ?? false) string(1.0 ?? foo) string(1.0 ?? foo) not endsWith str string(1.0 ?? list) string(1.0 ?? nil) string(1.0 ?? ok) string(1.0 ?? true) string(1.0 ^ 0) string(1.0 ^ 1) string(1.0 ^ 1.0) string(1.0 ^ f64) string(1.0 ^ i) string(1.0 in array) string(1.0 not in array) string(1.0 | median(array)) string(1.0) string(1.0) != str string(1.0) >= str string(1.0) >= string(i) string(1.0) ?? add string(1.0) endsWith str string(1.0) in first($env) string(1.0) not startsWith toJSON(false) string(1.0) startsWith str string(1.0) startsWith type(foo) string(1.0) | greet() string([$env, 0]) string([$env, foo]) string([$env, ok]) string([$env]) string([0, nil]) string([0]) string([1, true]) string([1.0, $env]) string([1.0]) string([1]) string([add, 1.0]) string([add]) string([array, i]) string([array]) string([f64, f64]) string([f64]) string([false, 1]) string([false]) string([foo]) string([greet, i]) string([greet]) string([i]) string([list, false]) string([list, list]) string([list]) string([nil, list]) string([nil]) string([ok, 1]) string([ok, list]) string([ok, nil]) string([ok]) string([str]) string([true, greet]) string([true, list]) string([true]) string(abs(0)) string(abs(1)) string(abs(1.0)) string(abs(f64)) string(abs(i)) string(add != $env) string(add == add) string(add == nil) string(add ?? 1.0) string(add ?? add) string(add ?? f64) string(add ?? foo) string(add(1, 0)) string(add(1, 1)) string(add(1, i)) string(add) string(add) ?? ok string(add) in foo string(add) matches str string(add) | greet() string(any($env, false)) string(any($env, ok)) string(any(array, false)) string(any(array, ok)) string(array != $env) string(array != array) string(array != list) string(array != nil) string(array == $env) string(array == array) string(array == list) string(array == nil) string(array ?? $env) string(array ?? 1.0) string(array ?? add) string(array ?? f64) string(array ?? foo) string(array ?? i) string(array | any(ok)) string(array | count(false)) string(array | findIndex(false)) string(array | findLast(false)) string(array | groupBy(i)) string(array | map(#)) string(array | map($env)) string(array | map(f64)) string(array | one(true)) string(array | reduce(#)) string(array | reduce(#acc)) string(array | reduce(add)) string(array | reduce(foo)) string(array | reduce(i)) string(array | reduce(list)) string(array | sortBy(#)) string(array | sortBy(i)) string(array | sum(#)) string(array | sum(1)) string(array | sum(f64)) string(array) string(array) > str string(array) >= foo.Bar string(array) in map(array, $env) string(array) matches str string(array) not in foo string(array) not startsWith str string(array) startsWith str string(array) | greet() string(array)[:i] string(array?.[i]) string(array[0:]) string(array[1:]) string(array[i:]) string(bitnot(0)) string(bitnot(1)) string(bitnot(i)) string(ceil(0)) string(ceil(1)) string(ceil(1.0)) string(ceil(f64)) string(ceil(i)) string(concat(array)) string(concat(list)) string(count($env, false)) string(count($env, ok)) string(count(list, ok)) string(f64 != $env) string(f64 != f64) string(f64 != nil) string(f64 * 1) string(f64 * 1.0) string(f64 * f64) string(f64 * i) string(f64 ** 0) string(f64 ** 1.0) string(f64 ** i) string(f64 + 1) string(f64 + 1.0) string(f64 + f64) string(f64 + i) string(f64 - 1) string(f64 - i) string(f64 / 0) string(f64 / 1.0) string(f64 < 1) string(f64 < 1.0) string(f64 < f64) string(f64 <= f64) string(f64 == $env) string(f64 == 0) string(f64 == 1) string(f64 == 1.0) string(f64 == nil) string(f64 > 0) string(f64 > 1) string(f64 > 1.0) string(f64 > f64) string(f64 > i) string(f64 >= 0) string(f64 >= 1) string(f64 >= 1.0) string(f64 >= i) string(f64 ?? $env) string(f64 ?? add) string(f64 ?? array) string(f64 ?? f64) string(f64 ?? false) string(f64 ?? foo) string(f64 ?? i) string(f64 ?? nil) string(f64 ^ 1.0) string(f64 ^ i) string(f64 not in array) string(f64) string(f64) + str string(f64) < str string(f64) <= str string(f64) >= str string(f64) ?? $env.ok string(f64) ?? [foo] string(false != $env) string(false != false) string(false != nil) string(false != true) string(false && $env) string(false && ok) string(false == $env) string(false == false) string(false == nil) string(false == true) string(false ? foo : 1) string(false ?: i) string(false ?? $env) string(false ?? 1.0) string(false ?? f64) string(false ?? foo) string(false ?? nil) string(false and $env) string(false and false) string(false or $env) string(false or false) string(false or ok) string(false || $env) string(false) + foo?.Bar string(false) < str string(false) == foo.Bar string(false) in $env?.[String] string(false) not contains str string(false) startsWith str string(false) | greet() string(find(array, false)) string(find(list, ok)) string(find(list, true)) string(findIndex($env, true)) string(findIndex(list, false)) string(findLast(list, false)) string(findLast(list, ok)) string(findLastIndex($env, false)) string(findLastIndex(list, false)) string(findLastIndex(list, ok)) string(first($env)) string(first(array)) string(first(list)) string(first(list)?.Bar) string(flatten(array)) string(flatten(list)) string(float(0)) string(float(1)) string(float(1.0)) string(float(f64 * 1.0)) string(float(f64)) string(float(i)) string(floor(0)) string(floor(1)) string(floor(1.0)) string(floor(f64)) string(floor(i)) string(foo != $env) string(foo != foo) string(foo != nil) string(foo == $env) string(foo == foo) string(foo == nil) string(foo ?? $env) string(foo ?? 0) string(foo ?? 1.0) string(foo ?? add) string(foo ?? array) string(foo ?? f64) string(foo ?? false) string(foo ?? foo) string(foo ?? foo) ?? list string(foo ?? greet) string(foo ?? i) string(foo ?? list) string(foo ?? ok) string(foo ?? true) string(foo in list) string(foo not in list) string(foo) string(foo) != $env?.Bar string(foo) != $env?.foobar string(foo) < str string(foo) == str string(foo) > str string(foo) >= str string(foo) ?? array string(foo) ?? i string(foo) ?? list string(foo) ?? ok string(foo) contains str string(foo) contains toJSON(foo) string(foo) in list?.[i] string(foo) matches str string(foo) not endsWith type(str) string(foo) not in foo string(foo) not matches greet(str) string(foo) startsWith str string(foo) | greet() string(foo)[:] string(foo.Bar) string(foo.String()) string(foo.String) string(foo?.Bar) string(foo?.Bar) not in foo string(foo?.String()) string(foo?.String) string(get(list, 1)) string(greet != $env) string(greet != greet) string(greet != nil) string(greet == greet) string(greet ?? 0) string(greet ?? 1.0) string(greet ?? add) string(greet ?? f64) string(greet ?? foo) string(greet ?? greet) string(greet(str)) string(greet) string(greet) + str string(greet) ?? {foo: 0} string(greet) not in foo string(greet) not matches str string(greet) startsWith $env?.[str] string(greet) | greet() string(groupBy(array, #)) string(groupBy(array, 0)) string(groupBy(list, 1.0)) string(groupBy(list, false)) string(groupBy(list, ok)?.greet) string(groupBy(list, str)) string(i != $env) string(i != 0) string(i != 1) string(i != 1.0) string(i != nil) string(i % 1) string(i * 0) string(i * 1.0) string(i ** 0) string(i ** 1.0) string(i ** f64) string(i ** i) string(i + 0) string(i + 1) string(i + 1.0) string(i + f64) string(i + i) string(i - 1) string(i - 1.0) string(i - f64) string(i - i) string(i .. 0) string(i .. 1) string(i / 0) string(i / f64) string(i / i) string(i < 0) string(i <= f64) string(i == $env) string(i == 1) string(i == 1.0) string(i == f64) string(i == nil) string(i > 0) string(i > 1) string(i > f64) string(i >= 1.0) string(i >= i) string(i ?? $env) string(i ?? f64) string(i ?? false) string(i ?? foo) string(i ?? i) string(i ?? list) string(i ?? ok) string(i ?? true) string(i ^ 1) string(i ^ 1.0) string(i ^ f64) string(i ^ i) string(i in array) string(i not in array) string(i | bitshr(i)) string(i | min(1.0, 1.0)) string(i) string(i) ?? i string(i) ?? toJSON(array) string(i) not endsWith str string(i) not in foo string(i) | greet() string(i) | indexOf(str) string(i)[:] string(if false ?? list { $env?.f64 } else { f64 }) string(if false { foo } else { false }) string(if false { ok } else { i }) string(if ok { 0 } else { str }) string(if ok { 1 } else { 1.0 }) string(if true { 1 } else { $env }) string(if true { 1.0 } else { foo }) string(if true { list } else { 0 }) string(if true { str } else { 1.0 }) string(int(0)) string(int(1)) string(int(1.0)) string(int(f64)) string(int(i)) string(keys($env)) string(last($env)) string(last(array)) string(last(list)) string(len($env)) string(len(array)) string(len(list)) string(len(str)) string(let foobar = 1.0; foobar + foobar) string(let x = foo; x) string(let z = 0; let x = foo; z) string(list != $env) string(list != array) string(list != list) string(list != nil) string(list == $env) string(list == array) string(list == list) string(list == nil) string(list ?? $env) string(list ?? 1.0) string(list ?? false) string(list ?? foo) string(list ?? greet) string(list ?? i) string(list ?? list) string(list ?? nil) string(list ?? true) string(list | concat(array)) string(list | count(true)) string(list | findIndex(ok)) string(list | groupBy(#)) string(list | groupBy(0)) string(list | groupBy(1)) string(list | groupBy(1.0)) string(list | groupBy(ok)) string(list | map(.Bar)) string(list | map(.String)) string(list | map(greet)) string(list | map(i)) string(list | one(false)) string(list | reduce(#)) string(list | reduce(#.String)) string(list | reduce(#index)) string(list | reduce(.String)) string(list | reduce(1)) string(list | reduce(false)) string(list | sortBy(1.0)) string(list) string(list) != str ?? true string(list) > str string(list) ?? add string(list) not contains str string(list) not contains str ?? add string(list) not startsWith str string(list) startsWith str string(list) | greet() string(list) | split(str) string(list?.[0]) string(list?.[i]) string(list?.[i]?.String) string(list[1:]) string(list[:0]) string(list[i:]) string(lower(str)) string(map($env, $env)) string(map($env, 1.0)) string(map($env, add)) string(map($env, f64)) string(map($env, false)) string(map($env, foo)) string(map($env, i)) string(map($env, true)) string(map(array, #index)) string(map(array, add)) string(map(array, f64)) string(map(array, greet)) string(map(array, str)) string(map(list, $env)) string(map(list, greet)) string(map(list, list)) string(map(list, true)) string(max($env)) string(max(0)) string(max(1)) string(max(1.0)) string(max(array)) string(max(f64)) string(max(f64, 0)) string(max(i)) string(mean(0)) string(mean(1)) string(mean(1.0)) string(mean(array)) string(mean(f64)) string(mean(i)) string(median(0)) string(median(1)) string(median(1.0)) string(median(1.0, 0)) string(median(array)) string(median(f64)) string(median(i)) string(median(i, 0)) string(median(round(i))) string(min($env)) string(min(0)) string(min(0, 1.0)) string(min(1)) string(min(1, f64)) string(min(1.0)) string(min(1.0, 0)) string(min(1.0, array)) string(min(array)) string(min(f64)) string(min(i)) string(min(i, 1.0)) string(nil != $env) string(nil != 0) string(nil != 1.0) string(nil != foo) string(nil != list) string(nil != nil) string(nil != ok) string(nil != str) string(nil == $env) string(nil == 0) string(nil == 1.0) string(nil == add) string(nil == array) string(nil == f64) string(nil == foo) string(nil == greet) string(nil == i) string(nil == list) string(nil == nil) string(nil == nil) <= str string(nil == ok) string(nil == true) string(nil ?? 0) string(nil ?? 1.0) string(nil ?? add) string(nil ?? array) string(nil ?? foo) string(nil ?? i) string(nil ?? nil) string(nil ?? true) string(nil in $env) string(nil in array) string(nil in list) string(nil not in $env) string(nil not in $env?.array) string(nil not in array) string(nil not in list) string(nil) != $env?.[String] string(nil) != str string(nil) == toJSON(nil) string(nil) > str string(nil) >= str string(nil) ?? f64 string(nil) ?? greet string(nil) ?? list string(nil) contains str string(nil) in foo string(nil) not matches greet(str) string(nil) not matches str string(nil) not startsWith str string(nil) | greet() string(nil) | trimSuffix(str) string(nil)[:i] string(nil)[i:] string(none($env, ok)) string(none(list, true)) string(not false) string(not ok) string(not true) string(ok != $env) string(ok != ok) string(ok && $env) string(ok && ok) string(ok && true) string(ok == $env) string(ok == false) string(ok == nil) string(ok == ok) string(ok ? $env : $env) string(ok ? $env : str) string(ok ? foo : nil) string(ok ? foo : ok) string(ok ? true : $env) string(ok ?: add) string(ok ?: f64) string(ok ?: foo) string(ok ?: list) string(ok ?? $env) string(ok ?? $env?.[i]) string(ok ?? foo) string(ok ?? i) string(ok and $env) string(ok and $env?.[Bar]) string(ok and ok) string(ok and true) string(ok or $env) string(ok or ok) string(ok or true) string(ok || $env) string(ok || false) string(ok) string(ok) >= str string(ok) contains str string(ok) in foo string(ok) matches str string(ok) matches trimPrefix(str) string(ok) | greet() string(ok) | indexOf(str) string(ok); ok string(ok)[1.0 ?? 1:] string(ok)[:] string(one($env, false)) string(reduce(array, #)) string(reduce(array, 1.0)) string(reduce(array, add)) string(reduce(array, foo)) string(reduce(array, greet)) string(reduce(array, i)) string(reduce(array, list)) string(reduce(list, #)) string(reduce(list, .Bar)) string(reduce(list, foo)) string(reduce(list, greet)) string(reduce(list, ok, 1.0)) string(reverse(array)) string(round(0)) string(round(1)) string(round(1.0)) string(round(f64)) string(round(i)) string(sort($env)) string(sort(array)) string(sort(ok ? foo : 1.0)) string(sortBy(array, #)) string(sortBy(list, .Bar)) string(sortBy(list, f64)) string(str != $env) string(str < str) string(str <= str) string(str == $env) string(str == $env?.[Bar]) string(str == nil) string(str == str) string(str > foo.Bar) string(str ?? add) string(str ?? ok) string(str ?? true) string(str contains str) string(str in $env) string(str in $env?.Bar) string(str in foo) string(str not contains $env?.[str]) string(str not in $env) string(str not in foo) string(str not matches str) string(str | greet()) string(str) string(str) != str string(str) + str string(str) contains str string(str) in foo string(str) matches str string(str) not contains str string(str) | greet() string(str)[:] string(str[:0]) string(str[:1]) string(str[:i]) string(string($env)) string(string(0)) string(string(1)) string(string(1.0)) string(string(add)) string(string(array)) string(string(f64)) string(string(false)) string(string(foo)) string(string(greet)) string(string(i)) string(string(list)) string(string(nil)) string(string(ok)) string(string(str)) string(string(true)) string(sum($env, 0)) string(sum($env, 1.0)) string(sum(array)) string(sum(array, #)) string(sum(list, 0)) string(toBase64(str)) string(toJSON(0)) string(toJSON(1)) string(toJSON(1.0)) string(toJSON(array)) string(toJSON(f64)) string(toJSON(false)) string(toJSON(foo)) string(toJSON(list)) string(toJSON(nil)) string(toJSON(ok)) string(toJSON(str)) string(toJSON(true)) string(toPairs($env)) string(trim(str)) string(trimPrefix(str)) string(trimSuffix(str)) string(true != $env) string(true != false) string(true != nil) string(true != ok) string(true != true) string(true && $env) string(true && false) string(true == $env) string(true == false) string(true == nil) string(true == true) string(true ? $env : f64) string(true ? add : nil) string(true ? false : greet) string(true ? false : i) string(true ? foo : $env) string(true ? str : add) string(true ?: $env) string(true ?: nil) string(true ?: ok) string(true ?? 0) string(true ?? array) string(true ?? foo) string(true ?? i) string(true ?? list) string(true and $env) string(true and false) string(true and ok) string(true or false) string(true or ok) string(true || $env) string(true || ok) string(true || true) string(true) + str string(true) ?? array | groupBy(foo) string(type($env)) string(type(0)) string(type(1)) string(type(1.0)) string(type(add)) string(type(array)) string(type(f64)) string(type(false)) string(type(foo)) string(type(greet)) string(type(list)) string(type(nil)) string(type(ok)) string(type(str)) string(type(true)) string(uniq(array)) string(uniq(list)) string(upper(str)) string(values($env)) string({foo: $env, foo: $env}?.f64) string({foo: $env, foo: nil}) string({foo: $env}) string({foo: 0}) string({foo: 1.0, foo: list}) string({foo: 1.0}) string({foo: 1}) string({foo: add ?? $env}) string({foo: add, foo: 1.0}) string({foo: add}) string({foo: array, foo: 1.0, foo: list}) string({foo: array}) string({foo: f64, foo: 1.0, foo: foo}) string({foo: f64, foo: 1.0}) string({foo: f64}) string({foo: false, foo: array}) string({foo: false}) string({foo: foo, foo: 1}) string({foo: foo, foo: array}) string({foo: foo, foo: list}) string({foo: foo, foo: str}) string({foo: foo}) string({foo: greet, foo: 1.0}) string({foo: greet, foo: foo}) string({foo: greet}) string({foo: i, foo: $env}) string({foo: i}) string({foo: list}) string({foo: nil, foo: $env}) string({foo: nil, foo: 1}) string({foo: nil, foo: foo}) string({foo: nil, foo: list}) string({foo: nil, foo: ok}) string({foo: nil}) string({foo: ok, foo: false, foo: list}) string({foo: ok, foo: ok, foo: array}) string({foo: ok, foo: str}) string({foo: ok}) string({foo: str}) string({foo: true}) string({foo: true}?.array) sum($env ?? greet, f64) sum($env | filter(false)) sum($env | filter(false), reduce(#, #)) sum($env | map(#index)) sum($env | map(0)) sum($env | map(1)) sum($env | map(1.0)) sum($env | map(f64)) sum($env | map(i)) sum($env | map(str), f64) sum($env | reduce(#acc, str)) sum($env | reduce(array, 0)) sum($env) or true ? foo : array sum($env, 0) in array sum($env, 0) | max(i) sum($env, 0) | median(1.0) sum($env, 1) != f64 sum($env, 1) >= 1.0 >= 1.0 sum($env, 1) >= i sum($env, 1.0) ** 1 ^ 1 sum($env, 1.0) / -0 sum($env, 1.0) >= f64 sum($env, 1.0) ?? add sum($env, 1.0) ?? str sum($env, f64) != sum(array) sum($env, f64) ** f64 + f64 sum($env, f64) ?? add sum($env, f64) | max(i) sum($env, i) <= abs(1.0) sum($env, i) ^ i sum($env, ok) or not false sum($env.array | sortBy(#)) sum($env.array | sortBy(i)) sum($env.array) sum($env.array, # ** #) sum($env.array, #) sum($env.array, f64) sum($env.array, i) sum($env.list, abs(1.0)) sum($env.list, f64) sum($env.list, i) sum($env?.[str]) sum($env?.[str]) != ok sum($env?.[str], #) sum($env?.[str], f64) sum($env?.[str], i) sum($env?.array) sum($env?.array) ?? add sum($env?.array, #) sum($env?.array, i) sum($env?.array, i) <= i sum($env?.list, f64 + 1.0) sum(0 .. 0) sum(0 .. 1) sum(0 .. i) sum(0..i) sum(1 .. 0) sum(1 .. 0, #) sum(1 .. 1) sum(1 .. i) sum(1..i) sum(1..i, # + #) sum(1..i, f64) sum([$env, add], f64) sum([-1]) sum([0, 0]) sum([0]) sum([1, 0]) sum([1, 1.0]) sum([1.0, 0]) sum([1.0, 1.0]) sum([1.0, 1.0], #) sum([1.0, 1]) sum([1.0, 1], f64) sum([1.0, f64]) sum([1.0]) sum([1.0], #) sum([1.0], i) sum([1]) sum([1], 1 / #) sum([f64, 0]) sum([f64, 1.0]) sum([f64]) sum([f64], i) sum([foo], f64) sum([i]) sum([nil], 1.0 + i) sum([ok], f64) sum([ok], i) sum([str, str]) sum([true], i) sum(array ?? 0, min(1)) sum(array ?? 1) sum(array ?? 1.0) sum(array ?? add) sum(array ?? add, #) sum(array ?? array) sum(array ?? f64) sum(array ?? false) sum(array ?? foo) sum(array ?? greet) sum(array ?? i) sum(array ?? list) sum(array ?? nil) sum(array ?? str) sum(array ?? true) sum(array | filter(false)) sum(array | filter(ok)) sum(array | filter(true)) sum(array | map(#)) sum(array | map(#index)) sum(array | map(0)) sum(array | map(1)) sum(array | map(1.0)) sum(array | map(f64)) sum(array | map(i)) sum(array | map(i), i) sum(array | sortBy(#)) sum(array | sortBy(0)) sum(array | sortBy(1)) sum(array | sortBy(1.0)) sum(array | sortBy(i)) sum(array | sortBy(str)) sum(array | take(0)) sum(array) sum(array) != f64 sum(array) != i sum(array) != i ** 1.0 sum(array) % i sum(array) * f64 sum(array) * i sum(array) ** f64 sum(array) ** i sum(array) + $env.f64 sum(array) + f64 sum(array) + i sum(array) - 0 > 1.0 sum(array) - ceil(0) sum(array) - f64 sum(array) - i sum(array) .. i sum(array) / f64 sum(array) < f64 sum(array) < i sum(array) <= f64 sum(array) <= i sum(array) <= i || $env sum(array) <= max(array) sum(array) == f64 sum(array) == i sum(array) > f64 sum(array) > reduce(array, i) sum(array) >= f64 != true sum(array) >= i sum(array) ?? all($env, #) sum(array) ?? f64 sum(array) ?? foo sum(array) ?? list sum(array) ?? ok sum(array) ?? str sum(array) ?? {foo: true} sum(array) ^ f64 sum(array) ^ i sum(array) ^ round(1) sum(array) not in $env.array sum(array) not in array sum(array) | bitnand(i) sum(array) | bitor(i) sum(array) | bitushr(0) sum(array) | bitxor(0) sum(array) | max(array) sum(array) | mean(1) sum(array) | mean(1.0) sum(array) | min(i) sum(array)..i sum(array); f64 sum(array, # % #) sum(array, # ** #) sum(array, # ** i) sum(array, # + #) sum(array, # - 0) sum(array, # / f64) sum(array, #) sum(array, #) * i sum(array, #) ** f64 sum(array, #) <= i sum(array, #) <= i ?? 1.0 sum(array, #) ?? foo sum(array, #) not in array sum(array, $env.f64) sum(array, $env.i) sum(array, $env?.f64) sum(array, $env?.i) sum(array, -#) sum(array, -0) sum(array, -1) sum(array, -1.0) sum(array, 0 ** f64) sum(array, 1 - #) sum(array, 1 ?? i) sum(array, 1) != i sum(array, 1) .. array?.[i] sum(array, 1) ?? i sum(array, 1) ^ i sum(array, 1.0 ** #) sum(array, 1.0 / #) sum(array, 1.0 ?? foo) sum(array, 1.0) * mean(i, 0) sum(array, 1.0) - f64 sum(array, 1.0) == f64 sum(array, abs(#)) sum(array, array | reduce(f64)) sum(array, array?.[i]) sum(array, bitnot(#)) sum(array, bitshr(#, #)) sum(array, bitushr(#, #)) sum(array, ceil(f64)) sum(array, f64) sum(array, f64) + int(i) sum(array, f64) == i sum(array, f64) > i sum(array, f64) ^ i sum(array, float(# | bitxor(#))) sum(array, float(#)) sum(array, float(1.0)) sum(array, floor(0)) sum(array, floor(f64)) sum(array, i + 1.0) sum(array, i) sum(array, int(i)) sum(array, max(#, #)) sum(array, mean(array)) sum(array, nil ?? #) sum(array, round(#)) sum(array, round(1.0)) sum(array, sum($env, 1)) sum(array, sum(array, #)) sum(array, true ? 0 : 0) sum(array[0:]) sum(array[1:]) sum(array[:0]) sum(array[:1]) sum(array[:i]) sum(array[i:]) sum(concat(array)) sum(concat(array), #) sum(concat(array, array)) sum(false ? $env : $env, f64) sum(false ? $env : array) sum(false ? i : str) sum(false ? nil : array) sum(false ? str : array) sum(false ?: array) sum(false ?: str) sum(filter($env, false)) sum(filter($env, false), .add?.str(false, false)) sum(filter(array, false)) sum(filter(array, ok), f64) sum(filter(array, ok), i) sum(filter(array, true)) sum(filter(list, false)) sum(flatten(array)) sum(flatten(array), max(#)) sum(flatten(sort(str ?? 1))) sum(get($env, str)) sum(i .. 0) sum(i .. 1) sum(i .. i) sum(i..i) sum(if false { 1 } else { array }) sum(if false { array } else { array }) sum(if false { foo } else { str }) sum(if ok { array } else { 1 }) sum(if ok { str } else { f64 }) sum(if true { array } else { 1.0 }) sum(if true { array } else { list }) sum(let foobar = array; foobar) sum(let y = array; y) sum(list | filter(false)) sum(list | map(#index)) sum(list | map(0)) sum(list | map(1)) sum(list | map(1.0)) sum(list | map(f64)) sum(list | map(greet), i) sum(list | map(i)) sum(list | reduce($env), i) sum(list | reduce(array)) sum(list | sortBy(str), f64) sum(list, $env.f64) sum(list, $env.i) sum(list, $env?.f64) sum(list, $env?.i) sum(list, -1.0) sum(list, 0 * 1.0) sum(list, 0 ?? #) sum(list, 0 ?? str) sum(list, 0) ** f64 sum(list, 0) ?? array sum(list, 1 ^ 0) sum(list, 1) | bitxor(0) sum(list, 1.0 ** i) sum(list, 1.0 / 1.0) sum(list, 1.0 ?? str) sum(list, f64 * 0) sum(list, f64 ** 0) sum(list, f64 - 1.0) sum(list, f64 - f64) sum(list, f64) sum(list, f64) ?? 1.0 ?? list sum(list, f64) | mean(f64) sum(list, i + 0) sum(list, i / 0) sum(list, i ?? true) sum(list, i) sum(list, i) ** i sum(list, int(i)) sum(list, len($env)) sum(list, len(str)) sum(list, list | sum(1.0)) sum(list, max(0)) sum(list, mean(i)) sum(list, round(1.0)) sum(list[i:0]) sum(list[i:i]) sum(map($env, #index)) sum(map($env, $env), i) sum(map($env, 0) | sortBy(1.0)) sum(map($env, 0)) sum(map($env, 1)) sum(map($env, 1.0)) sum(map($env, f64)) sum(map($env, i)) sum(map(array, #)) sum(map(array, #index)) sum(map(array, 0)) sum(map(array, 1)) sum(map(array, 1.0)) sum(map(array, f64)) sum(map(list, #index)) sum(map(list, 0)) sum(map(list, 1)) sum(map(list, 1.0)) sum(map(list, f64)) sum(map(list, i)) sum(max($env).array) sum(max($env?.[str])) sum(min($env), f64) sum(nil ?? array) sum(ok ? array : false) sum(ok ? array : foo) sum(reduce($env, array, $env)) sum(reduce($env, array, nil)) sum(reduce(array, array)) sum(reduce(array, array, false)) sum(reduce(list, array)) sum(reverse(array)) sum(sort($env)) sum(sort($env), #.Bar) sum(sort($env), #.add % 1) sum(sort($env), #.add not in #.add) sum(sort($env), $env == #) sum(sort($env), .array?.foobar) sum(sort($env), .list) sum(sort($env), 1.0 ?? #.greet) sum(sort($env), any(#, #.String)) sum(sort($env?.String)) sum(sort(array)) sum(sort(ok ? i : 1.0)) sum(sortBy(array, #)) sum(sortBy(array, 0)) sum(sortBy(array, 1)) sum(sortBy(array, 1.0)) sum(sortBy(array, f64)) sum(sortBy(array, i)) sum(sortBy(array, str)) sum(str ?? $env) sum(str ?? 0) sum(str ?? 1) sum(str ?? 1, #) sum(str ?? 1.0) sum(str ?? add) sum(str ?? array) sum(str ?? f64) sum(str ?? false) sum(str ?? false, #) sum(str ?? false, f64) sum(str ?? foo) sum(str ?? greet) sum(str ?? i) sum(str ?? list) sum(str ?? ok) sum(str ?? true) sum(string($env) ?? array) sum(take(array, i)) sum(toPairs($env), i) sum(true ? str : 1.0) sum(true ? str : add) sum(true ? str : foo) sum(uniq(array)) sum(uniq(array), 1.0 - 0) take(array, $env?.i) take(array, i) take(list, i) toBase64($env.foo?.Bar) toBase64($env.str) toBase64($env?.[str]) toBase64($env?.str) toBase64(foo.Bar) toBase64(foo.String()) toBase64(foo?.Bar ?? foo) toBase64(foo?.Bar) toBase64(foo?.Bar)[:] toBase64(foo?.String()) toBase64(greet(str)) toBase64(lower(str)) toBase64(reduce(list, str)) toBase64(str + str) toBase64(str ?? $env) toBase64(str ?? 1) toBase64(str ?? array) toBase64(str ?? i) toBase64(str ?? nil) toBase64(str ?? ok) toBase64(str | greet()) toBase64(str) toBase64(str) < str toBase64(str) > str toBase64(str) >= str toBase64(str) ?? array toBase64(str) endsWith first($env) toBase64(str) in foo ?? 0 toBase64(str) not contains $env?.str toBase64(str) not matches $env?.Bar toBase64(str) not startsWith str toBase64(str) | greet() toBase64(str) | repeat(i) toBase64(str)[i:] toBase64(str[:0]) toBase64(str[:1]) toBase64(str[:i]) toBase64(str[i:]) toBase64(string($env)) toBase64(string(0)) toBase64(string(1)) toBase64(string(1.0)) toBase64(string(add)) toBase64(string(array)) toBase64(string(f64)) toBase64(string(false)) toBase64(string(foo)) toBase64(string(foo?.Bar)) toBase64(string(greet)) toBase64(string(i)) toBase64(string(list)) toBase64(string(nil)) toBase64(string(ok)) toBase64(string(str)) toBase64(toBase64(str)) toBase64(toJSON(0)) toBase64(toJSON(1.0)) toBase64(toJSON(array)) toBase64(toJSON(f64)) toBase64(toJSON(false)) toBase64(toJSON(foo)) toBase64(toJSON(i / 1)) toBase64(toJSON(i)) toBase64(toJSON(list)) toBase64(toJSON(nil)) toBase64(toJSON(ok)) toBase64(toJSON(true)) toBase64(trim(str)) toBase64(trimPrefix(str)) toBase64(trimSuffix(str)) toBase64(type($env)) toBase64(type(0)) toBase64(type(1)) toBase64(type(1.0 < 1.0)) toBase64(type(1.0)) toBase64(type(add)) toBase64(type(array)) toBase64(type(f64)) toBase64(type(false)) toBase64(type(foo)) toBase64(type(greet)) toBase64(type(i)) toBase64(type(list)) toBase64(type(nil)) toBase64(type(ok)) toBase64(type(str)) toBase64(type(true)) toBase64(upper(str)) toJSON(!false) toJSON(!ok) toJSON(!true) toJSON($env != 0) toJSON($env != 1) toJSON($env != 1.0) toJSON($env != add) toJSON($env != array) toJSON($env != f64) toJSON($env != false) toJSON($env != foo) toJSON($env != greet) toJSON($env != i) toJSON($env != list) toJSON($env != nil) toJSON($env != str) toJSON($env != true) toJSON($env && false) toJSON($env == $env) toJSON($env == 0) toJSON($env == 1) toJSON($env == array) toJSON($env == f64) toJSON($env == false) toJSON($env == foo) toJSON($env == i) toJSON($env == list) toJSON($env == nil) toJSON($env == str) toJSON($env == true) toJSON($env in list) toJSON($env not in array) toJSON($env not in list) toJSON($env or true) toJSON($env | all(false)) toJSON($env | any(false)) toJSON($env | any(true)) toJSON($env | count(false)) toJSON($env | findIndex(ok)) toJSON($env | findLastIndex(ok)) toJSON($env | get(nil)) toJSON($env | map(array)) toJSON($env | map(f64)) toJSON($env | map(list)) toJSON($env | map(str)) toJSON($env | map(true)) toJSON($env | none(false)) toJSON($env | reduce(#index, $env)) toJSON($env | reduce(#index, nil)) toJSON($env | reduce(false, 1)) toJSON($env | sum(0)) toJSON($env | sum(1)) toJSON($env | sum(1.0)) toJSON($env || true) toJSON($env.array) toJSON($env.f64) toJSON($env.foo) toJSON($env.i) toJSON($env.list) toJSON($env.ok) toJSON($env.str) toJSON($env?.$env) toJSON($env?.Bar) toJSON($env?.Bar?.Bar()) toJSON($env?.Bar?.[greet]) toJSON($env?.Bar?.[list]) toJSON($env?.Bar?.f64) toJSON($env?.String) toJSON($env?.[Bar]) toJSON($env?.[String]) toJSON($env?.[foobar]) toJSON($env?.[foobar]?.i()) toJSON($env?.[foobar]?.list) toJSON($env?.[nil]) toJSON($env?.[str]) toJSON($env?.array) toJSON($env?.f64) toJSON($env?.false) toJSON($env?.foo) toJSON($env?.foobar) toJSON($env?.i) toJSON($env?.list) toJSON($env?.nil) toJSON($env?.ok) toJSON($env?.str) toJSON($env?.true) toJSON(-$env?.i) toJSON(-0 < 1.0) toJSON(-0) toJSON(-1) toJSON(-1.0) toJSON(-f64) toJSON(-i) toJSON(0 != $env) toJSON(0 != 1) toJSON(0 != 1.0) toJSON(0 != i) toJSON(0 != nil) toJSON(0 % 1) toJSON(0 % i) toJSON(0 * 1.0) toJSON(0 ** 1) toJSON(0 ** 1.0) toJSON(0 ** f64) toJSON(0 + 0) toJSON(0 + 1) toJSON(0 + 1.0) toJSON(0 + f64) toJSON(0 - 1) toJSON(0 - 1.0) toJSON(0 - f64) toJSON(0 - i) toJSON(0 .. 1) toJSON(0 .. i) toJSON(0 / 1.0) toJSON(0 / f64) toJSON(0 / i) toJSON(0 < 0) toJSON(0 < 1.0) toJSON(0 <= 0) toJSON(0 <= 1) toJSON(0 <= 1.0) toJSON(0 <= f64) toJSON(0 <= i) toJSON(0 == $env?.[foobar]) toJSON(0 == 1) toJSON(0 == 1.0) toJSON(0 == f64) toJSON(0 == nil) toJSON(0 > 1) toJSON(0 > 1.0) toJSON(0 > i) toJSON(0 >= 0) toJSON(0 >= 1) toJSON(0 >= 1.0) toJSON(0 ?? 1.0) toJSON(0 ?? f64) toJSON(0 ?? greet) toJSON(0 ?? list) toJSON(0 ?? nil) toJSON(0 ^ 1.0) toJSON(0 ^ f64) toJSON(0 ^ i) toJSON(0 in array) toJSON(0 not in array) toJSON(0 | bitor(i)) toJSON(0 | bitshl(0)) toJSON(0 | bitshr(0)) toJSON(0 | min(1.0)) toJSON(0) != greet(str) toJSON(0) + str toJSON(0) > str toJSON(0) >= str toJSON(0) ?? array toJSON(0) ?? not true toJSON(0) contains $env?.[String] toJSON(0) in foo toJSON(0) | greet() toJSON(0..i) toJSON(0.0) toJSON(0.1) toJSON(1 != $env) toJSON(1 != 0) toJSON(1 != 1.0) toJSON(1 != i) toJSON(1 != nil) toJSON(1 % i) toJSON(1 * 1.0) toJSON(1 * i) toJSON(1 ** 0) toJSON(1 ** 1) toJSON(1 ** i) toJSON(1 + 0) toJSON(1 + 1) toJSON(1 + 1.0) toJSON(1 + f64) toJSON(1 - 1.0) toJSON(1 - f64) toJSON(1 - i) toJSON(1 .. 0) toJSON(1 .. 1) toJSON(1 .. i) toJSON(1 / 1) toJSON(1 / f64) toJSON(1 / i) toJSON(1 < 0) toJSON(1 < 1.0) toJSON(1 <= 0) toJSON(1 <= 1) toJSON(1 <= f64) toJSON(1 <= i) toJSON(1 == $env) toJSON(1 == 0) toJSON(1 == 1.0) toJSON(1 == nil) toJSON(1 > 0) toJSON(1 > 1) toJSON(1 > 1.0) toJSON(1 > i) toJSON(1 >= 0) toJSON(1 >= 1) toJSON(1 >= 1.0) toJSON(1 >= f64) toJSON(1 >= i) toJSON(1 ?? $env?.[foo]) toJSON(1 ?? 1) toJSON(1 ?? false) toJSON(1 ?? foo) toJSON(1 ?? nil) toJSON(1 ^ 1.0) toJSON(1 not in array) toJSON(1 | min(f64)) toJSON(1) != str toJSON(1) > str toJSON(1) ?? $env.ok toJSON(1) ?? array toJSON(1) endsWith str toJSON(1) not contains str toJSON(1) not endsWith str toJSON(1) not in $env?.true toJSON(1) | greet() toJSON(1.0 != $env) toJSON(1.0 != 0) toJSON(1.0 != 1) toJSON(1.0 != 1.0) toJSON(1.0 != i) toJSON(1.0 != nil) toJSON(1.0 * 0) toJSON(1.0 * 1) toJSON(1.0 * 1.0) toJSON(1.0 * f64) toJSON(1.0 * i) toJSON(1.0 ** 0) toJSON(1.0 ** 1) toJSON(1.0 ** 1.0) toJSON(1.0 ** f64) toJSON(1.0 ** i) toJSON(1.0 + 0) toJSON(1.0 + 1) toJSON(1.0 + 1.0) toJSON(1.0 + f64) toJSON(1.0 + i) toJSON(1.0 - 0) toJSON(1.0 - 1) toJSON(1.0 - 1.0) toJSON(1.0 - f64) toJSON(1.0 - i) toJSON(1.0 / 1) toJSON(1.0 / 1.0) toJSON(1.0 / i) toJSON(1.0 < 0) toJSON(1.0 < 1.0) toJSON(1.0 < f64) toJSON(1.0 < i) toJSON(1.0 <= 0) toJSON(1.0 <= 1.0) toJSON(1.0 <= f64) toJSON(1.0 <= i) toJSON(1.0 == $env) toJSON(1.0 == 1) toJSON(1.0 == 1.0) toJSON(1.0 == f64) toJSON(1.0 == i) toJSON(1.0 > 0) toJSON(1.0 > 1.0) toJSON(1.0 > f64) toJSON(1.0 > i) toJSON(1.0 >= 0) toJSON(1.0 >= 1) toJSON(1.0 >= 1.0) toJSON(1.0 >= f64) toJSON(1.0 >= i) toJSON(1.0 ?? $env) toJSON(1.0 ?? 1) toJSON(1.0 ?? add) toJSON(1.0 ?? array) toJSON(1.0 ?? f64) toJSON(1.0 ?? foo) toJSON(1.0 ?? greet) toJSON(1.0 ?? i) toJSON(1.0 ?? nil) toJSON(1.0 ^ 0) toJSON(1.0 ^ 1) toJSON(1.0 ^ 1.0) toJSON(1.0 ^ f64) toJSON(1.0 ^ f64) + str toJSON(1.0 ^ i) toJSON(1.0 in $env?.[String]) toJSON(1.0 in array) toJSON(1.0 not in array) toJSON(1.0 | median(array)) toJSON(1.0) toJSON(1.0) + str toJSON(1.0) <= str toJSON(1.0) ?? add toJSON(1.0) ?? foo toJSON(1.0) contains str toJSON(1.0) matches str toJSON(1.0) not endsWith str toJSON(1.0) not in foo toJSON(1.0) startsWith str toJSON(1.0) | greet() toJSON(1.0) | indexOf(str) toJSON([0]) toJSON([1, 1]) toJSON([1, foo]) toJSON([1, i]) toJSON([1, str]) toJSON([1.0]) toJSON([1]) toJSON([array, 0]) toJSON([array]) toJSON([f64, nil]) toJSON([f64]) toJSON([false]) toJSON([foo, list]) toJSON([foo]) toJSON([i]) toJSON([nil]) toJSON([not true]) toJSON([ok]) toJSON([str, 1.0]) toJSON([str]) toJSON([true]) toJSON(abs(0)) toJSON(abs(1)) toJSON(abs(1.0)) toJSON(abs(f64 / 1.0)) toJSON(abs(f64)) toJSON(abs(i)) toJSON(add != $env) toJSON(add != add) toJSON(add == $env) toJSON(add == add) toJSON(add == nil) toJSON(add(i, 0)) toJSON(all(list, false)) toJSON(all(list, true)) toJSON(any(array, false)) toJSON(any(array, true)) toJSON(any(list, ok)) toJSON(array != $env) toJSON(array != array) toJSON(array != list) toJSON(array != nil) toJSON(array == array) toJSON(array == list) toJSON(array == nil) toJSON(array ?? 0) toJSON(array ?? 1) toJSON(array ?? 1.0) toJSON(array ?? array) toJSON(array ?? f64) toJSON(array ?? list) toJSON(array ?? str) toJSON(array | count(false)) toJSON(array | count(ok)) toJSON(array | count(true)) toJSON(array | filter(ok)) toJSON(array | find(true)) toJSON(array | findLast(true)) toJSON(array | map(#)) toJSON(array | map(array)) toJSON(array | max(i)) toJSON(array | min(i)) toJSON(array | none(false)) toJSON(array | one(ok)) toJSON(array | reduce(1)) toJSON(array | reduce(ok)) toJSON(array | sortBy(#)) toJSON(array | sortBy(0)) toJSON(array | sum(#)) toJSON(array | sum(1.0)) toJSON(array | sum(i)) toJSON(array) toJSON(array) != $env?.[Bar] toJSON(array) != str toJSON(array) + str toJSON(array) < str toJSON(array) == greet(str) toJSON(array) endsWith str toJSON(array) matches str toJSON(array) not contains str toJSON(array) | greet() toJSON(array?.[0]) toJSON(array?.[1]) toJSON(array?.[i]) toJSON(array[1:]) toJSON(bitand(0, 0)) toJSON(bitnand(1, 1)) toJSON(bitnot(0)) toJSON(bitnot(1)) toJSON(bitnot(i)) toJSON(ceil(0)) toJSON(ceil(1)) toJSON(ceil(1.0)) toJSON(ceil(f64)) toJSON(ceil(i)) toJSON(concat(array)) toJSON(concat(list)) toJSON(count(array, false)) toJSON(count(array, ok)) toJSON(count(array, true)) toJSON(count(list, false)) toJSON(count(list, true)) toJSON(f64 != 0) toJSON(f64 != 1) toJSON(f64 != 1.0) toJSON(f64 != f64) toJSON(f64 != nil) toJSON(f64 * 0) toJSON(f64 * 1.0) toJSON(f64 * f64) toJSON(f64 ** 1) toJSON(f64 ** f64) toJSON(f64 + 1.0) toJSON(f64 - 1.0) toJSON(f64 / 1) toJSON(f64 / 1.0) toJSON(f64 / i) toJSON(f64 < 0) toJSON(f64 < 1) toJSON(f64 < 1.0) toJSON(f64 <= 0) toJSON(f64 <= 1) toJSON(f64 <= 1.0) toJSON(f64 <= i) toJSON(f64 == $env) toJSON(f64 == 0) toJSON(f64 == 1.0) toJSON(f64 == nil) toJSON(f64 > 0) toJSON(f64 > 1.0) toJSON(f64 >= 1.0) toJSON(f64 >= i) toJSON(f64 ?? $env) toJSON(f64 ?? 1.0) toJSON(f64 ?? add) toJSON(f64 ?? array) toJSON(f64 ?? i) toJSON(f64 ?? nil) toJSON(f64 ?? ok) toJSON(f64 ^ 0) toJSON(f64 ^ 1.0) toJSON(f64 ^ f64) toJSON(f64 ^ i) toJSON(f64 in array) toJSON(f64 not in array) toJSON(f64 | mean(1.0)) toJSON(f64 | median(i)) toJSON(f64) toJSON(f64) > str toJSON(f64) ?? add toJSON(f64) in reduce(array, $env, array) toJSON(f64) not contains str ?? 0 toJSON(f64) not in foo toJSON(false != $env) toJSON(false != false) toJSON(false != nil) toJSON(false != ok) toJSON(false && $env) toJSON(false && $env?.[greet]) toJSON(false && ok) toJSON(false == $env) toJSON(false == nil) toJSON(false == ok) toJSON(false == true) toJSON(false ? ok : true) toJSON(false ?: f64) toJSON(false ?? 1.0) toJSON(false ?? add) toJSON(false ?? f64) toJSON(false ?? foo) toJSON(false ?? greet) toJSON(false ?? i) toJSON(false ?? nil) toJSON(false ?? ok) toJSON(false and $env) toJSON(false not in $env?.[String]) toJSON(false or false) toJSON(false || false) toJSON(false || ok) toJSON(false) <= $env.str toJSON(false) <= str toJSON(false) ?? f64 toJSON(false) ?? len(array) toJSON(false) not endsWith str toJSON(false) startsWith first($env) toJSON(false) | lastIndexOf(str) toJSON(find(array, true)) toJSON(find(list, false)) toJSON(find(list, ok)) toJSON(findIndex($env, false)) toJSON(findIndex($env, true)) toJSON(findIndex(list, false)) toJSON(findLastIndex($env, false)) toJSON(findLastIndex($env, ok)) toJSON(first($env)) toJSON(first(array)) toJSON(first(list)) toJSON(flatten(array)) toJSON(flatten(list)) toJSON(float(0)) toJSON(float(1)) toJSON(float(1.0)) toJSON(float(f64)) toJSON(float(i)) toJSON(floor(0)) toJSON(floor(1)) toJSON(floor(1.0)) toJSON(floor(f64)) toJSON(floor(i)) toJSON(foo != $env) toJSON(foo != foo) toJSON(foo != nil) toJSON(foo == $env) toJSON(foo == foo) toJSON(foo == nil) toJSON(foo ?? $env) toJSON(foo ?? $env?.[f64 >= foobar]) toJSON(foo ?? 0) toJSON(foo ?? 1) toJSON(foo ?? add) toJSON(foo ?? f64) toJSON(foo ?? foo) toJSON(foo ?? list) toJSON(foo ?? ok) toJSON(foo ?? str) toJSON(foo ?? true) toJSON(foo in list) toJSON(foo not in list) toJSON(foo) toJSON(foo) + str toJSON(foo) < str toJSON(foo) > str toJSON(foo) > toJSON(1.0) toJSON(foo) >= string(nil) toJSON(foo) ?? $env?.greet toJSON(foo) ?? i toJSON(foo) ?? ok toJSON(foo) not in $env?.String toJSON(foo) not matches $env?.[foobar] toJSON(foo) not matches str toJSON(foo) | greet() toJSON(foo) | repeat(i) toJSON(foo.Bar) toJSON(foo.String()) toJSON(foo?.Bar) toJSON(foo?.String()) toJSON(greet != $env) toJSON(greet != greet) toJSON(greet != nil) toJSON(greet == $env) toJSON(greet == nil) toJSON(greet(str)) toJSON(groupBy(array, 1.0)?.Bar) toJSON(i != 1.0) toJSON(i != f64) toJSON(i != i) toJSON(i != nil) toJSON(i % 1) toJSON(i * 0) toJSON(i * 1) toJSON(i * 1.0) toJSON(i * f64) toJSON(i * i) toJSON(i ** 1.0) | greet() toJSON(i ** f64) toJSON(i + 1 .. 0) toJSON(i + 1.0) toJSON(i - 1) toJSON(i - i) toJSON(i .. 1) toJSON(i / 1.0) toJSON(i / f64) toJSON(i / i) toJSON(i < 1) toJSON(i < 1.0) toJSON(i <= 1) toJSON(i == 0) toJSON(i == 1) toJSON(i == 1.0) toJSON(i == nil) toJSON(i == nil) <= str toJSON(i > 1) toJSON(i > f64) toJSON(i > i) toJSON(i >= 0) toJSON(i >= 1.0) toJSON(i >= f64) toJSON(i >= i) toJSON(i ?? $env) toJSON(i ?? 0) toJSON(i ?? 1.0) toJSON(i ?? add) toJSON(i ?? array) toJSON(i ?? foo) toJSON(i ?? greet) toJSON(i ?? list?.[i]) toJSON(i ?? nil) toJSON(i ?? str) toJSON(i ?? true) toJSON(i ^ 0) toJSON(i ^ 1.0) toJSON(i ^ f64) toJSON(i in array) toJSON(i not in array) toJSON(i | bitand(0)) toJSON(i) toJSON(i) + str toJSON(i) < foo.String() toJSON(i) <= str toJSON(i) ?? array toJSON(i) ?? i toJSON(i) not contains string(0) toJSON(i) not in foo ? 1.0 : foo toJSON(i) | greet() toJSON(if false { $env } else { nil }) toJSON(if false { add } else { ok }) toJSON(if false { nil } else { list }) toJSON(if false { str } else { str }) toJSON(if ok { foo } else { 1.0 }) toJSON(if true { foo } else { 1 }) toJSON(if true { ok } else { f64 }) toJSON(if true { true } else { i }) toJSON(int(0)) toJSON(int(1)) toJSON(int(1.0)) toJSON(int(f64)) toJSON(keys($env)) toJSON(last($env)) toJSON(last($env?.[foobar])) toJSON(last(array)) toJSON(last(list)) toJSON(len($env)) toJSON(len(list)) toJSON(len(str)) toJSON(let foobar = array; foobar) toJSON(let foobar = false; foobar) toJSON(list != list) toJSON(list != nil) toJSON(list == $env) toJSON(list == $env.list) toJSON(list == array) toJSON(list == list) toJSON(list == nil) toJSON(list ?? 0) toJSON(list ?? 1.0) toJSON(list ?? add) toJSON(list ?? array) toJSON(list ?? false) toJSON(list ?? foo) toJSON(list ?? nil) toJSON(list ?? ok) toJSON(list ?? true) toJSON(list | all(false)) toJSON(list | find(false)) toJSON(list | find(ok)) toJSON(list | findIndex(true)) toJSON(list | findLast(ok)) toJSON(list | map(#)) toJSON(list | map(#.Bar)) toJSON(list | map(0)) toJSON(list | map(1)) toJSON(list | map(foo)) toJSON(list | map(true)) toJSON(list | none(true)) toJSON(list | reduce(#)) toJSON(list | reduce(0)) toJSON(list | reduce(foo)) toJSON(list | sortBy(f64)) toJSON(list | sortBy(i)) toJSON(list | sum(1.0)) toJSON(list | sum(i)) toJSON(list) toJSON(list) + str toJSON(list) <= str toJSON(list) == str toJSON(list) > str toJSON(list) > string($env) toJSON(list) not in foo toJSON(list) startsWith str toJSON(list) | greet() toJSON(list?.[0]) toJSON(list?.[i]) toJSON(list[0:]) toJSON(list[:1]) toJSON(lower(str)) toJSON(map($env, 0)) toJSON(map($env, array)) toJSON(map($env, false)) toJSON(map($env, foo)) toJSON(map($env, i)) toJSON(map($env, list)) toJSON(map(array, #)) toJSON(map(array, 0)) toJSON(map(array, list)) toJSON(map(array, ok)) toJSON(map(array, str)) toJSON(map(list, #)) toJSON(map(list, #index)) toJSON(map(list, .Bar)) toJSON(map(list, array)) toJSON(map(list, f64)) toJSON(map(list, list)) toJSON(max(0)) toJSON(max(1)) toJSON(max(1.0)) toJSON(max(1.0, 0)) toJSON(max(1.0, 1)) toJSON(max(1.0, array)) toJSON(max(array)) toJSON(max(f64)) toJSON(max(i)) toJSON(mean(0)) toJSON(mean(1)) toJSON(mean(1.0)) toJSON(mean(array)) toJSON(mean(f64)) toJSON(mean(i)) toJSON(median(0)) toJSON(median(1)) toJSON(median(1, 0)) toJSON(median(1.0)) toJSON(median(array)) toJSON(median(array, array)) toJSON(median(f64)) toJSON(median(f64, i)) toJSON(median(i)) toJSON(min($env)?.list) toJSON(min(0)) toJSON(min(1)) toJSON(min(1, f64)) toJSON(min(1.0)) toJSON(min(array)) toJSON(min(f64)) toJSON(min(i)) toJSON(nil != $env) toJSON(nil != 0) toJSON(nil != 1) toJSON(nil != 1.0) toJSON(nil != add) toJSON(nil != array) toJSON(nil != f64) toJSON(nil != false) toJSON(nil != foo) toJSON(nil != greet) toJSON(nil != i) toJSON(nil != list) toJSON(nil != nil) toJSON(nil != ok) toJSON(nil != str) toJSON(nil != true or ok) toJSON(nil != true) toJSON(nil == $env) toJSON(nil == 0) toJSON(nil == 1) toJSON(nil == 1.0) toJSON(nil == array) toJSON(nil == foo) toJSON(nil == greet) toJSON(nil == i) toJSON(nil == list) toJSON(nil == nil) toJSON(nil == ok) toJSON(nil ?? 0) toJSON(nil ?? 1) toJSON(nil ?? array) toJSON(nil ?? f64) toJSON(nil ?? foo) toJSON(nil ?? i) toJSON(nil ?? list) toJSON(nil ?? nil) toJSON(nil ?? true) toJSON(nil in $env) toJSON(nil in array) toJSON(nil in list) toJSON(nil not in $env) toJSON(nil not in list) toJSON(nil) < str toJSON(nil) <= str toJSON(nil) > toJSON(true) toJSON(nil) >= str toJSON(nil) ?? str toJSON(nil) in $env?.String toJSON(nil) in foo toJSON(nil) matches str toJSON(nil) not contains $env?.[str] toJSON(nil) not in foo toJSON(nil) not matches foo?.Bar toJSON(nil) not startsWith str toJSON(nil) | greet() toJSON(nil)[:i] toJSON(none($env, false)) toJSON(none($env, true)) toJSON(none(list, false)) toJSON(none(list, ok)) toJSON(not false) toJSON(not ok) toJSON(not true) toJSON(ok != false) toJSON(ok != nil) toJSON(ok != ok) toJSON(ok && false) toJSON(ok && ok) toJSON(ok && true) toJSON(ok == $env) toJSON(ok == false) toJSON(ok == nil) toJSON(ok == nil) < foo?.String() toJSON(ok == true) toJSON(ok ? 1.0 : 0) toJSON(ok ? foo : ok) toJSON(ok ?: foo) toJSON(ok ?? $env) toJSON(ok ?? 1) toJSON(ok ?? 1.0) toJSON(ok ?? array) toJSON(ok ?? f64) toJSON(ok ?? false) toJSON(ok ?? foo) toJSON(ok ?? ok) toJSON(ok and true) toJSON(ok or false) toJSON(ok or true) toJSON(ok || false) toJSON(ok) toJSON(ok) != string(true) toJSON(ok) == trimSuffix(str) toJSON(ok) ?? i toJSON(ok) matches foo.Bar toJSON(ok) not startsWith str toJSON(ok) | greet() toJSON(one($env, true)) toJSON(one(list, ok)) toJSON(reduce($env, 1.0, 0)) toJSON(reduce(array, #index)) toJSON(reduce(array, 0)) toJSON(reduce(array, 1)) toJSON(reduce(array, f64)) toJSON(reduce(array, foo)) toJSON(reduce(array, str)) toJSON(reduce(list, #)) toJSON(reduce(list, #.Bar)) toJSON(reduce(list, 0)) toJSON(reduce(list, 1.0)) toJSON(reduce(list, f64)) toJSON(reduce(list, foo)) toJSON(reduce(list, ok)) toJSON(reverse(array)) toJSON(reverse(list)) toJSON(round(0)) toJSON(round(1)) toJSON(round(1.0)) toJSON(round(f64)) toJSON(round(i)) toJSON(sort($env)) toJSON(sort(array)) toJSON(sortBy(array, #)) toJSON(sortBy(array, 0)) toJSON(sortBy(array, 1)) toJSON(sortBy(array, f64)) toJSON(sortBy(list, 0)) toJSON(sortBy(list, i)) toJSON(str != nil) toJSON(str <= str) toJSON(str == nil) toJSON(str > str) toJSON(str >= str) toJSON(str ?? $env) toJSON(str ?? 0) toJSON(str ?? array) toJSON(str ?? false) toJSON(str ?? foo) toJSON(str ?? list) toJSON(str ?? ok) toJSON(str contains str) toJSON(str endsWith str) toJSON(str in $env) toJSON(str in foo) toJSON(str in list?.[i]) toJSON(str matches str) toJSON(str not contains str) toJSON(str not endsWith str) toJSON(str not in $env) toJSON(str not in [add, array, foo]) toJSON(str not in foo) toJSON(str startsWith str) toJSON(str) toJSON(str) ?? array toJSON(str) endsWith str toJSON(str) matches str toJSON(str) matches str || ok toJSON(str) | greet() toJSON(str[0:]) toJSON(str[:0]) toJSON(str[:]) toJSON(string($env | one(true))) toJSON(string($env)) toJSON(string($env?.[str])) toJSON(string(0)) toJSON(string(1)) toJSON(string(1.0 - 1)) toJSON(string(1.0)) toJSON(string(add)) toJSON(string(array)) toJSON(string(f64)) toJSON(string(false)) toJSON(string(foo)) toJSON(string(greet)) toJSON(string(i)) toJSON(string(list)) toJSON(string(nil)) toJSON(string(ok)) toJSON(string(str)) toJSON(string(true)) toJSON(string(values($env))) toJSON(sum($env, 1.0)) toJSON(sum(array)) toJSON(sum(array, #)) toJSON(sum(array, i)) toJSON(sum(i .. i)) toJSON(sum(list, i)) toJSON(toBase64(str)) toJSON(toJSON(1)) toJSON(toJSON(1.0)) toJSON(toJSON(array)) toJSON(toJSON(f64)) toJSON(toJSON(false)) toJSON(toJSON(foo)) toJSON(toJSON(i)) toJSON(toJSON(list)) toJSON(toJSON(nil)) toJSON(toJSON(ok)) toJSON(toJSON(str)) toJSON(toJSON(true)) toJSON(trim(greet(str))) toJSON(trim(str)) toJSON(trimPrefix($env?.[str])) toJSON(trimPrefix(str)) toJSON(trimSuffix($env?.str)) toJSON(trimSuffix(str)) toJSON(true != $env) toJSON(true != false) toJSON(true != nil) toJSON(true != ok) toJSON(true != true) toJSON(true && false) toJSON(true && ok) toJSON(true && true) toJSON(true == $env) toJSON(true == true) toJSON(true ? foo : 1.0) toJSON(true ? foo : f64) toJSON(true ? nil : false) toJSON(true ?: greet) toJSON(true ?: nil) toJSON(true ?? $env) toJSON(true ?? foo) toJSON(true ?? nil) toJSON(true ?? str) toJSON(true and ok) toJSON(true and true) toJSON(true or $env) toJSON(true or false) toJSON(true or ok) toJSON(true or true) toJSON(true || $env) toJSON(true || ok) toJSON(true || true) toJSON(true) + str | trimPrefix(str) toJSON(true) < str toJSON(true) > str toJSON(true) ?? $env.greet toJSON(true) ?? 1 | groupBy(true) toJSON(true) ?? f64 toJSON(true) ?? foo | filter(true) toJSON(true) in foo toJSON(true) not endsWith greet(str) toJSON(true) not startsWith str toJSON(true) | greet() toJSON(true) | repeat(i) toJSON(true); f64 toJSON(type($env)) toJSON(type(0)) toJSON(type(1.0)) toJSON(type(add)) toJSON(type(array)) toJSON(type(f64 + 1.0)) toJSON(type(f64)) toJSON(type(false)) toJSON(type(foo)) toJSON(type(greet)) toJSON(type(i)) toJSON(type(list)) toJSON(type(nil)) toJSON(type(ok)) toJSON(type(str)) toJSON(type(true)) toJSON(uniq(array)) toJSON(uniq(list)) toJSON(upper(str)) toJSON({foo: $env}?.list) toJSON({foo: 0, foo: f64}.i) toJSON({foo: 0}) toJSON({foo: 1, foo: 1.0, foo: $env}) toJSON({foo: 1, foo: true}) toJSON({foo: 1.0}) toJSON({foo: 1.0}.f64) toJSON({foo: 1}) toJSON({foo: array}) toJSON({foo: f64}) toJSON({foo: false}) toJSON({foo: foo, foo: array}) toJSON({foo: foo, foo: f64}) toJSON({foo: foo, foo: str}) toJSON({foo: foo, foo: true}) toJSON({foo: foo}) toJSON({foo: foo}.Bar) toJSON({foo: foo}?.array) toJSON({foo: i, foo: foo}) toJSON({foo: i}) toJSON({foo: list}) toJSON({foo: nil != 1.0}) toJSON({foo: nil, foo: $env, foo: 0}) toJSON({foo: nil, foo: 1.0}) toJSON({foo: nil, foo: i}) toJSON({foo: nil}) toJSON({foo: ok}) toJSON({foo: str, foo: 0}) toJSON({foo: str}) toJSON({foo: true}) toPairs($env ?? $env) toPairs($env ?? 0) toPairs($env ?? 1) toPairs($env ?? 1.0) toPairs($env ?? add) toPairs($env ?? array) toPairs($env ?? foo) toPairs($env ?? i) toPairs($env ?? ok) toPairs($env ?? str) toPairs($env ?? true) toPairs($env) != array toPairs($env) != list toPairs($env) == array toPairs($env) == list toPairs($env) ?? array toPairs($env) ?? foo toPairs($env) ?? greet toPairs($env) ?? list toPairs($env) ?? str toPairs($env) not in $env?.Bar toPairs($env) | concat(array) toPairs($env) | count(false) toPairs($env) | count(ok) toPairs($env) | findIndex(false) toPairs($env) | findLast(ok) toPairs($env) | findLastIndex(true) toPairs($env) | groupBy(1.0) toPairs($env) | groupBy(false) toPairs($env) | groupBy(foo) toPairs($env) | groupBy(i) toPairs($env) | map(#) toPairs($env) | map(1.0) toPairs($env) | one(false) toPairs($env) | one(true) toPairs($env) | reduce(#) toPairs($env) | reduce(#, foo) toPairs($env) | reduce($env) toPairs($env) | reduce(1.0) toPairs($env) | reduce(add) toPairs($env) | reduce(false) toPairs($env) | reduce(foo) toPairs($env) | reduce(greet) toPairs($env) | reduce(i) toPairs($env) | sortBy(0) toPairs($env) | sortBy(i) toPairs($env)?.[i] toPairs(array | groupBy(1.0)) toPairs(array | groupBy(f64)) toPairs(array | groupBy(ok)) toPairs(false ? $env : $env) toPairs(groupBy(array, 1.0)) toPairs(groupBy(array, str)) toPairs(groupBy(array, true)) toPairs(groupBy(list, #)) toPairs(groupBy(list, 1.0)) toPairs(list | groupBy(#)) toPairs(list | groupBy(false)) toPairs(list | groupBy(foo)) toPairs(list | groupBy(i)) toPairs(max($env)) toPairs(min($env)) toPairs(nil ?? $env) toPairs(reduce(array, $env)) toPairs({foo: $env, foo: true}) toPairs({foo: $env}) toPairs({foo: 0, foo: $env}) toPairs({foo: 0}) toPairs({foo: 1, foo: $env}) toPairs({foo: 1, foo: foo}) toPairs({foo: 1.0 - 1.0}) toPairs({foo: 1.0, foo: $env}) toPairs({foo: 1.0, foo: 1}) toPairs({foo: 1.0}) toPairs({foo: 1}) toPairs({foo: add, foo: add}) toPairs({foo: add}) toPairs({foo: array, foo: f64}) toPairs({foo: array}) toPairs({foo: f64}) toPairs({foo: false}) toPairs({foo: foo, foo: greet}) toPairs({foo: foo, foo: list}) toPairs({foo: foo, foo: ok}) toPairs({foo: foo, foo: str}) toPairs({foo: foo}) toPairs({foo: greet}) toPairs({foo: i}) toPairs({foo: list}) toPairs({foo: nil, foo: str}) toPairs({foo: nil}) toPairs({foo: ok}) toPairs({foo: str}) toPairs({foo: true}) trim($env.str) trim($env?.[str]) trim($env?.[str], str) trim($env?.str) trim(false ? foo : str) trim(foo.Bar) trim(foo.Bar, str) trim(foo.String()) trim(foo?.Bar) trim(foo?.String()) trim(greet(foo?.Bar)) trim(greet(str)) trim(last(list).Bar) trim(list | reduce(.Bar)) trim(lower(str)) trim(nil ?? str) trim(reduce($env, str, greet)) trim(reduce(array, str)) trim(str + str) trim(str ?? 1.0) trim(str ?? add) trim(str ?? list) trim(str | greet()) trim(str) trim(str) == str trim(str) >= str trim(str) ?? array trim(str) in foo trim(str) matches str trim(str) not endsWith $env?.[str] trim(str) not in list?.[i] trim(str) not matches foo.String() trim(str) not matches str trim(str) | greet() trim(str)[:] trim(str, foo.Bar) trim(str, str) trim(str, toJSON(ok)) trim(str[0:]) trim(str[:0]) trim(str[:1]) trim(str[:i]) trim(string($env)) trim(string($env.ok)) trim(string($env?.Bar)) trim(string(0)) trim(string(1)) trim(string(1.0)) trim(string(add)) trim(string(array)) trim(string(f64)) trim(string(false)) trim(string(foo)) trim(string(greet)) trim(string(i)) trim(string(list)) trim(string(nil)) trim(string(ok)) trim(string(str)) trim(string(true)) trim(string(upper(str))) trim(toBase64(str)) trim(toJSON($env.list)) trim(toJSON($env?.foo)) trim(toJSON(0)) trim(toJSON(1)) trim(toJSON(1.0)) trim(toJSON(array)) trim(toJSON(f64)) trim(toJSON(false)) trim(toJSON(foo != foo)) trim(toJSON(foo)) trim(toJSON(i)) trim(toJSON(list)) trim(toJSON(nil)) trim(toJSON(ok)) trim(toJSON(str)) trim(toJSON(true)) trim(trim(str)) trim(trimPrefix(str)) trim(trimSuffix(str)) trim(type($env)) trim(type(0)) trim(type(1)) trim(type(1.0)) trim(type(add)) trim(type(array)) trim(type(f64)) trim(type(false)) trim(type(foo)) trim(type(greet)) trim(type(i)) trim(type(list)) trim(type(nil)) trim(type(ok)) trim(type(str)) trim(type(true)) trim(upper(str)) trimPrefix($env) == nil || true trimPrefix($env.str) trimPrefix($env?.[str]) trimPrefix($env?.str) trimPrefix($env?.str, str) trimPrefix(array | reduce(str, add)) trimPrefix(false ? greet : str) trimPrefix(foo.Bar) trimPrefix(foo.String()) trimPrefix(foo?.Bar) trimPrefix(foo?.String()) trimPrefix(greet(foo?.String())) trimPrefix(greet(str)) trimPrefix(greet(toJSON(false))) trimPrefix(lower(str)) trimPrefix(nil ?? str) trimPrefix(reduce(array, str)) trimPrefix(reduce(list, str)) trimPrefix(str + foo?.Bar) trimPrefix(str ?? $env) trimPrefix(str ?? 0) trimPrefix(str ?? array) trimPrefix(str ?? false) trimPrefix(str ?? foo) trimPrefix(str ?? greet) trimPrefix(str ?? i) trimPrefix(str ?? str) trimPrefix(str | greet()) trimPrefix(str) trimPrefix(str) < type(nil) trimPrefix(str) <= str trimPrefix(str) == str trimPrefix(str) > str trimPrefix(str) ?? f64 trimPrefix(str) endsWith str trimPrefix(str) not contains str trimPrefix(str) not startsWith str trimPrefix(str) startsWith str trimPrefix(str, false ? i : str) trimPrefix(str, foo?.Bar) trimPrefix(str, str) trimPrefix(str, string(foo)) trimPrefix(str, toJSON(nil)) trimPrefix(str, type(false)) trimPrefix(str, type(true)) trimPrefix(str[0:]) trimPrefix(str[1:]) trimPrefix(str[:i]) trimPrefix(string($env)) trimPrefix(string(0)) trimPrefix(string(1)) trimPrefix(string(1.0)) trimPrefix(string(add)) trimPrefix(string(array)) trimPrefix(string(f64)) trimPrefix(string(false)) trimPrefix(string(foo)) trimPrefix(string(greet)) trimPrefix(string(i)) trimPrefix(string(list)) trimPrefix(string(nil)) trimPrefix(string(ok)) trimPrefix(string(str)) trimPrefix(string(true)) trimPrefix(toBase64(str)) trimPrefix(toJSON(0)) trimPrefix(toJSON(1)) trimPrefix(toJSON(1.0)) trimPrefix(toJSON(array)) trimPrefix(toJSON(f64)) trimPrefix(toJSON(false)) trimPrefix(toJSON(foo)) trimPrefix(toJSON(i)) trimPrefix(toJSON(nil)) trimPrefix(toJSON(ok)) trimPrefix(toJSON(str)) trimPrefix(toJSON(true)) trimPrefix(trim(str)) trimPrefix(trimPrefix(str)) trimPrefix(trimPrefix(str, str)) trimPrefix(trimPrefix(type($env))) trimPrefix(trimSuffix(str)) trimPrefix(type($env)) trimPrefix(type($env.ok)) trimPrefix(type(0)) trimPrefix(type(1)) trimPrefix(type(1.0)) trimPrefix(type(add)) trimPrefix(type(array)) trimPrefix(type(f64)) trimPrefix(type(false)) trimPrefix(type(foo)) trimPrefix(type(greet)) trimPrefix(type(i)) trimPrefix(type(list)) trimPrefix(type(nil)) trimPrefix(type(ok)) trimPrefix(type(str)) trimPrefix(type(true)) trimPrefix(upper(foo?.String())) trimPrefix(upper(str)) trimSuffix($env.str) trimSuffix($env?.[str]) trimSuffix($env?.str) trimSuffix(array | reduce(str, foo)) trimSuffix(foo.Bar) trimSuffix(foo.String()) trimSuffix(foo?.Bar) trimSuffix(foo?.Bar, str) trimSuffix(foo?.String()) trimSuffix(greet(foo?.String())) trimSuffix(greet(str)) trimSuffix(greet(str), str) trimSuffix(greet(string(add))) trimSuffix(list | reduce(#.Bar)) trimSuffix(lower(str)) trimSuffix(str ?? $env) trimSuffix(str ?? foo) trimSuffix(str ?? list) trimSuffix(str | greet()) trimSuffix(str) trimSuffix(str) != str trimSuffix(str) + str trimSuffix(str) <= greet(str) trimSuffix(str) ?? add trimSuffix(str) ?? foo trimSuffix(str) ?? ok trimSuffix(str) | greet() trimSuffix(str, $env?.[str]) trimSuffix(str, str) trimSuffix(string($env)) trimSuffix(string($env), str) trimSuffix(string(0)) trimSuffix(string(1)) trimSuffix(string(1.0)) trimSuffix(string(add)) trimSuffix(string(array)) trimSuffix(string(f64)) trimSuffix(string(false)) trimSuffix(string(foo)) trimSuffix(string(foo.Bar)) trimSuffix(string(greet)) trimSuffix(string(i)) trimSuffix(string(list)) trimSuffix(string(nil)) trimSuffix(string(ok)) trimSuffix(string(str)) trimSuffix(string(sum($env, 0))) trimSuffix(string(true)) trimSuffix(toBase64($env?.[str])) trimSuffix(toBase64($env?.str)) trimSuffix(toBase64(str)) trimSuffix(toJSON(0)) trimSuffix(toJSON(1.0)) trimSuffix(toJSON(array)) trimSuffix(toJSON(f64)) trimSuffix(toJSON(false)) trimSuffix(toJSON(foo)) trimSuffix(toJSON(i)) trimSuffix(toJSON(list)) trimSuffix(toJSON(nil)) trimSuffix(toJSON(ok)) trimSuffix(toJSON(str)) trimSuffix(toJSON(true)) trimSuffix(trim(str)) trimSuffix(trimPrefix(str)) trimSuffix(trimSuffix(str)) trimSuffix(type($env)) trimSuffix(type(0)) trimSuffix(type(1)) trimSuffix(type(1.0)) trimSuffix(type(add)) trimSuffix(type(array)) trimSuffix(type(f64)) trimSuffix(type(false)) trimSuffix(type(foo)) trimSuffix(type(greet)) trimSuffix(type(i)) trimSuffix(type(list)) trimSuffix(type(nil)) trimSuffix(type(ok)) trimSuffix(type(str)) trimSuffix(type(true)) trimSuffix(upper(str)) true != $env != 1 ?? foo true != $env || $env >= 1.0 true != $env || ok true != $env.ok true != $env?.Bar true != $env?.String true != $env?.String?.String true != $env?.String?.[str] true != $env?.[Bar] true != $env?.[String] true != $env?.[String]?.Bar true != $env?.[foobar?.[greet]] true != $env?.[foobar] true != $env?.[str] true != $env?.ok true != f64 - 0 ?? $env true != false == ok true != false ?? i true != i ?? f64 true != list ?? array true != list ?? not ok true != nil and foo ?? ok true != nil and ok true != ok != $env?.String true != ok ?? array true != str ?? add true != str ?? greet true != str ?? i true != true ?: foo true != true ?? array true != true ?? greet true && $env != list true && $env == list?.[i] true && $env == str true && $env ?? $env[:foo] true && $env ?? foo true && $env ?? groupBy(list, foo)?.f64 true && $env ?? not $env true && $env ?? ok true && $env.ok true && $env?.Bar true && $env?.String true && $env?.[Bar] true && $env?.[Bar]?.[str] true && $env?.[Bar]?.str true && $env?.[String] true && $env?.[foobar] true && $env?.[str] true && $env?.foobar true && $env?.i != f64 true && $env?.ok true && 0 * i < 1 true && 0 ?? add true && 1 < len($env) true && 1.0 == f64 true && 1.0 > 0 and true true && 1.0 >= f64 true && add ?? list true && false != false || true true && false && ok true && greet == greet true && nil != foo true && nil == ok true && nil == str true && ok ?: str true && str != str true && str ?? $env?.[ok] true && str ?? f64 true && str ?? i true && str startsWith $env?.String true && true ?? ok true == $env == ok true == $env || $env != ok true == $env || 1.0 >= f64 true == $env.ok true == $env?.Bar true == $env?.String true == $env?.[Bar] true == $env?.[String] true == $env?.[foobar] true == $env?.[str] true == $env?.foobar true == $env?.ok true == 1.0 ?? foo || ok true == f64 ?? greet true == false and ok true == foo ?? f64 true == nil && false != nil true == nil && foo in $env true == nil == ok true == ok && ok true == true ?: add true == true or !true true ? $env : $env.f64 true ? $env : $env.foo true ? $env : $env.str true ? $env : $env?.Bar true ? $env : $env?.String true ? $env : $env?.[array] true ? $env : $env?.[list] true ? $env : $env?.[ok] true ? $env : $env?.greet true ? $env : foo.String true ? $env : i | date(i) true ? 0 : $env.i true ? 0 : $env?.Bar true ? 0 : $env?.Bar?.greet true ? 0 : $env?.String true ? 0 : $env?.[Bar] true ? 0 : $env?.[add]?.[f64] true ? 0 : $env?.[sortBy(1, foobar)] true ? 0 : $env?.foobar true ? 0 : $env[:list(foobar)] true ? 0 : 1 < 1.0 ** 1.0 true ? 0 : foo.String() true ? 0 : i > f64 true ? 1 : $env | max(0, f64) true ? 1 : $env.f64 true ? 1 : $env?.[ok] true ? 1 : $env?.i true ? 1 : 1.0 / 1 == f64 true ? 1 : list | sortBy(add) true ? 1.0 : $env | sortBy(add) true ? 1.0 : $env.foo true ? 1.0 : $env.greet true ? 1.0 : $env.ok true ? 1.0 : $env.str true ? 1.0 : $env?.[Bar] true ? 1.0 : $env?.[i] true ? 1.0 : $env?.[str] true ? 1.0 : $env?.list true ? 1.0 : $env?.ok true ? 1.0 : str >= $env?.[Bar] true ? add : $env ^ 0 != $env true ? add : $env.f64 true ? add : $env?.Bar true ? add : $env?.[add] true ? add : $env?.[ok] true ? add : foo.String true ? add : i != i true ? array : $env.array true ? array : $env?.[str] true ? array : $env?.foo true ? array : foo.String true ? f64 : $env.add true ? f64 : $env?.[f64] true ? f64 : $env?.[i] true ? f64 : $env?.greet true ? f64 : $env?.i true ? f64 : $env[foo?.[String]:] true ? false : $env | count($env) true ? false : $env.list true ? false : $env?.[array] true ? false : $env?.[i] true ? false : $env?.f64 true ? false : $env[:Bar not matches $env] true ? false : array != array true ? foo : $env | greet() true ? foo : $env | one(ok) true ? foo : $env | sortBy(1.0) true ? foo : $env.array true ? foo : $env.foo true ? foo : $env?.[String] true ? foo : $env?.[foo]?.greet true ? foo : $env?.[str] true ? foo : $env?.array true ? foo : $env?.i true ? foo : $env?.str true ? foo : 1.0 + i true ? foo : array | sortBy(f64) true ? foo : foo ?? list true ? foo : foo.Bar true ? foo : foo.String true ? foo : foo?.Bar true ? foo : i .. i true ? greet : $env | sum(.greet) true ? greet : $env.greet true ? greet : $env?.[add].foo true ? greet : $env?.str true ? greet : foo?.Bar true ? greet : nil != none($env, #) true ? i : $env?.[Bar] true ? i : array | map(i) true ? list : $env | all(#.foo) true ? list : $env?.String true ? list : $env?.[f64] true ? list : $env?.[greet] true ? list : $env?.[ok] true ? list : $env?.ok true ? list : foo.Bar true ? list : foo?.Bar true ? list : foo?.String true ? nil : $env | bitxor(0) true ? nil : $env.str true ? nil : $env?.[f64] true ? nil : $env?.foo true ? nil : $env?.str true ? nil : $env[str(1.0):] | all(.list?.i(foobar)) true ? nil : foo.Bar true ? nil : nil != greet true ? ok : $env.foo true ? ok : $env?.[str] true ? ok : $env?.array true ? ok : foo.String true ? str : $env?.array true ? str : $env?.f64 true ? str : array | max(i) true ? str : foo.Bar true ? str : foo?.Bar true ? str : i + i true ? true : $env?.String.str true ? true : $env?.[array] true ? true : $env?.[array].greet true ? true : $env?.greet true ? true : $env?.str true ? true : 1.0 == $env?.Bar true ? true : array | date(false, foo) true ? true : foo?.Bar true ? true : list | sum(#) true ? true : str != str true ?: $env != 0 ^ $env true ?: $env % i true ?: $env or ok true ?: $env | any(.i) true ?: $env | count(.list) true ?: $env | find(#) true ?: $env | groupBy(.foo) true ?: $env | groupBy(1.0) true ?: $env | reduce(#.list) true ?: $env | reduce(1.0) true ?: $env.add true ?: $env.array true ?: $env.foo true ?: $env.greet true ?: $env.i true ?: $env.i ?? $env true ?: $env.list true ?: $env.ok true ?: $env.str true ?: $env?.Bar true ?: $env?.String true ?: $env?.[Bar] true ?: $env?.[String()] true ?: $env?.[array] true ?: $env?.[f64] true ?: $env?.[foo] true ?: $env?.[i] true ?: $env?.[list] true ?: $env?.add true ?: $env?.array true ?: $env?.f64 true ?: $env?.foo true ?: $env?.greet true ?: $env?.i true ?: $env?.ok true ?: $env?.str true ?: $env[:foobar] true ?: 0 != 0 ? true : false true ?: 1.0 - f64 true ?: 1.0 == f64 true ?: 1.0 >= f64 true ?: 1.0 | max($env) true ?: array | map(1.0) true ?: array?.[$env?.String()] true ?: foo ?? f64 true ?: foo.Bar true ?: foo.String true ?: foo?.Bar true ?: foo?.String true ?: nil != f64 true ?: nil == $env?.str true ?? $env.add true ?? $env.array true ?? $env.f64 true ?? $env.foo true ?? $env.greet true ?? $env.i true ?? $env.list true ?? $env.ok true ?? $env.str true ?? $env?.Bar true ?? $env?.String true ?? $env?.String() true ?? $env?.String?.f64 true ?? $env?.[1.0 not endsWith foobar] true ?? $env?.[Bar] true ?? $env?.[Bar]?.[str] true ?? $env?.[String] true ?? $env?.[abs(foobar)] true ?? $env?.[add] true ?? $env?.[array] true ?? $env?.[f64] true ?? $env?.[foo?.greet] true ?? $env?.[foo] true ?? $env?.[foo].array true ?? $env?.[foobar | one(#)] true ?? $env?.[foobar.f64(1, foobar, ok)] true ?? $env?.[greet] true ?? $env?.[i] true ?? $env?.[list] true ?? $env?.[ok] true ?? $env?.[ok]?.[greet] true ?? $env?.[str] true ?? $env?.add true ?? $env?.array true ?? $env?.f64 true ?? $env?.foo true ?? $env?.foobar true ?? $env?.foobar.String true ?? $env?.greet true ?? $env?.i true ?? $env?.list true ?? $env?.ok true ?? $env?.str true ?? $env[$env?.[str]:] true ?? $env[:String.greet].greet true ?? $env[:array[:f64]] true ?? $env[f64():] true ?? $env[false == str:] true ?? $env[foobar ^ foobar:findIndex($env, #index)] true ?? $env[foobar:foobar] true ?? 0 ?? greet true ?? 1 ?? groupBy($env, .str) true ?? 1.0 ?? i true ?? array?.[i] true ?? foo ?? i true ?? foo.Bar true ?? foo.String true ?? foo?.Bar true ?? foo?.String true ?? foo?.String() true ?? i | get(false) true ?? list?.[i] true ?? nil ?? greet true and $env != greet true and $env == f64 true and $env == last(array) true and $env ?? $env ?? add true and $env ?? count($env, #) true and $env ?? str true and $env startsWith $env?.Bar true and $env.ok true and $env?.Bar true and $env?.Bar?.Bar true and $env?.String true and $env?.String?.Bar true and $env?.String?.[array] true and $env?.String?.ok true and $env?.[Bar] true and $env?.[Bar]?.i true and $env?.[String] true and $env?.[str] true and $env?.foobar true and $env?.foobar?.array() true and $env?.ok true and 0 != f64 true and 0 < i true and 1 > f64 true and 1 > i true and 1 >= i true and 1 in sort($env) true and 1.0 > f64 true and 1.0 in array true and add ?? array true and array != list true and f64 < f64 true and f64 <= f64 true and f64 ?? foo true and false ?? ok true and false || ok true and foo != foo true and foo == foo true and i == i true and nil != greet true and nil != list true and nil == greet true and str != str true and str ?? greet true and true || $env >= $env true in $env?.Bar true in $env?.Bar?.foo true in $env?.String true in $env?.[Bar] true in $env?.[String] true in $env?.[first(foobar)] true in $env?.[foobar | last(nil)] true in $env?.[foobar] true not in $env?.Bar true not in $env?.String true not in $env?.String?.Bar(foo) true not in $env?.[Bar] true not in $env?.[Bar]?.String true not in $env?.[Bar]?.foo true not in $env?.[String] true not in $env?.[String]?.[list] true not in $env?.[foobar] true not in array ?? add true not in array ?? foo true not in list ?? i true or $env != array true or $env != ok true or $env && ok true or $env * findIndex(list, true) true or $env - f64 true or $env - list ?? false true or $env ?? $env?.[Bar] true or $env ?? foo true or $env endsWith $env?.greet($env) true or $env in str true or $env not in [i] true or $env startsWith str true or $env.ok true or $env?.Bar true or $env?.Bar() true or $env?.Bar(add not matches foobar) true or $env?.Bar(f64?.String() in count(greet)) true or $env?.Bar?.array true or $env?.String true or $env?.String() true or $env?.String(add()) true or $env?.String(true | findLastIndex(1)) true or $env?.String?.ok true or $env?.[0 | one(1.0)] true or $env?.[Bar] true or $env?.[Bar].ok true or $env?.[String] true or $env?.[add] true or $env?.[add]?.[add] true or $env?.[add]?.str true or $env?.[array(ok, foobar)] true or $env?.[array] true or $env?.[array]?.greet?.Bar true or $env?.[array]?.str() true or $env?.[f64] true or $env?.[float(array, foobar)] true or $env?.[foo | findLastIndex(#)] true or $env?.[foo] true or $env?.[foobar != foo] true or $env?.[foobar | concat(true)] true or $env?.[greet] true or $env?.[greet]?.[add] true or $env?.[i.f64] true or $env?.[i] true or $env?.[i] == ok true or $env?.[list(foobar, foobar)]?.foo true or $env?.[list] true or $env?.[list]?.list true or $env?.[ok(foobar)] true or $env?.[ok] true or $env?.[str.greet] true or $env?.[str] true or $env?.[str].ok true or $env?.foobar true or $env?.min(1.0) true or $env?.ok true or $env?.sortBy(foo, 1.0)?.foo() true or $env[:1.0 or list] true or $env[:Bar] true or $env[:array ?: foo] true or $env[:bitnand(greet, foobar)] true or $env[:foobar?.String(foobar, foobar)] true or $env[:greet] true or $env[:i] true or $env[:nil | filter(false)] true or $env[:str] true or $env[:true || foobar] true or $env[foobar:] true or $env[foobar?.[array]:] true or $env[none($env, .String):] true or $env[ok:] true or $env[trimSuffix(foobar, nil, 1.0, array):] true or 0 < f64 true or 0 < f64 ** 1 true or 0 <= $env?.[f64]?.[foo] true or 0 <= i true or 0 ?? foo?.Bar true or 1 > f64 true or 1 >= $env in $env true or 1.0 != i true or 1.0 <= $env ^ i true or 1.0 > i true or 1.0 >= f64 true or array == list true or f64 + $env?.[add] true or f64 ?? foo true or f64 ?? i true or f64 ?? list true or false ?: sum($env, .Bar) true or false or ok true or foo != foo && true true or greet == greet true or i > $env[:foobar] true or i not in $env * f64 true or list != list true or nil == add true or nil == str in $env true or nil not in $env?.[String] true or nil not in list true or ok && ok true or ok and foo == $env?.[String] true or ok in sum($env) true or str == toJSON(f64) true or str contains $env?.str true or str in $env[list:] true or str not in foo true || $env != 1.0 - $env true || $env != i true || $env <= foo?.Bar true || $env == greet true || $env > f64 true || $env >= f64 - 0 true || $env ?? add true || $env ?? array true || $env ?? f64 true || $env ?? foo true || $env ?? ok true || $env contains str true || $env in str true || $env not contains $env?.[foo] true || $env not contains str true || $env or ok true || $env.ok true || $env?.Bar true || $env?.Bar() true || $env?.Bar?.i() true || $env?.String true || $env?.String($env | bitshl(str)).str true || $env?.String() true || $env?.String(false > foobar, array(foobar)) true || $env?.String(foobar?.greet(foobar)) true || $env?.String(map(foobar | findIndex(#.str), .greet)) true || $env?.String(reduce(foobar, #.list).i) true || $env?.String?.list true || $env?.[$env > list] true || $env?.[Bar(nil, 0)] true || $env?.[Bar] true || $env?.[String] true || $env?.[add(String)] true || $env?.[add] true || $env?.[add].f64 true || $env?.[add].f64.list true || $env?.[array?.array()] true || $env?.[array] true || $env?.[f64] true || $env?.[foo.i] true || $env?.[foo] true || $env?.[foobar | findIndex(add)] true || $env?.[foobar | findLastIndex(.ok)] true || $env?.[foobar] true || $env?.[greet] true || $env?.[i] true || $env?.[i]?.[ok] true || $env?.[list] true || $env?.[list]?.String true || $env?.[ok not startsWith 1.0] true || $env?.[ok] true || $env?.[ok]?.[ok] true || $env?.[str] true || $env?.[{foo: nil}] true || $env?.any($env) true || $env?.foobar true || $env?.ok true || $env?.reduce($env) true || $env[:String == foo] true || $env[:array($env)] true || $env[:foobar] true || $env[:ok ? false : add] true || $env[:str] true || $env[Bar | map(1):foobar] true || $env[String.Bar(foobar):add()] true || $env[duration(String):] true || $env[false | bitand(str):] true || $env[foo(foobar):f64 contains list] true || $env[foobar:] true || $env[foobar?.[str]:str()] true || $env[list endsWith str:foobar] true || $env[list:] true || $env[ok + foobar:] true || $env[ok not in foobar:] true || 0 != $env?.f64 true || 0 != f64 true || 0 <= $env?.String(str) true || 0 > 1.0 != true true || 0 >= median(0, $env) true || 1 > f64 true || 1.0 ** f64 >= f64 true || 1.0 + 1.0 > 1.0 true || 1.0 < $env?.[str] true || 1.0 < find($env, #) true || 1.0 <= i true || 1.0 > f64 true || 1.0 > f64 == true true || 1.0 >= f64 true || 1.0 >= i true || 1.0 in $env?.[add] true || add != add true || add ?? f64 true || array != list true || array ?? !true true || array not in $env?.[f64] true || false == $env?.[add] true || false ?: f64 true || false ?: foo ?? f64 true || false ?? $env?.[array] true || foo == $env || ok true || foo ?? array true || foo ?? ok true || i == $env?.[f64] true || i > f64 true || i >= $env ?? $env true || i in array true || nil != f64 true || nil != greet ?? $env true || nil != i true || nil == foo true || nil == ok true || ok ?? greet true || true && f64 != 1.0 true || true and ok true; $env?.[str] true; foo?.String type(!false) type(!ok) type(!true) type($env != $env) type($env != 0) type($env != 1.0) type($env != add) type($env != f64) type($env != foo) type($env != greet) type($env != list) type($env != nil) type($env != str) type($env != true) type($env && true) type($env == $env) type($env == 1) type($env == 1.0) type($env == add) type($env == array) type($env == f64) type($env == false) type($env == foo) type($env == greet) type($env == nil) type($env == ok) type($env == str) type($env ?? $env) type($env ?? 1) type($env ?? 1.0) type($env ?? array) type($env ?? false) type($env ?? foo) type($env ?? greet) type($env ?? i) type($env ?? list) type($env ?? nil) type($env and false) type($env and true) type($env in array) type($env in list) type($env not in array) type($env not in list) type($env or false) type($env or true) type($env | all(true)) type($env | any(false)) type($env | any(ok)) type($env | any(true)) type($env | count(false)) type($env | count(ok)) type($env | count(true)) type($env | find(false)) type($env | findIndex(true)) type($env | findLastIndex(ok)) type($env | map(#index)) type($env | map($env)) type($env | map(1.0)) type($env | map(false)) type($env | map(foo)) type($env | map(ok)) type($env | map(str)) type($env | none(true)) type($env | one(false)) type($env | sum(0)) type($env | sum(1.0)) type($env || false) type($env || true) type($env) != foo?.Bar type($env) != str type($env) <= str type($env) contains str type($env) endsWith str type($env) in foo type($env) not contains toJSON(true) type($env) not in foo type($env) not matches str type($env) startsWith type($env) type($env) | greet() type($env) | indexOf(str) type($env.add) type($env.array) type($env.f64) type($env.foo) type($env.foo?.Bar) type($env.greet) type($env.i) type($env.list) type($env.ok) type($env.str) type($env?.$env) type($env?.Bar) type($env?.String) type($env?.String?.add) type($env?.String?.greet) type($env?.[Bar]) type($env?.[Bar]) | trimPrefix(str) type($env?.[String]) type($env?.[String]?.[i]) type($env?.[String]?.i) type($env?.[foobar]) type($env?.[nil]) type($env?.[str]) type($env?.add) type($env?.add) | greet() type($env?.array) type($env?.f64) type($env?.false) type($env?.foo) type($env?.foo?.String) type($env?.foobar) type($env?.greet) type($env?.i) type($env?.list ?? foo) type($env?.list) type($env?.nil) type($env?.ok) type($env?.str) type($env?.true) type(-0) type(-1) type(-1.0) type(-f64) type(-i) type(0 != $env) type(0 != 0) type(0 != 1.0) type(0 != f64) type(0 != i) type(0 != nil) type(0 % i) type(0 * 0) type(0 * 1) type(0 ** 0) type(0 + 0) type(0 + 1) type(0 + i) type(0 - 0) type(0 - 1) type(0 - f64) type(0 - i) type(0 .. 0) type(0 .. 1) type(0 .. i) type(0 / 1) type(0 / 1.0) type(0 / i) type(0 < 0) type(0 < 1) type(0 < 1.0) type(0 < f64) type(0 <= 1) type(0 <= 1.0) type(0 <= i) type(0 == $env) type(0 == 1) type(0 == 1.0) type(0 == i) type(0 == nil) type(0 > 0) type(0 > 1.0) type(0 > i) type(0 >= 1.0) type(0 ?? $env) type(0 ?? $env?.ok) type(0 ?? 1) type(0 ?? 1.0) type(0 ?? foo) type(0 ?? greet) type(0 ?? list) type(0 ?? nil) type(0 ?? ok) type(0 ?? str) type(0 ^ 1) type(0 ^ 1.0) type(0 ^ f64) type(0 ^ i) type(0 | bitshr(0)) type(0 | bitxor(1)) type(0 | median(1, 1.0)) type(0 | min(0)) type(0 | min(i)) type(0) != str type(0) ?? array type(0) ?? i type(0) ?? ok type(0) in foo type(0) not startsWith str type(0) | greet() type(0) | splitAfter(str) type(0) | trim(str) type(0)[i:] type(0..i) type(0.0) type(0.1) type(1 != $env) type(1 != 1.0) type(1 != f64) type(1 != nil) type(1 % 1) type(1 * 0) type(1 * 1) type(1 * 1.0) type(1 * f64) type(1 * i) type(1 ** 1.0) type(1 ** f64) type(1 + 0) type(1 + 1) type(1 + 1.0) type(1 + i) type(1 - 1.0) type(1 .. 0) type(1 .. 1) type(1 / 0) type(1 / 1) type(1 / 1.0) type(1 / f64) type(1 / i) type(1 < 1.0) type(1 <= 0) type(1 <= 1) type(1 <= 1.0) type(1 <= i) type(1 == $env) type(1 == 1.0) type(1 == f64) type(1 == i) type(1 == nil) type(1 > 0) type(1 > 1) type(1 > 1.0) type(1 > f64) type(1 > i) type(1 >= 0) type(1 >= 1.0) type(1 >= f64) type(1 >= i) type(1 ?? $env) type(1 ?? 0) type(1 ?? add) type(1 ?? foo) type(1 ?? ok) type(1 ?? str) type(1 ^ 0) type(1 ^ 1) type(1 ^ 1.0) type(1 in array) type(1 not in array) type(1) != str type(1) < str type(1) <= str type(1) >= type(ok) type(1) in $env?.Bar type(1) not in foo type(1) not matches str type(1) startsWith reduce(list, #.Bar) type(1) | greet() type(1.0 != $env) type(1.0 != $env?.i) type(1.0 != 1) type(1.0 != 1.0) type(1.0 != f64) type(1.0 != i) type(1.0 != nil) type(1.0 * 0) type(1.0 * 1) type(1.0 * 1.0) type(1.0 * f64) type(1.0 * i) type(1.0 * i) | greet() type(1.0 ** 1) type(1.0 ** 1.0) type(1.0 ** f64) type(1.0 + 0) type(1.0 + 1) type(1.0 + 1.0) type(1.0 + f64) type(1.0 + i) type(1.0 - 0) type(1.0 - 1.0) type(1.0 - f64) type(1.0 - i) type(1.0 / 1) type(1.0 / 1.0) type(1.0 / f64) type(1.0 / i) type(1.0 < 0) type(1.0 < 1) type(1.0 < 1.0) type(1.0 < f64) type(1.0 < i) type(1.0 <= 0) type(1.0 <= 1) type(1.0 <= 1.0) type(1.0 <= i) type(1.0 == $env) type(1.0 == 0) type(1.0 == 1.0) type(1.0 == f64) type(1.0 == i) type(1.0 == nil) type(1.0 > 1.0) type(1.0 > f64) type(1.0 > i) type(1.0 >= 0) type(1.0 >= 1) type(1.0 >= 1.0) type(1.0 >= f64) type(1.0 >= i) type(1.0 ?? $env) type(1.0 ?? 0) type(1.0 ?? add) type(1.0 ?? f64) type(1.0 ?? foo) type(1.0 ?? greet) type(1.0 ?? i) type(1.0 ?? nil) type(1.0 ?? ok) type(1.0 ?? str) type(1.0 ^ 0) type(1.0 ^ 1.0) type(1.0 ^ f64) type(1.0 ^ i) type(1.0 in array) type(1.0 | max(0)) type(1.0 | mean(1.0)) type(1.0) type(1.0) + foo.Bar type(1.0) + str type(1.0) < str type(1.0) >= str type(1.0) ?? array type(1.0) ?? f64 type(1.0) ?? greet($env) type(1.0) contains str type(1.0) not endsWith foo.Bar type(1.0) not endsWith str type(1.0) not matches str type(1.0) not startsWith foo?.Bar type(1.0) startsWith str type(1.0) | greet() type(1.0)[:i] type([$env, $env]) type([$env, 0]) type([$env, f64]) type([$env]) type([0]) type([1.0, 0]) type([1.0, foo]) type([1.0]) type([1]) type([add]) type([array]) type([f64]) type([false, $env]) type([false]) type([foo, foo]) type([foo, i]) type([foo, nil]) type([foo]) type([greet]) type([i, array]) type([i, foo, nil]) type([i]) type([list, 1.0, true]) type([list, ok]) type([list]) type([nil, foo]) type([nil]) type([ok, f64]) type([ok, nil]) type([ok]) type([str]) type([true, foo]) type([true]) type(abs(0)) type(abs(1)) type(abs(1.0)) type(abs(f64)) type(abs(i)) type(add != $env) type(add != add) type(add == nil) type(add ?? $env) type(add ?? $env?.[i]) type(add ?? 0) type(add ?? foo) type(add ?? i) type(add ?? list) type(add ?? ok) type(add ?? true) type(add(1, 0)) type(add(i, 0)) type(add) type(add) != str type(add) == foo.Bar type(add) > str type(add) ?? max(array) type(add) matches str type(add) not matches str type(add) | greet() type(add)[:] type(all($env, true)) type(all(array, false)) type(all(array, true)) type(all(list, true)) type(any($env, false)) type(any($env, ok)) type(any(array, 1 > #)) type(any(array, false)) type(any(array, ok)) type(any(list, false)) type(array != nil) type(array == $env) type(array == array) type(array == nil) type(array ?? $env) type(array ?? 1.0) type(array ?? add) type(array ?? array) type(array ?? f64) type(array ?? false) type(array ?? i) type(array ?? nil) type(array ?? str) type(array ?? true) type(array | find(false)) type(array | findIndex(false)) type(array | findIndex(ok)) type(array | groupBy(#)) type(array | groupBy(foo)) type(array | groupBy(ok)) type(array | map(#)) type(array | map(1)) type(array | map(greet)) type(array | min(array)) type(array | none(false)) type(array | none(ok)) type(array | reduce(#)) type(array | reduce(#, foo)) type(array | reduce(#index)) type(array | reduce(1.0, list)) type(array | reduce(1.0, ok)) type(array | reduce(false)) type(array | reduce(false, add)) type(array | reduce(foo)) type(array | reduce(true)) type(array | sortBy(#)) type(array | sum(#)) type(array | sum(1)) type(array | sum(1.0)) type(array | sum(i)) type(array) type(array) != false ?? i type(array) + str type(array) < str type(array) == str type(array) ?? f64 type(array) ?? greet type(array) ?? str type(array) endsWith $env?.[Bar]?.[str] type(array) in foo type(array) not in foo type(array) | repeat(1) type(array?.[0]) type(array?.[i]) type(array[1:]) type(array[:0]) type(array[:]) type(array[:i]) type(bitnand(i, 0)) type(bitnot(0)) type(bitnot(1)) type(bitnot(i)) type(bitshr(i, 1)) type(bitxor(i, i)) type(ceil(0)) type(ceil(1 - f64)) type(ceil(1)) type(ceil(1.0)) type(ceil(f64)) type(ceil(floor(i))) type(ceil(i)) type(concat(array)) type(concat(list)) type(count($env, ok)) type(count($env, true)) type(count([true])) type(f64 != 0) type(f64 != 1) type(f64 != 1.0) type(f64 != nil) type(f64 * 0) type(f64 * 1.0) type(f64 * f64) type(f64 * i) type(f64 ** 0) type(f64 ** 1.0) type(f64 ** i) type(f64 + 1) type(f64 + 1.0) type(f64 + f64) type(f64 + i) type(f64 - 0) type(f64 - 1.0) type(f64 / 0) type(f64 / 1.0) type(f64 / i) type(f64 < 1) type(f64 < 1.0) type(f64 <= 1) type(f64 <= 1.0) type(f64 <= i) type(f64 == 0) type(f64 == 1) type(f64 == f64) type(f64 == nil) type(f64 > 0 != $env) type(f64 > 1) type(f64 > 1.0) type(f64 > f64) type(f64 > i) type(f64 >= 1) type(f64 >= 1.0) type(f64 >= f64) type(f64 ?? $env?.[nil == nil]) type(f64 ?? array) type(f64 ?? false) type(f64 ?? foo) type(f64 ?? str) type(f64 ?? true) type(f64 ^ 1) type(f64 ^ 1.0) type(f64 ^ f64) type(f64 ^ i) type(f64 not in array) type(f64) type(f64) == str type(f64) > str type(f64) >= str type(f64) matches toJSON(1.0) type(f64) not startsWith str type(f64) startsWith str type(f64) | greet() type(false != false) type(false != nil) type(false != ok) type(false != true) type(false && $env) type(false && ok) type(false == $env) type(false == false) type(false == ok) type(false ? f64 : 1) type(false ? foo : add) type(false ? foo : list) type(false ? list : foo) type(false ?? $env) type(false ?? 1.0) type(false ?? add) type(false ?? f64) type(false ?? i) type(false ?? list) type(false ?? nil) type(false ?? ok) type(false ?? str) type(false ?? true) type(false and $env) type(false and true) type(false or $env) type(false or ok) type(false or true) type(false || $env) type(false || false) type(false || ok) type(false || true) type(false) == str type(false) > str type(false) ?? $env?.[i] type(false) ?? greet type(false) | greet() type(false) | splitAfter(str) type(filter($env, false)) type(find(array, false)) type(find(array, true)) type(findIndex($env, ok)) type(findIndex(list, ok)) type(findLast($env, false)) type(findLast(array, ok)) type(findLast(list, false)) type(findLast(list, ok)) type(findLastIndex(array, ok)) type(first($env)) type(first(array)) type(first(list)) type(flatten(array)) type(flatten(list)) type(float(0)) type(float(1)) type(float(1.0)) type(float(f64)) type(float(i)) type(floor(0)) type(floor(1)) type(floor(1.0)) type(floor(f64)) type(floor(i)) type(foo != $env) type(foo != $env?.foo) type(foo != foo) type(foo != nil) type(foo == $env) type(foo == foo) type(foo == nil) type(foo ?? $env) type(foo ?? 0) type(foo ?? 1) type(foo ?? 1.0) type(foo ?? add) type(foo ?? array) type(foo ?? f64) type(foo ?? false) type(foo ?? foo) type(foo ?? greet) type(foo ?? i) type(foo ?? list) type(foo ?? nil) type(foo ?? ok) type(foo ?? true) type(foo in list) type(foo not in list) type(foo) type(foo) != $env?.foobar type(foo) <= str type(foo) > str type(foo) ?? add type(foo) ?? array type(foo) contains $env?.Bar?.[add] type(foo) matches $env?.String?.[greet] type(foo) matches str type(foo) not endsWith str type(foo) not in $env and false type(foo) not in foo and $env type(foo) not matches str type(foo) not startsWith str type(foo) startsWith $env?.[Bar] type(foo) | greet() type(foo)[:] type(foo.Bar) type(foo.Bar) matches str type(foo.String()) type(foo.String) type(foo?.Bar) type(foo?.String()) type(foo?.String) type(greet != $env) type(greet != greet) type(greet == $env) type(greet == greet) type(greet == nil) type(greet ?? $env) type(greet ?? 1) type(greet ?? 1.0) type(greet ?? add) type(greet ?? array) type(greet ?? f64) type(greet ?? false) type(greet ?? greet) type(greet ?? list) type(greet ?? nil) type(greet ?? str) type(greet(str)) type(greet(toJSON(false))) type(greet) type(greet) ?? foo type(greet) contains foo.Bar type(greet) startsWith str type(greet) | greet() type(groupBy(array, #)) type(groupBy(array, 0)) type(groupBy(array, 1.0)) type(groupBy(array, false)) type(groupBy(array, foo)) type(groupBy(array, ok)) type(groupBy(list, #)) type(groupBy(list, .Bar)) type(groupBy(list, 0)) type(groupBy(list, 1.0)) type(groupBy(list, false)) type(i != $env) type(i != 1.0) type(i != array?.[i]) type(i != f64) type(i != i) type(i != nil) type(i * 0) type(i * 1) type(i * 1.0) type(i * f64) type(i ** 0) type(i ** 1.0) type(i ** f64) type(i + 0) type(i + 1) type(i + 1.0) type(i + f64) type(i + i) type(i - 0) type(i - 1) type(i - 1.0) type(i - f64) type(i .. 0) type(i .. i) type(i / 1.0) type(i < 1.0) type(i < i) type(i <= 0) type(i <= 1) type(i <= 1.0 + 1.0 == $env) type(i <= 1.0) type(i <= f64) type(i <= i) type(i == $env) type(i == 1) type(i == 1.0) type(i == nil) type(i > 1.0) type(i > f64) type(i >= 1.0) type(i >= f64) type(i >= i) type(i ?? $env) type(i ?? 1.0) type(i ?? add) type(i ?? false) type(i ?? foo) type(i ?? list) type(i ?? nil) type(i ^ 0) type(i ^ 1) type(i ^ i) type(i | bitushr(i)) type(i) type(i) <= str type(i) ?? foo type(i) ?? greet type(i) matches string(ok) type(i) not in foo type(i) not startsWith str type(i) | greet() type(i) | splitAfter(str) type(if false { $env } else { $env }) type(if false { f64 } else { 0 }) type(if false { nil } else { foo }) type(if false { nil } else { nil }) type(if false { nil } else { ok }) type(if false { str } else { add }) type(if false { true } else { array }) type(if ok { 1 } else { false }) type(if ok { array } else { ok }) type(if ok { foo } else { foo }) type(if ok { nil } else { str }) type(if true { i } else { 0 }) type(int(0)) type(int(1)) type(int(1.0)) type(int(f64)) type(int(i)) type(keys($env)) type(last($env)) type(last($env)?.String) type(last($env)?.[i]) type(last($env?.Bar)) type(last(array)) type(last(list)) type(len($env)) type(len(array)) type(len(list)) type(len(str)) type(let bar = $env; bar) type(let bar = true; bar) type(let foobar = 1; foobar) type(let y = list; let bar = i; y) type(list != $env) type(list != array) type(list != list) type(list != nil) type(list == $env) type(list == nil) type(list ?? $env) type(list ?? 0) type(list ?? 1.0) type(list ?? add) type(list ?? foo) type(list ?? greet) type(list | any(ok)) type(list | count(true)) type(list | filter(true)) type(list | find(false)) type(list | findLast(ok)) type(list | groupBy(#)) type(list | groupBy(0)) type(list | groupBy(1.0)) type(list | map(#)) type(list | map(#index)) type(list | map(0)) type(list | map(1.0)) type(list | map(foo)) type(list | map(greet)) type(list | one(false)) type(list | one(ok)) type(list | reduce(#)) type(list | reduce(#, 0)) type(list | reduce(#, nil)) type(list | reduce(#.Bar)) type(list | reduce(#acc)) type(list | reduce($env)) type(list | reduce(i)) type(list | reduce(ok, add)) type(list | sortBy(#.Bar)) type(list) type(list) == str type(list) >= string(0) type(list) ?? foo | reduce(foo, 1.0) type(list) ?? greet type(list) contains toBase64(str) type(list) | hasSuffix(str) type(list?.[i]) type(list?.[i].Bar) type(list[0:]) type(list[:i]) type(lower($env?.[str])) type(lower(str)) type(map($env, #index)) type(map($env, $env)) type(map($env, 1)) type(map($env, 1.0)) type(map($env, add)) type(map($env, f64)) type(map($env, foo)) type(map($env, greet)) type(map($env, i)) type(map(array, # == i)) type(map(array, #)) type(map(array, 0)) type(map(array, 1)) type(map(array, false)) type(map(list, #)) type(map(list, 1.0)) type(map(list, false)) type(map(list, foo)) type(max($env)) type(max(0)) type(max(0, array)) type(max(0, f64)) type(max(1)) type(max(1.0)) type(max(array)) type(max(f64)) type(max(i)) type(mean(0)) type(mean(1)) type(mean(1.0)) type(mean(array)) type(mean(array, 1.0)) type(mean(f64)) type(mean(i)) type(median($env.i)) type(median(0)) type(median(0, 1)) type(median(1.0)) type(median(array)) type(median(f64)) type(median(f64, 1.0)) type(median(i)) type(median(min(f64))) type(min($env)) type(min(0)) type(min(1)) type(min(1.0)) type(min(array)) type(min(f64)) type(min(f64, 1.0)) type(min(i)) type(nil != $env) type(nil != 0) type(nil != 1) type(nil != 1.0) type(nil != add) type(nil != array) type(nil != false) type(nil != foo) type(nil != greet) type(nil != i) type(nil != list) type(nil != nil) type(nil != str) type(nil == $env) type(nil == 0) type(nil == 1) type(nil == 1.0) type(nil == add) type(nil == array) type(nil == f64) type(nil == false) type(nil == foo) type(nil == greet) type(nil == i) type(nil == list) type(nil == nil) type(nil == ok) type(nil == str) type(nil ?? $env) type(nil ?? 0) type(nil ?? 1.0) type(nil ?? add) type(nil ?? array) type(nil ?? foo) type(nil ?? i) type(nil ?? nil) type(nil ?? ok) type(nil ?? str) type(nil ?? true) type(nil in $env) type(nil in array) type(nil in list) type(nil not in $env) type(nil not in array) type(nil not in list) type(nil) < str type(nil) <= str type(nil) >= str type(nil) ?? toJSON($env) type(nil) matches str type(nil) matches string(foo) type(nil) not endsWith str type(nil) not in foo type(nil) not in {foo: false} type(nil) startsWith str type(nil) | greet() type(nil)[:] type(none(array, false)) type(none(array, ok)) type(none(list, false)) type(none(list, ok)) type(not !false) type(not false) type(not ok) type(not true) type(ok != $env) type(ok != nil) type(ok && true) type(ok == $env) type(ok == false) type(ok == nil) type(ok == true) type(ok ? 1 : 1.0) type(ok ? 1 : foo) type(ok ? list : foo) type(ok ?: array) type(ok ?: greet) type(ok ?? 0) type(ok ?? 1) type(ok ?? 1.0) type(ok ?? add) type(ok ?? f64) type(ok ?? foo) type(ok ?? i) type(ok ?? list) type(ok ?? ok) type(ok ?? str) type(ok ?? true) type(ok and $env) type(ok and false) type(ok and ok) type(ok and true) type(ok or $env) type(ok or false) type(ok or true) type(ok || $env) type(ok || false) type(ok || ok) type(ok || true) type(ok) type(ok) <= str type(ok) ?? array type(ok) ?? f64 type(ok) ?? foo type(ok) contains str type(ok) in foo type(ok) in {foo: true} type(ok) | greet() type(one($env, false)) type(one($env, true)) type(reduce(array, #)) type(reduce(array, $env)) type(reduce(array, 0)) type(reduce(array, add)) type(reduce(array, array)) type(reduce(array, f64)) type(reduce(array, foo)) type(reduce(array, greet, false)) type(reduce(array, ok)) type(reduce(list, #)) type(reduce(list, #.String)) type(reduce(list, #index)) type(reduce(list, $env)) type(reduce(list, 0)) type(reduce(list, add)) type(reduce(list, false)) type(reduce(list, ok)) type(reverse([ok])) type(reverse(array)) type(reverse(list)) type(round(0)) type(round(1)) type(round(1.0)) type(round(f64)) type(round(i)) type(sort($env)) type(sort(array)) type(sortBy(array, #)) type(sortBy(array, 0)) type(sortBy(array, 1.0)) type(sortBy(list, 0)) type(sortBy(list, i)) type(str != $env) type(str != str) type(str <= str) type(str == $env) type(str == str) type(str > str) type(str >= str) type(str ?? $env) type(str ?? 1.0) type(str ?? f64) type(str ?? foo) type(str ?? i) type(str ?? list) type(str ?? nil) type(str ?? ok) type(str ?? str) type(str contains str) type(str in $env) type(str in foo) type(str not in $env) type(str not in foo) type(str) type(str) <= trim(str) type(str) == str type(str) >= str type(str) ?? -f64 type(str) ?? foo type(str) contains $env?.String type(str) matches str type(str) not endsWith str type(str) not in list?.[i] type(str)[:] type(str[:]) type(str[i:]) type(string($env)) type(string(0)) type(string(1)) type(string(1.0)) type(string(add)) type(string(array)) type(string(f64)) type(string(false != nil)) type(string(false)) type(string(foo)) type(string(greet)) type(string(list)) type(string(map($env, 1))) type(string(nil)) type(string(ok)) type(string(str)) type(string(true)) type(sum($env, f64)) type(sum(array)) type(sum(array, #)) type(sum(array, 1)) type(sum(list, 1.0)) type(toBase64(str)) type(toJSON(0)) type(toJSON(1)) type(toJSON(1.0)) type(toJSON(array)) type(toJSON(f64)) type(toJSON(false)) type(toJSON(foo)) type(toJSON(i)) type(toJSON(list)) type(toJSON(median(i))) type(toJSON(nil)) type(toJSON(ok)) type(toJSON(str)) type(toJSON(true)) type(toPairs($env)) type(trim(str)) type(trimPrefix(str)) type(trimSuffix(str)) type(true != $env) type(true != nil) type(true != ok) type(true && $env) type(true && ok) type(true && true) type(true == $env) type(true == false) type(true == ok) type(true == true) type(true ? $env : add) type(true ? foo : 1) type(true ? greet : 1.0) type(true ?: 1) type(true ?? 0) type(true ?? 1) type(true ?? 1.0) type(true ?? array) type(true ?? foo) type(true and false) type(true or $env) type(true or false) type(true or ok) type(true || $env) type(true || false) type(true || true) type(true) < foo?.String() type(true) <= str type(true) in foo type(true) not in [add, false] type(true) | greet() type(type($env)) type(type($env.foo)) type(type(0)) type(type(1)) type(type(1.0)) type(type(add)) type(type(array)) type(type(f64)) type(type(false)) type(type(foo)) type(type(greet)) type(type(i)) type(type(list)) type(type(nil)) type(type(ok)) type(type(str)) type(type(true)) type(uniq(array)) type(uniq(list)) type(upper(str)) type(values($env)) type({foo: $env}) type({foo: $env}?.ok) type({foo: -0}) type({foo: 0, foo: 1.0}) type({foo: 0, foo: add}) type({foo: 0, foo: false}) type({foo: 0, foo: foo}) type({foo: 0, foo: i}) type({foo: 0}) type({foo: 0}.greet) type({foo: 1, foo: str}) type({foo: 1.0, foo: $env}) type({foo: 1.0, foo: greet, foo: ok}) type({foo: 1.0, foo: greet}) type({foo: 1.0}) type({foo: 1}) type({foo: add}) type({foo: array, foo: array | reduce(#, i)}) type({foo: array, foo: foo}) type({foo: array}) type({foo: f64, foo: $env}) type({foo: f64, foo: add}) type({foo: f64, foo: true}) type({foo: f64}) type({foo: false, foo: 1.0}) type({foo: false, foo: foo}) type({foo: false, foo: nil}) type({foo: false}) type({foo: foo, foo: $env}) type({foo: foo, foo: 1}) type({foo: foo, foo: foo}) type({foo: foo, foo: i}) type({foo: foo, foo: list}) type({foo: foo}) type({foo: foo}.Bar) type({foo: greet, foo: i}) type({foo: greet}) type({foo: i, foo: ok}) type({foo: i}) type({foo: list}) type({foo: nil}) type({foo: ok, foo: 0}) type({foo: ok}) type({foo: str, foo: str}) type({foo: str}) type({foo: toJSON(foo)}) type({foo: true}) uniq($env | filter(false)) uniq($env | map(#index)) uniq($env | map(0)) uniq($env | map(1.0)) uniq($env | map(add)) uniq($env | map(f64)) uniq($env | map(foo)) uniq($env | map(ok)) uniq($env | map(str)) uniq($env | reduce(array, foo)) uniq($env.array) uniq($env.list) uniq($env?.array) uniq($env?.list) uniq($env?.list[i:]) uniq(0 .. 0) uniq(0 .. i) uniq(1 .. 0) uniq([$env, add]) uniq([$env]) uniq([0, 1.0]) uniq([0]) uniq([1 == nil]) uniq([1.0, $env, foo]) uniq([1.0, $env]) uniq([1.0, array]) uniq([1.0, ok]) uniq([1.0, str]) uniq([1.0]) uniq([1]) uniq([add, 1.0]) uniq([add]) uniq([array, true]) uniq([array]) uniq([f64]) uniq([false, str]) uniq([false, true]) uniq([false]) uniq([foo, foo]) uniq([foo]) uniq([greet, $env]) uniq([greet]) uniq([i]) uniq([list]) uniq([nil, $env]) uniq([nil, nil]) uniq([nil]) uniq([ok]) uniq([str, 1.0]) uniq([str, true]) uniq([str]) uniq([true, $env]) uniq([true, true]) uniq([true]) uniq(array ?? 0) uniq(array ?? 1) uniq(array ?? 1.0) uniq(array ?? add) uniq(array ?? false) uniq(array ?? i) uniq(array ?? list) uniq(array | filter(ok)) uniq(array | map(#)) uniq(array | map(1.0)) uniq(array | sortBy(#)) uniq(array | sortBy(1)) uniq(array) uniq(array) != array uniq(array) == array uniq(array) | all(ok) uniq(array) | count(false) uniq(array) | filter(false) uniq(array) | filter(true) uniq(array) | groupBy(1) uniq(array) | groupBy(1.0) uniq(array) | groupBy(ok) uniq(array) | map(1) uniq(array) | map(add) uniq(array) | map(true) uniq(array) | min(i) uniq(array) | one(false) uniq(array) | reduce(#) uniq(array) | reduce(1.0) uniq(array) | reduce(false) uniq(array) | reduce(foo) uniq(array) | reduce(greet) uniq(array) | reduce(i) uniq(array) | sortBy(#) uniq(array) | sortBy(1) uniq(array) | sum(#) uniq(array); str uniq(array)?.[i] uniq(array)[:] uniq(array)[:i] uniq(array)[i:] uniq(array[1:i]) uniq(array[:1]) uniq(array[:]) uniq(array[:i]) uniq(concat(array)) uniq(concat(list)) uniq(false ? 0 : array) uniq(filter(array, ok)) uniq(filter(array, true)) uniq(filter(list, false)) uniq(flatten(array)) uniq(flatten(list)) uniq(keys($env)) uniq(list ?? 1.0) uniq(list ?? f64) uniq(list ?? false) uniq(list ?? foo | map(#)) uniq(list ?? foo) uniq(list ?? str) uniq(list ?? true) uniq(list | map(#)) uniq(list | map(.String)) uniq(list | map(1.0)) uniq(list | map(add)) uniq(list | map(false)) uniq(list | map(foo)) uniq(list | map(greet)) uniq(list | reduce(list)) uniq(list | sortBy(#.Bar)) uniq(list | sortBy(1.0)) uniq(list) uniq(list) != array uniq(list) ?? ok uniq(list) | all(false) uniq(list) | all(true) uniq(list) | find(false) uniq(list) | findIndex(false) uniq(list) | findLast(false) uniq(list) | groupBy(#) uniq(list) | groupBy(1.0) uniq(list) | groupBy(i) uniq(list) | groupBy(ok) uniq(list) | map(#) uniq(list) | map(.String) uniq(list) | map(false) uniq(list) | map(greet) uniq(list) | one(true) uniq(list) | reduce(#.String) uniq(list) | reduce(foo, foo) uniq(list) | reduce(ok) uniq(list) | reduce(true, 1.0) uniq(list) | sortBy(0) uniq(list) | sortBy(1) uniq(list) | sum(0) uniq(list)?.[i] uniq(list)[$env.i:] uniq(list[1:]) uniq(list[:i]) uniq(list[i:]) uniq(map($env, 1.0)) uniq(map($env, array)) uniq(map($env, foo)) uniq(map($env, i)) uniq(map($env, list)) uniq(map($env, ok)) uniq(map($env, str)) uniq(map($env, true)) uniq(map(array, #)) uniq(map(array, 1.0)) uniq(map(array, array)) uniq(map(array, greet)) uniq(map(array, i)) uniq(map(array, ok)) uniq(map(list, #)) uniq(map(list, f64)) uniq(map(list, ok)) uniq(reduce(array, array)) uniq(reverse(array)) uniq(reverse(list)) uniq(sort($env)) uniq(sort(array)) uniq(sortBy(array, #)) uniq(sortBy(array, 0)) uniq(sortBy(list, #.Bar)) uniq(sortBy(list, 1)) uniq(sortBy(list, 1.0)) uniq(toPairs($env)) uniq(uniq(array)) uniq(uniq(list)) uniq(values($env)) upper($env | reduce(str, nil)) upper($env.str) upper($env?.[str]) upper($env?.str) upper(array | reduce(str, list)) upper(foo.Bar) upper(foo.Bar) > str upper(foo.Bar) ?? add upper(foo.String()) upper(foo?.Bar) upper(foo?.String()) upper(greet(str)) upper(list | reduce(#.Bar)) upper(list?.[i]?.Bar) upper(lower(str)) upper(nil ?? $env?.str) upper(reduce(array, str)) upper(str ?? 0) upper(str ?? 1.0) upper(str ?? array) upper(str ?? greet) upper(str ?? list) upper(str | greet()) upper(str) upper(str) <= string($env) upper(str) ?? add upper(str) in foo upper(str) matches str upper(str) not contains str upper(str) not endsWith str upper(str) not in foo upper(str) | greet() upper(str[1:]) upper(str[:0]) upper(str[i:]) upper(string($env)) upper(string(0)) upper(string(1)) upper(string(1.0)) upper(string(add)) upper(string(array)) upper(string(f64)) upper(string(foo)) upper(string(foo.Bar)) upper(string(greet)) upper(string(i)) upper(string(list)) upper(string(nil)) upper(string(ok)) upper(string(str)) upper(string(true)) upper(toBase64(str)) upper(toJSON(0)) upper(toJSON(1)) upper(toJSON(1.0)) upper(toJSON(array)) upper(toJSON(f64)) upper(toJSON(false)) upper(toJSON(foo)) upper(toJSON(i)) upper(toJSON(list)) upper(toJSON(nil)) upper(toJSON(ok)) upper(toJSON(reduce(list, ok))) upper(toJSON(str)) upper(toJSON(true)) upper(trim(str)) upper(trimPrefix(str)) upper(trimSuffix(str)) upper(type($env)) upper(type(0)) upper(type(1)) upper(type(1.0)) upper(type(add)) upper(type(array)) upper(type(f64)) upper(type(false)) upper(type(foo)) upper(type(foo?.Bar)) upper(type(greet)) upper(type(i)) upper(type(list)) upper(type(nil)) upper(type(ok)) upper(type(str)) upper(type(true)) upper(upper(str)) values($env ?? $env) values($env ?? 0) values($env ?? 1) values($env ?? 1.0) values($env ?? false) values($env ?? foo) values($env ?? greet) values($env ?? ok) values($env ?? true) values($env | reduce($env, 1)) values($env) ?? add values($env) ?? foo values($env) ?? i values($env) | all(ok) values($env) | find(false) values($env) | findIndex(ok) values($env) | findIndex(true) values($env) | findLast(ok) values($env) | findLastIndex(ok) values($env) | groupBy(1) values($env) | groupBy(f64) values($env) | groupBy(foo) values($env) | groupBy(str) values($env) | map(#) values($env) | map(1.0) values($env) | map(add) values($env) | map(f64) values($env) | map(foo) values($env) | map(greet) values($env) | one(true) values($env) | reduce(#) values($env) | reduce(#index) values($env) | reduce(1) values($env) | reduce(1.0, 0) values($env) | reduce(add, nil) values($env) | reduce(array) values($env) | reduce(foo, nil) values($env) | reduce(i) values($env) | sortBy(i) values($env) | sum(1) values($env) | sum(1.0) values($env)?.[i] values(array | groupBy(#)) values(array | groupBy(0)) values(array | groupBy(1)) values(array | groupBy(false)) values(false ? add : $env) values(groupBy(array, 0)) values(groupBy(array, 1.0)) values(groupBy(array, foo)) values(groupBy(array, ok)) values(groupBy(list, #)) values(groupBy(list, 1.0)) values(groupBy(list, f64)) values(groupBy(list, false)) values(groupBy(list, ok)) values(if ok { $env } else { str }) values(list | groupBy(#)) values(list | groupBy(.Bar)) values(list | groupBy(false)) values(max($env)) values(min($env)) values(nil ?? $env) values(ok ? $env : nil) values(reduce(array, $env)) values(reduce(list, $env)) values({foo: $env}) values({foo: $env}?.foo) values({foo: 0, foo: 0}) values({foo: 0}) values({foo: 1, foo: 0}) values({foo: 1.0 * 0}) values({foo: 1.0, foo: 1.0}) values({foo: 1.0, foo: f64}) values({foo: 1.0}) values({foo: 1}) values({foo: add, foo: i}) values({foo: array, foo: foo}) values({foo: array, foo: nil, foo: foo}) values({foo: array}) values({foo: f64}) values({foo: false, foo: false}) values({foo: false}) values({foo: foo, foo: list}) values({foo: foo}) values({foo: greet, foo: 0}) values({foo: greet, foo: 1.0, foo: false}) values({foo: greet, foo: foo}) values({foo: greet}) values({foo: i, foo: true}) values({foo: i}) values({foo: last($env)}) values({foo: list}) values({foo: nil, foo: list}) values({foo: nil, foo: ok}) values({foo: nil}) values({foo: ok, foo: $env}) values({foo: ok, foo: 1.0}) values({foo: ok, foo: list}) values({foo: ok}) values({foo: str}) values({foo: true, foo: 1.0}) values({foo: true, foo: false}) values({foo: true}) {foo: !false} {foo: !ok, foo: greet} {foo: !ok} {foo: !true, foo: greet} {foo: !true} {foo: $env != $env} {foo: $env != $env}.f64 {foo: $env != 0} {foo: $env != 1.0} {foo: $env != 1} {foo: $env != add} {foo: $env != array} {foo: $env != f64, foo: foo} {foo: $env != false} {foo: $env != foo} {foo: $env != greet} {foo: $env != greet}.Bar {foo: $env != i} {foo: $env != list} {foo: $env != nil, foo: array} {foo: $env != nil} {foo: $env != ok} {foo: $env != str} {foo: $env && false} {foo: $env && true} {foo: $env == $env} {foo: $env == 0} {foo: $env == 0}.array {foo: $env == 1.0} {foo: $env == 1} {foo: $env == 1}?.greet {foo: $env == add} {foo: $env == array} {foo: $env == f64} {foo: $env == false} {foo: $env == foo} {foo: $env == foo}.i {foo: $env == greet} {foo: $env == i} {foo: $env == list} {foo: $env == nil} {foo: $env == ok} {foo: $env == str} {foo: $env == true} {foo: $env ?? $env} {foo: $env ?? 1, foo: list} {foo: $env ?? 1.0} {foo: $env ?? 1} {foo: $env ?? array} {foo: $env ?? f64} {foo: $env ?? f64}.Bar {foo: $env ?? foo} {foo: $env ?? greet} {foo: $env ?? i} {foo: $env ?? list} {foo: $env ?? nil} {foo: $env ?? str} {foo: $env and false} {foo: $env and true} {foo: $env in array} {foo: $env in list} {foo: $env not in list} {foo: $env or false} {foo: $env or true} {foo: $env | all(ok)} {foo: $env | any(ok)} {foo: $env | any(true)} {foo: $env | find(false)} {foo: $env | map(#index)} {foo: $env | map($env)} {foo: $env | map(0)} {foo: $env | map(1)} {foo: $env | map(add), foo: i} {foo: $env | map(add)} {foo: $env | map(f64)} {foo: $env | map(foo)} {foo: $env | map(i)} {foo: $env | map(list)} {foo: $env | none(false)} {foo: $env | none(true)} {foo: $env | one(true)} {foo: $env | reduce($env, foo)}?.f64 {foo: $env | reduce(1, $env)} {foo: $env | reduce(foo, 1.0)} {foo: $env | reduce(greet, i)} {foo: $env | sum(0)} {foo: $env | sum(1.0)} {foo: $env || false} {foo: $env || true} {foo: $env, foo: $env, foo: true}?.add {foo: $env, foo: $env}.Bar {foo: $env, foo: $env}.String {foo: $env, foo: $env}.add {foo: $env, foo: $env}.array {foo: $env, foo: $env}.f64 {foo: $env, foo: $env}.foo {foo: $env, foo: $env}.greet {foo: $env, foo: $env}.i {foo: $env, foo: $env}.i?.[ok] {foo: $env, foo: $env}.ok {foo: $env, foo: $env}.str {foo: $env, foo: $env}?.String {foo: $env, foo: $env}?.[str] {foo: $env, foo: $env}?.add {foo: $env, foo: $env}?.array {foo: $env, foo: $env}?.f64 {foo: $env, foo: $env}?.foo {foo: $env, foo: $env}?.foobar {foo: $env, foo: $env}?.greet {foo: $env, foo: $env}?.i {foo: $env, foo: $env}?.list {foo: $env, foo: $env}?.ok {foo: $env, foo: $env}?.str {foo: $env, foo: 0}.Bar {foo: $env, foo: 0}.add {foo: $env, foo: 0}.foo {foo: $env, foo: 0}.greet {foo: $env, foo: 0}.list {foo: $env, foo: 0}.ok {foo: $env, foo: 0}?.Bar {foo: $env, foo: 0}?.false?.ok {foo: $env, foo: 0}?.i {foo: $env, foo: 0}?.list {foo: $env, foo: 1, foo: foo}?.foo {foo: $env, foo: 1.0, foo: foo}.ok {foo: $env, foo: 1.0, foo: greet}.str {foo: $env, foo: 1.0}.Bar {foo: $env, foo: 1.0}.String {foo: $env, foo: 1.0}.add {foo: $env, foo: 1.0}.f64 {foo: $env, foo: 1.0}.foo {foo: $env, foo: 1.0}.greet {foo: $env, foo: 1.0}.i {foo: $env, foo: 1.0}.list {foo: $env, foo: 1.0}.ok {foo: $env, foo: 1.0}.str {foo: $env, foo: 1.0}?.Bar {foo: $env, foo: 1.0}?.array {foo: $env, foo: 1.0}?.foo {foo: $env, foo: 1.0}?.greet {foo: $env, foo: 1.0}?.i {foo: $env, foo: 1.0}?.ok {foo: $env, foo: 1.0}?.str {foo: $env, foo: 1}.Bar {foo: $env, foo: 1}.String {foo: $env, foo: 1}.add {foo: $env, foo: 1}.f64 {foo: $env, foo: 1}.foo {foo: $env, foo: 1}.list {foo: $env, foo: 1}.ok {foo: $env, foo: 1}?.String {foo: $env, foo: 1}?.[str] {foo: $env, foo: 1}?.array {foo: $env, foo: 1}?.f64 {foo: $env, foo: 1}?.greet {foo: $env, foo: 1}?.i {foo: $env, foo: add, foo: $env}?.foo {foo: $env, foo: add}.Bar {foo: $env, foo: add}.foo?.list {foo: $env, foo: add}.i {foo: $env, foo: add}.list {foo: $env, foo: add}.str {foo: $env, foo: add}.str?.array {foo: $env, foo: add}?.Bar {foo: $env, foo: add}?.add {foo: $env, foo: add}?.foo {foo: $env, foo: add}?.list {foo: $env, foo: add}?.ok {foo: $env, foo: array}.array {foo: $env, foo: array}.foo {foo: $env, foo: array}.greet {foo: $env, foo: array}.i {foo: $env, foo: array}.list {foo: $env, foo: array}?.Bar {foo: $env, foo: array}?.array {foo: $env, foo: array}?.f64 {foo: $env, foo: array}?.foo {foo: $env, foo: array}?.greet {foo: $env, foo: array}?.str {foo: $env, foo: f64}.String {foo: $env, foo: f64}.String?.array {foo: $env, foo: f64}.add {foo: $env, foo: f64}.f64 {foo: $env, foo: f64}?.foo {foo: $env, foo: f64}?.i {foo: $env, foo: false, foo: foo}?.str {foo: $env, foo: false, foo: str}.array {foo: $env, foo: false}.add {foo: $env, foo: false}.array {foo: $env, foo: false}.i {foo: $env, foo: false}.list {foo: $env, foo: false}.str {foo: $env, foo: false}?.[str] {foo: $env, foo: false}?.array {foo: $env, foo: false}?.greet {foo: $env, foo: false}?.i {foo: $env, foo: foo, foo: $env}?.greet {foo: $env, foo: foo, foo: foo}?.i {foo: $env, foo: foo, foo: list}.String {foo: $env, foo: foo, foo: nil}.ok {foo: $env, foo: foo, foo: ok}?.ok {foo: $env, foo: foo}.String {foo: $env, foo: foo}.array {foo: $env, foo: foo}.foo {foo: $env, foo: foo}.foobar {foo: $env, foo: foo}.greet {foo: $env, foo: foo}.i {foo: $env, foo: foo}.list {foo: $env, foo: foo}.ok {foo: $env, foo: foo}.str {foo: $env, foo: foo}?.Bar {foo: $env, foo: foo}?.String {foo: $env, foo: foo}?.add {foo: $env, foo: foo}?.array {foo: $env, foo: foo}?.greet {foo: $env, foo: foo}?.i?.[array] {foo: $env, foo: foo}?.list {foo: $env, foo: foo}?.ok {foo: $env, foo: foo}?.str {foo: $env, foo: greet, foo: 0}.greet {foo: $env, foo: greet, foo: foo}.f64 {foo: $env, foo: greet, foo: nil}?.foo {foo: $env, foo: greet}.Bar?.[list]?.greet {foo: $env, foo: greet}.add {foo: $env, foo: greet}.f64 {foo: $env, foo: greet}.foo {foo: $env, foo: greet}.i {foo: $env, foo: greet}.str {foo: $env, foo: greet}?.Bar {foo: $env, foo: greet}?.[str] {foo: $env, foo: greet}?.add {foo: $env, foo: greet}?.f64 {foo: $env, foo: greet}?.greet {foo: $env, foo: greet}?.list {foo: $env, foo: i, foo: nil}.greet {foo: $env, foo: i}.greet {foo: $env, foo: i}?.Bar {foo: $env, foo: i}?.String {foo: $env, foo: i}?.add {foo: $env, foo: i}?.foo {foo: $env, foo: list, foo: 1}?.[str] {foo: $env, foo: list}.Bar {foo: $env, foo: list}.array {foo: $env, foo: list}.greet {foo: $env, foo: list}.ok {foo: $env, foo: list}?.Bar?.greet {foo: $env, foo: list}?.[str] {foo: $env, foo: list}?.add {foo: $env, foo: list}?.array {foo: $env, foo: list}?.greet {foo: $env, foo: list}?.list {foo: $env, foo: list}?.str {foo: $env, foo: nil}.Bar {foo: $env, foo: nil}.String {foo: $env, foo: nil}.array {foo: $env, foo: nil}.foo {foo: $env, foo: nil}.foobar?.i {foo: $env, foo: nil}.greet {foo: $env, foo: nil}.ok {foo: $env, foo: nil}.ok?.ok(ok) {foo: $env, foo: nil}.str {foo: $env, foo: nil}?.[str] {foo: $env, foo: nil}?.add {foo: $env, foo: nil}?.array {foo: $env, foo: nil}?.f64 {foo: $env, foo: nil}?.foobar {foo: $env, foo: nil}?.list {foo: $env, foo: nil}?.ok {foo: $env, foo: nil}?.str {foo: $env, foo: ok}.Bar {foo: $env, foo: ok}.String {foo: $env, foo: ok}.array {foo: $env, foo: ok}.f64 {foo: $env, foo: ok}.i {foo: $env, foo: ok}?.greet {foo: $env, foo: str, foo: f64}?.i {foo: $env, foo: str, foo: nil}?.array {foo: $env, foo: str}.array {foo: $env, foo: str}.f64 {foo: $env, foo: str}.ok {foo: $env, foo: str}?.Bar {foo: $env, foo: str}?.[str] {foo: $env, foo: str}?.f64 {foo: $env, foo: str}?.foo {foo: $env, foo: str}?.greet {foo: $env, foo: str}?.ok {foo: $env, foo: true, foo: 1.0}?.list {foo: $env, foo: true, foo: nil}?.greet {foo: $env, foo: true}.Bar {foo: $env, foo: true}.String?.list {foo: $env, foo: true}.array {foo: $env, foo: true}.foo {foo: $env, foo: true}.foobar {foo: $env, foo: true}.list {foo: $env, foo: true}.ok {foo: $env, foo: true}.str?.list {foo: $env, foo: true}?.String {foo: $env, foo: true}?.[str] {foo: $env, foo: true}?.array {foo: $env, foo: true}?.greet {foo: $env, foo: true}?.ok {foo: $env.add, foo: $env.ok} {foo: $env.add} {foo: $env.add}.String {foo: $env.add}.array {foo: $env.add}?.[str] {foo: $env.add}?.f64 {foo: $env.array, foo: $env != i}?.str {foo: $env.array, foo: add} {foo: $env.array, foo: greet} {foo: $env.array, foo: {foo: array}} {foo: $env.array} {foo: $env.array}.i {foo: $env.f64, foo: array} {foo: $env.f64, foo: str} {foo: $env.f64} {foo: $env.f64}.foo {foo: $env.f64}?.add {foo: $env.f64}?.array {foo: $env.foo, foo: f64}?.list {foo: $env.foo} {foo: $env.foo}.greet {foo: $env.foo}?.String {foo: $env.greet, foo: array} {foo: $env.greet, foo: i} {foo: $env.greet} {foo: $env.greet}.array {foo: $env.i, foo: add} {foo: $env.i, foo: array} {foo: $env.i, foo: ok != $env} {foo: $env.i} {foo: $env.i}?.str {foo: $env.list != list} {foo: $env.list, foo: 1.0 == 1.0} {foo: $env.list, foo: array} {foo: $env.list} {foo: $env.list}.foo {foo: $env.ok, foo: add} {foo: $env.ok, foo: ok} {foo: $env.ok} {foo: $env.ok}.String {foo: $env.ok}?.str {foo: $env.str} {foo: $env.str}.ok {foo: $env?.$env} {foo: $env?.Bar, foo: array} {foo: $env?.Bar, foo: if false { foo } else { 0 }} {foo: $env?.Bar, foo: ok} {foo: $env?.Bar?.Bar()} {foo: $env?.Bar?.Bar} {foo: $env?.Bar?.[greet]} {foo: $env?.Bar?.greet()} {foo: $env?.Bar?.list} {foo: $env?.Bar} {foo: $env?.Bar}.Bar {foo: $env?.Bar}.String {foo: $env?.Bar}.list {foo: $env?.Bar}?.list {foo: $env?.Bar}?.ok {foo: $env?.Bar}?.str {foo: $env?.String, foo: ok} {foo: $env?.String, foo: str} {foo: $env?.String} {foo: $env?.String}?.ok {foo: $env?.[Bar], foo: f64} {foo: $env?.[Bar], foo: i} {foo: $env?.[Bar], foo: list} {foo: $env?.[Bar], foo: str} {foo: $env?.[Bar]?.Bar} {foo: $env?.[Bar]?.[add]} {foo: $env?.[Bar]} {foo: $env?.[Bar]}?.greet {foo: $env?.[Bar]}?.ok {foo: $env?.[String], foo: $env.greet} {foo: $env?.[String], foo: ok} {foo: $env?.[String]?.array} {foo: $env?.[String]} {foo: $env?.[String]}.f64 {foo: $env?.[String]}.greet {foo: $env?.[foobar]?.add} {foo: $env?.[foobar]?.list} {foo: $env?.[foobar]} {foo: $env?.[foobar]}?.add {foo: $env?.[nil]} {foo: $env?.[str]} {foo: $env?.[str]}.str {foo: $env?.[str]}?.add {foo: $env?.add, foo: add} {foo: $env?.add} {foo: $env?.add}.greet {foo: $env?.add}?.array {foo: $env?.add}?.foo {foo: $env?.add}?.str {foo: $env?.array, foo: add} {foo: $env?.array} {foo: $env?.array}.ok {foo: $env?.array}?.Bar {foo: $env?.f64, foo: add} {foo: $env?.f64} {foo: $env?.f64}.ok?.add {foo: $env?.f64}.str {foo: $env?.f64}?.greet {foo: $env?.false} {foo: $env?.foo.String()} {foo: $env?.foobar, foo: greet} {foo: $env?.foobar} {foo: $env?.foobar}?.list {foo: $env?.foo} {foo: $env?.foo}.f64 {foo: $env?.foo}.str {foo: $env?.foo}?.ok {foo: $env?.greet, foo: first(array)} {foo: $env?.greet, foo: i} {foo: $env?.greet} {foo: $env?.greet}.foo {foo: $env?.greet}?.add {foo: $env?.greet}?.foo {foo: $env?.i, foo: foo?.Bar} {foo: $env?.i, foo: i} {foo: $env?.i, foo: ok} {foo: $env?.i, foo: string(i)} {foo: $env?.i, foo: str} {foo: $env?.i} {foo: $env?.i}.String {foo: $env?.i}?.f64 {foo: $env?.i}?.greet {foo: $env?.list, foo: [1.0]} {foo: $env?.list} {foo: $env?.list}.f64 {foo: $env?.nil?.[add]} {foo: $env?.nil?.[i]} {foo: $env?.nil} {foo: $env?.ok, foo: greet} {foo: $env?.ok} {foo: $env?.ok}.f64 {foo: $env?.ok}?.add {foo: $env?.ok}?.foo {foo: $env?.ok}?.list {foo: $env?.str, foo: $env?.ok} {foo: $env?.str, foo: array} {foo: $env?.str, foo: f64} {foo: $env?.str} {foo: $env?.str}.f64 {foo: $env?.str}?.Bar {foo: $env?.str}?.i {foo: $env?.true} {foo: $env} == nil or false {foo: $env} ?? $env.array {foo: $env} ?? add {foo: $env} ?? list {foo: $env}.Bar {foo: $env}.Bar?.[str] {foo: $env}.Bar?.add {foo: $env}.String {foo: $env}.String?.foo {foo: $env}.add {foo: $env}.add?.String {foo: $env}.add?.[add] {foo: $env}.add?.[array] {foo: $env}.add?.[foo] {foo: $env}.add?.[ok] {foo: $env}.add?.array {foo: $env}.add?.list {foo: $env}.array {foo: $env}.array?.Bar() {foo: $env}.array?.i {foo: $env}.array?.str {foo: $env}.f64 {foo: $env}.f64?.[foo] {foo: $env}.foo {foo: $env}.foo.array {foo: $env}.foo?.foo {foo: $env}.foo?.i {foo: $env}.foobar {foo: $env}.foobar?.[f64] {foo: $env}.foobar?.[list] {foo: $env}.greet {foo: $env}.greet?.Bar {foo: $env}.greet?.[ok] {foo: $env}.i {foo: $env}.i?.add() {foo: $env}.i?.greet() {foo: $env}.list {foo: $env}.list?.[f64] {foo: $env}.list?.greet {foo: $env}.ok {foo: $env}.ok?.[greet] {foo: $env}.ok?.[ok] {foo: $env}.ok?.array {foo: $env}.str {foo: $env}.str?.Bar {foo: $env}.str?.[f64] {foo: $env}.str?.str {foo: $env}?.$env?.Bar(1.0) {foo: $env}?.$env?.add() {foo: $env}?.Bar {foo: $env}?.Bar?.[add] {foo: $env}?.Bar?.foo {foo: $env}?.Bar?.i {foo: $env}?.String {foo: $env}?.String != str {foo: $env}?.String?.[add] {foo: $env}?.String?.[f64] {foo: $env}?.String?.list {foo: $env}?.String?.str() {foo: $env}?.[$env?.Bar] {foo: $env}?.[str] {foo: $env}?.add {foo: $env}?.array {foo: $env}?.array?.Bar(1.0) {foo: $env}?.array?.[array] {foo: $env}?.array?.[greet] {foo: $env}?.array?.[ok] {foo: $env}?.f64 {foo: $env}?.f64?.[f64] {foo: $env}?.foo {foo: $env}?.foo ?? ok {foo: $env}?.foo.Bar {foo: $env}?.foo.f64 {foo: $env}?.foo.ok {foo: $env}?.foobar {foo: $env}?.foobar?.[list]?.[list] {foo: $env}?.foobar?.array {foo: $env}?.foobar?.greet(nil) {foo: $env}?.greet {foo: $env}?.greet?.[f64] {foo: $env}?.greet?.f64 {foo: $env}?.greet?.list() {foo: $env}?.greet?.ok {foo: $env}?.i {foo: $env}?.i?.[array] {foo: $env}?.i?.add {foo: $env}?.list {foo: $env}?.list?.[foo] {foo: $env}?.list?.f64 {foo: $env}?.list?.greet?.[i] {foo: $env}?.list?.i {foo: $env}?.ok {foo: $env}?.ok?.[array]?.ok {foo: $env}?.ok?.[ok] {foo: $env}?.ok?.[str] {foo: $env}?.str {foo: $env}?.str?.[ok] {foo: $env}?.str?.array {foo: $env}?.str?.foo {foo: -$env?.f64} {foo: -0} {foo: -1.0 / i} {foo: -1.0, foo: $env?.f64} {foo: -1.0, foo: i} {foo: -1.0} {foo: -1} {foo: -f64} {foo: -i, foo: !ok} {foo: -i, foo: add} {foo: -i} {foo: -i}.list {foo: 0 != $env.i} {foo: 0 != $env} {foo: 0 != 0} {foo: 0 != 1.0} {foo: 0 != 1} {foo: 0 != f64} {foo: 0 != i} {foo: 0 != nil} {foo: 0 % i} {foo: 0 * 0} {foo: 0 * 1.0} {foo: 0 * 1} {foo: 0 * i} {foo: 0 * i}.add {foo: 0 ** 0} {foo: 0 ** 1} {foo: 0 ** f64} {foo: 0 ** i} {foo: 0 + 0} {foo: 0 + 1.0} {foo: 0 + f64} {foo: 0 - 0} {foo: 0 - 1.0, foo: array} {foo: 0 - 1.0} {foo: 0 - 1} {foo: 0 - f64} {foo: 0 - i} {foo: 0 .. 0} {foo: 0 .. 1} {foo: 0 .. i} {foo: 0 / 0} {foo: 0 / 1.0} {foo: 0 < $env.i} {foo: 0 < 0, foo: i} {foo: 0 < 0} {foo: 0 < 1.0} {foo: 0 < 1.0}?.f64 {foo: 0 < 1} {foo: 0 < f64} {foo: 0 <= 0} {foo: 0 <= 1.0} {foo: 0 <= f64} {foo: 0 == 0} {foo: 0 == 1.0} {foo: 0 == f64} {foo: 0 == i} {foo: 0 == nil} {foo: 0 > 0, foo: ok} {foo: 0 > 1.0} {foo: 0 > 1} {foo: 0 > i} {foo: 0 >= 0} {foo: 0 >= 1} {foo: 0 >= i} {foo: 0 ?? $env?.[ok]} {foo: 0 ?? $env} {foo: 0 ?? array} {foo: 0 ?? foo} {foo: 0 ?? i} {foo: 0 ?? str} {foo: 0 ?? true} {foo: 0 ^ 0} {foo: 0 ^ 1.0} {foo: 0 ^ i} {foo: 0 in array} {foo: 0 | add(i)} {foo: 0 | bitshl(i)} {foo: 0, foo: $env, foo: 1.0}?.greet {foo: 0, foo: $env}.String {foo: 0, foo: $env}.foo {foo: 0, foo: $env}.i {foo: 0, foo: $env}.list {foo: 0, foo: $env}.str {foo: 0, foo: $env}?.String {foo: 0, foo: $env}?.[str] {foo: 0, foo: $env}?.add {foo: 0, foo: $env}?.array {foo: 0, foo: $env}?.f64 {foo: 0, foo: $env}?.greet {foo: 0, foo: $env}?.ok {foo: 0, foo: $env}?.str {foo: 0, foo: 0, foo: false}?.list {foo: 0, foo: 0}.String {foo: 0, foo: 0}.add {foo: 0, foo: 0}.array {foo: 0, foo: 0}.foobar {foo: 0, foo: 0}?.f64 {foo: 0, foo: 0}?.ok {foo: 0, foo: 1, foo: 0} ?? i {foo: 0, foo: 1.0, foo: array}?.i {foo: 0, foo: 1.0, foo: ok}.str {foo: 0, foo: 1.0} ?? ok {foo: 0, foo: 1.0}.Bar {foo: 0, foo: 1.0}.array {foo: 0, foo: 1.0}.ok {foo: 0, foo: 1.0}.str {foo: 0, foo: 1.0}?.[str] {foo: 0, foo: 1.0}?.f64 {foo: 0, foo: 1.0}?.foo {foo: 0, foo: 1.0}?.i {foo: 0, foo: 1.0}?.list {foo: 0, foo: 1.0}?.str {foo: 0, foo: 1.0}?.str?.max(foo)?.ok {foo: 0, foo: 1}.Bar {foo: 0, foo: 1}.add {foo: 0, foo: 1}.array {foo: 0, foo: 1}.foo {foo: 0, foo: 1}.greet {foo: 0, foo: 1}?.add {foo: 0, foo: 1}?.i {foo: 0, foo: 1}?.ok {foo: 0, foo: add}.String?.[greet] {foo: 0, foo: add}.array {foo: 0, foo: add}?.[str] {foo: 0, foo: add}?.foobar {foo: 0, foo: add}?.greet {foo: 0, foo: array}.Bar {foo: 0, foo: array}.array {foo: 0, foo: array}.f64 {foo: 0, foo: array}.greet {foo: 0, foo: array}.list {foo: 0, foo: array}?.foo {foo: 0, foo: array}?.i {foo: 0, foo: array}?.not {foo: 0, foo: f64}.foo {foo: 0, foo: f64}.greet {foo: 0, foo: f64}?.foo {foo: 0, foo: false, foo: 1}.add {foo: 0, foo: false}?.f64 {foo: 0, foo: false}?.foo {foo: 0, foo: false}?.list {foo: 0, foo: false}?.list?.foo {foo: 0, foo: foo, foo: 1}?.String {foo: 0, foo: foo, foo: add}.array {foo: 0, foo: foo, foo: false}?.greet {foo: 0, foo: foo}.Bar {foo: 0, foo: foo}.String {foo: 0, foo: foo}.add {foo: 0, foo: foo}.foo {foo: 0, foo: foo}.foobar {foo: 0, foo: foo}.greet?.add {foo: 0, foo: foo}.i {foo: 0, foo: foo}.str {foo: 0, foo: foo}?.add {foo: 0, foo: foo}?.array {foo: 0, foo: foo}?.f64 {foo: 0, foo: foo}?.foo {foo: 0, foo: foo}?.ok {foo: 0, foo: greet, foo: i}?.array {foo: 0, foo: greet}.f64 {foo: 0, foo: greet}.foobar {foo: 0, foo: greet}.greet {foo: 0, foo: greet}.ok {foo: 0, foo: greet}?.add {foo: 0, foo: greet}?.greet {foo: 0, foo: greet}?.str {foo: 0, foo: i}.add {foo: 0, foo: i}.array {foo: 0, foo: i}.f64 {foo: 0, foo: i}?.foobar {foo: 0, foo: i}?.str {foo: 0, foo: list}?.Bar {foo: 0, foo: list}?.[str] {foo: 0, foo: list}?.greet {foo: 0, foo: nil, foo: foo}?.add {foo: 0, foo: nil}.Bar {foo: 0, foo: nil}.String?.i() {foo: 0, foo: nil}.array {foo: 0, foo: nil}.greet {foo: 0, foo: nil}.list {foo: 0, foo: nil}.ok {foo: 0, foo: nil}?.Bar {foo: 0, foo: nil}?.String {foo: 0, foo: ok}.add {foo: 0, foo: ok}.array {foo: 0, foo: ok}.f64 {foo: 0, foo: ok}.ok {foo: 0, foo: ok}.str {foo: 0, foo: ok}?.[str] {foo: 0, foo: ok}?.add {foo: 0, foo: ok}?.foo {foo: 0, foo: ok}?.ok {foo: 0, foo: str, foo: f64}.Bar {foo: 0, foo: str}.Bar {foo: 0, foo: str}?.f64 {foo: 0, foo: str}?.foo {foo: 0, foo: str}?.greet {foo: 0, foo: str}?.i {foo: 0, foo: str}?.ok {foo: 0, foo: true, foo: i}.list {foo: 0, foo: true}?.ok {foo: 0, foo: true}?.str {foo: 0..i} {foo: 0.0} {foo: 0.1} {foo: 0} ?? array {foo: 0} ?? list {foo: 0} ?? sum(array) {foo: 0}.Bar {foo: 0}.String {foo: 0}.String?.[f64] {foo: 0}.String?.[i] {foo: 0}.String?.ok() {foo: 0}.add {foo: 0}.array {foo: 0}.array?.ok {foo: 0}.f64 {foo: 0}.foo {foo: 0}.greet {foo: 0}.greet?.String {foo: 0}.greet?.[list] {foo: 0}.i {foo: 0}.i?.foo(nil) {foo: 0}.list {foo: 0}.list?.[add] {foo: 0}.list?.[foo].String {foo: 0}.nil?.[add] {foo: 0}.ok {foo: 0}.ok?.[array] {foo: 0}.ok?.f64 {foo: 0}.ok?.foo?.[i] {foo: 0}.str {foo: 0}.str?.String {foo: 0}.str?.[add]?.[add] {foo: 0}?.Bar {foo: 0}?.Bar?.foo {foo: 0}?.String {foo: 0}?.[str] {foo: 0}?.add {foo: 0}?.add?.ok {foo: 0}?.array {foo: 0}?.array?.[i] {foo: 0}?.f64 {foo: 0}?.foo {foo: 0}?.foobar {foo: 0}?.foobar == foo {foo: 0}?.foobar?.[array] {foo: 0}?.greet {foo: 0}?.i {foo: 0}?.list {foo: 0}?.ok {foo: 0}?.ok?.[str] {foo: 0}?.str {foo: 0}?.str?.Bar {foo: 0}?.str?.str {foo: 1 != $env} {foo: 1 != 0} {foo: 1 != 1.0} {foo: 1 != 1} {foo: 1 != f64} {foo: 1 != f64}.f64 {foo: 1 != i} {foo: 1 != nil} {foo: 1 % 1} {foo: 1 * 0} {foo: 1 * 1.0} {foo: 1 * 1} {foo: 1 * f64} {foo: 1 * i} {foo: 1 ** 0} {foo: 1 ** 1.0} {foo: 1 ** 1.0}.f64 {foo: 1 ** 1.0}.i {foo: 1 ** 1.0}?.[str] {foo: 1 ** 1} {foo: 1 ** f64} {foo: 1 ** i} {foo: 1 + 0} {foo: 1 + 1.0} {foo: 1 + 1} {foo: 1 + f64} {foo: 1 + i} {foo: 1 - 0} {foo: 1 - 1.0} {foo: 1 - 1} {foo: 1 - f64} {foo: 1 - i} {foo: 1 .. 0} {foo: 1 .. i} {foo: 1 / 0}?.String {foo: 1 / 1.0} {foo: 1 / 1} {foo: 1 / f64} {foo: 1 / i} {foo: 1 < 1.0} {foo: 1 < 1} {foo: 1 < f64} {foo: 1 < i} {foo: 1 <= 0} {foo: 1 <= 1.0} {foo: 1 <= 1} {foo: 1 <= f64, foo: array} {foo: 1 == $env} {foo: 1 == 0} {foo: 1 == 1.0} {foo: 1 == 1} {foo: 1 == f64} {foo: 1 == nil} {foo: 1 > 0} {foo: 1 > 1.0} {foo: 1 > 1} {foo: 1 > i} {foo: 1 >= 1.0} {foo: 1 >= 1} {foo: 1 >= f64} {foo: 1 >= i} {foo: 1 ?? $env, foo: str} {foo: 1 ?? $env} {foo: 1 ?? 1} {foo: 1 ?? greet} {foo: 1 ?? list} {foo: 1 ?? nil} {foo: 1 ?? ok} {foo: 1 ?? str} {foo: 1 ^ 0} {foo: 1 ^ 1.0} {foo: 1 ^ f64} {foo: 1 in array} {foo: 1 not in $env?.array} {foo: 1 | bitand(i)} {foo: 1, foo: $env, foo: add}?.ok {foo: 1, foo: $env}.Bar {foo: 1, foo: $env}.String {foo: 1, foo: $env}.array {foo: 1, foo: $env}.greet {foo: 1, foo: $env}.i {foo: 1, foo: $env}.list {foo: 1, foo: $env}.str {foo: 1, foo: $env}?.f64 {foo: 1, foo: $env}?.greet {foo: 1, foo: $env}?.str {foo: 1, foo: 0, foo: add}?.array {foo: 1, foo: 0} ?? foo?.Bar {foo: 1, foo: 0}.add {foo: 1, foo: 0}.f64 {foo: 1, foo: 0}.foo {foo: 1, foo: 0}.greet {foo: 1, foo: 0}.list {foo: 1, foo: 0}?.list {foo: 1, foo: 0}?.ok {foo: 1, foo: 1.0}.String {foo: 1, foo: 1.0}.f64 {foo: 1, foo: 1.0}.i {foo: 1, foo: 1.0}?.Bar {foo: 1, foo: 1.0}?.add {foo: 1, foo: 1.0}?.foobar {foo: 1, foo: 1.0}?.greet {foo: 1, foo: 1.0}?.str?.array() {foo: 1, foo: 1}.f64 {foo: 1, foo: 1}.greet {foo: 1, foo: 1}?.f64 {foo: 1, foo: 1}?.ok {foo: 1, foo: add, foo: 1.0}?.Bar {foo: 1, foo: add}.Bar {foo: 1, foo: add}.array {foo: 1, foo: add}.greet {foo: 1, foo: add}.i {foo: 1, foo: add}?.Bar {foo: 1, foo: add}?.i {foo: 1, foo: add}?.list {foo: 1, foo: array}?.String {foo: 1, foo: array}?.add {foo: 1, foo: array}?.i {foo: 1, foo: array}?.ok {foo: 1, foo: f64}.Bar {foo: 1, foo: f64}.array {foo: 1, foo: f64}.foo {foo: 1, foo: f64}.greet {foo: 1, foo: f64}?.f64 {foo: 1, foo: f64}?.i {foo: 1, foo: false}.array {foo: 1, foo: false}.f64 {foo: 1, foo: false}.foo {foo: 1, foo: false}.foobar?.foo() {foo: 1, foo: false}?.add {foo: 1, foo: false}?.f64 {foo: 1, foo: false}?.f64?.[f64] {foo: 1, foo: false}?.ok {foo: 1, foo: foo, foo: $env}?.[str] {foo: 1, foo: foo, foo: 1.0}.list {foo: 1, foo: foo, foo: nil}.foo {foo: 1, foo: foo}.Bar {foo: 1, foo: foo}.f64 {foo: 1, foo: foo}.foo {foo: 1, foo: foo}?.[str] {foo: 1, foo: foo}?.[str]?.greet {foo: 1, foo: foo}?.f64 {foo: 1, foo: foo}?.foo {foo: 1, foo: foo}?.foobar {foo: 1, foo: foo}?.greet {foo: 1, foo: foo}?.list {foo: 1, foo: greet, foo: 0}?.add {foo: 1, foo: greet, foo: i}.foobar {foo: 1, foo: greet, foo: list}?.ok {foo: 1, foo: greet}.String {foo: 1, foo: greet}.greet {foo: 1, foo: greet}.i {foo: 1, foo: greet}.ok?.String {foo: 1, foo: greet}?.[str] {foo: 1, foo: greet}?.add {foo: 1, foo: greet}?.array {foo: 1, foo: greet}?.greet {foo: 1, foo: i, foo: list}?.[str] {foo: 1, foo: i}.String {foo: 1, foo: i}?.greet {foo: 1, foo: list} ?? i {foo: 1, foo: list}.f64 {foo: 1, foo: list}.foo {foo: 1, foo: list}.list {foo: 1, foo: list}.str {foo: 1, foo: list}?.Bar {foo: 1, foo: list}?.String {foo: 1, foo: list}?.[str] {foo: 1, foo: list}?.add {foo: 1, foo: list}?.ok {foo: 1, foo: nil, foo: 1}.add {foo: 1, foo: nil, foo: greet}.foo {foo: 1, foo: nil}.add {foo: 1, foo: nil}.i {foo: 1, foo: nil}.list {foo: 1, foo: nil}.ok {foo: 1, foo: nil}?.Bar {foo: 1, foo: nil}?.String {foo: 1, foo: nil}?.[str] {foo: 1, foo: nil}?.add {foo: 1, foo: nil}?.f64 {foo: 1, foo: nil}?.list {foo: 1, foo: nil}?.str {foo: 1, foo: ok}.foo {foo: 1, foo: ok}.list {foo: 1, foo: ok}?.Bar {foo: 1, foo: ok}?.String {foo: 1, foo: ok}?.[str] {foo: 1, foo: ok}?.array {foo: 1, foo: ok}?.ok {foo: 1, foo: ok}?.str {foo: 1, foo: str, foo: 0}.i {foo: 1, foo: str}.f64 {foo: 1, foo: str}.list {foo: 1, foo: str}?.i {foo: 1, foo: str}?.str {foo: 1, foo: true}.String {foo: 1, foo: true}.array {foo: 1, foo: true}.ok {foo: 1.0 != $env?.String} {foo: 1.0 != 0} {foo: 1.0 != 1.0} {foo: 1.0 != 1} {foo: 1.0 != f64} {foo: 1.0 != i} {foo: 1.0 * 1.0} {foo: 1.0 * 1} {foo: 1.0 * f64} {foo: 1.0 * i} {foo: 1.0 * i}?.f64 {foo: 1.0 ** 0} {foo: 1.0 ** 1.0} {foo: 1.0 ** 1} {foo: 1.0 ** f64} {foo: 1.0 ** i} {foo: 1.0 + 1.0} {foo: 1.0 + 1} {foo: 1.0 + f64} {foo: 1.0 + f64}?.f64 {foo: 1.0 + i} {foo: 1.0 - 0} {foo: 1.0 - 1.0} {foo: 1.0 - 1} {foo: 1.0 - f64} {foo: 1.0 - i} {foo: 1.0 / 0} {foo: 1.0 / 1.0} {foo: 1.0 / 1} {foo: 1.0 / f64} {foo: 1.0 / i} {foo: 1.0 < 0} {foo: 1.0 < 1.0} {foo: 1.0 < 1.0}.String {foo: 1.0 < 1} {foo: 1.0 < f64} {foo: 1.0 < i} {foo: 1.0 <= 0} {foo: 1.0 <= 1.0, foo: str} {foo: 1.0 <= 1.0} {foo: 1.0 <= 1} {foo: 1.0 <= f64} {foo: 1.0 <= i} {foo: 1.0 == $env} {foo: 1.0 == 0} {foo: 1.0 == 1.0} {foo: 1.0 == 1} {foo: 1.0 == f64} {foo: 1.0 == f64}.foo {foo: 1.0 == i} {foo: 1.0 == nil} {foo: 1.0 == nil}?.String {foo: 1.0 > 0} {foo: 1.0 > 0}.list {foo: 1.0 > 1.0} {foo: 1.0 > 1} {foo: 1.0 > f64} {foo: 1.0 > f64}.array {foo: 1.0 > i} {foo: 1.0 >= 0} {foo: 1.0 >= 1.0} {foo: 1.0 >= 1} {foo: 1.0 >= f64} {foo: 1.0 >= i, foo: greet} {foo: 1.0 >= i} {foo: 1.0 ?? $env} {foo: 1.0 ?? 0} {foo: 1.0 ?? 1.0, foo: i} {foo: 1.0 ?? 1.0, foo: str} {foo: 1.0 ?? 1.0} {foo: 1.0 ?? 1} {foo: 1.0 ?? f64} {foo: 1.0 ?? foo} {foo: 1.0 ?? i} {foo: 1.0 ?? list} {foo: 1.0 ?? nil} {foo: 1.0 ?? ok} {foo: 1.0 ?? str} {foo: 1.0 ^ 0} {foo: 1.0 ^ 1.0} {foo: 1.0 ^ 1} {foo: 1.0 ^ i} {foo: 1.0 in array, foo: i} {foo: 1.0 in array} {foo: 1.0 not in array} {foo: 1.0 | max(1.0)} {foo: 1.0 | median(f64)} {foo: 1.0 | min(1)} {foo: 1.0, foo: $env, foo: foo}.f64 {foo: 1.0, foo: $env, foo: foo}.greet {foo: 1.0, foo: $env, foo: str}?.i?.[add] {foo: 1.0, foo: $env}.add {foo: 1.0, foo: $env}.array {foo: 1.0, foo: $env}.f64 {foo: 1.0, foo: $env}.foo {foo: 1.0, foo: $env}.foobar {foo: 1.0, foo: $env}.greet {foo: 1.0, foo: $env}.i {foo: 1.0, foo: $env}.ok {foo: 1.0, foo: $env}?.Bar {foo: 1.0, foo: $env}?.String {foo: 1.0, foo: $env}?.add {foo: 1.0, foo: $env}?.array {foo: 1.0, foo: $env}?.f64 {foo: 1.0, foo: $env}?.greet {foo: 1.0, foo: $env}?.list {foo: 1.0, foo: $env}?.ok {foo: 1.0, foo: 0, foo: $env}?.i {foo: 1.0, foo: 0, foo: 0}?.array {foo: 1.0, foo: 0, foo: array}.String {foo: 1.0, foo: 0}.Bar {foo: 1.0, foo: 0}.String {foo: 1.0, foo: 0}.String?.String {foo: 1.0, foo: 0}.i {foo: 1.0, foo: 0}.list {foo: 1.0, foo: 0}?.[str] {foo: 1.0, foo: 0}?.f64 {foo: 1.0, foo: 0}?.foo {foo: 1.0, foo: 0}?.str {foo: 1.0, foo: 1.0}.Bar {foo: 1.0, foo: 1.0}.add {foo: 1.0, foo: 1.0}.array {foo: 1.0, foo: 1.0}.f64 {foo: 1.0, foo: 1.0}.foo {foo: 1.0, foo: 1.0}.greet {foo: 1.0, foo: 1.0}.i {foo: 1.0, foo: 1.0}.list {foo: 1.0, foo: 1.0}.ok {foo: 1.0, foo: 1.0}.str {foo: 1.0, foo: 1.0}?.[str] {foo: 1.0, foo: 1.0}?.add {foo: 1.0, foo: 1.0}?.array {foo: 1.0, foo: 1.0}?.f64 {foo: 1.0, foo: 1.0}?.greet {foo: 1.0, foo: 1.0}?.i {foo: 1.0, foo: 1.0}?.ok {foo: 1.0, foo: 1}.add {foo: 1.0, foo: 1}.array {foo: 1.0, foo: 1}.foo {foo: 1.0, foo: 1}.list {foo: 1.0, foo: 1}?.Bar {foo: 1.0, foo: 1}?.String {foo: 1.0, foo: 1}?.[str] {foo: 1.0, foo: 1}?.add {foo: 1.0, foo: 1}?.foo {foo: 1.0, foo: 1}?.greet {foo: 1.0, foo: 1}?.i {foo: 1.0, foo: 1}?.list {foo: 1.0, foo: 1}?.ok {foo: 1.0, foo: add}.Bar {foo: 1.0, foo: add}.add {foo: 1.0, foo: add}?.String {foo: 1.0, foo: add}?.f64 {foo: 1.0, foo: add}?.f64?.str?.[array] {foo: 1.0, foo: add}?.greet {foo: 1.0, foo: add}?.list {foo: 1.0, foo: add}?.ok {foo: 1.0, foo: add}?.str {foo: 1.0, foo: array}.foo {foo: 1.0, foo: array}.greet {foo: 1.0, foo: array}.list {foo: 1.0, foo: array}.str {foo: 1.0, foo: array}?.Bar {foo: 1.0, foo: array}?.[str] {foo: 1.0, foo: array}?.add {foo: 1.0, foo: array}?.f64 {foo: 1.0, foo: array}?.list {foo: 1.0, foo: f64}.add {foo: 1.0, foo: f64}.foobar {foo: 1.0, foo: f64}.greet {foo: 1.0, foo: f64}.i {foo: 1.0, foo: f64}.list {foo: 1.0, foo: f64}.ok {foo: 1.0, foo: f64}.str {foo: 1.0, foo: f64}?.add {foo: 1.0, foo: f64}?.greet {foo: 1.0, foo: false, foo: $env}?.ok {foo: 1.0, foo: false, foo: 1.0}?.greet {foo: 1.0, foo: false}.String {foo: 1.0, foo: false}.array {foo: 1.0, foo: false}.array?.add {foo: 1.0, foo: false}.i {foo: 1.0, foo: false}.str {foo: 1.0, foo: false}?.[str] {foo: 1.0, foo: false}?.array {foo: 1.0, foo: false}?.list {foo: 1.0, foo: foo, foo: 1}.add {foo: 1.0, foo: foo, foo: foo}?.list {foo: 1.0, foo: foo, foo: list}?.f64 {foo: 1.0, foo: foo, foo: true}.Bar {foo: 1.0, foo: foo}.Bar {foo: 1.0, foo: foo}.array {foo: 1.0, foo: foo}.f64 {foo: 1.0, foo: foo}.f64?.[ok] {foo: 1.0, foo: foo}.foo {foo: 1.0, foo: foo}.greet {foo: 1.0, foo: foo}.list {foo: 1.0, foo: foo}.ok {foo: 1.0, foo: foo}.str {foo: 1.0, foo: foo}?.Bar {foo: 1.0, foo: foo}?.String {foo: 1.0, foo: foo}?.add {foo: 1.0, foo: foo}?.f64 {foo: 1.0, foo: foo}?.foo {foo: 1.0, foo: foo}?.greet {foo: 1.0, foo: foo}?.i {foo: 1.0, foo: foo}?.list {foo: 1.0, foo: foo}?.ok {foo: 1.0, foo: greet}.Bar {foo: 1.0, foo: greet}.array {foo: 1.0, foo: greet}.f64 {foo: 1.0, foo: greet}.i {foo: 1.0, foo: greet}.list {foo: 1.0, foo: greet}.ok {foo: 1.0, foo: greet}?.[str] {foo: 1.0, foo: greet}?.array {foo: 1.0, foo: greet}?.foo {foo: 1.0, foo: greet}?.greet {foo: 1.0, foo: greet}?.i?.[i] {foo: 1.0, foo: greet}?.ok {foo: 1.0, foo: greet}?.str {foo: 1.0, foo: i} ?? f64 {foo: 1.0, foo: i}.Bar {foo: 1.0, foo: i}.String {foo: 1.0, foo: i}.add {foo: 1.0, foo: i}.f64 {foo: 1.0, foo: i}.ok {foo: 1.0, foo: i}?.Bar {foo: 1.0, foo: i}?.String {foo: 1.0, foo: i}?.add {foo: 1.0, foo: i}?.f64 {foo: 1.0, foo: i}?.foobar {foo: 1.0, foo: i}?.greet {foo: 1.0, foo: i}?.i {foo: 1.0, foo: i}?.ok {foo: 1.0, foo: list}.f64 {foo: 1.0, foo: list}.foobar {foo: 1.0, foo: list}.i {foo: 1.0, foo: list}.list {foo: 1.0, foo: list}.ok {foo: 1.0, foo: list}?.String {foo: 1.0, foo: list}?.array {foo: 1.0, foo: list}?.ok {foo: 1.0, foo: nil}.Bar {foo: 1.0, foo: nil}.String {foo: 1.0, foo: nil}.add {foo: 1.0, foo: nil}.array {foo: 1.0, foo: nil}.foo {foo: 1.0, foo: nil}.greet {foo: 1.0, foo: nil}.i {foo: 1.0, foo: nil}.ok {foo: 1.0, foo: nil}?.Bar {foo: 1.0, foo: nil}?.Bar?.list {foo: 1.0, foo: nil}?.String {foo: 1.0, foo: nil}?.[str] {foo: 1.0, foo: nil}?.add {foo: 1.0, foo: nil}?.array {foo: 1.0, foo: nil}?.f64 {foo: 1.0, foo: nil}?.foo {foo: 1.0, foo: nil}?.foobar {foo: 1.0, foo: nil}?.greet {foo: 1.0, foo: nil}?.str {foo: 1.0, foo: ok, foo: str}.f64 {foo: 1.0, foo: ok}.String {foo: 1.0, foo: ok}.add {foo: 1.0, foo: ok}.f64 {foo: 1.0, foo: ok}.greet {foo: 1.0, foo: ok}.i {foo: 1.0, foo: ok}.str {foo: 1.0, foo: ok}?.String {foo: 1.0, foo: ok}?.[str] {foo: 1.0, foo: ok}?.f64 {foo: 1.0, foo: ok}?.greet {foo: 1.0, foo: ok}?.list {foo: 1.0, foo: ok}?.list?.ok {foo: 1.0, foo: ok}?.str {foo: 1.0, foo: str, foo: 1} != true ?? add {foo: 1.0, foo: str, foo: str}.list {foo: 1.0, foo: str}.array {foo: 1.0, foo: str}.str {foo: 1.0, foo: str}?.String {foo: 1.0, foo: str}?.f64 {foo: 1.0, foo: str}?.greet {foo: 1.0, foo: str}?.i {foo: 1.0, foo: str}?.str {foo: 1.0, foo: true, foo: foo}?.Bar {foo: 1.0, foo: true, foo: true}?.[str] {foo: 1.0, foo: true}.String {foo: 1.0, foo: true}.add {foo: 1.0, foo: true}.greet {foo: 1.0, foo: true}.i {foo: 1.0, foo: true}?.Bar {foo: 1.0, foo: true}?.String {foo: 1.0, foo: true}?.[str] {foo: 1.0, foo: true}?.add {foo: 1.0, foo: true}?.array {foo: 1.0, foo: true}?.f64 {foo: 1.0, foo: true}?.ok {foo: 1.0} {foo: 1.0} ?? foo {foo: 1.0} not in $env?.[String] {foo: 1.0} | get(str) {foo: 1.0}.Bar {foo: 1.0}.Bar?.str {foo: 1.0}.String {foo: 1.0}.String?.[foo] {foo: 1.0}.String?.array {foo: 1.0}.String?.foo {foo: 1.0}.add {foo: 1.0}.add?.Bar {foo: 1.0}.add?.f64 {foo: 1.0}.add?.list {foo: 1.0}.add?.ok {foo: 1.0}.array {foo: 1.0}.array?.array() {foo: 1.0}.f64 {foo: 1.0}.f64?.[add] {foo: 1.0}.f64?.foo {foo: 1.0}.f64?.greet() {foo: 1.0}.foo {foo: 1.0}.foobar {foo: 1.0}.foobar == 1.0 {foo: 1.0}.foobar?.String {foo: 1.0}.foobar?.i {foo: 1.0}.greet {foo: 1.0}.greet?.[ok] {foo: 1.0}.greet?.foo {foo: 1.0}.i {foo: 1.0}.i == ok {foo: 1.0}.i?.[str] {foo: 1.0}.list {foo: 1.0}.list?.[list]?.i {foo: 1.0}.list?.i {foo: 1.0}.ok {foo: 1.0}.ok?.[foo] {foo: 1.0}.ok?.ok() {foo: 1.0}.str {foo: 1.0}.str?.[f64] {foo: 1.0}.str?.[list]?.foo {foo: 1.0}.str?.str {foo: 1.0}?.$env?.String() {foo: 1.0}?.$env?.[add] {foo: 1.0}?.$env?.f64 {foo: 1.0}?.Bar {foo: 1.0}?.Bar?.[greet] {foo: 1.0}?.Bar?.[ok] {foo: 1.0}?.Bar?.add {foo: 1.0}?.Bar?.list(array, ok) {foo: 1.0}?.Bar?.list(foobar) {foo: 1.0}?.String {foo: 1.0}?.String?.[f64] {foo: 1.0}?.String?.[f64].str {foo: 1.0}?.[greet(str)] {foo: 1.0}?.[str] {foo: 1.0}?.add {foo: 1.0}?.add?.[i] {foo: 1.0}?.add?.list {foo: 1.0}?.array {foo: 1.0}?.array?.greet {foo: 1.0}?.array?.ok {foo: 1.0}?.array?.str(foobar) {foo: 1.0}?.f64 {foo: 1.0}?.f64?.[list] {foo: 1.0}?.f64?.foo {foo: 1.0}?.false?.[list] {foo: 1.0}?.foo {foo: 1.0}?.foobar {foo: 1.0}?.foobar?.String {foo: 1.0}?.greet {foo: 1.0}?.greet?.array() {foo: 1.0}?.greet?.list {foo: 1.0}?.i {foo: 1.0}?.i?.[foo] {foo: 1.0}?.list {foo: 1.0}?.list?.[i] {foo: 1.0}?.list?.[str] {foo: 1.0}?.not {foo: 1.0}?.ok {foo: 1.0}?.ok?.[ok] {foo: 1.0}?.str {foo: 1} == $env?.[String] {foo: 1} ?? array {foo: 1} ?? ok {foo: 1}.Bar {foo: 1}.Bar?.Bar() {foo: 1}.Bar?.foo?.i {foo: 1}.String {foo: 1}.String?.[array] {foo: 1}.String?.[greet] {foo: 1}.add {foo: 1}.add?.array {foo: 1}.add?.str() {foo: 1}.array {foo: 1}.array?.[list] {foo: 1}.f64 {foo: 1}.foo {foo: 1}.foobar {foo: 1}.greet {foo: 1}.greet?.[list] {foo: 1}.i {foo: 1}.list {foo: 1}.list != add {foo: 1}.list?.foo {foo: 1}.ok {foo: 1}.ok?.add {foo: 1}.ok?.greet {foo: 1}.str {foo: 1}.str?.[f64] {foo: 1}?.Bar {foo: 1}?.String {foo: 1}?.String not startsWith $env {foo: 1}?.String?.Bar {foo: 1}?.String?.[f64] {foo: 1}?.String?.add {foo: 1}?.String?.greet {foo: 1}?.[str] {foo: 1}?.[str] startsWith str {foo: 1}?.[str]?.String {foo: 1}?.add {foo: 1}?.add?.[str] {foo: 1}?.array {foo: 1}?.f64 {foo: 1}?.f64?.String {foo: 1}?.f64?.[ok] {foo: 1}?.foo {foo: 1}?.foobar {foo: 1}?.foobar?.foo.foobar?.[foo] {foo: 1}?.foobar?.greet(add) {foo: 1}?.foobar?.i.array {foo: 1}?.greet {foo: 1}?.i {foo: 1}?.i?.[add] {foo: 1}?.list {foo: 1}?.list?.[ok] {foo: 1}?.nil?.str(nil) {foo: 1}?.ok {foo: 1}?.ok?.str {foo: 1}?.str {foo: 1}?.str?.[i] {foo: 1}?.str?.[ok] {foo: [$env, 1.0]} {foo: [$env, false], foo: f64} {foo: [$env, nil]} {foo: [$env, ok]} {foo: [$env]} {foo: [$env]}?.String {foo: [0 + 0, list]} {foo: [0, 1.0]} {foo: [0]} {foo: [1, 1.0]} {foo: [1.0, $env]} {foo: [1.0, greet, 1.0]} {foo: [1.0], foo: greet} {foo: [1.0]} {foo: [1.0]}?.f64 {foo: [1], foo: foo?.String} {foo: [1]} {foo: [1]}.list {foo: [add, $env]} {foo: [add, 1]} {foo: [add, str]} {foo: [add]} {foo: [array, 1]} {foo: [array, list, foo]} {foo: [array]} {foo: [ceil(f64)]} {foo: [f64]} {foo: [f64]}.array {foo: [false, f64]} {foo: [false]} {foo: [foo, $env]} {foo: [foo, false]} {foo: [foo, i]} {foo: [foo, nil]} {foo: [foo, ok]} {foo: [foo]} {foo: [foo]}?.Bar {foo: [greet, array]} {foo: [greet]} {foo: [greet]}.Bar {foo: [i, 1, array]} {foo: [i, 1]} {foo: [i, str]} {foo: [i], foo: f64} {foo: [i]} {foo: [i]}?.[str] {foo: [list]} {foo: [nil, 1.0]} {foo: [nil, array]} {foo: [nil, nil]} {foo: [nil, true]} {foo: [nil]} {foo: [ok, foo]} {foo: [ok]} {foo: [str, ok]} {foo: [str, true]} {foo: [str]} {foo: [true, add], foo: foo} {foo: [true, false]} {foo: [true, nil]}.i {foo: [true]} {foo: abs(0)} {foo: abs(1)} {foo: abs(1.0)} {foo: abs(1.0)}?.str {foo: abs(f64)} {foo: abs(i)} {foo: add != $env} {foo: add != add} {foo: add != nil, foo: $env.list}.greet {foo: add != nil} {foo: add == $env} {foo: add == add} {foo: add ?? $env} {foo: add ?? 0} {foo: add ?? 1.0} {foo: add ?? add} {foo: add ?? false} {foo: add ?? foo} {foo: add ?? foo}?.list {foo: add ?? i} {foo: add ?? nil} {foo: add ?? str} {foo: add ?? true} {foo: add(1, 0)} {foo: add(i, 0)} {foo: add(i, i)} {foo: add, foo: $env in array} {foo: add, foo: $env.add} {foo: add, foo: $env.f64} {foo: add, foo: $env.i} {foo: add, foo: $env?.foobar} {foo: add, foo: $env?.list} {foo: add, foo: $env}.$env == f64 {foo: add, foo: $env}.Bar {foo: add, foo: $env}.array {foo: add, foo: $env}.f64 {foo: add, foo: $env}.ok {foo: add, foo: $env}?.Bar {foo: add, foo: $env}?.String {foo: add, foo: $env}?.foo {foo: add, foo: $env}?.i {foo: add, foo: $env}?.list {foo: add, foo: $env}?.ok {foo: add, foo: 0, foo: 0}.ok {foo: add, foo: 0, foo: nil}.String {foo: add, foo: 0}.f64 {foo: add, foo: 0}.list {foo: add, foo: 0}?.Bar {foo: add, foo: 0}?.f64 {foo: add, foo: 0}?.i {foo: add, foo: 1 ** i} {foo: add, foo: 1 < f64} {foo: add, foo: 1.0 / 1.0} {foo: add, foo: 1.0 > f64} {foo: add, foo: 1.0}.String {foo: add, foo: 1.0}.f64 {foo: add, foo: 1.0}.greet {foo: add, foo: 1.0}.i {foo: add, foo: 1.0}.list {foo: add, foo: 1.0}.str {foo: add, foo: 1.0}?.Bar {foo: add, foo: 1.0}?.greet {foo: add, foo: 1.0}?.list {foo: add, foo: 1.0}?.ok {foo: add, foo: 1} ?? f64 {foo: add, foo: 1}.Bar {foo: add, foo: 1}.String {foo: add, foo: 1}.add {foo: add, foo: 1}.foo {foo: add, foo: 1}.list {foo: add, foo: 1}?.foo {foo: add, foo: add} {foo: add, foo: add}.String {foo: add, foo: add}.add {foo: add, foo: add}.array {foo: add, foo: add}.foo {foo: add, foo: add}?.f64 {foo: add, foo: add}?.i {foo: add, foo: add}?.list {foo: add, foo: add}?.ok {foo: add, foo: add}?.str {foo: add, foo: array} {foo: add, foo: array}.String {foo: add, foo: array}.i {foo: add, foo: array}?.Bar {foo: add, foo: array}?.array {foo: add, foo: array}?.i?.Bar {foo: add, foo: f64, foo: $env}.foo {foo: add, foo: f64} {foo: add, foo: f64}.array {foo: add, foo: f64}.foo {foo: add, foo: f64}.greet {foo: add, foo: f64}.i {foo: add, foo: f64}.nil?.f64(foobar) {foo: add, foo: f64}?.Bar {foo: add, foo: f64}?.[str] {foo: add, foo: f64}?.greet?.[array] {foo: add, foo: f64}?.list {foo: add, foo: f64}?.ok {foo: add, foo: false}.array {foo: add, foo: false}.foo {foo: add, foo: false}.i {foo: add, foo: false}?.Bar {foo: add, foo: false}?.String {foo: add, foo: false}?.[str] {foo: add, foo: false}?.f64 {foo: add, foo: false}?.list {foo: add, foo: false}?.ok {foo: add, foo: false}?.str {foo: add, foo: foo.String()} {foo: add, foo: foo.String} {foo: add, foo: foo} {foo: add, foo: foo}.array {foo: add, foo: foo}.f64 {foo: add, foo: foo}.foo {foo: add, foo: foo}.greet {foo: add, foo: foo}.ok {foo: add, foo: foo}?.Bar {foo: add, foo: foo}?.add {foo: add, foo: foo}?.array {foo: add, foo: foo}?.f64 {foo: add, foo: foo}?.foo {foo: add, foo: foo}?.i {foo: add, foo: foo}?.list {foo: add, foo: foo}?.ok {foo: add, foo: greet} {foo: add, foo: greet}.Bar?.String {foo: add, foo: greet}.String {foo: add, foo: greet}.add {foo: add, foo: greet}.array {foo: add, foo: greet}.greet {foo: add, foo: greet}?.Bar {foo: add, foo: greet}?.f64 {foo: add, foo: greet}?.greet {foo: add, foo: greet}?.str {foo: add, foo: i} {foo: add, foo: i}.array {foo: add, foo: i}.f64 {foo: add, foo: i}.greet {foo: add, foo: i}.str {foo: add, foo: i}?.Bar {foo: add, foo: i}?.f64 {foo: add, foo: i}?.str {foo: add, foo: list?.[i]} {foo: add, foo: list} {foo: add, foo: list}.str {foo: add, foo: list}?.Bar {foo: add, foo: list}?.greet {foo: add, foo: list}?.list {foo: add, foo: mean(1.0)} {foo: add, foo: nil, foo: nil}?.f64 {foo: add, foo: nil}.array {foo: add, foo: nil}.foo {foo: add, foo: nil}.greet {foo: add, foo: nil}.str {foo: add, foo: nil}?.Bar {foo: add, foo: nil}?.[str] {foo: add, foo: nil}?.[str]?.str {foo: add, foo: nil}?.add {foo: add, foo: nil}?.f64 {foo: add, foo: nil}?.greet {foo: add, foo: nil}?.list {foo: add, foo: nil}?.ok {foo: add, foo: nil}?.ok?.Bar {foo: add, foo: ok} {foo: add, foo: ok}?.String {foo: add, foo: ok}?.list {foo: add, foo: str} {foo: add, foo: str}.String {foo: add, foo: str}.add {foo: add, foo: str}.foo {foo: add, foo: str}.greet {foo: add, foo: str}?.String {foo: add, foo: str}?.foo {foo: add, foo: str}?.ok {foo: add, foo: str}?.str {foo: add, foo: true}.foo {foo: add, foo: true}.i {foo: add, foo: true}.list {foo: add, foo: true}?.f64 {foo: add, foo: true}?.foo {foo: add, foo: true}?.i {foo: add, foo: true}?.list {foo: add} {foo: add} ?? greet {foo: add}.Bar {foo: add}.String {foo: add}.add {foo: add}.array {foo: add}.f64 {foo: add}.foo {foo: add}.foobar {foo: add}.greet {foo: add}.greet?.i {foo: add}.i {foo: add}.i?.[foo] {foo: add}.i?.[greet] {foo: add}.i?.greet {foo: add}.list {foo: add}.list?.add()?.Bar {foo: add}.nil?.[greet] {foo: add}.ok {foo: add}.ok?.Bar(ok) {foo: add}.str {foo: add}.str?.[ok] {foo: add}.true?.[str] {foo: add}?.$env?.array {foo: add}?.Bar {foo: add}?.Bar?.i(foobar) {foo: add}?.Bar?.list {foo: add}?.String {foo: add}?.String?.String {foo: add}?.String?.[str] {foo: add}?.[str] {foo: add}?.[str]?.[f64] {foo: add}?.add {foo: add}?.add?.String() {foo: add}?.array {foo: add}?.array?.[f64] {foo: add}?.array?.[list] {foo: add}?.array?.find(nil, true).String {foo: add}?.f64 {foo: add}?.f64?.[add] {foo: add}?.f64?.[greet] {foo: add}?.f64?.[str] {foo: add}?.f64?.i {foo: add}?.foo {foo: add}?.foobar {foo: add}?.foobar?.[array] {foo: add}?.foobar?.[ok] {foo: add}?.greet {foo: add}?.greet?.[f64] {foo: add}?.greet?.[foo] {foo: add}?.i {foo: add}?.list {foo: add}?.list?.[array].list {foo: add}?.list?.[ok] {foo: add}?.list?.add {foo: add}?.list?.list {foo: add}?.ok {foo: add}?.ok?.i {foo: add}?.str {foo: all($env, true)} {foo: all(array, ok)}.Bar {foo: all(array, true)} {foo: all(list, true)} {foo: any($env, false)} {foo: any($env, ok)} {foo: any($env, true)} {foo: any(array, false)} {foo: any(array, ok)} {foo: any(list, ok)} {foo: array != $env} {foo: array != list} {foo: array != nil} {foo: array == $env} {foo: array == array} {foo: array == list} {foo: array == nil} {foo: array ?? $env} {foo: array ?? 0} {foo: array ?? 1.0} {foo: array ?? 1} {foo: array ?? add} {foo: array ?? array} {foo: array ?? foo} {foo: array ?? greet} {foo: array ?? i} {foo: array ?? list} {foo: array ?? str} {foo: array ?? true} {foo: array | all(false)} {foo: array | filter(true)} {foo: array | find(true)} {foo: array | findIndex(true)} {foo: array | groupBy(0)} {foo: array | groupBy(1.0)} {foo: array | groupBy(foo)} {foo: array | groupBy(str)} {foo: array | map(#)} {foo: array | map($env)} {foo: array | map(1)}?.list {foo: array | map(false)} {foo: array | map(foo)} {foo: array | map(greet)} {foo: array | map(list)} {foo: array | map(ok)} {foo: array | map(str)} {foo: array | mean(i)} {foo: array | min(f64)} {foo: array | none(false)} {foo: array | one(ok)} {foo: array | reduce(#)} {foo: array | reduce($env, 1.0)} {foo: array | reduce(0)} {foo: array | reduce(1.0)} {foo: array | reduce(foo)} {foo: array | reduce(i)} {foo: array | reduce(i, f64)} {foo: array | sortBy(#)} {foo: array | sum(#)} {foo: array | sum(1.0)} {foo: array | sum(i)} {foo: array, foo: !false}?.greet {foo: array, foo: $env, foo: nil}.i {foo: array, foo: $env.add} {foo: array, foo: $env?.nil} {foo: array, foo: $env}.String {foo: array, foo: $env}.array?.[add] {foo: array, foo: $env}.foo {foo: array, foo: $env}.greet {foo: array, foo: $env}.list {foo: array, foo: $env}?.Bar {foo: array, foo: $env}?.[str] {foo: array, foo: $env}?.array {foo: array, foo: $env}?.f64 {foo: array, foo: $env}?.foo {foo: array, foo: $env}?.greet {foo: array, foo: $env}?.i {foo: array, foo: $env}?.ok {foo: array, foo: 0}.Bar {foo: array, foo: 0}?.ok {foo: array, foo: 0}?.str {foo: array, foo: 1.0 <= 0} {foo: array, foo: 1.0, foo: ok}?.String {foo: array, foo: 1.0}.String {foo: array, foo: 1.0}.add {foo: array, foo: 1.0}.list {foo: array, foo: 1.0}.str {foo: array, foo: 1.0}?.Bar {foo: array, foo: 1.0}?.[str] {foo: array, foo: 1.0}?.array {foo: array, foo: 1.0}?.f64 {foo: array, foo: 1.0}?.greet {foo: array, foo: 1.0}?.list {foo: array, foo: 1.0}?.ok {foo: array, foo: 1.0}?.str {foo: array, foo: 1}.Bar {foo: array, foo: 1}.add {foo: array, foo: 1}.f64 {foo: array, foo: 1}.i?.ok {foo: array, foo: 1}.ok {foo: array, foo: 1}?.String {foo: array, foo: 1}?.[str] {foo: array, foo: 1}?.array {foo: array, foo: 1}?.str {foo: array, foo: [$env, nil]} {foo: array, foo: add} {foo: array, foo: add}.ok {foo: array, foo: add}?.foo {foo: array, foo: add}?.list {foo: array, foo: array, foo: $env}.ok {foo: array, foo: array} {foo: array, foo: array}.Bar {foo: array, foo: array}.add?.list() {foo: array, foo: array}.array?.Bar(nil) {foo: array, foo: array}.f64 {foo: array, foo: array}.list {foo: array, foo: array}.str {foo: array, foo: array}?.str {foo: array, foo: f64, foo: 1.0}?.f64 {foo: array, foo: f64} {foo: array, foo: f64}.Bar {foo: array, foo: f64}.String {foo: array, foo: f64}.f64 {foo: array, foo: f64}.list {foo: array, foo: f64}.str {foo: array, foo: f64}?.foo {foo: array, foo: false}.add {foo: array, foo: false}.f64 {foo: array, foo: false}.foo {foo: array, foo: false}?.f64 {foo: array, foo: false}?.list {foo: array, foo: false}?.str {foo: array, foo: float(0)} {foo: array, foo: foo != foo} {foo: array, foo: foo, foo: foo}.i {foo: array, foo: foo.Bar} {foo: array, foo: foo.String} {foo: array, foo: foo} {foo: array, foo: foo}.Bar {foo: array, foo: foo}.String {foo: array, foo: foo}.add {foo: array, foo: foo}.array {foo: array, foo: foo}.greet {foo: array, foo: foo}.i {foo: array, foo: foo}.list {foo: array, foo: foo}.str {foo: array, foo: foo}?.Bar {foo: array, foo: foo}?.String {foo: array, foo: foo}?.array {foo: array, foo: foo}?.foobar?.array() {foo: array, foo: foo}?.greet {foo: array, foo: foo}?.i {foo: array, foo: foo}?.list {foo: array, foo: foo}?.ok {foo: array, foo: greet} {foo: array, foo: greet}.String {foo: array, foo: greet}?.f64 {foo: array, foo: greet}?.foo {foo: array, foo: greet}?.greet {foo: array, foo: greet}?.str {foo: array, foo: groupBy(list, false)} {foo: array, foo: i, foo: 1.0}?.f64 {foo: array, foo: i} {foo: array, foo: i}.String {foo: array, foo: i}.array {foo: array, foo: i}.i {foo: array, foo: i}.list {foo: array, foo: i}?.String {foo: array, foo: i}?.add {foo: array, foo: list} {foo: array, foo: list}.String {foo: array, foo: list}.array {foo: array, foo: list}.false?.[i] {foo: array, foo: list}.greet {foo: array, foo: list}.list {foo: array, foo: list}.ok {foo: array, foo: list}?.Bar {foo: array, foo: list}?.String {foo: array, foo: list}?.add {foo: array, foo: list}?.foo {foo: array, foo: list}?.greet {foo: array, foo: list}?.list {foo: array, foo: list}?.ok {foo: array, foo: nil}.Bar {foo: array, foo: nil}.Bar?.[f64] {foo: array, foo: nil}.add {foo: array, foo: nil}.array {foo: array, foo: nil}.greet {foo: array, foo: nil}.list {foo: array, foo: nil}.str {foo: array, foo: nil}?.[str] {foo: array, foo: nil}?.add {foo: array, foo: nil}?.foo {foo: array, foo: nil}?.greet {foo: array, foo: nil}?.i {foo: array, foo: nil}?.list {foo: array, foo: nil}?.ok {foo: array, foo: nil}?.str {foo: array, foo: ok, foo: 1.0}.ok {foo: array, foo: ok, foo: false}?.String?.String() {foo: array, foo: ok} {foo: array, foo: ok}.ok {foo: array, foo: ok}?.Bar {foo: array, foo: ok}?.String {foo: array, foo: ok}?.ok {foo: array, foo: reduce(array, #)}?.ok {foo: array, foo: str, foo: foo}?.array {foo: array, foo: str} {foo: array, foo: str}.Bar {foo: array, foo: str}.f64 {foo: array, foo: str}.i {foo: array, foo: str}.list {foo: array, foo: str}.ok {foo: array, foo: str}.str {foo: array, foo: toJSON(1.0)} {foo: array, foo: true}.greet {foo: array, foo: true}.str {foo: array, foo: true}?.Bar {foo: array, foo: true}?.foo {foo: array, foo: {foo: $env}} {foo: array?.[1]} {foo: array?.[i], foo: list} {foo: array?.[i]} {foo: array[0:]} {foo: array[1:]} {foo: array[:0]} {foo: array[:1]} {foo: array[:]} {foo: array[:i]}?.list {foo: array} {foo: array} ?? add {foo: array} ?? groupBy(list, 1) {foo: array} ?? list {foo: array}.Bar {foo: array}.Bar?.String {foo: array}.Bar?.[array] {foo: array}.Bar?.[i] {foo: array}.Bar?.[ok] {foo: array}.String {foo: array}.String?.[f64] {foo: array}.String?.list {foo: array}.add {foo: array}.add?.[add] {foo: array}.array {foo: array}.array?.add {foo: array}.array?.list {foo: array}.f64 {foo: array}.f64?.[i] {foo: array}.f64?.add {foo: array}.f64?.f64() {foo: array}.foo {foo: array}.foobar {foo: array}.greet {foo: array}.greet?.greet {foo: array}.i {foo: array}.i?.[list] {foo: array}.i?.[ok] {foo: array}.i?.array {foo: array}.i?.foo {foo: array}.list {foo: array}.list?.[f64] {foo: array}.ok {foo: array}.str {foo: array}.str?.[greet] {foo: array}.str?.add {foo: array}?.Bar {foo: array}?.Bar?.[array] {foo: array}?.String {foo: array}?.String?.[list] {foo: array}?.[str] {foo: array}?.[str]?.String() {foo: array}?.[str]?.[add] {foo: array}?.[str]?.[array] {foo: array}?.[type(nil)] {foo: array}?.add {foo: array}?.array {foo: array}?.array?.foobar {foo: array}?.f64 {foo: array}?.f64?.add {foo: array}?.f64?.ok {foo: array}?.foo {foo: array}?.foobar {foo: array}?.foobar?.array {foo: array}?.greet {foo: array}?.i {foo: array}?.list {foo: array}?.list?.add {foo: array}?.list?.f64 {foo: array}?.ok {foo: array}?.ok?.ok() {foo: array}?.str {foo: array}?.str?.[f64] {foo: array}?.str?.[greet] {foo: bitnand(i, 1)} {foo: bitnot(0)} {foo: bitnot(1)} {foo: bitnot(i)} {foo: bitor(0, 0)} {foo: bitor(i, i)} {foo: bitshr(1, i)} {foo: bitxor(0, i)} {foo: bitxor(i, 1)} {foo: ceil(0), foo: array} {foo: ceil(0)} {foo: ceil(1)} {foo: ceil(1.0), foo: ok} {foo: ceil(1.0)} {foo: ceil(f64)} {foo: ceil(f64)}.array {foo: ceil(i)} {foo: concat(array)} {foo: concat(list)} {foo: count($env, ok)} {foo: count($env, true), foo: f64} {foo: count($env, true)} {foo: count(array, false)} {foo: count(array, ok)} {foo: count(list, ok)} {foo: f64 != $env} {foo: f64 != 1.0} {foo: f64 != 1} {foo: f64 != f64} {foo: f64 != i} {foo: f64 != nil} {foo: f64 * 0} {foo: f64 * 1.0} {foo: f64 * f64} {foo: f64 * i} {foo: f64 * i}?.Bar {foo: f64 ** 1.0} {foo: f64 ** f64} {foo: f64 ** i} {foo: f64 + 1.0} {foo: f64 + 1} {foo: f64 + f64} {foo: f64 + i} {foo: f64 - 0} {foo: f64 / 0} {foo: f64 / f64} {foo: f64 / i} {foo: f64 < 0} {foo: f64 < 0}.f64 {foo: f64 < i} {foo: f64 <= 1.0} {foo: f64 <= f64} {foo: f64 <= i} {foo: f64 == $env} {foo: f64 == 0} {foo: f64 == 1.0} {foo: f64 == 1} {foo: f64 == i} {foo: f64 == nil} {foo: f64 > 0, foo: floor(1.0)} {foo: f64 > 0} {foo: f64 > f64} {foo: f64 >= 0} {foo: f64 >= 1.0} {foo: f64 >= 1} {foo: f64 ?? $env} {foo: f64 ?? 1.0} {foo: f64 ?? f64} {foo: f64 ?? foo} {foo: f64 ?? list} {foo: f64 ?? nil} {foo: f64 ?? str} {foo: f64 ^ 1.0} {foo: f64 ^ i} {foo: f64 in array} {foo: f64 not in array} {foo: f64 not in array}.f64 {foo: f64, foo: $env == array} {foo: f64, foo: $env.foo} {foo: f64, foo: $env?.[foobar]} {foo: f64, foo: $env?.list} {foo: f64, foo: $env?.ok} {foo: f64, foo: $env}.String {foo: f64, foo: $env}.greet {foo: f64, foo: $env}.i {foo: f64, foo: $env}.ok {foo: f64, foo: $env}.str {foo: f64, foo: $env}?.i {foo: f64, foo: $env}?.list {foo: f64, foo: $env}?.ok {foo: f64, foo: 0, foo: 1.0}.f64 {foo: f64, foo: 0}.Bar {foo: f64, foo: 0}.add {foo: f64, foo: 0}.array {foo: f64, foo: 0}.list {foo: f64, foo: 0}.ok {foo: f64, foo: 0}.str {foo: f64, foo: 0}?.foo {foo: f64, foo: 0}?.list {foo: f64, foo: 1 != $env} {foo: f64, foo: 1 / 0} {foo: f64, foo: 1, foo: $env}?.i {foo: f64, foo: 1, foo: nil}.String {foo: f64, foo: 1.0, foo: true}.foo {foo: f64, foo: 1.0}.f64 {foo: f64, foo: 1.0}.i {foo: f64, foo: 1.0}?.Bar {foo: f64, foo: 1.0}?.[str] {foo: f64, foo: 1.0}?.array {foo: f64, foo: 1.0}?.f64 {foo: f64, foo: 1.0}?.greet {foo: f64, foo: 1.0}?.i {foo: f64, foo: 1.0}?.ok {foo: f64, foo: 1.0}?.str {foo: f64, foo: 1}.ok {foo: f64, foo: 1}?.String {foo: f64, foo: 1}?.[str] {foo: f64, foo: 1}?.greet {foo: f64, foo: 1}?.list {foo: f64, foo: 1}?.str {foo: f64, foo: add} {foo: f64, foo: add}.Bar {foo: f64, foo: add}.add {foo: f64, foo: add}.foo {foo: f64, foo: add}.greet {foo: f64, foo: add}.str {foo: f64, foo: add}?.String {foo: f64, foo: add}?.f64 {foo: f64, foo: add}?.foo {foo: f64, foo: add}?.greet {foo: f64, foo: add}?.i {foo: f64, foo: array} {foo: f64, foo: array}.Bar {foo: f64, foo: array}.add {foo: f64, foo: array}?.Bar {foo: f64, foo: array}?.foo {foo: f64, foo: array}?.list {foo: f64, foo: array}?.str {foo: f64, foo: f64} {foo: f64, foo: f64}.String {foo: f64, foo: f64}.ok {foo: f64, foo: f64}.str {foo: f64, foo: f64}?.Bar {foo: f64, foo: f64}?.f64 {foo: f64, foo: f64}?.foo {foo: f64, foo: f64}?.str {foo: f64, foo: false != nil} {foo: f64, foo: false}.f64 {foo: f64, foo: false}.greet {foo: f64, foo: false}.ok?.[array] {foo: f64, foo: foo, foo: 0}.ok {foo: f64, foo: foo, foo: foo}.Bar {foo: f64, foo: foo, foo: foo}?.add {foo: f64, foo: foo, foo: foo}?.greet {foo: f64, foo: foo} {foo: f64, foo: foo}.Bar {foo: f64, foo: foo}.add {foo: f64, foo: foo}.array {foo: f64, foo: foo}.f64 {foo: f64, foo: foo}.foo {foo: f64, foo: foo}.greet {foo: f64, foo: foo}.i {foo: f64, foo: foo}.list {foo: f64, foo: foo}.ok {foo: f64, foo: foo}?.String {foo: f64, foo: foo}?.[str] {foo: f64, foo: foo}?.add {foo: f64, foo: foo}?.array {foo: f64, foo: foo}?.foo {foo: f64, foo: foo}?.greet {foo: f64, foo: foo}?.i {foo: f64, foo: foo}?.str {foo: f64, foo: greet(str)}.str {foo: f64, foo: greet, foo: i}?.str {foo: f64, foo: greet} {foo: f64, foo: greet}.add {foo: f64, foo: greet}.array {foo: f64, foo: greet}.i {foo: f64, foo: greet}?.foo {foo: f64, foo: greet}?.greet {foo: f64, foo: greet}?.ok {foo: f64, foo: i, foo: add}.ok {foo: f64, foo: i, foo: foo}?.greet {foo: f64, foo: if ok { foo } else { nil }}.foo {foo: f64, foo: i} {foo: f64, foo: i}.array {foo: f64, foo: i}.greet {foo: f64, foo: i}?.[str] {foo: f64, foo: list} {foo: f64, foo: list}.String {foo: f64, foo: list}.add {foo: f64, foo: list}.array {foo: f64, foo: list}.foo {foo: f64, foo: list}.list {foo: f64, foo: list}?.Bar {foo: f64, foo: list}?.String {foo: f64, foo: list}?.i?.[i] {foo: f64, foo: nil, foo: $env}?.f64 {foo: f64, foo: nil, foo: $env}?.ok {foo: f64, foo: nil, foo: 1.0}.array {foo: f64, foo: nil}.String {foo: f64, foo: nil}.array {foo: f64, foo: nil}.f64 {foo: f64, foo: nil}.foobar {foo: f64, foo: nil}.greet {foo: f64, foo: nil}?.[str] {foo: f64, foo: nil}?.add?.[f64] {foo: f64, foo: nil}?.array {foo: f64, foo: nil}?.f64 {foo: f64, foo: nil}?.foobar {foo: f64, foo: nil}?.i {foo: f64, foo: nil}?.str {foo: f64, foo: ok ?? f64} {foo: f64, foo: ok, foo: 1.0}?.str {foo: f64, foo: ok} {foo: f64, foo: ok}?.Bar {foo: f64, foo: ok}?.String {foo: f64, foo: ok}?.f64?.[i] {foo: f64, foo: ok}?.ok {foo: f64, foo: round(1)} {foo: f64, foo: str, foo: 0}?.[str] {foo: f64, foo: str} {foo: f64, foo: str}.array {foo: f64, foo: str}.f64 {foo: f64, foo: str}.i {foo: f64, foo: str}?.[str] {foo: f64, foo: str}?.add {foo: f64, foo: str}?.f64 {foo: f64, foo: str}?.list {foo: f64, foo: sum(array)} {foo: f64, foo: toJSON(1)} {foo: f64, foo: true != nil} {foo: f64, foo: true}.add {foo: f64, foo: true}?.foo {foo: f64, foo: true}?.str {foo: f64, foo: {foo: nil}} {foo: f64} {foo: f64} ?? abs(0) {foo: f64} ?? add {foo: f64} ?? greet {foo: f64} not in first($env) {foo: f64}.Bar {foo: f64}.String {foo: f64}.String?.foo {foo: f64}.add {foo: f64}.array {foo: f64}.array?.foo?.[ok] {foo: f64}.f64 {foo: f64}.f64 != array {foo: f64}.f64?.greet {foo: f64}.foo {foo: f64}.foobar {foo: f64}.foobar?.[add] {foo: f64}.greet {foo: f64}.i {foo: f64}.i?.add(foo) {foo: f64}.i?.array {foo: f64}.list {foo: f64}.list?.list() {foo: f64}.ok {foo: f64}.ok?.list {foo: f64}.str {foo: f64}.str?.array {foo: f64}?.Bar {foo: f64}?.String {foo: f64}?.[str] {foo: f64}?.[str]?.Bar?.f64.String {foo: f64}?.[str]?.list {foo: f64}?.[str]?.list() {foo: f64}?.add {foo: f64}?.add?.[array] {foo: f64}?.add?.add {foo: f64}?.array {foo: f64}?.array?.Bar() {foo: f64}?.f64 {foo: f64}?.f64?.[f64] {foo: f64}?.f64?.[ok] {foo: f64}?.f64?.array {foo: f64}?.foo {foo: f64}?.foobar {foo: f64}?.greet {foo: f64}?.i {foo: f64}?.i?.[foo] {foo: f64}?.i?.add {foo: f64}?.list {foo: f64}?.list?.[list] {foo: f64}?.ok {foo: f64}?.ok?.foo {foo: f64}?.str {foo: f64}?.str?.i {foo: false != $env} {foo: false != false} {foo: false != nil} {foo: false != ok} {foo: false != true} {foo: false && $env} {foo: false == false} {foo: false == nil} {foo: false == ok} {foo: false == true} {foo: false ? foo : i} {foo: false ? foo : ok} {foo: false ? greet : nil} {foo: false ? list : 1} {foo: false ? list : f64} {foo: false ? ok : f64} {foo: false ?: foo} {foo: false ?: greet} {foo: false ?? $env} {foo: false ?? 0} {foo: false ?? 1.0} {foo: false ?? 1} {foo: false ?? array} {foo: false ?? f64}.str {foo: false ?? false} {foo: false ?? foo} {foo: false ?? i} {foo: false ?? list} {foo: false ?? nil, foo: array} {foo: false ?? nil} {foo: false and $env} {foo: false and false} {foo: false and ok} {foo: false and true} {foo: false or $env} {foo: false or false} {foo: false or ok} {foo: false or true} {foo: false || $env} {foo: false || true} {foo: false, foo: $env, foo: foo}?.str {foo: false, foo: $env, foo: true}.foo {foo: false, foo: $env}.Bar {foo: false, foo: $env}.String {foo: false, foo: $env}.f64 {foo: false, foo: $env}.foo {foo: false, foo: $env}.greet {foo: false, foo: $env}.list {foo: false, foo: $env}.ok {foo: false, foo: $env}?.Bar {foo: false, foo: $env}?.String {foo: false, foo: $env}?.[str] {foo: false, foo: $env}?.greet {foo: false, foo: $env}?.list {foo: false, foo: $env}?.str {foo: false, foo: 0, foo: $env}?.list {foo: false, foo: 0, foo: 0}.str {foo: false, foo: 0}.f64 {foo: false, foo: 0}.greet {foo: false, foo: 0}?.array {foo: false, foo: 0}?.list {foo: false, foo: 1.0, foo: $env}.add {foo: false, foo: 1.0}.Bar {foo: false, foo: 1.0}.String {foo: false, foo: 1.0}.array {foo: false, foo: 1.0}.foo {foo: false, foo: 1.0}.greet {foo: false, foo: 1.0}.str {foo: false, foo: 1.0}?.String {foo: false, foo: 1.0}?.[str] {foo: false, foo: 1.0}?.ok {foo: false, foo: 1.0}?.str {foo: false, foo: 1.0}?.str?.[f64] {foo: false, foo: 1}.String {foo: false, foo: 1}.add {foo: false, foo: 1}.foo {foo: false, foo: 1}.i {foo: false, foo: 1}.list?.[greet] {foo: false, foo: 1}.ok {foo: false, foo: 1}?.String {foo: false, foo: 1}?.i {foo: false, foo: add}.array {foo: false, foo: add}?.String {foo: false, foo: add}?.f64 {foo: false, foo: add}?.foo {foo: false, foo: add}?.greet {foo: false, foo: array, foo: foo}?.Bar {foo: false, foo: array}.Bar?.[greet] {foo: false, foo: array}.foo {foo: false, foo: array}.ok {foo: false, foo: array}?.Bar {foo: false, foo: array}?.greet {foo: false, foo: array}?.i {foo: false, foo: array}?.ok {foo: false, foo: array}?.str?.greet {foo: false, foo: f64, foo: 1.0}.list {foo: false, foo: f64}.Bar {foo: false, foo: f64}.greet {foo: false, foo: f64}.i {foo: false, foo: f64}?.str {foo: false, foo: f64}?.str?.f64 {foo: false, foo: false, foo: foo}?.Bar {foo: false, foo: false}.Bar {foo: false, foo: false}?.f64 {foo: false, foo: false}?.foo {foo: false, foo: false}?.greet?.[foo]?.str {foo: false, foo: false}?.ok {foo: false, foo: foo, foo: add}.Bar {foo: false, foo: foo, foo: foo}.str {foo: false, foo: foo, foo: greet}.f64 {foo: false, foo: foo}.Bar {foo: false, foo: foo}.array {foo: false, foo: foo}.f64 {foo: false, foo: foo}.foo {foo: false, foo: foo}.greet {foo: false, foo: foo}.i {foo: false, foo: foo}.list {foo: false, foo: foo}.ok {foo: false, foo: foo}.str {foo: false, foo: foo}?.Bar {foo: false, foo: foo}?.[str] {foo: false, foo: foo}?.add {foo: false, foo: foo}?.array {foo: false, foo: foo}?.foo {foo: false, foo: foo}?.i {foo: false, foo: foo}?.str {foo: false, foo: greet}.Bar {foo: false, foo: greet}.add {foo: false, foo: greet}.array {foo: false, foo: greet}.greet {foo: false, foo: greet}.i {foo: false, foo: greet}.str {foo: false, foo: greet}?.array {foo: false, foo: greet}?.foobar {foo: false, foo: greet}?.ok {foo: false, foo: greet}?.str {foo: false, foo: i}.list {foo: false, foo: i}.ok {foo: false, foo: i}.str {foo: false, foo: i}?.Bar {foo: false, foo: i}?.foo {foo: false, foo: i}?.greet {foo: false, foo: i}?.i {foo: false, foo: i}?.list {foo: false, foo: list, foo: f64}?.str {foo: false, foo: list, foo: list}?.array {foo: false, foo: list}.foobar {foo: false, foo: list}?.[str] {foo: false, foo: list}?.add {foo: false, foo: list}?.array?.foo {foo: false, foo: nil}.Bar {foo: false, foo: nil}.String {foo: false, foo: nil}.add {foo: false, foo: nil}.foo {foo: false, foo: nil}.foobar?.str {foo: false, foo: nil}.greet {foo: false, foo: nil}?.String?.array {foo: false, foo: nil}?.add {foo: false, foo: nil}?.foo {foo: false, foo: nil}?.list {foo: false, foo: nil}?.ok {foo: false, foo: nil}?.str {foo: false, foo: ok}.add {foo: false, foo: ok}.list {foo: false, foo: ok}?.String {foo: false, foo: ok}?.[str] {foo: false, foo: ok}?.array {foo: false, foo: ok}?.greet {foo: false, foo: ok}?.i {foo: false, foo: str}.array {foo: false, foo: str}?.Bar {foo: false, foo: str}?.String {foo: false, foo: str}?.[str] {foo: false, foo: true}.Bar {foo: false, foo: true}.add {foo: false, foo: true}.array {foo: false, foo: true}.ok {foo: false, foo: true}?.array {foo: false, foo: true}?.list {foo: false, foo: true}?.ok {foo: false} ?? list {foo: false}.Bar {foo: false}.String {foo: false}.String?.[i] {foo: false}.add {foo: false}.array {foo: false}.array?.greet(foobar) {foo: false}.f64 {foo: false}.f64?.Bar {foo: false}.f64?.[ok] {foo: false}.f64?.list {foo: false}.foo {foo: false}.foobar {foo: false}.greet {foo: false}.i {foo: false}.i?.Bar {foo: false}.list {foo: false}.list?.str {foo: false}.ok {foo: false}.ok == i {foo: false}.ok?.f64 {foo: false}.str {foo: false}.str?.array {foo: false}?.$env?.array {foo: false}?.Bar {foo: false}?.String {foo: false}?.[str] {foo: false}?.add {foo: false}?.array {foo: false}?.f64 {foo: false}?.f64?.Bar {foo: false}?.f64?.array() {foo: false}?.foo {foo: false}?.foobar {foo: false}?.foobar?.foo {foo: false}?.greet {foo: false}?.greet?.greet {foo: false}?.i {foo: false}?.i?.[foo] {foo: false}?.list {foo: false}?.ok {foo: false}?.ok?.[foo] {foo: false}?.str {foo: false}?.str?.[f64] {foo: false}?.str?.[list] {foo: filter($env, false)} {foo: filter(array, ok)} {foo: filter(list, ok)} {foo: filter(list, true)} {foo: find(array, false)} {foo: find(array, ok)} {foo: find(array, true)} {foo: find(list, false)}.str {foo: find(list, true), foo: foo} {foo: findIndex($env, ok)} {foo: findIndex($env, true)} {foo: findIndex(array, ok)} {foo: findIndex(list, ok)} {foo: findIndex(list, true)} {foo: first($env)} {foo: first($env)}?.foo {foo: first(array)} {foo: first(list)} {foo: flatten(array)} {foo: flatten(list)} {foo: float(0)} {foo: float(1)} {foo: float(1.0)} {foo: float(1.0)}.i {foo: float(1.0)}?.String {foo: float(f64), foo: f64} {foo: float(f64)} {foo: float(i)} {foo: floor(0)} {foo: floor(1), foo: nil == foo} {foo: floor(1)} {foo: floor(1.0)} {foo: floor(f64)} {foo: floor(f64)}.add {foo: floor(i)} {foo: foo != $env} {foo: foo != $env}.list {foo: foo != foo, foo: greet} {foo: foo != foo} {foo: foo != foo}?.greet {foo: foo != nil} {foo: foo == $env} {foo: foo == foo} {foo: foo == nil} {foo: foo ?? $env.foo} {foo: foo ?? $env} {foo: foo ?? 0} {foo: foo ?? 1.0} {foo: foo ?? 1} {foo: foo ?? add} {foo: foo ?? array} {foo: foo ?? f64} {foo: foo ?? foo} {foo: foo ?? greet} {foo: foo ?? i} {foo: foo ?? list} {foo: foo ?? nil, foo: ok} {foo: foo ?? nil} {foo: foo ?? ok} {foo: foo in list} {foo: foo not in list, foo: f64}.i {foo: foo not in list} {foo: foo, foo: $env, foo: 1}?.str {foo: foo, foo: $env, foo: add}.foo {foo: foo, foo: $env, foo: nil}?.f64 {foo: foo, foo: $env, foo: ok}?.array {foo: foo, foo: $env.f64}.greet {foo: foo, foo: $env.greet} {foo: foo, foo: $env?.[foobar]} {foo: foo, foo: $env?.f64} {foo: foo, foo: $env}.Bar {foo: foo, foo: $env}.String?.str {foo: foo, foo: $env}.add {foo: foo, foo: $env}.array {foo: foo, foo: $env}.f64 {foo: foo, foo: $env}.foo {foo: foo, foo: $env}.greet {foo: foo, foo: $env}.list {foo: foo, foo: $env}.nil?.[foo] {foo: foo, foo: $env}.ok {foo: foo, foo: $env}.str {foo: foo, foo: $env}?.Bar {foo: foo, foo: $env}?.String {foo: foo, foo: $env}?.[str] {foo: foo, foo: $env}?.add {foo: foo, foo: $env}?.array {foo: foo, foo: $env}?.f64 {foo: foo, foo: $env}?.foo {foo: foo, foo: $env}?.greet {foo: foo, foo: $env}?.i {foo: foo, foo: $env}?.list {foo: foo, foo: $env}?.ok {foo: foo, foo: $env}?.str != foo {foo: foo, foo: 0, foo: add}?.str {foo: foo, foo: 0} ?? greet {foo: foo, foo: 0}.Bar {foo: foo, foo: 0}.String {foo: foo, foo: 0}.foo {foo: foo, foo: 0}.foobar {foo: foo, foo: 0}.greet {foo: foo, foo: 0}.ok {foo: foo, foo: 0}.str {foo: foo, foo: 0}?.$env?.[list] {foo: foo, foo: 0}?.Bar {foo: foo, foo: 0}?.String {foo: foo, foo: 0}?.[str] {foo: foo, foo: 0}?.add {foo: foo, foo: 0}?.f64 {foo: foo, foo: 0}?.foo {foo: foo, foo: 0}?.greet {foo: foo, foo: 0}?.list {foo: foo, foo: 1, foo: greet}?.str {foo: foo, foo: 1, foo: list}?.str {foo: foo, foo: 1.0 - 1.0} {foo: foo, foo: 1.0, foo: array}.str {foo: foo, foo: 1.0}.Bar {foo: foo, foo: 1.0}.String {foo: foo, foo: 1.0}.add {foo: foo, foo: 1.0}.array {foo: foo, foo: 1.0}.f64 {foo: foo, foo: 1.0}.foo {foo: foo, foo: 1.0}.greet {foo: foo, foo: 1.0}.i {foo: foo, foo: 1.0}.i?.list {foo: foo, foo: 1.0}.list {foo: foo, foo: 1.0}.ok {foo: foo, foo: 1.0}.str {foo: foo, foo: 1.0}?.Bar {foo: foo, foo: 1.0}?.String {foo: foo, foo: 1.0}?.[str] {foo: foo, foo: 1.0}?.add {foo: foo, foo: 1.0}?.add?.ok {foo: foo, foo: 1.0}?.array {foo: foo, foo: 1.0}?.f64 {foo: foo, foo: 1.0}?.foo {foo: foo, foo: 1.0}?.greet {foo: foo, foo: 1.0}?.list {foo: foo, foo: 1.0}?.ok?.[add] {foo: foo, foo: 1.0}?.str {foo: foo, foo: 1}.Bar {foo: foo, foo: 1}.String {foo: foo, foo: 1}.add {foo: foo, foo: 1}.f64 {foo: foo, foo: 1}.foo {foo: foo, foo: 1}.i {foo: foo, foo: 1}.list {foo: foo, foo: 1}.ok {foo: foo, foo: 1}.str {foo: foo, foo: 1}?.add {foo: foo, foo: 1}?.f64 {foo: foo, foo: 1}?.foo {foo: foo, foo: 1}?.list {foo: foo, foo: 1}?.ok {foo: foo, foo: 1}?.str {foo: foo, foo: [$env?.add]} {foo: foo, foo: add, foo: foo}?.add {foo: foo, foo: add, foo: nil}.f64 {foo: foo, foo: add} {foo: foo, foo: add}.array {foo: foo, foo: add}.f64 {foo: foo, foo: add}.foo {foo: foo, foo: add}.greet {foo: foo, foo: add}.i {foo: foo, foo: add}.list {foo: foo, foo: add}.str {foo: foo, foo: add}?.String {foo: foo, foo: add}?.add {foo: foo, foo: add}?.f64 {foo: foo, foo: add}?.list {foo: foo, foo: add}?.ok {foo: foo, foo: add}?.str {foo: foo, foo: array, foo: false}?.greet {foo: foo, foo: array, foo: i}.f64 {foo: foo, foo: array} {foo: foo, foo: array}.Bar {foo: foo, foo: array}.String {foo: foo, foo: array}.f64 {foo: foo, foo: array}.foo {foo: foo, foo: array}.greet {foo: foo, foo: array}.i {foo: foo, foo: array}.list {foo: foo, foo: array}.ok {foo: foo, foo: array}.str {foo: foo, foo: array}?.String {foo: foo, foo: array}?.[str] {foo: foo, foo: array}?.add {foo: foo, foo: array}?.array {foo: foo, foo: array}?.foo {foo: foo, foo: array}?.greet {foo: foo, foo: array}?.greet?.list {foo: foo, foo: array}?.i {foo: foo, foo: array}?.ok {foo: foo, foo: f64, foo: 1.0}?.array {foo: foo, foo: f64} {foo: foo, foo: f64}.String {foo: foo, foo: f64}.add {foo: foo, foo: f64}.array {foo: foo, foo: f64}.f64 {foo: foo, foo: f64}.i {foo: foo, foo: f64}.list {foo: foo, foo: f64}.list?.[i] {foo: foo, foo: f64}?.Bar {foo: foo, foo: f64}?.String {foo: foo, foo: f64}?.add {foo: foo, foo: f64}?.f64 {foo: foo, foo: f64}?.foo {foo: foo, foo: f64}?.ok {foo: foo, foo: f64}?.str {foo: foo, foo: false, foo: list}?.str?.add {foo: foo, foo: false}.Bar {foo: foo, foo: false}.String {foo: foo, foo: false}.array {foo: foo, foo: false}.f64 {foo: foo, foo: false}.foo {foo: foo, foo: false}.greet {foo: foo, foo: false}.i {foo: foo, foo: false}.list {foo: foo, foo: false}.ok {foo: foo, foo: false}.str {foo: foo, foo: false}?.[str] {foo: foo, foo: false}?.add {foo: foo, foo: false}?.foo {foo: foo, foo: false}?.i {foo: foo, foo: false}?.ok {foo: foo, foo: false}?.str {foo: foo, foo: foo, foo: $env}.String {foo: foo, foo: foo, foo: add}?.f64 {foo: foo, foo: foo, foo: foo}.greet {foo: foo, foo: foo, foo: greet} {foo: foo, foo: foo, foo: nil}.Bar {foo: foo, foo: foo, foo: ok}?.str {foo: foo, foo: foo.Bar} {foo: foo, foo: foo} {foo: foo, foo: foo}.Bar {foo: foo, foo: foo}.Bar?.[f64] {foo: foo, foo: foo}.String {foo: foo, foo: foo}.add {foo: foo, foo: foo}.array {foo: foo, foo: foo}.f64 {foo: foo, foo: foo}.foo {foo: foo, foo: foo}.greet {foo: foo, foo: foo}.list {foo: foo, foo: foo}.ok {foo: foo, foo: foo}.str {foo: foo, foo: foo}?.Bar {foo: foo, foo: foo}?.String {foo: foo, foo: foo}?.[str] {foo: foo, foo: foo}?.add {foo: foo, foo: foo}?.array {foo: foo, foo: foo}?.f64 {foo: foo, foo: foo}?.foo {foo: foo, foo: foo}?.foobar {foo: foo, foo: foo}?.greet {foo: foo, foo: foo}?.list {foo: foo, foo: foo}?.list?.f64 {foo: foo, foo: foo}?.ok {foo: foo, foo: foo}?.str {foo: foo, foo: greet, foo: 1.0}.list {foo: foo, foo: greet, foo: foo}?.i {foo: foo, foo: greet} {foo: foo, foo: greet}.Bar {foo: foo, foo: greet}.String {foo: foo, foo: greet}.add {foo: foo, foo: greet}.array {foo: foo, foo: greet}.foo {foo: foo, foo: greet}.greet {foo: foo, foo: greet}.i {foo: foo, foo: greet}.str {foo: foo, foo: greet}?.Bar {foo: foo, foo: greet}?.array {foo: foo, foo: greet}?.f64 {foo: foo, foo: greet}?.foo {foo: foo, foo: greet}?.greet {foo: foo, foo: greet}?.list {foo: foo, foo: i / f64} {foo: foo, foo: i, foo: 0}.ok {foo: foo, foo: i, foo: 1.0}.array {foo: foo, foo: i} {foo: foo, foo: i}.Bar {foo: foo, foo: i}.String {foo: foo, foo: i}.String?.String {foo: foo, foo: i}.add {foo: foo, foo: i}.foo {foo: foo, foo: i}.str {foo: foo, foo: i}?.String {foo: foo, foo: i}?.[str] {foo: foo, foo: i}?.array {foo: foo, foo: i}?.f64 {foo: foo, foo: i}?.foo {foo: foo, foo: i}?.foobar {foo: foo, foo: i}?.greet {foo: foo, foo: i}?.ok {foo: foo, foo: i}?.str {foo: foo, foo: list != list} {foo: foo, foo: list, foo: false and false} {foo: foo, foo: list, foo: greet}?.f64 {foo: foo, foo: list} {foo: foo, foo: list}.String {foo: foo, foo: list}.add?.[i] {foo: foo, foo: list}.array {foo: foo, foo: list}.array?.Bar {foo: foo, foo: list}.f64 {foo: foo, foo: list}.greet {foo: foo, foo: list}.ok {foo: foo, foo: list}.str {foo: foo, foo: list}?.Bar {foo: foo, foo: list}?.[str] {foo: foo, foo: list}?.add {foo: foo, foo: list}?.array {foo: foo, foo: list}?.f64 {foo: foo, foo: list}?.greet {foo: foo, foo: list}?.i {foo: foo, foo: list}?.list {foo: foo, foo: list}?.str {foo: foo, foo: list}?.str?.array(1.0) {foo: foo, foo: median(0)} {foo: foo, foo: nil in $env} {foo: foo, foo: nil, foo: 0}.f64 {foo: foo, foo: nil, foo: 0}?.f64?.i() {foo: foo, foo: nil, foo: 1}.greet {foo: foo, foo: nil, foo: nil}.f64 {foo: foo, foo: nil, foo: nil}.list {foo: foo, foo: nil, foo: ok}?.list {foo: foo, foo: nil}.Bar {foo: foo, foo: nil}.String {foo: foo, foo: nil}.add {foo: foo, foo: nil}.array {foo: foo, foo: nil}.f64 {foo: foo, foo: nil}.foo {foo: foo, foo: nil}.foobar?.[array] {foo: foo, foo: nil}.foobar?.[list] {foo: foo, foo: nil}.i {foo: foo, foo: nil}.i?.array {foo: foo, foo: nil}.list {foo: foo, foo: nil}.ok {foo: foo, foo: nil}.ok?.array() {foo: foo, foo: nil}.str {foo: foo, foo: nil}?.String {foo: foo, foo: nil}?.[str] {foo: foo, foo: nil}?.add {foo: foo, foo: nil}?.array {foo: foo, foo: nil}?.f64 {foo: foo, foo: nil}?.foo {foo: foo, foo: nil}?.greet {foo: foo, foo: nil}?.i {foo: foo, foo: nil}?.list {foo: foo, foo: nil}?.ok {foo: foo, foo: nil}?.str {foo: foo, foo: ok, foo: 1}.Bar?.i(foobar) {foo: foo, foo: ok, foo: f64}.foo {foo: foo, foo: ok} {foo: foo, foo: ok}.String {foo: foo, foo: ok}.add {foo: foo, foo: ok}.array {foo: foo, foo: ok}.i {foo: foo, foo: ok}.list {foo: foo, foo: ok}?.String {foo: foo, foo: ok}?.[str] {foo: foo, foo: ok}?.add {foo: foo, foo: ok}?.array {foo: foo, foo: ok}?.f64 {foo: foo, foo: ok}?.foo {foo: foo, foo: ok}?.i {foo: foo, foo: ok}?.list {foo: foo, foo: ok}?.str {foo: foo, foo: str, foo: 1.0}.Bar {foo: foo, foo: str, foo: foo}?.f64 {foo: foo, foo: str, foo: list}?.String {foo: foo, foo: str} {foo: foo, foo: str}.String {foo: foo, foo: str}.f64 {foo: foo, foo: str}.i {foo: foo, foo: str}.ok {foo: foo, foo: str}?.Bar {foo: foo, foo: str}?.add {foo: foo, foo: str}?.array {foo: foo, foo: str}?.f64 {foo: foo, foo: str}?.f64?.ok {foo: foo, foo: str}?.foo {foo: foo, foo: str}?.greet {foo: foo, foo: str}?.greet?.[i] {foo: foo, foo: str}?.i {foo: foo, foo: str}?.str {foo: foo, foo: true, foo: $env}?.add {foo: foo, foo: true, foo: array}.ok {foo: foo, foo: true, foo: nil}?.Bar {foo: foo, foo: true, foo: nil}?.i {foo: foo, foo: true}.Bar {foo: foo, foo: true}.add {foo: foo, foo: true}.add?.[array] {foo: foo, foo: true}.foo {foo: foo, foo: true}.greet?.Bar {foo: foo, foo: true}.i {foo: foo, foo: true}.str {foo: foo, foo: true}?.Bar {foo: foo, foo: true}?.String {foo: foo, foo: true}?.[str] {foo: foo, foo: true}?.add {foo: foo, foo: true}?.array {foo: foo, foo: true}?.f64 {foo: foo, foo: true}?.list {foo: foo, foo: true}?.list?.[i].Bar() {foo: foo, foo: true}?.ok {foo: foo, foo: true}?.str?.i {foo: foo, foo: {foo: foo}} {foo: foo.Bar, foo: false ? foo : str}?.ok {foo: foo.Bar, foo: greet} {foo: foo.Bar, foo: list} {foo: foo.Bar} {foo: foo.Bar}.greet {foo: foo.Bar}.list {foo: foo.Bar}?.f64 {foo: foo.String() not matches str} {foo: foo.String()} {foo: foo.String()}?.ok {foo: foo.String, foo: ok} {foo: foo.String, foo: str} {foo: foo.String} {foo: foo.String}.String {foo: foo.String}.add {foo: foo.String}.array {foo: foo.String}.greet {foo: foo.String}.str {foo: foo.String}?.add {foo: foo.String}?.str {foo: foo?.Bar, foo: add} {foo: foo?.Bar} {foo: foo?.Bar}?.list {foo: foo?.String(), foo: i} {foo: foo?.String()} {foo: foo?.String()}.Bar {foo: foo?.String()}?.list {foo: foo?.String, foo: f64} {foo: foo?.String, foo: greet} {foo: foo?.String, foo: str} {foo: foo?.String} {foo: foo?.String}.array {foo: foo?.String}?.Bar {foo: foo} {foo: foo} ?? $env?.f64 {foo: foo} ?? add {foo: foo} ?? greet {foo: foo} ?? ok {foo: foo}.Bar {foo: foo}.String {foo: foo}.String != str {foo: foo}.String?.[i] {foo: foo}.add {foo: foo}.add?.add() {foo: foo}.array {foo: foo}.array?.[str] {foo: foo}.array?.foo {foo: foo}.array?.greet() {foo: foo}.array?.i {foo: foo}.f64 {foo: foo}.f64?.Bar {foo: foo}.f64?.[array] {foo: foo}.f64?.[f64] {foo: foo}.f64?.add {foo: foo}.f64?.i {foo: foo}.f64?.ok {foo: foo}.f64?.str {foo: foo}.false?.f64 {foo: foo}.foo {foo: foo}.foobar {foo: foo}.foobar?.greet {foo: foo}.greet {foo: foo}.greet != f64 {foo: foo}.greet?.[f64] {foo: foo}.greet?.[i] {foo: foo}.greet?.[ok] {foo: foo}.greet?.array() {foo: foo}.i {foo: foo}.i?.[f64] {foo: foo}.i?.add {foo: foo}.list {foo: foo}.list?.[f64] {foo: foo}.list?.[str]?.foobar {foo: foo}.list?.str {foo: foo}.ok {foo: foo}.ok?.[add].add() {foo: foo}.ok?.f64 {foo: foo}.ok?.ok {foo: foo}.str {foo: foo}.str?.String {foo: foo}.str?.[array] {foo: foo}.str?.greet {foo: foo}?.Bar {foo: foo}?.String {foo: foo}?.String?.Bar {foo: foo}?.String?.String() {foo: foo}?.String?.array.str {foo: foo}?.[str] {foo: foo}?.[str]?.String {foo: foo}?.add {foo: foo}?.add?.f64(foobar, foobar) {foo: foo}?.add?.i {foo: foo}?.add?.ok {foo: foo}?.add?.str {foo: foo}?.array {foo: foo}?.array?.String?.[foo] {foo: foo}?.array?.[foo] {foo: foo}?.array?.i {foo: foo}?.f64 {foo: foo}?.f64?.[add] {foo: foo}?.f64?.[list] {foo: foo}?.f64?.[ok] {foo: foo}?.f64?.str {foo: foo}?.foo {foo: foo}?.foobar {foo: foo}?.foobar == foo {foo: foo}?.foobar?.[add] {foo: foo}?.foobar?.[array] {foo: foo}?.foobar?.array {foo: foo}?.foobar?.foo {foo: foo}?.foobar?.greet(foobar) {foo: foo}?.greet {foo: foo}?.greet?.String?.[greet] {foo: foo}?.greet?.[f64] {foo: foo}?.greet?.[i] {foo: foo}?.greet?.[str] {foo: foo}?.i {foo: foo}?.i?.[add] {foo: foo}?.i?.ok {foo: foo}?.list {foo: foo}?.list?.[add]?.str {foo: foo}?.list?.add {foo: foo}?.list?.foo {foo: foo}?.list?.list {foo: foo}?.ok {foo: foo}?.ok?.Bar {foo: foo}?.ok?.String {foo: foo}?.ok?.[i] {foo: foo}?.ok?.f64() {foo: foo}?.ok?.greet()?.f64() {foo: foo}?.ok?.ok {foo: foo}?.str {foo: foo}?.str?.add {foo: foo}?.str?.f64 {foo: greet != $env} {foo: greet != greet}.foo {foo: greet != nil} {foo: greet == $env} {foo: greet == greet} {foo: greet ?? $env} {foo: greet ?? 0} {foo: greet ?? 1.0} {foo: greet ?? 1} {foo: greet ?? add} {foo: greet ?? f64, foo: i} {foo: greet ?? f64} {foo: greet ?? false} {foo: greet ?? foo} {foo: greet ?? greet} {foo: greet ?? nil} {foo: greet($env?.[str])} {foo: greet(str), foo: array} {foo: greet(str)} {foo: greet(str)}.String {foo: greet(str)}.ok {foo: greet(str)}.str {foo: greet, foo: !false} {foo: greet, foo: $env.array} {foo: greet, foo: $env.f64} {foo: greet, foo: $env.ok} {foo: greet, foo: $env.str} {foo: greet, foo: $env?.ok} {foo: greet, foo: $env?.str} {foo: greet, foo: $env}.Bar {foo: greet, foo: $env}.Bar?.add {foo: greet, foo: $env}.String {foo: greet, foo: $env}.add {foo: greet, foo: $env}.greet {foo: greet, foo: $env}.str {foo: greet, foo: $env}?.String {foo: greet, foo: $env}?.add {foo: greet, foo: $env}?.array {foo: greet, foo: $env}?.greet {foo: greet, foo: $env}?.list {foo: greet, foo: $env}?.ok {foo: greet, foo: 0, foo: foo}?.String {foo: greet, foo: 0}.String {foo: greet, foo: 0}.foo {foo: greet, foo: 0}.i {foo: greet, foo: 0}?.Bar {foo: greet, foo: 0}?.add {foo: greet, foo: 0}?.f64 {foo: greet, foo: 0}?.ok {foo: greet, foo: 1 ** f64} {foo: greet, foo: 1, foo: $env}?.Bar {foo: greet, foo: 1.0}.Bar {foo: greet, foo: 1.0}.String {foo: greet, foo: 1.0}.i {foo: greet, foo: 1.0}.ok {foo: greet, foo: 1.0}.str {foo: greet, foo: 1.0}?.Bar {foo: greet, foo: 1.0}?.String {foo: greet, foo: 1.0}?.array {foo: greet, foo: 1.0}?.f64?.[i] {foo: greet, foo: 1.0}?.list {foo: greet, foo: 1.0}?.str {foo: greet, foo: 1}.Bar {foo: greet, foo: 1}.foo {foo: greet, foo: 1}.list {foo: greet, foo: 1}?.[str] {foo: greet, foo: 1}?.i {foo: greet, foo: 1}?.ok {foo: greet, foo: [$env]} {foo: greet, foo: add} {foo: greet, foo: add}.array {foo: greet, foo: add}.foo {foo: greet, foo: add}?.add {foo: greet, foo: add}?.add?.[add] {foo: greet, foo: add}?.f64 {foo: greet, foo: add}?.foo {foo: greet, foo: add}?.i {foo: greet, foo: array} {foo: greet, foo: array} ?? add {foo: greet, foo: array}.String {foo: greet, foo: array}.array {foo: greet, foo: array}.foo {foo: greet, foo: array}?.array {foo: greet, foo: f64} {foo: greet, foo: f64}.String {foo: greet, foo: f64}.greet {foo: greet, foo: f64}.i {foo: greet, foo: f64}?.Bar {foo: greet, foo: f64}?.String {foo: greet, foo: f64}?.i {foo: greet, foo: f64}?.list {foo: greet, foo: false == nil} {foo: greet, foo: false, foo: add}.Bar {foo: greet, foo: false, foo: foo}.String {foo: greet, foo: false}.add {foo: greet, foo: false}.array {foo: greet, foo: false}.f64 {foo: greet, foo: false}.greet {foo: greet, foo: false}.ok {foo: greet, foo: false}.str {foo: greet, foo: false}?.[str] {foo: greet, foo: false}?.f64 {foo: greet, foo: false}?.str {foo: greet, foo: float(f64)} {foo: greet, foo: foo != foo} {foo: greet, foo: foo ?? f64} {foo: greet, foo: foo, foo: array} {foo: greet, foo: foo, foo: greet}?.add {foo: greet, foo: foo.Bar} {foo: greet, foo: foo} {foo: greet, foo: foo}.String {foo: greet, foo: foo}.add {foo: greet, foo: foo}.f64 {foo: greet, foo: foo}.foo {foo: greet, foo: foo}.greet {foo: greet, foo: foo}.i {foo: greet, foo: foo}.list {foo: greet, foo: foo}.ok {foo: greet, foo: foo}.ok?.list {foo: greet, foo: foo}?.Bar {foo: greet, foo: foo}?.Bar?.[ok] {foo: greet, foo: foo}?.String {foo: greet, foo: foo}?.[str] {foo: greet, foo: foo}?.add {foo: greet, foo: foo}?.f64 {foo: greet, foo: foo}?.foo {foo: greet, foo: foo}?.greet {foo: greet, foo: foo}?.i {foo: greet, foo: foo}?.list {foo: greet, foo: foo}?.list?.str {foo: greet, foo: foo}?.ok {foo: greet, foo: foo}?.str {foo: greet, foo: greet(str)} {foo: greet, foo: greet} {foo: greet, foo: greet}?.str {foo: greet, foo: i == 1.0} {foo: greet, foo: i} {foo: greet, foo: i}.list {foo: greet, foo: i}?.String {foo: greet, foo: list} {foo: greet, foo: list}.Bar {foo: greet, foo: list}.list {foo: greet, foo: list}.str {foo: greet, foo: list}.true?.f64(false) {foo: greet, foo: list}?.add {foo: greet, foo: list}?.f64 {foo: greet, foo: nil == str} {foo: greet, foo: nil}.add {foo: greet, foo: nil}.array {foo: greet, foo: nil}.f64 {foo: greet, foo: nil}.f64?.[foo] {foo: greet, foo: nil}.foo(foobar?.[ok]) {foo: greet, foo: nil}.greet {foo: greet, foo: nil}?.[str] {foo: greet, foo: nil}?.foo {foo: greet, foo: nil}?.greet {foo: greet, foo: nil}?.ok {foo: greet, foo: ok} {foo: greet, foo: ok}.foo {foo: greet, foo: ok}.i {foo: greet, foo: ok}?.array {foo: greet, foo: ok}?.f64 {foo: greet, foo: ok}?.list {foo: greet, foo: ok}?.ok {foo: greet, foo: ok}?.str {foo: greet, foo: str} {foo: greet, foo: str}.Bar {foo: greet, foo: str}.String {foo: greet, foo: str}.add {foo: greet, foo: str}.foo {foo: greet, foo: str}.ok {foo: greet, foo: str}?.f64 {foo: greet, foo: trimPrefix(str)} {foo: greet, foo: true}.Bar {foo: greet, foo: true}?.String {foo: greet, foo: true}?.greet {foo: greet, foo: true}?.ok {foo: greet, foo: true}?.str {foo: greet} {foo: greet} ?? 1 ?? 1.0 {foo: greet} ?? add {foo: greet}.Bar {foo: greet}.Bar?.String {foo: greet}.Bar?.ok {foo: greet}.String {foo: greet}.String?.str() {foo: greet}.add {foo: greet}.add?.ok {foo: greet}.array {foo: greet}.array?.i {foo: greet}.f64 {foo: greet}.f64?.String {foo: greet}.f64?.f64 {foo: greet}.foo {foo: greet}.foobar {foo: greet}.foobar?.[1.0] {foo: greet}.foobar?.[foo] {foo: greet}.foobar?.foo() {foo: greet}.foobar?.str?.f64 {foo: greet}.greet {foo: greet}.greet?.i {foo: greet}.greet?.str {foo: greet}.i {foo: greet}.list {foo: greet}.list?.Bar() {foo: greet}.list?.[f64] {foo: greet}.list?.list?.[f64] {foo: greet}.ok {foo: greet}.ok?.Bar {foo: greet}.ok?.add {foo: greet}.str {foo: greet}?.Bar {foo: greet}?.String {foo: greet}?.String?.String {foo: greet}?.[str] {foo: greet}?.add {foo: greet}?.add?.String {foo: greet}?.array {foo: greet}?.array?.[array] {foo: greet}?.f64 {foo: greet}?.f64?.foo(array) {foo: greet}?.foo {foo: greet}?.foobar {foo: greet}?.foobar?.[foo] {foo: greet}?.foobar?.[ok] {foo: greet}?.greet {foo: greet}?.i {foo: greet}?.i?.[str] {foo: greet}?.list {foo: greet}?.list?.f64() {foo: greet}?.list?.i {foo: greet}?.ok {foo: greet}?.ok?.[foo] {foo: greet}?.ok?.list {foo: greet}?.str {foo: groupBy(array, #)} {foo: groupBy(array, 0), foo: min($env)} {foo: groupBy(array, 1.0)} {foo: groupBy(array, f64)} {foo: groupBy(array, false)} {foo: groupBy(array, foo)} {foo: groupBy(list, #)} {foo: groupBy(list, #.Bar)} {foo: groupBy(list, 0)} {foo: groupBy(list, 1)} {foo: groupBy(list, foo)} {foo: groupBy(list, foo.String())} {foo: groupBy(list, i)} {foo: groupBy(list, ok)} {foo: groupBy(list, true)} {foo: i != $env}?.String {foo: i != 0} {foo: i != 1.0} {foo: i != f64} {foo: i != f64}?.ok {foo: i != i, foo: greet(str)} {foo: i % 1} {foo: i * 0} {foo: i * 1.0} {foo: i * 1} {foo: i * f64} {foo: i * i} {foo: i ** 1, foo: ok}.f64 {foo: i ** 1.0} {foo: i ** 1} {foo: i ** f64} {foo: i + 0} {foo: i + 1.0} {foo: i + 1} {foo: i + 1}?.i {foo: i + f64} {foo: i + i} {foo: i - 0} {foo: i - 1} {foo: i .. 0} {foo: i .. 1, foo: i} {foo: i .. 1} {foo: i .. i} {foo: i / 0} {foo: i / 1, foo: string(false)} {foo: i / 1.0} {foo: i < 0} {foo: i < 1.0} {foo: i < 1} {foo: i < f64} {foo: i < i} {foo: i <= 0} {foo: i <= 1.0} {foo: i <= f64} {foo: i <= i} {foo: i == $env} {foo: i == $env}?.Bar {foo: i == 1.0} {foo: i == nil} {foo: i > 0, foo: 1 >= f64} {foo: i >= 0} {foo: i >= 1.0} {foo: i >= 1} {foo: i >= f64} {foo: i >= f64}.str {foo: i ?? $env} {foo: i ?? 0} {foo: i ?? 1.0} {foo: i ?? array} {foo: i ?? foo} {foo: i ?? greet} {foo: i ?? str} {foo: i ^ 0} {foo: i ^ 1.0} {foo: i ^ 1} {foo: i ^ f64} {foo: i ^ i, foo: array} {foo: i ^ i} {foo: i not in array} {foo: i not in array}?.greet {foo: i | bitnand(1)} {foo: i | bitor(i)} {foo: i | bitushr(i)} {foo: i | bitxor(i)} {foo: i | median(i)} {foo: i, foo: $env != foo} {foo: i, foo: $env != ok} {foo: i, foo: $env, foo: nil}?.add {foo: i, foo: $env?.[Bar]} {foo: i, foo: $env}.add {foo: i, foo: $env}.foo {foo: i, foo: $env}.ok {foo: i, foo: $env}?.[str] {foo: i, foo: $env}?.list {foo: i, foo: 0 ?? f64} {foo: i, foo: 0}.String {foo: i, foo: 0}.greet {foo: i, foo: 0}?.Bar {foo: i, foo: 0}?.f64 {foo: i, foo: 0}?.ok?.str {foo: i, foo: 1 - f64} {foo: i, foo: 1.0 < 0} {foo: i, foo: 1.0, foo: foo}?.[str] {foo: i, foo: 1.0, foo: foo}?.str {foo: i, foo: 1.0}.Bar {foo: i, foo: 1.0}.String {foo: i, foo: 1.0}.array {foo: i, foo: 1.0}.f64 {foo: i, foo: 1.0}.f64?.ok {foo: i, foo: 1.0}.foobar?.ok {foo: i, foo: 1.0}.i {foo: i, foo: 1.0}.ok {foo: i, foo: 1.0}.str {foo: i, foo: 1.0}?.String {foo: i, foo: 1.0}?.add {foo: i, foo: 1.0}?.f64 {foo: i, foo: 1.0}?.ok {foo: i, foo: 1.0}?.str {foo: i, foo: 1}.f64 {foo: i, foo: 1}?.array {foo: i, foo: 1}?.list {foo: i, foo: 1}?.ok {foo: i, foo: add} {foo: i, foo: add}.i {foo: i, foo: add}.str {foo: i, foo: add}?.String {foo: i, foo: add}?.foo {foo: i, foo: add}?.i {foo: i, foo: add}?.str {foo: i, foo: array} {foo: i, foo: array}.f64 {foo: i, foo: array}.greet {foo: i, foo: array}.i {foo: i, foo: array}.list {foo: i, foo: array}.str {foo: i, foo: f64} {foo: i, foo: f64}.f64 {foo: i, foo: f64}.foo {foo: i, foo: f64}.foobar?.f64(foo) {foo: i, foo: f64}?.i {foo: i, foo: f64}?.list {foo: i, foo: f64}?.ok {foo: i, foo: false}.array {foo: i, foo: false}.f64?.array {foo: i, foo: false}.str {foo: i, foo: false}?.Bar {foo: i, foo: false}?.String {foo: i, foo: false}?.i {foo: i, foo: false}?.str {foo: i, foo: foo, foo: $env}.ok {foo: i, foo: foo?.String} {foo: i, foo: foo} {foo: i, foo: foo}.Bar {foo: i, foo: foo}.String {foo: i, foo: foo}.String?.array {foo: i, foo: foo}.array {foo: i, foo: foo}.f64 {foo: i, foo: foo}.f64?.foo {foo: i, foo: foo}.greet {foo: i, foo: foo}.list {foo: i, foo: foo}?.String {foo: i, foo: foo}?.array {foo: i, foo: foo}?.greet {foo: i, foo: foo}?.i {foo: i, foo: foo}?.list {foo: i, foo: foo}?.list == foo {foo: i, foo: foo}?.ok {foo: i, foo: foo}?.str {foo: i, foo: greet(str)} {foo: i, foo: greet, foo: nil}?.Bar {foo: i, foo: greet} {foo: i, foo: greet}.Bar {foo: i, foo: greet}.foo {foo: i, foo: greet}.ok {foo: i, foo: greet}?.String {foo: i, foo: greet}?.f64 {foo: i, foo: greet}?.list {foo: i, foo: greet}?.str {foo: i, foo: i >= 1} {foo: i, foo: i, foo: 0}?.ok {foo: i, foo: i} {foo: i, foo: i}.String {foo: i, foo: i}.f64 {foo: i, foo: i}.foo {foo: i, foo: i}?.Bar {foo: i, foo: i}?.[str] {foo: i, foo: i}?.i {foo: i, foo: list | reduce(greet)} {foo: i, foo: list} {foo: i, foo: list}?.String {foo: i, foo: list}?.[str] {foo: i, foo: list}?.array {foo: i, foo: list}?.list {foo: i, foo: map(list, foo)} {foo: i, foo: nil, foo: true}.array {foo: i, foo: nil}.array {foo: i, foo: nil}.array?.f64 {foo: i, foo: nil}.foo {foo: i, foo: nil}.list {foo: i, foo: nil}?.Bar {foo: i, foo: nil}?.[str] {foo: i, foo: nil}?.add {foo: i, foo: nil}?.foo {foo: i, foo: nil}?.list {foo: i, foo: ok, foo: 1.0}?.ok {foo: i, foo: ok, foo: ok}.greet?.list(array) {foo: i, foo: ok} {foo: i, foo: sortBy(array, #)}.i {foo: i, foo: str} {foo: i, foo: str}.array {foo: i, foo: str}.f64 {foo: i, foo: str}.foo {foo: i, foo: str}.foobar?.i() {foo: i, foo: str}.i {foo: i, foo: str}?.Bar {foo: i, foo: str}?.add {foo: i, foo: str}?.add?.[str] {foo: i, foo: str}?.f64 {foo: i, foo: str}?.greet {foo: i, foo: str}?.list {foo: i, foo: true, foo: add}.str {foo: i, foo: true, foo: foo}.Bar {foo: i, foo: true}.foo {foo: i, foo: true}?.f64 {foo: i, foo: true}?.list {foo: i, foo: true}?.ok {foo: i, foo: true}?.str {foo: i, foo: {foo: add, foo: true}} {foo: i, foo: {foo: str}} {foo: i, foo: {foo: true}}?.foo {foo: i..i} {foo: if false { 1 } else { 1.0 }} {foo: if false { foo } else { $env }} {foo: if false { str } else { array }} {foo: if false { true } else { greet }} {foo: if ok { 1 } else { foo }} {foo: if true { $env } else { array }} {foo: if true { 0 } else { 1.0 }} {foo: if true { 1.0 } else { foo }} {foo: if true { f64 } else { add }} {foo: if true { foo } else { greet }} {foo: if true { ok } else { foo }} {foo: int(0)} {foo: int(1)} {foo: int(1.0)} {foo: int(f64)} {foo: int(f64)}?.foobar?.list() {foo: int(i)} {foo: i} {foo: i} ?? add {foo: i} not in [nil] {foo: i}.$env?.Bar(Bar) {foo: i}.Bar {foo: i}.Bar?.list {foo: i}.String {foo: i}.String?.i {foo: i}.add {foo: i}.add?.[list]?.[greet] {foo: i}.add?.add {foo: i}.add?.list() {foo: i}.array {foo: i}.array?.Bar {foo: i}.array?.[str] {foo: i}.f64 {foo: i}.f64?.[foo] {foo: i}.f64?.[list] {foo: i}.f64?.foo {foo: i}.foo {foo: i}.foo ?? 1 {foo: i}.foobar {foo: i}.greet {foo: i}.greet?.add {foo: i}.greet?.greet {foo: i}.i {foo: i}.i?.ok() {foo: i}.list {foo: i}.list?.greet() {foo: i}.nil?.array {foo: i}.not {foo: i}.ok {foo: i}.ok?.f64 {foo: i}.str {foo: i}.str?.[nil] {foo: i}?.Bar {foo: i}?.Bar?.String {foo: i}?.String {foo: i}?.String?.[str] {foo: i}?.[str] {foo: i}?.[str]?.[add] {foo: i}?.add {foo: i}?.add?.String() {foo: i}?.array {foo: i}?.array?.[foo] {foo: i}?.array?.greet {foo: i}?.f64 {foo: i}?.f64?.greet {foo: i}?.foo {foo: i}?.foo == add {foo: i}?.foobar {foo: i}?.greet {foo: i}?.greet?.[greet] {foo: i}?.greet?.ok {foo: i}?.i {foo: i}?.i?.f64 {foo: i}?.list {foo: i}?.list?.ok {foo: i}?.nil not contains $env {foo: i}?.ok {foo: i}?.ok?.array {foo: i}?.str {foo: i}?.str?.str {foo: keys($env), foo: list} {foo: keys($env)} {foo: keys($env)}?.i {foo: keys($env)}?.list {foo: keys($env)}?.ok {foo: last($env)?.String} {foo: last($env)} {foo: last(array)} {foo: last(list), foo: ok} {foo: last(list)} {foo: len($env)} {foo: len($env)}.foo {foo: len(array)} {foo: len(list)} {foo: len({foo: true})} {foo: let foobar = false; foobar} {foo: let foobar = str; foobar} {foo: let tmp = ok; tmp} {foo: list != $env} {foo: list != array} {foo: list != list} {foo: list != nil} {foo: list == $env?.[str]} {foo: list == $env} {foo: list == list} {foo: list == list}.array {foo: list == nil} {foo: list ?? $env} {foo: list ?? 0} {foo: list ?? 1.0} {foo: list ?? f64} {foo: list ?? foo} {foo: list ?? greet} {foo: list ?? list} {foo: list ?? nil} {foo: list ?? str} {foo: list | all(ok)} {foo: list | all(true)} {foo: list | count(false)} {foo: list | findIndex(false)} {foo: list | findIndex(true)}.add {foo: list | groupBy(#)} {foo: list | groupBy(1.0)} {foo: list | groupBy(foo)} {foo: list | groupBy(ok)} {foo: list | groupBy(str)} {foo: list | map(#)} {foo: list | map(1.0)} {foo: list | map(i)} {foo: list | one(false)} {foo: list | reduce(#)} {foo: list | reduce(#.Bar, nil)} {foo: list | reduce(#.String, nil)} {foo: list | reduce($env)} {foo: list | reduce(0)} {foo: list | reduce(f64)} {foo: list | reduce(false)} {foo: list | reduce(foo)} {foo: list | reduce(ok)} {foo: list | reduce(str)} {foo: list | sortBy(.Bar)} {foo: list | sortBy(0)} {foo: list | sortBy(1), foo: str}.foo {foo: list | sortBy(1.0)} {foo: list | sortBy(i)} {foo: list | sum(1.0)} {foo: list, foo: $env ?? list} {foo: list, foo: $env.f64} {foo: list, foo: $env.ok} {foo: list, foo: $env?.array} {foo: list, foo: $env?.f64} {foo: list, foo: $env}.String {foo: list, foo: $env}.add {foo: list, foo: $env}.foo {foo: list, foo: $env}.i {foo: list, foo: $env}.list {foo: list, foo: $env}.ok {foo: list, foo: $env}.str {foo: list, foo: $env}?.Bar {foo: list, foo: $env}?.add {foo: list, foo: $env}?.ok {foo: list, foo: $env}?.str {foo: list, foo: 0, foo: 0}?.add {foo: list, foo: 0, foo: nil}.add {foo: list, foo: 0}.list {foo: list, foo: 0}?.Bar {foo: list, foo: 0}?.list {foo: list, foo: 1, foo: false}?.list {foo: list, foo: 1.0 == 1.0} {foo: list, foo: 1.0, foo: true}?.i {foo: list, foo: 1.0}.f64 {foo: list, foo: 1.0}.foo {foo: list, foo: 1.0}.list {foo: list, foo: 1.0}?.String {foo: list, foo: 1.0}?.[str] {foo: list, foo: 1.0}?.add {foo: list, foo: 1.0}?.greet {foo: list, foo: 1.0}?.i {foo: list, foo: 1.0}?.ok {foo: list, foo: 1}.list {foo: list, foo: 1}?.String {foo: list, foo: 1}?.foo {foo: list, foo: 1}?.greet {foo: list, foo: 1}?.i {foo: list, foo: 1}?.list {foo: list, foo: add} {foo: list, foo: add}.array {foo: list, foo: add}.f64 {foo: list, foo: add}.greet {foo: list, foo: add}.i {foo: list, foo: add}?.[str] {foo: list, foo: add}?.array {foo: list, foo: add}?.f64 {foo: list, foo: array} {foo: list, foo: array}.f64 {foo: list, foo: array}.greet {foo: list, foo: array}.i {foo: list, foo: array}.ok {foo: list, foo: array}.str {foo: list, foo: array}?.array {foo: list, foo: array}?.f64 {foo: list, foo: array}?.ok {foo: list, foo: f64 - f64} {foo: list, foo: f64} {foo: list, foo: f64}.foo {foo: list, foo: f64}.greet {foo: list, foo: f64}?.Bar {foo: list, foo: false || $env} {foo: list, foo: false}.f64 {foo: list, foo: false}.foobar {foo: list, foo: false}?.[str] {foo: list, foo: false}?.add {foo: list, foo: false}?.f64 {foo: list, foo: false}?.foo {foo: list, foo: false}?.greet {foo: list, foo: false}?.i {foo: list, foo: false}?.ok {foo: list, foo: foo, foo: list}.Bar {foo: list, foo: foo, foo: true}.String {foo: list, foo: foo?.String()} {foo: list, foo: foo} {foo: list, foo: foo}.add {foo: list, foo: foo}.array {foo: list, foo: foo}.f64 {foo: list, foo: foo}.i {foo: list, foo: foo}.ok {foo: list, foo: foo}?.Bar {foo: list, foo: foo}?.[str] {foo: list, foo: foo}?.add {foo: list, foo: foo}?.foo {foo: list, foo: foo}?.foobar?.[str] {foo: list, foo: greet} {foo: list, foo: greet}.list {foo: list, foo: greet}.str {foo: list, foo: greet}?.greet {foo: list, foo: i, foo: 1.0}?.list {foo: list, foo: i} {foo: list, foo: i}.array {foo: list, foo: i}?.String?.add() {foo: list, foo: i}?.foo {foo: list, foo: i}?.list {foo: list, foo: list, foo: i}.foobar?.array {foo: list, foo: list} {foo: list, foo: list}.Bar {foo: list, foo: list}.String {foo: list, foo: list}.foo {foo: list, foo: list}.list {foo: list, foo: list}?.String {foo: list, foo: list}?.foo {foo: list, foo: list}?.greet {foo: list, foo: list}?.list {foo: list, foo: list}?.ok {foo: list, foo: max(0)} {foo: list, foo: median(array)} {foo: list, foo: nil} ?? f64 {foo: list, foo: nil}.String {foo: list, foo: nil}.add {foo: list, foo: nil}.foo {foo: list, foo: nil}.greet {foo: list, foo: nil}.list {foo: list, foo: nil}.str?.list {foo: list, foo: nil}?.String {foo: list, foo: nil}?.[str] {foo: list, foo: nil}?.i {foo: list, foo: nil}?.str {foo: list, foo: ok} {foo: list, foo: ok}.add {foo: list, foo: ok}.ok {foo: list, foo: ok}?.Bar {foo: list, foo: ok}?.[str] {foo: list, foo: ok}?.array {foo: list, foo: ok}?.foo {foo: list, foo: ok}?.i {foo: list, foo: str, foo: abs(f64)} {foo: list, foo: str} {foo: list, foo: str}.String {foo: list, foo: str}.array {foo: list, foo: str}.list {foo: list, foo: str}?.String {foo: list, foo: str}?.i {foo: list, foo: str}?.list {foo: list, foo: str}?.ok {foo: list, foo: sum(array)} {foo: list, foo: true, foo: add}?.ok {foo: list, foo: true, foo: foo}.list {foo: list, foo: true}.ok {foo: list, foo: true}?.array {foo: list?.[0]} {foo: list?.[1]}?.add {foo: list?.[i], foo: list} {foo: list?.[i], foo: ok} {foo: list?.[i]} {foo: list?.[i]}.greet?.[array] {foo: list?.[i]}.ok {foo: list[0:]} {foo: list[:0]} {foo: list[i:]} {foo: list} {foo: list} ?? reduce($env, 1.0, 1) {foo: list}.Bar {foo: list}.String {foo: list}.add {foo: list}.add?.str {foo: list}.array {foo: list}.array?.f64 {foo: list}.f64 {foo: list}.f64?.greet().list() {foo: list}.foo {foo: list}.foobar {foo: list}.foobar != true {foo: list}.greet {foo: list}.greet?.[str] {foo: list}.i {foo: list}.i?.[array] {foo: list}.i?.[foo] {foo: list}.list {foo: list}.list?.[f64] {foo: list}.list?.[greet] {foo: list}.ok {foo: list}.ok?.Bar {foo: list}.ok?.[f64] {foo: list}.str {foo: list}?.Bar {foo: list}?.Bar?.[foo] {foo: list}?.Bar?.[greet] {foo: list}?.Bar?.[list] {foo: list}?.Bar?.add {foo: list}?.String {foo: list}?.String?.[array] {foo: list}?.String?.list() {foo: list}?.[str] {foo: list}?.[str]?.[i] {foo: list}?.[str]?.list {foo: list}?.add {foo: list}?.array {foo: list}?.f64 {foo: list}?.f64?.array {foo: list}?.f64?.greet {foo: list}?.f64?.ok {foo: list}?.foo {foo: list}?.foobar {foo: list}?.greet {foo: list}?.greet?.list {foo: list}?.i {foo: list}?.i?.[greet] {foo: list}?.i?.[i] {foo: list}?.i?.array {foo: list}?.list {foo: list}?.ok {foo: list}?.ok?.[ok] {foo: list}?.str {foo: list}?.str?.[list] {foo: list}?.str?.[str] {foo: lower(str)} {foo: lower(str)}?.[str] {foo: map($env, $env)} {foo: map($env, 0)} {foo: map($env, 1)} {foo: map($env, 1.0), foo: i} {foo: map($env, 1.0)} {foo: map($env, array)} {foo: map($env, f64)} {foo: map($env, foo)} {foo: map($env, greet)} {foo: map($env, i)} {foo: map($env, i)}?.add {foo: map($env, list)} {foo: map($env, ok)} {foo: map($env, str)} {foo: map(array, #)} {foo: map(array, $env)} {foo: map(array, 1)} {foo: map(array, array)} {foo: map(array, foo)} {foo: map(list, #)} {foo: map(list, #.Bar)} {foo: map(list, $env)} {foo: map(list, .String)} {foo: map(list, add)} {foo: map(list, foo)} {foo: map(list, greet)} {foo: map(list, ok)} {foo: max($env), foo: array} {foo: max($env)} {foo: max($env)}.i {foo: max(0)} {foo: max(1)} {foo: max(1.0)} {foo: max(1.0, 1.0)} {foo: max(array)} {foo: max(f64)} {foo: max(f64)}?.str {foo: max(i)} {foo: mean(0)} {foo: mean(1)} {foo: mean(1, 0)} {foo: mean(1.0 * 1.0)} {foo: mean(1.0), foo: array} {foo: mean(1.0)} {foo: mean(1.0)}.ok {foo: mean(array)} {foo: mean(array, array)} {foo: mean(array, i)} {foo: mean(f64)} {foo: mean(i)} {foo: mean(i, 1)} {foo: median(0)} {foo: median(0)}?.ok {foo: median(1)} {foo: median(1.0)} {foo: median(array)} {foo: median(array, 1.0)} {foo: median(f64), foo: i} {foo: median(f64)} {foo: median(f64, i)}.i {foo: median(flatten(array))} {foo: median(i)} {foo: median(i, array)}.Bar {foo: min($env)?.String} {foo: min($env)} {foo: min(0)} {foo: min(1), foo: ok} {foo: min(1)} {foo: min(1, 1.0)} {foo: min(1.0)} {foo: min(1.0)}?.String {foo: min(array)} {foo: min(f64)} {foo: min(i)} {foo: min(i)}.list {foo: nil != $env, foo: foo} {foo: nil != $env} {foo: nil != 0} {foo: nil != 1.0} {foo: nil != 1} {foo: nil != 1}.ok {foo: nil != add} {foo: nil != array} {foo: nil != f64} {foo: nil != false, foo: i} {foo: nil != false} {foo: nil != foo?.String()} {foo: nil != foo} {foo: nil != foo}.str {foo: nil != greet} {foo: nil != i, foo: list} {foo: nil != list} {foo: nil != nil, foo: list} {foo: nil != nil} {foo: nil != ok} {foo: nil != str} {foo: nil != true} {foo: nil == $env} {foo: nil == 0} {foo: nil == 1.0} {foo: nil == 1} {foo: nil == add} {foo: nil == array} {foo: nil == f64} {foo: nil == false} {foo: nil == foo} {foo: nil == greet} {foo: nil == list}?.Bar {foo: nil == nil} {foo: nil == ok} {foo: nil == true} {foo: nil ?? $env} {foo: nil ?? 0} {foo: nil ?? 1.0} {foo: nil ?? 1} {foo: nil ?? add} {foo: nil ?? array} {foo: nil ?? f64} {foo: nil ?? false, foo: i} {foo: nil ?? false} {foo: nil ?? foo} {foo: nil ?? greet} {foo: nil ?? i} {foo: nil ?? list, foo: f64} {foo: nil ?? nil, foo: f64} {foo: nil ?? nil} {foo: nil ?? ok} {foo: nil in $env} {foo: nil in array} {foo: nil in list} {foo: nil not in $env} {foo: nil not in array} {foo: nil not in list} {foo: nil, foo: $env}.Bar {foo: nil, foo: $env}.String {foo: nil, foo: $env}.add {foo: nil, foo: $env}.array {foo: nil, foo: $env}.f64 {foo: nil, foo: $env}.foo {foo: nil, foo: $env}.foobar {foo: nil, foo: $env}.greet {foo: nil, foo: $env}.list {foo: nil, foo: $env}?.Bar {foo: nil, foo: $env}?.Bar?.[f64] {foo: nil, foo: $env}?.String {foo: nil, foo: $env}?.add {foo: nil, foo: $env}?.foo {foo: nil, foo: $env}?.i {foo: nil, foo: $env}?.list {foo: nil, foo: $env}?.str {foo: nil, foo: 0, foo: 0}.greet {foo: nil, foo: 0, foo: true}?.[str] {foo: nil, foo: 0}.Bar {foo: nil, foo: 0}.String {foo: nil, foo: 0}.f64 {foo: nil, foo: 0}.list {foo: nil, foo: 0}.ok {foo: nil, foo: 0}?.Bar {foo: nil, foo: 0}?.String?.[f64] {foo: nil, foo: 0}?.add {foo: nil, foo: 0}?.array {foo: nil, foo: 0}?.f64 {foo: nil, foo: 0}?.greet {foo: nil, foo: 0}?.ok {foo: nil, foo: 1, foo: false}?.String {foo: nil, foo: 1, foo: foo}.ok {foo: nil, foo: 1.0, foo: 1}.f64 {foo: nil, foo: 1.0, foo: array}?.str {foo: nil, foo: 1.0}.Bar {foo: nil, foo: 1.0}.String {foo: nil, foo: 1.0}.add {foo: nil, foo: 1.0}.array {foo: nil, foo: 1.0}.foo {foo: nil, foo: 1.0}.greet {foo: nil, foo: 1.0}.i {foo: nil, foo: 1.0}.list {foo: nil, foo: 1.0}.nil?.[greet] {foo: nil, foo: 1.0}.str {foo: nil, foo: 1.0}?.String {foo: nil, foo: 1.0}?.[str] {foo: nil, foo: 1.0}?.array {foo: nil, foo: 1.0}?.f64 {foo: nil, foo: 1.0}?.greet {foo: nil, foo: 1.0}?.i {foo: nil, foo: 1.0}?.list {foo: nil, foo: 1.0}?.ok {foo: nil, foo: 1.0}?.str {foo: nil, foo: 1}.Bar {foo: nil, foo: 1}.String {foo: nil, foo: 1}.add {foo: nil, foo: 1}.array {foo: nil, foo: 1}.f64 {foo: nil, foo: 1}.i {foo: nil, foo: 1}.list {foo: nil, foo: 1}?.[str] {foo: nil, foo: 1}?.add {foo: nil, foo: 1}?.f64 {foo: nil, foo: 1}?.foo {foo: nil, foo: add}.Bar {foo: nil, foo: add}.f64 {foo: nil, foo: add}.i {foo: nil, foo: add}.list {foo: nil, foo: add}?.Bar {foo: nil, foo: add}?.String {foo: nil, foo: add}?.add {foo: nil, foo: add}?.foo {foo: nil, foo: add}?.i {foo: nil, foo: add}?.ok {foo: nil, foo: array, foo: add}?.add {foo: nil, foo: array}.foo {foo: nil, foo: array}.str {foo: nil, foo: array}?.[str] {foo: nil, foo: array}?.array {foo: nil, foo: array}?.array?.[foo] {foo: nil, foo: array}?.f64 {foo: nil, foo: array}?.foobar {foo: nil, foo: array}?.greet {foo: nil, foo: array}?.i {foo: nil, foo: f64}.String {foo: nil, foo: f64}.add {foo: nil, foo: f64}.f64 {foo: nil, foo: f64}.greet {foo: nil, foo: f64}?.Bar {foo: nil, foo: f64}?.array {foo: nil, foo: f64}?.greet {foo: nil, foo: f64}?.ok {foo: nil, foo: false}.Bar {foo: nil, foo: false}.f64 {foo: nil, foo: false}.foo {foo: nil, foo: false}.list {foo: nil, foo: false}?.f64 {foo: nil, foo: false}?.greet {foo: nil, foo: false}?.i {foo: nil, foo: false}?.list {foo: nil, foo: false}?.ok {foo: nil, foo: foo, foo: 1}.foo {foo: nil, foo: foo, foo: 1}.i {foo: nil, foo: foo, foo: false}?.array {foo: nil, foo: foo, foo: i}?.i {foo: nil, foo: foo, foo: list}.Bar {foo: nil, foo: foo, foo: true}.ok {foo: nil, foo: foo}.String {foo: nil, foo: foo}.add {foo: nil, foo: foo}.array {foo: nil, foo: foo}.foo {foo: nil, foo: foo}.greet {foo: nil, foo: foo}.i {foo: nil, foo: foo}.ok {foo: nil, foo: foo}.str {foo: nil, foo: foo}?.Bar {foo: nil, foo: foo}?.[str] {foo: nil, foo: foo}?.add {foo: nil, foo: foo}?.f64 {foo: nil, foo: foo}?.foo {foo: nil, foo: foo}?.greet {foo: nil, foo: foo}?.i {foo: nil, foo: foo}?.list in list {foo: nil, foo: foo}?.ok {foo: nil, foo: foo}?.ok?.Bar() {foo: nil, foo: foo}?.str {foo: nil, foo: greet, foo: nil}.add {foo: nil, foo: greet}.String {foo: nil, foo: greet}.array {foo: nil, foo: greet}.i {foo: nil, foo: greet}.ok {foo: nil, foo: greet}?.f64 {foo: nil, foo: greet}?.foo {foo: nil, foo: greet}?.greet {foo: nil, foo: greet}?.i {foo: nil, foo: greet}?.str {foo: nil, foo: i, foo: $env}.f64 {foo: nil, foo: i, foo: foo}?.i {foo: nil, foo: i, foo: greet}?.String {foo: nil, foo: i}.f64 {foo: nil, foo: i}.foo {foo: nil, foo: i}.greet {foo: nil, foo: i}.i {foo: nil, foo: i}.list {foo: nil, foo: i}.ok {foo: nil, foo: i}?.String {foo: nil, foo: i}?.array {foo: nil, foo: list, foo: add}.Bar {foo: nil, foo: list, foo: nil}.f64 {foo: nil, foo: list}.Bar {foo: nil, foo: list}.f64 {foo: nil, foo: list}.f64?.str {foo: nil, foo: list}.ok {foo: nil, foo: list}?.Bar {foo: nil, foo: list}?.f64 {foo: nil, foo: list}?.foo {foo: nil, foo: list}?.i {foo: nil, foo: list}?.str {foo: nil, foo: nil, foo: 1.0}?.array {foo: nil, foo: nil, foo: greet}?.[str] {foo: nil, foo: nil, foo: i}?.String {foo: nil, foo: nil, foo: true}?.greet {foo: nil, foo: nil}.array {foo: nil, foo: nil}.foo {foo: nil, foo: nil}.greet {foo: nil, foo: nil}.i {foo: nil, foo: nil}.ok {foo: nil, foo: nil}.str {foo: nil, foo: nil}?.Bar {foo: nil, foo: nil}?.String {foo: nil, foo: nil}?.add {foo: nil, foo: nil}?.array {foo: nil, foo: nil}?.array?.array(foobar) {foo: nil, foo: nil}?.f64 {foo: nil, foo: nil}?.foo {foo: nil, foo: nil}?.i {foo: nil, foo: nil}?.list {foo: nil, foo: nil}?.ok {foo: nil, foo: nil}?.str {foo: nil, foo: ok, foo: nil}.String {foo: nil, foo: ok}.Bar {foo: nil, foo: ok}.String {foo: nil, foo: ok}.add {foo: nil, foo: ok}.array {foo: nil, foo: ok}.f64 {foo: nil, foo: ok}.foo {foo: nil, foo: ok}.i {foo: nil, foo: ok}?.Bar?.[add] {foo: nil, foo: ok}?.array {foo: nil, foo: ok}?.f64 {foo: nil, foo: ok}?.foo {foo: nil, foo: ok}?.str?.[greet] {foo: nil, foo: str}.String {foo: nil, foo: str}.add {foo: nil, foo: str}.array {foo: nil, foo: str}.f64 {foo: nil, foo: str}.foo {foo: nil, foo: str}.greet {foo: nil, foo: str}.i {foo: nil, foo: str}.ok {foo: nil, foo: str}.str {foo: nil, foo: str}?.add {foo: nil, foo: str}?.f64 {foo: nil, foo: true, foo: str}.list {foo: nil, foo: true}.String {foo: nil, foo: true}.f64 {foo: nil, foo: true}.ok {foo: nil, foo: true}.str {foo: nil, foo: true}?.String {foo: nil, foo: true}?.i {foo: nil, foo: true}?.ok {foo: nil} ?? array {foo: nil} ?? foo {foo: nil} ?? ok {foo: nil} not in $env?.[String] {foo: nil}.Bar {foo: nil}.Bar?.add?.list {foo: nil}.Bar?.f64 {foo: nil}.String {foo: nil}.String?.[i] {foo: nil}.String?.array {foo: nil}.String?.greet {foo: nil}.add {foo: nil}.add?.[ok] {foo: nil}.add?.[str] {foo: nil}.array {foo: nil}.array?.[array] {foo: nil}.array?.[foo] {foo: nil}.array?.[i] {foo: nil}.array?.[ok] {foo: nil}.array?.[str] {foo: nil}.array?.str {foo: nil}.f64 {foo: nil}.f64?.[list].ok {foo: nil}.f64?.f64 {foo: nil}.f64?.i {foo: nil}.foo {foo: nil}.foo?.[list] {foo: nil}.foo?.ok {foo: nil}.foobar {foo: nil}.foobar?.i {foo: nil}.greet {foo: nil}.greet?.[add] {foo: nil}.greet?.[f64] {foo: nil}.greet?.[foo] {foo: nil}.greet?.greet(foo) {foo: nil}.i {foo: nil}.list {foo: nil}.list?.String {foo: nil}.list?.String() {foo: nil}.list?.list {foo: nil}.not {foo: nil}.ok {foo: nil}.ok?.String {foo: nil}.ok?.greet {foo: nil}.str {foo: nil}.str?.ok {foo: nil}?.$env?.str {foo: nil}?.Bar {foo: nil}?.Bar?.String {foo: nil}?.String {foo: nil}?.String?.add {foo: nil}?.String?.greet {foo: nil}?.[str] {foo: nil}?.[str]?.[list] {foo: nil}?.[str]?.[str] {foo: nil}?.[str]?.ok {foo: nil}?.add {foo: nil}?.add?.Bar {foo: nil}?.add?.add {foo: nil}?.array {foo: nil}?.array?.Bar {foo: nil}?.f64 {foo: nil}?.f64?.[i] {foo: nil}?.foo {foo: nil}?.foo != f64 {foo: nil}?.foo?.[f64] {foo: nil}?.foo?.[ok] {foo: nil}?.foo?.i {foo: nil}?.foo?.str {foo: nil}?.foobar {foo: nil}?.foobar or true {foo: nil}?.foobar?.add {foo: nil}?.greet {foo: nil}?.greet?.ok {foo: nil}?.i {foo: nil}?.i?.[greet] {foo: nil}?.i?.[str] {foo: nil}?.list {foo: nil}?.list?.[list] {foo: nil}?.list?.f64(foobar) {foo: nil}?.ok {foo: nil}?.ok?.[f64] {foo: nil}?.ok?.add {foo: nil}?.str {foo: nil}?.str?.f64() {foo: nil}?.str?.list {foo: nil}?.str?.ok {foo: none($env, false)} {foo: none($env, ok)} {foo: none($env, true)} {foo: none(list, ok)} {foo: none(list, true)} {foo: not false} {foo: not false}?.add {foo: not false}?.ok {foo: not ok && $env} {foo: not ok} {foo: not true, foo: add} {foo: not true, foo: array} {foo: not true, foo: str} {foo: not true} {foo: not true}.f64 {foo: not true}?.str {foo: ok != $env} {foo: ok != false} {foo: ok != nil} {foo: ok != ok} {foo: ok != true} {foo: ok && $env} {foo: ok && false} {foo: ok && ok} {foo: ok == $env} {foo: ok == $env}.String {foo: ok == false} {foo: ok == nil} {foo: ok == ok} {foo: ok == true} {foo: ok == true}.f64 {foo: ok ? 1.0 : 1} {foo: ok ? 1.0 : greet} {foo: ok ? add : f64} {foo: ok ? foo : 0} {foo: ok ? greet : add} {foo: ok ? greet : list} {foo: ok ? nil : foo} {foo: ok ?: array} {foo: ok ?: nil} {foo: ok ?? $env} {foo: ok ?? 0} {foo: ok ?? 1.0} {foo: ok ?? 1} {foo: ok ?? array} {foo: ok ?? false} {foo: ok ?? foo} {foo: ok ?? i} {foo: ok ?? list} {foo: ok ?? true, foo: $env.list} {foo: ok and $env} {foo: ok and true} {foo: ok or $env} {foo: ok or false} {foo: ok || $env} {foo: ok || ok} {foo: ok || true} {foo: ok, foo: $env, foo: foo}?.array {foo: ok, foo: $env.add} {foo: ok, foo: $env.str} {foo: ok, foo: $env?.array} {foo: ok, foo: $env?.i, foo: str} {foo: ok, foo: $env}.foo {foo: ok, foo: $env}.i {foo: ok, foo: $env}.ok {foo: ok, foo: $env}?.Bar {foo: ok, foo: $env}?.String {foo: ok, foo: $env}?.[str] {foo: ok, foo: $env}?.add {foo: ok, foo: $env}?.f64 {foo: ok, foo: $env}?.str {foo: ok, foo: 0 > i} {foo: ok, foo: 0, foo: 1.0}.String {foo: ok, foo: 0, foo: array}?.String {foo: ok, foo: 0}.Bar {foo: ok, foo: 0}.String {foo: ok, foo: 0}.ok {foo: ok, foo: 0}?.list {foo: ok, foo: 0}?.ok {foo: ok, foo: 0}?.str {foo: ok, foo: 1, foo: nil}?.str {foo: ok, foo: 1.0 - i} {foo: ok, foo: 1.0}.Bar {foo: ok, foo: 1.0}.f64 {foo: ok, foo: 1.0}.foo {foo: ok, foo: 1.0}.greet {foo: ok, foo: 1.0}.i {foo: ok, foo: 1.0}.list {foo: ok, foo: 1.0}.ok {foo: ok, foo: 1.0}.str {foo: ok, foo: 1.0}?.Bar {foo: ok, foo: 1.0}?.f64 {foo: ok, foo: 1.0}?.foo {foo: ok, foo: 1.0}?.greet {foo: ok, foo: 1.0}?.i {foo: ok, foo: 1.0}?.ok {foo: ok, foo: 1}.array {foo: ok, foo: 1}.greet {foo: ok, foo: 1}?.[str] {foo: ok, foo: 1}?.add?.String {foo: ok, foo: 1}?.greet {foo: ok, foo: add ?? 1.0} {foo: ok, foo: add, foo: 1.0}?.greet {foo: ok, foo: add} {foo: ok, foo: add}.greet {foo: ok, foo: add}.i {foo: ok, foo: add}?.foo {foo: ok, foo: add}?.greet?.ok {foo: ok, foo: array | map(1.0)} {foo: ok, foo: array} {foo: ok, foo: array}.String {foo: ok, foo: array}.greet {foo: ok, foo: array}.str {foo: ok, foo: array}?.String {foo: ok, foo: array}?.String?.[f64] {foo: ok, foo: array}?.add {foo: ok, foo: array}?.f64 {foo: ok, foo: array}?.foo {foo: ok, foo: array}?.list {foo: ok, foo: f64 <= i} {foo: ok, foo: f64, foo: $env}?.foo {foo: ok, foo: f64} {foo: ok, foo: f64}.foo {foo: ok, foo: f64}.greet {foo: ok, foo: f64}.i {foo: ok, foo: f64}?.Bar {foo: ok, foo: f64}?.array {foo: ok, foo: f64}?.f64 {foo: ok, foo: f64}?.foo {foo: ok, foo: f64}?.greet {foo: ok, foo: f64}?.i {foo: ok, foo: false}?.String {foo: ok, foo: false}?.f64 {foo: ok, foo: false}?.ok {foo: ok, foo: false}?.str {foo: ok, foo: foo?.Bar} {foo: ok, foo: foo} {foo: ok, foo: foo}.Bar {foo: ok, foo: foo}.add {foo: ok, foo: foo}.array {foo: ok, foo: foo}.f64 {foo: ok, foo: foo}.foo {foo: ok, foo: foo}.greet {foo: ok, foo: foo}.i {foo: ok, foo: foo}.list {foo: ok, foo: foo}.ok {foo: ok, foo: foo}.str {foo: ok, foo: foo}?.Bar {foo: ok, foo: foo}?.array {foo: ok, foo: foo}?.f64 {foo: ok, foo: foo}?.foo {foo: ok, foo: foo}?.list {foo: ok, foo: foo}?.ok {foo: ok, foo: foo}?.str {foo: ok, foo: greet} {foo: ok, foo: greet}.greet {foo: ok, foo: greet}.i {foo: ok, foo: greet}?.greet {foo: ok, foo: greet}?.list {foo: ok, foo: i <= f64} {foo: ok, foo: i, foo: true}.foo {foo: ok, foo: i} {foo: ok, foo: i}.Bar {foo: ok, foo: i}.list {foo: ok, foo: i}?.list {foo: ok, foo: list, foo: 0}.i {foo: ok, foo: list} {foo: ok, foo: list}.i {foo: ok, foo: list}.str {foo: ok, foo: list}?.array {foo: ok, foo: list}?.foo {foo: ok, foo: list}?.greet {foo: ok, foo: list}?.ok {foo: ok, foo: list}?.str {foo: ok, foo: mean(0)} {foo: ok, foo: nil == ok} {foo: ok, foo: nil, foo: $env}?.ok {foo: ok, foo: nil, foo: greet}.i {foo: ok, foo: nil, foo: greet}?.add {foo: ok, foo: nil} ?? i {foo: ok, foo: nil}.Bar {foo: ok, foo: nil}.String {foo: ok, foo: nil}.add {foo: ok, foo: nil}.array {foo: ok, foo: nil}.foo {foo: ok, foo: nil}.greet {foo: ok, foo: nil}.i {foo: ok, foo: nil}.list {foo: ok, foo: nil}?.foo {foo: ok, foo: nil}?.ok {foo: ok, foo: nil}?.str {foo: ok, foo: nil}?.str?.i() {foo: ok, foo: ok} {foo: ok, foo: ok}.f64 {foo: ok, foo: ok}.i?.greet {foo: ok, foo: ok}?.list {foo: ok, foo: str} {foo: ok, foo: str}.f64 {foo: ok, foo: str}.greet {foo: ok, foo: str}?.f64 {foo: ok, foo: str}?.list {foo: ok, foo: true, foo: str}?.String {foo: ok, foo: true}.Bar {foo: ok, foo: true}.array {foo: ok, foo: true}.greet {foo: ok, foo: true}.true?.add {foo: ok, foo: true}?.Bar {foo: ok, foo: true}?.[str] {foo: ok, foo: true}?.add {foo: ok, foo: true}?.array?.greet {foo: ok, foo: true}?.f64 {foo: ok, foo: true}?.list {foo: ok, foo: true}?.ok {foo: ok, foo: true}?.str {foo: ok} {foo: ok} ?? str {foo: ok}.Bar {foo: ok}.String {foo: ok}.add {foo: ok}.add?.greet() {foo: ok}.array {foo: ok}.array?.String {foo: ok}.f64 {foo: ok}.f64?.[greet] {foo: ok}.foo {foo: ok}.foobar {foo: ok}.greet {foo: ok}.greet?.add {foo: ok}.i {foo: ok}.i?.[list] {foo: ok}.i?.[ok] {foo: ok}.list {foo: ok}.ok {foo: ok}.ok matches $env {foo: ok}.ok?.greet {foo: ok}.str {foo: ok}?.Bar {foo: ok}?.Bar?.[greet] {foo: ok}?.Bar?.[list] {foo: ok}?.Bar?.[str] {foo: ok}?.String {foo: ok}?.String?.[i] {foo: ok}?.String?.[str] {foo: ok}?.[str] {foo: ok}?.[str]?.[array] {foo: ok}?.add {foo: ok}?.add?.String?.ok {foo: ok}?.array {foo: ok}?.array?.i {foo: ok}?.array?.str {foo: ok}?.f64 {foo: ok}?.foo {foo: ok}?.foo != foo {foo: ok}?.foobar {foo: ok}?.foobar?.ok(foo) {foo: ok}?.greet {foo: ok}?.i {foo: ok}?.i?.ok {foo: ok}?.list {foo: ok}?.nil?.greet {foo: ok}?.ok {foo: ok}?.str {foo: one($env, false)} {foo: one($env, true)} {foo: one(array, ok)} {foo: one(array, true)} {foo: one(list, false)} {foo: one(list, ok)} {foo: one(list, true)} {foo: reduce($env, #acc, foo)} {foo: reduce(array, #)} {foo: reduce(array, $env, $env)} {foo: reduce(array, 0)} {foo: reduce(array, add)} {foo: reduce(array, array)} {foo: reduce(array, f64)} {foo: reduce(array, list)} {foo: reduce(array, ok, $env)} {foo: reduce(array, str)} {foo: reduce(list, #)} {foo: reduce(list, #.Bar)} {foo: reduce(list, #.String)} {foo: reduce(list, $env)} {foo: reduce(list, 1.0)} {foo: reduce(list, add)} {foo: reduce(list, array)}.str {foo: reduce(list, f64)} {foo: reduce(list, false), foo: 1.0 * f64} {foo: reduce(list, false)} {foo: reduce(list, foo)} {foo: reduce(list, ok)} {foo: reduce(list, str)} {foo: reduce(map(array, $env), #.list | reduce(foo))} {foo: reverse(array)} {foo: reverse(list)} {foo: round(0)} {foo: round(0)}?.Bar {foo: round(1)} {foo: round(1.0), foo: str} {foo: round(1.0)} {foo: round(f64)} {foo: round(i)} {foo: round(i)}?.ok {foo: sort($env)} {foo: sort(array), foo: str} {foo: sort(array)} {foo: sortBy(array, #)} {foo: sortBy(array, 0)} {foo: sortBy(array, 1)} {foo: sortBy(array, 1.0)} {foo: sortBy(array, f64)} {foo: sortBy(list, #.Bar)} {foo: sortBy(list, 1.0)} {foo: sortBy(list, i)} {foo: sortBy(list, str)} {foo: str != $env?.[Bar]} {foo: str != $env} {foo: str < str} {foo: str == $env} {foo: str == nil} {foo: str == str} {foo: str >= str, foo: str} {foo: str ?? 0} {foo: str ?? 1.0} {foo: str ?? add} {foo: str ?? array} {foo: str ?? f64} {foo: str ?? false} {foo: str ?? foo} {foo: str ?? true} {foo: str contains str} {foo: str endsWith str} {foo: str in $env} {foo: str in foo} {foo: str matches str} {foo: str not contains str} {foo: str not endsWith str} {foo: str not in $env} {foo: str not in foo} {foo: str not matches str} {foo: str not startsWith str} {foo: str startsWith str} {foo: str, foo: $env != 0} {foo: str, foo: $env, foo: 0}?.add {foo: str, foo: $env, foo: nil}.str {foo: str, foo: $env.f64} {foo: str, foo: $env.greet} {foo: str, foo: $env?.add} {foo: str, foo: $env?.foobar} {foo: str, foo: $env}.foo {foo: str, foo: $env}.foobar?.list() {foo: str, foo: $env}.greet {foo: str, foo: $env}.list {foo: str, foo: $env}.str {foo: str, foo: $env}?.[str] {foo: str, foo: $env}?.f64 {foo: str, foo: $env}?.foo {foo: str, foo: $env}?.str {foo: str, foo: 0, foo: f64}?.foo {foo: str, foo: 0, foo: nil}?.add {foo: str, foo: 0}.add {foo: str, foo: 0}.foobar {foo: str, foo: 0}.ok {foo: str, foo: 0}?.add {foo: str, foo: 0}?.array {foo: str, foo: 0}?.ok {foo: str, foo: 1.0, foo: greet}?.add {foo: str, foo: 1.0}.String {foo: str, foo: 1.0}.f64 {foo: str, foo: 1.0}.foo {foo: str, foo: 1.0}.greet {foo: str, foo: 1.0}.i {foo: str, foo: 1.0}.list {foo: str, foo: 1.0}.ok {foo: str, foo: 1.0}.str {foo: str, foo: 1.0}?.[str] {foo: str, foo: 1.0}?.add {foo: str, foo: 1.0}?.foo {foo: str, foo: 1.0}?.ok {foo: str, foo: 1.0}?.str {foo: str, foo: 1}.Bar {foo: str, foo: 1}.foo {foo: str, foo: 1}.ok {foo: str, foo: 1}.str {foo: str, foo: 1}?.String {foo: str, foo: 1}?.add {foo: str, foo: 1}?.i {foo: str, foo: 1}?.list {foo: str, foo: [f64]} {foo: str, foo: add, foo: f64}?.ok {foo: str, foo: add, foo: str}?.f64 {foo: str, foo: add} {foo: str, foo: add}.Bar {foo: str, foo: add}.String {foo: str, foo: add}.f64 {foo: str, foo: add}.greet {foo: str, foo: add}.i {foo: str, foo: add}?.[str] {foo: str, foo: add}?.array {foo: str, foo: array} {foo: str, foo: array}.greet {foo: str, foo: array}.i {foo: str, foo: array}.list {foo: str, foo: array}.ok {foo: str, foo: array}?.String {foo: str, foo: array}?.add {foo: str, foo: array}?.foo {foo: str, foo: array}?.i {foo: str, foo: ceil(1.0)} {foo: str, foo: f64} {foo: str, foo: f64} ?? foo {foo: str, foo: f64}.add {foo: str, foo: f64}?.String {foo: str, foo: f64}?.add {foo: str, foo: f64}?.add?.[add] {foo: str, foo: f64}?.list {foo: str, foo: false}.array {foo: str, foo: false}.f64 {foo: str, foo: false}.i {foo: str, foo: false}?.[str] {foo: str, foo: false}?.greet?.[add] {foo: str, foo: false}?.i {foo: str, foo: false}?.str {foo: str, foo: foo, foo: array}?.str {foo: str, foo: foo.String} {foo: str, foo: foo} {foo: str, foo: foo}.Bar {foo: str, foo: foo}.array {foo: str, foo: foo}.f64?.foo {foo: str, foo: foo}.greet {foo: str, foo: foo}.i {foo: str, foo: foo}.list {foo: str, foo: foo}.ok {foo: str, foo: foo}.str {foo: str, foo: foo}?.[str]?.String() {foo: str, foo: foo}?.add {foo: str, foo: foo}?.f64 {foo: str, foo: foo}?.f64?.f64 {foo: str, foo: foo}?.greet {foo: str, foo: greet(str)} {foo: str, foo: greet} {foo: str, foo: greet}.Bar {foo: str, foo: greet}.String {foo: str, foo: greet}.greet?.[greet] {foo: str, foo: greet}.ok {foo: str, foo: greet}?.add {foo: str, foo: greet}?.array {foo: str, foo: i} {foo: str, foo: i}.Bar {foo: str, foo: i}.add {foo: str, foo: i}.array {foo: str, foo: i}.foo {foo: str, foo: i}?.Bar {foo: str, foo: i}?.list {foo: str, foo: last($env)} {foo: str, foo: list} {foo: str, foo: list}.String {foo: str, foo: list}.add {foo: str, foo: list}.f64 {foo: str, foo: list}.ok {foo: str, foo: list}?.add {foo: str, foo: list}?.foo {foo: str, foo: list}?.str {foo: str, foo: map($env, 0)} {foo: str, foo: median(1.0)} {foo: str, foo: nil, foo: i}?.array {foo: str, foo: nil}.add {foo: str, foo: nil}.i {foo: str, foo: nil}?.Bar {foo: str, foo: nil}?.i {foo: str, foo: nil}?.list {foo: str, foo: ok, foo: $env}.add {foo: str, foo: ok, foo: array} {foo: str, foo: ok} {foo: str, foo: ok}.f64 {foo: str, foo: ok}.list {foo: str, foo: ok}?.Bar {foo: str, foo: ok}?.String {foo: str, foo: ok}?.[str] {foo: str, foo: ok}?.foobar != foo {foo: str, foo: ok}?.greet {foo: str, foo: str, foo: true}?.add {foo: str, foo: str} {foo: str, foo: str}.add {foo: str, foo: str}.f64 {foo: str, foo: str}.foo {foo: str, foo: str}?.array {foo: str, foo: str}?.greet {foo: str, foo: str}?.list {foo: str, foo: toJSON(0)} {foo: str, foo: true}.Bar {foo: str, foo: true}.array {foo: str, foo: true}.ok?.String {foo: str, foo: true}?.Bar {foo: str, foo: true}?.array {foo: str, foo: true}?.foo {foo: str, foo: true}?.i {foo: str, foo: true}?.ok {foo: str[:1]} {foo: str[:i]} {foo: string($env), foo: list} {foo: string($env)} {foo: string(0)} {foo: string(1)} {foo: string(1.0), foo: add} {foo: string(1.0)} {foo: string(add)} {foo: string(array)} {foo: string(array)}.foo {foo: string(f64)} {foo: string(false), foo: add} {foo: string(foo)} {foo: string(greet), foo: array} {foo: string(greet)} {foo: string(greet)}.greet {foo: string(i)} {foo: string(list), foo: i} {foo: string(list)} {foo: string(nil)} {foo: string(ok)} {foo: string(str)} {foo: string(str)}.i {foo: string(true)} {foo: str} {foo: str} != $env?.[Bar] {foo: str} != nil || $env {foo: str} ?? $env.i {foo: str} ?? str {foo: str}.Bar {foo: str}.String {foo: str}.String?.[ok] {foo: str}.add {foo: str}.array {foo: str}.f64 {foo: str}.f64?.[list] {foo: str}.f64?.[str] {foo: str}.foo {foo: str}.foobar?.Bar {foo: str}.greet {foo: str}.greet?.array {foo: str}.greet?.array?.i {foo: str}.i {foo: str}.list {foo: str}.list?.[add] {foo: str}.ok {foo: str}.ok?.array {foo: str}.ok?.str {foo: str}.str {foo: str}?.Bar {foo: str}?.Bar?.String {foo: str}?.Bar?.[str] {foo: str}?.String {foo: str}?.String?.[i] {foo: str}?.[str] {foo: str}?.[str]?.greet {foo: str}?.add {foo: str}?.add?.add {foo: str}?.array {foo: str}?.array?.[i] {foo: str}?.array?.ok {foo: str}?.f64 {foo: str}?.f64?.[f64] {foo: str}?.foo {foo: str}?.foobar {foo: str}?.greet {foo: str}?.greet?.Bar {foo: str}?.greet?.greet {foo: str}?.greet?.i {foo: str}?.i {foo: str}?.i in array {foo: str}?.i?.[ok] {foo: str}?.list {foo: str}?.list?.[array] {foo: str}?.nil?.Bar(true) {foo: str}?.ok {foo: str}?.ok not endsWith $env {foo: str}?.ok?.[ok] {foo: str}?.str {foo: str}?.str?.f64 {foo: sum($env, 1)} {foo: sum($env, 1.0)} {foo: sum($env, f64)} {foo: sum($env, i)} {foo: sum(array), foo: list} {foo: sum(array), foo: ok} {foo: sum(array)} {foo: sum(array)}.String {foo: sum(array)}.foo {foo: sum(array)}?.array {foo: sum(array, #)} {foo: sum(array, 1.0)} {foo: sum(list, 1)} {foo: sum(list, 1.0)} {foo: take(list, 1)} {foo: toBase64(str)} {foo: toJSON(0)} {foo: toJSON(1)} {foo: toJSON(1.0), foo: f64} {foo: toJSON(1.0)} {foo: toJSON(array)} {foo: toJSON(f64), foo: array} {foo: toJSON(f64)} {foo: toJSON(false)} {foo: toJSON(false)}.list {foo: toJSON(foo), foo: foo?.String} {foo: toJSON(foo)} {foo: toJSON(i), foo: add} {foo: toJSON(i)} {foo: toJSON(list)} {foo: toJSON(nil)} {foo: toJSON(ok)} {foo: toJSON(str)} {foo: toJSON(true)} {foo: toPairs($env), foo: list} {foo: toPairs($env)} {foo: trim(foo?.Bar)} {foo: trim(str)} {foo: trimPrefix(foo.Bar)} {foo: trimPrefix(str)} {foo: trimSuffix(str)} {foo: trimSuffix(string(nil))} {foo: true != $env} {foo: true != false} {foo: true != nil} {foo: true != ok} {foo: true && $env} {foo: true && true} {foo: true && true}.String {foo: true == $env} {foo: true == false} {foo: true == nil, foo: i} {foo: true == nil} {foo: true == true} {foo: true ? 1 : 1.0} {foo: true ? add : i} {foo: true ? false : greet} {foo: true ? list : 1} {foo: true ? ok : 0} {foo: true ?: foo} {foo: true ?? 0} {foo: true ?? 1} {foo: true ?? f64} {foo: true ?? foo} {foo: true ?? greet} {foo: true ?? nil} {foo: true ?? str} {foo: true and ok} {foo: true or $env} {foo: true or $env}?.[str] {foo: true or false} {foo: true or ok} {foo: true or true} {foo: true || $env} {foo: true || false} {foo: true || ok} {foo: true || true} {foo: true, foo: $env, foo: 1.0}?.greet {foo: true, foo: $env} ?? foo.Bar {foo: true, foo: $env}.array {foo: true, foo: $env}.f64 {foo: true, foo: $env}.greet {foo: true, foo: $env}.i {foo: true, foo: $env}.list {foo: true, foo: $env}?.String {foo: true, foo: $env}?.[str] {foo: true, foo: $env}?.add {foo: true, foo: $env}?.array {foo: true, foo: $env}?.foo {foo: true, foo: $env}?.i {foo: true, foo: $env}?.list {foo: true, foo: $env}?.ok {foo: true, foo: 0} != array ?? ok {foo: true, foo: 0}.$env?.[i]?.f64?.[add] {foo: true, foo: 0}.foo {foo: true, foo: 0}.str {foo: true, foo: 0}?.array {foo: true, foo: 0}?.i {foo: true, foo: 1.0, foo: nil}.list {foo: true, foo: 1.0, foo: true}?.[str] {foo: true, foo: 1.0}.Bar {foo: true, foo: 1.0}.array {foo: true, foo: 1.0}.i {foo: true, foo: 1.0}.i?.[str].add {foo: true, foo: 1.0}.ok {foo: true, foo: 1.0}?.String {foo: true, foo: 1.0}?.f64 {foo: true, foo: 1.0}?.i {foo: true, foo: 1.0}?.list {foo: true, foo: 1.0}?.ok {foo: true, foo: 1.0}?.str {foo: true, foo: 1}.Bar {foo: true, foo: 1}.array {foo: true, foo: 1}.foo {foo: true, foo: 1}.i {foo: true, foo: 1}?.[str] {foo: true, foo: 1}?.foo {foo: true, foo: 1}?.greet {foo: true, foo: 1}?.ok {foo: true, foo: 1}?.str {foo: true, foo: add}.add {foo: true, foo: add}.f64 {foo: true, foo: add}.i {foo: true, foo: add}?.Bar {foo: true, foo: add}?.String {foo: true, foo: add}?.array {foo: true, foo: add}?.f64 {foo: true, foo: add}?.greet {foo: true, foo: add}?.str {foo: true, foo: array}.add {foo: true, foo: array}.f64 {foo: true, foo: array}.i {foo: true, foo: array}?.add {foo: true, foo: array}?.greet {foo: true, foo: f64}.greet {foo: true, foo: f64}.i {foo: true, foo: f64}.ok {foo: true, foo: f64}?.foo {foo: true, foo: false}.Bar {foo: true, foo: false}.i?.[ok] {foo: true, foo: false}?.foo {foo: true, foo: false}?.greet {foo: true, foo: false}?.i {foo: true, foo: foo}.Bar {foo: true, foo: foo}.String {foo: true, foo: foo}.array {foo: true, foo: foo}.f64 {foo: true, foo: foo}.greet {foo: true, foo: foo}.i {foo: true, foo: foo}.ok {foo: true, foo: foo}.str?.list() {foo: true, foo: foo}?.Bar {foo: true, foo: foo}?.String {foo: true, foo: foo}?.[str] {foo: true, foo: foo}?.add {foo: true, foo: foo}?.f64 {foo: true, foo: foo}?.greet {foo: true, foo: foo}?.list {foo: true, foo: foo}?.ok {foo: true, foo: foo}?.str {foo: true, foo: greet}.Bar {foo: true, foo: greet}.array {foo: true, foo: greet}.f64 {foo: true, foo: greet}.foo {foo: true, foo: greet}?.[str] {foo: true, foo: greet}?.f64 {foo: true, foo: greet}?.str {foo: true, foo: i}.String {foo: true, foo: i}.add {foo: true, foo: i}.i {foo: true, foo: i}.str {foo: true, foo: i}?.Bar {foo: true, foo: i}?.[str]?.add {foo: true, foo: i}?.array {foo: true, foo: i}?.list {foo: true, foo: list}.String {foo: true, foo: list}.String?.Bar {foo: true, foo: list}.array {foo: true, foo: list}?.Bar {foo: true, foo: list}?.[str] {foo: true, foo: list}?.f64 {foo: true, foo: list}?.foo {foo: true, foo: list}?.greet {foo: true, foo: nil, foo: i}?.i?.i {foo: true, foo: nil, foo: list}?.[str] {foo: true, foo: nil}.add {foo: true, foo: nil}?.Bar {foo: true, foo: nil}?.String {foo: true, foo: nil}?.add {foo: true, foo: nil}?.greet {foo: true, foo: ok, foo: 1.0}?.greet {foo: true, foo: ok}.Bar {foo: true, foo: ok}.add {foo: true, foo: ok}.array {foo: true, foo: ok}.foo {foo: true, foo: ok}.list {foo: true, foo: ok}?.[str] {foo: true, foo: str}.Bar {foo: true, foo: str}.array {foo: true, foo: str}.f64 {foo: true, foo: str}.greet {foo: true, foo: str}.list {foo: true, foo: str}.ok {foo: true, foo: str}.str {foo: true, foo: str}?.array {foo: true, foo: str}?.array?.add {foo: true, foo: str}?.f64 {foo: true, foo: str}?.greet {foo: true, foo: str}?.ok {foo: true, foo: true, foo: greet}?.f64 {foo: true, foo: true}.add {foo: true, foo: true}.foo {foo: true, foo: true}.i {foo: true, foo: true}.list {foo: true, foo: true}?.array {foo: true} not in $env?.String {foo: true}.Bar {foo: true}.Bar?.[add] {foo: true}.String {foo: true}.String?.[foo] {foo: true}.add {foo: true}.add?.i {foo: true}.array {foo: true}.f64 {foo: true}.f64?.add {foo: true}.f64?.array.i() {foo: true}.false == add {foo: true}.foo {foo: true}.foo ? ok : nil {foo: true}.foobar {foo: true}.greet {foo: true}.i {foo: true}.i == i {foo: true}.list {foo: true}.list?.[str] {foo: true}.ok {foo: true}.ok?.add {foo: true}.ok?.array {foo: true}.str {foo: true}.str?.[list] {foo: true}.str?.ok {foo: true}?.$env ?? i {foo: true}?.Bar {foo: true}?.Bar?.[list] {foo: true}?.Bar?.f64 {foo: true}?.Bar?.list {foo: true}?.String {foo: true}?.String?.[greet] {foo: true}?.String?.[ok] {foo: true}?.[str] {foo: true}?.[str]?.foo?.[greet] {foo: true}?.add {foo: true}?.add?.[add] {foo: true}?.add?.[foo] {foo: true}?.add?.ok {foo: true}?.array {foo: true}?.array?.[ok] {foo: true}?.f64 {foo: true}?.f64?.[add] {foo: true}?.foo {foo: true}?.foobar?.i() {foo: true}?.greet {foo: true}?.greet?.[greet] {foo: true}?.greet?.foo {foo: true}?.greet?.greet {foo: true}?.i {foo: true}?.i?.Bar {foo: true}?.i?.[ok] {foo: true}?.i?.foo {foo: true}?.list {foo: true}?.list?.[greet] {foo: true}?.ok {foo: true}?.ok?.Bar {foo: true}?.ok?.[greet]?.list {foo: true}?.str {foo: true}?.str?.[f64] {foo: true}?.str?.greet {foo: true}?.str?.i {foo: type($env)} {foo: type(0)} {foo: type(1)} {foo: type(1.0)} {foo: type(1.0)}?.[str] {foo: type(1.0)}?.f64 {foo: type(add)} {foo: type(array)} {foo: type(f64)} {foo: type(false)} {foo: type(foo), foo: add} {foo: type(foo), foo: f64} {foo: type(foo)} {foo: type(greet)} {foo: type(i)} {foo: type(list)} {foo: type(nil)} {foo: type(ok), foo: add} {foo: type(ok)} {foo: type(str)} {foo: type(true)} {foo: uniq(array)} {foo: uniq(list)} {foo: upper(str)} {foo: values($env)} {foo: values($env)}.String {foo: {foo: $env, foo: i}} {foo: {foo: $env}} {foo: {foo: $env}}?.i {foo: {foo: 0, foo: $env}} {foo: {foo: 0, foo: 1.0}} {foo: {foo: 0, foo: foo, foo: $env}} {foo: {foo: 0, foo: foo}} {foo: {foo: 0, foo: nil}} {foo: {foo: 0}} {foo: {foo: 0}}?.array {foo: {foo: 0}}?.f64 {foo: {foo: 1, foo: 0}} {foo: {foo: 1.0, foo: 1.0, foo: foo}} {foo: {foo: 1.0, foo: true}} {foo: {foo: 1.0}} {foo: {foo: 1}} {foo: {foo: add, foo: $env}} {foo: {foo: add, foo: foo}} {foo: {foo: add, foo: greet}} {foo: {foo: add}} {foo: {foo: array, foo: 1.0}} {foo: {foo: array}} {foo: {foo: f64, foo: $env}} {foo: {foo: f64}} {foo: {foo: false, foo: $env}?.foo} {foo: {foo: false}} {foo: {foo: false}}.Bar {foo: {foo: foo, foo: 1.0}} {foo: {foo: foo, foo: foo}} {foo: {foo: foo}, foo: $env?.greet} {foo: {foo: foo}?.String} {foo: {foo: foo}?.ok} {foo: {foo: foo}?.str} {foo: {foo: foo}} {foo: {foo: foo}}?.i {foo: {foo: greet, foo: 0}} {foo: {foo: greet, foo: i}} {foo: {foo: greet}} {foo: {foo: i, foo: array}} {foo: {foo: i}} {foo: {foo: list?.[0]}} {foo: {foo: list}, foo: f64} {foo: {foo: list}.String} {foo: {foo: list}} {foo: {foo: list}}?.String {foo: {foo: nil, foo: $env}} {foo: {foo: nil, foo: 1}} {foo: {foo: nil, foo: foo}} {foo: {foo: nil}, foo: $env?.String} {foo: {foo: nil}} {foo: {foo: ok, foo: nil}} {foo: {foo: ok, foo: true}} {foo: {foo: ok}, foo: ok} {foo: {foo: ok}?.[str], foo: f64} {foo: {foo: ok}} {foo: {foo: ok}}.list {foo: {foo: ok}}?.i {foo: {foo: str}} {foo: {foo: true, foo: foo}} {foo: {foo: true}} ================================================ FILE: types/types.go ================================================ package types import ( "fmt" "reflect" "strings" . "github.com/expr-lang/expr/checker/nature" ) // Type is a type that can be used to represent a value. type Type interface { Nature() Nature Equal(Type) bool String() string } var ( Int = TypeOf(0) Int8 = TypeOf(int8(0)) Int16 = TypeOf(int16(0)) Int32 = TypeOf(int32(0)) Int64 = TypeOf(int64(0)) Uint = TypeOf(uint(0)) Uint8 = TypeOf(uint8(0)) Uint16 = TypeOf(uint16(0)) Uint32 = TypeOf(uint32(0)) Uint64 = TypeOf(uint64(0)) Float = TypeOf(float32(0)) Float64 = TypeOf(float64(0)) String = TypeOf("") Bool = TypeOf(true) Nil = nilType{} Any = anyType{} ) func TypeOf(v any) Type { if v == nil { return Nil } return rtype{t: reflect.TypeOf(v)} } type anyType struct{} func (anyType) Nature() Nature { return FromType(nil) } func (anyType) Equal(t Type) bool { return true } func (anyType) String() string { return "any" } type nilType struct{} func (nilType) Nature() Nature { return NatureOf(nil) } func (nilType) Equal(t Type) bool { if t == Any { return true } return t == Nil } func (nilType) String() string { return "nil" } type rtype struct { t reflect.Type } func (r rtype) Nature() Nature { return FromType(r.t) } func (r rtype) Equal(t Type) bool { if t == Any { return true } if rt, ok := t.(rtype); ok { return r.t.String() == rt.t.String() } return false } func (r rtype) String() string { return r.t.String() } // Map represents a map[string]any type with defined keys. type Map map[string]Type const Extra = "[[__extra_keys__]]" func (m Map) Nature() Nature { nt := NatureOf(map[string]any{}) if nt.TypeData == nil { nt.TypeData = new(TypeData) } nt.Fields = make(map[string]Nature, len(m)) nt.Strict = true for k, v := range m { if k == Extra { nt.Strict = false natureOfDefaultValue := v.Nature() nt.DefaultMapValue = &natureOfDefaultValue continue } nt.Fields[k] = v.Nature() } return nt } func (m Map) Equal(t Type) bool { if t == Any { return true } mt, ok := t.(Map) if !ok { return false } if len(m) != len(mt) { return false } for k, v := range m { if !v.Equal(mt[k]) { return false } } return true } func (m Map) String() string { pairs := make([]string, 0, len(m)) for k, v := range m { pairs = append(pairs, fmt.Sprintf("%s: %s", k, v.String())) } return fmt.Sprintf("Map{%s}", strings.Join(pairs, ", ")) } // Array returns a type that represents an array of the given type. func Array(of Type) Type { return array{of} } type array struct { of Type } func (a array) Nature() Nature { of := a.of.Nature() nt := NatureOf([]any{}) if nt.TypeData == nil { nt.TypeData = new(TypeData) } nt.Fields = make(map[string]Nature, 1) nt.Ref = &of return nt } func (a array) Equal(t Type) bool { if t == Any { return true } at, ok := t.(array) if !ok { return false } if a.of.Equal(at.of) { return true } return false } func (a array) String() string { return fmt.Sprintf("Array{%s}", a.of.String()) } ================================================ FILE: types/types_test.go ================================================ package types_test import ( "testing" "github.com/expr-lang/expr/internal/testify/require" . "github.com/expr-lang/expr/types" ) func TestType_Equal(t *testing.T) { tests := []struct { index string // Index added for IDEA to show green test marker per test. a, b Type want bool }{ {"1", Int, Int, true}, {"2", Int, Int8, false}, {"3", Int, Uint, false}, {"4", Int, Float, false}, {"5", Int, String, false}, {"6", Int, Bool, false}, {"7", Int, Nil, false}, {"8", Int, Array(Int), false}, {"9", Int, Map{"foo": Int}, false}, {"11", Int, Array(Int), false}, {"12", Array(Int), Array(Int), true}, {"13", Array(Int), Array(Float), false}, {"14", Map{"foo": Int}, Map{"foo": Int}, true}, {"15", Map{"foo": Int}, Map{"foo": Float}, false}, {"19", Map{"foo": Map{"bar": Int}}, Map{"foo": Map{"bar": Int}}, true}, {"20", Map{"foo": Map{"bar": Int}}, Map{"foo": Map{"bar": Float}}, false}, {"21", Any, Any, true}, {"22", Any, Int, true}, {"23", Int, Any, true}, {"24", Any, Map{"foo": Int}, true}, {"25", Map{"foo": Int}, Any, true}, {"28", Any, Array(Int), true}, {"29", Array(Int), Any, true}, } for _, tt := range tests { t.Run(tt.index, func(t *testing.T) { if tt.want { require.True(t, tt.a.Equal(tt.b), tt.a.String()+" == "+tt.b.String()) } else { require.False(t, tt.a.Equal(tt.b), tt.a.String()+" == "+tt.b.String()) } }) } } ================================================ FILE: vm/debug.go ================================================ //go:build expr_debug // +build expr_debug package vm const debug = true ================================================ FILE: vm/debug_off.go ================================================ //go:build !expr_debug // +build !expr_debug package vm const debug = false ================================================ FILE: vm/debug_test.go ================================================ //go:build expr_debug // +build expr_debug package vm_test import ( "testing" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr/compiler" "github.com/expr-lang/expr/parser" "github.com/expr-lang/expr/vm" ) func TestDebugger(t *testing.T) { input := `[1, 2]` node, err := parser.Parse(input) require.NoError(t, err) program, err := compiler.Compile(node, nil) require.NoError(t, err) debug := vm.Debug() go func() { debug.Step() debug.Step() debug.Step() debug.Step() }() go func() { for range debug.Position() { } }() _, err = debug.Run(program, nil) require.NoError(t, err) require.Len(t, debug.Stack, 0) require.Nil(t, debug.Scopes) } ================================================ FILE: vm/func_types/main.go ================================================ package main import ( "bytes" "fmt" "go/format" "reflect" "strings" "text/template" . "time" ) // Keep sorted. var types = []any{ nil, new(func() Duration), new(func() Month), new(func() Time), new(func() Weekday), new(func() []any), new(func() []byte), new(func() any), new(func() bool), new(func() byte), new(func() float32), new(func() float64), new(func() int), new(func() int16), new(func() int32), new(func() int64), new(func() int8), new(func() map[string]any), new(func() rune), new(func() string), new(func() uint), new(func() uint16), new(func() uint32), new(func() uint64), new(func() uint8), new(func(Duration) Duration), new(func(Duration) Time), new(func(Time) Duration), new(func(Time) bool), new(func([]any) []any), new(func([]any) any), new(func([]any) map[string]any), new(func([]any, string) string), new(func([]byte) string), new(func([]string, string) string), new(func(any) []any), new(func(any) any), new(func(any) bool), new(func(any) float64), new(func(any) int), new(func(any) map[string]any), new(func(any) string), new(func(any, any) []any), new(func(any, any) any), new(func(any, any) bool), new(func(any, any) string), new(func(bool) bool), new(func(bool) float64), new(func(bool) int), new(func(bool) string), new(func(bool, bool) bool), new(func(float32) float64), new(func(float64) bool), new(func(float64) float32), new(func(float64) float64), new(func(float64) int), new(func(float64) string), new(func(float64, float64) bool), new(func(int) bool), new(func(int) float64), new(func(int) int), new(func(int) string), new(func(int, int) bool), new(func(int, int) int), new(func(int, int) string), new(func(int16) int32), new(func(int32) float64), new(func(int32) int), new(func(int32) int64), new(func(int64) Time), new(func(int8) int), new(func(int8) int16), new(func(string) []byte), new(func(string) []string), new(func(string) bool), new(func(string) float64), new(func(string) int), new(func(string) string), new(func(string, byte) int), new(func(string, int) int), new(func(string, rune) int), new(func(string, string) bool), new(func(string, string) string), new(func(uint) float64), new(func(uint) int), new(func(uint) uint), new(func(uint16) uint), new(func(uint32) uint64), new(func(uint64) float64), new(func(uint64) int64), new(func(uint8) byte), } func main() { data := struct { Index string Code string }{} for i, t := range types { if i == 0 { continue } fn := reflect.ValueOf(t).Elem().Type() data.Index += fmt.Sprintf("%v: new(%v),\n", i, fn) data.Code += fmt.Sprintf("case %d:\n", i) args := make([]string, fn.NumIn()) for j := fn.NumIn() - 1; j >= 0; j-- { cast := fmt.Sprintf(".(%v)", fn.In(j)) if fn.In(j).Kind() == reflect.Interface { cast = "" } data.Code += fmt.Sprintf("arg%v := vm.pop()%v\n", j+1, cast) args[j] = fmt.Sprintf("arg%v", j+1) } data.Code += fmt.Sprintf("return fn.(%v)(%v)\n", fn, strings.Join(args, ", ")) } var b bytes.Buffer err := template.Must( template.New("func_types"). Parse(source), ).Execute(&b, data) if err != nil { panic(err) } formatted, err := format.Source(b.Bytes()) if err != nil { panic(err) } fmt.Print(string(formatted)) } const source = `// Code generated by vm/func_types/main.go. DO NOT EDIT. package vm import ( "fmt" "time" ) var FuncTypes = []any{ {{ .Index }} } func (vm *VM) call(fn any, kind int) any { switch kind { {{ .Code }} } panic(fmt.Sprintf("unknown function kind (%v)", kind)) } ` ================================================ FILE: vm/func_types[generated].go ================================================ // Code generated by vm/func_types/main.go. DO NOT EDIT. package vm import ( "fmt" "time" ) var FuncTypes = []any{ 1: new(func() time.Duration), 2: new(func() time.Month), 3: new(func() time.Time), 4: new(func() time.Weekday), 5: new(func() []interface{}), 6: new(func() []uint8), 7: new(func() interface{}), 8: new(func() bool), 9: new(func() uint8), 10: new(func() float32), 11: new(func() float64), 12: new(func() int), 13: new(func() int16), 14: new(func() int32), 15: new(func() int64), 16: new(func() int8), 17: new(func() map[string]interface{}), 18: new(func() int32), 19: new(func() string), 20: new(func() uint), 21: new(func() uint16), 22: new(func() uint32), 23: new(func() uint64), 24: new(func() uint8), 25: new(func(time.Duration) time.Duration), 26: new(func(time.Duration) time.Time), 27: new(func(time.Time) time.Duration), 28: new(func(time.Time) bool), 29: new(func([]interface{}) []interface{}), 30: new(func([]interface{}) interface{}), 31: new(func([]interface{}) map[string]interface{}), 32: new(func([]interface{}, string) string), 33: new(func([]uint8) string), 34: new(func([]string, string) string), 35: new(func(interface{}) []interface{}), 36: new(func(interface{}) interface{}), 37: new(func(interface{}) bool), 38: new(func(interface{}) float64), 39: new(func(interface{}) int), 40: new(func(interface{}) map[string]interface{}), 41: new(func(interface{}) string), 42: new(func(interface{}, interface{}) []interface{}), 43: new(func(interface{}, interface{}) interface{}), 44: new(func(interface{}, interface{}) bool), 45: new(func(interface{}, interface{}) string), 46: new(func(bool) bool), 47: new(func(bool) float64), 48: new(func(bool) int), 49: new(func(bool) string), 50: new(func(bool, bool) bool), 51: new(func(float32) float64), 52: new(func(float64) bool), 53: new(func(float64) float32), 54: new(func(float64) float64), 55: new(func(float64) int), 56: new(func(float64) string), 57: new(func(float64, float64) bool), 58: new(func(int) bool), 59: new(func(int) float64), 60: new(func(int) int), 61: new(func(int) string), 62: new(func(int, int) bool), 63: new(func(int, int) int), 64: new(func(int, int) string), 65: new(func(int16) int32), 66: new(func(int32) float64), 67: new(func(int32) int), 68: new(func(int32) int64), 69: new(func(int64) time.Time), 70: new(func(int8) int), 71: new(func(int8) int16), 72: new(func(string) []uint8), 73: new(func(string) []string), 74: new(func(string) bool), 75: new(func(string) float64), 76: new(func(string) int), 77: new(func(string) string), 78: new(func(string, uint8) int), 79: new(func(string, int) int), 80: new(func(string, int32) int), 81: new(func(string, string) bool), 82: new(func(string, string) string), 83: new(func(uint) float64), 84: new(func(uint) int), 85: new(func(uint) uint), 86: new(func(uint16) uint), 87: new(func(uint32) uint64), 88: new(func(uint64) float64), 89: new(func(uint64) int64), 90: new(func(uint8) uint8), } func (vm *VM) call(fn any, kind int) any { switch kind { case 1: return fn.(func() time.Duration)() case 2: return fn.(func() time.Month)() case 3: return fn.(func() time.Time)() case 4: return fn.(func() time.Weekday)() case 5: return fn.(func() []interface{})() case 6: return fn.(func() []uint8)() case 7: return fn.(func() interface{})() case 8: return fn.(func() bool)() case 9: return fn.(func() uint8)() case 10: return fn.(func() float32)() case 11: return fn.(func() float64)() case 12: return fn.(func() int)() case 13: return fn.(func() int16)() case 14: return fn.(func() int32)() case 15: return fn.(func() int64)() case 16: return fn.(func() int8)() case 17: return fn.(func() map[string]interface{})() case 18: return fn.(func() int32)() case 19: return fn.(func() string)() case 20: return fn.(func() uint)() case 21: return fn.(func() uint16)() case 22: return fn.(func() uint32)() case 23: return fn.(func() uint64)() case 24: return fn.(func() uint8)() case 25: arg1 := vm.pop().(time.Duration) return fn.(func(time.Duration) time.Duration)(arg1) case 26: arg1 := vm.pop().(time.Duration) return fn.(func(time.Duration) time.Time)(arg1) case 27: arg1 := vm.pop().(time.Time) return fn.(func(time.Time) time.Duration)(arg1) case 28: arg1 := vm.pop().(time.Time) return fn.(func(time.Time) bool)(arg1) case 29: arg1 := vm.pop().([]interface{}) return fn.(func([]interface{}) []interface{})(arg1) case 30: arg1 := vm.pop().([]interface{}) return fn.(func([]interface{}) interface{})(arg1) case 31: arg1 := vm.pop().([]interface{}) return fn.(func([]interface{}) map[string]interface{})(arg1) case 32: arg2 := vm.pop().(string) arg1 := vm.pop().([]interface{}) return fn.(func([]interface{}, string) string)(arg1, arg2) case 33: arg1 := vm.pop().([]uint8) return fn.(func([]uint8) string)(arg1) case 34: arg2 := vm.pop().(string) arg1 := vm.pop().([]string) return fn.(func([]string, string) string)(arg1, arg2) case 35: arg1 := vm.pop() return fn.(func(interface{}) []interface{})(arg1) case 36: arg1 := vm.pop() return fn.(func(interface{}) interface{})(arg1) case 37: arg1 := vm.pop() return fn.(func(interface{}) bool)(arg1) case 38: arg1 := vm.pop() return fn.(func(interface{}) float64)(arg1) case 39: arg1 := vm.pop() return fn.(func(interface{}) int)(arg1) case 40: arg1 := vm.pop() return fn.(func(interface{}) map[string]interface{})(arg1) case 41: arg1 := vm.pop() return fn.(func(interface{}) string)(arg1) case 42: arg2 := vm.pop() arg1 := vm.pop() return fn.(func(interface{}, interface{}) []interface{})(arg1, arg2) case 43: arg2 := vm.pop() arg1 := vm.pop() return fn.(func(interface{}, interface{}) interface{})(arg1, arg2) case 44: arg2 := vm.pop() arg1 := vm.pop() return fn.(func(interface{}, interface{}) bool)(arg1, arg2) case 45: arg2 := vm.pop() arg1 := vm.pop() return fn.(func(interface{}, interface{}) string)(arg1, arg2) case 46: arg1 := vm.pop().(bool) return fn.(func(bool) bool)(arg1) case 47: arg1 := vm.pop().(bool) return fn.(func(bool) float64)(arg1) case 48: arg1 := vm.pop().(bool) return fn.(func(bool) int)(arg1) case 49: arg1 := vm.pop().(bool) return fn.(func(bool) string)(arg1) case 50: arg2 := vm.pop().(bool) arg1 := vm.pop().(bool) return fn.(func(bool, bool) bool)(arg1, arg2) case 51: arg1 := vm.pop().(float32) return fn.(func(float32) float64)(arg1) case 52: arg1 := vm.pop().(float64) return fn.(func(float64) bool)(arg1) case 53: arg1 := vm.pop().(float64) return fn.(func(float64) float32)(arg1) case 54: arg1 := vm.pop().(float64) return fn.(func(float64) float64)(arg1) case 55: arg1 := vm.pop().(float64) return fn.(func(float64) int)(arg1) case 56: arg1 := vm.pop().(float64) return fn.(func(float64) string)(arg1) case 57: arg2 := vm.pop().(float64) arg1 := vm.pop().(float64) return fn.(func(float64, float64) bool)(arg1, arg2) case 58: arg1 := vm.pop().(int) return fn.(func(int) bool)(arg1) case 59: arg1 := vm.pop().(int) return fn.(func(int) float64)(arg1) case 60: arg1 := vm.pop().(int) return fn.(func(int) int)(arg1) case 61: arg1 := vm.pop().(int) return fn.(func(int) string)(arg1) case 62: arg2 := vm.pop().(int) arg1 := vm.pop().(int) return fn.(func(int, int) bool)(arg1, arg2) case 63: arg2 := vm.pop().(int) arg1 := vm.pop().(int) return fn.(func(int, int) int)(arg1, arg2) case 64: arg2 := vm.pop().(int) arg1 := vm.pop().(int) return fn.(func(int, int) string)(arg1, arg2) case 65: arg1 := vm.pop().(int16) return fn.(func(int16) int32)(arg1) case 66: arg1 := vm.pop().(int32) return fn.(func(int32) float64)(arg1) case 67: arg1 := vm.pop().(int32) return fn.(func(int32) int)(arg1) case 68: arg1 := vm.pop().(int32) return fn.(func(int32) int64)(arg1) case 69: arg1 := vm.pop().(int64) return fn.(func(int64) time.Time)(arg1) case 70: arg1 := vm.pop().(int8) return fn.(func(int8) int)(arg1) case 71: arg1 := vm.pop().(int8) return fn.(func(int8) int16)(arg1) case 72: arg1 := vm.pop().(string) return fn.(func(string) []uint8)(arg1) case 73: arg1 := vm.pop().(string) return fn.(func(string) []string)(arg1) case 74: arg1 := vm.pop().(string) return fn.(func(string) bool)(arg1) case 75: arg1 := vm.pop().(string) return fn.(func(string) float64)(arg1) case 76: arg1 := vm.pop().(string) return fn.(func(string) int)(arg1) case 77: arg1 := vm.pop().(string) return fn.(func(string) string)(arg1) case 78: arg2 := vm.pop().(uint8) arg1 := vm.pop().(string) return fn.(func(string, uint8) int)(arg1, arg2) case 79: arg2 := vm.pop().(int) arg1 := vm.pop().(string) return fn.(func(string, int) int)(arg1, arg2) case 80: arg2 := vm.pop().(int32) arg1 := vm.pop().(string) return fn.(func(string, int32) int)(arg1, arg2) case 81: arg2 := vm.pop().(string) arg1 := vm.pop().(string) return fn.(func(string, string) bool)(arg1, arg2) case 82: arg2 := vm.pop().(string) arg1 := vm.pop().(string) return fn.(func(string, string) string)(arg1, arg2) case 83: arg1 := vm.pop().(uint) return fn.(func(uint) float64)(arg1) case 84: arg1 := vm.pop().(uint) return fn.(func(uint) int)(arg1) case 85: arg1 := vm.pop().(uint) return fn.(func(uint) uint)(arg1) case 86: arg1 := vm.pop().(uint16) return fn.(func(uint16) uint)(arg1) case 87: arg1 := vm.pop().(uint32) return fn.(func(uint32) uint64)(arg1) case 88: arg1 := vm.pop().(uint64) return fn.(func(uint64) float64)(arg1) case 89: arg1 := vm.pop().(uint64) return fn.(func(uint64) int64)(arg1) case 90: arg1 := vm.pop().(uint8) return fn.(func(uint8) uint8)(arg1) } panic(fmt.Sprintf("unknown function kind (%v)", kind)) } ================================================ FILE: vm/opcodes.go ================================================ package vm type Opcode byte const ( OpInvalid Opcode = iota OpPush OpInt OpPop OpStore OpLoadVar OpLoadConst OpLoadField OpLoadFast OpLoadMethod OpLoadFunc OpLoadEnv OpFetch OpFetchField OpMethod OpTrue OpFalse OpNil OpNegate OpNot OpEqual OpEqualInt OpEqualString OpJump OpJumpIfTrue OpJumpIfFalse OpJumpIfNil OpJumpIfNotNil OpJumpIfEnd OpJumpBackward OpIn OpLess OpMore OpLessOrEqual OpMoreOrEqual OpAdd OpSubtract OpMultiply OpDivide OpModulo OpExponent OpRange OpMatches OpMatchesConst OpContains OpStartsWith OpEndsWith OpSlice OpCall OpCall0 OpCall1 OpCall2 OpCall3 OpCallN OpCallFast OpCallSafe OpCallTyped OpCallBuiltin1 OpArray OpMap OpLen OpCast OpDeref OpIncrementIndex OpDecrementIndex OpIncrementCount OpGetIndex OpGetCount OpGetLen OpGetAcc OpSetAcc OpSetIndex OpPointer OpThrow OpCreate OpGroupBy OpSortBy OpSort OpProfileStart OpProfileEnd OpBegin OpAnd OpOr OpEnd // This opcode must be at the end of this list. ) ================================================ FILE: vm/program.go ================================================ package vm import ( "bytes" "fmt" "io" "reflect" "regexp" "strings" "text/tabwriter" "github.com/expr-lang/expr/ast" "github.com/expr-lang/expr/builtin" "github.com/expr-lang/expr/file" "github.com/expr-lang/expr/vm/runtime" ) // Program represents a compiled expression. type Program struct { Bytecode []Opcode Arguments []int Constants []any source file.Source node ast.Node locations []file.Location variables int functions []Function debugInfo map[string]string span *Span } // NewProgram returns a new Program. It's used by the compiler. func NewProgram( source file.Source, node ast.Node, locations []file.Location, variables int, constants []any, bytecode []Opcode, arguments []int, functions []Function, debugInfo map[string]string, span *Span, ) *Program { return &Program{ source: source, node: node, locations: locations, variables: variables, Constants: constants, Bytecode: bytecode, Arguments: arguments, functions: functions, debugInfo: debugInfo, span: span, } } // Source returns origin file.Source. func (program *Program) Source() file.Source { return program.source } // Node returns origin ast.Node. func (program *Program) Node() ast.Node { return program.node } // Locations returns a slice of bytecode's locations. func (program *Program) Locations() []file.Location { return program.locations } // Disassemble returns opcodes as a string. func (program *Program) Disassemble() string { var buf bytes.Buffer w := tabwriter.NewWriter(&buf, 0, 0, 2, ' ', 0) program.DisassembleWriter(w) _ = w.Flush() return buf.String() } // DisassembleWriter takes a writer and writes opcodes to it. func (program *Program) DisassembleWriter(w io.Writer) { ip := 0 for ip < len(program.Bytecode) { pp := ip op := program.Bytecode[ip] arg := program.Arguments[ip] ip += 1 code := func(label string) { _, _ = fmt.Fprintf(w, "%v\t%v\n", pp, label) } jump := func(label string) { _, _ = fmt.Fprintf(w, "%v\t%v\t<%v>\t(%v)\n", pp, label, arg, ip+arg) } jumpBack := func(label string) { _, _ = fmt.Fprintf(w, "%v\t%v\t<%v>\t(%v)\n", pp, label, arg, ip-arg) } argument := func(label string) { _, _ = fmt.Fprintf(w, "%v\t%v\t<%v>\n", pp, label, arg) } argumentWithInfo := func(label string, prefix string) { _, _ = fmt.Fprintf(w, "%v\t%v\t<%v>\t%v\n", pp, label, arg, program.debugInfo[fmt.Sprintf("%s_%d", prefix, arg)]) } constant := func(label string) { var c any if arg < len(program.Constants) { c = program.Constants[arg] } else { c = "out of range" } if name, ok := program.debugInfo[fmt.Sprintf("const_%d", arg)]; ok { c = name } if r, ok := c.(*regexp.Regexp); ok { c = r.String() } if field, ok := c.(*runtime.Field); ok { c = fmt.Sprintf("{%v %v}", strings.Join(field.Path, "."), field.Index) } if method, ok := c.(*runtime.Method); ok { c = fmt.Sprintf("{%v %v}", method.Name, method.Index) } _, _ = fmt.Fprintf(w, "%v\t%v\t<%v>\t%v\n", pp, label, arg, c) } builtinArg := func(label string) { _, _ = fmt.Fprintf(w, "%v\t%v\t<%v>\t%v\n", pp, label, arg, builtin.Builtins[arg].Name) } switch op { case OpInvalid: code("OpInvalid") case OpPush: constant("OpPush") case OpInt: argument("OpInt") case OpPop: code("OpPop") case OpStore: argumentWithInfo("OpStore", "var") case OpLoadVar: argumentWithInfo("OpLoadVar", "var") case OpLoadConst: constant("OpLoadConst") case OpLoadField: constant("OpLoadField") case OpLoadFast: constant("OpLoadFast") case OpLoadMethod: constant("OpLoadMethod") case OpLoadFunc: argumentWithInfo("OpLoadFunc", "func") case OpLoadEnv: code("OpLoadEnv") case OpFetch: code("OpFetch") case OpFetchField: constant("OpFetchField") case OpMethod: constant("OpMethod") case OpTrue: code("OpTrue") case OpFalse: code("OpFalse") case OpNil: code("OpNil") case OpNegate: code("OpNegate") case OpNot: code("OpNot") case OpEqual: code("OpEqual") case OpEqualInt: code("OpEqualInt") case OpEqualString: code("OpEqualString") case OpJump: jump("OpJump") case OpJumpIfTrue: jump("OpJumpIfTrue") case OpJumpIfFalse: jump("OpJumpIfFalse") case OpJumpIfNil: jump("OpJumpIfNil") case OpJumpIfNotNil: jump("OpJumpIfNotNil") case OpJumpIfEnd: jump("OpJumpIfEnd") case OpJumpBackward: jumpBack("OpJumpBackward") case OpIn: code("OpIn") case OpLess: code("OpLess") case OpMore: code("OpMore") case OpLessOrEqual: code("OpLessOrEqual") case OpMoreOrEqual: code("OpMoreOrEqual") case OpAdd: code("OpAdd") case OpSubtract: code("OpSubtract") case OpMultiply: code("OpMultiply") case OpDivide: code("OpDivide") case OpModulo: code("OpModulo") case OpExponent: code("OpExponent") case OpRange: code("OpRange") case OpMatches: code("OpMatches") case OpMatchesConst: constant("OpMatchesConst") case OpContains: code("OpContains") case OpStartsWith: code("OpStartsWith") case OpEndsWith: code("OpEndsWith") case OpSlice: code("OpSlice") case OpCall: argument("OpCall") case OpCall0: argumentWithInfo("OpCall0", "func") case OpCall1: argumentWithInfo("OpCall1", "func") case OpCall2: argumentWithInfo("OpCall2", "func") case OpCall3: argumentWithInfo("OpCall3", "func") case OpCallN: argument("OpCallN") case OpCallFast: argument("OpCallFast") case OpCallSafe: argument("OpCallSafe") case OpCallTyped: signature := reflect.TypeOf(FuncTypes[arg]).Elem().String() _, _ = fmt.Fprintf(w, "%v\t%v\t<%v>\t%v\n", pp, "OpCallTyped", arg, signature) case OpCallBuiltin1: builtinArg("OpCallBuiltin1") case OpArray: code("OpArray") case OpMap: code("OpMap") case OpLen: code("OpLen") case OpCast: argument("OpCast") case OpDeref: code("OpDeref") case OpIncrementIndex: code("OpIncrementIndex") case OpDecrementIndex: code("OpDecrementIndex") case OpIncrementCount: code("OpIncrementCount") case OpGetIndex: code("OpGetIndex") case OpGetCount: code("OpGetCount") case OpGetLen: code("OpGetLen") case OpGetAcc: code("OpGetAcc") case OpSetAcc: code("OpSetAcc") case OpSetIndex: code("OpSetIndex") case OpPointer: code("OpPointer") case OpThrow: code("OpThrow") case OpCreate: argument("OpCreate") case OpGroupBy: code("OpGroupBy") case OpSortBy: code("OpSortBy") case OpSort: code("OpSort") case OpProfileStart: code("OpProfileStart") case OpProfileEnd: code("OpProfileEnd") case OpBegin: code("OpBegin") case OpAnd: code("OpAnd") case OpOr: code("OpOr") case OpEnd: code("OpEnd") default: _, _ = fmt.Fprintf(w, "%v\t%#x (unknown)\n", ip, op) } } } ================================================ FILE: vm/program_test.go ================================================ package vm_test import ( "strings" "testing" "github.com/expr-lang/expr/vm" ) func TestProgram_Disassemble(t *testing.T) { for op := vm.OpPush; op < vm.OpEnd; op++ { program := vm.Program{ Constants: []any{1, 2}, Bytecode: []vm.Opcode{op}, Arguments: []int{1}, } d := program.Disassemble() if strings.Contains(d, "(unknown)") { t.Errorf("cannot disassemble all opcodes") } } } ================================================ FILE: vm/runtime/helpers/main.go ================================================ package main import ( "bytes" "fmt" "go/format" "os" "strings" "text/template" ) func main() { var b bytes.Buffer err := template.Must( template.New("helpers"). Funcs(template.FuncMap{ "cases": func(op string) string { return cases(op, uints, ints, floats) }, "cases_int_only": func(op string) string { return cases(op, uints, ints) }, "cases_with_duration": func(op string) string { return cases(op, uints, ints, floats, []string{"time.Duration"}) }, "array_equal_cases": func() string { return arrayEqualCases([]string{"string"}, uints, ints, floats) }, }). Parse(helpers), ).Execute(&b, nil) if err != nil { panic(err) } formatted, err := format.Source(b.Bytes()) if err != nil { panic(err) } fmt.Print(string(formatted)) } var ints = []string{ "int", "int8", "int16", "int32", "int64", } var uints = []string{ "uint", "uint8", "uint16", "uint32", "uint64", } var floats = []string{ "float32", "float64", } func cases(op string, xs ...[]string) string { var types []string for _, x := range xs { types = append(types, x...) } _, _ = fmt.Fprintf(os.Stderr, "Generating %s cases for %v\n", op, types) var out string echo := func(s string, xs ...any) { out += fmt.Sprintf(s, xs...) + "\n" } for _, a := range types { echo(`case %v:`, a) echo(`switch y := b.(type) {`) for _, b := range types { t := "int" if isDuration(a) || isDuration(b) { t = "time.Duration" } if isFloat(a) || isFloat(b) { t = "float64" } echo(`case %v:`, b) if op == "/" { echo(`return float64(x) / float64(y)`) } else { echo(`return %v(x) %v %v(y)`, t, op, t) } } echo(`}`) } return strings.TrimRight(out, "\n") } func arrayEqualCases(xs ...[]string) string { var types []string for _, x := range xs { types = append(types, x...) } _, _ = fmt.Fprintf(os.Stderr, "Generating array equal cases for %v\n", types) var out string echo := func(s string, xs ...any) { out += fmt.Sprintf(s, xs...) + "\n" } echo(`case []any:`) echo(`switch y := b.(type) {`) for _, a := range append(types, "any") { echo(`case []%v:`, a) echo(`if len(x) != len(y) { return false }`) echo(`for i := range x {`) echo(`if !Equal(x[i], y[i]) { return false }`) echo(`}`) echo("return true") } echo(`}`) for _, a := range types { echo(`case []%v:`, a) echo(`switch y := b.(type) {`) echo(`case []any:`) echo(`return Equal(y, x)`) echo(`case []%v:`, a) echo(`if len(x) != len(y) { return false }`) echo(`for i := range x {`) echo(`if x[i] != y[i] { return false }`) echo(`}`) echo("return true") echo(`}`) } return strings.TrimRight(out, "\n") } func isFloat(t string) bool { return strings.HasPrefix(t, "float") } func isDuration(t string) bool { return t == "time.Duration" } const helpers = `// Code generated by vm/runtime/helpers/main.go. DO NOT EDIT. package runtime import ( "fmt" "reflect" "time" ) func Equal(a, b interface{}) bool { switch x := a.(type) { {{ cases "==" }} {{ array_equal_cases }} case string: switch y := b.(type) { case string: return x == y } case time.Time: switch y := b.(type) { case time.Time: return x.Equal(y) } case time.Duration: switch y := b.(type) { case time.Duration: return x == y } case bool: switch y := b.(type) { case bool: return x == y } } if IsNil(a) && IsNil(b) { return true } return reflect.DeepEqual(a, b) } func Less(a, b interface{}) bool { switch x := a.(type) { {{ cases "<" }} case string: switch y := b.(type) { case string: return x < y } case time.Time: switch y := b.(type) { case time.Time: return x.Before(y) } case time.Duration: switch y := b.(type) { case time.Duration: return x < y } } panic(fmt.Sprintf("invalid operation: %T < %T", a, b)) } func More(a, b interface{}) bool { switch x := a.(type) { {{ cases ">" }} case string: switch y := b.(type) { case string: return x > y } case time.Time: switch y := b.(type) { case time.Time: return x.After(y) } case time.Duration: switch y := b.(type) { case time.Duration: return x > y } } panic(fmt.Sprintf("invalid operation: %T > %T", a, b)) } func LessOrEqual(a, b interface{}) bool { switch x := a.(type) { {{ cases "<=" }} case string: switch y := b.(type) { case string: return x <= y } case time.Time: switch y := b.(type) { case time.Time: return x.Before(y) || x.Equal(y) } case time.Duration: switch y := b.(type) { case time.Duration: return x <= y } } panic(fmt.Sprintf("invalid operation: %T <= %T", a, b)) } func MoreOrEqual(a, b interface{}) bool { switch x := a.(type) { {{ cases ">=" }} case string: switch y := b.(type) { case string: return x >= y } case time.Time: switch y := b.(type) { case time.Time: return x.After(y) || x.Equal(y) } case time.Duration: switch y := b.(type) { case time.Duration: return x >= y } } panic(fmt.Sprintf("invalid operation: %T >= %T", a, b)) } func Add(a, b interface{}) interface{} { switch x := a.(type) { {{ cases "+" }} case string: switch y := b.(type) { case string: return x + y } case time.Time: switch y := b.(type) { case time.Duration: return x.Add(y) } case time.Duration: switch y := b.(type) { case time.Time: return y.Add(x) case time.Duration: return x + y } } panic(fmt.Sprintf("invalid operation: %T + %T", a, b)) } func Subtract(a, b interface{}) interface{} { switch x := a.(type) { {{ cases "-" }} case time.Time: switch y := b.(type) { case time.Time: return x.Sub(y) case time.Duration: return x.Add(-y) } case time.Duration: switch y := b.(type) { case time.Duration: return x - y } } panic(fmt.Sprintf("invalid operation: %T - %T", a, b)) } func Multiply(a, b interface{}) interface{} { switch x := a.(type) { {{ cases_with_duration "*" }} } panic(fmt.Sprintf("invalid operation: %T * %T", a, b)) } func Divide(a, b interface{}) float64 { switch x := a.(type) { {{ cases "/" }} } panic(fmt.Sprintf("invalid operation: %T / %T", a, b)) } func Modulo(a, b interface{}) int { switch x := a.(type) { {{ cases_int_only "%" }} } panic(fmt.Sprintf("invalid operation: %T %% %T", a, b)) } ` ================================================ FILE: vm/runtime/helpers[generated].go ================================================ // Code generated by vm/runtime/helpers/main.go. DO NOT EDIT. package runtime import ( "fmt" "reflect" "time" ) func Equal(a, b interface{}) bool { switch x := a.(type) { case uint: switch y := b.(type) { case uint: return int(x) == int(y) case uint8: return int(x) == int(y) case uint16: return int(x) == int(y) case uint32: return int(x) == int(y) case uint64: return int(x) == int(y) case int: return int(x) == int(y) case int8: return int(x) == int(y) case int16: return int(x) == int(y) case int32: return int(x) == int(y) case int64: return int(x) == int(y) case float32: return float64(x) == float64(y) case float64: return float64(x) == float64(y) } case uint8: switch y := b.(type) { case uint: return int(x) == int(y) case uint8: return int(x) == int(y) case uint16: return int(x) == int(y) case uint32: return int(x) == int(y) case uint64: return int(x) == int(y) case int: return int(x) == int(y) case int8: return int(x) == int(y) case int16: return int(x) == int(y) case int32: return int(x) == int(y) case int64: return int(x) == int(y) case float32: return float64(x) == float64(y) case float64: return float64(x) == float64(y) } case uint16: switch y := b.(type) { case uint: return int(x) == int(y) case uint8: return int(x) == int(y) case uint16: return int(x) == int(y) case uint32: return int(x) == int(y) case uint64: return int(x) == int(y) case int: return int(x) == int(y) case int8: return int(x) == int(y) case int16: return int(x) == int(y) case int32: return int(x) == int(y) case int64: return int(x) == int(y) case float32: return float64(x) == float64(y) case float64: return float64(x) == float64(y) } case uint32: switch y := b.(type) { case uint: return int(x) == int(y) case uint8: return int(x) == int(y) case uint16: return int(x) == int(y) case uint32: return int(x) == int(y) case uint64: return int(x) == int(y) case int: return int(x) == int(y) case int8: return int(x) == int(y) case int16: return int(x) == int(y) case int32: return int(x) == int(y) case int64: return int(x) == int(y) case float32: return float64(x) == float64(y) case float64: return float64(x) == float64(y) } case uint64: switch y := b.(type) { case uint: return int(x) == int(y) case uint8: return int(x) == int(y) case uint16: return int(x) == int(y) case uint32: return int(x) == int(y) case uint64: return int(x) == int(y) case int: return int(x) == int(y) case int8: return int(x) == int(y) case int16: return int(x) == int(y) case int32: return int(x) == int(y) case int64: return int(x) == int(y) case float32: return float64(x) == float64(y) case float64: return float64(x) == float64(y) } case int: switch y := b.(type) { case uint: return int(x) == int(y) case uint8: return int(x) == int(y) case uint16: return int(x) == int(y) case uint32: return int(x) == int(y) case uint64: return int(x) == int(y) case int: return int(x) == int(y) case int8: return int(x) == int(y) case int16: return int(x) == int(y) case int32: return int(x) == int(y) case int64: return int(x) == int(y) case float32: return float64(x) == float64(y) case float64: return float64(x) == float64(y) } case int8: switch y := b.(type) { case uint: return int(x) == int(y) case uint8: return int(x) == int(y) case uint16: return int(x) == int(y) case uint32: return int(x) == int(y) case uint64: return int(x) == int(y) case int: return int(x) == int(y) case int8: return int(x) == int(y) case int16: return int(x) == int(y) case int32: return int(x) == int(y) case int64: return int(x) == int(y) case float32: return float64(x) == float64(y) case float64: return float64(x) == float64(y) } case int16: switch y := b.(type) { case uint: return int(x) == int(y) case uint8: return int(x) == int(y) case uint16: return int(x) == int(y) case uint32: return int(x) == int(y) case uint64: return int(x) == int(y) case int: return int(x) == int(y) case int8: return int(x) == int(y) case int16: return int(x) == int(y) case int32: return int(x) == int(y) case int64: return int(x) == int(y) case float32: return float64(x) == float64(y) case float64: return float64(x) == float64(y) } case int32: switch y := b.(type) { case uint: return int(x) == int(y) case uint8: return int(x) == int(y) case uint16: return int(x) == int(y) case uint32: return int(x) == int(y) case uint64: return int(x) == int(y) case int: return int(x) == int(y) case int8: return int(x) == int(y) case int16: return int(x) == int(y) case int32: return int(x) == int(y) case int64: return int(x) == int(y) case float32: return float64(x) == float64(y) case float64: return float64(x) == float64(y) } case int64: switch y := b.(type) { case uint: return int(x) == int(y) case uint8: return int(x) == int(y) case uint16: return int(x) == int(y) case uint32: return int(x) == int(y) case uint64: return int(x) == int(y) case int: return int(x) == int(y) case int8: return int(x) == int(y) case int16: return int(x) == int(y) case int32: return int(x) == int(y) case int64: return int(x) == int(y) case float32: return float64(x) == float64(y) case float64: return float64(x) == float64(y) } case float32: switch y := b.(type) { case uint: return float64(x) == float64(y) case uint8: return float64(x) == float64(y) case uint16: return float64(x) == float64(y) case uint32: return float64(x) == float64(y) case uint64: return float64(x) == float64(y) case int: return float64(x) == float64(y) case int8: return float64(x) == float64(y) case int16: return float64(x) == float64(y) case int32: return float64(x) == float64(y) case int64: return float64(x) == float64(y) case float32: return float64(x) == float64(y) case float64: return float64(x) == float64(y) } case float64: switch y := b.(type) { case uint: return float64(x) == float64(y) case uint8: return float64(x) == float64(y) case uint16: return float64(x) == float64(y) case uint32: return float64(x) == float64(y) case uint64: return float64(x) == float64(y) case int: return float64(x) == float64(y) case int8: return float64(x) == float64(y) case int16: return float64(x) == float64(y) case int32: return float64(x) == float64(y) case int64: return float64(x) == float64(y) case float32: return float64(x) == float64(y) case float64: return float64(x) == float64(y) } case []any: switch y := b.(type) { case []string: if len(x) != len(y) { return false } for i := range x { if !Equal(x[i], y[i]) { return false } } return true case []uint: if len(x) != len(y) { return false } for i := range x { if !Equal(x[i], y[i]) { return false } } return true case []uint8: if len(x) != len(y) { return false } for i := range x { if !Equal(x[i], y[i]) { return false } } return true case []uint16: if len(x) != len(y) { return false } for i := range x { if !Equal(x[i], y[i]) { return false } } return true case []uint32: if len(x) != len(y) { return false } for i := range x { if !Equal(x[i], y[i]) { return false } } return true case []uint64: if len(x) != len(y) { return false } for i := range x { if !Equal(x[i], y[i]) { return false } } return true case []int: if len(x) != len(y) { return false } for i := range x { if !Equal(x[i], y[i]) { return false } } return true case []int8: if len(x) != len(y) { return false } for i := range x { if !Equal(x[i], y[i]) { return false } } return true case []int16: if len(x) != len(y) { return false } for i := range x { if !Equal(x[i], y[i]) { return false } } return true case []int32: if len(x) != len(y) { return false } for i := range x { if !Equal(x[i], y[i]) { return false } } return true case []int64: if len(x) != len(y) { return false } for i := range x { if !Equal(x[i], y[i]) { return false } } return true case []float32: if len(x) != len(y) { return false } for i := range x { if !Equal(x[i], y[i]) { return false } } return true case []float64: if len(x) != len(y) { return false } for i := range x { if !Equal(x[i], y[i]) { return false } } return true case []any: if len(x) != len(y) { return false } for i := range x { if !Equal(x[i], y[i]) { return false } } return true } case []string: switch y := b.(type) { case []any: return Equal(y, x) case []string: if len(x) != len(y) { return false } for i := range x { if x[i] != y[i] { return false } } return true } case []uint: switch y := b.(type) { case []any: return Equal(y, x) case []uint: if len(x) != len(y) { return false } for i := range x { if x[i] != y[i] { return false } } return true } case []uint8: switch y := b.(type) { case []any: return Equal(y, x) case []uint8: if len(x) != len(y) { return false } for i := range x { if x[i] != y[i] { return false } } return true } case []uint16: switch y := b.(type) { case []any: return Equal(y, x) case []uint16: if len(x) != len(y) { return false } for i := range x { if x[i] != y[i] { return false } } return true } case []uint32: switch y := b.(type) { case []any: return Equal(y, x) case []uint32: if len(x) != len(y) { return false } for i := range x { if x[i] != y[i] { return false } } return true } case []uint64: switch y := b.(type) { case []any: return Equal(y, x) case []uint64: if len(x) != len(y) { return false } for i := range x { if x[i] != y[i] { return false } } return true } case []int: switch y := b.(type) { case []any: return Equal(y, x) case []int: if len(x) != len(y) { return false } for i := range x { if x[i] != y[i] { return false } } return true } case []int8: switch y := b.(type) { case []any: return Equal(y, x) case []int8: if len(x) != len(y) { return false } for i := range x { if x[i] != y[i] { return false } } return true } case []int16: switch y := b.(type) { case []any: return Equal(y, x) case []int16: if len(x) != len(y) { return false } for i := range x { if x[i] != y[i] { return false } } return true } case []int32: switch y := b.(type) { case []any: return Equal(y, x) case []int32: if len(x) != len(y) { return false } for i := range x { if x[i] != y[i] { return false } } return true } case []int64: switch y := b.(type) { case []any: return Equal(y, x) case []int64: if len(x) != len(y) { return false } for i := range x { if x[i] != y[i] { return false } } return true } case []float32: switch y := b.(type) { case []any: return Equal(y, x) case []float32: if len(x) != len(y) { return false } for i := range x { if x[i] != y[i] { return false } } return true } case []float64: switch y := b.(type) { case []any: return Equal(y, x) case []float64: if len(x) != len(y) { return false } for i := range x { if x[i] != y[i] { return false } } return true } case string: switch y := b.(type) { case string: return x == y } case time.Time: switch y := b.(type) { case time.Time: return x.Equal(y) } case time.Duration: switch y := b.(type) { case time.Duration: return x == y } case bool: switch y := b.(type) { case bool: return x == y } } if IsNil(a) && IsNil(b) { return true } return reflect.DeepEqual(a, b) } func Less(a, b interface{}) bool { switch x := a.(type) { case uint: switch y := b.(type) { case uint: return int(x) < int(y) case uint8: return int(x) < int(y) case uint16: return int(x) < int(y) case uint32: return int(x) < int(y) case uint64: return int(x) < int(y) case int: return int(x) < int(y) case int8: return int(x) < int(y) case int16: return int(x) < int(y) case int32: return int(x) < int(y) case int64: return int(x) < int(y) case float32: return float64(x) < float64(y) case float64: return float64(x) < float64(y) } case uint8: switch y := b.(type) { case uint: return int(x) < int(y) case uint8: return int(x) < int(y) case uint16: return int(x) < int(y) case uint32: return int(x) < int(y) case uint64: return int(x) < int(y) case int: return int(x) < int(y) case int8: return int(x) < int(y) case int16: return int(x) < int(y) case int32: return int(x) < int(y) case int64: return int(x) < int(y) case float32: return float64(x) < float64(y) case float64: return float64(x) < float64(y) } case uint16: switch y := b.(type) { case uint: return int(x) < int(y) case uint8: return int(x) < int(y) case uint16: return int(x) < int(y) case uint32: return int(x) < int(y) case uint64: return int(x) < int(y) case int: return int(x) < int(y) case int8: return int(x) < int(y) case int16: return int(x) < int(y) case int32: return int(x) < int(y) case int64: return int(x) < int(y) case float32: return float64(x) < float64(y) case float64: return float64(x) < float64(y) } case uint32: switch y := b.(type) { case uint: return int(x) < int(y) case uint8: return int(x) < int(y) case uint16: return int(x) < int(y) case uint32: return int(x) < int(y) case uint64: return int(x) < int(y) case int: return int(x) < int(y) case int8: return int(x) < int(y) case int16: return int(x) < int(y) case int32: return int(x) < int(y) case int64: return int(x) < int(y) case float32: return float64(x) < float64(y) case float64: return float64(x) < float64(y) } case uint64: switch y := b.(type) { case uint: return int(x) < int(y) case uint8: return int(x) < int(y) case uint16: return int(x) < int(y) case uint32: return int(x) < int(y) case uint64: return int(x) < int(y) case int: return int(x) < int(y) case int8: return int(x) < int(y) case int16: return int(x) < int(y) case int32: return int(x) < int(y) case int64: return int(x) < int(y) case float32: return float64(x) < float64(y) case float64: return float64(x) < float64(y) } case int: switch y := b.(type) { case uint: return int(x) < int(y) case uint8: return int(x) < int(y) case uint16: return int(x) < int(y) case uint32: return int(x) < int(y) case uint64: return int(x) < int(y) case int: return int(x) < int(y) case int8: return int(x) < int(y) case int16: return int(x) < int(y) case int32: return int(x) < int(y) case int64: return int(x) < int(y) case float32: return float64(x) < float64(y) case float64: return float64(x) < float64(y) } case int8: switch y := b.(type) { case uint: return int(x) < int(y) case uint8: return int(x) < int(y) case uint16: return int(x) < int(y) case uint32: return int(x) < int(y) case uint64: return int(x) < int(y) case int: return int(x) < int(y) case int8: return int(x) < int(y) case int16: return int(x) < int(y) case int32: return int(x) < int(y) case int64: return int(x) < int(y) case float32: return float64(x) < float64(y) case float64: return float64(x) < float64(y) } case int16: switch y := b.(type) { case uint: return int(x) < int(y) case uint8: return int(x) < int(y) case uint16: return int(x) < int(y) case uint32: return int(x) < int(y) case uint64: return int(x) < int(y) case int: return int(x) < int(y) case int8: return int(x) < int(y) case int16: return int(x) < int(y) case int32: return int(x) < int(y) case int64: return int(x) < int(y) case float32: return float64(x) < float64(y) case float64: return float64(x) < float64(y) } case int32: switch y := b.(type) { case uint: return int(x) < int(y) case uint8: return int(x) < int(y) case uint16: return int(x) < int(y) case uint32: return int(x) < int(y) case uint64: return int(x) < int(y) case int: return int(x) < int(y) case int8: return int(x) < int(y) case int16: return int(x) < int(y) case int32: return int(x) < int(y) case int64: return int(x) < int(y) case float32: return float64(x) < float64(y) case float64: return float64(x) < float64(y) } case int64: switch y := b.(type) { case uint: return int(x) < int(y) case uint8: return int(x) < int(y) case uint16: return int(x) < int(y) case uint32: return int(x) < int(y) case uint64: return int(x) < int(y) case int: return int(x) < int(y) case int8: return int(x) < int(y) case int16: return int(x) < int(y) case int32: return int(x) < int(y) case int64: return int(x) < int(y) case float32: return float64(x) < float64(y) case float64: return float64(x) < float64(y) } case float32: switch y := b.(type) { case uint: return float64(x) < float64(y) case uint8: return float64(x) < float64(y) case uint16: return float64(x) < float64(y) case uint32: return float64(x) < float64(y) case uint64: return float64(x) < float64(y) case int: return float64(x) < float64(y) case int8: return float64(x) < float64(y) case int16: return float64(x) < float64(y) case int32: return float64(x) < float64(y) case int64: return float64(x) < float64(y) case float32: return float64(x) < float64(y) case float64: return float64(x) < float64(y) } case float64: switch y := b.(type) { case uint: return float64(x) < float64(y) case uint8: return float64(x) < float64(y) case uint16: return float64(x) < float64(y) case uint32: return float64(x) < float64(y) case uint64: return float64(x) < float64(y) case int: return float64(x) < float64(y) case int8: return float64(x) < float64(y) case int16: return float64(x) < float64(y) case int32: return float64(x) < float64(y) case int64: return float64(x) < float64(y) case float32: return float64(x) < float64(y) case float64: return float64(x) < float64(y) } case string: switch y := b.(type) { case string: return x < y } case time.Time: switch y := b.(type) { case time.Time: return x.Before(y) } case time.Duration: switch y := b.(type) { case time.Duration: return x < y } } panic(fmt.Sprintf("invalid operation: %T < %T", a, b)) } func More(a, b interface{}) bool { switch x := a.(type) { case uint: switch y := b.(type) { case uint: return int(x) > int(y) case uint8: return int(x) > int(y) case uint16: return int(x) > int(y) case uint32: return int(x) > int(y) case uint64: return int(x) > int(y) case int: return int(x) > int(y) case int8: return int(x) > int(y) case int16: return int(x) > int(y) case int32: return int(x) > int(y) case int64: return int(x) > int(y) case float32: return float64(x) > float64(y) case float64: return float64(x) > float64(y) } case uint8: switch y := b.(type) { case uint: return int(x) > int(y) case uint8: return int(x) > int(y) case uint16: return int(x) > int(y) case uint32: return int(x) > int(y) case uint64: return int(x) > int(y) case int: return int(x) > int(y) case int8: return int(x) > int(y) case int16: return int(x) > int(y) case int32: return int(x) > int(y) case int64: return int(x) > int(y) case float32: return float64(x) > float64(y) case float64: return float64(x) > float64(y) } case uint16: switch y := b.(type) { case uint: return int(x) > int(y) case uint8: return int(x) > int(y) case uint16: return int(x) > int(y) case uint32: return int(x) > int(y) case uint64: return int(x) > int(y) case int: return int(x) > int(y) case int8: return int(x) > int(y) case int16: return int(x) > int(y) case int32: return int(x) > int(y) case int64: return int(x) > int(y) case float32: return float64(x) > float64(y) case float64: return float64(x) > float64(y) } case uint32: switch y := b.(type) { case uint: return int(x) > int(y) case uint8: return int(x) > int(y) case uint16: return int(x) > int(y) case uint32: return int(x) > int(y) case uint64: return int(x) > int(y) case int: return int(x) > int(y) case int8: return int(x) > int(y) case int16: return int(x) > int(y) case int32: return int(x) > int(y) case int64: return int(x) > int(y) case float32: return float64(x) > float64(y) case float64: return float64(x) > float64(y) } case uint64: switch y := b.(type) { case uint: return int(x) > int(y) case uint8: return int(x) > int(y) case uint16: return int(x) > int(y) case uint32: return int(x) > int(y) case uint64: return int(x) > int(y) case int: return int(x) > int(y) case int8: return int(x) > int(y) case int16: return int(x) > int(y) case int32: return int(x) > int(y) case int64: return int(x) > int(y) case float32: return float64(x) > float64(y) case float64: return float64(x) > float64(y) } case int: switch y := b.(type) { case uint: return int(x) > int(y) case uint8: return int(x) > int(y) case uint16: return int(x) > int(y) case uint32: return int(x) > int(y) case uint64: return int(x) > int(y) case int: return int(x) > int(y) case int8: return int(x) > int(y) case int16: return int(x) > int(y) case int32: return int(x) > int(y) case int64: return int(x) > int(y) case float32: return float64(x) > float64(y) case float64: return float64(x) > float64(y) } case int8: switch y := b.(type) { case uint: return int(x) > int(y) case uint8: return int(x) > int(y) case uint16: return int(x) > int(y) case uint32: return int(x) > int(y) case uint64: return int(x) > int(y) case int: return int(x) > int(y) case int8: return int(x) > int(y) case int16: return int(x) > int(y) case int32: return int(x) > int(y) case int64: return int(x) > int(y) case float32: return float64(x) > float64(y) case float64: return float64(x) > float64(y) } case int16: switch y := b.(type) { case uint: return int(x) > int(y) case uint8: return int(x) > int(y) case uint16: return int(x) > int(y) case uint32: return int(x) > int(y) case uint64: return int(x) > int(y) case int: return int(x) > int(y) case int8: return int(x) > int(y) case int16: return int(x) > int(y) case int32: return int(x) > int(y) case int64: return int(x) > int(y) case float32: return float64(x) > float64(y) case float64: return float64(x) > float64(y) } case int32: switch y := b.(type) { case uint: return int(x) > int(y) case uint8: return int(x) > int(y) case uint16: return int(x) > int(y) case uint32: return int(x) > int(y) case uint64: return int(x) > int(y) case int: return int(x) > int(y) case int8: return int(x) > int(y) case int16: return int(x) > int(y) case int32: return int(x) > int(y) case int64: return int(x) > int(y) case float32: return float64(x) > float64(y) case float64: return float64(x) > float64(y) } case int64: switch y := b.(type) { case uint: return int(x) > int(y) case uint8: return int(x) > int(y) case uint16: return int(x) > int(y) case uint32: return int(x) > int(y) case uint64: return int(x) > int(y) case int: return int(x) > int(y) case int8: return int(x) > int(y) case int16: return int(x) > int(y) case int32: return int(x) > int(y) case int64: return int(x) > int(y) case float32: return float64(x) > float64(y) case float64: return float64(x) > float64(y) } case float32: switch y := b.(type) { case uint: return float64(x) > float64(y) case uint8: return float64(x) > float64(y) case uint16: return float64(x) > float64(y) case uint32: return float64(x) > float64(y) case uint64: return float64(x) > float64(y) case int: return float64(x) > float64(y) case int8: return float64(x) > float64(y) case int16: return float64(x) > float64(y) case int32: return float64(x) > float64(y) case int64: return float64(x) > float64(y) case float32: return float64(x) > float64(y) case float64: return float64(x) > float64(y) } case float64: switch y := b.(type) { case uint: return float64(x) > float64(y) case uint8: return float64(x) > float64(y) case uint16: return float64(x) > float64(y) case uint32: return float64(x) > float64(y) case uint64: return float64(x) > float64(y) case int: return float64(x) > float64(y) case int8: return float64(x) > float64(y) case int16: return float64(x) > float64(y) case int32: return float64(x) > float64(y) case int64: return float64(x) > float64(y) case float32: return float64(x) > float64(y) case float64: return float64(x) > float64(y) } case string: switch y := b.(type) { case string: return x > y } case time.Time: switch y := b.(type) { case time.Time: return x.After(y) } case time.Duration: switch y := b.(type) { case time.Duration: return x > y } } panic(fmt.Sprintf("invalid operation: %T > %T", a, b)) } func LessOrEqual(a, b interface{}) bool { switch x := a.(type) { case uint: switch y := b.(type) { case uint: return int(x) <= int(y) case uint8: return int(x) <= int(y) case uint16: return int(x) <= int(y) case uint32: return int(x) <= int(y) case uint64: return int(x) <= int(y) case int: return int(x) <= int(y) case int8: return int(x) <= int(y) case int16: return int(x) <= int(y) case int32: return int(x) <= int(y) case int64: return int(x) <= int(y) case float32: return float64(x) <= float64(y) case float64: return float64(x) <= float64(y) } case uint8: switch y := b.(type) { case uint: return int(x) <= int(y) case uint8: return int(x) <= int(y) case uint16: return int(x) <= int(y) case uint32: return int(x) <= int(y) case uint64: return int(x) <= int(y) case int: return int(x) <= int(y) case int8: return int(x) <= int(y) case int16: return int(x) <= int(y) case int32: return int(x) <= int(y) case int64: return int(x) <= int(y) case float32: return float64(x) <= float64(y) case float64: return float64(x) <= float64(y) } case uint16: switch y := b.(type) { case uint: return int(x) <= int(y) case uint8: return int(x) <= int(y) case uint16: return int(x) <= int(y) case uint32: return int(x) <= int(y) case uint64: return int(x) <= int(y) case int: return int(x) <= int(y) case int8: return int(x) <= int(y) case int16: return int(x) <= int(y) case int32: return int(x) <= int(y) case int64: return int(x) <= int(y) case float32: return float64(x) <= float64(y) case float64: return float64(x) <= float64(y) } case uint32: switch y := b.(type) { case uint: return int(x) <= int(y) case uint8: return int(x) <= int(y) case uint16: return int(x) <= int(y) case uint32: return int(x) <= int(y) case uint64: return int(x) <= int(y) case int: return int(x) <= int(y) case int8: return int(x) <= int(y) case int16: return int(x) <= int(y) case int32: return int(x) <= int(y) case int64: return int(x) <= int(y) case float32: return float64(x) <= float64(y) case float64: return float64(x) <= float64(y) } case uint64: switch y := b.(type) { case uint: return int(x) <= int(y) case uint8: return int(x) <= int(y) case uint16: return int(x) <= int(y) case uint32: return int(x) <= int(y) case uint64: return int(x) <= int(y) case int: return int(x) <= int(y) case int8: return int(x) <= int(y) case int16: return int(x) <= int(y) case int32: return int(x) <= int(y) case int64: return int(x) <= int(y) case float32: return float64(x) <= float64(y) case float64: return float64(x) <= float64(y) } case int: switch y := b.(type) { case uint: return int(x) <= int(y) case uint8: return int(x) <= int(y) case uint16: return int(x) <= int(y) case uint32: return int(x) <= int(y) case uint64: return int(x) <= int(y) case int: return int(x) <= int(y) case int8: return int(x) <= int(y) case int16: return int(x) <= int(y) case int32: return int(x) <= int(y) case int64: return int(x) <= int(y) case float32: return float64(x) <= float64(y) case float64: return float64(x) <= float64(y) } case int8: switch y := b.(type) { case uint: return int(x) <= int(y) case uint8: return int(x) <= int(y) case uint16: return int(x) <= int(y) case uint32: return int(x) <= int(y) case uint64: return int(x) <= int(y) case int: return int(x) <= int(y) case int8: return int(x) <= int(y) case int16: return int(x) <= int(y) case int32: return int(x) <= int(y) case int64: return int(x) <= int(y) case float32: return float64(x) <= float64(y) case float64: return float64(x) <= float64(y) } case int16: switch y := b.(type) { case uint: return int(x) <= int(y) case uint8: return int(x) <= int(y) case uint16: return int(x) <= int(y) case uint32: return int(x) <= int(y) case uint64: return int(x) <= int(y) case int: return int(x) <= int(y) case int8: return int(x) <= int(y) case int16: return int(x) <= int(y) case int32: return int(x) <= int(y) case int64: return int(x) <= int(y) case float32: return float64(x) <= float64(y) case float64: return float64(x) <= float64(y) } case int32: switch y := b.(type) { case uint: return int(x) <= int(y) case uint8: return int(x) <= int(y) case uint16: return int(x) <= int(y) case uint32: return int(x) <= int(y) case uint64: return int(x) <= int(y) case int: return int(x) <= int(y) case int8: return int(x) <= int(y) case int16: return int(x) <= int(y) case int32: return int(x) <= int(y) case int64: return int(x) <= int(y) case float32: return float64(x) <= float64(y) case float64: return float64(x) <= float64(y) } case int64: switch y := b.(type) { case uint: return int(x) <= int(y) case uint8: return int(x) <= int(y) case uint16: return int(x) <= int(y) case uint32: return int(x) <= int(y) case uint64: return int(x) <= int(y) case int: return int(x) <= int(y) case int8: return int(x) <= int(y) case int16: return int(x) <= int(y) case int32: return int(x) <= int(y) case int64: return int(x) <= int(y) case float32: return float64(x) <= float64(y) case float64: return float64(x) <= float64(y) } case float32: switch y := b.(type) { case uint: return float64(x) <= float64(y) case uint8: return float64(x) <= float64(y) case uint16: return float64(x) <= float64(y) case uint32: return float64(x) <= float64(y) case uint64: return float64(x) <= float64(y) case int: return float64(x) <= float64(y) case int8: return float64(x) <= float64(y) case int16: return float64(x) <= float64(y) case int32: return float64(x) <= float64(y) case int64: return float64(x) <= float64(y) case float32: return float64(x) <= float64(y) case float64: return float64(x) <= float64(y) } case float64: switch y := b.(type) { case uint: return float64(x) <= float64(y) case uint8: return float64(x) <= float64(y) case uint16: return float64(x) <= float64(y) case uint32: return float64(x) <= float64(y) case uint64: return float64(x) <= float64(y) case int: return float64(x) <= float64(y) case int8: return float64(x) <= float64(y) case int16: return float64(x) <= float64(y) case int32: return float64(x) <= float64(y) case int64: return float64(x) <= float64(y) case float32: return float64(x) <= float64(y) case float64: return float64(x) <= float64(y) } case string: switch y := b.(type) { case string: return x <= y } case time.Time: switch y := b.(type) { case time.Time: return x.Before(y) || x.Equal(y) } case time.Duration: switch y := b.(type) { case time.Duration: return x <= y } } panic(fmt.Sprintf("invalid operation: %T <= %T", a, b)) } func MoreOrEqual(a, b interface{}) bool { switch x := a.(type) { case uint: switch y := b.(type) { case uint: return int(x) >= int(y) case uint8: return int(x) >= int(y) case uint16: return int(x) >= int(y) case uint32: return int(x) >= int(y) case uint64: return int(x) >= int(y) case int: return int(x) >= int(y) case int8: return int(x) >= int(y) case int16: return int(x) >= int(y) case int32: return int(x) >= int(y) case int64: return int(x) >= int(y) case float32: return float64(x) >= float64(y) case float64: return float64(x) >= float64(y) } case uint8: switch y := b.(type) { case uint: return int(x) >= int(y) case uint8: return int(x) >= int(y) case uint16: return int(x) >= int(y) case uint32: return int(x) >= int(y) case uint64: return int(x) >= int(y) case int: return int(x) >= int(y) case int8: return int(x) >= int(y) case int16: return int(x) >= int(y) case int32: return int(x) >= int(y) case int64: return int(x) >= int(y) case float32: return float64(x) >= float64(y) case float64: return float64(x) >= float64(y) } case uint16: switch y := b.(type) { case uint: return int(x) >= int(y) case uint8: return int(x) >= int(y) case uint16: return int(x) >= int(y) case uint32: return int(x) >= int(y) case uint64: return int(x) >= int(y) case int: return int(x) >= int(y) case int8: return int(x) >= int(y) case int16: return int(x) >= int(y) case int32: return int(x) >= int(y) case int64: return int(x) >= int(y) case float32: return float64(x) >= float64(y) case float64: return float64(x) >= float64(y) } case uint32: switch y := b.(type) { case uint: return int(x) >= int(y) case uint8: return int(x) >= int(y) case uint16: return int(x) >= int(y) case uint32: return int(x) >= int(y) case uint64: return int(x) >= int(y) case int: return int(x) >= int(y) case int8: return int(x) >= int(y) case int16: return int(x) >= int(y) case int32: return int(x) >= int(y) case int64: return int(x) >= int(y) case float32: return float64(x) >= float64(y) case float64: return float64(x) >= float64(y) } case uint64: switch y := b.(type) { case uint: return int(x) >= int(y) case uint8: return int(x) >= int(y) case uint16: return int(x) >= int(y) case uint32: return int(x) >= int(y) case uint64: return int(x) >= int(y) case int: return int(x) >= int(y) case int8: return int(x) >= int(y) case int16: return int(x) >= int(y) case int32: return int(x) >= int(y) case int64: return int(x) >= int(y) case float32: return float64(x) >= float64(y) case float64: return float64(x) >= float64(y) } case int: switch y := b.(type) { case uint: return int(x) >= int(y) case uint8: return int(x) >= int(y) case uint16: return int(x) >= int(y) case uint32: return int(x) >= int(y) case uint64: return int(x) >= int(y) case int: return int(x) >= int(y) case int8: return int(x) >= int(y) case int16: return int(x) >= int(y) case int32: return int(x) >= int(y) case int64: return int(x) >= int(y) case float32: return float64(x) >= float64(y) case float64: return float64(x) >= float64(y) } case int8: switch y := b.(type) { case uint: return int(x) >= int(y) case uint8: return int(x) >= int(y) case uint16: return int(x) >= int(y) case uint32: return int(x) >= int(y) case uint64: return int(x) >= int(y) case int: return int(x) >= int(y) case int8: return int(x) >= int(y) case int16: return int(x) >= int(y) case int32: return int(x) >= int(y) case int64: return int(x) >= int(y) case float32: return float64(x) >= float64(y) case float64: return float64(x) >= float64(y) } case int16: switch y := b.(type) { case uint: return int(x) >= int(y) case uint8: return int(x) >= int(y) case uint16: return int(x) >= int(y) case uint32: return int(x) >= int(y) case uint64: return int(x) >= int(y) case int: return int(x) >= int(y) case int8: return int(x) >= int(y) case int16: return int(x) >= int(y) case int32: return int(x) >= int(y) case int64: return int(x) >= int(y) case float32: return float64(x) >= float64(y) case float64: return float64(x) >= float64(y) } case int32: switch y := b.(type) { case uint: return int(x) >= int(y) case uint8: return int(x) >= int(y) case uint16: return int(x) >= int(y) case uint32: return int(x) >= int(y) case uint64: return int(x) >= int(y) case int: return int(x) >= int(y) case int8: return int(x) >= int(y) case int16: return int(x) >= int(y) case int32: return int(x) >= int(y) case int64: return int(x) >= int(y) case float32: return float64(x) >= float64(y) case float64: return float64(x) >= float64(y) } case int64: switch y := b.(type) { case uint: return int(x) >= int(y) case uint8: return int(x) >= int(y) case uint16: return int(x) >= int(y) case uint32: return int(x) >= int(y) case uint64: return int(x) >= int(y) case int: return int(x) >= int(y) case int8: return int(x) >= int(y) case int16: return int(x) >= int(y) case int32: return int(x) >= int(y) case int64: return int(x) >= int(y) case float32: return float64(x) >= float64(y) case float64: return float64(x) >= float64(y) } case float32: switch y := b.(type) { case uint: return float64(x) >= float64(y) case uint8: return float64(x) >= float64(y) case uint16: return float64(x) >= float64(y) case uint32: return float64(x) >= float64(y) case uint64: return float64(x) >= float64(y) case int: return float64(x) >= float64(y) case int8: return float64(x) >= float64(y) case int16: return float64(x) >= float64(y) case int32: return float64(x) >= float64(y) case int64: return float64(x) >= float64(y) case float32: return float64(x) >= float64(y) case float64: return float64(x) >= float64(y) } case float64: switch y := b.(type) { case uint: return float64(x) >= float64(y) case uint8: return float64(x) >= float64(y) case uint16: return float64(x) >= float64(y) case uint32: return float64(x) >= float64(y) case uint64: return float64(x) >= float64(y) case int: return float64(x) >= float64(y) case int8: return float64(x) >= float64(y) case int16: return float64(x) >= float64(y) case int32: return float64(x) >= float64(y) case int64: return float64(x) >= float64(y) case float32: return float64(x) >= float64(y) case float64: return float64(x) >= float64(y) } case string: switch y := b.(type) { case string: return x >= y } case time.Time: switch y := b.(type) { case time.Time: return x.After(y) || x.Equal(y) } case time.Duration: switch y := b.(type) { case time.Duration: return x >= y } } panic(fmt.Sprintf("invalid operation: %T >= %T", a, b)) } func Add(a, b interface{}) interface{} { switch x := a.(type) { case uint: switch y := b.(type) { case uint: return int(x) + int(y) case uint8: return int(x) + int(y) case uint16: return int(x) + int(y) case uint32: return int(x) + int(y) case uint64: return int(x) + int(y) case int: return int(x) + int(y) case int8: return int(x) + int(y) case int16: return int(x) + int(y) case int32: return int(x) + int(y) case int64: return int(x) + int(y) case float32: return float64(x) + float64(y) case float64: return float64(x) + float64(y) } case uint8: switch y := b.(type) { case uint: return int(x) + int(y) case uint8: return int(x) + int(y) case uint16: return int(x) + int(y) case uint32: return int(x) + int(y) case uint64: return int(x) + int(y) case int: return int(x) + int(y) case int8: return int(x) + int(y) case int16: return int(x) + int(y) case int32: return int(x) + int(y) case int64: return int(x) + int(y) case float32: return float64(x) + float64(y) case float64: return float64(x) + float64(y) } case uint16: switch y := b.(type) { case uint: return int(x) + int(y) case uint8: return int(x) + int(y) case uint16: return int(x) + int(y) case uint32: return int(x) + int(y) case uint64: return int(x) + int(y) case int: return int(x) + int(y) case int8: return int(x) + int(y) case int16: return int(x) + int(y) case int32: return int(x) + int(y) case int64: return int(x) + int(y) case float32: return float64(x) + float64(y) case float64: return float64(x) + float64(y) } case uint32: switch y := b.(type) { case uint: return int(x) + int(y) case uint8: return int(x) + int(y) case uint16: return int(x) + int(y) case uint32: return int(x) + int(y) case uint64: return int(x) + int(y) case int: return int(x) + int(y) case int8: return int(x) + int(y) case int16: return int(x) + int(y) case int32: return int(x) + int(y) case int64: return int(x) + int(y) case float32: return float64(x) + float64(y) case float64: return float64(x) + float64(y) } case uint64: switch y := b.(type) { case uint: return int(x) + int(y) case uint8: return int(x) + int(y) case uint16: return int(x) + int(y) case uint32: return int(x) + int(y) case uint64: return int(x) + int(y) case int: return int(x) + int(y) case int8: return int(x) + int(y) case int16: return int(x) + int(y) case int32: return int(x) + int(y) case int64: return int(x) + int(y) case float32: return float64(x) + float64(y) case float64: return float64(x) + float64(y) } case int: switch y := b.(type) { case uint: return int(x) + int(y) case uint8: return int(x) + int(y) case uint16: return int(x) + int(y) case uint32: return int(x) + int(y) case uint64: return int(x) + int(y) case int: return int(x) + int(y) case int8: return int(x) + int(y) case int16: return int(x) + int(y) case int32: return int(x) + int(y) case int64: return int(x) + int(y) case float32: return float64(x) + float64(y) case float64: return float64(x) + float64(y) } case int8: switch y := b.(type) { case uint: return int(x) + int(y) case uint8: return int(x) + int(y) case uint16: return int(x) + int(y) case uint32: return int(x) + int(y) case uint64: return int(x) + int(y) case int: return int(x) + int(y) case int8: return int(x) + int(y) case int16: return int(x) + int(y) case int32: return int(x) + int(y) case int64: return int(x) + int(y) case float32: return float64(x) + float64(y) case float64: return float64(x) + float64(y) } case int16: switch y := b.(type) { case uint: return int(x) + int(y) case uint8: return int(x) + int(y) case uint16: return int(x) + int(y) case uint32: return int(x) + int(y) case uint64: return int(x) + int(y) case int: return int(x) + int(y) case int8: return int(x) + int(y) case int16: return int(x) + int(y) case int32: return int(x) + int(y) case int64: return int(x) + int(y) case float32: return float64(x) + float64(y) case float64: return float64(x) + float64(y) } case int32: switch y := b.(type) { case uint: return int(x) + int(y) case uint8: return int(x) + int(y) case uint16: return int(x) + int(y) case uint32: return int(x) + int(y) case uint64: return int(x) + int(y) case int: return int(x) + int(y) case int8: return int(x) + int(y) case int16: return int(x) + int(y) case int32: return int(x) + int(y) case int64: return int(x) + int(y) case float32: return float64(x) + float64(y) case float64: return float64(x) + float64(y) } case int64: switch y := b.(type) { case uint: return int(x) + int(y) case uint8: return int(x) + int(y) case uint16: return int(x) + int(y) case uint32: return int(x) + int(y) case uint64: return int(x) + int(y) case int: return int(x) + int(y) case int8: return int(x) + int(y) case int16: return int(x) + int(y) case int32: return int(x) + int(y) case int64: return int(x) + int(y) case float32: return float64(x) + float64(y) case float64: return float64(x) + float64(y) } case float32: switch y := b.(type) { case uint: return float64(x) + float64(y) case uint8: return float64(x) + float64(y) case uint16: return float64(x) + float64(y) case uint32: return float64(x) + float64(y) case uint64: return float64(x) + float64(y) case int: return float64(x) + float64(y) case int8: return float64(x) + float64(y) case int16: return float64(x) + float64(y) case int32: return float64(x) + float64(y) case int64: return float64(x) + float64(y) case float32: return float64(x) + float64(y) case float64: return float64(x) + float64(y) } case float64: switch y := b.(type) { case uint: return float64(x) + float64(y) case uint8: return float64(x) + float64(y) case uint16: return float64(x) + float64(y) case uint32: return float64(x) + float64(y) case uint64: return float64(x) + float64(y) case int: return float64(x) + float64(y) case int8: return float64(x) + float64(y) case int16: return float64(x) + float64(y) case int32: return float64(x) + float64(y) case int64: return float64(x) + float64(y) case float32: return float64(x) + float64(y) case float64: return float64(x) + float64(y) } case string: switch y := b.(type) { case string: return x + y } case time.Time: switch y := b.(type) { case time.Duration: return x.Add(y) } case time.Duration: switch y := b.(type) { case time.Time: return y.Add(x) case time.Duration: return x + y } } panic(fmt.Sprintf("invalid operation: %T + %T", a, b)) } func Subtract(a, b interface{}) interface{} { switch x := a.(type) { case uint: switch y := b.(type) { case uint: return int(x) - int(y) case uint8: return int(x) - int(y) case uint16: return int(x) - int(y) case uint32: return int(x) - int(y) case uint64: return int(x) - int(y) case int: return int(x) - int(y) case int8: return int(x) - int(y) case int16: return int(x) - int(y) case int32: return int(x) - int(y) case int64: return int(x) - int(y) case float32: return float64(x) - float64(y) case float64: return float64(x) - float64(y) } case uint8: switch y := b.(type) { case uint: return int(x) - int(y) case uint8: return int(x) - int(y) case uint16: return int(x) - int(y) case uint32: return int(x) - int(y) case uint64: return int(x) - int(y) case int: return int(x) - int(y) case int8: return int(x) - int(y) case int16: return int(x) - int(y) case int32: return int(x) - int(y) case int64: return int(x) - int(y) case float32: return float64(x) - float64(y) case float64: return float64(x) - float64(y) } case uint16: switch y := b.(type) { case uint: return int(x) - int(y) case uint8: return int(x) - int(y) case uint16: return int(x) - int(y) case uint32: return int(x) - int(y) case uint64: return int(x) - int(y) case int: return int(x) - int(y) case int8: return int(x) - int(y) case int16: return int(x) - int(y) case int32: return int(x) - int(y) case int64: return int(x) - int(y) case float32: return float64(x) - float64(y) case float64: return float64(x) - float64(y) } case uint32: switch y := b.(type) { case uint: return int(x) - int(y) case uint8: return int(x) - int(y) case uint16: return int(x) - int(y) case uint32: return int(x) - int(y) case uint64: return int(x) - int(y) case int: return int(x) - int(y) case int8: return int(x) - int(y) case int16: return int(x) - int(y) case int32: return int(x) - int(y) case int64: return int(x) - int(y) case float32: return float64(x) - float64(y) case float64: return float64(x) - float64(y) } case uint64: switch y := b.(type) { case uint: return int(x) - int(y) case uint8: return int(x) - int(y) case uint16: return int(x) - int(y) case uint32: return int(x) - int(y) case uint64: return int(x) - int(y) case int: return int(x) - int(y) case int8: return int(x) - int(y) case int16: return int(x) - int(y) case int32: return int(x) - int(y) case int64: return int(x) - int(y) case float32: return float64(x) - float64(y) case float64: return float64(x) - float64(y) } case int: switch y := b.(type) { case uint: return int(x) - int(y) case uint8: return int(x) - int(y) case uint16: return int(x) - int(y) case uint32: return int(x) - int(y) case uint64: return int(x) - int(y) case int: return int(x) - int(y) case int8: return int(x) - int(y) case int16: return int(x) - int(y) case int32: return int(x) - int(y) case int64: return int(x) - int(y) case float32: return float64(x) - float64(y) case float64: return float64(x) - float64(y) } case int8: switch y := b.(type) { case uint: return int(x) - int(y) case uint8: return int(x) - int(y) case uint16: return int(x) - int(y) case uint32: return int(x) - int(y) case uint64: return int(x) - int(y) case int: return int(x) - int(y) case int8: return int(x) - int(y) case int16: return int(x) - int(y) case int32: return int(x) - int(y) case int64: return int(x) - int(y) case float32: return float64(x) - float64(y) case float64: return float64(x) - float64(y) } case int16: switch y := b.(type) { case uint: return int(x) - int(y) case uint8: return int(x) - int(y) case uint16: return int(x) - int(y) case uint32: return int(x) - int(y) case uint64: return int(x) - int(y) case int: return int(x) - int(y) case int8: return int(x) - int(y) case int16: return int(x) - int(y) case int32: return int(x) - int(y) case int64: return int(x) - int(y) case float32: return float64(x) - float64(y) case float64: return float64(x) - float64(y) } case int32: switch y := b.(type) { case uint: return int(x) - int(y) case uint8: return int(x) - int(y) case uint16: return int(x) - int(y) case uint32: return int(x) - int(y) case uint64: return int(x) - int(y) case int: return int(x) - int(y) case int8: return int(x) - int(y) case int16: return int(x) - int(y) case int32: return int(x) - int(y) case int64: return int(x) - int(y) case float32: return float64(x) - float64(y) case float64: return float64(x) - float64(y) } case int64: switch y := b.(type) { case uint: return int(x) - int(y) case uint8: return int(x) - int(y) case uint16: return int(x) - int(y) case uint32: return int(x) - int(y) case uint64: return int(x) - int(y) case int: return int(x) - int(y) case int8: return int(x) - int(y) case int16: return int(x) - int(y) case int32: return int(x) - int(y) case int64: return int(x) - int(y) case float32: return float64(x) - float64(y) case float64: return float64(x) - float64(y) } case float32: switch y := b.(type) { case uint: return float64(x) - float64(y) case uint8: return float64(x) - float64(y) case uint16: return float64(x) - float64(y) case uint32: return float64(x) - float64(y) case uint64: return float64(x) - float64(y) case int: return float64(x) - float64(y) case int8: return float64(x) - float64(y) case int16: return float64(x) - float64(y) case int32: return float64(x) - float64(y) case int64: return float64(x) - float64(y) case float32: return float64(x) - float64(y) case float64: return float64(x) - float64(y) } case float64: switch y := b.(type) { case uint: return float64(x) - float64(y) case uint8: return float64(x) - float64(y) case uint16: return float64(x) - float64(y) case uint32: return float64(x) - float64(y) case uint64: return float64(x) - float64(y) case int: return float64(x) - float64(y) case int8: return float64(x) - float64(y) case int16: return float64(x) - float64(y) case int32: return float64(x) - float64(y) case int64: return float64(x) - float64(y) case float32: return float64(x) - float64(y) case float64: return float64(x) - float64(y) } case time.Time: switch y := b.(type) { case time.Time: return x.Sub(y) case time.Duration: return x.Add(-y) } case time.Duration: switch y := b.(type) { case time.Duration: return x - y } } panic(fmt.Sprintf("invalid operation: %T - %T", a, b)) } func Multiply(a, b interface{}) interface{} { switch x := a.(type) { case uint: switch y := b.(type) { case uint: return int(x) * int(y) case uint8: return int(x) * int(y) case uint16: return int(x) * int(y) case uint32: return int(x) * int(y) case uint64: return int(x) * int(y) case int: return int(x) * int(y) case int8: return int(x) * int(y) case int16: return int(x) * int(y) case int32: return int(x) * int(y) case int64: return int(x) * int(y) case float32: return float64(x) * float64(y) case float64: return float64(x) * float64(y) case time.Duration: return time.Duration(x) * time.Duration(y) } case uint8: switch y := b.(type) { case uint: return int(x) * int(y) case uint8: return int(x) * int(y) case uint16: return int(x) * int(y) case uint32: return int(x) * int(y) case uint64: return int(x) * int(y) case int: return int(x) * int(y) case int8: return int(x) * int(y) case int16: return int(x) * int(y) case int32: return int(x) * int(y) case int64: return int(x) * int(y) case float32: return float64(x) * float64(y) case float64: return float64(x) * float64(y) case time.Duration: return time.Duration(x) * time.Duration(y) } case uint16: switch y := b.(type) { case uint: return int(x) * int(y) case uint8: return int(x) * int(y) case uint16: return int(x) * int(y) case uint32: return int(x) * int(y) case uint64: return int(x) * int(y) case int: return int(x) * int(y) case int8: return int(x) * int(y) case int16: return int(x) * int(y) case int32: return int(x) * int(y) case int64: return int(x) * int(y) case float32: return float64(x) * float64(y) case float64: return float64(x) * float64(y) case time.Duration: return time.Duration(x) * time.Duration(y) } case uint32: switch y := b.(type) { case uint: return int(x) * int(y) case uint8: return int(x) * int(y) case uint16: return int(x) * int(y) case uint32: return int(x) * int(y) case uint64: return int(x) * int(y) case int: return int(x) * int(y) case int8: return int(x) * int(y) case int16: return int(x) * int(y) case int32: return int(x) * int(y) case int64: return int(x) * int(y) case float32: return float64(x) * float64(y) case float64: return float64(x) * float64(y) case time.Duration: return time.Duration(x) * time.Duration(y) } case uint64: switch y := b.(type) { case uint: return int(x) * int(y) case uint8: return int(x) * int(y) case uint16: return int(x) * int(y) case uint32: return int(x) * int(y) case uint64: return int(x) * int(y) case int: return int(x) * int(y) case int8: return int(x) * int(y) case int16: return int(x) * int(y) case int32: return int(x) * int(y) case int64: return int(x) * int(y) case float32: return float64(x) * float64(y) case float64: return float64(x) * float64(y) case time.Duration: return time.Duration(x) * time.Duration(y) } case int: switch y := b.(type) { case uint: return int(x) * int(y) case uint8: return int(x) * int(y) case uint16: return int(x) * int(y) case uint32: return int(x) * int(y) case uint64: return int(x) * int(y) case int: return int(x) * int(y) case int8: return int(x) * int(y) case int16: return int(x) * int(y) case int32: return int(x) * int(y) case int64: return int(x) * int(y) case float32: return float64(x) * float64(y) case float64: return float64(x) * float64(y) case time.Duration: return time.Duration(x) * time.Duration(y) } case int8: switch y := b.(type) { case uint: return int(x) * int(y) case uint8: return int(x) * int(y) case uint16: return int(x) * int(y) case uint32: return int(x) * int(y) case uint64: return int(x) * int(y) case int: return int(x) * int(y) case int8: return int(x) * int(y) case int16: return int(x) * int(y) case int32: return int(x) * int(y) case int64: return int(x) * int(y) case float32: return float64(x) * float64(y) case float64: return float64(x) * float64(y) case time.Duration: return time.Duration(x) * time.Duration(y) } case int16: switch y := b.(type) { case uint: return int(x) * int(y) case uint8: return int(x) * int(y) case uint16: return int(x) * int(y) case uint32: return int(x) * int(y) case uint64: return int(x) * int(y) case int: return int(x) * int(y) case int8: return int(x) * int(y) case int16: return int(x) * int(y) case int32: return int(x) * int(y) case int64: return int(x) * int(y) case float32: return float64(x) * float64(y) case float64: return float64(x) * float64(y) case time.Duration: return time.Duration(x) * time.Duration(y) } case int32: switch y := b.(type) { case uint: return int(x) * int(y) case uint8: return int(x) * int(y) case uint16: return int(x) * int(y) case uint32: return int(x) * int(y) case uint64: return int(x) * int(y) case int: return int(x) * int(y) case int8: return int(x) * int(y) case int16: return int(x) * int(y) case int32: return int(x) * int(y) case int64: return int(x) * int(y) case float32: return float64(x) * float64(y) case float64: return float64(x) * float64(y) case time.Duration: return time.Duration(x) * time.Duration(y) } case int64: switch y := b.(type) { case uint: return int(x) * int(y) case uint8: return int(x) * int(y) case uint16: return int(x) * int(y) case uint32: return int(x) * int(y) case uint64: return int(x) * int(y) case int: return int(x) * int(y) case int8: return int(x) * int(y) case int16: return int(x) * int(y) case int32: return int(x) * int(y) case int64: return int(x) * int(y) case float32: return float64(x) * float64(y) case float64: return float64(x) * float64(y) case time.Duration: return time.Duration(x) * time.Duration(y) } case float32: switch y := b.(type) { case uint: return float64(x) * float64(y) case uint8: return float64(x) * float64(y) case uint16: return float64(x) * float64(y) case uint32: return float64(x) * float64(y) case uint64: return float64(x) * float64(y) case int: return float64(x) * float64(y) case int8: return float64(x) * float64(y) case int16: return float64(x) * float64(y) case int32: return float64(x) * float64(y) case int64: return float64(x) * float64(y) case float32: return float64(x) * float64(y) case float64: return float64(x) * float64(y) case time.Duration: return float64(x) * float64(y) } case float64: switch y := b.(type) { case uint: return float64(x) * float64(y) case uint8: return float64(x) * float64(y) case uint16: return float64(x) * float64(y) case uint32: return float64(x) * float64(y) case uint64: return float64(x) * float64(y) case int: return float64(x) * float64(y) case int8: return float64(x) * float64(y) case int16: return float64(x) * float64(y) case int32: return float64(x) * float64(y) case int64: return float64(x) * float64(y) case float32: return float64(x) * float64(y) case float64: return float64(x) * float64(y) case time.Duration: return float64(x) * float64(y) } case time.Duration: switch y := b.(type) { case uint: return time.Duration(x) * time.Duration(y) case uint8: return time.Duration(x) * time.Duration(y) case uint16: return time.Duration(x) * time.Duration(y) case uint32: return time.Duration(x) * time.Duration(y) case uint64: return time.Duration(x) * time.Duration(y) case int: return time.Duration(x) * time.Duration(y) case int8: return time.Duration(x) * time.Duration(y) case int16: return time.Duration(x) * time.Duration(y) case int32: return time.Duration(x) * time.Duration(y) case int64: return time.Duration(x) * time.Duration(y) case float32: return float64(x) * float64(y) case float64: return float64(x) * float64(y) case time.Duration: return time.Duration(x) * time.Duration(y) } } panic(fmt.Sprintf("invalid operation: %T * %T", a, b)) } func Divide(a, b interface{}) float64 { switch x := a.(type) { case uint: switch y := b.(type) { case uint: return float64(x) / float64(y) case uint8: return float64(x) / float64(y) case uint16: return float64(x) / float64(y) case uint32: return float64(x) / float64(y) case uint64: return float64(x) / float64(y) case int: return float64(x) / float64(y) case int8: return float64(x) / float64(y) case int16: return float64(x) / float64(y) case int32: return float64(x) / float64(y) case int64: return float64(x) / float64(y) case float32: return float64(x) / float64(y) case float64: return float64(x) / float64(y) } case uint8: switch y := b.(type) { case uint: return float64(x) / float64(y) case uint8: return float64(x) / float64(y) case uint16: return float64(x) / float64(y) case uint32: return float64(x) / float64(y) case uint64: return float64(x) / float64(y) case int: return float64(x) / float64(y) case int8: return float64(x) / float64(y) case int16: return float64(x) / float64(y) case int32: return float64(x) / float64(y) case int64: return float64(x) / float64(y) case float32: return float64(x) / float64(y) case float64: return float64(x) / float64(y) } case uint16: switch y := b.(type) { case uint: return float64(x) / float64(y) case uint8: return float64(x) / float64(y) case uint16: return float64(x) / float64(y) case uint32: return float64(x) / float64(y) case uint64: return float64(x) / float64(y) case int: return float64(x) / float64(y) case int8: return float64(x) / float64(y) case int16: return float64(x) / float64(y) case int32: return float64(x) / float64(y) case int64: return float64(x) / float64(y) case float32: return float64(x) / float64(y) case float64: return float64(x) / float64(y) } case uint32: switch y := b.(type) { case uint: return float64(x) / float64(y) case uint8: return float64(x) / float64(y) case uint16: return float64(x) / float64(y) case uint32: return float64(x) / float64(y) case uint64: return float64(x) / float64(y) case int: return float64(x) / float64(y) case int8: return float64(x) / float64(y) case int16: return float64(x) / float64(y) case int32: return float64(x) / float64(y) case int64: return float64(x) / float64(y) case float32: return float64(x) / float64(y) case float64: return float64(x) / float64(y) } case uint64: switch y := b.(type) { case uint: return float64(x) / float64(y) case uint8: return float64(x) / float64(y) case uint16: return float64(x) / float64(y) case uint32: return float64(x) / float64(y) case uint64: return float64(x) / float64(y) case int: return float64(x) / float64(y) case int8: return float64(x) / float64(y) case int16: return float64(x) / float64(y) case int32: return float64(x) / float64(y) case int64: return float64(x) / float64(y) case float32: return float64(x) / float64(y) case float64: return float64(x) / float64(y) } case int: switch y := b.(type) { case uint: return float64(x) / float64(y) case uint8: return float64(x) / float64(y) case uint16: return float64(x) / float64(y) case uint32: return float64(x) / float64(y) case uint64: return float64(x) / float64(y) case int: return float64(x) / float64(y) case int8: return float64(x) / float64(y) case int16: return float64(x) / float64(y) case int32: return float64(x) / float64(y) case int64: return float64(x) / float64(y) case float32: return float64(x) / float64(y) case float64: return float64(x) / float64(y) } case int8: switch y := b.(type) { case uint: return float64(x) / float64(y) case uint8: return float64(x) / float64(y) case uint16: return float64(x) / float64(y) case uint32: return float64(x) / float64(y) case uint64: return float64(x) / float64(y) case int: return float64(x) / float64(y) case int8: return float64(x) / float64(y) case int16: return float64(x) / float64(y) case int32: return float64(x) / float64(y) case int64: return float64(x) / float64(y) case float32: return float64(x) / float64(y) case float64: return float64(x) / float64(y) } case int16: switch y := b.(type) { case uint: return float64(x) / float64(y) case uint8: return float64(x) / float64(y) case uint16: return float64(x) / float64(y) case uint32: return float64(x) / float64(y) case uint64: return float64(x) / float64(y) case int: return float64(x) / float64(y) case int8: return float64(x) / float64(y) case int16: return float64(x) / float64(y) case int32: return float64(x) / float64(y) case int64: return float64(x) / float64(y) case float32: return float64(x) / float64(y) case float64: return float64(x) / float64(y) } case int32: switch y := b.(type) { case uint: return float64(x) / float64(y) case uint8: return float64(x) / float64(y) case uint16: return float64(x) / float64(y) case uint32: return float64(x) / float64(y) case uint64: return float64(x) / float64(y) case int: return float64(x) / float64(y) case int8: return float64(x) / float64(y) case int16: return float64(x) / float64(y) case int32: return float64(x) / float64(y) case int64: return float64(x) / float64(y) case float32: return float64(x) / float64(y) case float64: return float64(x) / float64(y) } case int64: switch y := b.(type) { case uint: return float64(x) / float64(y) case uint8: return float64(x) / float64(y) case uint16: return float64(x) / float64(y) case uint32: return float64(x) / float64(y) case uint64: return float64(x) / float64(y) case int: return float64(x) / float64(y) case int8: return float64(x) / float64(y) case int16: return float64(x) / float64(y) case int32: return float64(x) / float64(y) case int64: return float64(x) / float64(y) case float32: return float64(x) / float64(y) case float64: return float64(x) / float64(y) } case float32: switch y := b.(type) { case uint: return float64(x) / float64(y) case uint8: return float64(x) / float64(y) case uint16: return float64(x) / float64(y) case uint32: return float64(x) / float64(y) case uint64: return float64(x) / float64(y) case int: return float64(x) / float64(y) case int8: return float64(x) / float64(y) case int16: return float64(x) / float64(y) case int32: return float64(x) / float64(y) case int64: return float64(x) / float64(y) case float32: return float64(x) / float64(y) case float64: return float64(x) / float64(y) } case float64: switch y := b.(type) { case uint: return float64(x) / float64(y) case uint8: return float64(x) / float64(y) case uint16: return float64(x) / float64(y) case uint32: return float64(x) / float64(y) case uint64: return float64(x) / float64(y) case int: return float64(x) / float64(y) case int8: return float64(x) / float64(y) case int16: return float64(x) / float64(y) case int32: return float64(x) / float64(y) case int64: return float64(x) / float64(y) case float32: return float64(x) / float64(y) case float64: return float64(x) / float64(y) } } panic(fmt.Sprintf("invalid operation: %T / %T", a, b)) } func Modulo(a, b interface{}) int { switch x := a.(type) { case uint: switch y := b.(type) { case uint: return int(x) % int(y) case uint8: return int(x) % int(y) case uint16: return int(x) % int(y) case uint32: return int(x) % int(y) case uint64: return int(x) % int(y) case int: return int(x) % int(y) case int8: return int(x) % int(y) case int16: return int(x) % int(y) case int32: return int(x) % int(y) case int64: return int(x) % int(y) } case uint8: switch y := b.(type) { case uint: return int(x) % int(y) case uint8: return int(x) % int(y) case uint16: return int(x) % int(y) case uint32: return int(x) % int(y) case uint64: return int(x) % int(y) case int: return int(x) % int(y) case int8: return int(x) % int(y) case int16: return int(x) % int(y) case int32: return int(x) % int(y) case int64: return int(x) % int(y) } case uint16: switch y := b.(type) { case uint: return int(x) % int(y) case uint8: return int(x) % int(y) case uint16: return int(x) % int(y) case uint32: return int(x) % int(y) case uint64: return int(x) % int(y) case int: return int(x) % int(y) case int8: return int(x) % int(y) case int16: return int(x) % int(y) case int32: return int(x) % int(y) case int64: return int(x) % int(y) } case uint32: switch y := b.(type) { case uint: return int(x) % int(y) case uint8: return int(x) % int(y) case uint16: return int(x) % int(y) case uint32: return int(x) % int(y) case uint64: return int(x) % int(y) case int: return int(x) % int(y) case int8: return int(x) % int(y) case int16: return int(x) % int(y) case int32: return int(x) % int(y) case int64: return int(x) % int(y) } case uint64: switch y := b.(type) { case uint: return int(x) % int(y) case uint8: return int(x) % int(y) case uint16: return int(x) % int(y) case uint32: return int(x) % int(y) case uint64: return int(x) % int(y) case int: return int(x) % int(y) case int8: return int(x) % int(y) case int16: return int(x) % int(y) case int32: return int(x) % int(y) case int64: return int(x) % int(y) } case int: switch y := b.(type) { case uint: return int(x) % int(y) case uint8: return int(x) % int(y) case uint16: return int(x) % int(y) case uint32: return int(x) % int(y) case uint64: return int(x) % int(y) case int: return int(x) % int(y) case int8: return int(x) % int(y) case int16: return int(x) % int(y) case int32: return int(x) % int(y) case int64: return int(x) % int(y) } case int8: switch y := b.(type) { case uint: return int(x) % int(y) case uint8: return int(x) % int(y) case uint16: return int(x) % int(y) case uint32: return int(x) % int(y) case uint64: return int(x) % int(y) case int: return int(x) % int(y) case int8: return int(x) % int(y) case int16: return int(x) % int(y) case int32: return int(x) % int(y) case int64: return int(x) % int(y) } case int16: switch y := b.(type) { case uint: return int(x) % int(y) case uint8: return int(x) % int(y) case uint16: return int(x) % int(y) case uint32: return int(x) % int(y) case uint64: return int(x) % int(y) case int: return int(x) % int(y) case int8: return int(x) % int(y) case int16: return int(x) % int(y) case int32: return int(x) % int(y) case int64: return int(x) % int(y) } case int32: switch y := b.(type) { case uint: return int(x) % int(y) case uint8: return int(x) % int(y) case uint16: return int(x) % int(y) case uint32: return int(x) % int(y) case uint64: return int(x) % int(y) case int: return int(x) % int(y) case int8: return int(x) % int(y) case int16: return int(x) % int(y) case int32: return int(x) % int(y) case int64: return int(x) % int(y) } case int64: switch y := b.(type) { case uint: return int(x) % int(y) case uint8: return int(x) % int(y) case uint16: return int(x) % int(y) case uint32: return int(x) % int(y) case uint64: return int(x) % int(y) case int: return int(x) % int(y) case int8: return int(x) % int(y) case int16: return int(x) % int(y) case int32: return int(x) % int(y) case int64: return int(x) % int(y) } } panic(fmt.Sprintf("invalid operation: %T %% %T", a, b)) } ================================================ FILE: vm/runtime/helpers_test.go ================================================ package runtime_test import ( "testing" "github.com/expr-lang/expr/internal/testify/assert" "github.com/expr-lang/expr/vm/runtime" ) var tests = []struct { name string a, b any want bool }{ {"int == int", 42, 42, true}, {"int != int", 42, 33, false}, {"int == int8", 42, int8(42), true}, {"int == int16", 42, int16(42), true}, {"int == int32", 42, int32(42), true}, {"int == int64", 42, int64(42), true}, {"float == float", 42.0, 42.0, true}, {"float != float", 42.0, 33.0, false}, {"float == int", 42.0, 42, true}, {"float != int", 42.0, 33, false}, {"string == string", "foo", "foo", true}, {"string != string", "foo", "bar", false}, {"bool == bool", true, true, true}, {"bool != bool", true, false, false}, {"[]any == []int", []any{1, 2, 3}, []int{1, 2, 3}, true}, {"[]any != []int", []any{1, 2, 3}, []int{1, 2, 99}, false}, {"deep []any == []any", []any{[]int{1}, 2, []any{"3"}}, []any{[]any{1}, 2, []string{"3"}}, true}, {"deep []any != []any", []any{[]int{1}, 2, []any{"3", "42"}}, []any{[]any{1}, 2, []string{"3"}}, false}, {"map[string]any == map[string]any", map[string]any{"a": 1}, map[string]any{"a": 1}, true}, {"map[string]any != map[string]any", map[string]any{"a": 1}, map[string]any{"a": 1, "b": 2}, false}, } func TestEqual(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got := runtime.Equal(tt.a, tt.b) assert.Equal(t, tt.want, got, "Equal(%v, %v) = %v; want %v", tt.a, tt.b, got, tt.want) got = runtime.Equal(tt.b, tt.a) assert.Equal(t, tt.want, got, "Equal(%v, %v) = %v; want %v", tt.b, tt.a, got, tt.want) }) } } func BenchmarkEqual(b *testing.B) { for _, tt := range tests { b.Run(tt.name, func(b *testing.B) { for i := 0; i < b.N; i++ { runtime.Equal(tt.a, tt.b) } }) } } ================================================ FILE: vm/runtime/runtime.go ================================================ package runtime //go:generate sh -c "go run ./helpers > ./helpers[generated].go" import ( "fmt" "math" "reflect" "sync" "github.com/expr-lang/expr/internal/deref" ) var fieldCache sync.Map type fieldCacheKey struct { t reflect.Type f string } func Fetch(from, i any) any { v := reflect.ValueOf(from) if v.Kind() == reflect.Invalid { panic(fmt.Sprintf("cannot fetch %v from %T", i, from)) } // Methods can be defined on any type. if v.NumMethod() > 0 { if methodName, ok := i.(string); ok { method := v.MethodByName(methodName) if method.IsValid() { return method.Interface() } } } // Structs, maps, and slices can be access through a pointer or through // a value, when they are accessed through a pointer we don't want to // copy them to a value. // De-reference everything if necessary (interface and pointers) v = deref.Value(v) switch v.Kind() { case reflect.Array, reflect.Slice, reflect.String: index := ToInt(i) l := v.Len() if index < 0 { index = l + index } if index < 0 || index >= l { panic(fmt.Sprintf("index out of range: %v (array length is %v)", index, l)) } value := v.Index(index) if value.IsValid() { return value.Interface() } case reflect.Map: var value reflect.Value if i == nil { value = v.MapIndex(reflect.Zero(v.Type().Key())) } else { value = v.MapIndex(reflect.ValueOf(i)) } if value.IsValid() { return value.Interface() } else { elem := reflect.TypeOf(from).Elem() return reflect.Zero(elem).Interface() } case reflect.Struct: fieldName := i.(string) t := v.Type() key := fieldCacheKey{ t: t, f: fieldName, } if cv, ok := fieldCache.Load(key); ok { return v.FieldByIndex(cv.([]int)).Interface() } field, ok := t.FieldByNameFunc(func(name string) bool { field, _ := t.FieldByName(name) switch field.Tag.Get("expr") { case "-": return false case fieldName: return true default: return name == fieldName } }) if ok && field.IsExported() { value := v.FieldByIndex(field.Index) if value.IsValid() { fieldCache.Store(key, field.Index) return value.Interface() } } } panic(fmt.Sprintf("cannot fetch %v from %T", i, from)) } type Field struct { Index []int Path []string } func FetchField(from any, field *Field) any { v := reflect.ValueOf(from) if v.Kind() != reflect.Invalid { v = reflect.Indirect(v) // We can use v.FieldByIndex here, but it will panic if the field // is not exists. And we need to recover() to generate a more // user-friendly error message. // Also, our fieldByIndex() function is slightly faster than the // v.FieldByIndex() function as we don't need to verify what a field // is a struct as we already did it on compilation step. value := fieldByIndex(v, field) if value.IsValid() { return value.Interface() } } panic(fmt.Sprintf("cannot get %v from %T", field.Path[0], from)) } func fieldByIndex(v reflect.Value, field *Field) reflect.Value { if len(field.Index) == 1 { return v.Field(field.Index[0]) } for i, x := range field.Index { if i > 0 { if v.Kind() == reflect.Ptr { if v.IsNil() { panic(fmt.Sprintf("cannot get %v from %v", field.Path[i], field.Path[i-1])) } v = v.Elem() } } v = v.Field(x) } return v } type Method struct { Index int Name string } func FetchMethod(from any, method *Method) any { v := reflect.ValueOf(from) kind := v.Kind() if kind != reflect.Invalid { // Methods can be defined on any type, no need to dereference. method := v.Method(method.Index) if method.IsValid() { return method.Interface() } } panic(fmt.Sprintf("cannot fetch %v from %T", method.Name, from)) } func Slice(array, from, to any) any { v := reflect.ValueOf(array) switch v.Kind() { case reflect.Array, reflect.Slice, reflect.String: length := v.Len() a, b := ToInt(from), ToInt(to) if a < 0 { a = length + a } if a < 0 { a = 0 } if b < 0 { b = length + b } if b < 0 { b = 0 } if b > length { b = length } if a > b { a = b } if v.Kind() == reflect.Array && !v.CanAddr() { newValue := reflect.New(v.Type()).Elem() newValue.Set(v) v = newValue } value := v.Slice(a, b) if value.IsValid() { return value.Interface() } case reflect.Ptr: value := v.Elem() if value.IsValid() { return Slice(value.Interface(), from, to) } } panic(fmt.Sprintf("cannot slice %v", from)) } func In(needle any, array any) bool { if array == nil { return false } v := reflect.ValueOf(array) switch v.Kind() { case reflect.Array, reflect.Slice: for i := 0; i < v.Len(); i++ { value := v.Index(i) if value.IsValid() { if Equal(value.Interface(), needle) { return true } } } return false case reflect.Map: var value reflect.Value if needle == nil { value = v.MapIndex(reflect.Zero(v.Type().Key())) } else { value = v.MapIndex(reflect.ValueOf(needle)) } if value.IsValid() { return true } return false case reflect.Struct: n := reflect.ValueOf(needle) if !n.IsValid() || n.Kind() != reflect.String { panic(fmt.Sprintf("cannot use %T as field name of %T", needle, array)) } field, ok := v.Type().FieldByName(n.String()) if !ok || !field.IsExported() || field.Tag.Get("expr") == "-" { return false } value := v.FieldByIndex(field.Index) if value.IsValid() { return true } return false case reflect.Ptr: value := v.Elem() if value.IsValid() { return In(needle, value.Interface()) } return false } panic(fmt.Sprintf(`operator "in" not defined on %T`, array)) } func Len(a any) int { v := reflect.ValueOf(a) switch v.Kind() { case reflect.Array, reflect.Slice, reflect.Map, reflect.String: return v.Len() default: panic(fmt.Sprintf("invalid argument for len (type %T)", a)) } } func Negate(i any) any { switch v := i.(type) { case float32: return -v case float64: return -v case int: return -v case int8: return -v case int16: return -v case int32: return -v case int64: return -v case uint: return -v case uint8: return -v case uint16: return -v case uint32: return -v case uint64: return -v default: panic(fmt.Sprintf("invalid operation: - %T", v)) } } func Exponent(a, b any) float64 { return math.Pow(ToFloat64(a), ToFloat64(b)) } func MakeRange(min, max int) []int { size := max - min + 1 if size <= 0 { return []int{} } rng := make([]int, size) for i := range rng { rng[i] = min + i } return rng } func ToInt(a any) int { switch x := a.(type) { case float32: return int(x) case float64: return int(x) case int: return x case int8: return int(x) case int16: return int(x) case int32: return int(x) case int64: return int(x) case uint: return int(x) case uint8: return int(x) case uint16: return int(x) case uint32: return int(x) case uint64: return int(x) default: panic(fmt.Sprintf("invalid operation: int(%T)", x)) } } func ToInt64(a any) int64 { switch x := a.(type) { case float32: return int64(x) case float64: return int64(x) case int: return int64(x) case int8: return int64(x) case int16: return int64(x) case int32: return int64(x) case int64: return x case uint: return int64(x) case uint8: return int64(x) case uint16: return int64(x) case uint32: return int64(x) case uint64: return int64(x) default: panic(fmt.Sprintf("invalid operation: int64(%T)", x)) } } func ToFloat64(a any) float64 { switch x := a.(type) { case float32: return float64(x) case float64: return x case int: return float64(x) case int8: return float64(x) case int16: return float64(x) case int32: return float64(x) case int64: return float64(x) case uint: return float64(x) case uint8: return float64(x) case uint16: return float64(x) case uint32: return float64(x) case uint64: return float64(x) default: panic(fmt.Sprintf("invalid operation: float(%T)", x)) } } func ToBool(a any) bool { if a == nil { return false } switch x := a.(type) { case bool: return x default: panic(fmt.Sprintf("invalid operation: bool(%T)", x)) } } func IsNil(v any) bool { if v == nil { return true } r := reflect.ValueOf(v) switch r.Kind() { case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Slice: return r.IsNil() default: return false } } ================================================ FILE: vm/runtime/sort.go ================================================ package runtime type SortBy struct { Desc bool Array []any Values []any } func (s *SortBy) Len() int { return len(s.Array) } func (s *SortBy) Swap(i, j int) { s.Array[i], s.Array[j] = s.Array[j], s.Array[i] s.Values[i], s.Values[j] = s.Values[j], s.Values[i] } func (s *SortBy) Less(i, j int) bool { a, b := s.Values[i], s.Values[j] if s.Desc { return Less(b, a) } return Less(a, b) } type Sort struct { Desc bool Array []any } func (s *Sort) Len() int { return len(s.Array) } func (s *Sort) Swap(i, j int) { s.Array[i], s.Array[j] = s.Array[j], s.Array[i] } func (s *Sort) Less(i, j int) bool { a, b := s.Array[i], s.Array[j] if s.Desc { return Less(b, a) } return Less(a, b) } ================================================ FILE: vm/utils.go ================================================ package vm import ( "reflect" "time" ) type ( Function = func(params ...any) (any, error) SafeFunction = func(params ...any) (any, uint, error) ) var ( errorType = reflect.TypeOf((*error)(nil)).Elem() ) type Scope struct { Array reflect.Value Index int Len int Count int Acc any // Fast paths Ints []int Floats []float64 Strings []string Anys []any } // Item returns the current element from the scope using fast paths when available. func (s *Scope) Item() any { if s.Ints != nil { return s.Ints[s.Index] } if s.Floats != nil { return s.Floats[s.Index] } if s.Strings != nil { return s.Strings[s.Index] } if s.Anys != nil { return s.Anys[s.Index] } return s.Array.Index(s.Index).Interface() } type groupBy = map[any][]any type Span struct { Name string `json:"name"` Expression string `json:"expression"` Duration int64 `json:"duration"` Children []*Span `json:"children"` start time.Time } func GetSpan(program *Program) *Span { return program.span } ================================================ FILE: vm/vm.go ================================================ package vm //go:generate sh -c "go run ./func_types > ./func_types[generated].go" import ( "fmt" "reflect" "regexp" "sort" "strings" "time" "github.com/expr-lang/expr/builtin" "github.com/expr-lang/expr/conf" "github.com/expr-lang/expr/file" "github.com/expr-lang/expr/internal/deref" "github.com/expr-lang/expr/vm/runtime" ) const maxFnArgsBuf = 256 func Run(program *Program, env any) (any, error) { if program == nil { return nil, fmt.Errorf("program is nil") } vm := VM{} return vm.Run(program, env) } func Debug() *VM { vm := &VM{ debug: true, step: make(chan struct{}, 0), curr: make(chan int, 0), } return vm } type VM struct { Stack []any Scopes []*Scope Variables []any MemoryBudget uint ip int memory uint debug bool step chan struct{} curr chan int scopePool []Scope // Pre-allocated pool of Scope values; grows as needed but never shrinks scopePoolIdx int // Current index into scopePool for allocation currScope *Scope // Cached pointer to the current scope (optimization) } func (vm *VM) Run(program *Program, env any) (_ any, err error) { defer func() { if r := recover(); r != nil { var location file.Location if vm.ip-1 < len(program.locations) { location = program.locations[vm.ip-1] } f := &file.Error{ Location: location, Message: fmt.Sprintf("%v", r), } if err, ok := r.(error); ok { f.Wrap(err) } err = f.Bind(program.source) } }() if vm.Stack == nil { vm.Stack = make([]any, 0, 2) } else { clearSlice(vm.Stack) vm.Stack = vm.Stack[0:0] } if vm.Scopes != nil { clearSlice(vm.Scopes) vm.Scopes = vm.Scopes[0:0] } vm.scopePoolIdx = 0 // Reset pool index for reuse vm.currScope = nil if len(vm.Variables) < program.variables { vm.Variables = make([]any, program.variables) } if vm.MemoryBudget == 0 { vm.MemoryBudget = conf.DefaultMemoryBudget } vm.memory = 0 vm.ip = 0 var fnArgsBuf []any for vm.ip < len(program.Bytecode) { if debug && vm.debug { <-vm.step } op := program.Bytecode[vm.ip] arg := program.Arguments[vm.ip] vm.ip += 1 switch op { case OpInvalid: panic("invalid opcode") case OpPush: vm.push(program.Constants[arg]) case OpInt: vm.push(arg) case OpPop: vm.pop() case OpStore: vm.Variables[arg] = vm.pop() case OpLoadVar: vm.push(vm.Variables[arg]) case OpLoadConst: vm.push(runtime.Fetch(env, program.Constants[arg])) case OpLoadField: vm.push(runtime.FetchField(env, program.Constants[arg].(*runtime.Field))) case OpLoadFast: vm.push(env.(map[string]any)[program.Constants[arg].(string)]) case OpLoadMethod: vm.push(runtime.FetchMethod(env, program.Constants[arg].(*runtime.Method))) case OpLoadFunc: vm.push(program.functions[arg]) case OpFetch: b := vm.pop() a := vm.pop() vm.push(runtime.Fetch(a, b)) case OpFetchField: a := vm.pop() vm.push(runtime.FetchField(a, program.Constants[arg].(*runtime.Field))) case OpLoadEnv: vm.push(env) case OpMethod: a := vm.pop() vm.push(runtime.FetchMethod(a, program.Constants[arg].(*runtime.Method))) case OpTrue: vm.push(true) case OpFalse: vm.push(false) case OpNil: vm.push(nil) case OpNegate: v := runtime.Negate(vm.pop()) vm.push(v) case OpNot: v := vm.pop().(bool) vm.push(!v) case OpEqual: b := vm.pop() a := vm.pop() vm.push(runtime.Equal(a, b)) case OpEqualInt: b := vm.pop() a := vm.pop() vm.push(a.(int) == b.(int)) case OpEqualString: b := vm.pop() a := vm.pop() vm.push(a.(string) == b.(string)) case OpJump: if arg < 0 { panic("negative jump offset is invalid") } vm.ip += arg case OpJumpIfTrue: if arg < 0 { panic("negative jump offset is invalid") } if vm.current().(bool) { vm.ip += arg } case OpJumpIfFalse: if arg < 0 { panic("negative jump offset is invalid") } if !vm.current().(bool) { vm.ip += arg } case OpJumpIfNil: if arg < 0 { panic("negative jump offset is invalid") } if runtime.IsNil(vm.current()) { vm.ip += arg } case OpJumpIfNotNil: if arg < 0 { panic("negative jump offset is invalid") } if !runtime.IsNil(vm.current()) { vm.ip += arg } case OpJumpIfEnd: if arg < 0 { panic("negative jump offset is invalid") } if vm.currScope.Index >= vm.currScope.Len { vm.ip += arg } case OpJumpBackward: vm.ip -= arg case OpIn: b := vm.pop() a := vm.pop() vm.push(runtime.In(a, b)) case OpLess: b := vm.pop() a := vm.pop() vm.push(runtime.Less(a, b)) case OpMore: b := vm.pop() a := vm.pop() vm.push(runtime.More(a, b)) case OpLessOrEqual: b := vm.pop() a := vm.pop() vm.push(runtime.LessOrEqual(a, b)) case OpMoreOrEqual: b := vm.pop() a := vm.pop() vm.push(runtime.MoreOrEqual(a, b)) case OpAdd: b := vm.pop() a := vm.pop() vm.push(runtime.Add(a, b)) case OpSubtract: b := vm.pop() a := vm.pop() vm.push(runtime.Subtract(a, b)) case OpMultiply: b := vm.pop() a := vm.pop() vm.push(runtime.Multiply(a, b)) case OpDivide: b := vm.pop() a := vm.pop() vm.push(runtime.Divide(a, b)) case OpModulo: b := vm.pop() a := vm.pop() vm.push(runtime.Modulo(a, b)) case OpExponent: b := vm.pop() a := vm.pop() vm.push(runtime.Exponent(a, b)) case OpRange: b := vm.pop() a := vm.pop() min := runtime.ToInt(a) max := runtime.ToInt(b) size := max - min + 1 if size <= 0 { size = 0 } vm.memGrow(uint(size)) vm.push(runtime.MakeRange(min, max)) case OpMatches: b := vm.pop() a := vm.pop() if runtime.IsNil(a) || runtime.IsNil(b) { vm.push(false) break } var match bool var err error if s, ok := a.(string); ok { match, err = regexp.MatchString(b.(string), s) } else { match, err = regexp.Match(b.(string), a.([]byte)) } if err != nil { panic(err) } vm.push(match) case OpMatchesConst: a := vm.pop() if runtime.IsNil(a) { vm.push(false) break } r := program.Constants[arg].(*regexp.Regexp) if s, ok := a.(string); ok { vm.push(r.MatchString(s)) } else { vm.push(r.Match(a.([]byte))) } case OpContains: b := vm.pop() a := vm.pop() if runtime.IsNil(a) || runtime.IsNil(b) { vm.push(false) break } vm.push(strings.Contains(a.(string), b.(string))) case OpStartsWith: b := vm.pop() a := vm.pop() if runtime.IsNil(a) || runtime.IsNil(b) { vm.push(false) break } vm.push(strings.HasPrefix(a.(string), b.(string))) case OpEndsWith: b := vm.pop() a := vm.pop() if runtime.IsNil(a) || runtime.IsNil(b) { vm.push(false) break } vm.push(strings.HasSuffix(a.(string), b.(string))) case OpSlice: from := vm.pop() to := vm.pop() node := vm.pop() vm.push(runtime.Slice(node, from, to)) case OpCall: v := vm.pop() if v == nil { panic("invalid operation: cannot call nil") } fn := reflect.ValueOf(v) if fn.Kind() != reflect.Func { panic(fmt.Sprintf("invalid operation: cannot call non-function of type %T", v)) } fnType := fn.Type() size := arg isVariadic := fnType.IsVariadic() numIn := fnType.NumIn() if isVariadic { if size < numIn-1 { panic(fmt.Sprintf("invalid number of arguments: expected at least %d, got %d", numIn-1, size)) } } else { if size != numIn { panic(fmt.Sprintf("invalid number of arguments: expected %d, got %d", numIn, size)) } } in := make([]reflect.Value, size) for i := int(size) - 1; i >= 0; i-- { param := vm.pop() if param == nil { var inType reflect.Type if isVariadic && i >= numIn-1 { inType = fnType.In(numIn - 1).Elem() } else { inType = fnType.In(i) } in[i] = reflect.Zero(inType) } else { in[i] = reflect.ValueOf(param) } } out := fn.Call(in) if len(out) == 2 && out[1].Type() == errorType && !out[1].IsNil() { panic(out[1].Interface().(error)) } vm.push(out[0].Interface()) case OpCall0: out, err := program.functions[arg]() if err != nil { panic(err) } vm.push(out) case OpCall1: var args []any args, fnArgsBuf = vm.getArgsForFunc(fnArgsBuf, program, 1) out, err := program.functions[arg](args...) if err != nil { panic(err) } vm.push(out) case OpCall2: var args []any args, fnArgsBuf = vm.getArgsForFunc(fnArgsBuf, program, 2) out, err := program.functions[arg](args...) if err != nil { panic(err) } vm.push(out) case OpCall3: var args []any args, fnArgsBuf = vm.getArgsForFunc(fnArgsBuf, program, 3) out, err := program.functions[arg](args...) if err != nil { panic(err) } vm.push(out) case OpCallN: fn := vm.pop().(Function) var args []any args, fnArgsBuf = vm.getArgsForFunc(fnArgsBuf, program, arg) out, err := fn(args...) if err != nil { panic(err) } vm.push(out) case OpCallFast: fn := vm.pop().(func(...any) any) var args []any args, fnArgsBuf = vm.getArgsForFunc(fnArgsBuf, program, arg) vm.push(fn(args...)) case OpCallSafe: fn := vm.pop().(SafeFunction) var args []any args, fnArgsBuf = vm.getArgsForFunc(fnArgsBuf, program, arg) out, mem, err := fn(args...) if err != nil { panic(err) } vm.memGrow(mem) vm.push(out) case OpCallTyped: vm.push(vm.call(vm.pop(), arg)) case OpCallBuiltin1: vm.push(builtin.Builtins[arg].Fast(vm.pop())) case OpArray: size := vm.pop().(int) vm.memGrow(uint(size)) array := make([]any, size) for i := size - 1; i >= 0; i-- { array[i] = vm.pop() } vm.push(array) case OpMap: size := vm.pop().(int) vm.memGrow(uint(size)) m := make(map[string]any) for i := size - 1; i >= 0; i-- { value := vm.pop() key := vm.pop() m[key.(string)] = value } vm.push(m) case OpLen: vm.push(runtime.Len(vm.current())) case OpCast: switch arg { case 0: vm.push(runtime.ToInt(vm.pop())) case 1: vm.push(runtime.ToInt64(vm.pop())) case 2: vm.push(runtime.ToFloat64(vm.pop())) case 3: vm.push(runtime.ToBool(vm.pop())) } case OpDeref: a := vm.pop() vm.push(deref.Interface(a)) case OpIncrementIndex: vm.currScope.Index++ case OpDecrementIndex: vm.currScope.Index-- case OpIncrementCount: vm.currScope.Count++ case OpGetIndex: vm.push(vm.currScope.Index) case OpGetCount: vm.push(vm.currScope.Count) case OpGetLen: vm.push(vm.currScope.Len) case OpGetAcc: vm.push(vm.currScope.Acc) case OpSetAcc: vm.currScope.Acc = vm.pop() case OpSetIndex: vm.currScope.Index = vm.pop().(int) case OpPointer: vm.push(vm.currScope.Item()) case OpThrow: panic(vm.pop().(error)) case OpCreate: switch arg { case 1: vm.push(make(groupBy)) case 2: scope := vm.currScope var desc bool order, ok := vm.pop().(string) if !ok { panic("sortBy order argument must be a string") } switch order { case "asc": desc = false case "desc": desc = true default: panic("unknown order, use asc or desc") } vm.push(&runtime.SortBy{ Desc: desc, Array: make([]any, 0, scope.Len), Values: make([]any, 0, scope.Len), }) default: panic(fmt.Sprintf("unknown OpCreate argument %v", arg)) } case OpGroupBy: scope := vm.currScope key := vm.pop() if key != nil && !reflect.TypeOf(key).Comparable() { panic(fmt.Sprintf("cannot use %T as a key for groupBy: type is not comparable", key)) } scope.Acc.(groupBy)[key] = append(scope.Acc.(groupBy)[key], scope.Item()) case OpSortBy: scope := vm.currScope value := vm.pop() sortable := scope.Acc.(*runtime.SortBy) sortable.Array = append(sortable.Array, scope.Item()) sortable.Values = append(sortable.Values, value) case OpSort: scope := vm.currScope sortable := scope.Acc.(*runtime.SortBy) sort.Sort(sortable) vm.memGrow(uint(scope.Len)) vm.push(sortable.Array) case OpProfileStart: span := program.Constants[arg].(*Span) span.start = time.Now() case OpProfileEnd: span := program.Constants[arg].(*Span) span.Duration += time.Since(span.start).Nanoseconds() case OpBegin: a := vm.pop() s := vm.allocScope() switch v := a.(type) { case []int: s.Ints = v s.Len = len(v) case []float64: s.Floats = v s.Len = len(v) case []string: s.Strings = v s.Len = len(v) case []any: s.Anys = v s.Len = len(v) default: s.Array = reflect.ValueOf(a) s.Len = s.Array.Len() } vm.Scopes = append(vm.Scopes, s) vm.currScope = s case OpAnd: a := vm.pop() b := vm.pop() vm.push(a.(bool) && b.(bool)) case OpOr: a := vm.pop() b := vm.pop() vm.push(a.(bool) || b.(bool)) case OpEnd: vm.Scopes = vm.Scopes[:len(vm.Scopes)-1] if len(vm.Scopes) > 0 { vm.currScope = vm.Scopes[len(vm.Scopes)-1] } else { vm.currScope = nil } default: panic(fmt.Sprintf("unknown bytecode %#x", op)) } if debug && vm.debug { vm.curr <- vm.ip } } if debug && vm.debug { close(vm.curr) close(vm.step) } if len(vm.Stack) > 0 { return vm.pop(), nil } return nil, nil } func (vm *VM) push(value any) { vm.Stack = append(vm.Stack, value) } func (vm *VM) current() any { if len(vm.Stack) == 0 { panic("stack underflow") } return vm.Stack[len(vm.Stack)-1] } func (vm *VM) pop() any { if len(vm.Stack) == 0 { panic("stack underflow") } value := vm.Stack[len(vm.Stack)-1] vm.Stack = vm.Stack[:len(vm.Stack)-1] return value } func (vm *VM) memGrow(size uint) { vm.memory += size if vm.memory >= vm.MemoryBudget { panic("memory budget exceeded") } } func (vm *VM) scope() *Scope { return vm.Scopes[len(vm.Scopes)-1] } // allocScope returns a pointer to a Scope from the pool, growing the pool if needed. // Callers must set Len and exactly one of: Ints, Floats, Strings, Anys, or Array. func (vm *VM) allocScope() *Scope { if vm.scopePoolIdx >= len(vm.scopePool) { vm.scopePool = append(vm.scopePool, Scope{}) } s := &vm.scopePool[vm.scopePoolIdx] vm.scopePoolIdx++ // Reset iteration state s.Index = 0 s.Count = 0 s.Acc = nil // Clear typed slice pointers to avoid stale fast-path matches s.Ints = nil s.Floats = nil s.Strings = nil s.Anys = nil // Clear Array to release reference for GC (only matters for fallback path) s.Array = reflect.Value{} return s } // getArgsForFunc lazily initializes the buffer the first time it is called for // a given program (thus, it also needs "program" to run). It will // take "needed" elements from the buffer and populate them with vm.pop() in // reverse order. Because the estimation can fall short, this function can // occasionally make a new allocation. func (vm *VM) getArgsForFunc(argsBuf []any, program *Program, needed int) (args []any, argsBufOut []any) { if needed == 0 || program == nil { return nil, argsBuf } // Step 1: fix estimations and preallocate if argsBuf == nil { estimatedFnArgsCount := estimateFnArgsCount(program) if estimatedFnArgsCount > maxFnArgsBuf { // put a practical limit to avoid excessive preallocation estimatedFnArgsCount = maxFnArgsBuf } if estimatedFnArgsCount < needed { // in the case that the first call is for example OpCallN with a large // number of arguments, then make sure we will be able to serve them at // least. estimatedFnArgsCount = needed } // in the case that we are preparing the arguments for the first // function call of the program, then argsBuf will be nil, so we // initialize it. We delay this initial allocation here because a // program could have many function calls but exit earlier than the // first call, so in that case we avoid allocating unnecessarily argsBuf = make([]any, estimatedFnArgsCount) } // Step 2: get the final slice that will be returned var buf []any if len(argsBuf) >= needed { // in this case, we are successfully using the single preallocation. We // use the full slice expression [low : high : max] because in that way // a function that receives this slice as variadic arguments will not be // able to make modifications to contiguous elements with append(). If // they call append on their variadic arguments they will make a new // allocation. buf = (argsBuf)[:needed:needed] argsBuf = (argsBuf)[needed:] // advance the buffer } else { // if we have been making calls to something like OpCallN with many more // arguments than what we estimated, then we will need to allocate // separately buf = make([]any, needed) } // Step 3: populate the final slice bulk copying from the stack. This is the // exact order and copy() is a highly optimized operation copy(buf, vm.Stack[len(vm.Stack)-needed:]) vm.Stack = vm.Stack[:len(vm.Stack)-needed] return buf, argsBuf } func (vm *VM) Step() { vm.step <- struct{}{} } func (vm *VM) Position() chan int { return vm.curr } func clearSlice[S ~[]E, E any](s S) { var zero E for i := range s { s[i] = zero // clear mem, optimized by the compiler, in Go 1.21 the "clear" builtin can be used } } // estimateFnArgsCount inspects a *Program and estimates how many function // arguments will be required to run it. func estimateFnArgsCount(program *Program) int { // Implementation note: a program will not necessarily go through all // operations, but this is just an estimation var count int for _, op := range program.Bytecode { if int(op) < len(opArgLenEstimation) { count += opArgLenEstimation[op] } } return count } var opArgLenEstimation = [...]int{ OpCall1: 1, OpCall2: 2, OpCall3: 3, // we don't know exactly but we know at least 4, so be conservative as this // is only an optimization and we also want to avoid excessive preallocation OpCallN: 4, // here we don't know either, but we can guess it could be common to receive // up to 3 arguments in a function OpCallFast: 3, OpCallSafe: 3, } ================================================ FILE: vm/vm_bench_test.go ================================================ package vm_test import ( "runtime" "testing" "github.com/expr-lang/expr" "github.com/expr-lang/expr/checker" "github.com/expr-lang/expr/compiler" "github.com/expr-lang/expr/conf" "github.com/expr-lang/expr/vm" ) func BenchmarkVM(b *testing.B) { cases := []struct { name, input string }{ {"function calls", ` func( func( func(func(a, 'a', 1, nil), func(a, 'a', 1, nil), func(a, 'a', 1, nil)), func(func(a, 'a', 1, nil), func(a, 'a', 1, nil), func(a, 'a', 1, nil)), func(func(a, 'a', 1, nil), func(a, 'a', 1, nil), func(a, 'a', 1, nil)), ), func( func(func(a, 'a', 1, nil), func(a, 'a', 1, nil), func(a, 'a', 1, nil)), func(func(a, 'a', 1, nil), func(a, 'a', 1, nil), func(a, 'a', 1, nil)), func(func(a, 'a', 1, nil), func(a, 'a', 1, nil), func(a, 'a', 1, nil)), ), func( func(func(a, 'a', 1, nil), func(a, 'a', 1, nil), func(a, 'a', 1, nil)), func(func(a, 'a', 1, nil), func(a, 'a', 1, nil), func(a, 'a', 1, nil)), func(func(a, 'a', 1, nil), func(a, 'a', 1, nil), func(a, 'a', 1, nil)), ) ) `}, } a := new(recursive) for i, b := 0, a; i < 40*4; i++ { b.Inner = new(recursive) b = b.Inner } f := func(params ...any) (any, error) { return nil, nil } env := map[string]any{ "a": a, "b": true, "func": f, } config := conf.New(env) expr.Function("func", f, f)(config) config.Check() for _, c := range cases { tree, err := checker.ParseCheck(c.input, config) if err != nil { b.Fatal(c.input, "parse and check", err) } prog, err := compiler.Compile(tree, config) if err != nil { b.Fatal(c.input, "compile", err) } //b.Logf("disassembled:\n%s", prog.Disassemble()) //b.FailNow() runtime.GC() var vm vm.VM b.Run("name="+c.name, func(b *testing.B) { for i := 0; i < b.N; i++ { _, err = vm.Run(prog, env) } }) if err != nil { b.Fatal(err) } } } type recursive struct { Inner *recursive `expr:"a"` } ================================================ FILE: vm/vm_test.go ================================================ package vm_test import ( "errors" "fmt" "reflect" "strings" "testing" "time" "github.com/expr-lang/expr/file" "github.com/expr-lang/expr/internal/testify/require" "github.com/expr-lang/expr" "github.com/expr-lang/expr/checker" "github.com/expr-lang/expr/compiler" "github.com/expr-lang/expr/conf" "github.com/expr-lang/expr/parser" "github.com/expr-lang/expr/vm" ) func TestRun_NilProgram(t *testing.T) { _, err := vm.Run(nil, nil) require.Error(t, err) } func TestRun_ReuseVM(t *testing.T) { node, err := parser.Parse(`map(1..2, {#})`) require.NoError(t, err) program, err := compiler.Compile(node, nil) require.NoError(t, err) reuse := vm.VM{} _, err = reuse.Run(program, nil) require.NoError(t, err) _, err = reuse.Run(program, nil) require.NoError(t, err) } func TestRun_ReuseVM_for_different_variables(t *testing.T) { v := vm.VM{} program, err := expr.Compile(`let a = 1; a + 1`) require.NoError(t, err) out, err := v.Run(program, nil) require.NoError(t, err) require.Equal(t, 2, out) program, err = expr.Compile(`let a = 2; a + 1`) require.NoError(t, err) out, err = v.Run(program, nil) require.NoError(t, err) require.Equal(t, 3, out) program, err = expr.Compile(`let a = 2; let b = 2; a + b`) require.NoError(t, err) out, err = v.Run(program, nil) require.NoError(t, err) require.Equal(t, 4, out) } func TestRun_Cast(t *testing.T) { tests := []struct { input string expect reflect.Kind want any }{ { input: `1`, expect: reflect.Float64, want: float64(1), }, { input: `1`, expect: reflect.Int, want: int(1), }, { input: `1`, expect: reflect.Int64, want: int64(1), }, { input: `true`, expect: reflect.Bool, want: true, }, { input: `false`, expect: reflect.Bool, want: false, }, { input: `nil`, expect: reflect.Bool, want: false, }, } for _, tt := range tests { t.Run(fmt.Sprintf("%v %v", tt.expect, tt.input), func(t *testing.T) { tree, err := parser.Parse(tt.input) require.NoError(t, err) program, err := compiler.Compile(tree, &conf.Config{Expect: tt.expect}) require.NoError(t, err) out, err := vm.Run(program, nil) require.NoError(t, err) require.Equal(t, tt.want, out) }) } } func TestRun_Helpers(t *testing.T) { values := []any{ uint(1), uint8(1), uint16(1), uint32(1), uint64(1), 1, int8(1), int16(1), int32(1), int64(1), float32(1), float64(1), } ops := []string{"+", "-", "*", "/", "%", "==", ">=", "<=", "<", ">"} for _, a := range values { for _, b := range values { for _, op := range ops { if op == "%" { switch a.(type) { case float32, float64: continue } switch b.(type) { case float32, float64: continue } } input := fmt.Sprintf("a %v b", op) env := map[string]any{ "a": a, "b": b, } config := conf.CreateNew() tree, err := parser.Parse(input) require.NoError(t, err) _, err = checker.Check(tree, config) require.NoError(t, err) program, err := compiler.Compile(tree, config) require.NoError(t, err) _, err = vm.Run(program, env) require.NoError(t, err) } } } } type ErrorEnv struct { InnerEnv InnerEnv } type InnerEnv struct{} func (ErrorEnv) WillError(param string) (bool, error) { if param == "yes" { return false, errors.New("error") } return true, nil } func (InnerEnv) WillError(param string) (bool, error) { if param == "yes" { return false, errors.New("inner error") } return true, nil } func TestRun_MethodWithError(t *testing.T) { input := `WillError("yes")` tree, err := parser.Parse(input) require.NoError(t, err) env := ErrorEnv{} funcConf := conf.New(env) _, err = checker.Check(tree, funcConf) require.NoError(t, err) program, err := compiler.Compile(tree, funcConf) require.NoError(t, err) out, err := vm.Run(program, env) require.EqualError(t, err, "error (1:1)\n | WillError(\"yes\")\n | ^") require.Equal(t, nil, out) selfErr := errors.Unwrap(err) require.NotNil(t, err) require.Equal(t, "error", selfErr.Error()) } func TestRun_FastMethods(t *testing.T) { input := `hello() + world()` tree, err := parser.Parse(input) require.NoError(t, err) env := map[string]any{ "hello": func(...any) any { return "hello " }, "world": func(...any) any { return "world" }, } funcConf := conf.New(env) _, err = checker.Check(tree, funcConf) require.NoError(t, err) program, err := compiler.Compile(tree, funcConf) require.NoError(t, err) out, err := vm.Run(program, env) require.NoError(t, err) require.Equal(t, "hello world", out) } func TestRun_InnerMethodWithError(t *testing.T) { input := `InnerEnv.WillError("yes")` tree, err := parser.Parse(input) require.NoError(t, err) env := ErrorEnv{} funcConf := conf.New(env) program, err := compiler.Compile(tree, funcConf) require.NoError(t, err) out, err := vm.Run(program, env) require.EqualError(t, err, "inner error (1:10)\n | InnerEnv.WillError(\"yes\")\n | .........^") require.Equal(t, nil, out) } func TestRun_InnerMethodWithError_NilSafe(t *testing.T) { input := `InnerEnv?.WillError("yes")` tree, err := parser.Parse(input) require.NoError(t, err) env := ErrorEnv{} funcConf := conf.New(env) program, err := compiler.Compile(tree, funcConf) require.NoError(t, err) out, err := vm.Run(program, env) require.EqualError(t, err, "inner error (1:11)\n | InnerEnv?.WillError(\"yes\")\n | ..........^") require.Equal(t, nil, out) } func TestRun_TaggedFieldName(t *testing.T) { input := `value` tree, err := parser.Parse(input) require.NoError(t, err) env := struct { V string `expr:"value"` }{ V: "hello world", } funcConf := conf.New(env) _, err = checker.Check(tree, funcConf) require.NoError(t, err) program, err := compiler.Compile(tree, funcConf) require.NoError(t, err) out, err := vm.Run(program, env) require.NoError(t, err) require.Equal(t, "hello world", out) } func TestRun_OpInvalid(t *testing.T) { program := &vm.Program{ Bytecode: []vm.Opcode{vm.OpInvalid}, Arguments: []int{0}, } _, err := vm.Run(program, nil) require.EqualError(t, err, "invalid opcode") } func TestVM_OpcodeOperations(t *testing.T) { tests := []struct { name string expr string env map[string]any want any expectError string }{ // Arithmetic Operations { name: "basic addition", expr: "2 + 3", want: 5, }, { name: "mixed type arithmetic", expr: "2.5 + 3", want: 5.5, }, { name: "chained arithmetic", expr: "1 + 2 * 3 - 4 / 2", want: 5.0, }, { name: "modulo operation", expr: "5 % 2", want: 1, }, { name: "exponent operation", expr: "2 ^ 3", want: 8.0, }, { name: "negation", expr: "-5", want: -5, }, // String Operations { name: "string concatenation", expr: `"hello" + " " + "world"`, want: "hello world", }, { name: "string starts with", expr: `"hello world" startsWith "hello"`, want: true, }, { name: "string ends with", expr: `"hello world" endsWith "world"`, want: true, }, { name: "string contains", expr: `"hello world" contains "lo wo"`, want: true, }, { name: "string matches regex", expr: `"hello123" matches "^hello\\d+$"`, want: true, }, { name: "byte slice matches regex", expr: `b matches "^hello\\d+$"`, env: map[string]any{"b": []byte("hello123")}, want: true, }, { name: "byte slice matches dynamic regex", expr: `b matches pattern`, env: map[string]any{"b": []byte("hello123"), "pattern": "^hello\\d+$"}, want: true, }, // Data Structure Operations { name: "array creation and access", expr: "[1, 2, 3][1]", want: 2, }, { name: "map creation and access", expr: `{"a": 1, "b": 2}.b`, want: 2, }, { name: "array length", expr: "len([1, 2, 3])", want: 3, }, { name: "array slice", expr: "[1, 2, 3, 4][1:3]", want: []any{2, 3}, }, { name: "array range", expr: "1..5", want: []int{1, 2, 3, 4, 5}, }, // Error Cases { name: "invalid array index", expr: "[1,2,3][5]", expectError: "index out of range", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { program, err := expr.Compile(tt.expr, expr.Env(tt.env)) require.NoError(t, err) testVM := &vm.VM{} got, err := testVM.Run(program, tt.env) if tt.expectError != "" { require.Error(t, err) require.Contains(t, err.Error(), tt.expectError) } else { require.NoError(t, err) require.Equal(t, tt.want, got) } }) } } func TestVM_GroupAndSortOperations(t *testing.T) { tests := []struct { name string expr string env map[string]any want any expectError string }{ { name: "group by single field", expr: `groupBy([{"id": 1, "type": "a"}, {"id": 2, "type": "b"}, {"id": 3, "type": "a"}], #.type)`, want: map[any][]any{ "a": { map[string]any{"id": 1, "type": "a"}, map[string]any{"id": 3, "type": "a"}, }, "b": { map[string]any{"id": 2, "type": "b"}, }, }, }, { name: "sort by field ascending", expr: `sortBy([{"id": 3}, {"id": 1}, {"id": 2}], #.id)`, want: []any{ map[string]any{"id": 1}, map[string]any{"id": 2}, map[string]any{"id": 3}, }, }, { name: "sort by field descending", expr: `sortBy([{"id": 3}, {"id": 1}, {"id": 2}], #.id, "desc")`, want: []any{ map[string]any{"id": 3}, map[string]any{"id": 2}, map[string]any{"id": 1}, }, }, { name: "sort by computed value", expr: `sortBy([1, 2, 3, 4], # % 2)`, want: []any{2, 4, 1, 3}, }, { name: "group by with complex key", expr: `groupBy([1, 2, 3, 4, 5, 6], # % 2 == 0 ? "even" : "odd")`, want: map[any][]any{ "even": {2, 4, 6}, "odd": {1, 3, 5}, }, }, { name: "group by with non-comparable key", expr: `groupBy([1, 2, 3], [#, # + 1])`, // predicate returns a slice, which is not comparable expectError: "not comparable", }, { name: "invalid sort order", expr: `sortBy([1, 2, 3], #, "invalid")`, expectError: "unknown order", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { program, err := expr.Compile(tt.expr, expr.Env(tt.env)) require.NoError(t, err) testVM := &vm.VM{} got, err := testVM.Run(program, tt.env) if tt.expectError != "" { require.Error(t, err) require.Contains(t, err.Error(), tt.expectError) } else { require.NoError(t, err) require.Equal(t, tt.want, got) } }) } } // TestVM_SortBy_NonStringOrder tests that sortBy with non-string order // returns a proper error instead of panicking (regression test for OSS-Fuzz #477658245). func TestVM_SortBy_NonStringOrder(t *testing.T) { env := map[string]any{} fn := expr.Function("fn", func(params ...any) (any, error) { return fmt.Sprintf("fn(%v)", params), nil }) // This expression passes a function result as the order argument to sortBy. // The function returns a string that is not "asc" or "desc", which should // produce a proper error rather than a panic. program, err := expr.Compile(`sortBy([1, 2, 3], #, fn($env))`, expr.Env(env), fn) require.NoError(t, err) testVM := &vm.VM{} _, err = testVM.Run(program, env) require.Error(t, err) require.Contains(t, err.Error(), "unknown order") } // TestVM_ProfileOperations tests the profiling opcodes func TestVM_ProfileOperations(t *testing.T) { program := &vm.Program{ Bytecode: []vm.Opcode{ vm.OpProfileStart, vm.OpPush, vm.OpCall, vm.OpProfileEnd, }, Arguments: []int{0, 1, 0, 0}, Constants: []any{ &vm.Span{}, func() (any, error) { time.Sleep(time.Millisecond * 10) return nil, nil }, }, } testVM := &vm.VM{} _, err := testVM.Run(program, nil) require.NoError(t, err) span := program.Constants[0].(*vm.Span) require.Greater(t, span.Duration, time.Millisecond) } // TestVM_IndexOperations tests the index manipulation opcodes func TestVM_IndexOperations(t *testing.T) { tests := []struct { name string expr string want any }{ { name: "decrement index in loop", expr: "reduce([1,2,3], #acc + #, 0)", want: 6, }, { name: "set index in loop", expr: "map([1,2,3], # * 2)", want: []any{2, 4, 6}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { program, err := expr.Compile(tt.expr) require.NoError(t, err) testVM := &vm.VM{} got, err := testVM.Run(program, nil) require.NoError(t, err) require.Equal(t, tt.want, got) }) } } // TestVM_DirectCallOpcodes tests the specialized call opcodes directly func TestVM_DirectCallOpcodes(t *testing.T) { tests := []struct { name string bytecode []vm.Opcode args []int consts []any funcs []vm.Function want any wantErr bool }{ { name: "OpCall0", bytecode: []vm.Opcode{vm.OpCall0}, args: []int{0}, funcs: []vm.Function{ func(args ...any) (any, error) { return 42, nil }, }, want: 42, }, { name: "OpCall1", bytecode: []vm.Opcode{ vm.OpPush, vm.OpCall1, }, args: []int{0, 0}, consts: []any{10}, funcs: []vm.Function{ func(args ...any) (any, error) { return args[0].(int) * 2, nil }, }, want: 20, }, { name: "OpCall2", bytecode: []vm.Opcode{ vm.OpPush, vm.OpPush, vm.OpCall2, }, args: []int{0, 1, 0}, consts: []any{10, 5}, funcs: []vm.Function{ func(args ...any) (any, error) { return args[0].(int) + args[1].(int), nil }, }, want: 15, }, { name: "OpCall3", bytecode: []vm.Opcode{ vm.OpPush, vm.OpPush, vm.OpPush, vm.OpCall3, }, args: []int{0, 1, 2, 0}, consts: []any{10, 5, 2}, funcs: []vm.Function{ func(args ...any) (any, error) { return args[0].(int) + args[1].(int) + args[2].(int), nil }, }, want: 17, }, { name: "OpCallN with error", bytecode: []vm.Opcode{ vm.OpLoadFunc, vm.OpCallN, }, args: []int{0, 0}, // Function index, number of args (0) funcs: []vm.Function{ func(args ...any) (any, error) { return nil, fmt.Errorf("test error") }, }, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { program := vm.NewProgram( file.Source{}, // source nil, // node nil, // locations 0, // variables tt.consts, tt.bytecode, tt.args, tt.funcs, nil, // debugInfo nil, // span ) vm := &vm.VM{} got, err := vm.Run(program, nil) if tt.wantErr { require.Error(t, err) } else { require.NoError(t, err) require.Equal(t, tt.want, got) } }) } } func TestVM_CallN(t *testing.T) { input := `fn(1, 2, 3)` tree, err := parser.Parse(input) require.NoError(t, err) env := map[string]any{ "fn": func(args ...any) (any, error) { sum := 0 for _, arg := range args { sum += arg.(int) } return sum, nil }, } config := conf.New(env) program, err := compiler.Compile(tree, config) require.NoError(t, err) out, err := vm.Run(program, env) require.NoError(t, err) require.Equal(t, 6, out) } // TestVM_IndexAndCountOperations tests the index and count manipulation opcodes directly func TestVM_IndexAndCountOperations(t *testing.T) { tests := []struct { name string bytecode []vm.Opcode args []int consts []any want any wantErr bool }{ { name: "GetIndex", bytecode: []vm.Opcode{ vm.OpPush, // Push array to stack vm.OpBegin, // Start scope vm.OpGetIndex, // Get current index }, args: []int{0, 0, 0}, consts: []any{[]any{1, 2, 3}}, // Array for scope want: 0, // Initial index is 0 }, { name: "DecrementIndex", bytecode: []vm.Opcode{ vm.OpPush, // Push array to stack vm.OpBegin, // Start scope vm.OpDecrementIndex, // Decrement index vm.OpGetIndex, // Get current index }, args: []int{0, 0, 0, 0}, consts: []any{[]any{1, 2, 3}}, // Array for scope want: -1, // After decrement }, { name: "GetCount", bytecode: []vm.Opcode{ vm.OpPush, // Push array to stack vm.OpBegin, // Start scope vm.OpGetCount, // Get current count }, args: []int{0, 0, 0}, consts: []any{[]any{1, 2, 3}}, // Array for scope want: 0, // Initial count is 0 }, { name: "IncrementCount", bytecode: []vm.Opcode{ vm.OpPush, // Push array to stack vm.OpBegin, // Start scope vm.OpIncrementCount, // Increment count vm.OpGetCount, // Get current count }, args: []int{0, 0, 0, 0}, consts: []any{[]any{1, 2, 3}}, // Array for scope want: 1, // After increment }, { name: "Multiple operations", bytecode: []vm.Opcode{ vm.OpPush, // Push array to stack vm.OpBegin, // Start scope vm.OpIncrementCount, // Count = 1 vm.OpIncrementCount, // Count = 2 vm.OpDecrementIndex, // Index = -1 vm.OpDecrementIndex, // Index = -2 vm.OpGetCount, // Push count (2) vm.OpGetIndex, // Push index (-2) vm.OpAdd, // Add them together }, args: []int{0, 0, 0, 0, 0, 0, 0, 0, 0}, consts: []any{[]any{1, 2, 3}}, // Array for scope want: 0, // 2 + (-2) = 0 }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { program := vm.NewProgram( file.Source{}, // source nil, // node nil, // locations 0, // variables tt.consts, tt.bytecode, tt.args, nil, // functions nil, // debugInfo nil, // span ) vm := &vm.VM{} got, err := vm.Run(program, nil) if tt.wantErr { require.Error(t, err) } else { require.NoError(t, err) require.Equal(t, tt.want, got) } }) } } // TestVM_DirectBasicOpcodes tests basic opcodes directly func TestVM_DirectBasicOpcodes(t *testing.T) { tests := []struct { name string bytecode []vm.Opcode args []int consts []any env any want any wantErr bool }{ { name: "OpLoadEnv", bytecode: []vm.Opcode{ vm.OpLoadEnv, // Load entire environment }, args: []int{0}, env: map[string]any{"key": "value"}, want: map[string]any{"key": "value"}, }, { name: "OpTrue", bytecode: []vm.Opcode{ vm.OpTrue, }, args: []int{0}, want: true, }, { name: "OpFalse", bytecode: []vm.Opcode{ vm.OpFalse, }, args: []int{0}, want: false, }, { name: "OpNil", bytecode: []vm.Opcode{ vm.OpNil, }, args: []int{0}, want: nil, }, { name: "OpNegate int", bytecode: []vm.Opcode{ vm.OpPush, // Push number vm.OpNegate, // Negate it }, args: []int{0, 0}, consts: []any{42}, want: -42, }, { name: "OpNegate float", bytecode: []vm.Opcode{ vm.OpPush, // Push number vm.OpNegate, // Negate it }, args: []int{0, 0}, consts: []any{42.5}, want: -42.5, }, { name: "OpNot true", bytecode: []vm.Opcode{ vm.OpTrue, // Push true vm.OpNot, // Negate it }, args: []int{0, 0}, want: false, }, { name: "OpNot false", bytecode: []vm.Opcode{ vm.OpFalse, // Push false vm.OpNot, // Negate it }, args: []int{0, 0}, want: true, }, { name: "OpNot error", bytecode: []vm.Opcode{ vm.OpPush, // Push non-bool vm.OpNot, // Try to negate it }, args: []int{0, 0}, consts: []any{"not a bool"}, wantErr: true, }, { name: "OpEqualString equal", bytecode: []vm.Opcode{ vm.OpPush, // Push first string vm.OpPush, // Push second string vm.OpEqualString, // Compare strings }, args: []int{0, 1, 0}, consts: []any{"hello", "hello"}, want: true, }, { name: "OpEqualString not equal", bytecode: []vm.Opcode{ vm.OpPush, // Push first string vm.OpPush, // Push second string vm.OpEqualString, // Compare strings }, args: []int{0, 1, 0}, consts: []any{"hello", "world"}, want: false, }, { name: "OpEqualString with empty strings", bytecode: []vm.Opcode{ vm.OpPush, // Push first string vm.OpPush, // Push second string vm.OpEqualString, // Compare strings }, args: []int{0, 1, 0}, consts: []any{"", ""}, want: true, }, { name: "OpEqualString type error", bytecode: []vm.Opcode{ vm.OpPush, // Push non-string vm.OpPush, // Push string vm.OpEqualString, // Try to compare }, args: []int{0, 1, 0}, consts: []any{42, "hello"}, wantErr: true, }, { name: "OpInt", bytecode: []vm.Opcode{ vm.OpInt, // Push int directly from args }, args: []int{42}, // The value 42 is passed directly in args consts: []any{}, // No constants needed want: 42, }, { name: "OpInt negative", bytecode: []vm.Opcode{ vm.OpInt, // Push negative int directly from args }, args: []int{-42}, // The value -42 is passed directly in args consts: []any{}, // No constants needed want: -42, }, { name: "OpInt zero", bytecode: []vm.Opcode{ vm.OpInt, // Push zero directly from args }, args: []int{0}, // The value 0 is passed directly in args consts: []any{}, // No constants needed want: 0, }, { name: "OpIn array true", bytecode: []vm.Opcode{ vm.OpPush, // Push element vm.OpPush, // Push array vm.OpIn, // Check if element is in array }, args: []int{0, 1, 0}, consts: []any{2, []any{1, 2, 3}}, want: true, }, { name: "OpIn array false", bytecode: []vm.Opcode{ vm.OpPush, // Push element vm.OpPush, // Push array vm.OpIn, // Check if element is in array }, args: []int{0, 1, 0}, consts: []any{4, []any{1, 2, 3}}, want: false, }, { name: "OpIn map true", bytecode: []vm.Opcode{ vm.OpPush, // Push key vm.OpPush, // Push map vm.OpIn, // Check if key is in map }, args: []int{0, 1, 0}, consts: []any{"b", map[string]any{"a": 1, "b": 2}}, want: true, }, { name: "OpIn map false", bytecode: []vm.Opcode{ vm.OpPush, // Push key vm.OpPush, // Push map vm.OpIn, // Check if key is in map }, args: []int{0, 1, 0}, consts: []any{"c", map[string]any{"a": 1, "b": 2}}, want: false, }, { name: "OpExponent integers", bytecode: []vm.Opcode{ vm.OpPush, // Push base vm.OpPush, // Push exponent vm.OpExponent, // Calculate power }, args: []int{0, 1, 0}, consts: []any{2, 3}, want: 8.0, }, { name: "OpExponent floats", bytecode: []vm.Opcode{ vm.OpPush, // Push base vm.OpPush, // Push exponent vm.OpExponent, // Calculate power }, args: []int{0, 1, 0}, consts: []any{2.0, 3.0}, want: 8.0, }, { name: "OpExponent negative exponent", bytecode: []vm.Opcode{ vm.OpPush, // Push base vm.OpPush, // Push exponent vm.OpExponent, // Calculate power }, args: []int{0, 1, 0}, consts: []any{2.0, -2.0}, want: 0.25, }, { name: "OpMatches valid regex", bytecode: []vm.Opcode{ vm.OpPush, // Push string vm.OpPush, // Push pattern vm.OpMatches, // Match string against pattern }, args: []int{0, 1, 0}, consts: []any{"hello123", "^hello\\d+$"}, want: true, }, { name: "OpMatches non-matching regex", bytecode: []vm.Opcode{ vm.OpPush, // Push string vm.OpPush, // Push pattern vm.OpMatches, // Match string against pattern }, args: []int{0, 1, 0}, consts: []any{"hello", "^\\d+$"}, want: false, }, { name: "OpMatches invalid regex", bytecode: []vm.Opcode{ vm.OpPush, // Push string vm.OpPush, // Push pattern vm.OpMatches, // Match string against pattern }, args: []int{0, 1, 0}, consts: []any{"hello", "[invalid"}, wantErr: true, }, { name: "OpMatches type error", bytecode: []vm.Opcode{ vm.OpPush, // Push non-string vm.OpPush, // Push pattern vm.OpMatches, // Match against pattern }, args: []int{0, 1, 0}, consts: []any{42, "^\\d+$"}, wantErr: true, }, { name: "OpCast int to float64", bytecode: []vm.Opcode{ vm.OpPush, // Push int vm.OpCast, // Cast to float64 }, args: []int{0, 2}, consts: []any{42}, want: float64(42), }, { name: "OpCast int32 to int64", bytecode: []vm.Opcode{ vm.OpPush, // Push int32 vm.OpCast, // Cast to int64 }, args: []int{0, 1}, consts: []any{int32(42)}, want: int64(42), }, { name: "OpCast bool to bool", bytecode: []vm.Opcode{ vm.OpTrue, // Push true vm.OpCast, // Cast to bool }, args: []int{0, 3}, want: true, }, { name: "OpCast nil to bool", bytecode: []vm.Opcode{ vm.OpNil, // Push nil vm.OpCast, // Cast to bool }, args: []int{0, 3}, want: false, }, { name: "OpCast int to bool", bytecode: []vm.Opcode{ vm.OpPush, // Push int vm.OpCast, // Cast to bool }, args: []int{0, 3}, consts: []any{1}, wantErr: true, }, { name: "OpCast invalid type", bytecode: []vm.Opcode{ vm.OpPush, // Push string vm.OpCast, // Try to cast to float64 }, args: []int{0, 0}, consts: []any{"not a number"}, wantErr: true, }, { name: "OpLen array", bytecode: []vm.Opcode{ vm.OpPush, // Push array vm.OpLen, // Get length }, args: []int{0, 0}, consts: []any{[]any{1, 2, 3}}, want: 3, }, { name: "OpLen empty array", bytecode: []vm.Opcode{ vm.OpPush, // Push empty array vm.OpLen, // Get length }, args: []int{0, 0}, consts: []any{[]any{}}, want: 0, }, { name: "OpLen string", bytecode: []vm.Opcode{ vm.OpPush, // Push string vm.OpLen, // Get length }, args: []int{0, 0}, consts: []any{"hello"}, want: 5, }, { name: "OpLen empty string", bytecode: []vm.Opcode{ vm.OpPush, // Push empty string vm.OpLen, // Get length }, args: []int{0, 0}, consts: []any{""}, want: 0, }, { name: "OpLen map", bytecode: []vm.Opcode{ vm.OpPush, // Push map vm.OpLen, // Get length }, args: []int{0, 0}, consts: []any{map[string]any{"a": 1, "b": 2, "c": 3}}, want: 3, }, { name: "OpLen empty map", bytecode: []vm.Opcode{ vm.OpPush, // Push empty map vm.OpLen, // Get length }, args: []int{0, 0}, consts: []any{map[string]any{}}, want: 0, }, { name: "OpLen invalid type", bytecode: []vm.Opcode{ vm.OpPush, // Push number vm.OpLen, // Try to get length }, args: []int{0, 0}, consts: []any{42}, wantErr: true, }, { name: "OpThrow with string", bytecode: []vm.Opcode{ vm.OpPush, // Push error message vm.OpThrow, // Throw error }, args: []int{0, 0}, consts: []any{"test error"}, wantErr: true, }, { name: "OpThrow with error", bytecode: []vm.Opcode{ vm.OpPush, // Push error vm.OpThrow, // Throw error }, args: []int{0, 0}, consts: []any{fmt.Errorf("test error")}, wantErr: true, }, { name: "OpDefault", bytecode: []vm.Opcode{ vm.OpEnd + 1, // OpEnd is always last, this is anunknown opcode }, args: []int{0, 0}, consts: []any{fmt.Errorf("test error")}, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { program := vm.NewProgram( file.Source{}, // source nil, // node nil, // locations 0, // variables tt.consts, tt.bytecode, tt.args, nil, // functions nil, // debugInfo nil, // span ) vm := &vm.VM{} got, err := vm.Run(program, tt.env) if tt.wantErr { require.Error(t, err) } else { require.NoError(t, err) require.Equal(t, tt.want, got) } }) } } func TestVM_MemoryBudget(t *testing.T) { tests := []struct { name string expr string memBudget uint expectError string }{ { name: "under budget", expr: "map(1..10, #)", memBudget: 100, }, { name: "exceeds budget", expr: "map(1..1000, #)", memBudget: 10, expectError: "memory budget exceeded", }, { name: "zero budget uses default", expr: "map(1..10, #)", memBudget: 0, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { node, err := parser.Parse(tt.expr) require.NoError(t, err) program, err := compiler.Compile(node, nil) require.NoError(t, err) vm := vm.VM{MemoryBudget: tt.memBudget} out, err := vm.Run(program, nil) if tt.expectError != "" { require.Error(t, err) require.Contains(t, err.Error(), tt.expectError) } else { require.NoError(t, err) require.NotNil(t, out) } }) } } // Helper functions for creating deeply nested expressions func createNestedArithmeticExpr(t *testing.T, depth int) string { t.Helper() if depth == 0 { return "a" } return fmt.Sprintf("(%s + %d)", createNestedArithmeticExpr(t, depth-1), depth) } func createNestedMapExpr(t *testing.T, depth int) string { t.Helper() if depth == 0 { return `{"value": 1}` } return fmt.Sprintf(`{"nested": %s}`, createNestedMapExpr(t, depth-1)) } func TestVM_Limits(t *testing.T) { tests := []struct { name string expr string memoryBudget uint maxNodes uint env map[string]any expectError string }{ { name: "nested arithmetic allowed with max nodes and memory budget", expr: createNestedArithmeticExpr(t, 100), env: map[string]any{"a": 1}, maxNodes: 1000, memoryBudget: 1, // arithmetic expressions not counted towards memory budget }, { name: "nested arithmetic blocked by max nodes", expr: createNestedArithmeticExpr(t, 10000), env: map[string]any{"a": 1}, maxNodes: 100, memoryBudget: 1, // arithmetic expressions not counted towards memory budget expectError: "compilation failed: expression exceeds maximum allowed nodes", }, { name: "nested map blocked by memory budget", expr: createNestedMapExpr(t, 100), env: map[string]any{}, maxNodes: 1000, memoryBudget: 10, // Small memory budget to trigger limit expectError: "memory budget exceeded", }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { var options []expr.Option options = append(options, expr.Env(test.env)) if test.maxNodes > 0 { options = append(options, func(c *conf.Config) { c.MaxNodes = test.maxNodes }) } program, err := expr.Compile(test.expr, options...) if err != nil { if test.expectError != "" && strings.Contains(err.Error(), test.expectError) { return } t.Fatal(err) } testVM := &vm.VM{ MemoryBudget: test.memoryBudget, } _, err = testVM.Run(program, test.env) if test.expectError == "" { require.NoError(t, err) } else { require.Error(t, err) require.Contains(t, err.Error(), test.expectError) } }) } } func TestVM_OpJump_NegativeOffset(t *testing.T) { program := vm.NewProgram( file.Source{}, nil, nil, 0, nil, []vm.Opcode{ vm.OpInt, vm.OpInt, vm.OpJump, vm.OpInt, vm.OpJump, }, []int{ 1, 2, -2, // negative offset for a forward jump opcode 3, -2, }, nil, nil, nil, ) _, err := vm.Run(program, nil) require.Error(t, err) require.Contains(t, err.Error(), "negative jump offset is invalid") } func TestVM_StackUnderflow(t *testing.T) { tests := []struct { name string bytecode []vm.Opcode args []int expectError string }{ { name: "pop after push", bytecode: []vm.Opcode{vm.OpInt, vm.OpPop}, args: []int{42, 0}, }, { name: "underflow after valid operations", bytecode: []vm.Opcode{vm.OpInt, vm.OpInt, vm.OpPop, vm.OpPop, vm.OpPop}, args: []int{1, 2, 0, 0, 0}, expectError: "stack underflow", }, { name: "pop on empty stack", bytecode: []vm.Opcode{vm.OpPop}, args: []int{0}, expectError: "stack underflow", }, { name: "pop after push", bytecode: []vm.Opcode{vm.OpInt, vm.OpPop}, args: []int{123, 0}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { program := &vm.Program{ Bytecode: tt.bytecode, Arguments: tt.args, Constants: []any{}, } _, err := vm.Run(program, nil) if tt.expectError != "" { require.Error(t, err) require.Contains(t, err.Error(), tt.expectError) } else { require.NoError(t, err) } }) } } func TestVM_EnvNotCallable(t *testing.T) { // $env is the environment, not a function. env := map[string]any{ "ok": true, } code := `$env('' matches ' '? : now().UTC(g))` _, err := expr.Compile(code, expr.Env(env)) require.Error(t, err) require.Contains(t, err.Error(), "is not callable") } func TestVM_OpCall_InvalidNumberOfArguments(t *testing.T) { // Test that the VM validates argument count at runtime. // Compile without Env() so compiler generates OpCall without type info. program, err := expr.Compile(`fn(1, 2)`) require.NoError(t, err) // Run with a function that has different arity env := map[string]any{ "fn": func(a int) int { return a }, } _, err = expr.Run(program, env) require.Error(t, err) require.Contains(t, err.Error(), "invalid number of arguments") } func TestVM_OpCall_InvalidNumberOfArguments_Variadic(t *testing.T) { // Test variadic function with too few arguments. program, err := expr.Compile(`fn()`) require.NoError(t, err) // Run with a variadic function that requires at least 1 argument env := map[string]any{ "fn": func(first int, rest ...int) int { return first }, } _, err = expr.Run(program, env) require.Error(t, err) require.Contains(t, err.Error(), "invalid number of arguments") }