diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TryCatchExpressionGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TryCatchExpressionGenerator.kt index 15d9fc09918..e260e1e5b0f 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TryCatchExpressionGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/generators/TryCatchExpressionGenerator.kt @@ -17,7 +17,8 @@ package org.jetbrains.kotlin.psi2ir.generators import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.impl.IrTryCatchImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrCatchImpl +import org.jetbrains.kotlin.ir.expressions.impl.IrTryImpl import org.jetbrains.kotlin.psi.KtTryExpression import org.jetbrains.kotlin.psi.psiUtil.endOffset import org.jetbrains.kotlin.psi.psiUtil.startOffset @@ -26,19 +27,18 @@ import org.jetbrains.kotlin.resolve.BindingContext class TryCatchExpressionGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) { fun generateTryCatch(ktTry: KtTryExpression): IrExpression { val resultType = getInferredTypeWithImplicitCastsOrFail(ktTry) - val irTryCatch = IrTryCatchImpl(ktTry.startOffset, ktTry.endOffset, resultType) + val irTryCatch = IrTryImpl(ktTry.startOffset, ktTry.endOffset, resultType) irTryCatch.tryResult = statementGenerator.generateExpression(ktTry.tryBlock) for (ktCatchClause in ktTry.catchClauses) { val ktCatchParameter = ktCatchClause.catchParameter!! val ktCatchBody = ktCatchClause.catchBody!! - val catchParameterDescriptor = getOrFail(BindingContext.VALUE_PARAMETER, ktCatchParameter) - val irCatchResult = statementGenerator.generateExpression(ktCatchBody) - - irTryCatch.addCatchClause(catchParameterDescriptor, irCatchResult) + val irCatch = IrCatchImpl(ktCatchClause.startOffset, ktCatchClause.endOffset, + catchParameterDescriptor, irCatchResult) + irTryCatch.catches.add(irCatch) } irTryCatch.finallyExpression = ktTry.finallyBlock?.let{ statementGenerator.generateExpression(it.finalExpression) } diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt index dd0032f8f80..fb031b423e6 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/transformations/InsertImplicitCasts.kt @@ -43,12 +43,12 @@ class InsertImplicitCasts(val builtIns: KotlinBuiltIns): IrElementTransformer when (element) { is IrSpreadElement -> - element.expression = element.expression.wrapWithImplicitCast(expression.type) + element.expression = element.expression.cast(expression.type) is IrExpression -> - expression.putElement(i, element.wrapWithImplicitCast(expression.varargElementType)) + expression.putElement(i, element.cast(expression.varargElementType)) } } return expression } - private fun IrExpression.wrapWithImplicitCast(expectedType: KotlinType?): IrExpression { + private fun IrExpression.cast(expectedType: KotlinType?): IrExpression { if (expectedType == null) return this if (expectedType.isError) return this if (KotlinBuiltIns.isUnit(expectedType)) return this // TODO expose coercion to Unit in IR? @@ -179,7 +178,7 @@ class InsertImplicitCasts(val builtIns: KotlinBuiltIns): IrElementTransformer var finallyExpression : IrExpression? } -val IrTryCatch.catchClauseIndices: IntRange get() = 0 ..catchClausesCount - 1 +interface IrCatch : IrElement { + val parameter: VariableDescriptor + var result: IrExpression + override fun transform(transformer: IrElementTransformer, data: D): IrCatch = + super.transform(transformer, data) as IrCatch +} diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrTryCatchImpl.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrTryImpl.kt similarity index 54% rename from compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrTryCatchImpl.kt rename to compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrTryImpl.kt index a2b5e8d2258..2eac16e4c99 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrTryCatchImpl.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/expressions/impl/IrTryImpl.kt @@ -17,57 +17,54 @@ package org.jetbrains.kotlin.ir.expressions.impl import org.jetbrains.kotlin.descriptors.VariableDescriptor +import org.jetbrains.kotlin.ir.IrElementBase +import org.jetbrains.kotlin.ir.expressions.IrCatch import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.IrTryCatch +import org.jetbrains.kotlin.ir.expressions.IrTry import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementVisitor import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.utils.SmartList -class IrTryCatchImpl(startOffset: Int, endOffset: Int, type: KotlinType) : - IrExpressionBase(startOffset, endOffset, type), IrTryCatch { +class IrTryImpl(startOffset: Int, endOffset: Int, type: KotlinType) : + IrExpressionBase(startOffset, endOffset, type), IrTry { override lateinit var tryResult: IrExpression - private val catchClauseParameters = SmartList() - private val catchClauseResults = SmartList() - - override val catchClausesCount: Int get() = catchClauseResults.size - - fun addCatchClause(parameter: VariableDescriptor, result: IrExpression) { - catchClauseParameters.add(parameter) - catchClauseResults.add(result) - } - - override fun getNthCatchParameter(n: Int): VariableDescriptor? = - catchClauseParameters.getOrNull(n) - - override fun getNthCatchResult(n: Int): IrExpression? = - catchClauseResults.getOrNull(n) - - override fun putNthCatchParameter(n: Int, variableDescriptor: VariableDescriptor) { - catchClauseParameters[n] = variableDescriptor - } - - override fun putNthCatchResult(n: Int, expression: IrExpression) { - catchClauseResults[n] = expression - } + override val catches: MutableList = SmartList() override var finallyExpression: IrExpression? = null override fun accept(visitor: IrElementVisitor, data: D): R { - return visitor.visitTryCatch(this, data) + return visitor.visitTry(this, data) } override fun acceptChildren(visitor: IrElementVisitor, data: D) { tryResult.accept(visitor, data) - catchClauseResults.forEach { it.accept(visitor, data) } + catches.forEach { it.accept(visitor, data) } finallyExpression?.accept(visitor, data) } override fun transformChildren(transformer: IrElementTransformer, data: D) { tryResult = tryResult.transform(transformer, data) - catchClauseResults.forEachIndexed { i, irExpression -> - catchClauseResults[i] = irExpression.transform(transformer, data) + catches.forEachIndexed { i, irCatch -> + catches[i] = irCatch.transform(transformer, data) } } +} + +class IrCatchImpl(startOffset: Int, endOffset: Int, + override val parameter: VariableDescriptor, + override var result: IrExpression +) : IrCatch, IrElementBase(startOffset, endOffset) { + override fun accept(visitor: IrElementVisitor, data: D): R { + return visitor.visitCatch(this, data) + } + + override fun acceptChildren(visitor: IrElementVisitor, data: D) { + result.accept(visitor, data) + } + + override fun transformChildren(transformer: IrElementTransformer, data: D) { + result = result.transform(transformer, data) + } } \ No newline at end of file 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 f07da2e31ea..2091666538d 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 @@ -142,14 +142,13 @@ class DumpIrTreeVisitor(out: Appendable): IrElementVisitor { } } - override fun visitTryCatch(tryCatch: IrTryCatch, data: String) { - tryCatch.dumpLabeledElementWith(data) { - tryCatch.tryResult.accept(this, "try") - for (i in 0 .. tryCatch.catchClausesCount - 1) { - val catchClauseParameter = tryCatch.getNthCatchParameter(i)!! - tryCatch.getNthCatchResult(i)!!.accept(this, "catch ${catchClauseParameter.name}") + override fun visitTry(aTry: IrTry, data: String) { + aTry.dumpLabeledElementWith(data) { + aTry.tryResult.accept(this, "try") + for (aCatch in aTry.catches) { + aCatch.accept(this, "") } - tryCatch.finallyExpression?.accept(this, "finally") + aTry.finallyExpression?.accept(this, "finally") } } 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 a44e93ecf59..8c2155e48e8 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 @@ -179,8 +179,11 @@ class RenderIrElementVisitor : IrElementVisitor { override fun visitGetClass(expression: IrGetClass, data: Nothing?): String = "GET_CLASS type=${expression.type.render()}" - override fun visitTryCatch(tryCatch: IrTryCatch, data: Nothing?): String = - "TRY_CATCH type=${tryCatch.type.render()}" + override fun visitTry(aTry: IrTry, data: Nothing?): String = + "TRY type=${aTry.type.render()}" + + override fun visitCatch(aCatch: IrCatch, data: Nothing?): String = + "CATCH parameter=${aCatch.parameter.ref()}" override fun visitErrorDeclaration(declaration: IrErrorDeclaration, data: Nothing?): String = "ERROR_DECL ${declaration.descriptor.javaClass.simpleName} ${declaration.descriptor.ref()}" diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementTransformer.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementTransformer.kt index dbb6faf92c2..9995c25be32 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementTransformer.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementTransformer.kt @@ -104,7 +104,12 @@ interface IrElementTransformer : IrElementVisitor { override fun visitLoop(loop: IrLoop, data: D) = visitExpression(loop, data) override fun visitWhileLoop(loop: IrWhileLoop, data: D) = visitLoop(loop, data) override fun visitDoWhileLoop(loop: IrDoWhileLoop, data: D) = visitLoop(loop, data) - override fun visitTryCatch(tryCatch: IrTryCatch, data: D) = visitExpression(tryCatch, data) + override fun visitTry(aTry: IrTry, data: D) = visitExpression(aTry, data) + + override fun visitCatch(aCatch: IrCatch, data: D): IrCatch { + aCatch.transformChildren(this, data) + return aCatch + } override fun visitBreakContinue(jump: IrBreakContinue, data: D) = visitExpression(jump, data) override fun visitBreak(jump: IrBreak, data: D) = visitBreakContinue(jump, data) 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 a21daa916ca..a4ead01c10c 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 @@ -81,7 +81,8 @@ interface IrElementVisitor { 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) - fun visitTryCatch(tryCatch: IrTryCatch, data: D) = visitExpression(tryCatch, data) + fun visitTry(aTry: IrTry, data: D) = visitExpression(aTry, data) + fun visitCatch(aCatch: IrCatch, data: D) = visitElement(aCatch, data) fun visitBreakContinue(jump: IrBreakContinue, data: D) = visitExpression(jump, data) fun visitBreak(jump: IrBreak, data: D) = visitBreakContinue(jump, data) diff --git a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitorVoid.kt b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitorVoid.kt index 84c3517705c..b9e1a4ea5c0 100644 --- a/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitorVoid.kt +++ b/compiler/ir/ir.tree/src/org/jetbrains/kotlin/ir/visitors/IrElementVisitorVoid.kt @@ -174,8 +174,11 @@ interface IrElementVisitorVoid : IrElementVisitor { fun visitDoWhileLoop(loop: IrDoWhileLoop) = visitLoop(loop) override fun visitDoWhileLoop(loop: IrDoWhileLoop, data: Nothing?) = visitDoWhileLoop(loop) - fun visitTryCatch(tryCatch: IrTryCatch) = visitExpression(tryCatch) - override fun visitTryCatch(tryCatch: IrTryCatch, data: Nothing?) = visitTryCatch(tryCatch) + fun visitTry(aTry: IrTry) = visitExpression(aTry) + override fun visitTry(aTry: IrTry, data: Nothing?) = visitTry(aTry) + + fun visitCatch(aCatch: IrCatch) = visitElement(aCatch) + override fun visitCatch(aCatch: IrCatch, data: Nothing?) = visitCatch(aCatch) fun visitBreakContinue(jump: IrBreakContinue) = visitExpression(jump) override fun visitBreakContinue(jump: IrBreakContinue, data: Nothing?) = visitBreakContinue(jump) diff --git a/compiler/testData/ir/irText/expressions/tryCatch.txt b/compiler/testData/ir/irText/expressions/tryCatch.txt index 32c2448c8dc..812e7c661ad 100644 --- a/compiler/testData/ir/irText/expressions/tryCatch.txt +++ b/compiler/testData/ir/irText/expressions/tryCatch.txt @@ -1,22 +1,24 @@ FILE /tryCatch.kt FUN public fun test1(): kotlin.Unit BLOCK_BODY - TRY_CATCH type=kotlin.Unit + TRY type=kotlin.Unit try: BLOCK type=kotlin.Unit origin=null CALL 'println(): Unit' type=kotlin.Unit origin=null - catch e: BLOCK type=kotlin.Unit origin=null - CALL 'println(): Unit' type=kotlin.Unit origin=null + CATCH parameter=e: Throwable + BLOCK type=kotlin.Unit origin=null + CALL 'println(): Unit' type=kotlin.Unit origin=null finally: BLOCK type=kotlin.Unit origin=null CALL 'println(): Unit' type=kotlin.Unit origin=null FUN public fun test2(): kotlin.Int BLOCK_BODY RETURN type=kotlin.Nothing from='test2(): Int' - TRY_CATCH type=kotlin.Int + TRY type=kotlin.Int try: BLOCK type=kotlin.Int origin=null CALL 'println(): Unit' type=kotlin.Unit origin=null CONST Int type=kotlin.Int value='42' - catch e: BLOCK type=kotlin.Int origin=null - CALL 'println(): Unit' type=kotlin.Unit origin=null - CONST Int type=kotlin.Int value='24' + CATCH parameter=e: Throwable + BLOCK type=kotlin.Int origin=null + CALL 'println(): Unit' type=kotlin.Unit origin=null + CONST Int type=kotlin.Int value='24' finally: BLOCK type=kotlin.Unit origin=null CALL 'println(): Unit' type=kotlin.Unit origin=null diff --git a/compiler/testData/ir/irText/expressions/tryCatchWithImplicitCast.txt b/compiler/testData/ir/irText/expressions/tryCatchWithImplicitCast.txt index 636cb45ad71..8e0875cc43e 100644 --- a/compiler/testData/ir/irText/expressions/tryCatchWithImplicitCast.txt +++ b/compiler/testData/ir/irText/expressions/tryCatchWithImplicitCast.txt @@ -6,9 +6,10 @@ FILE /tryCatchWithImplicitCast.kt GET_VAR 'value-parameter a: Any' type=kotlin.Any origin=null then: RETURN type=kotlin.Nothing from='testImplicitCast(Any): Unit' VAR val t: kotlin.String - TRY_CATCH type=kotlin.String + TRY type=kotlin.String try: BLOCK type=kotlin.String origin=null TYPE_OP origin=IMPLICIT_CAST typeOperand=kotlin.String GET_VAR 'value-parameter a: Any' type=kotlin.Any origin=null - catch e: BLOCK type=kotlin.String origin=null - CONST String type=kotlin.String value='' + CATCH parameter=e: Throwable + BLOCK type=kotlin.String origin=null + CONST String type=kotlin.String value=''