[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
|
||||
|
||||
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.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsEmpty
|
||||
|
||||
+7
-2
@@ -5,10 +5,15 @@
|
||||
|
||||
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.js.backend.ast.*
|
||||
|
||||
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 {
|
||||
return JsExpressionStatement(transformIrFunctionToJsFunction(declaration))
|
||||
}
|
||||
@@ -16,9 +21,9 @@ class IrDeclarationToJsTransformer : BaseIrElementToJsNodeTransformer<JsStatemen
|
||||
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")
|
||||
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) {
|
||||
val parameter = function.scope.declareName(parameterName)
|
||||
|
||||
+50
-2
@@ -5,12 +5,60 @@
|
||||
|
||||
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.js.backend.ast.JsExpression
|
||||
import org.jetbrains.kotlin.js.backend.ast.JsStringLiteral
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
|
||||
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 {
|
||||
// TODO: support all cases
|
||||
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
|
||||
|
||||
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
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
|
||||
class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsStatement, Nothing?> {
|
||||
override fun visitBlockBody(body: IrBlockBody, data: Nothing?): JsStatement {
|
||||
@@ -22,7 +18,23 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
|
||||
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 {
|
||||
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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.ir.backend.js
|
||||
package org.jetbrains.kotlin.ir.backend.js.utils
|
||||
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
|
||||
@@ -9,5 +9,9 @@ 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/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) }
|
||||
|
||||
+4
-48
@@ -7383,18 +7383,7 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
||||
@TestMetadata("useVariableOfNameOfFunction.kt")
|
||||
public void testUseVariableOfNameOfFunction() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/expression/identifierClash/useVariableOfNameOfFunction.kt");
|
||||
if (KotlinTestUtils.RUN_IGNORED_TESTS_AS_REGULAR) {
|
||||
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.");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8618,18 +8607,7 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
||||
@TestMetadata("stringConstant.kt")
|
||||
public void testStringConstant() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/expression/stringClass/stringConstant.kt");
|
||||
if (KotlinTestUtils.RUN_IGNORED_TESTS_AS_REGULAR) {
|
||||
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.");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("stringInTemplate.kt")
|
||||
@@ -16617,18 +16595,7 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
||||
@TestMetadata("nestedPackageFunctionCalledFromOtherPackage.kt")
|
||||
public void testNestedPackageFunctionCalledFromOtherPackage() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/multiPackage/nestedPackageFunctionCalledFromOtherPackage.kt");
|
||||
if (KotlinTestUtils.RUN_IGNORED_TESTS_AS_REGULAR) {
|
||||
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.");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("packageVariableVisibleFromOtherPackage.kt")
|
||||
@@ -19177,18 +19144,7 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
|
||||
@TestMetadata("deeplyNestedPackageFunctionCalled.kt")
|
||||
public void testDeeplyNestedPackageFunctionCalled() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("js/js.translator/testData/box/package/deeplyNestedPackageFunctionCalled.kt");
|
||||
if (KotlinTestUtils.RUN_IGNORED_TESTS_AS_REGULAR) {
|
||||
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.");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("initializersOfNestedPackagesExecute.kt")
|
||||
|
||||
Reference in New Issue
Block a user