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.psi.KtBlockExpression
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.startOffset
import java.util.*
class BodyGenerator(val scopeOwner: CallableDescriptor, override val context: GeneratorContext): GeneratorWithScope {
override val scope = Scope(scopeOwner)
private val loopTable = HashMap<KtExpression, IrLoop>()
private val loopTable = HashMap<KtLoopExpression, IrLoop>()
fun generateFunctionBody(ktBody: KtExpression): IrBody {
resetInternalContext()
@@ -64,7 +65,7 @@ class BodyGenerator(val scopeOwner: CallableDescriptor, override val context: Ge
private fun createStatementGenerator() =
StatementGenerator(context, scopeOwner, this, scope)
fun putLoop(expression: KtExpression, irLoop: IrLoop) {
fun putLoop(expression: KtLoopExpression, irLoop: IrLoop) {
loopTable[expression] = irLoop
}
@@ -44,7 +44,7 @@ class LoopExpressionGenerator(val statementGenerator: StatementGenerator) : Gene
private fun generateConditionalLoop(ktLoop: KtWhileExpressionBase, irLoop: IrLoopBase): IrLoop {
statementGenerator.bodyGenerator.putLoop(ktLoop, irLoop)
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)
return irLoop
}
@@ -105,7 +105,7 @@ class LoopExpressionGenerator(val statementGenerator: StatementGenerator) : Gene
}
val ktLoopRange = ktFor.loopRange!!
val ktForBody = ktFor.body!!
val ktForBody = ktFor.body
val iteratorResolvedCall = getOrFail(BindingContext.LOOP_RANGE_ITERATOR_RESOLVED_CALL, ktLoopRange)
val hasNextResolvedCall = getOrFail(BindingContext.LOOP_RANGE_HAS_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))
}
irInnerBody.addStatement(statementGenerator.generateExpression(ktForBody))
if (ktForBody != null) {
irInnerBody.addStatement(statementGenerator.generateExpression(ktForBody))
}
return irForBlock
}
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.types.KotlinType
interface IrLoop : IrExpression {
val operator: IrOperator?
var body: IrExpression
var body: IrExpression?
var condition: IrExpression
val label: String?
}
@@ -49,14 +49,12 @@ abstract class IrLoopBase(
value.setTreeLocation(this, LOOP_CONDITION_SLOT)
}
private var bodyImpl: IrExpression? = null
override var body: IrExpression
get() = bodyImpl!!
override var body: IrExpression? = null
set(value) {
value.assertDetached()
bodyImpl?.detach()
bodyImpl = value
value.setTreeLocation(this, LOOP_BODY_SLOT)
value?.assertDetached()
field?.detach()
field = value
value?.setTreeLocation(this, LOOP_BODY_SLOT)
}
override fun getChild(slot: Int): IrElement? =
@@ -98,7 +96,7 @@ class IrWhileLoopImpl(
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
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) {
body.accept(visitor, data)
body?.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) {
loop.dumpLabeledElementWith(data) {
loop.condition.accept(this, "condition")
loop.body.accept(this, "body")
loop.body?.accept(this, "body")
}
}
override fun visitDoWhileLoop(loop: IrDoWhileLoop, data: String) {
loop.dumpLabeledElementWith(data) {
loop.body.accept(this, "body")
loop.body?.accept(this, "body")
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>) {
for (s in ss) {
println(s)
+13
View File
@@ -1,4 +1,17 @@
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
BLOCK_BODY
BLOCK type=kotlin.Unit operator=FOR_LOOP
+2
View File
@@ -1,7 +1,9 @@
fun test() {
var x = 0
while (x < 0);
while (x < 5) x++
while (x < 10) { x++ }
do while (x < 0)
do x++ while (x < 15)
do { x ++ } while (x < 20)
}
+10
View File
@@ -3,6 +3,11 @@ FILE /whileDoWhile.kt
BLOCK_BODY
VAR var x: kotlin.Int
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
condition: CALL .LT0 type=kotlin.Boolean 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
$this: 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
body: BLOCK type=kotlin.Int operator=POSTFIX_INCR
VAR val tmp2: kotlin.Int