'while' and 'do-while' loop generator fixes.

Generate 'do-while' loop body as IrComposite, because variables declared
in loop body should be visible in loop condition.
Wrap 'do-while' loop in IrBlock so that variables declared in loop body
are not visible outside of the loop.

Generate 'while' and 'do-while' loops as expressions of type Unit.
This commit is contained in:
Dmitry Petrov
2017-03-06 19:02:52 +03:00
parent cb61c358ea
commit d096f1d381
6 changed files with 105 additions and 70 deletions
@@ -72,7 +72,7 @@ class FunctionGenerator(val function: IrFunction) {
return body.process()
}
override fun visitBlock(expression: IrBlock, data: Boolean): IrStatement? {
override fun visitContainerExpression(expression: IrContainerExpression, data: Boolean): IrStatement? {
return expression.process() ?: expression
}
@@ -39,14 +39,43 @@ class LoopExpressionGenerator(statementGenerator: StatementGenerator) : Statemen
IrDoWhileLoopImpl(ktDoWhile.startOffset, ktDoWhile.endOffset,
context.builtIns.unitType, IrStatementOrigin.DO_WHILE_LOOP))
private fun generateConditionalLoop(ktLoop: KtWhileExpressionBase, irLoop: IrLoopBase): IrLoop {
private fun generateConditionalLoop(ktLoop: KtWhileExpressionBase, irLoop: IrLoopBase): IrExpression {
irLoop.condition = statementGenerator.generateExpression(ktLoop.condition!!)
statementGenerator.bodyGenerator.putLoop(ktLoop, irLoop)
irLoop.body = ktLoop.body?.let { statementGenerator.generateExpression(ktLoop.body!!) }
irLoop.body = ktLoop.body?.let { ktLoopBody ->
if (ktLoopBody is KtBlockExpression) {
if (ktLoop is KtDoWhileExpression)
generateDoWhileLoopBody(ktLoopBody)
else
generateWhileLoopBody(ktLoopBody)
}
else
statementGenerator.generateExpression(ktLoopBody)
}
irLoop.label = getLoopLabel(ktLoop)
return irLoop
return if (ktLoop is KtDoWhileExpression) {
IrBlockImpl(ktLoop.startOffset, ktLoop.endOffset, context.builtIns.unitType).apply {
statements.add(irLoop)
}
}
else
irLoop
}
private fun generateWhileLoopBody(ktLoopBody: KtBlockExpression): IrExpression =
IrBlockImpl(
ktLoopBody.startOffset, ktLoopBody.endOffset, context.builtIns.unitType, null,
ktLoopBody.statements.map { statementGenerator.generateStatement(it) }
)
private fun generateDoWhileLoopBody(ktLoopBody: KtBlockExpression): IrExpression =
IrCompositeImpl(
ktLoopBody.startOffset, ktLoopBody.endOffset, context.builtIns.unitType, null,
ktLoopBody.statements.map { statementGenerator.generateStatement(it) }
)
fun generateBreak(ktBreak: KtBreakExpression): IrExpression {
val parentLoop = findParentLoop(ktBreak) ?:
return ErrorExpressionGenerator(statementGenerator).generateErrorExpression(