From ecc7a39bc7ab4015e2cd102fcbbcb20eafba1bac Mon Sep 17 00:00:00 2001 From: hesining Date: Fri, 8 Sep 2023 07:54:38 +0000 Subject: [PATCH 1/9] Propagate multi arguments types in ast --- checker/checker.go | 35 +++++++++++++++++++++++++++++------ compiler/compiler.go | 12 +++++++++++- expr_test.go | 29 +++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 7 deletions(-) diff --git a/checker/checker.go b/checker/checker.go index 3e787fa4f..55a13f53f 100644 --- a/checker/checker.go +++ b/checker/checker.go @@ -924,8 +924,13 @@ func (v *checker) checkArguments(name string, fn reflect.Type, method bool, argu } if isFloat(in) { - t = floatType - traverseAndReplaceIntegerNodesWithFloatNodes(&arg) + traverseAndReplaceIntegerNodesWithFloatNodes(&arguments[i], in) + continue + } + + if isInteger(in) && kind(t) != kind(in) { + traverseAndReplaceIntegerNodesWithIntegerNodes(&arguments[i], in) + continue } if t == nil { @@ -943,19 +948,37 @@ func (v *checker) checkArguments(name string, fn reflect.Type, method bool, argu return fn.Out(0), nil } -func traverseAndReplaceIntegerNodesWithFloatNodes(node *ast.Node) { +func traverseAndReplaceIntegerNodesWithFloatNodes(node *ast.Node, newType reflect.Type) { switch (*node).(type) { case *ast.IntegerNode: *node = &ast.FloatNode{Value: float64((*node).(*ast.IntegerNode).Value)} + (*node).SetType(newType) + case *ast.UnaryNode: + unaryNode := (*node).(*ast.UnaryNode) + traverseAndReplaceIntegerNodesWithFloatNodes(&unaryNode.Node, newType) + case *ast.BinaryNode: + binaryNode := (*node).(*ast.BinaryNode) + switch binaryNode.Operator { + case "+", "-", "*": + traverseAndReplaceIntegerNodesWithFloatNodes(&binaryNode.Left, newType) + traverseAndReplaceIntegerNodesWithFloatNodes(&binaryNode.Right, newType) + } + } +} + +func traverseAndReplaceIntegerNodesWithIntegerNodes(node *ast.Node, newType reflect.Type) { + switch (*node).(type) { + case *ast.IntegerNode: + (*node).SetType(newType) case *ast.UnaryNode: unaryNode := (*node).(*ast.UnaryNode) - traverseAndReplaceIntegerNodesWithFloatNodes(&unaryNode.Node) + traverseAndReplaceIntegerNodesWithIntegerNodes(&unaryNode.Node, newType) case *ast.BinaryNode: binaryNode := (*node).(*ast.BinaryNode) switch binaryNode.Operator { case "+", "-", "*": - traverseAndReplaceIntegerNodesWithFloatNodes(&binaryNode.Left) - traverseAndReplaceIntegerNodesWithFloatNodes(&binaryNode.Right) + traverseAndReplaceIntegerNodesWithIntegerNodes(&binaryNode.Left, newType) + traverseAndReplaceIntegerNodesWithIntegerNodes(&binaryNode.Right, newType) } } } diff --git a/compiler/compiler.go b/compiler/compiler.go index 66ad4f1f2..8e26d8788 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -307,7 +307,17 @@ func (c *compiler) IntegerNode(node *ast.IntegerNode) { } func (c *compiler) FloatNode(node *ast.FloatNode) { - c.emitPush(node.Value) + t := node.Type() + if t == nil { + c.emitPush(node.Value) + return + } + switch t.Kind() { + case reflect.Float32: + c.emitPush(float32(node.Value)) + case reflect.Float64: + c.emitPush(node.Value) + } } func (c *compiler) BoolNode(node *ast.BoolNode) { diff --git a/expr_test.go b/expr_test.go index 1857403ec..86945867f 100644 --- a/expr_test.go +++ b/expr_test.go @@ -1969,3 +1969,32 @@ func TestMemoryBudget(t *testing.T) { }) } } + +func TestIssue432(t *testing.T) { + env := map[string]any{ + "func": func( + paramUint32 uint32, + paramUint16 uint16, + paramUint8 uint8, + paramUint uint, + paramInt32 int32, + paramInt16 int16, + paramInt8 int8, + paramInt int, + paramFloat64 float64, + paramFloat32 float32, + ) float64 { + return float64(paramUint32) + float64(paramUint16) + float64(paramUint8) + float64(paramUint) + + float64(paramInt32) + float64(paramInt16) + float64(paramInt8) + float64(paramInt) + + float64(paramFloat64) + float64(paramFloat32) + }, + } + code := `func(1,1,1,1,1,1,1,1,1,1)` + + program, err := expr.Compile(code, expr.Env(env)) + assert.NoError(t, err) + + out, err := expr.Run(program, env) + assert.NoError(t, err) + assert.Equal(t, float64(10), out) +} \ No newline at end of file From 6b665fb7506c85840ab900d27147e3fbd2df33f5 Mon Sep 17 00:00:00 2001 From: hesining Date: Fri, 8 Sep 2023 08:19:28 +0000 Subject: [PATCH 2/9] fix --- checker/checker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checker/checker.go b/checker/checker.go index 55a13f53f..efa1b7eb9 100644 --- a/checker/checker.go +++ b/checker/checker.go @@ -928,7 +928,7 @@ func (v *checker) checkArguments(name string, fn reflect.Type, method bool, argu continue } - if isInteger(in) && kind(t) != kind(in) { + if isInteger(in) && isInteger(t) && kind(t) != kind(in) { traverseAndReplaceIntegerNodesWithIntegerNodes(&arguments[i], in) continue } From 72a2ac401ed44451d87f3cbefc3cffd2300550e8 Mon Sep 17 00:00:00 2001 From: hesining Date: Fri, 8 Sep 2023 08:31:29 +0000 Subject: [PATCH 3/9] fix --- checker/checker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checker/checker.go b/checker/checker.go index efa1b7eb9..b5ecf7d95 100644 --- a/checker/checker.go +++ b/checker/checker.go @@ -923,7 +923,7 @@ func (v *checker) checkArguments(name string, fn reflect.Type, method bool, argu in = fn.In(i + fnInOffset) } - if isFloat(in) { + if isFloat(in) && isNumber(t) && kind(t) != kind(in) { traverseAndReplaceIntegerNodesWithFloatNodes(&arguments[i], in) continue } From af8bcff2dd3a2a9cacc9bb77fdddb386fb05950e Mon Sep 17 00:00:00 2001 From: hesining Date: Fri, 8 Sep 2023 08:34:34 +0000 Subject: [PATCH 4/9] fix --- checker/checker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checker/checker.go b/checker/checker.go index b5ecf7d95..fc135ed9b 100644 --- a/checker/checker.go +++ b/checker/checker.go @@ -923,7 +923,7 @@ func (v *checker) checkArguments(name string, fn reflect.Type, method bool, argu in = fn.In(i + fnInOffset) } - if isFloat(in) && isNumber(t) && kind(t) != kind(in) { + if isFloat(in) && isNumber(t) && kind(t) != kind(in) { traverseAndReplaceIntegerNodesWithFloatNodes(&arguments[i], in) continue } From 3f0704920654cc1bde6f00b0bd8845b7a69f7f4e Mon Sep 17 00:00:00 2001 From: hesining Date: Mon, 11 Sep 2023 07:23:01 +0000 Subject: [PATCH 5/9] Update fuzz testing --- test/fuzz/fuzz_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/fuzz/fuzz_test.go b/test/fuzz/fuzz_test.go index e69aaec7b..9549bb42d 100644 --- a/test/fuzz/fuzz_test.go +++ b/test/fuzz/fuzz_test.go @@ -48,6 +48,12 @@ func FuzzExpr(f *testing.F) { regexp.MustCompile(`invalid date .*`), regexp.MustCompile(`cannot parse .* as .*`), regexp.MustCompile(`operator "in" not defined on .*`), + regexp.MustCompile(`invalid date .*`), + regexp.MustCompile(`cannot parse .* as .*`), + regexp.MustCompile(`operator "in" not defined on .*`), + regexp.MustCompile(`illegal base64 data at input byte .*`), + regexp.MustCompile(`sort: unsupported type float.*`), + regexp.MustCompile(`unknown time zone .*`), } env := NewEnv() From a6774c92eab4ee2ff25ee5ff3177fc751ff09712 Mon Sep 17 00:00:00 2001 From: hesining Date: Mon, 11 Sep 2023 07:27:04 +0000 Subject: [PATCH 6/9] Add fuzz filter --- test/fuzz/fuzz_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/test/fuzz/fuzz_test.go b/test/fuzz/fuzz_test.go index 9549bb42d..855262982 100644 --- a/test/fuzz/fuzz_test.go +++ b/test/fuzz/fuzz_test.go @@ -53,6 +53,7 @@ func FuzzExpr(f *testing.F) { regexp.MustCompile(`operator "in" not defined on .*`), regexp.MustCompile(`illegal base64 data at input byte .*`), regexp.MustCompile(`sort: unsupported type float.*`), + regexp.MustCompile(`sort: unsupported type bool`), regexp.MustCompile(`unknown time zone .*`), } From d17a9e49024967b5f2941514bae8a8a8624cd3fa Mon Sep 17 00:00:00 2001 From: hesining Date: Mon, 11 Sep 2023 07:42:30 +0000 Subject: [PATCH 7/9] Add fuzz filter --- test/fuzz/fuzz_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/test/fuzz/fuzz_test.go b/test/fuzz/fuzz_test.go index 855262982..52d491afb 100644 --- a/test/fuzz/fuzz_test.go +++ b/test/fuzz/fuzz_test.go @@ -55,6 +55,7 @@ func FuzzExpr(f *testing.F) { regexp.MustCompile(`sort: unsupported type float.*`), regexp.MustCompile(`sort: unsupported type bool`), regexp.MustCompile(`unknown time zone .*`), + regexp.MustCompile(`cannot use .* as argument (type .*) to call`), } env := NewEnv() From 1971b0fc7ad36127ae92fe8e79a47df891dbd220 Mon Sep 17 00:00:00 2001 From: hesining Date: Mon, 11 Sep 2023 10:19:17 +0000 Subject: [PATCH 8/9] Revert "Update fuzz testing" --- test/fuzz/fuzz_test.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/fuzz/fuzz_test.go b/test/fuzz/fuzz_test.go index 52d491afb..e69aaec7b 100644 --- a/test/fuzz/fuzz_test.go +++ b/test/fuzz/fuzz_test.go @@ -48,14 +48,6 @@ func FuzzExpr(f *testing.F) { regexp.MustCompile(`invalid date .*`), regexp.MustCompile(`cannot parse .* as .*`), regexp.MustCompile(`operator "in" not defined on .*`), - regexp.MustCompile(`invalid date .*`), - regexp.MustCompile(`cannot parse .* as .*`), - regexp.MustCompile(`operator "in" not defined on .*`), - regexp.MustCompile(`illegal base64 data at input byte .*`), - regexp.MustCompile(`sort: unsupported type float.*`), - regexp.MustCompile(`sort: unsupported type bool`), - regexp.MustCompile(`unknown time zone .*`), - regexp.MustCompile(`cannot use .* as argument (type .*) to call`), } env := NewEnv() From bb901a50013d46e2d733fd49de70c7b8f5f4e323 Mon Sep 17 00:00:00 2001 From: hesining Date: Mon, 11 Sep 2023 10:25:23 +0000 Subject: [PATCH 9/9] update --- checker/checker.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checker/checker.go b/checker/checker.go index fc135ed9b..efa1b7eb9 100644 --- a/checker/checker.go +++ b/checker/checker.go @@ -923,7 +923,7 @@ func (v *checker) checkArguments(name string, fn reflect.Type, method bool, argu in = fn.In(i + fnInOffset) } - if isFloat(in) && isNumber(t) && kind(t) != kind(in) { + if isFloat(in) { traverseAndReplaceIntegerNodesWithFloatNodes(&arguments[i], in) continue }