diff --git a/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/AddSubTransformer.kt b/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/AddSubTransformer.kt index 62a0cb96b5..7fa6201bd4 100644 --- a/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/AddSubTransformer.kt +++ b/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/AddSubTransformer.kt @@ -5,8 +5,9 @@ import com.github.javaparser.ast.Node import com.github.javaparser.ast.expr.BinaryExpr import com.github.javaparser.ast.expr.Expression import com.github.javaparser.ast.expr.UnaryExpr -import dev.openrs2.deob.ast.util.ExprUtils +import dev.openrs2.deob.ast.util.hasSideEffects import dev.openrs2.deob.ast.util.isString +import dev.openrs2.deob.ast.util.negate import dev.openrs2.deob.ast.util.walk class AddSubTransformer : Transformer() { @@ -24,20 +25,20 @@ class AddSubTransformer : Transformer() { if (op == BinaryExpr.Operator.PLUS && isNegative(right)) { // x + -y => x - y expr.operator = BinaryExpr.Operator.MINUS - expr.right = ExprUtils.negate(right) + expr.right = right.negate() } else if (op == BinaryExpr.Operator.PLUS && isNegative(left)) { - if (ExprUtils.hasSideEffects(left) || ExprUtils.hasSideEffects(right)) { + if (left.hasSideEffects() || right.hasSideEffects()) { return@walk } // -x + y => y - x expr.operator = BinaryExpr.Operator.MINUS expr.left = right.clone() - expr.right = ExprUtils.negate(left) + expr.right = left.negate() } else if (op == BinaryExpr.Operator.MINUS && isNegative(right)) { // x - -y => x + y expr.operator = BinaryExpr.Operator.PLUS - expr.right = ExprUtils.negate(right) + expr.right = right.negate() } } } diff --git a/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/BitMaskTransformer.kt b/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/BitMaskTransformer.kt index 309580d280..d3104603a2 100644 --- a/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/BitMaskTransformer.kt +++ b/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/BitMaskTransformer.kt @@ -4,7 +4,8 @@ import com.github.javaparser.ast.CompilationUnit import com.github.javaparser.ast.Node import com.github.javaparser.ast.expr.BinaryExpr import com.github.javaparser.ast.expr.IntegerLiteralExpr -import dev.openrs2.deob.ast.util.ExprUtils +import dev.openrs2.deob.ast.util.createLong +import dev.openrs2.deob.ast.util.isIntegerOrLongLiteral import dev.openrs2.deob.ast.util.walk class BitMaskTransformer : Transformer() { @@ -23,7 +24,7 @@ class BitMaskTransformer : Transformer() { val argExpr = bitwiseExpr.left var maskExpr = bitwiseExpr.right - if (!BITWISE_OPS.contains(bitwiseOp) || !ExprUtils.isIntegerOrLongLiteral(maskExpr)) { + if (!BITWISE_OPS.contains(bitwiseOp) || !maskExpr.isIntegerOrLongLiteral()) { return@walk } @@ -47,7 +48,7 @@ class BitMaskTransformer : Transformer() { else -> throw IllegalStateException() } - maskExpr = ExprUtils.createLong(mask) + maskExpr = createLong(mask) } expr.replace(BinaryExpr(BinaryExpr(argExpr.clone(), shamtExpr.clone(), shiftOp), maskExpr, bitwiseOp)) diff --git a/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/ComplementTransformer.kt b/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/ComplementTransformer.kt index 786a05d37e..355cf10190 100644 --- a/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/ComplementTransformer.kt +++ b/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/ComplementTransformer.kt @@ -6,7 +6,8 @@ import com.github.javaparser.ast.expr.BinaryExpr import com.github.javaparser.ast.expr.Expression import com.github.javaparser.ast.expr.IntegerLiteralExpr import com.github.javaparser.ast.expr.UnaryExpr -import dev.openrs2.deob.ast.util.ExprUtils +import dev.openrs2.deob.ast.util.createLong +import dev.openrs2.deob.ast.util.isIntegerOrLongLiteral import dev.openrs2.deob.ast.util.walk class ComplementTransformer : Transformer() { @@ -16,7 +17,7 @@ class ComplementTransformer : Transformer() { val left = expr.left val right = expr.right - val bothLiteral = ExprUtils.isIntegerOrLongLiteral(left) && ExprUtils.isIntegerOrLongLiteral(right) + val bothLiteral = left.isIntegerOrLongLiteral() && right.isIntegerOrLongLiteral() if (isComplementOrLiteral(left) && isComplementOrLiteral(right) && !bothLiteral) { expr.operator = op @@ -32,7 +33,7 @@ class ComplementTransformer : Transformer() { } private fun isComplementOrLiteral(expr: Expression): Boolean { - return isComplement(expr) || ExprUtils.isIntegerOrLongLiteral(expr) + return isComplement(expr) || expr.isIntegerOrLongLiteral() } private fun complement(op: BinaryExpr.Operator): BinaryExpr.Operator? { @@ -50,7 +51,7 @@ class ComplementTransformer : Transformer() { return when { expr.isUnaryExpr -> expr.asUnaryExpr().expression expr.isIntegerLiteralExpr -> IntegerLiteralExpr(expr.asIntegerLiteralExpr().asInt().inv()) - expr.isLongLiteralExpr -> ExprUtils.createLong(expr.asLongLiteralExpr().asLong().inv()) + expr.isLongLiteralExpr -> createLong(expr.asLongLiteralExpr().asLong().inv()) else -> throw IllegalArgumentException() } } diff --git a/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/IfElseTransformer.kt b/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/IfElseTransformer.kt index f65bfca5bf..8e2f47481e 100644 --- a/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/IfElseTransformer.kt +++ b/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/IfElseTransformer.kt @@ -5,7 +5,8 @@ import com.github.javaparser.ast.Node import com.github.javaparser.ast.stmt.BlockStmt import com.github.javaparser.ast.stmt.IfStmt import com.github.javaparser.ast.stmt.Statement -import dev.openrs2.deob.ast.util.ExprUtils +import dev.openrs2.deob.ast.util.countNots +import dev.openrs2.deob.ast.util.not import dev.openrs2.deob.ast.util.walk class IfElseTransformer : Transformer() { @@ -15,7 +16,7 @@ class IfElseTransformer : Transformer() { val condition = stmt.condition val thenStmt = stmt.thenStmt if (isIf(thenStmt) && !isIf(elseStmt)) { - stmt.condition = ExprUtils.not(condition) + stmt.condition = condition.not() stmt.thenStmt = elseStmt.clone() stmt.setElseStmt(thenStmt.clone()) } else if (!isIf(thenStmt) && isIf(elseStmt)) { @@ -28,8 +29,8 @@ class IfElseTransformer : Transformer() { } // Prefer fewer NOTs in the if condition - val notCondition = ExprUtils.not(condition) - if (ExprUtils.countNots(notCondition) < ExprUtils.countNots(condition)) { + val notCondition = condition.not() + if (notCondition.countNots() < condition.countNots()) { stmt.condition = notCondition if (elseStmt.isIfStmt) { val block = BlockStmt() @@ -102,7 +103,7 @@ class IfElseTransformer : Transformer() { } // rewrite - val condition = ExprUtils.not(ifStmt.condition) + val condition = ifStmt.condition.not() val tail = blockStmt.clone() tail.statements.removeAt(0) diff --git a/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/NegativeLiteralTransformer.kt b/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/NegativeLiteralTransformer.kt index d575359304..d224bac82d 100644 --- a/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/NegativeLiteralTransformer.kt +++ b/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/NegativeLiteralTransformer.kt @@ -3,14 +3,15 @@ package dev.openrs2.deob.ast.transform import com.github.javaparser.ast.CompilationUnit import com.github.javaparser.ast.Node import com.github.javaparser.ast.expr.UnaryExpr -import dev.openrs2.deob.ast.util.ExprUtils +import dev.openrs2.deob.ast.util.isIntegerOrLongLiteral +import dev.openrs2.deob.ast.util.negate import dev.openrs2.deob.ast.util.walk class NegativeLiteralTransformer : Transformer() { override fun transform(unit: CompilationUnit) { unit.walk(Node.TreeTraversal.POSTORDER) { expr: UnaryExpr -> val operand = expr.expression - if (!ExprUtils.isIntegerOrLongLiteral(operand)) { + if (!operand.isIntegerOrLongLiteral()) { return@walk } @@ -20,7 +21,7 @@ class NegativeLiteralTransformer : Transformer() { expr.replace(operand) } UnaryExpr.Operator.MINUS -> { - expr.replace(ExprUtils.negate(operand)) + expr.replace(operand.negate()) } } } diff --git a/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/TernaryTransformer.kt b/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/TernaryTransformer.kt index d1a0616995..b38ccd7b7c 100644 --- a/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/TernaryTransformer.kt +++ b/deob-ast/src/main/java/dev/openrs2/deob/ast/transform/TernaryTransformer.kt @@ -3,15 +3,16 @@ package dev.openrs2.deob.ast.transform import com.github.javaparser.ast.CompilationUnit import com.github.javaparser.ast.Node import com.github.javaparser.ast.expr.ConditionalExpr -import dev.openrs2.deob.ast.util.ExprUtils +import dev.openrs2.deob.ast.util.countNots +import dev.openrs2.deob.ast.util.not import dev.openrs2.deob.ast.util.walk class TernaryTransformer : Transformer() { override fun transform(unit: CompilationUnit) { unit.walk(Node.TreeTraversal.POSTORDER) { expr: ConditionalExpr -> val condition = expr.condition - val notCondition = ExprUtils.not(condition) - if (ExprUtils.countNots(notCondition) >= ExprUtils.countNots(condition)) { + val notCondition = condition.not() + if (notCondition.countNots() >= condition.countNots()) { return@walk } 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 deleted file mode 100644 index e503eba71d..0000000000 --- a/deob-ast/src/main/java/dev/openrs2/deob/ast/util/ExprUtils.java +++ /dev/null @@ -1,104 +0,0 @@ -package dev.openrs2.deob.ast.util; - -import com.github.javaparser.ast.expr.BinaryExpr; -import com.github.javaparser.ast.expr.BooleanLiteralExpr; -import com.github.javaparser.ast.expr.Expression; -import com.github.javaparser.ast.expr.IntegerLiteralExpr; -import com.github.javaparser.ast.expr.LongLiteralExpr; -import com.github.javaparser.ast.expr.UnaryExpr; - -public final class ExprUtils { - public static boolean isIntegerOrLongLiteral(Expression expr) { - return expr.isIntegerLiteralExpr() || expr.isLongLiteralExpr(); - } - - public static LongLiteralExpr createLong(long value) { - return new LongLiteralExpr(Long.toString(value).concat("L")); - } - - public static Expression negate(Expression expr) { - if (expr.isUnaryExpr() && expr.asUnaryExpr().getOperator() == UnaryExpr.Operator.MINUS) { - return expr.asUnaryExpr().getExpression().clone(); - } else if (expr.isIntegerLiteralExpr()) { - return new IntegerLiteralExpr(-expr.asIntegerLiteralExpr().asInt()); - } else if (expr.isLongLiteralExpr()) { - return createLong(-expr.asLongLiteralExpr().asLong()); - } else { - throw new IllegalArgumentException(); - } - } - - public static Expression not(Expression expr) { - if (expr.isUnaryExpr()) { - var unary = expr.asUnaryExpr(); - if (unary.getOperator() == UnaryExpr.Operator.LOGICAL_COMPLEMENT) { - return unary.getExpression().clone(); - } - } else if (expr.isBinaryExpr()) { - var binary = expr.asBinaryExpr(); - - var left = binary.getLeft(); - var right = binary.getRight(); - - switch (binary.getOperator()) { - case EQUALS: - return new BinaryExpr(left.clone(), right.clone(), BinaryExpr.Operator.NOT_EQUALS); - case NOT_EQUALS: - return new BinaryExpr(left.clone(), right.clone(), BinaryExpr.Operator.EQUALS); - case GREATER: - return new BinaryExpr(left.clone(), right.clone(), BinaryExpr.Operator.LESS_EQUALS); - case GREATER_EQUALS: - return new BinaryExpr(left.clone(), right.clone(), BinaryExpr.Operator.LESS); - case LESS: - return new BinaryExpr(left.clone(), right.clone(), BinaryExpr.Operator.GREATER_EQUALS); - case LESS_EQUALS: - return new BinaryExpr(left.clone(), right.clone(), BinaryExpr.Operator.GREATER); - case AND: - return new BinaryExpr(not(left), not(right), BinaryExpr.Operator.OR); - case OR: - return new BinaryExpr(not(left), not(right), BinaryExpr.Operator.AND); - } - } else if (expr.isBooleanLiteralExpr()) { - return new BooleanLiteralExpr(!expr.asBooleanLiteralExpr().getValue()); - } - return new UnaryExpr(expr.clone(), UnaryExpr.Operator.LOGICAL_COMPLEMENT); - } - - public static int countNots(Expression expr) { - int count = 0; - - if (expr.isUnaryExpr() && expr.asUnaryExpr().getOperator() == UnaryExpr.Operator.LOGICAL_COMPLEMENT) { - count++; - } else if (expr.isBinaryExpr() && expr.asBinaryExpr().getOperator() == BinaryExpr.Operator.NOT_EQUALS) { - count++; - } - - for (Expression child : expr.findAll(Expression.class)) { - if (child != expr) { - count += countNots(child); - } - } - - return count; - } - - public static boolean hasSideEffects(Expression expr) { - if (expr.isLiteralExpr() || expr.isNameExpr() | expr.isFieldAccessExpr()) { - return false; - } 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 */ - } -} diff --git a/deob-ast/src/main/java/dev/openrs2/deob/ast/util/ExprUtils.kt b/deob-ast/src/main/java/dev/openrs2/deob/ast/util/ExprUtils.kt new file mode 100644 index 0000000000..aa3ae8fb7f --- /dev/null +++ b/deob-ast/src/main/java/dev/openrs2/deob/ast/util/ExprUtils.kt @@ -0,0 +1,94 @@ +package dev.openrs2.deob.ast.util + +import com.github.javaparser.ast.expr.* + +fun Expression.isIntegerOrLongLiteral(): Boolean { + return isIntegerLiteralExpr || isLongLiteralExpr +} + +fun createLong(value: Long): LongLiteralExpr { + return LongLiteralExpr(java.lang.Long.toString(value) + "L") +} + +fun Expression.negate(): Expression { + return if (isUnaryExpr && asUnaryExpr().operator == UnaryExpr.Operator.MINUS) { + asUnaryExpr().expression.clone() + } else if (isIntegerLiteralExpr) { + IntegerLiteralExpr(-asIntegerLiteralExpr().asInt()) + } else if (isLongLiteralExpr) { + createLong(-asLongLiteralExpr().asLong()) + } else { + throw IllegalArgumentException() + } +} + +fun Expression.not(): Expression { + if (isUnaryExpr) { + val unary = asUnaryExpr() + if (unary.operator == UnaryExpr.Operator.LOGICAL_COMPLEMENT) { + return unary.expression.clone() + } + } else if (isBinaryExpr) { + val binary = asBinaryExpr() + + val left = binary.left + val right = binary.right + + @Suppress("NON_EXHAUSTIVE_WHEN") + when (binary.operator) { + BinaryExpr.Operator.EQUALS -> + return BinaryExpr(left.clone(), right.clone(), BinaryExpr.Operator.NOT_EQUALS) + BinaryExpr.Operator.NOT_EQUALS -> + return BinaryExpr(left.clone(), right.clone(), BinaryExpr.Operator.EQUALS) + BinaryExpr.Operator.GREATER -> + return BinaryExpr(left.clone(), right.clone(), BinaryExpr.Operator.LESS_EQUALS) + BinaryExpr.Operator.GREATER_EQUALS -> + return BinaryExpr(left.clone(), right.clone(), BinaryExpr.Operator.LESS) + BinaryExpr.Operator.LESS -> + return BinaryExpr(left.clone(), right.clone(), BinaryExpr.Operator.GREATER_EQUALS) + BinaryExpr.Operator.LESS_EQUALS -> + return BinaryExpr(left.clone(), right.clone(), BinaryExpr.Operator.GREATER) + BinaryExpr.Operator.AND -> + return BinaryExpr(left.not(), right.not(), BinaryExpr.Operator.OR) + BinaryExpr.Operator.OR -> + return BinaryExpr(left.not(), right.not(), BinaryExpr.Operator.AND) + } + } else if (isBooleanLiteralExpr) { + return BooleanLiteralExpr(!asBooleanLiteralExpr().value) + } + return UnaryExpr(clone(), UnaryExpr.Operator.LOGICAL_COMPLEMENT) +} + +fun Expression.countNots(): Int { + var count = 0 + + if (isUnaryExpr && asUnaryExpr().operator == UnaryExpr.Operator.LOGICAL_COMPLEMENT) { + count++ + } else if (isBinaryExpr && asBinaryExpr().operator == BinaryExpr.Operator.NOT_EQUALS) { + count++ + } + + for (child in findAll(Expression::class.java)) { + if (child !== this) { + count += child.countNots() + } + } + + return count +} + +fun Expression.hasSideEffects(): Boolean { + if (isLiteralExpr || isNameExpr || isFieldAccessExpr) { + return false + } else if (isUnaryExpr) { + return asUnaryExpr().expression.hasSideEffects() + } else if (isBinaryExpr) { + val binary = asBinaryExpr() + return binary.left.hasSideEffects() || binary.right.hasSideEffects() + } else if (isArrayAccessExpr) { + val access = asArrayAccessExpr() + return access.name.hasSideEffects() || access.index.hasSideEffects() + } + // TODO(gpe): more cases + return true +}