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.impl.*
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.startOffsetSkippingComments
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.types.KotlinType
import org.jetbrains.kotlin.types.TypeSubstitutor
import java.lang.AssertionError
fun StatementGenerator.generateReceiverOrNull(ktDefaultElement: KtElement, receiver: ReceiverValue?): IntermediateValue? =
receiver?.let { generateReceiver(ktDefaultElement, receiver) }
@@ -209,9 +209,10 @@ private fun StatementGenerator.generateReceiverForCalleeImportedFromObject(
}
}
fun StatementGenerator.generateVarargExpression(
fun StatementGenerator.generateVarargExpressionUsing(
varargArgument: VarargValueArgument,
valueParameter: ValueParameterDescriptor
valueParameter: ValueParameterDescriptor,
generateArgumentExpression: (KtExpression) -> IrExpression?
): IrExpression? {
if (varargArgument.arguments.isEmpty()) {
return null
@@ -232,14 +233,16 @@ fun StatementGenerator.generateVarargExpression(
for (argument in varargArgument.arguments) {
val ktArgumentExpression = argument.getArgumentExpression()
?: 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 =
if (argument.getSpreadElement() != null)
IrSpreadElementImpl(
ktArgumentExpression.startOffsetSkippingComments, ktArgumentExpression.endOffset,
generateExpression(ktArgumentExpression)
irArgumentExpression
)
else
generateExpression(ktArgumentExpression)
irArgumentExpression
irVararg.addElement(irVarargElement)
}
@@ -247,17 +250,23 @@ fun StatementGenerator.generateVarargExpression(
return irVararg
}
fun StatementGenerator.generateValueArgument(
private fun StatementGenerator.generateValueArgument(
valueArgument: ResolvedValueArgument,
valueParameter: ValueParameterDescriptor
) = generateValueArgumentUsing(valueArgument, valueParameter) { generateExpression(it) }
fun StatementGenerator.generateValueArgumentUsing(
valueArgument: ResolvedValueArgument,
valueParameter: ValueParameterDescriptor,
generateArgumentExpression: (KtExpression) -> IrExpression?
): IrExpression? =
when (valueArgument) {
is DefaultValueArgument ->
null
is ExpressionValueArgument ->
generateExpression(valueArgument.valueArgument!!.getArgumentExpression()!!)
generateArgumentExpression(valueArgument.valueArgument!!.getArgumentExpression()!!)
is VarargValueArgument ->
generateVarargExpression(valueArgument, valueParameter)
generateVarargExpressionUsing(valueArgument, valueParameter, generateArgumentExpression)
else ->
TODO("Unexpected valueArgument: ${valueArgument::class.java.simpleName}")
}
@@ -357,9 +366,19 @@ private fun ResolvedCall<*>.isExtensionInvokeCall(): Boolean {
}
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 ->
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(
ktLeft.arrayExpression!!.genExpr(),
ktLeft.indexExpressions,
ktLeft.indexExpressions.map { it.genExpr() },
indexedGetResolvedCall,
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.inlineStatement
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.pregenerateValueArgumentsUsing
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.types.KotlinType
class ArrayAccessAssignmentReceiver(
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 indexedSetResolvedCall: ResolvedCall<FunctionDescriptor>?,
private val indexedGetCall: () -> CallBuilder?,
@@ -57,15 +60,18 @@ class ArrayAccessAssignmentReceiver(
val irArrayValue = callGenerator.scope.createTemporaryVariableInBlock(callGenerator.context, irArray, irBlock, "array")
val irIndexValues = irIndices.mapIndexed { i, irIndex ->
callGenerator.scope.createTemporaryVariableInBlock(callGenerator.context, irIndex, irBlock, "index$i")
val ktExpressionToIrIndexValue = HashMap<KtExpression, IntermediateValue>()
for ((i, irIndex) in irIndexExpressions.withIndex()) {
ktExpressionToIrIndexValue[ktIndexExpressions[i]] =
callGenerator.scope.createTemporaryVariableInBlock(callGenerator.context, irIndex, irBlock, "index$i")
}
val irLValue = LValueWithGetterAndSetterCalls(
callGenerator,
descriptor,
{ indexedGetCall()?.fillArrayAndIndexArguments(irArrayValue, irIndexValues) },
{ indexedSetCall()?.fillArrayAndIndexArguments(irArrayValue, irIndexValues) },
{ indexedGetCall()?.fillArrayAndIndexArguments(irArrayValue, indexedGetResolvedCall!!, ktExpressionToIrIndexValue) },
{ indexedSetCall()?.fillArrayAndIndexArguments(irArrayValue, indexedSetResolvedCall!!, ktExpressionToIrIndexValue) },
callGenerator.translateType(kotlinType),
startOffset, endOffset, origin
)
@@ -76,18 +82,24 @@ class ArrayAccessAssignmentReceiver(
override fun assign(value: IrExpression): IrExpression {
val call = indexedSetCall() ?: throw AssertionError("Array access without indexed-get call")
val ktExpressionToIrIndexExpression = ktIndexExpressions.zip(irIndexExpressions).toMap()
call.setExplicitReceiverValue(OnceExpressionValue(irArray))
irIndices.forEachIndexed { i, irIndex ->
call.irValueArgumentsByIndex[i] = irIndex
callGenerator.statementGenerator.pregenerateValueArgumentsUsing(call, indexedSetResolvedCall!!) {
ktExpressionToIrIndexExpression[it]
}
call.lastArgument = value
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)
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");
}
@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")
public void testLambdaInCAO() throws Exception {
runTest("compiler/testData/ir/irText/expressions/lambdaInCAO.kt");