@@ -1494,7 +1494,7 @@ open class KotlinFileExtractor(
1494
1494
}
1495
1495
}
1496
1496
1497
- private fun extractVariableExpr (v : IrVariable , callable : Label <out DbCallable >, parent : Label <out DbExprparent >, idx : Int , enclosingStmt : Label <out DbStmt >) {
1497
+ private fun extractVariableExpr (v : IrVariable , callable : Label <out DbCallable >, parent : Label <out DbExprparent >, idx : Int , enclosingStmt : Label <out DbStmt >, extractInitializer : Boolean = true ) {
1498
1498
with (" variable expr" , v) {
1499
1499
val varId = useVariable(v)
1500
1500
val exprId = tw.getFreshIdLabel<DbLocalvariabledeclexpr >()
@@ -1509,7 +1509,7 @@ open class KotlinFileExtractor(
1509
1509
tw.writeCallableEnclosingExpr(exprId, callable)
1510
1510
tw.writeStatementEnclosingExpr(exprId, enclosingStmt)
1511
1511
val i = v.initializer
1512
- if (i != null ) {
1512
+ if (i != null && extractInitializer ) {
1513
1513
extractExpressionExpr(i, callable, exprId, 0 , enclosingStmt)
1514
1514
}
1515
1515
if (! v.isVar) {
@@ -3181,6 +3181,90 @@ open class KotlinFileExtractor(
3181
3181
}
3182
3182
}
3183
3183
3184
+ /* *
3185
+ * This method tries to extract a block as an enhanced for loop.
3186
+ * It returns true if it succeeds, and false otherwise.
3187
+ */
3188
+ private fun tryExtractForLoop (e : IrContainerExpression , callable : Label <out DbCallable >, parent : StmtExprParent ): Boolean {
3189
+ /*
3190
+ * We're expecting the pattern
3191
+ * {
3192
+ * val iterator = [expr].iterator()
3193
+ * while (iterator.hasNext()) {
3194
+ * val [loopVar] = iterator.next()
3195
+ * [block]
3196
+ * }
3197
+ * }
3198
+ */
3199
+
3200
+ if (e.origin != IrStatementOrigin .FOR_LOOP ||
3201
+ e.statements.size != 2 ) {
3202
+ return false
3203
+ }
3204
+
3205
+ val iteratorVariable = e.statements[0 ] as ? IrVariable
3206
+ val innerWhile = e.statements[1 ] as ? IrWhileLoop
3207
+
3208
+ if (iteratorVariable == null ||
3209
+ iteratorVariable.origin != IrDeclarationOrigin .FOR_LOOP_ITERATOR ||
3210
+ innerWhile == null ||
3211
+ innerWhile.origin != IrStatementOrigin .FOR_LOOP_INNER_WHILE ) {
3212
+ return false
3213
+ }
3214
+
3215
+ val initializer = iteratorVariable.initializer as ? IrCall
3216
+ if (initializer == null ||
3217
+ initializer.origin != IrStatementOrigin .FOR_LOOP_ITERATOR ||
3218
+ initializer.symbol.owner.name.asString() != " iterator" ) {
3219
+ return false
3220
+ }
3221
+
3222
+ val expr = initializer.dispatchReceiver
3223
+ val cond = innerWhile.condition as ? IrCall
3224
+ val body = innerWhile.body as ? IrBlock
3225
+
3226
+ if (expr == null ||
3227
+ cond == null ||
3228
+ cond.origin != IrStatementOrigin .FOR_LOOP_HAS_NEXT ||
3229
+ (cond.dispatchReceiver as ? IrGetValue )?.symbol?.owner != iteratorVariable ||
3230
+ body == null ||
3231
+ body.origin != IrStatementOrigin .FOR_LOOP_INNER_WHILE ||
3232
+ body.statements.size < 2 ) {
3233
+ return false
3234
+ }
3235
+
3236
+ val loopVar = body.statements[0 ] as ? IrVariable
3237
+ val nextCall = loopVar?.initializer as ? IrCall
3238
+
3239
+ if (loopVar == null ||
3240
+ ! (loopVar.origin == IrDeclarationOrigin .FOR_LOOP_VARIABLE || loopVar.origin == IrDeclarationOrigin .IR_TEMPORARY_VARIABLE ) ||
3241
+ nextCall == null ||
3242
+ nextCall.origin != IrStatementOrigin .FOR_LOOP_NEXT ||
3243
+ (nextCall.dispatchReceiver as ? IrGetValue )?.symbol?.owner != iteratorVariable) {
3244
+ return false
3245
+ }
3246
+
3247
+ val id = extractLoop(innerWhile, null , parent, callable) { p, idx ->
3248
+ tw.getFreshIdLabel<DbEnhancedforstmt >().also {
3249
+ tw.writeStmts_enhancedforstmt(it, p, idx, callable)
3250
+ }
3251
+ }
3252
+
3253
+ extractVariableExpr(loopVar, callable, id, 0 , id, extractInitializer = false )
3254
+ extractExpressionExpr(expr, callable, id, 1 , id)
3255
+ val block = body.statements[1 ] as ? IrBlock
3256
+ if (body.statements.size == 2 && block != null ) {
3257
+ // Extract the body that was given to us by the compiler
3258
+ extractExpressionStmt(block, callable, id, 2 )
3259
+ } else {
3260
+ // Extract a block with all but the first (loop variable declaration) statement
3261
+ extractBlock(body, body.statements.takeLast(body.statements.size - 1 ), id, 2 , callable)
3262
+ }
3263
+
3264
+ return true
3265
+ }
3266
+
3267
+
3184
3268
/* *
3185
3269
* This tried to extract a block as an array update.
3186
3270
* It returns true if it succeeds, and false otherwise.
@@ -3412,22 +3496,17 @@ open class KotlinFileExtractor(
3412
3496
}
3413
3497
}
3414
3498
is IrContainerExpression -> {
3415
- if (! tryExtractArrayUpdate(e, callable, parent)) {
3416
- val stmtParent = parent.stmt(e, callable)
3417
- val id = tw.getFreshIdLabel<DbBlock >()
3418
- val locId = tw.getLocation(e)
3419
- tw.writeStmts_block(id, stmtParent.parent, stmtParent.idx, callable)
3420
- tw.writeHasLocation(id, locId)
3421
- e.statements.forEachIndexed { i, s ->
3422
- extractStatement(s, callable, id, i)
3423
- }
3499
+ if (! tryExtractArrayUpdate(e, callable, parent) &&
3500
+ ! tryExtractForLoop(e, callable, parent)) {
3501
+
3502
+ extractBlock(e, e.statements, parent, callable)
3424
3503
}
3425
3504
}
3426
3505
is IrWhileLoop -> {
3427
- extractLoop (e, parent, callable)
3506
+ extractLoopWithCondition (e, parent, callable)
3428
3507
}
3429
3508
is IrDoWhileLoop -> {
3430
- extractLoop (e, parent, callable)
3509
+ extractLoopWithCondition (e, parent, callable)
3431
3510
}
3432
3511
is IrInstanceInitializerCall -> {
3433
3512
val irConstructor = declarationStack.peek().first as ? IrConstructor
@@ -3892,6 +3971,32 @@ open class KotlinFileExtractor(
3892
3971
}
3893
3972
}
3894
3973
3974
+ private fun extractBlock (
3975
+ e : IrContainerExpression ,
3976
+ statements : List <IrStatement >,
3977
+ parent : StmtExprParent ,
3978
+ callable : Label <out DbCallable >
3979
+ ) {
3980
+ val stmtParent = parent.stmt(e, callable)
3981
+ extractBlock(e, statements, stmtParent.parent, stmtParent.idx, callable)
3982
+ }
3983
+
3984
+ private fun extractBlock (
3985
+ e : IrElement ,
3986
+ statements : List <IrStatement >,
3987
+ parent : Label <out DbStmtparent >,
3988
+ idx : Int ,
3989
+ callable : Label <out DbCallable >
3990
+ ) {
3991
+ val id = tw.getFreshIdLabel<DbBlock >()
3992
+ val locId = tw.getLocation(e)
3993
+ tw.writeStmts_block(id, parent, idx, callable)
3994
+ tw.writeHasLocation(id, locId)
3995
+ statements.forEachIndexed { i, s ->
3996
+ extractStatement(s, callable, id, i)
3997
+ }
3998
+ }
3999
+
3895
4000
private inline fun <D : DeclarationDescriptor , reified B : IrSymbolOwner > getBoundSymbolOwner (symbol : IrBindableSymbol <D , B >, e : IrExpression ): B ? {
3896
4001
if (symbol.isBound) {
3897
4002
return symbol.owner
@@ -4000,9 +4105,11 @@ open class KotlinFileExtractor(
4000
4105
4001
4106
private fun extractLoop (
4002
4107
loop : IrLoop ,
4108
+ bodyIdx : Int? ,
4003
4109
stmtExprParent : StmtExprParent ,
4004
- callable : Label <out DbCallable >
4005
- ) {
4110
+ callable : Label <out DbCallable >,
4111
+ getId : (Label <out DbStmtparent >, Int ) -> Label <out DbStmt >
4112
+ ) : Label <out DbStmt > {
4006
4113
val stmtParent = stmtExprParent.stmt(loop, callable)
4007
4114
val locId = tw.getLocation(loop)
4008
4115
@@ -4023,22 +4130,34 @@ open class KotlinFileExtractor(
4023
4130
parent = stmtParent.parent
4024
4131
}
4025
4132
4026
- val id = if (loop is IrWhileLoop ) {
4027
- val id = tw.getFreshIdLabel<DbWhilestmt >()
4028
- tw.writeStmts_whilestmt(id, parent, idx, callable)
4029
- id
4030
- } else {
4031
- val id = tw.getFreshIdLabel<DbDostmt >()
4032
- tw.writeStmts_dostmt(id, parent, idx, callable)
4033
- id
4034
- }
4035
-
4133
+ val id = getId(parent, idx)
4036
4134
tw.writeHasLocation(id, locId)
4037
- extractExpressionExpr(loop.condition, callable, id, 0 , id)
4135
+
4038
4136
val body = loop.body
4039
- if (body != null ) {
4040
- extractExpressionStmt(body, callable, id, 1 )
4137
+ if (body != null && bodyIdx != null ) {
4138
+ extractExpressionStmt(body, callable, id, bodyIdx )
4041
4139
}
4140
+
4141
+ return id
4142
+ }
4143
+
4144
+ private fun extractLoopWithCondition (
4145
+ loop : IrLoop ,
4146
+ stmtExprParent : StmtExprParent ,
4147
+ callable : Label <out DbCallable >
4148
+ ) {
4149
+ val id = extractLoop(loop, 1 , stmtExprParent, callable) { parent, idx ->
4150
+ if (loop is IrWhileLoop ) {
4151
+ tw.getFreshIdLabel<DbWhilestmt >().also {
4152
+ tw.writeStmts_whilestmt(it, parent, idx, callable)
4153
+ }
4154
+ } else {
4155
+ tw.getFreshIdLabel<DbDostmt >().also {
4156
+ tw.writeStmts_dostmt(it, parent, idx, callable)
4157
+ }
4158
+ }
4159
+ }
4160
+ extractExpressionExpr(loop.condition, callable, id, 0 , id)
4042
4161
}
4043
4162
4044
4163
private fun IrValueParameter.isExtensionReceiver (): Boolean {
0 commit comments