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 thisObject: JsExpression?
|
||||||
val receiverObject: JsExpression?
|
val receiverObject: JsExpression?
|
||||||
val nullableReceiverForSafeCall: JsExpression?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if value == null, it is get access
|
// 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
|
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
|
val CallInfo.callableDescriptor: CallableDescriptor
|
||||||
get() {
|
get() {
|
||||||
@@ -57,9 +79,6 @@ fun CallInfo.isExtension(): Boolean {
|
|||||||
fun CallInfo.isMemberCall(): Boolean {
|
fun CallInfo.isMemberCall(): Boolean {
|
||||||
return thisObject != null
|
return thisObject != null
|
||||||
}
|
}
|
||||||
fun CallInfo.isSafeCall(): Boolean {
|
|
||||||
return resolvedCall.isSafeCall()
|
|
||||||
}
|
|
||||||
fun CallInfo.isNative(): Boolean {
|
fun CallInfo.isNative(): Boolean {
|
||||||
return AnnotationsUtils.isNativeObject(callableDescriptor)
|
return AnnotationsUtils.isNativeObject(callableDescriptor)
|
||||||
}
|
}
|
||||||
@@ -67,6 +86,20 @@ fun CallInfo.isSuperInvocation() : Boolean {
|
|||||||
val thisObject = resolvedCall.getThisObject()
|
val thisObject = resolvedCall.getThisObject()
|
||||||
return thisObject is ExpressionReceiver && ((thisObject as ExpressionReceiver)).getExpression() is JetSuperExpression
|
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
|
val VariableAccessInfo.variableDescriptor: VariableDescriptor
|
||||||
get() {
|
get() {
|
||||||
@@ -81,28 +114,21 @@ fun VariableAccessInfo.isGetAccess(): Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val FunctionCallInfo.functionName : JsName
|
val FunctionCallInfo.functionName : JsName
|
||||||
get() { // getter, because for several descriptors name is undefined. Example: {(a) -> a+1}(3)
|
get() {
|
||||||
return context.getNameForDescriptor(callableDescriptor)
|
return context.getNameForDescriptor(callableDescriptor)
|
||||||
}
|
}
|
||||||
fun FunctionCallInfo.hasSpreadOperator() : Boolean {
|
fun FunctionCallInfo.hasSpreadOperator() : Boolean {
|
||||||
return argumentsInfo.isHasSpreadOperator()
|
return argumentsInfo.isHasSpreadOperator()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun TranslationContext.getThisObject(receiverValue: ReceiverValue): JsExpression {
|
private fun TranslationContext.getThisObject(receiverValue: ReceiverValue): JsExpression {
|
||||||
assert(receiverValue.exists(), "receiverValue must be exist here")
|
assert(receiverValue.exists(), "receiverValue must be exist here")
|
||||||
return getThisObject(getDeclarationDescriptorForReceiver(receiverValue))
|
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()
|
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? {
|
fun getThisObject(): JsExpression? {
|
||||||
val receiverValue = resolvedCall.getThisObject()
|
val receiverValue = resolvedCall.getThisObject()
|
||||||
@@ -110,8 +136,7 @@ private fun TranslationContext.createCallInfo(resolvedCall: ResolvedCall<out Cal
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
return when (receiverKind) {
|
return when (receiverKind) {
|
||||||
THIS_OBJECT -> getNotNullReceiver1()
|
THIS_OBJECT, BOTH_RECEIVERS -> explicitReceivers.receiverOrThisObject
|
||||||
BOTH_RECEIVERS -> getNotNullReceiver2()
|
|
||||||
else -> this.getThisObject(receiverValue)
|
else -> this.getThisObject(receiverValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,7 +147,8 @@ private fun TranslationContext.createCallInfo(resolvedCall: ResolvedCall<out Cal
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
return when (receiverKind) {
|
return when (receiverKind) {
|
||||||
RECEIVER_ARGUMENT, BOTH_RECEIVERS -> getNotNullReceiver1()
|
RECEIVER_ARGUMENT -> explicitReceivers.receiverOrThisObject
|
||||||
|
BOTH_RECEIVERS -> explicitReceivers.receiverObject
|
||||||
else -> this.getThisObject(receiverValue)
|
else -> this.getThisObject(receiverValue)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -132,8 +158,8 @@ private fun TranslationContext.createCallInfo(resolvedCall: ResolvedCall<out Cal
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
return when (receiverKind) {
|
return when (receiverKind) {
|
||||||
BOTH_RECEIVERS -> getNotNullReceiver1()
|
BOTH_RECEIVERS -> explicitReceivers.receiverObject
|
||||||
else -> getNotNullReceiver1()
|
else -> explicitReceivers.receiverOrThisObject
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return object : CallInfo {
|
return object : CallInfo {
|
||||||
@@ -141,26 +167,5 @@ private fun TranslationContext.createCallInfo(resolvedCall: ResolvedCall<out Cal
|
|||||||
override val resolvedCall: ResolvedCall<out CallableDescriptor> = resolvedCall
|
override val resolvedCall: ResolvedCall<out CallableDescriptor> = resolvedCall
|
||||||
override val thisObject: JsExpression? = getThisObject()
|
override val thisObject: JsExpression? = getThisObject()
|
||||||
override val receiverObject: JsExpression? = getReceiverObject()
|
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()
|
val variableAccessCases: CallCaseDispatcher<VariableAccessCase, VariableAccessInfo> = createVariableAccessCases()
|
||||||
|
|
||||||
fun TranslationContext.buildCall(resolvedCall: ResolvedCall<out FunctionDescriptor>, receiverOrThisObject: JsExpression? = null): JsExpression {
|
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 {
|
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
|
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) {
|
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()
|
val variableCall = resolvedCall.getVariableCall()
|
||||||
if (variableCall.expectedReceivers()) {
|
if (variableCall.expectedReceivers()) {
|
||||||
val newReceiver = buildGet(variableCall, receiver1)
|
val newReceiver = buildGet(variableCall, explicitReceivers.receiverOrThisObject)
|
||||||
return buildCall(resolvedCall.getFunctionCall(), newReceiver, null)
|
return buildCall(resolvedCall.getFunctionCall(), ExplicitReceivers(newReceiver))
|
||||||
} else {
|
} else {
|
||||||
val newReceiver2 = buildGet(variableCall, null)
|
val thisObject = buildGet(variableCall, null)
|
||||||
if (receiver1 == null)
|
if (explicitReceivers.receiverOrThisObject == null)
|
||||||
return buildCall(resolvedCall.getFunctionCall(), newReceiver2)
|
return buildCall(resolvedCall.getFunctionCall(), ExplicitReceivers(thisObject))
|
||||||
else
|
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)
|
return functionCallCases.translate(functionCallInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,14 +113,6 @@ trait CallCase<I : CallInfo> {
|
|||||||
throw unsupported()
|
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 {
|
final fun translate(): JsExpression {
|
||||||
val result = if (callInfo.thisObject == null) {
|
val result = if (callInfo.thisObject == null) {
|
||||||
if (callInfo.receiverObject == null)
|
if (callInfo.receiverObject == null)
|
||||||
@@ -134,10 +126,7 @@ trait CallCase<I : CallInfo> {
|
|||||||
callInfo.bothReceivers()
|
callInfo.bothReceivers()
|
||||||
}
|
}
|
||||||
|
|
||||||
return if (callInfo.isSafeCall())
|
return callInfo.constructSafeCallIsNeeded(result)
|
||||||
constructSafeCall(result)
|
|
||||||
else
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user