[JS IR BE] support more constructions:
* generate declaration for top level properties * basic support for calls * break * continue * throw * generate declaration for local vals and vars
This commit is contained in:
+1
-1
@@ -6,7 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.backend.js.TODO
|
import org.jetbrains.kotlin.ir.backend.js.utils.TODO
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrTypeAlias
|
import org.jetbrains.kotlin.ir.declarations.IrTypeAlias
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsEmpty
|
import org.jetbrains.kotlin.js.backend.ast.JsEmpty
|
||||||
|
|||||||
+7
-2
@@ -5,10 +5,15 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.js.backend.ast.*
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
|
|
||||||
class IrDeclarationToJsTransformer : BaseIrElementToJsNodeTransformer<JsStatement, Nothing?> {
|
class IrDeclarationToJsTransformer : BaseIrElementToJsNodeTransformer<JsStatement, Nothing?> {
|
||||||
|
override fun visitProperty(declaration: IrProperty, data: Nothing?): JsStatement {
|
||||||
|
return jsVar(declaration.name, declaration.backingField?.initializer?.expression)
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitSimpleFunction(declaration: IrSimpleFunction, data: Nothing?): JsStatement {
|
override fun visitSimpleFunction(declaration: IrSimpleFunction, data: Nothing?): JsStatement {
|
||||||
return JsExpressionStatement(transformIrFunctionToJsFunction(declaration))
|
return JsExpressionStatement(transformIrFunctionToJsFunction(declaration))
|
||||||
}
|
}
|
||||||
@@ -16,9 +21,9 @@ class IrDeclarationToJsTransformer : BaseIrElementToJsNodeTransformer<JsStatemen
|
|||||||
private fun transformIrFunctionToJsFunction(declaration: IrSimpleFunction): JsFunction {
|
private fun transformIrFunctionToJsFunction(declaration: IrSimpleFunction): JsFunction {
|
||||||
val funName = declaration.name.asString()
|
val funName = declaration.name.asString()
|
||||||
val body = declaration.body?.accept(IrElementToJsStatementTransformer(), null) as? JsBlock ?: JsBlock()
|
val body = declaration.body?.accept(IrElementToJsStatementTransformer(), null) as? JsBlock ?: JsBlock()
|
||||||
val function = JsFunction(JsFunctionScope(JsDynamicScope, "scope for $funName"), body, "function $funName")
|
val function = JsFunction(JsFunctionScope(dummyScope, "scope for $funName"), body, "function $funName")
|
||||||
|
|
||||||
function.name = JsDynamicScope.declareName(funName)
|
function.name = declaration.name.toJsName()
|
||||||
|
|
||||||
fun JsFunction.addParameter(parameterName: String) {
|
fun JsFunction.addParameter(parameterName: String) {
|
||||||
val parameter = function.scope.declareName(parameterName)
|
val parameter = function.scope.declareName(parameterName)
|
||||||
|
|||||||
+50
-2
@@ -5,12 +5,60 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.utils.isPrimary
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.utils.parameterCount
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
|
||||||
import org.jetbrains.kotlin.js.backend.ast.JsStringLiteral
|
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||||
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
|
|
||||||
class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsExpression, Nothing?> {
|
class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsExpression, Nothing?> {
|
||||||
|
override fun visitExpressionBody(body: IrExpressionBody, data: Nothing?): JsExpression {
|
||||||
|
return body.expression.accept(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
override fun <T> visitConst(expression: IrConst<T>, data: Nothing?): JsExpression {
|
override fun <T> visitConst(expression: IrConst<T>, data: Nothing?): JsExpression {
|
||||||
|
// TODO: support all cases
|
||||||
return JsStringLiteral(expression.value.toString())
|
return JsStringLiteral(expression.value.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitCall(expression: IrCall, data: Nothing?): JsExpression {
|
||||||
|
// TODO rewrite more accurately, right now it just copy-pasted and adopted from old version
|
||||||
|
// TODO support:
|
||||||
|
// * ir intrinsics
|
||||||
|
// * js be intrinsics
|
||||||
|
// * js function
|
||||||
|
// * getters and setters
|
||||||
|
// * binary and unary operations
|
||||||
|
|
||||||
|
val symbol = expression.symbol
|
||||||
|
|
||||||
|
val dispatchReceiver = expression.dispatchReceiver?.accept(this, data)
|
||||||
|
val extensionReceiver = expression.extensionReceiver?.accept(this, data)
|
||||||
|
|
||||||
|
// TODO sanitize name
|
||||||
|
val symbolName = (symbol.owner as IrSimpleFunction).name.asString()
|
||||||
|
val ref = if (dispatchReceiver != null) JsNameRef(symbolName, dispatchReceiver) else JsNameRef(symbolName)
|
||||||
|
|
||||||
|
val arguments =
|
||||||
|
// TODO mapTo?
|
||||||
|
(0 until expression.symbol.parameterCount).map {
|
||||||
|
val argument = expression.getValueArgument(it)
|
||||||
|
if (argument != null) {
|
||||||
|
argument.accept(this, data)
|
||||||
|
} else {
|
||||||
|
JsPrefixOperation(JsUnaryOperator.VOID, JsIntLiteral(1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (symbol is IrConstructorSymbol && symbol.isPrimary) {
|
||||||
|
return JsNew(JsNameRef((symbol.owner.parent as IrClass).name.asString()), arguments)
|
||||||
|
}
|
||||||
|
|
||||||
|
return JsInvocation(ref, extensionReceiver?.let { listOf(extensionReceiver) + arguments } ?: arguments)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+20
-8
@@ -5,13 +5,9 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
|
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrReturn
|
import org.jetbrains.kotlin.js.backend.ast.*
|
||||||
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 : BaseIrElementToJsNodeTransformer<JsStatement, Nothing?> {
|
class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsStatement, Nothing?> {
|
||||||
override fun visitBlockBody(body: IrBlockBody, data: Nothing?): JsStatement {
|
override fun visitBlockBody(body: IrBlockBody, data: Nothing?): JsStatement {
|
||||||
@@ -22,7 +18,23 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
|
|||||||
return JsExpressionStatement(expression.accept(IrElementToJsExpressionTransformer(), data))
|
return JsExpressionStatement(expression.accept(IrElementToJsExpressionTransformer(), data))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun visitBreak(jump: IrBreak, data: Nothing?): JsStatement {
|
||||||
|
return JsBreak(jump.label?.let(::JsNameRef))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitContinue(jump: IrContinue, data: Nothing?): JsStatement {
|
||||||
|
return JsContinue(jump.label?.let(::JsNameRef))
|
||||||
|
}
|
||||||
|
|
||||||
override fun visitReturn(expression: IrReturn, data: Nothing?): JsStatement {
|
override fun visitReturn(expression: IrReturn, data: Nothing?): JsStatement {
|
||||||
return JsReturn(expression.value.accept(IrElementToJsExpressionTransformer(), null))
|
return JsReturn(expression.value.accept(IrElementToJsExpressionTransformer(), data))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitThrow(expression: IrThrow, data: Nothing?): JsStatement {
|
||||||
|
return JsThrow(expression.value.accept(IrElementToJsExpressionTransformer(), data))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitVariable(declaration: IrVariable, data: Nothing?): JsStatement {
|
||||||
|
return jsVar(declaration.name, declaration.initializer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* 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.IrExpression
|
||||||
|
import org.jetbrains.kotlin.js.backend.ast.JsDynamicScope
|
||||||
|
import org.jetbrains.kotlin.js.backend.ast.JsVars
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
|
// TODO don't use JsDynamicScope
|
||||||
|
val dummyScope = JsDynamicScope
|
||||||
|
|
||||||
|
fun Name.toJsName() =
|
||||||
|
// TODO sanitize
|
||||||
|
dummyScope.declareName(asString())
|
||||||
|
|
||||||
|
fun jsVar(name: Name, initializer: IrExpression?): JsVars {
|
||||||
|
val jsInitializer = initializer?.accept(IrElementToJsExpressionTransformer(), null)
|
||||||
|
return JsVars(JsVars.JsVar(name.toJsName(), jsInitializer))
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* 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.utils
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
|
|
||||||
|
val IrFunctionSymbol.parameterCount get() = descriptor.valueParameters.size
|
||||||
|
|
||||||
|
val IrConstructorSymbol.isPrimary get() = descriptor.isPrimary
|
||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
* that can be found in the license/LICENSE.txt file.
|
* that can be found in the license/LICENSE.txt file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.ir.backend.js
|
package org.jetbrains.kotlin.ir.backend.js.utils
|
||||||
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
|
||||||
@@ -9,5 +9,9 @@ import java.io.File
|
|||||||
|
|
||||||
val JS_IR_BACKEND_TEST_WHITELIST = listOf(
|
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"
|
"js/js.translator/testData/box/package/deeplyNestedPackage.kt",
|
||||||
|
"js/js.translator/testData/box/package/deeplyNestedPackageFunctionCalled.kt",
|
||||||
|
"js/js.translator/testData/box/multiPackage/nestedPackageFunctionCalledFromOtherPackage.kt",
|
||||||
|
"js/js.translator/testData/box/expression/identifierClash/useVariableOfNameOfFunction.kt",
|
||||||
|
"js/js.translator/testData/box/expression/stringClass/stringConstant.kt"
|
||||||
).map { File(it) }
|
).map { File(it) }
|
||||||
|
|||||||
+4
-48
@@ -7383,18 +7383,7 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
|||||||
@TestMetadata("useVariableOfNameOfFunction.kt")
|
@TestMetadata("useVariableOfNameOfFunction.kt")
|
||||||
public void testUseVariableOfNameOfFunction() throws Exception {
|
public void testUseVariableOfNameOfFunction() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/expression/identifierClash/useVariableOfNameOfFunction.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/expression/identifierClash/useVariableOfNameOfFunction.kt");
|
||||||
if (KotlinTestUtils.RUN_IGNORED_TESTS_AS_REGULAR) {
|
doTest(fileName);
|
||||||
doTest(fileName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
doTest(fileName);
|
|
||||||
}
|
|
||||||
catch (Throwable ignore) {
|
|
||||||
ignore.printStackTrace();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive or add it to whitelist for that.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8618,18 +8607,7 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
|||||||
@TestMetadata("stringConstant.kt")
|
@TestMetadata("stringConstant.kt")
|
||||||
public void testStringConstant() throws Exception {
|
public void testStringConstant() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/expression/stringClass/stringConstant.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/expression/stringClass/stringConstant.kt");
|
||||||
if (KotlinTestUtils.RUN_IGNORED_TESTS_AS_REGULAR) {
|
doTest(fileName);
|
||||||
doTest(fileName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
doTest(fileName);
|
|
||||||
}
|
|
||||||
catch (Throwable ignore) {
|
|
||||||
ignore.printStackTrace();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive or add it to whitelist for that.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("stringInTemplate.kt")
|
@TestMetadata("stringInTemplate.kt")
|
||||||
@@ -16617,18 +16595,7 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
|||||||
@TestMetadata("nestedPackageFunctionCalledFromOtherPackage.kt")
|
@TestMetadata("nestedPackageFunctionCalledFromOtherPackage.kt")
|
||||||
public void testNestedPackageFunctionCalledFromOtherPackage() throws Exception {
|
public void testNestedPackageFunctionCalledFromOtherPackage() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/multiPackage/nestedPackageFunctionCalledFromOtherPackage.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/multiPackage/nestedPackageFunctionCalledFromOtherPackage.kt");
|
||||||
if (KotlinTestUtils.RUN_IGNORED_TESTS_AS_REGULAR) {
|
doTest(fileName);
|
||||||
doTest(fileName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
doTest(fileName);
|
|
||||||
}
|
|
||||||
catch (Throwable ignore) {
|
|
||||||
ignore.printStackTrace();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive or add it to whitelist for that.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("packageVariableVisibleFromOtherPackage.kt")
|
@TestMetadata("packageVariableVisibleFromOtherPackage.kt")
|
||||||
@@ -19177,18 +19144,7 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
|||||||
@TestMetadata("deeplyNestedPackageFunctionCalled.kt")
|
@TestMetadata("deeplyNestedPackageFunctionCalled.kt")
|
||||||
public void testDeeplyNestedPackageFunctionCalled() throws Exception {
|
public void testDeeplyNestedPackageFunctionCalled() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/package/deeplyNestedPackageFunctionCalled.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/package/deeplyNestedPackageFunctionCalled.kt");
|
||||||
if (KotlinTestUtils.RUN_IGNORED_TESTS_AS_REGULAR) {
|
doTest(fileName);
|
||||||
doTest(fileName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
doTest(fileName);
|
|
||||||
}
|
|
||||||
catch (Throwable ignore) {
|
|
||||||
ignore.printStackTrace();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
throw new AssertionError("Looks like this test can be unmuted. Remove IGNORE_BACKEND directive or add it to whitelist for that.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestMetadata("initializersOfNestedPackagesExecute.kt")
|
@TestMetadata("initializersOfNestedPackagesExecute.kt")
|
||||||
|
|||||||
Reference in New Issue
Block a user