Translator: cleanup, add simple structure, function declarations

generation
This commit is contained in:
e5l
2016-07-08 17:08:14 +03:00
parent 498b4423af
commit 5ba772fff9
26 changed files with 285 additions and 175 deletions
+3 -3
View File
@@ -1,14 +1,14 @@
.DS_Store
.idea/shelf
/dependencies
/dist
dependencies
dist
out
tmp
workspace.xml
*.versionsBackup
.gradle
/build/
build
# Ignore Gradle GUI config
gradle-app.setting
+1
View File
@@ -0,0 +1 @@
ast-kotlin
+1 -1
View File
@@ -3,7 +3,6 @@
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="createEmptyContentRootDirectories" value="true" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleJvm" value="1.8" />
@@ -12,6 +11,7 @@
<option value="$PROJECT_DIR$" />
</set>
</option>
<option name="useAutoImport" value="true" />
</GradleProjectSettings>
</option>
</component>
+2 -2
View File
@@ -13,8 +13,8 @@
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="masterDetails">
<states>
Binary file not shown.
Binary file not shown.
-14
View File
@@ -1,14 +0,0 @@
package hello
class llvmBuilder{
private val llvmCode : StringBuilder = StringBuilder()
class llvmBuilder constructor() {}
fun addLlvmCode(code : String){
llvmCode.appendln(code)
}
override fun toString(): String {
return llvmCode.toString()
}
}
@@ -1,3 +0,0 @@
package hello
data class llvmVariable(val label : String)
+15 -144
View File
@@ -1,152 +1,23 @@
package hello
import com.intellij.openapi.util.Disposer
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiWhiteSpace
import com.intellij.psi.impl.source.tree.LeafPsiElement
import com.intellij.psi.impl.source.tree.TreeElement
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.KtNodeType
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.messages.*
import org.jetbrains.kotlin.cli.jvm.compiler.*
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
import org.jetbrains.kotlin.cli.jvm.config.getModuleName
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider
import org.jetbrains.kotlin.frontend.java.di.createContainerForTopDownAnalyzerForJvm
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.psi.KtBlockExpression
import org.jetbrains.kotlin.resolve. AnalyzingUtils
import org.jetbrains.kotlin.resolve.TopDownAnalysisContext
import org.jetbrains.kotlin.resolve.TopDownAnalysisMode
import org.jetbrains.kotlin.resolve.jvm.JvmAnalyzerFacade
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM
import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory
import org.jetbrains.kotlin.utils.PathUtil
import org.jetbrains.kotlin.cli.jvm.compiler.*
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.lexer.KtKeywordToken
import org.jetbrains.kotlin.lexer.KtSingleValueToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtConstantExpression
import org.jetbrains.kotlin.psi.KtReturnExpression
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
import org.jetbrains.kotlin.psi.psiUtil.getNextSiblingIgnoringWhitespaceAndComments
import org.kotlin.native.translator.debug.debugPrintNode
import org.jetbrains.kotlin.lexer.KtToken
import java.lang.StringBuilder
import java.io.File
import java.util.*
import java.util.logging.Logger
var llvmCode = llvmBuilder()
fun expressionWalker(expr : Any?) {
when(expr){
is KtBlockExpression -> evaluateBlockExpression(expr)
is PsiElement -> evaluatePsiExpression(expr)
null -> Unit
else -> UnsupportedOperationException()
}
}
fun evaluateBlockExpression(expr : KtBlockExpression){
var element = expr
expressionWalker(element.firstChild)
expressionWalker(element.getNextSiblingIgnoringWhitespaceAndComments())
}
var variableCount = 0
fun evaluatePsiExpression(expr : PsiElement){
var element = expr
evaluateExpression(element.firstChild)
evaluatePsiExpression(element.getNextSiblingIgnoringWhitespaceAndComments() ?: return)
}
fun evaluateExpression(expr: Any?) : llvmVariable?{
return when(expr){
is KtBinaryExpression -> evaluateBinaryExpression(expr)
is PsiWhiteSpace -> null
is PsiElement -> evaluatePsiElement(expr)
is KtConstantExpression -> evaluateConstantExpression(expr)
null -> null
else -> throw UnsupportedOperationException()
}
}
fun evaluateBinaryExpression(expr : KtBinaryExpression) : llvmVariable{
val left = evaluateExpression(expr.firstChild)
val right = evaluateExpression(expr.lastChild)
val operator = expr.operationToken
val llvmOperator = when (operator) {
KtTokens.PLUS -> "add nsw i32"
KtTokens.MINUS -> "sub nsw i32"
KtTokens.MUL -> "mul nsw i32"
else -> throw UnsupportedOperationException("Unkbown binary operator")
}
variableCount++
llvmCode.addLlvmCode("%var$variableCount = $llvmOperator ${left?.label}, ${right?.label}")
return llvmVariable("%var$variableCount")
}
fun evaluateConstantExpression(expr : KtConstantExpression) : llvmVariable {
val node = expr.node
return llvmVariable(node.firstChildNode.text)
}
fun evaluatePsiElement(element : PsiElement) : llvmVariable? {
return when(element){
is LeafPsiElement -> evaluateLeafPsiElement(element)
is KtConstantExpression -> evaluateConstantExpression(element)
KtTokens.INTEGER_LITERAL -> null
else -> null
}
}
fun evaluateLeafPsiElement(element : LeafPsiElement) : llvmVariable? {
return when(element.elementType){
KtTokens.RETURN_KEYWORD -> evaluateReturnInstruction(element)
else -> llvmVariable("")
}
}
fun evaluateReturnInstruction(element : LeafPsiElement) : llvmVariable?{
var next = element.getNextSiblingIgnoringWhitespaceAndComments();
val retVar = evaluateExpression(next)
llvmCode.addLlvmCode("ret i32 ${retVar?.label}")
return null
}
import org.kotlinnative.translator.FileTranslator
import org.kotlinnative.translator.TranslationState
fun main(args: Array<String>) {
val scriptFile = "/home/user/Kotlin/manual/sum.kt"
val parser = KotlinScriptParser()
if (args.isEmpty()) {
println("Enter filename")
return
}
val analyzeContext = parser.parse(scriptFile)
val disposer = Disposer.newDisposable()
val state = TranslationState(args.asList(), disposer)
val function = analyzeContext.functions.keys.first()
var body = function.bodyExpression as KtBlockExpression
val files = state.environment.getSourceFiles()
if (files.isEmpty()) {
print("Empty")
return
}
llvmCode.addLlvmCode("define i32 @${function.fqName}() #0{")
println(FileTranslator(state, files[0]).generateCode())
}
expressionWalker(body);
llvmCode.addLlvmCode("}")
println(llvmCode)
}
@@ -0,0 +1,32 @@
package org.kotlinnative.translator
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.resolve.BindingContext
import org.kotlin.native.translator.llvm.LLVMBuilder
import org.kotlinnative.translator.llvm.LLVMDescriptorGenearte
import org.kotlinnative.translator.llvm.LLVMMapStandardType
class FileTranslator(val state: TranslationState, val file: KtFile) {
private var codeBuilder = LLVMBuilder()
private var compiled = false;
fun generateCode(): String {
if (!compiled) {
generateFileBody()
}
compiled = true
return codeBuilder.toString()
}
private fun generateFileBody() {
for (declaration in file.declarations) {
when (declaration) {
is KtNamedFunction -> FunctionCodegen(state, declaration, codeBuilder).generate()
}
}
}
}
@@ -0,0 +1,122 @@
package org.kotlinnative.translator
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.psiUtil.getNextSiblingIgnoringWhitespaceAndComments
import org.jetbrains.kotlin.resolve.BindingContext
import org.kotlin.native.translator.llvm.LLVMBuilder
import org.kotlin.native.translator.llvm.LLVMVariable
import org.kotlinnative.translator.llvm.LLVMDescriptorGenearte
import org.kotlinnative.translator.llvm.LLVMMapStandardType
class FunctionCodegen(val state: TranslationState, val function: KtNamedFunction, val codeBuilder: LLVMBuilder) {
private var variableCount = 0
fun generate() {
generateDeclaration(function)
codeBuilder.addLlvmCode("{")
expressionWalker(function.bodyExpression)
codeBuilder.addLlvmCode("}")
}
private fun generateDeclaration(function: KtNamedFunction) {
val descriptor = state.bindingContext.get(BindingContext.FUNCTION, function)
var args = descriptor?.valueParameters?.map {
Pair(it.name.toString(), LLVMMapStandardType(it.type.toString()))
}
val returnType = LLVMMapStandardType(descriptor?.returnType.toString())
codeBuilder.addLlvmCode(LLVMDescriptorGenearte(function.fqName.toString(), args, returnType))
}
private fun expressionWalker(expr: Any?) {
when (expr) {
is KtBlockExpression -> evaluateBlockExpression(expr)
is PsiElement -> evaluatePsiExpression(expr)
null -> Unit
else -> UnsupportedOperationException()
}
}
private fun evaluateBlockExpression(expr: KtBlockExpression) {
var element = expr
expressionWalker(element.firstChild)
expressionWalker(element.getNextSiblingIgnoringWhitespaceAndComments())
}
private fun evaluatePsiExpression(expr: PsiElement) {
var element = expr
evaluateExpression(element.firstChild)
evaluatePsiExpression(element.getNextSiblingIgnoringWhitespaceAndComments() ?: return)
}
private fun evaluateExpression(expr: Any?): LLVMVariable? {
return when (expr) {
is KtBinaryExpression -> evaluateBinaryExpression(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)
val right = evaluateExpression(expr.lastChild)
val operator = expr.operationToken
val llvmOperator = when (operator) {
KtTokens.PLUS -> "add nsw i32"
KtTokens.MINUS -> "sub nsw i32"
KtTokens.MUL -> "mul nsw i32"
else -> throw UnsupportedOperationException("Unkbown binary operator")
}
variableCount++
codeBuilder.addLlvmCode("%var$variableCount = $llvmOperator ${left?.label}, ${right?.label}")
return LLVMVariable("%var$variableCount")
}
private fun evaluateConstantExpression(expr: KtConstantExpression): LLVMVariable {
val node = expr.node
return LLVMVariable(node.firstChildNode.text)
}
private fun evaluatePsiElement(element: PsiElement): LLVMVariable? {
return when (element) {
is LeafPsiElement -> evaluateLeafPsiElement(element)
is KtConstantExpression -> evaluateConstantExpression(element)
KtTokens.INTEGER_LITERAL -> null
else -> null
}
}
private fun evaluateLeafPsiElement(element: LeafPsiElement): LLVMVariable? {
return when (element.elementType) {
KtTokens.RETURN_KEYWORD -> evaluateReturnInstruction(element)
else -> LLVMVariable("")
}
}
private fun evaluateReturnInstruction(element: LeafPsiElement): LLVMVariable? {
var next = element.getNextSiblingIgnoringWhitespaceAndComments();
val retVar = evaluateExpression(next)
codeBuilder.addLlvmCode("ret i32 ${retVar?.label}")
return null
}
}
@@ -29,11 +29,7 @@ import org.jetbrains.kotlin.utils.PathUtil
import java.io.File
import java.util.*
import java.util.logging.Logger
import org.kotlin.native.translator.debug.*
/**
* Created by user on 7/8/16.
*/
class KotlinScriptParser {
companion object {
private val LOG = Logger.getLogger(KotlinScriptParser.javaClass.name)
@@ -0,0 +1,80 @@
package org.kotlinnative.translator
import com.intellij.openapi.Disposable
import org.jetbrains.kotlin.analyzer.AnalysisResult
import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys
import org.jetbrains.kotlin.cli.common.messages.*
import org.jetbrains.kotlin.cli.jvm.compiler.CliLightClassGenerationSupport
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.JvmPackagePartProvider
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.config.getModuleName
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.addKotlinSourceRoots
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM
import org.jetbrains.kotlin.utils.PathUtil
import org.kotlinnative.translator.exceptions.TranslationException
class TranslationState(sources: List<String>, disposer: Disposable) {
val environment: KotlinCoreEnvironment
val bindingContext: BindingContext
init {
val configuration = CompilerConfiguration()
val messageCollector = GroupingMessageCollector(object : MessageCollector {
private var hasError = false
override fun hasErrors(): Boolean {
return hasError;
}
override fun report(severity: CompilerMessageSeverity, message: String, location: CompilerMessageLocation) {
println("[report] $message")
hasError = severity.isError || hasError
}
})
configuration.put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, messageCollector)
configuration.put(JVMConfigurationKeys.MODULE_NAME, JvmAbi.DEFAULT_MODULE_NAME)
configuration.addKotlinSourceRoots(sources)
environment = KotlinCoreEnvironment.createForProduction(disposer, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
bindingContext = analyze(environment)?.bindingContext ?: throw TranslationException()
}
fun analyze(environment: KotlinCoreEnvironment): AnalysisResult? {
val collector = environment.configuration.getNotNull(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)
val analyzer = AnalyzerWithCompilerReport(collector)
analyzer.analyzeAndReport(environment.getSourceFiles(), object : AnalyzerWithCompilerReport.Analyzer {
override fun analyze(): AnalysisResult {
val sharedTrace = CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace()
val moduleContext = TopDownAnalyzerFacadeForJVM.createContextWithSealedModule(environment.project, environment.getModuleName())
return TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegrationWithCustomContext(
moduleContext,
environment.getSourceFiles(),
sharedTrace,
environment.configuration.get(JVMConfigurationKeys.MODULES),
environment.configuration.get(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS),
JvmPackagePartProvider(environment))
}
override fun reportEnvironmentErrors() {
var files = environment.configuration.jvmClasspathRoots
var runtimes = files.map { it.canonicalFile }.filter { it.name == PathUtil.KOTLIN_JAVA_RUNTIME_JAR && it.exists() }
collector.report(CompilerMessageSeverity.ERROR, runtimes.joinToString { it.path }, CompilerMessageLocation.NO_LOCATION)
println(runtimes.joinToString { it.toString() })
}
});
return if (analyzer.hasErrors()) null else analyzer.analysisResult
}
}
@@ -1,7 +1,4 @@
/**
* Created by user on 7/8/16.
*/
package org.kotlin.native.translator.debug
package org.kotlinnative.translator.debug
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiWhiteSpace
@@ -0,0 +1,3 @@
package org.kotlinnative.translator.exceptions
class TranslationException : Exception()
@@ -0,0 +1,13 @@
package org.kotlin.native.translator.llvm
class LLVMBuilder {
private val llvmCode: StringBuilder = StringBuilder()
fun addLlvmCode(code: String) {
llvmCode.appendln(code)
}
override fun toString(): String {
return llvmCode.toString()
}
}
@@ -0,0 +1,3 @@
package org.kotlin.native.translator.llvm
data class LLVMVariable(val label: String)
@@ -0,0 +1,9 @@
package org.kotlinnative.translator.llvm
fun LLVMDescriptorGenearte(name: String, argTypes: List<Pair<String, String>>?, returnType: String) =
"define $returnType @$name(${argTypes?.mapIndexed { i: Int, s: Pair<String, String> -> "${s.second} %${s.first}" }?.joinToString() ?: "" })"
fun LLVMMapStandardType(type: String) = when(type) {
"Int" -> "i32"
else -> "%$type*"
}