From 746eb4b93e940a696ffd81def03482465874452e Mon Sep 17 00:00:00 2001 From: Roman Artemev Date: Wed, 18 Apr 2018 22:43:15 +0300 Subject: [PATCH] Implement object class in JS BE --- .../IrElementToJsExpressionTransformer.kt | 13 ++++++++-- .../transformers/irToJs/JsClassGenerator.kt | 24 +++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt index 4fa543923b1..55c14613a1b 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt @@ -73,10 +73,19 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer { + if (expression.type.isUnit()) JsNullLiteral() + else { + val className = context.getNameForSymbol(expression.symbol) + val getInstanceName = className.ident + "_getInstance" + JsInvocation(JsNameRef(getInstanceName)) + } + } + else -> TODO() } + override fun visitSetField(expression: IrSetField, context: JsGenerationContext): JsExpression { val fieldName = context.getNameForSymbol(expression.symbol) val dest = JsNameRef(fieldName, expression.receiver?.accept(this, context)) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt index f53f7e0042f..db00af727b0 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsClassGenerator.kt @@ -53,9 +53,33 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo } classBlock.statements += generateClassMetadata() + irClass.onlyIf({ kind == ClassKind.OBJECT }) { classBlock.statements += maybeGenerateObjectInstance() } return classBlock } + private fun maybeGenerateObjectInstance(): List { + val instanceVarName = "${className.ident}_instance" + val getInstanceFunName = "${className.ident}_getInstance" + val jsVarNode = context.currentScope.declareName(instanceVarName) + val varStmt = JsVars(JsVars.JsVar(jsVarNode, JsNullLiteral())) + val function = generateGetInstanceFunction(jsVarNode, getInstanceFunName) + return listOf(varStmt, function.makeStmt()) + } + + private fun generateGetInstanceFunction(instanceVar: JsName, instanceFunName: String): JsFunction { + val functionBody = JsBlock() + val func = JsFunction(JsFunctionScope(context.currentScope, "getInstance for ${irClass.name} object"), functionBody, "getInstance") + func.name = context.currentScope.declareName(instanceFunName) + + functionBody.statements += JsIf( + JsBinaryOperation(JsBinaryOperator.REF_EQ, instanceVar.makeRef(), JsNullLiteral()), + jsAssignment(instanceVar.makeRef(), JsNew(classNameRef)).makeStmt() + ) + functionBody.statements += JsReturn(instanceVar.makeRef()) + + return func + } + private fun maybeGeneratePrimaryConstructor() { if (!irClass.declarations.any { it is IrConstructor }) { val func = JsFunction(JsFunctionScope(context.currentScope, "Ctor for ${irClass.name}"), JsBlock(), "Ctor for ${irClass.name}")