- function with expression bodies are desugared to blocks with return statement;
- property initializers are generated as regular expression bodies.
This commit is contained in:
Dmitry Petrov
2016-08-15 13:32:48 +03:00
committed by Dmitry Petrov
parent 2707d33ca7
commit aa7bf4637b
9 changed files with 112 additions and 47 deletions
@@ -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
View File
@@ -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
View File
@@ -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
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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