package org.openrs2.deob.ast.util import com.github.javaparser.ast.expr.ArrayAccessExpr 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.FieldAccessExpr import com.github.javaparser.ast.expr.IntegerLiteralExpr import com.github.javaparser.ast.expr.LiteralExpr import com.github.javaparser.ast.expr.LongLiteralExpr import com.github.javaparser.ast.expr.NameExpr import com.github.javaparser.ast.expr.ThisExpr import com.github.javaparser.ast.expr.UnaryExpr public fun IntegerLiteralExpr.checkedAsInt(): Int { val n = asNumber() if (n !is Int) { error("Invalid IntegerLiteralExpr type") } return n } public fun Int.toHexLiteralExpr(): IntegerLiteralExpr { return IntegerLiteralExpr("0x${Integer.toUnsignedString(this, 16).uppercase()}") } public fun LongLiteralExpr.checkedAsLong(): Long { val n = asNumber() if (n !is Long) { error("Invalid LongLiteralExpr type") } return n } public fun Long.toHexLiteralExpr(): LongLiteralExpr { return LongLiteralExpr("0x${java.lang.Long.toUnsignedString(this, 16).uppercase()}L") } public fun Expression.isIntegerOrLongLiteral(): Boolean { return this is IntegerLiteralExpr || this is LongLiteralExpr } public fun Long.toLongLiteralExpr(): LongLiteralExpr { return LongLiteralExpr(this.toString() + "L") } public fun Expression.negate(): Expression { return when (this) { is UnaryExpr -> when (operator) { UnaryExpr.Operator.PLUS -> UnaryExpr(expression.clone(), UnaryExpr.Operator.MINUS) UnaryExpr.Operator.MINUS -> expression.clone() else -> UnaryExpr(clone(), UnaryExpr.Operator.MINUS) } is IntegerLiteralExpr -> when (val n = asNumber()) { IntegerLiteralExpr.MAX_31_BIT_UNSIGNED_VALUE_AS_LONG -> IntegerLiteralExpr(Integer.MIN_VALUE.toString()) is Int -> IntegerLiteralExpr((-n.toInt()).toString()) else -> error("Invalid IntegerLiteralExpr type") } is LongLiteralExpr -> when (val n = asNumber()) { LongLiteralExpr.MAX_63_BIT_UNSIGNED_VALUE_AS_BIG_INTEGER -> Long.MIN_VALUE.toLongLiteralExpr() is Long -> (-n).toLongLiteralExpr() else -> error("Invalid LongLiteralExpr type") } else -> UnaryExpr(clone(), UnaryExpr.Operator.MINUS) } } public fun Expression.not(): Expression { when (this) { is UnaryExpr -> { if (operator == UnaryExpr.Operator.LOGICAL_COMPLEMENT) { return expression.clone() } } is BinaryExpr -> { @Suppress("NON_EXHAUSTIVE_WHEN") when (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) } } is BooleanLiteralExpr -> return BooleanLiteralExpr(!value) } return UnaryExpr(clone(), UnaryExpr.Operator.LOGICAL_COMPLEMENT) } public fun Expression.countNots(): Int { var count = 0 if (this is UnaryExpr && operator == UnaryExpr.Operator.LOGICAL_COMPLEMENT) { count++ } else if (this is BinaryExpr && operator == BinaryExpr.Operator.NOT_EQUALS) { count++ } for (child in findAll(Expression::class.java)) { if (child !== this) { count += child.countNots() } } return count } public fun Expression.hasSideEffects(): Boolean { return when (this) { is LiteralExpr, is NameExpr, is ThisExpr -> false is UnaryExpr -> expression.hasSideEffects() is BinaryExpr -> left.hasSideEffects() || right.hasSideEffects() is ArrayAccessExpr -> name.hasSideEffects() || index.hasSideEffects() is FieldAccessExpr -> scope.hasSideEffects() // TODO(gpe): more cases else -> true } } public fun BinaryExpr.Operator.flip(): BinaryExpr.Operator? { return when (this) { BinaryExpr.Operator.PLUS, BinaryExpr.Operator.MULTIPLY -> this BinaryExpr.Operator.EQUALS, BinaryExpr.Operator.NOT_EQUALS -> this BinaryExpr.Operator.BINARY_AND, BinaryExpr.Operator.BINARY_OR -> this BinaryExpr.Operator.XOR, BinaryExpr.Operator.OR, BinaryExpr.Operator.AND -> this BinaryExpr.Operator.GREATER -> BinaryExpr.Operator.LESS BinaryExpr.Operator.GREATER_EQUALS -> BinaryExpr.Operator.LESS_EQUALS BinaryExpr.Operator.LESS -> BinaryExpr.Operator.GREATER BinaryExpr.Operator.LESS_EQUALS -> BinaryExpr.Operator.GREATER_EQUALS else -> null } }