translator: add function extensions
This commit is contained in:
@@ -68,6 +68,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
is KtIfExpression -> evaluateIfOperator(expr.firstChild as LeafPsiElement, scopeDepth + 1, expr)
|
||||
is KtStringTemplateExpression -> evaluateStringTemplateExpression(expr)
|
||||
is KtReturnExpression -> evaluateReturnInstruction(expr.firstChild, scopeDepth)
|
||||
is KtThisExpression -> evaluateThisExpression(expr, scopeDepth)
|
||||
is PsiWhiteSpace -> null
|
||||
is PsiElement -> evaluatePsiElement(expr, scopeDepth)
|
||||
null -> null
|
||||
@@ -75,6 +76,10 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
}
|
||||
}
|
||||
|
||||
private fun evaluateThisExpression(expr: KtThisExpression, scopeDepth: Int): LLVMSingleValue? {
|
||||
return variableManager.getLLVMvalue("this")
|
||||
}
|
||||
|
||||
fun evaluateStringTemplateExpression(expr: KtStringTemplateExpression): LLVMSingleValue? {
|
||||
val receiveValue = state.bindingContext.get(BindingContext.COMPILE_TIME_VALUE, expr)
|
||||
val type = (receiveValue as TypedCompileTimeConstant).type
|
||||
@@ -87,11 +92,12 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
|
||||
private fun evaluateCallableReferenceExpression(expr: KtCallableReferenceExpression): LLVMSingleValue? {
|
||||
val kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)!!.type!!
|
||||
return LLVMMapStandardType(expr.text.substring(2), kotlinType, LLVMVariableScope())
|
||||
return LLVMInstanceOfStandardType(expr.text.substring(2), kotlinType, LLVMVariableScope())
|
||||
}
|
||||
|
||||
private fun evaluateDotExpression(expr: KtDotQualifiedExpression, scopeDepth: Int): LLVMSingleValue? {
|
||||
val receiverName = expr.receiverExpression.text
|
||||
val receiverExpr = expr.receiverExpression
|
||||
val receiverName = receiverExpr.text
|
||||
val selectorExpr = expr.selectorExpression!!
|
||||
|
||||
var receiver = variableManager.getLLVMvalue(receiverName)
|
||||
@@ -99,13 +105,37 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
if (receiver.pointer == 2) {
|
||||
receiver = codeBuilder.loadAndGetVariable(receiver)
|
||||
}
|
||||
return evaluateMemberMethodOrField(receiver, selectorExpr.text, scopeDepth, expr.lastChild)
|
||||
when (receiver.type) {
|
||||
is LLVMReferenceType -> return evaluateMemberMethodOrField(receiver, selectorExpr.text, scopeDepth, expr.lastChild)
|
||||
else -> return evaluateExtensionExpression(receiverExpr, selectorExpr as KtCallExpression, scopeDepth)
|
||||
}
|
||||
}
|
||||
|
||||
val clazz = state.classes[receiverName] ?: return null
|
||||
val clazz = state.classes[receiverName] ?: return evaluateExtensionExpression(receiverExpr, selectorExpr as KtCallExpression, scopeDepth)
|
||||
|
||||
return evaluateClassScopedDotExpression(clazz, selectorExpr, scopeDepth)
|
||||
}
|
||||
|
||||
private fun evaluateExtensionExpression(receiver: KtExpression, selector: KtCallExpression, scopeDepth: Int): LLVMSingleValue? {
|
||||
val receiverType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, receiver)
|
||||
val standartType = LLVMMapStandardType(receiverType!!.type!!)
|
||||
val function = selector.firstChild.firstChild.text
|
||||
val names = parseArgList(selector, scopeDepth)
|
||||
val extensionCodegen = state.extensionFunctions[standartType.toString()]!![function]!!
|
||||
val receiverExpression = evaluateExpression(receiver, scopeDepth + 1)!!
|
||||
|
||||
val typeThisArgument = when (standartType) {
|
||||
is LLVMReferenceType -> LLVMVariable("type", standartType, pointer = 1)
|
||||
else -> LLVMVariable("type", standartType, pointer = 0)
|
||||
}
|
||||
|
||||
val args = mutableListOf<LLVMSingleValue>(loadArgumentIfRequired(receiverExpression, typeThisArgument))
|
||||
|
||||
args.addAll(loadArgsIfRequired(names, extensionCodegen.args))
|
||||
|
||||
return evaluateFunctionCallExpression(LLVMVariable(extensionCodegen.fullName, extensionCodegen.returnType!!.type, scope = LLVMVariableScope()), args)
|
||||
}
|
||||
|
||||
private fun evaluateClassScopedDotExpression(clazz: ClassCodegen, selector: KtExpression, scopeDepth: Int): LLVMSingleValue? = when (selector) {
|
||||
|
||||
is KtCallExpression -> evaluateCallExpression(selector, scopeDepth, clazz)
|
||||
@@ -266,16 +296,21 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
return null
|
||||
}
|
||||
|
||||
private fun loadArgsIfRequired(names: List<LLVMSingleValue>, args: List<LLVMVariable>) = names.mapIndexed(fun(i: Int, value: LLVMSingleValue): LLVMSingleValue {
|
||||
private fun loadArgumentIfRequired(value: LLVMSingleValue, argument: LLVMVariable): LLVMSingleValue {
|
||||
var result = value
|
||||
|
||||
if (result.pointer > 0 && args[i].pointer == 0) {
|
||||
result = codeBuilder.getNewVariable(args[i].type)
|
||||
if (result.pointer > 0 && argument.pointer == 0) {
|
||||
result = codeBuilder.getNewVariable(argument.type)
|
||||
codeBuilder.loadVariable(result, value as LLVMVariable)
|
||||
}
|
||||
|
||||
return result
|
||||
}).toList()
|
||||
}
|
||||
|
||||
private fun loadArgsIfRequired(names: List<LLVMSingleValue>, args: List<LLVMVariable>) =
|
||||
names.mapIndexed(fun(i: Int, value: LLVMSingleValue): LLVMSingleValue {
|
||||
return loadArgumentIfRequired(value, args[i])
|
||||
}).toList()
|
||||
|
||||
private fun evaluateConstructorCallExpression(function: LLVMVariable, names: List<LLVMSingleValue>): LLVMSingleValue? {
|
||||
val store = codeBuilder.getNewVariable(function.type)
|
||||
@@ -457,7 +492,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
codeBuilder.addComment("start when expression")
|
||||
val whenExpression = expr.subjectExpression
|
||||
val kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, expr)!!.type!!
|
||||
val expressionType = LLVMMapStandardType("type", kotlinType, LLVMVariableScope()).type
|
||||
val expressionType = LLVMMapStandardType(kotlinType)
|
||||
|
||||
val targetExpression = evaluateExpression(whenExpression, scopeDepth + 1)!!
|
||||
|
||||
@@ -524,7 +559,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
private fun executeIfExpression(condition: KtBinaryExpression, thenExpression: PsiElement, elseExpression: PsiElement?, ifExpression: KtIfExpression, scopeDepth: Int): LLVMVariable? {
|
||||
val conditionResult: LLVMVariable = evaluateBinaryExpression(condition, scopeDepth + 1)
|
||||
val kotlinType = state.bindingContext.get(BindingContext.EXPRESSION_TYPE_INFO, ifExpression)!!.type!!
|
||||
val expressionType = LLVMMapStandardType("type", kotlinType, LLVMVariableScope()).type
|
||||
val expressionType = LLVMInstanceOfStandardType("type", kotlinType, LLVMVariableScope()).type
|
||||
val resultVariable = codeBuilder.getNewVariable(expressionType, pointer = 1)
|
||||
codeBuilder.allocStackPointedVarAsValue(resultVariable)
|
||||
val thenLabel = codeBuilder.getNewLabel(prefix = "if")
|
||||
@@ -586,7 +621,7 @@ abstract class BlockCodegen(open val state: TranslationState, open val variableM
|
||||
}
|
||||
is LLVMConstant -> {
|
||||
if (assignExpression.type is LLVMNullType) {
|
||||
val reference = LLVMMapStandardType(identifier, variable.type)
|
||||
val reference = LLVMInstanceOfStandardType(identifier, variable.type)
|
||||
if (state.classes.containsKey(variable.type.toString().dropLast(1))) {
|
||||
(reference.type as LLVMReferenceType).prefix = "class"
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.kotlinnative.translator
|
||||
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.kotlinnative.translator.debug.printFile
|
||||
|
||||
class FileTranslator(val state: TranslationState, val file: KtFile) {
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.kotlinnative.translator
|
||||
|
||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespaceAndComments
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isExtensionDeclaration
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.kotlinnative.translator.llvm.*
|
||||
import org.kotlinnative.translator.llvm.types.LLVMFunctionType
|
||||
@@ -20,15 +21,18 @@ class FunctionCodegen(override val state: TranslationState,
|
||||
|
||||
var name = function.fqName.toString()
|
||||
var args = LinkedList<LLVMVariable>()
|
||||
val isExtensionDeclaration = function.isExtensionDeclaration()
|
||||
var functionNamePrefix = ""
|
||||
val fullName: String
|
||||
get() = functionNamePrefix + name
|
||||
|
||||
init {
|
||||
val descriptor = state.bindingContext.get(BindingContext.FUNCTION, function)!!
|
||||
args.addAll(descriptor.valueParameters.map {
|
||||
LLVMMapStandardType(it.name.toString(), it.type)
|
||||
LLVMInstanceOfStandardType(it.name.toString(), it.type)
|
||||
})
|
||||
|
||||
|
||||
returnType = LLVMMapStandardType("instance", descriptor.returnType!!)
|
||||
returnType = LLVMInstanceOfStandardType("instance", descriptor.returnType!!)
|
||||
val retType = returnType!!.type
|
||||
when (retType) {
|
||||
is LLVMReferenceType -> {
|
||||
@@ -88,13 +92,28 @@ class FunctionCodegen(override val state: TranslationState,
|
||||
actualArgs.add(returnType!!)
|
||||
}
|
||||
|
||||
if (isExtensionDeclaration) {
|
||||
val receiverParameter = state.bindingContext.get(BindingContext.FUNCTION, function)!!.extensionReceiverParameter!!
|
||||
val receiverType = receiverParameter.type
|
||||
val translatorType = LLVMMapStandardType(receiverType)
|
||||
|
||||
val extensionFunctionsOfThisType = state.extensionFunctions.getOrDefault(translatorType, HashMap())
|
||||
extensionFunctionsOfThisType.put(name, this)
|
||||
state.extensionFunctions.put(translatorType.toString(), extensionFunctionsOfThisType)
|
||||
|
||||
val classVal = LLVMVariable("classvariable.this", translatorType, pointer = 0)
|
||||
variableManager.addVariable("this", classVal, 0)
|
||||
actualArgs.add(classVal)
|
||||
functionNamePrefix += translatorType.toString() + "."
|
||||
}
|
||||
|
||||
if (this_type != null) {
|
||||
actualArgs.add(this_type)
|
||||
}
|
||||
|
||||
actualArgs.addAll(args)
|
||||
|
||||
codeBuilder.addLLVMCode(LLVMFunctionDescriptor(function.fqName.toString(), actualArgs, actualReturnType, external, state.arm))
|
||||
codeBuilder.addLLVMCode(LLVMFunctionDescriptor(fullName, actualArgs, actualReturnType, external, state.arm))
|
||||
return external
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
package org.kotlinnative.translator
|
||||
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.kotlinnative.translator.llvm.LLVMBuilder
|
||||
|
||||
class ProjectTranslator(val state: TranslationState) {
|
||||
private var codeBuilder = state.codeBuilder
|
||||
|
||||
@@ -25,7 +22,11 @@ class ProjectTranslator(val state: TranslationState) {
|
||||
clazz.generate()
|
||||
}
|
||||
|
||||
for (function in state.functions.values) {
|
||||
for (function in state.functions.values.filter { it.isExtensionDeclaration }) {
|
||||
function.generate()
|
||||
}
|
||||
|
||||
for (function in state.functions.values.filter { !it.isExtensionDeclaration }) {
|
||||
function.generate()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import org.jetbrains.kotlin.js.descriptorUtils.nameIfStandardType
|
||||
import org.jetbrains.kotlin.psi.KtProperty
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.kotlinnative.translator.llvm.LLVMBuilder
|
||||
import org.kotlinnative.translator.llvm.LLVMMapStandardType
|
||||
import org.kotlinnative.translator.llvm.LLVMInstanceOfStandardType
|
||||
import org.kotlinnative.translator.llvm.LLVMVariable
|
||||
import org.kotlinnative.translator.llvm.LLVMVariableScope
|
||||
|
||||
@@ -17,7 +17,7 @@ class PropertyCodegen(val state: TranslationState, val variableManager: Variable
|
||||
val kotlinType = varInfo.type
|
||||
val value = varInfo.value
|
||||
if (kotlinType.nameIfStandardType != null) {
|
||||
val variableType = LLVMMapStandardType(property.name ?: return, kotlinType).type
|
||||
val variableType = LLVMInstanceOfStandardType(property.name ?: return, kotlinType).type
|
||||
val variable = LLVMVariable(property.name.toString(), variableType, property.name.toString(), LLVMVariableScope(), pointer = 1)
|
||||
variableManager.addGlobalVariable(property.name.toString(), variable)
|
||||
codeBuilder.declareGlobalVariable(variable, variableType.parseArg(value.toString()))
|
||||
|
||||
@@ -33,7 +33,7 @@ abstract class StructCodegen(open val state: TranslationState,
|
||||
var methods = HashMap<String, FunctionCodegen>()
|
||||
abstract val structName: 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>) {
|
||||
@@ -49,7 +49,7 @@ abstract class StructCodegen(open val state: TranslationState,
|
||||
}
|
||||
}
|
||||
|
||||
val classVal = LLVMVariable("classvariable.this", type, pointer = 1)
|
||||
val classVal = LLVMVariable("classvariable.this", type, pointer = if (type.isPrimitive()) 0 else 1)
|
||||
variableManager.addVariable("this", classVal, 0)
|
||||
|
||||
for (function in methods.values) {
|
||||
@@ -156,7 +156,7 @@ abstract class StructCodegen(open val state: TranslationState,
|
||||
protected fun resolveType(field: KtNamedDeclaration, ktType: KotlinType): LLVMClassVariable {
|
||||
val annotations = parseFieldAnnotations(field)
|
||||
|
||||
val result = LLVMMapStandardType(field.name!!, ktType, LLVMRegisterScope())
|
||||
val result = LLVMInstanceOfStandardType(field.name!!, ktType, LLVMRegisterScope())
|
||||
|
||||
if (result.type is LLVMReferenceType) {
|
||||
val type = result.type as LLVMReferenceType
|
||||
|
||||
@@ -30,6 +30,7 @@ class TranslationState(val environment: KotlinCoreEnvironment, val bindingContex
|
||||
var objects = HashMap<String, ObjectCodegen>()
|
||||
var properties = HashMap<String, PropertyCodegen>()
|
||||
val codeBuilder = LLVMBuilder(arm)
|
||||
val extensionFunctions = HashMap<String, HashMap<String, FunctionCodegen>>()
|
||||
}
|
||||
|
||||
fun parseAndAnalyze(sources: List<String>, disposer: Disposable, arm: Boolean = false): TranslationState {
|
||||
|
||||
@@ -12,7 +12,7 @@ fun LLVMFunctionDescriptor(name: String, argTypes: List<LLVMVariable>?, returnTy
|
||||
"${s.getType()} ${if (s.type is LLVMReferenceType && !(s.type as LLVMReferenceType).byRef) "byval" else ""} %${s.label}"
|
||||
}?.joinToString()}) ${if (arm) "#0" else ""}"
|
||||
|
||||
fun LLVMMapStandardType(name: String, type: KotlinType, scope: LLVMScope = LLVMRegisterScope()): LLVMVariable = when {
|
||||
fun LLVMInstanceOfStandardType(name: String, type: KotlinType, scope: LLVMScope = LLVMRegisterScope()): LLVMVariable = when {
|
||||
type.isFunctionTypeOrSubtype -> LLVMVariable(name, LLVMFunctionType(type), name, scope, pointer = 1)
|
||||
type.toString() == "Int" -> LLVMVariable(name, LLVMIntType(), name, scope)
|
||||
type.toString() == "Double" -> LLVMVariable(name, LLVMDoubleType(), name, scope)
|
||||
@@ -22,4 +22,7 @@ fun LLVMMapStandardType(name: String, type: KotlinType, scope: LLVMScope = LLVMR
|
||||
type.isUnit() -> LLVMVariable("", LLVMVoidType(), name, scope)
|
||||
type.isMarkedNullable -> LLVMVariable(name, LLVMReferenceType(type.toString().dropLast(1)), name, scope, pointer = 1)
|
||||
else -> LLVMVariable(name, LLVMReferenceType(type.toString()), name, scope, pointer = 1)
|
||||
}
|
||||
}
|
||||
|
||||
fun LLVMMapStandardType(type: KotlinType): LLVMType =
|
||||
LLVMInstanceOfStandardType("type", type, LLVMRegisterScope()).type
|
||||
|
||||
@@ -45,6 +45,7 @@ class LLVMBooleanType() : LLVMType() {
|
||||
override val align = 4
|
||||
override var size: Int = 1
|
||||
override val defaultValue = "0"
|
||||
override fun isPrimitive() = true
|
||||
|
||||
override fun toString() = "i1"
|
||||
}
|
||||
@@ -26,4 +26,5 @@ class LLVMByteType() : LLVMType() {
|
||||
override var size: Int = 1
|
||||
override fun toString(): String = "i8"
|
||||
override val defaultValue = "0"
|
||||
override fun isPrimitive() = true
|
||||
}
|
||||
|
||||
@@ -26,4 +26,5 @@ class LLVMCharType() : LLVMType() {
|
||||
override var size: Int = 1
|
||||
override fun toString(): String = "i8"
|
||||
override val defaultValue = "0"
|
||||
override fun isPrimitive() = true
|
||||
}
|
||||
|
||||
@@ -22,4 +22,5 @@ class LLVMDoubleType() : LLVMType() {
|
||||
override var size: Int = 8
|
||||
override fun toString() = "double"
|
||||
override val defaultValue = "0.0"
|
||||
override fun isPrimitive() = true
|
||||
}
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
package org.kotlinnative.translator.llvm.types
|
||||
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.kotlinnative.translator.llvm.LLVMMapStandardType
|
||||
import org.kotlinnative.translator.llvm.LLVMInstanceOfStandardType
|
||||
import org.kotlinnative.translator.llvm.LLVMVariable
|
||||
|
||||
class LLVMFunctionType(type: KotlinType) : LLVMType() {
|
||||
@@ -14,7 +14,7 @@ class LLVMFunctionType(type: KotlinType) : LLVMType() {
|
||||
val returnType: LLVMVariable
|
||||
|
||||
init {
|
||||
val types = type.arguments.map { LLVMMapStandardType("", it.type) }.toList()
|
||||
val types = type.arguments.map { LLVMInstanceOfStandardType("", it.type) }.toList()
|
||||
returnType = types.last()
|
||||
arguments = types.dropLast(1)
|
||||
}
|
||||
|
||||
@@ -60,4 +60,5 @@ class LLVMIntType() : LLVMType() {
|
||||
override val defaultValue = "0"
|
||||
|
||||
override fun toString() = "i32"
|
||||
override fun isPrimitive() = true
|
||||
}
|
||||
@@ -27,4 +27,5 @@ class LLVMShortType() : LLVMType() {
|
||||
override val defaultValue = "0"
|
||||
|
||||
override fun toString(): String = "i16"
|
||||
override fun isPrimitive() = true
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ abstract class LLVMType() : Cloneable {
|
||||
abstract val align: Int
|
||||
abstract var size: Int
|
||||
abstract val defaultValue: String
|
||||
open fun isPrimitive(): Boolean = false
|
||||
}
|
||||
|
||||
fun parseLLVMType(type: String): LLVMType = when (type) {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
function_extensions_1(118) == 291
|
||||
@@ -0,0 +1,7 @@
|
||||
fun Int.compareTo(x: Int) : Int{
|
||||
return this + x + 5
|
||||
}
|
||||
|
||||
fun function_extensions_1(x : Int): Int {
|
||||
return x.compareTo(1) + 39.compareTo(123)
|
||||
}
|
||||
Reference in New Issue
Block a user