Skip to content

Commit a9e45d8

Browse files
authored
Merge pull request #17761 from tamasvajk/ke2-binary-ops
KE2: extract binary operators
2 parents 83b3e8c + 53460d7 commit a9e45d8

File tree

2 files changed

+81
-182
lines changed

2 files changed

+81
-182
lines changed

java/kotlin-extractor2/src/main/kotlin/KotlinFileExtractor.kt

Lines changed: 0 additions & 149 deletions
Original file line numberDiff line numberDiff line change
@@ -2977,93 +2977,6 @@ OLD: KE1
29772977
29782978
val dr = c.dispatchReceiver
29792979
when {
2980-
isNumericFunction(
2981-
target,
2982-
"plus",
2983-
"minus",
2984-
"times",
2985-
"div",
2986-
"rem",
2987-
"and",
2988-
"or",
2989-
"xor",
2990-
"shl",
2991-
"shr",
2992-
"ushr"
2993-
) -> {
2994-
val type = useType(c.type)
2995-
val id: Label<out DbExpr> =
2996-
when (val targetName = target.name.asString()) {
2997-
"minus" -> {
2998-
val id = tw.getFreshIdLabel<DbSubexpr>()
2999-
tw.writeExprs_subexpr(id, type.javaResult.id, parent, idx)
3000-
id
3001-
}
3002-
"times" -> {
3003-
val id = tw.getFreshIdLabel<DbMulexpr>()
3004-
tw.writeExprs_mulexpr(id, type.javaResult.id, parent, idx)
3005-
id
3006-
}
3007-
"div" -> {
3008-
val id = tw.getFreshIdLabel<DbDivexpr>()
3009-
tw.writeExprs_divexpr(id, type.javaResult.id, parent, idx)
3010-
id
3011-
}
3012-
"rem" -> {
3013-
val id = tw.getFreshIdLabel<DbRemexpr>()
3014-
tw.writeExprs_remexpr(id, type.javaResult.id, parent, idx)
3015-
id
3016-
}
3017-
"and" -> {
3018-
val id = tw.getFreshIdLabel<DbAndbitexpr>()
3019-
tw.writeExprs_andbitexpr(id, type.javaResult.id, parent, idx)
3020-
id
3021-
}
3022-
"or" -> {
3023-
val id = tw.getFreshIdLabel<DbOrbitexpr>()
3024-
tw.writeExprs_orbitexpr(id, type.javaResult.id, parent, idx)
3025-
id
3026-
}
3027-
"xor" -> {
3028-
val id = tw.getFreshIdLabel<DbXorbitexpr>()
3029-
tw.writeExprs_xorbitexpr(id, type.javaResult.id, parent, idx)
3030-
id
3031-
}
3032-
"shl" -> {
3033-
val id = tw.getFreshIdLabel<DbLshiftexpr>()
3034-
tw.writeExprs_lshiftexpr(id, type.javaResult.id, parent, idx)
3035-
id
3036-
}
3037-
"shr" -> {
3038-
val id = tw.getFreshIdLabel<DbRshiftexpr>()
3039-
tw.writeExprs_rshiftexpr(id, type.javaResult.id, parent, idx)
3040-
id
3041-
}
3042-
"ushr" -> {
3043-
val id = tw.getFreshIdLabel<DbUrshiftexpr>()
3044-
tw.writeExprs_urshiftexpr(id, type.javaResult.id, parent, idx)
3045-
id
3046-
}
3047-
else -> {
3048-
logger.errorElement("Unhandled binary target name: $targetName", c)
3049-
return
3050-
}
3051-
}
3052-
tw.writeExprsKotlinType(id, type.kotlinResult.id)
3053-
if (
3054-
isFunction(
3055-
target,
3056-
"kotlin",
3057-
"Byte or Short",
3058-
{ it == "Byte" || it == "Short" },
3059-
"and",
3060-
"or",
3061-
"xor"
3062-
)
3063-
)
3064-
binopExt(id)
3065-
else binopDisp(id)
3066-
}
30672980
// != gets desugared into not and ==. Here we resugar it.
30682981
c.origin == IrStatementOrigin.EXCLEQ &&
30692982
isFunction(target, "kotlin", "Boolean", "not") &&
@@ -3077,18 +2990,6 @@ OLD: KE1
30772990
tw.writeExprsKotlinType(id, type.kotlinResult.id)
30782991
binOp(id, dr, callable, enclosingStmt)
30792992
}
3080-
c.origin == IrStatementOrigin.EXCLEQEQ &&
3081-
isFunction(target, "kotlin", "Boolean", "not") &&
3082-
c.valueArgumentsCount == 0 &&
3083-
dr != null &&
3084-
dr is IrCall &&
3085-
isBuiltinCallInternal(dr, "EQEQEQ") -> {
3086-
val id = tw.getFreshIdLabel<DbNeexpr>()
3087-
val type = useType(c.type)
3088-
tw.writeExprs_neexpr(id, type.javaResult.id, parent, idx)
3089-
tw.writeExprsKotlinType(id, type.kotlinResult.id)
3090-
binOp(id, dr, callable, enclosingStmt)
3091-
}
30922993
c.origin == IrStatementOrigin.EXCLEQ &&
30932994
isFunction(target, "kotlin", "Boolean", "not") &&
30942995
c.valueArgumentsCount == 0 &&
@@ -3148,46 +3049,6 @@ OLD: KE1
31483049
// We need to handle all the builtin operators defines in BuiltInOperatorNames in
31493050
// compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrBuiltIns.kt
31503051
// as they can't be extracted as external dependencies.
3151-
isBuiltinCallInternal(c, "less") -> {
3152-
if (c.origin != IrStatementOrigin.LT) {
3153-
logger.warnElement("Unexpected origin for LT: ${c.origin}", c)
3154-
}
3155-
val id = tw.getFreshIdLabel<DbLtexpr>()
3156-
val type = useType(c.type)
3157-
tw.writeExprs_ltexpr(id, type.javaResult.id, parent, idx)
3158-
tw.writeExprsKotlinType(id, type.kotlinResult.id)
3159-
binOp(id, c, callable, enclosingStmt)
3160-
}
3161-
isBuiltinCallInternal(c, "lessOrEqual") -> {
3162-
if (c.origin != IrStatementOrigin.LTEQ) {
3163-
logger.warnElement("Unexpected origin for LTEQ: ${c.origin}", c)
3164-
}
3165-
val id = tw.getFreshIdLabel<DbLeexpr>()
3166-
val type = useType(c.type)
3167-
tw.writeExprs_leexpr(id, type.javaResult.id, parent, idx)
3168-
tw.writeExprsKotlinType(id, type.kotlinResult.id)
3169-
binOp(id, c, callable, enclosingStmt)
3170-
}
3171-
isBuiltinCallInternal(c, "greater") -> {
3172-
if (c.origin != IrStatementOrigin.GT) {
3173-
logger.warnElement("Unexpected origin for GT: ${c.origin}", c)
3174-
}
3175-
val id = tw.getFreshIdLabel<DbGtexpr>()
3176-
val type = useType(c.type)
3177-
tw.writeExprs_gtexpr(id, type.javaResult.id, parent, idx)
3178-
tw.writeExprsKotlinType(id, type.kotlinResult.id)
3179-
binOp(id, c, callable, enclosingStmt)
3180-
}
3181-
isBuiltinCallInternal(c, "greaterOrEqual") -> {
3182-
if (c.origin != IrStatementOrigin.GTEQ) {
3183-
logger.warnElement("Unexpected origin for GTEQ: ${c.origin}", c)
3184-
}
3185-
val id = tw.getFreshIdLabel<DbGeexpr>()
3186-
val type = useType(c.type)
3187-
tw.writeExprs_geexpr(id, type.javaResult.id, parent, idx)
3188-
tw.writeExprsKotlinType(id, type.kotlinResult.id)
3189-
binOp(id, c, callable, enclosingStmt)
3190-
}
31913052
isBuiltinCallInternal(c, "EQEQ") -> {
31923053
if (c.origin != IrStatementOrigin.EQEQ) {
31933054
logger.warnElement("Unexpected origin for EQEQ: ${c.origin}", c)
@@ -3198,16 +3059,6 @@ OLD: KE1
31983059
tw.writeExprsKotlinType(id, type.kotlinResult.id)
31993060
binOp(id, c, callable, enclosingStmt)
32003061
}
3201-
isBuiltinCallInternal(c, "EQEQEQ") -> {
3202-
if (c.origin != IrStatementOrigin.EQEQEQ) {
3203-
logger.warnElement("Unexpected origin for EQEQEQ: ${c.origin}", c)
3204-
}
3205-
val id = tw.getFreshIdLabel<DbEqexpr>()
3206-
val type = useType(c.type)
3207-
tw.writeExprs_eqexpr(id, type.javaResult.id, parent, idx)
3208-
tw.writeExprsKotlinType(id, type.kotlinResult.id)
3209-
binOp(id, c, callable, enclosingStmt)
3210-
}
32113062
isBuiltinCallInternal(c, "ieee754equals") -> {
32123063
if (c.origin != IrStatementOrigin.EQEQ) {
32133064
logger.warnElement("Unexpected origin for ieee754equals: ${c.origin}", c)

java/kotlin-extractor2/src/main/kotlin/entities/Expression.kt

Lines changed: 81 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -256,13 +256,14 @@ private fun KaFunctionSymbol.hasName(
256256
)
257257
}
258258

259-
private fun KaFunctionSymbol.isNumericWithName(functionName: String): Boolean {
260-
return this.hasName("kotlin", "Int", functionName) ||
261-
this.hasName("kotlin", "Byte", functionName) ||
262-
this.hasName("kotlin", "Short", functionName) ||
263-
this.hasName("kotlin", "Long", functionName) ||
264-
this.hasName("kotlin", "Float", functionName) ||
265-
this.hasName("kotlin", "Double", functionName)
259+
private fun KaFunctionSymbol?.isNumericWithName(functionName: String): Boolean {
260+
return this != null &&
261+
(this.hasName("kotlin", "Int", functionName) ||
262+
this.hasName("kotlin", "Byte", functionName) ||
263+
this.hasName("kotlin", "Short", functionName) ||
264+
this.hasName("kotlin", "Long", functionName) ||
265+
this.hasName("kotlin", "Float", functionName) ||
266+
this.hasName("kotlin", "Double", functionName))
266267
}
267268

268269
context(KaSession)
@@ -297,37 +298,84 @@ private fun KotlinFileExtractor.extractBinaryExpression(
297298
val op = expression.operationToken
298299
val target = expression.resolveCallTarget()?.symbol
299300

300-
when (op) {
301-
KtTokens.PLUS -> {
302-
if (target == null) {
303-
TODO()
304-
}
305-
306-
if (target.isNumericWithName("plus") ||
307-
target.hasName("kotlin", "String", "plus") ||
308-
target.hasMatchingNames(
309-
CallableId(FqName("kotlin"), null, Name.identifier("plus")),
310-
ClassId(FqName("kotlin"), Name.identifier("String")),
311-
nullability = KaTypeNullability.NULLABLE,
312-
)
313-
) {
314-
val id = tw.getFreshIdLabel<DbAddexpr>()
315-
val type = useType(expression.expressionType)
316-
val exprParent = parent.expr(expression, callable)
317-
tw.writeExprs_addexpr(id, type.javaResult.id, exprParent.parent, exprParent.idx)
318-
tw.writeExprsKotlinType(id, type.kotlinResult.id)
319-
320-
extractExprContext(id, tw.getLocation(expression), callable, exprParent.enclosingStmt)
321-
extractExpressionExpr(expression.left!!, callable, id, 0, exprParent.enclosingStmt)
322-
extractExpressionExpr(expression.right!!, callable, id, 1, exprParent.enclosingStmt)
323-
} else {
324-
TODO("Extract as method call")
301+
if (op == KtTokens.PLUS && target.isBinaryPlus()) {
302+
extractBinaryExpression(expression, callable, parent, tw::writeExprs_addexpr)
303+
} else if (op == KtTokens.MINUS && target.isNumericWithName("minus")) {
304+
extractBinaryExpression(expression, callable, parent, tw::writeExprs_subexpr)
305+
} else if (op == KtTokens.MUL && target.isNumericWithName("times")) {
306+
extractBinaryExpression(expression, callable, parent, tw::writeExprs_mulexpr)
307+
} else if (op == KtTokens.DIV && target.isNumericWithName("div")) {
308+
extractBinaryExpression(expression, callable, parent, tw::writeExprs_divexpr)
309+
} else if (op == KtTokens.PERC && target.isNumericWithName("rem")) {
310+
extractBinaryExpression(expression, callable, parent, tw::writeExprs_remexpr)
311+
} else if (op == KtTokens.IDENTIFIER && target.isNumericWithName("and")) {
312+
extractBinaryExpression(expression, callable, parent, tw::writeExprs_andbitexpr)
313+
} else if (op == KtTokens.IDENTIFIER && target.isNumericWithName("or")) {
314+
extractBinaryExpression(expression, callable, parent, tw::writeExprs_orbitexpr)
315+
} else if (op == KtTokens.IDENTIFIER && target.isNumericWithName("xor")) {
316+
extractBinaryExpression(expression, callable, parent, tw::writeExprs_xorbitexpr)
317+
} else if (op == KtTokens.IDENTIFIER && target.isNumericWithName("shl")) {
318+
extractBinaryExpression(expression, callable, parent, tw::writeExprs_lshiftexpr)
319+
} else if (op == KtTokens.IDENTIFIER && target.isNumericWithName("shr")) {
320+
extractBinaryExpression(expression, callable, parent, tw::writeExprs_rshiftexpr)
321+
} else if (op == KtTokens.IDENTIFIER && target.isNumericWithName("ushr")) {
322+
extractBinaryExpression(expression, callable, parent, tw::writeExprs_urshiftexpr)
323+
} else if (op == KtTokens.EQEQEQ && target == null) {
324+
extractBinaryExpression(expression, callable, parent, tw::writeExprs_eqexpr)
325+
} else if (op == KtTokens.EXCLEQEQEQ && target == null) {
326+
extractBinaryExpression(expression, callable, parent, tw::writeExprs_neexpr)
327+
} else if (op in listOf(KtTokens.LT, KtTokens.GT, KtTokens.LTEQ, KtTokens.GTEQ)) {
328+
if (target.isNumericWithName("compareTo")) {
329+
when (op) {
330+
KtTokens.LT -> extractBinaryExpression(expression, callable, parent, tw::writeExprs_ltexpr)
331+
KtTokens.GT -> extractBinaryExpression(expression, callable, parent, tw::writeExprs_gtexpr)
332+
KtTokens.LTEQ -> extractBinaryExpression(expression, callable, parent, tw::writeExprs_leexpr)
333+
KtTokens.GTEQ -> extractBinaryExpression(expression, callable, parent, tw::writeExprs_geexpr)
334+
else -> TODO("error")
325335
}
336+
} else {
337+
TODO("Extract lowered equivalent call, such as `a.compareTo(b) < 0`")
326338
}
327339

328-
else -> TODO()
340+
} else {
341+
// todo: other operators, such as .., ..<, in, !in, =, +=, -=, *=, /=, %=, ==, !=,
342+
TODO("Extract as method call")
329343
}
344+
}
345+
346+
private fun KaFunctionSymbol?.isBinaryPlus(): Boolean {
347+
return this != null && (
348+
this.isNumericWithName("plus") ||
349+
this.hasName("kotlin", "String", "plus") ||
350+
/* The target for `(null as String?) + null` is `public operator fun String?.plus(other: Any?): String` */
351+
this.hasMatchingNames(
352+
CallableId(FqName("kotlin"), null, Name.identifier("plus")),
353+
ClassId(FqName("kotlin"), Name.identifier("String")),
354+
nullability = KaTypeNullability.NULLABLE,
355+
))
356+
}
330357

358+
context(KaSession)
359+
private fun <T : DbBinaryexpr> KotlinFileExtractor.extractBinaryExpression(
360+
expression: KtBinaryExpression,
361+
callable: Label<out DbCallable>,
362+
parent: StmtExprParent,
363+
extractExpression: (
364+
id: Label<out T>,
365+
typeid: Label<out DbType>,
366+
parent: Label<out DbExprparent>,
367+
idx: Int
368+
) -> Unit
369+
) {
370+
val id = tw.getFreshIdLabel<T>()
371+
val type = useType(expression.expressionType)
372+
val exprParent = parent.expr(expression, callable)
373+
extractExpression(id, type.javaResult.id, exprParent.parent, exprParent.idx)
374+
tw.writeExprsKotlinType(id, type.kotlinResult.id)
375+
376+
extractExprContext(id, tw.getLocation(expression), callable, exprParent.enclosingStmt)
377+
extractExpressionExpr(expression.left!!, callable, id, 0, exprParent.enclosingStmt)
378+
extractExpressionExpr(expression.right!!, callable, id, 1, exprParent.enclosingStmt)
331379
}
332380

333381
context(KaSession)

0 commit comments

Comments
 (0)