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.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
import org.kotlinnative.translator.llvm.LLVMBuilder
|
import org.kotlinnative.translator.llvm.LLVMBuilder
|
||||||
import org.kotlinnative.translator.utils.FunctionDescriptor
|
import org.kotlinnative.translator.utils.FunctionDescriptor
|
||||||
import org.kotlinnative.translator.utils.KtType
|
|
||||||
|
|
||||||
class FileTranslator(val state: TranslationState, val file: KtFile) {
|
class FileTranslator(val state: TranslationState, val file: KtFile) {
|
||||||
|
|
||||||
@@ -22,8 +21,8 @@ class FileTranslator(val state: TranslationState, val file: KtFile) {
|
|||||||
is KtNamedFunction -> {
|
is KtNamedFunction -> {
|
||||||
val function = FunctionCodegen(state, declaration, codeBuilder)
|
val function = FunctionCodegen(state, declaration, codeBuilder)
|
||||||
state.functions.put(function.name, FunctionDescriptor(
|
state.functions.put(function.name, FunctionDescriptor(
|
||||||
KtType(function.returnType),
|
function.returnType,
|
||||||
function.args?.map { KtType(it.type) }?.toList() ?: listOf()
|
function.args?.map { it.type }?.toList() ?: listOf()
|
||||||
))
|
))
|
||||||
|
|
||||||
function.generate()
|
function.generate()
|
||||||
|
|||||||
@@ -4,18 +4,15 @@ 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 org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.KtBinaryExpression
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.KtBlockExpression
|
|
||||||
import org.jetbrains.kotlin.psi.KtConstantExpression
|
|
||||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespaceAndComments
|
import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespaceAndComments
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.kotlinnative.translator.llvm.LLVMBuilder
|
import org.kotlinnative.translator.debug.printFunction
|
||||||
import org.kotlinnative.translator.llvm.LLVMDescriptorGenerate
|
import org.kotlinnative.translator.llvm.*
|
||||||
import org.kotlinnative.translator.llvm.LLVMMapStandardType
|
|
||||||
import org.kotlinnative.translator.llvm.LLVMVariable
|
|
||||||
import org.kotlinnative.translator.llvm.types.LLVMIntType
|
import org.kotlinnative.translator.llvm.types.LLVMIntType
|
||||||
|
import org.kotlinnative.translator.llvm.types.parseLLVMType
|
||||||
import org.kotlinnative.translator.utils.FunctionArgument
|
import org.kotlinnative.translator.utils.FunctionArgument
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction, val codeBuilder: LLVMBuilder) {
|
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))
|
codeBuilder.addLLVMCode(LLVMDescriptorGenerate(function.fqName.toString(), args, returnType))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun expressionWalker(expr: PsiElement?) {
|
||||||
private fun expressionWalker(expr: Any?) {
|
|
||||||
when (expr) {
|
when (expr) {
|
||||||
is KtBlockExpression -> evaluateBlockExpression(expr)
|
is KtBlockExpression -> expressionWalker(expr.firstChild)
|
||||||
is PsiElement -> evaluatePsiExpression(expr)
|
is KtProperty -> evaluateLeafPsiElement(expr.firstChild as LeafPsiElement)
|
||||||
null -> Unit
|
is PsiElement -> evaluateExpression(expr.firstChild)
|
||||||
|
null -> return
|
||||||
else -> UnsupportedOperationException()
|
else -> UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
expressionWalker(expr?.getNextSiblingIgnoringWhitespaceAndComments())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun evaluateBlockExpression(expr: KtBlockExpression) {
|
private fun evaluateExpression(expr: PsiElement?): LLVMNode? {
|
||||||
expressionWalker(expr.firstChild)
|
|
||||||
expressionWalker(expr.getNextSiblingIgnoringWhitespaceAndComments())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun evaluatePsiExpression(expr: PsiElement) {
|
|
||||||
evaluateExpression(expr.firstChild)
|
|
||||||
evaluatePsiExpression(expr.getNextSiblingIgnoringWhitespaceAndComments() ?: return)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun evaluateExpression(expr: Any?): LLVMVariable? {
|
|
||||||
return when (expr) {
|
return when (expr) {
|
||||||
is KtBinaryExpression -> evaluateBinaryExpression(expr)
|
is KtBinaryExpression -> evaluateBinaryExpression(expr)
|
||||||
|
is KtConstantExpression -> evaluateConstantExpression(expr)
|
||||||
|
is KtCallExpression -> evaluateCallExpression(expr)
|
||||||
is PsiWhiteSpace -> null
|
is PsiWhiteSpace -> null
|
||||||
is PsiElement -> evaluatePsiElement(expr)
|
is PsiElement -> evaluatePsiElement(expr)
|
||||||
is KtConstantExpression -> evaluateConstantExpression(expr)
|
|
||||||
null -> null
|
null -> null
|
||||||
else -> throw UnsupportedOperationException()
|
else -> throw UnsupportedOperationException()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun evaluateBinaryExpression(expr: KtBinaryExpression): LLVMVariable {
|
private fun evaluateCallExpression(expr: KtCallExpression): LLVMNode? {
|
||||||
val left = evaluateExpression(expr.firstChild) ?: throw UnsupportedOperationException("Wrong binary exception")
|
val function = expr.firstChild.firstChild
|
||||||
val right = evaluateExpression(expr.lastChild) ?: throw UnsupportedOperationException("Wrong binary exception")
|
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
|
val operator = expr.operationToken
|
||||||
|
|
||||||
return codeBuilder.addPrimitiveBinaryOperation(operator, left, right)
|
return codeBuilder.addPrimitiveBinaryOperation(operator, left, right)
|
||||||
@@ -100,13 +116,24 @@ class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction
|
|||||||
private fun evaluateLeafPsiElement(element: LeafPsiElement): LLVMVariable? {
|
private fun evaluateLeafPsiElement(element: LeafPsiElement): LLVMVariable? {
|
||||||
return when (element.elementType) {
|
return when (element.elementType) {
|
||||||
KtTokens.RETURN_KEYWORD -> evaluateReturnInstruction(element)
|
KtTokens.RETURN_KEYWORD -> evaluateReturnInstruction(element)
|
||||||
|
KtTokens.VAL_KEYWORD -> evaluateValExpression(element)
|
||||||
|
KtTokens.VAR_KEYWORD -> evaluateValExpression(element)
|
||||||
else -> null
|
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? {
|
private fun evaluateReturnInstruction(element: LeafPsiElement): LLVMVariable? {
|
||||||
var next = element.getNextSiblingIgnoringWhitespaceAndComments();
|
var next = element.getNextSiblingIgnoringWhitespaceAndComments()
|
||||||
val retVar = evaluateExpression(next)
|
val retVar = evaluateExpression(next) as LLVMVariable
|
||||||
|
|
||||||
codeBuilder.addLLVMCode("ret i32 ${retVar?.label}")
|
codeBuilder.addLLVMCode("ret i32 ${retVar?.label}")
|
||||||
return null
|
return null
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import org.kotlinnative.translator.utils.FunctionDescriptor
|
|||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
|
|
||||||
class TranslationState(val sources: List<String>, disposer: Disposable) {
|
class TranslationState(sources: List<String>, disposer: Disposable) {
|
||||||
|
|
||||||
val environment: KotlinCoreEnvironment
|
val environment: KotlinCoreEnvironment
|
||||||
val bindingContext: BindingContext
|
val bindingContext: BindingContext
|
||||||
|
|||||||
+1
-1
@@ -1,3 +1,3 @@
|
|||||||
package org.kotlinnative.translator.exceptions
|
package org.kotlinnative.translator.exceptions
|
||||||
|
|
||||||
class TranslationException : Exception()
|
class TranslationException : Exception()
|
||||||
|
|||||||
@@ -33,19 +33,24 @@ class LLVMBuilder {
|
|||||||
KtTokens.PLUS -> "add nsw i32"
|
KtTokens.PLUS -> "add nsw i32"
|
||||||
KtTokens.MINUS -> "sub nsw i32"
|
KtTokens.MINUS -> "sub nsw i32"
|
||||||
KtTokens.MUL -> "mul 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")
|
llvmCode.appendln("$newVar = $llvmOperator $firstOp, $secondOp")
|
||||||
return newVar
|
return newVar
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun clean() {
|
fun clean() {
|
||||||
llvmCode = StringBuilder()
|
llvmCode = StringBuilder()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun addAssignment(llvmVariable: LLVMVariable, rhs: LLVMNode) {
|
||||||
|
llvmCode.appendln("%$llvmVariable = $rhs")
|
||||||
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return llvmCode.toString()
|
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 org.kotlinnative.translator.llvm.types.LLVMType
|
||||||
import kotlin.reflect.KFunction0
|
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 {
|
fun generateExpression(builder: LLVMBuilder): LLVMVariable {
|
||||||
val newVar = builder.getNewVariable(variableType);
|
val newVar = builder.getNewVariable(variableType)
|
||||||
builder.addLLVMCode("%$newVar = $llvmCode");
|
builder.addLLVMCode("%$newVar = $llvmCode")
|
||||||
return newVar
|
return newVar
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,9 +2,10 @@ package org.kotlinnative.translator.llvm
|
|||||||
|
|
||||||
import org.kotlinnative.translator.llvm.types.LLVMType
|
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 {
|
override fun toString(): String {
|
||||||
return label
|
return label
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -5,9 +5,14 @@ import org.kotlinnative.translator.llvm.LLVMVariable
|
|||||||
|
|
||||||
|
|
||||||
class LLVMIntType() : LLVMType() {
|
class LLVMIntType() : LLVMType() {
|
||||||
|
|
||||||
override fun operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression {
|
override fun operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression {
|
||||||
//TODO switch by types: int + double = int
|
//TODO switch by types: int + double = int
|
||||||
return LLVMExpression(::LLVMIntType, "add nsw i32 $firstOp, $secondOp")
|
return LLVMExpression(::LLVMIntType, "add nsw i32 $firstOp, $secondOp")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return "i32"
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,14 @@
|
|||||||
package org.kotlinnative.translator.llvm.types;
|
package org.kotlinnative.translator.llvm.types;
|
||||||
|
|
||||||
|
import org.kotlinnative.translator.exceptions.TranslationException
|
||||||
import org.kotlinnative.translator.llvm.LLVMExpression
|
import org.kotlinnative.translator.llvm.LLVMExpression
|
||||||
import org.kotlinnative.translator.llvm.LLVMVariable
|
import org.kotlinnative.translator.llvm.LLVMVariable
|
||||||
|
|
||||||
abstract class LLVMType() {
|
abstract class LLVMType() {
|
||||||
abstract fun operatorPlus(result: LLVMVariable, firstOp: LLVMVariable, secondOp: LLVMVariable): LLVMExpression;
|
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 FunctionArgument(val type: String, val name: String)
|
||||||
|
|
||||||
data class KtType(val name: String)
|
data class FunctionDescriptor(val returnType: String, val argTypes: List<String>)
|
||||||
|
|
||||||
data class FunctionDescriptor(val returnType: KtType, val argTypes: List<KtType>)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user