diff --git a/conf/operators.go b/conf/operators.go index d3d7ff50..646153cb 100644 --- a/conf/operators.go +++ b/conf/operators.go @@ -20,7 +20,10 @@ func FindSuitableOperatorOverload(fns []string, types TypesTable, funcs Function func FindSuitableOperatorOverloadInTypes(fns []string, types TypesTable, l, r reflect.Type) (reflect.Type, string, bool) { for _, fn := range fns { - fnType := types[fn] + fnType, ok := types[fn] + if !ok { + continue + } firstInIndex := 0 if fnType.Method { firstInIndex = 1 // As first argument to method is receiver. diff --git a/test/operator/operator_test.go b/test/operator/operator_test.go index 0a71a005..59bc73f2 100644 --- a/test/operator/operator_test.go +++ b/test/operator/operator_test.go @@ -192,3 +192,33 @@ func TestOperator_CanBeDefinedEitherInTypesOrInFunctions(t *testing.T) { 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) +}