JS backend: In CallInfo: receiver1, receiver2 -> ExplicitReceivers. Drop CallInfo.nullableReceiverForSafeCall, move constructSafeCall to extension for CallInfo
This commit is contained in:
@@ -38,7 +38,6 @@ trait CallInfo {
|
||||
|
||||
val thisObject: JsExpression?
|
||||
val receiverObject: JsExpression?
|
||||
val nullableReceiverForSafeCall: JsExpression?
|
||||
}
|
||||
|
||||
// if value == null, it is get access
|
||||
@@ -46,6 +45,29 @@ class VariableAccessInfo(callInfo: CallInfo, val value: JsExpression? = null): C
|
||||
|
||||
class FunctionCallInfo(callInfo: CallInfo, val argumentsInfo: CallArgumentTranslator.ArgumentsInfo) : CallInfo by callInfo
|
||||
|
||||
/**
|
||||
* no receivers - thisObjectOrReceiverObject = null, receiverObject = null
|
||||
* this - thisObjectOrReceiverObject = this, receiverObject = null
|
||||
* receiver - thisObjectOrReceiverObject = receiver, receiverObject = null
|
||||
* both - thisObjectOrReceiverObject = this, receiverObject = receiver
|
||||
*/
|
||||
class ExplicitReceivers(val receiverOrThisObject: JsExpression?, val receiverObject: JsExpression? = null)
|
||||
|
||||
fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out CallableDescriptor>, receiver: JsExpression?): CallInfo {
|
||||
return createCallInfo(resolvedCall, ExplicitReceivers(receiver))
|
||||
}
|
||||
|
||||
fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out FunctionDescriptor>, receiver: JsExpression?): FunctionCallInfo {
|
||||
return getCallInfo(resolvedCall, ExplicitReceivers(receiver));
|
||||
}
|
||||
|
||||
// two receiver need only for FunctionCall in VariableAsFunctionResolvedCall
|
||||
fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out FunctionDescriptor>, explicitReceivers: ExplicitReceivers): FunctionCallInfo {
|
||||
val callInfo = createCallInfo(resolvedCall, explicitReceivers)
|
||||
val argumentsInfo = CallArgumentTranslator.translate(resolvedCall, explicitReceivers.receiverOrThisObject, this)
|
||||
return FunctionCallInfo(callInfo, argumentsInfo)
|
||||
}
|
||||
|
||||
|
||||
val CallInfo.callableDescriptor: CallableDescriptor
|
||||
get() {
|
||||
@@ -57,9 +79,6 @@ fun CallInfo.isExtension(): Boolean {
|
||||
fun CallInfo.isMemberCall(): Boolean {
|
||||
return thisObject != null
|
||||
}
|
||||
fun CallInfo.isSafeCall(): Boolean {
|
||||
return resolvedCall.isSafeCall()
|
||||
}
|
||||
fun CallInfo.isNative(): Boolean {
|
||||
return AnnotationsUtils.isNativeObject(callableDescriptor)
|
||||
}
|
||||
@@ -67,6 +86,20 @@ fun CallInfo.isSuperInvocation() : Boolean {
|
||||
val thisObject = resolvedCall.getThisObject()
|
||||
return thisObject is ExpressionReceiver && ((thisObject as ExpressionReceiver)).getExpression() is JetSuperExpression
|
||||
}
|
||||
fun CallInfo.constructSafeCallIsNeeded(result: JsExpression): JsExpression {
|
||||
if (!resolvedCall.isSafeCall())
|
||||
return result
|
||||
|
||||
val nullableReceiverForSafeCall = when (resolvedCall.getExplicitReceiverKind()) {
|
||||
BOTH_RECEIVERS, RECEIVER_ARGUMENT -> receiverObject
|
||||
else -> thisObject
|
||||
}
|
||||
return CallType.SAFE.constructCall(nullableReceiverForSafeCall, object : CallType.CallConstructor {
|
||||
override fun construct(receiver: JsExpression?): JsExpression {
|
||||
return result
|
||||
}
|
||||
}, context)
|
||||
}
|
||||
|
||||
val VariableAccessInfo.variableDescriptor: VariableDescriptor
|
||||
get() {
|
||||
@@ -81,28 +114,21 @@ fun VariableAccessInfo.isGetAccess(): Boolean {
|
||||
}
|
||||
|
||||
val FunctionCallInfo.functionName : JsName
|
||||
get() { // getter, because for several descriptors name is undefined. Example: {(a) -> a+1}(3)
|
||||
get() {
|
||||
return context.getNameForDescriptor(callableDescriptor)
|
||||
}
|
||||
fun FunctionCallInfo.hasSpreadOperator() : Boolean {
|
||||
return argumentsInfo.isHasSpreadOperator()
|
||||
}
|
||||
|
||||
|
||||
private fun TranslationContext.getThisObject(receiverValue: ReceiverValue): JsExpression {
|
||||
assert(receiverValue.exists(), "receiverValue must be exist here")
|
||||
return getThisObject(getDeclarationDescriptorForReceiver(receiverValue))
|
||||
}
|
||||
|
||||
private fun TranslationContext.createCallInfo(resolvedCall: ResolvedCall<out CallableDescriptor>, receiver1: JsExpression?, receiver2: JsExpression?): CallInfo {
|
||||
private fun TranslationContext.createCallInfo(resolvedCall: ResolvedCall<out CallableDescriptor>, explicitReceivers: ExplicitReceivers): CallInfo {
|
||||
val receiverKind = resolvedCall.getExplicitReceiverKind()
|
||||
fun getNotNullReceiver1(): JsExpression {
|
||||
assert(receiver1 != null, "ResolvedCall say, that receiver(1) must be not null")
|
||||
return receiver1!!
|
||||
}
|
||||
fun getNotNullReceiver2(): JsExpression {
|
||||
assert(receiver2 != null, "ResolvedCall say, that receiver(2) must be not null")
|
||||
return receiver2!!
|
||||
}
|
||||
|
||||
fun getThisObject(): JsExpression? {
|
||||
val receiverValue = resolvedCall.getThisObject()
|
||||
@@ -110,8 +136,7 @@ private fun TranslationContext.createCallInfo(resolvedCall: ResolvedCall<out Cal
|
||||
return null
|
||||
}
|
||||
return when (receiverKind) {
|
||||
THIS_OBJECT -> getNotNullReceiver1()
|
||||
BOTH_RECEIVERS -> getNotNullReceiver2()
|
||||
THIS_OBJECT, BOTH_RECEIVERS -> explicitReceivers.receiverOrThisObject
|
||||
else -> this.getThisObject(receiverValue)
|
||||
}
|
||||
}
|
||||
@@ -122,7 +147,8 @@ private fun TranslationContext.createCallInfo(resolvedCall: ResolvedCall<out Cal
|
||||
return null
|
||||
}
|
||||
return when (receiverKind) {
|
||||
RECEIVER_ARGUMENT, BOTH_RECEIVERS -> getNotNullReceiver1()
|
||||
RECEIVER_ARGUMENT -> explicitReceivers.receiverOrThisObject
|
||||
BOTH_RECEIVERS -> explicitReceivers.receiverObject
|
||||
else -> this.getThisObject(receiverValue)
|
||||
}
|
||||
}
|
||||
@@ -132,8 +158,8 @@ private fun TranslationContext.createCallInfo(resolvedCall: ResolvedCall<out Cal
|
||||
return null
|
||||
}
|
||||
return when (receiverKind) {
|
||||
BOTH_RECEIVERS -> getNotNullReceiver1()
|
||||
else -> getNotNullReceiver1()
|
||||
BOTH_RECEIVERS -> explicitReceivers.receiverObject
|
||||
else -> explicitReceivers.receiverOrThisObject
|
||||
}
|
||||
}
|
||||
return object : CallInfo {
|
||||
@@ -141,26 +167,5 @@ private fun TranslationContext.createCallInfo(resolvedCall: ResolvedCall<out Cal
|
||||
override val resolvedCall: ResolvedCall<out CallableDescriptor> = resolvedCall
|
||||
override val thisObject: JsExpression? = getThisObject()
|
||||
override val receiverObject: JsExpression? = getReceiverObject()
|
||||
override val nullableReceiverForSafeCall: JsExpression? = getNullableReceiverForSafeCall()
|
||||
};
|
||||
}
|
||||
|
||||
fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out CallableDescriptor>, receiver: JsExpression?): CallInfo {
|
||||
return createCallInfo(resolvedCall, receiver, null)
|
||||
}
|
||||
|
||||
fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out FunctionDescriptor>, receiver: JsExpression?): FunctionCallInfo {
|
||||
return getCallInfo(resolvedCall, receiver, null);
|
||||
}
|
||||
|
||||
// two receiver need only for FunctionCall in VariableAsFunctionResolvedCall
|
||||
fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out FunctionDescriptor>, receiver1: JsExpression?, receiver2: JsExpression?): FunctionCallInfo {
|
||||
val callInfo = createCallInfo(resolvedCall, receiver1, receiver2)
|
||||
|
||||
val receiverForArgsTranslator = if (resolvedCall.getExplicitReceiverKind() == BOTH_RECEIVERS) // TODO: remove this hack
|
||||
receiver2
|
||||
else
|
||||
receiver1
|
||||
val argumentsInfo = CallArgumentTranslator.translate(resolvedCall, receiverForArgsTranslator, this)
|
||||
return FunctionCallInfo(callInfo, argumentsInfo)
|
||||
}
|
||||
}
|
||||
+11
-22
@@ -37,7 +37,7 @@ val functionCallCases: CallCaseDispatcher<FunctionCallCase, FunctionCallInfo> =
|
||||
val variableAccessCases: CallCaseDispatcher<VariableAccessCase, VariableAccessInfo> = createVariableAccessCases()
|
||||
|
||||
fun TranslationContext.buildCall(resolvedCall: ResolvedCall<out FunctionDescriptor>, receiverOrThisObject: JsExpression? = null): JsExpression {
|
||||
return buildCall(resolvedCall, receiverOrThisObject, null)
|
||||
return buildCall(resolvedCall, ExplicitReceivers(receiverOrThisObject))
|
||||
}
|
||||
|
||||
fun TranslationContext.buildGet(resolvedCall: ResolvedCall<out VariableDescriptor>, receiverOrThisObject: JsExpression? = null): JsExpression {
|
||||
@@ -66,23 +66,23 @@ fun ResolvedCall<out CallableDescriptor>.expectedReceivers(): Boolean {
|
||||
return this.getExplicitReceiverKind() != NO_EXPLICIT_RECEIVER
|
||||
}
|
||||
|
||||
private fun TranslationContext.buildCall(resolvedCall: ResolvedCall<out FunctionDescriptor>, receiver1: JsExpression?, receiver2: JsExpression?): JsExpression {
|
||||
private fun TranslationContext.buildCall(resolvedCall: ResolvedCall<out FunctionDescriptor>, explicitReceivers: ExplicitReceivers): JsExpression {
|
||||
if (resolvedCall is VariableAsFunctionResolvedCall) {
|
||||
assert(receiver2 == null, "receiver2 for VariableAsFunctionResolvedCall must be null") // TODO: add debug info
|
||||
assert(explicitReceivers.receiverObject == null, "VariableAsFunctionResolvedCall must have one receiver") // TODO: add debug info
|
||||
val variableCall = resolvedCall.getVariableCall()
|
||||
if (variableCall.expectedReceivers()) {
|
||||
val newReceiver = buildGet(variableCall, receiver1)
|
||||
return buildCall(resolvedCall.getFunctionCall(), newReceiver, null)
|
||||
val newReceiver = buildGet(variableCall, explicitReceivers.receiverOrThisObject)
|
||||
return buildCall(resolvedCall.getFunctionCall(), ExplicitReceivers(newReceiver))
|
||||
} else {
|
||||
val newReceiver2 = buildGet(variableCall, null)
|
||||
if (receiver1 == null)
|
||||
return buildCall(resolvedCall.getFunctionCall(), newReceiver2)
|
||||
val thisObject = buildGet(variableCall, null)
|
||||
if (explicitReceivers.receiverOrThisObject == null)
|
||||
return buildCall(resolvedCall.getFunctionCall(), ExplicitReceivers(thisObject))
|
||||
else
|
||||
return buildCall(resolvedCall.getFunctionCall(), receiver1, newReceiver2)
|
||||
return buildCall(resolvedCall.getFunctionCall(), ExplicitReceivers(thisObject, explicitReceivers.receiverOrThisObject))
|
||||
}
|
||||
}
|
||||
|
||||
val functionCallInfo = getCallInfo(resolvedCall, receiver1, receiver2)
|
||||
val functionCallInfo = getCallInfo(resolvedCall, explicitReceivers)
|
||||
return functionCallCases.translate(functionCallInfo)
|
||||
}
|
||||
|
||||
@@ -113,14 +113,6 @@ trait CallCase<I : CallInfo> {
|
||||
throw unsupported()
|
||||
}
|
||||
|
||||
fun constructSafeCall(result: JsExpression): JsExpression {
|
||||
return CallType.SAFE.constructCall(callInfo.nullableReceiverForSafeCall, object : CallType.CallConstructor {
|
||||
override fun construct(receiver: JsExpression?): JsExpression {
|
||||
return result
|
||||
}
|
||||
}, callInfo.context)
|
||||
}
|
||||
|
||||
final fun translate(): JsExpression {
|
||||
val result = if (callInfo.thisObject == null) {
|
||||
if (callInfo.receiverObject == null)
|
||||
@@ -134,10 +126,7 @@ trait CallCase<I : CallInfo> {
|
||||
callInfo.bothReceivers()
|
||||
}
|
||||
|
||||
return if (callInfo.isSafeCall())
|
||||
constructSafeCall(result)
|
||||
else
|
||||
return result
|
||||
return callInfo.constructSafeCallIsNeeded(result)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user