When expression.
Fix object & enum references.
This commit is contained in:
committed by
Dmitry Petrov
parent
d6040d8570
commit
b96626fd4c
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.psi2ir.generators
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
@@ -50,6 +51,10 @@ class CallGenerator(val statementGenerator: StatementGenerator) : IrGenerator {
|
||||
return null
|
||||
}
|
||||
|
||||
return createTemporary(ktExpression, irExpression, nameHint)
|
||||
}
|
||||
|
||||
fun createTemporary(ktExpression: KtExpression, irExpression: IrExpression, nameHint: String?): IrVariable {
|
||||
val irTmpVar = temporaryVariableFactory.createTemporaryVariable(irExpression, nameHint)
|
||||
putValue(ktExpression, VariableLValue(irTmpVar))
|
||||
return irTmpVar
|
||||
@@ -75,12 +80,16 @@ class CallGenerator(val statementGenerator: StatementGenerator) : IrGenerator {
|
||||
receiverValues[receiver] = irValue
|
||||
}
|
||||
|
||||
fun putValue(valueArgument: ValueParameterDescriptor, irValue: IrValue) {
|
||||
valueArgumentValues[valueArgument] = irValue
|
||||
fun putValue(parameter: ValueParameterDescriptor, irValue: IrValue) {
|
||||
valueArgumentValues[parameter] = irValue
|
||||
}
|
||||
|
||||
fun valueOf(ktExpression: KtExpression) = expressionValues[ktExpression]?.load()
|
||||
fun valueOf(receiver: ReceiverValue) = receiverValues[receiver]?.load()
|
||||
fun valueOf(parameter: ValueParameterDescriptor) = valueArgumentValues[parameter]?.load()
|
||||
|
||||
fun generateCall(
|
||||
ktExpression: KtExpression,
|
||||
ktElement: KtElement,
|
||||
resolvedCall: ResolvedCall<out CallableDescriptor>,
|
||||
operator: IrOperator? = null,
|
||||
superQualifier: ClassDescriptor? = null
|
||||
@@ -91,15 +100,15 @@ class CallGenerator(val statementGenerator: StatementGenerator) : IrGenerator {
|
||||
return when (descriptor) {
|
||||
is PropertyDescriptor ->
|
||||
IrGetPropertyExpressionImpl(
|
||||
ktExpression.startOffset, ktExpression.endOffset,
|
||||
ktElement.startOffset, ktElement.endOffset,
|
||||
returnType,
|
||||
resolvedCall.call.isSafeCall(), descriptor
|
||||
).apply {
|
||||
dispatchReceiver = generateReceiver(ktExpression, resolvedCall.dispatchReceiver, descriptor.dispatchReceiverParameter)
|
||||
extensionReceiver = generateReceiver(ktExpression, resolvedCall.extensionReceiver, descriptor.extensionReceiverParameter)
|
||||
dispatchReceiver = generateReceiver(ktElement, resolvedCall.dispatchReceiver, descriptor.dispatchReceiverParameter)
|
||||
extensionReceiver = generateReceiver(ktElement, resolvedCall.extensionReceiver, descriptor.extensionReceiverParameter)
|
||||
}
|
||||
is FunctionDescriptor ->
|
||||
generateFunctionCall(descriptor, ktExpression, returnType, operator, resolvedCall, superQualifier)
|
||||
generateFunctionCall(descriptor, ktElement, returnType, operator, resolvedCall, superQualifier)
|
||||
else ->
|
||||
TODO("Unexpected callable descriptor: $descriptor ${descriptor.javaClass.simpleName}")
|
||||
}
|
||||
@@ -121,21 +130,21 @@ class CallGenerator(val statementGenerator: StatementGenerator) : IrGenerator {
|
||||
|
||||
private fun generateFunctionCall(
|
||||
descriptor: FunctionDescriptor,
|
||||
ktExpression: KtExpression,
|
||||
ktElement: KtElement,
|
||||
resultType: KotlinType?,
|
||||
operator: IrOperator?,
|
||||
resolvedCall: ResolvedCall<out CallableDescriptor>,
|
||||
superQualifier: ClassDescriptor?
|
||||
): IrExpression {
|
||||
val irCall = IrCallExpressionImpl(
|
||||
ktExpression.startOffset, ktExpression.endOffset, resultType,
|
||||
ktElement.startOffset, ktElement.endOffset, resultType,
|
||||
descriptor, resolvedCall.call.isSafeCall(), operator, superQualifier
|
||||
)
|
||||
irCall.dispatchReceiver = generateReceiver(ktExpression, resolvedCall.dispatchReceiver, descriptor.dispatchReceiverParameter)
|
||||
irCall.extensionReceiver = generateReceiver(ktExpression, resolvedCall.extensionReceiver, descriptor.extensionReceiverParameter)
|
||||
irCall.dispatchReceiver = generateReceiver(ktElement, resolvedCall.dispatchReceiver, descriptor.dispatchReceiverParameter)
|
||||
irCall.extensionReceiver = generateReceiver(ktElement, resolvedCall.extensionReceiver, descriptor.extensionReceiverParameter)
|
||||
|
||||
return if (resolvedCall.requiresArgumentReordering()) {
|
||||
generateCallWithArgumentReordering(irCall, ktExpression, resolvedCall, resultType)
|
||||
generateCallWithArgumentReordering(irCall, ktElement, resolvedCall, resultType)
|
||||
}
|
||||
else {
|
||||
irCall.apply {
|
||||
@@ -152,7 +161,7 @@ class CallGenerator(val statementGenerator: StatementGenerator) : IrGenerator {
|
||||
|
||||
private fun generateCallWithArgumentReordering(
|
||||
irCall: IrCallExpression,
|
||||
ktExpression: KtExpression,
|
||||
ktElement: KtElement,
|
||||
resolvedCall: ResolvedCall<out CallableDescriptor>,
|
||||
resultType: KotlinType?
|
||||
): IrExpression {
|
||||
@@ -161,8 +170,8 @@ class CallGenerator(val statementGenerator: StatementGenerator) : IrGenerator {
|
||||
val valueArgumentsInEvaluationOrder = resolvedCall.valueArguments.values
|
||||
val valueParameters = resolvedCall.resultingDescriptor.valueParameters
|
||||
|
||||
val hasResult = isUsedAsExpression(ktExpression)
|
||||
val irBlock = IrBlockExpressionImpl(ktExpression.startOffset, ktExpression.endOffset, resultType, hasResult,
|
||||
val hasResult = isUsedAsExpression(ktElement)
|
||||
val irBlock = IrBlockExpressionImpl(ktElement.startOffset, ktElement.endOffset, resultType, hasResult,
|
||||
IrOperator.SYNTHETIC_BLOCK)
|
||||
|
||||
val valueArgumentsToValueParameters = HashMap<ResolvedValueArgument, ValueParameterDescriptor>()
|
||||
@@ -189,22 +198,22 @@ class CallGenerator(val statementGenerator: StatementGenerator) : IrGenerator {
|
||||
return irBlock
|
||||
}
|
||||
|
||||
fun generateReceiver(ktExpression: KtExpression, receiver: ReceiverValue?, receiverParameterDescriptor: ReceiverParameterDescriptor?) =
|
||||
generateReceiver(ktExpression, receiver, receiverParameterDescriptor?.type)
|
||||
fun generateReceiver(ktElement: KtElement, receiver: ReceiverValue?, receiverParameterDescriptor: ReceiverParameterDescriptor?) =
|
||||
generateReceiver(ktElement, receiver, receiverParameterDescriptor?.type)
|
||||
|
||||
fun generateReceiver(ktExpression: KtExpression, receiver: ReceiverValue?, expectedType: KotlinType?) =
|
||||
generateReceiver(ktExpression, receiver)?.toExpectedType(expectedType)
|
||||
fun generateReceiver(ktElement: KtElement, receiver: ReceiverValue?, expectedType: KotlinType?) =
|
||||
generateReceiver(ktElement, receiver)?.toExpectedType(expectedType)
|
||||
|
||||
fun generateReceiver(ktExpression: KtExpression, receiver: ReceiverValue?): IrExpression? =
|
||||
fun generateReceiver(ktElement: KtElement, receiver: ReceiverValue?): IrExpression? =
|
||||
if (receiver == null)
|
||||
null
|
||||
else
|
||||
receiverValues[receiver]?.load() ?: doGenerateReceiver(ktExpression, receiver)
|
||||
receiverValues[receiver]?.load() ?: doGenerateReceiver(ktElement, receiver)
|
||||
|
||||
fun doGenerateReceiver(ktExpression: KtExpression, receiver: ReceiverValue?): IrExpression? =
|
||||
fun doGenerateReceiver(ktElement: KtElement, receiver: ReceiverValue?): IrExpression? =
|
||||
when (receiver) {
|
||||
is ImplicitClassReceiver ->
|
||||
IrThisExpressionImpl(ktExpression.startOffset, ktExpression.startOffset, receiver.type, receiver.classDescriptor)
|
||||
IrThisExpressionImpl(ktElement.startOffset, ktElement.startOffset, receiver.type, receiver.classDescriptor)
|
||||
is ThisClassReceiver ->
|
||||
(receiver as? ExpressionReceiver)?.expression?.let { receiverExpression ->
|
||||
IrThisExpressionImpl(receiverExpression.startOffset, receiverExpression.endOffset, receiver.type, receiver.classDescriptor)
|
||||
@@ -215,7 +224,7 @@ class CallGenerator(val statementGenerator: StatementGenerator) : IrGenerator {
|
||||
IrGetObjectValueExpressionImpl(receiver.expression.startOffset, receiver.expression.endOffset, receiver.type,
|
||||
receiver.classQualifier.descriptor)
|
||||
is ExtensionReceiver ->
|
||||
IrGetExtensionReceiverExpressionImpl(ktExpression.startOffset, ktExpression.startOffset, receiver.type,
|
||||
IrGetExtensionReceiverExpressionImpl(ktElement.startOffset, ktElement.startOffset, receiver.type,
|
||||
receiver.declarationDescriptor.extensionReceiverParameter!!)
|
||||
null ->
|
||||
null
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.ir.expressions.IrDummyExpression
|
||||
import org.jetbrains.kotlin.psi.KtBlockExpression
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
@@ -54,8 +55,8 @@ fun IrGenerator.getExpectedTypeForLastInferredCall(key: KtExpression): KotlinTyp
|
||||
fun IrGenerator.getInferredTypeWithSmarcastsOrFail(key: KtExpression): KotlinType =
|
||||
getInferredTypeWithSmartcasts(key) ?: TODO("No type for expression: ${key.text}")
|
||||
|
||||
fun IrGenerator.isUsedAsExpression(ktExpression: KtExpression) =
|
||||
get(BindingContext.USED_AS_EXPRESSION, ktExpression) ?: false
|
||||
fun IrGenerator.isUsedAsExpression(ktElement: KtElement) =
|
||||
get(BindingContext.USED_AS_EXPRESSION, ktElement) ?: false
|
||||
|
||||
fun IrGenerator.getResolvedCall(key: KtExpression): ResolvedCall<out CallableDescriptor>? =
|
||||
key.getResolvedCall(context.bindingContext)
|
||||
|
||||
+38
-27
@@ -31,8 +31,11 @@ import org.jetbrains.kotlin.psi2ir.toExpectedType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
|
||||
import org.jetbrains.kotlin.resolve.constants.IntValue
|
||||
import org.jetbrains.kotlin.resolve.constants.NullValue
|
||||
import org.jetbrains.kotlin.resolve.constants.StringValue
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
|
||||
@@ -140,6 +143,8 @@ class StatementGenerator(
|
||||
IrLiteralExpressionImpl.string(expression.startOffset, expression.endOffset, constantType, constantValue.value)
|
||||
is IntValue ->
|
||||
IrLiteralExpressionImpl.int(expression.startOffset, expression.endOffset, constantType, constantValue.value)
|
||||
is NullValue ->
|
||||
IrLiteralExpressionImpl.nullLiteral(expression.startOffset, expression.endOffset, constantType)
|
||||
else ->
|
||||
TODO("handle other literal types: ${constantValue.type}")
|
||||
}
|
||||
@@ -166,40 +171,45 @@ class StatementGenerator(
|
||||
IrLiteralExpressionImpl.string(entry.startOffset, entry.endOffset, context.builtIns.stringType, entry.text)
|
||||
|
||||
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression, data: Nothing?): IrExpression {
|
||||
val resolvedCall = getResolvedCall(expression)
|
||||
val resolvedCall = getResolvedCall(expression)!!
|
||||
|
||||
if (resolvedCall is VariableAsFunctionResolvedCall) {
|
||||
TODO("Unexpected VariableAsFunctionResolvedCall")
|
||||
}
|
||||
|
||||
val descriptor = resolvedCall?.resultingDescriptor
|
||||
val descriptor = resolvedCall.resultingDescriptor
|
||||
|
||||
return when (descriptor) {
|
||||
is ClassDescriptor ->
|
||||
if (DescriptorUtils.isObject(descriptor))
|
||||
IrGetObjectValueExpressionImpl(expression.startOffset, expression.endOffset, descriptor.classValueType, descriptor)
|
||||
else if (DescriptorUtils.isEnumEntry(descriptor))
|
||||
IrGetEnumValueExpressionImpl(expression.startOffset, expression.endOffset, descriptor.classValueType, descriptor)
|
||||
else {
|
||||
val companionObjectDescriptor = descriptor.companionObjectDescriptor
|
||||
?: error("Class value without companion object: $descriptor")
|
||||
IrGetObjectValueExpressionImpl(expression.startOffset, expression.endOffset,
|
||||
descriptor.classValueType,
|
||||
companionObjectDescriptor)
|
||||
}
|
||||
is PropertyDescriptor -> {
|
||||
CallGenerator(this).generateCall(expression, resolvedCall)
|
||||
}
|
||||
is VariableDescriptor ->
|
||||
IrGetVariableExpressionImpl(expression.startOffset, expression.endOffset, descriptor)
|
||||
else ->
|
||||
IrDummyExpression(
|
||||
expression.startOffset, expression.endOffset, getInferredTypeWithSmartcasts(expression),
|
||||
expression.getReferencedName() + ": ${descriptor?.name} ${descriptor?.javaClass?.simpleName}"
|
||||
)
|
||||
}
|
||||
return generateExpressionForReferencedDescriptor(descriptor, expression, resolvedCall)
|
||||
}
|
||||
|
||||
private fun generateExpressionForReferencedDescriptor(descriptor: DeclarationDescriptor, expression: KtExpression, resolvedCall: ResolvedCall<*>): IrExpression =
|
||||
when (descriptor) {
|
||||
is FakeCallableDescriptorForObject ->
|
||||
generateExpressionForReferencedDescriptor(descriptor.getReferencedDescriptor(), expression, resolvedCall)
|
||||
is ClassDescriptor ->
|
||||
if (DescriptorUtils.isObject(descriptor))
|
||||
IrGetObjectValueExpressionImpl(expression.startOffset, expression.endOffset, descriptor.classValueType, descriptor)
|
||||
else if (DescriptorUtils.isEnumEntry(descriptor))
|
||||
IrGetEnumValueExpressionImpl(expression.startOffset, expression.endOffset, descriptor.classValueType, descriptor)
|
||||
else {
|
||||
val companionObjectDescriptor = descriptor.companionObjectDescriptor
|
||||
?: error("Class value without companion object: $descriptor")
|
||||
IrGetObjectValueExpressionImpl(expression.startOffset, expression.endOffset,
|
||||
descriptor.classValueType,
|
||||
companionObjectDescriptor)
|
||||
}
|
||||
is PropertyDescriptor -> {
|
||||
CallGenerator(this).generateCall(expression, resolvedCall)
|
||||
}
|
||||
is VariableDescriptor ->
|
||||
IrGetVariableExpressionImpl(expression.startOffset, expression.endOffset, descriptor)
|
||||
else ->
|
||||
IrDummyExpression(
|
||||
expression.startOffset, expression.endOffset, getInferredTypeWithSmartcasts(expression),
|
||||
expression.text + ": ${descriptor.name} ${descriptor.javaClass.simpleName}"
|
||||
)
|
||||
}
|
||||
|
||||
override fun visitCallExpression(expression: KtCallExpression, data: Nothing?): IrStatement {
|
||||
val resolvedCall = getResolvedCall(expression) ?: TODO("No resolved call for call expression")
|
||||
|
||||
@@ -280,5 +290,6 @@ class StatementGenerator(
|
||||
return irWhen
|
||||
}
|
||||
|
||||
|
||||
override fun visitWhenExpression(expression: KtWhenExpression, data: Nothing?): IrStatement =
|
||||
WhenExpressionGenerator(this).generate(expression)
|
||||
}
|
||||
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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.ir.declarations.IrVariable
|
||||
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.load
|
||||
import org.jetbrains.kotlin.psi2ir.toExpectedType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
|
||||
class WhenExpressionGenerator(val statementGenerator: StatementGenerator) : IrGenerator {
|
||||
override val context: GeneratorContext get() = statementGenerator.context
|
||||
|
||||
fun generate(expression: KtWhenExpression): IrExpression {
|
||||
val conditionsGenerator = CallGenerator(statementGenerator)
|
||||
|
||||
val irSubject = expression.subjectExpression?.let {
|
||||
conditionsGenerator.createTemporary(it, statementGenerator.generateExpression(it), "subject")
|
||||
}
|
||||
|
||||
val resultType = getInferredTypeWithSmartcasts(expression)
|
||||
|
||||
val irWhen = IrWhenExpressionImpl(expression.startOffset, expression.endOffset, resultType, irSubject)
|
||||
|
||||
for (ktEntry in expression.entries) {
|
||||
if (ktEntry.isElse) {
|
||||
irWhen.elseExpression = statementGenerator.generateExpression(ktEntry.expression!!).toExpectedType(resultType)
|
||||
continue
|
||||
}
|
||||
|
||||
val irBranch = IrBranchImpl(ktEntry.startOffset, ktEntry.endOffset)
|
||||
|
||||
for (ktCondition in ktEntry.conditions) {
|
||||
val irCondition =
|
||||
if (irSubject != null)
|
||||
generateWhenConditionWithSubject(ktCondition, conditionsGenerator, irSubject)
|
||||
else
|
||||
generateWhenConditionNoSubject(ktCondition)
|
||||
irBranch.addCondition(irCondition)
|
||||
}
|
||||
|
||||
irBranch.result = statementGenerator.generateExpression(ktEntry.expression!!).toExpectedType(resultType)
|
||||
|
||||
irWhen.addBranch(irBranch)
|
||||
}
|
||||
|
||||
return irWhen
|
||||
}
|
||||
|
||||
private fun generateWhenConditionNoSubject(ktCondition: KtWhenCondition): IrExpression =
|
||||
statementGenerator.generateExpression((ktCondition as KtWhenConditionWithExpression).expression!!)
|
||||
.toExpectedType(context.builtIns.booleanType)
|
||||
|
||||
private fun generateWhenConditionWithSubject(
|
||||
ktCondition: KtWhenCondition,
|
||||
conditionsGenerator: CallGenerator,
|
||||
irSubject: IrVariable
|
||||
): IrExpression {
|
||||
return when (ktCondition) {
|
||||
is KtWhenConditionWithExpression ->
|
||||
generateEqualsCondition(irSubject, ktCondition)
|
||||
is KtWhenConditionInRange ->
|
||||
generateInRangeCondition(conditionsGenerator, ktCondition)
|
||||
is KtWhenConditionIsPattern ->
|
||||
generateIsPatternCondition(irSubject, ktCondition)
|
||||
else ->
|
||||
throw AssertionError("Unexpected 'when' condition: ${ktCondition.text}")
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateIsPatternCondition(irSubject: IrVariable, ktCondition: KtWhenConditionIsPattern): IrExpression {
|
||||
val isType = getOrFail(BindingContext.TYPE, ktCondition.typeReference)
|
||||
return IrTypeOperatorExpressionImpl(
|
||||
ktCondition.startOffset, ktCondition.endOffset, context.builtIns.booleanType,
|
||||
IrTypeOperator.INSTANCEOF, isType, irSubject.load()
|
||||
)
|
||||
}
|
||||
|
||||
private fun generateInRangeCondition(conditionsGenerator: CallGenerator, ktCondition: KtWhenConditionInRange): IrExpression {
|
||||
val inResolvedCall = getResolvedCall(ktCondition.operationReference)!!
|
||||
val inOperator = getIrBinaryOperator(ktCondition.operationReference.getReferencedNameElementType())
|
||||
val irInCall = conditionsGenerator.generateCall(ktCondition, inResolvedCall, inOperator)
|
||||
return when (inOperator) {
|
||||
IrOperator.IN -> irInCall
|
||||
IrOperator.NOT_IN ->
|
||||
IrUnaryOperatorExpressionImpl(ktCondition.startOffset, ktCondition.endOffset, context.builtIns.booleanType,
|
||||
IrOperator.EXCL, null, irInCall)
|
||||
else -> throw AssertionError("Expected 'in' or '!in', got $inOperator")
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateEqualsCondition(irSubject: IrVariable, ktCondition: KtWhenConditionWithExpression): IrBinaryOperatorExpressionImpl =
|
||||
IrBinaryOperatorExpressionImpl(
|
||||
ktCondition.startOffset, ktCondition.endOffset,
|
||||
context.builtIns.booleanType, IrOperator.EQEQ, null,
|
||||
irSubject.load(), statementGenerator.generateExpression(ktCondition.expression!!)
|
||||
)
|
||||
}
|
||||
@@ -27,5 +27,4 @@ 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_CONDITION_SLOT = -1
|
||||
const val BRANCH_RESULT_SLOT = -2
|
||||
const val BRANCH_RESULT_SLOT = -1
|
||||
@@ -58,6 +58,9 @@ class IrLiteralExpressionImpl<out T> (
|
||||
|
||||
fun int(startOffset: Int, endOffset: Int, type: KotlinType, value: Int): IrLiteralExpressionImpl<Int> =
|
||||
IrLiteralExpressionImpl(startOffset, endOffset, type, IrLiteralKind.Int, value)
|
||||
|
||||
fun nullLiteral(startOffset: Int, endOffset: Int, type: KotlinType): IrLiteralExpressionImpl<Nothing?> =
|
||||
IrLiteralExpressionImpl(startOffset, endOffset, type, IrLiteralKind.Null, null)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.ir.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
import java.util.*
|
||||
|
||||
interface IrWhenExpression : IrExpression {
|
||||
@@ -31,8 +32,10 @@ interface IrWhenExpression : IrExpression {
|
||||
}
|
||||
|
||||
interface IrBranch : IrElement {
|
||||
var condition: IrExpression
|
||||
val conditions: List<IrExpression>
|
||||
var result: IrExpression
|
||||
|
||||
fun addCondition(expression: IrExpression)
|
||||
}
|
||||
|
||||
class IrWhenExpressionImpl(
|
||||
@@ -44,7 +47,7 @@ class IrWhenExpressionImpl(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
type: KotlinType?,
|
||||
subject: IrVariable
|
||||
subject: IrVariable?
|
||||
) : this(startOffset, endOffset, type) {
|
||||
this.subject = subject
|
||||
}
|
||||
@@ -121,19 +124,17 @@ class IrWhenExpressionImpl(
|
||||
|
||||
class IrBranchImpl(startOffset: Int, endOffset: Int) : IrElementBase(startOffset, endOffset), IrBranch {
|
||||
constructor(startOffset: Int, endOffset: Int, condition: IrExpression, result: IrExpression) : this(startOffset, endOffset) {
|
||||
this.condition = condition
|
||||
this.result = result
|
||||
addCondition(condition)
|
||||
}
|
||||
|
||||
private var conditionImpl: IrExpression? = null
|
||||
override var condition: IrExpression
|
||||
get() = conditionImpl!!
|
||||
set(value) {
|
||||
value.assertDetached()
|
||||
conditionImpl?.detach()
|
||||
conditionImpl = value
|
||||
value.setTreeLocation(this, BRANCH_CONDITION_SLOT)
|
||||
}
|
||||
override val conditions: MutableList<IrExpression> = SmartList()
|
||||
|
||||
override fun addCondition(expression: IrExpression) {
|
||||
expression.assertDetached()
|
||||
expression.setTreeLocation(this, conditions.size)
|
||||
conditions.add(expression)
|
||||
}
|
||||
|
||||
private var resultImpl: IrExpression? = null
|
||||
override var result: IrExpression
|
||||
@@ -147,17 +148,19 @@ class IrBranchImpl(startOffset: Int, endOffset: Int) : IrElementBase(startOffset
|
||||
|
||||
override fun getChild(slot: Int): IrElement? =
|
||||
when (slot) {
|
||||
BRANCH_CONDITION_SLOT -> condition
|
||||
BRANCH_RESULT_SLOT -> result
|
||||
else -> null
|
||||
else -> conditions.getOrNull(slot)
|
||||
}
|
||||
|
||||
override fun replaceChild(slot: Int, newChild: IrElement) {
|
||||
when (slot) {
|
||||
BRANCH_CONDITION_SLOT ->
|
||||
condition = newChild.assertCast()
|
||||
BRANCH_RESULT_SLOT ->
|
||||
result = newChild.assertCast()
|
||||
in conditions.indices -> {
|
||||
conditions[slot].detach()
|
||||
conditions[slot] = newChild.assertCast()
|
||||
newChild.setTreeLocation(this, slot)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,7 +168,7 @@ class IrBranchImpl(startOffset: Int, endOffset: Int) : IrElementBase(startOffset
|
||||
visitor.visitBranch(this, data)
|
||||
|
||||
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||
conditionImpl?.accept(visitor, data)
|
||||
conditions.forEach { it.accept(visitor, data) }
|
||||
resultImpl?.accept(visitor, data)
|
||||
}
|
||||
}
|
||||
@@ -77,7 +77,7 @@ class DumpIrTreeVisitor(out: Appendable): IrElementVisitor<Unit, String> {
|
||||
subject.accept(this, "\$subject:")
|
||||
}
|
||||
for (branch in expression.branches) {
|
||||
branch.condition.accept(this, "if")
|
||||
branch.conditions.forEach { it.accept(this, "if") }
|
||||
branch.result.accept(this, "then")
|
||||
}
|
||||
expression.elseExpression?.accept(this, "else")
|
||||
|
||||
Reference in New Issue
Block a user