translator: add function call
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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<String> {
|
||||
val args = ArrayList<String>()
|
||||
|
||||
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
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.kotlinnative.translator.utils.FunctionDescriptor
|
||||
import java.util.*
|
||||
|
||||
|
||||
class TranslationState(val sources: List<String>, disposer: Disposable) {
|
||||
class TranslationState(sources: List<String>, disposer: Disposable) {
|
||||
|
||||
val environment: KotlinCoreEnvironment
|
||||
val bindingContext: BindingContext
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
package org.kotlinnative.translator.exceptions
|
||||
|
||||
class TranslationException : Exception()
|
||||
class TranslationException : Exception()
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package org.kotlinnative.translator.llvm
|
||||
|
||||
class LLVMCall(val returnType: String, val name: String, val arguments: List<LLVMVariable>) : LLVMNode() {
|
||||
|
||||
override fun toString(): String {
|
||||
return "call $returnType $name(${arguments.joinToString { "${it.type} ${it.label}" }})"
|
||||
}
|
||||
}
|
||||
@@ -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<LLVMType>, val llvmCode: String) : LLVMNode() {
|
||||
open class LLVMExpression(val variableType: KFunction0<LLVMType>, 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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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<KtType>)
|
||||
data class FunctionDescriptor(val returnType: String, val argTypes: List<String>)
|
||||
|
||||
Reference in New Issue
Block a user