Skip to content

Commit 803a97d

Browse files
committed
Kotlin: Resugar for loops with tuples as loop variables
1 parent 841340b commit 803a97d

File tree

5 files changed

+72
-66
lines changed

5 files changed

+72
-66
lines changed

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

Lines changed: 42 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3224,12 +3224,11 @@ open class KotlinFileExtractor(
32243224
(cond.dispatchReceiver as? IrGetValue)?.symbol?.owner != iteratorVariable ||
32253225
body == null ||
32263226
body.origin != IrStatementOrigin.FOR_LOOP_INNER_WHILE ||
3227-
body.statements.size != 2) {
3227+
body.statements.size < 2) {
32283228
return false
32293229
}
32303230

32313231
val loopVar = body.statements[0] as? IrVariable
3232-
val block = body.statements[1] as? IrBlock
32333232
val nextCall = loopVar?.initializer as? IrCall
32343233

32353234
if (loopVar == null ||
@@ -3240,14 +3239,22 @@ open class KotlinFileExtractor(
32403239
return false
32413240
}
32423241

3243-
val id = extractLoop(innerWhile, block, 2, parent, callable) { p, idx ->
3242+
val id = extractLoop(innerWhile, null, parent, callable) { p, idx ->
32443243
val loopId = tw.getFreshIdLabel<DbEnhancedforstmt>()
32453244
tw.writeStmts_enhancedforstmt(loopId, p, idx, callable)
32463245
loopId
32473246
}
32483247

3249-
extractExpressionExpr(expr, callable, id, 1, id)
32503248
extractVariableExpr(loopVar, callable, id, 0, id, extractInitializer = false)
3249+
extractExpressionExpr(expr, callable, id, 1, id)
3250+
val block = body.statements[1] as? IrBlock
3251+
if (body.statements.size == 2 && block != null) {
3252+
// Extract the body that was given to us by the compiler
3253+
extractExpressionStmt(block, callable, id, 2)
3254+
} else {
3255+
// Extract a block with all but the first (loop variable declaration) statement
3256+
extractBlock(body, body.statements.takeLast(body.statements.size - 1), id, 2, callable)
3257+
}
32513258

32523259
return true
32533260
}
@@ -3487,14 +3494,7 @@ open class KotlinFileExtractor(
34873494
if (!tryExtractArrayUpdate(e, callable, parent) &&
34883495
!tryExtractForLoop(e, callable, parent)) {
34893496

3490-
val stmtParent = parent.stmt(e, callable)
3491-
val id = tw.getFreshIdLabel<DbBlock>()
3492-
val locId = tw.getLocation(e)
3493-
tw.writeStmts_block(id, stmtParent.parent, stmtParent.idx, callable)
3494-
tw.writeHasLocation(id, locId)
3495-
e.statements.forEachIndexed { i, s ->
3496-
extractStatement(s, callable, id, i)
3497-
}
3497+
extractBlock(e, e.statements, parent, callable)
34983498
}
34993499
}
35003500
is IrWhileLoop -> {
@@ -3966,6 +3966,32 @@ open class KotlinFileExtractor(
39663966
}
39673967
}
39683968

3969+
private fun extractBlock(
3970+
e: IrContainerExpression,
3971+
statements: List<IrStatement>,
3972+
parent: StmtExprParent,
3973+
callable: Label<out DbCallable>
3974+
) {
3975+
val stmtParent = parent.stmt(e, callable)
3976+
extractBlock(e, statements, stmtParent.parent, stmtParent.idx, callable)
3977+
}
3978+
3979+
private fun extractBlock(
3980+
e: IrElement,
3981+
statements: List<IrStatement>,
3982+
parent: Label<out DbStmtparent>,
3983+
idx: Int,
3984+
callable: Label<out DbCallable>
3985+
) {
3986+
val id = tw.getFreshIdLabel<DbBlock>()
3987+
val locId = tw.getLocation(e)
3988+
tw.writeStmts_block(id, parent, idx, callable)
3989+
tw.writeHasLocation(id, locId)
3990+
statements.forEachIndexed { i, s ->
3991+
extractStatement(s, callable, id, i)
3992+
}
3993+
}
3994+
39693995
private inline fun <D: DeclarationDescriptor, reified B: IrSymbolOwner> getBoundSymbolOwner(symbol: IrBindableSymbol<D, B>, e: IrExpression): B? {
39703996
if (symbol.isBound) {
39713997
return symbol.owner
@@ -4074,8 +4100,7 @@ open class KotlinFileExtractor(
40744100

40754101
private fun extractLoop(
40764102
loop: IrLoop,
4077-
body: IrExpression?,
4078-
bodyIdx: Int,
4103+
bodyIdx: Int?,
40794104
stmtExprParent: StmtExprParent,
40804105
callable: Label<out DbCallable>,
40814106
getId: (Label<out DbStmtparent>, Int) -> Label<out DbStmt>
@@ -4103,7 +4128,8 @@ open class KotlinFileExtractor(
41034128
val id = getId(parent, idx)
41044129
tw.writeHasLocation(id, locId)
41054130

4106-
if (body != null) {
4131+
val body = loop.body
4132+
if (body != null && bodyIdx != null) {
41074133
extractExpressionStmt(body, callable, id, bodyIdx)
41084134
}
41094135

@@ -4115,7 +4141,7 @@ open class KotlinFileExtractor(
41154141
stmtExprParent: StmtExprParent,
41164142
callable: Label<out DbCallable>
41174143
) {
4118-
val id = extractLoop(loop, loop.body, 1, stmtExprParent, callable) { parent, idx ->
4144+
val id = extractLoop(loop, 1, stmtExprParent, callable) { parent, idx ->
41194145
if (loop is IrWhileLoop) {
41204146
val id = tw.getFreshIdLabel<DbWhilestmt>()
41214147
tw.writeStmts_whilestmt(id, parent, idx, callable)

java/ql/test/kotlin/library-tests/stmts/PrintAst.expected

Lines changed: 26 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -151,40 +151,32 @@ stmts.kt:
151151
# 37| 0: [VarAccess] x
152152
# 37| 1: [VarAccess] y
153153
# 37| 1: [BreakStmt] break
154-
# 41| 4: [BlockStmt] { ... }
155-
# 41| 0: [LocalVariableDeclStmt] var ...;
156-
# 41| 1: [LocalVariableDeclExpr] tmp2_iterator
157-
# 41| 0: [MethodAccess] iterator(...)
158-
# 41| -1: [MethodAccess] withIndex(...)
159-
# 41| -2: [TypeAccess] Integer
160-
# 41| -1: [TypeAccess] CollectionsKt
161-
# 41| 0: [MethodAccess] rangeTo(...)
162-
# 41| -1: [VarAccess] x
163-
# 41| 0: [VarAccess] y
164-
# 41| 1: [WhileStmt] while (...)
165-
# 41| 0: [MethodAccess] hasNext(...)
166-
# 41| -1: [VarAccess] tmp2_iterator
167-
# 41| 1: [BlockStmt] { ... }
168-
# 41| 0: [LocalVariableDeclStmt] var ...;
169-
# 41| 1: [LocalVariableDeclExpr] tmp3_loop_parameter
170-
# 41| 0: [MethodAccess] next(...)
171-
# 41| -1: [VarAccess] tmp2_iterator
172-
# 41| 1: [LocalVariableDeclStmt] var ...;
173-
# 41| 1: [LocalVariableDeclExpr] v
174-
# 41| 0: [MethodAccess] component1(...)
175-
# 41| -1: [VarAccess] tmp3_loop_parameter
176-
# 41| 2: [LocalVariableDeclStmt] var ...;
177-
# 41| 1: [LocalVariableDeclExpr] i
178-
# 41| 0: [MethodAccess] component2(...)
179-
# 41| -1: [VarAccess] tmp3_loop_parameter
180-
# 41| 3: [BlockStmt] { ... }
181-
# 42| 0: [ExprStmt] <Expr>;
182-
# 42| 0: [WhenExpr] when ...
183-
# 42| 0: [WhenBranch] ... -> ...
184-
# 42| 0: [GTExpr] ... > ...
185-
# 42| 0: [VarAccess] x
186-
# 42| 1: [VarAccess] y
187-
# 42| 1: [BreakStmt] break
154+
# 41| 4: [EnhancedForStmt] for (... : ...)
155+
#-----| 0: (Single Local Variable Declaration)
156+
# 41| 1: [LocalVariableDeclExpr] tmp3_loop_parameter
157+
# 41| 1: [MethodAccess] withIndex(...)
158+
# 41| -2: [TypeAccess] Integer
159+
# 41| -1: [TypeAccess] CollectionsKt
160+
# 41| 0: [MethodAccess] rangeTo(...)
161+
# 41| -1: [VarAccess] x
162+
# 41| 0: [VarAccess] y
163+
# 41| 2: [BlockStmt] { ... }
164+
# 41| 0: [LocalVariableDeclStmt] var ...;
165+
# 41| 1: [LocalVariableDeclExpr] v
166+
# 41| 0: [MethodAccess] component1(...)
167+
# 41| -1: [VarAccess] tmp3_loop_parameter
168+
# 41| 1: [LocalVariableDeclStmt] var ...;
169+
# 41| 1: [LocalVariableDeclExpr] i
170+
# 41| 0: [MethodAccess] component2(...)
171+
# 41| -1: [VarAccess] tmp3_loop_parameter
172+
# 41| 2: [BlockStmt] { ... }
173+
# 42| 0: [ExprStmt] <Expr>;
174+
# 42| 0: [WhenExpr] when ...
175+
# 42| 0: [WhenBranch] ... -> ...
176+
# 42| 0: [GTExpr] ... > ...
177+
# 42| 0: [VarAccess] x
178+
# 42| 1: [VarAccess] y
179+
# 42| 1: [BreakStmt] break
188180
# 46| 3: [Method] exceptions
189181
# 46| 3: [TypeAccess] int
190182
# 46| 5: [BlockStmt] { ... }

java/ql/test/kotlin/library-tests/stmts/exprs.expected

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,12 +85,6 @@
8585
| stmts.kt:41:11:41:11 | v | LocalVariableDeclExpr |
8686
| stmts.kt:41:13:41:13 | component2(...) | MethodAccess |
8787
| stmts.kt:41:13:41:13 | i | LocalVariableDeclExpr |
88-
| stmts.kt:41:19:41:36 | hasNext(...) | MethodAccess |
89-
| stmts.kt:41:19:41:36 | iterator(...) | MethodAccess |
90-
| stmts.kt:41:19:41:36 | next(...) | MethodAccess |
91-
| stmts.kt:41:19:41:36 | tmp2_iterator | LocalVariableDeclExpr |
92-
| stmts.kt:41:19:41:36 | tmp2_iterator | VarAccess |
93-
| stmts.kt:41:19:41:36 | tmp2_iterator | VarAccess |
9488
| stmts.kt:41:19:41:36 | tmp3_loop_parameter | LocalVariableDeclExpr |
9589
| stmts.kt:41:19:41:36 | tmp3_loop_parameter | VarAccess |
9690
| stmts.kt:41:19:41:36 | tmp3_loop_parameter | VarAccess |

java/ql/test/kotlin/library-tests/stmts/loops.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ jumpTarget
77
| stmts.kt:29:9:29:16 | continue | stmts.kt:28:5:29:16 | while (...) |
88
| stmts.kt:32:20:32:24 | break | stmts.kt:31:5:33:5 | for (... : ...) |
99
| stmts.kt:37:24:37:36 | break | stmts.kt:35:13:39:5 | for (... : ...) |
10-
| stmts.kt:42:20:42:24 | break | stmts.kt:41:5:43:5 | while (...) |
10+
| stmts.kt:42:20:42:24 | break | stmts.kt:41:5:43:5 | for (... : ...) |

java/ql/test/kotlin/library-tests/stmts/stmts.expected

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,10 @@ enclosing
5454
| stmts.kt:37:13:37:36 | ... -> ... | stmts.kt:37:13:37:36 | <Expr>; |
5555
| stmts.kt:37:13:37:36 | <Expr>; | stmts.kt:36:13:38:9 | { ... } |
5656
| stmts.kt:37:24:37:36 | break | stmts.kt:37:13:37:36 | ... -> ... |
57-
| stmts.kt:41:5:43:5 | while (...) | stmts.kt:41:5:43:5 | { ... } |
58-
| stmts.kt:41:5:43:5 | { ... } | stmts.kt:22:27:44:1 | { ... } |
59-
| stmts.kt:41:5:43:5 | { ... } | stmts.kt:41:5:43:5 | while (...) |
57+
| stmts.kt:41:5:43:5 | for (... : ...) | stmts.kt:22:27:44:1 | { ... } |
58+
| stmts.kt:41:5:43:5 | { ... } | stmts.kt:41:5:43:5 | for (... : ...) |
6059
| stmts.kt:41:11:41:11 | var ...; | stmts.kt:41:5:43:5 | { ... } |
6160
| stmts.kt:41:13:41:13 | var ...; | stmts.kt:41:5:43:5 | { ... } |
62-
| stmts.kt:41:19:41:36 | var ...; | stmts.kt:41:5:43:5 | { ... } |
63-
| stmts.kt:41:19:41:36 | var ...; | stmts.kt:41:5:43:5 | { ... } |
6461
| stmts.kt:41:39:43:5 | { ... } | stmts.kt:41:5:43:5 | { ... } |
6562
| stmts.kt:42:9:42:24 | ... -> ... | stmts.kt:42:9:42:24 | <Expr>; |
6663
| stmts.kt:42:9:42:24 | <Expr>; | stmts.kt:41:39:43:5 | { ... } |
@@ -131,13 +128,10 @@ enclosing
131128
| stmts.kt:37:13:37:36 | ... -> ... | WhenBranch |
132129
| stmts.kt:37:13:37:36 | <Expr>; | ExprStmt |
133130
| stmts.kt:37:24:37:36 | break | BreakStmt |
134-
| stmts.kt:41:5:43:5 | while (...) | WhileStmt |
135-
| stmts.kt:41:5:43:5 | { ... } | BlockStmt |
131+
| stmts.kt:41:5:43:5 | for (... : ...) | EnhancedForStmt |
136132
| stmts.kt:41:5:43:5 | { ... } | BlockStmt |
137133
| stmts.kt:41:11:41:11 | var ...; | LocalVariableDeclStmt |
138134
| stmts.kt:41:13:41:13 | var ...; | LocalVariableDeclStmt |
139-
| stmts.kt:41:19:41:36 | var ...; | LocalVariableDeclStmt |
140-
| stmts.kt:41:19:41:36 | var ...; | LocalVariableDeclStmt |
141135
| stmts.kt:41:39:43:5 | { ... } | BlockStmt |
142136
| stmts.kt:42:9:42:24 | ... -> ... | WhenBranch |
143137
| stmts.kt:42:9:42:24 | <Expr>; | ExprStmt |

0 commit comments

Comments
 (0)