Handle empty lambdas properly.

This commit is contained in:
Dmitry Petrov
2016-09-05 11:15:29 +03:00
committed by Dmitry Petrov
parent 539d7ccf6f
commit a4b9f6b215
5 changed files with 39 additions and 18 deletions
@@ -70,11 +70,17 @@ class BodyGenerator(val scopeOwner: DeclarationDescriptor, override val context:
val ktBody = ktFun.bodyExpression!!
val irBlockBody = IrBlockBodyImpl(ktBody.startOffset, ktBody.endOffset)
if (ktBody is KtBlockExpression) {
for (ktStatement in ktBody.statements.subList(0, ktBody.statements.size - 1)) {
irBlockBody.addStatement(statementGenerator.generateStatement(ktStatement))
val ktBodyStatements = ktBody.statements
if (ktBodyStatements.isNotEmpty()) {
for (ktStatement in ktBodyStatements.dropLast(1)) {
irBlockBody.addStatement(statementGenerator.generateStatement(ktStatement))
}
val ktReturnedValue = ktBodyStatements.last()
statementGenerator.generateReturnExpression(ktReturnedValue, irBlockBody)
}
else {
irBlockBody.addStatement(generateReturnExpression(ktBody.startOffset, ktBody.endOffset, null))
}
val ktReturnedValue = ktBody.statements.last()
statementGenerator.generateReturnExpression(ktReturnedValue, irBlockBody)
}
return irBlockBody
@@ -100,12 +106,15 @@ class BodyGenerator(val scopeOwner: DeclarationDescriptor, override val context:
if (KotlinBuiltIns.isNothing(type))
this
else {
val returnTarget = (scopeOwner as? CallableDescriptor) ?:
throw AssertionError("'return' in a non-callable: $scopeOwner")
IrReturnImpl(startOffset, endOffset, context.builtIns.nothingType,
returnTarget, this)
generateReturnExpression(startOffset, endOffset, this)
}
private fun generateReturnExpression(startOffset: Int, endOffset: Int, returnValue: IrExpression?): IrReturnImpl {
val returnTarget = (scopeOwner as? CallableDescriptor) ?:
throw AssertionError("'return' in a non-callable: $scopeOwner")
return IrReturnImpl(startOffset, endOffset, context.builtIns.nothingType, returnTarget, returnValue)
}
fun generateSecondaryConstructorBody(ktConstructor: KtSecondaryConstructor): IrBody {
val irBlockBody = IrBlockBodyImpl(ktConstructor.startOffset, ktConstructor.endOffset)
@@ -27,17 +27,20 @@ import org.jetbrains.kotlin.types.ErrorUtils
class ErrorExpressionGenerator(statementGenerator: StatementGenerator) : StatementGeneratorExtension(statementGenerator) {
private val ignoreErrors: Boolean get() = context.configuration.ignoreErrors
private inline fun generateErrorExpression(message: String? = null, body: () -> IrExpression) =
if (ignoreErrors) body() else throw RuntimeException(message)
private inline fun generateErrorExpression(ktElement: KtElement, e: Exception? = null, body: () -> IrExpression) =
if (ignoreErrors)
body()
else
throw RuntimeException("${e?.message}: ${ktElement.javaClass.simpleName}:\n${ktElement.text}", e)
fun generateErrorExpression(ktElement: KtElement, message: String?): IrExpression =
generateErrorExpression {
fun generateErrorExpression(ktElement: KtElement, e: Exception): IrExpression =
generateErrorExpression(ktElement, e) {
IrErrorExpressionImpl(ktElement.startOffset, ktElement.endOffset,
if (ktElement is KtExpression) getErrorExpressionType(ktElement) else ErrorUtils.createErrorType(""),
message ?: "")
e.message ?: "")
}
fun generateErrorCall(ktCall: KtCallExpression): IrExpression = generateErrorExpression {
fun generateErrorCall(ktCall: KtCallExpression): IrExpression = generateErrorExpression(ktCall) {
val type = getErrorExpressionType(ktCall)
val irErrorCall = IrErrorCallExpressionImpl(ktCall.startOffset, ktCall.endOffset, type, "") // TODO problem description?
@@ -62,7 +65,7 @@ class ErrorExpressionGenerator(statementGenerator: StatementGenerator) : Stateme
private fun getErrorExpressionType(ktExpression: KtExpression) =
getInferredTypeWithImplicitCasts(ktExpression) ?: ErrorUtils.createErrorType("")
fun generateErrorSimpleName(ktName: KtSimpleNameExpression): IrExpression = generateErrorExpression {
fun generateErrorSimpleName(ktName: KtSimpleNameExpression): IrExpression = generateErrorExpression(ktName) {
val type = getErrorExpressionType(ktName)
val irErrorCall = IrErrorCallExpressionImpl(ktName.startOffset, ktName.endOffset, type, "") // TODO problem description?
@@ -60,7 +60,7 @@ class StatementGenerator(
deparenthesize().accept(this@StatementGenerator, null)
}
catch (e: Exception) {
ErrorExpressionGenerator(this@StatementGenerator).generateErrorExpression(this, e.message)
ErrorExpressionGenerator(this@StatementGenerator).generateErrorExpression(this, e)
}
private fun KtElement.genExpr(): IrExpression =
+3 -1
View File
@@ -1 +1,3 @@
val lambda = { 42 }
val test1 = { 42 }
val test2 = { }
+8 -1
View File
@@ -1,5 +1,5 @@
FILE /justLambda.kt
PROPERTY public val lambda: () -> kotlin.Int
PROPERTY public val test1: () -> kotlin.Int
EXPRESSION_BODY
BLOCK type=() -> kotlin.Int operator=LAMBDA
FUN local final fun <anonymous>(): kotlin.Int
@@ -7,3 +7,10 @@ FILE /justLambda.kt
RETURN type=kotlin.Nothing from=<anonymous>
CONST Int type=kotlin.Int value='42'
CALLABLE_REFERENCE <anonymous> type=() -> kotlin.Int operator=LAMBDA
PROPERTY public val test2: () -> kotlin.Unit
EXPRESSION_BODY
BLOCK type=() -> kotlin.Unit operator=LAMBDA
FUN local final fun <anonymous>(): kotlin.Unit
BLOCK_BODY
RETURN type=kotlin.Nothing from=<anonymous>
CALLABLE_REFERENCE <anonymous> type=() -> kotlin.Unit operator=LAMBDA