translator: escape calculating reference type location
This commit is contained in:
@@ -4,7 +4,6 @@ import com.intellij.psi.PsiElement
|
|||||||
import com.intellij.psi.PsiWhiteSpace
|
import com.intellij.psi.PsiWhiteSpace
|
||||||
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
import com.intellij.psi.impl.source.tree.LeafPsiElement
|
||||||
import com.intellij.psi.tree.IElementType
|
import com.intellij.psi.tree.IElementType
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.getSubtypesPredicate
|
|
||||||
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
@@ -195,7 +194,7 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
is KtPostfixExpression,
|
is KtPostfixExpression,
|
||||||
is KtBinaryExpression -> evaluateExpression(receiverExpr, scopeDepth) as LLVMVariable
|
is KtBinaryExpression -> evaluateExpression(receiverExpr, scopeDepth) as LLVMVariable
|
||||||
is KtDotQualifiedExpression -> {
|
is KtDotQualifiedExpression -> {
|
||||||
val codegen = resolveCodegenByName(receiverName, receiverName.split("."))
|
val codegen = resolveCodegenByName(receiverName)
|
||||||
if (codegen != null) null else evaluateExpression(receiverExpr, scopeDepth) as LLVMVariable
|
if (codegen != null) null else evaluateExpression(receiverExpr, scopeDepth) as LLVMVariable
|
||||||
}
|
}
|
||||||
is KtNameReferenceExpression -> {
|
is KtNameReferenceExpression -> {
|
||||||
@@ -307,22 +306,32 @@ abstract class BlockCodegen(val state: TranslationState, val variableManager: Va
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveClassOrObjectLocation(type: LLVMReferenceType): StructCodegen? {
|
private fun resolveClassOrObjectLocation(type: LLVMReferenceType): StructCodegen? {
|
||||||
if (type.location.size == 0) {
|
val typeLocations = type.type.split('.')
|
||||||
return state.classes[type.type] ?: state.objects[type.type]
|
val currentLocation = StringBuilder()
|
||||||
}
|
var codegen: ClassCodegen? = null
|
||||||
|
var currentIndex = 0
|
||||||
|
|
||||||
var codegen = state.classes[type.location[0]]
|
do {
|
||||||
var i = 1
|
currentLocation.append((if (currentIndex > 0) "." else "") + typeLocations[currentIndex])
|
||||||
while (i < type.location.size) {
|
if (state.classes.containsKey(currentLocation.toString())) {
|
||||||
codegen = codegen?.nestedClasses?.get(type.location[i])
|
codegen = state.classes[currentLocation.toString()]
|
||||||
i++
|
} 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) {
|
if (codegen?.companionObjectCodegen != null && type.type == codegen?.companionObjectCodegen?.structName) {
|
||||||
return codegen?.companionObjectCodegen!!
|
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? {
|
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.getType(state.bindingContext)
|
||||||
?: expr.getQualifiedExpressionForReceiver()?.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)
|
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? {
|
private fun resolveCodegenByName(name: String): StructCodegen? =
|
||||||
val classType = LLVMReferenceType(name, prefix = "class")
|
resolveClassOrObjectLocation(LLVMReferenceType(name, prefix = "class"))
|
||||||
var locationPrefix = ""
|
|
||||||
for (currentLocation in location.dropLast(1)) {
|
|
||||||
locationPrefix += (if (locationPrefix.length > 0) "." else "") + currentLocation
|
|
||||||
classType.location.add(locationPrefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
return resolveClassOrObjectLocation(classType)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun evaluateCallExpression(expr: KtCallExpression, scopeDepth: Int, classScope: StructCodegen? = null, caller: LLVMVariable? = null): LLVMSingleValue? {
|
private fun evaluateCallExpression(expr: KtCallExpression, scopeDepth: Int, classScope: StructCodegen? = null, caller: LLVMVariable? = null): LLVMSingleValue? {
|
||||||
var names = parseArgList(expr, scopeDepth)
|
var names = parseArgList(expr, scopeDepth)
|
||||||
|
|||||||
@@ -30,10 +30,6 @@ class ClassCodegen(state: TranslationState,
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
type = LLVMReferenceType(structName, "class", align = TranslationState.pointerAlign, size = TranslationState.pointerSize, byRef = true)
|
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)
|
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 {
|
init {
|
||||||
type = LLVMReferenceType(structName, "class", align = TranslationState.pointerAlign, size = TranslationState.pointerSize, byRef = true)
|
type = LLVMReferenceType(structName, "class", align = TranslationState.pointerAlign, size = TranslationState.pointerSize, byRef = true)
|
||||||
if (parentCodegen != null) {
|
primaryConstructorIndex = LLVMType.mangleFunctionArguments(emptyList())
|
||||||
type.location.addAll(parentCodegen.type.location)
|
|
||||||
type.location.add(parentCodegen.structName)
|
|
||||||
}
|
|
||||||
primaryConstructorIndex = LLVMType.mangleFunctionArguments(emptyList())
|
|
||||||
constructorFields.put(primaryConstructorIndex!!, arrayListOf())
|
constructorFields.put(primaryConstructorIndex!!, arrayListOf())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -39,27 +39,25 @@ fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope
|
|||||||
val refName = declarationDescriptor.fqNameSafe.asString()
|
val refName = declarationDescriptor.fqNameSafe.asString()
|
||||||
val refType = state.classes[type.toString()]?.type ?: LLVMReferenceType(refName, align = TranslationState.pointerAlign, prefix = "class")
|
val refType = state.classes[type.toString()]?.type ?: LLVMReferenceType(refName, align = TranslationState.pointerAlign, prefix = "class")
|
||||||
|
|
||||||
val result = LLVMVariable(name, refType, name, scope, pointer = 1)
|
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun LLVMMapStandardType(type: KotlinType, state: TranslationState): LLVMType =
|
fun LLVMMapStandardType(type: KotlinType, state: TranslationState) =
|
||||||
LLVMInstanceOfStandardType("type", type, LLVMRegisterScope(), state).type
|
LLVMInstanceOfStandardType("type", type, LLVMRegisterScope(), state).type
|
||||||
|
|
||||||
fun String.addBeforeIfNotEmpty(add: String): String =
|
fun String.addBeforeIfNotEmpty(add: String): String =
|
||||||
if (this.length > 0) add + this else this
|
if (this.length > 0) add + this else this
|
||||||
|
|
||||||
|
|
||||||
fun String.addAfterIfNotEmpty(add: String): String =
|
fun String.addAfterIfNotEmpty(add: String): String =
|
||||||
if (this.length > 0) this + add else this
|
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 =
|
fun FqName.convertToNativeName(): String =
|
||||||
this.asString().replace(".<init>", "")
|
this.asString().replace(".<init>", "")
|
||||||
@@ -18,8 +18,6 @@ class LLVMReferenceType(val type: String,
|
|||||||
|
|
||||||
override fun toString() = "%$typename"
|
override fun toString() = "%$typename"
|
||||||
|
|
||||||
val location = ArrayList<String>()
|
|
||||||
|
|
||||||
override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
override fun operatorEq(firstOp: LLVMSingleValue, secondOp: LLVMSingleValue) =
|
||||||
LLVMExpression(LLVMBooleanType(), "icmp eq ${firstOp.getType()} $firstOp, ${if (secondOp.type is LLVMNullType) "null" else "$secondOp"}")
|
LLVMExpression(LLVMBooleanType(), "icmp eq ${firstOp.getType()} $firstOp, ${if (secondOp.type is LLVMNullType) "null" else "$secondOp"}")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user