translator: fix complex nested name resolving
This commit is contained in:
@@ -4,6 +4,7 @@ import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiWhiteSpace
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||
import com.intellij.psi.tree.IElementType
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.getSubtypesPredicate
|
||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
@@ -16,6 +17,7 @@ import org.jetbrains.kotlin.resolve.constants.TypedCompileTimeConstant
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.kotlinnative.translator.llvm.*
|
||||
import org.kotlinnative.translator.llvm.types.*
|
||||
import java.rmi.UnexpectedException
|
||||
import java.util.*
|
||||
|
||||
|
||||
@@ -176,7 +178,6 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
||||
is KtDotQualifiedExpression -> evaluateExpression(receiverExpr, scopeDepth) as LLVMVariable
|
||||
is KtNameReferenceExpression -> {
|
||||
val referenceContext = state.bindingContext.get(BindingContext.REFERENCE_TARGET, receiverExpr)
|
||||
variableManager[receiverName]
|
||||
when (referenceContext) {
|
||||
is PropertyDescriptorImpl -> {
|
||||
val receiverThis = variableManager["this"]!!
|
||||
@@ -198,8 +199,13 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
||||
}
|
||||
}
|
||||
|
||||
val clazz = state.classes[receiverName] ?: return evaluateExtensionExpression(receiverExpr, selectorExpr as KtCallExpression, scopeDepth)
|
||||
val location = receiverExpr.getType(state.bindingContext)?.getSubtypesPredicate()?.toString()?.split(".")
|
||||
val classReference = LLVMReferenceType(location?.last() ?: receiverName, "class")
|
||||
if (location != null) {
|
||||
classReference.location.addAll(location.dropLast(1))
|
||||
}
|
||||
|
||||
val clazz = resolveClassOrObjectLocation(classReference) ?: return evaluateExtensionExpression(receiverExpr, selectorExpr as KtCallExpression, scopeDepth)
|
||||
return evaluateClassScopedDotExpression(clazz, selectorExpr, scopeDepth)
|
||||
}
|
||||
|
||||
@@ -209,7 +215,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
||||
val function = selector.firstChild.firstChild.text
|
||||
val names = parseArgList(selector, scopeDepth)
|
||||
val type = if (names.size > 0) "_${names.joinToString(separator = "_", transform = { it.type!!.mangle() })}" else ""
|
||||
val extensionCodegen = state.extensionFunctions[standardType.toString()]!!["$function$type"]!!
|
||||
val extensionCodegen = state.extensionFunctions[standardType.toString()]?.get("$function$type") ?: throw UnexpectedException("$standardType:$function$type")
|
||||
val receiverExpression = evaluateExpression(receiver, scopeDepth + 1)!!
|
||||
|
||||
val typeThisArgument = when (standardType) {
|
||||
@@ -222,13 +228,13 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
||||
return evaluateFunctionCallExpression(LLVMVariable(extensionCodegen.fullName, extensionCodegen.returnType!!.type, scope = LLVMVariableScope()), args)
|
||||
}
|
||||
|
||||
private fun evaluateClassScopedDotExpression(clazz: ClassCodegen, selector: KtExpression, scopeDepth: Int): LLVMSingleValue? = when (selector) {
|
||||
private fun evaluateClassScopedDotExpression(clazz: StructCodegen, selector: KtExpression, scopeDepth: Int): LLVMSingleValue? = when (selector) {
|
||||
is KtCallExpression -> evaluateCallExpression(selector, scopeDepth, clazz)
|
||||
is KtReferenceExpression -> evaluateReferenceExpression(selector, scopeDepth, clazz)
|
||||
else -> throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
private fun evaluateNameReferenceExpression(expr: KtNameReferenceExpression, classScope: ClassCodegen? = null): LLVMSingleValue? {
|
||||
private fun evaluateNameReferenceExpression(expr: KtNameReferenceExpression, classScope: StructCodegen? = null): LLVMSingleValue? {
|
||||
val fieldName = state.bindingContext.get(BindingContext.REFERENCE_TARGET, expr)!!.name.toString()
|
||||
val field = classScope!!.companionFieldsIndex[fieldName]
|
||||
val companionObject = classScope.companionFieldsSource[fieldName]
|
||||
@@ -241,7 +247,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
||||
|
||||
fun evaluateMemberMethodOrField(receiver: LLVMVariable, selectorName: String, scopeDepth: Int, call: PsiElement? = null): LLVMSingleValue? {
|
||||
val type = receiver.type as LLVMReferenceType
|
||||
val clazz = resolveClassOrObjectLocation(type)
|
||||
val clazz = resolveClassOrObjectLocation(type) ?: throw UnexpectedException(type.toString())
|
||||
val field = clazz.fieldsIndex[selectorName]
|
||||
|
||||
if (field != null) {
|
||||
@@ -255,7 +261,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
||||
val types = if (names.size > 0) "_${names.joinToString(separator = "_", transform = { it.type!!.mangle() })}" else ""
|
||||
val methodName = "${if (typePath.length > 0) "$typePath." else ""}${clazz.structName}.${selectorName.substringBefore('(')}$types"
|
||||
|
||||
val method = clazz.methods[methodName]!!
|
||||
val method = clazz.methods[methodName] ?: throw UnexpectedException(methodName)
|
||||
val returnType = clazz.methods[methodName]!!.returnType!!.type
|
||||
|
||||
val loadedArgs = loadArgsIfRequired(names, method.args)
|
||||
@@ -265,19 +271,23 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
||||
return evaluateFunctionCallExpression(LLVMVariable(methodName, returnType, scope = LLVMVariableScope()), callArgs)
|
||||
}
|
||||
|
||||
private fun resolveClassOrObjectLocation(type: LLVMReferenceType): StructCodegen {
|
||||
private fun resolveClassOrObjectLocation(type: LLVMReferenceType): StructCodegen? {
|
||||
if (type.location.size == 0) {
|
||||
return state.classes[type.type] ?: state.objects[type.type]!!
|
||||
return state.classes[type.type] ?: state.objects[type.type]
|
||||
}
|
||||
|
||||
var codegen = state.classes[type.location[0]]!!
|
||||
var codegen = state.classes[type.location[0]]
|
||||
var i = 1
|
||||
while (i < type.location.size) {
|
||||
codegen = codegen.nestedClasses[type.location[i]]!!
|
||||
codegen = codegen?.nestedClasses?.get(type.location[i])
|
||||
i++
|
||||
}
|
||||
|
||||
return codegen.nestedClasses[type.type]!!
|
||||
if (codegen?.companionObjectCodegen != null && type.type == codegen?.companionObjectCodegen?.structName) {
|
||||
return codegen?.companionObjectCodegen!!
|
||||
}
|
||||
|
||||
return codegen?.nestedClasses?.get(type.type)
|
||||
}
|
||||
|
||||
fun evaluateArrayAccessExpression(expr: KtArrayAccessExpression, scope: Int): LLVMSingleValue? {
|
||||
@@ -300,7 +310,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
||||
val names = parseValueArguments(callMaker.valueArguments, scope)
|
||||
val methodName = "$targetClassName.$arrayActionType${if (names.size > 0) "_${names.joinToString(separator = "_", transform = { it.type!!.mangle() })}" else ""}"
|
||||
val type = receiver.type as LLVMReferenceType
|
||||
val clazz = resolveClassOrObjectLocation(type)
|
||||
val clazz = resolveClassOrObjectLocation(type) ?: throw UnexpectedException(type.toString())
|
||||
|
||||
val method = clazz.methods[methodName]!!
|
||||
val returnType = clazz.methods[methodName]!!.returnType!!.type
|
||||
@@ -325,10 +335,10 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
||||
}
|
||||
}
|
||||
|
||||
private fun evaluateReferenceExpression(expr: KtReferenceExpression, scopeDepth: Int, classScope: ClassCodegen? = null): LLVMSingleValue? = when {
|
||||
private fun evaluateReferenceExpression(expr: KtReferenceExpression, scopeDepth: Int, classScope: StructCodegen? = null): LLVMSingleValue? = when {
|
||||
expr is KtArrayAccessExpression -> evaluateArrayAccessExpression(expr, scopeDepth + 1)
|
||||
isEnumClassField(expr) -> resolveEnumClassField(expr)
|
||||
(expr is KtNameReferenceExpression) && (classScope != null) -> evaluateNameReferenceExpression(expr, classScope)
|
||||
(expr is KtNameReferenceExpression) && (classScope != null) -> evaluateNameReferenceExpression(expr, classScope.parentCodegen)
|
||||
resolveContainingClass(expr) != null -> evaluateMemberMethodOrField(variableManager["this"]!!, expr.firstChild.text, topLevel)
|
||||
else -> variableManager[expr.firstChild.text]
|
||||
}
|
||||
@@ -370,9 +380,9 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
||||
}
|
||||
|
||||
if (classScope != null) {
|
||||
val classDescriptor = state.classes[classScope.structName] ?: state.objects[classScope.structName] ?: return null
|
||||
val methodShortName = classScope.structName + "." + function
|
||||
if (classDescriptor.companionMethods.containsKey(methodShortName)) {
|
||||
val classDescriptor = classScope.parentCodegen
|
||||
val methodShortName = classDescriptor?.structName + "." + function
|
||||
if (classDescriptor != null && classDescriptor.companionMethods.containsKey(methodShortName)) {
|
||||
val descriptor = classDescriptor.companionMethods[methodShortName] ?: return null
|
||||
val parentDescriptor = descriptor.parentCodegen!!
|
||||
val receiver = variableManager[parentDescriptor.fullName]!!
|
||||
@@ -409,6 +419,15 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
||||
|
||||
private fun resolveContainingClass(expr: KtElement): StructCodegen? {
|
||||
val name = expr.getResolvedCallWithAssert(state.bindingContext).dispatchReceiver?.type?.toString() ?: return null
|
||||
val location = expr.getResolvedCallWithAssert(state.bindingContext).dispatchReceiver!!.type.getSubtypesPredicate().toString().split(".").dropLast(1)
|
||||
|
||||
if (location.size > 0) {
|
||||
val type = LLVMReferenceType(name, prefix = "class")
|
||||
type.location.addAll(location)
|
||||
|
||||
return resolveClassOrObjectLocation(type)
|
||||
}
|
||||
|
||||
return state.classes[name] ?: state.objects[name]
|
||||
}
|
||||
|
||||
@@ -508,15 +527,15 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
||||
if (operator == KtTokens.ELVIS) {
|
||||
return evaluateElvisOperator(expr, scopeDepth)
|
||||
}
|
||||
|
||||
val left = evaluateExpression(expr.firstChild, scopeDepth)
|
||||
if (expr.firstChild is KtArrayAccessExpression) {
|
||||
return null
|
||||
} else {
|
||||
left ?: throw UnsupportedOperationException("Wrong binary exception")
|
||||
left ?: throw UnsupportedOperationException("Wrong binary exception: ${expr.text}")
|
||||
}
|
||||
|
||||
val right = evaluateExpression(expr.lastChild, scopeDepth) ?: throw UnsupportedOperationException("Wrong binary exception: ${expr.text}")
|
||||
|
||||
return executeBinaryExpression(operator, expr.operationReference, left, right)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.kotlinnative.translator
|
||||
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.getSubtypesPredicate
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespaceAndComments
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration
|
||||
@@ -34,6 +35,9 @@ class FunctionCodegen(state: TranslationState,
|
||||
})
|
||||
|
||||
returnType = LLVMInstanceOfStandardType("instance", descriptor.returnType!!)
|
||||
if (returnType!!.type is LLVMReferenceType) {
|
||||
(returnType!!.type as LLVMReferenceType).location.addAll(descriptor.returnType!!.getSubtypesPredicate().toString().split(".").dropLast(1))
|
||||
}
|
||||
external = isExternal()
|
||||
name = "${function.fqName}${if (args.size > 0 && !external) "_${args.joinToString(separator = "_", transform = { it.type.mangle() })}" else ""}"
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ class companion_object_1 {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun companion_object_1_test(): Int {
|
||||
return companion_object_1.create()
|
||||
}
|
||||
Reference in New Issue
Block a user