JS backend: Add DelegatePropertyAccessIntrinsic

This commit is contained in:
Erokhin Stanislav
2013-12-19 17:14:19 +04:00
parent 740307e94a
commit 083e789692
3 changed files with 56 additions and 12 deletions
@@ -40,7 +40,7 @@ open class BaseCallInfo(
val receiverObject: JsExpression?,
val nullableReceiverForSafeCall: JsExpression?
) {
val callableDescriptor = resolvedCall.getResultingDescriptor().getOriginal()
open val callableDescriptor = resolvedCall.getResultingDescriptor().getOriginal()
fun isExtension(): Boolean = receiverObject != null
fun isMemberCall(): Boolean = thisObject != null
@@ -61,7 +61,7 @@ private open class CallInfoWrapper(callInfo: BaseCallInfo) :
// if setTo == null, it is get access
class VariableAccessInfo(callInfo: BaseCallInfo, private val setTo: JsExpression? = null): CallInfoWrapper(callInfo) {
val variableDescriptor = super.callableDescriptor as VariableDescriptor
val propertyName : JsName
val variableName : JsName
get() {
return context.getNameForDescriptor(variableDescriptor)
}
@@ -114,7 +114,7 @@ open class FunctionCallCase(override val callInfo: FunctionCallInfo) : CallCase<
open class VariableAccessCase(override val callInfo: VariableAccessInfo) : CallCase<VariableAccessInfo> {
protected fun VariableAccessInfo.getAccessFunctionName(): String {
return Namer.getNameForAccessor(propertyName.getIdent()!!, isGetAccess(), false)
return Namer.getNameForAccessor(variableName.getIdent()!!, isGetAccess(), false)
}
protected fun VariableAccessInfo.constructAccessExpression(ref: JsNameRef): JsExpression {
@@ -153,6 +153,7 @@ class CallCaseDispatcher<C : CallCase<I>, I : BaseCallInfo> {
}
trait DelegateIntrinsic<I : BaseCallInfo> : CallCase<I> {
fun I.canBeApply(): Boolean = true
fun I.getReceiver(): JsExpression? {
return when (resolvedCall.getExplicitReceiverKind()) {
THIS_OBJECT -> thisObject
@@ -171,6 +172,9 @@ trait DelegateIntrinsic<I : BaseCallInfo> : CallCase<I> {
}
fun intrinsic(): JsExpression? {
return callInfo.intrinsic()
return if (callInfo.canBeApply())
callInfo.intrinsic()
else
null
}
}
@@ -22,35 +22,40 @@ import com.google.dart.compiler.backend.js.ast.JsLiteral
import org.jetbrains.k2js.translate.utils.JsAstUtils
import com.google.dart.compiler.backend.js.ast.JsInvocation
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor
import org.jetbrains.jet.lang.descriptors.CallableDescriptor
import java.util.Collections
import org.jetbrains.jet.lang.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.jet.lang.resolve.DescriptorFactory
import org.jetbrains.jet.lang.descriptors.PropertyDescriptor
class NativeVariableAccessCase(callInfo: VariableAccessInfo) : VariableAccessCase(callInfo) {
override fun VariableAccessInfo.receiverArgument(): JsExpression {
return constructAccessExpression(JsNameRef(propertyName, receiverObject!!))
return constructAccessExpression(JsNameRef(variableName, receiverObject!!))
}
override fun VariableAccessInfo.thisObject(): JsExpression {
return constructAccessExpression(JsNameRef(propertyName, thisObject!!))
return constructAccessExpression(JsNameRef(variableName, thisObject!!))
}
override fun VariableAccessInfo.noReceivers(): JsExpression {
return constructAccessExpression(propertyName.makeRef()!!)
return constructAccessExpression(variableName.makeRef()!!)
}
}
class DefaultVariableAccessCase(callInfo: VariableAccessInfo) : VariableAccessCase(callInfo) {
override fun VariableAccessInfo.noReceivers(): JsExpression {
return constructAccessExpression(context.getQualifierForDescriptor(callableDescriptor)!!)
return constructAccessExpression(context.getQualifiedReference(variableDescriptor))
}
override fun VariableAccessInfo.thisObject(): JsExpression {
return constructAccessExpression(JsNameRef(propertyName, thisObject!!))
return constructAccessExpression(JsNameRef(variableName, thisObject!!))
}
override fun VariableAccessInfo.receiverArgument(): JsExpression {
val funRef = JsNameRef(getAccessFunctionName(), context.getQualifierForDescriptor(callableDescriptor))
val funRef = JsNameRef(getAccessFunctionName(), context.getQualifierForDescriptor(variableDescriptor))
return if (isGetAccess()) {
JsInvocation(funRef, receiverObject!!)
} else {
@@ -71,15 +76,50 @@ class DefaultVariableAccessCase(callInfo: VariableAccessInfo) : VariableAccessCa
class ValueParameterAccessCase(callInfo: VariableAccessInfo) : VariableAccessCase(callInfo) {
override fun VariableAccessInfo.noReceivers(): JsExpression {
assert(isGetAccess(), "It must be get access. CallInfo: $callInfo")
return propertyName.makeRef()!!
return variableName.makeRef()!!
}
}
class DelegatePropertyAccessIntrinsic(callInfo: VariableAccessInfo) : VariableAccessCase(callInfo), DelegateIntrinsic<VariableAccessInfo> {
override fun VariableAccessInfo.canBeApply(): Boolean {
return variableDescriptor is PropertyDescriptor
}
override fun VariableAccessInfo.getArgs(): List<JsExpression> {
return if (isGetAccess())
Collections.emptyList<JsExpression>()
else
Collections.singletonList(getSetToExpression())
}
override fun VariableAccessInfo.getDescriptor(): CallableDescriptor {
val propertyDescriptor = variableDescriptor as PropertyDescriptor
return if (isGetAccess()) {
var getter = propertyDescriptor.getGetter()
if (getter == null) {
val getterImpl = DescriptorFactory.createDefaultGetter(variableDescriptor)
getterImpl.initialize(propertyDescriptor.getType())
((propertyDescriptor as PropertyDescriptorImpl)).initialize(getterImpl, propertyDescriptor.getSetter())
getter = getterImpl
}
getter!!
} else {
var setter = propertyDescriptor.getSetter()
if (setter == null) {
val setterImpl = DescriptorFactory.createDefaultSetter(variableDescriptor)
((propertyDescriptor as PropertyDescriptorImpl)).initialize(propertyDescriptor.getGetter(), setterImpl)
setter = setterImpl
}
setter!!
}
}
}
fun createVariableAccessCases(): CallCaseDispatcher<VariableAccessCase, VariableAccessInfo> {
val caseDispatcher = CallCaseDispatcher<VariableAccessCase, VariableAccessInfo>()
caseDispatcher.addCase(::ValueParameterAccessCase) { it.callableDescriptor is ValueParameterDescriptor}
caseDispatcher.addCase { DelegatePropertyAccessIntrinsic(it).intrinsic() }
caseDispatcher.addCase(::ValueParameterAccessCase) { it.variableDescriptor is ValueParameterDescriptor}
caseDispatcher.addCase(::NativeVariableAccessCase) { it.isNative() }
caseDispatcher.addCase(::DefaultVariableAccessCase) { true } // TODO: fix this
return caseDispatcher