Skip to content

Commit 4fbf622

Browse files
committed
parser should not throw an error if predicate not present
1 parent 2aaa9aa commit 4fbf622

File tree

3 files changed

+122
-7
lines changed

3 files changed

+122
-7
lines changed

builtin/builtin_test.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,90 @@ func TestBuiltin_override_and_still_accessible(t *testing.T) {
460460
assert.Equal(t, true, out)
461461
}
462462

463+
func TestBuiltin_override(t *testing.T) {
464+
env := map[string]any{
465+
"upper": func(a string) string { return strings.ToLower(a) },
466+
}
467+
fn := expr.Function(
468+
"upper",
469+
func(params ...any) (any, error) {
470+
s := params[0].(string)
471+
return strings.ToUpper(s[:1]) + strings.ToLower(s[1:]), nil
472+
})
473+
474+
t.Run("with compiled env", func(t *testing.T) {
475+
program, err := expr.Compile(`upper("str")`, expr.Env(env))
476+
require.NoError(t, err)
477+
478+
out, err := expr.Run(program, env)
479+
require.NoError(t, err)
480+
assert.Equal(t, "str", out)
481+
})
482+
483+
t.Run("with uncompiled env", func(t *testing.T) {
484+
program, err := expr.Compile(`upper("str")`)
485+
require.NoError(t, err)
486+
487+
out, err := expr.Run(program, env)
488+
require.NoError(t, err)
489+
assert.Equal(t, "STR", out)
490+
})
491+
492+
t.Run("with uncompiled env and disabled builtin", func(t *testing.T) {
493+
program, err := expr.Compile(`upper("str")`, expr.DisableBuiltin("upper"))
494+
require.NoError(t, err)
495+
496+
out, err := expr.Run(program, env)
497+
require.NoError(t, err)
498+
assert.Equal(t, "str", out)
499+
})
500+
501+
t.Run("with function", func(t *testing.T) {
502+
program, err := expr.Compile(`upper("str")`, fn)
503+
require.NoError(t, err)
504+
505+
out, err := expr.Run(program, nil)
506+
require.NoError(t, err)
507+
assert.Equal(t, "Str", out)
508+
})
509+
510+
t.Run("with function and compiled env", func(t *testing.T) {
511+
program, err := expr.Compile(`upper("str")`, fn, expr.Env(env))
512+
require.NoError(t, err)
513+
514+
out, err := expr.Run(program, env)
515+
require.NoError(t, err)
516+
assert.Equal(t, "Str", out)
517+
})
518+
519+
t.Run("with function and compiled env and disabled builtin", func(t *testing.T) {
520+
program, err := expr.Compile(`upper("str")`, fn, expr.Env(env), expr.DisableBuiltin("upper"))
521+
require.NoError(t, err)
522+
523+
out, err := expr.Run(program, env)
524+
require.NoError(t, err)
525+
assert.Equal(t, "Str", out)
526+
})
527+
528+
t.Run("with function and uncompiled env", func(t *testing.T) {
529+
program, err := expr.Compile(`upper("str")`, fn)
530+
require.NoError(t, err)
531+
532+
out, err := expr.Run(program, env)
533+
require.NoError(t, err)
534+
assert.Equal(t, "Str", out)
535+
})
536+
537+
t.Run("with function and uncompiled env and disabled builtin", func(t *testing.T) {
538+
program, err := expr.Compile(`upper("str")`, fn, expr.DisableBuiltin("upper"))
539+
require.NoError(t, err)
540+
541+
out, err := expr.Run(program, env)
542+
require.NoError(t, err)
543+
assert.Equal(t, "Str", out)
544+
})
545+
}
546+
463547
func TestBuiltin_DisableBuiltin(t *testing.T) {
464548
t.Run("via env", func(t *testing.T) {
465549
for _, b := range builtin.Builtins {

expr_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1659,6 +1659,43 @@ func TestExpr_call_float_arg_func_with_int(t *testing.T) {
16591659
}
16601660
}
16611661

1662+
func TestExpr_unknown_call_compiled_without_env(t *testing.T) {
1663+
t.Run("some function", func(t *testing.T) {
1664+
program, err := expr.Compile(`fn(1)`)
1665+
require.NoError(t, err)
1666+
1667+
env := map[string]any{
1668+
"fn": func(a int) int { return a },
1669+
}
1670+
1671+
_, err = expr.Run(program, nil)
1672+
require.Error(t, err)
1673+
require.Contains(t, err.Error(), "cannot fetch fn from")
1674+
1675+
out, err := expr.Run(program, env)
1676+
require.NoError(t, err)
1677+
require.Equal(t, 1, out)
1678+
})
1679+
1680+
t.Run("disabled built-in function", func(t *testing.T) {
1681+
program, err := expr.Compile(`upper(1)`, expr.DisableBuiltin("upper"))
1682+
require.NoError(t, err)
1683+
1684+
env := map[string]any{
1685+
"upper": func(a int) int { return a },
1686+
}
1687+
1688+
_, err = expr.Run(program, nil)
1689+
require.Error(t, err)
1690+
require.Contains(t, err.Error(), "cannot fetch upper from")
1691+
1692+
out, err := expr.Run(program, env)
1693+
require.NoError(t, err)
1694+
require.Equal(t, 1, out)
1695+
})
1696+
1697+
}
1698+
16621699
func TestConstExpr_error_panic(t *testing.T) {
16631700
env := map[string]any{
16641701
"divide": func(a, b int) int { return a / b },

parser/parser.go

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -575,10 +575,7 @@ func (p *Parser) parseCall(token Token, arguments []Node, checkOverrides bool) N
575575
}
576576
isOverridden = isOverridden && checkOverrides
577577

578-
if _, ok := predicates[token.Value]; ok && p.config != nil && p.config.Disabled[token.Value] && !isOverridden {
579-
// Disabled predicate without replacement - fail immediately
580-
p.error("unknown name %s", token.Value)
581-
} else if b, ok := predicates[token.Value]; ok && !isOverridden {
578+
if b, ok := predicates[token.Value]; ok && !isOverridden {
582579
p.expect(Bracket, "(")
583580

584581
// In case of the pipe operator, the first argument is the left-hand side
@@ -622,9 +619,6 @@ func (p *Parser) parseCall(token Token, arguments []Node, checkOverrides bool) N
622619
if node == nil {
623620
return nil
624621
}
625-
} else if _, ok := builtin.Index[token.Value]; ok && p.config != nil && p.config.Disabled[token.Value] && !isOverridden {
626-
// Disabled builtin without replacement - fail immediately
627-
p.error("unknown name %s", token.Value)
628622
} else if _, ok := builtin.Index[token.Value]; ok && (p.config == nil || !p.config.Disabled[token.Value]) && !isOverridden {
629623
node = p.createNode(&BuiltinNode{
630624
Name: token.Value,

0 commit comments

Comments
 (0)