diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/FileTranslator.kt b/translator/src/main/kotlin/org/kotlinnative/translator/FileTranslator.kt index ceff49542d8..ea4288641ba 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/FileTranslator.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/FileTranslator.kt @@ -4,7 +4,6 @@ import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtNamedFunction import org.kotlinnative.translator.llvm.LLVMBuilder import org.kotlinnative.translator.utils.FunctionDescriptor -import org.kotlinnative.translator.utils.KtType class FileTranslator(val state: TranslationState, val file: KtFile) { @@ -22,8 +21,8 @@ class FileTranslator(val state: TranslationState, val file: KtFile) { is KtNamedFunction -> { val function = FunctionCodegen(state, declaration, codeBuilder) state.functions.put(function.name, FunctionDescriptor( - KtType(function.returnType), - function.args?.map { KtType(it.type) }?.toList() ?: listOf() + function.returnType, + function.args?.map { it.type }?.toList() ?: listOf() )) function.generate() diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt b/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt index 554978830fd..3eb5e3af692 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/FunctionCodegen.kt @@ -4,18 +4,15 @@ import com.intellij.psi.PsiElement import com.intellij.psi.PsiWhiteSpace import com.intellij.psi.impl.source.tree.LeafPsiElement import org.jetbrains.kotlin.lexer.KtTokens -import org.jetbrains.kotlin.psi.KtBinaryExpression -import org.jetbrains.kotlin.psi.KtBlockExpression -import org.jetbrains.kotlin.psi.KtConstantExpression -import org.jetbrains.kotlin.psi.KtNamedFunction +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespaceAndComments import org.jetbrains.kotlin.resolve.BindingContext -import org.kotlinnative.translator.llvm.LLVMBuilder -import org.kotlinnative.translator.llvm.LLVMDescriptorGenerate -import org.kotlinnative.translator.llvm.LLVMMapStandardType -import org.kotlinnative.translator.llvm.LLVMVariable +import org.kotlinnative.translator.debug.printFunction +import org.kotlinnative.translator.llvm.* import org.kotlinnative.translator.llvm.types.LLVMIntType +import org.kotlinnative.translator.llvm.types.parseLLVMType import org.kotlinnative.translator.utils.FunctionArgument +import java.util.* class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction, val codeBuilder: LLVMBuilder) { @@ -44,40 +41,59 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction codeBuilder.addLLVMCode(LLVMDescriptorGenerate(function.fqName.toString(), args, returnType)) } - - private fun expressionWalker(expr: Any?) { + private fun expressionWalker(expr: PsiElement?) { when (expr) { - is KtBlockExpression -> evaluateBlockExpression(expr) - is PsiElement -> evaluatePsiExpression(expr) - null -> Unit + is KtBlockExpression -> expressionWalker(expr.firstChild) + is KtProperty -> evaluateLeafPsiElement(expr.firstChild as LeafPsiElement) + is PsiElement -> evaluateExpression(expr.firstChild) + null -> return else -> UnsupportedOperationException() } + + expressionWalker(expr?.getNextSiblingIgnoringWhitespaceAndComments()) } - private fun evaluateBlockExpression(expr: KtBlockExpression) { - expressionWalker(expr.firstChild) - expressionWalker(expr.getNextSiblingIgnoringWhitespaceAndComments()) - } - - private fun evaluatePsiExpression(expr: PsiElement) { - evaluateExpression(expr.firstChild) - evaluatePsiExpression(expr.getNextSiblingIgnoringWhitespaceAndComments() ?: return) - } - - private fun evaluateExpression(expr: Any?): LLVMVariable? { + private fun evaluateExpression(expr: PsiElement?): LLVMNode? { return when (expr) { is KtBinaryExpression -> evaluateBinaryExpression(expr) + is KtConstantExpression -> evaluateConstantExpression(expr) + is KtCallExpression -> evaluateCallExpression(expr) is PsiWhiteSpace -> null is PsiElement -> evaluatePsiElement(expr) - is KtConstantExpression -> evaluateConstantExpression(expr) null -> null else -> throw UnsupportedOperationException() } } - private fun evaluateBinaryExpression(expr: KtBinaryExpression): LLVMVariable { - val left = evaluateExpression(expr.firstChild) ?: throw UnsupportedOperationException("Wrong binary exception") - val right = evaluateExpression(expr.lastChild) ?: throw UnsupportedOperationException("Wrong binary exception") + private fun evaluateCallExpression(expr: KtCallExpression): LLVMNode? { + val function = expr.firstChild.firstChild + val descriptor = state.functions[function.text] ?: return null + val names = parseArgList(expr + .firstChild + .getNextSiblingIgnoringWhitespaceAndComments() + ?.firstChild) + + return LLVMCall(descriptor.returnType, function.text, descriptor.argTypes.mapIndexed { i: Int, type: String -> LLVMVariable(names[i], parseLLVMType(type)) }) + } + + private fun parseArgList(argumentList: PsiElement?): List { + val args = ArrayList() + + var currentArg = argumentList?.getNextSiblingIgnoringWhitespaceAndComments() + + while (currentArg?.text != ")" && currentArg != null) { + args.add(currentArg?.text) + + currentArg = currentArg + ?.getNextSiblingIgnoringWhitespaceAndComments() + ?.getNextSiblingIgnoringWhitespaceAndComments() + } + return args + } + + private fun evaluateBinaryExpression(expr: KtBinaryExpression): LLVMNode { + val left = evaluateExpression(expr.firstChild) as LLVMVariable? ?: throw UnsupportedOperationException("Wrong binary exception") + val right = evaluateExpression(expr.lastChild) as LLVMVariable? ?: throw UnsupportedOperationException("Wrong binary exception") val operator = expr.operationToken return codeBuilder.addPrimitiveBinaryOperation(operator, left, right) @@ -100,13 +116,24 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction private fun evaluateLeafPsiElement(element: LeafPsiElement): LLVMVariable? { return when (element.elementType) { KtTokens.RETURN_KEYWORD -> evaluateReturnInstruction(element) + KtTokens.VAL_KEYWORD -> evaluateValExpression(element) + KtTokens.VAR_KEYWORD -> evaluateValExpression(element) else -> null } } + private fun evaluateValExpression(element: LeafPsiElement): LLVMVariable? { + val identifier = element.getNextSiblingIgnoringWhitespaceAndComments() + val eq = identifier?.getNextSiblingIgnoringWhitespaceAndComments() ?: return null + + val assignExpression = evaluateExpression(eq?.getNextSiblingIgnoringWhitespaceAndComments()) ?: return null + codeBuilder.addAssignment(LLVMVariable(identifier!!.text), assignExpression) + return null + } + private fun evaluateReturnInstruction(element: LeafPsiElement): LLVMVariable? { - var next = element.getNextSiblingIgnoringWhitespaceAndComments(); - val retVar = evaluateExpression(next) + var next = element.getNextSiblingIgnoringWhitespaceAndComments() + val retVar = evaluateExpression(next) as LLVMVariable codeBuilder.addLLVMCode("ret i32 ${retVar?.label}") return null diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/TranslationState.kt b/translator/src/main/kotlin/org/kotlinnative/translator/TranslationState.kt index 80eef985cd2..3ce29666312 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/TranslationState.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/TranslationState.kt @@ -22,7 +22,7 @@ import org.kotlinnative.translator.utils.FunctionDescriptor import java.util.* -class TranslationState(val sources: List, disposer: Disposable) { +class TranslationState(sources: List, disposer: Disposable) { val environment: KotlinCoreEnvironment val bindingContext: BindingContext diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/exceptions/TranslationException.kt b/translator/src/main/kotlin/org/kotlinnative/translator/exceptions/TranslationException.kt index 576f5d38e8a..3fa7723ff30 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/exceptions/TranslationException.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/exceptions/TranslationException.kt @@ -1,3 +1,3 @@ package org.kotlinnative.translator.exceptions -class TranslationException : Exception() \ No newline at end of file +class TranslationException : Exception() diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt index 520bb70cb30..ca988601418 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMBuilder.kt @@ -33,19 +33,24 @@ class LLVMBuilder { KtTokens.PLUS -> "add nsw i32" KtTokens.MINUS -> "sub nsw i32" KtTokens.MUL -> "mul nsw i32" - else -> throw UnsupportedOperationException("Unkbown binary operator") + else -> throw UnsupportedOperationException("Unknown binary operator") } llvmCode.appendln("$newVar = $llvmOperator $firstOp, $secondOp") return newVar } - fun clean() { llvmCode = StringBuilder() } + fun addAssignment(llvmVariable: LLVMVariable, rhs: LLVMNode) { + llvmCode.appendln("%$llvmVariable = $rhs") + } + override fun toString(): String { return llvmCode.toString() } + + } \ No newline at end of file diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMCall.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMCall.kt new file mode 100644 index 00000000000..80e1f598378 --- /dev/null +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMCall.kt @@ -0,0 +1,8 @@ +package org.kotlinnative.translator.llvm + +class LLVMCall(val returnType: String, val name: String, val arguments: List) : LLVMNode() { + + override fun toString(): String { + return "call $returnType $name(${arguments.joinToString { "${it.type} ${it.label}" }})" + } +} diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMExpression.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMExpression.kt index b70b8074ff7..c152429496a 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMExpression.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMExpression.kt @@ -3,10 +3,12 @@ package org.kotlinnative.translator.llvm import org.kotlinnative.translator.llvm.types.LLVMType import kotlin.reflect.KFunction0 -class LLVMExpression(val variableType: KFunction0, val llvmCode: String) : LLVMNode() { +open class LLVMExpression(val variableType: KFunction0, val llvmCode: String) : LLVMNode() { + fun generateExpression(builder: LLVMBuilder): LLVMVariable { - val newVar = builder.getNewVariable(variableType); - builder.addLLVMCode("%$newVar = $llvmCode"); + val newVar = builder.getNewVariable(variableType) + builder.addLLVMCode("%$newVar = $llvmCode") return newVar } + } \ No newline at end of file diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMVariable.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMVariable.kt index 5985324c56c..e711857d9b2 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMVariable.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/LLVMVariable.kt @@ -2,9 +2,10 @@ package org.kotlinnative.translator.llvm import org.kotlinnative.translator.llvm.types.LLVMType -class LLVMVariable(val label: String, val type: LLVMType?) : LLVMNode() { +class LLVMVariable(val label: String, val type: LLVMType? = null) : LLVMNode() { override fun toString(): String { return label } + } \ No newline at end of file diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMIntType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMIntType.kt index fb9d09a9689..cd8a406fe7c 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMIntType.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMIntType.kt @@ -5,9 +5,14 @@ import org.kotlinnative.translator.llvm.LLVMVariable class LLVMIntType() : LLVMType() { + override fun operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression { //TODO switch by types: int + double = int return LLVMExpression(::LLVMIntType, "add nsw i32 $firstOp, $secondOp") } + override fun toString(): String { + return "i32" + } + } \ No newline at end of file diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMType.kt b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMType.kt index 760c58b2664..d74e29a7ca9 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMType.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/llvm/types/LLVMType.kt @@ -1,8 +1,14 @@ package org.kotlinnative.translator.llvm.types; +import org.kotlinnative.translator.exceptions.TranslationException import org.kotlinnative.translator.llvm.LLVMExpression import org.kotlinnative.translator.llvm.LLVMVariable abstract class LLVMType() { abstract fun operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression; } + +fun parseLLVMType(type: String): LLVMType = when(type) { + "i32" -> LLVMIntType() + else -> throw TranslationException() +} diff --git a/translator/src/main/kotlin/org/kotlinnative/translator/utils/types.kt b/translator/src/main/kotlin/org/kotlinnative/translator/utils/types.kt index 5e372049dbd..0183303e8df 100644 --- a/translator/src/main/kotlin/org/kotlinnative/translator/utils/types.kt +++ b/translator/src/main/kotlin/org/kotlinnative/translator/utils/types.kt @@ -2,6 +2,4 @@ package org.kotlinnative.translator.utils data class FunctionArgument(val type: String, val name: String) -data class KtType(val name: String) - -data class FunctionDescriptor(val returnType: KtType, val argTypes: List) +data class FunctionDescriptor(val returnType: String, val argTypes: List)