From e38deb46fca48e769306a69cc91d99628b4893ab Mon Sep 17 00:00:00 2001 From: dbaumgarten Date: Fri, 29 Oct 2021 12:11:40 +0200 Subject: [PATCH] Exploid binop identities when optimizing #115 --- pkg/optimizers/static_expressions.go | 74 +++++++++++++++++++++++ pkg/optimizers/static_expressions_test.go | 12 ++++ 2 files changed, 86 insertions(+) diff --git a/pkg/optimizers/static_expressions.go b/pkg/optimizers/static_expressions.go index 5301459..844940d 100644 --- a/pkg/optimizers/static_expressions.go +++ b/pkg/optimizers/static_expressions.go @@ -81,6 +81,11 @@ func (o *StaticExpressionOptimizer) OptimizeExpressionNonRecursive(exp ast.Expre return varToConst(res, n.Exp1.Start()) } + + if binop, is := exp.(*ast.BinaryOperation); is { + return simplifyIdentities(binop) + } + return nil } @@ -130,3 +135,72 @@ func varToConst(v *vm.Variable, pos ast.Position) ast.Expression { Position: pos, } } + +func simplifyIdentities(binop *ast.BinaryOperation) ast.Expression { + + if _, is := binop.Exp1.(*ast.StringConstant); is { + return binop + } + if _, is := binop.Exp2.(*ast.StringConstant); is { + return binop + } + + switch binop.Operator { + case "+": + if isNumConstWithValue(binop.Exp1, "0") { + return binop.Exp2 + } + if isNumConstWithValue(binop.Exp2, "0") { + return binop.Exp1 + } + case "-": + if isNumConstWithValue(binop.Exp1, "0") { + return &ast.UnaryOperation{ + Position: binop.Start(), + Operator: "-", + Exp: binop.Exp2, + } + } + if isNumConstWithValue(binop.Exp2, "0") { + return binop.Exp1 + } + case "*": + if isNumConstWithValue(binop.Exp1, "1") { + return binop.Exp2 + } + if isNumConstWithValue(binop.Exp2, "1") { + return binop.Exp1 + } + if isNumConstWithValue(binop.Exp1, "0") { + return &ast.NumberConstant{Position: binop.Start(), Value: "0"} + } + if isNumConstWithValue(binop.Exp2, "0") { + return &ast.NumberConstant{Position: binop.Start(), Value: "0"} + } + case "/": + if isNumConstWithValue(binop.Exp2, "1") { + return binop.Exp1 + } + case "^": + if isNumConstWithValue(binop.Exp2, "0") { + return &ast.NumberConstant{Position: binop.Start(), Value: "1"} + } + if isNumConstWithValue(binop.Exp2, "1") { + return binop.Exp1 + } + } + + return binop +} + +// checkis if check is a NumberConstant and if it's value matches expected +func isNumConstWithValue(check ast.Expression, expected string) bool { + + if num, is := check.(*ast.NumberConstant); is { + if num.Value == expected { + return true + } + } + + return false +} diff --git a/pkg/optimizers/static_expressions_test.go b/pkg/optimizers/static_expressions_test.go index f68e1e1..733ab82 100644 --- a/pkg/optimizers/static_expressions_test.go +++ b/pkg/optimizers/static_expressions_test.go @@ -13,6 +13,18 @@ var staticCases = map[string]string{ "a=123+100+a": "a=223+a", "a=a+(123+100)+b": "a=a+223+b", "a=a+(123+100)+b*(10*10)": "a=a+223+b*100", + "a=0+b": "a=b", + "a=b+0": "a=b", + "a=b-0": "a=b", + "a=0-b": "a=-b", + "a=0*b": "a=0", + "a=b*0": "a=0", + "a=1*b": "a=b", + "a=b*1": "a=b", + "a=b/1": "a=b", + "a=b^0": "a=1", + "a=b^1": "a=b", + "a=\"a\"*1": "a=\"a\"*1", } func TestStaticExpressions(t *testing.T) {