JS backend: cosmetic changes & class for cases remake to object

This commit is contained in:
Erokhin Stanislav
2014-01-30 16:43:39 +04:00
parent 97955776c4
commit a4436806f7
4 changed files with 146 additions and 211 deletions
@@ -31,6 +31,9 @@ import org.jetbrains.jet.lang.descriptors.PropertyDescriptor
import org.jetbrains.jet.lang.descriptors.VariableDescriptor import org.jetbrains.jet.lang.descriptors.VariableDescriptor
import com.google.dart.compiler.backend.js.ast.JsName import com.google.dart.compiler.backend.js.ast.JsName
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils
import com.google.dart.compiler.backend.js.ast.JsNameRef
import org.jetbrains.k2js.translate.utils.JsAstUtils
import org.jetbrains.k2js.translate.context.Namer
trait CallInfo { trait CallInfo {
@@ -48,7 +51,7 @@ trait CallInfo {
} }
// if value == null, it is get access // if value == null, it is get access
class VariableAccessInfo(callInfo: CallInfo, val value: JsExpression? = null): CallInfo by callInfo class VariableAccessInfo(callInfo: CallInfo, val value: JsExpression? = null) : CallInfo by callInfo
class FunctionCallInfo(callInfo: CallInfo, val argumentsInfo: CallArgumentTranslator.ArgumentsInfo) : CallInfo by callInfo class FunctionCallInfo(callInfo: CallInfo, val argumentsInfo: CallArgumentTranslator.ArgumentsInfo) : CallInfo by callInfo
@@ -60,12 +63,12 @@ class FunctionCallInfo(callInfo: CallInfo, val argumentsInfo: CallArgumentTransl
*/ */
class ExplicitReceivers(val receiverOrThisObject: JsExpression?, val receiverObject: JsExpression? = null) class ExplicitReceivers(val receiverOrThisObject: JsExpression?, val receiverObject: JsExpression? = null)
fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out CallableDescriptor>, receiver: JsExpression?): CallInfo { fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out CallableDescriptor>, receiverOrThisObject: JsExpression?): CallInfo {
return createCallInfo(resolvedCall, ExplicitReceivers(receiver)) return createCallInfo(resolvedCall, ExplicitReceivers(receiverOrThisObject))
} }
fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out FunctionDescriptor>, receiver: JsExpression?): FunctionCallInfo { fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out FunctionDescriptor>, receiverOrThisObject: JsExpression?): FunctionCallInfo {
return getCallInfo(resolvedCall, ExplicitReceivers(receiver)); return getCallInfo(resolvedCall, ExplicitReceivers(receiverOrThisObject));
} }
// two receiver need only for FunctionCall in VariableAsFunctionResolvedCall // two receiver need only for FunctionCall in VariableAsFunctionResolvedCall
@@ -75,24 +78,20 @@ fun TranslationContext.getCallInfo(resolvedCall: ResolvedCall<out FunctionDescri
return FunctionCallInfo(callInfo, argumentsInfo) return FunctionCallInfo(callInfo, argumentsInfo)
} }
val CallInfo.callableDescriptor: CallableDescriptor val CallInfo.callableDescriptor: CallableDescriptor
get() { get() = resolvedCall.getResultingDescriptor().getOriginal()
return resolvedCall.getResultingDescriptor().getOriginal()
} fun CallInfo.isExtension(): Boolean = receiverObject != null
fun CallInfo.isExtension(): Boolean {
return receiverObject != null fun CallInfo.isMemberCall(): Boolean = thisObject != null
}
fun CallInfo.isMemberCall(): Boolean { fun CallInfo.isNative(): Boolean = AnnotationsUtils.isNativeObject(callableDescriptor)
return thisObject != null
} fun CallInfo.isSuperInvocation(): Boolean {
fun CallInfo.isNative(): Boolean {
return AnnotationsUtils.isNativeObject(callableDescriptor)
}
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 { fun CallInfo.constructSafeCallIsNeeded(result: JsExpression): JsExpression {
if (!resolvedCall.isSafeCall()) if (!resolvedCall.isSafeCall())
return result return result
@@ -109,25 +108,27 @@ fun CallInfo.constructSafeCallIsNeeded(result: JsExpression): JsExpression {
} }
val VariableAccessInfo.variableDescriptor: VariableDescriptor val VariableAccessInfo.variableDescriptor: VariableDescriptor
get() { get() = callableDescriptor as VariableDescriptor
return callableDescriptor as VariableDescriptor
val VariableAccessInfo.variableName: JsName
get() = context.getNameForDescriptor(variableDescriptor)
fun VariableAccessInfo.isGetAccess(): Boolean = value == null
fun VariableAccessInfo.getAccessFunctionName(): String = Namer.getNameForAccessor(variableName.getIdent()!!, isGetAccess(), false)
fun VariableAccessInfo.constructAccessExpression(ref: JsNameRef): JsExpression {
if (isGetAccess()) {
return ref
} else {
return JsAstUtils.assignment(ref, value!!)
} }
val VariableAccessInfo.variableName : JsName
get() {
return context.getNameForDescriptor(variableDescriptor)
}
fun VariableAccessInfo.isGetAccess(): Boolean {
return value == null
} }
val FunctionCallInfo.functionName : JsName val FunctionCallInfo.functionName: JsName
get() { get() = context.getNameForDescriptor(callableDescriptor)
return context.getNameForDescriptor(callableDescriptor)
}
fun FunctionCallInfo.hasSpreadOperator() : Boolean {
return argumentsInfo.isHasSpreadOperator()
}
fun FunctionCallInfo.hasSpreadOperator(): Boolean = 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")
@@ -160,15 +161,6 @@ private fun TranslationContext.createCallInfo(resolvedCall: ResolvedCall<out Cal
} }
} }
fun getNullableReceiverForSafeCall(): JsExpression? {
if (!resolvedCall.isSafeCall()) {
return null
}
return when (receiverKind) {
BOTH_RECEIVERS -> explicitReceivers.receiverObject
else -> explicitReceivers.receiverOrThisObject
}
}
return object : CallInfo { return object : CallInfo {
override val context: TranslationContext = this@createCallInfo override val context: TranslationContext = this@createCallInfo
override val resolvedCall: ResolvedCall<out CallableDescriptor> = resolvedCall override val resolvedCall: ResolvedCall<out CallableDescriptor> = resolvedCall
@@ -34,21 +34,18 @@ import org.jetbrains.k2js.translate.utils.AnnotationsUtils
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils
val functionCallCases: CallCaseDispatcher<FunctionCallCase, FunctionCallInfo> = createFunctionCases()
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, ExplicitReceivers(receiverOrThisObject)) 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 {
val variableAccessInfo = VariableAccessInfo(getCallInfo(resolvedCall, receiverOrThisObject), null); val variableAccessInfo = VariableAccessInfo(getCallInfo(resolvedCall, receiverOrThisObject), null);
return variableAccessCases.translate(variableAccessInfo) return variableAccessInfo.translateVariableAccess()
} }
fun TranslationContext.buildSet(resolvedCall: ResolvedCall<out VariableDescriptor>, value: JsExpression, receiverOrThisObject: JsExpression? = null): JsExpression { fun TranslationContext.buildSet(resolvedCall: ResolvedCall<out VariableDescriptor>, value: JsExpression, receiverOrThisObject: JsExpression? = null): JsExpression {
val variableAccessInfo = VariableAccessInfo(getCallInfo(resolvedCall, receiverOrThisObject), value); val variableAccessInfo = VariableAccessInfo(getCallInfo(resolvedCall, receiverOrThisObject), value);
return variableAccessCases.translate(variableAccessInfo) return variableAccessInfo.translateVariableAccess()
} }
fun TranslationContext.buildFakeCall(functionDescriptor: FunctionDescriptor, args: List<JsExpression>, thisObject: JsExpression?): JsExpression { fun TranslationContext.buildFakeCall(functionDescriptor: FunctionDescriptor, args: List<JsExpression>, thisObject: JsExpression?): JsExpression {
@@ -57,13 +54,13 @@ fun TranslationContext.buildFakeCall(functionDescriptor: FunctionDescriptor, arg
val isNative = AnnotationsUtils.isNativeObject(functionDescriptor) val isNative = AnnotationsUtils.isNativeObject(functionDescriptor)
val hasSpreadOperator = false val hasSpreadOperator = false
if (thisObject != null) { if (thisObject != null) {
return DefaultCallCase.buildDefaultCallWithThisObject(argumentsInfo, thisObject, functionName, isNative, hasSpreadOperator) return DefaultFunctionCallCase.buildDefaultCallWithThisObject(argumentsInfo, thisObject, functionName, isNative, hasSpreadOperator)
} else { } else {
return DefaultCallCase.buildDefaultCallWithoutReceiver(this, argumentsInfo, functionDescriptor, functionName, isNative, hasSpreadOperator) return DefaultFunctionCallCase.buildDefaultCallWithoutReceiver(this, argumentsInfo, functionDescriptor, functionName, isNative, hasSpreadOperator)
} }
} }
fun ResolvedCall<out CallableDescriptor>.expectedReceivers(): Boolean { private fun ResolvedCall<out CallableDescriptor>.expectedReceivers(): Boolean {
return this.getExplicitReceiverKind() != NO_EXPLICIT_RECEIVER return this.getExplicitReceiverKind() != NO_EXPLICIT_RECEIVER
} }
@@ -84,34 +81,23 @@ private fun TranslationContext.buildCall(resolvedCall: ResolvedCall<out Function
} }
val functionCallInfo = getCallInfo(resolvedCall, explicitReceivers) val functionCallInfo = getCallInfo(resolvedCall, explicitReceivers)
return functionCallCases.translate(functionCallInfo) return functionCallInfo.translateFunctionCall()
} }
trait CallCase<I : CallInfo> { trait CallCase<I : CallInfo> {
val callInfo: I
protected fun unsupported(message: String = "") : Nothing { protected fun I.unsupported(message: String = "") : Nothing = throw UnsupportedOperationException("this case unsopported. $this")
throw UnsupportedOperationException("this case unsopported. $callInfo")
}
protected fun I.noReceivers(): JsExpression { protected fun I.noReceivers(): JsExpression = unsupported()
unsupported()
}
protected fun I.thisObject(): JsExpression { protected fun I.thisObject(): JsExpression = unsupported()
unsupported()
}
protected fun I.receiverArgument(): JsExpression { protected fun I.receiverArgument(): JsExpression = unsupported()
unsupported()
}
protected fun I.bothReceivers(): JsExpression { protected fun I.bothReceivers(): JsExpression = unsupported()
unsupported()
}
final fun translate(): JsExpression { final fun translate(callInfo: I): JsExpression {
val result = if (callInfo.thisObject == null) { val result = if (callInfo.thisObject == null) {
if (callInfo.receiverObject == null) if (callInfo.receiverObject == null)
callInfo.noReceivers() callInfo.noReceivers()
@@ -128,62 +114,23 @@ trait CallCase<I : CallInfo> {
} }
} }
open class FunctionCallCase(override val callInfo: FunctionCallInfo) : CallCase<FunctionCallInfo> trait FunctionCallCase : CallCase<FunctionCallInfo>
open class VariableAccessCase(override val callInfo: VariableAccessInfo) : CallCase<VariableAccessInfo> { trait VariableAccessCase : CallCase<VariableAccessInfo>
protected fun VariableAccessInfo.getAccessFunctionName(): String {
return Namer.getNameForAccessor(variableName.getIdent()!!, isGetAccess(), false)
}
protected fun VariableAccessInfo.constructAccessExpression(ref: JsNameRef): JsExpression { trait DelegateIntrinsic<I : CallInfo> {
if (isGetAccess()) {
return ref
} else {
return JsAstUtils.assignment(ref, value!!)
}
}
}
class CallCaseDispatcher<C : CallCase<I>, I : CallInfo> {
private val cases: MutableList<(I) -> JsExpression?> = ArrayList()
fun addCase(canBeApplyCase: (I) -> JsExpression?) {
cases.add(canBeApplyCase)
}
fun addCase(caseConstructor: (I) -> C, canApply: (I) -> Boolean) {
cases.add({
if (canApply(it))
caseConstructor(it).translate()
else
null
})
}
fun translate(callInfo: I): JsExpression {
for (case in cases) {
val result = case(callInfo)
if (result != null)
return result
}
throw UnsupportedOperationException("This case of call unsopported. CallInfo: $callInfo")
}
}
trait DelegateIntrinsic<I : CallInfo> : CallCase<I> {
fun I.canBeApply(): Boolean = true fun I.canBeApply(): Boolean = true
fun I.getReceiver(): JsExpression? {
return when (resolvedCall.getExplicitReceiverKind()) {
THIS_OBJECT -> thisObject
RECEIVER_ARGUMENT, BOTH_RECEIVERS -> receiverObject
else -> null
}
}
fun I.getDescriptor(): CallableDescriptor fun I.getDescriptor(): CallableDescriptor
fun I.getArgs(): List<JsExpression> fun I.getArgs(): List<JsExpression>
fun I.intrinsic(): JsExpression? { fun intrinsic(callInfo: I): JsExpression? {
return if (callInfo.canBeApply())
callInfo.getIntrinsic()
else
null
}
private fun I.getIntrinsic(): JsExpression? {
val descriptor = getDescriptor(); val descriptor = getDescriptor();
// Now intrinsic support only FunctionDescriptor. See DelegatePropertyAccessIntrinsic.getDescriptor() // Now intrinsic support only FunctionDescriptor. See DelegatePropertyAccessIntrinsic.getDescriptor()
@@ -195,11 +142,4 @@ trait DelegateIntrinsic<I : CallInfo> : CallCase<I> {
} }
return null return null
} }
fun intrinsic(): JsExpression? {
return if (callInfo.canBeApply())
callInfo.intrinsic()
else
null
}
} }
@@ -48,44 +48,42 @@ public fun addReceiverToArgs(receiver: JsExpression, arguments: List<JsExpressio
// call may be native and|or with spreadOperator // call may be native and|or with spreadOperator
class DefaultCallCase(callInfo: FunctionCallInfo): FunctionCallCase(callInfo) { object DefaultFunctionCallCase : FunctionCallCase {
class object { // TODO: refactor after fix ArgumentsInfo - duplicate code
// TODO: refactor after fix ArgumentsInfo - duplicate code private fun nativeSpreadFunWithThisObjectOrReceiver(argumentsInfo: CallArgumentTranslator.ArgumentsInfo, functionName: JsName): JsExpression {
private fun nativeSpreadFunWithThisObjectOrReceiver(argumentsInfo: CallArgumentTranslator.ArgumentsInfo, functionName: JsName): JsExpression { val cachedReceiver = argumentsInfo.getCachedReceiver()!!
val cachedReceiver = argumentsInfo.getCachedReceiver()!! val functionCallRef = Namer.getFunctionApplyRef(JsNameRef(functionName, cachedReceiver.assignmentExpression()))
val functionCallRef = Namer.getFunctionApplyRef(JsNameRef(functionName, cachedReceiver.assignmentExpression())) return JsInvocation(functionCallRef, 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()) return JsInvocation(functionCallRef, argumentsInfo.getTranslateArguments())
} }
if (isNative) {
fun buildDefaultCallWithThisObject(argumentsInfo: CallArgumentTranslator.ArgumentsInfo, return JsInvocation(JsNameRef(functionName), argumentsInfo.getTranslateArguments())
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())
} }
val qualifierForFunction = context.getQualifierForDescriptor(callableDescriptor)
val functionCall = JsNameRef(functionName, qualifierForFunction)
return JsInvocation(functionCall, argumentsInfo.getTranslateArguments())
} }
override fun FunctionCallInfo.noReceivers(): JsExpression { override fun FunctionCallInfo.noReceivers(): JsExpression {
@@ -115,7 +113,7 @@ class DefaultCallCase(callInfo: FunctionCallInfo): FunctionCallCase(callInfo) {
} }
class DelegateFunctionIntrinsic(callInfo: FunctionCallInfo) : FunctionCallCase(callInfo), DelegateIntrinsic<FunctionCallInfo> { object DelegateFunctionIntrinsic : DelegateIntrinsic<FunctionCallInfo> {
override fun FunctionCallInfo.getArgs(): List<JsExpression> { override fun FunctionCallInfo.getArgs(): List<JsExpression> {
return argumentsInfo.getTranslateArguments() return argumentsInfo.getTranslateArguments()
} }
@@ -124,18 +122,16 @@ class DelegateFunctionIntrinsic(callInfo: FunctionCallInfo) : FunctionCallCase(c
} }
} }
class InvokeIntrinsic(callInfo: FunctionCallInfo) : FunctionCallCase(callInfo) { object InvokeIntrinsic : FunctionCallCase {
class object { fun canApply(callInfo: FunctionCallInfo): Boolean {
fun canApply(callInfo: FunctionCallInfo): Boolean { if (!callInfo.callableDescriptor.getName().asString().equals("invoke"))
if (!callInfo.callableDescriptor.getName().asString().equals("invoke")) return false
return false val parameterCount = callInfo.callableDescriptor.getValueParameters().size()
val parameterCount = callInfo.callableDescriptor.getValueParameters().size() val funDeclaration = callInfo.callableDescriptor.getContainingDeclaration()
val funDeclaration = callInfo.callableDescriptor.getContainingDeclaration() return funDeclaration == ((if (callInfo.callableDescriptor.getReceiverParameter() == null)
return funDeclaration == ((if (callInfo.callableDescriptor.getReceiverParameter() == null) KotlinBuiltIns.getInstance().getFunction(parameterCount)
KotlinBuiltIns.getInstance().getFunction(parameterCount) else
else KotlinBuiltIns.getInstance().getExtensionFunction(parameterCount)))
KotlinBuiltIns.getInstance().getExtensionFunction(parameterCount)))
}
} }
override fun FunctionCallInfo.thisObject(): JsExpression { override fun FunctionCallInfo.thisObject(): JsExpression {
@@ -146,7 +142,11 @@ class InvokeIntrinsic(callInfo: FunctionCallInfo) : FunctionCallCase(callInfo) {
} }
} }
class ConstructorCallCase(callInfo: FunctionCallInfo) : FunctionCallCase(callInfo) { object ConstructorCallCase : FunctionCallCase {
fun canApply(callInfo: FunctionCallInfo): Boolean {
return callInfo.callableDescriptor is ConstructorDescriptor
}
override fun FunctionCallInfo.noReceivers(): JsExpression { override fun FunctionCallInfo.noReceivers(): JsExpression {
if (isNative()) { if (isNative()) {
return JsNew(JsNameRef(functionName), argumentsInfo.getTranslateArguments()) return JsNew(JsNameRef(functionName), argumentsInfo.getTranslateArguments())
@@ -155,16 +155,14 @@ class ConstructorCallCase(callInfo: FunctionCallInfo) : FunctionCallCase(callInf
} }
} }
class ExpressionAsFunctionDescriptorIntrinsic(callInfo: FunctionCallInfo) : FunctionCallCase(callInfo) { object ExpressionAsFunctionDescriptorIntrinsic : FunctionCallCase {
class object { fun canApply(callInfo: FunctionCallInfo): Boolean {
fun canApply(callInfo: FunctionCallInfo): Boolean { return callInfo.callableDescriptor is ExpressionAsFunctionDescriptor
return callInfo.callableDescriptor is ExpressionAsFunctionDescriptor
}
} }
override fun FunctionCallInfo.noReceivers(): JsExpression { override fun FunctionCallInfo.noReceivers(): JsExpression {
if (callableDescriptor !is ExpressionAsFunctionDescriptor) { if (callableDescriptor !is ExpressionAsFunctionDescriptor) {
throw IllegalStateException("callableDescriptor must be ExpressionAsFunctionDescriptor $callInfo") throw IllegalStateException("callableDescriptor must be ExpressionAsFunctionDescriptor $this")
} }
val funRef = Translation.translateAsExpression((callableDescriptor as ExpressionAsFunctionDescriptor).getExpression()!!, context) val funRef = Translation.translateAsExpression((callableDescriptor as ExpressionAsFunctionDescriptor).getExpression()!!, context)
return JsInvocation(funRef, argumentsInfo.getTranslateArguments()) return JsInvocation(funRef, argumentsInfo.getTranslateArguments())
@@ -172,11 +170,9 @@ class ExpressionAsFunctionDescriptorIntrinsic(callInfo: FunctionCallInfo) : Func
} }
} }
class SuperCallCase(callInfo: FunctionCallInfo) : FunctionCallCase(callInfo) { object SuperCallCase : FunctionCallCase {
class object { fun canApply(callInfo: FunctionCallInfo): Boolean {
fun canApply(callInfo: FunctionCallInfo): Boolean { return callInfo.isSuperInvocation()
return callInfo.isSuperInvocation()
}
} }
override fun FunctionCallInfo.thisObject(): JsExpression { // TODO: spread operator override fun FunctionCallInfo.thisObject(): JsExpression { // TODO: spread operator
@@ -186,17 +182,21 @@ class SuperCallCase(callInfo: FunctionCallInfo) : FunctionCallCase(callInfo) {
} }
} }
fun createFunctionCases(): CallCaseDispatcher<FunctionCallCase, FunctionCallInfo> { fun FunctionCallInfo.translateFunctionCall(): JsExpression {
val caseDispatcher = CallCaseDispatcher<FunctionCallCase, FunctionCallInfo>() val intrinsic = DelegateFunctionIntrinsic.intrinsic(this)
caseDispatcher.addCase(::ExpressionAsFunctionDescriptorIntrinsic) {ExpressionAsFunctionDescriptorIntrinsic.canApply(it)} return when {
caseDispatcher.addCase(::InvokeIntrinsic) {InvokeIntrinsic.canApply(it)} intrinsic != null ->
intrinsic
caseDispatcher.addCase { DelegateFunctionIntrinsic(it).intrinsic() } ExpressionAsFunctionDescriptorIntrinsic.canApply(this) ->
ExpressionAsFunctionDescriptorIntrinsic.translate(this)
caseDispatcher.addCase(::ConstructorCallCase) {it.callableDescriptor is ConstructorDescriptor} InvokeIntrinsic.canApply(this) ->
caseDispatcher.addCase(::SuperCallCase) {SuperCallCase.canApply(it)} InvokeIntrinsic.translate(this)
ConstructorCallCase.canApply(this) ->
caseDispatcher.addCase(::DefaultCallCase) { true } // TODO: fix this ConstructorCallCase.translate(this)
return caseDispatcher SuperCallCase.canApply(this) ->
SuperCallCase.translate(this)
else ->
DefaultFunctionCallCase.translate(this)
}
} }
@@ -29,8 +29,7 @@ import org.jetbrains.jet.lang.resolve.DescriptorFactory
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor import org.jetbrains.jet.lang.descriptors.PropertyDescriptor
class NativeVariableAccessCase(callInfo: VariableAccessInfo) : VariableAccessCase(callInfo) { object NativeVariableAccessCase : VariableAccessCase {
override fun VariableAccessInfo.receiverArgument(): JsExpression { override fun VariableAccessInfo.receiverArgument(): JsExpression {
return constructAccessExpression(JsNameRef(variableName, receiverObject!!)) return constructAccessExpression(JsNameRef(variableName, receiverObject!!))
} }
@@ -44,8 +43,7 @@ class NativeVariableAccessCase(callInfo: VariableAccessInfo) : VariableAccessCas
} }
} }
class DefaultVariableAccessCase(callInfo: VariableAccessInfo) : VariableAccessCase(callInfo) { object DefaultVariableAccessCase : VariableAccessCase {
override fun VariableAccessInfo.noReceivers(): JsExpression { override fun VariableAccessInfo.noReceivers(): JsExpression {
return constructAccessExpression(context.getQualifiedReference(variableDescriptor)) return constructAccessExpression(context.getQualifiedReference(variableDescriptor))
} }
@@ -73,7 +71,7 @@ class DefaultVariableAccessCase(callInfo: VariableAccessInfo) : VariableAccessCa
} }
} }
class DelegatePropertyAccessIntrinsic(callInfo: VariableAccessInfo) : VariableAccessCase(callInfo), DelegateIntrinsic<VariableAccessInfo> { object DelegatePropertyAccessIntrinsic : DelegateIntrinsic<VariableAccessInfo> {
override fun VariableAccessInfo.canBeApply(): Boolean { override fun VariableAccessInfo.canBeApply(): Boolean {
if(variableDescriptor is PropertyDescriptor) { if(variableDescriptor is PropertyDescriptor) {
return isGetAccess() || (variableDescriptor as PropertyDescriptor).isVar() return isGetAccess() || (variableDescriptor as PropertyDescriptor).isVar()
@@ -98,7 +96,7 @@ class DelegatePropertyAccessIntrinsic(callInfo: VariableAccessInfo) : VariableAc
} }
} }
class SuperPropertyAccessCase(callInfo: VariableAccessInfo) : VariableAccessCase(callInfo) { object SuperPropertyAccessCase : VariableAccessCase {
override fun VariableAccessInfo.thisObject(): JsExpression { override fun VariableAccessInfo.thisObject(): JsExpression {
val variableName = context.program().getStringLiteral(this.variableName.getIdent()) val variableName = context.program().getStringLiteral(this.variableName.getIdent())
return if (isGetAccess()) return if (isGetAccess())
@@ -108,12 +106,17 @@ class SuperPropertyAccessCase(callInfo: VariableAccessInfo) : VariableAccessCase
} }
} }
fun createVariableAccessCases(): CallCaseDispatcher<VariableAccessCase, VariableAccessInfo> { fun VariableAccessInfo.translateVariableAccess(): JsExpression {
val caseDispatcher = CallCaseDispatcher<VariableAccessCase, VariableAccessInfo>() val intrinsic = DelegatePropertyAccessIntrinsic.intrinsic(this)
caseDispatcher.addCase { DelegatePropertyAccessIntrinsic(it).intrinsic() } return when {
caseDispatcher.addCase(::SuperPropertyAccessCase) { it.isSuperInvocation() } intrinsic != null ->
caseDispatcher.addCase(::NativeVariableAccessCase) { it.isNative() } intrinsic
caseDispatcher.addCase(::DefaultVariableAccessCase) { true } // TODO: fix this isSuperInvocation() ->
return caseDispatcher SuperPropertyAccessCase.translate(this)
isNative() ->
NativeVariableAccessCase.translate(this)
else ->
DefaultVariableAccessCase.translate(this)
}
} }