Empty loops.
This commit is contained in:
committed by
Dmitry Petrov
parent
179a06672b
commit
d45811a5da
@@ -20,13 +20,14 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
|||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.psi.KtBlockExpression
|
import org.jetbrains.kotlin.psi.KtBlockExpression
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtLoopExpression
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class BodyGenerator(val scopeOwner: CallableDescriptor, override val context: GeneratorContext): GeneratorWithScope {
|
class BodyGenerator(val scopeOwner: CallableDescriptor, override val context: GeneratorContext): GeneratorWithScope {
|
||||||
override val scope = Scope(scopeOwner)
|
override val scope = Scope(scopeOwner)
|
||||||
private val loopTable = HashMap<KtExpression, IrLoop>()
|
private val loopTable = HashMap<KtLoopExpression, IrLoop>()
|
||||||
|
|
||||||
fun generateFunctionBody(ktBody: KtExpression): IrBody {
|
fun generateFunctionBody(ktBody: KtExpression): IrBody {
|
||||||
resetInternalContext()
|
resetInternalContext()
|
||||||
@@ -64,7 +65,7 @@ class BodyGenerator(val scopeOwner: CallableDescriptor, override val context: Ge
|
|||||||
private fun createStatementGenerator() =
|
private fun createStatementGenerator() =
|
||||||
StatementGenerator(context, scopeOwner, this, scope)
|
StatementGenerator(context, scopeOwner, this, scope)
|
||||||
|
|
||||||
fun putLoop(expression: KtExpression, irLoop: IrLoop) {
|
fun putLoop(expression: KtLoopExpression, irLoop: IrLoop) {
|
||||||
loopTable[expression] = irLoop
|
loopTable[expression] = irLoop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-3
@@ -44,7 +44,7 @@ class LoopExpressionGenerator(val statementGenerator: StatementGenerator) : Gene
|
|||||||
private fun generateConditionalLoop(ktLoop: KtWhileExpressionBase, irLoop: IrLoopBase): IrLoop {
|
private fun generateConditionalLoop(ktLoop: KtWhileExpressionBase, irLoop: IrLoopBase): IrLoop {
|
||||||
statementGenerator.bodyGenerator.putLoop(ktLoop, irLoop)
|
statementGenerator.bodyGenerator.putLoop(ktLoop, irLoop)
|
||||||
irLoop.condition = statementGenerator.generateExpression(ktLoop.condition!!)
|
irLoop.condition = statementGenerator.generateExpression(ktLoop.condition!!)
|
||||||
irLoop.body = statementGenerator.generateExpression(ktLoop.body!!)
|
irLoop.body = ktLoop.body?.let { statementGenerator.generateExpression(ktLoop.body!!) }
|
||||||
irLoop.label = getLoopLabel(ktLoop)
|
irLoop.label = getLoopLabel(ktLoop)
|
||||||
return irLoop
|
return irLoop
|
||||||
}
|
}
|
||||||
@@ -105,7 +105,7 @@ class LoopExpressionGenerator(val statementGenerator: StatementGenerator) : Gene
|
|||||||
}
|
}
|
||||||
|
|
||||||
val ktLoopRange = ktFor.loopRange!!
|
val ktLoopRange = ktFor.loopRange!!
|
||||||
val ktForBody = ktFor.body!!
|
val ktForBody = ktFor.body
|
||||||
val iteratorResolvedCall = getOrFail(BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL, ktLoopRange)
|
val iteratorResolvedCall = getOrFail(BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL, ktLoopRange)
|
||||||
val hasNextResolvedCall = getOrFail(BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, ktLoopRange)
|
val hasNextResolvedCall = getOrFail(BindingContext.LOOP_RANGE_HAS_NEXT_RESOLVED_CALL, ktLoopRange)
|
||||||
val nextResolvedCall = getOrFail(BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL, ktLoopRange)
|
val nextResolvedCall = getOrFail(BindingContext.LOOP_RANGE_NEXT_RESOLVED_CALL, ktLoopRange)
|
||||||
@@ -150,7 +150,9 @@ class LoopExpressionGenerator(val statementGenerator: StatementGenerator) : Gene
|
|||||||
statementGenerator.declareComponentVariablesInBlock(ktLoopDestructuringParameter, irInnerBody, VariableLValue(irLoopParameter))
|
statementGenerator.declareComponentVariablesInBlock(ktLoopDestructuringParameter, irInnerBody, VariableLValue(irLoopParameter))
|
||||||
}
|
}
|
||||||
|
|
||||||
irInnerBody.addStatement(statementGenerator.generateExpression(ktForBody))
|
if (ktForBody != null) {
|
||||||
|
irInnerBody.addStatement(statementGenerator.generateExpression(ktForBody))
|
||||||
|
}
|
||||||
|
|
||||||
return irForBlock
|
return irForBlock
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
|
|
||||||
interface IrLoop : IrExpression {
|
interface IrLoop : IrExpression {
|
||||||
val operator: IrOperator?
|
val operator: IrOperator?
|
||||||
var body: IrExpression
|
var body: IrExpression?
|
||||||
var condition: IrExpression
|
var condition: IrExpression
|
||||||
val label: String?
|
val label: String?
|
||||||
}
|
}
|
||||||
@@ -49,14 +49,12 @@ abstract class IrLoopBase(
|
|||||||
value.setTreeLocation(this, LOOP_CONDITION_SLOT)
|
value.setTreeLocation(this, LOOP_CONDITION_SLOT)
|
||||||
}
|
}
|
||||||
|
|
||||||
private var bodyImpl: IrExpression? = null
|
override var body: IrExpression? = null
|
||||||
override var body: IrExpression
|
|
||||||
get() = bodyImpl!!
|
|
||||||
set(value) {
|
set(value) {
|
||||||
value.assertDetached()
|
value?.assertDetached()
|
||||||
bodyImpl?.detach()
|
field?.detach()
|
||||||
bodyImpl = value
|
field = value
|
||||||
value.setTreeLocation(this, LOOP_BODY_SLOT)
|
value?.setTreeLocation(this, LOOP_BODY_SLOT)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getChild(slot: Int): IrElement? =
|
override fun getChild(slot: Int): IrElement? =
|
||||||
@@ -98,7 +96,7 @@ class IrWhileLoopImpl(
|
|||||||
|
|
||||||
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||||
condition.accept(visitor, data)
|
condition.accept(visitor, data)
|
||||||
body.accept(visitor, data)
|
body?.accept(visitor, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,7 +123,7 @@ class IrDoWhileLoopImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||||
body.accept(visitor, data)
|
body?.accept(visitor, data)
|
||||||
condition.accept(visitor, data)
|
condition.accept(visitor, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -66,13 +66,13 @@ class DumpIrTreeVisitor(out: Appendable): IrElementVisitor<Unit, String> {
|
|||||||
override fun visitWhileLoop(loop: IrWhileLoop, data: String) {
|
override fun visitWhileLoop(loop: IrWhileLoop, data: String) {
|
||||||
loop.dumpLabeledElementWith(data) {
|
loop.dumpLabeledElementWith(data) {
|
||||||
loop.condition.accept(this, "condition")
|
loop.condition.accept(this, "condition")
|
||||||
loop.body.accept(this, "body")
|
loop.body?.accept(this, "body")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitDoWhileLoop(loop: IrDoWhileLoop, data: String) {
|
override fun visitDoWhileLoop(loop: IrDoWhileLoop, data: String) {
|
||||||
loop.dumpLabeledElementWith(data) {
|
loop.dumpLabeledElementWith(data) {
|
||||||
loop.body.accept(this, "body")
|
loop.body?.accept(this, "body")
|
||||||
loop.condition.accept(this, "condition")
|
loop.condition.accept(this, "condition")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+4
@@ -1,3 +1,7 @@
|
|||||||
|
fun testEmpty(ss: List<String>) {
|
||||||
|
for (s in ss);
|
||||||
|
}
|
||||||
|
|
||||||
fun testIterable(ss: List<String>) {
|
fun testIterable(ss: List<String>) {
|
||||||
for (s in ss) {
|
for (s in ss) {
|
||||||
println(s)
|
println(s)
|
||||||
|
|||||||
Vendored
+13
@@ -1,4 +1,17 @@
|
|||||||
FILE /for.kt
|
FILE /for.kt
|
||||||
|
FUN public fun testEmpty(/*0*/ ss: kotlin.collections.List<kotlin.String>): kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
BLOCK type=kotlin.Unit operator=FOR_LOOP
|
||||||
|
VAR val tmp0_iterator: kotlin.collections.Iterator<kotlin.String>
|
||||||
|
CALL .iterator type=kotlin.collections.Iterator<kotlin.String> operator=FOR_LOOP_ITERATOR
|
||||||
|
$this: GET_VAR ss type=kotlin.collections.List<kotlin.String> operator=null
|
||||||
|
WHILE label=null operator=FOR_LOOP_INNER_WHILE
|
||||||
|
condition: CALL .hasNext type=kotlin.Boolean operator=FOR_LOOP_HAS_NEXT
|
||||||
|
$this: GET_VAR tmp0_iterator type=kotlin.collections.Iterator<kotlin.String> operator=null
|
||||||
|
body: BLOCK type=kotlin.Unit operator=FOR_LOOP_INNER_WHILE
|
||||||
|
VAR val s: kotlin.String
|
||||||
|
CALL .next type=kotlin.String operator=FOR_LOOP_NEXT
|
||||||
|
$this: GET_VAR tmp0_iterator type=kotlin.collections.Iterator<kotlin.String> operator=null
|
||||||
FUN public fun testIterable(/*0*/ ss: kotlin.collections.List<kotlin.String>): kotlin.Unit
|
FUN public fun testIterable(/*0*/ ss: kotlin.collections.List<kotlin.String>): kotlin.Unit
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
BLOCK type=kotlin.Unit operator=FOR_LOOP
|
BLOCK type=kotlin.Unit operator=FOR_LOOP
|
||||||
|
|||||||
+2
@@ -1,7 +1,9 @@
|
|||||||
fun test() {
|
fun test() {
|
||||||
var x = 0
|
var x = 0
|
||||||
|
while (x < 0);
|
||||||
while (x < 5) x++
|
while (x < 5) x++
|
||||||
while (x < 10) { x++ }
|
while (x < 10) { x++ }
|
||||||
|
do while (x < 0)
|
||||||
do x++ while (x < 15)
|
do x++ while (x < 15)
|
||||||
do { x ++ } while (x < 20)
|
do { x ++ } while (x < 20)
|
||||||
}
|
}
|
||||||
|
|||||||
+10
@@ -3,6 +3,11 @@ FILE /whileDoWhile.kt
|
|||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
VAR var x: kotlin.Int
|
VAR var x: kotlin.Int
|
||||||
CONST Int type=kotlin.Int value='0'
|
CONST Int type=kotlin.Int value='0'
|
||||||
|
WHILE label=null operator=WHILE_LOOP
|
||||||
|
condition: CALL .LT0 type=kotlin.Boolean operator=LT
|
||||||
|
arg0: CALL .compareTo type=kotlin.Int operator=LT
|
||||||
|
$this: GET_VAR x type=kotlin.Int operator=null
|
||||||
|
other: CONST Int type=kotlin.Int value='0'
|
||||||
WHILE label=null operator=WHILE_LOOP
|
WHILE label=null operator=WHILE_LOOP
|
||||||
condition: CALL .LT0 type=kotlin.Boolean operator=LT
|
condition: CALL .LT0 type=kotlin.Boolean operator=LT
|
||||||
arg0: CALL .compareTo type=kotlin.Int operator=LT
|
arg0: CALL .compareTo type=kotlin.Int operator=LT
|
||||||
@@ -28,6 +33,11 @@ FILE /whileDoWhile.kt
|
|||||||
CALL .inc type=kotlin.Int operator=POSTFIX_INCR
|
CALL .inc type=kotlin.Int operator=POSTFIX_INCR
|
||||||
$this: GET_VAR tmp1 type=kotlin.Int operator=null
|
$this: GET_VAR tmp1 type=kotlin.Int operator=null
|
||||||
GET_VAR tmp1 type=kotlin.Int operator=null
|
GET_VAR tmp1 type=kotlin.Int operator=null
|
||||||
|
DO_WHILE label=null operator=DO_WHILE_LOOP
|
||||||
|
condition: CALL .LT0 type=kotlin.Boolean operator=LT
|
||||||
|
arg0: CALL .compareTo type=kotlin.Int operator=LT
|
||||||
|
$this: GET_VAR x type=kotlin.Int operator=null
|
||||||
|
other: CONST Int type=kotlin.Int value='0'
|
||||||
DO_WHILE label=null operator=DO_WHILE_LOOP
|
DO_WHILE label=null operator=DO_WHILE_LOOP
|
||||||
body: BLOCK type=kotlin.Int operator=POSTFIX_INCR
|
body: BLOCK type=kotlin.Int operator=POSTFIX_INCR
|
||||||
VAR val tmp2: kotlin.Int
|
VAR val tmp2: kotlin.Int
|
||||||
|
|||||||
Reference in New Issue
Block a user