Implement function literals in JS BE

This commit is contained in:
Roman Artemev
2018-04-04 14:09:51 +03:00
parent c83ff5e75f
commit ed0c26ef07
26 changed files with 650 additions and 157 deletions
@@ -3,7 +3,7 @@
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.jvm.descriptors
package org.jetbrains.kotlin.backend.common.descriptors
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
@@ -73,6 +73,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
is IrProperty -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations()
is IrField -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations()
is IrAnonymousInitializer -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations()
// TODO: visit children as well
else -> null
}
}
@@ -178,8 +179,6 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
private fun collectRewrittenDeclarations(): ArrayList<IrDeclaration> =
ArrayList<IrDeclaration>(localFunctions.size + localClasses.size + 1).apply {
add(memberDeclaration)
localFunctions.values.mapTo(this) {
val original = it.declaration
it.transformedDeclaration.apply {
@@ -195,6 +194,8 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
localClasses.values.mapTo(this) {
it.declaration
}
add(memberDeclaration)
}
private inner class FunctionBodiesRewriter(val localContext: LocalContext?) : IrElementTransformerVoid() {
@@ -490,7 +491,7 @@ class LocalDeclarationsLowering(val context: BackendContext, val localNameProvid
newValueParameters,
oldDescriptor.returnType,
Modality.FINAL,
Visibilities.PRIVATE
Visibilities.LOCAL
)
oldDescriptor.extensionReceiverParameter?.let {
@@ -7,9 +7,12 @@ package org.jetbrains.kotlin.ir.backend.js
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
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")
}
@@ -7,24 +7,31 @@ package org.jetbrains.kotlin.ir.backend.js
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.ReflectionTypes
import org.jetbrains.kotlin.backend.common.descriptors.KnownPackageFragmentDescriptor
import org.jetbrains.kotlin.backend.common.ir.Ir
import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.KotlinTypeFactory
import org.jetbrains.kotlin.types.Variance
class JsIrBackendContext(
val module: ModuleDescriptor,
@@ -36,7 +43,8 @@ class JsIrBackendContext(
val intrinsics = JsIntrinsics(module, irBuiltIns, symbolTable)
override val builtIns = module.builtIns
override val sharedVariablesManager = JsSharedVariablesManager(builtIns)
override val sharedVariablesManager =
JsSharedVariablesManager(builtIns, KnownPackageFragmentDescriptor(builtIns.builtInsModule, FqName("kotlin.js.internal")))
override val reflectionTypes: ReflectionTypes by lazy(LazyThreadSafetyMode.PUBLICATION) {
// TODO
@@ -5,29 +5,204 @@
package org.jetbrains.kotlin.ir.backend.js
import org.jetbrains.kotlin.backend.common.descriptors.KnownClassDescriptor
import org.jetbrains.kotlin.backend.common.descriptors.SharedVariablesManager
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.*
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetValue
import org.jetbrains.kotlin.ir.expressions.IrSetVariable
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
import org.jetbrains.kotlin.ir.symbols.impl.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.*
class JsSharedVariablesManager(builtIns: KotlinBuiltIns): SharedVariablesManager {
override fun createSharedVariableDescriptor(variableDescriptor: VariableDescriptor): VariableDescriptor {
TODO("not implemented")
}
class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPackage: PackageFragmentDescriptor) : SharedVariablesManager {
override fun createSharedVariableDescriptor(variableDescriptor: VariableDescriptor): VariableDescriptor =
LocalVariableDescriptor(
variableDescriptor.containingDeclaration, Annotations.EMPTY, variableDescriptor.name,
getSharedVariableType(variableDescriptor.type),
false, false, variableDescriptor.isLateInit, variableDescriptor.source
)
override fun defineSharedValue(sharedVariableDescriptor: VariableDescriptor, originalDeclaration: IrVariable): IrStatement {
TODO("not implemented")
val valueType = originalDeclaration.descriptor.type
val boxConstructor = closureBoxConstructorTypeDescriptor
val boxConstructorSymbol = closureBoxConstrctorTypeSymbol
val constructorTypeParam = closureBoxConstructorTypeDescriptor.typeParameters[0]
val boxConstructorTypeArgument = mapOf(constructorTypeParam to valueType)
val initializer = originalDeclaration.initializer ?: IrConstImpl.constNull(
originalDeclaration.startOffset,
originalDeclaration.endOffset,
valueType
)
val constructorCall = IrCallImpl(
originalDeclaration.startOffset,
originalDeclaration.endOffset,
boxConstructorSymbol,
boxConstructor,
boxConstructorTypeArgument,
JsLoweredDeclarationOrigin.JS_CLOSURE_BOX_CLASS
).apply { putValueArgument(0, initializer) }
return IrVariableImpl(
originalDeclaration.startOffset,
originalDeclaration.endOffset,
originalDeclaration.origin,
sharedVariableDescriptor,
constructorCall
)
}
override fun getSharedValue(sharedVariableDescriptor: VariableDescriptor, originalGet: IrGetValue): IrExpression {
TODO("not implemented")
override fun getSharedValue(sharedVariableDescriptor: VariableDescriptor, originalGet: IrGetValue): IrExpression =
IrGetFieldImpl(
originalGet.startOffset, originalGet.endOffset,
closureBoxFieldSymbol,
IrGetValueImpl(
originalGet.startOffset,
originalGet.endOffset,
symbolForDescriptor(sharedVariableDescriptor)
),
originalGet.origin
)
override fun setSharedValue(sharedVariableDescriptor: VariableDescriptor, originalSet: IrSetVariable): IrExpression =
IrSetFieldImpl(
originalSet.startOffset, originalSet.endOffset,
closureBoxFieldSymbol,
IrGetValueImpl(
originalSet.startOffset,
originalSet.endOffset,
symbolForDescriptor(sharedVariableDescriptor)
),
originalSet.value,
originalSet.origin
)
private val boxTypeName = "\$closureBox\$"
private val closureBoxTypeDescriptor = createClosureBoxClass()
private val closureBoxConstructorTypeDescriptor = createClosureBoxClassConstructor()
private val closureBoxFieldDescriptor = createClosureBoxField()
private val closureBoxTypeSymbol = IrClassSymbolImpl(closureBoxTypeDescriptor)
val closureBoxConstrctorTypeSymbol = createFunctionSymbol(closureBoxConstructorTypeDescriptor)
private val closureBoxFieldSymbol = IrFieldSymbolImpl(closureBoxFieldDescriptor)
private fun createClosureBoxClass(): ClassDescriptor =
KnownClassDescriptor.createClassWithTypeParameters(
Name.identifier(boxTypeName), jsInterinalPackage, listOf(builtIns.anyType), listOf(
Name.identifier("T")
)
)
private fun createClosureBoxClassConstructor(): ClassConstructorDescriptor =
ClassConstructorDescriptorImpl.create(
closureBoxTypeDescriptor,
Annotations.EMPTY,
true,
SourceElement.NO_SOURCE
).apply {
/// constructor<T>(v: T) : T
val typeParameter = constructedClass.declaredTypeParameters[0]
// val typeParameter = typeParameters[0]
val typeParameterType = KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
Annotations.EMPTY,
typeParameter.typeConstructor,
listOf(),
false,
MemberScope.Empty
)
val parameterType = KotlinTypeFactory.simpleType(
Annotations.EMPTY,
typeParameter.typeConstructor,
listOf(), true
)
val paramDesc = ValueParameterDescriptorImpl(
this,
null,
0,
Annotations.EMPTY,
Name.identifier("v"),
parameterType,
false,
false,
false,
null,
SourceElement.NO_SOURCE
)
initialize(listOf(paramDesc), Visibilities.PUBLIC)
returnType = KotlinTypeFactory.simpleNotNullType(
Annotations.EMPTY,
closureBoxTypeDescriptor,
listOf(TypeProjectionImpl(Variance.INVARIANT, typeParameterType))
)
}
private fun createClosureBoxField(): PropertyDescriptor {
val desc = PropertyDescriptorImpl.create(
closureBoxTypeDescriptor,
Annotations.EMPTY,
Modality.FINAL,
Visibilities.PUBLIC,
true,
Name.identifier("v"),
CallableMemberDescriptor.Kind.DECLARATION,
SourceElement.NO_SOURCE,
false,
false,
false,
false,
false,
false
)
desc.setType(builtIns.anyType, emptyList(), closureBoxTypeDescriptor.thisAsReceiverParameter, null as ReceiverParameterDescriptor?)
desc.initialize(null, null)
return desc
}
override fun setSharedValue(sharedVariableDescriptor: VariableDescriptor, originalSet: IrSetVariable): IrExpression {
TODO("not implemented")
}
private fun getSubstitutedRefConstructor(valueType: KotlinType): ClassConstructorDescriptor =
closureBoxConstructorTypeDescriptor.substitute(
TypeSubstitutor.create(
closureBoxConstructorTypeDescriptor.typeParameters.associate {
it.typeConstructor to TypeProjectionImpl(
Variance.INVARIANT,
valueType
)
}
)
)!!
private fun getRefType(valueType: KotlinType) =
KotlinTypeFactory.simpleNotNullType(
Annotations.EMPTY,
closureBoxTypeDescriptor,
listOf(TypeProjectionImpl(Variance.INVARIANT, valueType))
)
private fun getSharedVariableType(type: KotlinType) = getRefType(type)
private val variableSymbols = mutableMapOf<VariableDescriptor, IrValueSymbol>()
private fun symbolForDescriptor(sharedVariableDescriptor: VariableDescriptor): IrValueSymbol =
variableSymbols.getOrPut(sharedVariableDescriptor, { IrVariableSymbolImpl(sharedVariableDescriptor) })
}
@@ -9,8 +9,7 @@ import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.backend.common.lower.*
import org.jetbrains.kotlin.backend.common.runOnFilePostfix
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.ir.backend.js.lower.IntrinsicifyCallsLowering
import org.jetbrains.kotlin.ir.backend.js.lower.SecondaryCtorLowering
import org.jetbrains.kotlin.ir.backend.js.lower.*
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
@@ -56,11 +55,13 @@ fun compile(
fun JsIrBackendContext.lower(file: IrFile) {
LateinitLowering(this, true).lower(file)
LocalFunctionsLowering(this).lower(file)
DefaultArgumentStubGenerator(this).runOnFilePostfix(file)
SharedVariablesLowering(this).runOnFilePostfix(file)
LocalDeclarationsLowering(this).runOnFilePostfix(file)
PropertiesLowering().lower(file)
InitializersLowering(this, JsLoweredDeclarationOrigin.CLASS_STATIC_INITIALIZER, false).runOnFilePostfix(file)
SecondaryCtorLowering(this).lower(file)
IntrinsicifyCallsLowering(this).lower(file)
FunctionReferenceLowering(this).lower(file)
}
@@ -0,0 +1,178 @@
/*
* 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.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
import org.jetbrains.kotlin.ir.descriptors.IrTemporaryVariableDescriptorImpl
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
import org.jetbrains.kotlin.ir.expressions.copyTypeArgumentsFrom
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType
class FunctionReferenceLowering(val context: JsIrBackendContext) : FileLoweringPass {
override fun lower(irFile: IrFile) {
irFile.acceptVoid(FunctionReferenceCollector())
irFile.transformChildrenVoid(LambdaFunctionVisitor())
irFile.transformChildrenVoid(FunctionReferenceVisitor())
lambdaImpls.forEach { it.transformChildrenVoid(FunctionReferenceVisitor()) }
}
val lambdas = mutableMapOf<IrFunction, KotlinType>()
val oldToNewDeclMap = mutableMapOf<IrSymbolOwner, IrFunction>()
val lambdaImpls = mutableListOf<IrFunction>()
inner class FunctionReferenceCollector : IrElementVisitorVoid {
override fun visitFunctionReference(expression: IrFunctionReference) {
lambdas[expression.symbol.owner as IrFunction] = expression.type
}
override fun visitElement(element: IrElement) {
element.acceptChildrenVoid(this)
}
}
inner class FunctionReferenceVisitor : IrElementTransformerVoid() {
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
val newTarget = oldToNewDeclMap[expression.symbol.owner]
return if (newTarget != null) IrCallImpl(expression.startOffset, expression.endOffset, newTarget.symbol).apply {
copyTypeArgumentsFrom(expression)
var index = 0
for (i in 0 until expression.valueArgumentsCount) {
val arg = expression.getValueArgument(i)
if (arg != null) {
putValueArgument(index++, arg)
}
}
} else expression
}
}
inner class LambdaFunctionVisitor : IrElementTransformerVoid() {
override fun visitFunction(declaration: IrFunction): IrStatement {
if (declaration !in lambdas.keys) return declaration
// transform
// foo$lambda(a: A, b: B, c: closure$C, d: closure$D) { /*body*/ } ===>
// foo$lambda(c: closure$C, d: closure$D) {
// var $funcRef = function(a: A, b: B) { /*body*/ }
// return $funcRef
// }
val functionType = lambdas[declaration]!!
// FunctionN<T1, T2, ..., TN, TReturn>, arguments.size = N + 1
val lambdaParamCount =
if (declaration.extensionReceiverParameter == null) functionType.arguments.size - 1 else functionType.arguments.size - 2
assert(lambdaParamCount >= 0)
val descriptor = SimpleFunctionDescriptorImpl.create(
declaration.descriptor.containingDeclaration,
Annotations.EMPTY,
Name.identifier("${declaration.descriptor.name}_impl"),
declaration.descriptor.kind,
declaration.descriptor.source
)
descriptor.initialize(
null,
declaration.descriptor.dispatchReceiverParameter,
// declaration.descriptor.typeParameters,
emptyList(),
declaration.descriptor.valueParameters.drop(declaration.valueParameters.size - lambdaParamCount).mapIndexed { index, valueParameterDescriptor ->
valueParameterDescriptor.copy(descriptor, valueParameterDescriptor.name, index)
},
declaration.descriptor.returnType,
declaration.descriptor.modality,
declaration.descriptor.visibility
)
val symbol = IrSimpleFunctionSymbolImpl(descriptor)
val func = IrFunctionImpl(declaration.startOffset, declaration.endOffset, declaration.origin, symbol).apply {
dispatchReceiverParameter = declaration.dispatchReceiverParameter
extensionReceiverParameter = declaration.extensionReceiverParameter
declaration.valueParameters.drop(declaration.valueParameters.size - lambdaParamCount).forEachIndexed { index, param ->
valueParameters += IrValueParameterImpl(
param.startOffset,
param.endOffset,
param.origin,
descriptor.valueParameters[index]
)
}
}
val newDeclDescriptor = SimpleFunctionDescriptorImpl.create(
declaration.descriptor.containingDeclaration,
declaration.descriptor.annotations,
declaration.descriptor.name,
declaration.descriptor.kind,
declaration.descriptor.source
).initialize(
null,
declaration.descriptor.dispatchReceiverParameter,
// declaration.descriptor.typeParameters,
emptyList(),
declaration.descriptor.valueParameters.dropLast(lambdaParamCount),
functionType,
declaration.descriptor.modality,
declaration.descriptor.visibility
)
val newDeclSymbol = IrSimpleFunctionSymbolImpl(newDeclDescriptor)
val funcReference = IrFunctionReferenceImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, functionType, symbol, descriptor, null, null)
val varDescriptor = IrTemporaryVariableDescriptorImpl(newDeclDescriptor, Name.identifier("\$funRef"), functionType)
val closureStmt = IrVariableImpl(
declaration.startOffset,
declaration.endOffset,
JsLoweredDeclarationOrigin.JS_LAMBDA_CREATION,
varDescriptor,
funcReference
)
val returnStmt = IrReturnImpl(
declaration.startOffset,
declaration.endOffset,
symbol,
IrGetValueImpl(declaration.startOffset, declaration.endOffset, IrVariableSymbolImpl(varDescriptor))
)
val oldBody = declaration.body
val newBody = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, listOf(closureStmt, returnStmt))
func.body = oldBody
lambdaImpls += func
val newDeclaration = IrFunctionImpl(declaration.startOffset, declaration.endOffset, declaration.origin, newDeclSymbol).apply {
body = newBody
valueParameters += declaration.valueParameters.dropLast(lambdaParamCount)
}
oldToNewDeclMap[declaration] = newDeclaration
return newDeclaration
}
}
}
@@ -114,16 +114,19 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL
return irCall(call, it.symbol)
}
(symbol.owner as? IrFunction)?.dispatchReceiverParameter?.let {
val key = SimpleMemberKey(it.type, symbol.name)
if (symbol.isBound) {
memberToIrFunction[key]?.let {
// TODO: don't apply intrinsics when type of receiver or argument is Long
return irCall(call, it.symbol, dispatchReceiverAsFirstArgument = true)
}
(symbol.owner as? IrFunction)?.dispatchReceiverParameter?.let {
val key = SimpleMemberKey(it.type, symbol.name)
memberToTransformer[key]?.let {
return it(call)
memberToIrFunction[key]?.let {
// TODO: don't apply intrinsics when type of receiver or argument is Long
return irCall(call, it.symbol, dispatchReceiverAsFirstArgument = true)
}
memberToTransformer[key]?.let {
return it(call)
}
}
}
}
@@ -268,11 +268,18 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
override fun visitFunction(declaration: IrFunction, data: IrFunction?): IrStatement = super.visitFunction(declaration, declaration)
override fun visitCall(expression: IrCall, ownerFunc: IrFunction?): IrElement {
val target = expression.symbol.owner as IrFunction
if (expression.symbol.isBound) {
if (target is IrConstructor) {
if (!target.descriptor.isPrimary) {
return redirectCall(expression, context.secondaryConstructorsMap[target.symbol]!!.stub)
val target = expression.symbol.owner as IrFunction
if (target is IrConstructor) {
if (!target.descriptor.isPrimary) {
val ctor = context.secondaryConstructorsMap[target.symbol]
if (ctor != null) {
return redirectCall(expression, ctor.stub)
}
}
}
}
@@ -11,9 +11,6 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.js.backend.ast.*
class IrDeclarationToJsTransformer : BaseIrElementToJsNodeTransformer<JsStatement, JsGenerationContext> {
override fun visitProperty(declaration: IrProperty, context: JsGenerationContext): JsStatement {
return jsVar(declaration.name, declaration.backingField?.initializer?.expression, context)
}
override fun visitSimpleFunction(declaration: IrSimpleFunction, context: JsGenerationContext): JsStatement {
return declaration.accept(IrFunctionToJsTransformer(), context).makeStmt()
@@ -28,7 +25,7 @@ class IrDeclarationToJsTransformer : BaseIrElementToJsNodeTransformer<JsStatemen
}
override fun visitField(declaration: IrField, context: JsGenerationContext): JsStatement {
val fieldName = declaration.name.toJsName()
val fieldName = context.getNameForSymbol(declaration.symbol)
val initExpression =
declaration.initializer?.accept(IrElementToJsExpressionTransformer(), context) ?: JsPrefixOperation(
JsUnaryOperator.VOID,
@@ -5,32 +5,37 @@
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
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.isSpecial
import org.jetbrains.kotlin.ir.backend.js.utils.name
import org.jetbrains.kotlin.ir.declarations.IrClass
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.util.OperatorNameConventions
class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsExpression, JsGenerationContext> {
// TODO: should we prohibit using blocks as expression in the future?
override fun visitBlock(expression: IrBlock, context: JsGenerationContext): JsExpression {
if (expression.statements.isEmpty()) {
// TODO: what should we do here? Crash? Generate throw? Should it be treated as unreachable code?
return super.visitBlock(expression, context)
private val neutralExpression: JsExpression = JsPrefixOperation(JsUnaryOperator.VOID, JsIntLiteral(1))
override fun visitContainerExpression(expression: IrContainerExpression, context: JsGenerationContext): JsExpression =
expression.statements.map { it.accept(this, context) }.fold(neutralExpression) { left, right ->
if (left != neutralExpression) JsBinaryOperation(JsBinaryOperator.COMMA, left, right) else right
}
return expression.statements
.map { it.accept(this, context) }
.reduce { left, right -> JsBinaryOperation(JsBinaryOperator.COMMA, left, right) }
}
override fun visitBlock(expression: IrBlock, data: JsGenerationContext): JsExpression = visitContainerExpression(expression, data)
override fun visitExpressionBody(body: IrExpressionBody, context: JsGenerationContext): JsExpression {
return body.expression.accept(this, context)
override fun visitComposite(expression: IrComposite, data: JsGenerationContext): JsExpression =
visitContainerExpression(expression, data)
override fun visitExpressionBody(body: IrExpressionBody, context: JsGenerationContext): JsExpression =
body.expression.accept(this, context)
override fun visitFunctionReference(expression: IrFunctionReference, context: JsGenerationContext): JsExpression {
val irFunction = expression.symbol.owner as IrFunction
return irFunction.accept(IrFunctionToJsTransformer(), context)
}
override fun <T> visitConst(expression: IrConst<T>, context: JsGenerationContext): JsExpression {
@@ -61,36 +66,36 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
}
override fun visitGetField(expression: IrGetField, context: JsGenerationContext): JsExpression {
return JsNameRef(expression.symbol.name.asString(), expression.receiver?.accept(this, context))
val fieldName = context.getNameForSymbol(expression.symbol)
return JsNameRef(fieldName, expression.receiver?.accept(this, context))
}
override fun visitGetValue(expression: IrGetValue, context: JsGenerationContext): JsExpression {
return if (expression.symbol.isSpecial) {
context.getSpecialRefForName(expression.symbol.name)
} else {
JsNameRef(context.getNameForSymbol(expression.symbol))
}
override fun visitGetValue(expression: IrGetValue, context: JsGenerationContext): JsExpression =
context.getNameForSymbol(expression.symbol).makeRef()
override fun visitGetObjectValue(expression: IrGetObjectValue, data: JsGenerationContext): JsExpression {
TODO()
}
override fun visitSetField(expression: IrSetField, context: JsGenerationContext): JsExpression {
val dest = JsNameRef(expression.symbol.name.asString(), expression.receiver?.accept(this, context))
val fieldName = context.getNameForSymbol(expression.symbol)
val dest = JsNameRef(fieldName, expression.receiver?.accept(this, context))
val source = expression.value.accept(this, context)
return jsAssignment(dest, source)
}
override fun visitSetVariable(expression: IrSetVariable, context: JsGenerationContext): JsExpression {
val ref = JsNameRef(expression.symbol.name.toJsName())
val ref = JsNameRef(context.getNameForSymbol(expression.symbol))
val value = expression.value.accept(this, context)
return JsBinaryOperation(JsBinaryOperator.ASG, ref, value)
}
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, context: JsGenerationContext): JsExpression {
val classNameRef = expression.symbol.owner.descriptor.constructedClass.name.toJsName().makeRef()
val classNameRef = context.getNameForSymbol(expression.symbol).makeRef()
val callFuncRef = JsNameRef(Namer.CALL_FUNCTION, classNameRef)
val fromPrimary = context.currentFunction is IrConstructor
val thisRef = if (fromPrimary) JsThisRef() else JsNameRef("\$this")
val thisRef =
if (fromPrimary) JsThisRef() else context.getNameForSymbol(context.currentFunction!!.valueParameters.last().symbol).makeRef()
val arguments = translateCallArguments(expression, context)
return JsInvocation(callFuncRef, listOf(thisRef) + arguments)
}
@@ -102,18 +107,26 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
return it(expression, context)
}
val dispatchReceiver = expression.dispatchReceiver?.accept(this, context)
val extensionReceiver = expression.extensionReceiver?.accept(this, context)
val dispatchReceiver = expression.dispatchReceiver
val jsDispatchReceiver = expression.dispatchReceiver?.accept(this, context)
val jsExtensionReceiver = expression.extensionReceiver?.accept(this, context)
val arguments = translateCallArguments(expression, context)
if (dispatchReceiver != null && dispatchReceiver.type.isFunctionTypeOrSubtype && symbol.name == OperatorNameConventions.INVOKE) {
return JsInvocation(jsDispatchReceiver!!, arguments)
}
context.staticContext.intrinsics[symbol]?.let {
return it(expression, arguments)
}
return if (symbol is IrConstructorSymbol) {
JsNew(JsNameRef((symbol.owner.parent as IrClass).name.asString()), arguments)
JsNew(context.getNameForSymbol(symbol).makeRef(), arguments)
} else {
// TODO sanitize name
val symbolName = context.getNameForSymbol(symbol)
val ref = if (dispatchReceiver != null) JsNameRef(symbolName, dispatchReceiver) else JsNameRef(symbolName)
JsInvocation(ref, extensionReceiver?.let { listOf(extensionReceiver) + arguments } ?: arguments)
val ref = if (jsDispatchReceiver != null) JsNameRef(symbolName, jsDispatchReceiver) else JsNameRef(symbolName)
JsInvocation(ref, jsExtensionReceiver?.let { listOf(jsExtensionReceiver) + arguments } ?: arguments)
}
}
@@ -121,4 +134,4 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
// TODO check when w/o else branch and empty when
return expression.toJsNode(this, context, ::JsConditional)!!
}
}
}
@@ -56,7 +56,8 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
}
override fun visitVariable(declaration: IrVariable, context: JsGenerationContext): JsStatement {
return jsVar(declaration.name, declaration.initializer, context)
val varName = context.getNameForSymbol(declaration.symbol)
return jsVar(varName, declaration.initializer, context)
}
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, context: JsGenerationContext): JsStatement {
@@ -21,8 +21,7 @@ open class IrFunctionToJsTransformer : BaseIrElementToJsNodeTransformer<JsFuncti
override fun visitConstructor(declaration: IrConstructor, context: JsGenerationContext): JsFunction {
assert(declaration.symbol.isPrimary)
return translateFunction(declaration, declaration.symbol.constructedClassName.toJsName(), context)
val funcName = context.getNameForSymbol(declaration.symbol)
return translateFunction(declaration, funcName, context)
}
}
@@ -5,16 +5,15 @@
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.backend.js.utils.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.js.backend.ast.*
class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationContext) {
private val classNameRef = irClass.name.toJsName().makeRef()
private val className = context.getNameForSymbol(irClass.symbol)
private val classNameRef = className.makeRef()
private val classPrototypeRef = prototypeOf(classNameRef)
private val classBlock = JsBlock()
@@ -31,12 +30,19 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
if (declaration.symbol.kind != CallableMemberDescriptor.Kind.FAKE_OVERRIDE &&
declaration.symbol.modality != Modality.ABSTRACT
) {
classBlock.statements += declaration.accept(transformer, context).apply { name = null }.let {
val memberName = context.getNameForSymbol(declaration.symbol)
val memberRef = JsNameRef(memberName, classPrototypeRef)
jsAssignment(memberRef, it).makeStmt()
classBlock.statements += declaration.accept(transformer, context).let {
if (declaration.visibility == Visibilities.LOCAL) {
it.makeStmt()
} else {
val memberName = context.getNameForSymbol(declaration.symbol)
val memberRef = JsNameRef(memberName, classPrototypeRef)
jsAssignment(memberRef, it).makeStmt()
}
}
}
} else if (declaration is IrClass) {
//TODO: redesign inner classes generation
classBlock.statements += JsClassGenerator(declaration, context).generate()
}
}
@@ -47,7 +53,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
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}")
func.name = irClass.name.toJsName()
func.name = className
classBlock.statements += func.makeStmt()
classBlock.statements += generateInheritanceCode()
}
@@ -59,8 +65,9 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
return emptyList()
}
val baseName = context.getNameForSymbol(baseClass.owner.symbol)
val createCall = jsAssignment(
classPrototypeRef, JsInvocation(Namer.JS_OBJECT_CREATE_FUNCTION, prototypeOf(baseClass.owner.name.toJsName().makeRef()))
classPrototypeRef, JsInvocation(Namer.JS_OBJECT_CREATE_FUNCTION, prototypeOf(baseName.makeRef()))
).makeStmt()
val ctorAssign = jsAssignment(JsNameRef(Namer.CONSTRUCTOR_NAME, classPrototypeRef), classNameRef).makeStmt()
@@ -83,7 +90,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
private fun generateSuperClasses(): JsPropertyInitializer = JsPropertyInitializer(
JsNameRef(Namer.METADATA_INTERFACES),
JsArrayLiteral(irClass.superClasses.filter { it.kind == ClassKind.INTERFACE }.map { JsNameRef(it.owner.name.toJsName()) })
JsArrayLiteral(irClass.superClasses.filter { it.kind == ClassKind.INTERFACE }.map { JsNameRef(context.getNameForSymbol(it.owner.symbol)) })
)
}
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.ir.backend.js.JsIntrinsics
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
@@ -15,10 +15,12 @@ import org.jetbrains.kotlin.js.backend.ast.*
typealias IrCallTransformer = (IrCall, context: JsGenerationContext) -> JsExpression
class JsIntrinsicTransformers(intrinsics: JsIntrinsics) {
class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
private val transformers: Map<IrSymbol, IrCallTransformer>
init {
val intrinsics = backendContext.intrinsics
transformers = mutableMapOf()
transformers.apply {
@@ -63,7 +65,14 @@ class JsIntrinsicTransformers(intrinsics: JsIntrinsics) {
val classToCreate = call.getTypeArgument(0)!!
val prototype = prototypeOf(classToCreate.constructor.declarationDescriptor!!.name.toJsName().makeRef())
JsInvocation(Namer.JS_OBJECT_CREATE_FUNCTION, prototype)
}
add(backendContext.sharedVariablesManager.closureBoxConstructorTypeSymbol) { call, context ->
val args = translateCallArguments(call, context)
val initializer = args[0]
val propertyInit = JsPropertyInitializer(JsNameRef("v"), initializer)
val objectLiteral = JsObjectLiteral()
objectLiteral.apply { propertyInitializers += propertyInit }
}
addIfNotNull(intrinsics.jsCode) { call, context ->
@@ -71,7 +80,7 @@ class JsIntrinsicTransformers(intrinsics: JsIntrinsics) {
when (jsCode) {
is JsExpression -> jsCode
// TODO don't generate function for this case
// TODO don't generate function for this case
else -> JsInvocation(JsFunction(context.currentScope, jsCode as? JsBlock ?: JsBlock(jsCode as JsStatement), ""))
}
}
@@ -81,6 +90,10 @@ class JsIntrinsicTransformers(intrinsics: JsIntrinsics) {
operator fun get(symbol: IrSymbol): IrCallTransformer? = transformers[symbol]
}
private fun MutableMap<IrSymbol, IrCallTransformer>.add(functionSymbol: IrSymbol, t: IrCallTransformer) {
put(functionSymbol, t)
}
private fun MutableMap<IrSymbol, IrCallTransformer>.add(function: IrFunction, t: IrCallTransformer) {
put(function.symbol, t)
}
@@ -12,15 +12,23 @@ import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.name.Name
@Deprecated("Use context.getNameForSymbol(symbol) instead")
fun Name.toJsName() = JsDynamicScope.declareName(asString())
// TODO don't use JsDynamicScope
val dummyScope = JsDynamicScope
fun jsVar(name: Name, initializer: IrExpression?, context: JsGenerationContext): JsVars {
fun Name.toJsName() =
// TODO sanitize
dummyScope.declareName(asString())
fun jsVar(name: JsName, initializer: IrExpression?, context: JsGenerationContext): JsVars {
val jsInitializer = initializer?.accept(IrElementToJsExpressionTransformer(), context)
return JsVars(JsVars.JsVar(name.toJsName(), jsInitializer))
return JsVars(JsVars.JsVar(name, jsInitializer))
}
fun <T : JsNode, D : JsGenerationContext> IrWhen.toJsNode(tr: BaseIrElementToJsNodeTransformer<T, D>, data: D, node: (JsExpression, T, T?) -> T): T? =
fun <T : JsNode, D : JsGenerationContext> IrWhen.toJsNode(
tr: BaseIrElementToJsNodeTransformer<T, D>,
data: D,
node: (JsExpression, T, T?) -> T
): T? =
branches.foldRight<IrBranch, T?>(null) { br, n ->
val body = br.result.accept(tr, data)
if (br is IrElseBranch) body
@@ -47,14 +55,8 @@ fun translateFunction(declaration: IrFunction, name: JsName?, context: JsGenerat
parameters.add(JsParameter(parameter))
}
declaration.extensionReceiverParameter?.let { function.addParameter("\$receiver") }
declaration.valueParameters.forEach {
if (it.name.isSpecial) {
function.addParameter(context.staticContext.getSpecialNameString(it.name.asString()))
} else {
function.addParameter(it.name.asString())
}
}
declaration.extensionReceiverParameter?.let { function.addParameter(context.getNameForSymbol(it.symbol).ident) }
declaration.valueParameters.forEach { function.addParameter(context.getNameForSymbol(it.symbol).ident) }
return function
}
@@ -5,16 +5,10 @@
package org.jetbrains.kotlin.ir.backend.js.utils
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrElementToJsExpressionTransformer
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrElementToJsStatementTransformer
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.toJsName
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.js.backend.ast.*
import org.jetbrains.kotlin.name.Name
class JsGenerationContext {
fun newDeclaration(scope: JsScope, func: IrFunction? = null): JsGenerationContext {
@@ -48,5 +42,4 @@ class JsGenerationContext {
}
fun getNameForSymbol(symbol: IrSymbol): JsName = staticContext.getNameForSymbol(symbol)
fun getSpecialRefForName(name: Name): JsExpression = staticContext.getSpecialRefForName(name)
}
@@ -18,11 +18,9 @@ class JsStaticContext(
private val rootScope: JsRootScope,
private val globalBlock: JsGlobalBlock,
private val nameGenerator: NameGenerator,
val backendContext: JsIrBackendContext
backendContext: JsIrBackendContext
) {
val intrinsics = JsIntrinsicTransformers(backendContext.intrinsics)
val intrinsics = JsIntrinsicTransformers(backendContext)
fun getNameForSymbol(irSymbol: IrSymbol) = nameGenerator.getNameForSymbol(irSymbol, rootScope)
fun getSpecialRefForName(name: Name): JsExpression = nameGenerator.getSpecialRefForName(name)
fun getSpecialNameString(specNameString: String): String = nameGenerator.getSpecialNameString(specNameString)
}
@@ -5,16 +5,10 @@
package org.jetbrains.kotlin.ir.backend.js.utils
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.js.backend.ast.JsExpression
import org.jetbrains.kotlin.js.backend.ast.JsName
import org.jetbrains.kotlin.js.backend.ast.JsScope
import org.jetbrains.kotlin.name.Name
interface NameGenerator {
fun getNameForSymbol(symbol: IrSymbol, scope: JsScope): JsName
fun getSpecialRefForName(name: Name): JsExpression
fun getSpecialNameString(specNameString: String): String
}
@@ -40,7 +40,8 @@ object Namer {
val ROOT_PACKAGE = "_"
val RECEIVER_PARAMETER_NAME = "\$receiver"
val EXTENSION_RECEIVER_NAME = "\$receiver"
val IMPLICIT_RECEIVER_NAME = "this"
val ANOTHER_THIS_PARAMETER_NAME = "$this"
val THROW_CLASS_CAST_EXCEPTION_FUN_NAME = "throwCCE"
@@ -6,11 +6,14 @@
package org.jetbrains.kotlin.ir.backend.js.utils
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.*
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.name.Name
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
class SimpleNameGenerator : NameGenerator {
@@ -18,24 +21,34 @@ class SimpleNameGenerator : NameGenerator {
override fun getNameForSymbol(symbol: IrSymbol, scope: JsScope): JsName = getNameForDescriptor(symbol.descriptor, scope)
override fun getSpecialRefForName(name: Name): JsExpression {
assert(name.isSpecial)
val nameString = name.asString()
return when (nameString) {
Namer.THIS_SPECIAL_NAME -> JsThisRef()
else -> JsNameRef(getSpecialNameString(nameString))
}
}
override fun getSpecialNameString(specNameString: String): String = when (specNameString) {
Namer.SET_SPECIAL_NAME -> Namer.SETTER_ARGUMENT
else -> TODO("for Name ${specNameString}")
}
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)
}
}
}
is PropertyDescriptor -> {
nameBuilder.append(descriptor.name.identifier)
}
is PropertyAccessorDescriptor -> {
when (descriptor) {
is PropertyGetterDescriptor -> nameBuilder.append(Namer.GETTER_PREFIX)
@@ -43,6 +56,21 @@ class SimpleNameGenerator : NameGenerator {
}
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.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()}") }
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.backend.jvm.descriptors
import org.jetbrains.kotlin.backend.common.descriptors.KnownClassDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.name.Name
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.backend.jvm.descriptors
import org.jetbrains.kotlin.backend.common.descriptors.KnownClassDescriptor
import org.jetbrains.kotlin.codegen.descriptors.FileClassDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
@@ -16,7 +16,7 @@
package org.jetbrains.kotlin.backend.jvm.descriptors
import org.jetbrains.kotlin.backend.common.descriptors.SharedVariablesManager
import org.jetbrains.kotlin.backend.common.descriptors.*
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.descriptors.*
@@ -2,14 +2,42 @@
import kotlin.test.assertEquals
inline fun foo(x: String, block: (String) -> String) = block(x)
fun run(r: () -> Any) = r()
fun test(i: Int, j: Int, k: Int): String {
var i = 0
var j = 2
val k = 4
fun f(): String = "OK"
val funVal = {
println(k)
}
run(funVal)
val funLit = { i += 1
j += k
f() }
val ret = run(funLit) as String
if (i != 1 || j != 6 || k != 4) return "fail"
return ret
}
fun box(): String {
fun bar(y: String) = y + "cde"
val res = foo("abc") { bar(it) }
assertEquals("abccde", res)
return "OK"
return test(1, 2, 3)
}
//fun box(): String {
//// fun bar(y: String) = y + "cde"
//
//// val res = foo("abc") { bar(it) }
//
//// assertEquals("abccde", res)
//
// return "OK"
//}
@@ -2,13 +2,54 @@
// EXPECTED_REACHABLE_NODES: 1113
package foo
fun test(): String {
fun f(): String = "OK"
val funLit = { f() }
return funLit()
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 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"
}
//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 {
return test()
// val i_box = closureBox<Int>(99)
return test(1, 2, 3).toString()
}