IR:
- function with expression bodies are desugared to blocks with return statement; - property initializers are generated as regular expression bodies.
This commit is contained in:
committed by
Dmitry Petrov
parent
2707d33ca7
commit
aa7bf4637b
@@ -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))
|
||||
}
|
||||
+3
-1
@@ -1,4 +1,6 @@
|
||||
IrFile /boxOk.kt
|
||||
IrFunction public fun box(): kotlin.String
|
||||
IrExpressionBody
|
||||
LITERAL String type=kotlin.String value='OK'
|
||||
BLOCK type=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-type>
|
||||
LITERAL String type=kotlin.String value='OK'
|
||||
|
||||
+12
-4
@@ -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=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-type>
|
||||
LITERAL Int type=kotlin.Int value='1'
|
||||
IrFunction public fun noReorder2(): kotlin.Int
|
||||
IrExpressionBody
|
||||
LITERAL Int type=kotlin.Int value='2'
|
||||
BLOCK type=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-type>
|
||||
LITERAL Int type=kotlin.Int value='2'
|
||||
IrFunction public fun reordered1(): kotlin.Int
|
||||
IrExpressionBody
|
||||
LITERAL Int type=kotlin.Int value='1'
|
||||
BLOCK type=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-type>
|
||||
LITERAL Int type=kotlin.Int value='1'
|
||||
IrFunction public fun reordered2(): kotlin.Int
|
||||
IrExpressionBody
|
||||
LITERAL Int type=kotlin.Int value='2'
|
||||
BLOCK type=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-type>
|
||||
LITERAL Int type=kotlin.Int value='2'
|
||||
IrFunction public fun test(): kotlin.Unit
|
||||
IrExpressionBody
|
||||
BLOCK type=kotlin.Unit hasResult=false isDesugared=false
|
||||
|
||||
Vendored
+1
@@ -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)
|
||||
+31
-13
@@ -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=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-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=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-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=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-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=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-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=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-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=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-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
|
||||
|
||||
+8
-4
@@ -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=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-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=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-type>
|
||||
GET_PROPERTY ?.length type=kotlin.Int?
|
||||
$this: GET_VAR s type=kotlin.String?
|
||||
|
||||
@@ -2,8 +2,12 @@ IrFile /extensionPropertyGetterCall.kt
|
||||
IrProperty public val kotlin.String.okext: kotlin.String getter=<get-okext> setter=null
|
||||
IrPropertyGetter public fun kotlin.String.<get-okext>(): kotlin.String property=okext
|
||||
IrExpressionBody
|
||||
LITERAL String type=kotlin.String value='OK'
|
||||
BLOCK type=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-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=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-type>
|
||||
GET_PROPERTY .okext type=kotlin.String
|
||||
$receiver: $RECEIVER of: test5 type=kotlin.String
|
||||
|
||||
+19
-7
@@ -8,13 +8,19 @@ IrFile /references.kt
|
||||
IrProperty public val ok3: kotlin.String getter=<get-ok3> setter=null
|
||||
IrPropertyGetter public fun <get-ok3>(): kotlin.String property=ok3
|
||||
IrExpressionBody
|
||||
LITERAL String type=kotlin.String value='OK'
|
||||
BLOCK type=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-type>
|
||||
LITERAL String type=kotlin.String value='OK'
|
||||
IrFunction public fun test1(): kotlin.String
|
||||
IrExpressionBody
|
||||
GET_PROPERTY .ok type=kotlin.String
|
||||
BLOCK type=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-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=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-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=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-type>
|
||||
GET_PROPERTY .ok3 type=kotlin.String
|
||||
IrProperty public val kotlin.String.okext: kotlin.String getter=<get-okext> setter=null
|
||||
IrPropertyGetter public fun kotlin.String.<get-okext>(): kotlin.String property=okext
|
||||
IrExpressionBody
|
||||
LITERAL String type=kotlin.String value='OK'
|
||||
BLOCK type=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-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=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-type>
|
||||
GET_PROPERTY .okext type=kotlin.String
|
||||
$receiver: $RECEIVER of: test5 type=kotlin.String
|
||||
|
||||
+6
-2
@@ -10,14 +10,18 @@ IrFile /smoke.kt
|
||||
IrProperty public val testValWithGetter: kotlin.Int getter=<get-testValWithGetter> setter=null
|
||||
IrPropertyGetter public fun <get-testValWithGetter>(): kotlin.Int property=testValWithGetter
|
||||
IrExpressionBody
|
||||
LITERAL Int type=kotlin.Int value='42'
|
||||
BLOCK type=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-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=<get-testVarWithAccessors> setter=<set-testVarWithAccessors>
|
||||
IrPropertyGetter public fun <get-testVarWithAccessors>(): kotlin.Int property=testVarWithAccessors
|
||||
IrExpressionBody
|
||||
LITERAL Int type=kotlin.Int value='42'
|
||||
BLOCK type=<no-type> hasResult=false isDesugared=true
|
||||
RETURN type=<no-type>
|
||||
LITERAL Int type=kotlin.Int value='42'
|
||||
IrPropertySetter public fun <set-testVarWithAccessors>(/*0*/ v: kotlin.Int): kotlin.Unit property=testVarWithAccessors
|
||||
IrExpressionBody
|
||||
BLOCK type=kotlin.Unit hasResult=false isDesugared=false
|
||||
|
||||
Reference in New Issue
Block a user