Variable as function calls.
This commit is contained in:
committed by
Dmitry Petrov
parent
b3407de1e6
commit
3f256fab67
@@ -109,8 +109,10 @@ fun StatementGenerator.pregenerateCall(resolvedCall: ResolvedCall<*>): CallBuild
|
||||
fun StatementGenerator.pregenerateCallReceivers(resolvedCall: ResolvedCall<*>): CallBuilder {
|
||||
val call = CallBuilder(resolvedCall)
|
||||
|
||||
val ktDefaultCallElement = resolvedCall.call.callElement
|
||||
call.callReceiver = generateCallReceiver(ktDefaultCallElement, resolvedCall.dispatchReceiver, resolvedCall.extensionReceiver, resolvedCall.call.isSafeCall())
|
||||
call.callReceiver = generateCallReceiver(resolvedCall.call.callElement,
|
||||
resolvedCall.dispatchReceiver,
|
||||
resolvedCall.extensionReceiver,
|
||||
resolvedCall.call.isSafeCall())
|
||||
|
||||
return call
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.psi2ir.generators
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
@@ -50,6 +51,10 @@ class CallGenerator(
|
||||
return when (descriptor) {
|
||||
is PropertyDescriptor ->
|
||||
generatePropertyGetterCall(descriptor, startOffset, endOffset, call)
|
||||
is VariableDescriptor ->
|
||||
call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
||||
IrGetVariableImpl(startOffset, endOffset, descriptor, operator)
|
||||
}
|
||||
is FunctionDescriptor ->
|
||||
generateFunctionCall(descriptor, startOffset, endOffset, operator, call)
|
||||
else ->
|
||||
|
||||
+5
-5
@@ -26,9 +26,7 @@ import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.psi2ir.deparenthesize
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.Value
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.createRematerializableOrTemporary
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.setExplicitReceiverValue
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
@@ -183,7 +181,8 @@ class StatementGenerator(
|
||||
val resolvedCall = getResolvedCall(expression) ?: throw AssertionError("No resolved call for ${expression.text}")
|
||||
|
||||
if (resolvedCall is VariableAsFunctionResolvedCall) {
|
||||
TODO("Unexpected VariableAsFunctionResolvedCall")
|
||||
val variableCall = pregenerateCall(resolvedCall.variableCall)
|
||||
return CallGenerator(this).generateCall(expression, variableCall, IrOperator.VARIABLE_AS_FUNCTION)
|
||||
}
|
||||
|
||||
val descriptor = resolvedCall.resultingDescriptor
|
||||
@@ -222,7 +221,8 @@ class StatementGenerator(
|
||||
val resolvedCall = getResolvedCall(expression) ?: TODO("No resolved call for call expression")
|
||||
|
||||
if (resolvedCall is VariableAsFunctionResolvedCall) {
|
||||
TODO("VariableAsFunctionResolvedCall = variable call + invoke call")
|
||||
val functionCall = pregenerateCall(resolvedCall.functionCall)
|
||||
return CallGenerator(this).generateCall(expression, functionCall, IrOperator.INVOKE)
|
||||
}
|
||||
|
||||
return CallGenerator(this).generateCall(expression.startOffset, expression.endOffset, pregenerateCall(resolvedCall))
|
||||
|
||||
@@ -24,10 +24,10 @@ import org.jetbrains.kotlin.psi2ir.intermediate.CallBuilder
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
class OnceCallValue(
|
||||
val statementGenerator: StatementGenerator,
|
||||
val call: CallBuilder,
|
||||
val startOffset: Int,
|
||||
val endOffset: Int,
|
||||
val statementGenerator: StatementGenerator,
|
||||
val call: CallBuilder,
|
||||
val operator: IrOperator? = null
|
||||
): Value {
|
||||
private var instantiated = false
|
||||
|
||||
@@ -53,6 +53,7 @@ interface IrOperator {
|
||||
object RANGE : IrOperatorImpl("RANGE")
|
||||
|
||||
object INVOKE : IrOperatorImpl("INVOKE")
|
||||
object VARIABLE_AS_FUNCTION : IrOperatorImpl("VARIABLE_AS_FUNCTION")
|
||||
object GET_ARRAY_ELEMENT : IrOperatorImpl("GET_ARRAY_ELEMENT")
|
||||
|
||||
object PREFIX_INCR : IrOperatorImpl("PREFIX_INCR")
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
fun String.k(): () -> String = { -> this }
|
||||
|
||||
fun test1(f: () -> Unit) = f()
|
||||
fun test2(f: String.() -> Unit) = "hello".f()
|
||||
fun test3() = "hello".k()()
|
||||
fun test4(ns: String?) = ns?.k()?.invoke()
|
||||
@@ -0,0 +1,49 @@
|
||||
IrFile /variableAsFunctionCall.kt
|
||||
IrFunction public fun kotlin.String.k(): () -> kotlin.String
|
||||
IrExpressionBody
|
||||
BLOCK type=<no-type> hasResult=false operator=null
|
||||
RETURN type=<no-type>
|
||||
DUMMY KtLambdaExpression type=() -> kotlin.String
|
||||
IrFunction public fun test1(/*0*/ f: () -> kotlin.Unit): kotlin.Unit
|
||||
IrExpressionBody
|
||||
BLOCK type=<no-type> hasResult=false operator=null
|
||||
RETURN type=<no-type>
|
||||
CALL .invoke type=kotlin.Unit operator=INVOKE
|
||||
$this: GET_VAR f type=() -> kotlin.Unit operator=VARIABLE_AS_FUNCTION
|
||||
IrFunction public fun test2(/*0*/ f: kotlin.String.() -> kotlin.Unit): kotlin.Unit
|
||||
IrExpressionBody
|
||||
BLOCK type=<no-type> hasResult=false operator=null
|
||||
RETURN type=<no-type>
|
||||
CALL .invoke type=kotlin.Unit operator=INVOKE
|
||||
$this: GET_VAR f type=kotlin.String.() -> kotlin.Unit operator=VARIABLE_AS_FUNCTION
|
||||
$receiver: CONST String type=kotlin.String value='hello'
|
||||
IrFunction public fun test3(): kotlin.String
|
||||
IrExpressionBody
|
||||
BLOCK type=<no-type> hasResult=false operator=null
|
||||
RETURN type=<no-type>
|
||||
CALL .invoke type=kotlin.String operator=null
|
||||
$this: CALL .k type=() -> kotlin.String operator=null
|
||||
$receiver: CONST String type=kotlin.String value='hello'
|
||||
IrFunction public fun test4(/*0*/ ns: kotlin.String?): kotlin.String?
|
||||
IrExpressionBody
|
||||
BLOCK type=<no-type> hasResult=false operator=null
|
||||
RETURN type=<no-type>
|
||||
BLOCK type=kotlin.String? hasResult=true operator=SAFE_CALL
|
||||
VAR val tmp1_safe_receiver: (() -> kotlin.String)?
|
||||
BLOCK type=(() -> kotlin.String)? hasResult=true operator=SAFE_CALL
|
||||
VAR val tmp0_safe_receiver: kotlin.String?
|
||||
GET_VAR ns type=kotlin.String? operator=null
|
||||
WHEN type=(() -> kotlin.String)? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR tmp0_safe_receiver type=kotlin.String? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .k type=() -> kotlin.String operator=null
|
||||
$this: GET_VAR tmp0_safe_receiver type=kotlin.String? operator=null
|
||||
WHEN type=kotlin.String? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR tmp1_safe_receiver type=(() -> kotlin.String)? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .invoke type=kotlin.String operator=null
|
||||
$this: GET_VAR tmp1_safe_receiver type=(() -> kotlin.String)? operator=null
|
||||
@@ -287,6 +287,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("variableAsFunctionCall.kt")
|
||||
public void testVariableAsFunctionCall() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/variableAsFunctionCall.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("when.kt")
|
||||
public void testWhen() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/when.kt");
|
||||
|
||||
Reference in New Issue
Block a user