diff --git a/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/AddSubTransformer.java b/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/AddSubTransformer.java index 48526d47b7..e65b566593 100644 --- a/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/AddSubTransformer.java +++ b/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/AddSubTransformer.java @@ -38,9 +38,11 @@ public final class AddSubTransformer extends Transformer { /* x + -y => x - y */ expr.setOperator(BinaryExpr.Operator.MINUS); expr.setRight(ExprUtils.negate(right)); - } else if (op == BinaryExpr.Operator.PLUS && isNegative(left)) { + } else if (op == BinaryExpr.Operator.PLUS && isNegative(left) && !(ExprUtils.hasSideEffects(left) && ExprUtils.hasSideEffects(right))) { /* -x + y => y - x */ - // TODO(gpe): check for side effects before applying this transform + expr.setOperator(BinaryExpr.Operator.MINUS); + expr.setLeft(right.clone()); + expr.setRight(ExprUtils.negate(left)); } else if (op == BinaryExpr.Operator.MINUS && isNegative(right)) { /* x - -y => x + y */ expr.setOperator(BinaryExpr.Operator.PLUS); diff --git a/deob-ast/src/main/java/dev/openrs2/deob/ast/util/ExprUtils.java b/deob-ast/src/main/java/dev/openrs2/deob/ast/util/ExprUtils.java index ca766f336a..c346bde5c0 100644 --- a/deob-ast/src/main/java/dev/openrs2/deob/ast/util/ExprUtils.java +++ b/deob-ast/src/main/java/dev/openrs2/deob/ast/util/ExprUtils.java @@ -71,6 +71,24 @@ public final class ExprUtils { return new UnaryExpr(expr.clone(), UnaryExpr.Operator.LOGICAL_COMPLEMENT); } + public static boolean hasSideEffects(Expression expr) { + if (expr.isLiteralExpr() || expr.isNameExpr() | expr.isFieldAccessExpr()) { + return false; + } else if (expr.isEnclosedExpr()) { + return hasSideEffects(expr.asEnclosedExpr().getInner()); + } else if (expr.isUnaryExpr()) { + return hasSideEffects(expr.asUnaryExpr().getExpression()); + } else if (expr.isBinaryExpr()) { + var binary = expr.asBinaryExpr(); + return hasSideEffects(binary.getLeft()) || hasSideEffects(binary.getRight()); + } else if (expr.isArrayAccessExpr()) { + var access = expr.asArrayAccessExpr(); + return hasSideEffects(access.getName()) || hasSideEffects(access.getIndex()); + } + // TODO(gpe): more cases + return true; + } + private ExprUtils() { /* empty */ }