Lambda expressions (no closures yet).
This commit is contained in:
committed by
Dmitry Petrov
parent
0b647ac358
commit
83c3bdd788
+5
@@ -236,6 +236,11 @@
|
|||||||
<scope name="idea openapi" level="WARNING" enabled="true" />
|
<scope name="idea openapi" level="WARNING" enabled="true" />
|
||||||
<scope name="runtime.classes" level="ERROR" enabled="true" />
|
<scope name="runtime.classes" level="ERROR" enabled="true" />
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
|
<inspection_tool class="LoggerInitializedWithForeignClass" enabled="false" level="WARNING" enabled_by_default="false">
|
||||||
|
<option name="loggerClassName" value="org.apache.log4j.Logger,org.slf4j.LoggerFactory,org.apache.commons.logging.LogFactory,java.util.logging.Logger" />
|
||||||
|
<option name="loggerFactoryMethodName" value="getLogger,getLogger,getLog,getLogger" />
|
||||||
|
</inspection_tool>
|
||||||
|
<inspection_tool class="LoopToCallChain" enabled="false" level="INFO" enabled_by_default="false" />
|
||||||
<inspection_tool class="MethodMayBeStatic" enabled="true" level="WARNING" enabled_by_default="true">
|
<inspection_tool class="MethodMayBeStatic" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
<option name="m_onlyPrivateOrFinal" value="false" />
|
<option name="m_onlyPrivateOrFinal" value="false" />
|
||||||
<option name="m_ignoreEmptyMethods" value="true" />
|
<option name="m_ignoreEmptyMethods" value="true" />
|
||||||
|
|||||||
@@ -16,10 +16,12 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.psi2ir.generators
|
package org.jetbrains.kotlin.psi2ir.generators
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.psi.KtBlockExpression
|
import org.jetbrains.kotlin.psi.KtBlockExpression
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtFunctionLiteral
|
||||||
import org.jetbrains.kotlin.psi.KtLoopExpression
|
import org.jetbrains.kotlin.psi.KtLoopExpression
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
@@ -30,8 +32,6 @@ class BodyGenerator(val scopeOwner: CallableDescriptor, override val context: Ge
|
|||||||
private val loopTable = HashMap<KtLoopExpression, IrLoop>()
|
private val loopTable = HashMap<KtLoopExpression, IrLoop>()
|
||||||
|
|
||||||
fun generateFunctionBody(ktBody: KtExpression): IrBody {
|
fun generateFunctionBody(ktBody: KtExpression): IrBody {
|
||||||
resetInternalContext()
|
|
||||||
|
|
||||||
val statementGenerator = createStatementGenerator()
|
val statementGenerator = createStatementGenerator()
|
||||||
|
|
||||||
val irBlockBody = IrBlockBodyImpl(ktBody.startOffset, ktBody.endOffset)
|
val irBlockBody = IrBlockBodyImpl(ktBody.startOffset, ktBody.endOffset)
|
||||||
@@ -42,21 +42,17 @@ class BodyGenerator(val scopeOwner: CallableDescriptor, override val context: Ge
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val irBodyExpression = statementGenerator.generateExpression(ktBody)
|
val irBodyExpression = statementGenerator.generateExpression(ktBody)
|
||||||
val irReturn = IrReturnImpl(ktBody.startOffset, ktBody.endOffset, context.builtIns.nothingType, scopeOwner, irBodyExpression)
|
irBlockBody.addStatement(irBodyExpression.wrapWithReturn())
|
||||||
irBlockBody.addStatement(irReturn)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
postprocessFunctionBody()
|
|
||||||
|
|
||||||
return irBlockBody
|
return irBlockBody
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resetInternalContext() {
|
private fun IrExpression.wrapWithReturn() =
|
||||||
loopTable.clear()
|
if (KotlinBuiltIns.isNothing(type))
|
||||||
}
|
this
|
||||||
|
else
|
||||||
private fun postprocessFunctionBody() {
|
IrReturnImpl(startOffset, endOffset, context.builtIns.nothingType, scopeOwner, this)
|
||||||
}
|
|
||||||
|
|
||||||
fun generatePropertyInitializerBody(ktInitializer: KtExpression): IrBody =
|
fun generatePropertyInitializerBody(ktInitializer: KtExpression): IrBody =
|
||||||
IrExpressionBodyImpl(ktInitializer.startOffset, ktInitializer.endOffset,
|
IrExpressionBodyImpl(ktInitializer.startOffset, ktInitializer.endOffset,
|
||||||
@@ -71,5 +67,24 @@ class BodyGenerator(val scopeOwner: CallableDescriptor, override val context: Ge
|
|||||||
|
|
||||||
fun getLoop(expression: KtExpression): IrLoop? =
|
fun getLoop(expression: KtExpression): IrLoop? =
|
||||||
loopTable[expression]
|
loopTable[expression]
|
||||||
|
|
||||||
|
fun generateLambdaBody(ktFun: KtFunctionLiteral): IrBody {
|
||||||
|
val statementGenerator = createStatementGenerator()
|
||||||
|
|
||||||
|
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 ktReturnedValue = ktBody.statements.last()
|
||||||
|
irBlockBody.addStatement(statementGenerator.generateExpression(ktReturnedValue).wrapWithReturn())
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
irBlockBody.addStatement(statementGenerator.generateExpression(ktBody).wrapWithReturn())
|
||||||
|
}
|
||||||
|
|
||||||
|
return irBlockBody
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.psi2ir.generators
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFunctionImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrBlockImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrCallableReferenceImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrOperator
|
||||||
|
import org.jetbrains.kotlin.psi.KtLambdaExpression
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
|
||||||
|
class LocalFunctionGenerator(val statementGenerator: StatementGenerator) : GeneratorWithScope {
|
||||||
|
override val scope: Scope get() = statementGenerator.scope
|
||||||
|
override val context: GeneratorContext get() = statementGenerator.context
|
||||||
|
|
||||||
|
fun generateLambda(ktLambda: KtLambdaExpression): IrStatement {
|
||||||
|
val ktFun = ktLambda.functionLiteral
|
||||||
|
val lambdaExpressionType = getInferredTypeWithSmartcastsOrFail(ktLambda)
|
||||||
|
val lambdaDescriptor = getOrFail(BindingContext.FUNCTION, ktFun)
|
||||||
|
val irBlock = IrBlockImpl(ktLambda.startOffset, ktLambda.endOffset, lambdaExpressionType, IrOperator.LAMBDA)
|
||||||
|
|
||||||
|
val irFun = IrFunctionImpl(ktFun.startOffset, ktFun.endOffset, IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA, lambdaDescriptor)
|
||||||
|
irFun.body = BodyGenerator(lambdaDescriptor, statementGenerator.context).generateLambdaBody(ktFun)
|
||||||
|
irBlock.addStatement(irFun)
|
||||||
|
|
||||||
|
irBlock.addStatement(IrCallableReferenceImpl(ktLambda.startOffset, ktLambda.endOffset, lambdaExpressionType, lambdaDescriptor))
|
||||||
|
|
||||||
|
return irBlock
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+9
-3
@@ -26,7 +26,9 @@ import org.jetbrains.kotlin.psi.*
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||||
import org.jetbrains.kotlin.psi2ir.deparenthesize
|
import org.jetbrains.kotlin.psi2ir.deparenthesize
|
||||||
import org.jetbrains.kotlin.psi2ir.intermediate.*
|
import org.jetbrains.kotlin.psi2ir.intermediate.IntermediateValue
|
||||||
|
import org.jetbrains.kotlin.psi2ir.intermediate.createRematerializableOrTemporary
|
||||||
|
import org.jetbrains.kotlin.psi2ir.intermediate.setExplicitReceiverValue
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.BindingContextUtils
|
import org.jetbrains.kotlin.resolve.BindingContextUtils
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
@@ -40,10 +42,11 @@ import org.jetbrains.kotlin.resolve.constants.StringValue
|
|||||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
|
import org.jetbrains.kotlin.resolve.descriptorUtil.classValueType
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
||||||
|
import java.lang.AssertionError
|
||||||
|
|
||||||
class StatementGenerator(
|
class StatementGenerator(
|
||||||
override val context: GeneratorContext,
|
override val context: GeneratorContext,
|
||||||
val scopeOwner: DeclarationDescriptor,
|
val scopeOwner: CallableDescriptor,
|
||||||
val bodyGenerator: BodyGenerator,
|
val bodyGenerator: BodyGenerator,
|
||||||
override val scope: Scope
|
override val scope: Scope
|
||||||
) : KtVisitor<IrStatement, Nothing?>(), GeneratorWithScope {
|
) : KtVisitor<IrStatement, Nothing?>(), GeneratorWithScope {
|
||||||
@@ -316,4 +319,7 @@ class StatementGenerator(
|
|||||||
override fun visitTryExpression(expression: KtTryExpression, data: Nothing?): IrStatement =
|
override fun visitTryExpression(expression: KtTryExpression, data: Nothing?): IrStatement =
|
||||||
TryCatchExpressionGenerator(this).generateTryCatch(expression)
|
TryCatchExpressionGenerator(this).generateTryCatch(expression)
|
||||||
|
|
||||||
}
|
override fun visitLambdaExpression(expression: KtLambdaExpression, data: Nothing?): IrStatement =
|
||||||
|
LocalFunctionGenerator(this).generateLambda(expression)
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ enum class IrDeclarationKind {
|
|||||||
|
|
||||||
enum class IrDeclarationOrigin {
|
enum class IrDeclarationOrigin {
|
||||||
DEFINED,
|
DEFINED,
|
||||||
|
LOCAL_FUNCTION_FOR_LAMBDA,
|
||||||
IR_TEMPORARY_VARIABLE,
|
IR_TEMPORARY_VARIABLE,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.ir.expressions
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
|
|
||||||
|
interface IrCallableReference : IrDeclarationReference {
|
||||||
|
override val descriptor: CallableDescriptor
|
||||||
|
|
||||||
|
// TODO closure
|
||||||
|
}
|
||||||
|
|
||||||
|
class IrCallableReferenceImpl(
|
||||||
|
startOffset: Int,
|
||||||
|
endOffset: Int,
|
||||||
|
type: KotlinType,
|
||||||
|
descriptor: CallableDescriptor
|
||||||
|
) : IrDeclarationReferenceBase<CallableDescriptor>(startOffset, endOffset, type, descriptor), IrCallableReference {
|
||||||
|
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
|
||||||
|
return visitor.visitCallableReference(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getChild(slot: Int): IrElement? {
|
||||||
|
// TODO
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun replaceChild(slot: Int, newChild: IrElement) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -85,6 +85,9 @@ interface IrOperator {
|
|||||||
object FOR_LOOP_HAS_NEXT : IrOperatorImpl("FOR_LOOP_HAS_NEXT")
|
object FOR_LOOP_HAS_NEXT : IrOperatorImpl("FOR_LOOP_HAS_NEXT")
|
||||||
object FOR_LOOP_NEXT : IrOperatorImpl("FOR_LOOP_NEXT")
|
object FOR_LOOP_NEXT : IrOperatorImpl("FOR_LOOP_NEXT")
|
||||||
|
|
||||||
|
object LAMBDA : IrOperatorImpl("LAMBDA")
|
||||||
|
|
||||||
|
|
||||||
data class COMPONENT_N private constructor(val index: Int) : IrOperatorImpl("COMPONENT_$index") {
|
data class COMPONENT_N private constructor(val index: Int) : IrOperatorImpl("COMPONENT_$index") {
|
||||||
companion object {
|
companion object {
|
||||||
private val precreatedComponents = Array(32) { i -> COMPONENT_N(i + 1) }
|
private val precreatedComponents = Array(32) { i -> COMPONENT_N(i + 1) }
|
||||||
@@ -97,8 +100,6 @@ interface IrOperator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IrOperator.isAssignmentOperatorWithResult() =
|
fun IrOperator.isAssignmentOperatorWithResult() =
|
||||||
|
|||||||
@@ -67,10 +67,10 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
|
|||||||
"BLOCK_BODY"
|
"BLOCK_BODY"
|
||||||
|
|
||||||
override fun visitExpression(expression: IrExpression, data: Nothing?): String =
|
override fun visitExpression(expression: IrExpression, data: Nothing?): String =
|
||||||
"? ${expression.javaClass.simpleName} type=${expression.renderType()}"
|
"? ${expression.javaClass.simpleName} type=${expression.type.render()}"
|
||||||
|
|
||||||
override fun <T> visitConst(expression: IrConst<T>, data: Nothing?): String =
|
override fun <T> visitConst(expression: IrConst<T>, data: Nothing?): String =
|
||||||
"CONST ${expression.kind} type=${expression.renderType()} value='${expression.value}'"
|
"CONST ${expression.kind} type=${expression.type.render()} value='${expression.value}'"
|
||||||
|
|
||||||
override fun visitVararg(expression: IrVararg, data: Nothing?): String =
|
override fun visitVararg(expression: IrVararg, data: Nothing?): String =
|
||||||
"VARARG type=${expression.type} varargElementType=${expression.varargElementType}"
|
"VARARG type=${expression.type} varargElementType=${expression.varargElementType}"
|
||||||
@@ -79,35 +79,35 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
|
|||||||
"SPREAD_ELEMENT"
|
"SPREAD_ELEMENT"
|
||||||
|
|
||||||
override fun visitBlock(expression: IrBlock, data: Nothing?): String =
|
override fun visitBlock(expression: IrBlock, data: Nothing?): String =
|
||||||
"BLOCK type=${expression.renderType()} operator=${expression.operator}"
|
"BLOCK type=${expression.type.render()} operator=${expression.operator}"
|
||||||
|
|
||||||
override fun visitReturn(expression: IrReturn, data: Nothing?): String =
|
override fun visitReturn(expression: IrReturn, data: Nothing?): String =
|
||||||
"RETURN type=${expression.renderType()}"
|
"RETURN type=${expression.type.render()}"
|
||||||
|
|
||||||
override fun visitGetExtensionReceiver(expression: IrGetExtensionReceiver, data: Nothing?): String =
|
override fun visitGetExtensionReceiver(expression: IrGetExtensionReceiver, data: Nothing?): String =
|
||||||
"\$RECEIVER of: ${expression.descriptor.containingDeclaration.name} type=${expression.renderType()}"
|
"\$RECEIVER of: ${expression.descriptor.containingDeclaration.name} type=${expression.type.render()}"
|
||||||
|
|
||||||
override fun visitThisReference(expression: IrThisReference, data: Nothing?): String =
|
override fun visitThisReference(expression: IrThisReference, data: Nothing?): String =
|
||||||
"THIS ${expression.classDescriptor.render()} type=${expression.renderType()}"
|
"THIS ${expression.classDescriptor.render()} type=${expression.type.render()}"
|
||||||
|
|
||||||
override fun visitCall(expression: IrCall, data: Nothing?): String =
|
override fun visitCall(expression: IrCall, data: Nothing?): String =
|
||||||
"CALL .${expression.descriptor.name} " +
|
"CALL .${expression.descriptor.name} " +
|
||||||
"type=${expression.renderType()} operator=${expression.operator}"
|
"type=${expression.type.render()} operator=${expression.operator}"
|
||||||
|
|
||||||
override fun visitGetVariable(expression: IrGetVariable, data: Nothing?): String =
|
override fun visitGetVariable(expression: IrGetVariable, data: Nothing?): String =
|
||||||
"GET_VAR ${expression.descriptor.name} type=${expression.renderType()} operator=${expression.operator}"
|
"GET_VAR ${expression.descriptor.name} type=${expression.type.render()} operator=${expression.operator}"
|
||||||
|
|
||||||
override fun visitSetVariable(expression: IrSetVariable, data: Nothing?): String =
|
override fun visitSetVariable(expression: IrSetVariable, data: Nothing?): String =
|
||||||
"SET_VAR ${expression.descriptor.name} type=${expression.renderType()} operator=${expression.operator}"
|
"SET_VAR ${expression.descriptor.name} type=${expression.type.render()} operator=${expression.operator}"
|
||||||
|
|
||||||
override fun visitGetObjectValue(expression: IrGetObjectValue, data: Nothing?): String =
|
override fun visitGetObjectValue(expression: IrGetObjectValue, data: Nothing?): String =
|
||||||
"GET_OBJECT ${expression.descriptor.name} type=${expression.renderType()}"
|
"GET_OBJECT ${expression.descriptor.name} type=${expression.type.render()}"
|
||||||
|
|
||||||
override fun visitGetEnumValue(expression: IrGetEnumValue, data: Nothing?): String =
|
override fun visitGetEnumValue(expression: IrGetEnumValue, data: Nothing?): String =
|
||||||
"GET_ENUM_VALUE ${expression.descriptor.name} type=${expression.renderType()}"
|
"GET_ENUM_VALUE ${expression.descriptor.name} type=${expression.type.render()}"
|
||||||
|
|
||||||
override fun visitStringConcatenation(expression: IrStringConcatenation, data: Nothing?): String =
|
override fun visitStringConcatenation(expression: IrStringConcatenation, data: Nothing?): String =
|
||||||
"STRING_CONCATENATION type=${expression.renderType()}"
|
"STRING_CONCATENATION type=${expression.type.render()}"
|
||||||
|
|
||||||
override fun visitTypeOperator(expression: IrTypeOperatorCall, data: Nothing?): String =
|
override fun visitTypeOperator(expression: IrTypeOperatorCall, data: Nothing?): String =
|
||||||
"TYPE_OP operator=${expression.operator} typeOperand=${expression.typeOperand.render()}"
|
"TYPE_OP operator=${expression.operator} typeOperand=${expression.typeOperand.render()}"
|
||||||
@@ -128,16 +128,19 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
|
|||||||
"CONTINUE label=${jump.label} depth=${jump.getDepth()}"
|
"CONTINUE label=${jump.label} depth=${jump.getDepth()}"
|
||||||
|
|
||||||
override fun visitThrow(expression: IrThrow, data: Nothing?): String =
|
override fun visitThrow(expression: IrThrow, data: Nothing?): String =
|
||||||
"THROW type=${expression.renderType()}"
|
"THROW type=${expression.type.render()}"
|
||||||
|
|
||||||
|
override fun visitCallableReference(expression: IrCallableReference, data: Nothing?): String =
|
||||||
|
"CALLABLE_REFERENCE ${expression.descriptor.render()} type=${expression.type.render()}"
|
||||||
|
|
||||||
override fun visitTryCatch(tryCatch: IrTryCatch, data: Nothing?): String =
|
override fun visitTryCatch(tryCatch: IrTryCatch, data: Nothing?): String =
|
||||||
"TRY_CATCH type=${tryCatch.renderType()}"
|
"TRY_CATCH type=${tryCatch.type.render()}"
|
||||||
|
|
||||||
override fun visitDummyDeclaration(declaration: IrDummyDeclaration, data: Nothing?): String =
|
override fun visitDummyDeclaration(declaration: IrDummyDeclaration, data: Nothing?): String =
|
||||||
"DUMMY ${declaration.descriptor.javaClass.simpleName} ${declaration.descriptor.name}"
|
"DUMMY ${declaration.descriptor.javaClass.simpleName} ${declaration.descriptor.name}"
|
||||||
|
|
||||||
override fun visitDummyExpression(expression: IrDummyExpression, data: Nothing?): String =
|
override fun visitDummyExpression(expression: IrDummyExpression, data: Nothing?): String =
|
||||||
"DUMMY ${expression.description} type=${expression.renderType()}"
|
"DUMMY ${expression.description} type=${expression.type.render()}"
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val DESCRIPTOR_RENDERER = DescriptorRenderer.withOptions {
|
private val DESCRIPTOR_RENDERER = DescriptorRenderer.withOptions {
|
||||||
@@ -155,9 +158,6 @@ class RenderIrElementVisitor : IrElementVisitor<String, Nothing?> {
|
|||||||
internal fun DeclarationDescriptor?.render(): String =
|
internal fun DeclarationDescriptor?.render(): String =
|
||||||
this?.let { DESCRIPTOR_RENDERER.render(it) } ?: "<none>"
|
this?.let { DESCRIPTOR_RENDERER.render(it) } ?: "<none>"
|
||||||
|
|
||||||
internal fun IrExpression.renderType(): String =
|
|
||||||
type.render()
|
|
||||||
|
|
||||||
internal fun KotlinType?.render(): String =
|
internal fun KotlinType?.render(): String =
|
||||||
this?.let { DESCRIPTOR_RENDERER.renderType(it) } ?: "<no-type>"
|
this?.let { DESCRIPTOR_RENDERER.renderType(it) } ?: "<no-type>"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ interface IrElementVisitor<out R, in D> {
|
|||||||
fun visitSetVariable(expression: IrSetVariable, data: D) = visitDeclarationReference(expression, data)
|
fun visitSetVariable(expression: IrSetVariable, data: D) = visitDeclarationReference(expression, data)
|
||||||
fun visitGetExtensionReceiver(expression: IrGetExtensionReceiver, data: D) = visitDeclarationReference(expression, data)
|
fun visitGetExtensionReceiver(expression: IrGetExtensionReceiver, data: D) = visitDeclarationReference(expression, data)
|
||||||
fun visitCall(expression: IrCall, data: D) = visitDeclarationReference(expression, data)
|
fun visitCall(expression: IrCall, data: D) = visitDeclarationReference(expression, data)
|
||||||
|
fun visitCallableReference(expression: IrCallableReference, data: D) = visitDeclarationReference(expression, data)
|
||||||
|
|
||||||
fun visitTypeOperator(expression: IrTypeOperatorCall, data: D) = visitExpression(expression, data)
|
fun visitTypeOperator(expression: IrTypeOperatorCall, data: D) = visitExpression(expression, data)
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,12 @@ FILE /variableAsFunctionCall.kt
|
|||||||
FUN public fun kotlin.String.k(): () -> kotlin.String
|
FUN public fun kotlin.String.k(): () -> kotlin.String
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
RETURN type=kotlin.Nothing
|
RETURN type=kotlin.Nothing
|
||||||
DUMMY KtLambdaExpression type=() -> kotlin.String
|
BLOCK type=() -> kotlin.String operator=LAMBDA
|
||||||
|
FUN local final fun <anonymous>(): kotlin.String
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing
|
||||||
|
$RECEIVER of: k type=kotlin.String
|
||||||
|
CALLABLE_REFERENCE local final fun <anonymous>(): kotlin.String type=() -> kotlin.String
|
||||||
FUN public fun test1(/*0*/ f: () -> kotlin.Unit): kotlin.Unit
|
FUN public fun test1(/*0*/ f: () -> kotlin.Unit): kotlin.Unit
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
RETURN type=kotlin.Nothing
|
RETURN type=kotlin.Nothing
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
fun test1() = "42".run { length }
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
FILE /extensionLambda.kt
|
||||||
|
FUN public fun test1(): kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing
|
||||||
|
CALL .run type=kotlin.Int operator=null
|
||||||
|
$receiver: CONST String type=kotlin.String value='42'
|
||||||
|
block: BLOCK type=kotlin.String.() -> kotlin.Int operator=LAMBDA
|
||||||
|
FUN local final fun kotlin.String.<anonymous>(): kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing
|
||||||
|
CALL .<get-length> type=kotlin.Int operator=GET_PROPERTY
|
||||||
|
$this: $RECEIVER of: <anonymous> type=kotlin.String
|
||||||
|
CALLABLE_REFERENCE local final fun kotlin.String.<anonymous>(): kotlin.Int type=kotlin.String.() -> kotlin.Int
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
val lambda = { 42 }
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
FILE /justLambda.kt
|
||||||
|
PROPERTY public val lambda: () -> kotlin.Int getter=null setter=null
|
||||||
|
EXPRESSION_BODY
|
||||||
|
BLOCK type=() -> kotlin.Int operator=LAMBDA
|
||||||
|
FUN local final fun <anonymous>(): kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing
|
||||||
|
CONST Int type=kotlin.Int value='42'
|
||||||
|
CALLABLE_REFERENCE local final fun <anonymous>(): kotlin.Int type=() -> kotlin.Int
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
object A
|
||||||
|
object B
|
||||||
|
|
||||||
|
interface IFoo {
|
||||||
|
val A.foo: B get() = B
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IInvoke {
|
||||||
|
operator fun B.invoke() = 42
|
||||||
|
}
|
||||||
|
|
||||||
|
fun test(fooImpl: IFoo, invokeImpl: IInvoke) {
|
||||||
|
with(A) {
|
||||||
|
with(fooImpl) {
|
||||||
|
with(invokeImpl) {
|
||||||
|
foo()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
FILE /multipleImplicitReceivers.kt
|
||||||
|
CLASS OBJECT A
|
||||||
|
CLASS OBJECT B
|
||||||
|
CLASS INTERFACE IFoo
|
||||||
|
PROPERTY public open val A.foo: B getter=<get-foo> setter=null
|
||||||
|
PROPERTY_GETTER public open fun A.<get-foo>(): B property=foo
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing
|
||||||
|
GET_OBJECT B type=B
|
||||||
|
CLASS INTERFACE IInvoke
|
||||||
|
FUN public open operator fun B.invoke(): kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing
|
||||||
|
CONST Int type=kotlin.Int value='42'
|
||||||
|
FUN public fun test(/*0*/ fooImpl: IFoo, /*1*/ invokeImpl: IInvoke): kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
CALL .with type=kotlin.Int operator=null
|
||||||
|
receiver: GET_OBJECT A type=A
|
||||||
|
block: BLOCK type=A.() -> kotlin.Int operator=LAMBDA
|
||||||
|
FUN local final fun A.<anonymous>(): kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing
|
||||||
|
CALL .with type=kotlin.Int operator=null
|
||||||
|
receiver: GET_VAR fooImpl type=IFoo operator=null
|
||||||
|
block: BLOCK type=IFoo.() -> kotlin.Int operator=LAMBDA
|
||||||
|
FUN local final fun IFoo.<anonymous>(): kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing
|
||||||
|
CALL .with type=kotlin.Int operator=null
|
||||||
|
receiver: GET_VAR invokeImpl type=IInvoke operator=null
|
||||||
|
block: BLOCK type=IInvoke.() -> kotlin.Int operator=LAMBDA
|
||||||
|
FUN local final fun IInvoke.<anonymous>(): kotlin.Int
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing
|
||||||
|
CALL .invoke type=kotlin.Int operator=INVOKE
|
||||||
|
$this: $RECEIVER of: <anonymous> type=IInvoke
|
||||||
|
$receiver: CALL .<get-foo> type=B operator=GET_PROPERTY
|
||||||
|
$this: $RECEIVER of: <anonymous> type=IFoo
|
||||||
|
$receiver: $RECEIVER of: <anonymous> type=A
|
||||||
|
CALLABLE_REFERENCE local final fun IInvoke.<anonymous>(): kotlin.Int type=IInvoke.() -> kotlin.Int
|
||||||
|
CALLABLE_REFERENCE local final fun IFoo.<anonymous>(): kotlin.Int type=IFoo.() -> kotlin.Int
|
||||||
|
CALLABLE_REFERENCE local final fun A.<anonymous>(): kotlin.Int type=A.() -> kotlin.Int
|
||||||
@@ -352,4 +352,31 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/ir/irText/lambdas")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Lambdas extends AbstractIrTextTestCase {
|
||||||
|
public void testAllFilesPresentInLambdas() throws Exception {
|
||||||
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/ir/irText/lambdas"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("extensionLambda.kt")
|
||||||
|
public void testExtensionLambda() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/lambdas/extensionLambda.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("justLambda.kt")
|
||||||
|
public void testJustLambda() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/lambdas/justLambda.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("multipleImplicitReceivers.kt")
|
||||||
|
public void testMultipleImplicitReceivers() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/lambdas/multipleImplicitReceivers.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user