translator: escape calculating reference type location

This commit is contained in:
Alexey Stepanov
2016-08-30 14:27:29 +03:00
parent f243d91900
commit dcd08d7cc5
5 changed files with 31 additions and 46 deletions
@@ -4,7 +4,6 @@ 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.*
@@ -195,7 +194,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
is KtPostfixExpression,
is KtBinaryExpression -> evaluateExpression(receiverExpr, scopeDepth) as LLVMVariable
is KtDotQualifiedExpression -> {
val codegen = resolveCodegenByName(receiverName, receiverName.split("."))
val codegen = resolveCodegenByName(receiverName)
if (codegen != null) null else evaluateExpression(receiverExpr, scopeDepth) as LLVMVariable
}
is KtNameReferenceExpression -> {
@@ -307,22 +306,32 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
}
private fun resolveClassOrObjectLocation(type: LLVMReferenceType): StructCodegen? {
if (type.location.size == 0) {
return state.classes[type.type] ?: state.objects[type.type]
}
val typeLocations = type.type.split('.')
val currentLocation = StringBuilder()
var codegen: ClassCodegen? = null
var currentIndex = 0
var codegen = state.classes[type.location[0]]
var i = 1
while (i < type.location.size) {
codegen = codegen?.nestedClasses?.get(type.location[i])
i++
do {
currentLocation.append((if (currentIndex > 0) "." else "") + typeLocations[currentIndex])
if (state.classes.containsKey(currentLocation.toString())) {
codegen = state.classes[currentLocation.toString()]
} else if (state.objects.containsKey(currentLocation.toString())) {
return state.objects[currentLocation.toString()]
}
currentIndex++
} while ((currentIndex < typeLocations.size) && (codegen == null))
while (currentIndex < typeLocations.size - 1) {
currentLocation.append('.' + typeLocations[currentIndex])
currentIndex++
codegen = codegen?.nestedClasses?.get(currentLocation.toString())
}
if (codegen?.companionObjectCodegen != null && type.type == codegen?.companionObjectCodegen?.structName) {
return codegen?.companionObjectCodegen!!
}
return codegen?.nestedClasses?.get(type.type)
return if (codegen?.structName == type.type) codegen else codegen?.nestedClasses?.get(type.type)
}
fun evaluateArrayAccessExpression(expr: KtArrayAccessExpression, scope: Int): LLVMSingleValue? {
@@ -407,26 +416,14 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
?: expr.getType(state.bindingContext)
?: expr.getQualifiedExpressionForReceiver()?.getType(state.bindingContext)
val location = type?.getSubtypesPredicate()?.toString()?.split(".")
?: state.bindingContext.get(BindingContext.REFERENCE_TARGET, expr as KtReferenceExpression)?.fqNameSafe?.toString()?.split(".")
?: return null
val name = type?.constructor?.declarationDescriptor?.fqNameSafe?.asString() ?: throw UnexpectedException(expr.text)
return resolveCodegenByName(name, location)
return resolveCodegenByName(name)
}
private fun resolveCodegenByName(name: String, location: List<String>): StructCodegen? {
val classType = LLVMReferenceType(name, prefix = "class")
var locationPrefix = ""
for (currentLocation in location.dropLast(1)) {
locationPrefix += (if (locationPrefix.length > 0) "." else "") + currentLocation
classType.location.add(locationPrefix)
}
private fun resolveCodegenByName(name: String): StructCodegen? =
resolveClassOrObjectLocation(LLVMReferenceType(name, prefix = "class"))
return resolveClassOrObjectLocation(classType)
}
private fun evaluateCallExpression(expr: KtCallExpression, scopeDepth: Int, classScope: StructCodegen? = null, caller: LLVMVariable? = null): LLVMSingleValue? {
var names = parseArgList(expr, scopeDepth)
@@ -30,10 +30,6 @@ class ClassCodegen(state: TranslationState,
init {
type = LLVMReferenceType(structName, "class", align = TranslationState.pointerAlign, size = TranslationState.pointerSize, byRef = true)
if (parentCodegen != null) {
type.location.addAll(parentCodegen.type.location)
type.location.add(parentCodegen.structName)
}
descriptor = state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException("Can't receive descriptor of class " + clazz.name)
@@ -20,11 +20,7 @@ class ObjectCodegen(state: TranslationState,
init {
type = LLVMReferenceType(structName, "class", align = TranslationState.pointerAlign, size = TranslationState.pointerSize, byRef = true)
if (parentCodegen != null) {
type.location.addAll(parentCodegen.type.location)
type.location.add(parentCodegen.structName)
}
primaryConstructorIndex = LLVMType.mangleFunctionArguments(emptyList())
primaryConstructorIndex = LLVMType.mangleFunctionArguments(emptyList())
constructorFields.put(primaryConstructorIndex!!, arrayListOf())
}
@@ -39,27 +39,25 @@ fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope
val refName = declarationDescriptor.fqNameSafe.asString()
val refType = state.classes[type.toString()]?.type ?: LLVMReferenceType(refName, align = TranslationState.pointerAlign, prefix = "class")
val result = LLVMVariable(name, refType, name, scope, pointer = 1)
var currentPrefix = ""
for (currentLocation in type.getSubtypesPredicate().toString().split(".").dropLast(1)) {
currentPrefix += (if (currentPrefix.length > 0) "." else "") + currentLocation
refType.location.add(currentPrefix)
}
result
LLVMVariable(name, refType, name, scope, pointer = 1)
}
}
}
fun LLVMMapStandardType(type: KotlinType, state: TranslationState): LLVMType =
fun LLVMMapStandardType(type: KotlinType, state: TranslationState) =
LLVMInstanceOfStandardType("type", type, LLVMRegisterScope(), state).type
fun String.addBeforeIfNotEmpty(add: String): String =
if (this.length > 0) add + this else this
fun String.addAfterIfNotEmpty(add: String): String =
if (this.length > 0) this + add else this
fun String.indexOfOrLast(str: Char, startIndex: Int = 0): Int {
val pos = this.indexOf(str, startIndex)
return if (pos < 0) this.length else pos
}
fun FqName.convertToNativeName(): String =
this.asString().replace(".<init>", "")
@@ -18,8 +18,6 @@ class LLVMReferenceType(val type: String,
override fun toString() = "%$typename"
val location = ArrayList<String>()
override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
LLVMExpression(LLVMBooleanType(), "icmp eq ${firstOp.getType()} $firstOp, ${if (secondOp.type is LLVMNullType) "null" else "$secondOp"}")