@@ -1494,7 +1494,7 @@ open class KotlinFileExtractor(
14941494 }
14951495 }
14961496
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 ) {
14981498 with (" variable expr" , v) {
14991499 val varId = useVariable(v)
15001500 val exprId = tw.getFreshIdLabel<DbLocalvariabledeclexpr >()
@@ -1509,7 +1509,7 @@ open class KotlinFileExtractor(
15091509 tw.writeCallableEnclosingExpr(exprId, callable)
15101510 tw.writeStatementEnclosingExpr(exprId, enclosingStmt)
15111511 val i = v.initializer
1512- if (i != null ) {
1512+ if (i != null && extractInitializer ) {
15131513 extractExpressionExpr(i, callable, exprId, 0 , enclosingStmt)
15141514 }
15151515 if (! v.isVar) {
@@ -3181,6 +3181,90 @@ open class KotlinFileExtractor(
31813181 }
31823182 }
31833183
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+
31843268 /* *
31853269 * This tried to extract a block as an array update.
31863270 * It returns true if it succeeds, and false otherwise.
@@ -3412,22 +3496,17 @@ open class KotlinFileExtractor(
34123496 }
34133497 }
34143498 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)
34243503 }
34253504 }
34263505 is IrWhileLoop -> {
3427- extractLoop (e, parent, callable)
3506+ extractLoopWithCondition (e, parent, callable)
34283507 }
34293508 is IrDoWhileLoop -> {
3430- extractLoop (e, parent, callable)
3509+ extractLoopWithCondition (e, parent, callable)
34313510 }
34323511 is IrInstanceInitializerCall -> {
34333512 val irConstructor = declarationStack.peek().first as ? IrConstructor
@@ -3892,6 +3971,32 @@ open class KotlinFileExtractor(
38923971 }
38933972 }
38943973
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+
38954000 private inline fun <D : DeclarationDescriptor , reified B : IrSymbolOwner > getBoundSymbolOwner (symbol : IrBindableSymbol <D , B >, e : IrExpression ): B ? {
38964001 if (symbol.isBound) {
38974002 return symbol.owner
@@ -4000,9 +4105,11 @@ open class KotlinFileExtractor(
40004105
40014106 private fun extractLoop (
40024107 loop : IrLoop ,
4108+ bodyIdx : Int? ,
40034109 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 > {
40064113 val stmtParent = stmtExprParent.stmt(loop, callable)
40074114 val locId = tw.getLocation(loop)
40084115
@@ -4023,22 +4130,34 @@ open class KotlinFileExtractor(
40234130 parent = stmtParent.parent
40244131 }
40254132
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)
40364134 tw.writeHasLocation(id, locId)
4037- extractExpressionExpr(loop.condition, callable, id, 0 , id)
4135+
40384136 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 )
40414139 }
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)
40424161 }
40434162
40444163 private fun IrValueParameter.isExtensionReceiver (): Boolean {
0 commit comments