[JS IR BE] Implement type check for SuspendFunctionN

This commit is contained in:
Roman Artemev
2019-05-16 16:43:44 +03:00
committed by romanart
parent 9894c216c1
commit 9c7d47789c
8 changed files with 36 additions and 5 deletions
@@ -118,6 +118,7 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
val isArraySymbol = getInternalFunction("isArray")
// val isCharSymbol = getInternalFunction("isChar")
val isObjectSymbol = getInternalFunction("isObject")
val isSuspendFunctionSymbol = getInternalFunction("isSuspendFunction")
val isNumberSymbol = getInternalFunction("isNumber")
val isComparableSymbol = getInternalFunction("isComparable")
@@ -42,6 +42,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
private val isInterfaceSymbol get() = context.intrinsics.isInterfaceSymbol
private val isArraySymbol get() = context.intrinsics.isArraySymbol
private val isSuspenfFunctionSymbol = context.intrinsics.isSuspendFunctionSymbol
// private val isCharSymbol get() = context.intrinsics.isCharSymbol
private val isObjectSymbol get() = context.intrinsics.isObjectSymbol
@@ -209,6 +210,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
return when {
toType.isAny() -> generateIsObjectCheck(argument)
toType.isNothing() -> JsIrBuilder.buildComposite(context.irBuiltIns.booleanType, listOf(argument, litFalse))
toType.isSuspendFunctionTypeOrSubtype() -> generateSuspendFunctionCheck(argument, toType)
isTypeOfCheckingType(toType) -> generateTypeOfCheck(argument, toType)
// toType.isChar() -> generateCheckForChar(argument)
toType.isNumber() -> generateNumberCheck(argument)
@@ -254,6 +256,16 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
// private fun generateCheckForChar(argument: IrExpression) =
// JsIrBuilder.buildCall(isCharSymbol).apply { dispatchReceiver = argument }
private fun generateSuspendFunctionCheck(argument: IrExpression, toType: IrType): IrExpression {
val arity = (toType.classifierOrFail.owner as IrClass).typeParameters.size - 1 // drop return type
val irBuiltIns = context.irBuiltIns
return JsIrBuilder.buildCall(isSuspenfFunctionSymbol, irBuiltIns.booleanType).apply {
putValueArgument(0, argument)
putValueArgument(1, JsIrBuilder.buildInt(irBuiltIns.intType, arity))
}
}
private fun generateTypeOfCheck(argument: IrExpression, toType: IrType): IrExpression {
val marker = when {
toType.isFunctionOrKFunction() -> functionMarker
@@ -240,9 +240,21 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
metadataLiteral.propertyInitializers += JsPropertyInitializer(JsNameRef(Namer.METADATA_CLASS_KIND), classKind)
metadataLiteral.propertyInitializers += generateSuperClasses()
if (isCoroutineClass()) {
metadataLiteral.propertyInitializers += generateSuspendArity()
}
return jsAssignment(JsNameRef(Namer.METADATA, classNameRef), metadataLiteral).makeStmt()
}
private fun isCoroutineClass(): Boolean = irClass.superTypes.any { it.isSuspendFunctionTypeOrSubtype() }
private fun generateSuspendArity(): JsPropertyInitializer {
val arity = irClass.declarations.filterIsInstance<IrSimpleFunction>().first { it.isSuspend }.valueParameters.size
return JsPropertyInitializer(JsNameRef(Namer.METADATA_SUSPEND_ARITY), JsIntLiteral(arity))
}
private fun generateSuperClasses(): JsPropertyInitializer {
val functionTypeOrSubtype = irClass.defaultType.isFunctionTypeOrSubtype()
return JsPropertyInitializer(
@@ -35,6 +35,7 @@ object Namer {
val METADATA_INTERFACES = "interfaces"
val METADATA_SIMPLE_NAME = "simpleName"
val METADATA_CLASS_KIND = "kind"
val METADATA_SUSPEND_ARITY = "suspendArity"
val KCALLABLE_GET_NAME = "<get-name>"
val KCALLABLE_NAME = "callableName"