KT-28456 generate index arguments per expression

In the desugaring for compound assignment to a collection element,
argument expression 'i' is mapped to value parameters 'iG' and 'iS' of
corresponding 'get' and 'set' operators.
In general, these value parameters can have different indices.

This requires extra machinery in argument generation - that is, to be
able to generate a particular expression argument using an arbitrary
callback. In the vast majority of the cases this callback will just use
the corresponding StatementGenerator to generate IR subtree for the
provided expression. In case of 'get' and 'set' operator calls for an
augmented assignment expression this will map corresponding argument
expressions to pregenerated temporary variables.

Thus, in the following context:
```
  class A

  operator fun A.get(vararg xs: Int) = 0
  operator fun A.set(i: Int, j: Int, v: Int) {}
```

statement `a[1, 2] += 3` will be desugared as (in a really pseudo
Kotlin):
```
  {
    val tmp_array = a
    val tmp_index0 = 1
    val tmp_index1 = 2
    tmp_array.set(
      i = tmp_index0,
      j = tmp_index1,
      v = tmp_array.get(xs = [tmp_index0, tmp_index1]).plus(3)
    )
  }
```
This commit is contained in:
Dmitry Petrov
2018-11-27 12:03:22 +03:00
parent 036b12f408
commit 42e253b5ff
10 changed files with 311 additions and 19 deletions
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrExpressionWithCopy import org.jetbrains.kotlin.ir.expressions.IrExpressionWithCopy
import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
import org.jetbrains.kotlin.psi2ir.intermediate.* import org.jetbrains.kotlin.psi2ir.intermediate.*
@@ -38,7 +39,6 @@ import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.resolve.scopes.receivers.* import org.jetbrains.kotlin.resolve.scopes.receivers.*
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.TypeSubstitutor
import java.lang.AssertionError
fun StatementGenerator.generateReceiverOrNull(ktDefaultElement: KtElement, receiver: ReceiverValue?): IntermediateValue? = fun StatementGenerator.generateReceiverOrNull(ktDefaultElement: KtElement, receiver: ReceiverValue?): IntermediateValue? =
receiver?.let { generateReceiver(ktDefaultElement, receiver) } receiver?.let { generateReceiver(ktDefaultElement, receiver) }
@@ -209,9 +209,10 @@ private fun StatementGenerator.generateReceiverForCalleeImportedFromObject(
} }
} }
fun StatementGenerator.generateVarargExpression( fun StatementGenerator.generateVarargExpressionUsing(
varargArgument: VarargValueArgument, varargArgument: VarargValueArgument,
valueParameter: ValueParameterDescriptor valueParameter: ValueParameterDescriptor,
generateArgumentExpression: (KtExpression) -> IrExpression?
): IrExpression? { ): IrExpression? {
if (varargArgument.arguments.isEmpty()) { if (varargArgument.arguments.isEmpty()) {
return null return null
@@ -232,14 +233,16 @@ fun StatementGenerator.generateVarargExpression(
for (argument in varargArgument.arguments) { for (argument in varargArgument.arguments) {
val ktArgumentExpression = argument.getArgumentExpression() val ktArgumentExpression = argument.getArgumentExpression()
?: throw AssertionError("No argument expression for vararg element ${argument.asElement().text}") ?: throw AssertionError("No argument expression for vararg element ${argument.asElement().text}")
val irArgumentExpression = generateArgumentExpression(ktArgumentExpression)
?: throw AssertionError("'generateArgumentExpression' should return non-null for vararg element ${ktArgumentExpression.text}")
val irVarargElement = val irVarargElement =
if (argument.getSpreadElement() != null) if (argument.getSpreadElement() != null)
IrSpreadElementImpl( IrSpreadElementImpl(
ktArgumentExpression.startOffsetSkippingComments, ktArgumentExpression.endOffset, ktArgumentExpression.startOffsetSkippingComments, ktArgumentExpression.endOffset,
generateExpression(ktArgumentExpression) irArgumentExpression
) )
else else
generateExpression(ktArgumentExpression) irArgumentExpression
irVararg.addElement(irVarargElement) irVararg.addElement(irVarargElement)
} }
@@ -247,17 +250,23 @@ fun StatementGenerator.generateVarargExpression(
return irVararg return irVararg
} }
fun StatementGenerator.generateValueArgument( private fun StatementGenerator.generateValueArgument(
valueArgument: ResolvedValueArgument, valueArgument: ResolvedValueArgument,
valueParameter: ValueParameterDescriptor valueParameter: ValueParameterDescriptor
) = generateValueArgumentUsing(valueArgument, valueParameter) { generateExpression(it) }
fun StatementGenerator.generateValueArgumentUsing(
valueArgument: ResolvedValueArgument,
valueParameter: ValueParameterDescriptor,
generateArgumentExpression: (KtExpression) -> IrExpression?
): IrExpression? = ): IrExpression? =
when (valueArgument) { when (valueArgument) {
is DefaultValueArgument -> is DefaultValueArgument ->
null null
is ExpressionValueArgument -> is ExpressionValueArgument ->
generateExpression(valueArgument.valueArgument!!.getArgumentExpression()!!) generateArgumentExpression(valueArgument.valueArgument!!.getArgumentExpression()!!)
is VarargValueArgument -> is VarargValueArgument ->
generateVarargExpression(valueArgument, valueParameter) generateVarargExpressionUsing(valueArgument, valueParameter, generateArgumentExpression)
else -> else ->
TODO("Unexpected valueArgument: ${valueArgument::class.java.simpleName}") TODO("Unexpected valueArgument: ${valueArgument::class.java.simpleName}")
} }
@@ -357,9 +366,19 @@ private fun ResolvedCall<*>.isExtensionInvokeCall(): Boolean {
} }
private fun StatementGenerator.pregenerateValueArguments(call: CallBuilder, resolvedCall: ResolvedCall<*>) { private fun StatementGenerator.pregenerateValueArguments(call: CallBuilder, resolvedCall: ResolvedCall<*>) {
pregenerateValueArgumentsUsing(call, resolvedCall) {
generateExpression(it)
}
}
fun StatementGenerator.pregenerateValueArgumentsUsing(
call: CallBuilder,
resolvedCall: ResolvedCall<*>,
generateArgumentExpression: (KtExpression) -> IrExpression?
) {
resolvedCall.valueArgumentsByIndex!!.forEachIndexed { index, valueArgument -> resolvedCall.valueArgumentsByIndex!!.forEachIndexed { index, valueArgument ->
val valueParameter = call.descriptor.valueParameters[index] val valueParameter = call.descriptor.valueParameters[index]
call.irValueArgumentsByIndex[index] = generateValueArgument(valueArgument, valueParameter) call.irValueArgumentsByIndex[index] = generateValueArgumentUsing(valueArgument, valueParameter, generateArgumentExpression)
} }
} }
@@ -268,6 +268,7 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
return ArrayAccessAssignmentReceiver( return ArrayAccessAssignmentReceiver(
ktLeft.arrayExpression!!.genExpr(), ktLeft.arrayExpression!!.genExpr(),
ktLeft.indexExpressions,
ktLeft.indexExpressions.map { it.genExpr() }, ktLeft.indexExpressions.map { it.genExpr() },
indexedGetResolvedCall, indexedGetResolvedCall,
indexedSetResolvedCall, indexedSetResolvedCall,
@@ -22,13 +22,16 @@ import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
import org.jetbrains.kotlin.ir.expressions.impl.inlineStatement import org.jetbrains.kotlin.ir.expressions.impl.inlineStatement
import org.jetbrains.kotlin.ir.expressions.isAssignmentOperatorWithResult import org.jetbrains.kotlin.ir.expressions.isAssignmentOperatorWithResult
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi2ir.generators.CallGenerator import org.jetbrains.kotlin.psi2ir.generators.CallGenerator
import org.jetbrains.kotlin.psi2ir.generators.pregenerateValueArgumentsUsing
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
class ArrayAccessAssignmentReceiver( class ArrayAccessAssignmentReceiver(
private val irArray: IrExpression, private val irArray: IrExpression,
private val irIndices: List<IrExpression>, private val ktIndexExpressions: List<KtExpression>,
private val irIndexExpressions: List<IrExpression>,
private val indexedGetResolvedCall: ResolvedCall<FunctionDescriptor>?, private val indexedGetResolvedCall: ResolvedCall<FunctionDescriptor>?,
private val indexedSetResolvedCall: ResolvedCall<FunctionDescriptor>?, private val indexedSetResolvedCall: ResolvedCall<FunctionDescriptor>?,
private val indexedGetCall: () -> CallBuilder?, private val indexedGetCall: () -> CallBuilder?,
@@ -57,15 +60,18 @@ class ArrayAccessAssignmentReceiver(
val irArrayValue = callGenerator.scope.createTemporaryVariableInBlock(callGenerator.context, irArray, irBlock, "array") val irArrayValue = callGenerator.scope.createTemporaryVariableInBlock(callGenerator.context, irArray, irBlock, "array")
val irIndexValues = irIndices.mapIndexed { i, irIndex -> val ktExpressionToIrIndexValue = HashMap<KtExpression, IntermediateValue>()
callGenerator.scope.createTemporaryVariableInBlock(callGenerator.context, irIndex, irBlock, "index$i")
for ((i, irIndex) in irIndexExpressions.withIndex()) {
ktExpressionToIrIndexValue[ktIndexExpressions[i]] =
callGenerator.scope.createTemporaryVariableInBlock(callGenerator.context, irIndex, irBlock, "index$i")
} }
val irLValue = LValueWithGetterAndSetterCalls( val irLValue = LValueWithGetterAndSetterCalls(
callGenerator, callGenerator,
descriptor, descriptor,
{ indexedGetCall()?.fillArrayAndIndexArguments(irArrayValue, irIndexValues) }, { indexedGetCall()?.fillArrayAndIndexArguments(irArrayValue, indexedGetResolvedCall!!, ktExpressionToIrIndexValue) },
{ indexedSetCall()?.fillArrayAndIndexArguments(irArrayValue, irIndexValues) }, { indexedSetCall()?.fillArrayAndIndexArguments(irArrayValue, indexedSetResolvedCall!!, ktExpressionToIrIndexValue) },
callGenerator.translateType(kotlinType), callGenerator.translateType(kotlinType),
startOffset, endOffset, origin startOffset, endOffset, origin
) )
@@ -76,18 +82,24 @@ class ArrayAccessAssignmentReceiver(
override fun assign(value: IrExpression): IrExpression { override fun assign(value: IrExpression): IrExpression {
val call = indexedSetCall() ?: throw AssertionError("Array access without indexed-get call") val call = indexedSetCall() ?: throw AssertionError("Array access without indexed-get call")
val ktExpressionToIrIndexExpression = ktIndexExpressions.zip(irIndexExpressions).toMap()
call.setExplicitReceiverValue(OnceExpressionValue(irArray)) call.setExplicitReceiverValue(OnceExpressionValue(irArray))
irIndices.forEachIndexed { i, irIndex -> callGenerator.statementGenerator.pregenerateValueArgumentsUsing(call, indexedSetResolvedCall!!) {
call.irValueArgumentsByIndex[i] = irIndex ktExpressionToIrIndexExpression[it]
} }
call.lastArgument = value call.lastArgument = value
return callGenerator.generateCall(startOffset, endOffset, call, IrStatementOrigin.EQ) return callGenerator.generateCall(startOffset, endOffset, call, IrStatementOrigin.EQ)
} }
private fun CallBuilder.fillArrayAndIndexArguments(arrayValue: IntermediateValue, indexValues: List<IntermediateValue>) = apply { private fun CallBuilder.fillArrayAndIndexArguments(
arrayValue: IntermediateValue,
resolvedCall: ResolvedCall<FunctionDescriptor>,
ktExpressionToIrIndexValue: Map<KtExpression, IntermediateValue>
) = apply {
setExplicitReceiverValue(arrayValue) setExplicitReceiverValue(arrayValue)
indexValues.forEachIndexed { i, irIndexValue ->
irValueArgumentsByIndex[i] = irIndexValue.load() callGenerator.statementGenerator.pregenerateValueArgumentsUsing(this, resolvedCall) { ktExpression ->
ktExpressionToIrIndexValue[ktExpression]?.load()
} }
} }
} }
+15
View File
@@ -0,0 +1,15 @@
class A
operator fun A.get(vararg xs: Int) = 0
operator fun A.set(i: Int, j: Int, v: Int) {}
fun testSimpleAssignment(a: A) {
a[1, 2] = 0
}
fun testPostfixIncrement(a: A) = a[1, 2]++
fun testCompoundAssignment(a: A) {
a[1, 2] += 10
}
+85
View File
@@ -0,0 +1,85 @@
FILE fqName:<root> fileName:/kt28456.kt
CLASS CLASS name:A modality:FINAL visibility:public flags: superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:A flags:
CONSTRUCTOR visibility:public <> () returnType:A flags:primary
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'constructor Any()'
INSTANCE_INITIALIZER_CALL classDescriptor='A'
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean flags:
overridden:
FUN IR_EXTERNAL_DECLARATION_STUB name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean flags:
$this: VALUE_PARAMETER name:<this> type:kotlin.Any flags:
VALUE_PARAMETER name:other index:0 type:kotlin.Any? flags:
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int flags:
overridden:
FUN IR_EXTERNAL_DECLARATION_STUB name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int flags:
$this: VALUE_PARAMETER name:<this> type:kotlin.Any flags:
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String flags:
overridden:
FUN IR_EXTERNAL_DECLARATION_STUB name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String flags:
$this: VALUE_PARAMETER name:<this> type:kotlin.Any flags:
FUN name:get visibility:public modality:FINAL <> ($receiver:A, xs:kotlin.IntArray) returnType:kotlin.Int flags:
$receiver: VALUE_PARAMETER name:<this> type:A flags:
VALUE_PARAMETER name:xs index:0 type:kotlin.IntArray varargElementType:kotlin.Int flags:vararg
BLOCK_BODY
RETURN type=kotlin.Nothing from='get(vararg Int) on A: Int'
CONST Int type=kotlin.Int value=0
FUN name:set visibility:public modality:FINAL <> ($receiver:A, i:kotlin.Int, j:kotlin.Int, v:kotlin.Int) returnType:kotlin.Unit flags:
$receiver: VALUE_PARAMETER name:<this> type:A flags:
VALUE_PARAMETER name:i index:0 type:kotlin.Int flags:
VALUE_PARAMETER name:j index:1 type:kotlin.Int flags:
VALUE_PARAMETER name:v index:2 type:kotlin.Int flags:
BLOCK_BODY
FUN name:testSimpleAssignment visibility:public modality:FINAL <> (a:A) returnType:kotlin.Unit flags:
VALUE_PARAMETER name:a index:0 type:A flags:
BLOCK_BODY
CALL 'set(Int, Int, Int) on A: Unit' type=kotlin.Unit origin=EQ
$receiver: GET_VAR 'value-parameter a: A' type=A origin=null
i: CONST Int type=kotlin.Int value=1
j: CONST Int type=kotlin.Int value=2
v: CONST Int type=kotlin.Int value=0
FUN name:testPostfixIncrement visibility:public modality:FINAL <> (a:A) returnType:kotlin.Int flags:
VALUE_PARAMETER name:a index:0 type:A flags:
BLOCK_BODY
RETURN type=kotlin.Nothing from='testPostfixIncrement(A): Int'
BLOCK type=kotlin.Int origin=POSTFIX_INCR
VAR IR_TEMPORARY_VARIABLE name:tmp0_array type:A flags:val
GET_VAR 'value-parameter a: A' type=A origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp1_index0 type:kotlin.Int flags:val
CONST Int type=kotlin.Int value=1
VAR IR_TEMPORARY_VARIABLE name:tmp2_index1 type:kotlin.Int flags:val
CONST Int type=kotlin.Int value=2
VAR IR_TEMPORARY_VARIABLE name:tmp3 type:kotlin.Int flags:val
CALL 'get(vararg Int) on A: Int' type=kotlin.Int origin=POSTFIX_INCR
$receiver: GET_VAR 'tmp0_array: A' type=A origin=null
xs: VARARG type=kotlin.IntArray varargElementType=kotlin.Int
GET_VAR 'tmp1_index0: Int' type=kotlin.Int origin=null
GET_VAR 'tmp2_index1: Int' type=kotlin.Int origin=null
CALL 'set(Int, Int, Int) on A: Unit' type=kotlin.Unit origin=POSTFIX_INCR
$receiver: GET_VAR 'tmp0_array: A' type=A origin=null
i: GET_VAR 'tmp1_index0: Int' type=kotlin.Int origin=null
j: GET_VAR 'tmp2_index1: Int' type=kotlin.Int origin=null
v: CALL 'inc(): Int' type=kotlin.Int origin=POSTFIX_INCR
$this: GET_VAR 'tmp3: Int' type=kotlin.Int origin=null
GET_VAR 'tmp3: Int' type=kotlin.Int origin=null
FUN name:testCompoundAssignment visibility:public modality:FINAL <> (a:A) returnType:kotlin.Unit flags:
VALUE_PARAMETER name:a index:0 type:A flags:
BLOCK_BODY
BLOCK type=kotlin.Unit origin=PLUSEQ
VAR IR_TEMPORARY_VARIABLE name:tmp0_array type:A flags:val
GET_VAR 'value-parameter a: A' type=A origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp1_index0 type:kotlin.Int flags:val
CONST Int type=kotlin.Int value=1
VAR IR_TEMPORARY_VARIABLE name:tmp2_index1 type:kotlin.Int flags:val
CONST Int type=kotlin.Int value=2
CALL 'set(Int, Int, Int) on A: Unit' type=kotlin.Unit origin=PLUSEQ
$receiver: GET_VAR 'tmp0_array: A' type=A origin=null
i: GET_VAR 'tmp1_index0: Int' type=kotlin.Int origin=null
j: GET_VAR 'tmp2_index1: Int' type=kotlin.Int origin=null
v: CALL 'plus(Int): Int' type=kotlin.Int origin=PLUSEQ
$this: CALL 'get(vararg Int) on A: Int' type=kotlin.Int origin=PLUSEQ
$receiver: GET_VAR 'tmp0_array: A' type=A origin=null
xs: VARARG type=kotlin.IntArray varargElementType=kotlin.Int
GET_VAR 'tmp1_index0: Int' type=kotlin.Int origin=null
GET_VAR 'tmp2_index1: Int' type=kotlin.Int origin=null
other: CONST Int type=kotlin.Int value=10
+7
View File
@@ -0,0 +1,7 @@
class A
operator fun A.set(vararg i: Int, v: Int) {}
fun testSimpleAssignment(a: A) {
a[1, 2, 3] = 0
}
+35
View File
@@ -0,0 +1,35 @@
FILE fqName:<root> fileName:/kt28456a.kt
CLASS CLASS name:A modality:FINAL visibility:public flags: superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:A flags:
CONSTRUCTOR visibility:public <> () returnType:A flags:primary
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'constructor Any()'
INSTANCE_INITIALIZER_CALL classDescriptor='A'
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean flags:
overridden:
FUN IR_EXTERNAL_DECLARATION_STUB name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean flags:
$this: VALUE_PARAMETER name:<this> type:kotlin.Any flags:
VALUE_PARAMETER name:other index:0 type:kotlin.Any? flags:
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int flags:
overridden:
FUN IR_EXTERNAL_DECLARATION_STUB name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int flags:
$this: VALUE_PARAMETER name:<this> type:kotlin.Any flags:
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String flags:
overridden:
FUN IR_EXTERNAL_DECLARATION_STUB name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String flags:
$this: VALUE_PARAMETER name:<this> type:kotlin.Any flags:
FUN name:set visibility:public modality:FINAL <> ($receiver:A, i:kotlin.IntArray, v:kotlin.Int) returnType:kotlin.Unit flags:
$receiver: VALUE_PARAMETER name:<this> type:A flags:
VALUE_PARAMETER name:i index:0 type:kotlin.IntArray varargElementType:kotlin.Int flags:vararg
VALUE_PARAMETER name:v index:1 type:kotlin.Int flags:
BLOCK_BODY
FUN name:testSimpleAssignment visibility:public modality:FINAL <> (a:A) returnType:kotlin.Unit flags:
VALUE_PARAMETER name:a index:0 type:A flags:
BLOCK_BODY
CALL 'set(vararg Int, Int) on A: Unit' type=kotlin.Unit origin=EQ
$receiver: GET_VAR 'value-parameter a: A' type=A origin=null
i: VARARG type=kotlin.IntArray varargElementType=kotlin.Int
CONST Int type=kotlin.Int value=1
CONST Int type=kotlin.Int value=2
CONST Int type=kotlin.Int value=3
v: CONST Int type=kotlin.Int value=0
+15
View File
@@ -0,0 +1,15 @@
class A
operator fun A.get(i: Int, a: Int = 1, b: Int = 2, c: Int = 3, d: Int = 4) = 0
operator fun A.set(i: Int, j: Int = 42, v: Int) {}
fun testSimpleAssignment(a: A) {
a[1] = 0
}
fun testPostfixIncrement(a: A) = a[1]++
fun testCompoundAssignment(a: A) {
a[1] += 10
}
+88
View File
@@ -0,0 +1,88 @@
FILE fqName:<root> fileName:/kt28456b.kt
CLASS CLASS name:A modality:FINAL visibility:public flags: superTypes:[kotlin.Any]
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:A flags:
CONSTRUCTOR visibility:public <> () returnType:A flags:primary
BLOCK_BODY
DELEGATING_CONSTRUCTOR_CALL 'constructor Any()'
INSTANCE_INITIALIZER_CALL classDescriptor='A'
FUN FAKE_OVERRIDE name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean flags:
overridden:
FUN IR_EXTERNAL_DECLARATION_STUB name:equals visibility:public modality:OPEN <> ($this:kotlin.Any, other:kotlin.Any?) returnType:kotlin.Boolean flags:
$this: VALUE_PARAMETER name:<this> type:kotlin.Any flags:
VALUE_PARAMETER name:other index:0 type:kotlin.Any? flags:
FUN FAKE_OVERRIDE name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int flags:
overridden:
FUN IR_EXTERNAL_DECLARATION_STUB name:hashCode visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.Int flags:
$this: VALUE_PARAMETER name:<this> type:kotlin.Any flags:
FUN FAKE_OVERRIDE name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String flags:
overridden:
FUN IR_EXTERNAL_DECLARATION_STUB name:toString visibility:public modality:OPEN <> ($this:kotlin.Any) returnType:kotlin.String flags:
$this: VALUE_PARAMETER name:<this> type:kotlin.Any flags:
FUN name:get visibility:public modality:FINAL <> ($receiver:A, i:kotlin.Int, a:kotlin.Int, b:kotlin.Int, c:kotlin.Int, d:kotlin.Int) returnType:kotlin.Int flags:
$receiver: VALUE_PARAMETER name:<this> type:A flags:
VALUE_PARAMETER name:i index:0 type:kotlin.Int flags:
VALUE_PARAMETER name:a index:1 type:kotlin.Int flags:
EXPRESSION_BODY
CONST Int type=kotlin.Int value=1
VALUE_PARAMETER name:b index:2 type:kotlin.Int flags:
EXPRESSION_BODY
CONST Int type=kotlin.Int value=2
VALUE_PARAMETER name:c index:3 type:kotlin.Int flags:
EXPRESSION_BODY
CONST Int type=kotlin.Int value=3
VALUE_PARAMETER name:d index:4 type:kotlin.Int flags:
EXPRESSION_BODY
CONST Int type=kotlin.Int value=4
BLOCK_BODY
RETURN type=kotlin.Nothing from='get(Int, Int = ..., Int = ..., Int = ..., Int = ...) on A: Int'
CONST Int type=kotlin.Int value=0
FUN name:set visibility:public modality:FINAL <> ($receiver:A, i:kotlin.Int, j:kotlin.Int, v:kotlin.Int) returnType:kotlin.Unit flags:
$receiver: VALUE_PARAMETER name:<this> type:A flags:
VALUE_PARAMETER name:i index:0 type:kotlin.Int flags:
VALUE_PARAMETER name:j index:1 type:kotlin.Int flags:
EXPRESSION_BODY
CONST Int type=kotlin.Int value=42
VALUE_PARAMETER name:v index:2 type:kotlin.Int flags:
BLOCK_BODY
FUN name:testSimpleAssignment visibility:public modality:FINAL <> (a:A) returnType:kotlin.Unit flags:
VALUE_PARAMETER name:a index:0 type:A flags:
BLOCK_BODY
CALL 'set(Int, Int = ..., Int) on A: Unit' type=kotlin.Unit origin=EQ
$receiver: GET_VAR 'value-parameter a: A' type=A origin=null
i: CONST Int type=kotlin.Int value=1
v: CONST Int type=kotlin.Int value=0
FUN name:testPostfixIncrement visibility:public modality:FINAL <> (a:A) returnType:kotlin.Int flags:
VALUE_PARAMETER name:a index:0 type:A flags:
BLOCK_BODY
RETURN type=kotlin.Nothing from='testPostfixIncrement(A): Int'
BLOCK type=kotlin.Int origin=POSTFIX_INCR
VAR IR_TEMPORARY_VARIABLE name:tmp0_array type:A flags:val
GET_VAR 'value-parameter a: A' type=A origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp1_index0 type:kotlin.Int flags:val
CONST Int type=kotlin.Int value=1
VAR IR_TEMPORARY_VARIABLE name:tmp2 type:kotlin.Int flags:val
CALL 'get(Int, Int = ..., Int = ..., Int = ..., Int = ...) on A: Int' type=kotlin.Int origin=POSTFIX_INCR
$receiver: GET_VAR 'tmp0_array: A' type=A origin=null
i: GET_VAR 'tmp1_index0: Int' type=kotlin.Int origin=null
CALL 'set(Int, Int = ..., Int) on A: Unit' type=kotlin.Unit origin=POSTFIX_INCR
$receiver: GET_VAR 'tmp0_array: A' type=A origin=null
i: GET_VAR 'tmp1_index0: Int' type=kotlin.Int origin=null
v: CALL 'inc(): Int' type=kotlin.Int origin=POSTFIX_INCR
$this: GET_VAR 'tmp2: Int' type=kotlin.Int origin=null
GET_VAR 'tmp2: Int' type=kotlin.Int origin=null
FUN name:testCompoundAssignment visibility:public modality:FINAL <> (a:A) returnType:kotlin.Unit flags:
VALUE_PARAMETER name:a index:0 type:A flags:
BLOCK_BODY
BLOCK type=kotlin.Unit origin=PLUSEQ
VAR IR_TEMPORARY_VARIABLE name:tmp0_array type:A flags:val
GET_VAR 'value-parameter a: A' type=A origin=null
VAR IR_TEMPORARY_VARIABLE name:tmp1_index0 type:kotlin.Int flags:val
CONST Int type=kotlin.Int value=1
CALL 'set(Int, Int = ..., Int) on A: Unit' type=kotlin.Unit origin=PLUSEQ
$receiver: GET_VAR 'tmp0_array: A' type=A origin=null
i: GET_VAR 'tmp1_index0: Int' type=kotlin.Int origin=null
v: CALL 'plus(Int): Int' type=kotlin.Int origin=PLUSEQ
$this: CALL 'get(Int, Int = ..., Int = ..., Int = ..., Int = ...) on A: Int' type=kotlin.Int origin=PLUSEQ
$receiver: GET_VAR 'tmp0_array: A' type=A origin=null
i: GET_VAR 'tmp1_index0: Int' type=kotlin.Int origin=null
other: CONST Int type=kotlin.Int value=10
@@ -957,6 +957,21 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
runTest("compiler/testData/ir/irText/expressions/kt28006.kt"); runTest("compiler/testData/ir/irText/expressions/kt28006.kt");
} }
@TestMetadata("kt28456.kt")
public void testKt28456() throws Exception {
runTest("compiler/testData/ir/irText/expressions/kt28456.kt");
}
@TestMetadata("kt28456a.kt")
public void testKt28456a() throws Exception {
runTest("compiler/testData/ir/irText/expressions/kt28456a.kt");
}
@TestMetadata("kt28456b.kt")
public void testKt28456b() throws Exception {
runTest("compiler/testData/ir/irText/expressions/kt28456b.kt");
}
@TestMetadata("lambdaInCAO.kt") @TestMetadata("lambdaInCAO.kt")
public void testLambdaInCAO() throws Exception { public void testLambdaInCAO() throws Exception {
runTest("compiler/testData/ir/irText/expressions/lambdaInCAO.kt"); runTest("compiler/testData/ir/irText/expressions/lambdaInCAO.kt");