Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: expr-lang/expr
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.15.5
Choose a base ref
...
head repository: expr-lang/expr
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
Loading
Showing with 70,754 additions and 31,178 deletions.
  1. +1 −0 .gitattributes
  2. +1 −0 .github/FUNDING.yml
  3. +14 −7 .github/scripts/coverage.mjs
  4. +23 −0 .github/workflows/build.yml
  5. +1 −1 .github/workflows/check.yml
  6. +3 −1 .github/workflows/diff.yml
  7. +2 −2 .github/workflows/fuzz.yml
  8. +23 −1 .github/workflows/test.yml
  9. +3 −0 .gitignore
  10. +1 −1 LICENSE
  11. +42 −33 README.md
  12. +2 −5 SECURITY.md
  13. +18 −0 ast/find.go
  14. +31 −0 ast/find_test.go
  15. +0 −12 ast/func.go
  16. +123 −74 ast/node.go
  17. +90 −17 ast/print.go
  18. +24 −9 ast/print_test.go
  19. +8 −1 ast/visitor.go
  20. +3 −2 ast/visitor_test.go
  21. +25 −4 bench_test.go
  22. +342 −248 builtin/builtin.go
  23. +332 −47 builtin/builtin_test.go
  24. +0 −274 builtin/func.go
  25. +23 −0 builtin/function.go
  26. +437 −0 builtin/lib.go
  27. +0 −96 builtin/sort.go
  28. +54 −29 builtin/utils.go
  29. +38 −0 builtin/validation.go
  30. +607 −499 checker/checker.go
  31. +395 −292 checker/checker_test.go
  32. +129 −0 checker/info.go
  33. +28 −0 checker/info_test.go
  34. +261 −0 checker/nature/nature.go
  35. +81 −0 checker/nature/utils.go
  36. +98 −152 checker/types.go
  37. +387 −132 compiler/compiler.go
  38. +397 −16 compiler/compiler_test.go
  39. +55 −71 conf/config.go
  40. +68 −0 conf/env.go
  41. +0 −1 conf/functions.go
  42. +0 −59 conf/operators.go
  43. +0 −136 conf/types_table.go
  44. +8 −7 debug/debugger.go
  45. +3 −3 debug/go.mod
  46. +0 −4 debug/go.sum
  47. +2 −2 docgen/README.md
  48. +12 −17 docgen/docgen.go
  49. +16 −11 docgen/docgen_test.go
  50. +0 −156 docs/Configuration.md
  51. +0 −61 docs/Internals.md
  52. +0 −52 docs/Operator-Overloading.md
  53. +0 −38 docs/Tips.md
  54. +0 −98 docs/Visitor-and-Patch.md
  55. +134 −0 docs/configuration.md
  56. +111 −0 docs/environment.md
  57. +89 −0 docs/functions.md
  58. +52 −48 docs/{Getting-Started.md → getting-started.md}
  59. BIN docs/images/debug.gif
  60. BIN docs/images/logo-small.png
  61. BIN docs/images/logo.png
  62. +409 −125 docs/{Language-Definition.md → language-definition.md}
  63. +136 −0 docs/patch.md
  64. +58 −0 docs/visitor.md
  65. +62 −33 expr.go
  66. +688 −123 expr_test.go
  67. +21 −7 file/error.go
  68. +2 −6 file/location.go
  69. +23 −51 file/source.go
  70. +0 −15 file/source_test.go
  71. +1 −9 go.mod
  72. +0 −10 go.sum
  73. +47 −0 internal/deref/deref.go
  74. +111 −0 internal/deref/deref_test.go
  75. +775 −0 internal/difflib/difflib.go
  76. +426 −0 internal/difflib/difflib_test.go
  77. +146 −0 internal/spew/bypass.go
  78. +39 −0 internal/spew/bypasssafe.go
  79. +341 −0 internal/spew/common.go
  80. +298 −0 internal/spew/common_test.go
  81. +306 −0 internal/spew/config.go
  82. +217 −0 internal/spew/doc.go
  83. +509 −0 internal/spew/dump.go
  84. +1,042 −0 internal/spew/dump_test.go
  85. +102 −0 internal/spew/dumpcgo_test.go
  86. +27 −0 internal/spew/dumpnocgo_test.go
  87. +226 −0 internal/spew/example_test.go
  88. +419 −0 internal/spew/format.go
  89. +1,558 −0 internal/spew/format_test.go
  90. +84 −0 internal/spew/internal_test.go
  91. +102 −0 internal/spew/internalunsafe_test.go
  92. +148 −0 internal/spew/spew.go
  93. +320 −0 internal/spew/spew_test.go
  94. +83 −0 internal/spew/testdata/dumpcgo.go
  95. +489 −0 internal/testify/assert/assertion_compare.go
  96. +472 −0 internal/testify/assert/assertion_compare_test.go
  97. +807 −0 internal/testify/assert/assertion_format.go
  98. +5 −0 internal/testify/assert/assertion_format.go.tmpl
  99. +1,605 −0 internal/testify/assert/assertion_forward.go
  100. +5 −0 internal/testify/assert/assertion_forward.go.tmpl
  101. +81 −0 internal/testify/assert/assertion_order.go
  102. +203 −0 internal/testify/assert/assertion_order_test.go
  103. +2,091 −0 internal/testify/assert/assertions.go
  104. +3,155 −0 internal/testify/assert/assertions_test.go
  105. +46 −0 internal/testify/assert/doc.go
  106. +10 −0 internal/testify/assert/errors.go
  107. +16 −0 internal/testify/assert/forward_assertions.go
  108. +654 −0 internal/testify/assert/forward_assertions_test.go
  109. +165 −0 internal/testify/assert/http_assertions.go
  110. +214 −0 internal/testify/assert/http_assertions_test.go
  111. +4 −0 internal/testify/assert/internal/unsafetests/doc.go
  112. +34 −0 internal/testify/assert/internal/unsafetests/unsafetests_test.go
  113. +29 −0 internal/testify/require/doc.go
  114. +16 −0 internal/testify/require/forward_requirements.go
  115. +397 −0 internal/testify/require/forward_requirements_test.go
  116. +2,039 −0 internal/testify/require/require.go
  117. +6 −0 internal/testify/require/require.go.tmpl
  118. +1,607 −0 internal/testify/require/require_forward.go
  119. +5 −0 internal/testify/require/require_forward.go.tmpl
  120. +29 −0 internal/testify/require/requirements.go
  121. +578 −0 internal/testify/require/requirements_test.go
  122. +4 −8 optimizer/const_expr.go
  123. +0 −40 optimizer/const_range.go
  124. +3 −3 optimizer/filter_first.go
  125. +3 −3 optimizer/filter_last.go
  126. +2 −2 optimizer/filter_len.go
  127. +13 −5 optimizer/filter_map.go
  128. +114 −0 optimizer/filter_map_test.go
  129. +38 −54 optimizer/fold.go
  130. +82 −0 optimizer/fold_test.go
  131. +9 −5 optimizer/in_array.go
  132. +2 −2 optimizer/in_range.go
  133. +41 −3 optimizer/optimizer.go
  134. +185 −79 optimizer/optimizer_test.go
  135. +61 −0 optimizer/predicate_combination.go
  136. +37 −0 optimizer/sum_array.go
  137. +72 −0 optimizer/sum_array_test.go
  138. +25 −0 optimizer/sum_map.go
  139. +35 −0 optimizer/sum_map_test.go
  140. +57 −48 parser/lexer/lexer.go
  141. +82 −17 parser/lexer/lexer_test.go
  142. +15 −12 parser/lexer/state.go
  143. +1 −1 parser/lexer/token.go
  144. +17 −0 parser/operator/operator.go
  145. +466 −257 parser/parser.go
  146. +640 −80 parser/parser_test.go
  147. +147 −0 patcher/operator_override.go
  148. +73 −0 patcher/value/bench_test.go
  149. +216 −0 patcher/value/value.go
  150. +42 −0 patcher/value/value_example_test.go
  151. +171 −0 patcher/value/value_test.go
  152. +45 −0 patcher/with_context.go
  153. +154 −0 patcher/with_context_test.go
  154. +25 −0 patcher/with_timezone.go
  155. +28 −0 patcher/with_timezone_test.go
  156. +5 −5 repl/go.mod
  157. +0 −4 repl/go.sum
  158. +10 −6 repl/repl.go
  159. +63 −0 test/bench/bench_call_test.go
  160. +4 −3 test/coredns/coredns_test.go
  161. +4 −3 test/crowdsec/crowdsec_test.go
  162. +139 −2 test/deref/deref_test.go
  163. +32 −0 test/examples/examples_test.go
  164. +59 −0 test/examples/markdown.go
  165. +13,223 −10,049 test/fuzz/fuzz_corpus.txt
  166. +12 −0 test/fuzz/fuzz_env.go
  167. BIN test/fuzz/fuzz_expr_seed_corpus.zip
  168. +8 −2 test/fuzz/fuzz_test.go
  169. +21 −0 test/gen/env.go
  170. +208 −195 test/gen/gen.go
  171. +47 −7 test/gen/gen_test.go
  172. +9 −27 test/gen/utils.go
  173. +5 −5 test/{interface_method → interface}/interface_method_test.go
  174. +40 −0 test/interface/interface_test.go
  175. +93 −0 test/issues/461/issue_test.go
  176. +52 −0 test/issues/688/issue_test.go
  177. +24 −0 test/issues/723/issue_test.go
  178. +60 −0 test/issues/730/issue_test.go
  179. +19 −0 test/issues/739/issue_test.go
  180. +31 −0 test/issues/756/issue_test.go
  181. +38 −0 test/issues/785/issue_test.go
  182. +54 −1 test/mock/mock.go
  183. +73 −0 test/operator/issues584/issues584_test.go
  184. +208 −9 test/operator/operator_test.go
  185. +61 −0 test/patch/change_ident_test.go
  186. +61 −0 test/patch/patch_count_test.go
  187. +5 −4 test/patch/patch_test.go
  188. +3 −3 test/patch/set_type/set_type_test.go
  189. +3 −2 test/pipes/pipes_test.go
  190. +0 −119 test/real_world/README.md
  191. +0 −14 test/real_world/real_docs/generate.go
  192. +0 −116 test/real_world/real_world.go
  193. +8 −7 test/time/time_test.go
  194. BIN testdata/crash.txt
  195. +129 −0 testdata/examples.md
  196. +0 −16,371 testdata/examples.txt
  197. +22,359 −0 testdata/generated.txt
  198. +181 −0 types/types.go
  199. +50 −0 types/types_test.go
  200. +6 −0 vm/debug.go
  201. +6 −0 vm/debug_off.go
  202. +41 −0 vm/debug_test.go
  203. +46 −18 vm/func_types/main.go
  204. +370 −0 vm/func_types[generated].go
  205. +0 −262 vm/generated.go
  206. +8 −3 vm/opcodes.go
  207. +85 −23 vm/program.go
  208. +1 −1 vm/program_test.go
  209. +46 −4 vm/runtime/helpers/main.go
  210. +343 −0 vm/runtime/{generated.go → helpers[generated].go}
  211. +58 −0 vm/runtime/helpers_test.go
  212. +14 −42 vm/runtime/runtime.go
  213. +45 −0 vm/runtime/sort.go
  214. +37 −0 vm/utils.go
  215. +158 −95 vm/vm.go
  216. +1,099 −59 vm/vm_test.go
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*\[generated\].go linguist-language=txt
1 change: 1 addition & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
github: antonmedv
21 changes: 14 additions & 7 deletions .github/scripts/coverage.mjs
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
#!/usr/bin/env zx --experimental
#!/usr/bin/env zx

const expected = 90
const exclude = [
'expr/test',
'checker/mock',
'vm/func_types',
'vm/runtime/helpers',
'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/antonmedv/expr/... ./...`
await $`go test -coverprofile=coverage.out -coverpkg=github.com/expr-lang/expr/... ./...`
const coverage = fs.readFileSync('coverage.out').toString()
.split('\n')
.filter(line => {
@@ -24,9 +29,11 @@ await spinner('Running tests', async () => {
await $`go tool cover -html=coverage.out -o coverage.html`
})

const cover = await $`go tool cover -func=coverage.out`
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)`)
}
23 changes: 23 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
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' ]
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
2 changes: 1 addition & 1 deletion .github/workflows/check.yml
Original file line number Diff line number Diff line change
@@ -16,4 +16,4 @@ jobs:
with:
go-version: 1.18
- name: Test
run: npx zx --experimental .github/scripts/coverage.mjs
run: npx zx .github/scripts/coverage.mjs
4 changes: 3 additions & 1 deletion .github/workflows/diff.yml
Original file line number Diff line number Diff line change
@@ -13,7 +13,9 @@ jobs:
with:
go-version: 1.18
- name: Install benchstat
run: go install golang.org/x/perf/cmd/benchstat@latest
# 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
4 changes: 2 additions & 2 deletions .github/workflows/fuzz.yml
Original file line number Diff line number Diff line change
@@ -21,14 +21,14 @@ jobs:
fuzz-seconds: 600
output-sarif: true
- name: Upload Crash
uses: actions/upload-artifact@v3
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@v2
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
24 changes: 23 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
go-versions: [ '1.18', '1.19', '1.20', '1.21' ]
go-versions: [ '1.18', '1.19', '1.20', '1.21', '1.22', '1.23', '1.24' ]
steps:
- uses: actions/checkout@v3
- name: Setup Go ${{ matrix.go-version }}
@@ -20,3 +20,25 @@ jobs:
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 .
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -6,3 +6,6 @@
*.test
*.out
*.html
custom_tests.json
pro/
test/avs/
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2019 Anton Medvedev
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
75 changes: 42 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
# Expr
[![test](https://github.com/antonmedv/expr/actions/workflows/test.yml/badge.svg)](https://github.com/antonmedv/expr/actions/workflows/test.yml)
[![Go Report Card](https://goreportcard.com/badge/github.com/antonmedv/expr)](https://goreportcard.com/report/github.com/antonmedv/expr)
[![GoDoc](https://godoc.org/github.com/antonmedv/expr?status.svg)](https://godoc.org/github.com/antonmedv/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)
<h1><a href="https://expr-lang.org"><img src="https://expr-lang.org/img/logo.png" alt="Zx logo" height="48"align="right"></a> Expr</h1>

> [!IMPORTANT]
> The repository [github.com/antonmedv/expr](https://github.com/antonmedv/expr) moved to [github.com/**expr-lang**/expr](https://github.com/expr-lang/expr).
**Expr** is a Go-centric expression language designed to deliver dynamic configurations with unparalleled accuracy, safety, and speed.
[![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)

<img src="https://expr.medv.io/img/logo-small.png" width="150" alt="expr logo" align="right"/>
**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, .Size <= 240)
all(tweets, len(.Content) <= 240)
```

## Features
@@ -53,34 +61,24 @@ Here are its standout features:
## Install

```
go get github.com/antonmedv/expr
go get github.com/expr-lang/expr
```

## Documentation

* See [Getting Started](https://expr.medv.io/docs/Getting-Started) page for developer documentation.
* See [Language Definition](https://expr.medv.io/docs/Language-Definition) page to learn the syntax.

## Expr Code Editor

<a href="https://bit.ly/expr-code-editor">
<img src="https://antonmedv.github.io/expr/ogimage.png" align="center" alt="Expr Code Editor" width="1200"/>
</a>

Also, I have an embeddable code editor written in JavaScript which allows editing expressions with syntax highlighting and autocomplete based on your types declaration.

[Learn more →](https://antonmedv.github.io/expr/)
* 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://play.golang.org/p/z7T8ytJ1T1d)
[Play Online](https://go.dev/play/p/XCoNXEjm3TS)

```go
package main

import (
"fmt"
"github.com/antonmedv/expr"
"github.com/expr-lang/expr"
)

func main() {
@@ -106,14 +104,14 @@ func main() {
}
```

[Play Online](https://play.golang.org/p/4S4brsIvU4i)
[Play Online](https://go.dev/play/p/tz-ZneBfSuw)

```go
package main

import (
"fmt"
"github.com/antonmedv/expr"
"github.com/expr-lang/expr"
)

type Tweet struct {
@@ -153,20 +151,31 @@ func main() {
* [Aviasales](https://aviasales.ru) utilizes Expr as a business rule engine for its flight search engine.
* [Wish.com](https://www.wish.com) employs Expr in its decision-making rule engine for the Wish Assistant.
* [Argo](https://argoproj.github.io) integrates Expr into Argo Rollouts and Argo Workflows for Kubernetes.
* [Crowdsec](https://crowdsec.net) incorporates Expr into its security automation tool.
* [FACEIT](https://www.faceit.com) uses Expr to enhance customization of its eSports matchmaking algorithm.
* [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.
* [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.
* [Milvus](https://milvus.io) integrates Expr into Milvus, an open-source vector database.
* [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.

[Add your company too](https://github.com/antonmedv/expr/edit/master/README.md)
* [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.

[Add your company too](https://github.com/expr-lang/expr/edit/master/README.md)

## License

[MIT](https://github.com/antonmedv/expr/blob/master/LICENSE)
[MIT](https://github.com/expr-lang/expr/blob/master/LICENSE)

<p align="center"><img src="https://expr-lang.org/img/gopher-small.png" width="150" /></p>
7 changes: 2 additions & 5 deletions SECURITY.md
Original file line number Diff line number Diff line change
@@ -11,11 +11,8 @@ unless this is not possible or feasible with a reasonable effort.

| Version | Supported |
|---------|--------------------|
| 1.15 | :white_check_mark: |
| 1.14 | :white_check_mark: |
| 1.13 | :white_check_mark: |
| 1.12 | :white_check_mark: |
| < 1.12 | :x: |
| 1.x | :white_check_mark: |
| 0.x | :x: |

## Reporting a Vulnerability

18 changes: 18 additions & 0 deletions ast/find.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
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
}
}
31 changes: 31 additions & 0 deletions ast/find_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
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)
}
12 changes: 0 additions & 12 deletions ast/func.go

This file was deleted.

Loading