translator: fix complex nested name resolving

This commit is contained in:
e5l
2016-08-10 18:06:04 +03:00
parent 3c8bdb61cb
commit 318a4b182e
3 changed files with 43 additions and 21 deletions
@@ -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()
}