psi2ir: dynamic array element get/set
This commit is contained in:
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.ir.types.classifierOrFail
|
|||||||
import org.jetbrains.kotlin.ir.util.referenceFunction
|
import org.jetbrains.kotlin.ir.util.referenceFunction
|
||||||
import org.jetbrains.kotlin.ir.util.render
|
import org.jetbrains.kotlin.ir.util.render
|
||||||
import org.jetbrains.kotlin.load.java.sam.SamConstructorDescriptor
|
import org.jetbrains.kotlin.load.java.sam.SamConstructorDescriptor
|
||||||
|
import org.jetbrains.kotlin.psi.KtArrayAccessExpression
|
||||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||||
@@ -236,13 +237,19 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
|||||||
return dispatchReceiver
|
return dispatchReceiver
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun ResolvedCall<*>.isImplicitInvokeOnDynamic(): Boolean {
|
private fun ResolvedCall<*>.isImplicitInvoke(): Boolean {
|
||||||
if (resultingDescriptor.name != OperatorNameConventions.INVOKE) return false
|
if (resultingDescriptor.name != OperatorNameConventions.INVOKE) return false
|
||||||
val callExression = call.callElement as? KtCallExpression ?: return true
|
val callExpression = call.callElement as? KtCallExpression ?: return true
|
||||||
val calleeExpression = callExression.calleeExpression as? KtSimpleNameExpression ?: return true
|
val calleeExpression = callExpression.calleeExpression as? KtSimpleNameExpression ?: return true
|
||||||
return calleeExpression.getReferencedName() != OperatorNameConventions.INVOKE.asString()
|
return calleeExpression.getReferencedName() != OperatorNameConventions.INVOKE.asString()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun ResolvedCall<*>.isImplicitGet(): Boolean =
|
||||||
|
resultingDescriptor.name == OperatorNameConventions.GET && call.callElement is KtArrayAccessExpression
|
||||||
|
|
||||||
|
private fun ResolvedCall<*>.isImplicitSet(): Boolean =
|
||||||
|
resultingDescriptor.name == OperatorNameConventions.SET && call.callElement is KtArrayAccessExpression
|
||||||
|
|
||||||
private fun generateFunctionCall(
|
private fun generateFunctionCall(
|
||||||
functionDescriptor: FunctionDescriptor,
|
functionDescriptor: FunctionDescriptor,
|
||||||
startOffset: Int,
|
startOffset: Int,
|
||||||
@@ -255,27 +262,56 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
|||||||
val irType = returnType.toIrType()
|
val irType = returnType.toIrType()
|
||||||
|
|
||||||
if (functionDescriptor.isDynamic()) {
|
if (functionDescriptor.isDynamic()) {
|
||||||
IrDynamicOperatorExpressionImpl(
|
fun makeDynamicOperatorExpression(operator: IrDynamicOperator) =
|
||||||
startOffset, endOffset,
|
IrDynamicOperatorExpressionImpl(
|
||||||
irType,
|
startOffset, endOffset,
|
||||||
IrDynamicOperator.INVOKE
|
irType,
|
||||||
).apply {
|
operator
|
||||||
val dispatchReceiver = getDynamicExpressionReceiver(dispatchReceiverValue, extensionReceiverValue, functionDescriptor)
|
)
|
||||||
|
|
||||||
receiver =
|
fun makeDynamicOperatorExpression(operator: IrDynamicOperator, dynamicReceiver: IrExpression) =
|
||||||
if (call.original.isImplicitInvokeOnDynamic())
|
IrDynamicOperatorExpressionImpl(
|
||||||
dispatchReceiver
|
startOffset, endOffset,
|
||||||
else
|
irType,
|
||||||
|
operator
|
||||||
|
).apply {
|
||||||
|
receiver = dynamicReceiver
|
||||||
|
arguments.addAll(call.getValueArgumentsInParameterOrder().mapIndexed { index: Int, arg: IrExpression? ->
|
||||||
|
arg ?: throw AssertionError("No argument in dynamic call $functionDescriptor at position $index")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
val dynamicReceiver = getDynamicExpressionReceiver(dispatchReceiverValue, extensionReceiverValue, functionDescriptor)
|
||||||
|
|
||||||
|
when {
|
||||||
|
call.original.isImplicitInvoke() ->
|
||||||
|
makeDynamicOperatorExpression(IrDynamicOperator.INVOKE, dynamicReceiver)
|
||||||
|
call.original.isImplicitGet() ->
|
||||||
|
makeDynamicOperatorExpression(IrDynamicOperator.ARRAY_ACCESS, dynamicReceiver)
|
||||||
|
call.original.isImplicitSet() ->
|
||||||
|
makeDynamicOperatorExpression(IrDynamicOperator.EQ).apply {
|
||||||
|
val args = call.getValueArgumentsInParameterOrder()
|
||||||
|
val arg0 = args[0]
|
||||||
|
?: throw AssertionError("No index argument in dynamic array set: ${call.original.call.callElement.text}")
|
||||||
|
val arg1 = args[1]
|
||||||
|
?: throw AssertionError("No value argument in dynamic array set: ${call.original.call.callElement.text}")
|
||||||
|
receiver =
|
||||||
|
makeDynamicOperatorExpression(IrDynamicOperator.ARRAY_ACCESS).apply {
|
||||||
|
receiver = dynamicReceiver
|
||||||
|
arguments.add(arg0)
|
||||||
|
}
|
||||||
|
arguments.add(arg1)
|
||||||
|
}
|
||||||
|
else ->
|
||||||
|
makeDynamicOperatorExpression(
|
||||||
|
IrDynamicOperator.INVOKE,
|
||||||
IrDynamicMemberExpressionImpl(
|
IrDynamicMemberExpressionImpl(
|
||||||
startOffset, endOffset, // TODO obtain more exact start/end offsets for explicit receiver expression
|
startOffset, endOffset, // TODO obtain more exact start/end offsets for explicit receiver expression
|
||||||
dispatchReceiver.type,
|
dynamicReceiver.type,
|
||||||
functionDescriptor.name.asString(),
|
functionDescriptor.name.asString(),
|
||||||
dispatchReceiver
|
dynamicReceiver
|
||||||
)
|
)
|
||||||
|
)
|
||||||
arguments.addAll(call.getValueArgumentsInParameterOrder().mapIndexed { index: Int, arg: IrExpression? ->
|
|
||||||
arg ?: throw AssertionError("No argument in dynamic call $functionDescriptor at position $index")
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val functionSymbol = context.symbolTable.referenceFunction(functionDescriptor.original)
|
val functionSymbol = context.symbolTable.referenceFunction(functionDescriptor.original)
|
||||||
|
|||||||
+19
-1
@@ -20,11 +20,13 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
|||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrDynamicOperator
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
|
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
|
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
|
||||||
import org.jetbrains.kotlin.ir.types.makeNotNull
|
import org.jetbrains.kotlin.ir.types.makeNotNull
|
||||||
import org.jetbrains.kotlin.ir.util.referenceClassifier
|
import org.jetbrains.kotlin.ir.util.referenceClassifier
|
||||||
@@ -45,7 +47,6 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType
|
import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||||
import java.lang.AssertionError
|
|
||||||
|
|
||||||
|
|
||||||
class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) {
|
class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) {
|
||||||
@@ -433,4 +434,21 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
|
|||||||
|
|
||||||
return generateCall(resolvedCall, expression, origin)
|
return generateCall(resolvedCall, expression, origin)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun generateDynamicOperatorExpression(
|
||||||
|
irOperator: IrDynamicOperator,
|
||||||
|
irType: IrType,
|
||||||
|
ktOperatorExpression: KtExpression,
|
||||||
|
ktReceiverExpression: KtExpression,
|
||||||
|
ktArgumentExpressions: List<KtExpression>
|
||||||
|
): IrExpression =
|
||||||
|
IrDynamicOperatorExpressionImpl(
|
||||||
|
ktOperatorExpression.startOffsetSkippingComments,
|
||||||
|
ktOperatorExpression.endOffset,
|
||||||
|
irType,
|
||||||
|
irOperator
|
||||||
|
).apply {
|
||||||
|
receiver = statementGenerator.generateExpression(ktReceiverExpression)
|
||||||
|
ktArgumentExpressions.mapTo(arguments) { statementGenerator.generateExpression(it) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-4
@@ -41,6 +41,7 @@ import org.jetbrains.kotlin.resolve.BindingContextUtils
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic
|
||||||
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
|
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
|
||||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
@@ -353,10 +354,19 @@ class StatementGenerator(
|
|||||||
override fun visitArrayAccessExpression(expression: KtArrayAccessExpression, data: Nothing?): IrStatement {
|
override fun visitArrayAccessExpression(expression: KtArrayAccessExpression, data: Nothing?): IrStatement {
|
||||||
val indexedGetCall = getOrFail(BindingContext.INDEXED_LVALUE_GET, expression)
|
val indexedGetCall = getOrFail(BindingContext.INDEXED_LVALUE_GET, expression)
|
||||||
|
|
||||||
return CallGenerator(this).generateCall(
|
return if (indexedGetCall.resultingDescriptor.isDynamic())
|
||||||
expression.startOffsetSkippingComments, expression.endOffset,
|
OperatorExpressionGenerator(this).generateDynamicOperatorExpression(
|
||||||
pregenerateCall(indexedGetCall), IrStatementOrigin.GET_ARRAY_ELEMENT
|
IrDynamicOperator.ARRAY_ACCESS,
|
||||||
)
|
indexedGetCall.resultingDescriptor.returnType!!.toIrType(),
|
||||||
|
expression,
|
||||||
|
expression.arrayExpression ?: throw AssertionError("Array expression not found"),
|
||||||
|
expression.indexExpressions
|
||||||
|
)
|
||||||
|
else
|
||||||
|
CallGenerator(this).generateCall(
|
||||||
|
expression.startOffsetSkippingComments, expression.endOffset,
|
||||||
|
pregenerateCall(indexedGetCall), IrStatementOrigin.GET_ARRAY_ELEMENT
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitDotQualifiedExpression(expression: KtDotQualifiedExpression, data: Nothing?): IrStatement =
|
override fun visitDotQualifiedExpression(expression: KtDotQualifiedExpression, data: Nothing?): IrStatement =
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
fun testArrayAccess1(d: dynamic) = d["KEY"]
|
||||||
|
|
||||||
|
fun testArrayAccess2(d: dynamic) = d()["KEY"]
|
||||||
|
|
||||||
|
fun testArrayAccess3(d: dynamic) = d.get("KEY")
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
FILE fqName:<root> fileName:/dynamicArrayAccess.kt
|
||||||
|
FUN name:testArrayAccess1 visibility:public modality:FINAL <> (d:dynamic) returnType:dynamic flags:
|
||||||
|
VALUE_PARAMETER name:d index:0 type:dynamic flags:
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='testArrayAccess1(dynamic): dynamic'
|
||||||
|
DYN_OP operator=ARRAY_ACCESS type=dynamic
|
||||||
|
receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||||
|
0: CONST String type=kotlin.String value="KEY"
|
||||||
|
FUN name:testArrayAccess2 visibility:public modality:FINAL <> (d:dynamic) returnType:dynamic flags:
|
||||||
|
VALUE_PARAMETER name:d index:0 type:dynamic flags:
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='testArrayAccess2(dynamic): dynamic'
|
||||||
|
DYN_OP operator=ARRAY_ACCESS type=dynamic
|
||||||
|
receiver: DYN_OP operator=INVOKE type=dynamic
|
||||||
|
receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=VARIABLE_AS_FUNCTION
|
||||||
|
0: CONST String type=kotlin.String value="KEY"
|
||||||
|
FUN name:testArrayAccess3 visibility:public modality:FINAL <> (d:dynamic) returnType:dynamic flags:
|
||||||
|
VALUE_PARAMETER name:d index:0 type:dynamic flags:
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='testArrayAccess3(dynamic): dynamic'
|
||||||
|
DYN_OP operator=INVOKE type=dynamic
|
||||||
|
receiver: DYN_MEMBER memberName='get' type=dynamic
|
||||||
|
GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||||
|
0: CONST String type=kotlin.String value="KEY"
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fun testArrayAssignment(d: dynamic) {
|
||||||
|
d["KEY"] = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testArrayAssignmentFake(d: dynamic) {
|
||||||
|
d.set("KEY", 2)
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
FILE fqName:<root> fileName:/dynamicArrayAssignment.kt
|
||||||
|
FUN name:testArrayAssignment visibility:public modality:FINAL <> (d:dynamic) returnType:kotlin.Unit flags:
|
||||||
|
VALUE_PARAMETER name:d index:0 type:dynamic flags:
|
||||||
|
BLOCK_BODY
|
||||||
|
DYN_OP operator=EQ type=dynamic
|
||||||
|
receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic
|
||||||
|
receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||||
|
0: CONST String type=kotlin.String value="KEY"
|
||||||
|
0: CONST Int type=kotlin.Int value=1
|
||||||
|
FUN name:testArrayAssignmentFake visibility:public modality:FINAL <> (d:dynamic) returnType:kotlin.Unit flags:
|
||||||
|
VALUE_PARAMETER name:d index:0 type:dynamic flags:
|
||||||
|
BLOCK_BODY
|
||||||
|
DYN_OP operator=INVOKE type=dynamic
|
||||||
|
receiver: DYN_MEMBER memberName='set' type=dynamic
|
||||||
|
GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||||
|
0: CONST String type=kotlin.String value="KEY"
|
||||||
|
1: CONST Int type=kotlin.Int value=2
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fun testArrayAugmentedAssignment(d: dynamic) {
|
||||||
|
d["KEY"] += "+="
|
||||||
|
d["KEY"] -= "-="
|
||||||
|
d["KEY"] *= "*="
|
||||||
|
d["KEY"] /= "/="
|
||||||
|
d["KEY"] %= "%="
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
FILE fqName:<root> fileName:/dynamicArrayAugmentedAssignment.kt
|
||||||
|
FUN name:testArrayAugmentedAssignment visibility:public modality:FINAL <> (d:dynamic) returnType:kotlin.Unit flags:
|
||||||
|
VALUE_PARAMETER name:d index:0 type:dynamic flags:
|
||||||
|
BLOCK_BODY
|
||||||
|
BLOCK type=kotlin.Unit origin=PLUSEQ
|
||||||
|
VAR IR_TEMPORARY_VARIABLE name:tmp0_array type:dynamic flags:val
|
||||||
|
GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||||
|
VAR IR_TEMPORARY_VARIABLE name:tmp1_index0 type:kotlin.String flags:val
|
||||||
|
CONST String type=kotlin.String value="KEY"
|
||||||
|
DYN_OP operator=PLUSEQ type=kotlin.Unit
|
||||||
|
receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic
|
||||||
|
receiver: GET_VAR 'tmp0_array: dynamic' type=dynamic origin=null
|
||||||
|
0: GET_VAR 'tmp1_index0: String' type=kotlin.String origin=null
|
||||||
|
0: CONST String type=kotlin.String value="+="
|
||||||
|
BLOCK type=kotlin.Unit origin=MINUSEQ
|
||||||
|
VAR IR_TEMPORARY_VARIABLE name:tmp2_array type:dynamic flags:val
|
||||||
|
GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||||
|
VAR IR_TEMPORARY_VARIABLE name:tmp3_index0 type:kotlin.String flags:val
|
||||||
|
CONST String type=kotlin.String value="KEY"
|
||||||
|
DYN_OP operator=MINUSEQ type=kotlin.Unit
|
||||||
|
receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic
|
||||||
|
receiver: GET_VAR 'tmp2_array: dynamic' type=dynamic origin=null
|
||||||
|
0: GET_VAR 'tmp3_index0: String' type=kotlin.String origin=null
|
||||||
|
0: CONST String type=kotlin.String value="-="
|
||||||
|
BLOCK type=kotlin.Unit origin=MULTEQ
|
||||||
|
VAR IR_TEMPORARY_VARIABLE name:tmp4_array type:dynamic flags:val
|
||||||
|
GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||||
|
VAR IR_TEMPORARY_VARIABLE name:tmp5_index0 type:kotlin.String flags:val
|
||||||
|
CONST String type=kotlin.String value="KEY"
|
||||||
|
DYN_OP operator=MULEQ type=kotlin.Unit
|
||||||
|
receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic
|
||||||
|
receiver: GET_VAR 'tmp4_array: dynamic' type=dynamic origin=null
|
||||||
|
0: GET_VAR 'tmp5_index0: String' type=kotlin.String origin=null
|
||||||
|
0: CONST String type=kotlin.String value="*="
|
||||||
|
BLOCK type=kotlin.Unit origin=DIVEQ
|
||||||
|
VAR IR_TEMPORARY_VARIABLE name:tmp6_array type:dynamic flags:val
|
||||||
|
GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||||
|
VAR IR_TEMPORARY_VARIABLE name:tmp7_index0 type:kotlin.String flags:val
|
||||||
|
CONST String type=kotlin.String value="KEY"
|
||||||
|
DYN_OP operator=DIVEQ type=kotlin.Unit
|
||||||
|
receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic
|
||||||
|
receiver: GET_VAR 'tmp6_array: dynamic' type=dynamic origin=null
|
||||||
|
0: GET_VAR 'tmp7_index0: String' type=kotlin.String origin=null
|
||||||
|
0: CONST String type=kotlin.String value="/="
|
||||||
|
BLOCK type=kotlin.Unit origin=PERCEQ
|
||||||
|
VAR IR_TEMPORARY_VARIABLE name:tmp8_array type:dynamic flags:val
|
||||||
|
GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||||
|
VAR IR_TEMPORARY_VARIABLE name:tmp9_index0 type:kotlin.String flags:val
|
||||||
|
CONST String type=kotlin.String value="KEY"
|
||||||
|
DYN_OP operator=MODEQ type=kotlin.Unit
|
||||||
|
receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic
|
||||||
|
receiver: GET_VAR 'tmp8_array: dynamic' type=dynamic origin=null
|
||||||
|
0: GET_VAR 'tmp9_index0: String' type=kotlin.String origin=null
|
||||||
|
0: CONST String type=kotlin.String value="%="
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
|
||||||
|
fun testArrayIncrementDecrement(d: dynamic) {
|
||||||
|
val t1 = ++d["prefixIncr"]
|
||||||
|
val t2 = --d["prefixDecr"]
|
||||||
|
val t3 = d["postfixIncr"]++
|
||||||
|
val t4 = d["postfixDecr"]--
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
FILE fqName:<root> fileName:/dynamicArrayIncrementDecrement.kt
|
||||||
|
FUN name:testArrayIncrementDecrement visibility:public modality:FINAL <> (d:dynamic) returnType:kotlin.Unit flags:
|
||||||
|
VALUE_PARAMETER name:d index:0 type:dynamic flags:
|
||||||
|
BLOCK_BODY
|
||||||
|
VAR name:t1 type:dynamic flags:val
|
||||||
|
BLOCK type=dynamic origin=PREFIX_INCR
|
||||||
|
VAR IR_TEMPORARY_VARIABLE name:tmp0_array type:dynamic flags:val
|
||||||
|
GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||||
|
VAR IR_TEMPORARY_VARIABLE name:tmp1_index0 type:kotlin.String flags:val
|
||||||
|
CONST String type=kotlin.String value="prefixIncr"
|
||||||
|
DYN_OP operator=PREFIX_INCREMENT type=dynamic
|
||||||
|
receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic
|
||||||
|
receiver: GET_VAR 'tmp0_array: dynamic' type=dynamic origin=null
|
||||||
|
0: GET_VAR 'tmp1_index0: String' type=kotlin.String origin=null
|
||||||
|
VAR name:t2 type:dynamic flags:val
|
||||||
|
BLOCK type=dynamic origin=PREFIX_DECR
|
||||||
|
VAR IR_TEMPORARY_VARIABLE name:tmp2_array type:dynamic flags:val
|
||||||
|
GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||||
|
VAR IR_TEMPORARY_VARIABLE name:tmp3_index0 type:kotlin.String flags:val
|
||||||
|
CONST String type=kotlin.String value="prefixDecr"
|
||||||
|
DYN_OP operator=PREFIX_DECREMENT type=dynamic
|
||||||
|
receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic
|
||||||
|
receiver: GET_VAR 'tmp2_array: dynamic' type=dynamic origin=null
|
||||||
|
0: GET_VAR 'tmp3_index0: String' type=kotlin.String origin=null
|
||||||
|
VAR name:t3 type:dynamic flags:val
|
||||||
|
BLOCK type=dynamic origin=POSTFIX_INCR
|
||||||
|
VAR IR_TEMPORARY_VARIABLE name:tmp4_array type:dynamic flags:val
|
||||||
|
GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||||
|
VAR IR_TEMPORARY_VARIABLE name:tmp5_index0 type:kotlin.String flags:val
|
||||||
|
CONST String type=kotlin.String value="postfixIncr"
|
||||||
|
DYN_OP operator=POSTFIX_INCREMENT type=dynamic
|
||||||
|
receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic
|
||||||
|
receiver: GET_VAR 'tmp4_array: dynamic' type=dynamic origin=null
|
||||||
|
0: GET_VAR 'tmp5_index0: String' type=kotlin.String origin=null
|
||||||
|
VAR name:t4 type:dynamic flags:val
|
||||||
|
BLOCK type=dynamic origin=POSTFIX_DECR
|
||||||
|
VAR IR_TEMPORARY_VARIABLE name:tmp6_array type:dynamic flags:val
|
||||||
|
GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||||
|
VAR IR_TEMPORARY_VARIABLE name:tmp7_index0 type:kotlin.String flags:val
|
||||||
|
CONST String type=kotlin.String value="postfixDecr"
|
||||||
|
DYN_OP operator=POSTFIX_DECREMENT type=dynamic
|
||||||
|
receiver: DYN_OP operator=ARRAY_ACCESS type=dynamic
|
||||||
|
receiver: GET_VAR 'tmp6_array: dynamic' type=dynamic origin=null
|
||||||
|
0: GET_VAR 'tmp7_index0: String' type=kotlin.String origin=null
|
||||||
@@ -46,6 +46,26 @@ public class IrJsTextTestCaseGenerated extends AbstractIrJsTextTestCase {
|
|||||||
runTest("compiler/testData/ir/irJsText/dynamic/dynamicAndMembersOfAny.kt");
|
runTest("compiler/testData/ir/irJsText/dynamic/dynamicAndMembersOfAny.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("dynamicArrayAccess.kt")
|
||||||
|
public void testDynamicArrayAccess() throws Exception {
|
||||||
|
runTest("compiler/testData/ir/irJsText/dynamic/dynamicArrayAccess.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("dynamicArrayAssignment.kt")
|
||||||
|
public void testDynamicArrayAssignment() throws Exception {
|
||||||
|
runTest("compiler/testData/ir/irJsText/dynamic/dynamicArrayAssignment.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("dynamicArrayAugmentedAssignment.kt")
|
||||||
|
public void testDynamicArrayAugmentedAssignment() throws Exception {
|
||||||
|
runTest("compiler/testData/ir/irJsText/dynamic/dynamicArrayAugmentedAssignment.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("dynamicArrayIncrementDecrement.kt")
|
||||||
|
public void testDynamicArrayIncrementDecrement() throws Exception {
|
||||||
|
runTest("compiler/testData/ir/irJsText/dynamic/dynamicArrayIncrementDecrement.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("dynamicCall.kt")
|
@TestMetadata("dynamicCall.kt")
|
||||||
public void testDynamicCall() throws Exception {
|
public void testDynamicCall() throws Exception {
|
||||||
runTest("compiler/testData/ir/irJsText/dynamic/dynamicCall.kt");
|
runTest("compiler/testData/ir/irJsText/dynamic/dynamicCall.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user