diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrUtils.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrUtils.kt index f28e4383e2a..bce1966c8fb 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrUtils.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrUtils.kt @@ -23,24 +23,5 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.checker.KotlinTypeChecker import org.jetbrains.kotlin.types.isNullabilityFlexible -fun IrExpression.toExpectedType(expectedType: KotlinType?): IrExpression { - if (expectedType == null) return this - if (KotlinBuiltIns.isUnit(expectedType)) return this // TODO expose coercion to Unit in IR? - - val valueType = type ?: throw AssertionError("expectedType != null, valueType == null: $this") - - if (valueType.isNullabilityFlexible() && !expectedType.isMarkedNullable) { - return IrUnaryOperatorExpressionImpl(startOffset, endOffset, expectedType, - IrOperator.IMPLICIT_NOTNULL, null, this) - } - - if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType, expectedType)) { - return IrTypeOperatorExpressionImpl(startOffset, endOffset, expectedType, - IrTypeOperator.IMPLICIT_CAST, expectedType, this) - } - - return this -} - -fun IrVariable.load(): IrExpression = - IrGetVariableExpressionImpl(startOffset, endOffset, descriptor) \ No newline at end of file +fun IrVariable.defaultLoad(): IrExpression = + IrGetVariableImpl(startOffset, endOffset, descriptor) \ No newline at end of file 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 f4bcef01b73..99e79b4015f 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 @@ -17,77 +17,18 @@ package org.jetbrains.kotlin.psi2ir.generators import org.jetbrains.kotlin.descriptors.* -import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.expressions.* 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.startOffset -import org.jetbrains.kotlin.psi2ir.generators.values.VariableLValue -import org.jetbrains.kotlin.psi2ir.generators.values.IrValue -import org.jetbrains.kotlin.psi2ir.generators.values.createRematerializableValue -import org.jetbrains.kotlin.psi2ir.toExpectedType import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.scopes.receivers.* import org.jetbrains.kotlin.types.KotlinType import java.util.* -class CallGenerator(val statementGenerator: StatementGenerator) : IrGenerator { - override val context: GeneratorContext get() = - statementGenerator.context - - private val temporaryVariableFactory: TemporaryVariableFactory get() = - statementGenerator.temporaryVariableFactory - - private val expressionValues = HashMap() - private val receiverValues = HashMap() - private val valueArgumentValues = HashMap() - - fun introduceTemporary(ktExpression: KtExpression, irExpression: IrExpression, nameHint: String? = null): IrVariable? { - val rematerializable = createRematerializableValue(irExpression) - if (rematerializable != null) { - putValue(ktExpression, rematerializable) - return null - } - - return createTemporary(ktExpression, irExpression, nameHint) - } - - fun createTemporary(ktExpression: KtExpression, irExpression: IrExpression, nameHint: String?): IrVariable { - val irTmpVar = temporaryVariableFactory.createTemporaryVariable(irExpression, nameHint) - putValue(ktExpression, VariableLValue(irTmpVar)) - return irTmpVar - } - - fun introduceTemporary(valueParameterDescriptor: ValueParameterDescriptor, irExpression: IrExpression): IrVariable? { - val rematerializable = createRematerializableValue(irExpression) - if (rematerializable != null) { - putValue(valueParameterDescriptor, rematerializable) - return null - } - - val irTmpVar = temporaryVariableFactory.createTemporaryVariable(irExpression, valueParameterDescriptor.name.asString()) - putValue(valueParameterDescriptor, VariableLValue(irTmpVar)) - return irTmpVar - } - - fun putValue(ktExpression: KtExpression, irValue: IrValue) { - expressionValues[ktExpression] = irValue - } - - fun putValue(receiver: ReceiverValue, irValue: IrValue) { - receiverValues[receiver] = irValue - } - - fun putValue(parameter: ValueParameterDescriptor, irValue: IrValue) { - valueArgumentValues[parameter] = irValue - } - - fun valueOf(ktExpression: KtExpression) = expressionValues[ktExpression]?.load() - fun valueOf(receiver: ReceiverValue) = receiverValues[receiver]?.load() - fun valueOf(parameter: ValueParameterDescriptor) = valueArgumentValues[parameter]?.load() - +class CallGenerator(statementGenerator: StatementGenerator) : IrChildBodyGeneratorBase(statementGenerator) { fun generateCall( ktElement: KtElement, resolvedCall: ResolvedCall, @@ -110,13 +51,13 @@ class CallGenerator(val statementGenerator: StatementGenerator) : IrGenerator { descriptor: PropertyDescriptor, ktElement: KtElement, resolvedCall: ResolvedCall<*> - ): IrGetterCallExpressionImpl { + ): IrGetterCallImpl { val returnType = getReturnType(resolvedCall) val dispatchReceiver = generateReceiver(ktElement, resolvedCall.dispatchReceiver, descriptor.dispatchReceiverParameter) val extensionReceiver = generateReceiver(ktElement, resolvedCall.extensionReceiver, descriptor.extensionReceiverParameter) - return IrGetterCallExpressionImpl(ktElement.startOffset, ktElement.endOffset, - returnType, descriptor.getter!!, resolvedCall.call.isSafeCall(), - dispatchReceiver, extensionReceiver, IrOperator.GET_PROPERTY) + return IrGetterCallImpl(ktElement.startOffset, ktElement.endOffset, + returnType, descriptor.getter!!, resolvedCall.call.isSafeCall(), + dispatchReceiver, extensionReceiver, IrOperator.GET_PROPERTY) } private fun ResolvedCall<*>.requiresArgumentReordering(): Boolean { @@ -142,7 +83,7 @@ class CallGenerator(val statementGenerator: StatementGenerator) : IrGenerator { ): IrExpression { val returnType = descriptor.returnType - val irCall = IrCallExpressionImpl( + val irCall = IrCallImpl( ktElement.startOffset, ktElement.endOffset, returnType, descriptor, resolvedCall.call.isSafeCall(), operator, superQualifier ) @@ -166,7 +107,7 @@ class CallGenerator(val statementGenerator: StatementGenerator) : IrGenerator { } private fun generateCallWithArgumentReordering( - irCall: IrCallExpression, + irCall: IrCall, ktElement: KtElement, resolvedCall: ResolvedCall, resultType: KotlinType? @@ -177,8 +118,8 @@ class CallGenerator(val statementGenerator: StatementGenerator) : IrGenerator { val valueParameters = resolvedCall.resultingDescriptor.valueParameters val hasResult = isUsedAsExpression(ktElement) - val irBlock = IrBlockExpressionImpl(ktElement.startOffset, ktElement.endOffset, resultType, hasResult, - IrOperator.SYNTHETIC_BLOCK) + val irBlock = IrBlockImpl(ktElement.startOffset, ktElement.endOffset, resultType, hasResult, + IrOperator.SYNTHETIC_BLOCK) val valueArgumentsToValueParameters = HashMap() for ((index, valueArgument) in resolvedCall.valueArgumentsByIndex!!.withIndex()) { @@ -186,17 +127,19 @@ class CallGenerator(val statementGenerator: StatementGenerator) : IrGenerator { valueArgumentsToValueParameters[valueArgument] = valueParameter } + val reorderingScope = Scope(this.scope) + for (valueArgument in valueArgumentsInEvaluationOrder) { val valueParameter = valueArgumentsToValueParameters[valueArgument]!! val irArgument = generateValueArgument(valueArgument, valueParameter) ?: continue - val irTmpArg = introduceTemporary(valueParameter, irArgument) + val irTmpArg = reorderingScope.introduceTemporary(valueParameter, irArgument) irBlock.addIfNotNull(irTmpArg) } for ((index, valueArgument) in resolvedCall.valueArgumentsByIndex!!.withIndex()) { val valueParameter = valueParameters[index] - val irGetTemporary = valueArgumentValues[valueParameter]!!.load() - irCall.putArgument(index, irGetTemporary.toExpectedType(valueParameter.type)) + val irGetTemporary = reorderingScope.valueOf(valueParameter)!! + irCall.putArgument(index, toExpectedType(irGetTemporary, valueParameter.type)) } irBlock.addStatement(irCall) @@ -208,30 +151,30 @@ class CallGenerator(val statementGenerator: StatementGenerator) : IrGenerator { generateReceiver(ktElement, receiver, receiverParameterDescriptor?.type) fun generateReceiver(ktElement: KtElement, receiver: ReceiverValue?, expectedType: KotlinType?) = - generateReceiver(ktElement, receiver)?.toExpectedType(expectedType) + toExpectedTypeOrNull(generateReceiver(ktElement, receiver), expectedType) fun generateReceiver(ktElement: KtElement, receiver: ReceiverValue?): IrExpression? = if (receiver == null) null else - receiverValues[receiver]?.load() ?: doGenerateReceiver(ktElement, receiver) + scope.valueOf(receiver) ?: doGenerateReceiver(ktElement, receiver) fun doGenerateReceiver(ktElement: KtElement, receiver: ReceiverValue?): IrExpression? = when (receiver) { is ImplicitClassReceiver -> - IrThisExpressionImpl(ktElement.startOffset, ktElement.startOffset, receiver.type, receiver.classDescriptor) + IrThisReferenceImpl(ktElement.startOffset, ktElement.startOffset, receiver.type, receiver.classDescriptor) is ThisClassReceiver -> (receiver as? ExpressionReceiver)?.expression?.let { receiverExpression -> - IrThisExpressionImpl(receiverExpression.startOffset, receiverExpression.endOffset, receiver.type, receiver.classDescriptor) + IrThisReferenceImpl(receiverExpression.startOffset, receiverExpression.endOffset, receiver.type, receiver.classDescriptor) } ?: TODO("Non-implicit ThisClassReceiver should be an expression receiver") is ExpressionReceiver -> generateExpression(receiver.expression) is ClassValueReceiver -> - IrGetObjectValueExpressionImpl(receiver.expression.startOffset, receiver.expression.endOffset, receiver.type, - receiver.classQualifier.descriptor) + IrGetObjectValueImpl(receiver.expression.startOffset, receiver.expression.endOffset, receiver.type, + receiver.classQualifier.descriptor) is ExtensionReceiver -> - IrGetExtensionReceiverExpressionImpl(ktElement.startOffset, ktElement.startOffset, receiver.type, - receiver.declarationDescriptor.extensionReceiverParameter!!) + IrGetExtensionReceiverImpl(ktElement.startOffset, ktElement.startOffset, receiver.type, + receiver.declarationDescriptor.extensionReceiverParameter!!) null -> null else -> @@ -245,13 +188,13 @@ class CallGenerator(val statementGenerator: StatementGenerator) : IrGenerator { if (valueParameterDescriptor.varargElementType != null) doGenerateValueArgument(valueArgument, valueParameterDescriptor) else - doGenerateValueArgument(valueArgument, valueParameterDescriptor)?.toExpectedType(expectedType) + toExpectedTypeOrNull(doGenerateValueArgument(valueArgument, valueParameterDescriptor), expectedType) private fun doGenerateValueArgument(valueArgument: ResolvedValueArgument, valueParameterDescriptor: ValueParameterDescriptor): IrExpression? = if (valueArgument is DefaultValueArgument) null else - valueArgumentValues[valueParameterDescriptor]?.load() ?: doGenerateValueArgument(valueArgument) + scope.valueOf(valueParameterDescriptor) ?: doGenerateValueArgument(valueArgument) private fun doGenerateValueArgument(valueArgument: ResolvedValueArgument): IrExpression? = when (valueArgument) { @@ -264,6 +207,6 @@ class CallGenerator(val statementGenerator: StatementGenerator) : IrGenerator { } private fun generateExpression(ktExpression: KtExpression): IrExpression = - expressionValues[ktExpression]?.load() ?: statementGenerator.generateExpression(ktExpression) + scope.valueOf(ktExpression) ?: parentGenerator.generateExpression(ktExpression) } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt index 8d4ea34b2b6..715040b23e1 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/DeclarationGenerator.kt @@ -64,20 +64,6 @@ class DeclarationGenerator(override val context: GeneratorContext) : IrGenerator return createFunction(ktNamedFunction, functionDescriptor, body) } - fun generateLocalVariable(scopeOwner: DeclarationDescriptor, ktProperty: KtProperty): IrVariable { - if (ktProperty.delegateExpression != null) TODO("Local delegated property") - - val variableDescriptor = getOrFail(BindingContext.VARIABLE, ktProperty) - - val irLocalVariable = IrVariableImpl(ktProperty.startOffset, ktProperty.endOffset, IrDeclarationOriginKind.DEFINED, variableDescriptor) - - irLocalVariable.initializer = ktProperty.initializer?.let { - generateExpressionWithinContext(it, scopeOwner) - } - - return irLocalVariable - } - fun generatePropertyDeclaration(ktProperty: KtProperty): IrProperty { val propertyDescriptor = getPropertyDescriptor(ktProperty) if (ktProperty.hasDelegate()) TODO("handle delegated property") @@ -135,22 +121,11 @@ class DeclarationGenerator(override val context: GeneratorContext) : IrGenerator return propertyDescriptor } - private fun generateExpressionWithinContext(ktExpression: KtExpression, scopeOwner: DeclarationDescriptor): IrExpression = - FunctionBodyGenerator(context).generateFunctionBody(scopeOwner, ktExpression) - - private fun generateFunctionBody(scopeOwner: CallableDescriptor, ktBody: KtExpression): IrBody { - val irRhs = generateExpressionWithinContext(ktBody, scopeOwner) - val irExpressionBody = - if (ktBody is KtBlockExpression) - irRhs - else - IrBlockExpressionImpl(ktBody.startOffset, ktBody.endOffset, null, false).apply { - addStatement(IrReturnExpressionImpl(ktBody.startOffset, ktBody.endOffset, scopeOwner, irRhs)) - } - return IrExpressionBodyImpl(ktBody.startOffset, ktBody.endOffset, irExpressionBody) - } - - private fun generateInitializerBody(scopeOwner: DeclarationDescriptor, ktBody: KtExpression): IrBody = + private fun generateFunctionBody(scopeOwner: CallableDescriptor, ktBody: KtExpression): IrBody = IrExpressionBodyImpl(ktBody.startOffset, ktBody.endOffset, - generateExpressionWithinContext(ktBody, scopeOwner)) + ExoressionBodyGenerator(scopeOwner, context).generateFunctionBody(ktBody)) + + private fun generateInitializerBody(scopeOwner: CallableDescriptor, ktBody: KtExpression): IrBody = + IrExpressionBodyImpl(ktBody.startOffset, ktBody.endOffset, + ExoressionBodyGenerator(scopeOwner, context).generatePropertyInitializerBody(ktBody)) } \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ExoressionBodyGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ExoressionBodyGenerator.kt new file mode 100644 index 00000000000..15cb53116c0 --- /dev/null +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/ExoressionBodyGenerator.kt @@ -0,0 +1,60 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.psi2ir.generators + +import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.ir.expressions.IrBlockImpl +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrReturnImpl +import org.jetbrains.kotlin.psi.KtBlockExpression +import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.psi.psiUtil.endOffset +import org.jetbrains.kotlin.psi.psiUtil.startOffset + +class ExoressionBodyGenerator(val scopeOwner: CallableDescriptor, override val context: GeneratorContext): IrBodyGenerator { + override val scope = Scope.rootScope(scopeOwner, this) + + fun generateFunctionBody(ktBody: KtExpression): IrExpression { + resetInternalContext() + + val irBodyExpression = createStatementGenerator().generateExpressionWithExpectedType(ktBody, scopeOwner.returnType) + + val irBodyExpressionAsBlock = + if (ktBody is KtBlockExpression) + irBodyExpression + else IrBlockImpl(ktBody.startOffset, ktBody.endOffset, null, false).apply { + addStatement(IrReturnImpl(ktBody.startOffset, ktBody.endOffset, scopeOwner, irBodyExpression)) + } + + postprocessFunctionBody() + + return irBodyExpressionAsBlock + } + + private fun resetInternalContext() { + } + + private fun postprocessFunctionBody() { + } + + fun generatePropertyInitializerBody(ktInitializer: KtExpression): IrExpression = + createStatementGenerator().generateExpressionWithExpectedType(ktInitializer, scopeOwner.returnType!!) + + private fun createStatementGenerator() = + StatementGenerator(context, scopeOwner, this, scope) +} + diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionBodyGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionBodyGenerator.kt deleted file mode 100644 index 1c887ce8bf0..00000000000 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/FunctionBodyGenerator.kt +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2010-2016 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.psi2ir.generators - -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor -import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.kotlin.psi2ir.toExpectedType - -class FunctionBodyGenerator(override val context: GeneratorContext): IrGenerator { - fun generateFunctionBody(scopeOwner: DeclarationDescriptor, ktExpression: KtExpression): IrExpression { - resetInternalContext() - val irExpression = StatementGenerator(context, scopeOwner, this) - .generateExpression(ktExpression) - .toExpectedType(getExpectedTypeForLastInferredCall(ktExpression)) - postprocessFunctionBody() - return irExpression - } - - private fun resetInternalContext() { - } - - private fun postprocessFunctionBody() { - } -} - diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrBlockBuilder.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrBlockBuilder.kt new file mode 100644 index 00000000000..87410b336b3 --- /dev/null +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrBlockBuilder.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.psi2ir.generators + +import org.jetbrains.kotlin.ir.IrStatement +import org.jetbrains.kotlin.ir.expressions.IrBlockImpl +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.ir.expressions.IrOperator +import org.jetbrains.kotlin.psi.KtElement +import org.jetbrains.kotlin.psi.psiUtil.endOffset +import org.jetbrains.kotlin.psi.psiUtil.startOffset +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.utils.SmartList + +class IrBlockBuilder(val startOffset: Int, val endOffset: Int, val irOperator: IrOperator, val generator: IrBodyGenerator) { + private val statements = SmartList() + private var resultType: KotlinType? = null + private var hasResult = false + val scope: Scope get() = generator.scope + + fun add(irStatement: T): T { + if (irStatement != null) { + statements.add(irStatement) + } + return irStatement + } + + fun result(irExpression: T): T { + resultType = irExpression.type + hasResult = true + return irExpression + } + + fun build() = + if (statements.size == 1) + statements[0] + else + IrBlockImpl(startOffset, endOffset, resultType, hasResult, irOperator).apply { + statements.forEach { addStatement(it) } + } +} + +fun IrBodyGenerator.block(ktElement: KtElement, irOperator: IrOperator, body: IrBlockBuilder.() -> Unit) = + IrBlockBuilder(ktElement.startOffset, ktElement.endOffset, irOperator, this).apply(body).build() + +fun IrBodyGenerator.block(irExpression: IrExpression, irOperator: IrOperator, body: IrBlockBuilder.() -> Unit) = + IrBlockBuilder(irExpression.startOffset, irExpression.endOffset, irOperator, this).apply(body).build() \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrBodyGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrBodyGenerator.kt new file mode 100644 index 00000000000..1a68ed4cb54 --- /dev/null +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrBodyGenerator.kt @@ -0,0 +1,61 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.psi2ir.generators + +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.checker.KotlinTypeChecker +import org.jetbrains.kotlin.types.isNullabilityFlexible + +interface IrBodyGenerator : IrGenerator { + val scope: Scope +} + +abstract class IrChildBodyGeneratorBase(val parentGenerator: T) : IrBodyGenerator { + override val context: GeneratorContext get() = parentGenerator.context + override val scope: Scope get() = parentGenerator.scope +} + +fun IrBodyGenerator.toExpectedType(irExpression: IrExpression, expectedType: KotlinType?): IrExpression { + if (irExpression is IrBlock && !irExpression.hasResult) return irExpression + + if (expectedType == null) return irExpression + if (KotlinBuiltIns.isUnit(expectedType)) return irExpression // TODO expose coercion to Unit in IR? + + val valueType = irExpression.type ?: throw AssertionError("expectedType != null, valueType == null: $this") + + if (valueType.isNullabilityFlexible() && !expectedType.isMarkedNullable) { + return IrUnaryOperatorImpl(irExpression.startOffset, irExpression.endOffset, IrOperator.IMPLICIT_NOTNULL, + context.irBuiltIns.implicitNotNull, + irExpression) + } + + if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(valueType, expectedType)) { + return IrTypeOperatorCallImpl(irExpression.startOffset, irExpression.endOffset, expectedType, + IrTypeOperator.IMPLICIT_CAST, expectedType, irExpression) + } + + return irExpression +} + +fun StatementGenerator.generateExpressionWithExpectedType(ktExpression: KtExpression, expectedType: KotlinType?) = + toExpectedType(generateExpression(ktExpression), expectedType) + +fun IrBodyGenerator.toExpectedTypeOrNull(irExpression: IrExpression?, expectedType: KotlinType?): IrExpression? = + irExpression?.let { toExpectedType(it, expectedType) } \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrGenerator.kt index 2496b11e2cf..88775fcbec9 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/IrGenerator.kt @@ -32,6 +32,8 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.typeUtil.makeNullable import org.jetbrains.kotlin.util.slicedMap.ReadOnlySlice +import java.lang.AssertionError +import java.lang.RuntimeException interface IrGenerator { val context: GeneratorContext 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 5ee1dda9124..3a3119951a7 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 @@ -16,8 +16,6 @@ package org.jetbrains.kotlin.psi2ir.generators -import org.jetbrains.kotlin.builtins.KotlinBuiltIns -import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.ir.IrStatement @@ -26,17 +24,15 @@ import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset +import org.jetbrains.kotlin.psi2ir.defaultLoad import org.jetbrains.kotlin.psi2ir.generators.values.* -import org.jetbrains.kotlin.psi2ir.load -import org.jetbrains.kotlin.psi2ir.toExpectedType import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall import org.jetbrains.kotlin.types.typeUtil.makeNullable +import java.lang.AssertionError -class OperatorExpressionGenerator(val statementGenerator: StatementGenerator): IrGenerator { - override val context: GeneratorContext get() = statementGenerator.context - +class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : IrChildBodyGeneratorBase(statementGenerator) { fun generatePrefixExpression(expression: KtPrefixExpression): IrExpression { val ktOperator = expression.operationReference.getReferencedNameElementType() val irOperator = getIrPrefixOperator(ktOperator) @@ -66,8 +62,8 @@ class OperatorExpressionGenerator(val statementGenerator: StatementGenerator): I throw AssertionError("Unexpected IrTypeOperator: $irOperator") } - return IrTypeOperatorExpressionImpl(expression.startOffset, expression.endOffset, resultType, irOperator, rhsType, - statementGenerator.generateExpression(expression.left)) + return IrTypeOperatorCallImpl(expression.startOffset, expression.endOffset, resultType, irOperator, rhsType, + parentGenerator.generateExpression(expression.left)) } fun generateInstanceOfExpression(expression: KtIsExpression): IrStatement { @@ -75,8 +71,8 @@ class OperatorExpressionGenerator(val statementGenerator: StatementGenerator): I val irOperator = getIrTypeOperator(ktOperator)!! val againstType = getOrFail(BindingContext.TYPE, expression.typeReference) - return IrTypeOperatorExpressionImpl(expression.startOffset, expression.endOffset, context.builtIns.booleanType, irOperator, - againstType, statementGenerator.generateExpression(expression.leftHandSide)) + return IrTypeOperatorCallImpl(expression.startOffset, expression.endOffset, context.builtIns.booleanType, irOperator, + againstType, parentGenerator.generateExpression(expression.leftHandSide)) } fun generateBinaryExpression(expression: KtBinaryExpression): IrExpression { @@ -103,105 +99,108 @@ class OperatorExpressionGenerator(val statementGenerator: StatementGenerator): I } private fun generateElvis(expression: KtBinaryExpression): IrExpression { - // TODO desugar '?:' to 'if'? + // TODO desugar '?:' to 'if' val specialCallForElvis = getResolvedCall(expression)!! val returnType = specialCallForElvis.resultingDescriptor.returnType!! - val irArgument0 = statementGenerator.generateExpression(expression.left!!).toExpectedType(returnType.makeNullable()) - val irArgument1 = statementGenerator.generateExpression(expression.right!!).toExpectedType(returnType) - return IrBinaryOperatorExpressionImpl( - expression.startOffset, expression.endOffset, returnType, - IrOperator.ELVIS, null, irArgument0, irArgument1 - ) + val irArgument0 = toExpectedType(parentGenerator.generateExpression(expression.left!!), returnType.makeNullable()) + val irArgument1 = toExpectedType(parentGenerator.generateExpression(expression.right!!), returnType) +// return IrBinaryOperatorImpl( +// expression.startOffset, expression.endOffset, returnType, +// IrOperator.ELVIS, null, irArgument0, irArgument1 +// ) + return createDummyExpression(expression, "elvis") } private fun generateBinaryBooleanOperator(expression: KtBinaryExpression, irOperator: IrOperator): IrExpression { - val irArgument0 = statementGenerator.generateExpression(expression.left!!).toExpectedType(context.builtIns.booleanType) - val irArgument1 = statementGenerator.generateExpression(expression.right!!).toExpectedType(context.builtIns.booleanType) - return IrBinaryOperatorExpressionImpl( - expression.startOffset, expression.endOffset, context.builtIns.booleanType, - irOperator, getResolvedCall(expression)?.resultingDescriptor, irArgument0, irArgument1 - ) + val irArgument0 = toExpectedType(parentGenerator.generateExpression(expression.left!!), context.builtIns.booleanType) + val irArgument1 = toExpectedType(parentGenerator.generateExpression(expression.right!!), context.builtIns.booleanType) + return when (irOperator) { + IrOperator.OROR -> + IrIfThenElseImpl.oror(expression.startOffset, expression.endOffset, irArgument0, irArgument1) + IrOperator.ANDAND -> + IrIfThenElseImpl.andand(expression.startOffset, expression.endOffset, irArgument0, irArgument1) + else -> + throw AssertionError("Unexpected binary boolean operator $irOperator") + } } private fun generateInOperator(expression: KtBinaryExpression, irOperator: IrOperator): IrExpression { - val operatorCall = getResolvedCall(expression)!! + val containsCall = getResolvedCall(expression)!! - val irOperatorCall = CallGenerator(statementGenerator).generateCall(expression, operatorCall, irOperator) + val irContainsCall = CallGenerator(parentGenerator).generateCall(expression, containsCall, irOperator) + + return when (irOperator) { + IrOperator.IN -> + irContainsCall + IrOperator.NOT_IN -> + IrUnaryOperatorImpl(expression.startOffset, expression.endOffset, IrOperator.EXCL, context.irBuiltIns.booleanNot, + irContainsCall) + else -> + throw AssertionError("Unexpected in-operator $irOperator") + } - return if (irOperator == IrOperator.IN) - irOperatorCall - else - IrUnaryOperatorExpressionImpl(expression.startOffset, expression.endOffset, context.builtIns.booleanType, - IrOperator.EXCL, null, irOperatorCall) } private fun generateIdentityOperator(expression: KtBinaryExpression, irOperator: IrOperator): IrExpression { - val irArgument0 = statementGenerator.generateExpression(expression.left!!) - val irArgument1 = statementGenerator.generateExpression(expression.right!!) - return IrBinaryOperatorExpressionImpl( - expression.startOffset, expression.endOffset, context.builtIns.booleanType, - irOperator, null, irArgument0, irArgument1 - ) + val irArgument0 = parentGenerator.generateExpression(expression.left!!) + val irArgument1 = parentGenerator.generateExpression(expression.right!!) + + + val irIdentityEquals = IrBinaryOperatorImpl(expression.startOffset, expression.endOffset, irOperator, context.irBuiltIns.eqeqeq, + irArgument0, irArgument1) + + return when (irOperator) { + IrOperator.EQEQEQ -> + irIdentityEquals + IrOperator.EXCLEQEQ -> + IrUnaryOperatorImpl(expression.startOffset, expression.endOffset, IrOperator.EXCL, context.irBuiltIns.booleanNot, + irIdentityEquals) + else -> + throw AssertionError("Unexpected identity operator $irOperator") + } + } private fun generateEqualityOperator(expression: KtBinaryExpression, irOperator: IrOperator): IrExpression { - val relatedCall = getResolvedCall(expression)!! - val relatedDescriptor = relatedCall.resultingDescriptor + val irArgument0 = parentGenerator.generateExpression(expression.left!!) + val irArgument1 = parentGenerator.generateExpression(expression.right!!) - val irCallGenerator = CallGenerator(statementGenerator) + val irEquals = IrBinaryOperatorImpl(expression.startOffset, expression.endOffset, + irOperator, context.irBuiltIns.eqeq, irArgument0, irArgument1) - // NB special typing rules for equality operators: both arguments are nullable + return when (irOperator) { + IrOperator.EQEQ -> + irEquals + IrOperator.EXCLEQ -> + IrUnaryOperatorImpl(expression.startOffset, expression.endOffset, IrOperator.EXCLEQ, + context.irBuiltIns.booleanNot, irEquals) + else -> + throw AssertionError("Unexpected equality operator $irOperator") + } - val irArgument0 = - irCallGenerator.generateReceiver(expression.left!!, relatedCall.dispatchReceiver)!! - .toExpectedType(relatedDescriptor.dispatchReceiverParameter!!.type.makeNullable()) - - val valueParameter0 = relatedDescriptor.valueParameters[0] - val irArgument1 = - irCallGenerator.generateValueArgument( - relatedCall.valueArgumentsByIndex!![0], - valueParameter0, valueParameter0.type.makeNullable() - )!! - - return IrBinaryOperatorExpressionImpl( - expression.startOffset, expression.endOffset, context.builtIns.booleanType, - irOperator, relatedDescriptor, irArgument0, irArgument1 - ) } private fun generateComparisonOperator(expression: KtBinaryExpression, irOperator: IrOperator): IrExpression { val compareToCall = getResolvedCall(expression)!! - val compareToDescriptor = compareToCall.resultingDescriptor - val irCallGenerator = CallGenerator(statementGenerator) + val irCallGenerator = CallGenerator(parentGenerator) + val irCompareToCall = irCallGenerator.generateCall(expression, compareToCall, irOperator) - return if (shouldKeepComparisonAsBinaryOperation(compareToDescriptor)) { - val irArgument0 = irCallGenerator.generateReceiver(expression.left!!, compareToCall.dispatchReceiver, compareToDescriptor.dispatchReceiverParameter!!)!! - val valueParameter0 = compareToDescriptor.valueParameters[0] - val irArgument1 = irCallGenerator.generateValueArgument(compareToCall.valueArgumentsByIndex!![0], valueParameter0)!! - IrBinaryOperatorExpressionImpl( - expression.startOffset, expression.endOffset, context.builtIns.booleanType, - irOperator, compareToDescriptor, irArgument0, irArgument1 - ) - } - else { - val irCompareToCall = irCallGenerator.generateCall(expression, compareToCall, irOperator) - IrBinaryOperatorExpressionImpl( - expression.startOffset, expression.endOffset, context.builtIns.booleanType, - irOperator, null, irCompareToCall, - IrConstExpressionImpl.int(expression.startOffset, expression.endOffset, context.builtIns.intType, 0) - ) + val compareToZeroDescriptor = when (irOperator) { + IrOperator.LT -> context.irBuiltIns.lt0 + IrOperator.LTEQ -> context.irBuiltIns.lteq0 + IrOperator.GT -> context.irBuiltIns.gt0 + IrOperator.GTEQ -> context.irBuiltIns.gteq0 + else -> throw AssertionError("Unexpected comparison operator: $irOperator") } + + return IrUnaryOperatorImpl(expression.startOffset, expression.endOffset, irOperator, compareToZeroDescriptor, irCompareToCall) } - private fun shouldKeepComparisonAsBinaryOperation(compareToDescriptor: CallableDescriptor) = - compareToDescriptor.dispatchReceiverParameter?.type.let { - it != null && (KotlinBuiltIns.isPrimitiveType(it) || KotlinBuiltIns.isString(it)) - } private fun generateBinaryOperatorWithConventionalCall(expression: KtBinaryExpression, irOperator: IrOperator?): IrExpression { val operatorCall = getResolvedCall(expression)!! - return CallGenerator(statementGenerator).generateCall(expression, operatorCall, irOperator) + return CallGenerator(parentGenerator).generateCall(expression, operatorCall, irOperator) } private fun generatePrefixIncrementDecrementOperator(expression: KtPrefixExpression, irOperator: IrOperator): IrExpression { @@ -213,13 +212,13 @@ class OperatorExpressionGenerator(val statementGenerator: StatementGenerator): I return irLValue.prefixAugmentedStore(operatorCall, irOperator) } - val opCallGenerator = CallGenerator(statementGenerator).apply { putValue(ktBaseExpression, irLValue) } - val irBlock = IrBlockExpressionImpl(expression.startOffset, expression.endOffset, irLValue.type, true, irOperator) + val opCallGenerator = CallGenerator(parentGenerator).apply { scope.putValue(ktBaseExpression, irLValue) } + val irBlock = IrBlockImpl(expression.startOffset, expression.endOffset, irLValue.type, true, irOperator) val irOpCall = opCallGenerator.generateCall(expression, operatorCall, irOperator) - val irTmp = statementGenerator.temporaryVariableFactory.createTemporaryVariable(irOpCall) + val irTmp = parentGenerator.scope.createTemporaryVariable(irOpCall) irBlock.addStatement(irTmp) - irBlock.addStatement(irLValue.store(irTmp.load())) - irBlock.addStatement(irTmp.load()) + irBlock.addStatement(irLValue.store(irTmp.defaultLoad())) + irBlock.addStatement(irTmp.defaultLoad()) return irBlock } @@ -231,10 +230,10 @@ class OperatorExpressionGenerator(val statementGenerator: StatementGenerator): I val isSimpleAssignment = get(BindingContext.VARIABLE_REASSIGNMENT, expression) ?: false if (isSimpleAssignment && irLValue is IrLValueWithAugmentedStore) { - return irLValue.augmentedStore(operatorCall, irOperator, statementGenerator.generateExpression(expression.right!!)) + return irLValue.augmentedStore(operatorCall, irOperator, parentGenerator.generateExpression(expression.right!!)) } - val opCallGenerator = CallGenerator(statementGenerator).apply { putValue(ktLeft, irLValue) } + val opCallGenerator = CallGenerator(parentGenerator).apply { scope.putValue(ktLeft, irLValue) } val irOpCall = opCallGenerator.generateCall(expression, operatorCall, irOperator) return if (isSimpleAssignment) { @@ -251,19 +250,19 @@ class OperatorExpressionGenerator(val statementGenerator: StatementGenerator): I val ktLeft = expression.left!! val ktRight = expression.right!! val irLValue = generateLValue(ktLeft, IrOperator.EQ) - return irLValue.store(statementGenerator.generateExpression(ktRight)) + return irLValue.store(parentGenerator.generateExpression(ktRight)) } private fun generateLValue(ktLeft: KtExpression, irOperator: IrOperator?): IrLValue { if (ktLeft is KtArrayAccessExpression) { - val irArrayValue = statementGenerator.generateExpression(ktLeft.arrayExpression!!) - val indexExpressions = ktLeft.indexExpressions.map { it to statementGenerator.generateExpression(it) } + val irArrayValue = parentGenerator.generateExpression(ktLeft.arrayExpression!!) + val indexExpressions = ktLeft.indexExpressions.map { it to parentGenerator.generateExpression(it) } val indexedGetCall = get(BindingContext.INDEXED_LVALUE_GET, ktLeft) val indexedSetCall = get(BindingContext.INDEXED_LVALUE_SET, ktLeft) val type = indexedGetCall?.run { resultingDescriptor.returnType } ?: indexedSetCall?.run { resultingDescriptor.valueParameters.last().type } ?: throw AssertionError("Either 'get' or 'set' call should be present for an indexed LValue: ${ktLeft.text}") - return IndexedLValue(statementGenerator, ktLeft, irOperator, + return IndexedLValue(parentGenerator, ktLeft, irOperator, irArrayValue, type, indexExpressions, indexedGetCall, indexedSetCall) } @@ -275,10 +274,11 @@ class OperatorExpressionGenerator(val statementGenerator: StatementGenerator): I if (descriptor.isDelegated) TODO("Delegated local variable") else - VariableLValue(ktLeft.startOffset, ktLeft.endOffset, descriptor, irOperator) + VariableLValue(this, ktLeft.startOffset, ktLeft.endOffset, descriptor, irOperator) is PropertyDescriptor -> - CallGenerator(statementGenerator).run { + CallGenerator(parentGenerator).run { PropertyLValue( + this, ktLeft, irOperator, descriptor, generateReceiver(ktLeft, resolvedCall.dispatchReceiver, descriptor.dispatchReceiverParameter), generateReceiver(ktLeft, resolvedCall.extensionReceiver, descriptor.extensionReceiverParameter), diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/Scope.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/Scope.kt new file mode 100644 index 00000000000..3ed82308463 --- /dev/null +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/Scope.kt @@ -0,0 +1,126 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.psi2ir.generators + +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor +import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginKind +import org.jetbrains.kotlin.ir.declarations.IrVariable +import org.jetbrains.kotlin.ir.declarations.IrVariableImpl +import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptor +import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl +import org.jetbrains.kotlin.ir.expressions.IrExpression +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.KtExpression +import org.jetbrains.kotlin.psi2ir.generators.values.IrValue +import org.jetbrains.kotlin.psi2ir.generators.values.VariableLValue +import org.jetbrains.kotlin.psi2ir.generators.values.createRematerializableValue +import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue +import org.jetbrains.kotlin.types.KotlinType +import java.util.* + +class Scope private constructor(val scopeOwner: DeclarationDescriptor, val parent: Scope? = null) { + internal lateinit var generator: IrBodyGenerator + + constructor(parent: Scope) : this(parent.scopeOwner, parent) { + this.generator = parent.generator + } + + private var lastTemporaryIndex: Int = parent?.lastTemporaryIndex ?: 0 + private fun nextTemporaryIndex(): Int = parent?.nextTemporaryIndex() ?: lastTemporaryIndex++ + + private val expressionValues = HashMap() + private val receiverValues = HashMap() + private val valueArgumentValues = HashMap() + + private fun createDescriptorForTemporaryVariable(type: KotlinType, nameHint: String? = null): IrTemporaryVariableDescriptor = + IrTemporaryVariableDescriptorImpl( + scopeOwner, + Name.identifier( + if (nameHint != null) + "tmp${nextTemporaryIndex()}_$nameHint" + else + "tmp${nextTemporaryIndex()}" + ), + type) + + fun createTemporaryVariable(irExpression: IrExpression, nameHint: String? = null): IrVariable = + IrVariableImpl(irExpression.startOffset, irExpression.endOffset, IrDeclarationOriginKind.IR_TEMPORARY_VARIABLE, + createDescriptorForTemporaryVariable( + irExpression.type ?: throw AssertionError("No type for $irExpression"), + nameHint + ), + irExpression) + + fun introduceTemporary(ktExpression: KtExpression, irExpression: IrExpression, nameHint: String? = null): IrVariable? { + val rematerializable = createRematerializableValue(irExpression) + if (rematerializable != null) { + putValue(ktExpression, rematerializable) + return null + } + + return createTemporary(ktExpression, irExpression, nameHint) + } + + fun createTemporary(ktExpression: KtExpression, irExpression: IrExpression, nameHint: String?): IrVariable { + val irTmpVar = createTemporaryVariable(irExpression, nameHint) + putValue(ktExpression, VariableLValue(generator, irTmpVar)) + return irTmpVar + } + + fun createTemporary(irExpression: IrExpression, nameHint: String?): IrVariable = + createTemporaryVariable(irExpression, nameHint) + + fun introduceTemporary(valueParameterDescriptor: ValueParameterDescriptor, irExpression: IrExpression): IrVariable? { + val rematerializable = createRematerializableValue(irExpression) + if (rematerializable != null) { + putValue(valueParameterDescriptor, rematerializable) + return null + } + + val irTmpVar = createTemporaryVariable(irExpression, valueParameterDescriptor.name.asString()) + putValue(valueParameterDescriptor, VariableLValue(generator, irTmpVar)) + return irTmpVar + } + + fun putValue(ktExpression: KtExpression, irValue: IrValue) { + expressionValues[ktExpression] = irValue + } + + fun putValue(receiver: ReceiverValue, irValue: IrValue) { + receiverValues[receiver] = irValue + } + + fun putValue(parameter: ValueParameterDescriptor, irValue: IrValue) { + valueArgumentValues[parameter] = irValue + } + + fun valueOf(ktExpression: KtExpression): IrExpression? = + expressionValues[ktExpression]?.load() ?: parent?.valueOf(ktExpression) + fun valueOf(receiver: ReceiverValue): IrExpression? = + receiverValues[receiver]?.load() ?: parent?.valueOf(receiver) + fun valueOf(parameter: ValueParameterDescriptor): IrExpression? = + valueArgumentValues[parameter]?.load() ?: parent?.valueOf(parameter) + + companion object { + fun rootScope(scopeOwner: DeclarationDescriptor, generator: IrBodyGenerator): Scope { + val scope = Scope(scopeOwner) + scope.generator = generator + return scope + } + } +} diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt index 84c15330617..8ec475d973e 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/StatementGenerator.kt @@ -1,4 +1,4 @@ -/* +/** * Copyright 2010-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -27,7 +27,6 @@ import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.psi2ir.deparenthesize import org.jetbrains.kotlin.psi2ir.generators.values.VariableLValue -import org.jetbrains.kotlin.psi2ir.toExpectedType import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContextUtils import org.jetbrains.kotlin.resolve.DescriptorUtils @@ -44,10 +43,9 @@ import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils class StatementGenerator( override val context: GeneratorContext, val scopeOwner: DeclarationDescriptor, - val functionBodyGenerator: FunctionBodyGenerator -) : KtVisitor(), IrGenerator { - val temporaryVariableFactory: TemporaryVariableFactory = TemporaryVariableFactory(scopeOwner) - + val declarationBodyGenerator: ExoressionBodyGenerator, + override val scope: Scope +) : KtVisitor(), IrBodyGenerator { fun generateExpression(ktExpression: KtExpression): IrExpression = ktExpression.genExpr() @@ -67,7 +65,7 @@ class StatementGenerator( val irLocalVariable = IrVariableImpl(property.startOffset, property.endOffset, IrDeclarationOriginKind.DEFINED, variableDescriptor) irLocalVariable.initializer = property.initializer?.let { - it.genExpr().toExpectedType(variableDescriptor.type) + toExpectedType(it.genExpr(), variableDescriptor.type) } return irLocalVariable @@ -76,13 +74,13 @@ class StatementGenerator( override fun visitDestructuringDeclaration(multiDeclaration: KtDestructuringDeclaration, data: Nothing?): IrStatement { // TODO use some special form that introduces multiple declarations into surrounding scope? - val irBlock = IrBlockExpressionImpl(multiDeclaration.startOffset, multiDeclaration.endOffset, null, false, IrOperator.SYNTHETIC_BLOCK) + val irBlock = IrBlockImpl(multiDeclaration.startOffset, multiDeclaration.endOffset, null, false, IrOperator.SYNTHETIC_BLOCK) val ktInitializer = multiDeclaration.initializer!! - val irTmpInitializer = temporaryVariableFactory.createTemporaryVariable(ktInitializer.genExpr()) + val irTmpInitializer = scope.createTemporaryVariable(ktInitializer.genExpr()) irBlock.addStatement(irTmpInitializer) val irCallGenerator = CallGenerator(this) - irCallGenerator.putValue(ktInitializer, VariableLValue(irTmpInitializer)) + irCallGenerator.scope.putValue(ktInitializer, VariableLValue(this, irTmpInitializer)) for ((index, ktEntry) in multiDeclaration.entries.withIndex()) { val componentResolvedCall = getOrFail(BindingContext.COMPONENT_RESOLVED_CALL, ktEntry) @@ -97,8 +95,8 @@ class StatementGenerator( } override fun visitBlockExpression(expression: KtBlockExpression, data: Nothing?): IrStatement { - val irBlock = IrBlockExpressionImpl(expression.startOffset, expression.endOffset, - getReturnType(expression), isUsedAsExpression(expression)) + val irBlock = IrBlockImpl(expression.startOffset, expression.endOffset, + getReturnType(expression), isUsedAsExpression(expression)) expression.statements.forEach { irBlock.addStatement(it.genStmt()) } return irBlock } @@ -106,9 +104,9 @@ class StatementGenerator( override fun visitReturnExpression(expression: KtReturnExpression, data: Nothing?): IrStatement { val returnTarget = getReturnExpressionTarget(expression) val irReturnedExpression = expression.returnedExpression?.let { - it.genExpr().toExpectedType(returnTarget.returnType) + toExpectedType(it.genExpr(), returnTarget.returnType) } - return IrReturnExpressionImpl( + return IrReturnImpl( expression.startOffset, expression.endOffset, returnTarget, irReturnedExpression ) @@ -141,11 +139,11 @@ class StatementGenerator( return when (constantValue) { is StringValue -> - IrConstExpressionImpl.string(expression.startOffset, expression.endOffset, constantType, constantValue.value) + IrConstImpl.string(expression.startOffset, expression.endOffset, constantType, constantValue.value) is IntValue -> - IrConstExpressionImpl.int(expression.startOffset, expression.endOffset, constantType, constantValue.value) + IrConstImpl.int(expression.startOffset, expression.endOffset, constantType, constantValue.value) is NullValue -> - IrConstExpressionImpl.constNull(expression.startOffset, expression.endOffset, constantType) + IrConstImpl.constNull(expression.startOffset, expression.endOffset, constantType) else -> TODO("handle other literal types: ${constantValue.type}") } @@ -160,16 +158,16 @@ class StatementGenerator( return entry0.genExpr() } } - entries.size == 0 -> return IrConstExpressionImpl.string(expression.startOffset, expression.endOffset, getInferredTypeWithSmarcastsOrFail(expression), "") + entries.size == 0 -> return IrConstImpl.string(expression.startOffset, expression.endOffset, getInferredTypeWithSmarcastsOrFail(expression), "") } - val irStringTemplate = IrStringConcatenationExpressionImpl(expression.startOffset, expression.endOffset, getInferredTypeWithSmartcasts(expression)) + val irStringTemplate = IrStringConcatenationImpl(expression.startOffset, expression.endOffset, getInferredTypeWithSmartcasts(expression)) entries.forEach { it.expression!!.let { irStringTemplate.addArgument(it.genExpr()) } } return irStringTemplate } override fun visitLiteralStringTemplateEntry(entry: KtLiteralStringTemplateEntry, data: Nothing?): IrStatement = - IrConstExpressionImpl.string(entry.startOffset, entry.endOffset, context.builtIns.stringType, entry.text) + IrConstImpl.string(entry.startOffset, entry.endOffset, context.builtIns.stringType, entry.text) override fun visitSimpleNameExpression(expression: KtSimpleNameExpression, data: Nothing?): IrExpression { val resolvedCall = getResolvedCall(expression)!! @@ -189,21 +187,21 @@ class StatementGenerator( generateExpressionForReferencedDescriptor(descriptor.getReferencedDescriptor(), expression, resolvedCall) is ClassDescriptor -> if (DescriptorUtils.isObject(descriptor)) - IrGetObjectValueExpressionImpl(expression.startOffset, expression.endOffset, descriptor.classValueType, descriptor) + IrGetObjectValueImpl(expression.startOffset, expression.endOffset, descriptor.classValueType, descriptor) else if (DescriptorUtils.isEnumEntry(descriptor)) - IrGetEnumValueExpressionImpl(expression.startOffset, expression.endOffset, descriptor.classValueType, descriptor) + IrGetEnumValueImpl(expression.startOffset, expression.endOffset, descriptor.classValueType, descriptor) else { val companionObjectDescriptor = descriptor.companionObjectDescriptor ?: error("Class value without companion object: $descriptor") - IrGetObjectValueExpressionImpl(expression.startOffset, expression.endOffset, - descriptor.classValueType, - companionObjectDescriptor) + IrGetObjectValueImpl(expression.startOffset, expression.endOffset, + descriptor.classValueType, + companionObjectDescriptor) } is PropertyDescriptor -> { CallGenerator(this).generateCall(expression, resolvedCall) } is VariableDescriptor -> - IrGetVariableExpressionImpl(expression.startOffset, expression.endOffset, descriptor) + IrGetVariableImpl(expression.startOffset, expression.endOffset, descriptor) else -> IrDummyExpression( expression.startOffset, expression.endOffset, getInferredTypeWithSmartcasts(expression), @@ -231,14 +229,14 @@ class StatementGenerator( val referenceTarget = getOrFail(BindingContext.REFERENCE_TARGET, expression.instanceReference) { "No reference target for this" } return when (referenceTarget) { is ClassDescriptor -> - IrThisExpressionImpl( + IrThisReferenceImpl( expression.startOffset, expression.endOffset, referenceTarget.defaultType, // TODO substituted type for 'this'? referenceTarget ) is CallableDescriptor -> { val extensionReceiver = referenceTarget.extensionReceiverParameter ?: TODO("No extension receiver: $referenceTarget") - IrGetExtensionReceiverExpressionImpl( + IrGetExtensionReceiverImpl( expression.startOffset, expression.endOffset, extensionReceiver.type, extensionReceiver @@ -266,11 +264,11 @@ class StatementGenerator( override fun visitIfExpression(expression: KtIfExpression, data: Nothing?): IrStatement { val resultType = getInferredTypeWithSmartcasts(expression) - val irCondition = expression.condition!!.genExpr().toExpectedType(context.builtIns.booleanType) - val irThenBranch = expression.then!!.genExpr().toExpectedType(resultType) - val irElseBranch = expression.`else`?.let { it.genExpr().toExpectedType(resultType) } - return IrIfExpressionImpl(expression.startOffset, expression.endOffset, resultType, - irCondition, irThenBranch, irElseBranch, IrOperator.IF) + val irCondition = toExpectedType(expression.condition!!.genExpr(), context.builtIns.booleanType) + val irThenBranch = toExpectedType(expression.then!!.genExpr(), resultType) + val irElseBranch = toExpectedTypeOrNull(expression.`else`?.genExpr(), resultType) + return IrIfThenElseImpl(expression.startOffset, expression.endOffset, resultType, + irCondition, irThenBranch, irElseBranch, IrOperator.IF) } override fun visitWhenExpression(expression: KtWhenExpression, data: Nothing?): IrStatement = diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TemporaryVariableFactory.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TemporaryVariableFactory.kt index 0acf30bcd81..8a24d7662d2 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TemporaryVariableFactory.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TemporaryVariableFactory.kt @@ -27,25 +27,6 @@ import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.KotlinType class TemporaryVariableFactory(val scopeOwner: DeclarationDescriptor) { - private var lastTemporaryIndex = 0 - private fun nextTemporaryIndex() = lastTemporaryIndex++ - private fun createDescriptorForTemporaryVariable(type: KotlinType, nameHint: String? = null): IrTemporaryVariableDescriptor = - IrTemporaryVariableDescriptorImpl( - scopeOwner, - Name.identifier( - if (nameHint != null) - "tmp${nextTemporaryIndex()}_$nameHint" - else - "tmp${nextTemporaryIndex()}" - ), - type) - fun createTemporaryVariable(irExpression: IrExpression, nameHint: String? = null): IrVariable = - IrVariableImpl(irExpression.startOffset, irExpression.endOffset, IrDeclarationOriginKind.IR_TEMPORARY_VARIABLE, - createDescriptorForTemporaryVariable( - irExpression.type ?: throw AssertionError("No type for $irExpression"), - nameHint - ), - irExpression) } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/WhenExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/WhenExpressionGenerator.kt index 85f808afc10..f4a8dced6e7 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/WhenExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/WhenExpressionGenerator.kt @@ -21,19 +21,16 @@ import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset -import org.jetbrains.kotlin.psi2ir.load -import org.jetbrains.kotlin.psi2ir.toExpectedType +import org.jetbrains.kotlin.psi2ir.defaultLoad import org.jetbrains.kotlin.resolve.BindingContext import java.util.* -class WhenExpressionGenerator(val statementGenerator: StatementGenerator) : IrGenerator { - override val context: GeneratorContext get() = statementGenerator.context - +class WhenExpressionGenerator(statementGenerator: StatementGenerator) : IrChildBodyGeneratorBase(statementGenerator) { fun generate(expression: KtWhenExpression): IrExpression { - val conditionsGenerator = CallGenerator(statementGenerator) + val conditionsGenerator = CallGenerator(parentGenerator) val irSubject = expression.subjectExpression?.let { - conditionsGenerator.createTemporary(it, statementGenerator.generateExpression(it), "subject") + conditionsGenerator.scope.createTemporary(it, parentGenerator.generateExpression(it), "subject") } val resultType = getInferredTypeWithSmartcasts(expression) @@ -43,7 +40,7 @@ class WhenExpressionGenerator(val statementGenerator: StatementGenerator) : IrGe for (ktEntry in expression.entries) { if (ktEntry.isElse) { - irElseExpression = statementGenerator.generateExpression(ktEntry.expression!!).toExpectedType(resultType) + irElseExpression = parentGenerator.generateExpressionWithExpectedType(ktEntry.expression!!, resultType) break } @@ -54,11 +51,11 @@ class WhenExpressionGenerator(val statementGenerator: StatementGenerator) : IrGe generateWhenConditionWithSubject(ktCondition, conditionsGenerator, irSubject) else generateWhenConditionNoSubject(ktCondition) - irBranchCondition = irBranchCondition?.let { IrIfExpressionImpl.whenComma(it, irCondition) } ?: irCondition + irBranchCondition = irBranchCondition?.let { IrIfThenElseImpl.whenComma(it, irCondition) } ?: irCondition } - val irBranchResult = statementGenerator.generateExpression(ktEntry.expression!!).toExpectedType(resultType) + val irBranchResult = parentGenerator.generateExpressionWithExpectedType(ktEntry.expression!!, resultType) irBranches.add(Pair(irBranchCondition!!, irBranchResult)) } @@ -67,32 +64,32 @@ class WhenExpressionGenerator(val statementGenerator: StatementGenerator) : IrGe irBranches.reverse() val (irLastCondition, irLastResult) = irBranches[0] - var irTopBranch = IrIfExpressionImpl(irLastCondition.startOffset, irLastCondition.endOffset, resultType, - irLastCondition, irLastResult, irElseExpression, IrOperator.WHEN) + var irTopBranch = IrIfThenElseImpl(irLastCondition.startOffset, irLastCondition.endOffset, resultType, + irLastCondition, irLastResult, irElseExpression, IrOperator.WHEN) for ((irBranchCondition, irBranchResult) in irBranches.subList(1, irBranches.size)) { - irTopBranch = IrIfExpressionImpl(irBranchCondition.startOffset, irBranchCondition.endOffset, resultType, - irBranchCondition, irBranchResult, irTopBranch, IrOperator.WHEN) + irTopBranch = IrIfThenElseImpl(irBranchCondition.startOffset, irBranchCondition.endOffset, resultType, + irBranchCondition, irBranchResult, irTopBranch, IrOperator.WHEN) } return generateWhenBody(expression, irSubject, irTopBranch) } - private fun generateWhenBody(expression: KtWhenExpression, irSubject: IrVariable?, irTopBranch: IrIfExpression? = null): IrExpression { + private fun generateWhenBody(expression: KtWhenExpression, irSubject: IrVariable?, irTopBranch: IrIfThenElse? = null): IrExpression { if (irSubject == null) { if (irTopBranch == null) - return IrBlockExpressionImpl(expression.startOffset, expression.endOffset, null, false, IrOperator.WHEN) + return IrBlockImpl(expression.startOffset, expression.endOffset, null, false, IrOperator.WHEN) else return irTopBranch } else { if (irTopBranch == null) { - val irBlock = IrBlockExpressionImpl(expression.startOffset, expression.endOffset, null, false, IrOperator.WHEN) + val irBlock = IrBlockImpl(expression.startOffset, expression.endOffset, null, false, IrOperator.WHEN) irBlock.addStatement(irSubject) return irBlock } else { - val irBlock = IrBlockExpressionImpl(expression.startOffset, expression.endOffset, irTopBranch.type, true, IrOperator.WHEN) + val irBlock = IrBlockImpl(expression.startOffset, expression.endOffset, irTopBranch.type, true, IrOperator.WHEN) irBlock.addStatement(irSubject) irBlock.addStatement(irTopBranch) return irBlock @@ -101,8 +98,8 @@ class WhenExpressionGenerator(val statementGenerator: StatementGenerator) : IrGe } private fun generateWhenConditionNoSubject(ktCondition: KtWhenCondition): IrExpression = - statementGenerator.generateExpression((ktCondition as KtWhenConditionWithExpression).expression!!) - .toExpectedType(context.builtIns.booleanType) + parentGenerator.generateExpressionWithExpectedType((ktCondition as KtWhenConditionWithExpression).expression!!, + context.builtIns.booleanType) private fun generateWhenConditionWithSubject( ktCondition: KtWhenCondition, @@ -123,9 +120,9 @@ class WhenExpressionGenerator(val statementGenerator: StatementGenerator) : IrGe private fun generateIsPatternCondition(irSubject: IrVariable, ktCondition: KtWhenConditionIsPattern): IrExpression { val isType = getOrFail(BindingContext.TYPE, ktCondition.typeReference) - return IrTypeOperatorExpressionImpl( + return IrTypeOperatorCallImpl( ktCondition.startOffset, ktCondition.endOffset, context.builtIns.booleanType, - IrTypeOperator.INSTANCEOF, isType, irSubject.load() + IrTypeOperator.INSTANCEOF, isType, irSubject.defaultLoad() ) } @@ -136,16 +133,15 @@ class WhenExpressionGenerator(val statementGenerator: StatementGenerator) : IrGe return when (inOperator) { IrOperator.IN -> irInCall IrOperator.NOT_IN -> - IrUnaryOperatorExpressionImpl(ktCondition.startOffset, ktCondition.endOffset, context.builtIns.booleanType, - IrOperator.EXCL, null, irInCall) + IrUnaryOperatorImpl(ktCondition.startOffset, ktCondition.endOffset, IrOperator.EXCL, context.irBuiltIns.booleanNot, irInCall) else -> throw AssertionError("Expected 'in' or '!in', got $inOperator") } } - private fun generateEqualsCondition(irSubject: IrVariable, ktCondition: KtWhenConditionWithExpression): IrBinaryOperatorExpressionImpl = - IrBinaryOperatorExpressionImpl( + private fun generateEqualsCondition(irSubject: IrVariable, ktCondition: KtWhenConditionWithExpression): IrBinaryOperatorImpl = + IrBinaryOperatorImpl( ktCondition.startOffset, ktCondition.endOffset, - context.builtIns.booleanType, IrOperator.EQEQ, null, - irSubject.load(), statementGenerator.generateExpression(ktCondition.expression!!) + IrOperator.EQEQ, context.irBuiltIns.eqeq, + irSubject.defaultLoad(), parentGenerator.generateExpression(ktCondition.expression!!) ) } \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/IndexedLValue.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/IndexedLValue.kt index 2e10027da93..fc3a2bb8772 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/IndexedLValue.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/IndexedLValue.kt @@ -21,8 +21,9 @@ import org.jetbrains.kotlin.psi.KtArrayAccessExpression import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset -import org.jetbrains.kotlin.psi2ir.load +import org.jetbrains.kotlin.psi2ir.defaultLoad import org.jetbrains.kotlin.psi2ir.generators.CallGenerator +import org.jetbrains.kotlin.psi2ir.generators.Scope import org.jetbrains.kotlin.psi2ir.generators.StatementGenerator import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.types.KotlinType @@ -51,10 +52,10 @@ class IndexedLValue( private fun generateGetOrSetCallAsDesugaredBlock(call: ResolvedCall<*>, irArgument: IrExpression? = null): IrExpression { val callGenerator = CallGenerator(statementGenerator) - setupCallGeneratorContext(callGenerator) + setupCallGeneratorContext(callGenerator.scope) if (irArgument != null) { - callGenerator.putValue(call.resultingDescriptor.valueParameters.last(), IrSingleExpressionValue(irArgument)) + callGenerator.scope.putValue(call.resultingDescriptor.valueParameters.last(), IrSingleExpressionValue(irArgument)) } return callGenerator.generateCall(ktArrayAccessExpression, call, irOperator) @@ -69,18 +70,18 @@ class IndexedLValue( val irBlock = createDesugaredBlockWithTemporaries(indexedSetCall, callGenerator, true, irOperator) val operatorCallReceiver = operatorCall.extensionReceiver ?: operatorCall.dispatchReceiver - callGenerator.putValue(operatorCallReceiver!!, + callGenerator.scope.putValue(operatorCallReceiver!!, IrSingleExpressionValue(callGenerator.generateCall(ktArrayAccessExpression, indexedGetCall, irOperator))) - val irTmp = statementGenerator.temporaryVariableFactory.createTemporaryVariable( + val irTmp = statementGenerator.scope.createTemporaryVariable( callGenerator.generateCall(ktArrayAccessExpression, operatorCall, irOperator)) irBlock.addStatement(irTmp) - callGenerator.putValue(indexedSetCall.resultingDescriptor.valueParameters.last(), - VariableLValue(irTmp)) + callGenerator.scope.putValue(indexedSetCall.resultingDescriptor.valueParameters.last(), + VariableLValue(statementGenerator, irTmp)) irBlock.addStatement(callGenerator.generateCall(ktArrayAccessExpression, indexedSetCall, irOperator)) - irBlock.addStatement(irTmp.load()) + irBlock.addStatement(irTmp.defaultLoad()) return irBlock } @@ -93,13 +94,13 @@ class IndexedLValue( val irBlock = createDesugaredBlockWithTemporaries(indexedSetCall, callGenerator, false, irOperator) - callGenerator.putValue(operatorCall.resultingDescriptor.valueParameters[0], IrSingleExpressionValue(irOperatorArgument)) + callGenerator.scope.putValue(operatorCall.resultingDescriptor.valueParameters[0], IrSingleExpressionValue(irOperatorArgument)) val operatorCallReceiver = operatorCall.extensionReceiver ?: operatorCall.dispatchReceiver - callGenerator.putValue(operatorCallReceiver!!, + callGenerator.scope.putValue(operatorCallReceiver!!, IrSingleExpressionValue(callGenerator.generateCall(ktArrayAccessExpression, indexedGetCall, irOperator))) - callGenerator.putValue(indexedSetCall.resultingDescriptor.valueParameters.last(), + callGenerator.scope.putValue(indexedSetCall.resultingDescriptor.valueParameters.last(), IrSingleExpressionValue(callGenerator.generateCall(ktArrayAccessExpression, operatorCall, irOperator))) irBlock.addStatement(callGenerator.generateCall(ktArrayAccessExpression, indexedSetCall, irOperator)) @@ -112,32 +113,32 @@ class IndexedLValue( callGenerator: CallGenerator, hasResult: Boolean, operator: IrOperator? - ): IrBlockExpressionImpl { + ): IrBlockImpl { val irBlock = createDesugaredBlock(call, hasResult, operator) - defineTemporaryVariables(irBlock, callGenerator) + defineTemporaryVariables(irBlock, callGenerator.scope) return irBlock } - private fun createDesugaredBlock(call: ResolvedCall<*>, hasResult: Boolean, operator: IrOperator?): IrBlockExpressionImpl { - return IrBlockExpressionImpl(ktArrayAccessExpression.startOffset, ktArrayAccessExpression.endOffset, - if (hasResult) type else call.resultingDescriptor.returnType, - hasResult, operator) + private fun createDesugaredBlock(call: ResolvedCall<*>, hasResult: Boolean, operator: IrOperator?): IrBlockImpl { + return IrBlockImpl(ktArrayAccessExpression.startOffset, ktArrayAccessExpression.endOffset, + if (hasResult) type else call.resultingDescriptor.returnType, + hasResult, operator) } - private fun defineTemporaryVariables(irBlock: IrBlockExpressionImpl, callGenerator: CallGenerator) { - irBlock.addIfNotNull(callGenerator.introduceTemporary(ktArrayAccessExpression.arrayExpression!!, irArray, "array")) + private fun defineTemporaryVariables(irBlock: IrBlockImpl, scope: Scope) { + irBlock.addIfNotNull(scope.introduceTemporary(ktArrayAccessExpression.arrayExpression!!, irArray, "array")) var index = 0 for ((ktIndexExpression, irIndexValue) in indexValues) { - irBlock.addIfNotNull(callGenerator.introduceTemporary(ktIndexExpression, irIndexValue, "index${index++}")) + irBlock.addIfNotNull(scope.introduceTemporary(ktIndexExpression, irIndexValue, "index${index++}")) } } - private fun setupCallGeneratorContext(callGenerator: CallGenerator) { - callGenerator.putValue(ktArrayAccessExpression.arrayExpression!!, IrSingleExpressionValue(irArray)) + private fun setupCallGeneratorContext(scope: Scope) { + scope.putValue(ktArrayAccessExpression.arrayExpression!!, IrSingleExpressionValue(irArray)) for ((ktIndexExpression, irIndexValue) in indexValues) { - callGenerator.putValue(ktIndexExpression, IrSingleExpressionValue(irIndexValue)) + scope.putValue(ktIndexExpression, IrSingleExpressionValue(irIndexValue)) } } } \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/PropertyLValue.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/PropertyLValue.kt index 837cdd5da06..7883ae0c521 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/PropertyLValue.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/PropertyLValue.kt @@ -21,10 +21,12 @@ import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset -import org.jetbrains.kotlin.psi2ir.toExpectedType +import org.jetbrains.kotlin.psi2ir.generators.IrBodyGenerator +import org.jetbrains.kotlin.psi2ir.generators.toExpectedType import org.jetbrains.kotlin.types.KotlinType class PropertyLValue( + val irBodyGenerator: IrBodyGenerator, val ktElement: KtElement, val irOperator: IrOperator?, val descriptor: PropertyDescriptor, @@ -37,7 +39,7 @@ class PropertyLValue( override fun load(): IrExpression { val getter = descriptor.getter!! - return IrGetterCallExpressionImpl( + return IrGetterCallImpl( ktElement.startOffset, ktElement.endOffset, getter.returnType, getter, isSafe, dispatchReceiver, extensionReceiver, IrOperator.GET_PROPERTY @@ -46,10 +48,10 @@ class PropertyLValue( override fun store(irExpression: IrExpression): IrExpression { val setter = descriptor.setter!! - val irArgument = irExpression.toExpectedType(descriptor.type) - val irCall = IrSetterCallExpressionImpl(ktElement.startOffset, ktElement.endOffset, - setter.returnType, setter, isSafe, - dispatchReceiver, extensionReceiver, irArgument, irOperator) + val irArgument = irBodyGenerator.toExpectedType(irExpression, descriptor.type) + val irCall = IrSetterCallImpl(ktElement.startOffset, ktElement.endOffset, + setter.returnType, setter, isSafe, + dispatchReceiver, extensionReceiver, irArgument, irOperator) return irCall } } \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/RematerializableValue.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/RematerializableValue.kt index 2f4ad887611..f75ec70bbed 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/RematerializableValue.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/RematerializableValue.kt @@ -28,30 +28,30 @@ interface IrRematerializableValue : IrValue { fun createRematerializableValue(irExpression: IrExpression): IrRematerializableValue? = when (irExpression) { - is IrConstExpression<*> -> IrRematerializableLiteralValue(irExpression) - is IrGetVariableExpression -> IrRematerializableVariableValue(irExpression) - is IrGetExtensionReceiverExpression -> IrRematerializableExtensionReceiverValue(irExpression) - is IrThisExpression -> IrRematerializableThisValue(irExpression) + is IrConst<*> -> IrRematerializableLiteralValue(irExpression) + is IrGetVariable -> IrRematerializableVariableValue(irExpression) + is IrGetExtensionReceiver -> IrRematerializableExtensionReceiverValue(irExpression) + is IrThisReference -> IrRematerializableThisValue(irExpression) else -> null } -class IrRematerializableLiteralValue(override val irExpression: IrConstExpression<*>): IrRematerializableValue { +class IrRematerializableLiteralValue(override val irExpression: IrConst<*>): IrRematerializableValue { override fun load(): IrExpression = - IrConstExpressionImpl(irExpression.startOffset, irExpression.endOffset, irExpression.type, - irExpression.kind, irExpression.kind.valueOf(irExpression)) + IrConstImpl(irExpression.startOffset, irExpression.endOffset, irExpression.type, + irExpression.kind, irExpression.kind.valueOf(irExpression)) } -class IrRematerializableVariableValue(override val irExpression: IrGetVariableExpression) : IrRematerializableValue { +class IrRematerializableVariableValue(override val irExpression: IrGetVariable) : IrRematerializableValue { override fun load(): IrExpression = - IrGetVariableExpressionImpl(irExpression.startOffset, irExpression.endOffset, irExpression.descriptor) + IrGetVariableImpl(irExpression.startOffset, irExpression.endOffset, irExpression.descriptor) } -class IrRematerializableExtensionReceiverValue(override val irExpression: IrGetExtensionReceiverExpression) : IrRematerializableValue { +class IrRematerializableExtensionReceiverValue(override val irExpression: IrGetExtensionReceiver) : IrRematerializableValue { override fun load(): IrExpression = - IrGetExtensionReceiverExpressionImpl(irExpression.startOffset, irExpression.endOffset, irExpression.type, irExpression.descriptor) + IrGetExtensionReceiverImpl(irExpression.startOffset, irExpression.endOffset, irExpression.type, irExpression.descriptor) } -class IrRematerializableThisValue(override val irExpression: IrThisExpression): IrRematerializableValue { +class IrRematerializableThisValue(override val irExpression: IrThisReference): IrRematerializableValue { override fun load(): IrExpression = - IrThisExpressionImpl(irExpression.startOffset, irExpression.endOffset, irExpression.type, irExpression.classDescriptor) + IrThisReferenceImpl(irExpression.startOffset, irExpression.endOffset, irExpression.type, irExpression.classDescriptor) } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/VariableLValue.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/VariableLValue.kt index 2e191604996..7fe7ec9d05a 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/VariableLValue.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/values/VariableLValue.kt @@ -19,29 +19,32 @@ package org.jetbrains.kotlin.psi2ir.generators.values import org.jetbrains.kotlin.descriptors.VariableDescriptor import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.IrGetVariableExpressionImpl +import org.jetbrains.kotlin.ir.expressions.IrGetVariableImpl import org.jetbrains.kotlin.ir.expressions.IrOperator -import org.jetbrains.kotlin.ir.expressions.IrSetVariableExpressionImpl -import org.jetbrains.kotlin.psi2ir.toExpectedType +import org.jetbrains.kotlin.ir.expressions.IrSetVariableImpl +import org.jetbrains.kotlin.psi2ir.generators.IrBodyGenerator +import org.jetbrains.kotlin.psi2ir.generators.toExpectedType import org.jetbrains.kotlin.types.KotlinType class VariableLValue( + val irBodyGenerator: IrBodyGenerator, val startOffset: Int, val endOffset: Int, val descriptor: VariableDescriptor, val irOperator: IrOperator? = null ) : IrLValue { constructor( + irBodyGenerator: IrBodyGenerator, irVariable: IrVariable, irOperator: IrOperator? = null - ) : this(irVariable.startOffset, irVariable.endOffset, irVariable.descriptor, irOperator) + ) : this(irBodyGenerator, irVariable.startOffset, irVariable.endOffset, irVariable.descriptor, irOperator) override val type: KotlinType? get() = descriptor.type override fun load(): IrExpression = - IrGetVariableExpressionImpl(startOffset, endOffset, descriptor, irOperator) + IrGetVariableImpl(startOffset, endOffset, descriptor, irOperator) override fun store(irExpression: IrExpression): IrExpression = - IrSetVariableExpressionImpl(startOffset, endOffset, descriptor, - irExpression.toExpectedType(descriptor.type), irOperator) + IrSetVariableImpl(startOffset, endOffset, descriptor, + irBodyGenerator.toExpectedType(irExpression, descriptor.type), irOperator) } \ No newline at end of file diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/FoldStringConcatenation.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/FoldStringConcatenation.kt index d1e0c81c130..725e72d4787 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/FoldStringConcatenation.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/FoldStringConcatenation.kt @@ -20,10 +20,10 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.detach -import org.jetbrains.kotlin.ir.expressions.IrCallExpression +import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.IrStringConcatenationExpression -import org.jetbrains.kotlin.ir.expressions.IrStringConcatenationExpressionImpl +import org.jetbrains.kotlin.ir.expressions.IrStringConcatenation +import org.jetbrains.kotlin.ir.expressions.IrStringConcatenationImpl import org.jetbrains.kotlin.ir.replaceWith import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.util.OperatorNameConventions @@ -38,7 +38,7 @@ class FoldStringConcatenation : IrElementVisitor { element.acceptChildren(this, data) } - override fun visitCallExpression(expression: IrCallExpression, data: Nothing?) { + override fun visitCall(expression: IrCall, data: Nothing?) { if (!isStringPlus(expression.descriptor)) { visitElement(expression, data) return @@ -46,7 +46,7 @@ class FoldStringConcatenation : IrElementVisitor { val arguments = ArrayList() collectStringConcatenationArguments(expression, arguments) - val irStringConcatenation = IrStringConcatenationExpressionImpl(expression.startOffset, expression.endOffset, expression.type) + val irStringConcatenation = IrStringConcatenationImpl(expression.startOffset, expression.endOffset, expression.type) arguments.forEach { irStringConcatenation.addArgument(it) } expression.replaceWith(irStringConcatenation) @@ -54,11 +54,11 @@ class FoldStringConcatenation : IrElementVisitor { private fun collectStringConcatenationArguments(expression: IrExpression, arguments: ArrayList) { when { - expression is IrCallExpression && isStringPlus(expression.descriptor)-> { + expression is IrCall && isStringPlus(expression.descriptor)-> { collectStringConcatenationArguments(expression.dispatchReceiver!!, arguments) collectStringConcatenationArguments(expression.getArgument(0)!!, arguments) } - expression is IrStringConcatenationExpression -> { + expression is IrStringConcatenation -> { arguments.addAll(expression.arguments) expression.arguments.forEach { it.detach() } } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InlineDesugaredBlocks.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InlineDesugaredBlocks.kt index 143ccca0be8..521a71fd568 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InlineDesugaredBlocks.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InlineDesugaredBlocks.kt @@ -18,8 +18,8 @@ package org.jetbrains.kotlin.psi2ir.transformations import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.detach -import org.jetbrains.kotlin.ir.expressions.IrBlockExpression -import org.jetbrains.kotlin.ir.expressions.IrBlockExpressionImpl +import org.jetbrains.kotlin.ir.expressions.IrBlock +import org.jetbrains.kotlin.ir.expressions.IrBlockImpl import org.jetbrains.kotlin.ir.replaceWith import org.jetbrains.kotlin.ir.visitors.IrElementVisitor @@ -32,14 +32,14 @@ class InlineDesugaredBlocks : IrElementVisitor { element.acceptChildren(this, data) } - override fun visitBlockExpression(expression: IrBlockExpression, data: Nothing?) { - val transformedBlock = IrBlockExpressionImpl( + override fun visitBlock(expression: IrBlock, data: Nothing?) { + val transformedBlock = IrBlockImpl( expression.startOffset, expression.endOffset, expression.type, expression.hasResult, expression.operator ) for (statement in expression.statements) { statement.accept(this, data) - if (statement is IrBlockExpression && statement.operator != null) { + if (statement is IrBlock && statement.operator != null) { statement.statements.forEach { transformedBlock.addStatement(it.detach()) } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrElement.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrElement.kt index 8c5f2794f8a..093dc3ea6e9 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrElement.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/IrElement.kt @@ -50,6 +50,7 @@ fun T.detach(): T { } fun IrElement.replaceWith(otherElement: IrElement) { + if (otherElement == this) return val parent = this.parent ?: throw AssertionError("Can't replace a non-root element $this") parent.replaceChild(slot, otherElement.detach()) } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt index 12062b50888..38ed8fe1112 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/descriptors/IrBuiltIns.kt @@ -17,23 +17,36 @@ package org.jetbrains.kotlin.ir.descriptors import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.TypeSubstitution class IrBuiltIns(val builtIns: KotlinBuiltIns) { val packageFragment = IrBuiltinsPackageFragmentDescriptorImpl(builtIns.builtInsModule) - val eqeqeq: IrBuiltinOperatorDescriptor - val eqeq: IrBuiltinOperatorDescriptor - val lt0: IrBuiltinOperatorDescriptor - val lteq0: IrBuiltinOperatorDescriptor - val gt0: IrBuiltinOperatorDescriptor - val gteq0: IrBuiltinOperatorDescriptor + val eqeqeq: FunctionDescriptor + val eqeq: FunctionDescriptor + val lt0: FunctionDescriptor + val lteq0: FunctionDescriptor + val gt0: FunctionDescriptor + val gteq0: FunctionDescriptor + val notNull: FunctionDescriptor + val throwNpe: FunctionDescriptor + + val booleanNot: FunctionDescriptor + + val implicitNotNull: CallableDescriptor // TODO drop init { val bool = builtIns.booleanType + val any = builtIns.anyType val anyN = builtIns.nullableAnyType val int = builtIns.intType + val nothing = builtIns.nothingType eqeqeq = defineOperator("EQEQEQ", bool, listOf(anyN, anyN)) eqeq = defineOperator("EQEQ", bool, listOf(anyN, anyN)) @@ -41,6 +54,13 @@ class IrBuiltIns(val builtIns: KotlinBuiltIns) { lteq0 = defineOperator("LTEQ0", bool, listOf(int)) gt0 = defineOperator("GT0", bool, listOf(int)) gteq0 = defineOperator("GTEQ0", bool, listOf(int)) + notNull = defineOperator("NOT_NULL", bool, listOf(anyN)) + throwNpe = defineOperator("THROW_NPE", nothing, listOf()) + + implicitNotNull = defineOperator("IMPLICIT_NOT_NULL", any, listOf(anyN)) + + // booleanNot = builtIns.boolean.findSingleFunction("not") // TODO requires receiver + booleanNot = defineOperator("NOT", bool, listOf(bool)) } private fun defineOperator(name: String, returnType: KotlinType, valueParameterTypes: List): IrBuiltinOperatorDescriptor { @@ -51,4 +71,9 @@ class IrBuiltIns(val builtIns: KotlinBuiltIns) { } return operatorDescriptor } + + private fun ClassDescriptor.findSingleFunction(name: String): FunctionDescriptor = + getMemberScope(TypeSubstitution.EMPTY).getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BUILTINS).single() + + } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBlockExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBlock.kt similarity index 88% rename from compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBlockExpression.kt rename to compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBlock.kt index 331ff1197e5..d941e2a2ca6 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBlockExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrBlock.kt @@ -22,24 +22,24 @@ import org.jetbrains.kotlin.types.KotlinType import java.util.* -interface IrBlockExpression : IrExpression { +interface IrBlock : IrExpression { val hasResult: Boolean val operator: IrOperator? val statements: List } -fun IrBlockExpressionImpl.addIfNotNull(statement: IrStatement?) { +fun IrBlockImpl.addIfNotNull(statement: IrStatement?) { if (statement != null) addStatement(statement) } -class IrBlockExpressionImpl( +class IrBlockImpl( startOffset: Int, endOffset: Int, type: KotlinType?, override val hasResult: Boolean, override val operator: IrOperator? = null -) : IrExpressionBase(startOffset, endOffset, type), IrBlockExpression { +) : IrExpressionBase(startOffset, endOffset, type), IrBlock { override val statements: MutableList = ArrayList() fun addStatement(statement: IrStatement) { @@ -61,7 +61,7 @@ class IrBlockExpressionImpl( } override fun accept(visitor: IrElementVisitor, data: D): R = - visitor.visitBlockExpression(this, data) + visitor.visitBlock(this, data) override fun acceptChildren(visitor: IrElementVisitor, data: D) { statements.forEach { it.accept(visitor, data) } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCallExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCall.kt similarity index 90% rename from compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCallExpression.kt rename to compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCall.kt index 898b59386dd..658281a7f88 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCallExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrCall.kt @@ -22,7 +22,7 @@ import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType -interface IrCallExpression : IrMemberAccessExpression { +interface IrCall : IrMemberAccessExpression { val superQualifier: ClassDescriptor? val operator: IrOperator? override val descriptor: CallableDescriptor @@ -32,7 +32,7 @@ interface IrCallExpression : IrMemberAccessExpression { fun removeArgument(index: Int) } -class IrCallExpressionImpl( +class IrCallImpl( startOffset: Int, endOffset: Int, type: KotlinType?, @@ -40,7 +40,7 @@ class IrCallExpressionImpl( isSafe: Boolean, override val operator: IrOperator? = null, override val superQualifier: ClassDescriptor? = null -) : IrMemberAccessExpressionBase(startOffset, endOffset, type, isSafe), IrCallExpression { +) : IrMemberAccessExpressionBase(startOffset, endOffset, type, isSafe), IrCall { private val argumentsByParameterIndex = arrayOfNulls(descriptor.valueParameters.size) @@ -76,7 +76,7 @@ class IrCallExpressionImpl( } override fun accept(visitor: IrElementVisitor, data: D): R = - visitor.visitCallExpression(this, data) + visitor.visitCall(this, data) override fun acceptChildren(visitor: IrElementVisitor, data: D) { super.acceptChildren(visitor, data) @@ -84,7 +84,7 @@ class IrCallExpressionImpl( } } -abstract class IrPropertyAccessorCallExpressionBase( +abstract class IrPropertyAccessorCallBase( startOffset: Int, endOffset: Int, type: KotlinType?, @@ -92,13 +92,13 @@ abstract class IrPropertyAccessorCallExpressionBase( isSafe: Boolean, override val operator: IrOperator? = null, override val superQualifier: ClassDescriptor? = null -) : IrMemberAccessExpressionBase(startOffset, endOffset, type, isSafe), IrCallExpression { +) : IrMemberAccessExpressionBase(startOffset, endOffset, type, isSafe), IrCall { override fun accept(visitor: IrElementVisitor, data: D): R { - return visitor.visitCallExpression(this, data) + return visitor.visitCall(this, data) } } -class IrGetterCallExpressionImpl( +class IrGetterCallImpl( startOffset: Int, endOffset: Int, type: KotlinType?, @@ -106,7 +106,7 @@ class IrGetterCallExpressionImpl( isSafe: Boolean, operator: IrOperator? = null, superQualifier: ClassDescriptor? = null -) : IrPropertyAccessorCallExpressionBase(startOffset, endOffset, type, descriptor, isSafe, operator, superQualifier), IrCallExpression { +) : IrPropertyAccessorCallBase(startOffset, endOffset, type, descriptor, isSafe, operator, superQualifier), IrCall { constructor( startOffset: Int, endOffset: Int, @@ -133,7 +133,7 @@ class IrGetterCallExpressionImpl( } } -class IrSetterCallExpressionImpl( +class IrSetterCallImpl( startOffset: Int, endOffset: Int, type: KotlinType?, @@ -141,7 +141,7 @@ class IrSetterCallExpressionImpl( isSafe: Boolean, operator: IrOperator? = null, superQualifier: ClassDescriptor? = null -) : IrPropertyAccessorCallExpressionBase(startOffset, endOffset, type, descriptor, isSafe, operator, superQualifier), IrCallExpression { +) : IrPropertyAccessorCallBase(startOffset, endOffset, type, descriptor, isSafe, operator, superQualifier), IrCall { constructor( startOffset: Int, endOffset: Int, diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConstExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConst.kt similarity index 72% rename from compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConstExpression.kt rename to compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConst.kt index f61e4c561b4..d67cad6bfee 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConstExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrConst.kt @@ -19,15 +19,15 @@ package org.jetbrains.kotlin.ir.expressions import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType -interface IrConstExpression : IrExpression { +interface IrConst : IrExpression { val kind: IrLiteralKind val value: T } sealed class IrLiteralKind(val asString: kotlin.String) { @Suppress("UNCHECKED_CAST") - fun valueOf(aConst: IrConstExpression<*>) = - (aConst as IrConstExpression).value + fun valueOf(aConst: IrConst<*>) = + (aConst as IrConst).value object Null : IrLiteralKind("Null") object Boolean : IrLiteralKind("Boolean") @@ -42,33 +42,33 @@ sealed class IrLiteralKind(val asString: kotlin.String) { override fun toString() = asString } -class IrConstExpressionImpl ( +class IrConstImpl ( startOffset: Int, endOffset: Int, type: KotlinType?, override val kind: IrLiteralKind, override val value: T -) : IrTerminalExpressionBase(startOffset, endOffset, type), IrConstExpression { +) : IrTerminalExpressionBase(startOffset, endOffset, type), IrConst { override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitConst(this, data) companion object { - fun string(startOffset: Int, endOffset: Int, type: KotlinType, value: String): IrConstExpressionImpl = - IrConstExpressionImpl(startOffset, endOffset, type, IrLiteralKind.String, value) + fun string(startOffset: Int, endOffset: Int, type: KotlinType, value: String): IrConstImpl = + IrConstImpl(startOffset, endOffset, type, IrLiteralKind.String, value) - fun int(startOffset: Int, endOffset: Int, type: KotlinType, value: Int): IrConstExpressionImpl = - IrConstExpressionImpl(startOffset, endOffset, type, IrLiteralKind.Int, value) + fun int(startOffset: Int, endOffset: Int, type: KotlinType, value: Int): IrConstImpl = + IrConstImpl(startOffset, endOffset, type, IrLiteralKind.Int, value) - fun constNull(startOffset: Int, endOffset: Int, type: KotlinType): IrConstExpressionImpl = - IrConstExpressionImpl(startOffset, endOffset, type, IrLiteralKind.Null, null) + fun constNull(startOffset: Int, endOffset: Int, type: KotlinType): IrConstImpl = + IrConstImpl(startOffset, endOffset, type, IrLiteralKind.Null, null) - fun boolean(startOffset: Int, endOffset: Int, type: KotlinType, value: Boolean): IrConstExpressionImpl = - IrConstExpressionImpl(startOffset, endOffset, type, IrLiteralKind.Boolean, value) + fun boolean(startOffset: Int, endOffset: Int, type: KotlinType, value: Boolean): IrConstImpl = + IrConstImpl(startOffset, endOffset, type, IrLiteralKind.Boolean, value) - fun constTrue(startOffset: Int, endOffset: Int, type: KotlinType): IrConstExpressionImpl = + fun constTrue(startOffset: Int, endOffset: Int, type: KotlinType): IrConstImpl = boolean(startOffset, endOffset, type, true) - fun constFalse(startOffset: Int, endOffset: Int, type: KotlinType): IrConstExpressionImpl = + fun constFalse(startOffset: Int, endOffset: Int, type: KotlinType): IrConstImpl = boolean(startOffset, endOffset, type, false) } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDeclarationReference.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDeclarationReference.kt index 9494c838a6f..4afc54e14f3 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDeclarationReference.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrDeclarationReference.kt @@ -28,13 +28,13 @@ interface IrDeclarationReference : IrExpression { val descriptor: DeclarationDescriptor } -interface IrGetSingletonValueExpression : IrDeclarationReference { +interface IrGetSingletonValue : IrDeclarationReference { override val descriptor: ClassDescriptor } -interface IrGetObjectValueExpression : IrGetSingletonValueExpression +interface IrGetObjectValue : IrGetSingletonValue -interface IrGetEnumValueExpression : IrGetSingletonValueExpression +interface IrGetEnumValue : IrGetSingletonValue abstract class IrDeclarationReferenceBase( startOffset: Int, @@ -60,22 +60,22 @@ abstract class IrTerminalDeclarationReferenceBase } } -class IrGetObjectValueExpressionImpl( +class IrGetObjectValueImpl( startOffset: Int, endOffset: Int, type: KotlinType?, descriptor: ClassDescriptor -) : IrTerminalDeclarationReferenceBase(startOffset, endOffset, type, descriptor), IrGetObjectValueExpression { +) : IrTerminalDeclarationReferenceBase(startOffset, endOffset, type, descriptor), IrGetObjectValue { override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitGetObjectValue(this, data) } -class IrGetEnumValueExpressionImpl( +class IrGetEnumValueImpl( startOffset: Int, endOffset: Int, type: KotlinType?, descriptor: ClassDescriptor -) : IrTerminalDeclarationReferenceBase(startOffset, endOffset, type, descriptor), IrGetEnumValueExpression { +) : IrTerminalDeclarationReferenceBase(startOffset, endOffset, type, descriptor), IrGetEnumValue { override fun accept(visitor: IrElementVisitor, data: D): R { return visitor.visitGetEnumValue(this, data) } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrGetExtensionReceiverExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrGetExtensionReceiver.kt similarity index 90% rename from compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrGetExtensionReceiverExpression.kt rename to compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrGetExtensionReceiver.kt index 37f0f2c76a3..5a7fca3f38c 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrGetExtensionReceiverExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrGetExtensionReceiver.kt @@ -20,16 +20,16 @@ import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType -interface IrGetExtensionReceiverExpression : IrDeclarationReference { +interface IrGetExtensionReceiver : IrDeclarationReference { override val descriptor: ReceiverParameterDescriptor } -class IrGetExtensionReceiverExpressionImpl( +class IrGetExtensionReceiverImpl( startOffset: Int, endOffset: Int, type: KotlinType?, descriptor: ReceiverParameterDescriptor -) : IrTerminalDeclarationReferenceBase(startOffset, endOffset, type, descriptor), IrGetExtensionReceiverExpression { +) : IrTerminalDeclarationReferenceBase(startOffset, endOffset, type, descriptor), IrGetExtensionReceiver { override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitGetExtensionReceiver(this, data) } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrIfExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrIfThenElse.kt similarity index 75% rename from compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrIfExpression.kt rename to compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrIfThenElse.kt index b4efe9d40ec..ebd72d15e90 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrIfExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrIfThenElse.kt @@ -23,19 +23,19 @@ import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.utils.SmartList import java.util.* -interface IrIfExpression : IrExpression { +interface IrIfThenElse : IrExpression { val operator: IrOperator? var condition: IrExpression var thenBranch: IrExpression var elseBranch: IrExpression? } -class IrIfExpressionImpl( +class IrIfThenElseImpl( startOffset: Int, endOffset: Int, type: KotlinType?, override val operator: IrOperator? = null -) : IrExpressionBase(startOffset, endOffset, type), IrIfExpression { +) : IrExpressionBase(startOffset, endOffset, type), IrIfThenElse { constructor( startOffset: Int, endOffset: Int, @@ -109,18 +109,25 @@ class IrIfExpressionImpl( companion object { // a || b == if (a) true else b - fun oror(a: IrExpression, b: IrExpression, operator: IrOperator = IrOperator.OROR): IrIfExpression = - IrIfExpressionImpl(b.startOffset, b.endOffset, b.type!!, - a, IrConstExpressionImpl.constTrue(b.startOffset, b.endOffset, b.type!!), b, - operator) + fun oror(startOffset: Int, endOffset: Int, a: IrExpression, b: IrExpression, operator: IrOperator = IrOperator.OROR): IrIfThenElse = + IrIfThenElseImpl(startOffset, endOffset, b.type!!, + a, IrConstImpl.constTrue(b.startOffset, b.endOffset, b.type!!), b, + operator) + + fun oror(a: IrExpression, b: IrExpression, operator: IrOperator = IrOperator.OROR): IrIfThenElse = + oror(b.startOffset, b.endOffset, a, b, operator) + + fun whenComma(a: IrExpression, b: IrExpression): IrIfThenElse = + oror(a, b, IrOperator.WHEN_COMMA) // a && b == if (a) b else false - fun andand(a: IrExpression, b: IrExpression): IrIfExpression = - IrIfExpressionImpl(b.startOffset, b.endOffset, b.type!!, - a, b, IrConstExpressionImpl.constFalse(b.startOffset, b.endOffset, b.type!!), - IrOperator.OROR) + fun andand(startOffset: Int, endOffset: Int, a: IrExpression, b: IrExpression, operator: IrOperator = IrOperator.ANDAND): IrIfThenElse = + IrIfThenElseImpl(startOffset, endOffset, b.type!!, + a, b, IrConstImpl.constFalse(b.startOffset, b.endOffset, b.type!!), + operator) + + fun andand(a: IrExpression, b: IrExpression, operator: IrOperator = IrOperator.ANDAND): IrIfThenElse = + andand(b.startOffset, b.endOffset, a, b, operator) - fun whenComma(a: IrExpression, b: IrExpression): IrIfExpression = - oror(a, b, IrOperator.WHEN_COMMA) } } diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrLoopExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrLoop.kt similarity index 83% rename from compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrLoopExpression.kt rename to compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrLoop.kt index b3c88fff907..9e76b41c1ef 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrLoopExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrLoop.kt @@ -19,22 +19,22 @@ package org.jetbrains.kotlin.ir.expressions import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitor -interface IrLoopExpression : IrExpression { +interface IrLoop : IrExpression { var body: IrExpression } -interface IrConditionalLoopExpression : IrLoopExpression { +interface IrConditionalLoop : IrLoop { var condition: IrExpression } -interface IrWhileLoopExpression : IrConditionalLoopExpression +interface IrWhileLoop : IrConditionalLoop -interface IrDoWhileLoopExpression : IrConditionalLoopExpression +interface IrDoWhileLoop : IrConditionalLoop -abstract class IrLoopExpressionBase( +abstract class IrLoopBase( startOffset: Int, endOffset: Int -) : IrExpressionBase(startOffset, endOffset, null), IrLoopExpression { +) : IrExpressionBase(startOffset, endOffset, null), IrLoop { private var bodyImpl: IrExpression? = null @@ -60,10 +60,10 @@ abstract class IrLoopExpressionBase( } } -abstract class IrConditionalLoopExpressionBase( +abstract class IrConditionalLoopBase( startOffset: Int, endOffset: Int -) : IrLoopExpressionBase(startOffset, endOffset), IrConditionalLoopExpression { +) : IrLoopBase(startOffset, endOffset), IrConditionalLoop { private var conditionImpl: IrExpression? = null override var condition: IrExpression get() = conditionImpl!! @@ -88,10 +88,10 @@ abstract class IrConditionalLoopExpressionBase( } } -class IrWhileLoopExpressionImpl( +class IrWhileLoopImpl( startOffset: Int, endOffset: Int -) : IrConditionalLoopExpressionBase(startOffset, endOffset), IrWhileLoopExpression { +) : IrConditionalLoopBase(startOffset, endOffset), IrWhileLoop { constructor( startOffset: Int, endOffset: Int, @@ -112,10 +112,10 @@ class IrWhileLoopExpressionImpl( } } -class IrDoWhileLoopExpressionImpl( +class IrDoWhileLoopImpl( startOffset: Int, endOffset: Int -) : IrConditionalLoopExpressionBase(startOffset, endOffset), IrDoWhileLoopExpression { +) : IrConditionalLoopBase(startOffset, endOffset), IrDoWhileLoop { constructor( startOffset: Int, endOffset: Int, diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperatorExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperatorExpression.kt index a7fd09fd926..11c63ac3152 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperatorExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrOperatorExpression.kt @@ -17,46 +17,78 @@ package org.jetbrains.kotlin.ir.expressions import org.jetbrains.kotlin.descriptors.CallableDescriptor +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType -interface IrOperatorExpression : IrExpression { - val operator: IrOperator - val relatedDescriptor: CallableDescriptor? -} - -interface IrUnaryOperatorExpression : IrOperatorExpression { - override val operator: IrOperator - var argument: IrExpression -} - -interface IrBinaryOperatorExpression : IrOperatorExpression { - override val operator: IrOperator - var argument0: IrExpression - var argument1: IrExpression -} - -class IrUnaryOperatorExpressionImpl( +abstract class IrOperatorCallBase( startOffset: Int, endOffset: Int, - type: KotlinType?, override val operator: IrOperator, - override val relatedDescriptor: CallableDescriptor? -) : IrExpressionBase(startOffset, endOffset, type), IrUnaryOperatorExpression { + override val descriptor: CallableDescriptor +) : IrExpressionBase(startOffset, endOffset, descriptor.returnType), IrCall { + override val superQualifier: ClassDescriptor? get() = null + override var dispatchReceiver: IrExpression? + get() = null + set(value) = throw UnsupportedOperationException("Operator call expression can't have a receiver") + + override val isSafe: Boolean get() = false + + override var extensionReceiver: IrExpression? + get() = null + set(value) = throw UnsupportedOperationException("Operator call expression can't have a receiver") + + override fun getArgument(index: Int): IrExpression? = getChild(index)?.assertCast() + + override fun putArgument(index: Int, valueArgument: IrExpression?) { + replaceChild(index, valueArgument ?: throw AssertionError("Operator call expression can't have a default argument")) + } + + override fun removeArgument(index: Int) { + throw AssertionError("Operator call expression can't have a default argument") + } + + override fun accept(visitor: IrElementVisitor, data: D): R { + return visitor.visitCall(this, data) + } +} + +class IrNullaryOperatorImpl constructor( + startOffset: Int, + endOffset: Int, + operator: IrOperator, + descriptor: CallableDescriptor +) : IrOperatorCallBase(startOffset, endOffset, operator, descriptor) { + override fun getChild(slot: Int): IrElement? = null + + override fun replaceChild(slot: Int, newChild: IrElement) { + // no children + } + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + // no children + } +} + +class IrUnaryOperatorImpl private constructor( + startOffset: Int, + endOffset: Int, + operator: IrOperator, + descriptor: CallableDescriptor +) : IrOperatorCallBase(startOffset, endOffset, operator, descriptor) { constructor( startOffset: Int, endOffset: Int, - type: KotlinType?, operator: IrOperator, - relatedDescriptor: CallableDescriptor?, + descriptor: CallableDescriptor, argument: IrExpression - ) : this(startOffset, endOffset, type, operator, relatedDescriptor) { + ) : this(startOffset, endOffset, operator, descriptor) { this.argument = argument } private var argumentImpl: IrExpression? = null - override var argument: IrExpression + var argument: IrExpression get() = argumentImpl!! set(value) { value.assertDetached() @@ -78,37 +110,31 @@ class IrUnaryOperatorExpressionImpl( } } - override fun accept(visitor: IrElementVisitor, data: D): R { - return visitor.visitUnaryOperator(this, data) - } - override fun acceptChildren(visitor: IrElementVisitor, data: D) { argument.accept(visitor, data) } } -class IrBinaryOperatorExpressionImpl( +class IrBinaryOperatorImpl( startOffset: Int, endOffset: Int, - type: KotlinType?, - override val operator: IrOperator, - override val relatedDescriptor: CallableDescriptor? -) : IrExpressionBase(startOffset, endOffset, type), IrBinaryOperatorExpression { + operator: IrOperator, + descriptor: CallableDescriptor +) : IrOperatorCallBase(startOffset, endOffset, operator, descriptor) { constructor( startOffset: Int, endOffset: Int, - type: KotlinType?, operator: IrOperator, - relatedDescriptor: CallableDescriptor?, + descriptor: CallableDescriptor, argument0: IrExpression, argument1: IrExpression - ) : this(startOffset, endOffset, type, operator, relatedDescriptor) { + ) : this(startOffset, endOffset, operator, descriptor) { this.argument0 = argument0 this.argument1 = argument1 } private var argument0Impl: IrExpression? = null - override var argument0: IrExpression + var argument0: IrExpression get() = argument0Impl!! set(value) { value.assertDetached() @@ -118,7 +144,7 @@ class IrBinaryOperatorExpressionImpl( } private var argument1Impl: IrExpression? = null - override var argument1: IrExpression + var argument1: IrExpression get() = argument1Impl!! set(value) { value.assertDetached() @@ -143,7 +169,7 @@ class IrBinaryOperatorExpressionImpl( } override fun accept(visitor: IrElementVisitor, data: D): R = - visitor.visitBinaryOperator(this, data) + visitor.visitCall(this, data) override fun acceptChildren(visitor: IrElementVisitor, data: D) { argument0.accept(visitor, data) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrReturnExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrReturn.kt similarity index 91% rename from compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrReturnExpression.kt rename to compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrReturn.kt index e9a06c12bd4..7cbabdb0255 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrReturnExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrReturn.kt @@ -22,16 +22,16 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType -interface IrReturnExpression : IrExpression { +interface IrReturn : IrExpression { var value: IrExpression? val returnTarget: CallableDescriptor } -class IrReturnExpressionImpl( +class IrReturnImpl( startOffset: Int, endOffset: Int, override val returnTarget: CallableDescriptor -) : IrExpressionBase(startOffset, endOffset, null), IrReturnExpression { +) : IrExpressionBase(startOffset, endOffset, null), IrReturn { constructor( startOffset: Int, endOffset: Int, @@ -63,7 +63,7 @@ class IrReturnExpressionImpl( } override fun accept(visitor: IrElementVisitor, data: D): R = - visitor.visitReturnExpression(this, data) + visitor.visitReturn(this, data) override fun acceptChildren(visitor: IrElementVisitor, data: D) { value?.accept(visitor, data) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrStringConcatenationExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrStringConcatenation.kt similarity index 94% rename from compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrStringConcatenationExpression.kt rename to compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrStringConcatenation.kt index 023942e101b..0cf63a72978 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrStringConcatenationExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrStringConcatenation.kt @@ -21,16 +21,16 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType import java.util.* -interface IrStringConcatenationExpression : IrExpression { +interface IrStringConcatenation : IrExpression { val arguments: List fun addArgument(argument: IrExpression) } -class IrStringConcatenationExpressionImpl( +class IrStringConcatenationImpl( startOffset: Int, endOffset: Int, type: KotlinType? -) : IrExpressionBase(startOffset, endOffset, type), IrStringConcatenationExpression { +) : IrExpressionBase(startOffset, endOffset, type), IrStringConcatenation { override val arguments: MutableList = ArrayList() override fun addArgument(argument: IrExpression) { diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrThisExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrThisReference.kt similarity index 88% rename from compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrThisExpression.kt rename to compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrThisReference.kt index 33ea0dd30dc..db28aefa99a 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrThisExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrThisReference.kt @@ -20,16 +20,16 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType -interface IrThisExpression : IrExpression { +interface IrThisReference : IrExpression { val classDescriptor: ClassDescriptor } -class IrThisExpressionImpl( +class IrThisReferenceImpl( startOffset: Int, endOffset: Int, type: KotlinType?, override val classDescriptor: ClassDescriptor -) : IrTerminalExpressionBase(startOffset, endOffset, type), IrThisExpression { +) : IrTerminalExpressionBase(startOffset, endOffset, type), IrThisReference { override fun accept(visitor: IrElementVisitor, data: D): R = - visitor.visitThisExpression(this, data) + visitor.visitThisReference(this, data) } \ No newline at end of file diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorCall.kt similarity index 93% rename from compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorExpression.kt rename to compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorCall.kt index 6c27298d293..848680604f3 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrTypeOperatorCall.kt @@ -28,19 +28,19 @@ enum class IrTypeOperator { NOT_INSTANCEOF; } -interface IrTypeOperatorExpression : IrExpression { +interface IrTypeOperatorCall : IrExpression { val operator: IrTypeOperator var argument: IrExpression val typeOperand: KotlinType } -class IrTypeOperatorExpressionImpl( +class IrTypeOperatorCallImpl( startOffset: Int, endOffset: Int, type: KotlinType?, override val operator: IrTypeOperator, override val typeOperand: KotlinType -) : IrExpressionBase(startOffset, endOffset, type), IrTypeOperatorExpression { +) : IrExpressionBase(startOffset, endOffset, type), IrTypeOperatorCall { constructor( startOffset: Int, endOffset: Int, @@ -76,7 +76,7 @@ class IrTypeOperatorExpressionImpl( } override fun accept(visitor: IrElementVisitor, data: D): R = - visitor.visitTypeOperatorExpression(this, data) + visitor.visitTypeOperator(this, data) override fun acceptChildren(visitor: IrElementVisitor, data: D) { argument.accept(visitor, data) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrVariableAccessExpression.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrVariableAccessExpression.kt index d3a2986bd7c..53626413655 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrVariableAccessExpression.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/IrVariableAccessExpression.kt @@ -26,29 +26,29 @@ interface IrVariableAccessExpression : IrDeclarationReference { val operator: IrOperator? } -interface IrGetVariableExpression : IrVariableAccessExpression +interface IrGetVariable : IrVariableAccessExpression -interface IrSetVariableExpression : IrVariableAccessExpression { +interface IrSetVariable : IrVariableAccessExpression { val value: IrExpression } -class IrGetVariableExpressionImpl( +class IrGetVariableImpl( startOffset: Int, endOffset: Int, descriptor: VariableDescriptor, override val operator: IrOperator? = null -) : IrTerminalDeclarationReferenceBase(startOffset, endOffset, descriptor.type, descriptor), IrGetVariableExpression { +) : IrTerminalDeclarationReferenceBase(startOffset, endOffset, descriptor.type, descriptor), IrGetVariable { override fun accept(visitor: IrElementVisitor, data: D): R = visitor.visitGetVariable(this, data) } -class IrSetVariableExpressionImpl( +class IrSetVariableImpl( startOffset: Int, endOffset: Int, override val descriptor: VariableDescriptor, override val operator: IrOperator? -) : IrExpressionBase(startOffset, endOffset, null), IrSetVariableExpression { +) : IrExpressionBase(startOffset, endOffset, null), IrSetVariable { constructor( startOffset: Int, endOffset: Int, diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt index 9fffe93840f..939ee8e0ef1 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/DumpIrTree.kt @@ -19,8 +19,8 @@ package org.jetbrains.kotlin.ir.util import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.SourceLocationManager import org.jetbrains.kotlin.ir.declarations.IrFile -import org.jetbrains.kotlin.ir.expressions.IrCallExpression -import org.jetbrains.kotlin.ir.expressions.IrIfExpression +import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.expressions.IrIfThenElse import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.utils.Printer @@ -44,7 +44,7 @@ class DumpIrTreeVisitor(out: Appendable): IrElementVisitor { element.dumpLabeledSubTree(data) } - override fun visitCallExpression(expression: IrCallExpression, data: String) { + override fun visitCall(expression: IrCall, data: String) { expression.dumpLabeledElementWith(data) { expression.dispatchReceiver?.accept(this, "\$this") expression.extensionReceiver?.accept(this, "\$receiver") @@ -54,7 +54,7 @@ class DumpIrTreeVisitor(out: Appendable): IrElementVisitor { } } - override fun visitIf(expression: IrIfExpression, data: String) { + override fun visitIf(expression: IrIfThenElse, data: String) { expression.dumpLabeledElementWith(data) { expression.condition.accept(this, "if") expression.thenBranch.accept(this, "then") diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt index 7a54671270f..8f64d050eec 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/util/RenderIrElement.kt @@ -60,54 +60,44 @@ class RenderIrElementVisitor : IrElementVisitor { override fun visitExpression(expression: IrExpression, data: Nothing?): String = "? ${expression.javaClass.simpleName} type=${expression.renderType()}" - override fun visitConst(expression: IrConstExpression, data: Nothing?): String = + override fun visitConst(expression: IrConst, data: Nothing?): String = "LITERAL ${expression.kind} type=${expression.renderType()} value='${expression.value}'" - override fun visitBlockExpression(expression: IrBlockExpression, data: Nothing?): String = + override fun visitBlock(expression: IrBlock, data: Nothing?): String = "BLOCK type=${expression.renderType()} hasResult=${expression.hasResult} operator=${expression.operator}" - override fun visitReturnExpression(expression: IrReturnExpression, data: Nothing?): String = + override fun visitReturn(expression: IrReturn, data: Nothing?): String = "RETURN type=${expression.renderType()}" - override fun visitGetExtensionReceiver(expression: IrGetExtensionReceiverExpression, data: Nothing?): String = + override fun visitGetExtensionReceiver(expression: IrGetExtensionReceiver, data: Nothing?): String = "\$RECEIVER of: ${expression.descriptor.containingDeclaration.name} type=${expression.renderType()}" - override fun visitThisExpression(expression: IrThisExpression, data: Nothing?): String = + override fun visitThisReference(expression: IrThisReference, data: Nothing?): String = "THIS ${expression.classDescriptor.render()} type=${expression.renderType()}" - override fun visitCallExpression(expression: IrCallExpression, data: Nothing?): String = + override fun visitCall(expression: IrCall, data: Nothing?): String = "CALL ${if (expression.isSafe) "?." else "."}${expression.descriptor.name} " + "type=${expression.renderType()} operator=${expression.operator}" - override fun visitGetVariable(expression: IrGetVariableExpression, data: Nothing?): String = + override fun visitGetVariable(expression: IrGetVariable, data: Nothing?): String = "GET_VAR ${expression.descriptor.name} type=${expression.renderType()} operator=${expression.operator}" - override fun visitSetVariable(expression: IrSetVariableExpression, data: Nothing?): String = + override fun visitSetVariable(expression: IrSetVariable, data: Nothing?): String = "SET_VAR ${expression.descriptor.name} type=${expression.renderType()} operator=${expression.operator}" - override fun visitGetObjectValue(expression: IrGetObjectValueExpression, data: Nothing?): String = + override fun visitGetObjectValue(expression: IrGetObjectValue, data: Nothing?): String = "GET_OBJECT ${expression.descriptor.name} type=${expression.renderType()}" - override fun visitGetEnumValue(expression: IrGetEnumValueExpression, data: Nothing?): String = + override fun visitGetEnumValue(expression: IrGetEnumValue, data: Nothing?): String = "GET_ENUM_VALUE ${expression.descriptor.name} type=${expression.renderType()}" - override fun visitUnaryOperator(expression: IrUnaryOperatorExpression, data: Nothing?): String = - "UNARY_OP operator=${expression.operator} " + - "type=${expression.renderType()} " + - "related=${expression.relatedDescriptor?.render()}" - - override fun visitBinaryOperator(expression: IrBinaryOperatorExpression, data: Nothing?): String = - "BINARY_OP operator=${expression.operator} " + - "type=${expression.renderType()} " + - "related=${expression.relatedDescriptor?.render()}" - - override fun visitStringConcatenation(expression: IrStringConcatenationExpression, data: Nothing?): String = + override fun visitStringConcatenation(expression: IrStringConcatenation, data: Nothing?): String = "STRING_CONCATENATION type=${expression.renderType()}" - override fun visitTypeOperatorExpression(expression: IrTypeOperatorExpression, data: Nothing?): String = + override fun visitTypeOperator(expression: IrTypeOperatorCall, data: Nothing?): String = "TYPE_OP operator=${expression.operator} typeOperand=${expression.typeOperand.render()}" - override fun visitIf(expression: IrIfExpression, data: Nothing?): String = + override fun visitIf(expression: IrIfThenElse, data: Nothing?): String = "IF type=${expression.type.render()} operator=${expression.operator}" override fun visitDummyDeclaration(declaration: IrDummyDeclaration, data: Nothing?): String = diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt index 3977d4d0fc5..d288bf616d3 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitor.kt @@ -39,30 +39,27 @@ interface IrElementVisitor { fun visitExpressionBody(body: IrExpressionBody, data: D): R = visitBody(body, data) fun visitExpression(expression: IrExpression, data: D): R = visitElement(expression, data) - fun visitConst(expression: IrConstExpression, data: D): R = visitExpression(expression, data) - fun visitReturnExpression(expression: IrReturnExpression, data: D): R = visitExpression(expression, data) - fun visitBlockExpression(expression: IrBlockExpression, data: D): R = visitExpression(expression, data) - fun visitStringConcatenation(expression: IrStringConcatenationExpression, data: D) = visitExpression(expression, data) - fun visitThisExpression(expression: IrThisExpression, data: D) = visitExpression(expression, data) + fun visitConst(expression: IrConst, data: D): R = visitExpression(expression, data) + fun visitReturn(expression: IrReturn, data: D): R = visitExpression(expression, data) + fun visitBlock(expression: IrBlock, data: D): R = visitExpression(expression, data) + fun visitStringConcatenation(expression: IrStringConcatenation, data: D) = visitExpression(expression, data) + fun visitThisReference(expression: IrThisReference, data: D) = visitExpression(expression, data) fun visitDeclarationReference(expression: IrDeclarationReference, data: D) = visitExpression(expression, data) - fun visitSingletonReference(expression: IrGetSingletonValueExpression, data: D) = visitDeclarationReference(expression, data) - fun visitGetObjectValue(expression: IrGetObjectValueExpression, data: D) = visitSingletonReference(expression, data) - fun visitGetEnumValue(expression: IrGetEnumValueExpression, data: D) = visitSingletonReference(expression, data) - fun visitGetVariable(expression: IrGetVariableExpression, data: D) = visitDeclarationReference(expression, data) - fun visitSetVariable(expression: IrSetVariableExpression, data: D) = visitDeclarationReference(expression, data) - fun visitGetExtensionReceiver(expression: IrGetExtensionReceiverExpression, data: D) = visitDeclarationReference(expression, data) - fun visitCallExpression(expression: IrCallExpression, data: D) = visitDeclarationReference(expression, data) + fun visitSingletonReference(expression: IrGetSingletonValue, data: D) = visitDeclarationReference(expression, data) + fun visitGetObjectValue(expression: IrGetObjectValue, data: D) = visitSingletonReference(expression, data) + fun visitGetEnumValue(expression: IrGetEnumValue, data: D) = visitSingletonReference(expression, data) + fun visitGetVariable(expression: IrGetVariable, data: D) = visitDeclarationReference(expression, data) + fun visitSetVariable(expression: IrSetVariable, data: D) = visitDeclarationReference(expression, data) + fun visitGetExtensionReceiver(expression: IrGetExtensionReceiver, data: D) = visitDeclarationReference(expression, data) + fun visitCall(expression: IrCall, data: D) = visitDeclarationReference(expression, data) - fun visitOperatorExpression(expression: IrOperatorExpression, data: D) = visitExpression(expression, data) - fun visitUnaryOperator(expression: IrUnaryOperatorExpression, data: D) = visitOperatorExpression(expression, data) - fun visitBinaryOperator(expression: IrBinaryOperatorExpression, data: D) = visitOperatorExpression(expression, data) - fun visitTypeOperatorExpression(expression: IrTypeOperatorExpression, data: D) = visitExpression(expression, data) + fun visitTypeOperator(expression: IrTypeOperatorCall, data: D) = visitExpression(expression, data) - fun visitIf(expression: IrIfExpression, data: D) = visitExpression(expression, data) - fun visitLoop(loop: IrLoopExpression, data: D) = visitExpression(loop, data) - fun visitWhileLoop(loop: IrWhileLoopExpression, data: D) = visitLoop(loop, data) - fun visitDoWhileLoop(loop: IrDoWhileLoopExpression, data: D) = visitLoop(loop, data) + fun visitIf(expression: IrIfThenElse, data: D) = visitExpression(expression, data) + fun visitLoop(loop: IrLoop, data: D) = visitExpression(loop, data) + fun visitWhileLoop(loop: IrWhileLoop, data: D) = visitLoop(loop, data) + fun visitDoWhileLoop(loop: IrDoWhileLoop, data: D) = visitLoop(loop, data) // NB Use it only for testing purposes; will be removed as soon as all Kotlin expression types are covered fun visitDummyDeclaration(declaration: IrDummyDeclaration, data: D) = visitDeclaration(declaration, data) diff --git a/compiler/testData/ir/irText/booleanOperators.txt b/compiler/testData/ir/irText/booleanOperators.txt index d0eff01dfad..defcea5a186 100644 --- a/compiler/testData/ir/irText/booleanOperators.txt +++ b/compiler/testData/ir/irText/booleanOperators.txt @@ -3,16 +3,18 @@ IrFile /booleanOperators.kt IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=ANDAND type=kotlin.Boolean related=null - GET_VAR a type=kotlin.Boolean operator=null - GET_VAR b type=kotlin.Boolean operator=null + IF type=kotlin.Boolean operator=ANDAND + if: GET_VAR a type=kotlin.Boolean operator=null + then: GET_VAR b type=kotlin.Boolean operator=null + else: LITERAL Boolean type=kotlin.Boolean value='false' IrFunction public fun test2(/*0*/ a: kotlin.Boolean, /*1*/ b: kotlin.Boolean): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=OROR type=kotlin.Boolean related=null - GET_VAR a type=kotlin.Boolean operator=null - GET_VAR b type=kotlin.Boolean operator=null + IF type=kotlin.Boolean operator=OROR + if: GET_VAR a type=kotlin.Boolean operator=null + then: LITERAL Boolean type=kotlin.Boolean value='true' + else: GET_VAR b type=kotlin.Boolean operator=null IrFunction public fun test1x(/*0*/ a: kotlin.Boolean, /*1*/ b: kotlin.Boolean): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null diff --git a/compiler/testData/ir/irText/conventionComparisons.txt b/compiler/testData/ir/irText/conventionComparisons.txt index 2162065c9b3..74e03186403 100644 --- a/compiler/testData/ir/irText/conventionComparisons.txt +++ b/compiler/testData/ir/irText/conventionComparisons.txt @@ -5,39 +5,35 @@ IrFile /conventionComparisons.kt IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=GT type=kotlin.Boolean related=null - CALL .compareTo type=kotlin.Int operator=GT + CALL .GT0 type=kotlin.Boolean operator=GT + arg0: CALL .compareTo type=kotlin.Int operator=GT $this: $RECEIVER of: test1 type=IB $receiver: GET_VAR a1 type=IA operator=null other: GET_VAR a2 type=IA operator=null - LITERAL Int type=kotlin.Int value='0' IrFunction public fun IB.test2(/*0*/ a1: IA, /*1*/ a2: IA): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=GTEQ type=kotlin.Boolean related=null - CALL .compareTo type=kotlin.Int operator=GTEQ + CALL .GTEQ0 type=kotlin.Boolean operator=GTEQ + arg0: CALL .compareTo type=kotlin.Int operator=GTEQ $this: $RECEIVER of: test2 type=IB $receiver: GET_VAR a1 type=IA operator=null other: GET_VAR a2 type=IA operator=null - LITERAL Int type=kotlin.Int value='0' IrFunction public fun IB.test3(/*0*/ a1: IA, /*1*/ a2: IA): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=LT type=kotlin.Boolean related=null - CALL .compareTo type=kotlin.Int operator=LT + CALL .LT0 type=kotlin.Boolean operator=LT + arg0: CALL .compareTo type=kotlin.Int operator=LT $this: $RECEIVER of: test3 type=IB $receiver: GET_VAR a1 type=IA operator=null other: GET_VAR a2 type=IA operator=null - LITERAL Int type=kotlin.Int value='0' IrFunction public fun IB.test4(/*0*/ a1: IA, /*1*/ a2: IA): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=LTEQ type=kotlin.Boolean related=null - CALL .compareTo type=kotlin.Int operator=LTEQ + CALL .LTEQ0 type=kotlin.Boolean operator=LTEQ + arg0: CALL .compareTo type=kotlin.Int operator=LTEQ $this: $RECEIVER of: test4 type=IB $receiver: GET_VAR a1 type=IA operator=null other: GET_VAR a2 type=IA operator=null - LITERAL Int type=kotlin.Int value='0' diff --git a/compiler/testData/ir/irText/elvis.txt b/compiler/testData/ir/irText/elvis.txt index 0874ebfd721..66e8abecfd2 100644 --- a/compiler/testData/ir/irText/elvis.txt +++ b/compiler/testData/ir/irText/elvis.txt @@ -3,16 +3,12 @@ IrFile /elvis.kt IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=ELVIS type=kotlin.Any related=null - GET_VAR a type=kotlin.Any? operator=null - GET_VAR b type=kotlin.Any operator=null + DUMMY elvis type=kotlin.Any IrFunction public fun test2(/*0*/ a: kotlin.String?, /*1*/ b: kotlin.Any): kotlin.Any IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=ELVIS type=kotlin.Any related=null - GET_VAR a type=kotlin.String? operator=null - GET_VAR b type=kotlin.Any operator=null + DUMMY elvis type=kotlin.Any IrFunction public fun test3(/*0*/ a: kotlin.Any?, /*1*/ b: kotlin.Any?): kotlin.String IrExpressionBody BLOCK type= hasResult=false operator=null @@ -27,8 +23,4 @@ IrFile /elvis.kt then: RETURN type= LITERAL String type=kotlin.String value='' RETURN type= - BINARY_OP operator=ELVIS type=kotlin.String related=null - TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String? - GET_VAR a type=kotlin.Any? operator=null - TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String - GET_VAR b type=kotlin.Any? operator=null + DUMMY elvis type=kotlin.String diff --git a/compiler/testData/ir/irText/equality.txt b/compiler/testData/ir/irText/equality.txt index 32f00030bc4..ad40677b58a 100644 --- a/compiler/testData/ir/irText/equality.txt +++ b/compiler/testData/ir/irText/equality.txt @@ -3,20 +3,21 @@ IrFile /equality.kt IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=EQEQ type=kotlin.Boolean related=public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean - GET_VAR a type=kotlin.Int operator=null - GET_VAR b type=kotlin.Int operator=null + CALL .EQEQ type=kotlin.Boolean operator=EQEQ + arg0: GET_VAR a type=kotlin.Int operator=null + arg1: GET_VAR b type=kotlin.Int operator=null IrFunction public fun test2(/*0*/ a: kotlin.Int, /*1*/ b: kotlin.Int): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=EXCLEQ type=kotlin.Boolean related=public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean - GET_VAR a type=kotlin.Int operator=null - GET_VAR b type=kotlin.Int operator=null + CALL .NOT type=kotlin.Boolean operator=EXCLEQ + arg0: CALL .EQEQ type=kotlin.Boolean operator=EXCLEQ + arg0: GET_VAR a type=kotlin.Int operator=null + arg1: GET_VAR b type=kotlin.Int operator=null IrFunction public fun test3(/*0*/ a: kotlin.Any?, /*1*/ b: kotlin.Any?): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=EQEQ type=kotlin.Boolean related=public open operator fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean - GET_VAR a type=kotlin.Any? operator=null - GET_VAR b type=kotlin.Any? operator=null + CALL .EQEQ type=kotlin.Boolean operator=EQEQ + arg0: GET_VAR a type=kotlin.Any? operator=null + arg1: GET_VAR b type=kotlin.Any? operator=null diff --git a/compiler/testData/ir/irText/identity.txt b/compiler/testData/ir/irText/identity.txt index 47f43eb367e..f7ceb9f655c 100644 --- a/compiler/testData/ir/irText/identity.txt +++ b/compiler/testData/ir/irText/identity.txt @@ -3,20 +3,21 @@ IrFile /identity.kt IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=EQEQEQ type=kotlin.Boolean related=null - GET_VAR a type=kotlin.Int operator=null - GET_VAR b type=kotlin.Int operator=null + CALL .EQEQEQ type=kotlin.Boolean operator=EQEQEQ + arg0: GET_VAR a type=kotlin.Int operator=null + arg1: GET_VAR b type=kotlin.Int operator=null IrFunction public fun test2(/*0*/ a: kotlin.Int, /*1*/ b: kotlin.Int): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=EXCLEQEQ type=kotlin.Boolean related=null - GET_VAR a type=kotlin.Int operator=null - GET_VAR b type=kotlin.Int operator=null + CALL .NOT type=kotlin.Boolean operator=EXCL + arg0: CALL .EQEQEQ type=kotlin.Boolean operator=EXCLEQEQ + arg0: GET_VAR a type=kotlin.Int operator=null + arg1: GET_VAR b type=kotlin.Int operator=null IrFunction public fun test3(/*0*/ a: kotlin.Any?, /*1*/ b: kotlin.Any?): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=EQEQEQ type=kotlin.Boolean related=null - GET_VAR a type=kotlin.Any? operator=null - GET_VAR b type=kotlin.Any? operator=null + CALL .EQEQEQ type=kotlin.Boolean operator=EQEQEQ + arg0: GET_VAR a type=kotlin.Any? operator=null + arg1: GET_VAR b type=kotlin.Any? operator=null diff --git a/compiler/testData/ir/irText/ifElseIf.txt b/compiler/testData/ir/irText/ifElseIf.txt index 9a96f89af70..048fa926ff8 100644 --- a/compiler/testData/ir/irText/ifElseIf.txt +++ b/compiler/testData/ir/irText/ifElseIf.txt @@ -4,13 +4,15 @@ IrFile /ifElseIf.kt BLOCK type= hasResult=false operator=null RETURN type= IF type=kotlin.Int operator=IF - if: BINARY_OP operator=GT type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Int): kotlin.Int - GET_VAR i type=kotlin.Int operator=null - LITERAL Int type=kotlin.Int value='0' + if: CALL .GT0 type=kotlin.Boolean operator=GT + arg0: CALL .compareTo type=kotlin.Int operator=GT + $this: GET_VAR i type=kotlin.Int operator=null + other: LITERAL Int type=kotlin.Int value='0' then: LITERAL Int type=kotlin.Int value='1' else: IF type=kotlin.Int operator=IF - if: BINARY_OP operator=LT type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Int): kotlin.Int - GET_VAR i type=kotlin.Int operator=null - LITERAL Int type=kotlin.Int value='0' + if: CALL .LT0 type=kotlin.Boolean operator=LT + arg0: CALL .compareTo type=kotlin.Int operator=LT + $this: GET_VAR i type=kotlin.Int operator=null + other: LITERAL Int type=kotlin.Int value='0' then: DUMMY MINUS type=kotlin.Int else: LITERAL Int type=kotlin.Int value='0' diff --git a/compiler/testData/ir/irText/implicitCastOnPlatformType.txt b/compiler/testData/ir/irText/implicitCastOnPlatformType.txt index 359a5e58429..3699eaa09a8 100644 --- a/compiler/testData/ir/irText/implicitCastOnPlatformType.txt +++ b/compiler/testData/ir/irText/implicitCastOnPlatformType.txt @@ -3,6 +3,6 @@ IrFile /implicitCastOnPlatformType.kt IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - UNARY_OP operator=IMPLICIT_NOTNULL type=kotlin.String related=null - CALL .getProperty type=kotlin.String! operator=null + CALL .IMPLICIT_NOT_NULL type=kotlin.Any operator=IMPLICIT_NOTNULL + arg0: CALL .getProperty type=kotlin.String! operator=null p0: LITERAL String type=kotlin.String value='test' diff --git a/compiler/testData/ir/irText/in.txt b/compiler/testData/ir/irText/in.txt index ed7b0f9422b..f73fe6fba8a 100644 --- a/compiler/testData/ir/irText/in.txt +++ b/compiler/testData/ir/irText/in.txt @@ -10,8 +10,8 @@ IrFile /in.kt IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - UNARY_OP operator=EXCL type=kotlin.Boolean related=null - CALL .contains type=kotlin.Boolean operator=NOT_IN + CALL .NOT type=kotlin.Boolean operator=EXCL + arg0: CALL .contains type=kotlin.Boolean operator=NOT_IN $this: GET_VAR x type=kotlin.collections.Collection operator=null element: GET_VAR a type=kotlin.Any operator=null IrFunction public fun test3(/*0*/ a: T, /*1*/ x: kotlin.collections.Collection): kotlin.Boolean @@ -25,7 +25,7 @@ IrFile /in.kt IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - UNARY_OP operator=EXCL type=kotlin.Boolean related=null - CALL .contains type=kotlin.Boolean operator=NOT_IN + CALL .NOT type=kotlin.Boolean operator=EXCL + arg0: CALL .contains type=kotlin.Boolean operator=NOT_IN $this: GET_VAR x type=kotlin.collections.Collection operator=null element: GET_VAR a type=T operator=null diff --git a/compiler/testData/ir/irText/primitiveComparisons.txt b/compiler/testData/ir/irText/primitiveComparisons.txt index e51a1d2b043..f979fecf528 100644 --- a/compiler/testData/ir/irText/primitiveComparisons.txt +++ b/compiler/testData/ir/irText/primitiveComparisons.txt @@ -3,167 +3,191 @@ IrFile /primitiveComparisons.kt IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=GT type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Byte): kotlin.Int - GET_VAR a type=kotlin.Byte operator=null - GET_VAR b type=kotlin.Byte operator=null + CALL .GT0 type=kotlin.Boolean operator=GT + arg0: CALL .compareTo type=kotlin.Int operator=GT + $this: GET_VAR a type=kotlin.Byte operator=null + other: GET_VAR b type=kotlin.Byte operator=null IrFunction public fun btest2(/*0*/ a: kotlin.Byte, /*1*/ b: kotlin.Byte): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=LT type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Byte): kotlin.Int - GET_VAR a type=kotlin.Byte operator=null - GET_VAR b type=kotlin.Byte operator=null + CALL .LT0 type=kotlin.Boolean operator=LT + arg0: CALL .compareTo type=kotlin.Int operator=LT + $this: GET_VAR a type=kotlin.Byte operator=null + other: GET_VAR b type=kotlin.Byte operator=null IrFunction public fun btest3(/*0*/ a: kotlin.Byte, /*1*/ b: kotlin.Byte): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=GTEQ type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Byte): kotlin.Int - GET_VAR a type=kotlin.Byte operator=null - GET_VAR b type=kotlin.Byte operator=null + CALL .GTEQ0 type=kotlin.Boolean operator=GTEQ + arg0: CALL .compareTo type=kotlin.Int operator=GTEQ + $this: GET_VAR a type=kotlin.Byte operator=null + other: GET_VAR b type=kotlin.Byte operator=null IrFunction public fun btest4(/*0*/ a: kotlin.Byte, /*1*/ b: kotlin.Byte): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=LTEQ type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Byte): kotlin.Int - GET_VAR a type=kotlin.Byte operator=null - GET_VAR b type=kotlin.Byte operator=null + CALL .LTEQ0 type=kotlin.Boolean operator=LTEQ + arg0: CALL .compareTo type=kotlin.Int operator=LTEQ + $this: GET_VAR a type=kotlin.Byte operator=null + other: GET_VAR b type=kotlin.Byte operator=null IrFunction public fun stest1(/*0*/ a: kotlin.Short, /*1*/ b: kotlin.Short): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=GT type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Short): kotlin.Int - GET_VAR a type=kotlin.Short operator=null - GET_VAR b type=kotlin.Short operator=null + CALL .GT0 type=kotlin.Boolean operator=GT + arg0: CALL .compareTo type=kotlin.Int operator=GT + $this: GET_VAR a type=kotlin.Short operator=null + other: GET_VAR b type=kotlin.Short operator=null IrFunction public fun stest2(/*0*/ a: kotlin.Short, /*1*/ b: kotlin.Short): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=LT type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Short): kotlin.Int - GET_VAR a type=kotlin.Short operator=null - GET_VAR b type=kotlin.Short operator=null + CALL .LT0 type=kotlin.Boolean operator=LT + arg0: CALL .compareTo type=kotlin.Int operator=LT + $this: GET_VAR a type=kotlin.Short operator=null + other: GET_VAR b type=kotlin.Short operator=null IrFunction public fun stest3(/*0*/ a: kotlin.Short, /*1*/ b: kotlin.Short): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=GTEQ type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Short): kotlin.Int - GET_VAR a type=kotlin.Short operator=null - GET_VAR b type=kotlin.Short operator=null + CALL .GTEQ0 type=kotlin.Boolean operator=GTEQ + arg0: CALL .compareTo type=kotlin.Int operator=GTEQ + $this: GET_VAR a type=kotlin.Short operator=null + other: GET_VAR b type=kotlin.Short operator=null IrFunction public fun stest4(/*0*/ a: kotlin.Short, /*1*/ b: kotlin.Short): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=LTEQ type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Short): kotlin.Int - GET_VAR a type=kotlin.Short operator=null - GET_VAR b type=kotlin.Short operator=null + CALL .LTEQ0 type=kotlin.Boolean operator=LTEQ + arg0: CALL .compareTo type=kotlin.Int operator=LTEQ + $this: GET_VAR a type=kotlin.Short operator=null + other: GET_VAR b type=kotlin.Short operator=null IrFunction public fun itest1(/*0*/ a: kotlin.Int, /*1*/ b: kotlin.Int): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=GT type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Int): kotlin.Int - GET_VAR a type=kotlin.Int operator=null - GET_VAR b type=kotlin.Int operator=null + CALL .GT0 type=kotlin.Boolean operator=GT + arg0: CALL .compareTo type=kotlin.Int operator=GT + $this: GET_VAR a type=kotlin.Int operator=null + other: GET_VAR b type=kotlin.Int operator=null IrFunction public fun itest2(/*0*/ a: kotlin.Int, /*1*/ b: kotlin.Int): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=LT type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Int): kotlin.Int - GET_VAR a type=kotlin.Int operator=null - GET_VAR b type=kotlin.Int operator=null + CALL .LT0 type=kotlin.Boolean operator=LT + arg0: CALL .compareTo type=kotlin.Int operator=LT + $this: GET_VAR a type=kotlin.Int operator=null + other: GET_VAR b type=kotlin.Int operator=null IrFunction public fun itest3(/*0*/ a: kotlin.Int, /*1*/ b: kotlin.Int): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=GTEQ type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Int): kotlin.Int - GET_VAR a type=kotlin.Int operator=null - GET_VAR b type=kotlin.Int operator=null + CALL .GTEQ0 type=kotlin.Boolean operator=GTEQ + arg0: CALL .compareTo type=kotlin.Int operator=GTEQ + $this: GET_VAR a type=kotlin.Int operator=null + other: GET_VAR b type=kotlin.Int operator=null IrFunction public fun itest4(/*0*/ a: kotlin.Int, /*1*/ b: kotlin.Int): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=LTEQ type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Int): kotlin.Int - GET_VAR a type=kotlin.Int operator=null - GET_VAR b type=kotlin.Int operator=null + CALL .LTEQ0 type=kotlin.Boolean operator=LTEQ + arg0: CALL .compareTo type=kotlin.Int operator=LTEQ + $this: GET_VAR a type=kotlin.Int operator=null + other: GET_VAR b type=kotlin.Int operator=null IrFunction public fun ltest1(/*0*/ a: kotlin.Long, /*1*/ b: kotlin.Long): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=GT type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Long): kotlin.Int - GET_VAR a type=kotlin.Long operator=null - GET_VAR b type=kotlin.Long operator=null + CALL .GT0 type=kotlin.Boolean operator=GT + arg0: CALL .compareTo type=kotlin.Int operator=GT + $this: GET_VAR a type=kotlin.Long operator=null + other: GET_VAR b type=kotlin.Long operator=null IrFunction public fun ltest2(/*0*/ a: kotlin.Long, /*1*/ b: kotlin.Long): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=LT type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Long): kotlin.Int - GET_VAR a type=kotlin.Long operator=null - GET_VAR b type=kotlin.Long operator=null + CALL .LT0 type=kotlin.Boolean operator=LT + arg0: CALL .compareTo type=kotlin.Int operator=LT + $this: GET_VAR a type=kotlin.Long operator=null + other: GET_VAR b type=kotlin.Long operator=null IrFunction public fun ltest3(/*0*/ a: kotlin.Long, /*1*/ b: kotlin.Long): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=GTEQ type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Long): kotlin.Int - GET_VAR a type=kotlin.Long operator=null - GET_VAR b type=kotlin.Long operator=null + CALL .GTEQ0 type=kotlin.Boolean operator=GTEQ + arg0: CALL .compareTo type=kotlin.Int operator=GTEQ + $this: GET_VAR a type=kotlin.Long operator=null + other: GET_VAR b type=kotlin.Long operator=null IrFunction public fun ltest4(/*0*/ a: kotlin.Long, /*1*/ b: kotlin.Long): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=LTEQ type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Long): kotlin.Int - GET_VAR a type=kotlin.Long operator=null - GET_VAR b type=kotlin.Long operator=null + CALL .LTEQ0 type=kotlin.Boolean operator=LTEQ + arg0: CALL .compareTo type=kotlin.Int operator=LTEQ + $this: GET_VAR a type=kotlin.Long operator=null + other: GET_VAR b type=kotlin.Long operator=null IrFunction public fun ftest1(/*0*/ a: kotlin.Float, /*1*/ b: kotlin.Float): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=GT type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Float): kotlin.Int - GET_VAR a type=kotlin.Float operator=null - GET_VAR b type=kotlin.Float operator=null + CALL .GT0 type=kotlin.Boolean operator=GT + arg0: CALL .compareTo type=kotlin.Int operator=GT + $this: GET_VAR a type=kotlin.Float operator=null + other: GET_VAR b type=kotlin.Float operator=null IrFunction public fun ftest2(/*0*/ a: kotlin.Float, /*1*/ b: kotlin.Float): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=LT type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Float): kotlin.Int - GET_VAR a type=kotlin.Float operator=null - GET_VAR b type=kotlin.Float operator=null + CALL .LT0 type=kotlin.Boolean operator=LT + arg0: CALL .compareTo type=kotlin.Int operator=LT + $this: GET_VAR a type=kotlin.Float operator=null + other: GET_VAR b type=kotlin.Float operator=null IrFunction public fun ftest3(/*0*/ a: kotlin.Float, /*1*/ b: kotlin.Float): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=GTEQ type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Float): kotlin.Int - GET_VAR a type=kotlin.Float operator=null - GET_VAR b type=kotlin.Float operator=null + CALL .GTEQ0 type=kotlin.Boolean operator=GTEQ + arg0: CALL .compareTo type=kotlin.Int operator=GTEQ + $this: GET_VAR a type=kotlin.Float operator=null + other: GET_VAR b type=kotlin.Float operator=null IrFunction public fun ftest4(/*0*/ a: kotlin.Float, /*1*/ b: kotlin.Float): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=LTEQ type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Float): kotlin.Int - GET_VAR a type=kotlin.Float operator=null - GET_VAR b type=kotlin.Float operator=null + CALL .LTEQ0 type=kotlin.Boolean operator=LTEQ + arg0: CALL .compareTo type=kotlin.Int operator=LTEQ + $this: GET_VAR a type=kotlin.Float operator=null + other: GET_VAR b type=kotlin.Float operator=null IrFunction public fun dtest1(/*0*/ a: kotlin.Double, /*1*/ b: kotlin.Double): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=GT type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Double): kotlin.Int - GET_VAR a type=kotlin.Double operator=null - GET_VAR b type=kotlin.Double operator=null + CALL .GT0 type=kotlin.Boolean operator=GT + arg0: CALL .compareTo type=kotlin.Int operator=GT + $this: GET_VAR a type=kotlin.Double operator=null + other: GET_VAR b type=kotlin.Double operator=null IrFunction public fun dtest2(/*0*/ a: kotlin.Double, /*1*/ b: kotlin.Double): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=LT type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Double): kotlin.Int - GET_VAR a type=kotlin.Double operator=null - GET_VAR b type=kotlin.Double operator=null + CALL .LT0 type=kotlin.Boolean operator=LT + arg0: CALL .compareTo type=kotlin.Int operator=LT + $this: GET_VAR a type=kotlin.Double operator=null + other: GET_VAR b type=kotlin.Double operator=null IrFunction public fun dtest3(/*0*/ a: kotlin.Double, /*1*/ b: kotlin.Double): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=GTEQ type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Double): kotlin.Int - GET_VAR a type=kotlin.Double operator=null - GET_VAR b type=kotlin.Double operator=null + CALL .GTEQ0 type=kotlin.Boolean operator=GTEQ + arg0: CALL .compareTo type=kotlin.Int operator=GTEQ + $this: GET_VAR a type=kotlin.Double operator=null + other: GET_VAR b type=kotlin.Double operator=null IrFunction public fun dtest4(/*0*/ a: kotlin.Double, /*1*/ b: kotlin.Double): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=LTEQ type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.Double): kotlin.Int - GET_VAR a type=kotlin.Double operator=null - GET_VAR b type=kotlin.Double operator=null + CALL .LTEQ0 type=kotlin.Boolean operator=LTEQ + arg0: CALL .compareTo type=kotlin.Int operator=LTEQ + $this: GET_VAR a type=kotlin.Double operator=null + other: GET_VAR b type=kotlin.Double operator=null diff --git a/compiler/testData/ir/irText/stringComparisons.txt b/compiler/testData/ir/irText/stringComparisons.txt index 692d173fd69..9a82efa9f14 100644 --- a/compiler/testData/ir/irText/stringComparisons.txt +++ b/compiler/testData/ir/irText/stringComparisons.txt @@ -3,27 +3,31 @@ IrFile /stringComparisons.kt IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=GT type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.String): kotlin.Int - GET_VAR a type=kotlin.String operator=null - GET_VAR b type=kotlin.String operator=null + CALL .GT0 type=kotlin.Boolean operator=GT + arg0: CALL .compareTo type=kotlin.Int operator=GT + $this: GET_VAR a type=kotlin.String operator=null + other: GET_VAR b type=kotlin.String operator=null IrFunction public fun test2(/*0*/ a: kotlin.String, /*1*/ b: kotlin.String): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=LT type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.String): kotlin.Int - GET_VAR a type=kotlin.String operator=null - GET_VAR b type=kotlin.String operator=null + CALL .LT0 type=kotlin.Boolean operator=LT + arg0: CALL .compareTo type=kotlin.Int operator=LT + $this: GET_VAR a type=kotlin.String operator=null + other: GET_VAR b type=kotlin.String operator=null IrFunction public fun test3(/*0*/ a: kotlin.String, /*1*/ b: kotlin.String): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=GTEQ type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.String): kotlin.Int - GET_VAR a type=kotlin.String operator=null - GET_VAR b type=kotlin.String operator=null + CALL .GTEQ0 type=kotlin.Boolean operator=GTEQ + arg0: CALL .compareTo type=kotlin.Int operator=GTEQ + $this: GET_VAR a type=kotlin.String operator=null + other: GET_VAR b type=kotlin.String operator=null IrFunction public fun test4(/*0*/ a: kotlin.String, /*1*/ b: kotlin.String): kotlin.Boolean IrExpressionBody BLOCK type= hasResult=false operator=null RETURN type= - BINARY_OP operator=LTEQ type=kotlin.Boolean related=public open override /*1*/ fun compareTo(/*0*/ other: kotlin.String): kotlin.Int - GET_VAR a type=kotlin.String operator=null - GET_VAR b type=kotlin.String operator=null + CALL .LTEQ0 type=kotlin.Boolean operator=LTEQ + arg0: CALL .compareTo type=kotlin.Int operator=LTEQ + $this: GET_VAR a type=kotlin.String operator=null + other: GET_VAR b type=kotlin.String operator=null diff --git a/compiler/testData/ir/irText/when.txt b/compiler/testData/ir/irText/when.txt index 91646c59fdd..5c78ed8436a 100644 --- a/compiler/testData/ir/irText/when.txt +++ b/compiler/testData/ir/irText/when.txt @@ -8,14 +8,14 @@ IrFile /when.kt VAR val tmp0_subject: kotlin.Any? GET_VAR x type=kotlin.Any? operator=null IF type=kotlin.String operator=WHEN - if: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null - GET_VAR tmp0_subject type=kotlin.Any? operator=null - LITERAL Null type=kotlin.Nothing? value='null' + if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ + arg0: GET_VAR tmp0_subject type=kotlin.Any? operator=null + arg1: LITERAL Null type=kotlin.Nothing? value='null' then: LITERAL String type=kotlin.String value='null' else: IF type=kotlin.String operator=WHEN - if: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null - GET_VAR tmp0_subject type=kotlin.Any? operator=null - GET_OBJECT A type=A + if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ + arg0: GET_VAR tmp0_subject type=kotlin.Any? operator=null + arg1: GET_OBJECT A type=A then: LITERAL String type=kotlin.String value='A' else: IF type=kotlin.String operator=WHEN if: TYPE_OP operator=INSTANCEOF typeOperand=kotlin.String @@ -33,14 +33,14 @@ IrFile /when.kt BLOCK type= hasResult=false operator=null RETURN type= IF type=kotlin.String operator=WHEN - if: BINARY_OP operator=EQEQ type=kotlin.Boolean related=public open operator fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean - GET_VAR x type=kotlin.Any? operator=null - LITERAL Null type=kotlin.Nothing? value='null' + if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ + arg0: GET_VAR x type=kotlin.Any? operator=null + arg1: LITERAL Null type=kotlin.Nothing? value='null' then: LITERAL String type=kotlin.String value='null' else: IF type=kotlin.String operator=WHEN - if: BINARY_OP operator=EQEQ type=kotlin.Boolean related=public open operator fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean - GET_VAR x type=kotlin.Any? operator=null - GET_OBJECT A type=A + if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ + arg0: GET_VAR x type=kotlin.Any? operator=null + arg1: GET_OBJECT A type=A then: LITERAL String type=kotlin.String value='A' else: IF type=kotlin.String operator=WHEN if: TYPE_OP operator=INSTANCEOF typeOperand=kotlin.String @@ -64,45 +64,45 @@ IrFile /when.kt if: IF type=kotlin.Boolean operator=WHEN_COMMA if: IF type=kotlin.Boolean operator=WHEN_COMMA if: IF type=kotlin.Boolean operator=WHEN_COMMA - if: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null - GET_VAR tmp0_subject type=kotlin.Int operator=null - LITERAL Int type=kotlin.Int value='1' + if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ + arg0: GET_VAR tmp0_subject type=kotlin.Int operator=null + arg1: LITERAL Int type=kotlin.Int value='1' then: LITERAL Boolean type=kotlin.Boolean value='true' - else: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null - GET_VAR tmp0_subject type=kotlin.Int operator=null - LITERAL Int type=kotlin.Int value='2' + else: CALL .EQEQ type=kotlin.Boolean operator=EQEQ + arg0: GET_VAR tmp0_subject type=kotlin.Int operator=null + arg1: LITERAL Int type=kotlin.Int value='2' then: LITERAL Boolean type=kotlin.Boolean value='true' - else: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null - GET_VAR tmp0_subject type=kotlin.Int operator=null - LITERAL Int type=kotlin.Int value='3' + else: CALL .EQEQ type=kotlin.Boolean operator=EQEQ + arg0: GET_VAR tmp0_subject type=kotlin.Int operator=null + arg1: LITERAL Int type=kotlin.Int value='3' then: LITERAL Boolean type=kotlin.Boolean value='true' - else: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null - GET_VAR tmp0_subject type=kotlin.Int operator=null - LITERAL Int type=kotlin.Int value='4' + else: CALL .EQEQ type=kotlin.Boolean operator=EQEQ + arg0: GET_VAR tmp0_subject type=kotlin.Int operator=null + arg1: LITERAL Int type=kotlin.Int value='4' then: LITERAL String type=kotlin.String value='1234' else: IF type=kotlin.String operator=WHEN if: IF type=kotlin.Boolean operator=WHEN_COMMA if: IF type=kotlin.Boolean operator=WHEN_COMMA - if: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null - GET_VAR tmp0_subject type=kotlin.Int operator=null - LITERAL Int type=kotlin.Int value='5' + if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ + arg0: GET_VAR tmp0_subject type=kotlin.Int operator=null + arg1: LITERAL Int type=kotlin.Int value='5' then: LITERAL Boolean type=kotlin.Boolean value='true' - else: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null - GET_VAR tmp0_subject type=kotlin.Int operator=null - LITERAL Int type=kotlin.Int value='6' + else: CALL .EQEQ type=kotlin.Boolean operator=EQEQ + arg0: GET_VAR tmp0_subject type=kotlin.Int operator=null + arg1: LITERAL Int type=kotlin.Int value='6' then: LITERAL Boolean type=kotlin.Boolean value='true' - else: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null - GET_VAR tmp0_subject type=kotlin.Int operator=null - LITERAL Int type=kotlin.Int value='7' + else: CALL .EQEQ type=kotlin.Boolean operator=EQEQ + arg0: GET_VAR tmp0_subject type=kotlin.Int operator=null + arg1: LITERAL Int type=kotlin.Int value='7' then: LITERAL String type=kotlin.String value='567' else: IF type=kotlin.String operator=WHEN if: IF type=kotlin.Boolean operator=WHEN_COMMA - if: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null - GET_VAR tmp0_subject type=kotlin.Int operator=null - LITERAL Int type=kotlin.Int value='8' + if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ + arg0: GET_VAR tmp0_subject type=kotlin.Int operator=null + arg1: LITERAL Int type=kotlin.Int value='8' then: LITERAL Boolean type=kotlin.Boolean value='true' - else: BINARY_OP operator=EQEQ type=kotlin.Boolean related=null - GET_VAR tmp0_subject type=kotlin.Int operator=null - LITERAL Int type=kotlin.Int value='9' + else: CALL .EQEQ type=kotlin.Boolean operator=EQEQ + arg0: GET_VAR tmp0_subject type=kotlin.Int operator=null + arg1: LITERAL Int type=kotlin.Int value='9' then: LITERAL String type=kotlin.String value='89' else: LITERAL String type=kotlin.String value='?'