JS backend: Add DelegatePropertyAccessIntrinsic
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user