Repository: VKCOM/noverify
Pull request #865 (2020-12-18 13:20:20)

constfold: minor improvement in constant folding
- Added folding of constants for addition, subtraction and
  multiplication of int and float and vice versa;
- Added conversion from float to string.


Patch:
diff --git a/src/constfold/binary_op.go b/src/constfold/binary_op.go
index b1c9cf2..050697f 100644
--- a/src/constfold/binary_op.go
+++ b/src/constfold/binary_op.go
@@ -8,11 +8,17 @@ import (
 func Plus(x, y meta.ConstValue) meta.ConstValue {
 	switch x.Type {
 	case meta.Integer:
-		if y.Type == meta.Integer {
+		switch y.Type {
+		case meta.Integer:
 			return meta.NewIntConst(x.GetInt() + y.GetInt())
+		case meta.Float:
+			return meta.NewFloatConst(float64(x.GetInt()) + y.GetFloat())
 		}
 	case meta.Float:
-		if y.Type == meta.Float {
+		switch y.Type {
+		case meta.Integer:
+			return meta.NewFloatConst(x.GetFloat() + float64(y.GetInt()))
+		case meta.Float:
 			return meta.NewFloatConst(x.GetFloat() + y.GetFloat())
 		}
 	}
@@ -23,11 +29,17 @@ func Plus(x, y meta.ConstValue) meta.ConstValue {
 func Minus(x, y meta.ConstValue) meta.ConstValue {
 	switch x.Type {
 	case meta.Integer:
-		if y.Type == meta.Integer {
+		switch y.Type {
+		case meta.Integer:
 			return meta.NewIntConst(x.GetInt() - y.GetInt())
+		case meta.Float:
+			return meta.NewFloatConst(float64(x.GetInt()) - y.GetFloat())
 		}
 	case meta.Float:
-		if y.Type == meta.Float {
+		switch y.Type {
+		case meta.Integer:
+			return meta.NewFloatConst(x.GetFloat() - float64(y.GetInt()))
+		case meta.Float:
 			return meta.NewFloatConst(x.GetFloat() - y.GetFloat())
 		}
 	}
@@ -38,11 +50,17 @@ func Minus(x, y meta.ConstValue) meta.ConstValue {
 func Mul(x, y meta.ConstValue) meta.ConstValue {
 	switch x.Type {
 	case meta.Integer:
-		if y.Type == meta.Integer {
+		switch y.Type {
+		case meta.Integer:
 			return meta.NewIntConst(x.GetInt() * y.GetInt())
+		case meta.Float:
+			return meta.NewFloatConst(float64(x.GetInt()) * y.GetFloat())
 		}
 	case meta.Float:
-		if y.Type == meta.Float {
+		switch y.Type {
+		case meta.Integer:
+			return meta.NewFloatConst(x.GetFloat() * float64(y.GetInt()))
+		case meta.Float:
 			return meta.NewFloatConst(x.GetFloat() * y.GetFloat())
 		}
 	}
diff --git a/src/meta/const_value.go b/src/meta/const_value.go
index 4cdd60f..ce72aae 100644
--- a/src/meta/const_value.go
+++ b/src/meta/const_value.go
@@ -143,6 +143,8 @@ func (c ConstValue) ToString() (string, bool) {
 		return strconv.FormatInt(c.GetInt(), 10), true
 	case String:
 		return c.GetString(), true
+	case Float:
+		return fmt.Sprintf("%g", c.GetFloat()), true
 	}
 	return "", false
 }


Test patch:
diff --git a/src/ir/normalize/normalize_test.go b/src/ir/normalize/normalize_test.go
index dbe4393..c4e65a2 100644
--- a/src/ir/normalize/normalize_test.go
+++ b/src/ir/normalize/normalize_test.go
@@ -177,6 +177,15 @@ func TestNormalizeExpr(t *testing.T) {
 		{`(1 + 2) * 4`, `12`},
 		{`5 - 6`, `-1`},
 		{`(5 - 6) * 8 + 6`, `-2`},
+		{`5.5 + 3`, `8.5`},
+		{`3 + 5.5`, `8.5`},
+		{`5.5 + 3.5`, `9`},
+		{`5.5 - 3`, `2.5`},
+		{`8 - 5.5`, `2.5`},
+		{`5.5 - 3.5`, `2`},
+		{`5.5 * 3`, `16.5`},
+		{`3 * 5.5`, `16.5`},
+		{`1.5 * 1.5`, `2.25`},
 		{`!true`, `false`},
 		{`!false`, `true`},
 		{`!!false`, `false`},