Implement object class in JS BE

This commit is contained in:
Roman Artemev
2018-04-18 22:43:15 +03:00
parent 17ee38a0b7
commit 746eb4b93e
2 changed files with 35 additions and 2 deletions
@@ -73,10 +73,19 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
override fun visitGetValue(expression: IrGetValue, context: JsGenerationContext): JsExpression =
context.getNameForSymbol(expression.symbol).makeRef()
override fun visitGetObjectValue(expression: IrGetObjectValue, data: JsGenerationContext): JsExpression {
TODO()
override fun visitGetObjectValue(expression: IrGetObjectValue, context: JsGenerationContext) = when (expression.symbol.kind) {
ClassKind.OBJECT -> {
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))
@@ -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<JsStatement> {
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}")