pri2ir: dynamic unary & binary expressions
NB1 Not every dynamic unary or binary expression is translated to dynamic operator expressions literally. For example, assignments and increments can have safe calls in LHS, which require some extra logic. NB2 There are some open design questions left regarding how dynamic expressions should actually be translated.
This commit is contained in:
+7
-2
@@ -267,8 +267,13 @@ fun StatementGenerator.generateValueArgumentUsing(
|
||||
when (valueArgument) {
|
||||
is DefaultValueArgument ->
|
||||
null
|
||||
is ExpressionValueArgument ->
|
||||
generateArgumentExpression(valueArgument.valueArgument!!.getArgumentExpression()!!)
|
||||
is ExpressionValueArgument -> {
|
||||
val valueArgument1 = valueArgument.valueArgument
|
||||
?: throw AssertionError("No value argument: $valueArgument")
|
||||
val argumentExpression = valueArgument1.getArgumentExpression()
|
||||
?: throw AssertionError("No argument expression: $valueArgument1")
|
||||
generateArgumentExpression(argumentExpression)
|
||||
}
|
||||
is VarargValueArgument ->
|
||||
generateVarargExpressionUsing(valueArgument, valueParameter, generateArgumentExpression)
|
||||
else ->
|
||||
|
||||
@@ -26,10 +26,7 @@ import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||
import org.jetbrains.kotlin.ir.util.referenceFunction
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
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.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.*
|
||||
@@ -41,7 +38,6 @@ import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import java.util.*
|
||||
|
||||
class CallGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) {
|
||||
@@ -237,19 +233,6 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
return dispatchReceiver
|
||||
}
|
||||
|
||||
private fun ResolvedCall<*>.isImplicitInvoke(): Boolean {
|
||||
if (resultingDescriptor.name != OperatorNameConventions.INVOKE) return false
|
||||
val callExpression = call.callElement as? KtCallExpression ?: return true
|
||||
val calleeExpression = callExpression.calleeExpression as? KtSimpleNameExpression ?: return true
|
||||
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(
|
||||
functionDescriptor: FunctionDescriptor,
|
||||
startOffset: Int,
|
||||
@@ -269,12 +252,8 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
operator
|
||||
)
|
||||
|
||||
fun makeDynamicOperatorExpression(operator: IrDynamicOperator, dynamicReceiver: IrExpression) =
|
||||
IrDynamicOperatorExpressionImpl(
|
||||
startOffset, endOffset,
|
||||
irType,
|
||||
operator
|
||||
).apply {
|
||||
fun makeDynamicOperatorExpressionWithArguments(operator: IrDynamicOperator, dynamicReceiver: IrExpression) =
|
||||
makeDynamicOperatorExpression(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")
|
||||
@@ -285,9 +264,9 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
|
||||
when {
|
||||
call.original.isImplicitInvoke() ->
|
||||
makeDynamicOperatorExpression(IrDynamicOperator.INVOKE, dynamicReceiver)
|
||||
makeDynamicOperatorExpressionWithArguments(IrDynamicOperator.INVOKE, dynamicReceiver)
|
||||
call.original.isImplicitGet() ->
|
||||
makeDynamicOperatorExpression(IrDynamicOperator.ARRAY_ACCESS, dynamicReceiver)
|
||||
makeDynamicOperatorExpressionWithArguments(IrDynamicOperator.ARRAY_ACCESS, dynamicReceiver)
|
||||
call.original.isImplicitSet() ->
|
||||
makeDynamicOperatorExpression(IrDynamicOperator.EQ).apply {
|
||||
val args = call.getValueArgumentsInParameterOrder()
|
||||
@@ -303,7 +282,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
arguments.add(arg1)
|
||||
}
|
||||
else ->
|
||||
makeDynamicOperatorExpression(
|
||||
makeDynamicOperatorExpressionWithArguments(
|
||||
IrDynamicOperator.INVOKE,
|
||||
IrDynamicMemberExpressionImpl(
|
||||
startOffset, endOffset, // TODO obtain more exact start/end offsets for explicit receiver expression
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.psi2ir.generators
|
||||
|
||||
import org.jetbrains.kotlin.ir.expressions.IrDynamicOperator
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
internal fun ResolvedCall<*>.isImplicitInvoke(): Boolean {
|
||||
if (resultingDescriptor.name != OperatorNameConventions.INVOKE) return false
|
||||
val callExpression = call.callElement as? KtCallExpression ?: return true
|
||||
val calleeExpression = callExpression.calleeExpression as? KtSimpleNameExpression ?: return true
|
||||
return calleeExpression.getReferencedName() != OperatorNameConventions.INVOKE.asString()
|
||||
}
|
||||
|
||||
internal fun ResolvedCall<*>.isImplicitGet(): Boolean =
|
||||
resultingDescriptor.name == OperatorNameConventions.GET && call.callElement is KtArrayAccessExpression
|
||||
|
||||
internal fun ResolvedCall<*>.isImplicitSet(): Boolean =
|
||||
resultingDescriptor.name == OperatorNameConventions.SET && call.callElement is KtArrayAccessExpression
|
||||
|
||||
internal fun KtElement.getDynamicOperator(): IrDynamicOperator {
|
||||
return when (this) {
|
||||
is KtUnaryExpression ->
|
||||
when (operationToken) {
|
||||
KtTokens.PLUS -> IrDynamicOperator.UNARY_PLUS
|
||||
KtTokens.MINUS -> IrDynamicOperator.UNARY_MINUS
|
||||
KtTokens.EXCL -> IrDynamicOperator.EXCL
|
||||
else -> throw AssertionError("Unexpected unary operator expression: $text")
|
||||
}
|
||||
is KtBinaryExpression ->
|
||||
when (operationToken) {
|
||||
KtTokens.PLUS -> IrDynamicOperator.BINARY_PLUS
|
||||
KtTokens.MINUS -> IrDynamicOperator.BINARY_MINUS
|
||||
KtTokens.MUL -> IrDynamicOperator.MUL
|
||||
KtTokens.DIV -> IrDynamicOperator.DIV
|
||||
KtTokens.PERC -> IrDynamicOperator.MOD
|
||||
KtTokens.LT -> IrDynamicOperator.LT
|
||||
KtTokens.LTEQ -> IrDynamicOperator.LE
|
||||
KtTokens.GT -> IrDynamicOperator.GT
|
||||
KtTokens.GTEQ -> IrDynamicOperator.GE
|
||||
KtTokens.ANDAND -> IrDynamicOperator.ANDAND
|
||||
KtTokens.OROR -> IrDynamicOperator.OROR
|
||||
KtTokens.EQEQ -> IrDynamicOperator.EQEQ
|
||||
KtTokens.EQEQEQ -> IrDynamicOperator.EQEQEQ
|
||||
KtTokens.EXCLEQ -> IrDynamicOperator.EXCLEQ
|
||||
KtTokens.EXCLEQEQEQ -> IrDynamicOperator.EXCLEQEQ
|
||||
else -> throw AssertionError("Unexpected binary operator expression: $text")
|
||||
}
|
||||
else -> throw AssertionError("Unexpected operator expression: $text")
|
||||
}
|
||||
}
|
||||
+86
-17
@@ -20,10 +20,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
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.IrStatementOrigin
|
||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
@@ -44,6 +41,7 @@ import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.checkers.PrimitiveNumericComparisonInfo
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.isDynamic
|
||||
import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberType
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
@@ -148,6 +146,51 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
|
||||
}
|
||||
}
|
||||
|
||||
private fun isDynamicUnaryOperator(ktUnaryExpression: KtUnaryExpression): Boolean {
|
||||
val arg = ktUnaryExpression.baseExpression ?: return false
|
||||
val argType = context.bindingContext.getType(arg) ?: return false
|
||||
return argType.isDynamic()
|
||||
}
|
||||
|
||||
private fun isDynamicBinaryOperator(ktExpression: KtBinaryExpression): Boolean {
|
||||
val lhs = ktExpression.left ?: return false
|
||||
val lhsType = context.bindingContext.getType(lhs) ?: return false
|
||||
return lhsType.isDynamic()
|
||||
}
|
||||
|
||||
private fun generateDynamicUnaryExpression(ktExpression: KtUnaryExpression): IrExpression {
|
||||
val ktArg = ktExpression.baseExpression ?: throw AssertionError("No arg in ${ktExpression.text}")
|
||||
val kotlinType = context.bindingContext.getType(ktExpression) ?: throw AssertionError("No type for ${ktExpression.text}")
|
||||
val operator = ktExpression.getDynamicOperator()
|
||||
return IrDynamicOperatorExpressionImpl(
|
||||
ktExpression.startOffsetSkippingComments,
|
||||
ktExpression.endOffset,
|
||||
kotlinType.toIrType(),
|
||||
operator
|
||||
).apply {
|
||||
receiver = ktArg.genExpr()
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateDynamicBinaryExpression(ktExpression: KtBinaryExpression): IrExpression {
|
||||
val ktLeft = ktExpression.left ?: throw AssertionError("No LHS in ${ktExpression.text}")
|
||||
val ktRight = ktExpression.right ?: throw AssertionError("No RHS in ${ktExpression.text}")
|
||||
|
||||
val kotlinType = context.bindingContext.getType(ktExpression) ?: throw AssertionError("No type for ${ktExpression.text}")
|
||||
|
||||
val operator = ktExpression.getDynamicOperator()
|
||||
|
||||
return IrDynamicOperatorExpressionImpl(
|
||||
ktExpression.startOffsetSkippingComments,
|
||||
ktExpression.endOffset,
|
||||
kotlinType.toIrType(),
|
||||
operator
|
||||
).apply {
|
||||
left = ktLeft.genExpr()
|
||||
right = ktRight.genExpr()
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateElvis(expression: KtBinaryExpression): IrExpression {
|
||||
val specialCallForElvis = getResolvedCall(expression)!!
|
||||
val resultType = specialCallForElvis.resultingDescriptor.returnType!!.toIrType()
|
||||
@@ -165,14 +208,23 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateBinaryBooleanOperator(expression: KtBinaryExpression, irOperator: IrStatementOrigin): IrExpression {
|
||||
val irArgument0 = expression.left!!.genExpr()
|
||||
val irArgument1 = expression.right!!.genExpr()
|
||||
private fun generateBinaryBooleanOperator(ktExpression: KtBinaryExpression, irOperator: IrStatementOrigin): IrExpression {
|
||||
if (isDynamicBinaryOperator(ktExpression)) return generateDynamicBinaryExpression(ktExpression)
|
||||
|
||||
val ktLeft = ktExpression.left ?: throw AssertionError("No LHS in ${ktExpression.text}")
|
||||
val ktRight = ktExpression.right ?: throw AssertionError("No RHS in ${ktExpression.text}")
|
||||
|
||||
val irArgument0 = ktLeft.genExpr()
|
||||
val irArgument1 = ktRight.genExpr()
|
||||
|
||||
val startOffset = ktExpression.startOffsetSkippingComments
|
||||
val endOffset = ktExpression.endOffset
|
||||
|
||||
return when (irOperator) {
|
||||
IrStatementOrigin.OROR ->
|
||||
context.oror(expression.startOffsetSkippingComments, expression.endOffset, irArgument0, irArgument1)
|
||||
context.oror(startOffset, endOffset, irArgument0, irArgument1)
|
||||
IrStatementOrigin.ANDAND ->
|
||||
context.andand(expression.startOffsetSkippingComments, expression.endOffset, irArgument0, irArgument1)
|
||||
context.andand(startOffset, endOffset, irArgument0, irArgument1)
|
||||
else ->
|
||||
throw AssertionError("Unexpected binary boolean operator $irOperator")
|
||||
}
|
||||
@@ -201,6 +253,8 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
|
||||
}
|
||||
|
||||
private fun generateIdentityOperator(expression: KtBinaryExpression, irOperator: IrStatementOrigin): IrExpression {
|
||||
if (isDynamicBinaryOperator(expression)) return generateDynamicBinaryExpression(expression)
|
||||
|
||||
val irArgument0 = expression.left!!.genExpr()
|
||||
val irArgument1 = expression.right!!.genExpr()
|
||||
|
||||
@@ -237,6 +291,8 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
|
||||
context.bindingContext[BindingContext.PRIMITIVE_NUMERIC_COMPARISON_INFO, ktExpression]
|
||||
|
||||
private fun generateEqualityOperator(expression: KtBinaryExpression, irOperator: IrStatementOrigin): IrExpression {
|
||||
if (isDynamicBinaryOperator(expression)) return generateDynamicBinaryExpression(expression)
|
||||
|
||||
val comparisonInfo = getPrimitiveNumericComparisonInfo(expression)
|
||||
val comparisonType = comparisonInfo?.comparisonType
|
||||
|
||||
@@ -356,11 +412,16 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
|
||||
return memberScope.findSingleFunction(Name.identifier("to$targetTypeName"))
|
||||
}
|
||||
|
||||
private fun generateComparisonOperator(expression: KtBinaryExpression, origin: IrStatementOrigin): IrExpression {
|
||||
val startOffset = expression.startOffsetSkippingComments
|
||||
val endOffset = expression.endOffset
|
||||
private fun generateComparisonOperator(ktExpression: KtBinaryExpression, origin: IrStatementOrigin): IrExpression {
|
||||
if (isDynamicBinaryOperator(ktExpression)) return generateDynamicBinaryExpression(ktExpression)
|
||||
|
||||
val comparisonInfo = getPrimitiveNumericComparisonInfo(expression)
|
||||
val startOffset = ktExpression.startOffsetSkippingComments
|
||||
val endOffset = ktExpression.endOffset
|
||||
|
||||
val comparisonInfo = getPrimitiveNumericComparisonInfo(ktExpression)
|
||||
|
||||
val ktLeft = ktExpression.left ?: throw AssertionError("No LHS in ${ktExpression.text}")
|
||||
val ktRight = ktExpression.right ?: throw AssertionError("No RHS in ${ktExpression.text}")
|
||||
|
||||
return if (comparisonInfo != null) {
|
||||
IrBinaryPrimitiveImpl(
|
||||
@@ -368,16 +429,19 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
|
||||
context.irBuiltIns.booleanType,
|
||||
origin,
|
||||
getComparisonOperatorSymbol(origin, comparisonInfo.comparisonType),
|
||||
expression.left!!.generateAsPrimitiveNumericComparisonOperand(comparisonInfo.leftType, comparisonInfo.comparisonType),
|
||||
expression.right!!.generateAsPrimitiveNumericComparisonOperand(comparisonInfo.rightType, comparisonInfo.comparisonType)
|
||||
ktLeft.generateAsPrimitiveNumericComparisonOperand(comparisonInfo.leftType, comparisonInfo.comparisonType),
|
||||
ktRight.generateAsPrimitiveNumericComparisonOperand(comparisonInfo.rightType, comparisonInfo.comparisonType)
|
||||
)
|
||||
} else {
|
||||
val resolvedCall = getResolvedCall(ktExpression)
|
||||
?: throw AssertionError("No resolved call for comparison operator ${ktExpression.text}")
|
||||
|
||||
IrBinaryPrimitiveImpl(
|
||||
startOffset, endOffset,
|
||||
context.irBuiltIns.booleanType,
|
||||
origin,
|
||||
getComparisonOperatorSymbol(origin, context.irBuiltIns.int),
|
||||
generateCall(getResolvedCall(expression)!!, expression, origin),
|
||||
generateCall(resolvedCall, ktExpression, origin),
|
||||
IrConstImpl.int(startOffset, endOffset, context.irBuiltIns.intType, 0)
|
||||
)
|
||||
}
|
||||
@@ -418,7 +482,10 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
|
||||
}
|
||||
|
||||
private fun generateBinaryOperatorAsCall(expression: KtBinaryExpression, origin: IrStatementOrigin?): IrExpression =
|
||||
generateCall(getResolvedCall(expression)!!, expression, origin)
|
||||
if (isDynamicBinaryOperator(expression))
|
||||
generateDynamicBinaryExpression(expression)
|
||||
else
|
||||
generateCall(getResolvedCall(expression)!!, expression, origin)
|
||||
|
||||
private fun generatePrefixOperatorAsCall(expression: KtPrefixExpression, origin: IrStatementOrigin): IrExpression {
|
||||
val resolvedCall = getResolvedCall(expression)!!
|
||||
@@ -432,6 +499,8 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
|
||||
}
|
||||
}
|
||||
|
||||
if (isDynamicUnaryOperator(expression)) return generateDynamicUnaryExpression(expression)
|
||||
|
||||
return generateCall(resolvedCall, expression, origin)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
fun testEqeq(d: dynamic) = d == 3
|
||||
fun testExclEq(d: dynamic) = d != 3
|
||||
fun testEqeqeq(d: dynamic) = d === 3
|
||||
fun testExclEqeq(d: dynamic) = d !== 3
|
||||
@@ -0,0 +1,29 @@
|
||||
FILE fqName:<root> fileName:/dynamicBinaryEqualityOperator.kt
|
||||
FUN name:testEqeq visibility:public modality:FINAL <> (d:dynamic) returnType:kotlin.Boolean flags:
|
||||
VALUE_PARAMETER name:d index:0 type:dynamic flags:
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='testEqeq(dynamic): Boolean'
|
||||
DYN_OP operator=EQEQ type=kotlin.Boolean
|
||||
receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||
0: CONST Int type=kotlin.Int value=3
|
||||
FUN name:testExclEq visibility:public modality:FINAL <> (d:dynamic) returnType:kotlin.Boolean flags:
|
||||
VALUE_PARAMETER name:d index:0 type:dynamic flags:
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='testExclEq(dynamic): Boolean'
|
||||
DYN_OP operator=EXCLEQ type=kotlin.Boolean
|
||||
receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||
0: CONST Int type=kotlin.Int value=3
|
||||
FUN name:testEqeqeq visibility:public modality:FINAL <> (d:dynamic) returnType:kotlin.Boolean flags:
|
||||
VALUE_PARAMETER name:d index:0 type:dynamic flags:
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='testEqeqeq(dynamic): Boolean'
|
||||
DYN_OP operator=EQEQEQ type=kotlin.Boolean
|
||||
receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||
0: CONST Int type=kotlin.Int value=3
|
||||
FUN name:testExclEqeq visibility:public modality:FINAL <> (d:dynamic) returnType:kotlin.Boolean flags:
|
||||
VALUE_PARAMETER name:d index:0 type:dynamic flags:
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='testExclEqeq(dynamic): Boolean'
|
||||
DYN_OP operator=EXCLEQEQ type=kotlin.Boolean
|
||||
receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||
0: CONST Int type=kotlin.Int value=3
|
||||
@@ -0,0 +1,2 @@
|
||||
fun testAndAnd(d: dynamic) = d && d
|
||||
fun testOrOr(d: dynamic) = d || d
|
||||
@@ -0,0 +1,15 @@
|
||||
FILE fqName:<root> fileName:/dynamicBinaryLogicalOperator.kt
|
||||
FUN name:testAndAnd visibility:public modality:FINAL <> (d:dynamic) returnType:kotlin.Boolean flags:
|
||||
VALUE_PARAMETER name:d index:0 type:dynamic flags:
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='testAndAnd(dynamic): Boolean'
|
||||
DYN_OP operator=ANDAND type=kotlin.Boolean
|
||||
receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||
0: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||
FUN name:testOrOr visibility:public modality:FINAL <> (d:dynamic) returnType:kotlin.Boolean flags:
|
||||
VALUE_PARAMETER name:d index:0 type:dynamic flags:
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='testOrOr(dynamic): Boolean'
|
||||
DYN_OP operator=OROR type=kotlin.Boolean
|
||||
receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||
0: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||
@@ -0,0 +1,5 @@
|
||||
fun testBinaryPlus(d: dynamic) = d + 1
|
||||
fun testBinaryMinus(d: dynamic) = d - 1
|
||||
fun testMul(d: dynamic) = d * 2
|
||||
fun testDiv(d: dynamic) = d / 2
|
||||
fun testMod(d: dynamic) = d % 2
|
||||
@@ -0,0 +1,36 @@
|
||||
FILE fqName:<root> fileName:/dynamicBinaryOperator.kt
|
||||
FUN name:testBinaryPlus 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='testBinaryPlus(dynamic): dynamic'
|
||||
DYN_OP operator=BINARY_PLUS type=dynamic
|
||||
receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||
0: CONST Int type=kotlin.Int value=1
|
||||
FUN name:testBinaryMinus 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='testBinaryMinus(dynamic): dynamic'
|
||||
DYN_OP operator=BINARY_MINUS type=dynamic
|
||||
receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||
0: CONST Int type=kotlin.Int value=1
|
||||
FUN name:testMul 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='testMul(dynamic): dynamic'
|
||||
DYN_OP operator=MUL type=dynamic
|
||||
receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||
0: CONST Int type=kotlin.Int value=2
|
||||
FUN name:testDiv 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='testDiv(dynamic): dynamic'
|
||||
DYN_OP operator=DIV type=dynamic
|
||||
receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||
0: CONST Int type=kotlin.Int value=2
|
||||
FUN name:testMod 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='testMod(dynamic): dynamic'
|
||||
DYN_OP operator=MOD type=dynamic
|
||||
receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||
0: CONST Int type=kotlin.Int value=2
|
||||
@@ -0,0 +1,4 @@
|
||||
fun testLess(d: dynamic) = d < 2
|
||||
fun testLessOrEqual(d: dynamic) = d <= 2
|
||||
fun testGreater(d: dynamic) = d > 2
|
||||
fun testGreaterOrEqual(d: dynamic) = d >= 2
|
||||
@@ -0,0 +1,29 @@
|
||||
FILE fqName:<root> fileName:/dynamicBinaryRelationalOperator.kt
|
||||
FUN name:testLess visibility:public modality:FINAL <> (d:dynamic) returnType:kotlin.Boolean flags:
|
||||
VALUE_PARAMETER name:d index:0 type:dynamic flags:
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='testLess(dynamic): Boolean'
|
||||
DYN_OP operator=LT type=kotlin.Boolean
|
||||
receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||
0: CONST Int type=kotlin.Int value=2
|
||||
FUN name:testLessOrEqual visibility:public modality:FINAL <> (d:dynamic) returnType:kotlin.Boolean flags:
|
||||
VALUE_PARAMETER name:d index:0 type:dynamic flags:
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='testLessOrEqual(dynamic): Boolean'
|
||||
DYN_OP operator=LE type=kotlin.Boolean
|
||||
receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||
0: CONST Int type=kotlin.Int value=2
|
||||
FUN name:testGreater visibility:public modality:FINAL <> (d:dynamic) returnType:kotlin.Boolean flags:
|
||||
VALUE_PARAMETER name:d index:0 type:dynamic flags:
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='testGreater(dynamic): Boolean'
|
||||
DYN_OP operator=GT type=kotlin.Boolean
|
||||
receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||
0: CONST Int type=kotlin.Int value=2
|
||||
FUN name:testGreaterOrEqual visibility:public modality:FINAL <> (d:dynamic) returnType:kotlin.Boolean flags:
|
||||
VALUE_PARAMETER name:d index:0 type:dynamic flags:
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='testGreaterOrEqual(dynamic): Boolean'
|
||||
DYN_OP operator=GE type=kotlin.Boolean
|
||||
receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||
0: CONST Int type=kotlin.Int value=2
|
||||
@@ -0,0 +1,3 @@
|
||||
fun testUnaryMinus(d: dynamic) = -d
|
||||
fun testUnaryPlus(d: dynamic) = +d
|
||||
fun testExcl(d: dynamic) = !d
|
||||
@@ -0,0 +1,19 @@
|
||||
FILE fqName:<root> fileName:/dynamicUnaryOperator.kt
|
||||
FUN name:testUnaryMinus 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='testUnaryMinus(dynamic): dynamic'
|
||||
DYN_OP operator=UNARY_MINUS type=dynamic
|
||||
receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||
FUN name:testUnaryPlus 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='testUnaryPlus(dynamic): dynamic'
|
||||
DYN_OP operator=UNARY_PLUS type=dynamic
|
||||
receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||
FUN name:testExcl 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='testExcl(dynamic): dynamic'
|
||||
DYN_OP operator=EXCL type=dynamic
|
||||
receiver: GET_VAR 'value-parameter d: dynamic' type=dynamic origin=null
|
||||
@@ -66,6 +66,26 @@ public class IrJsTextTestCaseGenerated extends AbstractIrJsTextTestCase {
|
||||
runTest("compiler/testData/ir/irJsText/dynamic/dynamicArrayIncrementDecrement.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("dynamicBinaryEqualityOperator.kt")
|
||||
public void testDynamicBinaryEqualityOperator() throws Exception {
|
||||
runTest("compiler/testData/ir/irJsText/dynamic/dynamicBinaryEqualityOperator.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("dynamicBinaryLogicalOperator.kt")
|
||||
public void testDynamicBinaryLogicalOperator() throws Exception {
|
||||
runTest("compiler/testData/ir/irJsText/dynamic/dynamicBinaryLogicalOperator.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("dynamicBinaryOperator.kt")
|
||||
public void testDynamicBinaryOperator() throws Exception {
|
||||
runTest("compiler/testData/ir/irJsText/dynamic/dynamicBinaryOperator.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("dynamicBinaryRelationalOperator.kt")
|
||||
public void testDynamicBinaryRelationalOperator() throws Exception {
|
||||
runTest("compiler/testData/ir/irJsText/dynamic/dynamicBinaryRelationalOperator.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("dynamicCall.kt")
|
||||
public void testDynamicCall() throws Exception {
|
||||
runTest("compiler/testData/ir/irJsText/dynamic/dynamicCall.kt");
|
||||
@@ -91,6 +111,11 @@ public class IrJsTextTestCaseGenerated extends AbstractIrJsTextTestCase {
|
||||
runTest("compiler/testData/ir/irJsText/dynamic/dynamicMemberIncrementDecrement.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("dynamicUnaryOperator.kt")
|
||||
public void testDynamicUnaryOperator() throws Exception {
|
||||
runTest("compiler/testData/ir/irJsText/dynamic/dynamicUnaryOperator.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("dynamicWithImplicitCast.kt")
|
||||
public void testDynamicWithImplicitCast() throws Exception {
|
||||
runTest("compiler/testData/ir/irJsText/dynamic/dynamicWithImplicitCast.kt");
|
||||
|
||||
Reference in New Issue
Block a user