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