Use smart casts in the AST deobfuscator

Many of the old is/as calls were left over from the original Java code.

Signed-off-by: Graham <gpe@openrs2.dev>
Graham 4 years ago
parent bde818230b
commit 880be759b7
  1. 8
      deob-ast/src/main/java/dev/openrs2/deob/ast/transform/AddSubTransformer.kt
  2. 4
      deob-ast/src/main/java/dev/openrs2/deob/ast/transform/BinaryExprOrderTransformer.kt
  3. 23
      deob-ast/src/main/java/dev/openrs2/deob/ast/transform/BitMaskTransformer.kt
  4. 11
      deob-ast/src/main/java/dev/openrs2/deob/ast/transform/ComplementTransformer.kt
  5. 83
      deob-ast/src/main/java/dev/openrs2/deob/ast/transform/EncloseTransformer.kt
  6. 9
      deob-ast/src/main/java/dev/openrs2/deob/ast/transform/ForLoopConditionTransformer.kt
  7. 52
      deob-ast/src/main/java/dev/openrs2/deob/ast/transform/GlTransformer.kt
  8. 14
      deob-ast/src/main/java/dev/openrs2/deob/ast/transform/IdentityTransformer.kt
  9. 54
      deob-ast/src/main/java/dev/openrs2/deob/ast/transform/IfElseTransformer.kt
  10. 11
      deob-ast/src/main/java/dev/openrs2/deob/ast/transform/IncrementTransformer.kt
  11. 29
      deob-ast/src/main/java/dev/openrs2/deob/ast/util/ExprUtils.kt

@ -88,14 +88,14 @@ class AddSubTransformer : Transformer() {
}
private fun Expression.isNegative(): Boolean {
return when {
isUnaryExpr -> asUnaryExpr().operator == UnaryExpr.Operator.MINUS
isIntegerLiteralExpr -> when (val n = asIntegerLiteralExpr().asNumber()) {
return when (this) {
is UnaryExpr -> operator == UnaryExpr.Operator.MINUS
is IntegerLiteralExpr -> when (val n = asNumber()) {
IntegerLiteralExpr.MAX_31_BIT_UNSIGNED_VALUE_AS_LONG -> false
is Int -> n < 0
else -> error("Invalid IntegerLiteralExpr type")
}
isLongLiteralExpr -> when (val n = asLongLiteralExpr().asNumber()) {
is LongLiteralExpr -> when (val n = asNumber()) {
LongLiteralExpr.MAX_63_BIT_UNSIGNED_VALUE_AS_BIG_INTEGER -> false
is Long -> n < 0
else -> error("Invalid LongLiteralExpr type")

@ -3,6 +3,8 @@ package dev.openrs2.deob.ast.transform
import com.github.javaparser.ast.CompilationUnit
import com.github.javaparser.ast.expr.BinaryExpr
import com.github.javaparser.ast.expr.Expression
import com.github.javaparser.ast.expr.LiteralExpr
import com.github.javaparser.ast.expr.ThisExpr
import dev.openrs2.deob.ast.Library
import dev.openrs2.deob.ast.LibraryGroup
import dev.openrs2.deob.ast.util.flip
@ -32,5 +34,5 @@ class BinaryExprOrderTransformer : Transformer() {
}
private val Expression.isLiteralOrThisExpr: Boolean
get() = isLiteralExpr || isThisExpr
get() = this is LiteralExpr || this is ThisExpr
}

@ -3,11 +3,11 @@ package dev.openrs2.deob.ast.transform
import com.github.javaparser.ast.CompilationUnit
import com.github.javaparser.ast.expr.BinaryExpr
import com.github.javaparser.ast.expr.IntegerLiteralExpr
import com.github.javaparser.ast.expr.LongLiteralExpr
import dev.openrs2.deob.ast.Library
import dev.openrs2.deob.ast.LibraryGroup
import dev.openrs2.deob.ast.util.checkedAsInt
import dev.openrs2.deob.ast.util.checkedAsLong
import dev.openrs2.deob.ast.util.isIntegerOrLongLiteral
import dev.openrs2.deob.ast.util.toLongLiteralExpr
import dev.openrs2.deob.ast.util.walk
import javax.inject.Singleton
@ -17,25 +17,25 @@ class BitMaskTransformer : Transformer() {
override fun transformUnit(group: LibraryGroup, library: Library, unit: CompilationUnit) {
unit.walk { expr: BinaryExpr ->
val shiftOp = expr.operator
val left = expr.left
val bitwiseExpr = expr.left
val shamtExpr = expr.right
if (shiftOp !in SHIFT_OPS || !left.isBinaryExpr || !shamtExpr.isIntegerLiteralExpr) {
if (shiftOp !in SHIFT_OPS || bitwiseExpr !is BinaryExpr || shamtExpr !is IntegerLiteralExpr) {
return@walk
}
val bitwiseExpr = left.asBinaryExpr()
val bitwiseOp = bitwiseExpr.operator
val argExpr = bitwiseExpr.left
var maskExpr = bitwiseExpr.right
if (bitwiseOp !in BITWISE_OPS || !maskExpr.isIntegerOrLongLiteral()) {
if (bitwiseOp !in BITWISE_OPS) {
return@walk
}
val shamt = shamtExpr.asIntegerLiteralExpr().checkedAsInt()
if (maskExpr.isIntegerLiteralExpr) {
var mask = maskExpr.asIntegerLiteralExpr().checkedAsInt()
val shamt = shamtExpr.checkedAsInt()
when (maskExpr) {
is IntegerLiteralExpr -> {
var mask = maskExpr.checkedAsInt()
mask = when (shiftOp) {
BinaryExpr.Operator.SIGNED_RIGHT_SHIFT -> mask shr shamt
@ -44,8 +44,9 @@ class BitMaskTransformer : Transformer() {
}
maskExpr = IntegerLiteralExpr(mask.toString())
} else {
var mask = maskExpr.asLongLiteralExpr().checkedAsLong()
}
is LongLiteralExpr -> {
var mask = maskExpr.checkedAsLong()
mask = when (shiftOp) {
BinaryExpr.Operator.SIGNED_RIGHT_SHIFT -> mask shr shamt
@ -55,6 +56,8 @@ class BitMaskTransformer : Transformer() {
maskExpr = mask.toLongLiteralExpr()
}
else -> return@walk
}
expr.replace(BinaryExpr(BinaryExpr(argExpr.clone(), shamtExpr.clone(), shiftOp), maskExpr, bitwiseOp))
}

@ -4,6 +4,7 @@ import com.github.javaparser.ast.CompilationUnit
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.LongLiteralExpr
import com.github.javaparser.ast.expr.UnaryExpr
import dev.openrs2.deob.ast.Library
import dev.openrs2.deob.ast.LibraryGroup
@ -34,7 +35,7 @@ class ComplementTransformer : Transformer() {
private companion object {
private fun Expression.isComplement(): Boolean {
return isUnaryExpr && asUnaryExpr().operator == UnaryExpr.Operator.BITWISE_COMPLEMENT
return this is UnaryExpr && operator == UnaryExpr.Operator.BITWISE_COMPLEMENT
}
private fun Expression.isComplementOrLiteral(): Boolean {
@ -53,10 +54,10 @@ class ComplementTransformer : Transformer() {
}
private fun Expression.complement(): Expression {
return when {
isUnaryExpr -> asUnaryExpr().expression
isIntegerLiteralExpr -> IntegerLiteralExpr(asIntegerLiteralExpr().checkedAsInt().inv().toString())
isLongLiteralExpr -> asLongLiteralExpr().checkedAsLong().inv().toLongLiteralExpr()
return when (this) {
is UnaryExpr -> expression
is IntegerLiteralExpr -> IntegerLiteralExpr(checkedAsInt().inv().toString())
is LongLiteralExpr -> checkedAsLong().inv().toLongLiteralExpr()
else -> throw IllegalArgumentException()
}
}

@ -1,9 +1,19 @@
package dev.openrs2.deob.ast.transform
import com.github.javaparser.ast.CompilationUnit
import com.github.javaparser.ast.expr.ArrayAccessExpr
import com.github.javaparser.ast.expr.ArrayCreationExpr
import com.github.javaparser.ast.expr.AssignExpr
import com.github.javaparser.ast.expr.BinaryExpr
import com.github.javaparser.ast.expr.CastExpr
import com.github.javaparser.ast.expr.ConditionalExpr
import com.github.javaparser.ast.expr.EnclosedExpr
import com.github.javaparser.ast.expr.Expression
import com.github.javaparser.ast.expr.FieldAccessExpr
import com.github.javaparser.ast.expr.InstanceOfExpr
import com.github.javaparser.ast.expr.MethodCallExpr
import com.github.javaparser.ast.expr.ObjectCreationExpr
import com.github.javaparser.ast.expr.UnaryExpr
import dev.openrs2.deob.ast.Library
import dev.openrs2.deob.ast.LibraryGroup
import dev.openrs2.deob.ast.util.walk
@ -45,12 +55,12 @@ class EncloseTransformer : Transformer() {
companion object {
fun from(expr: Expression): Op? {
return when {
expr.isArrayAccessExpr || expr.isFieldAccessExpr -> ACCESS_PARENS
expr.isMethodCallExpr || expr.isEnclosedExpr -> ACCESS_PARENS
expr.isUnaryExpr -> if (expr.asUnaryExpr().operator.isPostfix) POSTFIX else UNARY
expr.isCastExpr || expr.isObjectCreationExpr || expr.isArrayCreationExpr -> CAST_NEW
expr.isBinaryExpr -> when (expr.asBinaryExpr().operator) {
return when (expr) {
is ArrayAccessExpr, is FieldAccessExpr -> ACCESS_PARENS
is MethodCallExpr, is EnclosedExpr -> ACCESS_PARENS
is UnaryExpr -> if (expr.operator.isPostfix) POSTFIX else UNARY
is CastExpr, is ObjectCreationExpr, is ArrayCreationExpr -> CAST_NEW
is BinaryExpr -> when (expr.operator) {
BinaryExpr.Operator.MULTIPLY -> MULTIPLICATIVE
BinaryExpr.Operator.DIVIDE, BinaryExpr.Operator.REMAINDER -> MULTIPLICATIVE
BinaryExpr.Operator.PLUS, BinaryExpr.Operator.MINUS -> ADDITIVE
@ -66,9 +76,9 @@ class EncloseTransformer : Transformer() {
BinaryExpr.Operator.OR -> LOGICAL_OR
else -> null
}
expr.isInstanceOfExpr -> RELATIONAL
expr.isConditionalExpr -> TERNARY
expr.isAssignExpr -> ASSIGNMENT
is InstanceOfExpr -> RELATIONAL
is ConditionalExpr -> TERNARY
is AssignExpr -> ASSIGNMENT
else -> null
}
}
@ -77,49 +87,34 @@ class EncloseTransformer : Transformer() {
override fun transformUnit(group: LibraryGroup, library: Library, unit: CompilationUnit) {
unit.walk { expr: Expression ->
when {
expr.isArrayAccessExpr -> {
val accessExpr = expr.asArrayAccessExpr()
encloseLeft(expr, accessExpr.name)
}
expr.isFieldAccessExpr -> {
encloseLeft(expr, expr.asFieldAccessExpr().scope)
}
expr.isMethodCallExpr -> {
expr.asMethodCallExpr().scope.ifPresent { scope ->
when (expr) {
is ArrayAccessExpr -> encloseLeft(expr, expr.name)
is FieldAccessExpr -> encloseLeft(expr, expr.scope)
is MethodCallExpr -> {
expr.scope.ifPresent { scope ->
encloseLeft(expr, scope)
}
}
expr.isUnaryExpr -> {
val unaryExpr = expr.asUnaryExpr()
encloseRight(expr, unaryExpr.expression)
}
expr.isCastExpr -> {
encloseRight(expr, expr.asCastExpr().expression)
}
expr.isObjectCreationExpr -> {
expr.asObjectCreationExpr().scope.ifPresent { scope ->
is UnaryExpr -> encloseRight(expr, expr.expression)
is CastExpr -> encloseRight(expr, expr.expression)
is ObjectCreationExpr -> {
expr.scope.ifPresent { scope ->
encloseLeft(expr, scope)
}
}
expr.isBinaryExpr -> {
val binaryExpr = expr.asBinaryExpr()
encloseLeft(expr, binaryExpr.left)
encloseRight(expr, binaryExpr.right)
}
expr.isInstanceOfExpr -> {
encloseLeft(expr, expr.asInstanceOfExpr().expression)
is BinaryExpr -> {
encloseLeft(expr, expr.left)
encloseRight(expr, expr.right)
}
expr.isConditionalExpr -> {
val conditionalExpr = expr.asConditionalExpr()
encloseLeft(expr, conditionalExpr.condition)
encloseLeft(expr, conditionalExpr.thenExpr)
encloseRight(expr, conditionalExpr.elseExpr)
is InstanceOfExpr -> encloseLeft(expr, expr.expression)
is ConditionalExpr -> {
encloseLeft(expr, expr.condition)
encloseLeft(expr, expr.thenExpr)
encloseRight(expr, expr.elseExpr)
}
expr.isAssignExpr -> {
val assignExpr = expr.asAssignExpr()
encloseLeft(expr, assignExpr.target)
encloseRight(expr, assignExpr.value)
is AssignExpr -> {
encloseLeft(expr, expr.target)
encloseRight(expr, expr.value)
}
}
}

@ -23,13 +23,10 @@ class ForLoopConditionTransformer : Transformer() {
unit.walk { stmt: ForStmt ->
val updatedExprs = stmt.update.mapNotNull { it.getUpdatedExpr() }
stmt.compare.ifPresent { compare ->
if (!compare.isBinaryExpr) {
stmt.compare.ifPresent { expr ->
if (expr !is BinaryExpr) {
return@ifPresent
}
val expr = compare.asBinaryExpr()
if (expr.hasSideEffects()) {
} else if (expr.hasSideEffects()) {
return@ifPresent
}

@ -9,13 +9,17 @@ import com.github.javaparser.ast.body.Parameter
import com.github.javaparser.ast.body.TypeDeclaration
import com.github.javaparser.ast.body.VariableDeclarator
import com.github.javaparser.ast.expr.BinaryExpr
import com.github.javaparser.ast.expr.ConditionalExpr
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.MethodCallExpr
import com.github.javaparser.ast.expr.NameExpr
import com.github.javaparser.ast.expr.SimpleName
import com.github.javaparser.ast.type.PrimitiveType
import com.github.javaparser.resolution.types.ResolvedArrayType
import com.github.javaparser.resolution.types.ResolvedPrimitiveType
import com.github.javaparser.resolution.types.ResolvedReferenceType
import com.github.javaparser.resolution.types.ResolvedType
import com.github.michaelbull.logging.InlineLogger
import dev.openrs2.deob.ast.Library
@ -65,11 +69,11 @@ class GlTransformer @Inject constructor(private val registry: GlRegistry) : Tran
}
private fun transformFramebufferStatus(unit: CompilationUnit, expr: Expression) {
if (!expr.isIntegerLiteralExpr) {
if (expr !is IntegerLiteralExpr) {
return
}
val value = expr.asIntegerLiteralExpr().checkedAsInt()
val value = expr.checkedAsInt()
if (value.toLong() != GL_FRAMEBUFFER_COMPLETE.value) {
return
}
@ -92,8 +96,8 @@ class GlTransformer @Inject constructor(private val registry: GlRegistry) : Tran
private fun ResolvedType.isFollowedByOffset(): Boolean {
return when {
isArray && asArrayType().componentType.isPrimitive -> true
isReferenceType && asReferenceType().qualifiedName == "java.lang.Object" -> true
this is ResolvedArrayType && componentType.isPrimitive -> true
this is ResolvedReferenceType && qualifiedName == "java.lang.Object" -> true
else -> false
}
}
@ -164,11 +168,11 @@ class GlTransformer @Inject constructor(private val registry: GlRegistry) : Tran
expr.scope.ifPresent { scope ->
val type = scope.calculateResolvedType()
if (!type.isReferenceType) {
if (type !is ResolvedReferenceType) {
return@ifPresent
}
val name = type.asReferenceType().qualifiedName
val name = type.qualifiedName
if (name in GL_CLASSES) {
transformArguments(unit, expr)
}
@ -235,26 +239,28 @@ class GlTransformer @Inject constructor(private val registry: GlRegistry) : Tran
parameter: GlParameter,
expr: Expression
) {
if (expr.isBinaryExpr) {
val binaryExpr = expr.asBinaryExpr()
transformExpr(unit, command, parameter, binaryExpr.left)
transformExpr(unit, command, parameter, binaryExpr.right)
} else if (expr.isConditionalExpr) {
val conditionalExpr = expr.asConditionalExpr()
transformExpr(unit, command, parameter, conditionalExpr.thenExpr)
transformExpr(unit, command, parameter, conditionalExpr.elseExpr)
} else if (expr.isIntegerLiteralExpr) {
when (expr) {
is BinaryExpr -> {
transformExpr(unit, command, parameter, expr.left)
transformExpr(unit, command, parameter, expr.right)
}
is ConditionalExpr -> {
transformExpr(unit, command, parameter, expr.thenExpr)
transformExpr(unit, command, parameter, expr.elseExpr)
}
is IntegerLiteralExpr -> {
transformIntegerLiteralExpr(unit, command, parameter, expr)
}
}
}
private fun transformIntegerLiteralExpr(
unit: CompilationUnit,
command: GlCommand,
parameter: GlParameter,
expr: Expression
expr: IntegerLiteralExpr
) {
var value = expr.asIntegerLiteralExpr().checkedAsInt()
var value = expr.checkedAsInt()
val group = parameter.group ?: return
if (parameter.bitfield) {
@ -320,21 +326,21 @@ class GlTransformer @Inject constructor(private val registry: GlRegistry) : Tran
private val FIELD_METHOD_COMPARATOR = Comparator<BodyDeclaration<*>> { a, b ->
when {
a.isFieldDeclaration && !b.isFieldDeclaration -> -1
!a.isFieldDeclaration && b.isFieldDeclaration -> 1
a is FieldDeclaration && b !is FieldDeclaration -> -1
a !is FieldDeclaration && b is FieldDeclaration -> 1
else -> 0
}
}
private fun BodyDeclaration<*>.getIntValue(): Int? {
if (!isFieldDeclaration) {
if (this !is FieldDeclaration) {
return null
}
val variable = asFieldDeclaration().variables.firstOrNull() ?: return null
val variable = variables.firstOrNull() ?: return null
return variable.initializer.map {
if (it.isIntegerLiteralExpr) {
it.asIntegerLiteralExpr().checkedAsInt()
if (it is IntegerLiteralExpr) {
it.checkedAsInt()
} else {
null
}

@ -3,6 +3,8 @@ package dev.openrs2.deob.ast.transform
import com.github.javaparser.ast.CompilationUnit
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.LongLiteralExpr
import com.github.javaparser.ast.expr.UnaryExpr
import dev.openrs2.deob.ast.Library
import dev.openrs2.deob.ast.LibraryGroup
@ -47,17 +49,17 @@ class IdentityTransformer : Transformer() {
}
private fun Expression.isZero(): Boolean {
return when {
isIntegerLiteralExpr -> asIntegerLiteralExpr().asNumber() == 0
isLongLiteralExpr -> asLongLiteralExpr().asNumber() == 0L
return when (this) {
is IntegerLiteralExpr -> asNumber() == 0
is LongLiteralExpr -> asNumber() == 0L
else -> false
}
}
private fun Expression.isOne(): Boolean {
return when {
isIntegerLiteralExpr -> asIntegerLiteralExpr().asNumber() == 1
isLongLiteralExpr -> asLongLiteralExpr().asNumber() == 1L
return when (this) {
is IntegerLiteralExpr -> asNumber() == 1
is LongLiteralExpr -> asNumber() == 1L
else -> false
}
}

@ -7,6 +7,7 @@ import com.github.javaparser.ast.stmt.BlockStmt
import com.github.javaparser.ast.stmt.IfStmt
import com.github.javaparser.ast.stmt.ReturnStmt
import com.github.javaparser.ast.stmt.Statement
import com.github.javaparser.ast.stmt.ThrowStmt
import dev.openrs2.deob.ast.Library
import dev.openrs2.deob.ast.LibraryGroup
import dev.openrs2.deob.ast.util.countNots
@ -78,7 +79,7 @@ class IfElseTransformer : Transformer() {
val notCondition = condition.not()
if (notCondition.countNots() < condition.countNots()) {
stmt.condition = notCondition
if (elseStmt.isIfStmt) {
if (elseStmt is IfStmt) {
val block = BlockStmt()
block.statements.add(elseStmt.clone())
stmt.thenStmt = block
@ -136,23 +137,19 @@ class IfElseTransformer : Transformer() {
unit.walk { stmt: IfStmt ->
stmt.elseStmt.ifPresent { elseStmt ->
// match
if (!elseStmt.isBlockStmt) {
if (elseStmt !is BlockStmt) {
return@ifPresent
}
val blockStmt = elseStmt.asBlockStmt()
val statements = blockStmt.statements
val statements = elseStmt.statements
if (statements.isEmpty()) {
return@ifPresent
}
val head = statements[0]
if (!head.isIfStmt) {
val ifStmt = statements[0]
if (ifStmt !is IfStmt) {
return@ifPresent
}
val ifStmt = head.asIfStmt()
if (ifStmt.elseStmt.isPresent) {
} else if (ifStmt.elseStmt.isPresent) {
return@ifPresent
}
@ -164,7 +161,7 @@ class IfElseTransformer : Transformer() {
// rewrite
val condition = ifStmt.condition.not()
val tail = blockStmt.clone()
val tail = elseStmt.clone()
tail.statements.removeAt(0)
elseStmt.replace(IfStmt(condition, tail, thenStmt.clone()))
@ -213,44 +210,47 @@ class IfElseTransformer : Transformer() {
}
private fun Statement.isIf(): Boolean {
return when {
isIfStmt -> true
isBlockStmt -> {
val stmts = asBlockStmt().statements
stmts.size == 1 && stmts[0].isIfStmt
return when (this) {
is IfStmt -> true
is BlockStmt -> {
val stmts = statements
stmts.size == 1 && stmts[0] is IfStmt
}
else -> false
}
}
private fun Statement.getIf(): Statement {
if (isIfStmt) {
when (this) {
is IfStmt -> {
return clone()
} else if (isBlockStmt) {
val stmts = asBlockStmt().statements
}
is BlockStmt -> {
val stmts = statements
if (stmts.size == 1) {
val head = stmts[0]
if (head.isIfStmt) {
if (head is IfStmt) {
return head.clone()
}
}
}
}
throw IllegalArgumentException()
}
private fun Statement.isTailThrowOrReturn(): Boolean {
return if (isThrowStmt || isReturnStmt) {
true
} else if (isBlockStmt) {
val stmts = asBlockStmt().statements
return when (this) {
is ThrowStmt, is ReturnStmt -> true
is BlockStmt -> {
val stmts = statements
if (stmts.isEmpty()) {
return false
}
val tail = stmts[stmts.size - 1]
tail.isThrowStmt || tail.isReturnStmt
} else {
false
tail is ThrowStmt || tail is ReturnStmt
}
else -> false
}
}
}

@ -13,22 +13,21 @@ import javax.inject.Singleton
class IncrementTransformer : Transformer() {
override fun transformUnit(group: LibraryGroup, library: Library, unit: CompilationUnit) {
unit.walk { stmt: ExpressionStmt ->
if (!stmt.expression.isUnaryExpr) {
val expr = stmt.expression
if (expr !is UnaryExpr) {
return@walk
}
val unaryExpr = stmt.expression.asUnaryExpr()
unaryExpr.operator = unaryExpr.operator.toPostfix()
expr.operator = expr.operator.toPostfix()
}
unit.walk { stmt: ForStmt ->
for (expr in stmt.update) {
if (!expr.isUnaryExpr) {
if (expr !is UnaryExpr) {
continue
}
val unaryExpr = expr.asUnaryExpr()
unaryExpr.operator = unaryExpr.operator.toPostfix()
expr.operator = expr.operator.toPostfix()
}
}
}

@ -37,7 +37,7 @@ fun Long.toHexLiteralExpr(): LongLiteralExpr {
}
fun Expression.isIntegerOrLongLiteral(): Boolean {
return isIntegerLiteralExpr || isLongLiteralExpr
return this is IntegerLiteralExpr || this is LongLiteralExpr
}
fun Long.toLongLiteralExpr(): LongLiteralExpr {
@ -66,19 +66,15 @@ fun Expression.negate(): Expression {
}
fun Expression.not(): Expression {
if (isUnaryExpr) {
val unary = asUnaryExpr()
if (unary.operator == UnaryExpr.Operator.LOGICAL_COMPLEMENT) {
return unary.expression.clone()
when (this) {
is UnaryExpr -> {
if (operator == UnaryExpr.Operator.LOGICAL_COMPLEMENT) {
return expression.clone()
}
} else if (isBinaryExpr) {
val binary = asBinaryExpr()
val left = binary.left
val right = binary.right
}
is BinaryExpr -> {
@Suppress("NON_EXHAUSTIVE_WHEN")
when (binary.operator) {
when (operator) {
BinaryExpr.Operator.EQUALS ->
return BinaryExpr(left.clone(), right.clone(), BinaryExpr.Operator.NOT_EQUALS)
BinaryExpr.Operator.NOT_EQUALS ->
@ -96,18 +92,19 @@ fun Expression.not(): Expression {
BinaryExpr.Operator.OR ->
return BinaryExpr(left.not(), right.not(), BinaryExpr.Operator.AND)
}
} else if (isBooleanLiteralExpr) {
return BooleanLiteralExpr(!asBooleanLiteralExpr().value)
}
is BooleanLiteralExpr -> return BooleanLiteralExpr(!value)
}
return UnaryExpr(clone(), UnaryExpr.Operator.LOGICAL_COMPLEMENT)
}
fun Expression.countNots(): Int {
var count = 0
if (isUnaryExpr && asUnaryExpr().operator == UnaryExpr.Operator.LOGICAL_COMPLEMENT) {
if (this is UnaryExpr && operator == UnaryExpr.Operator.LOGICAL_COMPLEMENT) {
count++
} else if (isBinaryExpr && asBinaryExpr().operator == BinaryExpr.Operator.NOT_EQUALS) {
} else if (this is BinaryExpr && operator == BinaryExpr.Operator.NOT_EQUALS) {
count++
}

Loading…
Cancel
Save