Formatting: psi2ir

This commit is contained in:
Dmitry Petrov
2018-01-11 14:09:11 +03:00
parent 432c743771
commit 1f841e35bc
48 changed files with 1827 additions and 1614 deletions
-1
View File
@@ -1,4 +1,3 @@
apply { plugin("kotlin") } apply { plugin("kotlin") }
jvmTarget = "1.6" jvmTarget = "1.6"
@@ -21,5 +21,5 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
fun IrVariable.defaultLoad(): IrExpression = fun IrVariable.defaultLoad(): IrExpression =
IrGetValueImpl(startOffset, endOffset, symbol) IrGetValueImpl(startOffset, endOffset, symbol)
@@ -40,16 +40,16 @@ import org.jetbrains.kotlin.types.TypeUtils
import java.lang.Exception import java.lang.Exception
fun KotlinType.containsNull() = fun KotlinType.containsNull() =
TypeUtils.isNullableType(this) TypeUtils.isNullableType(this)
fun KtElement.deparenthesize(): KtElement = fun KtElement.deparenthesize(): KtElement =
if (this is KtExpression) KtPsiUtil.safeDeparenthesize(this) else this if (this is KtExpression) KtPsiUtil.safeDeparenthesize(this) else this
fun ResolvedCall<*>.isValueArgumentReorderingRequired(): Boolean { fun ResolvedCall<*>.isValueArgumentReorderingRequired(): Boolean {
var lastValueParameterIndex = -1 var lastValueParameterIndex = -1
for (valueArgument in call.valueArguments) { for (valueArgument in call.valueArguments) {
val argumentMapping = getArgumentMapping(valueArgument) as? ArgumentMatch ?: val argumentMapping =
throw Exception("Value argument in function call is mapped with error") getArgumentMapping(valueArgument) as? ArgumentMatch ?: throw Exception("Value argument in function call is mapped with error")
val argumentIndex = argumentMapping.valueParameter.index val argumentIndex = argumentMapping.valueParameter.index
if (argumentIndex < lastValueParameterIndex) { if (argumentIndex < lastValueParameterIndex) {
return true return true
@@ -68,16 +68,16 @@ fun KtSecondaryConstructor.isConstructorDelegatingToSuper(bindingContext: Bindin
} }
inline fun ClassDescriptor.findFirstFunction(name: String, predicate: (CallableMemberDescriptor) -> Boolean) = inline fun ClassDescriptor.findFirstFunction(name: String, predicate: (CallableMemberDescriptor) -> Boolean) =
unsubstitutedMemberScope.findFirstFunction(name, predicate) unsubstitutedMemberScope.findFirstFunction(name, predicate)
inline fun MemberScope.findFirstFunction(name: String, predicate: (CallableMemberDescriptor) -> Boolean) = inline fun MemberScope.findFirstFunction(name: String, predicate: (CallableMemberDescriptor) -> Boolean) =
getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).first(predicate) getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).first(predicate)
fun MemberScope.findSingleFunction(name: Name): FunctionDescriptor = fun MemberScope.findSingleFunction(name: Name): FunctionDescriptor =
getContributedFunctions(name, NoLookupLocation.FROM_BACKEND).single() getContributedFunctions(name, NoLookupLocation.FROM_BACKEND).single()
fun KotlinBuiltIns.findSingleFunction(name: Name): FunctionDescriptor = fun KotlinBuiltIns.findSingleFunction(name: Name): FunctionDescriptor =
builtInsPackageScope.findSingleFunction(name) builtInsPackageScope.findSingleFunction(name)
val PsiElement?.startOffsetOrUndefined get() = this?.startOffset ?: UNDEFINED_OFFSET val PsiElement?.startOffsetOrUndefined get() = this?.startOffset ?: UNDEFINED_OFFSET
val PsiElement?.endOffsetOrUndefined get() = this?.endOffset ?: UNDEFINED_OFFSET val PsiElement?.endOffsetOrUndefined get() = this?.endOffset ?: UNDEFINED_OFFSET
@@ -17,5 +17,5 @@
package org.jetbrains.kotlin.psi2ir package org.jetbrains.kotlin.psi2ir
class Psi2IrConfiguration( class Psi2IrConfiguration(
val ignoreErrors: Boolean = false val ignoreErrors: Boolean = false
) )
@@ -43,7 +43,7 @@ class Psi2IrTranslator(val configuration: Psi2IrConfiguration = Psi2IrConfigurat
} }
fun createGeneratorContext(moduleDescriptor: ModuleDescriptor, bindingContext: BindingContext) = fun createGeneratorContext(moduleDescriptor: ModuleDescriptor, bindingContext: BindingContext) =
GeneratorContext(configuration, moduleDescriptor, bindingContext) GeneratorContext(configuration, moduleDescriptor, bindingContext)
fun generateModuleFragment(context: GeneratorContext, ktFiles: Collection<KtFile>): IrModuleFragment { fun generateModuleFragment(context: GeneratorContext, ktFiles: Collection<KtFile>): IrModuleFragment {
val irModule = ModuleGenerator(context).generateModuleFragment(ktFiles) val irModule = ModuleGenerator(context).generateModuleFragment(ktFiles)
@@ -35,9 +35,9 @@ class PsiSourceManager : SourceManager {
maxOffset = document.textLength maxOffset = document.textLength
lineStartOffsets = (0 .. document.lineCount - 1) lineStartOffsets = (0..document.lineCount - 1)
.map { document.getLineStartOffset(it) } .map { document.getLineStartOffset(it) }
.toIntArray() .toIntArray()
} }
override fun getLineNumber(offset: Int): Int { override fun getLineNumber(offset: Int): Int {
@@ -53,15 +53,15 @@ class PsiSourceManager : SourceManager {
} }
override fun getSourceRangeInfo(beginOffset: Int, endOffset: Int): SourceRangeInfo = override fun getSourceRangeInfo(beginOffset: Int, endOffset: Int): SourceRangeInfo =
SourceRangeInfo( SourceRangeInfo(
filePath = getRecognizableName(), filePath = getRecognizableName(),
startOffset = beginOffset, startOffset = beginOffset,
startLineNumber = getLineNumber(beginOffset), startLineNumber = getLineNumber(beginOffset),
startColumnNumber = getColumnNumber(beginOffset), startColumnNumber = getColumnNumber(beginOffset),
endOffset = endOffset, endOffset = endOffset,
endLineNumber = getLineNumber(endOffset), endLineNumber = getLineNumber(endOffset),
endColumnNumber = getColumnNumber(endOffset) endColumnNumber = getColumnNumber(endOffset)
) )
private fun getRecognizableName(): String = psiFileName private fun getRecognizableName(): String = psiFileName
@@ -87,14 +87,14 @@ class PsiSourceManager : SourceManager {
} }
fun getOrCreateFileEntry(ktFile: KtFile): PsiFileEntry = fun getOrCreateFileEntry(ktFile: KtFile): PsiFileEntry =
fileEntriesByKtFile.getOrElse(ktFile) { createFileEntry(ktFile) } fileEntriesByKtFile.getOrElse(ktFile) { createFileEntry(ktFile) }
fun getKtFile(fileEntry: PsiFileEntry): KtFile? = fun getKtFile(fileEntry: PsiFileEntry): KtFile? =
ktFileByFileEntry[fileEntry] ktFileByFileEntry[fileEntry]
fun getKtFile(irFile: IrFile): KtFile? = fun getKtFile(irFile: IrFile): KtFile? =
(irFile.fileEntry as? PsiFileEntry)?.let { ktFileByFileEntry[it] } (irFile.fileEntry as? PsiFileEntry)?.let { ktFileByFileEntry[it] }
override fun getFileEntry(irFile: IrFile): SourceManager.FileEntry = override fun getFileEntry(irFile: IrFile): SourceManager.FileEntry =
fileEntriesByIrFile[irFile]!! fileEntriesByIrFile[irFile]!!
} }
@@ -26,20 +26,22 @@ import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset
class AnonymousInitializerGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGeneratorExtension(declarationGenerator) { class AnonymousInitializerGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGeneratorExtension(declarationGenerator) {
fun generateAnonymousInitializerDeclaration(ktAnonymousInitializer: KtAnonymousInitializer, classDescriptor: ClassDescriptor): IrDeclaration = fun generateAnonymousInitializerDeclaration(
context.symbolTable.declareAnonymousInitializer( ktAnonymousInitializer: KtAnonymousInitializer,
ktAnonymousInitializer.startOffset, ktAnonymousInitializer.endOffset, IrDeclarationOrigin.DEFINED, classDescriptor classDescriptor: ClassDescriptor
).buildWithScope { irAnonymousInitializer -> ): IrDeclaration =
val bodyGenerator = createBodyGenerator(irAnonymousInitializer.symbol) context.symbolTable.declareAnonymousInitializer(
val statementGenerator = bodyGenerator.createStatementGenerator() ktAnonymousInitializer.startOffset, ktAnonymousInitializer.endOffset, IrDeclarationOrigin.DEFINED, classDescriptor
val ktBody = ktAnonymousInitializer.body!! ).buildWithScope { irAnonymousInitializer ->
val irBlockBody = IrBlockBodyImpl(ktBody.startOffset, ktBody.endOffset) val bodyGenerator = createBodyGenerator(irAnonymousInitializer.symbol)
if (ktBody is KtBlockExpression) { val statementGenerator = bodyGenerator.createStatementGenerator()
statementGenerator.generateStatements(ktBody.statements, irBlockBody) val ktBody = ktAnonymousInitializer.body!!
} val irBlockBody = IrBlockBodyImpl(ktBody.startOffset, ktBody.endOffset)
else { if (ktBody is KtBlockExpression) {
irBlockBody.statements.add(statementGenerator.generateStatement(ktBody)) statementGenerator.generateStatements(ktBody.statements, irBlockBody)
} } else {
irAnonymousInitializer.body = irBlockBody irBlockBody.statements.add(statementGenerator.generateStatement(ktBody))
} }
irAnonymousInitializer.body = irBlockBody
}
} }
@@ -41,94 +41,113 @@ import org.jetbrains.kotlin.types.TypeSubstitutor
import java.lang.AssertionError import java.lang.AssertionError
fun StatementGenerator.generateReceiverOrNull(ktDefaultElement: KtElement, receiver: ReceiverValue?): IntermediateValue? = fun StatementGenerator.generateReceiverOrNull(ktDefaultElement: KtElement, receiver: ReceiverValue?): IntermediateValue? =
receiver?.let { generateReceiver(ktDefaultElement, receiver) } receiver?.let { generateReceiver(ktDefaultElement, receiver) }
fun StatementGenerator.generateReceiver(ktDefaultElement: KtElement, receiver: ReceiverValue): IntermediateValue = fun StatementGenerator.generateReceiver(ktDefaultElement: KtElement, receiver: ReceiverValue): IntermediateValue =
generateReceiver(ktDefaultElement.startOffset, ktDefaultElement.endOffset, receiver) generateReceiver(ktDefaultElement.startOffset, ktDefaultElement.endOffset, receiver)
fun StatementGenerator.generateReceiver(defaultStartOffset: Int, defaultEndOffset: Int, receiver: ReceiverValue): IntermediateValue = fun StatementGenerator.generateReceiver(defaultStartOffset: Int, defaultEndOffset: Int, receiver: ReceiverValue): IntermediateValue =
if (receiver is TransientReceiver) if (receiver is TransientReceiver)
TransientReceiverValue(receiver.type) TransientReceiverValue(receiver.type)
else generateDelegatedValue(receiver.type) { else generateDelegatedValue(receiver.type) {
val receiverExpression = when (receiver) { val receiverExpression = when (receiver) {
is ImplicitClassReceiver -> { is ImplicitClassReceiver -> {
val receiverClassDescriptor = receiver.classDescriptor val receiverClassDescriptor = receiver.classDescriptor
if (shouldGenerateReceiverAsSingletonReference(receiverClassDescriptor)) if (shouldGenerateReceiverAsSingletonReference(receiverClassDescriptor))
generateSingletonReference(receiverClassDescriptor, defaultStartOffset, defaultEndOffset, receiver.type) generateSingletonReference(receiverClassDescriptor, defaultStartOffset, defaultEndOffset, receiver.type)
else else
IrGetValueImpl(defaultStartOffset, defaultEndOffset, IrGetValueImpl(
context.symbolTable.referenceValueParameter(receiverClassDescriptor.thisAsReceiverParameter)) defaultStartOffset, defaultEndOffset,
} context.symbolTable.referenceValueParameter(receiverClassDescriptor.thisAsReceiverParameter)
is ThisClassReceiver -> )
generateThisOrSuperReceiver(receiver, receiver.classDescriptor)
is SuperCallReceiverValue ->
generateThisOrSuperReceiver(receiver, receiver.thisType.constructor.declarationDescriptor as ClassDescriptor)
is ExpressionReceiver ->
generateExpression(receiver.expression)
is ClassValueReceiver ->
IrGetObjectValueImpl(receiver.expression.startOffset, receiver.expression.endOffset, receiver.type,
context.symbolTable.referenceClass(receiver.classQualifier.descriptor as ClassDescriptor))
is ExtensionReceiver ->
IrGetValueImpl(defaultStartOffset, defaultStartOffset,
context.symbolTable.referenceValueParameter(receiver.declarationDescriptor.extensionReceiverParameter!!))
else ->
TODO("Receiver: ${receiver::class.java.simpleName}")
} }
is ThisClassReceiver ->
if (receiverExpression is IrExpressionWithCopy) generateThisOrSuperReceiver(receiver, receiver.classDescriptor)
RematerializableValue(receiverExpression) is SuperCallReceiverValue ->
else generateThisOrSuperReceiver(receiver, receiver.thisType.constructor.declarationDescriptor as ClassDescriptor)
OnceExpressionValue(receiverExpression) is ExpressionReceiver ->
generateExpression(receiver.expression)
is ClassValueReceiver ->
IrGetObjectValueImpl(
receiver.expression.startOffset, receiver.expression.endOffset, receiver.type,
context.symbolTable.referenceClass(receiver.classQualifier.descriptor as ClassDescriptor)
)
is ExtensionReceiver ->
IrGetValueImpl(
defaultStartOffset, defaultStartOffset,
context.symbolTable.referenceValueParameter(receiver.declarationDescriptor.extensionReceiverParameter!!)
)
else ->
TODO("Receiver: ${receiver::class.java.simpleName}")
} }
fun StatementGenerator.generateSingletonReference(descriptor: ClassDescriptor, startOffset: Int, endOffset: Int, type: KotlinType): IrDeclarationReference = if (receiverExpression is IrExpressionWithCopy)
when { RematerializableValue(receiverExpression)
DescriptorUtils.isObject(descriptor) -> else
IrGetObjectValueImpl(startOffset, endOffset, type, OnceExpressionValue(receiverExpression)
context.symbolTable.referenceClass(descriptor)) }
DescriptorUtils.isEnumEntry(descriptor) ->
IrGetEnumValueImpl(startOffset, endOffset, type, fun StatementGenerator.generateSingletonReference(
context.symbolTable.referenceEnumEntry(descriptor)) descriptor: ClassDescriptor,
else -> { startOffset: Int,
val companionObjectDescriptor = descriptor.companionObjectDescriptor endOffset: Int,
?: throw java.lang.AssertionError("Class value without companion object: $descriptor") type: KotlinType
IrGetObjectValueImpl(startOffset, endOffset, type, ): IrDeclarationReference =
context.symbolTable.referenceClass(companionObjectDescriptor)) when {
} DescriptorUtils.isObject(descriptor) ->
IrGetObjectValueImpl(
startOffset, endOffset, type,
context.symbolTable.referenceClass(descriptor)
)
DescriptorUtils.isEnumEntry(descriptor) ->
IrGetEnumValueImpl(
startOffset, endOffset, type,
context.symbolTable.referenceEnumEntry(descriptor)
)
else -> {
val companionObjectDescriptor = descriptor.companionObjectDescriptor
?: throw java.lang.AssertionError("Class value without companion object: $descriptor")
IrGetObjectValueImpl(
startOffset, endOffset, type,
context.symbolTable.referenceClass(companionObjectDescriptor)
)
} }
}
private fun StatementGenerator.shouldGenerateReceiverAsSingletonReference(receiverClassDescriptor: ClassDescriptor): Boolean { private fun StatementGenerator.shouldGenerateReceiverAsSingletonReference(receiverClassDescriptor: ClassDescriptor): Boolean {
return receiverClassDescriptor.kind.isSingleton && return receiverClassDescriptor.kind.isSingleton &&
this.scopeOwner != receiverClassDescriptor && //For anonymous initializers this.scopeOwner != receiverClassDescriptor && //For anonymous initializers
this.scopeOwner.containingDeclaration != receiverClassDescriptor this.scopeOwner.containingDeclaration != receiverClassDescriptor
} }
private fun StatementGenerator.generateThisOrSuperReceiver(receiver: ReceiverValue, classDescriptor: ClassDescriptor): IrExpression { private fun StatementGenerator.generateThisOrSuperReceiver(receiver: ReceiverValue, classDescriptor: ClassDescriptor): IrExpression {
val expressionReceiver = receiver as? ExpressionReceiver ?: val expressionReceiver =
throw AssertionError("'this' or 'super' receiver should be an expression receiver") receiver as? ExpressionReceiver ?: throw AssertionError("'this' or 'super' receiver should be an expression receiver")
val ktReceiver = expressionReceiver.expression val ktReceiver = expressionReceiver.expression
return IrGetValueImpl(ktReceiver.startOffset, ktReceiver.endOffset, return IrGetValueImpl(
context.symbolTable.referenceValueParameter(classDescriptor.thisAsReceiverParameter)) ktReceiver.startOffset, ktReceiver.endOffset,
context.symbolTable.referenceValueParameter(classDescriptor.thisAsReceiverParameter)
)
} }
fun StatementGenerator.generateBackingFieldReceiver( fun StatementGenerator.generateBackingFieldReceiver(
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
resolvedCall: ResolvedCall<*>?, resolvedCall: ResolvedCall<*>?,
fieldDescriptor: SyntheticFieldDescriptor fieldDescriptor: SyntheticFieldDescriptor
): IntermediateValue? { ): IntermediateValue? {
val receiver = resolvedCall?.dispatchReceiver ?: fieldDescriptor.getDispatchReceiverForBackend() ?: return null val receiver = resolvedCall?.dispatchReceiver ?: fieldDescriptor.getDispatchReceiverForBackend() ?: return null
return this.generateReceiver(startOffset, endOffset, receiver) return this.generateReceiver(startOffset, endOffset, receiver)
} }
fun StatementGenerator.generateCallReceiver( fun StatementGenerator.generateCallReceiver(
ktDefaultElement: KtElement, ktDefaultElement: KtElement,
calleeDescriptor: CallableDescriptor, calleeDescriptor: CallableDescriptor,
dispatchReceiver: ReceiverValue?, dispatchReceiver: ReceiverValue?,
extensionReceiver: ReceiverValue?, extensionReceiver: ReceiverValue?,
isSafe: Boolean, isSafe: Boolean,
isAssignmentReceiver: Boolean = false isAssignmentReceiver: Boolean = false
) : CallReceiver { ): CallReceiver {
val dispatchReceiverValue: IntermediateValue? val dispatchReceiverValue: IntermediateValue?
val extensionReceiverValue: IntermediateValue? val extensionReceiverValue: IntermediateValue?
when (calleeDescriptor) { when (calleeDescriptor) {
@@ -136,13 +155,14 @@ fun StatementGenerator.generateCallReceiver(
assert(dispatchReceiver == null) { assert(dispatchReceiver == null) {
"Call for member imported from object $calleeDescriptor has non-null dispatch receiver $dispatchReceiver" "Call for member imported from object $calleeDescriptor has non-null dispatch receiver $dispatchReceiver"
} }
dispatchReceiverValue = generateReceiverForCalleeImportedFromObject(ktDefaultElement.startOffset, ktDefaultElement.endOffset, calleeDescriptor) dispatchReceiverValue =
generateReceiverForCalleeImportedFromObject(ktDefaultElement.startOffset, ktDefaultElement.endOffset, calleeDescriptor)
extensionReceiverValue = generateReceiverOrNull(ktDefaultElement, extensionReceiver) extensionReceiverValue = generateReceiverOrNull(ktDefaultElement, extensionReceiver)
} }
is TypeAliasConstructorDescriptor -> { is TypeAliasConstructorDescriptor -> {
assert(!(dispatchReceiver != null && extensionReceiver != null)) { assert(!(dispatchReceiver != null && extensionReceiver != null)) {
"Type alias constructor call for $calleeDescriptor can't have both dispatch receiver and extension receiver: " + "Type alias constructor call for $calleeDescriptor can't have both dispatch receiver and extension receiver: " +
"$dispatchReceiver, $extensionReceiver" "$dispatchReceiver, $extensionReceiver"
} }
dispatchReceiverValue = generateReceiverOrNull(ktDefaultElement, extensionReceiver ?: dispatchReceiver) dispatchReceiverValue = generateReceiverOrNull(ktDefaultElement, extensionReceiver ?: dispatchReceiver)
extensionReceiverValue = null extensionReceiverValue = null
@@ -156,28 +176,35 @@ fun StatementGenerator.generateCallReceiver(
return when { return when {
!isSafe -> !isSafe ->
SimpleCallReceiver(dispatchReceiverValue, extensionReceiverValue) SimpleCallReceiver(dispatchReceiverValue, extensionReceiverValue)
extensionReceiverValue != null || dispatchReceiverValue != null-> extensionReceiverValue != null || dispatchReceiverValue != null ->
SafeCallReceiver(this, ktDefaultElement.startOffset, ktDefaultElement.endOffset, SafeCallReceiver(
extensionReceiverValue, dispatchReceiverValue, isAssignmentReceiver) this, ktDefaultElement.startOffset, ktDefaultElement.endOffset,
extensionReceiverValue, dispatchReceiverValue, isAssignmentReceiver
)
else -> else ->
throw AssertionError("Safe call should have an explicit receiver: ${ktDefaultElement.text}") throw AssertionError("Safe call should have an explicit receiver: ${ktDefaultElement.text}")
} }
} }
private fun StatementGenerator.generateReceiverForCalleeImportedFromObject( private fun StatementGenerator.generateReceiverForCalleeImportedFromObject(
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
calleeDescriptor: ImportedFromObjectCallableDescriptor<*> calleeDescriptor: ImportedFromObjectCallableDescriptor<*>
): ExpressionValue { ): ExpressionValue {
val objectDescriptor = calleeDescriptor.containingObject val objectDescriptor = calleeDescriptor.containingObject
val objectType = objectDescriptor.defaultType val objectType = objectDescriptor.defaultType
return generateExpressionValue(objectType) { return generateExpressionValue(objectType) {
IrGetObjectValueImpl(startOffset, endOffset, objectType, IrGetObjectValueImpl(
context.symbolTable.referenceClass(objectDescriptor)) startOffset, endOffset, objectType,
context.symbolTable.referenceClass(objectDescriptor)
)
} }
} }
fun StatementGenerator.generateVarargExpression(varargArgument: VarargValueArgument, valueParameter: ValueParameterDescriptor) : IrExpression? { fun StatementGenerator.generateVarargExpression(
varargArgument: VarargValueArgument,
valueParameter: ValueParameterDescriptor
): IrExpression? {
if (varargArgument.arguments.isEmpty()) { if (varargArgument.arguments.isEmpty()) {
return null return null
} }
@@ -189,20 +216,22 @@ fun StatementGenerator.generateVarargExpression(varargArgument: VarargValueArgum
Math.max(maxEndOffset, argument.asElement().endOffset) Math.max(maxEndOffset, argument.asElement().endOffset)
} }
val varargElementType = valueParameter.varargElementType ?: val varargElementType =
throw AssertionError("Vararg argument for non-vararg parameter $valueParameter") valueParameter.varargElementType ?: throw AssertionError("Vararg argument for non-vararg parameter $valueParameter")
val irVararg = IrVarargImpl(varargStartOffset, varargEndOffset, valueParameter.type, varargElementType) val irVararg = IrVarargImpl(varargStartOffset, varargEndOffset, valueParameter.type, varargElementType)
for (argument in varargArgument.arguments) { for (argument in varargArgument.arguments) {
val ktArgumentExpression = argument.getArgumentExpression() ?: val ktArgumentExpression = argument.getArgumentExpression()
throw AssertionError("No argument expression for vararg element ${argument.asElement().text}") ?: throw AssertionError("No argument expression for vararg element ${argument.asElement().text}")
val irVarargElement = val irVarargElement =
if (argument.getSpreadElement() != null) if (argument.getSpreadElement() != null)
IrSpreadElementImpl(ktArgumentExpression.startOffset, ktArgumentExpression.endOffset, IrSpreadElementImpl(
generateExpression(ktArgumentExpression)) ktArgumentExpression.startOffset, ktArgumentExpression.endOffset,
else
generateExpression(ktArgumentExpression) generateExpression(ktArgumentExpression)
)
else
generateExpression(ktArgumentExpression)
irVararg.addElement(irVarargElement) irVararg.addElement(irVarargElement)
} }
@@ -210,17 +239,20 @@ fun StatementGenerator.generateVarargExpression(varargArgument: VarargValueArgum
return irVararg return irVararg
} }
fun StatementGenerator.generateValueArgument(valueArgument: ResolvedValueArgument, valueParameter: ValueParameterDescriptor): IrExpression? = fun StatementGenerator.generateValueArgument(
when (valueArgument) { valueArgument: ResolvedValueArgument,
is DefaultValueArgument -> valueParameter: ValueParameterDescriptor
null ): IrExpression? =
is ExpressionValueArgument -> when (valueArgument) {
generateExpression(valueArgument.valueArgument!!.getArgumentExpression()!!) is DefaultValueArgument ->
is VarargValueArgument -> null
generateVarargExpression(valueArgument, valueParameter) is ExpressionValueArgument ->
else -> generateExpression(valueArgument.valueArgument!!.getArgumentExpression()!!)
TODO("Unexpected valueArgument: ${valueArgument::class.java.simpleName}") is VarargValueArgument ->
} generateVarargExpression(valueArgument, valueParameter)
else ->
TODO("Unexpected valueArgument: ${valueArgument::class.java.simpleName}")
}
fun Generator.getSuperQualifier(resolvedCall: ResolvedCall<*>): ClassDescriptor? { fun Generator.getSuperQualifier(resolvedCall: ResolvedCall<*>): ClassDescriptor? {
val superCallExpression = getSuperCallExpression(resolvedCall.call) ?: return null val superCallExpression = getSuperCallExpression(resolvedCall.call) ?: return null
@@ -239,11 +271,12 @@ fun StatementGenerator.pregenerateCall(resolvedCall: ResolvedCall<*>): CallBuild
fun StatementGenerator.pregenerateExtensionInvokeCall(resolvedCall: ResolvedCall<*>): CallBuilder { fun StatementGenerator.pregenerateExtensionInvokeCall(resolvedCall: ResolvedCall<*>): CallBuilder {
val extensionInvoke = resolvedCall.resultingDescriptor val extensionInvoke = resolvedCall.resultingDescriptor
val functionNClass = extensionInvoke.containingDeclaration as? ClassDescriptor ?: val functionNClass = extensionInvoke.containingDeclaration as? ClassDescriptor
throw AssertionError("'invoke' should be a class member: $extensionInvoke") ?: throw AssertionError("'invoke' should be a class member: $extensionInvoke")
val unsubstitutedPlainInvokes = functionNClass.unsubstitutedMemberScope.getContributedFunctions(extensionInvoke.name, NoLookupLocation.FROM_BACKEND) val unsubstitutedPlainInvokes =
val unsubstitutedPlainInvoke = unsubstitutedPlainInvokes.singleOrNull() ?: functionNClass.unsubstitutedMemberScope.getContributedFunctions(extensionInvoke.name, NoLookupLocation.FROM_BACKEND)
throw AssertionError("There should be a single 'invoke' in FunctionN class: $unsubstitutedPlainInvokes") val unsubstitutedPlainInvoke = unsubstitutedPlainInvokes.singleOrNull()
?: throw AssertionError("There should be a single 'invoke' in FunctionN class: $unsubstitutedPlainInvokes")
val expectedValueParametersCount = extensionInvoke.valueParameters.size + 1 val expectedValueParametersCount = extensionInvoke.valueParameters.size + 1
assert(unsubstitutedPlainInvoke.valueParameters.size == expectedValueParametersCount) { assert(unsubstitutedPlainInvoke.valueParameters.size == expectedValueParametersCount) {
@@ -251,29 +284,31 @@ fun StatementGenerator.pregenerateExtensionInvokeCall(resolvedCall: ResolvedCall
} }
val functionNType = extensionInvoke.dispatchReceiverParameter!!.type val functionNType = extensionInvoke.dispatchReceiverParameter!!.type
val plainInvoke = unsubstitutedPlainInvoke.substitute(TypeSubstitutor.create(functionNType)) ?: val plainInvoke = unsubstitutedPlainInvoke.substitute(TypeSubstitutor.create(functionNType))
throw AssertionError("Substitution failed for $unsubstitutedPlainInvoke, type=$functionNType") ?: throw AssertionError("Substitution failed for $unsubstitutedPlainInvoke, type=$functionNType")
val ktCallElement = resolvedCall.call.callElement val ktCallElement = resolvedCall.call.callElement
val call = CallBuilder(resolvedCall, plainInvoke, isExtensionInvokeCall = true) val call = CallBuilder(resolvedCall, plainInvoke, isExtensionInvokeCall = true)
val functionReceiverValue = run { val functionReceiverValue = run {
val dispatchReceiver = resolvedCall.dispatchReceiver ?: val dispatchReceiver =
throw AssertionError("Extension 'invoke' call should have a dispatch receiver") resolvedCall.dispatchReceiver ?: throw AssertionError("Extension 'invoke' call should have a dispatch receiver")
generateReceiver(ktCallElement, dispatchReceiver) generateReceiver(ktCallElement, dispatchReceiver)
} }
val extensionInvokeReceiverValue = run { val extensionInvokeReceiverValue = run {
val extensionReceiver = resolvedCall.extensionReceiver ?: val extensionReceiver =
throw AssertionError("Extension 'invoke' call should have an extension receiver") resolvedCall.extensionReceiver ?: throw AssertionError("Extension 'invoke' call should have an extension receiver")
generateReceiver(ktCallElement, extensionReceiver) generateReceiver(ktCallElement, extensionReceiver)
} }
call.callReceiver = call.callReceiver =
if (resolvedCall.call.isSafeCall()) if (resolvedCall.call.isSafeCall())
SafeExtensionInvokeCallReceiver(this, ktCallElement.startOffset, ktCallElement.endOffset, SafeExtensionInvokeCallReceiver(
call, functionReceiverValue, extensionInvokeReceiverValue) this, ktCallElement.startOffset, ktCallElement.endOffset,
call, functionReceiverValue, extensionInvokeReceiverValue
)
else else
ExtensionInvokeCallReceiver(call, functionReceiverValue, extensionInvokeReceiverValue) ExtensionInvokeCallReceiver(call, functionReceiverValue, extensionInvokeReceiverValue)
@@ -313,11 +348,13 @@ private fun StatementGenerator.pregenerateValueArguments(call: CallBuilder, reso
fun StatementGenerator.pregenerateCallReceivers(resolvedCall: ResolvedCall<*>): CallBuilder { fun StatementGenerator.pregenerateCallReceivers(resolvedCall: ResolvedCall<*>): CallBuilder {
val call = CallBuilder(resolvedCall, unwrapCallableDescriptor(resolvedCall.resultingDescriptor)) val call = CallBuilder(resolvedCall, unwrapCallableDescriptor(resolvedCall.resultingDescriptor))
call.callReceiver = generateCallReceiver(resolvedCall.call.callElement, call.callReceiver = generateCallReceiver(
resolvedCall.resultingDescriptor, resolvedCall.call.callElement,
resolvedCall.dispatchReceiver, resolvedCall.resultingDescriptor,
resolvedCall.extensionReceiver, resolvedCall.dispatchReceiver,
isSafe = resolvedCall.call.isSafeCall()) resolvedCall.extensionReceiver,
isSafe = resolvedCall.call.isSafeCall()
)
call.superQualifier = getSuperQualifier(resolvedCall) call.superQualifier = getSuperQualifier(resolvedCall)
@@ -325,11 +362,11 @@ fun StatementGenerator.pregenerateCallReceivers(resolvedCall: ResolvedCall<*>):
} }
fun unwrapCallableDescriptor(resultingDescriptor: CallableDescriptor): CallableDescriptor = fun unwrapCallableDescriptor(resultingDescriptor: CallableDescriptor): CallableDescriptor =
when (resultingDescriptor) { when (resultingDescriptor) {
is ImportedFromObjectCallableDescriptor<*> -> is ImportedFromObjectCallableDescriptor<*> ->
resultingDescriptor.callableFromObject resultingDescriptor.callableFromObject
is TypeAliasConstructorDescriptor -> is TypeAliasConstructorDescriptor ->
resultingDescriptor.underlyingConstructorDescriptor resultingDescriptor.underlyingConstructorDescriptor
else -> else ->
resultingDescriptor resultingDescriptor
} }
@@ -58,8 +58,7 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
if (isSimpleAssignment) { if (isSimpleAssignment) {
// Set( Op( Get(), RHS ) ) // Set( Op( Get(), RHS ) )
irLValue.store(irOpCall) irLValue.store(irOpCall)
} } else {
else {
// Op( Get(), RHS ) // Op( Get(), RHS )
irOpCall irOpCall
} }
@@ -109,32 +108,33 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
return when (descriptor) { return when (descriptor) {
is SyntheticFieldDescriptor -> { is SyntheticFieldDescriptor -> {
val receiverValue = statementGenerator.generateBackingFieldReceiver(ktLeft.startOffset, ktLeft.endOffset, resolvedCall, descriptor) val receiverValue =
statementGenerator.generateBackingFieldReceiver(ktLeft.startOffset, ktLeft.endOffset, resolvedCall, descriptor)
createBackingFieldLValue(ktLeft, descriptor.propertyDescriptor, receiverValue, origin) createBackingFieldLValue(ktLeft, descriptor.propertyDescriptor, receiverValue, origin)
} }
is LocalVariableDescriptor -> is LocalVariableDescriptor ->
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
if (descriptor.isDelegated) if (descriptor.isDelegated)
DelegatedLocalPropertyLValue( DelegatedLocalPropertyLValue(
ktLeft.startOffset, ktLeft.endOffset, ktLeft.startOffset, ktLeft.endOffset,
descriptor.type, descriptor.type,
descriptor.getter?.let { context.symbolTable.referenceDeclaredFunction(it) }, descriptor.getter?.let { context.symbolTable.referenceDeclaredFunction(it) },
descriptor.setter?.let { context.symbolTable.referenceDeclaredFunction(it) }, descriptor.setter?.let { context.symbolTable.referenceDeclaredFunction(it) },
origin origin
) )
else else
VariableLValue( VariableLValue(
ktLeft.startOffset, ktLeft.endOffset, ktLeft.startOffset, ktLeft.endOffset,
context.symbolTable.referenceVariable(descriptor), context.symbolTable.referenceVariable(descriptor),
origin origin
) )
is PropertyDescriptor -> is PropertyDescriptor ->
generateAssignmentReceiverForProperty(descriptor, origin, ktLeft, resolvedCall) generateAssignmentReceiverForProperty(descriptor, origin, ktLeft, resolvedCall)
is ValueDescriptor -> is ValueDescriptor ->
VariableLValue( VariableLValue(
ktLeft.startOffset, ktLeft.endOffset, ktLeft.startOffset, ktLeft.endOffset,
context.symbolTable.referenceValue(descriptor), context.symbolTable.referenceValue(descriptor),
origin origin
) )
else -> else ->
OnceExpressionValue(statementGenerator.generateExpression(ktLeft)) OnceExpressionValue(statementGenerator.generateExpression(ktLeft))
@@ -142,50 +142,50 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
} }
private fun createBackingFieldLValue( private fun createBackingFieldLValue(
ktExpression: KtExpression, ktExpression: KtExpression,
descriptor: PropertyDescriptor, descriptor: PropertyDescriptor,
receiverValue: IntermediateValue?, receiverValue: IntermediateValue?,
origin: IrStatementOrigin? origin: IrStatementOrigin?
): BackingFieldLValue = ): BackingFieldLValue =
BackingFieldLValue( BackingFieldLValue(
ktExpression.startOffset, ktExpression.endOffset, ktExpression.startOffset, ktExpression.endOffset,
descriptor.type, descriptor.type,
context.symbolTable.referenceField(descriptor), context.symbolTable.referenceField(descriptor),
receiverValue, origin receiverValue, origin
) )
private fun generateAssignmentReceiverForProperty( private fun generateAssignmentReceiverForProperty(
descriptor: PropertyDescriptor, descriptor: PropertyDescriptor,
origin: IrStatementOrigin, origin: IrStatementOrigin,
ktLeft: KtExpression, ktLeft: KtExpression,
resolvedCall: ResolvedCall<*> resolvedCall: ResolvedCall<*>
): AssignmentReceiver = ): AssignmentReceiver =
if (isValInitializationInConstructor(descriptor, resolvedCall)) { if (isValInitializationInConstructor(descriptor, resolvedCall)) {
val thisClass = getThisClass() val thisClass = getThisClass()
val irThis = IrGetValueImpl( val irThis = IrGetValueImpl(
ktLeft.startOffset, ktLeft.endOffset, ktLeft.startOffset, ktLeft.endOffset,
context.symbolTable.referenceValueParameter(thisClass.thisAsReceiverParameter) context.symbolTable.referenceValueParameter(thisClass.thisAsReceiverParameter)
) )
createBackingFieldLValue(ktLeft, descriptor, RematerializableValue(irThis), null) createBackingFieldLValue(ktLeft, descriptor, RematerializableValue(irThis), null)
} } else {
else { val propertyReceiver = statementGenerator.generateCallReceiver(
val propertyReceiver = statementGenerator.generateCallReceiver( ktLeft, descriptor, resolvedCall.dispatchReceiver, resolvedCall.extensionReceiver,
ktLeft, descriptor, resolvedCall.dispatchReceiver, resolvedCall.extensionReceiver, isSafe = resolvedCall.call.isSafeCall(),
isSafe = resolvedCall.call.isSafeCall(), isAssignmentReceiver = true
isAssignmentReceiver = true) )
val superQualifier = getSuperQualifier(resolvedCall) val superQualifier = getSuperQualifier(resolvedCall)
createPropertyLValue(ktLeft, descriptor, propertyReceiver, getTypeArguments(resolvedCall), origin, superQualifier) createPropertyLValue(ktLeft, descriptor, propertyReceiver, getTypeArguments(resolvedCall), origin, superQualifier)
} }
private fun createPropertyLValue( private fun createPropertyLValue(
ktExpression: KtExpression, ktExpression: KtExpression,
descriptor: PropertyDescriptor, descriptor: PropertyDescriptor,
propertyReceiver: CallReceiver, propertyReceiver: CallReceiver,
typeArguments: Map<TypeParameterDescriptor, KotlinType>?, typeArguments: Map<TypeParameterDescriptor, KotlinType>?,
origin: IrStatementOrigin?, origin: IrStatementOrigin?,
superQualifier: ClassDescriptor? superQualifier: ClassDescriptor?
): PropertyLValueBase { ): PropertyLValueBase {
val superQualifierSymbol = superQualifier?.let { context.symbolTable.referenceClass(it) } val superQualifierSymbol = superQualifier?.let { context.symbolTable.referenceClass(it) }
@@ -197,33 +197,32 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
return if (getterSymbol != null || setterSymbol != null) { return if (getterSymbol != null || setterSymbol != null) {
AccessorPropertyLValue( AccessorPropertyLValue(
scope, scope,
ktExpression.startOffset, ktExpression.endOffset, origin, ktExpression.startOffset, ktExpression.endOffset, origin,
descriptor.type, descriptor.type,
getterSymbol, getterSymbol,
getterDescriptor, getterDescriptor,
setterSymbol, setterSymbol,
setterDescriptor, setterDescriptor,
typeArguments, typeArguments,
propertyReceiver, propertyReceiver,
superQualifierSymbol superQualifierSymbol
) )
} } else
else
FieldPropertyLValue( FieldPropertyLValue(
scope, scope,
ktExpression.startOffset, ktExpression.endOffset, origin, ktExpression.startOffset, ktExpression.endOffset, origin,
context.symbolTable.referenceField(descriptor), context.symbolTable.referenceField(descriptor),
propertyReceiver, propertyReceiver,
superQualifierSymbol superQualifierSymbol
) )
} }
private fun isValInitializationInConstructor(descriptor: PropertyDescriptor, resolvedCall: ResolvedCall<*>): Boolean = private fun isValInitializationInConstructor(descriptor: PropertyDescriptor, resolvedCall: ResolvedCall<*>): Boolean =
!descriptor.isVar && !descriptor.isVar &&
descriptor.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE && descriptor.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE &&
statementGenerator.scopeOwner.let { it is ConstructorDescriptor || it is ClassDescriptor } && statementGenerator.scopeOwner.let { it is ConstructorDescriptor || it is ClassDescriptor } &&
resolvedCall.dispatchReceiver is ThisClassReceiver resolvedCall.dispatchReceiver is ThisClassReceiver
private fun getThisClass(): ClassDescriptor { private fun getThisClass(): ClassDescriptor {
val scopeOwner = statementGenerator.scopeOwner val scopeOwner = statementGenerator.scopeOwner
@@ -234,7 +233,10 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
} }
} }
private fun generateArrayAccessAssignmentReceiver(ktLeft: KtArrayAccessExpression, origin: IrStatementOrigin): ArrayAccessAssignmentReceiver { private fun generateArrayAccessAssignmentReceiver(
ktLeft: KtArrayAccessExpression,
origin: IrStatementOrigin
): ArrayAccessAssignmentReceiver {
val irArray = statementGenerator.generateExpression(ktLeft.arrayExpression!!) val irArray = statementGenerator.generateExpression(ktLeft.arrayExpression!!)
val irIndexExpressions = ktLeft.indexExpressions.map { statementGenerator.generateExpression(it) } val irIndexExpressions = ktLeft.indexExpressions.map { statementGenerator.generateExpression(it) }
@@ -244,9 +246,11 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
val indexedSetResolvedCall = get(BindingContext.INDEXED_LVALUE_SET, ktLeft) val indexedSetResolvedCall = get(BindingContext.INDEXED_LVALUE_SET, ktLeft)
val indexedSetCall = indexedSetResolvedCall?.let { statementGenerator.pregenerateCallReceivers(it) } val indexedSetCall = indexedSetResolvedCall?.let { statementGenerator.pregenerateCallReceivers(it) }
return ArrayAccessAssignmentReceiver(irArray, irIndexExpressions, indexedGetCall, indexedSetCall, return ArrayAccessAssignmentReceiver(
CallGenerator(statementGenerator), irArray, irIndexExpressions, indexedGetCall, indexedSetCall,
ktLeft.startOffset, ktLeft.endOffset, origin) CallGenerator(statementGenerator),
ktLeft.startOffset, ktLeft.endOffset, origin
)
} }
} }
@@ -34,8 +34,8 @@ import java.lang.AssertionError
import java.util.* import java.util.*
class BodyGenerator( class BodyGenerator(
val scopeOwnerSymbol: IrSymbol, val scopeOwnerSymbol: IrSymbol,
override val context: GeneratorContext override val context: GeneratorContext
) : GeneratorWithScope { ) : GeneratorWithScope {
val scopeOwner: DeclarationDescriptor get() = scopeOwnerSymbol.descriptor val scopeOwner: DeclarationDescriptor get() = scopeOwnerSymbol.descriptor
@@ -48,8 +48,7 @@ class BodyGenerator(
val irBlockBody = IrBlockBodyImpl(ktBody.startOffset, ktBody.endOffset) val irBlockBody = IrBlockBodyImpl(ktBody.startOffset, ktBody.endOffset)
if (ktBody is KtBlockExpression) { if (ktBody is KtBlockExpression) {
statementGenerator.generateStatements(ktBody.statements, irBlockBody) statementGenerator.generateStatements(ktBody.statements, irBlockBody)
} } else {
else {
statementGenerator.generateReturnExpression(ktBody, irBlockBody) statementGenerator.generateReturnExpression(ktBody, irBlockBody)
} }
@@ -57,7 +56,7 @@ class BodyGenerator(
} }
fun generateExpressionBody(ktExpression: KtExpression): IrExpressionBody = fun generateExpressionBody(ktExpression: KtExpression): IrExpressionBody =
IrExpressionBodyImpl(createStatementGenerator().generateExpression(ktExpression)) IrExpressionBodyImpl(createStatementGenerator().generateExpression(ktExpression))
fun generateLambdaBody(ktFun: KtFunctionLiteral): IrBody { fun generateLambdaBody(ktFun: KtFunctionLiteral): IrBody {
val statementGenerator = createStatementGenerator() val statementGenerator = createStatementGenerator()
@@ -68,9 +67,11 @@ class BodyGenerator(
for (ktParameter in ktFun.valueParameters) { for (ktParameter in ktFun.valueParameters) {
val ktDestructuringDeclaration = ktParameter.destructuringDeclaration ?: continue val ktDestructuringDeclaration = ktParameter.destructuringDeclaration ?: continue
val valueParameter = getOrFail(BindingContext.VALUE_PARAMETER, ktParameter) val valueParameter = getOrFail(BindingContext.VALUE_PARAMETER, ktParameter)
val parameterValue = VariableLValue(ktDestructuringDeclaration.startOffset, ktDestructuringDeclaration.endOffset, val parameterValue = VariableLValue(
context.symbolTable.referenceValue(valueParameter), ktDestructuringDeclaration.startOffset, ktDestructuringDeclaration.endOffset,
IrStatementOrigin.DESTRUCTURING_DECLARATION) context.symbolTable.referenceValue(valueParameter),
IrStatementOrigin.DESTRUCTURING_DECLARATION
)
statementGenerator.declareComponentVariablesInBlock(ktDestructuringDeclaration, irBlockBody, parameterValue) statementGenerator.declareComponentVariablesInBlock(ktDestructuringDeclaration, irBlockBody, parameterValue)
} }
@@ -81,12 +82,16 @@ class BodyGenerator(
} }
val ktReturnedValue = ktBodyStatements.last() val ktReturnedValue = ktBodyStatements.last()
statementGenerator.generateReturnExpression(ktReturnedValue, irBlockBody) statementGenerator.generateReturnExpression(ktReturnedValue, irBlockBody)
} } else {
else { irBlockBody.statements.add(
irBlockBody.statements.add(generateReturnExpression( generateReturnExpression(
ktBody.startOffset, ktBody.endOffset, ktBody.startOffset, ktBody.endOffset,
IrGetObjectValueImpl(ktBody.startOffset, ktBody.endOffset, context.builtIns.unitType, IrGetObjectValueImpl(
context.symbolTable.referenceClass(context.builtIns.unit)))) ktBody.startOffset, ktBody.endOffset, context.builtIns.unitType,
context.symbolTable.referenceClass(context.builtIns.unit)
)
)
)
} }
return irBlockBody return irBlockBody
@@ -96,25 +101,26 @@ class BodyGenerator(
val irReturnExpression = generateStatement(ktExpression) val irReturnExpression = generateStatement(ktExpression)
if (irReturnExpression is IrExpression) { if (irReturnExpression is IrExpression) {
irBlockBody.statements.add(irReturnExpression.wrapWithReturn()) irBlockBody.statements.add(irReturnExpression.wrapWithReturn())
} } else {
else {
irBlockBody.statements.add(irReturnExpression) irBlockBody.statements.add(irReturnExpression)
} }
} }
private fun IrExpression.wrapWithReturn() = private fun IrExpression.wrapWithReturn() =
if (this is IrReturn || this is IrErrorExpression || this is IrThrow) if (this is IrReturn || this is IrErrorExpression || this is IrThrow)
this this
else { else {
generateReturnExpression(startOffset, endOffset, this) } generateReturnExpression(startOffset, endOffset, this)
}
private fun generateReturnExpression(startOffset: Int, endOffset: Int, returnValue: IrExpression): IrReturnImpl { private fun generateReturnExpression(startOffset: Int, endOffset: Int, returnValue: IrExpression): IrReturnImpl {
val returnTarget = (scopeOwner as? CallableDescriptor) ?: val returnTarget = (scopeOwner as? CallableDescriptor) ?: throw AssertionError("'return' in a non-callable: $scopeOwner")
throw AssertionError("'return' in a non-callable: $scopeOwner") return IrReturnImpl(
return IrReturnImpl(startOffset, endOffset, context.builtIns.nothingType, startOffset, endOffset, context.builtIns.nothingType,
context.symbolTable.referenceFunction(returnTarget), context.symbolTable.referenceFunction(returnTarget),
returnValue) returnValue
)
} }
@@ -140,8 +146,7 @@ class BodyGenerator(
if (delegatingConstructorResolvedCall == null) { if (delegatingConstructorResolvedCall == null) {
if (constructorDescriptor.containingDeclaration.kind == ClassKind.ENUM_CLASS) { if (constructorDescriptor.containingDeclaration.kind == ClassKind.ENUM_CLASS) {
generateEnumSuperConstructorCall(irBlockBody, ktConstructor) generateEnumSuperConstructorCall(irBlockBody, ktConstructor)
} } else {
else {
generateAnySuperConstructorCall(irBlockBody, ktConstructor) generateAnySuperConstructorCall(irBlockBody, ktConstructor)
} }
return return
@@ -149,8 +154,9 @@ class BodyGenerator(
val delegatingConstructorCall = statementGenerator.pregenerateCall(delegatingConstructorResolvedCall) val delegatingConstructorCall = statementGenerator.pregenerateCall(delegatingConstructorResolvedCall)
val irDelegatingConstructorCall = CallGenerator(statementGenerator).generateDelegatingConstructorCall( val irDelegatingConstructorCall = CallGenerator(statementGenerator).generateDelegatingConstructorCall(
ktDelegatingConstructorCall.startOffset, ktDelegatingConstructorCall.endOffset, ktDelegatingConstructorCall.startOffset, ktDelegatingConstructorCall.endOffset,
delegatingConstructorCall) delegatingConstructorCall
)
irBlockBody.statements.add(irDelegatingConstructorCall) irBlockBody.statements.add(irDelegatingConstructorCall)
} }
@@ -161,7 +167,7 @@ class BodyGenerator(
} }
fun getLoop(expression: KtExpression): IrLoop? = fun getLoop(expression: KtExpression): IrLoop? =
loopTable[expression] loopTable[expression]
fun generatePrimaryConstructorBody(ktClassOrObject: KtClassOrObject): IrBody { fun generatePrimaryConstructorBody(ktClassOrObject: KtClassOrObject): IrBody {
val irBlockBody = IrBlockBodyImpl(ktClassOrObject.startOffset, ktClassOrObject.endOffset) val irBlockBody = IrBlockBodyImpl(ktClassOrObject.startOffset, ktClassOrObject.endOffset)
@@ -169,8 +175,12 @@ class BodyGenerator(
generateSuperConstructorCall(irBlockBody, ktClassOrObject) generateSuperConstructorCall(irBlockBody, ktClassOrObject)
val classDescriptor = (scopeOwner as ClassConstructorDescriptor).containingDeclaration val classDescriptor = (scopeOwner as ClassConstructorDescriptor).containingDeclaration
irBlockBody.statements.add(IrInstanceInitializerCallImpl(ktClassOrObject.startOffset, ktClassOrObject.endOffset, irBlockBody.statements.add(
context.symbolTable.referenceClass(classDescriptor))) IrInstanceInitializerCallImpl(
ktClassOrObject.startOffset, ktClassOrObject.endOffset,
context.symbolTable.referenceClass(classDescriptor)
)
)
return irBlockBody return irBlockBody
} }
@@ -181,8 +191,12 @@ class BodyGenerator(
generateDelegatingConstructorCall(irBlockBody, ktConstructor) generateDelegatingConstructorCall(irBlockBody, ktConstructor)
val classDescriptor = getOrFail(BindingContext.CONSTRUCTOR, ktConstructor).containingDeclaration as ClassDescriptor val classDescriptor = getOrFail(BindingContext.CONSTRUCTOR, ktConstructor).containingDeclaration as ClassDescriptor
irBlockBody.statements.add(IrInstanceInitializerCallImpl(ktConstructor.startOffset, ktConstructor.endOffset, irBlockBody.statements.add(
context.symbolTable.referenceClass(classDescriptor))) IrInstanceInitializerCallImpl(
ktConstructor.startOffset, ktConstructor.endOffset,
context.symbolTable.referenceClass(classDescriptor)
)
)
ktConstructor.bodyExpression?.let { ktBody -> ktConstructor.bodyExpression?.let { ktBody ->
createStatementGenerator().generateStatements(ktBody.statements, irBlockBody) createStatementGenerator().generateStatements(ktBody.statements, irBlockBody)
@@ -209,7 +223,8 @@ class BodyGenerator(
if (ktSuperTypeListEntry is KtSuperTypeCallEntry) { if (ktSuperTypeListEntry is KtSuperTypeCallEntry) {
val superConstructorCall = statementGenerator.pregenerateCall(getResolvedCall(ktSuperTypeListEntry)!!) val superConstructorCall = statementGenerator.pregenerateCall(getResolvedCall(ktSuperTypeListEntry)!!)
val irSuperConstructorCall = CallGenerator(statementGenerator).generateDelegatingConstructorCall( val irSuperConstructorCall = CallGenerator(statementGenerator).generateDelegatingConstructorCall(
ktSuperTypeListEntry.startOffset, ktSuperTypeListEntry.endOffset, superConstructorCall) ktSuperTypeListEntry.startOffset, ktSuperTypeListEntry.endOffset, superConstructorCall
)
irBlockBody.statements.add(irSuperConstructorCall) irBlockBody.statements.add(irSuperConstructorCall)
return return
} }
@@ -228,22 +243,22 @@ class BodyGenerator(
private fun generateAnySuperConstructorCall(irBlockBody: IrBlockBodyImpl, ktElement: KtElement) { private fun generateAnySuperConstructorCall(irBlockBody: IrBlockBodyImpl, ktElement: KtElement) {
val anyConstructor = context.builtIns.any.constructors.single() val anyConstructor = context.builtIns.any.constructors.single()
irBlockBody.statements.add( irBlockBody.statements.add(
IrDelegatingConstructorCallImpl( IrDelegatingConstructorCallImpl(
ktElement.startOffset, ktElement.endOffset, ktElement.startOffset, ktElement.endOffset,
context.symbolTable.referenceConstructor(anyConstructor), context.symbolTable.referenceConstructor(anyConstructor),
anyConstructor, anyConstructor,
null null
) )
) )
} }
private fun generateEnumSuperConstructorCall(irBlockBody: IrBlockBodyImpl, ktElement: KtElement) { private fun generateEnumSuperConstructorCall(irBlockBody: IrBlockBodyImpl, ktElement: KtElement) {
val enumConstructor = context.builtIns.enum.constructors.single() val enumConstructor = context.builtIns.enum.constructors.single()
irBlockBody.statements.add( irBlockBody.statements.add(
IrEnumConstructorCallImpl( IrEnumConstructorCallImpl(
ktElement.startOffset, ktElement.endOffset, ktElement.startOffset, ktElement.endOffset,
context.symbolTable.referenceConstructor(enumConstructor) context.symbolTable.referenceConstructor(enumConstructor)
) )
) )
} }
@@ -255,8 +270,8 @@ class BodyGenerator(
if (ktEnumEntry.declarations.isNotEmpty()) { if (ktEnumEntry.declarations.isNotEmpty()) {
val enumEntryConstructor = enumEntryDescriptor.unsubstitutedPrimaryConstructor!! val enumEntryConstructor = enumEntryDescriptor.unsubstitutedPrimaryConstructor!!
return IrEnumConstructorCallImpl( return IrEnumConstructorCallImpl(
ktEnumEntry.startOffset, ktEnumEntry.endOffset, ktEnumEntry.startOffset, ktEnumEntry.endOffset,
context.symbolTable.referenceConstructor(enumEntryConstructor) context.symbolTable.referenceConstructor(enumEntryConstructor)
) )
} }
@@ -264,8 +279,8 @@ class BodyGenerator(
} }
private fun generateEnumConstructorCallOrSuperCall( private fun generateEnumConstructorCallOrSuperCall(
ktEnumEntry: KtEnumEntry, ktEnumEntry: KtEnumEntry,
enumClassDescriptor: ClassDescriptor enumClassDescriptor: ClassDescriptor
): IrExpression { ): IrExpression {
val statementGenerator = createStatementGenerator() val statementGenerator = createStatementGenerator()
@@ -282,17 +297,22 @@ class BodyGenerator(
// Default enum entry constructor // Default enum entry constructor
val enumClassConstructor = val enumClassConstructor =
enumClassDescriptor.constructors.singleOrNull { it.valueParameters.all { it.hasDefaultValue() } } ?: enumClassDescriptor.constructors.singleOrNull { it.valueParameters.all { it.hasDefaultValue() } }
throw AssertionError("Enum class $enumClassDescriptor should have a default constructor") ?: throw AssertionError("Enum class $enumClassDescriptor should have a default constructor")
return IrEnumConstructorCallImpl( return IrEnumConstructorCallImpl(
ktEnumEntry.startOffset, ktEnumEntry.endOffset, ktEnumEntry.startOffset, ktEnumEntry.endOffset,
context.symbolTable.referenceConstructor(enumClassConstructor) context.symbolTable.referenceConstructor(enumClassConstructor)
) )
} }
private fun StatementGenerator.generateEnumConstructorCall(constructorCall: ResolvedCall<out CallableDescriptor>, ktEnumEntry: KtEnumEntry) = private fun StatementGenerator.generateEnumConstructorCall(
CallGenerator(this).generateEnumConstructorSuperCall(ktEnumEntry.startOffset, ktEnumEntry.endOffset, constructorCall: ResolvedCall<out CallableDescriptor>,
pregenerateCall(constructorCall)) ktEnumEntry: KtEnumEntry
) =
CallGenerator(this).generateEnumConstructorSuperCall(
ktEnumEntry.startOffset, ktEnumEntry.endOffset,
pregenerateCall(constructorCall)
)
} }
@@ -39,7 +39,7 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta
val irBranches = SmartList<IrBranch>() val irBranches = SmartList<IrBranch>()
var irElseBranch: IrExpression? = null var irElseBranch: IrExpression? = null
whenBranches@while (true) { whenBranches@ while (true) {
val irCondition = statementGenerator.generateExpression(ktLastIf.condition!!) val irCondition = statementGenerator.generateExpression(ktLastIf.condition!!)
val irThenBranch = statementGenerator.generateExpression(ktLastIf.then!!) val irThenBranch = statementGenerator.generateExpression(ktLastIf.then!!)
irBranches.add(IrBranchImpl(irCondition, irThenBranch)) irBranches.add(IrBranchImpl(irCondition, irThenBranch))
@@ -60,14 +60,16 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta
} }
private fun createIrWhen( private fun createIrWhen(
ktIf: KtIfExpression, ktIf: KtIfExpression,
irBranches: List<IrBranch>, irBranches: List<IrBranch>,
irElseResult: IrExpression?, irElseResult: IrExpression?,
resultType: KotlinType resultType: KotlinType
): IrWhen { ): IrWhen {
if (irBranches.size == 1) { if (irBranches.size == 1) {
return IrIfThenElseImpl(ktIf.startOffset, ktIf.endOffset, resultType, return IrIfThenElseImpl(
irBranches[0].condition, irBranches[0].result, irElseResult) ktIf.startOffset, ktIf.endOffset, resultType,
irBranches[0].condition, irBranches[0].result, irElseResult
)
} }
val irWhen = IrWhenImpl(ktIf.startOffset, ktIf.endOffset, resultType, IrStatementOrigin.WHEN) val irWhen = IrWhenImpl(ktIf.startOffset, ktIf.endOffset, resultType, IrStatementOrigin.WHEN)
@@ -110,10 +112,10 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta
var irBranchCondition: IrExpression? = null var irBranchCondition: IrExpression? = null
for (ktCondition in ktEntry.conditions) { for (ktCondition in ktEntry.conditions) {
val irCondition = val irCondition =
if (irSubject != null) if (irSubject != null)
generateWhenConditionWithSubject(ktCondition, irSubject) generateWhenConditionWithSubject(ktCondition, irSubject)
else else
generateWhenConditionNoSubject(ktCondition) generateWhenConditionNoSubject(ktCondition)
irBranchCondition = irBranchCondition?.let { context.whenComma(it, irCondition) } ?: irCondition irBranchCondition = irBranchCondition?.let { context.whenComma(it, irCondition) } ?: irCondition
} }
@@ -131,7 +133,7 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta
val bindingContext = context.bindingContext val bindingContext = context.bindingContext
//TODO: check condition: seems it's safe to always generate exception //TODO: check condition: seems it's safe to always generate exception
val isExhaustive = java.lang.Boolean.TRUE == bindingContext.get(BindingContext.IMPLICIT_EXHAUSTIVE_WHEN, whenExpression) || val isExhaustive = java.lang.Boolean.TRUE == bindingContext.get(BindingContext.IMPLICIT_EXHAUSTIVE_WHEN, whenExpression) ||
java.lang.Boolean.TRUE == bindingContext.get(BindingContext.EXHAUSTIVE_WHEN, whenExpression) java.lang.Boolean.TRUE == bindingContext.get(BindingContext.EXHAUSTIVE_WHEN, whenExpression)
if (isExhaustive) { if (isExhaustive) {
val call = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.noWhenBranchMatchedExceptionSymbol) val call = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.noWhenBranchMatchedExceptionSymbol)
@@ -146,14 +148,12 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta
IrBlockImpl(expression.startOffset, expression.endOffset, context.builtIns.unitType, IrStatementOrigin.WHEN) IrBlockImpl(expression.startOffset, expression.endOffset, context.builtIns.unitType, IrStatementOrigin.WHEN)
else else
irWhen irWhen
} } else {
else {
if (irWhen.branches.isEmpty()) { if (irWhen.branches.isEmpty()) {
val irBlock = IrBlockImpl(expression.startOffset, expression.endOffset, context.builtIns.unitType, IrStatementOrigin.WHEN) val irBlock = IrBlockImpl(expression.startOffset, expression.endOffset, context.builtIns.unitType, IrStatementOrigin.WHEN)
irBlock.statements.add(irSubject) irBlock.statements.add(irSubject)
irBlock irBlock
} } else {
else {
val irBlock = IrBlockImpl(expression.startOffset, expression.endOffset, irWhen.type, IrStatementOrigin.WHEN) val irBlock = IrBlockImpl(expression.startOffset, expression.endOffset, irWhen.type, IrStatementOrigin.WHEN)
irBlock.statements.add(irSubject) irBlock.statements.add(irSubject)
irBlock.statements.add(irWhen) irBlock.statements.add(irWhen)
@@ -163,7 +163,7 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta
} }
private fun generateWhenConditionNoSubject(ktCondition: KtWhenCondition): IrExpression = private fun generateWhenConditionNoSubject(ktCondition: KtWhenCondition): IrExpression =
statementGenerator.generateExpression((ktCondition as KtWhenConditionWithExpression).expression!!) statementGenerator.generateExpression((ktCondition as KtWhenConditionWithExpression).expression!!)
private fun generateWhenConditionWithSubject(ktCondition: KtWhenCondition, irSubject: IrVariable): IrExpression { private fun generateWhenConditionWithSubject(ktCondition: KtWhenCondition, irSubject: IrVariable): IrExpression {
return when (ktCondition) { return when (ktCondition) {
@@ -181,8 +181,8 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta
private fun generateIsPatternCondition(irSubject: IrVariable, ktCondition: KtWhenConditionIsPattern): IrExpression { private fun generateIsPatternCondition(irSubject: IrVariable, ktCondition: KtWhenConditionIsPattern): IrExpression {
val isType = getOrFail(BindingContext.TYPE, ktCondition.typeReference) val isType = getOrFail(BindingContext.TYPE, ktCondition.typeReference)
return IrTypeOperatorCallImpl( return IrTypeOperatorCallImpl(
ktCondition.startOffset, ktCondition.endOffset, context.builtIns.booleanType, ktCondition.startOffset, ktCondition.endOffset, context.builtIns.booleanType,
IrTypeOperator.INSTANCEOF, isType, irSubject.defaultLoad() IrTypeOperator.INSTANCEOF, isType, irSubject.defaultLoad()
) )
} }
@@ -196,18 +196,18 @@ class BranchingExpressionGenerator(statementGenerator: StatementGenerator) : Sta
irInCall irInCall
IrStatementOrigin.NOT_IN -> IrStatementOrigin.NOT_IN ->
IrUnaryPrimitiveImpl( IrUnaryPrimitiveImpl(
ktCondition.startOffset, ktCondition.endOffset, ktCondition.startOffset, ktCondition.endOffset,
IrStatementOrigin.EXCL, context.irBuiltIns.booleanNotSymbol, IrStatementOrigin.EXCL, context.irBuiltIns.booleanNotSymbol,
irInCall irInCall
) )
else -> throw AssertionError("Expected 'in' or '!in', got $inOperator") else -> throw AssertionError("Expected 'in' or '!in', got $inOperator")
} }
} }
private fun generateEqualsCondition(irSubject: IrVariable, ktCondition: KtWhenConditionWithExpression): IrBinaryPrimitiveImpl = private fun generateEqualsCondition(irSubject: IrVariable, ktCondition: KtWhenConditionWithExpression): IrBinaryPrimitiveImpl =
IrBinaryPrimitiveImpl( IrBinaryPrimitiveImpl(
ktCondition.startOffset, ktCondition.endOffset, ktCondition.startOffset, ktCondition.endOffset,
IrStatementOrigin.EQEQ, context.irBuiltIns.eqeqSymbol, IrStatementOrigin.EQEQ, context.irBuiltIns.eqeqSymbol,
irSubject.defaultLoad(), statementGenerator.generateExpression(ktCondition.expression!!) irSubject.defaultLoad(), statementGenerator.generateExpression(ktCondition.expression!!)
) )
} }
@@ -35,7 +35,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import java.util.* import java.util.*
class CallGenerator(statementGenerator: StatementGenerator): StatementGeneratorExtension(statementGenerator) { class CallGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) {
fun generateCall(startOffset: Int, endOffset: Int, call: CallBuilder, origin: IrStatementOrigin? = null): IrExpression { fun generateCall(startOffset: Int, endOffset: Int, call: CallBuilder, origin: IrStatementOrigin? = null): IrExpression {
val descriptor = call.descriptor val descriptor = call.descriptor
@@ -52,64 +52,66 @@ class CallGenerator(statementGenerator: StatementGenerator): StatementGeneratorE
} }
fun generateValueReference( fun generateValueReference(
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
descriptor: DeclarationDescriptor, descriptor: DeclarationDescriptor,
resolvedCall: ResolvedCall<*>?, resolvedCall: ResolvedCall<*>?,
origin: IrStatementOrigin? origin: IrStatementOrigin?
): IrExpression = ): IrExpression =
when (descriptor) { when (descriptor) {
is FakeCallableDescriptorForObject -> is FakeCallableDescriptorForObject ->
generateValueReference(startOffset, endOffset, descriptor.getReferencedDescriptor(), resolvedCall, origin) generateValueReference(startOffset, endOffset, descriptor.getReferencedDescriptor(), resolvedCall, origin)
is TypeAliasDescriptor -> is TypeAliasDescriptor ->
generateValueReference(startOffset, endOffset, descriptor.classDescriptor!!, null, origin) generateValueReference(startOffset, endOffset, descriptor.classDescriptor!!, null, origin)
is ClassDescriptor -> { is ClassDescriptor -> {
val classValueType = descriptor.classValueType!! val classValueType = descriptor.classValueType!!
statementGenerator.generateSingletonReference(descriptor, startOffset, endOffset, classValueType) statementGenerator.generateSingletonReference(descriptor, startOffset, endOffset, classValueType)
}
is PropertyDescriptor -> {
generateCall(startOffset, endOffset, statementGenerator.pregenerateCall(resolvedCall!!))
}
is SyntheticFieldDescriptor -> {
val receiver = statementGenerator.generateBackingFieldReceiver(startOffset, endOffset, resolvedCall, descriptor)
val field = statementGenerator.context.symbolTable.referenceField(descriptor.propertyDescriptor)
IrGetFieldImpl(startOffset, endOffset, field, receiver?.load())
}
is VariableDescriptor ->
generateGetVariable(startOffset, endOffset, descriptor, getTypeArguments(resolvedCall), origin)
else ->
TODO("Unexpected callable descriptor: $descriptor ${descriptor::class.java.simpleName}")
} }
is PropertyDescriptor -> {
generateCall(startOffset, endOffset, statementGenerator.pregenerateCall(resolvedCall!!))
}
is SyntheticFieldDescriptor -> {
val receiver = statementGenerator.generateBackingFieldReceiver(startOffset, endOffset, resolvedCall, descriptor)
val field = statementGenerator.context.symbolTable.referenceField(descriptor.propertyDescriptor)
IrGetFieldImpl(startOffset, endOffset, field, receiver?.load())
}
is VariableDescriptor ->
generateGetVariable(startOffset, endOffset, descriptor, getTypeArguments(resolvedCall), origin)
else ->
TODO("Unexpected callable descriptor: $descriptor ${descriptor::class.java.simpleName}")
}
private fun generateGetVariable( private fun generateGetVariable(
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
descriptor: VariableDescriptor, descriptor: VariableDescriptor,
typeArguments: Map<TypeParameterDescriptor, KotlinType>?, typeArguments: Map<TypeParameterDescriptor, KotlinType>?,
origin: IrStatementOrigin? = null origin: IrStatementOrigin? = null
) = ) =
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
if (descriptor is LocalVariableDescriptor && descriptor.isDelegated) { if (descriptor is LocalVariableDescriptor && descriptor.isDelegated) {
val getterDescriptor = descriptor.getter!! val getterDescriptor = descriptor.getter!!
val getterSymbol = context.symbolTable.referenceFunction(getterDescriptor.original) val getterSymbol = context.symbolTable.referenceFunction(getterDescriptor.original)
IrCallImpl(startOffset, endOffset, descriptor.type, getterSymbol, getterDescriptor, IrCallImpl(
typeArguments, origin ?: IrStatementOrigin.GET_LOCAL_PROPERTY) startOffset, endOffset, descriptor.type, getterSymbol, getterDescriptor,
} typeArguments, origin ?: IrStatementOrigin.GET_LOCAL_PROPERTY
else )
IrGetValueImpl(startOffset, endOffset, context.symbolTable.referenceValue(descriptor), origin) } else
IrGetValueImpl(startOffset, endOffset, context.symbolTable.referenceValue(descriptor), origin)
fun generateDelegatingConstructorCall(startOffset: Int, endOffset: Int, call: CallBuilder) : IrExpression = fun generateDelegatingConstructorCall(startOffset: Int, endOffset: Int, call: CallBuilder): IrExpression =
call.callReceiver.call { dispatchReceiver, extensionReceiver -> call.callReceiver.call { dispatchReceiver, extensionReceiver ->
val descriptor = call.descriptor as? ClassConstructorDescriptor val descriptor = call.descriptor as? ClassConstructorDescriptor
?: throw AssertionError("Class constructor expected: ${call.descriptor}") ?: throw AssertionError("Class constructor expected: ${call.descriptor}")
val constructorSymbol = context.symbolTable.referenceConstructor(descriptor.original) val constructorSymbol = context.symbolTable.referenceConstructor(descriptor.original)
val irCall = IrDelegatingConstructorCallImpl(startOffset, endOffset, constructorSymbol, descriptor, getTypeArguments(call.original)) val irCall =
irCall.dispatchReceiver = dispatchReceiver?.load() IrDelegatingConstructorCallImpl(startOffset, endOffset, constructorSymbol, descriptor, getTypeArguments(call.original))
irCall.extensionReceiver = extensionReceiver?.load() irCall.dispatchReceiver = dispatchReceiver?.load()
addParametersToCall(startOffset, endOffset, call, irCall, descriptor.builtIns.unitType) irCall.extensionReceiver = extensionReceiver?.load()
} addParametersToCall(startOffset, endOffset, call, irCall, descriptor.builtIns.unitType)
}
fun generateEnumConstructorSuperCall(startOffset: Int, endOffset: Int, call: CallBuilder) : IrExpression { fun generateEnumConstructorSuperCall(startOffset: Int, endOffset: Int, call: CallBuilder): IrExpression {
val constructorDescriptor = call.descriptor val constructorDescriptor = call.descriptor
if (constructorDescriptor !is ClassConstructorDescriptor) throw AssertionError("Constructor expected: $constructorDescriptor") if (constructorDescriptor !is ClassConstructorDescriptor) throw AssertionError("Constructor expected: $constructorDescriptor")
val classDescriptor = constructorDescriptor.containingDeclaration val classDescriptor = constructorDescriptor.containingDeclaration
@@ -125,10 +127,10 @@ class CallGenerator(statementGenerator: StatementGenerator): StatementGeneratorE
} }
private fun generatePropertyGetterCall( private fun generatePropertyGetterCall(
descriptor: PropertyDescriptor, descriptor: PropertyDescriptor,
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
call: CallBuilder call: CallBuilder
): IrExpression { ): IrExpression {
return call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue -> return call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
val superQualifierSymbol = call.superQualifier?.let { context.symbolTable.referenceClass(it) } val superQualifierSymbol = call.superQualifier?.let { context.symbolTable.referenceClass(it) }
@@ -137,73 +139,77 @@ class CallGenerator(statementGenerator: StatementGenerator): StatementGeneratorE
if (getterDescriptor != null) { if (getterDescriptor != null) {
val getterSymbol = context.symbolTable.referenceFunction(getterDescriptor.original) val getterSymbol = context.symbolTable.referenceFunction(getterDescriptor.original)
IrGetterCallImpl( IrGetterCallImpl(
startOffset, endOffset, startOffset, endOffset,
getterSymbol, getterSymbol,
getterDescriptor, getterDescriptor,
getTypeArguments(call.original), getTypeArguments(call.original),
dispatchReceiverValue?.load(), dispatchReceiverValue?.load(),
extensionReceiverValue?.load(), extensionReceiverValue?.load(),
IrStatementOrigin.GET_PROPERTY, IrStatementOrigin.GET_PROPERTY,
superQualifierSymbol superQualifierSymbol
) )
} } else {
else {
val fieldSymbol = context.symbolTable.referenceField(descriptor) val fieldSymbol = context.symbolTable.referenceField(descriptor)
IrGetFieldImpl( IrGetFieldImpl(
startOffset, endOffset, startOffset, endOffset,
fieldSymbol, fieldSymbol,
dispatchReceiverValue?.load(), dispatchReceiverValue?.load(),
IrStatementOrigin.GET_PROPERTY, IrStatementOrigin.GET_PROPERTY,
superQualifierSymbol superQualifierSymbol
) )
} }
} }
} }
private fun generateFunctionCall( private fun generateFunctionCall(
functionDescriptor: FunctionDescriptor, functionDescriptor: FunctionDescriptor,
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
origin: IrStatementOrigin?, origin: IrStatementOrigin?,
call: CallBuilder call: CallBuilder
): IrExpression = ): IrExpression =
call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue -> call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
val returnType = functionDescriptor.returnType!! val returnType = functionDescriptor.returnType!!
val functionSymbol = context.symbolTable.referenceFunction(functionDescriptor.original) val functionSymbol = context.symbolTable.referenceFunction(functionDescriptor.original)
val superQualifierSymbol = call.superQualifier?.let { context.symbolTable.referenceClass(it) } val superQualifierSymbol = call.superQualifier?.let { context.symbolTable.referenceClass(it) }
val irCall = IrCallImpl( val irCall = IrCallImpl(
startOffset, endOffset, startOffset, endOffset,
returnType, returnType,
functionSymbol, functionSymbol,
functionDescriptor, functionDescriptor,
getTypeArguments(call.original), getTypeArguments(call.original),
origin, origin,
superQualifierSymbol superQualifierSymbol
) )
irCall.dispatchReceiver = dispatchReceiverValue?.load() irCall.dispatchReceiver = dispatchReceiverValue?.load()
irCall.extensionReceiver = extensionReceiverValue?.load() irCall.extensionReceiver = extensionReceiverValue?.load()
addParametersToCall(startOffset, endOffset, call, irCall, returnType) addParametersToCall(startOffset, endOffset, call, irCall, returnType)
} }
private fun addParametersToCall(startOffset: Int, endOffset: Int, call: CallBuilder, irCall: IrFunctionAccessExpression, returnType: KotlinType): IrExpression = private fun addParametersToCall(
if (call.isValueArgumentReorderingRequired()) { startOffset: Int,
generateCallWithArgumentReordering(irCall, startOffset, endOffset, call, returnType) endOffset: Int,
} call: CallBuilder,
else { irCall: IrFunctionAccessExpression,
val valueArguments = call.getValueArgumentsInParameterOrder() returnType: KotlinType
for ((index, valueArgument) in valueArguments.withIndex()) { ): IrExpression =
irCall.putValueArgument(index, valueArgument) if (call.isValueArgumentReorderingRequired()) {
} generateCallWithArgumentReordering(irCall, startOffset, endOffset, call, returnType)
irCall } else {
val valueArguments = call.getValueArgumentsInParameterOrder()
for ((index, valueArgument) in valueArguments.withIndex()) {
irCall.putValueArgument(index, valueArgument)
} }
irCall
}
private fun generateCallWithArgumentReordering( private fun generateCallWithArgumentReordering(
irCall: IrFunctionAccessExpression, irCall: IrFunctionAccessExpression,
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
call: CallBuilder, call: CallBuilder,
resultType: KotlinType resultType: KotlinType
): IrExpression { ): IrExpression {
val resolvedCall = call.original val resolvedCall = call.original
@@ -239,7 +245,7 @@ class CallGenerator(statementGenerator: StatementGenerator): StatementGeneratorE
} }
fun CallGenerator.generateCall(ktElement: KtElement, call: CallBuilder, origin: IrStatementOrigin? = null) = fun CallGenerator.generateCall(ktElement: KtElement, call: CallBuilder, origin: IrStatementOrigin? = null) =
generateCall(ktElement.startOffset, ktElement.endOffset, call, origin) generateCall(ktElement.startOffset, ktElement.endOffset, call, origin)
fun CallGenerator.generateCall(irExpression: IrExpression, call: CallBuilder, origin: IrStatementOrigin? = null) = fun CallGenerator.generateCall(irExpression: IrExpression, call: CallBuilder, origin: IrStatementOrigin? = null) =
generateCall(irExpression.startOffset, irExpression.endOffset, call, origin) generateCall(irExpression.startOffset, irExpression.endOffset, call, origin)
@@ -23,12 +23,12 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl
import org.jetbrains.kotlin.ir.descriptors.IrImplementingDelegateDescriptorImpl import org.jetbrains.kotlin.ir.descriptors.IrImplementingDelegateDescriptorImpl
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.expressions.mapValueParameters import org.jetbrains.kotlin.ir.expressions.mapValueParameters
import org.jetbrains.kotlin.ir.util.StableDescriptorsComparator
import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry import org.jetbrains.kotlin.psi.KtDelegatedSuperTypeEntry
import org.jetbrains.kotlin.psi.KtEnumEntry import org.jetbrains.kotlin.psi.KtEnumEntry
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.ir.util.StableDescriptorsComparator
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.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
@@ -40,14 +40,14 @@ class ClassGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGe
val descriptor = getOrFail(BindingContext.CLASS, ktClassOrObject) val descriptor = getOrFail(BindingContext.CLASS, ktClassOrObject)
return context.symbolTable.declareClass( return context.symbolTable.declareClass(
ktClassOrObject.startOffset, ktClassOrObject.endOffset, ktClassOrObject.startOffset, ktClassOrObject.endOffset,
IrDeclarationOrigin.DEFINED, IrDeclarationOrigin.DEFINED,
descriptor descriptor
).buildWithScope { irClass -> ).buildWithScope { irClass ->
irClass.thisReceiver = context.symbolTable.declareValueParameter( irClass.thisReceiver = context.symbolTable.declareValueParameter(
ktClassOrObject.startOffset, ktClassOrObject.endOffset, ktClassOrObject.startOffset, ktClassOrObject.endOffset,
IrDeclarationOrigin.INSTANCE_RECEIVER, IrDeclarationOrigin.INSTANCE_RECEIVER,
irClass.descriptor.thisAsReceiverParameter irClass.descriptor.thisAsReceiverParameter
) )
declarationGenerator.generateTypeParameterDeclarations(irClass, descriptor.declaredTypeParameters) declarationGenerator.generateTypeParameterDeclarations(irClass, descriptor.declaredTypeParameters)
@@ -75,24 +75,24 @@ class ClassGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGe
private fun generateFakeOverrideMemberDeclarations(irClass: IrClass, ktClassOrObject: KtClassOrObject) { private fun generateFakeOverrideMemberDeclarations(irClass: IrClass, ktClassOrObject: KtClassOrObject) {
irClass.descriptor.unsubstitutedMemberScope.getContributedDescriptors() irClass.descriptor.unsubstitutedMemberScope.getContributedDescriptors()
.mapNotNull { .mapNotNull {
it.safeAs<CallableMemberDescriptor>().takeIf { it.safeAs<CallableMemberDescriptor>().takeIf {
it?.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE it?.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE
}
}
.sortedWith(StableDescriptorsComparator)
.forEach { fakeOverride ->
irClass.addMember(declarationGenerator.generateFakeOverrideDeclaration(fakeOverride, ktClassOrObject))
} }
}
.sortedWith(StableDescriptorsComparator)
.forEach { fakeOverride ->
irClass.addMember(declarationGenerator.generateFakeOverrideDeclaration(fakeOverride, ktClassOrObject))
}
} }
private fun generateMembersDeclaredInSupertypeList(irClass: IrClass, ktClassOrObject: KtClassOrObject) { private fun generateMembersDeclaredInSupertypeList(irClass: IrClass, ktClassOrObject: KtClassOrObject) {
ktClassOrObject.getSuperTypeList()?.let { ktSuperTypeList -> ktClassOrObject.getSuperTypeList()?.let { ktSuperTypeList ->
val delegatedMembers = irClass.descriptor.unsubstitutedMemberScope val delegatedMembers = irClass.descriptor.unsubstitutedMemberScope
.getContributedDescriptors(DescriptorKindFilter.CALLABLES) .getContributedDescriptors(DescriptorKindFilter.CALLABLES)
.filterIsInstance<CallableMemberDescriptor>() .filterIsInstance<CallableMemberDescriptor>()
.filter { it.kind == CallableMemberDescriptor.Kind.DELEGATION } .filter { it.kind == CallableMemberDescriptor.Kind.DELEGATION }
.sortedWith(StableDescriptorsComparator) .sortedWith(StableDescriptorsComparator)
if (delegatedMembers.isEmpty()) return if (delegatedMembers.isEmpty()) return
for (ktEntry in ktSuperTypeList.entries) { for (ktEntry in ktSuperTypeList.entries) {
@@ -104,22 +104,22 @@ class ClassGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGe
} }
private fun generateDelegatedImplementationMembers( private fun generateDelegatedImplementationMembers(
irClass: IrClass, irClass: IrClass,
ktEntry: KtDelegatedSuperTypeEntry, ktEntry: KtDelegatedSuperTypeEntry,
delegatedMembers: List<CallableMemberDescriptor> delegatedMembers: List<CallableMemberDescriptor>
) { ) {
val ktDelegateExpression = ktEntry.delegateExpression!! val ktDelegateExpression = ktEntry.delegateExpression!!
val delegateType = getInferredTypeWithImplicitCastsOrFail(ktDelegateExpression) val delegateType = getInferredTypeWithImplicitCastsOrFail(ktDelegateExpression)
val superType = getOrFail(BindingContext.TYPE, ktEntry.typeReference!!) val superType = getOrFail(BindingContext.TYPE, ktEntry.typeReference!!)
val superTypeConstructorDescriptor = superType.constructor.declarationDescriptor val superTypeConstructorDescriptor = superType.constructor.declarationDescriptor
val superClass = superTypeConstructorDescriptor as? ClassDescriptor ?: val superClass = superTypeConstructorDescriptor as? ClassDescriptor
throw AssertionError("Unexpected supertype constructor for delegation: $superTypeConstructorDescriptor") ?: throw AssertionError("Unexpected supertype constructor for delegation: $superTypeConstructorDescriptor")
val delegateDescriptor = IrImplementingDelegateDescriptorImpl(irClass.descriptor, delegateType, superType) val delegateDescriptor = IrImplementingDelegateDescriptorImpl(irClass.descriptor, delegateType, superType)
val irDelegateField = context.symbolTable.declareField( val irDelegateField = context.symbolTable.declareField(
ktDelegateExpression.startOffset, ktDelegateExpression.endOffset, ktDelegateExpression.startOffset, ktDelegateExpression.endOffset,
IrDeclarationOrigin.DELEGATE, IrDeclarationOrigin.DELEGATE,
delegateDescriptor, delegateDescriptor,
createBodyGenerator(irClass.symbol).generateExpressionBody(ktDelegateExpression) createBodyGenerator(irClass.symbol).generateExpressionBody(ktDelegateExpression)
) )
irClass.addMember(irDelegateField) irClass.addMember(irDelegateField)
@@ -131,8 +131,10 @@ class ClassGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGe
} }
} }
private fun generateDelegatedMember(irClass: IrClass, irDelegate: IrField, private fun generateDelegatedMember(
delegatedMember: CallableMemberDescriptor, overriddenMember: CallableMemberDescriptor) { irClass: IrClass, irDelegate: IrField,
delegatedMember: CallableMemberDescriptor, overriddenMember: CallableMemberDescriptor
) {
when (delegatedMember) { when (delegatedMember) {
is FunctionDescriptor -> is FunctionDescriptor ->
generateDelegatedFunction(irClass, irDelegate, delegatedMember, overriddenMember as FunctionDescriptor) generateDelegatedFunction(irClass, irDelegate, delegatedMember, overriddenMember as FunctionDescriptor)
@@ -142,11 +144,20 @@ class ClassGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGe
} }
private fun generateDelegatedProperty(irClass: IrClass, irDelegate: IrField, delegated: PropertyDescriptor, overridden: PropertyDescriptor) { private fun generateDelegatedProperty(
irClass: IrClass,
irDelegate: IrField,
delegated: PropertyDescriptor,
overridden: PropertyDescriptor
) {
irClass.addMember(generateDelegatedProperty(irDelegate, delegated, overridden)) irClass.addMember(generateDelegatedProperty(irDelegate, delegated, overridden))
} }
private fun generateDelegatedProperty(irDelegate: IrField, delegated: PropertyDescriptor, overridden: PropertyDescriptor): IrPropertyImpl { private fun generateDelegatedProperty(
irDelegate: IrField,
delegated: PropertyDescriptor,
overridden: PropertyDescriptor
): IrPropertyImpl {
val startOffset = irDelegate.startOffset val startOffset = irDelegate.startOffset
val endOffset = irDelegate.endOffset val endOffset = irDelegate.endOffset
@@ -160,31 +171,39 @@ class ClassGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGe
return irProperty return irProperty
} }
private fun generateDelegatedFunction(irClass: IrClass, irDelegate: IrField, delegated: FunctionDescriptor, overridden: FunctionDescriptor) { private fun generateDelegatedFunction(
irClass: IrClass,
irDelegate: IrField,
delegated: FunctionDescriptor,
overridden: FunctionDescriptor
) {
irClass.addMember(generateDelegatedFunction(irDelegate, delegated, overridden)) irClass.addMember(generateDelegatedFunction(irDelegate, delegated, overridden))
} }
private fun generateDelegatedFunction(irDelegate: IrField, delegated: FunctionDescriptor, overridden: FunctionDescriptor): IrFunction = private fun generateDelegatedFunction(irDelegate: IrField, delegated: FunctionDescriptor, overridden: FunctionDescriptor): IrFunction =
context.symbolTable.declareSimpleFunction( context.symbolTable.declareSimpleFunction(
irDelegate.startOffset, irDelegate.endOffset, irDelegate.startOffset, irDelegate.endOffset,
IrDeclarationOrigin.DELEGATED_MEMBER, IrDeclarationOrigin.DELEGATED_MEMBER,
delegated delegated
).buildWithScope { irFunction -> ).buildWithScope { irFunction ->
FunctionGenerator(declarationGenerator).generateSyntheticFunctionParameterDeclarations(irFunction) FunctionGenerator(declarationGenerator).generateSyntheticFunctionParameterDeclarations(irFunction)
irFunction.body = generateDelegateFunctionBody(irDelegate, delegated, overridden, irFunction) irFunction.body = generateDelegateFunctionBody(irDelegate, delegated, overridden, irFunction)
} }
private fun generateDelegateFunctionBody(irDelegate: IrField, delegated: FunctionDescriptor, overridden: FunctionDescriptor, private fun generateDelegateFunctionBody(
irDelegatedFunction: IrSimpleFunction): IrBlockBodyImpl { irDelegate: IrField, delegated: FunctionDescriptor, overridden: FunctionDescriptor,
irDelegatedFunction: IrSimpleFunction
): IrBlockBodyImpl {
val startOffset = irDelegate.startOffset val startOffset = irDelegate.startOffset
val endOffset = irDelegate.endOffset val endOffset = irDelegate.endOffset
val irBlockBody = IrBlockBodyImpl(startOffset, endOffset) val irBlockBody = IrBlockBodyImpl(startOffset, endOffset)
val returnType = overridden.returnType!! val returnType = overridden.returnType!!
val irCall = IrCallImpl(startOffset, endOffset, returnType, context.symbolTable.referenceFunction(overridden.original), overridden, null) val irCall =
IrCallImpl(startOffset, endOffset, returnType, context.symbolTable.referenceFunction(overridden.original), overridden, null)
irCall.dispatchReceiver = irCall.dispatchReceiver =
IrGetFieldImpl( IrGetFieldImpl(
startOffset, endOffset, irDelegate.symbol, startOffset, endOffset, irDelegate.symbol,
IrGetValueImpl(startOffset, endOffset, irDelegatedFunction.dispatchReceiverParameter!!.symbol) IrGetValueImpl(startOffset, endOffset, irDelegatedFunction.dispatchReceiverParameter!!.symbol)
) )
irCall.extensionReceiver = irCall.extensionReceiver =
irDelegatedFunction.extensionReceiverParameter?.let { extensionReceiver -> irDelegatedFunction.extensionReceiverParameter?.let { extensionReceiver ->
@@ -197,8 +216,7 @@ class ClassGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGe
} }
if (KotlinBuiltIns.isUnit(returnType) || KotlinBuiltIns.isNothing(returnType)) { if (KotlinBuiltIns.isUnit(returnType) || KotlinBuiltIns.isNothing(returnType)) {
irBlockBody.statements.add(irCall) irBlockBody.statements.add(irCall)
} } else {
else {
val irReturn = IrReturnImpl(startOffset, endOffset, context.builtIns.nothingType, irDelegatedFunction.symbol, irCall) val irReturn = IrReturnImpl(startOffset, endOffset, context.builtIns.nothingType, irDelegatedFunction.symbol, irCall)
irBlockBody.statements.add(irReturn) irBlockBody.statements.add(irReturn)
} }
@@ -217,7 +235,8 @@ class ClassGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGe
val classDescriptor = irClass.descriptor val classDescriptor = irClass.descriptor
val primaryConstructorDescriptor = classDescriptor.unsubstitutedPrimaryConstructor ?: return null val primaryConstructorDescriptor = classDescriptor.unsubstitutedPrimaryConstructor ?: return null
val irPrimaryConstructor = FunctionGenerator(declarationGenerator).generatePrimaryConstructor(primaryConstructorDescriptor, ktClassOrObject) val irPrimaryConstructor =
FunctionGenerator(declarationGenerator).generatePrimaryConstructor(primaryConstructorDescriptor, ktClassOrObject)
if (!DescriptorUtils.isAnnotationClass(classDescriptor)) { if (!DescriptorUtils.isAnnotationClass(classDescriptor)) {
irClass.addMember(irPrimaryConstructor) irClass.addMember(irPrimaryConstructor)
@@ -227,9 +246,9 @@ class ClassGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGe
} }
private fun generateDeclarationsForPrimaryConstructorParameters( private fun generateDeclarationsForPrimaryConstructorParameters(
irClass: IrClass, irClass: IrClass,
irPrimaryConstructor: IrConstructor, irPrimaryConstructor: IrConstructor,
ktClassOrObject: KtClassOrObject ktClassOrObject: KtClassOrObject
) { ) {
ktClassOrObject.primaryConstructor?.let { ktPrimaryConstructor -> ktClassOrObject.primaryConstructor?.let { ktPrimaryConstructor ->
irPrimaryConstructor.valueParameters.forEach { irPrimaryConstructor.valueParameters.forEach {
@@ -240,7 +259,7 @@ class ClassGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGe
val irValueParameter = irPrimaryConstructor.valueParameters[i] val irValueParameter = irPrimaryConstructor.valueParameters[i]
if (ktParameter.hasValOrVar()) { if (ktParameter.hasValOrVar()) {
val irProperty = PropertyGenerator(declarationGenerator) val irProperty = PropertyGenerator(declarationGenerator)
.generatePropertyForPrimaryConstructorParameter(ktParameter, irValueParameter) .generatePropertyForPrimaryConstructorParameter(ktParameter, irValueParameter)
irClass.addMember(irProperty) irClass.addMember(irProperty)
} }
} }
@@ -258,14 +277,14 @@ class ClassGenerator(declarationGenerator: DeclarationGenerator) : DeclarationGe
fun generateEnumEntry(ktEnumEntry: KtEnumEntry): IrEnumEntry { fun generateEnumEntry(ktEnumEntry: KtEnumEntry): IrEnumEntry {
val enumEntryDescriptor = getOrFail(BindingContext.CLASS, ktEnumEntry) val enumEntryDescriptor = getOrFail(BindingContext.CLASS, ktEnumEntry)
return context.symbolTable.declareEnumEntry( return context.symbolTable.declareEnumEntry(
ktEnumEntry.startOffset, ktEnumEntry.startOffset,
ktEnumEntry.endOffset, ktEnumEntry.endOffset,
IrDeclarationOrigin.DEFINED, IrDeclarationOrigin.DEFINED,
enumEntryDescriptor enumEntryDescriptor
).buildWithScope { irEnumEntry -> ).buildWithScope { irEnumEntry ->
irEnumEntry.initializerExpression = irEnumEntry.initializerExpression =
createBodyGenerator(irEnumEntry.symbol) createBodyGenerator(irEnumEntry.symbol)
.generateEnumEntryInitializer(ktEnumEntry, enumEntryDescriptor) .generateEnumEntryInitializer(ktEnumEntry, enumEntryDescriptor)
if (ktEnumEntry.declarations.isNotEmpty()) { if (ktEnumEntry.declarations.isNotEmpty()) {
irEnumEntry.correspondingClass = generateClass(ktEnumEntry) irEnumEntry.correspondingClass = generateClass(ktEnumEntry)
@@ -48,16 +48,16 @@ class DataClassMembersGenerator(declarationGenerator: DeclarationGenerator) : De
} }
private fun declareSimpleFunction(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, function: FunctionDescriptor) = private fun declareSimpleFunction(startOffset: Int, endOffset: Int, origin: IrDeclarationOrigin, function: FunctionDescriptor) =
context.symbolTable.declareSimpleFunction(startOffset, endOffset, origin, function) context.symbolTable.declareSimpleFunction(startOffset, endOffset, origin, function)
private inner class MemberFunctionBuilder( private inner class MemberFunctionBuilder(
val irClass: IrClass, val irClass: IrClass,
val function: FunctionDescriptor, val function: FunctionDescriptor,
val origin: IrDeclarationOrigin, val origin: IrDeclarationOrigin,
startOffset: Int = UNDEFINED_OFFSET, startOffset: Int = UNDEFINED_OFFSET,
endOffset: Int = UNDEFINED_OFFSET, endOffset: Int = UNDEFINED_OFFSET,
val irFunction: IrFunction = declareSimpleFunction(startOffset, endOffset, origin, function) val irFunction: IrFunction = declareSimpleFunction(startOffset, endOffset, origin, function)
) : IrBlockBodyBuilder(context, Scope(irFunction.symbol), startOffset, endOffset) { ) : IrBlockBodyBuilder(context, Scope(irFunction.symbol), startOffset, endOffset) {
inline fun addToClass(builder: MemberFunctionBuilder.(IrFunction) -> Unit): IrFunction { inline fun addToClass(builder: MemberFunctionBuilder.(IrFunction) -> Unit): IrFunction {
irFunction.buildWithScope { irFunction.buildWithScope {
builder(irFunction) builder(irFunction)
@@ -73,24 +73,24 @@ class DataClassMembersGenerator(declarationGenerator: DeclarationGenerator) : De
} }
fun irThis(): IrExpression = fun irThis(): IrExpression =
IrGetValueImpl(startOffset, endOffset, irFunction.dispatchReceiverParameter!!.symbol) IrGetValueImpl(startOffset, endOffset, irFunction.dispatchReceiverParameter!!.symbol)
fun irOther(): IrExpression = fun irOther(): IrExpression =
IrGetValueImpl(startOffset, endOffset, irFunction.valueParameters[0].symbol) IrGetValueImpl(startOffset, endOffset, irFunction.valueParameters[0].symbol)
} }
private inner class MyDataClassMethodGenerator( private inner class MyDataClassMethodGenerator(
ktClassOrObject: KtClassOrObject, ktClassOrObject: KtClassOrObject,
val irClass: IrClass val irClass: IrClass
) : DataClassMethodGenerator(ktClassOrObject, declarationGenerator.context.bindingContext) { ) : DataClassMethodGenerator(ktClassOrObject, declarationGenerator.context.bindingContext) {
private inline fun buildMember( private inline fun buildMember(
function: FunctionDescriptor, function: FunctionDescriptor,
psiElement: PsiElement? = null, psiElement: PsiElement? = null,
body: MemberFunctionBuilder.(IrFunction) -> Unit body: MemberFunctionBuilder.(IrFunction) -> Unit
) { ) {
MemberFunctionBuilder( MemberFunctionBuilder(
irClass, function, IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER, irClass, function, IrDeclarationOrigin.GENERATED_DATA_CLASS_MEMBER,
psiElement.startOffsetOrUndefined, psiElement.endOffsetOrUndefined psiElement.startOffsetOrUndefined, psiElement.endOffsetOrUndefined
).addToClass { irFunction -> ).addToClass { irFunction ->
irFunction.buildWithScope { irFunction.buildWithScope {
FunctionGenerator(declarationGenerator).generateSyntheticFunctionParameterDeclarations(irFunction) FunctionGenerator(declarationGenerator).generateSyntheticFunctionParameterDeclarations(irFunction)
@@ -100,8 +100,8 @@ class DataClassMembersGenerator(declarationGenerator: DeclarationGenerator) : De
} }
override fun generateComponentFunction(function: FunctionDescriptor, parameter: ValueParameterDescriptor) { override fun generateComponentFunction(function: FunctionDescriptor, parameter: ValueParameterDescriptor) {
val ktParameter = DescriptorToSourceUtils.descriptorToDeclaration(parameter) ?: val ktParameter = DescriptorToSourceUtils.descriptorToDeclaration(parameter)
throw AssertionError("No definition for data class constructor parameter $parameter") ?: throw AssertionError("No definition for data class constructor parameter $parameter")
buildMember(function, ktParameter) { buildMember(function, ktParameter) {
+irReturn(irGet(irThis(), getPropertyGetterSymbol(parameter))) +irReturn(irGet(irThis(), getPropertyGetterSymbol(parameter)))
@@ -114,11 +114,11 @@ class DataClassMembersGenerator(declarationGenerator: DeclarationGenerator) : De
} }
private fun getPropertyGetterSymbol(property: PropertyDescriptor) = private fun getPropertyGetterSymbol(property: PropertyDescriptor) =
context.symbolTable.referenceFunction(property.getter!!) context.symbolTable.referenceFunction(property.getter!!)
override fun generateCopyFunction(function: FunctionDescriptor, constructorParameters: List<KtParameter>) { override fun generateCopyFunction(function: FunctionDescriptor, constructorParameters: List<KtParameter>) {
val dataClassConstructor = classDescriptor.unsubstitutedPrimaryConstructor ?: val dataClassConstructor = classDescriptor.unsubstitutedPrimaryConstructor
throw AssertionError("Data class should have a primary constructor: $classDescriptor") ?: throw AssertionError("Data class should have a primary constructor: $classDescriptor")
val constructorSymbol = context.symbolTable.referenceConstructor(dataClassConstructor) val constructorSymbol = context.symbolTable.referenceConstructor(dataClassConstructor)
buildMember(function, declaration) { irFunction -> buildMember(function, declaration) { irFunction ->
@@ -138,8 +138,11 @@ class DataClassMembersGenerator(declarationGenerator: DeclarationGenerator) : De
val otherWithCast = irTemporary(irAs(irOther(), classDescriptor.defaultType), "other_with_cast") val otherWithCast = irTemporary(irAs(irOther(), classDescriptor.defaultType), "other_with_cast")
for (property in properties) { for (property in properties) {
+irIfThenReturnFalse( +irIfThenReturnFalse(
irNotEquals(irGet(irThis(), getPropertyGetterSymbol(property)), irNotEquals(
irGet(irGet(otherWithCast.symbol), getPropertyGetterSymbol(property)))) irGet(irThis(), getPropertyGetterSymbol(property)),
irGet(irGet(otherWithCast.symbol), getPropertyGetterSymbol(property))
)
)
} }
+irReturnTrue() +irReturnTrue()
} }
@@ -149,12 +152,12 @@ class DataClassMembersGenerator(declarationGenerator: DeclarationGenerator) : De
private val intType = context.builtIns.intType private val intType = context.builtIns.intType
private val intTimes = private val intTimes =
intClass.findFirstFunction("times") { KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, intType) } intClass.findFirstFunction("times") { KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, intType) }
.let { context.symbolTable.referenceFunction(it) } .let { context.symbolTable.referenceFunction(it) }
private val intPlus = private val intPlus =
intClass.findFirstFunction("plus") { KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, intType) } intClass.findFirstFunction("plus") { KotlinTypeChecker.DEFAULT.equalTypes(it.valueParameters[0].type, intType) }
.let { context.symbolTable.referenceFunction(it) } .let { context.symbolTable.referenceFunction(it) }
private fun getHashCodeFunction(type: KotlinType): IrFunctionSymbol { private fun getHashCodeFunction(type: KotlinType): IrFunctionSymbol {
@@ -163,9 +166,9 @@ class DataClassMembersGenerator(declarationGenerator: DeclarationGenerator) : De
is ClassDescriptor -> { is ClassDescriptor -> {
if (KotlinBuiltIns.isArrayOrPrimitiveArray(typeConstructorDescriptor)) { if (KotlinBuiltIns.isArrayOrPrimitiveArray(typeConstructorDescriptor)) {
context.irBuiltIns.dataClassArrayMemberHashCodeSymbol context.irBuiltIns.dataClassArrayMemberHashCodeSymbol
} } else {
else { val hashCodeDescriptor: CallableDescriptor =
val hashCodeDescriptor: CallableDescriptor = typeConstructorDescriptor.findFirstFunction("hashCode") { it.valueParameters.isEmpty() } typeConstructorDescriptor.findFirstFunction("hashCode") { it.valueParameters.isEmpty() }
context.symbolTable.referenceFunction(hashCodeDescriptor) context.symbolTable.referenceFunction(hashCodeDescriptor)
} }
} }
@@ -184,8 +187,8 @@ class DataClassMembersGenerator(declarationGenerator: DeclarationGenerator) : De
for (property in properties) { for (property in properties) {
val hashCodeOfProperty = getHashCodeOfProperty(irThis(), property) val hashCodeOfProperty = getHashCodeOfProperty(irThis(), property)
val irNewValue = val irNewValue =
if (first) hashCodeOfProperty if (first) hashCodeOfProperty
else irCallOp(intPlus, irCallOp(intTimes, irGet(result), irInt(31)), hashCodeOfProperty) else irCallOp(intPlus, irCallOp(intTimes, irGet(result), irInt(31)), hashCodeOfProperty)
+irSetVar(result, irNewValue) +irSetVar(result, irNewValue)
first = false first = false
} }
@@ -206,14 +209,13 @@ class DataClassMembersGenerator(declarationGenerator: DeclarationGenerator) : De
} }
private fun MemberFunctionBuilder.getHashCodeOf(irValue: IrExpression): IrExpression = private fun MemberFunctionBuilder.getHashCodeOf(irValue: IrExpression): IrExpression =
irCall(getHashCodeFunction(irValue.type)).apply { irCall(getHashCodeFunction(irValue.type)).apply {
if (descriptor.dispatchReceiverParameter != null) { if (descriptor.dispatchReceiverParameter != null) {
dispatchReceiver = irValue dispatchReceiver = irValue
} } else {
else { putValueArgument(0, irValue)
putValueArgument(0, irValue)
}
} }
}
override fun generateToStringMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>) { override fun generateToStringMethod(function: FunctionDescriptor, properties: List<PropertyDescriptor>) {
buildMember(function, declaration) { buildMember(function, declaration) {
@@ -226,13 +228,13 @@ class DataClassMembersGenerator(declarationGenerator: DeclarationGenerator) : De
val irPropertyValue = irGet(irThis(), getPropertyGetterSymbol(property)) val irPropertyValue = irGet(irThis(), getPropertyGetterSymbol(property))
val typeConstructorDescriptor = property.type.constructor.declarationDescriptor val typeConstructorDescriptor = property.type.constructor.declarationDescriptor
val irPropertyStringValue = val irPropertyStringValue =
if (typeConstructorDescriptor is ClassDescriptor && if (typeConstructorDescriptor is ClassDescriptor &&
KotlinBuiltIns.isArrayOrPrimitiveArray(typeConstructorDescriptor)) KotlinBuiltIns.isArrayOrPrimitiveArray(typeConstructorDescriptor))
irCall(context.irBuiltIns.dataClassArrayMemberToStringSymbol).apply { irCall(context.irBuiltIns.dataClassArrayMemberToStringSymbol).apply {
putValueArgument(0, irPropertyValue) putValueArgument(0, irPropertyValue)
} }
else else
irPropertyValue irPropertyValue
irConcat.addArgument(irPropertyStringValue) irConcat.addArgument(irPropertyStringValue)
first = false first = false
} }
@@ -34,48 +34,50 @@ import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
class DeclarationGenerator(override val context: GeneratorContext) : Generator { class DeclarationGenerator(override val context: GeneratorContext) : Generator {
fun generateMemberDeclaration(ktDeclaration: KtDeclaration): IrDeclaration = fun generateMemberDeclaration(ktDeclaration: KtDeclaration): IrDeclaration =
when (ktDeclaration) { when (ktDeclaration) {
is KtNamedFunction -> is KtNamedFunction ->
FunctionGenerator(this).generateFunctionDeclaration(ktDeclaration) FunctionGenerator(this).generateFunctionDeclaration(ktDeclaration)
is KtProperty -> is KtProperty ->
PropertyGenerator(this).generatePropertyDeclaration(ktDeclaration) PropertyGenerator(this).generatePropertyDeclaration(ktDeclaration)
is KtClassOrObject -> is KtClassOrObject ->
generateClassOrObjectDeclaration(ktDeclaration) generateClassOrObjectDeclaration(ktDeclaration)
is KtTypeAlias -> is KtTypeAlias ->
generateTypeAliasDeclaration(ktDeclaration) generateTypeAliasDeclaration(ktDeclaration)
else -> else ->
IrErrorDeclarationImpl( IrErrorDeclarationImpl(
ktDeclaration.startOffset, ktDeclaration.endOffset, ktDeclaration.startOffset, ktDeclaration.endOffset,
getOrFail(BindingContext.DECLARATION_TO_DESCRIPTOR, ktDeclaration) getOrFail(BindingContext.DECLARATION_TO_DESCRIPTOR, ktDeclaration)
) )
} }
fun generateClassMemberDeclaration(ktDeclaration: KtDeclaration, classDescriptor: ClassDescriptor): IrDeclaration = fun generateClassMemberDeclaration(ktDeclaration: KtDeclaration, classDescriptor: ClassDescriptor): IrDeclaration =
when (ktDeclaration) { when (ktDeclaration) {
is KtAnonymousInitializer -> is KtAnonymousInitializer ->
AnonymousInitializerGenerator(this).generateAnonymousInitializerDeclaration(ktDeclaration, classDescriptor) AnonymousInitializerGenerator(this).generateAnonymousInitializerDeclaration(ktDeclaration, classDescriptor)
is KtSecondaryConstructor -> is KtSecondaryConstructor ->
FunctionGenerator(this).generateSecondaryConstructor(ktDeclaration) FunctionGenerator(this).generateSecondaryConstructor(ktDeclaration)
is KtEnumEntry -> is KtEnumEntry ->
generateEnumEntryDeclaration(ktDeclaration) generateEnumEntryDeclaration(ktDeclaration)
else -> else ->
generateMemberDeclaration(ktDeclaration) generateMemberDeclaration(ktDeclaration)
} }
private fun generateEnumEntryDeclaration(ktEnumEntry: KtEnumEntry): IrEnumEntry = private fun generateEnumEntryDeclaration(ktEnumEntry: KtEnumEntry): IrEnumEntry =
ClassGenerator(this).generateEnumEntry(ktEnumEntry) ClassGenerator(this).generateEnumEntry(ktEnumEntry)
fun generateClassOrObjectDeclaration(ktClassOrObject: KtClassOrObject): IrClass = fun generateClassOrObjectDeclaration(ktClassOrObject: KtClassOrObject): IrClass =
ClassGenerator(this).generateClass(ktClassOrObject) ClassGenerator(this).generateClass(ktClassOrObject)
fun generateTypeAliasDeclaration(ktDeclaration: KtTypeAlias): IrDeclaration = fun generateTypeAliasDeclaration(ktDeclaration: KtTypeAlias): IrDeclaration =
IrTypeAliasImpl(ktDeclaration.startOffset, ktDeclaration.endOffset, IrDeclarationOrigin.DEFINED, IrTypeAliasImpl(
getOrFail(BindingContext.TYPE_ALIAS, ktDeclaration)) ktDeclaration.startOffset, ktDeclaration.endOffset, IrDeclarationOrigin.DEFINED,
getOrFail(BindingContext.TYPE_ALIAS, ktDeclaration)
)
fun generateTypeParameterDeclarations( fun generateTypeParameterDeclarations(
irTypeParametersOwner: IrTypeParametersContainer, irTypeParametersOwner: IrTypeParametersContainer,
from: List<TypeParameterDescriptor> from: List<TypeParameterDescriptor>
) { ) {
from.mapTo(irTypeParametersOwner.typeParameters) { typeParameterDescriptor -> from.mapTo(irTypeParametersOwner.typeParameters) { typeParameterDescriptor ->
val ktTypeParameterDeclaration = DescriptorToSourceUtils.getSourceFromDescriptor(typeParameterDescriptor) val ktTypeParameterDeclaration = DescriptorToSourceUtils.getSourceFromDescriptor(typeParameterDescriptor)
@@ -86,7 +88,7 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator {
} }
fun generateInitializerBody(scopeOwnerSymbol: IrSymbol, ktBody: KtExpression): IrExpressionBody = fun generateInitializerBody(scopeOwnerSymbol: IrSymbol, ktBody: KtExpression): IrExpressionBody =
createBodyGenerator(scopeOwnerSymbol).generateExpressionBody(ktBody) createBodyGenerator(scopeOwnerSymbol).generateExpressionBody(ktBody)
fun generateFakeOverrideDeclaration(memberDescriptor: CallableMemberDescriptor, ktElement: KtElement): IrDeclaration { fun generateFakeOverrideDeclaration(memberDescriptor: CallableMemberDescriptor, ktElement: KtElement): IrDeclaration {
assert(memberDescriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) { assert(memberDescriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
@@ -103,35 +105,35 @@ class DeclarationGenerator(override val context: GeneratorContext) : Generator {
} }
private fun generateFakeOverrideProperty(propertyDescriptor: PropertyDescriptor, ktElement: KtElement): IrProperty = private fun generateFakeOverrideProperty(propertyDescriptor: PropertyDescriptor, ktElement: KtElement): IrProperty =
IrPropertyImpl( IrPropertyImpl(
ktElement.startOffsetOrUndefined, ktElement.endOffsetOrUndefined, ktElement.startOffsetOrUndefined, ktElement.endOffsetOrUndefined,
IrDeclarationOrigin.FAKE_OVERRIDE, IrDeclarationOrigin.FAKE_OVERRIDE,
false, false,
propertyDescriptor, propertyDescriptor,
if (propertyDescriptor.getter == null) if (propertyDescriptor.getter == null)
context.symbolTable.declareField( context.symbolTable.declareField(
ktElement.startOffsetOrUndefined, ktElement.endOffsetOrUndefined, IrDeclarationOrigin.FAKE_OVERRIDE, ktElement.startOffsetOrUndefined, ktElement.endOffsetOrUndefined, IrDeclarationOrigin.FAKE_OVERRIDE,
propertyDescriptor propertyDescriptor
) )
else null, else null,
propertyDescriptor.getter?.let { generateFakeOverrideFunction(it, ktElement) }, propertyDescriptor.getter?.let { generateFakeOverrideFunction(it, ktElement) },
propertyDescriptor.setter?.let { generateFakeOverrideFunction(it, ktElement) } propertyDescriptor.setter?.let { generateFakeOverrideFunction(it, ktElement) }
) )
private fun generateFakeOverrideFunction(functionDescriptor: FunctionDescriptor, ktElement: KtElement): IrFunction = private fun generateFakeOverrideFunction(functionDescriptor: FunctionDescriptor, ktElement: KtElement): IrFunction =
FunctionGenerator(this).generateFakeOverrideFunction(functionDescriptor, ktElement) FunctionGenerator(this).generateFakeOverrideFunction(functionDescriptor, ktElement)
} }
abstract class DeclarationGeneratorExtension(val declarationGenerator: DeclarationGenerator) : Generator { abstract class DeclarationGeneratorExtension(val declarationGenerator: DeclarationGenerator) : Generator {
override val context: GeneratorContext get() = declarationGenerator.context override val context: GeneratorContext get() = declarationGenerator.context
inline fun <T : IrDeclaration> T.buildWithScope(builder: (T) -> Unit): T = inline fun <T : IrDeclaration> T.buildWithScope(builder: (T) -> Unit): T =
also { irDeclaration -> also { irDeclaration ->
context.symbolTable.withScope(irDeclaration.descriptor) { context.symbolTable.withScope(irDeclaration.descriptor) {
builder(irDeclaration) builder(irDeclaration)
}
} }
}
} }
fun Generator.createBodyGenerator(scopeOwnerSymbol: IrSymbol) = fun Generator.createBodyGenerator(scopeOwnerSymbol: IrSymbol) =
BodyGenerator(scopeOwnerSymbol, context) BodyGenerator(scopeOwnerSymbol, context)
@@ -46,16 +46,16 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
constructor(context: GeneratorContext) : this(DeclarationGenerator(context)) constructor(context: GeneratorContext) : this(DeclarationGenerator(context))
fun generateDelegatedProperty( fun generateDelegatedProperty(
ktProperty: KtProperty, ktProperty: KtProperty,
ktDelegate: KtPropertyDelegate, ktDelegate: KtPropertyDelegate,
propertyDescriptor: PropertyDescriptor propertyDescriptor: PropertyDescriptor
): IrProperty { ): IrProperty {
val kPropertyType = getKPropertyTypeForDelegatedProperty(propertyDescriptor) val kPropertyType = getKPropertyTypeForDelegatedProperty(propertyDescriptor)
val irProperty = IrPropertyImpl( val irProperty = IrPropertyImpl(
ktProperty.startOffset, ktProperty.endOffset, IrDeclarationOrigin.DEFINED, true, ktProperty.startOffset, ktProperty.endOffset, IrDeclarationOrigin.DEFINED, true,
propertyDescriptor propertyDescriptor
).apply { ).apply {
backingField = generateDelegateFieldForProperty(propertyDescriptor, kPropertyType, ktDelegate) backingField = generateDelegateFieldForProperty(propertyDescriptor, kPropertyType, ktDelegate)
} }
@@ -67,9 +67,9 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
val getterDescriptor = propertyDescriptor.getter!! val getterDescriptor = propertyDescriptor.getter!!
irProperty.getter = generateDelegatedPropertyAccessor(ktProperty, ktDelegate, getterDescriptor) { irGetter -> irProperty.getter = generateDelegatedPropertyAccessor(ktProperty, ktDelegate, getterDescriptor) { irGetter ->
generateDelegatedPropertyGetterBody( generateDelegatedPropertyGetterBody(
irGetter, irGetter,
ktDelegate, getterDescriptor, delegateReceiverValue, ktDelegate, getterDescriptor, delegateReceiverValue,
createCallableReference(ktDelegate, kPropertyType, propertyDescriptor, irGetter.symbol) createCallableReference(ktDelegate, kPropertyType, propertyDescriptor, irGetter.symbol)
) )
} }
@@ -77,9 +77,9 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
val setterDescriptor = propertyDescriptor.setter!! val setterDescriptor = propertyDescriptor.setter!!
irProperty.setter = generateDelegatedPropertyAccessor(ktProperty, ktDelegate, setterDescriptor) { irSetter -> irProperty.setter = generateDelegatedPropertyAccessor(ktProperty, ktDelegate, setterDescriptor) { irSetter ->
generateDelegatedPropertySetterBody( generateDelegatedPropertySetterBody(
irSetter, irSetter,
ktDelegate, setterDescriptor, delegateReceiverValue, ktDelegate, setterDescriptor, delegateReceiverValue,
createCallableReference(ktDelegate, kPropertyType, propertyDescriptor, irSetter.symbol) createCallableReference(ktDelegate, kPropertyType, propertyDescriptor, irSetter.symbol)
) )
} }
} }
@@ -88,131 +88,143 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
} }
private inline fun generateDelegatedPropertyAccessor( private inline fun generateDelegatedPropertyAccessor(
ktProperty: KtProperty, ktProperty: KtProperty,
ktDelegate: KtPropertyDelegate, ktDelegate: KtPropertyDelegate,
accessorDescriptor: PropertyAccessorDescriptor, accessorDescriptor: PropertyAccessorDescriptor,
generateBody: (IrFunction) -> IrBody generateBody: (IrFunction) -> IrBody
): IrFunction = ): IrFunction =
context.symbolTable.declareSimpleFunction( context.symbolTable.declareSimpleFunction(
ktDelegate.startOffset, ktDelegate.endOffset, ktDelegate.startOffset, ktDelegate.endOffset,
IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR, IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR,
accessorDescriptor accessorDescriptor
).buildWithScope { irAccessor -> ).buildWithScope { irAccessor ->
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarations(irAccessor, ktProperty, null) FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarations(irAccessor, ktProperty, null)
irAccessor.body = generateBody(irAccessor) irAccessor.body = generateBody(irAccessor)
} }
private fun getKPropertyTypeForDelegatedProperty(propertyDescriptor: PropertyDescriptor): KotlinType { private fun getKPropertyTypeForDelegatedProperty(propertyDescriptor: PropertyDescriptor): KotlinType {
val receivers = listOfNotNull(propertyDescriptor.extensionReceiverParameter, propertyDescriptor.dispatchReceiverParameter) val receivers = listOfNotNull(propertyDescriptor.extensionReceiverParameter, propertyDescriptor.dispatchReceiverParameter)
return context.reflectionTypes.getKPropertyType(Annotations.EMPTY, receivers.map{ it.type }, propertyDescriptor.type, propertyDescriptor.isVar) return context.reflectionTypes.getKPropertyType(
Annotations.EMPTY,
receivers.map { it.type },
propertyDescriptor.type,
propertyDescriptor.isVar
)
} }
private fun generateDelegateFieldForProperty( private fun generateDelegateFieldForProperty(
propertyDescriptor: PropertyDescriptor, propertyDescriptor: PropertyDescriptor,
kPropertyType: KotlinType, kPropertyType: KotlinType,
ktDelegate: KtPropertyDelegate ktDelegate: KtPropertyDelegate
): IrField { ): IrField {
val delegateType = getDelegatedPropertyDelegateType(propertyDescriptor, ktDelegate) val delegateType = getDelegatedPropertyDelegateType(propertyDescriptor, ktDelegate)
val delegateDescriptor = createPropertyDelegateDescriptor(propertyDescriptor, delegateType, kPropertyType) val delegateDescriptor = createPropertyDelegateDescriptor(propertyDescriptor, delegateType, kPropertyType)
return context.symbolTable.declareField( return context.symbolTable.declareField(
ktDelegate.startOffset, ktDelegate.endOffset, IrDeclarationOrigin.DELEGATE, ktDelegate.startOffset, ktDelegate.endOffset, IrDeclarationOrigin.DELEGATE,
delegateDescriptor delegateDescriptor
).also { irDelegate -> ).also { irDelegate ->
irDelegate.initializer = generateInitializerBodyForPropertyDelegate( irDelegate.initializer = generateInitializerBodyForPropertyDelegate(
propertyDescriptor, kPropertyType, ktDelegate, propertyDescriptor, kPropertyType, ktDelegate,
irDelegate.symbol irDelegate.symbol
) )
} }
} }
private fun generateInitializerBodyForPropertyDelegate( private fun generateInitializerBodyForPropertyDelegate(
property: VariableDescriptorWithAccessors, property: VariableDescriptorWithAccessors,
kPropertyType: KotlinType, kPropertyType: KotlinType,
ktDelegate: KtPropertyDelegate, ktDelegate: KtPropertyDelegate,
scopeOwner: IrSymbol scopeOwner: IrSymbol
): IrExpressionBody { ): IrExpressionBody {
val ktDelegateExpression = ktDelegate.expression!! val ktDelegateExpression = ktDelegate.expression!!
val irDelegateInitializer = declarationGenerator.generateInitializerBody(scopeOwner, ktDelegateExpression) val irDelegateInitializer = declarationGenerator.generateInitializerBody(scopeOwner, ktDelegateExpression)
val provideDelegateResolvedCall = get(BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL, property) val provideDelegateResolvedCall = get(BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL, property)
?: return irDelegateInitializer ?: return irDelegateInitializer
val statementGenerator = createBodyGenerator(scopeOwner).createStatementGenerator() val statementGenerator = createBodyGenerator(scopeOwner).createStatementGenerator()
val provideDelegateCall = statementGenerator.pregenerateCall(provideDelegateResolvedCall) val provideDelegateCall = statementGenerator.pregenerateCall(provideDelegateResolvedCall)
provideDelegateCall.setExplicitReceiverValue(OnceExpressionValue(irDelegateInitializer.expression)) provideDelegateCall.setExplicitReceiverValue(OnceExpressionValue(irDelegateInitializer.expression))
provideDelegateCall.irValueArgumentsByIndex[1] = createCallableReference(ktDelegate, kPropertyType, property, scopeOwner) provideDelegateCall.irValueArgumentsByIndex[1] = createCallableReference(ktDelegate, kPropertyType, property, scopeOwner)
val irProvideDelegate = CallGenerator(statementGenerator).generateCall(ktDelegate.startOffset, ktDelegate.endOffset, provideDelegateCall) val irProvideDelegate =
CallGenerator(statementGenerator).generateCall(ktDelegate.startOffset, ktDelegate.endOffset, provideDelegateCall)
return IrExpressionBodyImpl(irProvideDelegate) return IrExpressionBodyImpl(irProvideDelegate)
} }
private fun createBackingFieldValueForDelegate(irDelegateField: IrFieldSymbol, thisClass: ClassDescriptor?, ktDelegate: KtPropertyDelegate): IntermediateValue { private fun createBackingFieldValueForDelegate(
irDelegateField: IrFieldSymbol,
thisClass: ClassDescriptor?,
ktDelegate: KtPropertyDelegate
): IntermediateValue {
val thisValue = createThisValueForDelegate(thisClass, ktDelegate) val thisValue = createThisValueForDelegate(thisClass, ktDelegate)
return BackingFieldLValue(ktDelegate.startOffset, ktDelegate.endOffset, return BackingFieldLValue(
irDelegateField.descriptor.type, ktDelegate.startOffset, ktDelegate.endOffset,
irDelegateField, irDelegateField.descriptor.type,
thisValue, irDelegateField,
null) thisValue,
null
)
} }
private fun createThisValueForDelegate(thisClass: ClassDescriptor?, ktDelegate: KtPropertyDelegate): IntermediateValue? = private fun createThisValueForDelegate(thisClass: ClassDescriptor?, ktDelegate: KtPropertyDelegate): IntermediateValue? =
thisClass?.let { thisClass?.let {
generateExpressionValue(it.thisAsReceiverParameter.type) { generateExpressionValue(it.thisAsReceiverParameter.type) {
IrGetValueImpl( IrGetValueImpl(
ktDelegate.startOffset, ktDelegate.endOffset, ktDelegate.startOffset, ktDelegate.endOffset,
context.symbolTable.referenceValueParameter(thisClass.thisAsReceiverParameter) context.symbolTable.referenceValueParameter(thisClass.thisAsReceiverParameter)
) )
}
} }
}
private fun createCallableReference( private fun createCallableReference(
ktElement: KtElement, ktElement: KtElement,
type: KotlinType, type: KotlinType,
referencedDescriptor: CallableDescriptor, referencedDescriptor: CallableDescriptor,
statementGenerator: StatementGenerator statementGenerator: StatementGenerator
): IrCallableReference = ): IrCallableReference =
ReflectionReferencesGenerator(statementGenerator).generateCallableReference( ReflectionReferencesGenerator(statementGenerator).generateCallableReference(
ktElement.startOffset, ktElement.endOffset, type, ktElement.startOffset, ktElement.endOffset, type,
referencedDescriptor, referencedDescriptor,
null, IrStatementOrigin.PROPERTY_REFERENCE_FOR_DELEGATE null, IrStatementOrigin.PROPERTY_REFERENCE_FOR_DELEGATE
) )
private fun createCallableReference( private fun createCallableReference(
ktElement: KtElement, ktElement: KtElement,
type: KotlinType, type: KotlinType,
referencedDescriptor: CallableDescriptor, referencedDescriptor: CallableDescriptor,
scopeOwner: IrSymbol scopeOwner: IrSymbol
): IrCallableReference = ): IrCallableReference =
createCallableReference( createCallableReference(
ktElement, type, referencedDescriptor, ktElement, type, referencedDescriptor,
createBodyGenerator(scopeOwner).createStatementGenerator() createBodyGenerator(scopeOwner).createStatementGenerator()
) )
private fun createLocalDelegatedPropertyReference( private fun createLocalDelegatedPropertyReference(
ktElement: KtElement, ktElement: KtElement,
type: KotlinType, type: KotlinType,
variableDescriptor: VariableDescriptorWithAccessors, variableDescriptor: VariableDescriptorWithAccessors,
irDelegateSymbol: IrVariableSymbol, irDelegateSymbol: IrVariableSymbol,
scopeOwner: IrSymbol scopeOwner: IrSymbol
): IrLocalDelegatedPropertyReference = ): IrLocalDelegatedPropertyReference =
ReflectionReferencesGenerator(createBodyGenerator(scopeOwner).createStatementGenerator()).generateLocalDelegatedPropertyReference( ReflectionReferencesGenerator(createBodyGenerator(scopeOwner).createStatementGenerator()).generateLocalDelegatedPropertyReference(
ktElement.startOffset, ktElement.endOffset, ktElement.startOffset, ktElement.endOffset,
type, variableDescriptor, irDelegateSymbol, type, variableDescriptor, irDelegateSymbol,
IrStatementOrigin.PROPERTY_REFERENCE_FOR_DELEGATE IrStatementOrigin.PROPERTY_REFERENCE_FOR_DELEGATE
) )
fun generateLocalDelegatedProperty( fun generateLocalDelegatedProperty(
ktProperty: KtProperty, ktProperty: KtProperty,
ktDelegate: KtPropertyDelegate, ktDelegate: KtPropertyDelegate,
variableDescriptor: VariableDescriptorWithAccessors, variableDescriptor: VariableDescriptorWithAccessors,
scopeOwnerSymbol: IrSymbol scopeOwnerSymbol: IrSymbol
): IrLocalDelegatedProperty { ): IrLocalDelegatedProperty {
val kPropertyType = getKPropertyTypeForLocalDelegatedProperty(variableDescriptor) val kPropertyType = getKPropertyTypeForLocalDelegatedProperty(variableDescriptor)
val irLocalDelegatedProperty = IrLocalDelegatedPropertyImpl( val irLocalDelegatedProperty = IrLocalDelegatedPropertyImpl(
ktProperty.startOffset, ktProperty.endOffset, IrDeclarationOrigin.DEFINED, ktProperty.startOffset, ktProperty.endOffset, IrDeclarationOrigin.DEFINED,
variableDescriptor variableDescriptor
).apply { ).apply {
delegate = generateDelegateVariableForLocalDelegatedProperty(ktDelegate, variableDescriptor, kPropertyType, scopeOwnerSymbol) delegate = generateDelegateVariableForLocalDelegatedProperty(ktDelegate, variableDescriptor, kPropertyType, scopeOwnerSymbol)
} }
@@ -224,12 +236,12 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
irLocalDelegatedProperty.getter = irLocalDelegatedProperty.getter =
createLocalPropertyAccessor(getterDescriptor, ktDelegate) { irGetter -> createLocalPropertyAccessor(getterDescriptor, ktDelegate) { irGetter ->
generateDelegatedPropertyGetterBody( generateDelegatedPropertyGetterBody(
irGetter,ktDelegate, getterDescriptor, delegateReceiverValue, irGetter, ktDelegate, getterDescriptor, delegateReceiverValue,
createLocalDelegatedPropertyReference( createLocalDelegatedPropertyReference(
ktDelegate, kPropertyType, ktDelegate, kPropertyType,
variableDescriptor, irDelegate.symbol, variableDescriptor, irDelegate.symbol,
irGetter.symbol irGetter.symbol
) )
) )
} }
@@ -238,12 +250,12 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
irLocalDelegatedProperty.setter = irLocalDelegatedProperty.setter =
createLocalPropertyAccessor(setterDescriptor, ktDelegate) { irSetter -> createLocalPropertyAccessor(setterDescriptor, ktDelegate) { irSetter ->
generateDelegatedPropertySetterBody( generateDelegatedPropertySetterBody(
irSetter, ktDelegate, setterDescriptor, delegateReceiverValue, irSetter, ktDelegate, setterDescriptor, delegateReceiverValue,
createLocalDelegatedPropertyReference( createLocalDelegatedPropertyReference(
ktDelegate, kPropertyType, ktDelegate, kPropertyType,
variableDescriptor, irDelegate.symbol, variableDescriptor, irDelegate.symbol,
irSetter.symbol irSetter.symbol
) )
) )
} }
} }
@@ -252,29 +264,29 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
} }
private fun generateDelegateVariableForLocalDelegatedProperty( private fun generateDelegateVariableForLocalDelegatedProperty(
ktDelegate: KtPropertyDelegate, ktDelegate: KtPropertyDelegate,
variableDescriptor: VariableDescriptorWithAccessors, variableDescriptor: VariableDescriptorWithAccessors,
kPropertyType: KotlinType, kPropertyType: KotlinType,
scopeOwner: IrSymbol scopeOwner: IrSymbol
): IrVariable { ): IrVariable {
val delegateType = getDelegatedPropertyDelegateType(variableDescriptor, ktDelegate) val delegateType = getDelegatedPropertyDelegateType(variableDescriptor, ktDelegate)
val delegateDescriptor = createLocalPropertyDelegatedDescriptor(variableDescriptor, delegateType, kPropertyType) val delegateDescriptor = createLocalPropertyDelegatedDescriptor(variableDescriptor, delegateType, kPropertyType)
return context.symbolTable.declareVariable( return context.symbolTable.declareVariable(
ktDelegate.startOffset, ktDelegate.endOffset, IrDeclarationOrigin.DELEGATE, ktDelegate.startOffset, ktDelegate.endOffset, IrDeclarationOrigin.DELEGATE,
delegateDescriptor delegateDescriptor
).also { irVariable -> ).also { irVariable ->
irVariable.initializer = generateInitializerForLocalDelegatedPropertyDelegate( irVariable.initializer = generateInitializerForLocalDelegatedPropertyDelegate(
variableDescriptor, kPropertyType, ktDelegate, variableDescriptor, kPropertyType, ktDelegate,
irVariable.symbol, irVariable.symbol,
scopeOwner scopeOwner
) )
} }
} }
private fun getDelegatedPropertyDelegateType( private fun getDelegatedPropertyDelegateType(
delegatedPropertyDescriptor: VariableDescriptorWithAccessors, delegatedPropertyDescriptor: VariableDescriptorWithAccessors,
ktDelegate: KtPropertyDelegate ktDelegate: KtPropertyDelegate
): KotlinType { ): KotlinType {
val provideDelegateResolvedCall = get(BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL, delegatedPropertyDescriptor) val provideDelegateResolvedCall = get(BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL, delegatedPropertyDescriptor)
return if (provideDelegateResolvedCall != null) return if (provideDelegateResolvedCall != null)
@@ -284,17 +296,17 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
} }
private fun generateInitializerForLocalDelegatedPropertyDelegate( private fun generateInitializerForLocalDelegatedPropertyDelegate(
variableDescriptor: VariableDescriptorWithAccessors, variableDescriptor: VariableDescriptorWithAccessors,
kPropertyType: KotlinType, kPropertyType: KotlinType,
ktDelegate: KtPropertyDelegate, ktDelegate: KtPropertyDelegate,
delegateSymbol: IrVariableSymbol, delegateSymbol: IrVariableSymbol,
scopeOwner: IrSymbol scopeOwner: IrSymbol
): IrExpression { ): IrExpression {
val ktDelegateExpression = ktDelegate.expression!! val ktDelegateExpression = ktDelegate.expression!!
val irDelegateInitializer = createBodyGenerator(scopeOwner).createStatementGenerator().generateExpression(ktDelegateExpression) val irDelegateInitializer = createBodyGenerator(scopeOwner).createStatementGenerator().generateExpression(ktDelegateExpression)
val provideDelegateResolvedCall = get(BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL, variableDescriptor) ?: val provideDelegateResolvedCall =
return irDelegateInitializer get(BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL, variableDescriptor) ?: return irDelegateInitializer
val statementGenerator = createBodyGenerator(scopeOwner).createStatementGenerator() val statementGenerator = createBodyGenerator(scopeOwner).createStatementGenerator()
@@ -308,64 +320,70 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
} }
private fun createVariableValueForDelegate(irDelegate: IrVariableSymbol, ktDelegate: KtPropertyDelegate) = private fun createVariableValueForDelegate(irDelegate: IrVariableSymbol, ktDelegate: KtPropertyDelegate) =
VariableLValue(ktDelegate.startOffset, ktDelegate.endOffset, irDelegate) VariableLValue(ktDelegate.startOffset, ktDelegate.endOffset, irDelegate)
private inline fun createLocalPropertyAccessor( private inline fun createLocalPropertyAccessor(
getterDescriptor: VariableAccessorDescriptor, getterDescriptor: VariableAccessorDescriptor,
ktDelegate: KtPropertyDelegate, ktDelegate: KtPropertyDelegate,
generateBody: (IrFunction) -> IrBody generateBody: (IrFunction) -> IrBody
) = ) =
context.symbolTable.declareSimpleFunction( context.symbolTable.declareSimpleFunction(
ktDelegate.startOffset, ktDelegate.endOffset, ktDelegate.startOffset, ktDelegate.endOffset,
IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR, IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR,
getterDescriptor getterDescriptor
).buildWithScope { irAccessor -> ).buildWithScope { irAccessor ->
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarations(irAccessor, ktDelegate, null) FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarations(irAccessor, ktDelegate, null)
irAccessor.body = generateBody(irAccessor) irAccessor.body = generateBody(irAccessor)
} }
private fun createLocalPropertyDelegatedDescriptor( private fun createLocalPropertyDelegatedDescriptor(
variableDescriptor: VariableDescriptorWithAccessors, variableDescriptor: VariableDescriptorWithAccessors,
delegateType: KotlinType, delegateType: KotlinType,
kPropertyType: KotlinType kPropertyType: KotlinType
): IrLocalDelegatedPropertyDelegateDescriptor { ): IrLocalDelegatedPropertyDelegateDescriptor {
return IrLocalDelegatedPropertyDelegateDescriptorImpl(variableDescriptor, delegateType, kPropertyType) return IrLocalDelegatedPropertyDelegateDescriptorImpl(variableDescriptor, delegateType, kPropertyType)
} }
private fun getKPropertyTypeForLocalDelegatedProperty(variableDescriptor: VariableDescriptorWithAccessors) = private fun getKPropertyTypeForLocalDelegatedProperty(variableDescriptor: VariableDescriptorWithAccessors) =
context.reflectionTypes.getKPropertyType(Annotations.EMPTY, emptyList(), variableDescriptor.type, variableDescriptor.isVar) context.reflectionTypes.getKPropertyType(Annotations.EMPTY, emptyList(), variableDescriptor.type, variableDescriptor.isVar)
private fun createPropertyDelegateDescriptor( private fun createPropertyDelegateDescriptor(
propertyDescriptor: PropertyDescriptor, propertyDescriptor: PropertyDescriptor,
delegateType: KotlinType, delegateType: KotlinType,
kPropertyType: KotlinType kPropertyType: KotlinType
): IrPropertyDelegateDescriptor = ): IrPropertyDelegateDescriptor =
IrPropertyDelegateDescriptorImpl(propertyDescriptor, delegateType, kPropertyType) IrPropertyDelegateDescriptorImpl(propertyDescriptor, delegateType, kPropertyType)
private fun generateDelegatedPropertyGetterBody( private fun generateDelegatedPropertyGetterBody(
irGetter: IrFunction, irGetter: IrFunction,
ktDelegate: KtPropertyDelegate, ktDelegate: KtPropertyDelegate,
getterDescriptor: VariableAccessorDescriptor, getterDescriptor: VariableAccessorDescriptor,
delegateReceiverValue: IntermediateValue, delegateReceiverValue: IntermediateValue,
irPropertyReference: IrCallableReference irPropertyReference: IrCallableReference
): IrBody = ): IrBody =
with(createBodyGenerator(irGetter.symbol)) { with(createBodyGenerator(irGetter.symbol)) {
irBlockBody(ktDelegate) { irBlockBody(ktDelegate) {
val statementGenerator = createStatementGenerator() val statementGenerator = createStatementGenerator()
val conventionMethodResolvedCall = getOrFail(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, getterDescriptor) val conventionMethodResolvedCall = getOrFail(BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, getterDescriptor)
val conventionMethodCall = statementGenerator.pregenerateCall(conventionMethodResolvedCall) val conventionMethodCall = statementGenerator.pregenerateCall(conventionMethodResolvedCall)
conventionMethodCall.setExplicitReceiverValue(delegateReceiverValue) conventionMethodCall.setExplicitReceiverValue(delegateReceiverValue)
conventionMethodCall.irValueArgumentsByIndex[1] = irPropertyReference conventionMethodCall.irValueArgumentsByIndex[1] = irPropertyReference
+irReturn(CallGenerator(statementGenerator).generateCall(ktDelegate.startOffset, ktDelegate.endOffset, conventionMethodCall)) +irReturn(
} CallGenerator(statementGenerator).generateCall(
ktDelegate.startOffset,
ktDelegate.endOffset,
conventionMethodCall
)
)
} }
}
private fun generateDelegatedPropertySetterBody( private fun generateDelegatedPropertySetterBody(
irSetter: IrFunction, irSetter: IrFunction,
ktDelegate: KtPropertyDelegate, ktDelegate: KtPropertyDelegate,
setterDescriptor: VariableAccessorDescriptor, setterDescriptor: VariableAccessorDescriptor,
delegateReceiverValue: IntermediateValue, delegateReceiverValue: IntermediateValue,
irPropertyReference: IrCallableReference irPropertyReference: IrCallableReference
): IrBody = with(createBodyGenerator(irSetter.symbol)) { ): IrBody = with(createBodyGenerator(irSetter.symbol)) {
irBlockBody(ktDelegate) { irBlockBody(ktDelegate) {
val statementGenerator = createStatementGenerator() val statementGenerator = createStatementGenerator()
@@ -33,38 +33,38 @@ class EnumClassMembersGenerator(declarationGenerator: DeclarationGenerator) : De
private fun generateValues(irClass: IrClass) { private fun generateValues(irClass: IrClass) {
val valuesFunction = irClass.descriptor.staticScope.findFirstFunction("values") { val valuesFunction = irClass.descriptor.staticScope.findFirstFunction("values") {
it.dispatchReceiverParameter == null && it.dispatchReceiverParameter == null &&
it.extensionReceiverParameter == null && it.extensionReceiverParameter == null &&
it.valueParameters.size == 0 it.valueParameters.size == 0
} }
irClass.addMember( irClass.addMember(
context.symbolTable.declareSimpleFunction( context.symbolTable.declareSimpleFunction(
irClass.startOffset, irClass.endOffset, irClass.startOffset, irClass.endOffset,
IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER, IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER,
valuesFunction valuesFunction
).also { irFunction -> ).also { irFunction ->
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarations(irFunction, null, null) FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarations(irFunction, null, null)
irFunction.body = IrSyntheticBodyImpl(irClass.startOffset, irClass.endOffset, IrSyntheticBodyKind.ENUM_VALUES) irFunction.body = IrSyntheticBodyImpl(irClass.startOffset, irClass.endOffset, IrSyntheticBodyKind.ENUM_VALUES)
} }
) )
} }
private fun generateValueOf(irClass: IrClass) { private fun generateValueOf(irClass: IrClass) {
val valueOfFunction = irClass.descriptor.staticScope.findFirstFunction("valueOf") { val valueOfFunction = irClass.descriptor.staticScope.findFirstFunction("valueOf") {
it.dispatchReceiverParameter == null && it.dispatchReceiverParameter == null &&
it.extensionReceiverParameter == null && it.extensionReceiverParameter == null &&
it.valueParameters.size == 1 it.valueParameters.size == 1
} }
irClass.addMember( irClass.addMember(
context.symbolTable.declareSimpleFunction( context.symbolTable.declareSimpleFunction(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, UNDEFINED_OFFSET, UNDEFINED_OFFSET,
IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER, IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER,
valueOfFunction valueOfFunction
).also { irFunction -> ).also { irFunction ->
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarations(irFunction, null, null) FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarations(irFunction, null, null)
irFunction.body = IrSyntheticBodyImpl(irClass.startOffset, irClass.endOffset, IrSyntheticBodyKind.ENUM_VALUEOF) irFunction.body = IrSyntheticBodyImpl(irClass.startOffset, irClass.endOffset, IrSyntheticBodyKind.ENUM_VALUEOF)
} }
) )
} }
} }
@@ -28,17 +28,19 @@ class ErrorExpressionGenerator(statementGenerator: StatementGenerator) : Stateme
private val ignoreErrors: Boolean get() = context.configuration.ignoreErrors private val ignoreErrors: Boolean get() = context.configuration.ignoreErrors
private inline fun generateErrorExpression(ktElement: KtElement, e: Exception? = null, body: () -> IrExpression) = private inline fun generateErrorExpression(ktElement: KtElement, e: Exception? = null, body: () -> IrExpression) =
if (ignoreErrors) if (ignoreErrors)
body() body()
else else
throw RuntimeException("${e?.message}: ${ktElement::class.java.simpleName}:\n${ktElement.text}", e) throw RuntimeException("${e?.message}: ${ktElement::class.java.simpleName}:\n${ktElement.text}", e)
fun generateErrorExpression(ktElement: KtElement, e: Exception): IrExpression = fun generateErrorExpression(ktElement: KtElement, e: Exception): IrExpression =
generateErrorExpression(ktElement, e) { generateErrorExpression(ktElement, e) {
IrErrorExpressionImpl(ktElement.startOffset, ktElement.endOffset, IrErrorExpressionImpl(
if (ktElement is KtExpression) getErrorExpressionType(ktElement) else ErrorUtils.createErrorType(""), ktElement.startOffset, ktElement.endOffset,
e.message ?: "") if (ktElement is KtExpression) getErrorExpressionType(ktElement) else ErrorUtils.createErrorType(""),
} e.message ?: ""
)
}
fun generateErrorCall(ktCall: KtCallExpression): IrExpression = generateErrorExpression(ktCall) { fun generateErrorCall(ktCall: KtCallExpression): IrExpression = generateErrorExpression(ktCall) {
val type = getErrorExpressionType(ktCall) val type = getErrorExpressionType(ktCall)
@@ -63,7 +65,7 @@ class ErrorExpressionGenerator(statementGenerator: StatementGenerator) : Stateme
} }
private fun getErrorExpressionType(ktExpression: KtExpression) = private fun getErrorExpressionType(ktExpression: KtExpression) =
getInferredTypeWithImplicitCasts(ktExpression) ?: ErrorUtils.createErrorType("") getInferredTypeWithImplicitCasts(ktExpression) ?: ErrorUtils.createErrorType("")
fun generateErrorSimpleName(ktName: KtSimpleNameExpression): IrExpression = generateErrorExpression(ktName) { fun generateErrorSimpleName(ktName: KtSimpleNameExpression): IrExpression = generateErrorExpression(ktName) {
val type = getErrorExpressionType(ktName) val type = getErrorExpressionType(ktName)
@@ -35,103 +35,107 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
constructor(context: GeneratorContext) : this(DeclarationGenerator(context)) constructor(context: GeneratorContext) : this(DeclarationGenerator(context))
fun generateFunctionDeclaration(ktFunction: KtNamedFunction): IrFunction = fun generateFunctionDeclaration(ktFunction: KtNamedFunction): IrFunction =
declareSimpleFunction( declareSimpleFunction(
ktFunction, ktFunction,
ktFunction.receiverTypeReference, ktFunction.receiverTypeReference,
IrDeclarationOrigin.DEFINED, IrDeclarationOrigin.DEFINED,
getOrFail(BindingContext.FUNCTION, ktFunction) getOrFail(BindingContext.FUNCTION, ktFunction)
) { ) {
ktFunction.bodyExpression?.let { generateFunctionBody(it) } ktFunction.bodyExpression?.let { generateFunctionBody(it) }
} }
fun generateLambdaFunctionDeclaration(ktFunction: KtFunctionLiteral): IrFunction = fun generateLambdaFunctionDeclaration(ktFunction: KtFunctionLiteral): IrFunction =
declareSimpleFunction( declareSimpleFunction(
ktFunction, ktFunction,
null, null,
IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA, IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA,
getOrFail(BindingContext.FUNCTION, ktFunction) getOrFail(BindingContext.FUNCTION, ktFunction)
) { ) {
generateLambdaBody(ktFunction) generateLambdaBody(ktFunction)
} }
fun generateFakeOverrideFunction(functionDescriptor: FunctionDescriptor, ktElement: KtElement): IrFunction = fun generateFakeOverrideFunction(functionDescriptor: FunctionDescriptor, ktElement: KtElement): IrFunction =
context.symbolTable.declareSimpleFunction( context.symbolTable.declareSimpleFunction(
ktElement.startOffsetOrUndefined, ktElement.endOffsetOrUndefined, ktElement.startOffsetOrUndefined, ktElement.endOffsetOrUndefined,
IrDeclarationOrigin.FAKE_OVERRIDE, IrDeclarationOrigin.FAKE_OVERRIDE,
functionDescriptor functionDescriptor
).buildWithScope { irFunction -> ).buildWithScope { irFunction ->
generateFunctionParameterDeclarations(irFunction, ktElement, null) generateFunctionParameterDeclarations(irFunction, ktElement, null)
} }
private inline fun declareSimpleFunction( private inline fun declareSimpleFunction(
ktFunction: KtFunction, ktFunction: KtFunction,
ktReceiver: KtElement?, ktReceiver: KtElement?,
origin: IrDeclarationOrigin, origin: IrDeclarationOrigin,
descriptor: FunctionDescriptor, descriptor: FunctionDescriptor,
generateBody: BodyGenerator.() -> IrBody? generateBody: BodyGenerator.() -> IrBody?
): IrSimpleFunction = ): IrSimpleFunction =
context.symbolTable.declareSimpleFunction( context.symbolTable.declareSimpleFunction(
ktFunction.startOffset, ktFunction.endOffset, origin, descriptor ktFunction.startOffset, ktFunction.endOffset, origin, descriptor
).buildWithScope { irFunction -> ).buildWithScope { irFunction ->
generateFunctionParameterDeclarations(irFunction, ktFunction, ktReceiver) generateFunctionParameterDeclarations(irFunction, ktFunction, ktReceiver)
irFunction.body = createBodyGenerator(irFunction.symbol).generateBody() irFunction.body = createBodyGenerator(irFunction.symbol).generateBody()
} }
fun generateFunctionParameterDeclarations( fun generateFunctionParameterDeclarations(
irFunction: IrFunction, irFunction: IrFunction,
ktParameterOwner: KtElement?, ktParameterOwner: KtElement?,
ktReceiverParameterElement: KtElement? ktReceiverParameterElement: KtElement?
) { ) {
declarationGenerator.generateTypeParameterDeclarations(irFunction, irFunction.descriptor.typeParameters) declarationGenerator.generateTypeParameterDeclarations(irFunction, irFunction.descriptor.typeParameters)
generateValueParameterDeclarations(irFunction, ktParameterOwner, ktReceiverParameterElement) generateValueParameterDeclarations(irFunction, ktParameterOwner, ktReceiverParameterElement)
} }
fun generatePropertyAccessor( fun generatePropertyAccessor(
descriptor: PropertyAccessorDescriptor, descriptor: PropertyAccessorDescriptor,
ktProperty: KtProperty, ktProperty: KtProperty,
ktAccessor: KtPropertyAccessor? ktAccessor: KtPropertyAccessor?
): IrSimpleFunction = ): IrSimpleFunction =
context.symbolTable.declareSimpleFunction( context.symbolTable.declareSimpleFunction(
ktAccessor?.startOffset ?: ktProperty.startOffset, ktAccessor?.startOffset ?: ktProperty.startOffset,
ktAccessor?.endOffset ?: ktProperty.endOffset, ktAccessor?.endOffset ?: ktProperty.endOffset,
if (ktAccessor != null) IrDeclarationOrigin.DEFINED else IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR, if (ktAccessor != null) IrDeclarationOrigin.DEFINED else IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR,
descriptor descriptor
).buildWithScope { irAccessor -> ).buildWithScope { irAccessor ->
generateFunctionParameterDeclarations(irAccessor, ktAccessor ?: ktProperty, ktProperty.receiverTypeReference) generateFunctionParameterDeclarations(irAccessor, ktAccessor ?: ktProperty, ktProperty.receiverTypeReference)
val ktBodyExpression = ktAccessor?.bodyExpression val ktBodyExpression = ktAccessor?.bodyExpression
irAccessor.body = irAccessor.body =
if (ktBodyExpression != null) if (ktBodyExpression != null)
createBodyGenerator(irAccessor.symbol).generateFunctionBody(ktBodyExpression) createBodyGenerator(irAccessor.symbol).generateFunctionBody(ktBodyExpression)
else else
generateDefaultAccessorBody(ktProperty, descriptor, irAccessor) generateDefaultAccessorBody(ktProperty, descriptor, irAccessor)
} }
fun generateDefaultAccessorForPrimaryConstructorParameter( fun generateDefaultAccessorForPrimaryConstructorParameter(
descriptor: PropertyAccessorDescriptor, descriptor: PropertyAccessorDescriptor,
ktParameter: KtParameter ktParameter: KtParameter
): IrFunction = ): IrFunction =
context.symbolTable.declareSimpleFunction( context.symbolTable.declareSimpleFunction(
ktParameter.startOffsetOrUndefined, ktParameter.startOffsetOrUndefined,
ktParameter.endOffsetOrUndefined, ktParameter.endOffsetOrUndefined,
IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR, IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR,
descriptor descriptor
).buildWithScope { irAccessor -> ).buildWithScope { irAccessor ->
declarationGenerator.generateTypeParameterDeclarations(irAccessor, descriptor.typeParameters) declarationGenerator.generateTypeParameterDeclarations(irAccessor, descriptor.typeParameters)
FunctionGenerator(declarationGenerator).generateSyntheticFunctionParameterDeclarations(irAccessor) FunctionGenerator(declarationGenerator).generateSyntheticFunctionParameterDeclarations(irAccessor)
irAccessor.body = generateDefaultAccessorBody(ktParameter, descriptor, irAccessor) irAccessor.body = generateDefaultAccessorBody(ktParameter, descriptor, irAccessor)
} }
private fun generateDefaultAccessorBody(ktProperty: KtElement, accessor: PropertyAccessorDescriptor, irAccessor: IrSimpleFunction) = private fun generateDefaultAccessorBody(ktProperty: KtElement, accessor: PropertyAccessorDescriptor, irAccessor: IrSimpleFunction) =
if (accessor.modality == Modality.ABSTRACT) if (accessor.modality == Modality.ABSTRACT)
null null
else else
when (accessor) { when (accessor) {
is PropertyGetterDescriptor -> generateDefaultGetterBody(ktProperty, accessor, irAccessor) is PropertyGetterDescriptor -> generateDefaultGetterBody(ktProperty, accessor, irAccessor)
is PropertySetterDescriptor -> generateDefaultSetterBody(ktProperty, accessor, irAccessor) is PropertySetterDescriptor -> generateDefaultSetterBody(ktProperty, accessor, irAccessor)
else -> throw AssertionError("Should be getter or setter: $accessor") else -> throw AssertionError("Should be getter or setter: $accessor")
} }
private fun generateDefaultGetterBody(ktProperty: KtElement, getter: PropertyGetterDescriptor, irAccessor: IrSimpleFunction): IrBlockBody { private fun generateDefaultGetterBody(
ktProperty: KtElement,
getter: PropertyGetterDescriptor,
irAccessor: IrSimpleFunction
): IrBlockBody {
val property = getter.correspondingProperty val property = getter.correspondingProperty
val irBody = IrBlockBodyImpl(ktProperty.startOffset, ktProperty.endOffset) val irBody = IrBlockBodyImpl(ktProperty.startOffset, ktProperty.endOffset)
@@ -139,20 +143,24 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
val receiver = generateReceiverExpressionForDefaultPropertyAccessor(ktProperty, property) val receiver = generateReceiverExpressionForDefaultPropertyAccessor(ktProperty, property)
irBody.statements.add( irBody.statements.add(
IrReturnImpl( IrReturnImpl(
ktProperty.startOffset, ktProperty.endOffset, context.builtIns.nothingType, ktProperty.startOffset, ktProperty.endOffset, context.builtIns.nothingType,
irAccessor.symbol, irAccessor.symbol,
IrGetFieldImpl( IrGetFieldImpl(
ktProperty.startOffset, ktProperty.endOffset, ktProperty.startOffset, ktProperty.endOffset,
context.symbolTable.referenceField(property), context.symbolTable.referenceField(property),
receiver receiver
)
) )
)
) )
return irBody return irBody
} }
private fun generateDefaultSetterBody(ktProperty: KtElement, setter: PropertySetterDescriptor, irAccessor: IrSimpleFunction): IrBlockBody { private fun generateDefaultSetterBody(
ktProperty: KtElement,
setter: PropertySetterDescriptor,
irAccessor: IrSimpleFunction
): IrBlockBody {
val property = setter.correspondingProperty val property = setter.correspondingProperty
val irBody = IrBlockBodyImpl(ktProperty.startOffset, ktProperty.endOffset) val irBody = IrBlockBodyImpl(ktProperty.startOffset, ktProperty.endOffset)
@@ -161,12 +169,12 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
val setterParameter = irAccessor.valueParameters.single().symbol val setterParameter = irAccessor.valueParameters.single().symbol
irBody.statements.add( irBody.statements.add(
IrSetFieldImpl( IrSetFieldImpl(
ktProperty.startOffset, ktProperty.endOffset, ktProperty.startOffset, ktProperty.endOffset,
context.symbolTable.referenceField(property), context.symbolTable.referenceField(property),
receiver, receiver,
IrGetValueImpl(ktProperty.startOffset, ktProperty.endOffset, setterParameter) IrGetValueImpl(ktProperty.startOffset, ktProperty.endOffset, setterParameter)
) )
) )
return irBody return irBody
} }
@@ -175,44 +183,46 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
val containingDeclaration = property.containingDeclaration val containingDeclaration = property.containingDeclaration
return when (containingDeclaration) { return when (containingDeclaration) {
is ClassDescriptor -> is ClassDescriptor ->
IrGetValueImpl(ktProperty.startOffset, ktProperty.endOffset, IrGetValueImpl(
context.symbolTable.referenceValue(containingDeclaration.thisAsReceiverParameter)) ktProperty.startOffset, ktProperty.endOffset,
context.symbolTable.referenceValue(containingDeclaration.thisAsReceiverParameter)
)
else -> null else -> null
} }
} }
fun generatePrimaryConstructor( fun generatePrimaryConstructor(
primaryConstructorDescriptor: ClassConstructorDescriptor, primaryConstructorDescriptor: ClassConstructorDescriptor,
ktClassOrObject: KtClassOrObject ktClassOrObject: KtClassOrObject
): IrConstructor = ): IrConstructor =
declareConstructor(ktClassOrObject, ktClassOrObject.primaryConstructor ?: ktClassOrObject, primaryConstructorDescriptor) { declareConstructor(ktClassOrObject, ktClassOrObject.primaryConstructor ?: ktClassOrObject, primaryConstructorDescriptor) {
generatePrimaryConstructorBody(ktClassOrObject) generatePrimaryConstructorBody(ktClassOrObject)
} }
fun generateSecondaryConstructor(ktConstructor: KtSecondaryConstructor): IrConstructor = fun generateSecondaryConstructor(ktConstructor: KtSecondaryConstructor): IrConstructor =
declareConstructor( declareConstructor(
ktConstructor, ktConstructor, ktConstructor, ktConstructor,
getOrFail(BindingContext.CONSTRUCTOR, ktConstructor) as ClassConstructorDescriptor getOrFail(BindingContext.CONSTRUCTOR, ktConstructor) as ClassConstructorDescriptor
) { ) {
if (ktConstructor.isConstructorDelegatingToSuper(context.bindingContext)) if (ktConstructor.isConstructorDelegatingToSuper(context.bindingContext))
generateSecondaryConstructorBodyWithNestedInitializers(ktConstructor) generateSecondaryConstructorBodyWithNestedInitializers(ktConstructor)
else else
generateSecondaryConstructorBody(ktConstructor) generateSecondaryConstructorBody(ktConstructor)
} }
private inline fun declareConstructor( private inline fun declareConstructor(
ktConstructorElement: KtElement, ktConstructorElement: KtElement,
ktParametersElement: KtElement, ktParametersElement: KtElement,
constructorDescriptor: ClassConstructorDescriptor, constructorDescriptor: ClassConstructorDescriptor,
generateBody: BodyGenerator.() -> IrBody generateBody: BodyGenerator.() -> IrBody
): IrConstructor = ): IrConstructor =
context.symbolTable.declareConstructor( context.symbolTable.declareConstructor(
ktConstructorElement.startOffset, ktConstructorElement.endOffset, IrDeclarationOrigin.DEFINED, constructorDescriptor ktConstructorElement.startOffset, ktConstructorElement.endOffset, IrDeclarationOrigin.DEFINED, constructorDescriptor
).buildWithScope { irConstructor -> ).buildWithScope { irConstructor ->
generateValueParameterDeclarations(irConstructor, ktParametersElement, null) generateValueParameterDeclarations(irConstructor, ktParametersElement, null)
irConstructor.body = createBodyGenerator(irConstructor.symbol).generateBody() irConstructor.body = createBodyGenerator(irConstructor.symbol).generateBody()
} }
fun generateSyntheticFunctionParameterDeclarations(irFunction: IrFunction) { fun generateSyntheticFunctionParameterDeclarations(irFunction: IrFunction) {
declarationGenerator.generateTypeParameterDeclarations(irFunction, irFunction.descriptor.typeParameters) declarationGenerator.generateTypeParameterDeclarations(irFunction, irFunction.descriptor.typeParameters)
@@ -220,10 +230,10 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
} }
private fun generateValueParameterDeclarations( private fun generateValueParameterDeclarations(
irFunction: IrFunction, irFunction: IrFunction,
ktParameterOwner: KtElement?, ktParameterOwner: KtElement?,
ktReceiverParameterElement: KtElement?, ktReceiverParameterElement: KtElement?,
withDefaultValues: Boolean = true withDefaultValues: Boolean = true
) { ) {
val functionDescriptor = irFunction.descriptor val functionDescriptor = irFunction.descriptor
@@ -243,33 +253,33 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
} }
private fun generateValueParameterDeclaration( private fun generateValueParameterDeclaration(
valueParameterDescriptor: ValueParameterDescriptor, valueParameterDescriptor: ValueParameterDescriptor,
ktParameter: KtParameter?, ktParameter: KtParameter?,
bodyGenerator: BodyGenerator, bodyGenerator: BodyGenerator,
withDefaultValues: Boolean withDefaultValues: Boolean
): IrValueParameter = ): IrValueParameter =
context.symbolTable.declareValueParameter( context.symbolTable.declareValueParameter(
ktParameter.startOffsetOrUndefined, ktParameter.startOffsetOrUndefined,
ktParameter.endOffsetOrUndefined, ktParameter.endOffsetOrUndefined,
IrDeclarationOrigin.DEFINED, IrDeclarationOrigin.DEFINED,
valueParameterDescriptor valueParameterDescriptor
).also { ).also {
if (withDefaultValues) { if (withDefaultValues) {
it.defaultValue = ktParameter?.defaultValue?.let { it.defaultValue = ktParameter?.defaultValue?.let {
bodyGenerator.generateExpressionBody(it) bodyGenerator.generateExpressionBody(it)
}
} }
} }
}
private fun generateReceiverParameterDeclaration( private fun generateReceiverParameterDeclaration(
receiverParameterDescriptor: ReceiverParameterDescriptor, receiverParameterDescriptor: ReceiverParameterDescriptor,
ktElement: KtElement? ktElement: KtElement?
): IrValueParameter = ): IrValueParameter =
context.symbolTable.declareValueParameter( context.symbolTable.declareValueParameter(
ktElement.startOffsetOrUndefined, ktElement.startOffsetOrUndefined,
ktElement.endOffsetOrUndefined, ktElement.endOffsetOrUndefined,
IrDeclarationOrigin.DEFINED, IrDeclarationOrigin.DEFINED,
receiverParameterDescriptor receiverParameterDescriptor
) )
} }
@@ -44,33 +44,39 @@ interface GeneratorWithScope : Generator, IrGeneratorWithScope {
fun <K, V : Any> Generator.get(slice: ReadOnlySlice<K, V>, key: K): V? = fun <K, V : Any> Generator.get(slice: ReadOnlySlice<K, V>, key: K): V? =
context.bindingContext[slice, key] context.bindingContext[slice, key]
fun <K, V : Any> Generator.getOrFail(slice: ReadOnlySlice<K, V>, key: K): V = fun <K, V : Any> Generator.getOrFail(slice: ReadOnlySlice<K, V>, key: K): V =
context.bindingContext[slice, key] ?: throw RuntimeException("No $slice for $key") context.bindingContext[slice, key] ?: throw RuntimeException("No $slice for $key")
inline fun <K, V : Any> Generator.getOrFail(slice: ReadOnlySlice<K, V>, key: K, message: (K) -> String): V = inline fun <K, V : Any> Generator.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 Generator.getInferredTypeWithImplicitCasts(key: KtExpression): KotlinType? = fun Generator.getInferredTypeWithImplicitCasts(key: KtExpression): KotlinType? =
context.bindingContext.getType(key) context.bindingContext.getType(key)
fun Generator.getInferredTypeWithImplicitCastsOrFail(key: KtExpression): KotlinType = fun Generator.getInferredTypeWithImplicitCastsOrFail(key: KtExpression): KotlinType =
getInferredTypeWithImplicitCasts(key) ?: throw RuntimeException("No type for expression: ${key.text}") getInferredTypeWithImplicitCasts(key) ?: throw RuntimeException("No type for expression: ${key.text}")
fun Generator.getResolvedCall(key: KtElement): ResolvedCall<out CallableDescriptor>? = fun Generator.getResolvedCall(key: KtElement): ResolvedCall<out CallableDescriptor>? =
key.getResolvedCall(context.bindingContext) key.getResolvedCall(context.bindingContext)
fun Generator.createDummyExpression(ktExpression: KtExpression, description: String): IrErrorExpressionImpl = fun Generator.createDummyExpression(ktExpression: KtExpression, description: String): IrErrorExpressionImpl =
IrErrorExpressionImpl(ktExpression.startOffset, ktExpression.endOffset, getInferredTypeWithImplicitCastsOrFail(ktExpression), description) IrErrorExpressionImpl(
ktExpression.startOffset,
ktExpression.endOffset,
getInferredTypeWithImplicitCastsOrFail(ktExpression),
description
)
inline fun GeneratorWithScope.irBlock(ktElement: KtElement?, inline fun GeneratorWithScope.irBlock(
origin: IrStatementOrigin? = null, resultType: KotlinType? = null, ktElement: KtElement?,
body: IrBlockBuilder.() -> Unit origin: IrStatementOrigin? = null, resultType: KotlinType? = null,
body: IrBlockBuilder.() -> Unit
): IrExpression = ): IrExpression =
this.irBlock(ktElement.startOffsetOrUndefined, ktElement.endOffsetOrUndefined, origin, resultType, body) this.irBlock(ktElement.startOffsetOrUndefined, ktElement.endOffsetOrUndefined, origin, resultType, body)
inline fun GeneratorWithScope.irBlockBody(ktElement: KtElement?, body: IrBlockBodyBuilder.() -> Unit) : IrBlockBody = inline fun GeneratorWithScope.irBlockBody(ktElement: KtElement?, body: IrBlockBodyBuilder.() -> Unit): IrBlockBody =
this.irBlockBody(ktElement.startOffsetOrUndefined, ktElement.endOffsetOrUndefined, body) this.irBlockBody(ktElement.startOffsetOrUndefined, ktElement.endOffsetOrUndefined, body)
@@ -28,9 +28,9 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.storage.LockBasedStorageManager import org.jetbrains.kotlin.storage.LockBasedStorageManager
class GeneratorContext( class GeneratorContext(
val configuration: Psi2IrConfiguration, val configuration: Psi2IrConfiguration,
val moduleDescriptor: ModuleDescriptor, val moduleDescriptor: ModuleDescriptor,
val bindingContext: BindingContext val bindingContext: BindingContext
) : IrGeneratorContext(IrBuiltIns(moduleDescriptor.builtIns)) { ) : IrGeneratorContext(IrBuiltIns(moduleDescriptor.builtIns)) {
val sourceManager = PsiSourceManager() val sourceManager = PsiSourceManager()
@@ -25,16 +25,17 @@ import org.jetbrains.kotlin.psi.KtObjectLiteralExpression
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
class LocalClassGenerator(statementGenerator: StatementGenerator): StatementGeneratorExtension(statementGenerator) { class LocalClassGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) {
fun generateObjectLiteral(ktObjectLiteral: KtObjectLiteralExpression): IrStatement { fun generateObjectLiteral(ktObjectLiteral: KtObjectLiteralExpression): IrStatement {
val objectLiteralType = getInferredTypeWithImplicitCastsOrFail(ktObjectLiteral) val objectLiteralType = getInferredTypeWithImplicitCastsOrFail(ktObjectLiteral)
val irBlock = IrBlockImpl(ktObjectLiteral.startOffset, ktObjectLiteral.endOffset, objectLiteralType, IrStatementOrigin.OBJECT_LITERAL) val irBlock =
IrBlockImpl(ktObjectLiteral.startOffset, ktObjectLiteral.endOffset, objectLiteralType, IrStatementOrigin.OBJECT_LITERAL)
val irClass = DeclarationGenerator(statementGenerator.context).generateClassOrObjectDeclaration(ktObjectLiteral.objectDeclaration) val irClass = DeclarationGenerator(statementGenerator.context).generateClassOrObjectDeclaration(ktObjectLiteral.objectDeclaration)
irBlock.statements.add(irClass) irBlock.statements.add(irClass)
val objectConstructor = irClass.descriptor.unsubstitutedPrimaryConstructor ?: val objectConstructor = irClass.descriptor.unsubstitutedPrimaryConstructor
throw AssertionError("Object literal should have a primary constructor: ${irClass.descriptor}") ?: throw AssertionError("Object literal should have a primary constructor: ${irClass.descriptor}")
assert(objectConstructor.dispatchReceiverParameter == null) { assert(objectConstructor.dispatchReceiverParameter == null) {
"Object literal constructor should have no dispatch receiver parameter: $objectConstructor" "Object literal constructor should have no dispatch receiver parameter: $objectConstructor"
} }
@@ -46,19 +47,19 @@ class LocalClassGenerator(statementGenerator: StatementGenerator): StatementGene
} }
irBlock.statements.add( irBlock.statements.add(
IrCallImpl( IrCallImpl(
ktObjectLiteral.startOffset, ktObjectLiteral.endOffset, objectLiteralType, ktObjectLiteral.startOffset, ktObjectLiteral.endOffset, objectLiteralType,
context.symbolTable.referenceConstructor(objectConstructor), context.symbolTable.referenceConstructor(objectConstructor),
objectConstructor, objectConstructor,
null, null,
IrStatementOrigin.OBJECT_LITERAL IrStatementOrigin.OBJECT_LITERAL
) )
) )
return irBlock return irBlock
} }
fun generateLocalClass(ktClassOrObject: KtClassOrObject): IrStatement = fun generateLocalClass(ktClassOrObject: KtClassOrObject): IrStatement =
DeclarationGenerator(statementGenerator.context).generateClassOrObjectDeclaration(ktClassOrObject) DeclarationGenerator(statementGenerator.context).generateClassOrObjectDeclaration(ktClassOrObject)
} }
@@ -35,38 +35,37 @@ class LocalFunctionGenerator(statementGenerator: StatementGenerator) : Statement
val irBlock = IrBlockImpl(ktLambda.startOffset, ktLambda.endOffset, lambdaExpressionType, IrStatementOrigin.LAMBDA) val irBlock = IrBlockImpl(ktLambda.startOffset, ktLambda.endOffset, lambdaExpressionType, IrStatementOrigin.LAMBDA)
irBlock.statements.add(irLambdaFunction) irBlock.statements.add(irLambdaFunction)
irBlock.statements.add( irBlock.statements.add(
IrFunctionReferenceImpl( IrFunctionReferenceImpl(
ktLambda.startOffset, ktLambda.endOffset, lambdaExpressionType, ktLambda.startOffset, ktLambda.endOffset, lambdaExpressionType,
irLambdaFunction.symbol, irLambdaFunction.symbol.descriptor, irLambdaFunction.symbol, irLambdaFunction.symbol.descriptor,
null, IrStatementOrigin.LAMBDA null, IrStatementOrigin.LAMBDA
) )
) )
return irBlock return irBlock
} }
fun generateFunction(ktFun: KtNamedFunction): IrStatement = fun generateFunction(ktFun: KtNamedFunction): IrStatement =
if (ktFun.name != null) { if (ktFun.name != null) {
generateFunctionDeclaration(ktFun) generateFunctionDeclaration(ktFun)
} } else {
else { // anonymous function expression
// anonymous function expression val funExpressionType = getInferredTypeWithImplicitCastsOrFail(ktFun)
val funExpressionType = getInferredTypeWithImplicitCastsOrFail(ktFun) val irBlock = IrBlockImpl(ktFun.startOffset, ktFun.endOffset, funExpressionType, IrStatementOrigin.ANONYMOUS_FUNCTION)
val irBlock = IrBlockImpl(ktFun.startOffset, ktFun.endOffset, funExpressionType, IrStatementOrigin.ANONYMOUS_FUNCTION)
val irFun = generateFunctionDeclaration(ktFun) val irFun = generateFunctionDeclaration(ktFun)
irBlock.statements.add(irFun) irBlock.statements.add(irFun)
irBlock.statements.add( irBlock.statements.add(
IrFunctionReferenceImpl( IrFunctionReferenceImpl(
ktFun.startOffset, ktFun.endOffset, funExpressionType, ktFun.startOffset, ktFun.endOffset, funExpressionType,
irFun.symbol, irFun.symbol.descriptor, irFun.symbol, irFun.symbol.descriptor,
null, IrStatementOrigin.ANONYMOUS_FUNCTION null, IrStatementOrigin.ANONYMOUS_FUNCTION
)
) )
)
irBlock irBlock
} }
private fun generateFunctionDeclaration(ktFun: KtNamedFunction): IrFunction = private fun generateFunctionDeclaration(ktFun: KtNamedFunction): IrFunction =
FunctionGenerator(context).generateFunctionDeclaration(ktFun) FunctionGenerator(context).generateFunctionDeclaration(ktFun)
} }
@@ -29,10 +29,12 @@ import org.jetbrains.kotlin.psi2ir.intermediate.VariableLValue
import org.jetbrains.kotlin.psi2ir.intermediate.setExplicitReceiverValue import org.jetbrains.kotlin.psi2ir.intermediate.setExplicitReceiverValue
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
class LoopExpressionGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator){ class LoopExpressionGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) {
fun generateWhileLoop(ktWhile: KtWhileExpression): IrExpression { fun generateWhileLoop(ktWhile: KtWhileExpression): IrExpression {
val irLoop = IrWhileLoopImpl(ktWhile.startOffset, ktWhile.endOffset, val irLoop = IrWhileLoopImpl(
context.builtIns.unitType, IrStatementOrigin.WHILE_LOOP) ktWhile.startOffset, ktWhile.endOffset,
context.builtIns.unitType, IrStatementOrigin.WHILE_LOOP
)
irLoop.condition = statementGenerator.generateExpression(ktWhile.condition!!) irLoop.condition = statementGenerator.generateExpression(ktWhile.condition!!)
@@ -51,8 +53,10 @@ class LoopExpressionGenerator(statementGenerator: StatementGenerator) : Statemen
} }
fun generateDoWhileLoop(ktDoWhile: KtDoWhileExpression): IrExpression { fun generateDoWhileLoop(ktDoWhile: KtDoWhileExpression): IrExpression {
val irLoop = IrDoWhileLoopImpl(ktDoWhile.startOffset, ktDoWhile.endOffset, val irLoop = IrDoWhileLoopImpl(
context.builtIns.unitType, IrStatementOrigin.DO_WHILE_LOOP) ktDoWhile.startOffset, ktDoWhile.endOffset,
context.builtIns.unitType, IrStatementOrigin.DO_WHILE_LOOP
)
statementGenerator.bodyGenerator.putLoop(ktDoWhile, irLoop) statementGenerator.bodyGenerator.putLoop(ktDoWhile, irLoop)
@@ -73,41 +77,41 @@ class LoopExpressionGenerator(statementGenerator: StatementGenerator) : Statemen
} }
private fun generateWhileLoopBody(ktLoopBody: KtBlockExpression): IrExpression = private fun generateWhileLoopBody(ktLoopBody: KtBlockExpression): IrExpression =
IrBlockImpl( IrBlockImpl(
ktLoopBody.startOffset, ktLoopBody.endOffset, context.builtIns.unitType, null, ktLoopBody.startOffset, ktLoopBody.endOffset, context.builtIns.unitType, null,
ktLoopBody.statements.map { statementGenerator.generateStatement(it) } ktLoopBody.statements.map { statementGenerator.generateStatement(it) }
) )
private fun generateDoWhileLoopBody(ktLoopBody: KtBlockExpression): IrExpression = private fun generateDoWhileLoopBody(ktLoopBody: KtBlockExpression): IrExpression =
IrCompositeImpl( IrCompositeImpl(
ktLoopBody.startOffset, ktLoopBody.endOffset, context.builtIns.unitType, null, ktLoopBody.startOffset, ktLoopBody.endOffset, context.builtIns.unitType, null,
ktLoopBody.statements.map { statementGenerator.generateStatement(it) } ktLoopBody.statements.map { statementGenerator.generateStatement(it) }
) )
fun generateBreak(ktBreak: KtBreakExpression): IrExpression { fun generateBreak(ktBreak: KtBreakExpression): IrExpression {
val parentLoop = findParentLoop(ktBreak) ?: val parentLoop = findParentLoop(ktBreak) ?: return ErrorExpressionGenerator(statementGenerator).generateErrorExpression(
return ErrorExpressionGenerator(statementGenerator).generateErrorExpression( ktBreak, RuntimeException("Loop not found for break expression: ${ktBreak.text}")
ktBreak, RuntimeException("Loop not found for break expression: ${ktBreak.text}")) )
return IrBreakImpl(ktBreak.startOffset, ktBreak.endOffset, context.builtIns.nothingType, parentLoop).apply { return IrBreakImpl(ktBreak.startOffset, ktBreak.endOffset, context.builtIns.nothingType, parentLoop).apply {
label = ktBreak.getLabelName() label = ktBreak.getLabelName()
} }
} }
fun generateContinue(ktContinue: KtContinueExpression): IrExpression { fun generateContinue(ktContinue: KtContinueExpression): IrExpression {
val parentLoop = findParentLoop(ktContinue) ?: val parentLoop = findParentLoop(ktContinue) ?: return ErrorExpressionGenerator(statementGenerator).generateErrorExpression(
return ErrorExpressionGenerator(statementGenerator).generateErrorExpression( ktContinue, RuntimeException("Loop not found for continue expression: ${ktContinue.text}")
ktContinue, RuntimeException("Loop not found for continue expression: ${ktContinue.text}")) )
return IrContinueImpl(ktContinue.startOffset, ktContinue.endOffset, context.builtIns.nothingType, parentLoop).apply { return IrContinueImpl(ktContinue.startOffset, ktContinue.endOffset, context.builtIns.nothingType, parentLoop).apply {
label = ktContinue.getLabelName() label = ktContinue.getLabelName()
} }
} }
private fun getLoopLabel(ktLoop: KtLoopExpression): String? = private fun getLoopLabel(ktLoop: KtLoopExpression): String? =
(ktLoop.parent as? KtLabeledExpression)?.getLabelName() (ktLoop.parent as? KtLabeledExpression)?.getLabelName()
private fun findParentLoop(ktWithLabel: KtExpressionWithLabel): IrLoop? = private fun findParentLoop(ktWithLabel: KtExpressionWithLabel): IrLoop? =
findParentLoop(ktWithLabel, ktWithLabel.getLabelName()) findParentLoop(ktWithLabel, ktWithLabel.getLabelName())
private fun findParentLoop(ktExpression: KtExpression, targetLabel: String?): IrLoop? { private fun findParentLoop(ktExpression: KtExpression, targetLabel: String?): IrLoop? {
var finger: KtExpression? = ktExpression var finger: KtExpression? = ktExpression
@@ -118,8 +122,7 @@ class LoopExpressionGenerator(statementGenerator: StatementGenerator) : Statemen
} }
if (targetLabel == null) { if (targetLabel == null) {
return getLoop(finger) ?: continue return getLoop(finger) ?: continue
} } else {
else {
val parent = finger.parent val parent = finger.parent
if (parent is KtLabeledExpression) { if (parent is KtLabeledExpression) {
val label = parent.getLabelName()!! val label = parent.getLabelName()!!
@@ -159,7 +162,8 @@ class LoopExpressionGenerator(statementGenerator: StatementGenerator) : Statemen
val iteratorValue = VariableLValue(irIterator) val iteratorValue = VariableLValue(irIterator)
irForBlock.statements.add(irIterator) irForBlock.statements.add(irIterator)
val irInnerWhile = IrWhileLoopImpl(ktFor.startOffset, ktFor.endOffset, context.builtIns.unitType, IrStatementOrigin.FOR_LOOP_INNER_WHILE) val irInnerWhile =
IrWhileLoopImpl(ktFor.startOffset, ktFor.endOffset, context.builtIns.unitType, IrStatementOrigin.FOR_LOOP_INNER_WHILE)
irInnerWhile.label = getLoopLabel(ktFor) irInnerWhile.label = getLoopLabel(ktFor)
statementGenerator.bodyGenerator.putLoop(ktFor, irInnerWhile) statementGenerator.bodyGenerator.putLoop(ktFor, irInnerWhile)
irForBlock.statements.add(irInnerWhile) irForBlock.statements.add(irInnerWhile)
@@ -176,18 +180,22 @@ class LoopExpressionGenerator(statementGenerator: StatementGenerator) : Statemen
nextCall.setExplicitReceiverValue(iteratorValue) nextCall.setExplicitReceiverValue(iteratorValue)
val irNextCall = callGenerator.generateCall(ktLoopRange, nextCall, IrStatementOrigin.FOR_LOOP_NEXT) val irNextCall = callGenerator.generateCall(ktLoopRange, nextCall, IrStatementOrigin.FOR_LOOP_NEXT)
val irLoopParameter = val irLoopParameter =
if (ktLoopParameter != null && ktLoopDestructuringDeclaration == null) if (ktLoopParameter != null && ktLoopDestructuringDeclaration == null)
context.symbolTable.declareVariable( context.symbolTable.declareVariable(
ktLoopParameter.startOffset, ktLoopParameter.endOffset, IrDeclarationOrigin.FOR_LOOP_VARIABLE, ktLoopParameter.startOffset, ktLoopParameter.endOffset, IrDeclarationOrigin.FOR_LOOP_VARIABLE,
getOrFail(BindingContext.VALUE_PARAMETER, ktLoopParameter), getOrFail(BindingContext.VALUE_PARAMETER, ktLoopParameter),
irNextCall irNextCall
) )
else else
scope.createTemporaryVariable(irNextCall, "loop_parameter", origin = IrDeclarationOrigin.FOR_LOOP_IMPLICIT_VARIABLE) scope.createTemporaryVariable(irNextCall, "loop_parameter", origin = IrDeclarationOrigin.FOR_LOOP_IMPLICIT_VARIABLE)
irInnerBody.statements.add(irLoopParameter) irInnerBody.statements.add(irLoopParameter)
if (ktLoopDestructuringDeclaration != null) { if (ktLoopDestructuringDeclaration != null) {
statementGenerator.declareComponentVariablesInBlock(ktLoopDestructuringDeclaration, irInnerBody, VariableLValue(irLoopParameter)) statementGenerator.declareComponentVariablesInBlock(
ktLoopDestructuringDeclaration,
irInnerBody,
VariableLValue(irLoopParameter)
)
} }
if (ktForBody != null) { if (ktForBody != null) {
@@ -27,14 +27,14 @@ import org.jetbrains.kotlin.resolve.lazy.descriptors.findPackageFragmentForFile
class ModuleGenerator(override val context: GeneratorContext) : Generator { class ModuleGenerator(override val context: GeneratorContext) : Generator {
fun generateModuleFragment(ktFiles: Collection<KtFile>): IrModuleFragment = fun generateModuleFragment(ktFiles: Collection<KtFile>): IrModuleFragment =
generateModuleFragmentWithoutDependencies(ktFiles).also { irModule -> generateModuleFragmentWithoutDependencies(ktFiles).also { irModule ->
generateUnboundSymbolsAsDependencies(irModule) generateUnboundSymbolsAsDependencies(irModule)
} }
fun generateModuleFragmentWithoutDependencies(ktFiles: Collection<KtFile>): IrModuleFragment = fun generateModuleFragmentWithoutDependencies(ktFiles: Collection<KtFile>): IrModuleFragment =
IrModuleFragmentImpl(context.moduleDescriptor, context.irBuiltIns).also { irModule -> IrModuleFragmentImpl(context.moduleDescriptor, context.irBuiltIns).also { irModule ->
irModule.files.addAll(generateFiles(ktFiles)) irModule.files.addAll(generateFiles(ktFiles))
} }
private fun generateUnboundSymbolsAsDependencies(irModule: IrModuleFragment) { private fun generateUnboundSymbolsAsDependencies(irModule: IrModuleFragment) {
ExternalDependenciesGenerator(context.symbolTable, context.irBuiltIns).generateUnboundSymbolsAsDependencies(irModule) ExternalDependenciesGenerator(context.symbolTable, context.irBuiltIns).generateUnboundSymbolsAsDependencies(irModule)
@@ -23,86 +23,95 @@ import org.jetbrains.kotlin.lexer.KtTokens
fun getInfixOperator(ktOperator: IElementType): IrStatementOrigin? = fun getInfixOperator(ktOperator: IElementType): IrStatementOrigin? =
when (ktOperator) { when (ktOperator) {
KtTokens.EQ -> IrStatementOrigin.EQ KtTokens.EQ -> IrStatementOrigin.EQ
KtTokens.PLUSEQ -> IrStatementOrigin.PLUSEQ KtTokens.PLUSEQ -> IrStatementOrigin.PLUSEQ
KtTokens.MINUSEQ -> IrStatementOrigin.MINUSEQ KtTokens.MINUSEQ -> IrStatementOrigin.MINUSEQ
KtTokens.MULTEQ -> IrStatementOrigin.MULTEQ KtTokens.MULTEQ -> IrStatementOrigin.MULTEQ
KtTokens.DIVEQ -> IrStatementOrigin.DIVEQ KtTokens.DIVEQ -> IrStatementOrigin.DIVEQ
KtTokens.PERCEQ -> IrStatementOrigin.PERCEQ KtTokens.PERCEQ -> IrStatementOrigin.PERCEQ
KtTokens.PLUS -> IrStatementOrigin.PLUS KtTokens.PLUS -> IrStatementOrigin.PLUS
KtTokens.MINUS -> IrStatementOrigin.MINUS KtTokens.MINUS -> IrStatementOrigin.MINUS
KtTokens.MUL -> IrStatementOrigin.MUL KtTokens.MUL -> IrStatementOrigin.MUL
KtTokens.DIV -> IrStatementOrigin.DIV KtTokens.DIV -> IrStatementOrigin.DIV
KtTokens.PERC -> IrStatementOrigin.PERC KtTokens.PERC -> IrStatementOrigin.PERC
KtTokens.RANGE -> IrStatementOrigin.RANGE KtTokens.RANGE -> IrStatementOrigin.RANGE
KtTokens.LT -> IrStatementOrigin.LT KtTokens.LT -> IrStatementOrigin.LT
KtTokens.LTEQ -> IrStatementOrigin.LTEQ KtTokens.LTEQ -> IrStatementOrigin.LTEQ
KtTokens.GT -> IrStatementOrigin.GT KtTokens.GT -> IrStatementOrigin.GT
KtTokens.GTEQ -> IrStatementOrigin.GTEQ KtTokens.GTEQ -> IrStatementOrigin.GTEQ
KtTokens.EQEQ -> IrStatementOrigin.EQEQ KtTokens.EQEQ -> IrStatementOrigin.EQEQ
KtTokens.EXCLEQ -> IrStatementOrigin.EXCLEQ KtTokens.EXCLEQ -> IrStatementOrigin.EXCLEQ
KtTokens.EQEQEQ -> IrStatementOrigin.EQEQEQ KtTokens.EQEQEQ -> IrStatementOrigin.EQEQEQ
KtTokens.EXCLEQEQEQ -> IrStatementOrigin.EXCLEQEQ KtTokens.EXCLEQEQEQ -> IrStatementOrigin.EXCLEQEQ
KtTokens.IN_KEYWORD -> IrStatementOrigin.IN KtTokens.IN_KEYWORD -> IrStatementOrigin.IN
KtTokens.NOT_IN -> IrStatementOrigin.NOT_IN KtTokens.NOT_IN -> IrStatementOrigin.NOT_IN
KtTokens.ANDAND -> IrStatementOrigin.ANDAND KtTokens.ANDAND -> IrStatementOrigin.ANDAND
KtTokens.OROR -> IrStatementOrigin.OROR KtTokens.OROR -> IrStatementOrigin.OROR
KtTokens.ELVIS -> IrStatementOrigin.ELVIS KtTokens.ELVIS -> IrStatementOrigin.ELVIS
else -> null else -> null
} }
fun getPrefixOperator(ktOperator: IElementType): IrStatementOrigin? = fun getPrefixOperator(ktOperator: IElementType): IrStatementOrigin? =
when (ktOperator) { when (ktOperator) {
KtTokens.PLUSPLUS -> IrStatementOrigin.PREFIX_INCR KtTokens.PLUSPLUS -> IrStatementOrigin.PREFIX_INCR
KtTokens.MINUSMINUS -> IrStatementOrigin.PREFIX_DECR KtTokens.MINUSMINUS -> IrStatementOrigin.PREFIX_DECR
KtTokens.EXCL -> IrStatementOrigin.EXCL KtTokens.EXCL -> IrStatementOrigin.EXCL
KtTokens.MINUS -> IrStatementOrigin.UMINUS KtTokens.MINUS -> IrStatementOrigin.UMINUS
KtTokens.PLUS -> IrStatementOrigin.UPLUS KtTokens.PLUS -> IrStatementOrigin.UPLUS
else -> null else -> null
} }
fun getPostfixOperator(ktOperator: IElementType): IrStatementOrigin? = fun getPostfixOperator(ktOperator: IElementType): IrStatementOrigin? =
when (ktOperator) { when (ktOperator) {
KtTokens.PLUSPLUS -> IrStatementOrigin.POSTFIX_INCR KtTokens.PLUSPLUS -> IrStatementOrigin.POSTFIX_INCR
KtTokens.MINUSMINUS -> IrStatementOrigin.POSTFIX_DECR KtTokens.MINUSMINUS -> IrStatementOrigin.POSTFIX_DECR
KtTokens.EXCLEXCL -> IrStatementOrigin.EXCLEXCL KtTokens.EXCLEXCL -> IrStatementOrigin.EXCLEXCL
else -> null else -> null
} }
fun getIrTypeOperator(ktOperator: IElementType): IrTypeOperator? = fun getIrTypeOperator(ktOperator: IElementType): IrTypeOperator? =
when (ktOperator) { when (ktOperator) {
KtTokens.IS_KEYWORD -> IrTypeOperator.INSTANCEOF KtTokens.IS_KEYWORD -> IrTypeOperator.INSTANCEOF
KtTokens.NOT_IS -> IrTypeOperator.NOT_INSTANCEOF KtTokens.NOT_IS -> IrTypeOperator.NOT_INSTANCEOF
KtTokens.AS_KEYWORD -> IrTypeOperator.CAST KtTokens.AS_KEYWORD -> IrTypeOperator.CAST
KtTokens.AS_SAFE -> IrTypeOperator.SAFE_CAST KtTokens.AS_SAFE -> IrTypeOperator.SAFE_CAST
else -> null else -> null
} }
val AUGMENTED_ASSIGNMENTS = val AUGMENTED_ASSIGNMENTS =
setOf(IrStatementOrigin.PLUSEQ, IrStatementOrigin.MINUSEQ, IrStatementOrigin.MULTEQ, IrStatementOrigin.DIVEQ, IrStatementOrigin.PERCEQ) setOf(IrStatementOrigin.PLUSEQ, IrStatementOrigin.MINUSEQ, IrStatementOrigin.MULTEQ, IrStatementOrigin.DIVEQ, IrStatementOrigin.PERCEQ)
val OPERATORS_DESUGARED_TO_CALLS = val OPERATORS_DESUGARED_TO_CALLS =
setOf(IrStatementOrigin.PLUS, IrStatementOrigin.MINUS, IrStatementOrigin.MUL, IrStatementOrigin.DIV, IrStatementOrigin.PERC, IrStatementOrigin.RANGE, setOf(
IrStatementOrigin.EXCL, IrStatementOrigin.UMINUS, IrStatementOrigin.UPLUS) IrStatementOrigin.PLUS,
IrStatementOrigin.MINUS,
IrStatementOrigin.MUL,
IrStatementOrigin.DIV,
IrStatementOrigin.PERC,
IrStatementOrigin.RANGE,
IrStatementOrigin.EXCL,
IrStatementOrigin.UMINUS,
IrStatementOrigin.UPLUS
)
val COMPARISON_OPERATORS = val COMPARISON_OPERATORS =
setOf(IrStatementOrigin.LT, IrStatementOrigin.LTEQ, IrStatementOrigin.GT, IrStatementOrigin.GTEQ) setOf(IrStatementOrigin.LT, IrStatementOrigin.LTEQ, IrStatementOrigin.GT, IrStatementOrigin.GTEQ)
val EQUALITY_OPERATORS = val EQUALITY_OPERATORS =
setOf(IrStatementOrigin.EQEQ, IrStatementOrigin.EXCLEQ) setOf(IrStatementOrigin.EQEQ, IrStatementOrigin.EXCLEQ)
val IDENTITY_OPERATORS = val IDENTITY_OPERATORS =
setOf(IrStatementOrigin.EQEQEQ, IrStatementOrigin.EXCLEQEQ) setOf(IrStatementOrigin.EQEQEQ, IrStatementOrigin.EXCLEQEQ)
val IN_OPERATORS = val IN_OPERATORS =
setOf(IrStatementOrigin.IN, IrStatementOrigin.NOT_IN) setOf(IrStatementOrigin.IN, IrStatementOrigin.NOT_IN)
val BINARY_BOOLEAN_OPERATORS = val BINARY_BOOLEAN_OPERATORS =
setOf(IrStatementOrigin.ANDAND, IrStatementOrigin.OROR) setOf(IrStatementOrigin.ANDAND, IrStatementOrigin.OROR)
val INCREMENT_DECREMENT_OPERATORS = val INCREMENT_DECREMENT_OPERATORS =
setOf(IrStatementOrigin.PREFIX_INCR, IrStatementOrigin.PREFIX_DECR, IrStatementOrigin.POSTFIX_INCR, IrStatementOrigin.POSTFIX_DECR) setOf(IrStatementOrigin.PREFIX_INCR, IrStatementOrigin.PREFIX_DECR, IrStatementOrigin.POSTFIX_INCR, IrStatementOrigin.POSTFIX_DECR)
val POSTFIX_INCREMENT_DECREMENT_OPERATORS = val POSTFIX_INCREMENT_DECREMENT_OPERATORS =
setOf(IrStatementOrigin.POSTFIX_INCR, IrStatementOrigin.POSTFIX_DECR) setOf(IrStatementOrigin.POSTFIX_INCR, IrStatementOrigin.POSTFIX_DECR)
@@ -44,7 +44,10 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
return when (irOperator) { return when (irOperator) {
null -> throw AssertionError("Unexpected prefix operator: $ktOperator") null -> throw AssertionError("Unexpected prefix operator: $ktOperator")
in INCREMENT_DECREMENT_OPERATORS -> AssignmentGenerator(statementGenerator).generatePrefixIncrementDecrement(expression, irOperator) in INCREMENT_DECREMENT_OPERATORS -> AssignmentGenerator(statementGenerator).generatePrefixIncrementDecrement(
expression,
irOperator
)
in OPERATORS_DESUGARED_TO_CALLS -> generatePrefixOperatorAsCall(expression, irOperator) in OPERATORS_DESUGARED_TO_CALLS -> generatePrefixOperatorAsCall(expression, irOperator)
else -> createDummyExpression(expression, ktOperator.toString()) else -> createDummyExpression(expression, ktOperator.toString())
} }
@@ -56,7 +59,10 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
return when (irOperator) { return when (irOperator) {
null -> throw AssertionError("Unexpected postfix operator: $ktOperator") null -> throw AssertionError("Unexpected postfix operator: $ktOperator")
in INCREMENT_DECREMENT_OPERATORS -> AssignmentGenerator(statementGenerator).generatePostfixIncrementDecrement(expression, irOperator) in INCREMENT_DECREMENT_OPERATORS -> AssignmentGenerator(statementGenerator).generatePostfixIncrementDecrement(
expression,
irOperator
)
IrStatementOrigin.EXCLEXCL -> generateExclExclOperator(expression, irOperator) IrStatementOrigin.EXCLEXCL -> generateExclExclOperator(expression, irOperator)
else -> createDummyExpression(expression, ktOperator.toString()) else -> createDummyExpression(expression, ktOperator.toString())
} }
@@ -76,8 +82,10 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
throw AssertionError("Unexpected IrTypeOperator: $irOperator") throw AssertionError("Unexpected IrTypeOperator: $irOperator")
} }
return IrTypeOperatorCallImpl(expression.startOffset, expression.endOffset, resultType, irOperator, rhsType, return IrTypeOperatorCallImpl(
statementGenerator.generateExpression(expression.left)) expression.startOffset, expression.endOffset, resultType, irOperator, rhsType,
statementGenerator.generateExpression(expression.left)
)
} }
fun generateInstanceOfExpression(expression: KtIsExpression): IrStatement { fun generateInstanceOfExpression(expression: KtIsExpression): IrStatement {
@@ -85,8 +93,10 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
val irOperator = getIrTypeOperator(ktOperator)!! val irOperator = getIrTypeOperator(ktOperator)!!
val againstType = getOrFail(BindingContext.TYPE, expression.typeReference) val againstType = getOrFail(BindingContext.TYPE, expression.typeReference)
return IrTypeOperatorCallImpl(expression.startOffset, expression.endOffset, context.builtIns.booleanType, irOperator, return IrTypeOperatorCallImpl(
againstType, statementGenerator.generateExpression(expression.leftHandSide)) expression.startOffset, expression.endOffset, context.builtIns.booleanType, irOperator,
againstType, statementGenerator.generateExpression(expression.leftHandSide)
)
} }
fun generateBinaryExpression(expression: KtBinaryExpression): IrExpression { fun generateBinaryExpression(expression: KtBinaryExpression): IrExpression {
@@ -140,15 +150,18 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
private fun generateInOperator(expression: KtBinaryExpression, irOperator: IrStatementOrigin): IrExpression { private fun generateInOperator(expression: KtBinaryExpression, irOperator: IrStatementOrigin): IrExpression {
val containsCall = getResolvedCall(expression)!! val containsCall = getResolvedCall(expression)!!
val irContainsCall = CallGenerator(statementGenerator).generateCall(expression, statementGenerator.pregenerateCall(containsCall), irOperator) val irContainsCall =
CallGenerator(statementGenerator).generateCall(expression, statementGenerator.pregenerateCall(containsCall), irOperator)
return when (irOperator) { return when (irOperator) {
IrStatementOrigin.IN -> IrStatementOrigin.IN ->
irContainsCall irContainsCall
IrStatementOrigin.NOT_IN -> IrStatementOrigin.NOT_IN ->
IrUnaryPrimitiveImpl(expression.startOffset, expression.endOffset, IrStatementOrigin.NOT_IN, IrUnaryPrimitiveImpl(
context.irBuiltIns.booleanNotSymbol, expression.startOffset, expression.endOffset, IrStatementOrigin.NOT_IN,
irContainsCall) context.irBuiltIns.booleanNotSymbol,
irContainsCall
)
else -> else ->
throw AssertionError("Unexpected in-operator $irOperator") throw AssertionError("Unexpected in-operator $irOperator")
} }
@@ -160,17 +173,21 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
val irArgument1 = statementGenerator.generateExpression(expression.right!!) val irArgument1 = statementGenerator.generateExpression(expression.right!!)
val irIdentityEquals = IrBinaryPrimitiveImpl(expression.startOffset, expression.endOffset, irOperator, val irIdentityEquals = IrBinaryPrimitiveImpl(
context.irBuiltIns.eqeqeqSymbol, expression.startOffset, expression.endOffset, irOperator,
irArgument0, irArgument1) context.irBuiltIns.eqeqeqSymbol,
irArgument0, irArgument1
)
return when (irOperator) { return when (irOperator) {
IrStatementOrigin.EQEQEQ -> IrStatementOrigin.EQEQEQ ->
irIdentityEquals irIdentityEquals
IrStatementOrigin.EXCLEQEQ -> IrStatementOrigin.EXCLEQEQ ->
IrUnaryPrimitiveImpl(expression.startOffset, expression.endOffset, IrStatementOrigin.EXCLEQEQ, IrUnaryPrimitiveImpl(
context.irBuiltIns.booleanNotSymbol, expression.startOffset, expression.endOffset, IrStatementOrigin.EXCLEQEQ,
irIdentityEquals) context.irBuiltIns.booleanNotSymbol,
irIdentityEquals
)
else -> else ->
throw AssertionError("Unexpected identity operator $irOperator") throw AssertionError("Unexpected identity operator $irOperator")
} }
@@ -181,18 +198,22 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
val irArgument0 = statementGenerator.generateExpression(expression.left!!) val irArgument0 = statementGenerator.generateExpression(expression.left!!)
val irArgument1 = statementGenerator.generateExpression(expression.right!!) val irArgument1 = statementGenerator.generateExpression(expression.right!!)
val irEquals = IrBinaryPrimitiveImpl(expression.startOffset, expression.endOffset, val irEquals = IrBinaryPrimitiveImpl(
irOperator, expression.startOffset, expression.endOffset,
context.irBuiltIns.eqeqSymbol, irOperator,
irArgument0, irArgument1) context.irBuiltIns.eqeqSymbol,
irArgument0, irArgument1
)
return when (irOperator) { return when (irOperator) {
IrStatementOrigin.EQEQ -> IrStatementOrigin.EQEQ ->
irEquals irEquals
IrStatementOrigin.EXCLEQ -> IrStatementOrigin.EXCLEQ ->
IrUnaryPrimitiveImpl(expression.startOffset, expression.endOffset, IrStatementOrigin.EXCLEQ, IrUnaryPrimitiveImpl(
context.irBuiltIns.booleanNotSymbol, expression.startOffset, expression.endOffset, IrStatementOrigin.EXCLEQ,
irEquals) context.irBuiltIns.booleanNotSymbol,
irEquals
)
else -> else ->
throw AssertionError("Unexpected equality operator $irOperator") throw AssertionError("Unexpected equality operator $irOperator")
} }
@@ -202,7 +223,8 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
private fun generateComparisonOperator(expression: KtBinaryExpression, origin: IrStatementOrigin): IrExpression { private fun generateComparisonOperator(expression: KtBinaryExpression, origin: IrStatementOrigin): IrExpression {
val compareToCall = getResolvedCall(expression)!! val compareToCall = getResolvedCall(expression)!!
val irCompareToCall = CallGenerator(statementGenerator).generateCall(expression, statementGenerator.pregenerateCall(compareToCall), origin) val irCompareToCall =
CallGenerator(statementGenerator).generateCall(expression, statementGenerator.pregenerateCall(compareToCall), origin)
val compareToZeroSymbol = when (origin) { val compareToZeroSymbol = when (origin) {
IrStatementOrigin.LT -> context.irBuiltIns.lt0Symbol IrStatementOrigin.LT -> context.irBuiltIns.lt0Symbol
@@ -45,76 +45,80 @@ class PropertyGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
val propertyDescriptor = getOrFail(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, ktParameter) val propertyDescriptor = getOrFail(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, ktParameter)
return IrPropertyImpl( return IrPropertyImpl(
ktParameter.startOffset, ktParameter.endOffset, ktParameter.startOffset, ktParameter.endOffset,
IrDeclarationOrigin.DEFINED, false, IrDeclarationOrigin.DEFINED, false,
propertyDescriptor propertyDescriptor
).also { irProperty -> ).also { irProperty ->
irProperty.backingField = irProperty.backingField =
generatePropertyBackingField(ktParameter, propertyDescriptor) { generatePropertyBackingField(ktParameter, propertyDescriptor) {
IrExpressionBodyImpl(IrGetValueImpl( IrExpressionBodyImpl(
IrGetValueImpl(
ktParameter.startOffset, ktParameter.endOffset, ktParameter.startOffset, ktParameter.endOffset,
irValueParameter.symbol, irValueParameter.symbol,
IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER
)) )
)
} }
val getter = propertyDescriptor.getter ?: val getter = propertyDescriptor.getter
throw AssertionError("Property declared in primary constructor has no getter: $propertyDescriptor") ?: throw AssertionError("Property declared in primary constructor has no getter: $propertyDescriptor")
irProperty.getter = FunctionGenerator(declarationGenerator).generateDefaultAccessorForPrimaryConstructorParameter(getter, ktParameter) irProperty.getter =
FunctionGenerator(declarationGenerator).generateDefaultAccessorForPrimaryConstructorParameter(getter, ktParameter)
if (propertyDescriptor.isVar) { if (propertyDescriptor.isVar) {
val setter = propertyDescriptor.setter ?: val setter = propertyDescriptor.setter
throw AssertionError("Property declared in primary constructor has no setter: $propertyDescriptor") ?: throw AssertionError("Property declared in primary constructor has no setter: $propertyDescriptor")
irProperty.setter = FunctionGenerator(declarationGenerator).generateDefaultAccessorForPrimaryConstructorParameter(setter, ktParameter) irProperty.setter =
FunctionGenerator(declarationGenerator).generateDefaultAccessorForPrimaryConstructorParameter(setter, ktParameter)
} }
} }
} }
private inline fun generatePropertyBackingField( private inline fun generatePropertyBackingField(
ktPropertyElement: KtElement, ktPropertyElement: KtElement,
propertyDescriptor: PropertyDescriptor, propertyDescriptor: PropertyDescriptor,
generateInitializer: (IrField) -> IrExpressionBody? generateInitializer: (IrField) -> IrExpressionBody?
) : IrField = ): IrField =
context.symbolTable.declareField( context.symbolTable.declareField(
ktPropertyElement.startOffset, ktPropertyElement.endOffset, ktPropertyElement.startOffset, ktPropertyElement.endOffset,
IrDeclarationOrigin.PROPERTY_BACKING_FIELD, IrDeclarationOrigin.PROPERTY_BACKING_FIELD,
propertyDescriptor propertyDescriptor
).also { ).also {
it.initializer = generateInitializer(it) it.initializer = generateInitializer(it)
} }
private fun generateDelegatedProperty( private fun generateDelegatedProperty(
ktProperty: KtProperty, ktProperty: KtProperty,
ktDelegate: KtPropertyDelegate, ktDelegate: KtPropertyDelegate,
propertyDescriptor: PropertyDescriptor propertyDescriptor: PropertyDescriptor
): IrProperty = ): IrProperty =
DelegatedPropertyGenerator(declarationGenerator) DelegatedPropertyGenerator(declarationGenerator)
.generateDelegatedProperty(ktProperty, ktDelegate, propertyDescriptor) .generateDelegatedProperty(ktProperty, ktDelegate, propertyDescriptor)
private fun generateSimpleProperty(ktProperty: KtProperty, propertyDescriptor: PropertyDescriptor): IrProperty = private fun generateSimpleProperty(ktProperty: KtProperty, propertyDescriptor: PropertyDescriptor): IrProperty =
IrPropertyImpl( IrPropertyImpl(
ktProperty.startOffset, ktProperty.endOffset, ktProperty.startOffset, ktProperty.endOffset,
IrDeclarationOrigin.DEFINED, false, IrDeclarationOrigin.DEFINED, false,
propertyDescriptor propertyDescriptor
).buildWithScope { irProperty -> ).buildWithScope { irProperty ->
irProperty.backingField = irProperty.backingField =
if (propertyDescriptor.hasBackingField()) if (propertyDescriptor.hasBackingField())
generatePropertyBackingField(ktProperty, propertyDescriptor) { irField -> generatePropertyBackingField(ktProperty, propertyDescriptor) { irField ->
ktProperty.initializer?.let { ktInitializer -> ktProperty.initializer?.let { ktInitializer ->
declarationGenerator.generateInitializerBody(irField.symbol, ktInitializer) declarationGenerator.generateInitializerBody(irField.symbol, ktInitializer)
}
} }
else }
null else
null
irProperty.getter = generateGetterIfRequired(ktProperty, propertyDescriptor) irProperty.getter = generateGetterIfRequired(ktProperty, propertyDescriptor)
irProperty.setter = generateSetterIfRequired(ktProperty, propertyDescriptor) irProperty.setter = generateSetterIfRequired(ktProperty, propertyDescriptor)
} }
private fun PropertyDescriptor.hasBackingField(): Boolean = private fun PropertyDescriptor.hasBackingField(): Boolean =
get(BindingContext.BACKING_FIELD_REQUIRED, this) ?: false get(BindingContext.BACKING_FIELD_REQUIRED, this) ?: false
private fun generateGetterIfRequired(ktProperty: KtProperty, property: PropertyDescriptor): IrFunction? { private fun generateGetterIfRequired(ktProperty: KtProperty, property: PropertyDescriptor): IrFunction? {
val getter = property.getter ?: return null val getter = property.getter ?: return null
@@ -37,15 +37,18 @@ class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : St
val resultType = getInferredTypeWithImplicitCastsOrFail(ktClassLiteral) val resultType = getInferredTypeWithImplicitCastsOrFail(ktClassLiteral)
return if (lhs is DoubleColonLHS.Expression && !lhs.isObjectQualifier) { return if (lhs is DoubleColonLHS.Expression && !lhs.isObjectQualifier) {
IrGetClassImpl(ktClassLiteral.startOffset, ktClassLiteral.endOffset, resultType, IrGetClassImpl(
statementGenerator.generateExpression(ktArgument)) ktClassLiteral.startOffset, ktClassLiteral.endOffset, resultType,
} statementGenerator.generateExpression(ktArgument)
else { )
} else {
val typeConstructorDeclaration = lhs.type.constructor.declarationDescriptor val typeConstructorDeclaration = lhs.type.constructor.declarationDescriptor
val typeClass = typeConstructorDeclaration ?: val typeClass = typeConstructorDeclaration
throw AssertionError("Unexpected type constructor for ${lhs.type}: $typeConstructorDeclaration") ?: throw AssertionError("Unexpected type constructor for ${lhs.type}: $typeConstructorDeclaration")
IrClassReferenceImpl(ktClassLiteral.startOffset, ktClassLiteral.endOffset, resultType, IrClassReferenceImpl(
context.symbolTable.referenceClassifier(typeClass), lhs.type) ktClassLiteral.startOffset, ktClassLiteral.endOffset, resultType,
context.symbolTable.referenceClassifier(typeClass), lhs.type
)
} }
} }
@@ -60,16 +63,16 @@ class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : St
val endOffset = ktCallableReference.endOffset val endOffset = ktCallableReference.endOffset
return statementGenerator.generateCallReceiver( return statementGenerator.generateCallReceiver(
ktCallableReference, ktCallableReference,
resultingDescriptor, resultingDescriptor,
resolvedCall.dispatchReceiver, resolvedCall.extensionReceiver, resolvedCall.dispatchReceiver, resolvedCall.extensionReceiver,
isSafe = false isSafe = false
).call { dispatchReceiverValue, extensionReceiverValue -> ).call { dispatchReceiverValue, extensionReceiverValue ->
generateCallableReference( generateCallableReference(
startOffset, endOffset, startOffset, endOffset,
getInferredTypeWithImplicitCastsOrFail(ktCallableReference), getInferredTypeWithImplicitCastsOrFail(ktCallableReference),
referencedDescriptor, referencedDescriptor,
typeArguments = null typeArguments = null
).also { irCallableReference -> ).also { irCallableReference ->
irCallableReference.dispatchReceiver = dispatchReceiverValue?.loadIfExists() irCallableReference.dispatchReceiver = dispatchReceiverValue?.loadIfExists()
irCallableReference.extensionReceiver = extensionReceiverValue?.loadIfExists() irCallableReference.extensionReceiver = extensionReceiverValue?.loadIfExists()
@@ -78,58 +81,58 @@ class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : St
} }
fun generateCallableReference( fun generateCallableReference(
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
type: KotlinType, type: KotlinType,
callableDescriptor: CallableDescriptor, callableDescriptor: CallableDescriptor,
typeArguments: Map<TypeParameterDescriptor, KotlinType>?, typeArguments: Map<TypeParameterDescriptor, KotlinType>?,
origin: IrStatementOrigin? = null origin: IrStatementOrigin? = null
): IrCallableReference = ): IrCallableReference =
when (callableDescriptor) { when (callableDescriptor) {
is FunctionDescriptor -> is FunctionDescriptor ->
generateFunctionReference( generateFunctionReference(
startOffset, endOffset, type, startOffset, endOffset, type,
context.symbolTable.referenceFunction(callableDescriptor.original), context.symbolTable.referenceFunction(callableDescriptor.original),
callableDescriptor, callableDescriptor,
typeArguments, typeArguments,
origin origin
) )
is PropertyDescriptor -> is PropertyDescriptor ->
generatePropertyReference(startOffset, endOffset, type, callableDescriptor, typeArguments, origin) generatePropertyReference(startOffset, endOffset, type, callableDescriptor, typeArguments, origin)
else -> else ->
throw AssertionError("Unexpected callable reference: $callableDescriptor") throw AssertionError("Unexpected callable reference: $callableDescriptor")
} }
fun generateLocalDelegatedPropertyReference( fun generateLocalDelegatedPropertyReference(
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
type: KotlinType, type: KotlinType,
variableDescriptor: VariableDescriptorWithAccessors, variableDescriptor: VariableDescriptorWithAccessors,
irDelegateSymbol: IrVariableSymbol, irDelegateSymbol: IrVariableSymbol,
origin: IrStatementOrigin? origin: IrStatementOrigin?
): IrLocalDelegatedPropertyReference { ): IrLocalDelegatedPropertyReference {
val getterDescriptor = variableDescriptor.getter ?: val getterDescriptor =
throw AssertionError("Local delegated property should have a getter: $variableDescriptor") variableDescriptor.getter ?: throw AssertionError("Local delegated property should have a getter: $variableDescriptor")
val setterDescriptor = variableDescriptor.setter val setterDescriptor = variableDescriptor.setter
val getterSymbol = context.symbolTable.referenceFunction(getterDescriptor) val getterSymbol = context.symbolTable.referenceFunction(getterDescriptor)
val setterSymbol = setterDescriptor?.let { context.symbolTable.referenceFunction(it) } val setterSymbol = setterDescriptor?.let { context.symbolTable.referenceFunction(it) }
return IrLocalDelegatedPropertyReferenceImpl( return IrLocalDelegatedPropertyReferenceImpl(
startOffset, endOffset, type, startOffset, endOffset, type,
variableDescriptor, variableDescriptor,
irDelegateSymbol, getterSymbol, setterSymbol, irDelegateSymbol, getterSymbol, setterSymbol,
origin origin
) )
} }
private fun generatePropertyReference( private fun generatePropertyReference(
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
type: KotlinType, type: KotlinType,
propertyDescriptor: PropertyDescriptor, propertyDescriptor: PropertyDescriptor,
typeArguments: Map<TypeParameterDescriptor, KotlinType>?, typeArguments: Map<TypeParameterDescriptor, KotlinType>?,
origin: IrStatementOrigin? origin: IrStatementOrigin?
): IrPropertyReference { ): IrPropertyReference {
val getterDescriptor = propertyDescriptor.getter val getterDescriptor = propertyDescriptor.getter
val setterDescriptor = propertyDescriptor.setter val setterDescriptor = propertyDescriptor.setter
@@ -139,27 +142,27 @@ class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : St
val setterSymbol = setterDescriptor?.let { context.symbolTable.referenceFunction(it.original) } val setterSymbol = setterDescriptor?.let { context.symbolTable.referenceFunction(it.original) }
return IrPropertyReferenceImpl( return IrPropertyReferenceImpl(
startOffset, endOffset, type, startOffset, endOffset, type,
propertyDescriptor, propertyDescriptor,
fieldSymbol, getterSymbol, setterSymbol, fieldSymbol, getterSymbol, setterSymbol,
typeArguments, typeArguments,
origin origin
) )
} }
fun generateFunctionReference( fun generateFunctionReference(
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
type: KotlinType, type: KotlinType,
symbol: IrFunctionSymbol, symbol: IrFunctionSymbol,
descriptor: FunctionDescriptor, descriptor: FunctionDescriptor,
typeArguments: Map<TypeParameterDescriptor, KotlinType>?, typeArguments: Map<TypeParameterDescriptor, KotlinType>?,
origin: IrStatementOrigin? origin: IrStatementOrigin?
): IrFunctionReference = ): IrFunctionReference =
IrFunctionReferenceImpl( IrFunctionReferenceImpl(
startOffset, endOffset, type, startOffset, endOffset, type,
symbol, descriptor, symbol, descriptor,
typeArguments, typeArguments,
origin origin
) )
} }
@@ -45,61 +45,64 @@ import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
import java.lang.AssertionError import java.lang.AssertionError
class StatementGenerator( class StatementGenerator(
val bodyGenerator: BodyGenerator, val bodyGenerator: BodyGenerator,
override val scope: Scope override val scope: Scope
) : KtVisitor<IrStatement, Nothing?>(), GeneratorWithScope { ) : KtVisitor<IrStatement, Nothing?>(), GeneratorWithScope {
override val context: GeneratorContext get() = bodyGenerator.context override val context: GeneratorContext get() = bodyGenerator.context
val scopeOwner: DeclarationDescriptor get() = bodyGenerator.scopeOwner val scopeOwner: DeclarationDescriptor get() = bodyGenerator.scopeOwner
fun generateStatement(ktElement: KtElement): IrStatement = fun generateStatement(ktElement: KtElement): IrStatement =
ktElement.genStmt() ktElement.genStmt()
fun generateStatements(ktStatements: List<KtExpression>, to: IrStatementContainer) = fun generateStatements(ktStatements: List<KtExpression>, to: IrStatementContainer) =
ktStatements.mapTo(to.statements) { generateStatement(it) } ktStatements.mapTo(to.statements) { generateStatement(it) }
fun generateExpression(ktExpression: KtExpression): IrExpression = fun generateExpression(ktExpression: KtExpression): IrExpression =
ktExpression.genExpr() ktExpression.genExpr()
private fun KtElement.genStmt(): IrStatement = private fun KtElement.genStmt(): IrStatement =
try { try {
deparenthesize().accept(this@StatementGenerator, null) deparenthesize().accept(this@StatementGenerator, null)
} } catch (e: Exception) {
catch (e: Exception) { ErrorExpressionGenerator(this@StatementGenerator).generateErrorExpression(this, e)
ErrorExpressionGenerator(this@StatementGenerator).generateErrorExpression(this, e) }
}
private fun KtElement.genExpr(): IrExpression = private fun KtElement.genExpr(): IrExpression =
genStmt().assertCast() genStmt().assertCast()
override fun visitExpression(expression: KtExpression, data: Nothing?): IrStatement = override fun visitExpression(expression: KtExpression, data: Nothing?): IrStatement =
createDummyExpression(expression, expression::class.java.simpleName) createDummyExpression(expression, expression::class.java.simpleName)
override fun visitProperty(property: KtProperty, data: Nothing?): IrStatement { override fun visitProperty(property: KtProperty, data: Nothing?): IrStatement {
val variableDescriptor = getOrFail(BindingContext.VARIABLE, property) val variableDescriptor = getOrFail(BindingContext.VARIABLE, property)
property.delegate?.let { ktDelegate -> property.delegate?.let { ktDelegate ->
return generateLocalDelegatedProperty(property, ktDelegate, variableDescriptor as VariableDescriptorWithAccessors, return generateLocalDelegatedProperty(
bodyGenerator.scopeOwnerSymbol) property, ktDelegate, variableDescriptor as VariableDescriptorWithAccessors,
bodyGenerator.scopeOwnerSymbol
)
} }
return context.symbolTable.declareVariable( return context.symbolTable.declareVariable(
property.startOffset, property.endOffset, IrDeclarationOrigin.DEFINED, property.startOffset, property.endOffset, IrDeclarationOrigin.DEFINED,
variableDescriptor, property.initializer?.genExpr() variableDescriptor, property.initializer?.genExpr()
) )
} }
private fun generateLocalDelegatedProperty( private fun generateLocalDelegatedProperty(
ktProperty: KtProperty, ktProperty: KtProperty,
ktDelegate: KtPropertyDelegate, ktDelegate: KtPropertyDelegate,
variableDescriptor: VariableDescriptorWithAccessors, variableDescriptor: VariableDescriptorWithAccessors,
scopeOwnerSymbol: IrSymbol scopeOwnerSymbol: IrSymbol
): IrStatement = ): IrStatement =
DelegatedPropertyGenerator(context) DelegatedPropertyGenerator(context)
.generateLocalDelegatedProperty(ktProperty, ktDelegate, variableDescriptor, scopeOwnerSymbol) .generateLocalDelegatedProperty(ktProperty, ktDelegate, variableDescriptor, scopeOwnerSymbol)
override fun visitDestructuringDeclaration(multiDeclaration: KtDestructuringDeclaration, data: Nothing?): IrStatement { override fun visitDestructuringDeclaration(multiDeclaration: KtDestructuringDeclaration, data: Nothing?): IrStatement {
val irBlock = IrCompositeImpl(multiDeclaration.startOffset, multiDeclaration.endOffset, val irBlock = IrCompositeImpl(
context.builtIns.unitType, IrStatementOrigin.DESTRUCTURING_DECLARATION) multiDeclaration.startOffset, multiDeclaration.endOffset,
context.builtIns.unitType, IrStatementOrigin.DESTRUCTURING_DECLARATION
)
val ktInitializer = multiDeclaration.initializer!! val ktInitializer = multiDeclaration.initializer!!
val containerValue = scope.createTemporaryVariableInBlock(ktInitializer.genExpr(), irBlock, "container") val containerValue = scope.createTemporaryVariableInBlock(ktInitializer.genExpr(), irBlock, "container")
@@ -108,7 +111,11 @@ class StatementGenerator(
return irBlock return irBlock
} }
fun declareComponentVariablesInBlock(multiDeclaration: KtDestructuringDeclaration, irBlock: IrStatementContainer, containerValue: IntermediateValue) { fun declareComponentVariablesInBlock(
multiDeclaration: KtDestructuringDeclaration,
irBlock: IrStatementContainer,
containerValue: IntermediateValue
) {
val callGenerator = CallGenerator(this) val callGenerator = CallGenerator(this)
for ((index, ktEntry) in multiDeclaration.entries.withIndex()) { for ((index, ktEntry) in multiDeclaration.entries.withIndex()) {
val componentResolvedCall = getOrFail(BindingContext.COMPONENT_RESOLVED_CALL, ktEntry) val componentResolvedCall = getOrFail(BindingContext.COMPONENT_RESOLVED_CALL, ktEntry)
@@ -121,11 +128,13 @@ class StatementGenerator(
// componentN for '_' SHOULD NOT be evaluated // componentN for '_' SHOULD NOT be evaluated
if (componentVariable.name.isSpecial) continue if (componentVariable.name.isSpecial) continue
val irComponentCall = callGenerator.generateCall(ktEntry.startOffset, ktEntry.endOffset, componentSubstitutedCall, val irComponentCall = callGenerator.generateCall(
IrStatementOrigin.COMPONENT_N.withIndex(index + 1)) ktEntry.startOffset, ktEntry.endOffset, componentSubstitutedCall,
IrStatementOrigin.COMPONENT_N.withIndex(index + 1)
)
val irComponentVar = context.symbolTable.declareVariable( val irComponentVar = context.symbolTable.declareVariable(
ktEntry.startOffset, ktEntry.endOffset, IrDeclarationOrigin.DEFINED, ktEntry.startOffset, ktEntry.endOffset, IrDeclarationOrigin.DEFINED,
componentVariable, irComponentCall componentVariable, irComponentCall
) )
irBlock.statements.add(irComponentVar) irBlock.statements.add(irComponentVar)
} }
@@ -147,45 +156,54 @@ class StatementGenerator(
override fun visitReturnExpression(expression: KtReturnExpression, data: Nothing?): IrStatement { override fun visitReturnExpression(expression: KtReturnExpression, data: Nothing?): IrStatement {
val returnTarget = getReturnExpressionTarget(expression) val returnTarget = getReturnExpressionTarget(expression)
val irReturnedExpression = expression.returnedExpression?.genExpr() ?: val irReturnedExpression = expression.returnedExpression?.genExpr() ?: IrGetObjectValueImpl(
IrGetObjectValueImpl(expression.startOffset, expression.endOffset, context.builtIns.unitType, expression.startOffset, expression.endOffset, context.builtIns.unitType,
context.symbolTable.referenceClass(context.builtIns.unit)) context.symbolTable.referenceClass(context.builtIns.unit)
return IrReturnImpl(expression.startOffset, expression.endOffset, context.builtIns.nothingType, )
context.symbolTable.referenceFunction(returnTarget), irReturnedExpression) return IrReturnImpl(
expression.startOffset, expression.endOffset, context.builtIns.nothingType,
context.symbolTable.referenceFunction(returnTarget), irReturnedExpression
)
} }
private fun scopeOwnerAsCallable() = private fun scopeOwnerAsCallable() =
(scopeOwner as? CallableDescriptor) ?: throw AssertionError("'return' in a non-callable: $scopeOwner") (scopeOwner as? CallableDescriptor) ?: throw AssertionError("'return' in a non-callable: $scopeOwner")
private fun getReturnExpressionTarget(expression: KtReturnExpression): CallableDescriptor = private fun getReturnExpressionTarget(expression: KtReturnExpression): CallableDescriptor =
if (!ExpressionTypingUtils.isFunctionLiteral(scopeOwner) && !ExpressionTypingUtils.isFunctionExpression(scopeOwner)) { if (!ExpressionTypingUtils.isFunctionLiteral(scopeOwner) && !ExpressionTypingUtils.isFunctionExpression(scopeOwner)) {
scopeOwnerAsCallable() scopeOwnerAsCallable()
} } else {
else { val label = expression.getTargetLabel()
val label = expression.getTargetLabel() when {
when { label != null -> {
label != null -> { val labelTarget = getOrFail(BindingContext.LABEL_TARGET, label)
val labelTarget = getOrFail(BindingContext.LABEL_TARGET, label) val labelTargetDescriptor = getOrFail(BindingContext.DECLARATION_TO_DESCRIPTOR, labelTarget)
val labelTargetDescriptor = getOrFail(BindingContext.DECLARATION_TO_DESCRIPTOR, labelTarget) labelTargetDescriptor as CallableDescriptor
labelTargetDescriptor as CallableDescriptor }
} ExpressionTypingUtils.isFunctionLiteral(scopeOwner) -> {
ExpressionTypingUtils.isFunctionLiteral(scopeOwner) -> { BindingContextUtils.getContainingFunctionSkipFunctionLiterals(scopeOwner, true).first
BindingContextUtils.getContainingFunctionSkipFunctionLiterals(scopeOwner, true).first }
} else -> {
else -> { scopeOwnerAsCallable()
scopeOwnerAsCallable()
}
} }
} }
}
override fun visitThrowExpression(expression: KtThrowExpression, data: Nothing?): IrStatement { override fun visitThrowExpression(expression: KtThrowExpression, data: Nothing?): IrStatement {
return IrThrowImpl(expression.startOffset, expression.endOffset, context.builtIns.nothingType, expression.thrownExpression!!.genExpr()) return IrThrowImpl(
expression.startOffset,
expression.endOffset,
context.builtIns.nothingType,
expression.thrownExpression!!.genExpr()
)
} }
override fun visitConstantExpression(expression: KtConstantExpression, data: Nothing?): IrExpression = override fun visitConstantExpression(expression: KtConstantExpression, data: Nothing?): IrExpression =
generateConstantExpression(expression, generateConstantExpression(
ConstantExpressionEvaluator.getConstant(expression, context.bindingContext) ?: expression,
error("KtConstantExpression was not evaluated: ${expression.text}")) ConstantExpressionEvaluator.getConstant(expression, context.bindingContext)
?: error("KtConstantExpression was not evaluated: ${expression.text}")
)
fun generateConstantExpression(expression: KtExpression, constant: CompileTimeConstant<*>): IrExpression { fun generateConstantExpression(expression: KtExpression, constant: CompileTimeConstant<*>): IrExpression {
val constantValue = constant.toConstantValue(getInferredTypeWithImplicitCastsOrFail(expression)) val constantValue = constant.toConstantValue(getInferredTypeWithImplicitCastsOrFail(expression))
@@ -236,13 +254,13 @@ class StatementGenerator(
} }
override fun visitLiteralStringTemplateEntry(entry: KtLiteralStringTemplateEntry, data: Nothing?): IrStatement = override fun visitLiteralStringTemplateEntry(entry: KtLiteralStringTemplateEntry, data: Nothing?): IrStatement =
IrConstImpl.string(entry.startOffset, entry.endOffset, context.builtIns.stringType, entry.text) IrConstImpl.string(entry.startOffset, entry.endOffset, context.builtIns.stringType, entry.text)
override fun visitEscapeStringTemplateEntry(entry: KtEscapeStringTemplateEntry, data: Nothing?): IrStatement = override fun visitEscapeStringTemplateEntry(entry: KtEscapeStringTemplateEntry, data: Nothing?): IrStatement =
IrConstImpl.string(entry.startOffset, entry.endOffset, context.builtIns.stringType, entry.unescapedValue) IrConstImpl.string(entry.startOffset, entry.endOffset, context.builtIns.stringType, entry.unescapedValue)
override fun visitStringTemplateEntryWithExpression(entry: KtStringTemplateEntryWithExpression, data: Nothing?): IrStatement = override fun visitStringTemplateEntryWithExpression(entry: KtStringTemplateEntryWithExpression, data: Nothing?): IrStatement =
entry.expression!!.genExpr() entry.expression!!.genExpr()
override fun visitSimpleNameExpression(expression: KtSimpleNameExpression, data: Nothing?): IrExpression { override fun visitSimpleNameExpression(expression: KtSimpleNameExpression, data: Nothing?): IrExpression {
val resolvedCall = getResolvedCall(expression) val resolvedCall = getResolvedCall(expression)
@@ -267,18 +285,17 @@ class StatementGenerator(
} }
private fun generateExpressionForReferencedDescriptor( private fun generateExpressionForReferencedDescriptor(
descriptor: DeclarationDescriptor, descriptor: DeclarationDescriptor,
expression: KtExpression, expression: KtExpression,
resolvedCall: ResolvedCall<*>? resolvedCall: ResolvedCall<*>?
): IrExpression = ): IrExpression =
CallGenerator(this).generateValueReference( CallGenerator(this).generateValueReference(
expression.startOffset, expression.endOffset, expression.startOffset, expression.endOffset,
descriptor, resolvedCall, null descriptor, resolvedCall, null
) )
override fun visitCallExpression(expression: KtCallExpression, data: Nothing?): IrStatement { override fun visitCallExpression(expression: KtCallExpression, data: Nothing?): IrStatement {
val resolvedCall = getResolvedCall(expression) ?: val resolvedCall = getResolvedCall(expression) ?: return ErrorExpressionGenerator(this).generateErrorCall(expression)
return ErrorExpressionGenerator(this).generateErrorCall(expression)
if (resolvedCall is VariableAsFunctionResolvedCall) { if (resolvedCall is VariableAsFunctionResolvedCall) {
val functionCall = pregenerateCall(resolvedCall.functionCall) val functionCall = pregenerateCall(resolvedCall.functionCall)
@@ -291,26 +308,32 @@ class StatementGenerator(
override fun visitArrayAccessExpression(expression: KtArrayAccessExpression, data: Nothing?): IrStatement { override fun visitArrayAccessExpression(expression: KtArrayAccessExpression, data: Nothing?): IrStatement {
val indexedGetCall = getOrFail(BindingContext.INDEXED_LVALUE_GET, expression) val indexedGetCall = getOrFail(BindingContext.INDEXED_LVALUE_GET, expression)
return CallGenerator(this).generateCall(expression.startOffset, expression.endOffset, return CallGenerator(this).generateCall(
pregenerateCall(indexedGetCall), IrStatementOrigin.GET_ARRAY_ELEMENT) expression.startOffset, expression.endOffset,
pregenerateCall(indexedGetCall), IrStatementOrigin.GET_ARRAY_ELEMENT
)
} }
override fun visitDotQualifiedExpression(expression: KtDotQualifiedExpression, data: Nothing?): IrStatement = override fun visitDotQualifiedExpression(expression: KtDotQualifiedExpression, data: Nothing?): IrStatement =
expression.selectorExpression!!.accept(this, data) expression.selectorExpression!!.accept(this, data)
override fun visitSafeQualifiedExpression(expression: KtSafeQualifiedExpression, data: Nothing?): IrStatement = override fun visitSafeQualifiedExpression(expression: KtSafeQualifiedExpression, data: Nothing?): IrStatement =
expression.selectorExpression!!.accept(this, data) expression.selectorExpression!!.accept(this, data)
override fun visitThisExpression(expression: KtThisExpression, data: Nothing?): IrExpression { override fun visitThisExpression(expression: KtThisExpression, data: Nothing?): IrExpression {
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 ->
IrGetValueImpl(expression.startOffset, expression.endOffset, IrGetValueImpl(
context.symbolTable.referenceValueParameter(referenceTarget.thisAsReceiverParameter)) expression.startOffset, expression.endOffset,
context.symbolTable.referenceValueParameter(referenceTarget.thisAsReceiverParameter)
)
is CallableDescriptor -> { is CallableDescriptor -> {
val extensionReceiver = referenceTarget.extensionReceiverParameter ?: TODO("No extension receiver: $referenceTarget") val extensionReceiver = referenceTarget.extensionReceiverParameter ?: TODO("No extension receiver: $referenceTarget")
IrGetValueImpl(expression.startOffset, expression.endOffset, IrGetValueImpl(
context.symbolTable.referenceValueParameter(extensionReceiver)) expression.startOffset, expression.endOffset,
context.symbolTable.referenceValueParameter(extensionReceiver)
)
} }
else -> else ->
error("Expected this or receiver: $referenceTarget") error("Expected this or receiver: $referenceTarget")
@@ -318,65 +341,67 @@ class StatementGenerator(
} }
override fun visitBinaryExpression(expression: KtBinaryExpression, data: Nothing?): IrStatement = override fun visitBinaryExpression(expression: KtBinaryExpression, data: Nothing?): IrStatement =
OperatorExpressionGenerator(this).generateBinaryExpression(expression) OperatorExpressionGenerator(this).generateBinaryExpression(expression)
override fun visitPrefixExpression(expression: KtPrefixExpression, data: Nothing?): IrStatement = override fun visitPrefixExpression(expression: KtPrefixExpression, data: Nothing?): IrStatement =
OperatorExpressionGenerator(this).generatePrefixExpression(expression) OperatorExpressionGenerator(this).generatePrefixExpression(expression)
override fun visitPostfixExpression(expression: KtPostfixExpression, data: Nothing?): IrStatement = override fun visitPostfixExpression(expression: KtPostfixExpression, data: Nothing?): IrStatement =
OperatorExpressionGenerator(this).generatePostfixExpression(expression) OperatorExpressionGenerator(this).generatePostfixExpression(expression)
override fun visitBinaryWithTypeRHSExpression(expression: KtBinaryExpressionWithTypeRHS, data: Nothing?): IrStatement = override fun visitBinaryWithTypeRHSExpression(expression: KtBinaryExpressionWithTypeRHS, data: Nothing?): IrStatement =
OperatorExpressionGenerator(this).generateCastExpression(expression) OperatorExpressionGenerator(this).generateCastExpression(expression)
override fun visitIsExpression(expression: KtIsExpression, data: Nothing?): IrStatement = override fun visitIsExpression(expression: KtIsExpression, data: Nothing?): IrStatement =
OperatorExpressionGenerator(this).generateInstanceOfExpression(expression) OperatorExpressionGenerator(this).generateInstanceOfExpression(expression)
override fun visitIfExpression(expression: KtIfExpression, data: Nothing?): IrStatement = override fun visitIfExpression(expression: KtIfExpression, data: Nothing?): IrStatement =
BranchingExpressionGenerator(this).generateIfExpression(expression) BranchingExpressionGenerator(this).generateIfExpression(expression)
override fun visitWhenExpression(expression: KtWhenExpression, data: Nothing?): IrStatement = override fun visitWhenExpression(expression: KtWhenExpression, data: Nothing?): IrStatement =
BranchingExpressionGenerator(this).generateWhenExpression(expression) BranchingExpressionGenerator(this).generateWhenExpression(expression)
override fun visitWhileExpression(expression: KtWhileExpression, data: Nothing?): IrStatement = override fun visitWhileExpression(expression: KtWhileExpression, data: Nothing?): IrStatement =
LoopExpressionGenerator(this).generateWhileLoop(expression) LoopExpressionGenerator(this).generateWhileLoop(expression)
override fun visitDoWhileExpression(expression: KtDoWhileExpression, data: Nothing?): IrStatement = override fun visitDoWhileExpression(expression: KtDoWhileExpression, data: Nothing?): IrStatement =
LoopExpressionGenerator(this).generateDoWhileLoop(expression) LoopExpressionGenerator(this).generateDoWhileLoop(expression)
override fun visitForExpression(expression: KtForExpression, data: Nothing?): IrStatement = override fun visitForExpression(expression: KtForExpression, data: Nothing?): IrStatement =
LoopExpressionGenerator(this).generateForLoop(expression) LoopExpressionGenerator(this).generateForLoop(expression)
override fun visitBreakExpression(expression: KtBreakExpression, data: Nothing?): IrStatement = override fun visitBreakExpression(expression: KtBreakExpression, data: Nothing?): IrStatement =
LoopExpressionGenerator(this).generateBreak(expression) LoopExpressionGenerator(this).generateBreak(expression)
override fun visitContinueExpression(expression: KtContinueExpression, data: Nothing?): IrStatement = override fun visitContinueExpression(expression: KtContinueExpression, data: Nothing?): IrStatement =
LoopExpressionGenerator(this).generateContinue(expression) LoopExpressionGenerator(this).generateContinue(expression)
override fun visitTryExpression(expression: KtTryExpression, data: Nothing?): IrStatement = override fun visitTryExpression(expression: KtTryExpression, data: Nothing?): IrStatement =
TryCatchExpressionGenerator(this).generateTryCatch(expression) TryCatchExpressionGenerator(this).generateTryCatch(expression)
override fun visitLambdaExpression(expression: KtLambdaExpression, data: Nothing?): IrStatement = override fun visitLambdaExpression(expression: KtLambdaExpression, data: Nothing?): IrStatement =
LocalFunctionGenerator(this).generateLambda(expression) LocalFunctionGenerator(this).generateLambda(expression)
override fun visitNamedFunction(function: KtNamedFunction, data: Nothing?): IrStatement = override fun visitNamedFunction(function: KtNamedFunction, data: Nothing?): IrStatement =
LocalFunctionGenerator(this).generateFunction(function) LocalFunctionGenerator(this).generateFunction(function)
override fun visitObjectLiteralExpression(expression: KtObjectLiteralExpression, data: Nothing?): IrStatement = override fun visitObjectLiteralExpression(expression: KtObjectLiteralExpression, data: Nothing?): IrStatement =
LocalClassGenerator(this).generateObjectLiteral(expression) LocalClassGenerator(this).generateObjectLiteral(expression)
override fun visitClassOrObject(classOrObject: KtClassOrObject, data: Nothing?): IrStatement = override fun visitClassOrObject(classOrObject: KtClassOrObject, data: Nothing?): IrStatement =
LocalClassGenerator(this).generateLocalClass(classOrObject) LocalClassGenerator(this).generateLocalClass(classOrObject)
override fun visitTypeAlias(typeAlias: KtTypeAlias, data: Nothing?): IrStatement = override fun visitTypeAlias(typeAlias: KtTypeAlias, data: Nothing?): IrStatement =
IrTypeAliasImpl(typeAlias.startOffset, typeAlias.endOffset, IrDeclarationOrigin.DEFINED, IrTypeAliasImpl(
getOrFail(BindingContext.TYPE_ALIAS, typeAlias)) typeAlias.startOffset, typeAlias.endOffset, IrDeclarationOrigin.DEFINED,
getOrFail(BindingContext.TYPE_ALIAS, typeAlias)
)
override fun visitClassLiteralExpression(expression: KtClassLiteralExpression, data: Nothing?): IrStatement = override fun visitClassLiteralExpression(expression: KtClassLiteralExpression, data: Nothing?): IrStatement =
ReflectionReferencesGenerator(this).generateClassLiteral(expression) ReflectionReferencesGenerator(this).generateClassLiteral(expression)
override fun visitCallableReferenceExpression(expression: KtCallableReferenceExpression, data: Nothing?): IrStatement = override fun visitCallableReferenceExpression(expression: KtCallableReferenceExpression, data: Nothing?): IrStatement =
ReflectionReferencesGenerator(this).generateCallableReference(expression) ReflectionReferencesGenerator(this).generateCallableReference(expression)
} }
abstract class StatementGeneratorExtension(val statementGenerator: StatementGenerator) : GeneratorWithScope { abstract class StatementGeneratorExtension(val statementGenerator: StatementGenerator) : GeneratorWithScope {
@@ -56,16 +56,16 @@ class SyntheticDescriptorsFactory {
} }
private fun isStaticPropertyInClass(propertyDescriptor: PropertyDescriptor): Boolean = private fun isStaticPropertyInClass(propertyDescriptor: PropertyDescriptor): Boolean =
propertyDescriptor.containingDeclaration is ClassDescriptor && propertyDescriptor.containingDeclaration is ClassDescriptor &&
propertyDescriptor.dispatchReceiverParameter == null && propertyDescriptor.dispatchReceiverParameter == null &&
propertyDescriptor.extensionReceiverParameter == null propertyDescriptor.extensionReceiverParameter == null
private fun isPropertyInClass(propertyDescriptor: PropertyDescriptor): Boolean = private fun isPropertyInClass(propertyDescriptor: PropertyDescriptor): Boolean =
propertyDescriptor.containingDeclaration is ClassDescriptor propertyDescriptor.containingDeclaration is ClassDescriptor
fun getOrCreatePropertyGetter(propertyDescriptor: PropertyDescriptor): PropertyGetterDescriptor = fun getOrCreatePropertyGetter(propertyDescriptor: PropertyDescriptor): PropertyGetterDescriptor =
propertyGetters.getOrPut(propertyDescriptor) { generateGetter(propertyDescriptor) } propertyGetters.getOrPut(propertyDescriptor) { generateGetter(propertyDescriptor) }
fun getOrCreatePropertySetter(propertyDescriptor: PropertyDescriptor): PropertySetterDescriptor = fun getOrCreatePropertySetter(propertyDescriptor: PropertyDescriptor): PropertySetterDescriptor =
propertySetters.getOrPut(propertyDescriptor) { generateSetter(propertyDescriptor) } propertySetters.getOrPut(propertyDescriptor) { generateSetter(propertyDescriptor) }
} }
@@ -38,12 +38,12 @@ class TryCatchExpressionGenerator(statementGenerator: StatementGenerator) : Stat
val catchParameterDescriptor = getOrFail(BindingContext.VALUE_PARAMETER, ktCatchParameter) val catchParameterDescriptor = getOrFail(BindingContext.VALUE_PARAMETER, ktCatchParameter)
val irCatch = IrCatchImpl( val irCatch = IrCatchImpl(
ktCatchClause.startOffset, ktCatchClause.endOffset, ktCatchClause.startOffset, ktCatchClause.endOffset,
context.symbolTable.declareVariable( context.symbolTable.declareVariable(
ktCatchParameter.startOffset, ktCatchParameter.endOffset, ktCatchParameter.startOffset, ktCatchParameter.endOffset,
IrDeclarationOrigin.CATCH_PARAMETER, IrDeclarationOrigin.CATCH_PARAMETER,
catchParameterDescriptor catchParameterDescriptor
) )
).apply { ).apply {
result = statementGenerator.generateExpression(ktCatchBody) result = statementGenerator.generateExpression(ktCatchBody)
} }
@@ -51,7 +51,7 @@ class TryCatchExpressionGenerator(statementGenerator: StatementGenerator) : Stat
irTryCatch.catches.add(irCatch) irTryCatch.catches.add(irCatch)
} }
irTryCatch.finallyExpression = ktTry.finallyBlock?.let{ statementGenerator.generateExpression(it.finalExpression) } irTryCatch.finallyExpression = ktTry.finallyBlock?.let { statementGenerator.generateExpression(it.finalExpression) }
return irTryCatch return irTryCatch
} }
@@ -26,18 +26,18 @@ import org.jetbrains.kotlin.types.KotlinType
import java.lang.AssertionError import java.lang.AssertionError
class ArrayAccessAssignmentReceiver( class ArrayAccessAssignmentReceiver(
val irArray: IrExpression, val irArray: IrExpression,
val irIndices: List<IrExpression>, val irIndices: List<IrExpression>,
val indexedGetCall: CallBuilder?, val indexedGetCall: CallBuilder?,
val indexedSetCall: CallBuilder?, val indexedSetCall: CallBuilder?,
val callGenerator: CallGenerator, val callGenerator: CallGenerator,
val startOffset: Int, val startOffset: Int,
val endOffset: Int, val endOffset: Int,
val origin: IrStatementOrigin val origin: IrStatementOrigin
) : AssignmentReceiver { ) : AssignmentReceiver {
private val type: KotlinType = indexedGetCall?.run { descriptor.returnType!! } ?: private val type: KotlinType =
indexedSetCall?.run { descriptor.valueParameters.last().type } ?: indexedGetCall?.run { descriptor.returnType!! } ?: indexedSetCall?.run { descriptor.valueParameters.last().type }
throw AssertionError("Array access should have either indexed-get call or indexed-set call") ?: throw AssertionError("Array access should have either indexed-get call or indexed-set call")
override fun assign(withLValue: (LValue) -> IrExpression): IrExpression { override fun assign(withLValue: (LValue) -> IrExpression): IrExpression {
val hasResult = origin.isAssignmentOperatorWithResult() val hasResult = origin.isAssignmentOperatorWithResult()
@@ -24,19 +24,19 @@ import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
class BackingFieldLValue( class BackingFieldLValue(
val startOffset: Int, val startOffset: Int,
val endOffset: Int, val endOffset: Int,
override val type: KotlinType, override val type: KotlinType,
val symbol: IrFieldSymbol, val symbol: IrFieldSymbol,
val receiver: IntermediateValue?, val receiver: IntermediateValue?,
val origin: IrStatementOrigin? val origin: IrStatementOrigin?
) : LValue, AssignmentReceiver { ) : LValue, AssignmentReceiver {
override fun store(irExpression: IrExpression): IrExpression = override fun store(irExpression: IrExpression): IrExpression =
IrSetFieldImpl(startOffset, endOffset, symbol, receiver?.load(), irExpression, origin) IrSetFieldImpl(startOffset, endOffset, symbol, receiver?.load(), irExpression, origin)
override fun load(): IrExpression = override fun load(): IrExpression =
IrGetFieldImpl(startOffset, endOffset, symbol, receiver?.load(), origin) IrGetFieldImpl(startOffset, endOffset, symbol, receiver?.load(), origin)
override fun assign(withLValue: (LValue) -> IrExpression): IrExpression = override fun assign(withLValue: (LValue) -> IrExpression): IrExpression =
withLValue(this) withLValue(this)
} }
@@ -26,9 +26,9 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
class CallBuilder( class CallBuilder(
val original: ResolvedCall<*>, val original: ResolvedCall<*>,
val descriptor: CallableDescriptor, val descriptor: CallableDescriptor,
val isExtensionInvokeCall: Boolean = false val isExtensionInvokeCall: Boolean = false
) { ) {
var superQualifier: ClassDescriptor? = null var superQualifier: ClassDescriptor? = null
@@ -39,10 +39,11 @@ class CallBuilder(
val irValueArgumentsByIndex = arrayOfNulls<IrExpression>(descriptor.valueParameters.size) val irValueArgumentsByIndex = arrayOfNulls<IrExpression>(descriptor.valueParameters.size)
fun getValueArgument(valueParameterDescriptor: ValueParameterDescriptor) = fun getValueArgument(valueParameterDescriptor: ValueParameterDescriptor) =
irValueArgumentsByIndex[valueParameterDescriptor.index + parametersOffset] irValueArgumentsByIndex[valueParameterDescriptor.index + parametersOffset]
} }
val CallBuilder.argumentsCount: Int get() = val CallBuilder.argumentsCount: Int
get() =
irValueArgumentsByIndex.size irValueArgumentsByIndex.size
var CallBuilder.lastArgument: IrExpression? var CallBuilder.lastArgument: IrExpression?
@@ -52,27 +53,33 @@ var CallBuilder.lastArgument: IrExpression?
} }
fun CallBuilder.getValueArgumentsInParameterOrder(): List<IrExpression?> = fun CallBuilder.getValueArgumentsInParameterOrder(): List<IrExpression?> =
descriptor.valueParameters.map { irValueArgumentsByIndex[it.index] } descriptor.valueParameters.map { irValueArgumentsByIndex[it.index] }
fun CallBuilder.isValueArgumentReorderingRequired() = fun CallBuilder.isValueArgumentReorderingRequired() =
original.isValueArgumentReorderingRequired() original.isValueArgumentReorderingRequired()
val CallBuilder.hasExtensionReceiver: Boolean get() = val CallBuilder.hasExtensionReceiver: Boolean
get() =
descriptor.extensionReceiverParameter != null descriptor.extensionReceiverParameter != null
val CallBuilder.hasDispatchReceiver: Boolean get() = val CallBuilder.hasDispatchReceiver: Boolean
get() =
descriptor.dispatchReceiverParameter != null descriptor.dispatchReceiverParameter != null
val CallBuilder.extensionReceiverType: KotlinType? get() = val CallBuilder.extensionReceiverType: KotlinType?
get() =
descriptor.extensionReceiverParameter?.type descriptor.extensionReceiverParameter?.type
val CallBuilder.dispatchReceiverType: KotlinType? get() = val CallBuilder.dispatchReceiverType: KotlinType?
get() =
descriptor.dispatchReceiverParameter?.type descriptor.dispatchReceiverParameter?.type
val CallBuilder.explicitReceiverParameter: ReceiverParameterDescriptor? get() = val CallBuilder.explicitReceiverParameter: ReceiverParameterDescriptor?
get() =
descriptor.extensionReceiverParameter ?: descriptor.dispatchReceiverParameter descriptor.extensionReceiverParameter ?: descriptor.dispatchReceiverParameter
val CallBuilder.explicitReceiverType: KotlinType? get() = val CallBuilder.explicitReceiverType: KotlinType?
get() =
explicitReceiverParameter?.type explicitReceiverParameter?.type
fun CallBuilder.setExplicitReceiverValue(explicitReceiverValue: IntermediateValue) { fun CallBuilder.setExplicitReceiverValue(explicitReceiverValue: IntermediateValue) {
@@ -23,21 +23,21 @@ import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
class DelegatedLocalPropertyLValue( class DelegatedLocalPropertyLValue(
val startOffset: Int, val startOffset: Int,
val endOffset: Int, val endOffset: Int,
override val type: KotlinType, override val type: KotlinType,
val getterSymbol: IrSimpleFunctionSymbol?, val getterSymbol: IrSimpleFunctionSymbol?,
val setterSymbol: IrSimpleFunctionSymbol?, val setterSymbol: IrSimpleFunctionSymbol?,
val origin: IrStatementOrigin? = null val origin: IrStatementOrigin? = null
) : LValue, AssignmentReceiver { ) : LValue, AssignmentReceiver {
override fun load(): IrExpression = override fun load(): IrExpression =
IrCallImpl(startOffset, endOffset, type, getterSymbol!!, getterSymbol.descriptor, null, origin) IrCallImpl(startOffset, endOffset, type, getterSymbol!!, getterSymbol.descriptor, null, origin)
override fun store(irExpression: IrExpression): IrExpression = override fun store(irExpression: IrExpression): IrExpression =
IrCallImpl(startOffset, endOffset, type, setterSymbol!!, setterSymbol.descriptor, null, origin).apply { IrCallImpl(startOffset, endOffset, type, setterSymbol!!, setterSymbol.descriptor, null, origin).apply {
putValueArgument(0, irExpression) putValueArgument(0, irExpression)
} }
override fun assign(withLValue: (LValue) -> IrExpression): IrExpression = override fun assign(withLValue: (LValue) -> IrExpression): IrExpression =
withLValue(this) withLValue(this)
} }
@@ -19,9 +19,9 @@ package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
class ExtensionInvokeCallReceiver( class ExtensionInvokeCallReceiver(
val callBuilder: CallBuilder, val callBuilder: CallBuilder,
val functionReceiver: IntermediateValue, val functionReceiver: IntermediateValue,
val extensionInvokeReceiver: IntermediateValue val extensionInvokeReceiver: IntermediateValue
) : CallReceiver { ) : CallReceiver {
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression { override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression {
// extensionInvokeReceiver is actually a first argument: // extensionInvokeReceiver is actually a first argument:
@@ -23,18 +23,17 @@ import org.jetbrains.kotlin.psi2ir.generators.CallGenerator
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
class LValueWithGetterAndSetterCalls( class LValueWithGetterAndSetterCalls(
val callGenerator: CallGenerator, val callGenerator: CallGenerator,
val getterCall: CallBuilder?, val getterCall: CallBuilder?,
val setterCall: CallBuilder?, val setterCall: CallBuilder?,
override val type: KotlinType, override val type: KotlinType,
val startOffset: Int, val startOffset: Int,
val endOffset: Int, val endOffset: Int,
val origin: IrStatementOrigin? = null val origin: IrStatementOrigin? = null
) : LValue { ) : LValue {
private val descriptor: CallableDescriptor = private val descriptor: CallableDescriptor =
getterCall?.descriptor ?: getterCall?.descriptor ?: setterCall?.descriptor
setterCall?.descriptor ?: ?: throw AssertionError("Call-based LValue should have either a getter or a setter call")
throw AssertionError("Call-based LValue should have either a getter or a setter call")
override fun load(): IrExpression { override fun load(): IrExpression {
if (getterCall == null) throw AssertionError("No getter call for $descriptor") if (getterCall == null) throw AssertionError("No getter call for $descriptor")
@@ -23,12 +23,12 @@ import org.jetbrains.kotlin.psi2ir.generators.StatementGenerator
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
class OnceCallValue( class OnceCallValue(
val startOffset: Int, val startOffset: Int,
val endOffset: Int, val endOffset: Int,
val statementGenerator: StatementGenerator, val statementGenerator: StatementGenerator,
val call: CallBuilder, val call: CallBuilder,
val origin: IrStatementOrigin? = null val origin: IrStatementOrigin? = null
): IntermediateValue { ) : IntermediateValue {
private var instantiated = false private var instantiated = false
override fun load(): IrExpression { override fun load(): IrExpression {
@@ -23,15 +23,15 @@ import org.jetbrains.kotlin.types.KotlinType
abstract class ExpressionValue(override val type: KotlinType) : IntermediateValue abstract class ExpressionValue(override val type: KotlinType) : IntermediateValue
inline fun generateExpressionValue(type: KotlinType, crossinline generate: () -> IrExpression) = inline fun generateExpressionValue(type: KotlinType, crossinline generate: () -> IrExpression) =
object : ExpressionValue(type) { object : ExpressionValue(type) {
override fun load(): IrExpression = generate() override fun load(): IrExpression = generate()
} }
inline fun generateDelegatedValue(type: KotlinType, crossinline generateValue: () -> IntermediateValue) = inline fun generateDelegatedValue(type: KotlinType, crossinline generateValue: () -> IntermediateValue) =
object : ExpressionValue(type) { object : ExpressionValue(type) {
val lazyDelegate by lazy { generateValue() } val lazyDelegate by lazy { generateValue() }
override fun load(): IrExpression = lazyDelegate.load() override fun load(): IrExpression = lazyDelegate.load()
} }
class OnceExpressionValue(val irExpression: IrExpression) : LValue, AssignmentReceiver { class OnceExpressionValue(val irExpression: IrExpression) : LValue, AssignmentReceiver {
private var instantiated = false private var instantiated = false
@@ -49,5 +49,5 @@ class OnceExpressionValue(val irExpression: IrExpression) : LValue, AssignmentRe
} }
override fun assign(withLValue: (LValue) -> IrExpression): IrExpression = override fun assign(withLValue: (LValue) -> IrExpression): IrExpression =
withLValue(this) withLValue(this)
} }
@@ -28,131 +28,131 @@ import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
abstract class PropertyLValueBase( abstract class PropertyLValueBase(
val scope: Scope, val scope: Scope,
val startOffset: Int, val startOffset: Int,
val endOffset: Int, val endOffset: Int,
val origin: IrStatementOrigin?, val origin: IrStatementOrigin?,
override val type: KotlinType, override val type: KotlinType,
val callReceiver: CallReceiver, val callReceiver: CallReceiver,
val superQualifier: IrClassSymbol? val superQualifier: IrClassSymbol?
) : LValue, AssignmentReceiver { ) : LValue, AssignmentReceiver {
override fun assign(withLValue: (LValue) -> IrExpression) = override fun assign(withLValue: (LValue) -> IrExpression) =
callReceiver.call { dispatchReceiverValue, extensionReceiverValue -> callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
val dispatchReceiverVariable2 = dispatchReceiverValue?.let { val dispatchReceiverVariable2 = dispatchReceiverValue?.let {
scope.createTemporaryVariable(dispatchReceiverValue.load(), "this") scope.createTemporaryVariable(dispatchReceiverValue.load(), "this")
}
val dispatchReceiverValue2 = dispatchReceiverVariable2?.let { VariableLValue(it) }
val extensionReceiverVariable2 = extensionReceiverValue?.let {
scope.createTemporaryVariable(extensionReceiverValue.load(), "receiver")
}
val extensionReceiverValue2 = extensionReceiverVariable2?.let { VariableLValue(it) }
val irResultExpression = withLValue(withReceiver(dispatchReceiverValue2, extensionReceiverValue2))
val irBlock = IrBlockImpl(startOffset, endOffset, irResultExpression.type, origin)
irBlock.addIfNotNull(dispatchReceiverVariable2)
irBlock.addIfNotNull(extensionReceiverVariable2)
irBlock.statements.add(irResultExpression)
irBlock
} }
val dispatchReceiverValue2 = dispatchReceiverVariable2?.let { VariableLValue(it) }
val extensionReceiverVariable2 = extensionReceiverValue?.let {
scope.createTemporaryVariable(extensionReceiverValue.load(), "receiver")
}
val extensionReceiverValue2 = extensionReceiverVariable2?.let { VariableLValue(it) }
val irResultExpression = withLValue(withReceiver(dispatchReceiverValue2, extensionReceiverValue2))
val irBlock = IrBlockImpl(startOffset, endOffset, irResultExpression.type, origin)
irBlock.addIfNotNull(dispatchReceiverVariable2)
irBlock.addIfNotNull(extensionReceiverVariable2)
irBlock.statements.add(irResultExpression)
irBlock
}
override fun assign(value: IrExpression): IrExpression = override fun assign(value: IrExpression): IrExpression =
store(value) store(value)
protected abstract fun withReceiver(dispatchReceiver: VariableLValue?, extensionReceiver: VariableLValue?): PropertyLValueBase protected abstract fun withReceiver(dispatchReceiver: VariableLValue?, extensionReceiver: VariableLValue?): PropertyLValueBase
} }
class FieldPropertyLValue( class FieldPropertyLValue(
scope: Scope, scope: Scope,
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
origin: IrStatementOrigin?, origin: IrStatementOrigin?,
val field: IrFieldSymbol, val field: IrFieldSymbol,
callReceiver: CallReceiver, callReceiver: CallReceiver,
superQualifier: IrClassSymbol? superQualifier: IrClassSymbol?
) : PropertyLValueBase(scope, startOffset, endOffset, origin, field.descriptor.type, callReceiver, superQualifier) { ) : PropertyLValueBase(scope, startOffset, endOffset, origin, field.descriptor.type, callReceiver, superQualifier) {
override fun load(): IrExpression = override fun load(): IrExpression =
callReceiver.call { dispatchReceiverValue, extensionReceiverValue -> callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
assert(extensionReceiverValue == null) { "Field can't have an extension receiver: ${field.descriptor}" } assert(extensionReceiverValue == null) { "Field can't have an extension receiver: ${field.descriptor}" }
IrGetFieldImpl( IrGetFieldImpl(
startOffset, endOffset, startOffset, endOffset,
field, field,
dispatchReceiverValue?.load(), dispatchReceiverValue?.load(),
origin, origin,
superQualifier superQualifier
) )
} }
override fun store(irExpression: IrExpression) = override fun store(irExpression: IrExpression) =
callReceiver.call { dispatchReceiverValue, extensionReceiverValue -> callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
assert(extensionReceiverValue == null) { "Field can't have an extension receiver: ${field.descriptor}" } assert(extensionReceiverValue == null) { "Field can't have an extension receiver: ${field.descriptor}" }
IrSetFieldImpl( IrSetFieldImpl(
startOffset, endOffset, startOffset, endOffset,
field, field,
dispatchReceiverValue?.load(), dispatchReceiverValue?.load(),
irExpression, irExpression,
origin, origin,
superQualifier superQualifier
) )
} }
override fun withReceiver(dispatchReceiver: VariableLValue?, extensionReceiver: VariableLValue?): PropertyLValueBase = override fun withReceiver(dispatchReceiver: VariableLValue?, extensionReceiver: VariableLValue?): PropertyLValueBase =
FieldPropertyLValue( FieldPropertyLValue(
scope, startOffset, endOffset, origin, scope, startOffset, endOffset, origin,
field, field,
SimpleCallReceiver(dispatchReceiver, extensionReceiver), SimpleCallReceiver(dispatchReceiver, extensionReceiver),
superQualifier superQualifier
) )
} }
class AccessorPropertyLValue( class AccessorPropertyLValue(
scope: Scope, scope: Scope,
startOffset: Int, startOffset: Int,
endOffset: Int, endOffset: Int,
origin: IrStatementOrigin?, origin: IrStatementOrigin?,
type: KotlinType, type: KotlinType,
val getter: IrFunctionSymbol?, val getter: IrFunctionSymbol?,
val getterDescriptor: FunctionDescriptor?, val getterDescriptor: FunctionDescriptor?,
val setter: IrFunctionSymbol?, val setter: IrFunctionSymbol?,
val setterDescriptor: FunctionDescriptor?, val setterDescriptor: FunctionDescriptor?,
val typeArguments: Map<TypeParameterDescriptor, KotlinType>?, val typeArguments: Map<TypeParameterDescriptor, KotlinType>?,
callReceiver: CallReceiver, callReceiver: CallReceiver,
superQualifier: IrClassSymbol? superQualifier: IrClassSymbol?
) : PropertyLValueBase(scope, startOffset, endOffset, origin, type, callReceiver, superQualifier) { ) : PropertyLValueBase(scope, startOffset, endOffset, origin, type, callReceiver, superQualifier) {
override fun load(): IrExpression = override fun load(): IrExpression =
callReceiver.call { dispatchReceiverValue, extensionReceiverValue -> callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
IrGetterCallImpl( IrGetterCallImpl(
startOffset, endOffset, startOffset, endOffset,
getter!!, getterDescriptor!!, getter!!, getterDescriptor!!,
typeArguments, typeArguments,
dispatchReceiverValue?.load(), dispatchReceiverValue?.load(),
extensionReceiverValue?.load(), extensionReceiverValue?.load(),
origin, origin,
superQualifier superQualifier
) )
} }
override fun store(irExpression: IrExpression) = override fun store(irExpression: IrExpression) =
callReceiver.call { dispatchReceiverValue, extensionReceiverValue -> callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
IrSetterCallImpl( IrSetterCallImpl(
startOffset, endOffset, startOffset, endOffset,
setter!!, setterDescriptor!!, setter!!, setterDescriptor!!,
typeArguments, typeArguments,
dispatchReceiverValue?.load(), dispatchReceiverValue?.load(),
extensionReceiverValue?.load(), extensionReceiverValue?.load(),
irExpression, irExpression,
origin, origin,
superQualifier superQualifier
) )
} }
override fun withReceiver(dispatchReceiver: VariableLValue?, extensionReceiver: VariableLValue?): PropertyLValueBase = override fun withReceiver(dispatchReceiver: VariableLValue?, extensionReceiver: VariableLValue?): PropertyLValueBase =
AccessorPropertyLValue( AccessorPropertyLValue(
scope, startOffset, endOffset, origin, scope, startOffset, endOffset, origin,
type, getter, getterDescriptor, setter, setterDescriptor, type, getter, getterDescriptor, setter, setterDescriptor,
typeArguments, typeArguments,
SimpleCallReceiver(dispatchReceiver, extensionReceiver), SimpleCallReceiver(dispatchReceiver, extensionReceiver),
superQualifier superQualifier
) )
} }
@@ -28,7 +28,11 @@ class RematerializableValue(val irExpression: IrExpressionWithCopy) : Intermedia
override fun load(): IrExpression = irExpression.copy() override fun load(): IrExpression = irExpression.copy()
} }
fun Scope.createTemporaryVariableInBlock(irExpression: IrExpression, block: IrContainerExpressionBase, nameHint: String? = null): IntermediateValue { fun Scope.createTemporaryVariableInBlock(
irExpression: IrExpression,
block: IrContainerExpressionBase,
nameHint: String? = null
): IntermediateValue {
val temporaryVariable = createTemporaryVariable(irExpression, nameHint) val temporaryVariable = createTemporaryVariable(irExpression, nameHint)
block.statements.add(temporaryVariable) block.statements.add(temporaryVariable)
return VariableLValue(temporaryVariable) return VariableLValue(temporaryVariable)
@@ -28,12 +28,12 @@ import org.jetbrains.kotlin.types.typeUtil.makeNullable
class SafeCallReceiver( class SafeCallReceiver(
val generator: GeneratorWithScope, val generator: GeneratorWithScope,
val startOffset: Int, val startOffset: Int,
val endOffset: Int, val endOffset: Int,
val extensionReceiver: IntermediateValue?, val extensionReceiver: IntermediateValue?,
val dispatchReceiver: IntermediateValue?, val dispatchReceiver: IntermediateValue?,
val isAssignmentReceiver: Boolean val isAssignmentReceiver: Boolean
) : CallReceiver { ) : CallReceiver {
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression { override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression {
val irTmp = generator.scope.createTemporaryVariable(extensionReceiver?.load() ?: dispatchReceiver!!.load(), "safe_receiver") val irTmp = generator.scope.createTemporaryVariable(extensionReceiver?.load() ?: dispatchReceiver!!.load(), "safe_receiver")
@@ -44,8 +44,7 @@ class SafeCallReceiver(
if (extensionReceiver != null) { if (extensionReceiver != null) {
dispatchReceiverValue = dispatchReceiver dispatchReceiverValue = dispatchReceiver
extensionReceiverValue = safeReceiverValue extensionReceiverValue = safeReceiverValue
} } else {
else {
dispatchReceiverValue = safeReceiverValue dispatchReceiverValue = safeReceiverValue
extensionReceiverValue = null extensionReceiverValue = null
} }
@@ -57,11 +56,13 @@ class SafeCallReceiver(
irBlock.statements.add(irTmp) irBlock.statements.add(irTmp)
val irIfThenElse = IrIfThenElseImpl(startOffset, endOffset, resultType, val irIfThenElse = IrIfThenElseImpl(
generator.context.equalsNull(startOffset, endOffset, safeReceiverValue.load()), startOffset, endOffset, resultType,
generator.context.constNull(startOffset, endOffset), generator.context.equalsNull(startOffset, endOffset, safeReceiverValue.load()),
irResult, generator.context.constNull(startOffset, endOffset),
IrStatementOrigin.SAFE_CALL) irResult,
IrStatementOrigin.SAFE_CALL
)
irBlock.statements.add(irIfThenElse) irBlock.statements.add(irIfThenElse)
return irBlock return irBlock
@@ -26,12 +26,12 @@ import org.jetbrains.kotlin.psi2ir.generators.GeneratorWithScope
import org.jetbrains.kotlin.types.typeUtil.makeNullable import org.jetbrains.kotlin.types.typeUtil.makeNullable
class SafeExtensionInvokeCallReceiver( class SafeExtensionInvokeCallReceiver(
val generator: GeneratorWithScope, val generator: GeneratorWithScope,
val startOffset: Int, val startOffset: Int,
val endOffset: Int, val endOffset: Int,
val callBuilder: CallBuilder, val callBuilder: CallBuilder,
val functionReceiver: IntermediateValue, val functionReceiver: IntermediateValue,
val extensionInvokeReceiver: IntermediateValue val extensionInvokeReceiver: IntermediateValue
) : CallReceiver { ) : CallReceiver {
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression { override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression {
// extensionInvokeReceiver is actually a first argument: // extensionInvokeReceiver is actually a first argument:
@@ -54,17 +54,17 @@ class SafeExtensionInvokeCallReceiver(
val resultType = irResult.type.makeNullable() val resultType = irResult.type.makeNullable()
return IrBlockImpl( return IrBlockImpl(
startOffset, endOffset, resultType, IrStatementOrigin.SAFE_CALL, startOffset, endOffset, resultType, IrStatementOrigin.SAFE_CALL,
arrayListOf( arrayListOf(
irTmp, irTmp,
IrIfThenElseImpl( IrIfThenElseImpl(
startOffset, endOffset, resultType, startOffset, endOffset, resultType,
generator.context.equalsNull(startOffset, endOffset, safeReceiverValue.load()), generator.context.equalsNull(startOffset, endOffset, safeReceiverValue.load()),
generator.context.constNull(startOffset, endOffset), generator.context.constNull(startOffset, endOffset),
irResult, irResult,
IrStatementOrigin.SAFE_CALL IrStatementOrigin.SAFE_CALL
)
) )
)
) )
} }
} }
@@ -19,8 +19,8 @@ package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
class SimpleCallReceiver( class SimpleCallReceiver(
val dispatchReceiverValue: IntermediateValue?, val dispatchReceiverValue: IntermediateValue?,
val extensionReceiverValue: IntermediateValue? val extensionReceiverValue: IntermediateValue?
) : CallReceiver { ) : CallReceiver {
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression { override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression {
return withDispatchAndExtensionReceivers(dispatchReceiverValue, extensionReceiverValue) return withDispatchAndExtensionReceivers(dispatchReceiverValue, extensionReceiverValue)
@@ -19,7 +19,7 @@ package org.jetbrains.kotlin.psi2ir.intermediate
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
class TransientReceiverValue(override val type: KotlinType): IntermediateValue { class TransientReceiverValue(override val type: KotlinType) : IntermediateValue {
override fun load(): IrExpression { override fun load(): IrExpression {
throw AssertionError("Transient receiver should not be instantiated") throw AssertionError("Transient receiver should not be instantiated")
} }
@@ -27,26 +27,27 @@ import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.utils.addToStdlib.assertedCast import org.jetbrains.kotlin.utils.addToStdlib.assertedCast
class VariableLValue( class VariableLValue(
val startOffset: Int, val startOffset: Int,
val endOffset: Int, val endOffset: Int,
val symbol: IrValueSymbol, val symbol: IrValueSymbol,
val origin: IrStatementOrigin? = null val origin: IrStatementOrigin? = null
) : LValue, AssignmentReceiver { ) : LValue, AssignmentReceiver {
constructor(irVariable: IrVariable, origin: IrStatementOrigin? = null) : this( constructor(irVariable: IrVariable, origin: IrStatementOrigin? = null) : this(
irVariable.startOffset, irVariable.endOffset, irVariable.symbol, origin) irVariable.startOffset, irVariable.endOffset, irVariable.symbol, origin
)
override val type: KotlinType get() = symbol.descriptor.type override val type: KotlinType get() = symbol.descriptor.type
override fun load(): IrExpression = override fun load(): IrExpression =
IrGetValueImpl(startOffset, endOffset, symbol, origin) IrGetValueImpl(startOffset, endOffset, symbol, origin)
override fun store(irExpression: IrExpression): IrExpression = override fun store(irExpression: IrExpression): IrExpression =
IrSetVariableImpl( IrSetVariableImpl(
startOffset, endOffset, startOffset, endOffset,
symbol.assertedCast<IrVariableSymbol> { "Not a variable: ${symbol.descriptor}" }, symbol.assertedCast<IrVariableSymbol> { "Not a variable: ${symbol.descriptor}" },
irExpression, origin irExpression, origin
) )
override fun assign(withLValue: (LValue) -> IrExpression): IrExpression = override fun assign(withLValue: (LValue) -> IrExpression): IrExpression =
withLValue(this) withLValue(this)
} }
@@ -17,8 +17,6 @@
package org.jetbrains.kotlin.psi2ir.transformations package org.jetbrains.kotlin.psi2ir.transformations
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.isBuiltinExtensionFunctionalType
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrField import org.jetbrains.kotlin.ir.declarations.IrField
@@ -27,7 +25,6 @@ import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.psi2ir.containsNull import org.jetbrains.kotlin.psi2ir.containsNull
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
@@ -40,7 +37,7 @@ fun insertImplicitCasts(builtIns: KotlinBuiltIns, element: IrElement) {
element.transformChildren(InsertImplicitCasts(builtIns), null) element.transformChildren(InsertImplicitCasts(builtIns), null)
} }
class InsertImplicitCasts(val builtIns: KotlinBuiltIns): IrElementTransformerVoid() { class InsertImplicitCasts(val builtIns: KotlinBuiltIns) : IrElementTransformerVoid() {
override fun visitCallableReference(expression: IrCallableReference): IrExpression = override fun visitCallableReference(expression: IrCallableReference): IrExpression =
expression.transformPostfix { expression.transformPostfix {
transformReceiverArguments() transformReceiverArguments()
@@ -52,113 +49,113 @@ class InsertImplicitCasts(val builtIns: KotlinBuiltIns): IrElementTransformerVoi
} }
override fun visitMemberAccess(expression: IrMemberAccessExpression): IrExpression = override fun visitMemberAccess(expression: IrMemberAccessExpression): IrExpression =
expression.transformPostfix { expression.transformPostfix {
transformReceiverArguments() transformReceiverArguments()
for (index in descriptor.valueParameters.indices) { for (index in descriptor.valueParameters.indices) {
val argument = getValueArgument(index) ?: continue val argument = getValueArgument(index) ?: continue
val parameterType = descriptor.valueParameters[index].type val parameterType = descriptor.valueParameters[index].type
putValueArgument(index, argument.cast(parameterType)) putValueArgument(index, argument.cast(parameterType))
}
} }
}
override fun visitBlockBody(body: IrBlockBody): IrBody = override fun visitBlockBody(body: IrBlockBody): IrBody =
body.transformPostfix { body.transformPostfix {
statements.forEachIndexed { i, irStatement -> statements.forEachIndexed { i, irStatement ->
if (irStatement is IrExpression) { if (irStatement is IrExpression) {
body.statements[i] = irStatement.coerceToUnit() body.statements[i] = irStatement.coerceToUnit()
}
} }
} }
}
override fun visitContainerExpression(expression: IrContainerExpression): IrExpression = override fun visitContainerExpression(expression: IrContainerExpression): IrExpression =
expression.transformPostfix { expression.transformPostfix {
if (statements.isEmpty()) return this if (statements.isEmpty()) return this
val lastIndex = statements.lastIndex val lastIndex = statements.lastIndex
statements.forEachIndexed { i, irStatement -> statements.forEachIndexed { i, irStatement ->
if (irStatement is IrExpression) { if (irStatement is IrExpression) {
statements[i] = statements[i] =
if (i == lastIndex) if (i == lastIndex)
irStatement.cast(type) irStatement.cast(type)
else else
irStatement.coerceToUnit() irStatement.coerceToUnit()
}
} }
} }
}
override fun visitReturn(expression: IrReturn): IrExpression = override fun visitReturn(expression: IrReturn): IrExpression =
expression.transformPostfix { expression.transformPostfix {
value = value.cast(expression.returnTarget.returnType) value = value.cast(expression.returnTarget.returnType)
} }
override fun visitSetVariable(expression: IrSetVariable): IrExpression = override fun visitSetVariable(expression: IrSetVariable): IrExpression =
expression.transformPostfix { expression.transformPostfix {
value = value.cast(expression.descriptor.type) value = value.cast(expression.descriptor.type)
} }
override fun visitSetField(expression: IrSetField): IrExpression = override fun visitSetField(expression: IrSetField): IrExpression =
expression.transformPostfix { expression.transformPostfix {
value = value.cast(expression.descriptor.type) value = value.cast(expression.descriptor.type)
} }
override fun visitVariable(declaration: IrVariable): IrVariable = override fun visitVariable(declaration: IrVariable): IrVariable =
declaration.transformPostfix { declaration.transformPostfix {
initializer = initializer?.cast(declaration.descriptor.type) initializer = initializer?.cast(declaration.descriptor.type)
} }
override fun visitField(declaration: IrField): IrStatement = override fun visitField(declaration: IrField): IrStatement =
declaration.transformPostfix { declaration.transformPostfix {
initializer?.coerceInnerExpression(descriptor.type) initializer?.coerceInnerExpression(descriptor.type)
} }
override fun visitFunction(declaration: IrFunction): IrStatement = override fun visitFunction(declaration: IrFunction): IrStatement =
declaration.transformPostfix { declaration.transformPostfix {
valueParameters.forEach { valueParameters.forEach {
it.defaultValue?.coerceInnerExpression(it.descriptor.type) it.defaultValue?.coerceInnerExpression(it.descriptor.type)
}
} }
}
override fun visitWhen(expression: IrWhen): IrExpression = override fun visitWhen(expression: IrWhen): IrExpression =
expression.transformPostfix { expression.transformPostfix {
for (irBranch in branches) { for (irBranch in branches) {
irBranch.condition = irBranch.condition.cast(builtIns.booleanType) irBranch.condition = irBranch.condition.cast(builtIns.booleanType)
irBranch.result = irBranch.result.cast(type) irBranch.result = irBranch.result.cast(type)
}
} }
}
override fun visitLoop(loop: IrLoop): IrExpression = override fun visitLoop(loop: IrLoop): IrExpression =
loop.transformPostfix { loop.transformPostfix {
condition = condition.cast(builtIns.booleanType) condition = condition.cast(builtIns.booleanType)
body = body?.coerceToUnit() body = body?.coerceToUnit()
} }
override fun visitThrow(expression: IrThrow): IrExpression = override fun visitThrow(expression: IrThrow): IrExpression =
expression.transformPostfix { expression.transformPostfix {
value = value.cast(builtIns.throwable.defaultType) value = value.cast(builtIns.throwable.defaultType)
} }
override fun visitTry(aTry: IrTry): IrExpression = override fun visitTry(aTry: IrTry): IrExpression =
aTry.transformPostfix { aTry.transformPostfix {
tryResult = tryResult.cast(type) tryResult = tryResult.cast(type)
for (aCatch in catches) { for (aCatch in catches) {
aCatch.result = aCatch.result.cast(type) aCatch.result = aCatch.result.cast(type)
}
finallyExpression = finallyExpression?.coerceToUnit()
} }
finallyExpression = finallyExpression?.coerceToUnit()
}
override fun visitVararg(expression: IrVararg): IrExpression = override fun visitVararg(expression: IrVararg): IrExpression =
expression.transformPostfix { expression.transformPostfix {
elements.forEachIndexed { i, element -> elements.forEachIndexed { i, element ->
when (element) { when (element) {
is IrSpreadElement -> is IrSpreadElement ->
element.expression = element.expression.cast(expression.type) element.expression = element.expression.cast(expression.type)
is IrExpression -> is IrExpression ->
putElement(i, element.cast(varargElementType)) putElement(i, element.cast(varargElementType))
}
} }
} }
}
private fun IrExpressionBody.coerceInnerExpression(expectedType: KotlinType) { private fun IrExpressionBody.coerceInnerExpression(expectedType: KotlinType) {
expression = expression.cast(expectedType) expression = expression.cast(expectedType)
@@ -178,18 +175,22 @@ class InsertImplicitCasts(val builtIns: KotlinBuiltIns): IrElementTransformerVoi
valueType.isNullabilityFlexible() && valueType.containsNull() && !expectedType.containsNull() -> { valueType.isNullabilityFlexible() && valueType.containsNull() && !expectedType.containsNull() -> {
val nonNullValueType = valueType.upperIfFlexible().makeNotNullable() val nonNullValueType = valueType.upperIfFlexible().makeNotNullable()
IrTypeOperatorCallImpl( IrTypeOperatorCallImpl(
startOffset, endOffset, nonNullValueType, startOffset, endOffset, nonNullValueType,
IrTypeOperator.IMPLICIT_NOTNULL, nonNullValueType, this IrTypeOperator.IMPLICIT_NOTNULL, nonNullValueType, this
).cast(expectedType) ).cast(expectedType)
} }
KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType.makeNotNullable(), expectedType) -> KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType.makeNotNullable(), expectedType) ->
this this
KotlinBuiltIns.isInt(valueType) && notNullableExpectedType.isBuiltInIntegerType() -> KotlinBuiltIns.isInt(valueType) && notNullableExpectedType.isBuiltInIntegerType() ->
IrTypeOperatorCallImpl(startOffset, endOffset, notNullableExpectedType, IrTypeOperatorCallImpl(
IrTypeOperator.IMPLICIT_INTEGER_COERCION, notNullableExpectedType, this) startOffset, endOffset, notNullableExpectedType,
IrTypeOperator.IMPLICIT_INTEGER_COERCION, notNullableExpectedType, this
)
else -> else ->
IrTypeOperatorCallImpl(startOffset, endOffset, expectedType, IrTypeOperatorCallImpl(
IrTypeOperator.IMPLICIT_CAST, expectedType, this) startOffset, endOffset, expectedType,
IrTypeOperator.IMPLICIT_CAST, expectedType, this
)
} }
} }
@@ -199,14 +200,16 @@ class InsertImplicitCasts(val builtIns: KotlinBuiltIns): IrElementTransformerVoi
return if (KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType, builtIns.unitType)) return if (KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType, builtIns.unitType))
this this
else else
IrTypeOperatorCallImpl(startOffset, endOffset, builtIns.unitType, IrTypeOperatorCallImpl(
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, builtIns.unitType, this) startOffset, endOffset, builtIns.unitType,
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, builtIns.unitType, this
)
} }
private fun KotlinType.isBuiltInIntegerType(): Boolean = private fun KotlinType.isBuiltInIntegerType(): Boolean =
KotlinBuiltIns.isByte(this) || KotlinBuiltIns.isByte(this) ||
KotlinBuiltIns.isShort(this) || KotlinBuiltIns.isShort(this) ||
KotlinBuiltIns.isInt(this) || KotlinBuiltIns.isInt(this) ||
KotlinBuiltIns.isLong(this) KotlinBuiltIns.isLong(this)
} }