JS backend: cosmetic changes & remake fakeCall
This commit is contained in:
@@ -39,52 +39,53 @@ trait CallInfo {
|
||||
val thisObject: JsExpression?
|
||||
val receiverObject: JsExpression?
|
||||
val nullableReceiverForSafeCall: JsExpression?
|
||||
|
||||
val callableDescriptor: CallableDescriptor
|
||||
get() {
|
||||
return resolvedCall.getResultingDescriptor().getOriginal()
|
||||
}
|
||||
|
||||
fun isExtension(): Boolean = receiverObject != null
|
||||
fun isMemberCall(): Boolean = thisObject != null
|
||||
fun isSafeCall(): Boolean = nullableReceiverForSafeCall != null
|
||||
fun isNative(): Boolean = AnnotationsUtils.isNativeObject(callableDescriptor)
|
||||
|
||||
fun isSuperInvocation() : Boolean {
|
||||
val thisObject = resolvedCall.getThisObject()
|
||||
return thisObject is ExpressionReceiver && ((thisObject as ExpressionReceiver)).getExpression() is JetSuperExpression
|
||||
}
|
||||
|
||||
// TODO: toString for debug
|
||||
}
|
||||
|
||||
// if setTo == null, it is get access
|
||||
class VariableAccessInfo(callInfo: CallInfo, private val setTo: JsExpression? = null): CallInfo by callInfo {
|
||||
val variableDescriptor = super.callableDescriptor as VariableDescriptor
|
||||
val variableName : JsName
|
||||
get() {
|
||||
return context.getNameForDescriptor(variableDescriptor)
|
||||
}
|
||||
// if value == null, it is get access
|
||||
class VariableAccessInfo(callInfo: CallInfo, val value: JsExpression? = null): CallInfo by callInfo
|
||||
|
||||
fun isGetAccess(): Boolean = setTo == null
|
||||
class FunctionCallInfo(callInfo: CallInfo, val argumentsInfo: CallArgumentTranslator.ArgumentsInfo) : CallInfo by callInfo
|
||||
|
||||
fun getSetToExpression(): JsExpression {
|
||||
if (isGetAccess()) {
|
||||
throw IllegalStateException("This is get, setTo is null. callInfo: $this")
|
||||
}
|
||||
return setTo!!
|
||||
|
||||
val CallInfo.callableDescriptor: CallableDescriptor
|
||||
get() {
|
||||
return resolvedCall.getResultingDescriptor().getOriginal()
|
||||
}
|
||||
fun CallInfo.isExtension(): Boolean {
|
||||
return receiverObject != null
|
||||
}
|
||||
fun CallInfo.isMemberCall(): Boolean {
|
||||
return thisObject != null
|
||||
}
|
||||
fun CallInfo.isSafeCall(): Boolean {
|
||||
return resolvedCall.isSafeCall()
|
||||
}
|
||||
fun CallInfo.isNative(): Boolean {
|
||||
return AnnotationsUtils.isNativeObject(callableDescriptor)
|
||||
}
|
||||
fun CallInfo.isSuperInvocation() : Boolean {
|
||||
val thisObject = resolvedCall.getThisObject()
|
||||
return thisObject is ExpressionReceiver && ((thisObject as ExpressionReceiver)).getExpression() is JetSuperExpression
|
||||
}
|
||||
|
||||
class FunctionCallInfo(callInfo: CallInfo, val argumentsInfo: CallArgumentTranslator.ArgumentsInfo) : CallInfo by callInfo {
|
||||
val functionName : JsName
|
||||
get() { // getter, because for several descriptors name is undefined. Example: {(a) -> a+1}(3)
|
||||
return context.getNameForDescriptor(callableDescriptor)
|
||||
}
|
||||
|
||||
fun hasSpreadOperator() : Boolean {
|
||||
return argumentsInfo.isHasSpreadOperator()
|
||||
val VariableAccessInfo.variableDescriptor: VariableDescriptor
|
||||
get() {
|
||||
return callableDescriptor as VariableDescriptor
|
||||
}
|
||||
val VariableAccessInfo.variableName : JsName
|
||||
get() {
|
||||
return context.getNameForDescriptor(variableDescriptor)
|
||||
}
|
||||
fun VariableAccessInfo.isGetAccess(): Boolean {
|
||||
return value == null
|
||||
}
|
||||
|
||||
val FunctionCallInfo.functionName : JsName
|
||||
get() { // getter, because for several descriptors name is undefined. Example: {(a) -> a+1}(3)
|
||||
return context.getNameForDescriptor(callableDescriptor)
|
||||
}
|
||||
fun FunctionCallInfo.hasSpreadOperator() : Boolean {
|
||||
return argumentsInfo.isHasSpreadOperator()
|
||||
}
|
||||
|
||||
private fun TranslationContext.getThisObject(receiverValue: ReceiverValue): JsExpression {
|
||||
@@ -92,7 +93,7 @@ private fun TranslationContext.getThisObject(receiverValue: ReceiverValue): JsEx
|
||||
return getThisObject(getDeclarationDescriptorForReceiver(receiverValue))
|
||||
}
|
||||
|
||||
private fun TranslationContext.mainGetCallInfo(resolvedCall: ResolvedCall<out CallableDescriptor>, receiver1: JsExpression?, receiver2: JsExpression?): CallInfo {
|
||||
private fun TranslationContext.createCallInfo(resolvedCall: ResolvedCall<out CallableDescriptor>, receiver1: JsExpression?, receiver2: JsExpression?): CallInfo {
|
||||
val receiverKind = resolvedCall.getExplicitReceiverKind()
|
||||
fun getNotNullReceiver1(): JsExpression {
|
||||
assert(receiver1 != null, "ResolvedCall say, that receiver(1) must be not null")
|
||||
@@ -136,7 +137,7 @@ private fun TranslationContext.mainGetCallInfo(resolvedCall: ResolvedCall<out Ca
|
||||
}
|
||||
}
|
||||
return object : CallInfo {
|
||||
override val context: TranslationContext = this@mainGetCallInfo
|
||||
override val context: TranslationContext = this@createCallInfo
|
||||
override val resolvedCall: ResolvedCall<out CallableDescriptor> = resolvedCall
|
||||
override val thisObject: JsExpression? = getThisObject()
|
||||
override val receiverObject: JsExpression? = getReceiverObject()
|
||||
@@ -144,12 +145,8 @@ private fun TranslationContext.mainGetCallInfo(resolvedCall: ResolvedCall<out Ca
|
||||
};
|
||||
}
|
||||
|
||||
fun ResolvedCall<out CallableDescriptor>.expectedReceivers(): Boolean {
|
||||
return this.getExplicitReceiverKind() != NO_EXPLICIT_RECEIVER
|
||||
}
|
||||
|
||||
fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out CallableDescriptor>, receiver: JsExpression?): CallInfo {
|
||||
return mainGetCallInfo(resolvedCall, receiver, null)
|
||||
return createCallInfo(resolvedCall, receiver, null)
|
||||
}
|
||||
|
||||
fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out FunctionDescriptor>, receiver: JsExpression?): FunctionCallInfo {
|
||||
@@ -158,7 +155,7 @@ fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out FunctionDescri
|
||||
|
||||
// two receiver need only for FunctionCall in VariableAsFunctionResolvedCall
|
||||
fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out FunctionDescriptor>, receiver1: JsExpression?, receiver2: JsExpression?): FunctionCallInfo {
|
||||
val callInfo = mainGetCallInfo(resolvedCall, receiver1, receiver2)
|
||||
val callInfo = createCallInfo(resolvedCall, receiver1, receiver2)
|
||||
|
||||
val receiverForArgsTranslator = if (resolvedCall.getExplicitReceiverKind() == BOTH_RECEIVERS) // TODO: remove this hack
|
||||
receiver2
|
||||
|
||||
+20
-19
@@ -30,39 +30,40 @@ import com.google.dart.compiler.backend.js.ast.JsNameRef
|
||||
import org.jetbrains.k2js.translate.utils.JsAstUtils
|
||||
import org.jetbrains.k2js.translate.context.Namer
|
||||
import org.jetbrains.k2js.translate.utils.ErrorReportingUtils
|
||||
import org.jetbrains.k2js.translate.utils.AnnotationsUtils
|
||||
|
||||
|
||||
val functionCallCases: CallCaseDispatcher<FunctionCallCase, FunctionCallInfo> = createFunctionCases()
|
||||
val variableAccessCases: CallCaseDispatcher<VariableAccessCase, VariableAccessInfo> = createVariableAccessCases()
|
||||
|
||||
fun TranslationContext.buildCall(resolvedCall: ResolvedCall<out FunctionDescriptor>, receiver: JsExpression? = null): JsExpression {
|
||||
return buildCall(resolvedCall, receiver, null)
|
||||
fun TranslationContext.buildCall(resolvedCall: ResolvedCall<out FunctionDescriptor>, receiverOrThisObject: JsExpression? = null): JsExpression {
|
||||
return buildCall(resolvedCall, receiverOrThisObject, null)
|
||||
}
|
||||
|
||||
fun TranslationContext.buildGet(resolvedCall: ResolvedCall<out VariableDescriptor>, receiver: JsExpression? = null): JsExpression {
|
||||
val variableAccessInfo = VariableAccessInfo(getCallInfo(resolvedCall, receiver), null);
|
||||
fun TranslationContext.buildGet(resolvedCall: ResolvedCall<out VariableDescriptor>, receiverOrThisObject: JsExpression? = null): JsExpression {
|
||||
val variableAccessInfo = VariableAccessInfo(getCallInfo(resolvedCall, receiverOrThisObject), null);
|
||||
return variableAccessCases.translate(variableAccessInfo)
|
||||
}
|
||||
|
||||
fun TranslationContext.buildSet(resolvedCall: ResolvedCall<out VariableDescriptor>, setTo: JsExpression, receiver: JsExpression? = null): JsExpression {
|
||||
val variableAccessInfo = VariableAccessInfo(getCallInfo(resolvedCall, receiver), setTo);
|
||||
fun TranslationContext.buildSet(resolvedCall: ResolvedCall<out VariableDescriptor>, value: JsExpression, receiverOrThisObject: JsExpression? = null): JsExpression {
|
||||
val variableAccessInfo = VariableAccessInfo(getCallInfo(resolvedCall, receiverOrThisObject), value);
|
||||
return variableAccessCases.translate(variableAccessInfo)
|
||||
}
|
||||
|
||||
fun TranslationContext.buildFakeCall(functionDescriptor: FunctionDescriptor, args: List<JsExpression>, thisObject: JsExpression?): JsExpression {
|
||||
val fakeCallInfo = object: CallInfo {
|
||||
override val context: TranslationContext = this@buildFakeCall
|
||||
override val resolvedCall: ResolvedCall<out CallableDescriptor>
|
||||
get() {
|
||||
throw UnsupportedOperationException("Resolved call for direct call unsupported")
|
||||
}
|
||||
override val callableDescriptor: CallableDescriptor = functionDescriptor
|
||||
override val thisObject: JsExpression? = thisObject
|
||||
override val receiverObject: JsExpression? = null
|
||||
override val nullableReceiverForSafeCall: JsExpression? = null
|
||||
val argumentsInfo = CallArgumentTranslator.ArgumentsInfo(args, false, null);
|
||||
val functionName = getNameForDescriptor(functionDescriptor)
|
||||
val isNative = AnnotationsUtils.isNativeObject(functionDescriptor)
|
||||
val hasSpreadOperator = false
|
||||
if (thisObject != null) {
|
||||
return DefaultCallCase.buildDefaultCallWithThisObject(argumentsInfo, thisObject, functionName, isNative, hasSpreadOperator)
|
||||
} else {
|
||||
return DefaultCallCase.buildDefaultCallWithoutReceiver(this, argumentsInfo, functionDescriptor, functionName, isNative, hasSpreadOperator)
|
||||
}
|
||||
val fakeFunctionInfo = FunctionCallInfo(fakeCallInfo, CallArgumentTranslator.ArgumentsInfo(args, false, null));
|
||||
return DefaultCallCase(fakeFunctionInfo).translate()
|
||||
}
|
||||
|
||||
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 {
|
||||
@@ -151,7 +152,7 @@ open class VariableAccessCase(override val callInfo: VariableAccessInfo) : CallC
|
||||
if (isGetAccess()) {
|
||||
return ref
|
||||
} else {
|
||||
return JsAstUtils.assignment(ref, getSetToExpression())
|
||||
return JsAstUtils.assignment(ref, value!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.jetbrains.k2js.translate.general.Translation
|
||||
import org.jetbrains.k2js.translate.utils.PsiUtils
|
||||
import com.google.dart.compiler.backend.js.ast.JsLiteral
|
||||
import com.google.dart.compiler.backend.js.ast.JsName
|
||||
import org.jetbrains.k2js.translate.context.TranslationContext
|
||||
|
||||
public fun addReceiverToArgs(receiver: JsExpression, arguments: List<JsExpression>) : List<JsExpression> {
|
||||
if (arguments.isEmpty())
|
||||
@@ -47,26 +48,52 @@ public fun addReceiverToArgs(receiver: JsExpression, arguments: List<JsExpressio
|
||||
|
||||
|
||||
// call may be native and|or with spreadOperator
|
||||
class DefaultCallCase(callInfo: FunctionCallInfo): FunctionCallCase(callInfo) { //TODO: check spreadOperator
|
||||
class DefaultCallCase(callInfo: FunctionCallInfo): FunctionCallCase(callInfo) {
|
||||
class object {
|
||||
// TODO: refactor after fix ArgumentsInfo - duplicate code
|
||||
private fun nativeSpreadFunWithThisObjectOrReceiver(argumentsInfo: CallArgumentTranslator.ArgumentsInfo, functionName: JsName): JsExpression {
|
||||
val cachedReceiver = argumentsInfo.getCachedReceiver()!!
|
||||
val functionCallRef = Namer.getFunctionApplyRef(JsNameRef(functionName, cachedReceiver.assignmentExpression()))
|
||||
return JsInvocation(functionCallRef, argumentsInfo.getTranslateArguments())
|
||||
}
|
||||
|
||||
override fun FunctionCallInfo.bothReceivers(): JsExpression { // TODO: think about crazy case: spreadOperator + native
|
||||
val functionRef = JsNameRef(functionName, thisObject!!)
|
||||
return JsInvocation(functionRef, addReceiverToArgs(receiverObject!!, argumentsInfo.getTranslateArguments()))
|
||||
fun buildDefaultCallWithThisObject(argumentsInfo: CallArgumentTranslator.ArgumentsInfo,
|
||||
thisObject: JsExpression,
|
||||
functionName: JsName,
|
||||
isNative: Boolean,
|
||||
hasSpreadOperator: Boolean): JsExpression {
|
||||
if (isNative && hasSpreadOperator) {
|
||||
return nativeSpreadFunWithThisObjectOrReceiver(argumentsInfo, functionName)
|
||||
}
|
||||
val functionRef = JsNameRef(functionName, thisObject)
|
||||
return JsInvocation(functionRef, argumentsInfo.getTranslateArguments())
|
||||
}
|
||||
|
||||
fun buildDefaultCallWithoutReceiver(context: TranslationContext,
|
||||
argumentsInfo: CallArgumentTranslator.ArgumentsInfo,
|
||||
callableDescriptor: CallableDescriptor,
|
||||
functionName: JsName,
|
||||
isNative: Boolean,
|
||||
hasSpreadOperator: Boolean): JsExpression {
|
||||
if (isNative && hasSpreadOperator) {
|
||||
val functionCallRef = Namer.getFunctionApplyRef(JsNameRef(functionName))
|
||||
return JsInvocation(functionCallRef, argumentsInfo.getTranslateArguments())
|
||||
}
|
||||
if (isNative) {
|
||||
return JsInvocation(JsNameRef(functionName), argumentsInfo.getTranslateArguments())
|
||||
}
|
||||
val qualifierForFunction = context.getQualifierForDescriptor(callableDescriptor)
|
||||
val functionCall = JsNameRef(functionName, qualifierForFunction)
|
||||
return JsInvocation(functionCall, argumentsInfo.getTranslateArguments())
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: refactor after fix ArgumentsInfo - duplicate code
|
||||
private fun nativeSpreadFunWithThisObjectOrReceiver(argumentsInfo: CallArgumentTranslator.ArgumentsInfo, functionName: JsName): JsExpression {
|
||||
val cachedReceiver = argumentsInfo.getCachedReceiver()!!
|
||||
val functionCallRef = Namer.getFunctionApplyRef(JsNameRef(functionName, cachedReceiver.assignmentExpression()))
|
||||
return JsInvocation(functionCallRef, argumentsInfo.getTranslateArguments())
|
||||
override fun FunctionCallInfo.noReceivers(): JsExpression {
|
||||
return buildDefaultCallWithoutReceiver(context, argumentsInfo, callableDescriptor, functionName, isNative(), hasSpreadOperator())
|
||||
}
|
||||
|
||||
override fun FunctionCallInfo.thisObject(): JsExpression {
|
||||
if (isNative() && hasSpreadOperator()) {
|
||||
return nativeSpreadFunWithThisObjectOrReceiver(argumentsInfo, functionName)
|
||||
}
|
||||
val functionRef = JsNameRef(functionName, thisObject!!)
|
||||
return JsInvocation(functionRef, argumentsInfo.getTranslateArguments())
|
||||
return buildDefaultCallWithThisObject(argumentsInfo, thisObject!!, functionName, isNative(), hasSpreadOperator())
|
||||
}
|
||||
|
||||
override fun FunctionCallInfo.receiverArgument(): JsExpression {
|
||||
@@ -80,17 +107,10 @@ class DefaultCallCase(callInfo: FunctionCallInfo): FunctionCallCase(callInfo) {
|
||||
val functionCall = JsNameRef(functionName, qualifierForFunction) // TODO: remake to call
|
||||
return JsInvocation(functionCall, addReceiverToArgs(receiverObject!!, argumentsInfo.getTranslateArguments()))
|
||||
}
|
||||
override fun FunctionCallInfo.noReceivers(): JsExpression {
|
||||
if (isNative() && hasSpreadOperator()) {
|
||||
val functionCallRef = Namer.getFunctionApplyRef(JsNameRef(functionName))
|
||||
return JsInvocation(functionCallRef, argumentsInfo.getTranslateArguments())
|
||||
}
|
||||
if (isNative()) {
|
||||
return JsInvocation(JsNameRef(functionName), argumentsInfo.getTranslateArguments())
|
||||
}
|
||||
val qualifierForFunction = context.getQualifierForDescriptor(callableDescriptor)
|
||||
val functionCall = JsNameRef(functionName, qualifierForFunction)
|
||||
return JsInvocation(functionCall, argumentsInfo.getTranslateArguments())
|
||||
|
||||
override fun FunctionCallInfo.bothReceivers(): JsExpression { // TODO: think about crazy case: spreadOperator + native
|
||||
val functionRef = JsNameRef(functionName, thisObject!!)
|
||||
return JsInvocation(functionRef, addReceiverToArgs(receiverObject!!, argumentsInfo.getTranslateArguments()))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ class DefaultVariableAccessCase(callInfo: VariableAccessInfo) : VariableAccessCa
|
||||
return if (isGetAccess()) {
|
||||
JsInvocation(funRef, receiverObject!!)
|
||||
} else {
|
||||
JsInvocation(funRef, receiverObject!!, getSetToExpression())
|
||||
JsInvocation(funRef, receiverObject!!, value!!)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,18 +68,11 @@ class DefaultVariableAccessCase(callInfo: VariableAccessInfo) : VariableAccessCa
|
||||
return if (isGetAccess()) {
|
||||
JsInvocation(funRef, receiverObject!!)
|
||||
} else {
|
||||
JsInvocation(funRef, receiverObject!!, getSetToExpression())
|
||||
JsInvocation(funRef, receiverObject!!, value!!)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ValueParameterAccessCase(callInfo: VariableAccessInfo) : VariableAccessCase(callInfo) {
|
||||
override fun VariableAccessInfo.noReceivers(): JsExpression {
|
||||
assert(isGetAccess(), "It must be get access. CallInfo: $callInfo")
|
||||
return variableName.makeRef()!!
|
||||
}
|
||||
}
|
||||
|
||||
class DelegatePropertyAccessIntrinsic(callInfo: VariableAccessInfo) : VariableAccessCase(callInfo), DelegateIntrinsic<VariableAccessInfo> {
|
||||
override fun VariableAccessInfo.canBeApply(): Boolean {
|
||||
return variableDescriptor is PropertyDescriptor
|
||||
@@ -89,7 +82,7 @@ class DelegatePropertyAccessIntrinsic(callInfo: VariableAccessInfo) : VariableAc
|
||||
return if (isGetAccess())
|
||||
Collections.emptyList<JsExpression>()
|
||||
else
|
||||
Collections.singletonList(getSetToExpression())
|
||||
Collections.singletonList(value!!)
|
||||
}
|
||||
|
||||
override fun VariableAccessInfo.getDescriptor(): CallableDescriptor {
|
||||
@@ -97,7 +90,7 @@ class DelegatePropertyAccessIntrinsic(callInfo: VariableAccessInfo) : VariableAc
|
||||
return if (isGetAccess()) {
|
||||
var getter = propertyDescriptor.getGetter()
|
||||
if (getter == null) {
|
||||
val getterImpl = DescriptorFactory.createDefaultGetter(variableDescriptor)
|
||||
val getterImpl = DescriptorFactory.createDefaultGetter(propertyDescriptor)
|
||||
getterImpl.initialize(propertyDescriptor.getType())
|
||||
((propertyDescriptor as PropertyDescriptorImpl)).initialize(getterImpl, propertyDescriptor.getSetter())
|
||||
getter = getterImpl
|
||||
@@ -106,7 +99,7 @@ class DelegatePropertyAccessIntrinsic(callInfo: VariableAccessInfo) : VariableAc
|
||||
} else {
|
||||
var setter = propertyDescriptor.getSetter()
|
||||
if (setter == null) {
|
||||
val setterImpl = DescriptorFactory.createDefaultSetter(variableDescriptor)
|
||||
val setterImpl = DescriptorFactory.createDefaultSetter(propertyDescriptor)
|
||||
((propertyDescriptor as PropertyDescriptorImpl)).initialize(propertyDescriptor.getGetter(), setterImpl)
|
||||
setter = setterImpl
|
||||
}
|
||||
@@ -121,7 +114,7 @@ class SuperPropertyAccessCase(callInfo: VariableAccessInfo) : VariableAccessCase
|
||||
return if (isGetAccess())
|
||||
JsInvocation(context.namer().getCallGetProperty(), JsLiteral.THIS, thisObject!!, variableName)
|
||||
else
|
||||
JsInvocation(context.namer().getCallSetProperty(), JsLiteral.THIS, thisObject!!, variableName, getSetToExpression())
|
||||
JsInvocation(context.namer().getCallSetProperty(), JsLiteral.THIS, thisObject!!, variableName, value!!)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +123,6 @@ fun createVariableAccessCases(): CallCaseDispatcher<VariableAccessCase, Variable
|
||||
|
||||
caseDispatcher.addCase { DelegatePropertyAccessIntrinsic(it).intrinsic() }
|
||||
caseDispatcher.addCase(::SuperPropertyAccessCase) { it.isSuperInvocation() }
|
||||
//caseDispatcher.addCase(::ValueParameterAccessCase) { it.variableDescriptor is ValueParameterDescriptor}
|
||||
caseDispatcher.addCase(::NativeVariableAccessCase) { it.isNative() }
|
||||
caseDispatcher.addCase(::DefaultVariableAccessCase) { true } // TODO: fix this
|
||||
return caseDispatcher
|
||||
|
||||
Reference in New Issue
Block a user