IrBody is no longer a declaration owner.

Local declarations in expression tree.
Call generator supports argument reordering.
This commit is contained in:
Dmitry Petrov
2016-08-12 19:08:42 +03:00
committed by Dmitry Petrov
parent b1af1af8a4
commit 030111b130
36 changed files with 631 additions and 269 deletions
@@ -0,0 +1,174 @@
/*
* 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
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginKind
import org.jetbrains.kotlin.ir.declarations.IrLocalVariableImpl
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptor
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.scopes.receivers.*
import org.jetbrains.kotlin.types.KotlinType
import java.util.*
class IrCallGenerator(
override val context: IrGeneratorContext,
val irExpressionGenerator: IrExpressionGenerator
) : IrGenerator {
fun generateCall(
ktExpression: KtExpression,
resolvedCall: ResolvedCall<out CallableDescriptor>,
operator: IrOperator? = null,
superQualifier: ClassDescriptor? = null
): IrExpression {
val descriptor = resolvedCall.resultingDescriptor
return when (descriptor) {
is PropertyDescriptor ->
IrGetPropertyExpressionImpl(
ktExpression.startOffset, ktExpression.endOffset, getTypeOrFail(ktExpression),
resolvedCall.call.isSafeCall(), descriptor
).apply {
dispatchReceiver = generateReceiver(ktExpression, resolvedCall.dispatchReceiver)
extensionReceiver = generateReceiver(ktExpression, resolvedCall.extensionReceiver)
}
is FunctionDescriptor ->
generateFunctionCall(descriptor, ktExpression, operator, resolvedCall, superQualifier)
else ->
TODO("Unexpected callable descriptor: $descriptor ${descriptor.javaClass.simpleName}")
}
}
private fun ResolvedCall<*>.requiresArgumentReordering(): Boolean {
var lastValueParameterIndex = -1
for (valueArgument in call.valueArguments) {
val argumentMapping = getArgumentMapping(valueArgument)
if (argumentMapping !is ArgumentMatch || argumentMapping.isError()) {
error("Value argument in function call is mapped with error")
}
val argumentIndex = argumentMapping.valueParameter.index
if (argumentIndex < lastValueParameterIndex) return true
lastValueParameterIndex = argumentIndex
}
return false
}
private fun generateFunctionCall(
descriptor: FunctionDescriptor,
ktExpression: KtExpression,
operator: IrOperator?,
resolvedCall: ResolvedCall<out CallableDescriptor>,
superQualifier: ClassDescriptor?
): IrExpression {
val resultType = getTypeOrFail(ktExpression)
val irCall = IrCallExpressionImpl(
ktExpression.startOffset, ktExpression.endOffset, resultType,
descriptor, resolvedCall.call.isSafeCall(), operator, superQualifier
)
irCall.dispatchReceiver = generateReceiver(ktExpression, resolvedCall.dispatchReceiver)
irCall.extensionReceiver = generateReceiver(ktExpression, resolvedCall.extensionReceiver)
return if (resolvedCall.requiresArgumentReordering()) {
generateCallWithArgumentReordering(irCall, ktExpression, resolvedCall, resultType)
}
else {
irCall.apply {
val valueArguments = resolvedCall.valueArgumentsByIndex
for (index in valueArguments!!.indices) {
val valueArgument = valueArguments[index]
val irArgument = generateValueArgument(valueArgument) ?: continue
irCall.putValueArgument(index, irArgument)
}
}
}
}
private fun generateCallWithArgumentReordering(
irCall: IrCallExpression,
ktExpression: KtExpression,
resolvedCall: ResolvedCall<out CallableDescriptor>,
resultType: KotlinType
): IrExpression {
val valueArgumentsInEvaluationOrder = resolvedCall.valueArguments.values
val hasResult = isUsedAsExpression(ktExpression)
val irBlock = IrBlockExpressionImpl(ktExpression.startOffset, ktExpression.endOffset, resultType, hasResult)
val temporaryVariablesForValueArguments = HashMap<ResolvedValueArgument, Pair<VariableDescriptor, IrExpression>>()
for (valueArgument in valueArgumentsInEvaluationOrder) {
val irArgument = generateValueArgument(valueArgument) ?: continue
val irTemporary = irExpressionGenerator.declarationFactory.createTemporaryVariable(irArgument)
val irTemporaryDeclaration = IrLocalVariableDeclarationExpressionImpl(irArgument.startOffset, irArgument.endOffset, irArgument.type)
irTemporaryDeclaration.childDeclaration = irTemporary
irBlock.addChildExpression(irTemporaryDeclaration)
temporaryVariablesForValueArguments[valueArgument] = Pair(irTemporary.descriptor, irArgument)
}
for ((index, valueArgument) in resolvedCall.valueArgumentsByIndex!!.withIndex()) {
val (temporaryDescriptor, irArgument) = temporaryVariablesForValueArguments[valueArgument]!!
val irGetTemporary = IrGetVariableExpressionImpl(irArgument.startOffset, irArgument.endOffset,
irArgument.type, temporaryDescriptor)
irCall.putValueArgument(index, irGetTemporary)
}
irBlock.addChildExpression(irCall)
return irBlock
}
private fun generateReceiver(ktExpression: KtExpression, receiver: ReceiverValue?): IrExpression? =
when (receiver) {
is ImplicitClassReceiver ->
IrThisExpressionImpl(ktExpression.startOffset, ktExpression.startOffset, receiver.type, receiver.classDescriptor)
is ThisClassReceiver ->
(receiver as? ExpressionReceiver)?.expression?.let { receiverExpression ->
IrThisExpressionImpl(receiverExpression.startOffset, receiverExpression.endOffset, receiver.type, receiver.classDescriptor)
} ?: TODO("Non-implicit ThisClassReceiver should be an expression receiver")
is ExpressionReceiver ->
irExpressionGenerator.generateExpression(receiver.expression)
is ClassValueReceiver ->
IrGetObjectValueExpressionImpl(receiver.expression.startOffset, receiver.expression.endOffset, receiver.type,
receiver.classQualifier.descriptor)
is ExtensionReceiver ->
IrGetExtensionReceiverExpressionImpl(ktExpression.startOffset, ktExpression.startOffset, receiver.type,
receiver.declarationDescriptor.extensionReceiverParameter!!)
null ->
null
else ->
TODO("Receiver: ${receiver.javaClass.simpleName}")
}
private fun generateValueArgument(valueArgument: ResolvedValueArgument): IrExpression? {
when (valueArgument) {
is DefaultValueArgument ->
return null
is ExpressionValueArgument ->
return irExpressionGenerator.generateExpression(valueArgument.valueArgument!!.getArgumentExpression()!!)
is VarargValueArgument ->
TODO("vararg")
else ->
TODO("Unexpected valueArgument: ${valueArgument.javaClass.simpleName}")
}
}
}
@@ -18,31 +18,27 @@ package org.jetbrains.kotlin.psi2ir
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptor
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
import org.jetbrains.kotlin.ir.expressions.IrBody import org.jetbrains.kotlin.ir.expressions.IrBody
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.KtProperty
import org.jetbrains.kotlin.psi.KtPropertyAccessor
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 org.jetbrains.kotlin.types.KotlinType
class IrDeclarationFactory private constructor( abstract class IrDeclarationFactoryBase {
val fileEntry: PsiSourceManager.PsiFileEntry,
val irFileImpl: IrFileImpl,
val containingDeclaration: IrCompoundDeclaration
) {
fun createChild(containingDeclaration: IrCompoundDeclaration) =
IrDeclarationFactory(fileEntry, irFileImpl, containingDeclaration)
private fun <D : IrMemberDeclaration> D.addToContainer(): D =
apply { containingDeclaration.addChildDeclaration(this) }
fun createFunction(ktFunction: KtFunction, functionDescriptor: FunctionDescriptor, body: IrBody): IrFunction = fun createFunction(ktFunction: KtFunction, functionDescriptor: FunctionDescriptor, body: IrBody): IrFunction =
IrFunctionImpl(ktFunction.startOffset, ktFunction.endOffset, IrFunctionImpl(ktFunction.startOffset, ktFunction.endOffset,
IrDeclarationOriginKind.DEFINED, functionDescriptor, body) IrDeclarationOriginKind.DEFINED, functionDescriptor, body)
.addToContainer()
fun createSimpleProperty(ktProperty: KtProperty, propertyDescriptor: PropertyDescriptor, valueInitializer: IrBody?): IrSimpleProperty = fun createSimpleProperty(ktProperty: KtProperty, propertyDescriptor: PropertyDescriptor, valueInitializer: IrBody?): IrSimpleProperty =
IrSimplePropertyImpl(ktProperty.startOffset, ktProperty.endOffset, IrSimplePropertyImpl(ktProperty.startOffset, ktProperty.endOffset,
IrDeclarationOriginKind.DEFINED, propertyDescriptor, valueInitializer) IrDeclarationOriginKind.DEFINED, propertyDescriptor, valueInitializer)
.addToContainer()
fun createPropertyGetter( fun createPropertyGetter(
ktPropertyAccessor: KtPropertyAccessor, ktPropertyAccessor: KtPropertyAccessor,
@@ -53,7 +49,6 @@ class IrDeclarationFactory private constructor(
IrPropertyGetterImpl(ktPropertyAccessor.startOffset, ktPropertyAccessor.endOffset, IrPropertyGetterImpl(ktPropertyAccessor.startOffset, ktPropertyAccessor.endOffset,
IrDeclarationOriginKind.DEFINED, getterDescriptor, getterBody) IrDeclarationOriginKind.DEFINED, getterDescriptor, getterBody)
.apply { irProperty.getter = this } .apply { irProperty.getter = this }
.addToContainer()
fun createPropertySetter( fun createPropertySetter(
ktPropertyAccessor: KtPropertyAccessor, ktPropertyAccessor: KtPropertyAccessor,
@@ -64,16 +59,30 @@ class IrDeclarationFactory private constructor(
IrPropertySetterImpl(ktPropertyAccessor.startOffset, ktPropertyAccessor.endOffset, IrPropertySetterImpl(ktPropertyAccessor.startOffset, ktPropertyAccessor.endOffset,
IrDeclarationOriginKind.DEFINED, setterDescriptor, setterBody) IrDeclarationOriginKind.DEFINED, setterDescriptor, setterBody)
.apply { irProperty.setter = this } .apply { irProperty.setter = this }
.addToContainer() }
companion object { class IrDeclarationFactory() : IrDeclarationFactoryBase()
fun create(irModule: IrModuleImpl, sourceManager: PsiSourceManager, ktFile: KtFile, descriptor: PackageFragmentDescriptor): IrDeclarationFactory {
val fileEntry = sourceManager.getOrCreateFileEntry(ktFile) class IrLocalDeclarationsFactory(val scopeOwner: DeclarationDescriptor) : IrDeclarationFactoryBase() {
val fileName = fileEntry.getRecognizableName() private var lastTemporaryIndex = 0
val irFile = IrFileImpl(fileEntry, fileName, descriptor) private fun nextTemporaryIndex() = lastTemporaryIndex++
sourceManager.putFileEntry(irFile, fileEntry)
irModule.addFile(irFile) fun createDescriptorForTemporaryVariable(type: KotlinType): IrTemporaryVariableDescriptor =
return IrDeclarationFactory(fileEntry, irFile, irFile) IrTemporaryVariableDescriptorImpl(scopeOwner, Name.identifier("tmp${nextTemporaryIndex()}"), type)
}
} fun createTemporaryVariable(ktElement: KtElement, type: KotlinType): IrLocalVariable =
} IrLocalVariableImpl(ktElement.startOffset, ktElement.endOffset,
IrDeclarationOriginKind.IR_TEMPORARY_VARIABLE,
createDescriptorForTemporaryVariable(type))
fun createTemporaryVariable(irExpression: IrExpression): IrLocalVariable =
IrLocalVariableImpl(irExpression.startOffset, irExpression.endOffset,
IrDeclarationOriginKind.IR_TEMPORARY_VARIABLE,
createDescriptorForTemporaryVariable(irExpression.type)
).apply { initializerExpression = irExpression }
fun createLocalVariable(ktElement: KtElement, type: KotlinType, descriptor: VariableDescriptor): IrLocalVariable =
IrLocalVariableImpl(ktElement.startOffset, ktElement.endOffset,
IrDeclarationOriginKind.DEFINED,
descriptor)
}
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.psi2ir package org.jetbrains.kotlin.psi2ir
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor
import org.jetbrains.kotlin.descriptors.PropertySetterDescriptor import org.jetbrains.kotlin.descriptors.PropertySetterDescriptor
@@ -29,20 +30,15 @@ import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
interface IrDeclarationGenerator : IrGenerator { interface IrDeclarationGenerator : IrGenerator
val irDeclaration: IrDeclaration
val parent: IrDeclarationGenerator?
}
abstract class IrDeclarationGeneratorBase( abstract class IrDeclarationGeneratorBase(
override val context: IrGeneratorContext, override val context: IrGeneratorContext,
override val irDeclaration: IrDeclaration, val container: IrDeclarationOwnerN,
override val parent: IrDeclarationGenerator, val declarationFactory: IrDeclarationFactoryBase
val declarationFactory: IrDeclarationFactory
) : IrDeclarationGenerator { ) : IrDeclarationGenerator {
val irExpressionGenerator = IrExpressionGenerator(context, declarationFactory) private fun <D : IrMemberDeclaration> D.register(): D =
apply { container.addChildDeclaration(this) }
val containingDeclaration: IrCompoundDeclaration get() = declarationFactory.containingDeclaration
fun generateAnnotationEntries(annotationEntries: List<KtAnnotationEntry>) { fun generateAnnotationEntries(annotationEntries: List<KtAnnotationEntry>) {
// TODO create IrAnnotation's for each KtAnnotationEntry // TODO create IrAnnotation's for each KtAnnotationEntry
@@ -64,26 +60,26 @@ abstract class IrDeclarationGeneratorBase(
fun generateFunctionDeclaration(ktNamedFunction: KtNamedFunction) { fun generateFunctionDeclaration(ktNamedFunction: KtNamedFunction) {
val functionDescriptor = getOrFail(BindingContext.FUNCTION, ktNamedFunction) { "unresolved fun" } val functionDescriptor = getOrFail(BindingContext.FUNCTION, ktNamedFunction) { "unresolved fun" }
val body = generateExpressionBody(ktNamedFunction.bodyExpression ?: TODO("function without body expression")) val body = generateExpressionBody(functionDescriptor, ktNamedFunction.bodyExpression ?: TODO("function without body expression"))
declarationFactory.createFunction(ktNamedFunction, functionDescriptor, body) declarationFactory.createFunction(ktNamedFunction, functionDescriptor, body).register()
} }
fun generatePropertyDeclaration(ktProperty: KtProperty) { fun generatePropertyDeclaration(ktProperty: KtProperty) {
val propertyDescriptor = getPropertyDescriptor(ktProperty) val propertyDescriptor = getPropertyDescriptor(ktProperty)
if (ktProperty.hasDelegate()) TODO("handle delegated property") if (ktProperty.hasDelegate()) TODO("handle delegated property")
val initializer = ktProperty.initializer?.let { generateExpressionBody(it) } val initializer = ktProperty.initializer?.let { generateExpressionBody(propertyDescriptor, it) }
val irProperty = declarationFactory.createSimpleProperty(ktProperty, propertyDescriptor, initializer) val irProperty = declarationFactory.createSimpleProperty(ktProperty, propertyDescriptor, initializer).register()
ktProperty.getter?.let { ktGetter -> ktProperty.getter?.let { ktGetter ->
val accessorDescriptor = getOrFail(BindingContext.PROPERTY_ACCESSOR, ktGetter) { "unresolved getter" } val accessorDescriptor = getOrFail(BindingContext.PROPERTY_ACCESSOR, ktGetter) { "unresolved getter" }
val getterDescriptor = accessorDescriptor as? PropertyGetterDescriptor ?: TODO("not a getter?") val getterDescriptor = accessorDescriptor as? PropertyGetterDescriptor ?: TODO("not a getter?")
val getterBody = generateExpressionBody(ktGetter.bodyExpression ?: TODO("default getter")) val getterBody = generateExpressionBody(getterDescriptor, ktGetter.bodyExpression ?: TODO("default getter"))
declarationFactory.createPropertyGetter(ktGetter, irProperty, getterDescriptor, getterBody) declarationFactory.createPropertyGetter(ktGetter, irProperty, getterDescriptor, getterBody).register()
} }
ktProperty.setter?.let { ktSetter -> ktProperty.setter?.let { ktSetter ->
val accessorDescriptor = getOrFail(BindingContext.PROPERTY_ACCESSOR, ktSetter) { "unresolved setter" } val accessorDescriptor = getOrFail(BindingContext.PROPERTY_ACCESSOR, ktSetter) { "unresolved setter" }
val setterDescriptor = accessorDescriptor as? PropertySetterDescriptor ?: TODO("not a setter?") val setterDescriptor = accessorDescriptor as? PropertySetterDescriptor ?: TODO("not a setter?")
val setterBody = generateExpressionBody(ktSetter.bodyExpression ?: TODO("default setter")) val setterBody = generateExpressionBody(setterDescriptor, ktSetter.bodyExpression ?: TODO("default setter"))
declarationFactory.createPropertySetter(ktSetter, irProperty, setterDescriptor, setterBody) declarationFactory.createPropertySetter(ktSetter, irProperty, setterDescriptor, setterBody).register()
} }
} }
@@ -93,19 +89,8 @@ abstract class IrDeclarationGeneratorBase(
return propertyDescriptor return propertyDescriptor
} }
fun generateExpressionBody(ktBody: KtExpression): IrBody { fun generateExpressionBody(scopeOwner: DeclarationDescriptor, ktBody: KtExpression): IrBody =
val irExpression = irExpressionGenerator.generateExpression(ktBody) IrExpressionBodyImpl(ktBody.startOffset, ktBody.endOffset).apply {
argument = IrExpressionGenerator(context, IrLocalDeclarationsFactory(scopeOwner)).generateExpression(ktBody)
val startOffset = ktBody.startOffset }
val endOffset = ktBody.endOffset
val bodyExpression =
if (ktBody is KtBlockExpression)
irExpression
else
IrReturnExpressionImpl(startOffset, endOffset, irExpression.type)
.apply { returnedExpression = irExpression }
return IrExpressionBodyImpl(startOffset, endOffset, containingDeclaration).apply { argument = bodyExpression }
}
} }
@@ -16,66 +16,64 @@
package org.jetbrains.kotlin.psi2ir package org.jetbrains.kotlin.psi2ir
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
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 org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
import org.jetbrains.kotlin.resolve.constants.IntValue import org.jetbrains.kotlin.resolve.constants.IntValue
import org.jetbrains.kotlin.resolve.constants.StringValue import org.jetbrains.kotlin.resolve.constants.StringValue
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.resolve.scopes.receivers.*
class IrExpressionGenerator( class IrExpressionGenerator(
override val context: IrGeneratorContext, override val context: IrGeneratorContext,
val declarationFactory: IrDeclarationFactory val declarationFactory: IrLocalDeclarationsFactory
) : KtVisitor<IrExpression, Nothing?>(), IrGenerator { ) : KtVisitor<IrExpression, Nothing?>(), IrGenerator {
private val irCallGenerator = IrCallGenerator(context, this)
fun generateExpression(ktExpression: KtExpression) = ktExpression.generate() fun generateExpression(ktExpression: KtExpression) = ktExpression.generate()
private fun KtElement.generate(): IrExpression = private fun KtElement.generate(): IrExpression =
deparenthesize() deparenthesize()
.accept(this@IrExpressionGenerator, null) .accept(this@IrExpressionGenerator, null)
.smartCastIfNeeded(this) .applySmartCastIfNeeded(this)
private fun KtExpression.type() = private fun IrExpression.applySmartCastIfNeeded(ktElement: KtElement): IrExpression {
getType(this) ?: TODO("no type for expression")
private fun IrExpression.smartCastIfNeeded(ktElement: KtElement): IrExpression {
if (ktElement is KtExpression) { if (ktElement is KtExpression) {
val smartCastType = get(BindingContext.SMARTCAST, ktElement) val smartCastType = get(BindingContext.SMARTCAST, ktElement)
if (smartCastType != null) { if (smartCastType != null) {
return IrTypeOperatorExpressionImpl( return IrTypeOperatorExpressionImpl(
ktElement.startOffset, ktElement.endOffset, smartCastType, ktElement.startOffset, ktElement.endOffset, smartCastType,
IrTypeOperator.SMART_AS, smartCastType IrTypeOperator.SMART_AS, smartCastType
).apply { argument = this@smartCastIfNeeded } ).apply { argument = this@applySmartCastIfNeeded }
} }
} }
return this return this
} }
override fun visitExpression(expression: KtExpression, data: Nothing?): IrExpression = override fun visitExpression(expression: KtExpression, data: Nothing?): IrExpression =
IrDummyExpression(expression.startOffset, expression.endOffset, expression.type(), expression.javaClass.simpleName) IrDummyExpression(expression.startOffset, expression.endOffset, getTypeOrFail(expression), expression.javaClass.simpleName)
override fun visitBlockExpression(expression: KtBlockExpression, data: Nothing?): IrExpression { override fun visitBlockExpression(expression: KtBlockExpression, data: Nothing?): IrExpression {
val irBlock = IrBlockExpressionImpl(expression.startOffset, expression.endOffset, expression.type(), false) val irBlock = IrBlockExpressionImpl(expression.startOffset, expression.endOffset, getTypeOrFail(expression), false)
expression.statements.forEach { irBlock.addChildExpression(it.generate()) } expression.statements.forEach { irBlock.addChildExpression(it.generate()) }
return irBlock return irBlock
} }
override fun visitReturnExpression(expression: KtReturnExpression, data: Nothing?): IrExpression = override fun visitReturnExpression(expression: KtReturnExpression, data: Nothing?): IrExpression =
IrReturnExpressionImpl(expression.startOffset, expression.endOffset, expression.type()) IrReturnExpressionImpl(expression.startOffset, expression.endOffset, getTypeOrFail(expression))
.apply { this.argument = expression.returnedExpression?.generate() } .apply { this.argument = expression.returnedExpression?.generate() }
override fun visitConstantExpression(expression: KtConstantExpression, data: Nothing?): IrExpression { override fun visitConstantExpression(expression: KtConstantExpression, data: Nothing?): IrExpression {
val compileTimeConstant = ConstantExpressionEvaluator.getConstant(expression, context.bindingContext) val compileTimeConstant = ConstantExpressionEvaluator.getConstant(expression, context.bindingContext)
?: error("KtConstantExpression was not evaluated: ${expression.text}") ?: error("KtConstantExpression was not evaluated: ${expression.text}")
val constantValue = compileTimeConstant.toConstantValue(expression.type()) val constantValue = compileTimeConstant.toConstantValue(getTypeOrFail(expression))
val constantType = constantValue.type val constantType = constantValue.type
return when (constantValue) { return when (constantValue) {
@@ -93,7 +91,7 @@ class IrExpressionGenerator(
return expression.entries[0].generate() return expression.entries[0].generate()
} }
val irStringTemplate = IrStringConcatenationExpressionImpl(expression.startOffset, expression.endOffset, expression.type()) val irStringTemplate = IrStringConcatenationExpressionImpl(expression.startOffset, expression.endOffset, getTypeOrFail(expression))
expression.entries.forEach { irStringTemplate.addChildExpression(it.generate()) } expression.entries.forEach { irStringTemplate.addChildExpression(it.generate()) }
return irStringTemplate return irStringTemplate
} }
@@ -108,24 +106,24 @@ class IrExpressionGenerator(
TODO("Unexpected VariableAsFunctionResolvedCall") TODO("Unexpected VariableAsFunctionResolvedCall")
} }
val descriptor = resolvedCall?.resultingDescriptor ?: get(BindingContext.REFERENCE_TARGET, expression) val descriptor = resolvedCall?.resultingDescriptor
return when (descriptor) { return when (descriptor) {
is ClassDescriptor -> is ClassDescriptor ->
if (DescriptorUtils.isObject(descriptor)) if (DescriptorUtils.isObject(descriptor))
IrGetObjectValueExpressionImpl(expression.startOffset, expression.endOffset, expression.type(), descriptor) IrGetObjectValueExpressionImpl(expression.startOffset, expression.endOffset, getTypeOrFail(expression), descriptor)
else if (DescriptorUtils.isEnumEntry(descriptor)) else if (DescriptorUtils.isEnumEntry(descriptor))
IrGetEnumValueExpressionImpl(expression.startOffset, expression.endOffset, expression.type(), descriptor) IrGetEnumValueExpressionImpl(expression.startOffset, expression.endOffset, getTypeOrFail(expression), descriptor)
else else
IrGetObjectValueExpressionImpl(expression.startOffset, expression.endOffset, expression.type(), IrGetObjectValueExpressionImpl(expression.startOffset, expression.endOffset, getTypeOrFail(expression),
descriptor.companionObjectDescriptor ?: error("Class value without companion object: $descriptor")) descriptor.companionObjectDescriptor ?: error("Class value without companion object: $descriptor"))
is PropertyDescriptor -> { is PropertyDescriptor -> {
generateCall(expression, resolvedCall ?: TODO("Property, no resolved call: ${descriptor.name}"), null) irCallGenerator.generateCall(expression, resolvedCall)
} }
is VariableDescriptor -> is VariableDescriptor ->
IrGetVariableExpressionImpl(expression.startOffset, expression.endOffset, expression.type(), descriptor) IrGetVariableExpressionImpl(expression.startOffset, expression.endOffset, getTypeOrFail(expression), descriptor)
else -> else ->
IrDummyExpression(expression.startOffset, expression.endOffset, expression.type(), IrDummyExpression(expression.startOffset, expression.endOffset, getTypeOrFail(expression),
expression.getReferencedName() + expression.getReferencedName() +
": ${descriptor?.name} ${descriptor?.javaClass?.simpleName}") ": ${descriptor?.name} ${descriptor?.javaClass?.simpleName}")
} }
@@ -138,7 +136,7 @@ class IrExpressionGenerator(
TODO("VariableAsFunctionResolvedCall = variable call + invoke call") TODO("VariableAsFunctionResolvedCall = variable call + invoke call")
} }
return generateCall(expression, resolvedCall, null, null) return irCallGenerator.generateCall(expression, resolvedCall)
} }
override fun visitDotQualifiedExpression(expression: KtDotQualifiedExpression, data: Nothing?): IrExpression = override fun visitDotQualifiedExpression(expression: KtDotQualifiedExpression, data: Nothing?): IrExpression =
@@ -151,77 +149,16 @@ class IrExpressionGenerator(
val referenceTarget = getOrFail(BindingContext.REFERENCE_TARGET, expression.instanceReference) { "No reference target for this" } val referenceTarget = getOrFail(BindingContext.REFERENCE_TARGET, expression.instanceReference) { "No reference target for this" }
return when (referenceTarget) { return when (referenceTarget) {
is ClassDescriptor -> is ClassDescriptor ->
IrThisExpressionImpl(expression.startOffset, expression.endOffset, expression.type(), referenceTarget) IrThisExpressionImpl(expression.startOffset, expression.endOffset, getTypeOrFail(expression), referenceTarget)
is CallableDescriptor -> is CallableDescriptor ->
IrGetExtensionReceiverExpressionImpl(expression.startOffset, expression.endOffset, expression.type(), IrGetExtensionReceiverExpressionImpl(
referenceTarget.extensionReceiverParameter!!) expression.startOffset, expression.endOffset, getTypeOrFail(expression),
referenceTarget.extensionReceiverParameter!!
)
else -> else ->
error("Expected this or receiver: $referenceTarget") error("Expected this or receiver: $referenceTarget")
} }
} }
private fun generateCall(
ktExpression: KtExpression,
resolvedCall: ResolvedCall<out CallableDescriptor>,
operator: IrOperator? = null,
superQualifier: ClassDescriptor? = null
): IrExpression {
val descriptor = resolvedCall.resultingDescriptor
return when (descriptor) {
is PropertyDescriptor ->
IrGetPropertyExpressionImpl(
ktExpression.startOffset, ktExpression.endOffset, ktExpression.type(),
resolvedCall.call.isSafeCall(), descriptor
)
else ->
IrCallExpressionImpl(
ktExpression.startOffset, ktExpression.endOffset, ktExpression.type(),
resolvedCall.resultingDescriptor, resolvedCall.call.isSafeCall(), operator, superQualifier
).apply {
val valueParameters = resolvedCall.resultingDescriptor.valueParameters
val valueArguments = resolvedCall.valueArgumentsByIndex ?: TODO("null for value arguments: ${ktExpression.text}")
for (index in valueArguments.indices) {
val valueArgument = valueArguments[index]
val valueParameter = valueParameters[index]
putValueArgument(valueParameter, generateValueArgument(valueParameter, valueArgument))
}
}
}.apply {
dispatchReceiver = generateReceiver(ktExpression, resolvedCall.dispatchReceiver)
extensionReceiver = generateReceiver(ktExpression, resolvedCall.extensionReceiver)
}
}
private fun generateReceiver(ktExpression: KtExpression, receiver: ReceiverValue?): IrExpression? =
when (receiver) {
is ImplicitClassReceiver ->
IrThisExpressionImpl(ktExpression.startOffset, ktExpression.startOffset, receiver.type, receiver.classDescriptor)
is ThisClassReceiver ->
(receiver as? ExpressionReceiver)?.expression?.let { receiverExpression ->
IrThisExpressionImpl(receiverExpression.startOffset, receiverExpression.endOffset, receiver.type, receiver.classDescriptor)
} ?: TODO("Non-implicit ThisClassReceiver should be an expression receiver")
is ExpressionReceiver ->
receiver.expression.generate()
is ClassValueReceiver ->
IrGetObjectValueExpressionImpl(receiver.expression.startOffset, receiver.expression.endOffset, receiver.type,
receiver.classQualifier.descriptor)
is ExtensionReceiver ->
IrGetExtensionReceiverExpressionImpl(ktExpression.startOffset, ktExpression.startOffset, receiver.type,
receiver.declarationDescriptor.extensionReceiverParameter!!)
null ->
null
else ->
TODO("Receiver: ${receiver.javaClass.simpleName}")
}
private fun generateValueArgument(valueParameter: ValueParameterDescriptor, valueArgument: ResolvedValueArgument): IrExpression? {
if (valueParameter.varargElementType == null) {
assert(valueArgument.arguments.size == 1) { "Single value argument expected for a non-vararg parameter" }
return valueArgument.arguments.single().getArgumentExpression()!!.generate()
}
else {
TODO("vararg")
}
}
} }
@@ -16,16 +16,17 @@
package org.jetbrains.kotlin.psi2ir package org.jetbrains.kotlin.psi2ir
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrFileImpl import org.jetbrains.kotlin.ir.declarations.IrFileImpl
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
class IrFileGenerator( class IrFileGenerator(
private val ktFile: KtFile, private val ktFile: KtFile,
context: IrGeneratorContext, context: IrGeneratorContext,
irDeclaration: IrFileImpl, irFile: IrFile,
parent: IrModuleGenerator, parent: IrModuleGenerator,
declarationFactory: IrDeclarationFactory declarationFactory: IrDeclarationFactory
) : IrDeclarationGeneratorBase(context, irDeclaration, parent, declarationFactory) { ) : IrDeclarationGeneratorBase(context, irFile, declarationFactory) {
fun generateFileContent() { fun generateFileContent() {
generateAnnotationEntries(ktFile.annotationEntries) generateAnnotationEntries(ktFile.annotationEntries)
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.psi2ir
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
@@ -30,12 +31,18 @@ interface IrGenerator {
fun IrGenerator.getType(key: KtExpression): KotlinType? = fun IrGenerator.getType(key: KtExpression): KotlinType? =
context.bindingContext.getType(key) context.bindingContext.getType(key)
fun IrGenerator.getTypeOrFail(key: KtExpression): KotlinType =
getType(key) ?: TODO("No type for expression: ${key.text}")
fun <K, V : Any> IrGenerator.get(slice: ReadOnlySlice<K, V>, key: K): V? = fun <K, V : Any> IrGenerator.get(slice: ReadOnlySlice<K, V>, key: K): V? =
context.bindingContext[slice, key] context.bindingContext[slice, key]
inline fun <K, V : Any> IrGenerator.getOrFail(slice: ReadOnlySlice<K, V>, key: K, message: (K) -> String): V = inline fun <K, V : Any> IrGenerator.getOrFail(slice: ReadOnlySlice<K, V>, key: K, message: (K) -> String): V =
context.bindingContext[slice, key] ?: throw RuntimeException(message(key)) context.bindingContext[slice, key] ?: throw RuntimeException(message(key))
fun IrGenerator.isUsedAsExpression(ktExpression: KtExpression) =
get(BindingContext.USED_AS_EXPRESSION, ktExpression) ?: false
inline fun <K, V : Any> IrGenerator.getOrElse(slice: ReadOnlySlice<K, V>, key: K, otherwise: (K) -> V): V = inline fun <K, V : Any> IrGenerator.getOrElse(slice: ReadOnlySlice<K, V>, key: K, otherwise: (K) -> V): V =
context.bindingContext[slice, key] ?: otherwise(key) context.bindingContext[slice, key] ?: otherwise(key)
@@ -16,19 +16,19 @@
package org.jetbrains.kotlin.psi2ir package org.jetbrains.kotlin.psi2ir
import org.jetbrains.kotlin.ir.declarations.IrModule import org.jetbrains.kotlin.ir.declarations.IrFileImpl
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
class IrModuleGenerator(override val context: IrGeneratorContext) : IrDeclarationGenerator { class IrModuleGenerator(override val context: IrGeneratorContext) : IrDeclarationGenerator {
override val irDeclaration: IrModule get() = context.irModule
override val parent: IrDeclarationGenerator? get() = null
fun generateModuleContent() { fun generateModuleContent() {
for (ktFile in context.inputFiles) { for (ktFile in context.inputFiles) {
val packageFragmentDescriptor = getOrFail(BindingContext.FILE_TO_PACKAGE_FRAGMENT, ktFile) { "no package fragment for file" } val packageFragmentDescriptor = getOrFail(BindingContext.FILE_TO_PACKAGE_FRAGMENT, ktFile) { "no package fragment for file" }
val irFileElementFactory = IrDeclarationFactory.create(context.irModule, context.sourceManager, ktFile, packageFragmentDescriptor) val fileEntry = context.sourceManager.getOrCreateFileEntry(ktFile)
val irFile = irFileElementFactory.irFileImpl val fileName = fileEntry.getRecognizableName()
val irFile = IrFileImpl(fileEntry, fileName, packageFragmentDescriptor)
context.sourceManager.putFileEntry(irFile, fileEntry)
context.irModule.addFile(irFile) context.irModule.addFile(irFile)
val irFileElementFactory = IrDeclarationFactory()
val generator = IrFileGenerator(ktFile, context, irFile, this, irFileElementFactory) val generator = IrFileGenerator(ktFile, context, irFile, this, irFileElementFactory)
generator.generateFileContent() generator.generateFileContent()
} }
@@ -14,8 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.ir.expressions package org.jetbrains.kotlin.ir
const val CHILD_DECLARATION_INDEX = 0
const val DETACHED_INDEX = Int.MIN_VALUE const val DETACHED_INDEX = Int.MIN_VALUE
const val CHILD_EXPRESSION_INDEX = 0 const val CHILD_EXPRESSION_INDEX = 0
const val ARGUMENT0_INDEX = 0 const val ARGUMENT0_INDEX = 0
@@ -16,36 +16,43 @@
package org.jetbrains.kotlin.ir.declarations package org.jetbrains.kotlin.ir.declarations
import org.jetbrains.kotlin.ir.CHILD_DECLARATION_INDEX
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrElementBase import org.jetbrains.kotlin.ir.IrElementBase
import org.jetbrains.kotlin.ir.DETACHED_INDEX
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import java.util.* import java.util.*
interface IrDeclarationOwner : IrElement { interface IrDeclarationOwner : IrElement {
val childrenCount: Int
fun getChildDeclaration(index: Int): IrMemberDeclaration? fun getChildDeclaration(index: Int): IrMemberDeclaration?
fun addChildDeclaration(child: IrMemberDeclaration)
fun replaceChildDeclaration(oldChild: IrMemberDeclaration, newChild: IrMemberDeclaration) fun replaceChildDeclaration(oldChild: IrMemberDeclaration, newChild: IrMemberDeclaration)
fun removeAllChildDeclarations() }
// TODO This can be an expensive operation / prohibited for some children. interface IrDeclarationOwner1 : IrDeclarationOwner {
val childDeclaration: IrMemberDeclaration
}
interface IrDeclarationOwnerN : IrDeclarationOwner {
val childrenCount: Int
fun addChildDeclaration(child: IrMemberDeclaration)
fun removeChildDeclaration(child: IrMemberDeclaration) fun removeChildDeclaration(child: IrMemberDeclaration)
fun removeAllChildDeclarations()
fun <D> acceptChildDeclarations(visitor: IrElementVisitor<Unit, D>, data: D) fun <D> acceptChildDeclarations(visitor: IrElementVisitor<Unit, D>, data: D)
} }
interface IrCompoundDeclaration : IrDeclaration, IrDeclarationOwner interface IrCompoundDeclaration : IrDeclaration, IrDeclarationOwnerN
interface IrMemberDeclaration : IrDeclaration { interface IrMemberDeclaration : IrDeclaration {
override val parent: IrDeclarationOwner override var parent: IrDeclarationOwner?
fun setTreeLocation(parent: IrDeclarationOwner?, index: Int) fun setTreeLocation(parent: IrDeclarationOwner?, index: Int)
} }
abstract class IrDeclarationOwnerBase( abstract class IrDeclarationOwnerNBase(
startOffset: Int, startOffset: Int,
endOffset: Int endOffset: Int
) : IrElementBase(startOffset, endOffset), IrDeclarationOwner { ) : IrElementBase(startOffset, endOffset), IrDeclarationOwnerN {
protected val childDeclarations: MutableList<IrMemberDeclaration> = ArrayList() protected val childDeclarations: MutableList<IrMemberDeclaration> = ArrayList()
override val childrenCount: Int override val childrenCount: Int
@@ -90,7 +97,7 @@ abstract class IrCompoundDeclarationBase(
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
override val originKind: IrDeclarationOriginKind override val originKind: IrDeclarationOriginKind
) : IrDeclarationOwnerBase(startOffset, endOffset), IrCompoundDeclaration { ) : IrDeclarationOwnerNBase(startOffset, endOffset), IrCompoundDeclaration {
override var indexInParent: Int = IrDeclaration.DETACHED_INDEX override var indexInParent: Int = IrDeclaration.DETACHED_INDEX
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) { override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
@@ -105,7 +112,7 @@ abstract class IrCompoundMemberDeclarationBase(
) : IrCompoundDeclarationBase(startOffset, endOffset, originKind), IrMemberDeclaration { ) : IrCompoundDeclarationBase(startOffset, endOffset, originKind), IrMemberDeclaration {
private var parentImpl: IrDeclarationOwner? = null private var parentImpl: IrDeclarationOwner? = null
override var parent: IrDeclarationOwner override var parent: IrDeclarationOwner?
get() = parentImpl!! get() = parentImpl!!
set(newParent) { set(newParent) {
parentImpl = newParent parentImpl = newParent
@@ -124,7 +131,7 @@ abstract class IrMemberDeclarationBase(
) : IrDeclarationBase(startOffset, endOffset, originKind), IrMemberDeclaration { ) : IrDeclarationBase(startOffset, endOffset, originKind), IrMemberDeclaration {
private var parentImpl: IrDeclarationOwner? = null private var parentImpl: IrDeclarationOwner? = null
override var parent: IrDeclarationOwner override var parent: IrDeclarationOwner?
get() = parentImpl!! get() = parentImpl!!
set(newParent) { set(newParent) {
parentImpl = newParent parentImpl = newParent
@@ -38,15 +38,16 @@ enum class IrDeclarationKind {
MODULE, MODULE,
FILE, FILE,
FUNCTION, FUNCTION,
PROPERTY,
PROPERTY_GETTER, PROPERTY_GETTER,
PROPERTY_SETTER, PROPERTY_SETTER,
PROPERTY,
LOCAL_VARIABLE,
CLASS CLASS
} }
enum class IrDeclarationOriginKind { enum class IrDeclarationOriginKind {
DEFINED, DEFINED,
DEFAULT_PROPERTY_ACCESSOR, IR_TEMPORARY_VARIABLE,
} }
abstract class IrDeclarationBase( abstract class IrDeclarationBase(
@@ -45,6 +45,10 @@ class IrFunctionImpl(
override val descriptor: FunctionDescriptor, override val descriptor: FunctionDescriptor,
override val body: IrBody override val body: IrBody
) : IrFunctionBase(startOffset, endOffset, originKind) { ) : IrFunctionBase(startOffset, endOffset, originKind) {
init {
body.parent = this
}
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R = override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitFunction(this, data) visitor.visitFunction(this, data)
} }
@@ -0,0 +1,65 @@
/*
* 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.declarations
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.ir.CHILD_EXPRESSION_INDEX
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
interface IrLocalVariable : IrMemberDeclaration, IrExpressionOwner {
override val descriptor: VariableDescriptor
override val declarationKind: IrDeclarationKind
get() = IrDeclarationKind.LOCAL_VARIABLE
var initializerExpression: IrExpression?
}
class IrLocalVariableImpl(
startOffset: Int,
endOffset: Int,
originKind: IrDeclarationOriginKind,
override val descriptor: VariableDescriptor
) : IrMemberDeclarationBase(startOffset, endOffset, originKind), IrLocalVariable {
override var initializerExpression: IrExpression? = null
set(value) {
field?.detach()
field = value
value?.setTreeLocation(this, CHILD_EXPRESSION_INDEX)
}
override fun getChildExpression(index: Int): IrExpression? =
if (index == CHILD_EXPRESSION_INDEX) initializerExpression else null
override fun replaceChildExpression(oldChild: IrExpression, newChild: IrExpression) {
validateChild(oldChild)
initializerExpression = newChild
}
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
return visitor.visitLocalVariable(this, data)
}
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
acceptChildExpressions(visitor, data)
}
override fun <D> acceptChildExpressions(visitor: IrElementVisitor<Unit, D>, data: D) {
initializerExpression?.accept(visitor, data)
}
}
@@ -71,6 +71,10 @@ class IrSimplePropertyImpl(
descriptor: PropertyDescriptor, descriptor: PropertyDescriptor,
override val valueInitializer: IrBody? override val valueInitializer: IrBody?
) : IrPropertyBase(startOffset, endOffset, originKind, descriptor), IrSimpleProperty { ) : IrPropertyBase(startOffset, endOffset, originKind, descriptor), IrSimpleProperty {
init {
valueInitializer?.parent = this
}
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R = override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitSimpleProperty(this, data) visitor.visitSimpleProperty(this, data)
@@ -47,6 +47,10 @@ abstract class IrPropertyAccessorBase(
originKind: IrDeclarationOriginKind, originKind: IrDeclarationOriginKind,
override val body: IrBody override val body: IrBody
) : IrFunctionBase(startOffset, endOffset, originKind), IrPropertyAccessor { ) : IrFunctionBase(startOffset, endOffset, originKind), IrPropertyAccessor {
init {
body.parent = this
}
override var property: IrProperty? = null override var property: IrProperty? = null
} }
@@ -0,0 +1,48 @@
/*
* 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.descriptors
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.VariableDescriptorImpl
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.constants.ConstantValue
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeSubstitutor
interface IrTemporaryVariableDescriptor : VariableDescriptor
class IrTemporaryVariableDescriptorImpl(
containingDeclaration: DeclarationDescriptor,
name: Name,
outType: KotlinType
): VariableDescriptorImpl(containingDeclaration, Annotations.EMPTY, name, outType, SourceElement.NO_SOURCE),
IrTemporaryVariableDescriptor
{
override fun getCompileTimeInitializer(): ConstantValue<*>? = null
override fun getVisibility(): Visibility = Visibilities.LOCAL
override fun substitute(substitutor: TypeSubstitutor): VariableDescriptor {
throw UnsupportedOperationException("Temporary variable descriptor shouldn't be substituted (so far): $this")
}
override fun isVar(): Boolean = false
override fun <R, D> accept(visitor: DeclarationDescriptorVisitor<R, D>, data: D): R =
visitor.visitVariableDescriptor(this, data)
}
@@ -16,24 +16,27 @@
package org.jetbrains.kotlin.ir.expressions package org.jetbrains.kotlin.ir.expressions
import org.jetbrains.kotlin.ir.CHILD_EXPRESSION_INDEX
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrElementBase
import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOwner import org.jetbrains.kotlin.ir.declarations.IrDeclarationOwner
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOwnerBase import org.jetbrains.kotlin.ir.declarations.IrDeclarationOwnerNBase
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
interface IrBody : IrElement { interface IrBody : IrElement {
override val parent: IrDeclaration override var parent: IrDeclaration
} }
interface IrExpressionBody : IrBody, IrExpressionOwner1, IrDeclarationOwner interface IrExpressionBody : IrBody, IrExpressionOwner1
// TODO IrExpressionBodyImpl vs IrCompoundExpression1Impl: extract common base class? // TODO IrExpressionBodyImpl vs IrCompoundExpression1Impl: extract common base class?
class IrExpressionBodyImpl( class IrExpressionBodyImpl(
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int
override val parent: IrDeclaration ) : IrElementBase(startOffset, endOffset), IrExpressionBody {
) : IrDeclarationOwnerBase(startOffset, endOffset), IrExpressionBody { override lateinit var parent: IrDeclaration
override var argument: IrExpression? = null override var argument: IrExpression? = null
set(newExpression) { set(newExpression) {
field?.detach() field?.detach()
@@ -18,7 +18,8 @@ package org.jetbrains.kotlin.ir.expressions
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.ir.DISPATCH_RECEIVER_INDEX
import org.jetbrains.kotlin.ir.EXTENSION_RECEIVER_INDEX
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
@@ -27,16 +28,13 @@ interface IrCallExpression : IrMemberAccessExpression, IrCompoundExpression {
val operator: IrOperator? val operator: IrOperator?
override val descriptor: CallableDescriptor override val descriptor: CallableDescriptor
fun getValueArgument(valueParameterDescriptor: ValueParameterDescriptor): IrExpression? fun getValueArgument(index: Int): IrExpression?
fun putValueArgument(valueParameterDescriptor: ValueParameterDescriptor, valueArgument: IrExpression?) fun putValueArgument(index: Int, valueArgument: IrExpression?)
fun removeValueArgument(valueParameterDescriptor: ValueParameterDescriptor) fun removeValueArgument(index: Int)
fun <D> acceptValueArguments(visitor: IrElementVisitor<Unit, D>, data: D) fun <D> acceptValueArguments(visitor: IrElementVisitor<Unit, D>, data: D)
} }
fun IrCallExpression.getMappedValueArguments(): List<IrExpression?> =
descriptor.valueParameters.mapNotNull { getValueArgument(it) }
class IrCallExpressionImpl( class IrCallExpressionImpl(
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
@@ -49,22 +47,18 @@ class IrCallExpressionImpl(
private val argumentsByParameterIndex = private val argumentsByParameterIndex =
kotlin.arrayOfNulls<IrExpression>(descriptor.valueParameters.size) kotlin.arrayOfNulls<IrExpression>(descriptor.valueParameters.size)
override fun getValueArgument(valueParameterDescriptor: ValueParameterDescriptor): IrExpression? = override fun getValueArgument(index: Int): IrExpression? =
argumentsByParameterIndex[valueParameterDescriptor.index] argumentsByParameterIndex[index]
override fun putValueArgument(valueParameterDescriptor: ValueParameterDescriptor, valueArgument: IrExpression?) { override fun putValueArgument(index: Int, valueArgument: IrExpression?) {
putValueArgument(valueParameterDescriptor.index, valueArgument)
}
private fun putValueArgument(index: Int, valueArgument: IrExpression?) {
argumentsByParameterIndex[index]?.detach() argumentsByParameterIndex[index]?.detach()
argumentsByParameterIndex[index] = valueArgument argumentsByParameterIndex[index] = valueArgument
valueArgument?.setTreeLocation(this, index) valueArgument?.setTreeLocation(this, index)
} }
override fun removeValueArgument(valueParameterDescriptor: ValueParameterDescriptor) { override fun removeValueArgument(index: Int) {
argumentsByParameterIndex[valueParameterDescriptor.index]?.detach() argumentsByParameterIndex[index]?.detach()
argumentsByParameterIndex[valueParameterDescriptor.index] = null argumentsByParameterIndex[index] = null
} }
override fun getChildExpression(index: Int): IrExpression? = override fun getChildExpression(index: Int): IrExpression? =
@@ -16,6 +16,8 @@
package org.jetbrains.kotlin.ir.expressions package org.jetbrains.kotlin.ir.expressions
import org.jetbrains.kotlin.ir.ARGUMENT0_INDEX
import org.jetbrains.kotlin.ir.ARGUMENT1_INDEX
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import java.util.* import java.util.*
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.ir.expressions package org.jetbrains.kotlin.ir.expressions
import org.jetbrains.kotlin.ir.DETACHED_INDEX
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrElementBase import org.jetbrains.kotlin.ir.IrElementBase
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
@@ -0,0 +1,67 @@
/*
* 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.CHILD_DECLARATION_INDEX
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.types.KotlinType
interface IrLocalDeclarationExpression<out D : IrMemberDeclaration> : IrExpression, IrDeclarationOwner1 {
override val childDeclaration: D
}
interface IrLocalVariableDeclarationExpression : IrLocalDeclarationExpression<IrLocalVariable> {
override var childDeclaration: IrLocalVariable
}
abstract class IrLocalDeclarationExpressionBase(
startOffset: Int,
endOffset: Int,
type: KotlinType
) : IrExpressionBase(startOffset, endOffset, type), IrLocalVariableDeclarationExpression {
private var childDeclarationImpl: IrLocalVariable? = null
override var childDeclaration: IrLocalVariable
get() = childDeclarationImpl!!
set(value) {
childDeclarationImpl?.detach()
childDeclarationImpl = value
value.setTreeLocation(this, CHILD_DECLARATION_INDEX)
}
override fun getChildDeclaration(index: Int): IrMemberDeclaration? =
if (index == CHILD_DECLARATION_INDEX) childDeclaration else null
override fun replaceChildDeclaration(oldChild: IrMemberDeclaration, newChild: IrMemberDeclaration) {
if (newChild !is IrLocalVariable) throw AssertionError("IrLocalVariable expected: $newChild")
validateChild(oldChild)
childDeclaration = newChild
}
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
childDeclarationImpl?.accept(visitor, data)
}
}
class IrLocalVariableDeclarationExpressionImpl(
startOffset: Int,
endOffset: Int,
type: KotlinType
) : IrLocalDeclarationExpressionBase(startOffset, endOffset, type), IrLocalVariableDeclarationExpression {
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
visitor.visitLocalVariableDeclarationExpression(this, data)
}
@@ -16,6 +16,8 @@
package org.jetbrains.kotlin.ir.expressions package org.jetbrains.kotlin.ir.expressions
import org.jetbrains.kotlin.ir.DISPATCH_RECEIVER_INDEX
import org.jetbrains.kotlin.ir.EXTENSION_RECEIVER_INDEX
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
interface IrMemberAccessExpression : IrDeclarationReference, IrExpressionOwner { interface IrMemberAccessExpression : IrDeclarationReference, IrExpressionOwner {
@@ -17,11 +17,12 @@
package org.jetbrains.kotlin.ir.expressions package org.jetbrains.kotlin.ir.expressions
enum class IrOperator { enum class IrOperator {
INVOKE, INVOKE_EXTENSION, INVOKE,
PREFIX_INCR, PREFIX_DECR, POSTFIX_INCR, POSTFIX_DECR, PREFIX_INCR, PREFIX_DECR, POSTFIX_INCR, POSTFIX_DECR,
UMINUS, UMINUS,
EXCL, EXCL,
EXCLEXCL, EXCLEXCL,
ELVIS,
LT, GT, LTEQ, GTEQ, LT, GT, LTEQ, GTEQ,
EQEQ, EQEQEQ, EXCLEQ, EXCLEQEQ, EQEQ, EQEQEQ, EXCLEQ, EXCLEQEQ,
IN, NOT_IN, IN, NOT_IN,
@@ -32,32 +33,36 @@ enum class IrOperator {
PLUSEQ, MINUSEQ, MULEQ, DIVEQ, MODEQ; PLUSEQ, MINUSEQ, MULEQ, DIVEQ, MODEQ;
} }
private val CAO_START = IrOperator.PLUSEQ private val CAO_START = IrOperator.PLUSEQ.ordinal
private val CAO_END = IrOperator.MODEQ private val CAO_END = IrOperator.MODEQ.ordinal
private val DUAL_START = IrOperator.PLUS private val DUAL_START = IrOperator.PLUS.ordinal
private val DUAL_END = IrOperator.MOD private val DUAL_END = IrOperator.MOD.ordinal
private val INCR_DECR_START = IrOperator.PREFIX_INCR private val INCR_DECR_START = IrOperator.PREFIX_INCR.ordinal
private val INCR_DECR_END = IrOperator.POSTFIX_DECR private val INCR_DECR_END = IrOperator.POSTFIX_DECR.ordinal
private val RELATIONAL_START = IrOperator.LT.ordinal
private val RELATIONAL_END = IrOperator.GTEQ.ordinal
fun IrOperator.isIncrementOrDecrement(): Boolean = fun IrOperator.isIncrementOrDecrement(): Boolean =
this in INCR_DECR_START..INCR_DECR_END this.ordinal in INCR_DECR_START..INCR_DECR_END
fun IrOperator.isCompoundAssignment(): Boolean = fun IrOperator.isCompoundAssignment(): Boolean =
this in CAO_START .. CAO_END this.ordinal in CAO_START .. CAO_END
fun IrOperator.isAssignmentOrCompoundAssignment(): Boolean = fun IrOperator.isAssignmentOrCompoundAssignment(): Boolean =
this == IrOperator.EQ || isCompoundAssignment() this == IrOperator.EQ || isCompoundAssignment()
fun IrOperator.hasCompoundAssignmentDual(): Boolean = fun IrOperator.hasCompoundAssignmentDual(): Boolean =
this in DUAL_START .. DUAL_END this.ordinal in DUAL_START .. DUAL_END
fun IrOperator.toDualOperator(): IrOperator = fun IrOperator.toDualOperator(): IrOperator =
when { when {
isCompoundAssignment() -> isCompoundAssignment() ->
IrOperator.values()[this.ordinal - CAO_START.ordinal + DUAL_START.ordinal] IrOperator.values()[this.ordinal - CAO_START + DUAL_START]
hasCompoundAssignmentDual() -> hasCompoundAssignmentDual() ->
IrOperator.values()[this.ordinal - DUAL_START.ordinal + CAO_START.ordinal] IrOperator.values()[this.ordinal - DUAL_START + CAO_START]
else -> else ->
throw UnsupportedOperationException("Operator $this is not a compound assignment") throw UnsupportedOperationException("Operator $this is not a compound assignment")
} }
fun IrOperator.isRelational(): Boolean =
this.ordinal in RELATIONAL_START .. RELATIONAL_END
@@ -17,6 +17,9 @@
package org.jetbrains.kotlin.ir.expressions package org.jetbrains.kotlin.ir.expressions
import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.ir.ARGUMENT0_INDEX
import org.jetbrains.kotlin.ir.DISPATCH_RECEIVER_INDEX
import org.jetbrains.kotlin.ir.EXTENSION_RECEIVER_INDEX
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
@@ -50,7 +50,7 @@ class DumpIrTreeVisitor(out: Appendable): IrElementVisitor<Unit, String> {
expression.dispatchReceiver?.accept(this, "\$this") expression.dispatchReceiver?.accept(this, "\$this")
expression.extensionReceiver?.accept(this, "\$receiver") expression.extensionReceiver?.accept(this, "\$receiver")
for (valueParameter in expression.descriptor.valueParameters) { for (valueParameter in expression.descriptor.valueParameters) {
expression.getValueArgument(valueParameter)?.accept(this, valueParameter.name.asString()) expression.getValueArgument(valueParameter.index)?.accept(this, valueParameter.name.asString())
} }
} }
} }
@@ -48,6 +48,9 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
override fun visitPropertySetter(declaration: IrPropertySetter, data: Nothing?): String = override fun visitPropertySetter(declaration: IrPropertySetter, data: Nothing?): String =
"IrPropertySetter ${declaration.descriptor.render()} property=${declaration.property?.name()}" "IrPropertySetter ${declaration.descriptor.render()} property=${declaration.property?.name()}"
override fun visitLocalVariable(declaration: IrLocalVariable, data: Nothing?): String =
"IrLocalVariable ${declaration.descriptor.render()}"
override fun visitExpressionBody(body: IrExpressionBody, data: Nothing?): String = override fun visitExpressionBody(body: IrExpressionBody, data: Nothing?): String =
"IrExpressionBody" "IrExpressionBody"
@@ -57,6 +60,9 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
override fun <T> visitLiteral(expression: IrLiteralExpression<T>, data: Nothing?): String = override fun <T> visitLiteral(expression: IrLiteralExpression<T>, data: Nothing?): String =
"LITERAL ${expression.kind} type=${expression.renderType()} value='${expression.value}'" "LITERAL ${expression.kind} type=${expression.renderType()} value='${expression.value}'"
override fun visitLocalVariableDeclarationExpression(expression: IrLocalVariableDeclarationExpression, data: Nothing?): String =
"LOCAL ${expression.childDeclaration.descriptor.name}"
override fun visitBlockExpression(expression: IrBlockExpression, data: Nothing?): String = override fun visitBlockExpression(expression: IrBlockExpression, data: Nothing?): String =
"BLOCK type=${expression.renderType()}" "BLOCK type=${expression.renderType()}"
@@ -34,6 +34,7 @@ interface IrElementVisitor<out R, in D> {
fun visitProperty(declaration: IrProperty, data: D): R = visitDeclaration(declaration, data) fun visitProperty(declaration: IrProperty, data: D): R = visitDeclaration(declaration, data)
fun visitSimpleProperty(declaration: IrSimpleProperty, data: D): R = visitProperty(declaration, data) fun visitSimpleProperty(declaration: IrSimpleProperty, data: D): R = visitProperty(declaration, data)
fun visitDelegatedProperty(declaration: IrDelegatedProperty, data: D): R = visitProperty(declaration, data) fun visitDelegatedProperty(declaration: IrDelegatedProperty, data: D): R = visitProperty(declaration, data)
fun visitLocalVariable(declaration: IrLocalVariable, data: D) = visitDeclaration(declaration, data)
fun visitBody(body: IrBody, data: D): R = visitElement(body, data) fun visitBody(body: IrBody, data: D): R = visitElement(body, data)
fun visitExpressionBody(body: IrExpressionBody, data: D): R = visitBody(body, data) fun visitExpressionBody(body: IrExpressionBody, data: D): R = visitBody(body, data)
@@ -45,6 +46,11 @@ interface IrElementVisitor<out R, in D> {
fun visitStringTemplate(expression: IrStringConcatenationExpression, data: D) = visitExpression(expression, data) fun visitStringTemplate(expression: IrStringConcatenationExpression, data: D) = visitExpression(expression, data)
fun visitThisExpression(expression: IrThisExpression, data: D) = visitExpression(expression, data) fun visitThisExpression(expression: IrThisExpression, data: D) = visitExpression(expression, data)
fun <T : IrMemberDeclaration> visitLocalDeclarationExpression(expression: IrLocalDeclarationExpression<T>, data: D) =
visitExpression(expression, data)
fun visitLocalVariableDeclarationExpression(expression: IrLocalVariableDeclarationExpression, data: D) =
visitLocalDeclarationExpression(expression, data)
fun visitDeclarationReference(expression: IrDeclarationReference, data: D) = visitExpression(expression, data) fun visitDeclarationReference(expression: IrDeclarationReference, data: D) = visitExpression(expression, data)
fun visitGetObjectValue(expression: IrGetObjectValueExpression, data: D) = visitDeclarationReference(expression, data) fun visitGetObjectValue(expression: IrGetObjectValueExpression, data: D) = visitDeclarationReference(expression, data)
fun visitGetEnumValue(expression: IrGetEnumValueExpression, data: D) = visitDeclarationReference(expression, data) fun visitGetEnumValue(expression: IrGetEnumValueExpression, data: D) = visitDeclarationReference(expression, data)
@@ -65,6 +71,4 @@ interface IrElementVisitor<out R, in D> {
fun visitDummyExpression(expression: IrDummyExpression, data: D) = visitExpression(expression, data) fun visitDummyExpression(expression: IrDummyExpression, data: D) = visitExpression(expression, data)
} }
+1 -2
View File
@@ -1,5 +1,4 @@
IrFile /boxOk.kt IrFile /boxOk.kt
IrFunction public fun box(): kotlin.String IrFunction public fun box(): kotlin.String
IrExpressionBody IrExpressionBody
RETURN type=kotlin.String LITERAL String type=kotlin.String value='OK'
LITERAL String type=kotlin.String value='OK'
@@ -0,0 +1,13 @@
// <<< callWithReorderedArguments.txt
fun foo(a: Int, b: Int) {}
fun noReorder1() = 1
fun noReorder2() = 2
fun reordered1() = 1
fun reordered2() = 2
fun test() {
foo(a = noReorder1(), b = noReorder2())
foo(b = reordered1(), a = reordered2())
}
@@ -0,0 +1,32 @@
IrFile /callWithReorderedArguments.kt
IrFunction public fun foo(/*0*/ a: kotlin.Int, /*1*/ b: kotlin.Int): kotlin.Unit
IrExpressionBody
BLOCK type=kotlin.Unit
IrFunction public fun noReorder1(): kotlin.Int
IrExpressionBody
LITERAL Int type=kotlin.Int value='1'
IrFunction public fun noReorder2(): kotlin.Int
IrExpressionBody
LITERAL Int type=kotlin.Int value='2'
IrFunction public fun reordered1(): kotlin.Int
IrExpressionBody
LITERAL Int type=kotlin.Int value='1'
IrFunction public fun reordered2(): kotlin.Int
IrExpressionBody
LITERAL Int type=kotlin.Int value='2'
IrFunction public fun test(): kotlin.Unit
IrExpressionBody
BLOCK type=kotlin.Unit
CALL .foo
a: CALL .noReorder1
b: CALL .noReorder2
BLOCK type=kotlin.Unit
LOCAL tmp0
IrLocalVariable val tmp0: kotlin.Int
CALL .reordered1
LOCAL tmp1
IrLocalVariable val tmp1: kotlin.Int
CALL .reordered2
CALL .foo
a: GET_VAR tmp1
b: GET_VAR tmp0
+12 -17
View File
@@ -1,29 +1,24 @@
IrFile /calls.kt IrFile /calls.kt
IrFunction public fun foo(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int): kotlin.Int IrFunction public fun foo(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int): kotlin.Int
IrExpressionBody IrExpressionBody
RETURN type=kotlin.Int GET_VAR x
GET_VAR x
IrFunction public fun bar(/*0*/ x: kotlin.Int): kotlin.Int IrFunction public fun bar(/*0*/ x: kotlin.Int): kotlin.Int
IrExpressionBody IrExpressionBody
RETURN type=kotlin.Int CALL .foo
CALL .foo x: GET_VAR x
x: GET_VAR x y: LITERAL Int type=kotlin.Int value='1'
y: LITERAL Int type=kotlin.Int value='1'
IrFunction public fun qux(/*0*/ x: kotlin.Int): kotlin.Int IrFunction public fun qux(/*0*/ x: kotlin.Int): kotlin.Int
IrExpressionBody IrExpressionBody
RETURN type=kotlin.Int CALL .foo
CALL .foo x: CALL .foo
x: CALL .foo x: GET_VAR x
x: GET_VAR x
y: GET_VAR x
y: GET_VAR x y: GET_VAR x
y: GET_VAR x
IrFunction public fun kotlin.Int.ext1(): kotlin.Int IrFunction public fun kotlin.Int.ext1(): kotlin.Int
IrExpressionBody IrExpressionBody
RETURN type=kotlin.Int $RECEIVER of: ext1
$RECEIVER of: ext1
IrFunction public fun kotlin.Int.ext2(/*0*/ x: kotlin.Int): kotlin.Int IrFunction public fun kotlin.Int.ext2(/*0*/ x: kotlin.Int): kotlin.Int
IrExpressionBody IrExpressionBody
RETURN type=kotlin.Int CALL .foo
CALL .foo x: $RECEIVER of: ext2
x: $RECEIVER of: ext2 y: GET_VAR x
y: GET_VAR x
+4 -6
View File
@@ -1,11 +1,9 @@
IrFile /dotQualified.kt IrFile /dotQualified.kt
IrFunction public fun length(/*0*/ s: kotlin.String): kotlin.Int IrFunction public fun length(/*0*/ s: kotlin.String): kotlin.Int
IrExpressionBody IrExpressionBody
RETURN type=kotlin.Int GET_PROPERTY .length
GET_PROPERTY .length $this: GET_VAR s
$this: GET_VAR s
IrFunction public fun lengthN(/*0*/ s: kotlin.String?): kotlin.Int? IrFunction public fun lengthN(/*0*/ s: kotlin.String?): kotlin.Int?
IrExpressionBody IrExpressionBody
RETURN type=kotlin.Int? GET_PROPERTY ?.length
GET_PROPERTY ?.length $this: GET_VAR s
$this: GET_VAR s
@@ -2,10 +2,8 @@ IrFile /extensionPropertyGetterCall.kt
IrProperty public val kotlin.String.okext: kotlin.String getter=<get-okext> setter=null IrProperty public val kotlin.String.okext: kotlin.String getter=<get-okext> setter=null
IrPropertyGetter public fun kotlin.String.<get-okext>(): kotlin.String property=okext IrPropertyGetter public fun kotlin.String.<get-okext>(): kotlin.String property=okext
IrExpressionBody IrExpressionBody
RETURN type=kotlin.String LITERAL String type=kotlin.String value='OK'
LITERAL String type=kotlin.String value='OK'
IrFunction public fun kotlin.String.test5(): kotlin.String IrFunction public fun kotlin.String.test5(): kotlin.String
IrExpressionBody IrExpressionBody
RETURN type=kotlin.String GET_PROPERTY .okext
GET_PROPERTY .okext $receiver: $RECEIVER of: test5
$receiver: $RECEIVER of: test5
+9 -17
View File
@@ -1,25 +1,20 @@
IrFile /references.kt IrFile /references.kt
IrProperty public val ok: kotlin.String = "OK" getter=null setter=null IrProperty public val ok: kotlin.String = "OK" getter=null setter=null
IrExpressionBody IrExpressionBody
RETURN type=kotlin.String LITERAL String type=kotlin.String value='OK'
LITERAL String type=kotlin.String value='OK'
IrProperty public val ok2: kotlin.String = "OK" getter=null setter=null IrProperty public val ok2: kotlin.String = "OK" getter=null setter=null
IrExpressionBody IrExpressionBody
RETURN type=kotlin.String GET_PROPERTY .ok
GET_PROPERTY .ok
IrProperty public val ok3: kotlin.String getter=<get-ok3> setter=null IrProperty public val ok3: kotlin.String getter=<get-ok3> setter=null
IrPropertyGetter public fun <get-ok3>(): kotlin.String property=ok3 IrPropertyGetter public fun <get-ok3>(): kotlin.String property=ok3
IrExpressionBody IrExpressionBody
RETURN type=kotlin.String LITERAL String type=kotlin.String value='OK'
LITERAL String type=kotlin.String value='OK'
IrFunction public fun test1(): kotlin.String IrFunction public fun test1(): kotlin.String
IrExpressionBody IrExpressionBody
RETURN type=kotlin.String GET_PROPERTY .ok
GET_PROPERTY .ok
IrFunction public fun test2(/*0*/ x: kotlin.String): kotlin.String IrFunction public fun test2(/*0*/ x: kotlin.String): kotlin.String
IrExpressionBody IrExpressionBody
RETURN type=kotlin.String GET_VAR x
GET_VAR x
IrFunction public fun test3(): kotlin.String IrFunction public fun test3(): kotlin.String
IrExpressionBody IrExpressionBody
BLOCK type=kotlin.Nothing BLOCK type=kotlin.Nothing
@@ -28,15 +23,12 @@ IrFile /references.kt
GET_VAR x GET_VAR x
IrFunction public fun test4(): kotlin.String IrFunction public fun test4(): kotlin.String
IrExpressionBody IrExpressionBody
RETURN type=kotlin.String GET_PROPERTY .ok3
GET_PROPERTY .ok3
IrProperty public val kotlin.String.okext: kotlin.String getter=<get-okext> setter=null IrProperty public val kotlin.String.okext: kotlin.String getter=<get-okext> setter=null
IrPropertyGetter public fun kotlin.String.<get-okext>(): kotlin.String property=okext IrPropertyGetter public fun kotlin.String.<get-okext>(): kotlin.String property=okext
IrExpressionBody IrExpressionBody
RETURN type=kotlin.String LITERAL String type=kotlin.String value='OK'
LITERAL String type=kotlin.String value='OK'
IrFunction public fun kotlin.String.test5(): kotlin.String IrFunction public fun kotlin.String.test5(): kotlin.String
IrExpressionBody IrExpressionBody
RETURN type=kotlin.String GET_PROPERTY .okext
GET_PROPERTY .okext $receiver: $RECEIVER of: test5
$receiver: $RECEIVER of: test5
+1 -2
View File
@@ -1,4 +1,3 @@
IrProperty public val testSimpleVal: kotlin.Int = 1 getter=null setter=null IrProperty public val testSimpleVal: kotlin.Int = 1 getter=null setter=null
IrExpressionBody IrExpressionBody
RETURN type=kotlin.Int LITERAL Int type=kotlin.Int value='1'
LITERAL Int type=kotlin.Int value='1'
+4 -8
View File
@@ -6,22 +6,18 @@ IrFile /smoke.kt
LITERAL String type=kotlin.String value='OK' LITERAL String type=kotlin.String value='OK'
IrProperty public val testSimpleVal: kotlin.Int = 1 getter=null setter=null IrProperty public val testSimpleVal: kotlin.Int = 1 getter=null setter=null
IrExpressionBody IrExpressionBody
RETURN type=kotlin.Int LITERAL Int type=kotlin.Int value='1'
LITERAL Int type=kotlin.Int value='1'
IrProperty public val testValWithGetter: kotlin.Int getter=<get-testValWithGetter> setter=null IrProperty public val testValWithGetter: kotlin.Int getter=<get-testValWithGetter> setter=null
IrPropertyGetter public fun <get-testValWithGetter>(): kotlin.Int property=testValWithGetter IrPropertyGetter public fun <get-testValWithGetter>(): kotlin.Int property=testValWithGetter
IrExpressionBody IrExpressionBody
RETURN type=kotlin.Int LITERAL Int type=kotlin.Int value='42'
LITERAL Int type=kotlin.Int value='42'
IrProperty public var testSimpleVar: kotlin.Int getter=null setter=null IrProperty public var testSimpleVar: kotlin.Int getter=null setter=null
IrExpressionBody IrExpressionBody
RETURN type=kotlin.Int LITERAL Int type=kotlin.Int value='2'
LITERAL Int type=kotlin.Int value='2'
IrProperty public var testVarWithAccessors: kotlin.Int getter=<get-testVarWithAccessors> setter=<set-testVarWithAccessors> IrProperty public var testVarWithAccessors: kotlin.Int getter=<get-testVarWithAccessors> setter=<set-testVarWithAccessors>
IrPropertyGetter public fun <get-testVarWithAccessors>(): kotlin.Int property=testVarWithAccessors IrPropertyGetter public fun <get-testVarWithAccessors>(): kotlin.Int property=testVarWithAccessors
IrExpressionBody IrExpressionBody
RETURN type=kotlin.Int LITERAL Int type=kotlin.Int value='42'
LITERAL Int type=kotlin.Int value='42'
IrPropertySetter public fun <set-testVarWithAccessors>(/*0*/ v: kotlin.Int): kotlin.Unit property=testVarWithAccessors IrPropertySetter public fun <set-testVarWithAccessors>(/*0*/ v: kotlin.Int): kotlin.Unit property=testVarWithAccessors
IrExpressionBody IrExpressionBody
BLOCK type=kotlin.Unit BLOCK type=kotlin.Unit
@@ -41,6 +41,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("callWithReorderedArguments.kt")
public void testCallWithReorderedArguments() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/callWithReorderedArguments.kt");
doTest(fileName);
}
@TestMetadata("calls.kt") @TestMetadata("calls.kt")
public void testCalls() throws Exception { public void testCalls() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/calls.kt"); String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/calls.kt");