diff --git a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrDeclarationGenerator.kt b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrDeclarationGenerator.kt index fde93f22ec4..8b68069f818 100644 --- a/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrDeclarationGenerator.kt +++ b/compiler/ir/ir.psi2ir/src/org/jetbrains/kotlin/psi2ir/IrDeclarationGenerator.kt @@ -20,11 +20,9 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.PropertyGetterDescriptor import org.jetbrains.kotlin.descriptors.PropertySetterDescriptor -import org.jetbrains.kotlin.ir.assertCast -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.expressions.IrBody -import org.jetbrains.kotlin.ir.expressions.IrExpressionBodyImpl -import org.jetbrains.kotlin.ir.expressions.IrReturnExpressionImpl +import org.jetbrains.kotlin.ir.declarations.IrDeclaration +import org.jetbrains.kotlin.ir.declarations.IrDummyDeclaration +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 @@ -64,25 +62,25 @@ abstract class IrDeclarationGeneratorBase( fun generateFunctionDeclaration(ktNamedFunction: KtNamedFunction) { val functionDescriptor = getOrFail(BindingContext.FUNCTION, ktNamedFunction) - val body = generateExpressionBody(functionDescriptor, ktNamedFunction.bodyExpression ?: TODO("function without body expression")) + val body = generateFunctionBody(functionDescriptor, ktNamedFunction.bodyExpression ?: TODO("function without body expression")) declarationFactory.createFunction(ktNamedFunction, functionDescriptor, body).register() } fun generatePropertyDeclaration(ktProperty: KtProperty) { val propertyDescriptor = getPropertyDescriptor(ktProperty) if (ktProperty.hasDelegate()) TODO("handle delegated property") - val initializer = ktProperty.initializer?.let { generateExpressionBody(propertyDescriptor, it) } + val initializer = ktProperty.initializer?.let { generateInitializerBody(propertyDescriptor, it) } val irProperty = declarationFactory.createSimpleProperty(ktProperty, propertyDescriptor, initializer).register() ktProperty.getter?.let { ktGetter -> val accessorDescriptor = getOrFail(BindingContext.PROPERTY_ACCESSOR, ktGetter) val getterDescriptor = accessorDescriptor as? PropertyGetterDescriptor ?: TODO("not a getter?") - val getterBody = generateExpressionBody(getterDescriptor, ktGetter.bodyExpression ?: TODO("default getter")) + val getterBody = generateFunctionBody(getterDescriptor, ktGetter.bodyExpression ?: TODO("default getter")) declarationFactory.createPropertyGetter(ktGetter, irProperty, getterDescriptor, getterBody).register() } ktProperty.setter?.let { ktSetter -> val accessorDescriptor = getOrFail(BindingContext.PROPERTY_ACCESSOR, ktSetter) val setterDescriptor = accessorDescriptor as? PropertySetterDescriptor ?: TODO("not a setter?") - val setterBody = generateExpressionBody(setterDescriptor, ktSetter.bodyExpression ?: TODO("default setter")) + val setterBody = generateFunctionBody(setterDescriptor, ktSetter.bodyExpression ?: TODO("default setter")) declarationFactory.createPropertySetter(ktSetter, irProperty, setterDescriptor, setterBody).register() } } @@ -93,8 +91,22 @@ abstract class IrDeclarationGeneratorBase( return propertyDescriptor } - fun generateExpressionBody(scopeOwner: DeclarationDescriptor, ktBody: KtExpression): IrBody = - IrExpressionBodyImpl(ktBody.startOffset, ktBody.endOffset).apply { - expression = IrStatementGenerator(context, IrLocalDeclarationsFactory(scopeOwner)).generateStatement(ktBody).assertCast() - } + private fun generateExpressionWithinContext(ktExpression: KtExpression, scopeOwner: DeclarationDescriptor): IrExpression = + IrStatementGenerator(context, IrLocalDeclarationsFactory(scopeOwner)).generateExpression(ktExpression) + + private fun generateFunctionBody(scopeOwner: DeclarationDescriptor, ktBody: KtExpression): IrBody { + val irRhs = generateExpressionWithinContext(ktBody, scopeOwner) + val irExpressionBody = + if (ktBody is KtBlockExpression) + irRhs + else + IrBlockExpressionImpl(ktBody.startOffset, ktBody.endOffset, null, hasResult = false, isDesugared = true).apply { + addStatement(IrReturnExpressionImpl(ktBody.startOffset, ktBody.endOffset, null, irRhs)) + } + return IrExpressionBodyImpl(ktBody.startOffset, ktBody.endOffset, irExpressionBody) + } + + private fun generateInitializerBody(scopeOwner: DeclarationDescriptor, ktBody: KtExpression): IrBody = + IrExpressionBodyImpl(ktBody.startOffset, ktBody.endOffset, + generateExpressionWithinContext(ktBody, scopeOwner)) } \ No newline at end of file diff --git a/compiler/testData/ir/irText/boxOk.txt b/compiler/testData/ir/irText/boxOk.txt index 7bb9a5cc33b..c71591c49af 100644 --- a/compiler/testData/ir/irText/boxOk.txt +++ b/compiler/testData/ir/irText/boxOk.txt @@ -1,4 +1,6 @@ IrFile /boxOk.kt IrFunction public fun box(): kotlin.String IrExpressionBody - LITERAL String type=kotlin.String value='OK' + BLOCK type= hasResult=false isDesugared=true + RETURN type= + LITERAL String type=kotlin.String value='OK' diff --git a/compiler/testData/ir/irText/callWithReorderedArguments.txt b/compiler/testData/ir/irText/callWithReorderedArguments.txt index 272e769f641..5270eac507d 100644 --- a/compiler/testData/ir/irText/callWithReorderedArguments.txt +++ b/compiler/testData/ir/irText/callWithReorderedArguments.txt @@ -4,16 +4,24 @@ IrFile /callWithReorderedArguments.kt BLOCK type=kotlin.Unit hasResult=false isDesugared=false IrFunction public fun noReorder1(): kotlin.Int IrExpressionBody - LITERAL Int type=kotlin.Int value='1' + BLOCK type= hasResult=false isDesugared=true + RETURN type= + LITERAL Int type=kotlin.Int value='1' IrFunction public fun noReorder2(): kotlin.Int IrExpressionBody - LITERAL Int type=kotlin.Int value='2' + BLOCK type= hasResult=false isDesugared=true + RETURN type= + LITERAL Int type=kotlin.Int value='2' IrFunction public fun reordered1(): kotlin.Int IrExpressionBody - LITERAL Int type=kotlin.Int value='1' + BLOCK type= hasResult=false isDesugared=true + RETURN type= + LITERAL Int type=kotlin.Int value='1' IrFunction public fun reordered2(): kotlin.Int IrExpressionBody - LITERAL Int type=kotlin.Int value='2' + BLOCK type= hasResult=false isDesugared=true + RETURN type= + LITERAL Int type=kotlin.Int value='2' IrFunction public fun test(): kotlin.Unit IrExpressionBody BLOCK type=kotlin.Unit hasResult=false isDesugared=false diff --git a/compiler/testData/ir/irText/calls.kt b/compiler/testData/ir/irText/calls.kt index 6b46c6c6d7f..50169e63f0d 100644 --- a/compiler/testData/ir/irText/calls.kt +++ b/compiler/testData/ir/irText/calls.kt @@ -5,3 +5,4 @@ fun qux(x: Int) = foo(foo(x, x), x) fun Int.ext1() = this fun Int.ext2(x: Int) = foo(this, x) +fun Int.ext3(x: Int) = foo(ext1(), x) \ No newline at end of file diff --git a/compiler/testData/ir/irText/calls.txt b/compiler/testData/ir/irText/calls.txt index 02854c6dd53..aa616ae2597 100644 --- a/compiler/testData/ir/irText/calls.txt +++ b/compiler/testData/ir/irText/calls.txt @@ -1,24 +1,42 @@ IrFile /calls.kt IrFunction public fun foo(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.Int): kotlin.Int IrExpressionBody - GET_VAR x type=kotlin.Int + BLOCK type= hasResult=false isDesugared=true + RETURN type= + GET_VAR x type=kotlin.Int IrFunction public fun bar(/*0*/ x: kotlin.Int): kotlin.Int IrExpressionBody - CALL .foo type=kotlin.Int operator= - x: GET_VAR x type=kotlin.Int - y: LITERAL Int type=kotlin.Int value='1' + BLOCK type= hasResult=false isDesugared=true + RETURN type= + CALL .foo type=kotlin.Int operator= + x: GET_VAR x type=kotlin.Int + y: LITERAL Int type=kotlin.Int value='1' IrFunction public fun qux(/*0*/ x: kotlin.Int): kotlin.Int IrExpressionBody - CALL .foo type=kotlin.Int operator= - x: CALL .foo type=kotlin.Int operator= - x: GET_VAR x type=kotlin.Int - y: GET_VAR x type=kotlin.Int - y: GET_VAR x type=kotlin.Int + BLOCK type= hasResult=false isDesugared=true + RETURN type= + CALL .foo type=kotlin.Int operator= + x: CALL .foo type=kotlin.Int operator= + x: GET_VAR x type=kotlin.Int + y: GET_VAR x type=kotlin.Int + y: GET_VAR x type=kotlin.Int IrFunction public fun kotlin.Int.ext1(): kotlin.Int IrExpressionBody - $RECEIVER of: ext1 type=kotlin.Int + BLOCK type= hasResult=false isDesugared=true + RETURN type= + $RECEIVER of: ext1 type=kotlin.Int IrFunction public fun kotlin.Int.ext2(/*0*/ x: kotlin.Int): kotlin.Int IrExpressionBody - CALL .foo type=kotlin.Int operator= - x: $RECEIVER of: ext2 type=kotlin.Int - y: GET_VAR x type=kotlin.Int + BLOCK type= hasResult=false isDesugared=true + RETURN type= + CALL .foo type=kotlin.Int operator= + x: $RECEIVER of: ext2 type=kotlin.Int + y: GET_VAR x type=kotlin.Int + IrFunction public fun kotlin.Int.ext3(/*0*/ x: kotlin.Int): kotlin.Int + IrExpressionBody + BLOCK type= hasResult=false isDesugared=true + RETURN type= + CALL .foo type=kotlin.Int operator= + x: CALL .ext1 type=kotlin.Int operator= + $receiver: $RECEIVER of: ext3 type=kotlin.Int + y: GET_VAR x type=kotlin.Int diff --git a/compiler/testData/ir/irText/dotQualified.txt b/compiler/testData/ir/irText/dotQualified.txt index 171187295ed..2fc95f69332 100644 --- a/compiler/testData/ir/irText/dotQualified.txt +++ b/compiler/testData/ir/irText/dotQualified.txt @@ -1,9 +1,13 @@ IrFile /dotQualified.kt IrFunction public fun length(/*0*/ s: kotlin.String): kotlin.Int IrExpressionBody - GET_PROPERTY .length type=kotlin.Int - $this: GET_VAR s type=kotlin.String + BLOCK type= hasResult=false isDesugared=true + RETURN type= + GET_PROPERTY .length type=kotlin.Int + $this: GET_VAR s type=kotlin.String IrFunction public fun lengthN(/*0*/ s: kotlin.String?): kotlin.Int? IrExpressionBody - GET_PROPERTY ?.length type=kotlin.Int? - $this: GET_VAR s type=kotlin.String? + BLOCK type= hasResult=false isDesugared=true + RETURN type= + GET_PROPERTY ?.length type=kotlin.Int? + $this: GET_VAR s type=kotlin.String? diff --git a/compiler/testData/ir/irText/extensionPropertyGetterCall.txt b/compiler/testData/ir/irText/extensionPropertyGetterCall.txt index c259f6c5bfe..fb1d03dbcfd 100644 --- a/compiler/testData/ir/irText/extensionPropertyGetterCall.txt +++ b/compiler/testData/ir/irText/extensionPropertyGetterCall.txt @@ -2,8 +2,12 @@ IrFile /extensionPropertyGetterCall.kt IrProperty public val kotlin.String.okext: kotlin.String getter= setter=null IrPropertyGetter public fun kotlin.String.(): kotlin.String property=okext IrExpressionBody - LITERAL String type=kotlin.String value='OK' + BLOCK type= hasResult=false isDesugared=true + RETURN type= + LITERAL String type=kotlin.String value='OK' IrFunction public fun kotlin.String.test5(): kotlin.String IrExpressionBody - GET_PROPERTY .okext type=kotlin.String - $receiver: $RECEIVER of: test5 type=kotlin.String + BLOCK type= hasResult=false isDesugared=true + RETURN type= + GET_PROPERTY .okext type=kotlin.String + $receiver: $RECEIVER of: test5 type=kotlin.String diff --git a/compiler/testData/ir/irText/references.txt b/compiler/testData/ir/irText/references.txt index 00e9213abed..aac1f4d4351 100644 --- a/compiler/testData/ir/irText/references.txt +++ b/compiler/testData/ir/irText/references.txt @@ -8,13 +8,19 @@ IrFile /references.kt IrProperty public val ok3: kotlin.String getter= setter=null IrPropertyGetter public fun (): kotlin.String property=ok3 IrExpressionBody - LITERAL String type=kotlin.String value='OK' + BLOCK type= hasResult=false isDesugared=true + RETURN type= + LITERAL String type=kotlin.String value='OK' IrFunction public fun test1(): kotlin.String IrExpressionBody - GET_PROPERTY .ok type=kotlin.String + BLOCK type= hasResult=false isDesugared=true + RETURN type= + GET_PROPERTY .ok type=kotlin.String IrFunction public fun test2(/*0*/ x: kotlin.String): kotlin.String IrExpressionBody - GET_VAR x type=kotlin.String + BLOCK type= hasResult=false isDesugared=true + RETURN type= + GET_VAR x type=kotlin.String IrFunction public fun test3(): kotlin.String IrExpressionBody BLOCK type=kotlin.Nothing hasResult=false isDesugared=false @@ -24,12 +30,18 @@ IrFile /references.kt GET_VAR x type=kotlin.String IrFunction public fun test4(): kotlin.String IrExpressionBody - GET_PROPERTY .ok3 type=kotlin.String + BLOCK type= hasResult=false isDesugared=true + RETURN type= + GET_PROPERTY .ok3 type=kotlin.String IrProperty public val kotlin.String.okext: kotlin.String getter= setter=null IrPropertyGetter public fun kotlin.String.(): kotlin.String property=okext IrExpressionBody - LITERAL String type=kotlin.String value='OK' + BLOCK type= hasResult=false isDesugared=true + RETURN type= + LITERAL String type=kotlin.String value='OK' IrFunction public fun kotlin.String.test5(): kotlin.String IrExpressionBody - GET_PROPERTY .okext type=kotlin.String - $receiver: $RECEIVER of: test5 type=kotlin.String + BLOCK type= hasResult=false isDesugared=true + RETURN type= + GET_PROPERTY .okext type=kotlin.String + $receiver: $RECEIVER of: test5 type=kotlin.String diff --git a/compiler/testData/ir/irText/smoke.txt b/compiler/testData/ir/irText/smoke.txt index 5457cf4937d..012859c4d59 100644 --- a/compiler/testData/ir/irText/smoke.txt +++ b/compiler/testData/ir/irText/smoke.txt @@ -10,14 +10,18 @@ IrFile /smoke.kt IrProperty public val testValWithGetter: kotlin.Int getter= setter=null IrPropertyGetter public fun (): kotlin.Int property=testValWithGetter IrExpressionBody - LITERAL Int type=kotlin.Int value='42' + BLOCK type= hasResult=false isDesugared=true + RETURN type= + LITERAL Int type=kotlin.Int value='42' IrProperty public var testSimpleVar: kotlin.Int getter=null setter=null IrExpressionBody LITERAL Int type=kotlin.Int value='2' IrProperty public var testVarWithAccessors: kotlin.Int getter= setter= IrPropertyGetter public fun (): kotlin.Int property=testVarWithAccessors IrExpressionBody - LITERAL Int type=kotlin.Int value='42' + BLOCK type= hasResult=false isDesugared=true + RETURN type= + LITERAL Int type=kotlin.Int value='42' IrPropertySetter public fun (/*0*/ v: kotlin.Int): kotlin.Unit property=testVarWithAccessors IrExpressionBody BLOCK type=kotlin.Unit hasResult=false isDesugared=false