[JS IR BE] basic compiler

This commit is contained in:
Zalim Bashorov
2018-03-14 20:24:02 +03:00
parent 4404c6dd2c
commit e0a070ff35
12 changed files with 202 additions and 16 deletions
@@ -0,0 +1,8 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.backend.js
class JsIrBackendContext
@@ -1,16 +1,33 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.backend.js
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleTransformer
import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
// Dummy compile function to work on the test infrastructure
fun compile(
files: List<KtFile>
project: Project,
files: List<KtFile>,
configuration: CompilerConfiguration,
export: FqName
): String {
if (files.none { it.name == "nestedPackage.kt" }) return ""
return "function box() { return \"OK\"; }"
}
val analysisResult = TopDownAnalyzerFacadeForJS.analyzeFiles(files, project, configuration, emptyList(), emptyList())
ProgressIndicatorAndCompilationCanceledStatus.checkCanceled()
TopDownAnalyzerFacadeForJS.checkForErrors(files, analysisResult.bindingContext)
val moduleFragment = Psi2IrTranslator().generateModule(analysisResult.moduleDescriptor, files, analysisResult.bindingContext)
val program = moduleFragment.accept(IrModuleTransformer(), null)
return program.toString()
}
@@ -0,0 +1,36 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.js.backend.ast.*
class IrDeclarationToJsTransformer : IrElementToJsNodeTransformer<JsStatement, Nothing?> {
override fun visitSimpleFunction(declaration: IrSimpleFunction, data: Nothing?): JsStatement {
return JsExpressionStatement(transformIrFunctionToJsFunction(declaration))
}
private fun transformIrFunctionToJsFunction(declaration: IrSimpleFunction): JsFunction {
val funName = declaration.name.asString()
val body = declaration.body?.accept(IrElementToJsStatementTransformer(), null) as? JsBlock ?: JsBlock()
val function = JsFunction(JsFunctionScope(JsDynamicScope, "scope for $funName"), body, "function $funName")
function.name = JsDynamicScope.declareName(funName)
fun JsFunction.addParameter(parameterName: String) {
val parameter = function.scope.declareName(parameterName)
parameters.add(JsParameter(parameter))
}
declaration.extensionReceiverParameter?.let { function.addParameter("\$receiver") }
declaration.valueParameters.forEach {
function.addParameter(it.name.asString())
}
return function
}
}
@@ -0,0 +1,16 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.ir.expressions.IrConst
import org.jetbrains.kotlin.js.backend.ast.JsExpression
import org.jetbrains.kotlin.js.backend.ast.JsStringLiteral
class IrElementToJsExpressionTransformer : IrElementToJsNodeTransformer<JsExpression, Nothing?> {
override fun <T> visitConst(expression: IrConst<T>, data: Nothing?): JsExpression {
return JsStringLiteral(expression.value.toString())
}
}
@@ -0,0 +1,24 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.backend.js.TODO
import org.jetbrains.kotlin.ir.declarations.IrTypeAlias
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
import org.jetbrains.kotlin.js.backend.ast.JsEmpty
import org.jetbrains.kotlin.js.backend.ast.JsNode
interface IrElementToJsNodeTransformer<out R : JsNode, in D> : IrElementVisitor<R, D> {
override fun visitElement(element: IrElement, data: D): R {
TODO(element)
}
override fun visitTypeAlias(declaration: IrTypeAlias, data: D): R {
@Suppress("UNCHECKED_CAST")
return JsEmpty as R
}
}
@@ -0,0 +1,28 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrReturn
import org.jetbrains.kotlin.js.backend.ast.JsBlock
import org.jetbrains.kotlin.js.backend.ast.JsExpressionStatement
import org.jetbrains.kotlin.js.backend.ast.JsReturn
import org.jetbrains.kotlin.js.backend.ast.JsStatement
class IrElementToJsStatementTransformer : IrElementToJsNodeTransformer<JsStatement, Nothing?> {
override fun visitBlockBody(body: IrBlockBody, data: Nothing?): JsStatement {
return JsBlock(body.statements.map { it.accept(this, data) })
}
override fun visitExpression(expression: IrExpression, data: Nothing?): JsStatement {
return JsExpressionStatement(expression.accept(IrElementToJsExpressionTransformer(), data))
}
override fun visitReturn(expression: IrReturn, data: Nothing?): JsStatement {
return JsReturn(expression.value.accept(IrElementToJsExpressionTransformer(), null))
}
}
@@ -0,0 +1,22 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.js.backend.ast.JsBlock
import org.jetbrains.kotlin.js.backend.ast.JsStatement
class IrFileTransformer : IrElementToJsNodeTransformer<JsStatement, Nothing?> {
override fun visitFile(declaration: IrFile, data: Nothing?): JsStatement {
val block = JsBlock()
declaration.declarations.forEach {
block.statements.add(it.accept(IrDeclarationToJsTransformer(), null))
}
return block
}
}
@@ -0,0 +1,22 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.js.backend.ast.JsNode
import org.jetbrains.kotlin.js.backend.ast.JsProgram
class IrModuleTransformer : IrElementToJsNodeTransformer<JsNode, Nothing?> {
override fun visitModuleFragment(declaration: IrModuleFragment, data: Nothing?): JsNode {
val program = JsProgram()
declaration.files.forEach {
program.globalBlock.statements.add(it.accept(IrFileTransformer(), null))
}
return program
}
}
@@ -0,0 +1,10 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.ir.backend.js
import org.jetbrains.kotlin.ir.IrElement
fun TODO(element: IrElement): Nothing = TODO(element::class.java.simpleName + " is not supported yet here")
@@ -8,5 +8,6 @@ package org.jetbrains.kotlin.test
import java.io.File
val JS_IR_BACKEND_TEST_WHITELIST = listOf(
"js/js.translator/testData/box/package/nestedPackage.kt"
"js/js.translator/testData/box/package/nestedPackage.kt",
"js/js.translator/testData/box/package/deeplyNestedPackage.kt"
).map { File(it) }
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.ir.backend.js.compile
import org.jetbrains.kotlin.js.config.JsConfig
import org.jetbrains.kotlin.js.facade.MainCallParameters
import org.jetbrains.kotlin.js.facade.TranslationUnit
import org.jetbrains.kotlin.name.FqName
import java.io.File
abstract class BasicIrBoxTest(
@@ -33,7 +34,14 @@ abstract class BasicIrBoxTest(
testPackage: String?,
testFunction: String
) {
val code = compile(units.map { (it as TranslationUnit.SourceFile).file })
val code = compile(
config.project,
units.map { (it as TranslationUnit.SourceFile).file }
// TODO: temporary ignore _commonFiles/asserts.kt since it depends on stdlib but we don't have any library support in JS IR BE yet
// and probably it will be better to avoid using stdlib in testData as much as possible.
.filter { !it.virtualFilePath.endsWith("js/js.translator/testData/_commonFiles/asserts.kt") },
config.configuration,
FqName((testPackage?.let { it + "." } ?: "") + testFunction))
outputFile.parentFile.mkdirs()
outputFile.writeText(code)
@@ -13731,13 +13731,7 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
@TestMetadata("deeplyNestedPackage.kt")
public void testDeeplyNestedPackage() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/package/deeplyNestedPackage.kt");
try {
doTest(fileName);
}
catch (Throwable ignore) {
return;
}
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive or add it to white list for that.");
doTest(fileName);
}
@TestMetadata("deeplyNestedPackageFunctionCalled.kt")