Convert ExprUtils to Kotlin

pull/48/head
Graham 4 years ago
parent fc00d69539
commit 130a05956e
  1. 11
      deob-ast/src/main/java/dev/openrs2/deob/ast/transform/AddSubTransformer.kt
  2. 7
      deob-ast/src/main/java/dev/openrs2/deob/ast/transform/BitMaskTransformer.kt
  3. 9
      deob-ast/src/main/java/dev/openrs2/deob/ast/transform/ComplementTransformer.kt
  4. 11
      deob-ast/src/main/java/dev/openrs2/deob/ast/transform/IfElseTransformer.kt
  5. 7
      deob-ast/src/main/java/dev/openrs2/deob/ast/transform/NegativeLiteralTransformer.kt
  6. 7
      deob-ast/src/main/java/dev/openrs2/deob/ast/transform/TernaryTransformer.kt
  7. 104
      deob-ast/src/main/java/dev/openrs2/deob/ast/util/ExprUtils.java
  8. 94
      deob-ast/src/main/java/dev/openrs2/deob/ast/util/ExprUtils.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()
}
}
}

@ -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))

@ -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()
}
}

@ -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)

@ -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())
}
}
}

@ -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
}

@ -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 */
}
}

@ -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
}
Loading…
Cancel
Save