Empty loops.

This commit is contained in:
Dmitry Petrov
2016-08-25 14:48:46 +03:00
committed by Dmitry Petrov
parent 179a06672b
commit d45811a5da
8 changed files with 47 additions and 17 deletions
@@ -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
} }
@@ -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")
} }
} }
+4
View File
@@ -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)
+13
View File
@@ -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
View File
@@ -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
View File
@@ -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