From 997328f584354e1dbe9a1f6950ca05a5bca9b254 Mon Sep 17 00:00:00 2001 From: Roman Artemev Date: Wed, 18 Apr 2018 22:48:27 +0300 Subject: [PATCH] Refactoring and fixes --- .../ir/backend/js/DeclarationOrigins.kt | 2 - .../IrElementToJsExpressionTransformer.kt | 9 +- .../irToJs/IrFileToJsTransformer.kt | 2 +- .../irToJs/JsIntrinsicTransformers.kt | 7 +- .../js/transformers/irToJs/jsAstUtils.kt | 8 -- .../backend/js/utils/JsGenerationContext.kt | 16 ++- .../ir/backend/js/utils/JsStaticContext.kt | 4 +- .../ir/backend/js/utils/NameGenerator.kt | 3 +- .../backend/js/utils/SimpleNameGenerator.kt | 109 +++++++++--------- .../box/closure/closureLocalFunction.kt | 49 +------- 10 files changed, 83 insertions(+), 126 deletions(-) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/DeclarationOrigins.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/DeclarationOrigins.kt index e85fffd82c1..8c79d980d8f 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/DeclarationOrigins.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/DeclarationOrigins.kt @@ -11,8 +11,6 @@ import org.jetbrains.kotlin.ir.expressions.IrStatementOriginImpl object JsLoweredDeclarationOrigin : IrDeclarationOrigin { object CLASS_STATIC_INITIALIZER : IrDeclarationOriginImpl("CLASS_STATIC_INITIALIZER") - object SECONDARY_CTOR_RECEIVER : IrDeclarationOriginImpl("SECONDARY_CTOR_RECEIVER") object JS_INTRINSICS_STUB : IrDeclarationOriginImpl("JS_INTRINSICS_STUB") object JS_CLOSURE_BOX_CLASS : IrStatementOriginImpl("JS_CLOSURE_BOX_CLASS") - object JS_LAMBDA_CREATION : IrDeclarationOriginImpl("JS_LAMBDA_CREATION") } \ No newline at end of file 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 55c14613a1b..72044e586be 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 @@ -6,14 +6,17 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype +import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext import org.jetbrains.kotlin.ir.backend.js.utils.Namer +import org.jetbrains.kotlin.ir.backend.js.utils.kind import org.jetbrains.kotlin.ir.backend.js.utils.name import org.jetbrains.kotlin.ir.declarations.IrConstructor import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.js.backend.ast.* +import org.jetbrains.kotlin.types.typeUtil.isUnit import org.jetbrains.kotlin.util.OperatorNameConventions class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer { @@ -35,7 +38,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer visitConst(expression: IrConst, context: JsGenerationContext): JsExpression { @@ -125,10 +128,6 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer { override fun visitFile(declaration: IrFile, context: JsGenerationContext): JsStatement { - val fileContext = context.newDeclaration(JsDeclarationScope(context.currentScope, "scope for file ${declaration.name}")) + val fileContext = context.newDeclaration(JsDeclarationScope(context.currentScope, "scope for file ${declaration.name}"), null, declaration) val block = fileContext.currentBlock declaration.declarations.forEach { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt index a44f72be410..2e605fe3efa 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsIntrinsicTransformers.kt @@ -5,12 +5,14 @@ package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs +import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext import org.jetbrains.kotlin.ir.backend.js.utils.Namer import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.symbols.IrSymbol +import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl import org.jetbrains.kotlin.js.backend.ast.* typealias IrCallTransformer = (IrCall, context: JsGenerationContext) -> JsExpression @@ -61,9 +63,10 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) { binOp(intrinsics.jsInstanceOf, JsBinaryOperator.INSTANCEOF) - add(intrinsics.jsObjectCreate) { call, _ -> + add(intrinsics.jsObjectCreate) { call, context -> val classToCreate = call.getTypeArgument(0)!! - val prototype = prototypeOf(classToCreate.constructor.declarationDescriptor!!.name.toJsName().makeRef()) + val className = context.getNameForSymbol(IrClassSymbolImpl(classToCreate.constructor.declarationDescriptor as ClassDescriptor)) + val prototype = prototypeOf(className.makeRef()) JsInvocation(Namer.JS_OBJECT_CREATE_FUNCTION, prototype) } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/jsAstUtils.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/jsAstUtils.kt index f4c068e9c73..05551e9d7db 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/jsAstUtils.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/jsAstUtils.kt @@ -10,14 +10,6 @@ import org.jetbrains.kotlin.ir.backend.js.utils.Namer import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.js.backend.ast.* -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: JsName, initializer: IrExpression?, context: JsGenerationContext): JsVars { val jsInitializer = initializer?.accept(IrElementToJsExpressionTransformer(), context) diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsGenerationContext.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsGenerationContext.kt index 49e14092f90..53e341b0ddd 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsGenerationContext.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsGenerationContext.kt @@ -5,18 +5,21 @@ package org.jetbrains.kotlin.ir.backend.js.utils +import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext +import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.js.backend.ast.* class JsGenerationContext { - fun newDeclaration(scope: JsScope, func: IrFunction? = null): JsGenerationContext { - return JsGenerationContext(this, JsBlock(), scope, func) + fun newDeclaration(scope: JsScope, func: IrFunction? = null, file: IrFile? = null): JsGenerationContext { + return JsGenerationContext(this, JsBlock(), scope, func, file) } val currentBlock: JsBlock val currentScope: JsScope + val currentFile: IrFile? val currentFunction: IrFunction? val parent: JsGenerationContext? val staticContext: JsStaticContext @@ -30,16 +33,21 @@ class JsGenerationContext { this.currentScope = rootScope this.currentBlock = program.globalBlock this.currentFunction = null + this.currentFile = null } - constructor(parent: JsGenerationContext, block: JsBlock, scope: JsScope, func: IrFunction?) { + constructor(parent: JsGenerationContext, block: JsBlock, scope: JsScope, func: IrFunction?, file: IrFile? = null) { this.parent = parent this.program = parent.program this.staticContext = parent.staticContext this.currentBlock = block this.currentScope = scope this.currentFunction = func + this.currentFile = file ?: parent.currentFile } - fun getNameForSymbol(symbol: IrSymbol): JsName = staticContext.getNameForSymbol(symbol) + fun getNameForSymbol(symbol: IrSymbol): JsName = staticContext.getNameForSymbol(symbol, this) + + val currentPackage: PackageFragmentDescriptor + get() = currentFile!!.packageFragmentDescriptor } \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsStaticContext.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsStaticContext.kt index 12572630681..4173b6c7615 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsStaticContext.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/JsStaticContext.kt @@ -8,10 +8,8 @@ package org.jetbrains.kotlin.ir.backend.js.utils import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.JsIntrinsicTransformers import org.jetbrains.kotlin.ir.symbols.IrSymbol -import org.jetbrains.kotlin.js.backend.ast.JsExpression import org.jetbrains.kotlin.js.backend.ast.JsGlobalBlock import org.jetbrains.kotlin.js.backend.ast.JsRootScope -import org.jetbrains.kotlin.name.Name class JsStaticContext( @@ -22,5 +20,5 @@ class JsStaticContext( ) { val intrinsics = JsIntrinsicTransformers(backendContext) - fun getNameForSymbol(irSymbol: IrSymbol) = nameGenerator.getNameForSymbol(irSymbol, rootScope) + fun getNameForSymbol(irSymbol: IrSymbol, context: JsGenerationContext) = nameGenerator.getNameForSymbol(irSymbol, context) } \ No newline at end of file diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameGenerator.kt index 382f49042e5..d7190f6f5f5 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/NameGenerator.kt @@ -7,8 +7,7 @@ package org.jetbrains.kotlin.ir.backend.js.utils import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.js.backend.ast.JsName -import org.jetbrains.kotlin.js.backend.ast.JsScope interface NameGenerator { - fun getNameForSymbol(symbol: IrSymbol, scope: JsScope): JsName + fun getNameForSymbol(symbol: IrSymbol, context: JsGenerationContext): JsName } diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt index e5647df92e7..0f2000a528b 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/utils/SimpleNameGenerator.kt @@ -9,9 +9,9 @@ import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor import org.jetbrains.kotlin.ir.symbols.IrSymbol import org.jetbrains.kotlin.js.backend.ast.JsName -import org.jetbrains.kotlin.js.backend.ast.JsScope import org.jetbrains.kotlin.js.naming.isES5IdentifierPart import org.jetbrains.kotlin.js.naming.isES5IdentifierStart +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver @@ -19,67 +19,68 @@ class SimpleNameGenerator : NameGenerator { private val nameCache = mutableMapOf() - override fun getNameForSymbol(symbol: IrSymbol, scope: JsScope): JsName = getNameForDescriptor(symbol.descriptor, scope) + override fun getNameForSymbol(symbol: IrSymbol, context: JsGenerationContext): JsName = getNameForDescriptor(symbol.descriptor, context) - private fun getNameForDescriptor(descriptor: DeclarationDescriptor, scope: JsScope): JsName = nameCache.getOrPut(descriptor, { - val nameBuilder = StringBuilder() - when (descriptor) { - is ReceiverParameterDescriptor -> { - when (descriptor.value) { - is ExtensionReceiver -> nameBuilder.append(Namer.EXTENSION_RECEIVER_NAME) - is ImplicitClassReceiver -> nameBuilder.append(Namer.IMPLICIT_RECEIVER_NAME) - else -> TODO("name for $descriptor") - } - } - is ValueParameterDescriptor -> { - if (descriptor.name.isSpecial) { - // TODO: consider this case more carefully - nameBuilder.append(Namer.IMPLICIT_RECEIVER_NAME) - nameBuilder.append('_') - nameBuilder.append(descriptor.index) - } else { - val declaredName = descriptor.name.identifier - nameBuilder.append(declaredName) - if (declaredName.startsWith("\$")) { - nameBuilder.append('_') - nameBuilder.append(descriptor.index) + private fun getNameForDescriptor(descriptor: DeclarationDescriptor, context: JsGenerationContext): JsName = + nameCache.getOrPut(descriptor) { + val nameBuilder = StringBuilder() + when (descriptor) { + is ReceiverParameterDescriptor -> { + when (descriptor.value) { + is ExtensionReceiver -> nameBuilder.append(Namer.EXTENSION_RECEIVER_NAME) + is ImplicitClassReceiver -> nameBuilder.append(Namer.IMPLICIT_RECEIVER_NAME) + else -> TODO("name for $descriptor") } } - } - is PropertyDescriptor -> { - nameBuilder.append(descriptor.name.identifier) - } - is PropertyAccessorDescriptor -> { - when (descriptor) { - is PropertyGetterDescriptor -> nameBuilder.append(Namer.GETTER_PREFIX) - is PropertySetterDescriptor -> nameBuilder.append(Namer.SETTER_PREFIX) + is ValueParameterDescriptor -> { + if (descriptor.name.isSpecial) { + // TODO: consider this case more carefully + nameBuilder.append(Namer.IMPLICIT_RECEIVER_NAME) + nameBuilder.append('_') + nameBuilder.append(descriptor.index) + } else { + val declaredName = descriptor.name.identifier + nameBuilder.append(declaredName) + if (declaredName.startsWith("\$")) { + nameBuilder.append('_') + nameBuilder.append(descriptor.index) + } + } } - nameBuilder.append(descriptor.correspondingProperty.name.asString()) - } - is ClassDescriptor -> { - if (descriptor.name.isSpecial) { - nameBuilder.append(descriptor.name.asString().let { - it.substring(1, it.length - 1) + "${descriptor.hashCode()}" - }) - } else { + is PropertyDescriptor -> { nameBuilder.append(descriptor.name.identifier) } - } - is ConstructorDescriptor -> { - nameBuilder.append(getNameForDescriptor(descriptor.constructedClass, scope)) - } - is LocalVariableDescriptor -> { - nameBuilder.append(descriptor.name.identifier) - } - is CallableDescriptor -> { - nameBuilder.append(descriptor.name.asString()) - descriptor.typeParameters.forEach { nameBuilder.append("_${it.name.asString()}") } - descriptor.valueParameters.forEach { nameBuilder.append("_${it.type}") } - } + is PropertyAccessorDescriptor -> { + when (descriptor) { + is PropertyGetterDescriptor -> nameBuilder.append(Namer.GETTER_PREFIX) + is PropertySetterDescriptor -> nameBuilder.append(Namer.SETTER_PREFIX) + } + nameBuilder.append(descriptor.correspondingProperty.name.asString()) + } + is ClassDescriptor -> { + if (descriptor.name.isSpecial) { + nameBuilder.append(descriptor.name.asString().let { + it.substring(1, it.length - 1) + "${descriptor.hashCode()}" + }) + } else { + nameBuilder.append(descriptor.fqNameSafe.asString().replace('.', '$')) + } + } + is ConstructorDescriptor -> { + nameBuilder.append(getNameForDescriptor(descriptor.constructedClass, context)) + } + is LocalVariableDescriptor -> { + nameBuilder.append(descriptor.name.identifier) + } + is CallableDescriptor -> { + nameBuilder.append(descriptor.name.asString()) + descriptor.typeParameters.forEach { nameBuilder.append("_${it.name.asString()}") } + descriptor.valueParameters.forEach { nameBuilder.append("_${it.type}") } + } + } + context.currentScope.declareName(sanitizeName(nameBuilder.toString())) } - scope.declareName(sanitizeName(nameBuilder.toString())) - }) private fun sanitizeName(name: String): String { if (name.isEmpty()) return "_" diff --git a/js/js.translator/testData/box/closure/closureLocalFunction.kt b/js/js.translator/testData/box/closure/closureLocalFunction.kt index f574790a3cf..c96cefee30f 100644 --- a/js/js.translator/testData/box/closure/closureLocalFunction.kt +++ b/js/js.translator/testData/box/closure/closureLocalFunction.kt @@ -2,54 +2,13 @@ // EXPECTED_REACHABLE_NODES: 1113 package foo - -class closureBox(var v: T) - - - -//fun run(r: () -> Any) = r() - -fun wrapper(t1:T1, t2:T2, i1:Int, block: (t1:T1, t2:T2, i1:Int) -> T3): T3 { - val f = { tt1:T1, tt2:T2, ii:Int -> block(tt1, tt2, ii) } - return f(t1, t2, i1) -} - -fun test(ii: Int, jj: Int, kk: Int): String { - - var i = ii - var j = jj - val k = kk - var ggg: Int - +fun test(): String { fun f(): String = "OK" -// fun f() {} - val funVal = { - k - } - -// run(funVal) - - val funLit = { x:Int, l:Int, a:Int, b:Int, c:Int, d:Int, g:Int -> i += 1 - j += k - ggg = 333 + x - f() } - val ret = funLit(50, 77, 1, 2, 3, 4, 5) -// funLit(50, 77L) - if (i != 1 || j != 6 || k != 4) return "fail" - return ret -// return "OK" + val funLit = { f() } + return funLit() } -//fun test(aa:Int, bb:Int, cc:Int) : Int { -// val c = cc -// var d = 0 -// val f = { a:Int,b:Int -> d = a*b+c} -// f(aa, bb) -// return d -//} - fun box(): String { -// val i_box = closureBox(99) - return test(1, 2, 3).toString() + return test() } \ No newline at end of file