From bd73b5abbf49e0c59f3100b76c53fdc4e9afc8a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Furkan=20T=C3=BCrkal?= Date: Sat, 5 Nov 2022 15:47:13 +0300 Subject: [PATCH] Fix DivideOp: change resulting type to float64 (#272) --- expr_test.go | 60 +++++++++++ vm/runtime/generate/main.go | 4 + vm/runtime/helpers.go | 204 ++++++++++++++++++------------------ 3 files changed, 166 insertions(+), 102 deletions(-) diff --git a/expr_test.go b/expr_test.go index 3c90ebd81..ed60ac010 100644 --- a/expr_test.go +++ b/expr_test.go @@ -1449,6 +1449,66 @@ func TestIssue154(t *testing.T) { } } +func TestIssue270(t *testing.T) { + env := map[string]interface{}{ + "int8": int8(1), + "int16": int16(3), + "int32": int32(5), + "int64": int64(7), + "uint8": uint8(11), + "uint16": uint16(13), + "uint32": uint32(17), + "uint64": uint64(19), + "int8a": uint(23), + "int8b": uint(29), + "int16a": uint(31), + "int16b": uint(37), + "int32a": uint(41), + "int32b": uint(43), + "int64a": uint(47), + "int64b": uint(53), + "uint8a": uint(59), + "uint8b": uint(61), + "uint16a": uint(67), + "uint16b": uint(71), + "uint32a": uint(73), + "uint32b": uint(79), + "uint64a": uint(83), + "uint64b": uint(89), + "float32a": float32(97), + "float32b": float32(101), + "float64a": float64(103), + "float64b": float64(107), + } + for _, each := range []struct { + input string + }{ + {"int8 / int16"}, + {"int32 / int64"}, + {"uint8 / uint16"}, + {"uint32 / uint64"}, + {"int8 / uint64"}, + {"int64 / uint8"}, + {"int8a / int8b"}, + {"int16a / int16b"}, + {"int32a / int32b"}, + {"int64a / int64b"}, + {"uint8a / uint8b"}, + {"uint16a / uint16b"}, + {"uint32a / uint32b"}, + {"uint64a / uint64b"}, + {"float32a / float32b"}, + {"float64a / float64b"}, + } { + p, err := expr.Compile(each.input, expr.Env(env)) + require.NoError(t, err) + + out, err := expr.Run(p, env) + require.NoError(t, err) + require.IsType(t, float64(0), out) + } +} + // Mock types type mockEnv struct { Any interface{} diff --git a/vm/runtime/generate/main.go b/vm/runtime/generate/main.go index cff33d274..2222ba906 100644 --- a/vm/runtime/generate/main.go +++ b/vm/runtime/generate/main.go @@ -66,6 +66,10 @@ func cases(op string, noFloat bool) string { t = "float64" } echo(`case %v:`, b) + if op == "/" { + echo(`return float64(x) / float64(y)`) + continue + } if i == j { echo(`return x %v y`, op) } diff --git a/vm/runtime/helpers.go b/vm/runtime/helpers.go index 707b66bc1..b84071030 100644 --- a/vm/runtime/helpers.go +++ b/vm/runtime/helpers.go @@ -2726,25 +2726,25 @@ func Divide(a, b interface{}) interface{} { case uint: switch y := b.(type) { case uint: - return x / y + return float64(x) / float64(y) case uint8: - return int(x) / int(y) + return float64(x) / float64(y) case uint16: - return int(x) / int(y) + return float64(x) / float64(y) case uint32: - return int(x) / int(y) + return float64(x) / float64(y) case uint64: - return int(x) / int(y) + return float64(x) / float64(y) case int: - return int(x) / int(y) + return float64(x) / float64(y) case int8: - return int(x) / int(y) + return float64(x) / float64(y) case int16: - return int(x) / int(y) + return float64(x) / float64(y) case int32: - return int(x) / int(y) + return float64(x) / float64(y) case int64: - return int(x) / int(y) + return float64(x) / float64(y) case float32: return float64(x) / float64(y) case float64: @@ -2753,25 +2753,25 @@ func Divide(a, b interface{}) interface{} { case uint8: switch y := b.(type) { case uint: - return int(x) / int(y) + return float64(x) / float64(y) case uint8: - return x / y + return float64(x) / float64(y) case uint16: - return int(x) / int(y) + return float64(x) / float64(y) case uint32: - return int(x) / int(y) + return float64(x) / float64(y) case uint64: - return int(x) / int(y) + return float64(x) / float64(y) case int: - return int(x) / int(y) + return float64(x) / float64(y) case int8: - return int(x) / int(y) + return float64(x) / float64(y) case int16: - return int(x) / int(y) + return float64(x) / float64(y) case int32: - return int(x) / int(y) + return float64(x) / float64(y) case int64: - return int(x) / int(y) + return float64(x) / float64(y) case float32: return float64(x) / float64(y) case float64: @@ -2780,25 +2780,25 @@ func Divide(a, b interface{}) interface{} { case uint16: switch y := b.(type) { case uint: - return int(x) / int(y) + return float64(x) / float64(y) case uint8: - return int(x) / int(y) + return float64(x) / float64(y) case uint16: - return x / y + return float64(x) / float64(y) case uint32: - return int(x) / int(y) + return float64(x) / float64(y) case uint64: - return int(x) / int(y) + return float64(x) / float64(y) case int: - return int(x) / int(y) + return float64(x) / float64(y) case int8: - return int(x) / int(y) + return float64(x) / float64(y) case int16: - return int(x) / int(y) + return float64(x) / float64(y) case int32: - return int(x) / int(y) + return float64(x) / float64(y) case int64: - return int(x) / int(y) + return float64(x) / float64(y) case float32: return float64(x) / float64(y) case float64: @@ -2807,25 +2807,25 @@ func Divide(a, b interface{}) interface{} { case uint32: switch y := b.(type) { case uint: - return int(x) / int(y) + return float64(x) / float64(y) case uint8: - return int(x) / int(y) + return float64(x) / float64(y) case uint16: - return int(x) / int(y) + return float64(x) / float64(y) case uint32: - return x / y + return float64(x) / float64(y) case uint64: - return int(x) / int(y) + return float64(x) / float64(y) case int: - return int(x) / int(y) + return float64(x) / float64(y) case int8: - return int(x) / int(y) + return float64(x) / float64(y) case int16: - return int(x) / int(y) + return float64(x) / float64(y) case int32: - return int(x) / int(y) + return float64(x) / float64(y) case int64: - return int(x) / int(y) + return float64(x) / float64(y) case float32: return float64(x) / float64(y) case float64: @@ -2834,25 +2834,25 @@ func Divide(a, b interface{}) interface{} { case uint64: switch y := b.(type) { case uint: - return int(x) / int(y) + return float64(x) / float64(y) case uint8: - return int(x) / int(y) + return float64(x) / float64(y) case uint16: - return int(x) / int(y) + return float64(x) / float64(y) case uint32: - return int(x) / int(y) + return float64(x) / float64(y) case uint64: - return x / y + return float64(x) / float64(y) case int: - return int(x) / int(y) + return float64(x) / float64(y) case int8: - return int(x) / int(y) + return float64(x) / float64(y) case int16: - return int(x) / int(y) + return float64(x) / float64(y) case int32: - return int(x) / int(y) + return float64(x) / float64(y) case int64: - return int(x) / int(y) + return float64(x) / float64(y) case float32: return float64(x) / float64(y) case float64: @@ -2861,25 +2861,25 @@ func Divide(a, b interface{}) interface{} { case int: switch y := b.(type) { case uint: - return int(x) / int(y) + return float64(x) / float64(y) case uint8: - return int(x) / int(y) + return float64(x) / float64(y) case uint16: - return int(x) / int(y) + return float64(x) / float64(y) case uint32: - return int(x) / int(y) + return float64(x) / float64(y) case uint64: - return int(x) / int(y) + return float64(x) / float64(y) case int: - return x / y + return float64(x) / float64(y) case int8: - return int(x) / int(y) + return float64(x) / float64(y) case int16: - return int(x) / int(y) + return float64(x) / float64(y) case int32: - return int(x) / int(y) + return float64(x) / float64(y) case int64: - return int(x) / int(y) + return float64(x) / float64(y) case float32: return float64(x) / float64(y) case float64: @@ -2888,25 +2888,25 @@ func Divide(a, b interface{}) interface{} { case int8: switch y := b.(type) { case uint: - return int(x) / int(y) + return float64(x) / float64(y) case uint8: - return int(x) / int(y) + return float64(x) / float64(y) case uint16: - return int(x) / int(y) + return float64(x) / float64(y) case uint32: - return int(x) / int(y) + return float64(x) / float64(y) case uint64: - return int(x) / int(y) + return float64(x) / float64(y) case int: - return int(x) / int(y) + return float64(x) / float64(y) case int8: - return x / y + return float64(x) / float64(y) case int16: - return int(x) / int(y) + return float64(x) / float64(y) case int32: - return int(x) / int(y) + return float64(x) / float64(y) case int64: - return int(x) / int(y) + return float64(x) / float64(y) case float32: return float64(x) / float64(y) case float64: @@ -2915,25 +2915,25 @@ func Divide(a, b interface{}) interface{} { case int16: switch y := b.(type) { case uint: - return int(x) / int(y) + return float64(x) / float64(y) case uint8: - return int(x) / int(y) + return float64(x) / float64(y) case uint16: - return int(x) / int(y) + return float64(x) / float64(y) case uint32: - return int(x) / int(y) + return float64(x) / float64(y) case uint64: - return int(x) / int(y) + return float64(x) / float64(y) case int: - return int(x) / int(y) + return float64(x) / float64(y) case int8: - return int(x) / int(y) + return float64(x) / float64(y) case int16: - return x / y + return float64(x) / float64(y) case int32: - return int(x) / int(y) + return float64(x) / float64(y) case int64: - return int(x) / int(y) + return float64(x) / float64(y) case float32: return float64(x) / float64(y) case float64: @@ -2942,25 +2942,25 @@ func Divide(a, b interface{}) interface{} { case int32: switch y := b.(type) { case uint: - return int(x) / int(y) + return float64(x) / float64(y) case uint8: - return int(x) / int(y) + return float64(x) / float64(y) case uint16: - return int(x) / int(y) + return float64(x) / float64(y) case uint32: - return int(x) / int(y) + return float64(x) / float64(y) case uint64: - return int(x) / int(y) + return float64(x) / float64(y) case int: - return int(x) / int(y) + return float64(x) / float64(y) case int8: - return int(x) / int(y) + return float64(x) / float64(y) case int16: - return int(x) / int(y) + return float64(x) / float64(y) case int32: - return x / y + return float64(x) / float64(y) case int64: - return int(x) / int(y) + return float64(x) / float64(y) case float32: return float64(x) / float64(y) case float64: @@ -2969,25 +2969,25 @@ func Divide(a, b interface{}) interface{} { case int64: switch y := b.(type) { case uint: - return int(x) / int(y) + return float64(x) / float64(y) case uint8: - return int(x) / int(y) + return float64(x) / float64(y) case uint16: - return int(x) / int(y) + return float64(x) / float64(y) case uint32: - return int(x) / int(y) + return float64(x) / float64(y) case uint64: - return int(x) / int(y) + return float64(x) / float64(y) case int: - return int(x) / int(y) + return float64(x) / float64(y) case int8: - return int(x) / int(y) + return float64(x) / float64(y) case int16: - return int(x) / int(y) + return float64(x) / float64(y) case int32: - return int(x) / int(y) + return float64(x) / float64(y) case int64: - return x / y + return float64(x) / float64(y) case float32: return float64(x) / float64(y) case float64: @@ -3016,7 +3016,7 @@ func Divide(a, b interface{}) interface{} { case int64: return float64(x) / float64(y) case float32: - return x / y + return float64(x) / float64(y) case float64: return float64(x) / float64(y) } @@ -3045,7 +3045,7 @@ func Divide(a, b interface{}) interface{} { case float32: return float64(x) / float64(y) case float64: - return x / y + return float64(x) / float64(y) } } panic(fmt.Sprintf("invalid operation: %T / %T", a, b))