Skip to content

Commit

Permalink
Fix check for nil interface
Browse files Browse the repository at this point in the history
  • Loading branch information
antonmedv committed Feb 21, 2020
1 parent ab801d4 commit 3c6ea97
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 9 deletions.
11 changes: 10 additions & 1 deletion expr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -876,12 +876,15 @@ func TestExpr_map_default_values_compile_check(t *testing.T) {
func TestExpr_calls_with_nil(t *testing.T) {
env := map[string]interface{}{
"equals": func(a, b interface{}) interface{} {
assert.Nil(t, a, "a is not nil")
assert.Nil(t, b, "b is not nil")
return a == b
},
"is": is{},
}

p, err := expr.Compile(
"a == nil && equals(b, nil)",
"a == nil && equals(b, nil) && is.Nil(c)",
expr.Env(env),
expr.Operator("==", "equals"),
expr.AllowUndefinedVariables(),
Expand Down Expand Up @@ -1020,3 +1023,9 @@ func (m mockMapStringStringEnv) Split(s, sep string) []string {
}

type mockMapStringIntEnv map[string]int

type is struct{}

func (is) Nil(a interface{}) bool {
return a == nil
}
18 changes: 10 additions & 8 deletions vm/vm.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,12 +251,13 @@ func (vm *VM) Run(program *Program, env interface{}) interface{} {
in := make([]reflect.Value, call.Size)
for i := call.Size - 1; i >= 0; i-- {
param := vm.pop()
if param == nil {
// In case of nil interface{} (nil type) use this hack,
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.
param = reflect.ValueOf(&in).Elem()
in[i] = reflect.ValueOf(&param).Elem()
} else {
in[i] = reflect.ValueOf(param)
}
in[i] = reflect.ValueOf(param)
}
out := fetchFn(env, call.Name).Call(in)
vm.push(out[0].Interface())
Expand All @@ -275,12 +276,13 @@ func (vm *VM) Run(program *Program, env interface{}) interface{} {
in := make([]reflect.Value, call.Size)
for i := call.Size - 1; i >= 0; i-- {
param := vm.pop()
if param == nil {
// In case of nil interface{} (nil type) use this hack,
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.
param = reflect.ValueOf(&in).Elem()
in[i] = reflect.ValueOf(&param).Elem()
} else {
in[i] = reflect.ValueOf(param)
}
in[i] = reflect.ValueOf(param)
}
out := fetchFn(vm.pop(), call.Name).Call(in)
vm.push(out[0].Interface())
Expand Down

0 comments on commit 3c6ea97

Please sign in to comment.