Refactoring and fixes
This commit is contained in:
@@ -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")
|
||||
}
|
||||
+4
-5
@@ -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<JsExpression, JsGenerationContext> {
|
||||
@@ -35,7 +38,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
|
||||
override fun visitFunctionReference(expression: IrFunctionReference, context: JsGenerationContext): JsExpression {
|
||||
val irFunction = expression.symbol.owner as IrFunction
|
||||
return irFunction.accept(IrFunctionToJsTransformer(), context)
|
||||
return irFunction.accept(IrFunctionToJsTransformer(), context).apply { name = null }
|
||||
}
|
||||
|
||||
override fun <T> visitConst(expression: IrConst<T>, context: JsGenerationContext): JsExpression {
|
||||
@@ -125,10 +128,6 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
return JsInvocation(jsDispatchReceiver!!, arguments)
|
||||
}
|
||||
|
||||
context.staticContext.intrinsics[symbol]?.let {
|
||||
return it(expression, arguments)
|
||||
}
|
||||
|
||||
return if (symbol is IrConstructorSymbol) {
|
||||
JsNew(context.getNameForSymbol(symbol).makeRef(), arguments)
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.js.backend.ast.JsStatement
|
||||
|
||||
class IrFileToJsTransformer : BaseIrElementToJsNodeTransformer<JsStatement, JsGenerationContext> {
|
||||
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 {
|
||||
|
||||
+5
-2
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
-8
@@ -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)
|
||||
|
||||
+12
-4
@@ -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
|
||||
}
|
||||
+1
-3
@@ -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)
|
||||
}
|
||||
+1
-2
@@ -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
|
||||
}
|
||||
|
||||
+55
-54
@@ -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<DeclarationDescriptor, JsName>()
|
||||
|
||||
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 "_"
|
||||
|
||||
@@ -2,54 +2,13 @@
|
||||
// EXPECTED_REACHABLE_NODES: 1113
|
||||
package foo
|
||||
|
||||
|
||||
class closureBox<T>(var v: T)
|
||||
|
||||
|
||||
|
||||
//fun run(r: () -> Any) = r()
|
||||
|
||||
fun <T1, T2, T3> 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<Int>(99)
|
||||
return test(1, 2, 3).toString()
|
||||
return test()
|
||||
}
|
||||
Reference in New Issue
Block a user