Introduce IrFunctionExpression IR element

Use it to represent proper function expressions (lambdas and anonymous
functions).
This commit is contained in:
Dmitry Petrov
2019-07-15 10:42:50 +03:00
parent 022275b781
commit ed2b4a8bec
40 changed files with 131 additions and 133 deletions
@@ -42,7 +42,7 @@ class FunctionGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
constructor(context: GeneratorContext) : this(DeclarationGenerator(context))
fun generateFunctionDeclaration(ktFunction: KtNamedFunction): IrFunction =
fun generateFunctionDeclaration(ktFunction: KtNamedFunction): IrSimpleFunction =
declareSimpleFunction(
ktFunction,
ktFunction.receiverTypeReference,
@@ -17,55 +17,30 @@
package org.jetbrains.kotlin.psi2ir.generators
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionExpressionImpl
import org.jetbrains.kotlin.psi.KtLambdaExpression
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.psiUtil.endOffset
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
import org.jetbrains.kotlin.psi.psiUtil.startOffset
class LocalFunctionGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) {
fun generateLambda(ktLambda: KtLambdaExpression): IrStatement {
val ktFun = ktLambda.functionLiteral
val lambdaExpressionType = getInferredTypeWithImplicitCastsOrFail(ktLambda).toIrType()
val irLambdaFunction = FunctionGenerator(context).generateLambdaFunctionDeclaration(ktFun)
val irBlock = IrBlockImpl(ktLambda.startOffset, ktLambda.endOffset, lambdaExpressionType, IrStatementOrigin.LAMBDA)
irBlock.statements.add(irLambdaFunction)
irBlock.statements.add(
IrFunctionReferenceImpl(
ktLambda.startOffset, ktLambda.endOffset, lambdaExpressionType,
irLambdaFunction.symbol, irLambdaFunction.symbol.descriptor, 0,
IrStatementOrigin.LAMBDA
)
)
return irBlock
return IrFunctionExpressionImpl(ktLambda.startOffset, ktLambda.endOffset, lambdaExpressionType, irLambdaFunction)
}
fun generateFunction(ktFun: KtNamedFunction): IrStatement =
if (ktFun.name != null) {
generateFunctionDeclaration(ktFun)
} else {
// anonymous function expression
val funExpressionType = getInferredTypeWithImplicitCastsOrFail(ktFun).toIrType()
val irBlock = IrBlockImpl(ktFun.startOffsetSkippingComments, ktFun.endOffset, funExpressionType, IrStatementOrigin.ANONYMOUS_FUNCTION)
fun generateFunction(ktFun: KtNamedFunction): IrStatement {
val irFun = generateFunctionDeclaration(ktFun)
if (ktFun.name != null) return irFun
val irFun = generateFunctionDeclaration(ktFun)
irBlock.statements.add(irFun)
val funExpressionType = getInferredTypeWithImplicitCastsOrFail(ktFun).toIrType()
return IrFunctionExpressionImpl(ktFun.startOffset, ktFun.endOffset, funExpressionType, irFun)
}
irBlock.statements.add(
IrFunctionReferenceImpl(
ktFun.startOffsetSkippingComments, ktFun.endOffset, funExpressionType,
irFun.symbol, irFun.symbol.descriptor, 0,
IrStatementOrigin.ANONYMOUS_FUNCTION
)
)
irBlock
}
private fun generateFunctionDeclaration(ktFun: KtNamedFunction): IrFunction =
private fun generateFunctionDeclaration(ktFun: KtNamedFunction) =
FunctionGenerator(context).generateFunctionDeclaration(ktFun)
}
@@ -0,0 +1,14 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.expressions
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
interface IrFunctionExpression : IrExpression {
var function: IrSimpleFunction
}
@@ -0,0 +1,34 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.expressions.impl
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.expressions.IrFunctionExpression
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
class IrFunctionExpressionImpl(
startOffset: Int,
endOffset: Int,
type: IrType,
override var function: IrSimpleFunction
) :
IrExpressionBase(startOffset, endOffset, type),
IrFunctionExpression {
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
return visitor.visitFunctionExpression(this, data)
}
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
function.accept(visitor, data)
}
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
function = function.transform(transformer, data) as IrSimpleFunction
}
}
@@ -589,6 +589,13 @@ open class DeepCopyIrTreeWithSymbols(
mapStatementOrigin(expression.origin)
)
override fun visitFunctionExpression(expression: IrFunctionExpression): IrFunctionExpression =
IrFunctionExpressionImpl(
expression.startOffset, expression.endOffset,
expression.type.remapType(),
expression.function.transform()
)
override fun visitClassReference(expression: IrClassReference): IrClassReference =
IrClassReferenceImpl(
expression.startOffset, expression.endOffset,
@@ -601,6 +601,11 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
append("origin=${expression.origin}")
}
override fun visitFunctionExpression(expression: IrFunctionExpression, data: Nothing?): String =
buildTrimEnd {
append("FUN_EXPR type=${expression.type.render()}")
}
override fun visitClassReference(expression: IrClassReference, data: Nothing?): String =
"CLASS_REFERENCE '${expression.symbol.renderReference()}' type=${expression.type.render()}"
@@ -98,6 +98,8 @@ interface IrElementTransformer<in D> : IrElementVisitor<IrElement, D> {
override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference, data: D) =
visitCallableReference(expression, data)
override fun visitFunctionExpression(expression: IrFunctionExpression, data: D): IrElement = visitExpression(expression, data)
override fun visitClassReference(expression: IrClassReference, data: D) = visitDeclarationReference(expression, data)
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall, data: D) = visitExpression(expression, data)
@@ -194,6 +194,10 @@ abstract class IrElementTransformerVoid : IrElementTransformer<Nothing?> {
final override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference, data: Nothing?) =
visitLocalDelegatedPropertyReference(expression)
open fun visitFunctionExpression(expression: IrFunctionExpression) = visitExpression(expression)
final override fun visitFunctionExpression(expression: IrFunctionExpression, data: Nothing?): IrElement =
visitFunctionExpression(expression)
open fun visitClassReference(expression: IrClassReference) = visitDeclarationReference(expression)
final override fun visitClassReference(expression: IrClassReference, data: Nothing?) = visitClassReference(expression)
@@ -84,6 +84,8 @@ interface IrElementVisitor<out R, in D> {
fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference, data: D) =
visitCallableReference(expression, data)
fun visitFunctionExpression(expression: IrFunctionExpression, data: D) = visitExpression(expression, data)
fun visitClassReference(expression: IrClassReference, data: D) = visitDeclarationReference(expression, data)
fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall, data: D) = visitExpression(expression, data)
@@ -184,6 +184,9 @@ interface IrElementVisitorVoid : IrElementVisitor<Unit, Nothing?> {
override fun visitLocalDelegatedPropertyReference(expression: IrLocalDelegatedPropertyReference, data: Nothing?) =
visitLocalDelegatedPropertyReference(expression)
fun visitFunctionExpression(expression: IrFunctionExpression) = visitExpression(expression)
override fun visitFunctionExpression(expression: IrFunctionExpression, data: Nothing?) = visitFunctionExpression(expression)
fun visitClassReference(expression: IrClassReference) = visitDeclarationReference(expression)
override fun visitClassReference(expression: IrClassReference, data: Nothing?) = visitClassReference(expression)