translator: add companion objects with methods
This commit is contained in:
@@ -101,6 +101,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun evaluateClassScopedDotExpression(clazz: ClassCodegen, selector: KtExpression, scopeDepth: Int): LLVMSingleValue? = when (selector) {
|
private fun evaluateClassScopedDotExpression(clazz: ClassCodegen, selector: KtExpression, scopeDepth: Int): LLVMSingleValue? = when (selector) {
|
||||||
|
|
||||||
is KtCallExpression -> evaluateCallExpression(selector, scopeDepth, clazz)
|
is KtCallExpression -> evaluateCallExpression(selector, scopeDepth, clazz)
|
||||||
else -> throw UnsupportedOperationException()
|
else -> throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
@@ -182,6 +183,27 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
|||||||
return evaluateFunctionCallExpression(LLVMVariable(function, type.returnType.type, scope = LLVMRegisterScope()), args)
|
return evaluateFunctionCallExpression(LLVMVariable(function, type.returnType.type, scope = LLVMRegisterScope()), args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state.classes.containsKey(classScope?.structName)) {
|
||||||
|
val classDescriptor = state.classes[classScope?.structName] ?: return null
|
||||||
|
val methodShortName = classScope?.structName + "." + function
|
||||||
|
if (classDescriptor.companionMethods.containsKey(methodShortName)) {
|
||||||
|
val descriptor = classDescriptor.companionMethods[methodShortName] ?: return null
|
||||||
|
val parentDescriptor = descriptor.parentCodegen!!
|
||||||
|
val receiver = variableManager.getLLVMvalue(parentDescriptor.structName)!!
|
||||||
|
val methodFullName = descriptor.name
|
||||||
|
|
||||||
|
val returnType = descriptor.returnType!!.type
|
||||||
|
|
||||||
|
val loadedArgs = loadArgsIfRequired(names, descriptor.args)
|
||||||
|
val callArgs = mutableListOf<LLVMSingleValue>(receiver)
|
||||||
|
callArgs.addAll(loadedArgs)
|
||||||
|
|
||||||
|
return evaluateFunctionCallExpression(LLVMVariable(methodFullName, returnType, scope = LLVMVariableScope()), callArgs)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
val nestedConstructor = classScope?.nestedClasses?.get(expr.calleeExpression!!.text)
|
val nestedConstructor = classScope?.nestedClasses?.get(expr.calleeExpression!!.text)
|
||||||
if (nestedConstructor != null) {
|
if (nestedConstructor != null) {
|
||||||
val args = loadArgsIfRequired(names, nestedConstructor.constructorFields)
|
val args = loadArgsIfRequired(names, nestedConstructor.constructorFields)
|
||||||
|
|||||||
@@ -23,10 +23,11 @@ class ClassCodegen(override val state: TranslationState,
|
|||||||
|
|
||||||
override var size: Int = 0
|
override var size: Int = 0
|
||||||
override val structName: String
|
override val structName: String
|
||||||
override val type: LLVMReferenceType = LLVMReferenceType(clazz.name.toString(), "class", byRef = true)
|
override val type: LLVMReferenceType
|
||||||
|
|
||||||
init {
|
init {
|
||||||
structName = clazz.name!!
|
structName = (if (parentCodegen != null) parentCodegen.structName + "." else "") + clazz.name!!
|
||||||
|
type = LLVMReferenceType(structName, "class", byRef = true)
|
||||||
val descriptor = state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException()
|
val descriptor = state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException()
|
||||||
val parameterList = clazz.getPrimaryConstructorParameterList()?.parameters ?: listOf()
|
val parameterList = clazz.getPrimaryConstructorParameterList()?.parameters ?: listOf()
|
||||||
|
|
||||||
@@ -76,6 +77,20 @@ class ClassCodegen(override val state: TranslationState,
|
|||||||
|
|
||||||
generate(clazz.declarations)
|
generate(clazz.declarations)
|
||||||
nestedClasses.forEach { x, classCodegen -> classCodegen.generate() }
|
nestedClasses.forEach { x, classCodegen -> classCodegen.generate() }
|
||||||
|
|
||||||
|
val descriptor = state.bindingContext.get(BindingContext.CLASS, clazz) ?: throw TranslationException()
|
||||||
|
val companionObjectDescriptor = descriptor.companionObjectDescriptor
|
||||||
|
if (companionObjectDescriptor != null) {
|
||||||
|
val companionObject = clazz.getCompanionObjects().first()
|
||||||
|
val property = ObjectCodegen(state, variableManager, companionObject, codeBuilder, this)
|
||||||
|
val companionObjectName = structName + "." + companionObject.name
|
||||||
|
property.generate()
|
||||||
|
|
||||||
|
for (method in property.methods) {
|
||||||
|
val methodName = method.key.removePrefix(companionObjectName + ".")
|
||||||
|
companionMethods.put(structName + "." + methodName, method.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,11 @@ import org.kotlinnative.translator.llvm.types.LLVMVoidType
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
class FunctionCodegen(override val state: TranslationState, override val variableManager: VariableManager, val function: KtNamedFunction,
|
class FunctionCodegen(override val state: TranslationState,
|
||||||
override val codeBuilder: LLVMBuilder) :
|
override val variableManager: VariableManager,
|
||||||
|
val function: KtNamedFunction,
|
||||||
|
override val codeBuilder: LLVMBuilder,
|
||||||
|
val parentCodegen: StructCodegen? = null) :
|
||||||
BlockCodegen(state, variableManager, codeBuilder) {
|
BlockCodegen(state, variableManager, codeBuilder) {
|
||||||
|
|
||||||
var name = function.fqName.toString()
|
var name = function.fqName.toString()
|
||||||
|
|||||||
@@ -8,21 +8,26 @@ import org.kotlinnative.translator.llvm.LLVMVariable
|
|||||||
import org.kotlinnative.translator.llvm.LLVMVariableScope
|
import org.kotlinnative.translator.llvm.LLVMVariableScope
|
||||||
import org.kotlinnative.translator.llvm.types.LLVMReferenceType
|
import org.kotlinnative.translator.llvm.types.LLVMReferenceType
|
||||||
|
|
||||||
class ObjectCodegen(override val state: TranslationState, override val variableManager: VariableManager, val objectDeclaration: KtObjectDeclaration, override val codeBuilder: LLVMBuilder) :
|
class ObjectCodegen(override val state: TranslationState,
|
||||||
|
override val variableManager: VariableManager,
|
||||||
|
val objectDeclaration: KtObjectDeclaration,
|
||||||
|
override val codeBuilder: LLVMBuilder,
|
||||||
|
override val parentCodegen: StructCodegen? = null) :
|
||||||
StructCodegen(state, variableManager, objectDeclaration, state.bindingContext.get(BindingContext.CLASS, objectDeclaration) ?: throw TranslationException(),
|
StructCodegen(state, variableManager, objectDeclaration, state.bindingContext.get(BindingContext.CLASS, objectDeclaration) ?: throw TranslationException(),
|
||||||
codeBuilder) {
|
codeBuilder, parentCodegen = parentCodegen) {
|
||||||
override var size: Int = 0
|
override var size: Int = 0
|
||||||
override val structName: String
|
override val structName: String
|
||||||
override val type: LLVMReferenceType = LLVMReferenceType(objectDeclaration.name.toString(), "class", byRef = true)
|
override val type: LLVMReferenceType
|
||||||
|
|
||||||
init {
|
init {
|
||||||
structName = objectDeclaration.name!!
|
structName = (if (parentCodegen != null) parentCodegen.structName + "." else "") + objectDeclaration.name!!
|
||||||
|
type = LLVMReferenceType(structName, "class", byRef = true)
|
||||||
generateInnerFields(objectDeclaration.declarations)
|
generateInnerFields(objectDeclaration.declarations)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun generate() {
|
fun generate() {
|
||||||
generate(objectDeclaration.declarations)
|
generate(objectDeclaration.declarations)
|
||||||
val classInstance = LLVMVariable("object.instance.$structName", type, objectDeclaration.name, LLVMVariableScope(), pointer=1)
|
val classInstance = LLVMVariable("object.instance.$structName", type, objectDeclaration.name, LLVMVariableScope(), pointer = 1)
|
||||||
codeBuilder.addGlobalIntialize(classInstance, type)
|
codeBuilder.addGlobalIntialize(classInstance, type)
|
||||||
variableManager.addGlobalVariable(structName, classInstance)
|
variableManager.addGlobalVariable(structName, classInstance)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,11 +16,12 @@ abstract class StructCodegen(open val state: TranslationState,
|
|||||||
open val classOrObject: KtClassOrObject,
|
open val classOrObject: KtClassOrObject,
|
||||||
val classDescriptor: ClassDescriptor,
|
val classDescriptor: ClassDescriptor,
|
||||||
open val codeBuilder: LLVMBuilder,
|
open val codeBuilder: LLVMBuilder,
|
||||||
val owner: StructCodegen? = null) {
|
open val parentCodegen: StructCodegen? = null) {
|
||||||
|
|
||||||
val fields = ArrayList<LLVMVariable>()
|
val fields = ArrayList<LLVMVariable>()
|
||||||
val fieldsIndex = HashMap<String, LLVMClassVariable>()
|
val fieldsIndex = HashMap<String, LLVMClassVariable>()
|
||||||
val nestedClasses = HashMap<String, ClassCodegen>()
|
val nestedClasses = HashMap<String, ClassCodegen>()
|
||||||
|
val companionMethods = HashMap<String, FunctionCodegen>()
|
||||||
|
|
||||||
val constructorFields = ArrayList<LLVMVariable>()
|
val constructorFields = ArrayList<LLVMVariable>()
|
||||||
|
|
||||||
@@ -31,6 +32,7 @@ abstract class StructCodegen(open val state: TranslationState,
|
|||||||
val fullName: String
|
val fullName: String
|
||||||
get() = "${if (type.location.size > 0) "${type.location.joinToString(".")}." else ""}$structName"
|
get() = "${if (type.location.size > 0) "${type.location.joinToString(".")}." else ""}$structName"
|
||||||
|
|
||||||
|
|
||||||
fun generate(declarations: List<KtDeclaration>) {
|
fun generate(declarations: List<KtDeclaration>) {
|
||||||
generateStruct()
|
generateStruct()
|
||||||
generatePrimaryConstructor()
|
generatePrimaryConstructor()
|
||||||
@@ -38,13 +40,15 @@ abstract class StructCodegen(open val state: TranslationState,
|
|||||||
for (declaration in declarations) {
|
for (declaration in declarations) {
|
||||||
when (declaration) {
|
when (declaration) {
|
||||||
is KtNamedFunction -> {
|
is KtNamedFunction -> {
|
||||||
val function = FunctionCodegen(state, variableManager, declaration, codeBuilder)
|
val function = FunctionCodegen(state, variableManager, declaration, codeBuilder, this)
|
||||||
methods.put(function.name, function)
|
methods.put(function.name, function)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val classVal = LLVMVariable("classvariable.this", type, pointer = 1)
|
val classVal = LLVMVariable("classvariable.this", type, pointer = 1)
|
||||||
variableManager.addVariable("this", classVal, 0)
|
variableManager.addVariable("this", classVal, 0)
|
||||||
|
|
||||||
for (function in methods.values) {
|
for (function in methods.values) {
|
||||||
function.generate(classVal)
|
function.generate(classVal)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
companion_object_1() == 5
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
class companion_object {
|
||||||
|
companion object Factory {
|
||||||
|
val fieldCompanion: Int = 5790
|
||||||
|
|
||||||
|
fun create(): Int {
|
||||||
|
return 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun companion_object_1(): Int {
|
||||||
|
return companion_object.create()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user