Preliminary work on loops.

This commit is contained in:
Dmitry Petrov
2016-08-19 16:09:00 +03:00
committed by Dmitry Petrov
parent de5181d642
commit 8500f5ddb2
7 changed files with 190 additions and 9 deletions
@@ -22,11 +22,7 @@ import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.psi2ir.toExpectedType
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.singletonList
class DeclarationGenerator(override val context: GeneratorContext) : IrGenerator {
fun generateAnnotationEntries(annotationEntries: List<KtAnnotationEntry>) {
@@ -140,9 +136,7 @@ class DeclarationGenerator(override val context: GeneratorContext) : IrGenerator
}
private fun generateExpressionWithinContext(ktExpression: KtExpression, scopeOwner: DeclarationDescriptor): IrExpression =
StatementGenerator(context, scopeOwner, TemporaryVariableFactory(scopeOwner))
.generateExpression(ktExpression)
.toExpectedType(getExpectedTypeForLastInferredCall(ktExpression))
FunctionBodyGenerator(context).generateFunctionBody(scopeOwner, ktExpression)
private fun generateFunctionBody(scopeOwner: CallableDescriptor, ktBody: KtExpression): IrBody {
val irRhs = generateExpressionWithinContext(ktBody, scopeOwner)
@@ -0,0 +1,40 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi2ir.toExpectedType
class FunctionBodyGenerator(override val context: GeneratorContext): IrGenerator {
fun generateFunctionBody(scopeOwner: DeclarationDescriptor, ktExpression: KtExpression): IrExpression {
resetInternalContext()
val irExpression = StatementGenerator(context, scopeOwner, this)
.generateExpression(ktExpression)
.toExpectedType(getExpectedTypeForLastInferredCall(ktExpression))
postprocessFunctionBody()
return irExpression
}
private fun resetInternalContext() {
}
private fun postprocessFunctionBody() {
}
}
@@ -44,8 +44,9 @@ import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
class StatementGenerator(
override val context: GeneratorContext,
val scopeOwner: DeclarationDescriptor,
val temporaryVariableFactory: TemporaryVariableFactory
val functionBodyGenerator: FunctionBodyGenerator
) : KtVisitor<IrStatement, Nothing?>(), IrGenerator {
val temporaryVariableFactory: TemporaryVariableFactory = TemporaryVariableFactory(scopeOwner)
fun generateExpression(ktExpression: KtExpression): IrExpression =
ktExpression.genExpr()
@@ -292,4 +293,6 @@ class StatementGenerator(
override fun visitWhenExpression(expression: KtWhenExpression, data: Nothing?): IrStatement =
WhenExpressionGenerator(this).generate(expression)
}
@@ -27,4 +27,6 @@ const val MODULE_SLOT = 0
const val INITIALIZER_SLOT = 0
const val WHEN_SUBJECT_VARIABLE_SLOT = -1
const val WHEN_ELSE_EXPRESSION_SLOT = -2
const val BRANCH_RESULT_SLOT = -1
const val BRANCH_RESULT_SLOT = -1
const val LOOP_BODY_SLOT = -1
const val LOOP_CONDITION_SLOT = -2
@@ -0,0 +1,137 @@
/*
* Copyright 2010-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.ir.expressions
import org.jetbrains.kotlin.ir.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
interface IrLoopExpression : IrExpression {
var body: IrExpression
}
interface IrConditionalLoopExpression : IrLoopExpression {
var condition: IrExpression
}
interface IrWhileLoopExpression : IrConditionalLoopExpression
interface IrDoWhileLoopExpression : IrConditionalLoopExpression
abstract class IrLoopExpressionBase(
startOffset: Int,
endOffset: Int
) : IrExpressionBase(startOffset, endOffset, null), IrLoopExpression {
private var bodyImpl: IrExpression? = null
override var body: IrExpression
get() = bodyImpl!!
set(value) {
value.assertDetached()
bodyImpl?.detach()
bodyImpl = value
value.setTreeLocation(this, LOOP_BODY_SLOT)
}
override fun getChild(slot: Int): IrElement? =
when (slot) {
LOOP_BODY_SLOT -> body
else -> null
}
override fun replaceChild(slot: Int, newChild: IrElement) {
when (slot) {
LOOP_BODY_SLOT -> body = newChild.assertCast()
}
}
}
abstract class IrConditionalLoopExpressionBase(
startOffset: Int,
endOffset: Int
) : IrLoopExpressionBase(startOffset, endOffset), IrConditionalLoopExpression {
private var conditionImpl: IrExpression? = null
override var condition: IrExpression
get() = conditionImpl!!
set(value) {
value.assertDetached()
conditionImpl?.detach()
conditionImpl = value
value.setTreeLocation(this, LOOP_CONDITION_SLOT)
}
override fun getChild(slot: Int): IrElement? =
when (slot) {
LOOP_CONDITION_SLOT -> condition
else -> super.getChild(slot)
}
override fun replaceChild(slot: Int, newChild: IrElement) {
when (slot) {
LOOP_CONDITION_SLOT -> condition = newChild.assertCast()
else -> super.replaceChild(slot, newChild)
}
}
}
class IrWhileLoopExpressionImpl(
startOffset: Int,
endOffset: Int
) : IrConditionalLoopExpressionBase(startOffset, endOffset), IrWhileLoopExpression {
constructor(
startOffset: Int,
endOffset: Int,
condition: IrExpression,
body: IrExpression
) : this(startOffset, endOffset) {
this.condition = condition
this.body = body
}
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
return visitor.visitWhileLoop(this, data)
}
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
condition.accept(visitor, data)
body.accept(visitor, data)
}
}
class IrDoWhileLoopExpressionImpl(
startOffset: Int,
endOffset: Int
) : IrConditionalLoopExpressionBase(startOffset, endOffset), IrDoWhileLoopExpression {
constructor(
startOffset: Int,
endOffset: Int,
body: IrExpression,
condition: IrExpression
) : this(startOffset, endOffset) {
this.condition = condition
this.body = body
}
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
return visitor.visitDoWhileLoop(this, data)
}
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
body.accept(visitor, data)
condition.accept(visitor, data)
}
}
@@ -66,7 +66,12 @@ interface IrElementVisitor<out R, in D> {
fun visitWhenExpression(expression: IrWhenExpression, data: D) = visitExpression(expression, data)
fun visitBranch(branch: IrBranch, data: D): R = visitElement(branch, data)
fun visitLoop(loop: IrLoopExpression, data: D) = visitExpression(loop, data)
fun visitWhileLoop(loop: IrWhileLoopExpression, data: D) = visitLoop(loop, data)
fun visitDoWhileLoop(loop: IrDoWhileLoopExpression, data: D) = visitLoop(loop, data)
// NB Use it only for testing purposes; will be removed as soon as all Kotlin expression types are covered
fun visitDummyDeclaration(declaration: IrDummyDeclaration, data: D) = visitDeclaration(declaration, data)
fun visitDummyExpression(expression: IrDummyExpression, data: D) = visitExpression(expression, data)
}