Skip to content

Commit f716dc5

Browse files
committed
Add predicates to list of builtins
1 parent 604a9e0 commit f716dc5

File tree

4 files changed

+68
-23
lines changed

4 files changed

+68
-23
lines changed

builtin/builtin.go

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@ import (
1212
)
1313

1414
type Function struct {
15-
Name string
16-
Func func(args ...interface{}) (interface{}, error)
17-
Types []reflect.Type
18-
Builtin1 func(arg interface{}) interface{}
19-
Validate func(args []reflect.Type) (reflect.Type, error)
15+
Name string
16+
Func func(args ...interface{}) (interface{}, error)
17+
Types []reflect.Type
18+
Builtin1 func(arg interface{}) interface{}
19+
Validate func(args []reflect.Type) (reflect.Type, error)
20+
Predicate bool
2021
}
2122

2223
var (
@@ -34,6 +35,41 @@ func init() {
3435
}
3536

3637
var Builtins = []*Function{
38+
{
39+
Name: "all",
40+
Predicate: true,
41+
Types: types(new(func([]interface{}, func(interface{}) bool) bool)),
42+
},
43+
{
44+
Name: "none",
45+
Predicate: true,
46+
Types: types(new(func([]interface{}, func(interface{}) bool) bool)),
47+
},
48+
{
49+
Name: "any",
50+
Predicate: true,
51+
Types: types(new(func([]interface{}, func(interface{}) bool) bool)),
52+
},
53+
{
54+
Name: "one",
55+
Predicate: true,
56+
Types: types(new(func([]interface{}, func(interface{}) bool) bool)),
57+
},
58+
{
59+
Name: "filter",
60+
Predicate: true,
61+
Types: types(new(func([]interface{}, func(interface{}) bool) []interface{})),
62+
},
63+
{
64+
Name: "map",
65+
Predicate: true,
66+
Types: types(new(func([]interface{}, func(interface{}) interface{}) []interface{})),
67+
},
68+
{
69+
Name: "count",
70+
Predicate: true,
71+
Types: types(new(func([]interface{}, func(interface{}) bool) int)),
72+
},
3773
{
3874
Name: "len",
3975
Builtin1: Len,

builtin/builtin_test.go

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,9 @@ func TestBuiltin_works_with_any(t *testing.T) {
113113
}
114114

115115
for _, b := range builtin.Builtins {
116+
if b.Predicate {
117+
continue
118+
}
116119
t.Run(b.Name, func(t *testing.T) {
117120
arity := 1
118121
if c, ok := config[b.Name]; ok {
@@ -249,12 +252,15 @@ func TestBuiltin_disallow_builtins_override(t *testing.T) {
249252

250253
func TestBuiltin_DisableBuiltin(t *testing.T) {
251254
t.Run("via env", func(t *testing.T) {
252-
for _, name := range builtin.Names {
253-
t.Run(name, func(t *testing.T) {
255+
for _, b := range builtin.Builtins {
256+
if b.Predicate {
257+
continue // TODO: allow to disable predicates
258+
}
259+
t.Run(b.Name, func(t *testing.T) {
254260
env := map[string]interface{}{
255-
name: func() int { return 42 },
261+
b.Name: func() int { return 42 },
256262
}
257-
program, err := expr.Compile(name+"()", expr.Env(env), expr.DisableBuiltin(name))
263+
program, err := expr.Compile(b.Name+"()", expr.Env(env), expr.DisableBuiltin(b.Name))
258264
require.NoError(t, err)
259265

260266
out, err := expr.Run(program, env)
@@ -264,15 +270,18 @@ func TestBuiltin_DisableBuiltin(t *testing.T) {
264270
}
265271
})
266272
t.Run("via expr.Function", func(t *testing.T) {
267-
for _, name := range builtin.Names {
268-
t.Run(name, func(t *testing.T) {
269-
fn := expr.Function(name,
273+
for _, b := range builtin.Builtins {
274+
if b.Predicate {
275+
continue // TODO: allow to disable predicates
276+
}
277+
t.Run(b.Name, func(t *testing.T) {
278+
fn := expr.Function(b.Name,
270279
func(params ...interface{}) (interface{}, error) {
271280
return 42, nil
272281
},
273282
new(func() int),
274283
)
275-
program, err := expr.Compile(name+"()", fn, expr.DisableBuiltin(name))
284+
program, err := expr.Compile(b.Name+"()", fn, expr.DisableBuiltin(b.Name))
276285
require.NoError(t, err)
277286

278287
out, err := expr.Run(program, nil)

checker/checker_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -635,7 +635,7 @@ func TestCheck_AllowUndefinedVariables(t *testing.T) {
635635
A int
636636
}
637637

638-
tree, err := parser.Parse(`any + fn()`)
638+
tree, err := parser.Parse(`Any + fn()`)
639639
require.NoError(t, err)
640640

641641
config := conf.New(Env{})
@@ -648,7 +648,7 @@ func TestCheck_AllowUndefinedVariables(t *testing.T) {
648648
func TestCheck_AllowUndefinedVariables_DefaultType(t *testing.T) {
649649
env := map[string]bool{}
650650

651-
tree, err := parser.Parse(`any`)
651+
tree, err := parser.Parse(`Any`)
652652
require.NoError(t, err)
653653

654654
config := conf.New(env)

test/deref/deref_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,28 +12,28 @@ func TestDeref_binary(t *testing.T) {
1212
i := 1
1313
env := map[string]interface{}{
1414
"i": &i,
15-
"map": map[string]interface{}{
15+
"obj": map[string]interface{}{
1616
"i": &i,
1717
},
1818
}
1919
t.Run("==", func(t *testing.T) {
20-
program, err := expr.Compile(`i == 1 && map.i == 1`, expr.Env(env))
20+
program, err := expr.Compile(`i == 1 && obj.i == 1`, expr.Env(env))
2121
require.NoError(t, err)
2222

2323
out, err := expr.Run(program, env)
2424
require.NoError(t, err)
2525
require.Equal(t, true, out)
2626
})
2727
t.Run("><", func(t *testing.T) {
28-
program, err := expr.Compile(`i > 0 && map.i < 99`, expr.Env(env))
28+
program, err := expr.Compile(`i > 0 && obj.i < 99`, expr.Env(env))
2929
require.NoError(t, err)
3030

3131
out, err := expr.Run(program, env)
3232
require.NoError(t, err)
3333
require.Equal(t, true, out)
3434
})
3535
t.Run("??+", func(t *testing.T) {
36-
program, err := expr.Compile(`(i ?? map.i) + 1`, expr.Env(env))
36+
program, err := expr.Compile(`(i ?? obj.i) + 1`, expr.Env(env))
3737
require.NoError(t, err)
3838

3939
out, err := expr.Run(program, env)
@@ -47,12 +47,12 @@ func TestDeref_unary(t *testing.T) {
4747
ok := true
4848
env := map[string]interface{}{
4949
"i": &i,
50-
"map": map[string]interface{}{
50+
"obj": map[string]interface{}{
5151
"ok": &ok,
5252
},
5353
}
5454

55-
program, err := expr.Compile(`-i < 0 && !!map.ok`, expr.Env(env))
55+
program, err := expr.Compile(`-i < 0 && !!obj.ok`, expr.Env(env))
5656
require.NoError(t, err)
5757

5858
out, err := expr.Run(program, env)
@@ -64,11 +64,11 @@ func TestDeref_eval(t *testing.T) {
6464
i := 1
6565
env := map[string]interface{}{
6666
"i": &i,
67-
"map": map[string]interface{}{
67+
"obj": map[string]interface{}{
6868
"i": &i,
6969
},
7070
}
71-
out, err := expr.Eval(`i == 1 && map.i == 1`, env)
71+
out, err := expr.Eval(`i == 1 && obj.i == 1`, env)
7272
require.NoError(t, err)
7373
require.Equal(t, true, out)
7474
}

0 commit comments

Comments
 (0)