[PSI2IR] Generate IR for functions and calls with context receivers
This commit is contained in:
committed by
TeamCityServer
parent
f4ddf66ac4
commit
307f318c9e
+28
@@ -16107,6 +16107,34 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
public void testWhenFail() throws Exception {
|
public void testWhenFail() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/extensionFunctions/contextReceivers")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class ContextReceivers {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInContextReceivers() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/extensionFunctions/contextReceivers"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("dp.kt")
|
||||||
|
public void testDp() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/dp.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("plusMatrix.kt")
|
||||||
|
public void testPlusMatrix() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/plusMatrix.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("simpleCall.kt")
|
||||||
|
public void testSimpleCall() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/simpleCall.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
+22
-6
@@ -66,8 +66,13 @@ fun StatementGenerator.generateReceiver(ktDefaultElement: KtElement, receiver: R
|
|||||||
fun StatementGenerator.generateReceiver(defaultStartOffset: Int, defaultEndOffset: Int, receiver: ReceiverValue): IntermediateValue {
|
fun StatementGenerator.generateReceiver(defaultStartOffset: Int, defaultEndOffset: Int, receiver: ReceiverValue): IntermediateValue {
|
||||||
val irReceiverType =
|
val irReceiverType =
|
||||||
when (receiver) {
|
when (receiver) {
|
||||||
is ExtensionReceiver ->
|
is ExtensionReceiver -> {
|
||||||
receiver.declarationDescriptor.extensionReceiverParameter!!.type.toIrType()
|
val receiverParameters =
|
||||||
|
receiver.declarationDescriptor.contextReceiverParameters + listOfNotNull(receiver.declarationDescriptor.extensionReceiverParameter)
|
||||||
|
val receiverParameter = receiverParameters.firstOrNull { it.value == receiver }
|
||||||
|
?: receiver.declarationDescriptor.extensionReceiverParameter!!
|
||||||
|
receiverParameter.type.toIrType()
|
||||||
|
}
|
||||||
else ->
|
else ->
|
||||||
receiver.type.toIrType()
|
receiver.type.toIrType()
|
||||||
}
|
}
|
||||||
@@ -93,11 +98,16 @@ fun StatementGenerator.generateReceiver(defaultStartOffset: Int, defaultEndOffse
|
|||||||
generateThisOrSuperReceiver(receiver, receiver.thisType.constructor.declarationDescriptor as ClassDescriptor)
|
generateThisOrSuperReceiver(receiver, receiver.thisType.constructor.declarationDescriptor as ClassDescriptor)
|
||||||
is ExpressionReceiver ->
|
is ExpressionReceiver ->
|
||||||
generateExpression(receiver.expression)
|
generateExpression(receiver.expression)
|
||||||
is ExtensionReceiver ->
|
is ExtensionReceiver -> {
|
||||||
|
val receiverParameters = listOfNotNull(receiver.declarationDescriptor.extensionReceiverParameter) +
|
||||||
|
receiver.declarationDescriptor.contextReceiverParameters
|
||||||
|
val receiverParameter = receiverParameters.singleOrNull { it.value == receiver }
|
||||||
|
?: receiver.declarationDescriptor.extensionReceiverParameter!!
|
||||||
IrGetValueImpl(
|
IrGetValueImpl(
|
||||||
defaultStartOffset, defaultStartOffset, irReceiverType,
|
defaultStartOffset, defaultStartOffset, irReceiverType,
|
||||||
context.symbolTable.referenceValueParameter(receiver.declarationDescriptor.extensionReceiverParameter!!)
|
context.symbolTable.referenceValueParameter(receiverParameter)
|
||||||
)
|
)
|
||||||
|
}
|
||||||
else ->
|
else ->
|
||||||
throw AssertionError("Unexpected receiver: ${receiver::class.java.simpleName}")
|
throw AssertionError("Unexpected receiver: ${receiver::class.java.simpleName}")
|
||||||
}
|
}
|
||||||
@@ -170,11 +180,13 @@ fun StatementGenerator.generateCallReceiver(
|
|||||||
calleeDescriptor: CallableDescriptor,
|
calleeDescriptor: CallableDescriptor,
|
||||||
dispatchReceiver: ReceiverValue?,
|
dispatchReceiver: ReceiverValue?,
|
||||||
extensionReceiver: ReceiverValue?,
|
extensionReceiver: ReceiverValue?,
|
||||||
|
contextReceivers: List<ReceiverValue>,
|
||||||
isSafe: Boolean,
|
isSafe: Boolean,
|
||||||
isAssignmentReceiver: Boolean = false
|
isAssignmentReceiver: Boolean = false
|
||||||
): CallReceiver {
|
): CallReceiver {
|
||||||
val dispatchReceiverValue: IntermediateValue?
|
val dispatchReceiverValue: IntermediateValue?
|
||||||
val extensionReceiverValue: IntermediateValue?
|
val extensionReceiverValue: IntermediateValue?
|
||||||
|
val contextReceiverValues: List<IntermediateValue>
|
||||||
val startOffset = ktDefaultElement.startOffsetSkippingComments
|
val startOffset = ktDefaultElement.startOffsetSkippingComments
|
||||||
val endOffset = ktDefaultElement.endOffset
|
val endOffset = ktDefaultElement.endOffset
|
||||||
when (calleeDescriptor) {
|
when (calleeDescriptor) {
|
||||||
@@ -184,6 +196,7 @@ fun StatementGenerator.generateCallReceiver(
|
|||||||
}
|
}
|
||||||
dispatchReceiverValue = generateReceiverForCalleeImportedFromObject(startOffset, endOffset, calleeDescriptor)
|
dispatchReceiverValue = generateReceiverForCalleeImportedFromObject(startOffset, endOffset, calleeDescriptor)
|
||||||
extensionReceiverValue = generateReceiverOrNull(ktDefaultElement, extensionReceiver)
|
extensionReceiverValue = generateReceiverOrNull(ktDefaultElement, extensionReceiver)
|
||||||
|
contextReceiverValues = contextReceivers.mapNotNull { generateReceiverOrNull(ktDefaultElement, it) }
|
||||||
}
|
}
|
||||||
is TypeAliasConstructorDescriptor -> {
|
is TypeAliasConstructorDescriptor -> {
|
||||||
assert(!(dispatchReceiver != null && extensionReceiver != null)) {
|
assert(!(dispatchReceiver != null && extensionReceiver != null)) {
|
||||||
@@ -192,20 +205,22 @@ fun StatementGenerator.generateCallReceiver(
|
|||||||
}
|
}
|
||||||
dispatchReceiverValue = generateReceiverOrNull(ktDefaultElement, extensionReceiver ?: dispatchReceiver)
|
dispatchReceiverValue = generateReceiverOrNull(ktDefaultElement, extensionReceiver ?: dispatchReceiver)
|
||||||
extensionReceiverValue = null
|
extensionReceiverValue = null
|
||||||
|
contextReceiverValues = emptyList()
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
dispatchReceiverValue = generateReceiverOrNull(ktDefaultElement, dispatchReceiver)
|
dispatchReceiverValue = generateReceiverOrNull(ktDefaultElement, dispatchReceiver)
|
||||||
extensionReceiverValue = generateReceiverOrNull(ktDefaultElement, extensionReceiver)
|
extensionReceiverValue = generateReceiverOrNull(ktDefaultElement, extensionReceiver)
|
||||||
|
contextReceiverValues = contextReceivers.mapNotNull { generateReceiverOrNull(ktDefaultElement, it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
!isSafe ->
|
!isSafe ->
|
||||||
SimpleCallReceiver(dispatchReceiverValue, extensionReceiverValue)
|
SimpleCallReceiver(dispatchReceiverValue, extensionReceiverValue, contextReceiverValues)
|
||||||
extensionReceiverValue != null || dispatchReceiverValue != null ->
|
extensionReceiverValue != null || dispatchReceiverValue != null ->
|
||||||
SafeCallReceiver(
|
SafeCallReceiver(
|
||||||
this, startOffset, endOffset,
|
this, startOffset, endOffset,
|
||||||
extensionReceiverValue, dispatchReceiverValue, isAssignmentReceiver
|
extensionReceiverValue, contextReceiverValues, dispatchReceiverValue, isAssignmentReceiver
|
||||||
)
|
)
|
||||||
else ->
|
else ->
|
||||||
throw AssertionError("Safe call should have an explicit receiver: ${ktDefaultElement.text}")
|
throw AssertionError("Safe call should have an explicit receiver: ${ktDefaultElement.text}")
|
||||||
@@ -697,6 +712,7 @@ fun StatementGenerator.pregenerateCallReceivers(resolvedCall: ResolvedCall<*>):
|
|||||||
resolvedCall.resultingDescriptor,
|
resolvedCall.resultingDescriptor,
|
||||||
resolvedCall.dispatchReceiver,
|
resolvedCall.dispatchReceiver,
|
||||||
resolvedCall.extensionReceiver,
|
resolvedCall.extensionReceiver,
|
||||||
|
resolvedCall.contextReceivers,
|
||||||
isSafe = resolvedCall.call.isSafeCall()
|
isSafe = resolvedCall.call.isSafeCall()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+6
-2
@@ -273,7 +273,9 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
|
|||||||
descriptor.type.toIrType(),
|
descriptor.type.toIrType(),
|
||||||
descriptor.name.asString(),
|
descriptor.name.asString(),
|
||||||
statementGenerator.generateCallReceiver(
|
statementGenerator.generateCallReceiver(
|
||||||
ktLeft, descriptor, resolvedCall.dispatchReceiver, resolvedCall.extensionReceiver,
|
ktLeft, descriptor, resolvedCall.dispatchReceiver,
|
||||||
|
resolvedCall.extensionReceiver,
|
||||||
|
resolvedCall.contextReceivers,
|
||||||
isSafe = resolvedCall.call.isSafeCall(),
|
isSafe = resolvedCall.call.isSafeCall(),
|
||||||
isAssignmentReceiver = isAssignmentStatement
|
isAssignmentReceiver = isAssignmentStatement
|
||||||
)
|
)
|
||||||
@@ -285,7 +287,9 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
|
|||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val propertyReceiver = statementGenerator.generateCallReceiver(
|
val propertyReceiver = statementGenerator.generateCallReceiver(
|
||||||
ktLeft, descriptor, resolvedCall.dispatchReceiver, resolvedCall.extensionReceiver,
|
ktLeft, descriptor, resolvedCall.dispatchReceiver,
|
||||||
|
resolvedCall.extensionReceiver,
|
||||||
|
resolvedCall.contextReceivers,
|
||||||
isSafe = resolvedCall.call.isSafeCall(),
|
isSafe = resolvedCall.call.isSafeCall(),
|
||||||
isAssignmentReceiver = isAssignmentStatement
|
isAssignmentReceiver = isAssignmentStatement
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
|||||||
is FunctionDescriptor ->
|
is FunctionDescriptor ->
|
||||||
generateFunctionCall(descriptor, startOffset, endOffset, origin, call)
|
generateFunctionCall(descriptor, startOffset, endOffset, origin, call)
|
||||||
else ->
|
else ->
|
||||||
call.callReceiver.call { _, _ ->
|
call.callReceiver.call { _, _, _ ->
|
||||||
generateValueReference(startOffset, endOffset, descriptor, call.original, origin)
|
generateValueReference(startOffset, endOffset, descriptor, call.original, origin)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,7 +155,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun generateDelegatingConstructorCall(startOffset: Int, endOffset: Int, call: CallBuilder): IrExpression =
|
fun generateDelegatingConstructorCall(startOffset: Int, endOffset: Int, call: CallBuilder): IrExpression =
|
||||||
call.callReceiver.call { dispatchReceiver, extensionReceiver ->
|
call.callReceiver.call { dispatchReceiver, extensionReceiver, contextReceivers ->
|
||||||
val descriptor = call.descriptor as? ClassConstructorDescriptor
|
val descriptor = call.descriptor as? ClassConstructorDescriptor
|
||||||
?: throw AssertionError("Class constructor expected: ${call.descriptor}")
|
?: throw AssertionError("Class constructor expected: ${call.descriptor}")
|
||||||
val constructorSymbol = context.symbolTable.referenceConstructor(descriptor.original)
|
val constructorSymbol = context.symbolTable.referenceConstructor(descriptor.original)
|
||||||
@@ -169,7 +169,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
|||||||
this.dispatchReceiver = dispatchReceiver?.load()
|
this.dispatchReceiver = dispatchReceiver?.load()
|
||||||
this.extensionReceiver = extensionReceiver?.load()
|
this.extensionReceiver = extensionReceiver?.load()
|
||||||
}
|
}
|
||||||
addParametersToCall(startOffset, endOffset, call, irCall, context.irBuiltIns.unitType)
|
addParametersToCall(startOffset, endOffset, call, irCall, context.irBuiltIns.unitType, contextReceivers.map { it.load() })
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generateEnumConstructorSuperCall(startOffset: Int, endOffset: Int, call: CallBuilder): IrExpression {
|
fun generateEnumConstructorSuperCall(startOffset: Int, endOffset: Int, call: CallBuilder): IrExpression {
|
||||||
@@ -178,9 +178,10 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
|||||||
val classDescriptor = constructorDescriptor.containingDeclaration
|
val classDescriptor = constructorDescriptor.containingDeclaration
|
||||||
if (classDescriptor.kind != ClassKind.ENUM_CLASS) throw AssertionError("Enum class constructor expected: $classDescriptor")
|
if (classDescriptor.kind != ClassKind.ENUM_CLASS) throw AssertionError("Enum class constructor expected: $classDescriptor")
|
||||||
|
|
||||||
return call.callReceiver.call { dispatchReceiver, extensionReceiver ->
|
return call.callReceiver.call { dispatchReceiver, extensionReceiver, contextReceivers ->
|
||||||
if (dispatchReceiver != null) throw AssertionError("Dispatch receiver should be null: $dispatchReceiver")
|
if (dispatchReceiver != null) throw AssertionError("Dispatch receiver should be null: $dispatchReceiver")
|
||||||
if (extensionReceiver != null) throw AssertionError("Extension receiver should be null: $extensionReceiver")
|
if (extensionReceiver != null) throw AssertionError("Extension receiver should be null: $extensionReceiver")
|
||||||
|
if (contextReceivers.isNotEmpty()) throw AssertionError("Context receivers should be empty: $contextReceivers")
|
||||||
val descriptor = constructorDescriptor.original
|
val descriptor = constructorDescriptor.original
|
||||||
val constructorSymbol = context.symbolTable.referenceConstructor(descriptor)
|
val constructorSymbol = context.symbolTable.referenceConstructor(descriptor)
|
||||||
val returnType = constructorDescriptor.returnType.toIrType()
|
val returnType = constructorDescriptor.returnType.toIrType()
|
||||||
@@ -188,7 +189,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
|||||||
startOffset, endOffset, returnType, constructorSymbol, descriptor.typeParametersCount, descriptor.valueParameters.size
|
startOffset, endOffset, returnType, constructorSymbol, descriptor.typeParametersCount, descriptor.valueParameters.size
|
||||||
)
|
)
|
||||||
context.callToSubstitutedDescriptorMap[irCall] = constructorDescriptor
|
context.callToSubstitutedDescriptorMap[irCall] = constructorDescriptor
|
||||||
addParametersToCall(startOffset, endOffset, call, irCall, irCall.type)
|
addParametersToCall(startOffset, endOffset, call, irCall, irCall.type, emptyList())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,7 +209,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
|||||||
}
|
}
|
||||||
val fieldSymbol =
|
val fieldSymbol =
|
||||||
context.symbolTable.referenceField(context.extensions.remapDebuggerFieldPropertyDescriptor(descriptor.resolveFakeOverride().original))
|
context.symbolTable.referenceField(context.extensions.remapDebuggerFieldPropertyDescriptor(descriptor.resolveFakeOverride().original))
|
||||||
call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue, _ ->
|
||||||
IrGetFieldImpl(
|
IrGetFieldImpl(
|
||||||
startOffset, endOffset,
|
startOffset, endOffset,
|
||||||
fieldSymbol,
|
fieldSymbol,
|
||||||
@@ -220,36 +221,40 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val superQualifierSymbol = call.superQualifier?.let { context.symbolTable.referenceClass(it) }
|
val superQualifierSymbol = call.superQualifier?.let { context.symbolTable.referenceClass(it) }
|
||||||
call.callReceiver.adjustForCallee(getMethodDescriptor).call { dispatchReceiverValue, extensionReceiverValue ->
|
call.callReceiver.adjustForCallee(getMethodDescriptor)
|
||||||
if (descriptor.isDynamic()) {
|
.call { dispatchReceiverValue, extensionReceiverValue, contextReceiverValues ->
|
||||||
val dispatchReceiver = getDynamicExpressionReceiver(dispatchReceiverValue, extensionReceiverValue, descriptor)
|
if (descriptor.isDynamic()) {
|
||||||
|
val dispatchReceiver = getDynamicExpressionReceiver(dispatchReceiverValue, extensionReceiverValue, descriptor)
|
||||||
|
|
||||||
IrDynamicMemberExpressionImpl(
|
IrDynamicMemberExpressionImpl(
|
||||||
startOffset, endOffset,
|
startOffset, endOffset,
|
||||||
irType,
|
irType,
|
||||||
descriptor.name.asString(),
|
descriptor.name.asString(),
|
||||||
dispatchReceiver
|
dispatchReceiver
|
||||||
)
|
|
||||||
} else {
|
|
||||||
val getterSymbol = context.symbolTable.referenceSimpleFunction(getMethodDescriptor.original)
|
|
||||||
IrCallImpl(
|
|
||||||
startOffset, endOffset,
|
|
||||||
irType,
|
|
||||||
getterSymbol,
|
|
||||||
descriptor.typeParametersCount,
|
|
||||||
0,
|
|
||||||
IrStatementOrigin.GET_PROPERTY,
|
|
||||||
superQualifierSymbol
|
|
||||||
).apply {
|
|
||||||
context.callToSubstitutedDescriptorMap[this] = computeSubstitutedSyntheticAccessor(
|
|
||||||
descriptor, getMethodDescriptor, descriptor.getter!!
|
|
||||||
)
|
)
|
||||||
putTypeArguments(call.typeArguments) { it.toIrType() }
|
} else {
|
||||||
dispatchReceiver = dispatchReceiverValue?.load()
|
val getterSymbol = context.symbolTable.referenceSimpleFunction(getMethodDescriptor.original)
|
||||||
extensionReceiver = extensionReceiverValue?.load()
|
IrCallImpl(
|
||||||
|
startOffset, endOffset,
|
||||||
|
irType,
|
||||||
|
getterSymbol,
|
||||||
|
descriptor.typeParametersCount,
|
||||||
|
descriptor.contextReceiverParameters.size,
|
||||||
|
IrStatementOrigin.GET_PROPERTY,
|
||||||
|
superQualifierSymbol
|
||||||
|
).apply {
|
||||||
|
context.callToSubstitutedDescriptorMap[this] = computeSubstitutedSyntheticAccessor(
|
||||||
|
descriptor, getMethodDescriptor, descriptor.getter!!
|
||||||
|
)
|
||||||
|
|
||||||
|
putTypeArguments(call.typeArguments) { it.toIrType() }
|
||||||
|
dispatchReceiver = dispatchReceiverValue?.load()
|
||||||
|
extensionReceiver = extensionReceiverValue?.load()
|
||||||
|
val contextReceivers = contextReceiverValues.map { it.load() }
|
||||||
|
addParametersToCall(startOffset, endOffset, call, this, irType, contextReceivers)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -280,7 +285,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
|||||||
origin: IrStatementOrigin?,
|
origin: IrStatementOrigin?,
|
||||||
call: CallBuilder
|
call: CallBuilder
|
||||||
): IrExpression =
|
): IrExpression =
|
||||||
call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue, contextReceiverValues ->
|
||||||
val irType = constructorDescriptor.returnType.toIrType()
|
val irType = constructorDescriptor.returnType.toIrType()
|
||||||
val originalSymbol = context.symbolTable.referenceConstructor(constructorDescriptor.original)
|
val originalSymbol = context.symbolTable.referenceConstructor(constructorDescriptor.original)
|
||||||
|
|
||||||
@@ -294,7 +299,8 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
|||||||
putTypeArguments(call.typeArguments) { it.toIrType() }
|
putTypeArguments(call.typeArguments) { it.toIrType() }
|
||||||
dispatchReceiver = dispatchReceiverValue?.load()
|
dispatchReceiver = dispatchReceiverValue?.load()
|
||||||
extensionReceiver = extensionReceiverValue?.load()
|
extensionReceiver = extensionReceiverValue?.load()
|
||||||
addParametersToCall(startOffset, endOffset, call, this, irType)
|
val contextReceivers = contextReceiverValues.map { it.load() }
|
||||||
|
addParametersToCall(startOffset, endOffset, call, this, irType, contextReceivers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,7 +311,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
|||||||
origin: IrStatementOrigin?,
|
origin: IrStatementOrigin?,
|
||||||
call: CallBuilder
|
call: CallBuilder
|
||||||
): IrExpression =
|
): IrExpression =
|
||||||
call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue, contextReceiverValues ->
|
||||||
val irType = functionDescriptor.returnType!!.toIrType()
|
val irType = functionDescriptor.returnType!!.toIrType()
|
||||||
|
|
||||||
if (functionDescriptor.isDynamic()) {
|
if (functionDescriptor.isDynamic()) {
|
||||||
@@ -369,7 +375,8 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
|||||||
putTypeArguments(call.typeArguments) { it.toIrType() }
|
putTypeArguments(call.typeArguments) { it.toIrType() }
|
||||||
dispatchReceiver = dispatchReceiverValue?.load()
|
dispatchReceiver = dispatchReceiverValue?.load()
|
||||||
extensionReceiver = extensionReceiverValue?.load()
|
extensionReceiver = extensionReceiverValue?.load()
|
||||||
addParametersToCall(startOffset, endOffset, call, this, irType)
|
val contextReceivers = contextReceiverValues.map { it.load() }
|
||||||
|
addParametersToCall(startOffset, endOffset, call, this, irType, contextReceivers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -379,14 +386,18 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
|||||||
endOffset: Int,
|
endOffset: Int,
|
||||||
call: CallBuilder,
|
call: CallBuilder,
|
||||||
irCall: IrFunctionAccessExpression,
|
irCall: IrFunctionAccessExpression,
|
||||||
irResultType: IrType
|
irResultType: IrType,
|
||||||
|
contextReceivers: List<IrExpression>
|
||||||
): IrExpression =
|
): IrExpression =
|
||||||
if (call.isValueArgumentReorderingRequired()) {
|
if (call.isValueArgumentReorderingRequired()) {
|
||||||
generateCallWithArgumentReordering(irCall, startOffset, endOffset, call, irResultType)
|
generateCallWithArgumentReordering(irCall, startOffset, endOffset, call, irResultType)
|
||||||
} else {
|
} else {
|
||||||
|
for ((index, valueArgument) in contextReceivers.withIndex()) {
|
||||||
|
irCall.putValueArgument(index, valueArgument)
|
||||||
|
}
|
||||||
val valueArguments = call.getValueArgumentsInParameterOrder()
|
val valueArguments = call.getValueArgumentsInParameterOrder()
|
||||||
for ((index, valueArgument) in valueArguments.withIndex()) {
|
for ((index, valueArgument) in valueArguments.withIndex()) {
|
||||||
irCall.putValueArgument(index, valueArgument)
|
irCall.putValueArgument(index + contextReceivers.size, valueArgument)
|
||||||
}
|
}
|
||||||
irCall
|
irCall
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -103,7 +103,7 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
|
|||||||
IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR,
|
IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR,
|
||||||
accessorDescriptor
|
accessorDescriptor
|
||||||
).buildWithScope { irAccessor ->
|
).buildWithScope { irAccessor ->
|
||||||
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarationsAndReturnType(irAccessor, ktProperty, null)
|
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarationsAndReturnType(irAccessor, ktProperty, null, emptyList())
|
||||||
irAccessor.body = generateBody(irAccessor)
|
irAccessor.body = generateBody(irAccessor)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -363,7 +363,7 @@ class DelegatedPropertyGenerator(declarationGenerator: DeclarationGenerator) : D
|
|||||||
IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR,
|
IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR,
|
||||||
getterDescriptor
|
getterDescriptor
|
||||||
).buildWithScope { irAccessor ->
|
).buildWithScope { irAccessor ->
|
||||||
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarationsAndReturnType(irAccessor, ktDelegate, null)
|
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarationsAndReturnType(irAccessor, ktDelegate, null, emptyList())
|
||||||
irAccessor.body = generateBody(irAccessor)
|
irAccessor.body = generateBody(irAccessor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -44,7 +44,7 @@ class EnumClassMembersGenerator(declarationGenerator: DeclarationGenerator) : De
|
|||||||
IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER,
|
IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER,
|
||||||
valuesFunction
|
valuesFunction
|
||||||
).also { irFunction ->
|
).also { irFunction ->
|
||||||
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarationsAndReturnType(irFunction, null, null)
|
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarationsAndReturnType(irFunction, null, null, emptyList())
|
||||||
irFunction.body = IrSyntheticBodyImpl(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrSyntheticBodyKind.ENUM_VALUES)
|
irFunction.body = IrSyntheticBodyImpl(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrSyntheticBodyKind.ENUM_VALUES)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -63,7 +63,7 @@ class EnumClassMembersGenerator(declarationGenerator: DeclarationGenerator) : De
|
|||||||
IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER,
|
IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER,
|
||||||
valueOfFunction
|
valueOfFunction
|
||||||
).also { irFunction ->
|
).also { irFunction ->
|
||||||
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarationsAndReturnType(irFunction, null, null)
|
FunctionGenerator(declarationGenerator).generateFunctionParameterDeclarationsAndReturnType(irFunction, null, null, emptyList())
|
||||||
irFunction.body = IrSyntheticBodyImpl(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrSyntheticBodyKind.ENUM_VALUEOF)
|
irFunction.body = IrSyntheticBodyImpl(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrSyntheticBodyKind.ENUM_VALUEOF)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
+28
-12
@@ -50,6 +50,7 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
|||||||
declareSimpleFunction(
|
declareSimpleFunction(
|
||||||
ktFunction,
|
ktFunction,
|
||||||
ktFunction.receiverTypeReference,
|
ktFunction.receiverTypeReference,
|
||||||
|
ktFunction.contextReceiverTypeReferences,
|
||||||
origin,
|
origin,
|
||||||
getOrFail(BindingContext.FUNCTION, ktFunction)
|
getOrFail(BindingContext.FUNCTION, ktFunction)
|
||||||
) {
|
) {
|
||||||
@@ -60,6 +61,7 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
|||||||
declareSimpleFunction(
|
declareSimpleFunction(
|
||||||
ktFunction,
|
ktFunction,
|
||||||
null,
|
null,
|
||||||
|
emptyList(),
|
||||||
IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA,
|
IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA,
|
||||||
getOrFail(BindingContext.FUNCTION, ktFunction)
|
getOrFail(BindingContext.FUNCTION, ktFunction)
|
||||||
) {
|
) {
|
||||||
@@ -71,19 +73,20 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
|||||||
?.let {
|
?.let {
|
||||||
declareSimpleFunctionInner(it, ktElement, IrDeclarationOrigin.FAKE_OVERRIDE)
|
declareSimpleFunctionInner(it, ktElement, IrDeclarationOrigin.FAKE_OVERRIDE)
|
||||||
.buildWithScope { irFunction ->
|
.buildWithScope { irFunction ->
|
||||||
generateFunctionParameterDeclarationsAndReturnType(irFunction, ktElement, null)
|
generateFunctionParameterDeclarationsAndReturnType(irFunction, ktElement, null, emptyList())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun declareSimpleFunction(
|
private inline fun declareSimpleFunction(
|
||||||
ktFunction: KtFunction,
|
ktFunction: KtFunction,
|
||||||
ktReceiver: KtElement?,
|
ktReceiver: KtElement?,
|
||||||
|
ktContextReceivers: List<KtElement>,
|
||||||
origin: IrDeclarationOrigin,
|
origin: IrDeclarationOrigin,
|
||||||
descriptor: FunctionDescriptor,
|
descriptor: FunctionDescriptor,
|
||||||
generateBody: BodyGenerator.() -> IrBody?
|
generateBody: BodyGenerator.() -> IrBody?
|
||||||
): IrSimpleFunction =
|
): IrSimpleFunction =
|
||||||
declareSimpleFunctionInner(descriptor, ktFunction, origin).buildWithScope { irFunction ->
|
declareSimpleFunctionInner(descriptor, ktFunction, origin).buildWithScope { irFunction ->
|
||||||
generateFunctionParameterDeclarationsAndReturnType(irFunction, ktFunction, ktReceiver)
|
generateFunctionParameterDeclarationsAndReturnType(irFunction, ktFunction, ktReceiver, ktContextReceivers)
|
||||||
irFunction.body = createBodyGenerator(irFunction.symbol).generateBody()
|
irFunction.body = createBodyGenerator(irFunction.symbol).generateBody()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,11 +105,12 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
|||||||
fun generateFunctionParameterDeclarationsAndReturnType(
|
fun generateFunctionParameterDeclarationsAndReturnType(
|
||||||
irFunction: IrFunction,
|
irFunction: IrFunction,
|
||||||
ktParameterOwner: KtPureElement?,
|
ktParameterOwner: KtPureElement?,
|
||||||
ktReceiverParameterElement: KtElement?
|
ktReceiverParameterElement: KtElement?,
|
||||||
|
ktContextReceiverParametersElements: List<KtElement>
|
||||||
) {
|
) {
|
||||||
declarationGenerator.generateScopedTypeParameterDeclarations(irFunction, irFunction.descriptor.propertyIfAccessor.typeParameters)
|
declarationGenerator.generateScopedTypeParameterDeclarations(irFunction, irFunction.descriptor.propertyIfAccessor.typeParameters)
|
||||||
irFunction.returnType = irFunction.descriptor.returnType!!.toIrType()
|
irFunction.returnType = irFunction.descriptor.returnType!!.toIrType()
|
||||||
generateValueParameterDeclarations(irFunction, ktParameterOwner, ktReceiverParameterElement)
|
generateValueParameterDeclarations(irFunction, ktParameterOwner, ktReceiverParameterElement, ktContextReceiverParametersElements)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generatePropertyAccessor(
|
fun generatePropertyAccessor(
|
||||||
@@ -121,7 +125,10 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
|||||||
).buildWithScope { irAccessor ->
|
).buildWithScope { irAccessor ->
|
||||||
declarationGenerator.generateScopedTypeParameterDeclarations(irAccessor, descriptor.correspondingProperty.typeParameters)
|
declarationGenerator.generateScopedTypeParameterDeclarations(irAccessor, descriptor.correspondingProperty.typeParameters)
|
||||||
irAccessor.returnType = irAccessor.descriptor.returnType!!.toIrType()
|
irAccessor.returnType = irAccessor.descriptor.returnType!!.toIrType()
|
||||||
generateValueParameterDeclarations(irAccessor, ktAccessor ?: ktProperty, ktProperty.receiverTypeReference)
|
generateValueParameterDeclarations(
|
||||||
|
irAccessor, ktAccessor ?: ktProperty, ktProperty.receiverTypeReference,
|
||||||
|
ktProperty.contextReceiverTypeReferences
|
||||||
|
)
|
||||||
val ktBodyExpression = ktAccessor?.bodyExpression
|
val ktBodyExpression = ktAccessor?.bodyExpression
|
||||||
irAccessor.body =
|
irAccessor.body =
|
||||||
if (ktBodyExpression != null)
|
if (ktBodyExpression != null)
|
||||||
@@ -272,7 +279,7 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
|||||||
metadata = DescriptorMetadataSource.Function(it.descriptor)
|
metadata = DescriptorMetadataSource.Function(it.descriptor)
|
||||||
}
|
}
|
||||||
}.buildWithScope { irConstructor ->
|
}.buildWithScope { irConstructor ->
|
||||||
generateValueParameterDeclarations(irConstructor, ktParametersElement, null)
|
generateValueParameterDeclarations(irConstructor, ktParametersElement, null, emptyList())
|
||||||
irConstructor.body = createBodyGenerator(irConstructor.symbol).generateBody()
|
irConstructor.body = createBodyGenerator(irConstructor.symbol).generateBody()
|
||||||
irConstructor.returnType = constructorDescriptor.returnType.toIrType()
|
irConstructor.returnType = constructorDescriptor.returnType.toIrType()
|
||||||
}
|
}
|
||||||
@@ -286,13 +293,14 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
|||||||
else
|
else
|
||||||
descriptor.typeParameters
|
descriptor.typeParameters
|
||||||
declarationGenerator.generateScopedTypeParameterDeclarations(irFunction, typeParameters)
|
declarationGenerator.generateScopedTypeParameterDeclarations(irFunction, typeParameters)
|
||||||
generateValueParameterDeclarations(irFunction, null, null, withDefaultValues = false)
|
generateValueParameterDeclarations(irFunction, null, null, emptyList(), withDefaultValues = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateValueParameterDeclarations(
|
private fun generateValueParameterDeclarations(
|
||||||
irFunction: IrFunction,
|
irFunction: IrFunction,
|
||||||
ktParameterOwner: KtPureElement?,
|
ktParameterOwner: KtPureElement?,
|
||||||
ktReceiverParameterElement: KtPureElement?,
|
ktReceiverParameterElement: KtPureElement?,
|
||||||
|
ktContextReceiverParameterElements: List<KtPureElement>,
|
||||||
withDefaultValues: Boolean = true
|
withDefaultValues: Boolean = true
|
||||||
) {
|
) {
|
||||||
val functionDescriptor = irFunction.descriptor
|
val functionDescriptor = irFunction.descriptor
|
||||||
@@ -307,10 +315,16 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
|||||||
|
|
||||||
val bodyGenerator = createBodyGenerator(irFunction.symbol)
|
val bodyGenerator = createBodyGenerator(irFunction.symbol)
|
||||||
|
|
||||||
|
val contextReceiversNumber = ktContextReceiverParameterElements.size
|
||||||
|
assert(functionDescriptor.contextReceiverParameters.size == contextReceiversNumber)
|
||||||
|
irFunction.valueParameters += functionDescriptor.contextReceiverParameters.mapIndexed { i, additionalReceiver ->
|
||||||
|
declareParameter(additionalReceiver, ktContextReceiverParameterElements[i], irFunction, null, i)
|
||||||
|
}
|
||||||
|
|
||||||
// Declare all the value parameters up first.
|
// Declare all the value parameters up first.
|
||||||
irFunction.valueParameters += functionDescriptor.valueParameters.map { valueParameterDescriptor ->
|
irFunction.valueParameters += functionDescriptor.valueParameters.mapIndexed { i, valueParameterDescriptor ->
|
||||||
val ktParameter = DescriptorToSourceUtils.getSourceFromDescriptor(valueParameterDescriptor) as? KtParameter
|
val ktParameter = DescriptorToSourceUtils.getSourceFromDescriptor(valueParameterDescriptor) as? KtParameter
|
||||||
declareParameter(valueParameterDescriptor, ktParameter, irFunction)
|
declareParameter(valueParameterDescriptor, ktParameter, irFunction, null, i + contextReceiversNumber)
|
||||||
}
|
}
|
||||||
// Only after value parameters have been declared, generate default values. This ensures
|
// Only after value parameters have been declared, generate default values. This ensures
|
||||||
// that forward references to other parameters works in default value lambdas. For example:
|
// that forward references to other parameters works in default value lambdas. For example:
|
||||||
@@ -318,7 +332,7 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
|||||||
// fun f(f1: () -> String = { f2() },
|
// fun f(f1: () -> String = { f2() },
|
||||||
// f2: () -> String) = f1()
|
// f2: () -> String) = f1()
|
||||||
if (withDefaultValues) {
|
if (withDefaultValues) {
|
||||||
irFunction.valueParameters.forEachIndexed { index, irValueParameter ->
|
irFunction.valueParameters.drop(contextReceiversNumber).forEachIndexed { index, irValueParameter ->
|
||||||
val valueParameterDescriptor = functionDescriptor.valueParameters[index]
|
val valueParameterDescriptor = functionDescriptor.valueParameters[index]
|
||||||
val ktParameter = DescriptorToSourceUtils.getSourceFromDescriptor(valueParameterDescriptor) as? KtParameter
|
val ktParameter = DescriptorToSourceUtils.getSourceFromDescriptor(valueParameterDescriptor) as? KtParameter
|
||||||
irValueParameter.defaultValue = ktParameter?.defaultValue?.let { defaultValue ->
|
irValueParameter.defaultValue = ktParameter?.defaultValue?.let { defaultValue ->
|
||||||
@@ -376,7 +390,8 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
|||||||
descriptor: ParameterDescriptor,
|
descriptor: ParameterDescriptor,
|
||||||
ktElement: KtPureElement?,
|
ktElement: KtPureElement?,
|
||||||
irOwnerElement: IrElement,
|
irOwnerElement: IrElement,
|
||||||
name: Name? = null
|
name: Name? = null,
|
||||||
|
index: Int? = null
|
||||||
): IrValueParameter {
|
): IrValueParameter {
|
||||||
var origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
|
var origin: IrDeclarationOrigin = IrDeclarationOrigin.DEFINED
|
||||||
if (ktElement is KtParameter) {
|
if (ktElement is KtParameter) {
|
||||||
@@ -392,7 +407,8 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
|||||||
origin,
|
origin,
|
||||||
descriptor, descriptor.type.toIrType(),
|
descriptor, descriptor.type.toIrType(),
|
||||||
(descriptor as? ValueParameterDescriptor)?.varargElementType?.toIrType(),
|
(descriptor as? ValueParameterDescriptor)?.varargElementType?.toIrType(),
|
||||||
name
|
name,
|
||||||
|
index
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-6
@@ -80,10 +80,11 @@ class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : St
|
|||||||
|
|
||||||
return statementGenerator.generateCallReceiver(
|
return statementGenerator.generateCallReceiver(
|
||||||
ktCallableReference,
|
ktCallableReference,
|
||||||
resolvedDescriptor,
|
resolvedDescriptor, resolvedCall.dispatchReceiver,
|
||||||
resolvedCall.dispatchReceiver, resolvedCall.extensionReceiver,
|
resolvedCall.extensionReceiver,
|
||||||
|
resolvedCall.contextReceivers,
|
||||||
isSafe = false
|
isSafe = false
|
||||||
).call { dispatchReceiverValue, extensionReceiverValue ->
|
).call { dispatchReceiverValue, extensionReceiverValue, _ ->
|
||||||
generateCallableReference(
|
generateCallableReference(
|
||||||
ktCallableReference,
|
ktCallableReference,
|
||||||
callableReferenceType,
|
callableReferenceType,
|
||||||
@@ -150,10 +151,11 @@ class ReflectionReferencesGenerator(statementGenerator: StatementGenerator) : St
|
|||||||
val resolvedCall = callBuilder.original
|
val resolvedCall = callBuilder.original
|
||||||
return statementGenerator.generateCallReceiver(
|
return statementGenerator.generateCallReceiver(
|
||||||
ktCallableReference,
|
ktCallableReference,
|
||||||
resolvedCall.resultingDescriptor,
|
resolvedCall.resultingDescriptor, resolvedCall.dispatchReceiver,
|
||||||
resolvedCall.dispatchReceiver, resolvedCall.extensionReceiver,
|
resolvedCall.extensionReceiver,
|
||||||
|
resolvedCall.contextReceivers,
|
||||||
isSafe = false
|
isSafe = false
|
||||||
).call { dispatchReceiverValue, extensionReceiverValue ->
|
).call { dispatchReceiverValue, extensionReceiverValue, _ ->
|
||||||
val irDispatchReceiver = dispatchReceiverValue?.loadIfExists()
|
val irDispatchReceiver = dispatchReceiverValue?.loadIfExists()
|
||||||
val irExtensionReceiver = extensionReceiverValue?.loadIfExists()
|
val irExtensionReceiver = extensionReceiverValue?.loadIfExists()
|
||||||
check(irDispatchReceiver == null || irExtensionReceiver == null) {
|
check(irDispatchReceiver == null || irExtensionReceiver == null) {
|
||||||
|
|||||||
@@ -84,11 +84,11 @@ val CallBuilder.explicitReceiverType: KotlinType?
|
|||||||
fun CallBuilder.setExplicitReceiverValue(explicitReceiverValue: IntermediateValue) {
|
fun CallBuilder.setExplicitReceiverValue(explicitReceiverValue: IntermediateValue) {
|
||||||
val previousCallReceiver = callReceiver
|
val previousCallReceiver = callReceiver
|
||||||
callReceiver = object : CallReceiver {
|
callReceiver = object : CallReceiver {
|
||||||
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression {
|
override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List<IntermediateValue>) -> IrExpression): IrExpression {
|
||||||
return previousCallReceiver.call { dispatchReceiverValue, _ ->
|
return previousCallReceiver.call { dispatchReceiverValue, _, contextReceiverValues ->
|
||||||
val newDispatchReceiverValue = if (hasExtensionReceiver) dispatchReceiverValue else explicitReceiverValue
|
val newDispatchReceiverValue = if (hasExtensionReceiver) dispatchReceiverValue else explicitReceiverValue
|
||||||
val newExtensionReceiverValue = if (hasExtensionReceiver) explicitReceiverValue else null
|
val newExtensionReceiverValue = if (hasExtensionReceiver) explicitReceiverValue else null
|
||||||
withDispatchAndExtensionReceivers(newDispatchReceiverValue, newExtensionReceiverValue)
|
withDispatchAndExtensionAndContextReceivers(newDispatchReceiverValue, newExtensionReceiverValue, contextReceiverValues)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-4
@@ -24,7 +24,7 @@ class DynamicMemberLValue(
|
|||||||
) : LValue, AssignmentReceiver {
|
) : LValue, AssignmentReceiver {
|
||||||
|
|
||||||
override fun load(): IrExpression =
|
override fun load(): IrExpression =
|
||||||
receiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
receiver.call { dispatchReceiverValue, extensionReceiverValue, _ ->
|
||||||
val dynamicReceiver = getDynamicReceiver(dispatchReceiverValue, extensionReceiverValue)
|
val dynamicReceiver = getDynamicReceiver(dispatchReceiverValue, extensionReceiverValue)
|
||||||
|
|
||||||
IrDynamicMemberExpressionImpl(
|
IrDynamicMemberExpressionImpl(
|
||||||
@@ -36,7 +36,7 @@ class DynamicMemberLValue(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun store(irExpression: IrExpression): IrExpression =
|
override fun store(irExpression: IrExpression): IrExpression =
|
||||||
receiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
receiver.call { dispatchReceiverValue, extensionReceiverValue, _ ->
|
||||||
val dynamicReceiver = getDynamicReceiver(dispatchReceiverValue, extensionReceiverValue)
|
val dynamicReceiver = getDynamicReceiver(dispatchReceiverValue, extensionReceiverValue)
|
||||||
|
|
||||||
IrDynamicOperatorExpressionImpl(
|
IrDynamicOperatorExpressionImpl(
|
||||||
@@ -55,11 +55,11 @@ class DynamicMemberLValue(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun assign(withLValue: (LValue) -> IrExpression): IrExpression =
|
override fun assign(withLValue: (LValue) -> IrExpression): IrExpression =
|
||||||
receiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
receiver.call { dispatchReceiverValue, extensionReceiverValue, contextReceiverValues ->
|
||||||
withLValue(
|
withLValue(
|
||||||
DynamicMemberLValue(
|
DynamicMemberLValue(
|
||||||
context, startOffset, endOffset, type, memberName,
|
context, startOffset, endOffset, type, memberName,
|
||||||
SimpleCallReceiver(dispatchReceiverValue, extensionReceiverValue)
|
SimpleCallReceiver(dispatchReceiverValue, extensionReceiverValue, contextReceiverValues)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -24,7 +24,7 @@ class ExtensionInvokeCallReceiver(
|
|||||||
private val extensionInvokeReceiver: IntermediateValue
|
private val extensionInvokeReceiver: IntermediateValue
|
||||||
) : CallReceiver {
|
) : CallReceiver {
|
||||||
|
|
||||||
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression {
|
override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List<IntermediateValue>) -> IrExpression): IrExpression {
|
||||||
// extensionInvokeReceiver is actually a first argument:
|
// extensionInvokeReceiver is actually a first argument:
|
||||||
// receiver.extFun(p1, ..., pN)
|
// receiver.extFun(p1, ..., pN)
|
||||||
// =>
|
// =>
|
||||||
@@ -34,6 +34,6 @@ class ExtensionInvokeCallReceiver(
|
|||||||
"Extension 'invoke' call should have null as its 1st value argument, got: ${callBuilder.irValueArgumentsByIndex[0]}"
|
"Extension 'invoke' call should have null as its 1st value argument, got: ${callBuilder.irValueArgumentsByIndex[0]}"
|
||||||
}
|
}
|
||||||
callBuilder.irValueArgumentsByIndex[0] = extensionInvokeReceiver.load()
|
callBuilder.irValueArgumentsByIndex[0] = extensionInvokeReceiver.load()
|
||||||
return withDispatchAndExtensionReceivers(functionReceiver, null)
|
return withDispatchAndExtensionAndContextReceivers(functionReceiver, null, emptyList())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -27,8 +27,8 @@ fun IrVariable.loadAt(startOffset: Int, endOffset: Int): IrExpression =
|
|||||||
|
|
||||||
fun CallReceiver.adjustForCallee(callee: CallableMemberDescriptor): CallReceiver =
|
fun CallReceiver.adjustForCallee(callee: CallableMemberDescriptor): CallReceiver =
|
||||||
object : CallReceiver {
|
object : CallReceiver {
|
||||||
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression =
|
override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List<IntermediateValue>) -> IrExpression): IrExpression =
|
||||||
this@adjustForCallee.call { dispatchReceiverValue, extensionReceiverValue ->
|
this@adjustForCallee.call { dispatchReceiverValue, extensionReceiverValue, contextReceiverValues ->
|
||||||
val numReceiversPresent = listOfNotNull(dispatchReceiverValue, extensionReceiverValue).size
|
val numReceiversPresent = listOfNotNull(dispatchReceiverValue, extensionReceiverValue).size
|
||||||
val numReceiversExpected = listOfNotNull(callee.dispatchReceiverParameter, callee.extensionReceiverParameter).size
|
val numReceiversExpected = listOfNotNull(callee.dispatchReceiverParameter, callee.extensionReceiverParameter).size
|
||||||
if (numReceiversPresent != numReceiversExpected)
|
if (numReceiversPresent != numReceiversExpected)
|
||||||
@@ -46,7 +46,8 @@ fun CallReceiver.adjustForCallee(callee: CallableMemberDescriptor): CallReceiver
|
|||||||
dispatchReceiverValue != null && callee.dispatchReceiverParameter == null -> dispatchReceiverValue
|
dispatchReceiverValue != null && callee.dispatchReceiverParameter == null -> dispatchReceiverValue
|
||||||
else -> extensionReceiverValue
|
else -> extensionReceiverValue
|
||||||
}
|
}
|
||||||
withDispatchAndExtensionReceivers(newDispatchReceiverValue, newExtensionReceiverValue)
|
// TODO: Create new context receiver values
|
||||||
|
withDispatchAndExtensionAndContextReceivers(newDispatchReceiverValue, newExtensionReceiverValue, contextReceiverValues)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-7
@@ -40,7 +40,7 @@ abstract class PropertyLValueBase(
|
|||||||
val superQualifier: IrClassSymbol?
|
val superQualifier: IrClassSymbol?
|
||||||
) : LValue, AssignmentReceiver {
|
) : LValue, AssignmentReceiver {
|
||||||
override fun assign(withLValue: (LValue) -> IrExpression) =
|
override fun assign(withLValue: (LValue) -> IrExpression) =
|
||||||
callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
callReceiver.call { dispatchReceiverValue, extensionReceiverValue, _ ->
|
||||||
val dispatchReceiverVariable2 = dispatchReceiverValue?.let {
|
val dispatchReceiverVariable2 = dispatchReceiverValue?.let {
|
||||||
scope.createTemporaryVariable(dispatchReceiverValue.load(), "this")
|
scope.createTemporaryVariable(dispatchReceiverValue.load(), "this")
|
||||||
}
|
}
|
||||||
@@ -81,7 +81,8 @@ class FieldPropertyLValue(
|
|||||||
PropertyLValueBase(context, scope, startOffset, endOffset, origin, type, callReceiver, superQualifier) {
|
PropertyLValueBase(context, scope, startOffset, endOffset, origin, type, callReceiver, superQualifier) {
|
||||||
|
|
||||||
override fun load(): IrExpression =
|
override fun load(): IrExpression =
|
||||||
callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
// TODO: Use context receiver values
|
||||||
|
callReceiver.call { dispatchReceiverValue, extensionReceiverValue, _ ->
|
||||||
assert(extensionReceiverValue == null) { "Field can't have an extension receiver: ${field.descriptor}" }
|
assert(extensionReceiverValue == null) { "Field can't have an extension receiver: ${field.descriptor}" }
|
||||||
IrGetFieldImpl(
|
IrGetFieldImpl(
|
||||||
startOffset, endOffset,
|
startOffset, endOffset,
|
||||||
@@ -94,7 +95,8 @@ class FieldPropertyLValue(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun store(irExpression: IrExpression) =
|
override fun store(irExpression: IrExpression) =
|
||||||
callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
// TODO: Use context receiver values
|
||||||
|
callReceiver.call { dispatchReceiverValue, extensionReceiverValue, _ ->
|
||||||
assert(extensionReceiverValue == null) { "Field can't have an extension receiver: ${field.descriptor}" }
|
assert(extensionReceiverValue == null) { "Field can't have an extension receiver: ${field.descriptor}" }
|
||||||
IrSetFieldImpl(
|
IrSetFieldImpl(
|
||||||
startOffset, endOffset,
|
startOffset, endOffset,
|
||||||
@@ -114,7 +116,7 @@ class FieldPropertyLValue(
|
|||||||
field,
|
field,
|
||||||
descriptor,
|
descriptor,
|
||||||
type,
|
type,
|
||||||
SimpleCallReceiver(dispatchReceiver, extensionReceiver),
|
SimpleCallReceiver(dispatchReceiver, extensionReceiver, emptyList()),
|
||||||
superQualifier
|
superQualifier
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -144,7 +146,8 @@ class AccessorPropertyLValue(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun load(): IrExpression =
|
override fun load(): IrExpression =
|
||||||
callReceiver.adjustForCallee(getterDescriptor!!).call { dispatchReceiverValue, extensionReceiverValue ->
|
// TODO: Use context receiver values
|
||||||
|
callReceiver.adjustForCallee(getterDescriptor!!).call { dispatchReceiverValue, extensionReceiverValue, _ ->
|
||||||
IrCallImpl(
|
IrCallImpl(
|
||||||
startOffset, endOffset,
|
startOffset, endOffset,
|
||||||
type,
|
type,
|
||||||
@@ -161,7 +164,8 @@ class AccessorPropertyLValue(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun store(irExpression: IrExpression) =
|
override fun store(irExpression: IrExpression) =
|
||||||
callReceiver.adjustForCallee(setterDescriptor!!).call { dispatchReceiverValue, extensionReceiverValue ->
|
// TODO: Use context receiver values
|
||||||
|
callReceiver.adjustForCallee(setterDescriptor!!).call { dispatchReceiverValue, extensionReceiverValue, _ ->
|
||||||
IrCallImpl(
|
IrCallImpl(
|
||||||
startOffset, endOffset,
|
startOffset, endOffset,
|
||||||
context.irBuiltIns.unitType,
|
context.irBuiltIns.unitType,
|
||||||
@@ -184,7 +188,7 @@ class AccessorPropertyLValue(
|
|||||||
startOffset, endOffset, origin,
|
startOffset, endOffset, origin,
|
||||||
type, getter, getterDescriptor, setter, setterDescriptor,
|
type, getter, getterDescriptor, setter, setterDescriptor,
|
||||||
typeArguments,
|
typeArguments,
|
||||||
SimpleCallReceiver(dispatchReceiver, extensionReceiver),
|
SimpleCallReceiver(dispatchReceiver, extensionReceiver, emptyList()),
|
||||||
superQualifier
|
superQualifier
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
+6
-3
@@ -31,11 +31,13 @@ class SafeCallReceiver(
|
|||||||
val startOffset: Int,
|
val startOffset: Int,
|
||||||
val endOffset: Int,
|
val endOffset: Int,
|
||||||
val extensionReceiver: IntermediateValue?,
|
val extensionReceiver: IntermediateValue?,
|
||||||
|
// TODO: Use context receivers
|
||||||
|
val contextReceivers: List<IntermediateValue>,
|
||||||
val dispatchReceiver: IntermediateValue?,
|
val dispatchReceiver: IntermediateValue?,
|
||||||
val isStatement: Boolean
|
val isStatement: Boolean
|
||||||
) : CallReceiver {
|
) : CallReceiver {
|
||||||
|
|
||||||
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression {
|
override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List<IntermediateValue>) -> IrExpression): IrExpression {
|
||||||
val irTmp = generator.scope.createTemporaryVariable(extensionReceiver?.load() ?: dispatchReceiver!!.load(), "safe_receiver")
|
val irTmp = generator.scope.createTemporaryVariable(extensionReceiver?.load() ?: dispatchReceiver!!.load(), "safe_receiver")
|
||||||
val safeReceiverValue = VariableLValue(generator.context, irTmp)
|
val safeReceiverValue = VariableLValue(generator.context, irTmp)
|
||||||
|
|
||||||
@@ -49,7 +51,7 @@ class SafeCallReceiver(
|
|||||||
extensionReceiverValue = null
|
extensionReceiverValue = null
|
||||||
}
|
}
|
||||||
|
|
||||||
val irResult = withDispatchAndExtensionReceivers(dispatchReceiverValue, extensionReceiverValue)
|
val irResult = withDispatchAndExtensionAndContextReceivers(dispatchReceiverValue, extensionReceiverValue, emptyList())
|
||||||
|
|
||||||
val resultType = if (isStatement) generator.context.irBuiltIns.unitType else irResult.type.makeNullable()
|
val resultType = if (isStatement) generator.context.irBuiltIns.unitType else irResult.type.makeNullable()
|
||||||
|
|
||||||
@@ -77,8 +79,9 @@ fun IrExpression.safeCallOnDispatchReceiver(
|
|||||||
SafeCallReceiver(
|
SafeCallReceiver(
|
||||||
generator, startOffset, endOffset,
|
generator, startOffset, endOffset,
|
||||||
extensionReceiver = null,
|
extensionReceiver = null,
|
||||||
|
contextReceivers = emptyList(),
|
||||||
dispatchReceiver = OnceExpressionValue(this),
|
dispatchReceiver = OnceExpressionValue(this),
|
||||||
isStatement = false
|
isStatement = false
|
||||||
).call { dispatchReceiverValue, _ ->
|
).call { dispatchReceiverValue, _, _ ->
|
||||||
ifNotNull(dispatchReceiverValue!!.load())
|
ifNotNull(dispatchReceiverValue!!.load())
|
||||||
}
|
}
|
||||||
+2
-2
@@ -33,7 +33,7 @@ class SafeExtensionInvokeCallReceiver(
|
|||||||
val extensionInvokeReceiver: IntermediateValue
|
val extensionInvokeReceiver: IntermediateValue
|
||||||
) : CallReceiver {
|
) : CallReceiver {
|
||||||
|
|
||||||
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression {
|
override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List<IntermediateValue>) -> IrExpression): IrExpression {
|
||||||
// extensionInvokeReceiver is actually a first argument:
|
// extensionInvokeReceiver is actually a first argument:
|
||||||
// receiver?.extFun(p1, ..., pN)
|
// receiver?.extFun(p1, ..., pN)
|
||||||
// =>
|
// =>
|
||||||
@@ -49,7 +49,7 @@ class SafeExtensionInvokeCallReceiver(
|
|||||||
"Safe extension 'invoke' call should have null as its 1st value argument, got: ${callBuilder.irValueArgumentsByIndex[0]}"
|
"Safe extension 'invoke' call should have null as its 1st value argument, got: ${callBuilder.irValueArgumentsByIndex[0]}"
|
||||||
}
|
}
|
||||||
callBuilder.irValueArgumentsByIndex[0] = safeReceiverValue.load()
|
callBuilder.irValueArgumentsByIndex[0] = safeReceiverValue.load()
|
||||||
val irResult = withDispatchAndExtensionReceivers(functionReceiver, null)
|
val irResult = withDispatchAndExtensionAndContextReceivers(functionReceiver, null, emptyList())
|
||||||
|
|
||||||
val resultType = irResult.type.makeNullable()
|
val resultType = irResult.type.makeNullable()
|
||||||
|
|
||||||
|
|||||||
+4
-3
@@ -20,10 +20,11 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
|
|||||||
|
|
||||||
class SimpleCallReceiver(
|
class SimpleCallReceiver(
|
||||||
private val dispatchReceiverValue: IntermediateValue?,
|
private val dispatchReceiverValue: IntermediateValue?,
|
||||||
private val extensionReceiverValue: IntermediateValue?
|
private val extensionReceiverValue: IntermediateValue?,
|
||||||
|
private val contextReceiverValues: List<IntermediateValue>
|
||||||
) : CallReceiver {
|
) : CallReceiver {
|
||||||
|
|
||||||
override fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression {
|
override fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List<IntermediateValue>) -> IrExpression): IrExpression {
|
||||||
return withDispatchAndExtensionReceivers(dispatchReceiverValue, extensionReceiverValue)
|
return withDispatchAndExtensionAndContextReceivers(dispatchReceiverValue, extensionReceiverValue, contextReceiverValues)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,5 +36,5 @@ interface AssignmentReceiver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface CallReceiver {
|
interface CallReceiver {
|
||||||
fun call(withDispatchAndExtensionReceivers: (IntermediateValue?, IntermediateValue?) -> IrExpression): IrExpression
|
fun call(withDispatchAndExtensionAndContextReceivers: (IntermediateValue?, IntermediateValue?, List<IntermediateValue>) -> IrExpression): IrExpression
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ class IrCallImpl(
|
|||||||
type: IrType,
|
type: IrType,
|
||||||
symbol: IrSimpleFunctionSymbol,
|
symbol: IrSimpleFunctionSymbol,
|
||||||
typeArgumentsCount: Int = symbol.descriptor.typeParametersCount,
|
typeArgumentsCount: Int = symbol.descriptor.typeParametersCount,
|
||||||
valueArgumentsCount: Int = symbol.descriptor.valueParameters.size,
|
valueArgumentsCount: Int = symbol.descriptor.valueParameters.size + symbol.descriptor.contextReceiverParameters.size,
|
||||||
origin: IrStatementOrigin? = null,
|
origin: IrStatementOrigin? = null,
|
||||||
superQualifierSymbol: IrClassSymbol? = null,
|
superQualifierSymbol: IrClassSymbol? = null,
|
||||||
) =
|
) =
|
||||||
|
|||||||
@@ -933,11 +933,12 @@ open class SymbolTable(
|
|||||||
type: IrType,
|
type: IrType,
|
||||||
varargElementType: IrType? = null,
|
varargElementType: IrType? = null,
|
||||||
name: Name? = null,
|
name: Name? = null,
|
||||||
|
index: Int? = null,
|
||||||
isAssignable: Boolean = false,
|
isAssignable: Boolean = false,
|
||||||
valueParameterFactory: (IrValueParameterSymbol) -> IrValueParameter = {
|
valueParameterFactory: (IrValueParameterSymbol) -> IrValueParameter = {
|
||||||
irFactory.createValueParameter(
|
irFactory.createValueParameter(
|
||||||
startOffset, endOffset, origin, it, name ?: nameProvider.nameForDeclaration(descriptor),
|
startOffset, endOffset, origin, it, name ?: nameProvider.nameForDeclaration(descriptor),
|
||||||
descriptor.indexOrMinusOne, type, varargElementType, descriptor.isCrossinline, descriptor.isNoinline,
|
index ?: descriptor.indexOrMinusOne, type, varargElementType, descriptor.isCrossinline, descriptor.isNoinline,
|
||||||
isHidden = false, isAssignable = isAssignable
|
isHidden = false, isAssignable = isAssignable
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
class View {
|
||||||
|
val coefficient = 42
|
||||||
|
}
|
||||||
|
|
||||||
|
context(View) val Int.dp get() = coefficient * this
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
with(View()) {
|
||||||
|
if (listOf(1, 2, 10).map { it.dp } == listOf(42, 84, 420)) {
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
return "fail"
|
||||||
|
}
|
||||||
|
}
|
||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
interface NumberOperations {
|
||||||
|
operator fun Number.plus(other: Number): Number
|
||||||
|
}
|
||||||
|
|
||||||
|
object DoubleOperations : NumberOperations {
|
||||||
|
override operator fun Number.plus(other: Number) = this.toDouble() + other.toDouble()
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Matrix(val rows: Int, val columns: Int, val data: Array<out Number>) {
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as Matrix
|
||||||
|
|
||||||
|
if (rows != other.rows) return false
|
||||||
|
if (columns != other.columns) return false
|
||||||
|
if (!data.contentEquals(other.data)) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = rows
|
||||||
|
result = 31 * result + columns
|
||||||
|
result = 31 * result + data.contentHashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun matrixOf(rows: Int, columns: Int, vararg data: Number): Matrix {
|
||||||
|
assert(rows * columns == data.size) { "Wrong dimentions" }
|
||||||
|
return Matrix(rows, columns, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
context(NumberOperations) operator fun Matrix.plus(other: Matrix): Matrix {
|
||||||
|
assert(rows == other.rows && columns == other.columns) { "Matrices should have the same dimentions" }
|
||||||
|
return matrixOf(rows, columns, *data.mapIndexed { i, element -> element + other.data[i] }.toTypedArray())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val m1 = matrixOf(2, 2, 1, 2, 3, 4)
|
||||||
|
val m2 = matrixOf(2, 2, .4, .3, .2, .1)
|
||||||
|
with(DoubleOperations) {
|
||||||
|
return if (m1 + m2 == matrixOf(2, 2, 1.4, 2.3, 3.2, 4.1)) "OK" else "fail"
|
||||||
|
}
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
// TARGET_BACKEND: JVM_IR
|
||||||
|
// IGNORE_BACKEND_FIR: JVM_IR
|
||||||
|
|
||||||
|
class A {
|
||||||
|
val o = "O"
|
||||||
|
}
|
||||||
|
class B {
|
||||||
|
val k = "K"
|
||||||
|
}
|
||||||
|
|
||||||
|
context(B) fun A.f(a: Any, b: Any) = o + k
|
||||||
|
|
||||||
|
fun B.g(a: A): String {
|
||||||
|
with (a) {
|
||||||
|
return f(1, "2")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return B().g(A())
|
||||||
|
}
|
||||||
+10
@@ -16029,6 +16029,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
public void testWhenFail() throws Exception {
|
public void testWhenFail() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/extensionFunctions/contextReceivers")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class ContextReceivers {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInContextReceivers() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/extensionFunctions/contextReceivers"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
+28
@@ -16107,6 +16107,34 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
public void testWhenFail() throws Exception {
|
public void testWhenFail() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/extensionFunctions/contextReceivers")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class ContextReceivers {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInContextReceivers() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/extensionFunctions/contextReceivers"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("dp.kt")
|
||||||
|
public void testDp() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/dp.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("plusMatrix.kt")
|
||||||
|
public void testPlusMatrix() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/plusMatrix.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("simpleCall.kt")
|
||||||
|
public void testSimpleCall() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/extensionFunctions/contextReceivers/simpleCall.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
+13
@@ -13192,6 +13192,19 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
public void testWhenFail() throws Exception {
|
public void testWhenFail() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/extensionFunctions/contextReceivers")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class ContextReceivers extends AbstractLightAnalysisModeTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInContextReceivers() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/extensionFunctions/contextReceivers"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/extensionProperties")
|
@TestMetadata("compiler/testData/codegen/box/extensionProperties")
|
||||||
|
|||||||
Generated
+13
@@ -14778,6 +14778,19 @@ public class VisualizerBlackBoxTestGenerated extends AbstractVisualizerBlackBoxT
|
|||||||
public void testWhenFail() throws Exception {
|
public void testWhenFail() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/extensionFunctions/contextReceivers")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class ContextReceivers extends AbstractIrJsCodegenBoxES6Test {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInContextReceivers() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/extensionFunctions/contextReceivers"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
+13
@@ -12443,6 +12443,19 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
public void testWhenFail() throws Exception {
|
public void testWhenFail() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/extensionFunctions/contextReceivers")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class ContextReceivers extends AbstractJsCodegenBoxTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInContextReceivers() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/extensionFunctions/contextReceivers"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
+13
@@ -12485,6 +12485,19 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
public void testWhenFail() throws Exception {
|
public void testWhenFail() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/extensionFunctions/contextReceivers")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class ContextReceivers extends AbstractIrJsCodegenBoxTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInContextReceivers() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/extensionFunctions/contextReceivers"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
+13
@@ -10359,6 +10359,19 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
|
|||||||
public void testWhenFail() throws Exception {
|
public void testWhenFail() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
runTest("compiler/testData/codegen/box/extensionFunctions/whenFail.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/extensionFunctions/contextReceivers")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class ContextReceivers extends AbstractIrCodegenBoxWasmTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInContextReceivers() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/extensionFunctions/contextReceivers"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/extensionProperties")
|
@TestMetadata("compiler/testData/codegen/box/extensionProperties")
|
||||||
|
|||||||
Reference in New Issue
Block a user