diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt index 448b0112ea9..ab418920595 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ArgumentsGenerationUtils.kt @@ -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 -> diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt index b8e9bf02c9c..80ab0acf25f 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/CallGenerator.kt @@ -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 diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DynamicCalls.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DynamicCalls.kt new file mode 100644 index 00000000000..9c918dd7cf4 --- /dev/null +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DynamicCalls.kt @@ -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") + } +} \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt index d77def6d51a..2ce2dcab678 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/OperatorExpressionGenerator.kt @@ -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) } diff --git a/compiler/testData/ir/irJsText/dynamic/dynamicBinaryEqualityOperator.kt b/compiler/testData/ir/irJsText/dynamic/dynamicBinaryEqualityOperator.kt new file mode 100644 index 00000000000..51f0399c277 --- /dev/null +++ b/compiler/testData/ir/irJsText/dynamic/dynamicBinaryEqualityOperator.kt @@ -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 diff --git a/compiler/testData/ir/irJsText/dynamic/dynamicBinaryEqualityOperator.txt b/compiler/testData/ir/irJsText/dynamic/dynamicBinaryEqualityOperator.txt new file mode 100644 index 00000000000..42dd24e330e --- /dev/null +++ b/compiler/testData/ir/irJsText/dynamic/dynamicBinaryEqualityOperator.txt @@ -0,0 +1,29 @@ +FILE fqName: 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 diff --git a/compiler/testData/ir/irJsText/dynamic/dynamicBinaryLogicalOperator.kt b/compiler/testData/ir/irJsText/dynamic/dynamicBinaryLogicalOperator.kt new file mode 100644 index 00000000000..48409698c97 --- /dev/null +++ b/compiler/testData/ir/irJsText/dynamic/dynamicBinaryLogicalOperator.kt @@ -0,0 +1,2 @@ +fun testAndAnd(d: dynamic) = d && d +fun testOrOr(d: dynamic) = d || d diff --git a/compiler/testData/ir/irJsText/dynamic/dynamicBinaryLogicalOperator.txt b/compiler/testData/ir/irJsText/dynamic/dynamicBinaryLogicalOperator.txt new file mode 100644 index 00000000000..7d933b396ed --- /dev/null +++ b/compiler/testData/ir/irJsText/dynamic/dynamicBinaryLogicalOperator.txt @@ -0,0 +1,15 @@ +FILE fqName: 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 diff --git a/compiler/testData/ir/irJsText/dynamic/dynamicBinaryOperator.kt b/compiler/testData/ir/irJsText/dynamic/dynamicBinaryOperator.kt new file mode 100644 index 00000000000..7b8e1ae89fa --- /dev/null +++ b/compiler/testData/ir/irJsText/dynamic/dynamicBinaryOperator.kt @@ -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 diff --git a/compiler/testData/ir/irJsText/dynamic/dynamicBinaryOperator.txt b/compiler/testData/ir/irJsText/dynamic/dynamicBinaryOperator.txt new file mode 100644 index 00000000000..5c8983eaf33 --- /dev/null +++ b/compiler/testData/ir/irJsText/dynamic/dynamicBinaryOperator.txt @@ -0,0 +1,36 @@ +FILE fqName: 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 diff --git a/compiler/testData/ir/irJsText/dynamic/dynamicBinaryRelationalOperator.kt b/compiler/testData/ir/irJsText/dynamic/dynamicBinaryRelationalOperator.kt new file mode 100644 index 00000000000..2827598766b --- /dev/null +++ b/compiler/testData/ir/irJsText/dynamic/dynamicBinaryRelationalOperator.kt @@ -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 \ No newline at end of file diff --git a/compiler/testData/ir/irJsText/dynamic/dynamicBinaryRelationalOperator.txt b/compiler/testData/ir/irJsText/dynamic/dynamicBinaryRelationalOperator.txt new file mode 100644 index 00000000000..4f9a5542bf1 --- /dev/null +++ b/compiler/testData/ir/irJsText/dynamic/dynamicBinaryRelationalOperator.txt @@ -0,0 +1,29 @@ +FILE fqName: 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 diff --git a/compiler/testData/ir/irJsText/dynamic/dynamicUnaryOperator.kt b/compiler/testData/ir/irJsText/dynamic/dynamicUnaryOperator.kt new file mode 100644 index 00000000000..9d4240a1f01 --- /dev/null +++ b/compiler/testData/ir/irJsText/dynamic/dynamicUnaryOperator.kt @@ -0,0 +1,3 @@ +fun testUnaryMinus(d: dynamic) = -d +fun testUnaryPlus(d: dynamic) = +d +fun testExcl(d: dynamic) = !d \ No newline at end of file diff --git a/compiler/testData/ir/irJsText/dynamic/dynamicUnaryOperator.txt b/compiler/testData/ir/irJsText/dynamic/dynamicUnaryOperator.txt new file mode 100644 index 00000000000..a1a276bea6a --- /dev/null +++ b/compiler/testData/ir/irJsText/dynamic/dynamicUnaryOperator.txt @@ -0,0 +1,19 @@ +FILE fqName: 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 diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrJsTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrJsTextTestCaseGenerated.java index 5b1ab3342b5..0cc6feb56a6 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrJsTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrJsTextTestCaseGenerated.java @@ -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");