@@ -1499,7 +1499,7 @@ open class KotlinFileExtractor(
14991499 }
15001500 }
15011501
1502- private fun extractVariableExpr (v : IrVariable , callable : Label <out DbCallable >, parent : Label <out DbExprparent >, idx : Int , enclosingStmt : Label <out DbStmt >) {
1502+ private fun extractVariableExpr (v : IrVariable , callable : Label <out DbCallable >, parent : Label <out DbExprparent >, idx : Int , enclosingStmt : Label <out DbStmt >, extractInitializer : Boolean = true ) {
15031503 with (" variable expr" , v) {
15041504 val varId = useVariable(v)
15051505 val exprId = tw.getFreshIdLabel<DbLocalvariabledeclexpr >()
@@ -1514,7 +1514,7 @@ open class KotlinFileExtractor(
15141514 tw.writeCallableEnclosingExpr(exprId, callable)
15151515 tw.writeStatementEnclosingExpr(exprId, enclosingStmt)
15161516 val i = v.initializer
1517- if (i != null ) {
1517+ if (i != null && extractInitializer ) {
15181518 extractExpressionExpr(i, callable, exprId, 0 , enclosingStmt)
15191519 }
15201520 if (! v.isVar) {
@@ -3174,6 +3174,85 @@ open class KotlinFileExtractor(
31743174 }
31753175 }
31763176
3177+ /* *
3178+ * This method tries to extract a block as an enhanced for loop.
3179+ * It returns true if it succeeds, and false otherwise.
3180+ */
3181+ private fun tryExtractForLoop (e : IrContainerExpression , callable : Label <out DbCallable >, parent : StmtExprParent ): Boolean {
3182+ /*
3183+ * We're expecting the pattern
3184+ * {
3185+ * val iterator = [expr].iterator()
3186+ * while (iterator.hasNext()) {
3187+ * val [loopVar] = iterator.next()
3188+ * [block]
3189+ * }
3190+ * }
3191+ */
3192+
3193+ if (e.origin != IrStatementOrigin .FOR_LOOP ||
3194+ e.statements.size != 2 ||
3195+ (e.statements[0 ] as ? IrVariable )?.origin != IrDeclarationOrigin .FOR_LOOP_ITERATOR ||
3196+ (e.statements[1 ] as ? IrWhileLoop )?.origin != IrStatementOrigin .FOR_LOOP_INNER_WHILE ) {
3197+ return false
3198+ }
3199+
3200+ val iteratorVariable = e.statements[0 ] as ? IrVariable
3201+ val innerWhile = e.statements[1 ] as ? IrWhileLoop
3202+
3203+ if (iteratorVariable == null ||
3204+ iteratorVariable.origin != IrDeclarationOrigin .FOR_LOOP_ITERATOR ||
3205+ innerWhile == null ||
3206+ innerWhile.origin != IrStatementOrigin .FOR_LOOP_INNER_WHILE ) {
3207+ return false
3208+ }
3209+
3210+ val initializer = iteratorVariable.initializer as ? IrCall
3211+ if (initializer == null ||
3212+ initializer.origin != IrStatementOrigin .FOR_LOOP_ITERATOR ||
3213+ initializer.symbol.owner.name.asString() != " iterator" ) {
3214+ return false
3215+ }
3216+
3217+ val expr = initializer.dispatchReceiver
3218+ val cond = innerWhile.condition as ? IrCall
3219+ val body = innerWhile.body as ? IrBlock
3220+
3221+ if (expr == null ||
3222+ cond == null ||
3223+ cond.origin != IrStatementOrigin .FOR_LOOP_HAS_NEXT ||
3224+ (cond.dispatchReceiver as ? IrGetValue )?.symbol?.owner != iteratorVariable ||
3225+ body == null ||
3226+ body.origin != IrStatementOrigin .FOR_LOOP_INNER_WHILE ||
3227+ body.statements.size != 2 ) {
3228+ return false
3229+ }
3230+
3231+ val loopVar = body.statements[0 ] as ? IrVariable
3232+ val block = body.statements[1 ] as ? IrBlock
3233+ val nextCall = loopVar?.initializer as ? IrCall
3234+
3235+ if (loopVar == null ||
3236+ ! (loopVar.origin == IrDeclarationOrigin .FOR_LOOP_VARIABLE || loopVar.origin == IrDeclarationOrigin .IR_TEMPORARY_VARIABLE ) ||
3237+ nextCall == null ||
3238+ nextCall.origin != IrStatementOrigin .FOR_LOOP_NEXT ||
3239+ (nextCall.dispatchReceiver as ? IrGetValue )?.symbol?.owner != iteratorVariable) {
3240+ return false
3241+ }
3242+
3243+ val id = extractLoop(innerWhile, block, 2 , parent, callable) { p, idx ->
3244+ val loopId = tw.getFreshIdLabel<DbEnhancedforstmt >()
3245+ tw.writeStmts_enhancedforstmt(loopId, p, idx, callable)
3246+ loopId
3247+ }
3248+
3249+ extractExpressionExpr(expr, callable, id, 1 , id)
3250+ extractVariableExpr(loopVar, callable, id, 0 , id, extractInitializer = false )
3251+
3252+ return true
3253+ }
3254+
3255+
31773256 /* *
31783257 * This tried to extract a block as an array update.
31793258 * It returns true if it succeeds, and false otherwise.
@@ -3405,7 +3484,9 @@ open class KotlinFileExtractor(
34053484 }
34063485 }
34073486 is IrContainerExpression -> {
3408- if (! tryExtractArrayUpdate(e, callable, parent)) {
3487+ if (! tryExtractArrayUpdate(e, callable, parent) &&
3488+ ! tryExtractForLoop(e, callable, parent)) {
3489+
34093490 val stmtParent = parent.stmt(e, callable)
34103491 val id = tw.getFreshIdLabel<DbBlock >()
34113492 val locId = tw.getLocation(e)
@@ -3417,10 +3498,10 @@ open class KotlinFileExtractor(
34173498 }
34183499 }
34193500 is IrWhileLoop -> {
3420- extractLoop (e, parent, callable)
3501+ extractLoopWithCondition (e, parent, callable)
34213502 }
34223503 is IrDoWhileLoop -> {
3423- extractLoop (e, parent, callable)
3504+ extractLoopWithCondition (e, parent, callable)
34243505 }
34253506 is IrInstanceInitializerCall -> {
34263507 val irConstructor = declarationStack.peek().first as ? IrConstructor
@@ -3993,9 +4074,12 @@ open class KotlinFileExtractor(
39934074
39944075 private fun extractLoop (
39954076 loop : IrLoop ,
4077+ body : IrExpression ? ,
4078+ bodyIdx : Int ,
39964079 stmtExprParent : StmtExprParent ,
3997- callable : Label <out DbCallable >
3998- ) {
4080+ callable : Label <out DbCallable >,
4081+ getId : (Label <out DbStmtparent >, Int ) -> Label <out DbStmt >
4082+ ) : Label <out DbStmt > {
39994083 val stmtParent = stmtExprParent.stmt(loop, callable)
40004084 val locId = tw.getLocation(loop)
40014085
@@ -4016,22 +4100,33 @@ open class KotlinFileExtractor(
40164100 parent = stmtParent.parent
40174101 }
40184102
4019- val id = if (loop is IrWhileLoop ) {
4020- val id = tw.getFreshIdLabel<DbWhilestmt >()
4021- tw.writeStmts_whilestmt(id, parent, idx, callable)
4022- id
4023- } else {
4024- val id = tw.getFreshIdLabel<DbDostmt >()
4025- tw.writeStmts_dostmt(id, parent, idx, callable)
4026- id
4027- }
4028-
4103+ val id = getId(parent, idx)
40294104 tw.writeHasLocation(id, locId)
4030- extractExpressionExpr(loop.condition, callable, id, 0 , id)
4031- val body = loop.body
4105+
40324106 if (body != null ) {
4033- extractExpressionStmt(body, callable, id, 1 )
4107+ extractExpressionStmt(body, callable, id, bodyIdx)
4108+ }
4109+
4110+ return id
4111+ }
4112+
4113+ private fun extractLoopWithCondition (
4114+ loop : IrLoop ,
4115+ stmtExprParent : StmtExprParent ,
4116+ callable : Label <out DbCallable >
4117+ ) {
4118+ val id = extractLoop(loop, loop.body, 1 , stmtExprParent, callable) { parent, idx ->
4119+ if (loop is IrWhileLoop ) {
4120+ val id = tw.getFreshIdLabel<DbWhilestmt >()
4121+ tw.writeStmts_whilestmt(id, parent, idx, callable)
4122+ id
4123+ } else {
4124+ val id = tw.getFreshIdLabel<DbDostmt >()
4125+ tw.writeStmts_dostmt(id, parent, idx, callable)
4126+ id
4127+ }
40344128 }
4129+ extractExpressionExpr(loop.condition, callable, id, 0 , id)
40354130 }
40364131
40374132 private fun IrValueParameter.isExtensionReceiver (): Boolean {
0 commit comments