Use NSNumber subclasses for Kotlin numbers when producing framework (#1956)
This commit is contained in:
committed by
GitHub
parent
838956f4df
commit
aac798e5ac
+1
-1
@@ -20,7 +20,7 @@ internal open class ObjCCodeGenerator(val codegen: CodeGenerator) {
|
||||
return load(selectorRef.llvm)
|
||||
}
|
||||
|
||||
fun FunctionGenerationContext.genGetSystemClass(name: String): LLVMValueRef {
|
||||
fun FunctionGenerationContext.genGetLinkedClass(name: String): LLVMValueRef {
|
||||
val classRef = dataGenerator.genClassRef(name)
|
||||
return load(classRef.llvm)
|
||||
}
|
||||
|
||||
+6
-3
@@ -169,6 +169,9 @@ internal class ObjCExportCodeGenerator(
|
||||
dataGenerator.emitEmptyClass(namer.getPackageName(fqName), namer.kotlinAnyName)
|
||||
}
|
||||
|
||||
NSNumberKind.values().mapNotNull { it.mappedKotlinClassId }.forEach {
|
||||
dataGenerator.exportClass("Kotlin${it.shortClassName}")
|
||||
}
|
||||
dataGenerator.exportClass("KotlinMutableSet")
|
||||
dataGenerator.exportClass("KotlinMutableDictionary")
|
||||
|
||||
@@ -345,7 +348,7 @@ private fun ObjCExportCodeGenerator.emitBoxConverters() {
|
||||
emitBoxConverter(irBuiltIns.shortClass, ObjCValueType.SHORT, "numberWithShort:")
|
||||
emitBoxConverter(irBuiltIns.intClass, ObjCValueType.INT, "numberWithInt:")
|
||||
emitBoxConverter(irBuiltIns.longClass, ObjCValueType.LONG_LONG, "numberWithLongLong:")
|
||||
emitBoxConverter(symbols.uByte, ObjCValueType.UNSIGNED_CHAR, "numberWithUnsignedChar")
|
||||
emitBoxConverter(symbols.uByte, ObjCValueType.UNSIGNED_CHAR, "numberWithUnsignedChar:")
|
||||
emitBoxConverter(symbols.uShort, ObjCValueType.UNSIGNED_SHORT, "numberWithUnsignedShort:")
|
||||
emitBoxConverter(symbols.uInt, ObjCValueType.UNSIGNED_INT, "numberWithUnsignedInt:")
|
||||
emitBoxConverter(symbols.uLong, ObjCValueType.UNSIGNED_LONG_LONG, "numberWithUnsignedLongLong:")
|
||||
@@ -371,8 +374,8 @@ private fun ObjCExportCodeGenerator.emitBoxConverter(
|
||||
|
||||
val value = kotlinToObjC(kotlinValue, objCValueType)
|
||||
|
||||
val nsNumber = genGetSystemClass("NSNumber")
|
||||
ret(genSendMessage(int8TypePtr, nsNumber, nsNumberFactorySelector, value))
|
||||
val nsNumberSubclass = genGetLinkedClass("Kotlin${boxClass.name}")
|
||||
ret(genSendMessage(int8TypePtr, nsNumberSubclass, nsNumberFactorySelector, value))
|
||||
}
|
||||
|
||||
LLVMSetLinkage(converter, LLVMLinkage.LLVMPrivateLinkage)
|
||||
|
||||
+82
-10
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.UnsignedType
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.constants.ArrayValue
|
||||
@@ -44,6 +45,16 @@ abstract class ObjCExportHeaderGenerator(
|
||||
internal val generatedClasses = mutableSetOf<ClassDescriptor>()
|
||||
internal val topLevel = mutableMapOf<FqName, MutableList<CallableMemberDescriptor>>()
|
||||
|
||||
private val mappedToNSNumber: List<ClassDescriptor> = with(builtIns) {
|
||||
val result = mutableListOf(boolean, byte, short, int, long, float, double)
|
||||
|
||||
UnsignedType.values().mapTo(result) { unsignedType ->
|
||||
moduleDescriptor.findClassAcrossModuleDependencies(unsignedType.classId)!!
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
private val customTypeMappers: Map<ClassDescriptor, CustomTypeMapper> = with(builtIns) {
|
||||
val result = mutableListOf<CustomTypeMapper>()
|
||||
|
||||
@@ -56,16 +67,13 @@ abstract class ObjCExportHeaderGenerator(
|
||||
result += CustomTypeMapper.Collection(generator, map, "NSDictionary")
|
||||
result += CustomTypeMapper.Collection(generator, mutableMap, namer.mutableMapName)
|
||||
|
||||
for (descriptor in listOf(boolean, byte, short, int, long, float, double)) {
|
||||
// TODO: Kotlin code doesn't have any checkcasts on unboxing,
|
||||
// so it is possible that it expects boxed number of other type and unboxes it incorrectly.
|
||||
NSNumberKind.values().forEach {
|
||||
// TODO: NSNumber seem to have different equality semantics.
|
||||
result += CustomTypeMapper.Simple(descriptor, "NSNumber")
|
||||
}
|
||||
if (it.mappedKotlinClassId != null) {
|
||||
val descriptor = moduleDescriptor.findClassAcrossModuleDependencies(it.mappedKotlinClassId)!!
|
||||
result += CustomTypeMapper.Simple(descriptor, namer.numberBoxName(descriptor))
|
||||
}
|
||||
|
||||
for (unsignedType in UnsignedType.values()) {
|
||||
val descriptor = moduleDescriptor.findClassAcrossModuleDependencies(unsignedType.classId)!!
|
||||
result += CustomTypeMapper.Simple(descriptor, "NSNumber")
|
||||
}
|
||||
|
||||
result += CustomTypeMapper.Simple(string, "NSString")
|
||||
@@ -121,7 +129,7 @@ abstract class ObjCExportHeaderGenerator(
|
||||
namer.mutableSetName,
|
||||
generics = listOf("ObjectType"),
|
||||
superClass = "NSMutableSet<ObjectType>",
|
||||
attributes = listOf("objc_runtime_name(\"KotlinMutableSet\")")
|
||||
attributes = listOf(objcRuntimeNameAttribute("KotlinMutableSet"))
|
||||
))
|
||||
|
||||
// TODO: only if appears
|
||||
@@ -129,13 +137,15 @@ abstract class ObjCExportHeaderGenerator(
|
||||
namer.mutableMapName,
|
||||
generics = listOf("KeyType", "ObjectType"),
|
||||
superClass = "NSMutableDictionary<KeyType, ObjectType>",
|
||||
attributes = listOf("objc_runtime_name(\"KotlinMutableDictionary\")")
|
||||
attributes = listOf(objcRuntimeNameAttribute("KotlinMutableDictionary"))
|
||||
))
|
||||
|
||||
stubs.add(ObjCInterface("NSError", categoryName = "NSErrorKotlinException", members = buildMembers {
|
||||
+ObjCProperty("kotlinException", null, ObjCNullableReferenceType(ObjCIdType), listOf("readonly"))
|
||||
}))
|
||||
|
||||
genKotlinNumbers()
|
||||
|
||||
val packageFragments = moduleDescriptor.getPackageFragments()
|
||||
|
||||
packageFragments.forEach { packageFragment ->
|
||||
@@ -195,6 +205,67 @@ abstract class ObjCExportHeaderGenerator(
|
||||
return stubs
|
||||
}
|
||||
|
||||
private fun genKotlinNumbers() {
|
||||
val members = buildMembers {
|
||||
NSNumberKind.values().forEach {
|
||||
+nsNumberFactory(it, listOf("unavailable"))
|
||||
}
|
||||
NSNumberKind.values().forEach {
|
||||
+nsNumberInit(it, listOf("unavailable"))
|
||||
}
|
||||
}
|
||||
stubs.add(ObjCInterface(
|
||||
namer.kotlinNumberName,
|
||||
superClass = "NSNumber",
|
||||
members = members,
|
||||
attributes = listOf(objcRuntimeNameAttribute("KotlinNumber"))
|
||||
))
|
||||
|
||||
NSNumberKind.values().forEach {
|
||||
if (it.mappedKotlinClassId != null) {
|
||||
stubs += genKotlinNumber(it.mappedKotlinClassId, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun genKotlinNumber(kotlinClassId: ClassId, kind: NSNumberKind): ObjCInterface {
|
||||
val descriptor = moduleDescriptor.findClassAcrossModuleDependencies(kotlinClassId)!!
|
||||
val name = namer.numberBoxName(descriptor)
|
||||
|
||||
val members = buildMembers {
|
||||
+nsNumberFactory(kind)
|
||||
+nsNumberInit(kind)
|
||||
}
|
||||
return ObjCInterface(
|
||||
name,
|
||||
superClass = namer.kotlinNumberName,
|
||||
members = members,
|
||||
attributes = listOf(objcRuntimeNameAttribute("Kotlin${kotlinClassId.shortClassName}"))
|
||||
)
|
||||
}
|
||||
|
||||
private fun nsNumberInit(kind: NSNumberKind, attributes: List<String> = emptyList()): ObjCMethod {
|
||||
return ObjCMethod(
|
||||
null,
|
||||
false,
|
||||
ObjCInstanceType,
|
||||
listOf(kind.factorySelector),
|
||||
listOf(ObjCParameter("value", null, kind.objCType)),
|
||||
attributes
|
||||
)
|
||||
}
|
||||
|
||||
private fun nsNumberFactory(kind: NSNumberKind, attributes: List<String> = emptyList()): ObjCMethod {
|
||||
return ObjCMethod(
|
||||
null,
|
||||
true,
|
||||
ObjCInstanceType,
|
||||
listOf(kind.initSelector),
|
||||
listOf(ObjCParameter("value", null, kind.objCType)),
|
||||
attributes
|
||||
)
|
||||
}
|
||||
|
||||
private fun translateClassName(descriptor: ClassDescriptor): String = classOrInterfaceToName.getOrPut(descriptor) {
|
||||
assert(mapper.shouldBeExposed(descriptor))
|
||||
val forwardDeclarations = if (descriptor.isInterface) protocolForwardDeclarations else classForwardDeclarations
|
||||
@@ -549,6 +620,7 @@ abstract class ObjCExportHeaderGenerator(
|
||||
}
|
||||
|
||||
private fun swiftNameAttribute(swiftName: String) = "swift_name(\"$swiftName\")"
|
||||
private fun objcRuntimeNameAttribute(name: String) = "objc_runtime_name(\"$name\")"
|
||||
|
||||
private val methodsWithThrowAnnotationConsidered = mutableSetOf<FunctionDescriptor>()
|
||||
|
||||
|
||||
+49
@@ -12,8 +12,11 @@ import org.jetbrains.kotlin.backend.konan.descriptors.allOverriddenDescriptors
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isArray
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.PrimitiveType
|
||||
import org.jetbrains.kotlin.builtins.UnsignedType
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
@@ -215,3 +218,49 @@ internal fun ObjCExportMapper.bridgePropertyType(descriptor: PropertyDescriptor)
|
||||
|
||||
return bridgeType(descriptor.type)
|
||||
}
|
||||
|
||||
internal enum class NSNumberKind(val mappedKotlinClassId: ClassId?, val objCType: ObjCType) {
|
||||
CHAR(PrimitiveType.BYTE, "char"),
|
||||
UNSIGNED_CHAR(UnsignedType.UBYTE, "unsigned char"),
|
||||
SHORT(PrimitiveType.SHORT, "short"),
|
||||
UNSIGNED_SHORT(UnsignedType.USHORT, "unsigned short"),
|
||||
INT(PrimitiveType.INT, "int"),
|
||||
UNSIGNED_INT(UnsignedType.UINT, "unsigned int"),
|
||||
LONG("long"),
|
||||
UNSIGNED_LONG("unsigned long"),
|
||||
LONG_LONG(PrimitiveType.LONG, "long long"),
|
||||
UNSIGNED_LONG_LONG(UnsignedType.ULONG, "unsigned long long"),
|
||||
FLOAT(PrimitiveType.FLOAT, "float"),
|
||||
DOUBLE(PrimitiveType.DOUBLE, "double"),
|
||||
BOOL(PrimitiveType.BOOLEAN, "BOOL"),
|
||||
INTEGER("NSInteger"),
|
||||
UNSIGNED_INTEGER("NSUInteger")
|
||||
|
||||
;
|
||||
|
||||
// UNSIGNED_SHORT -> unsignedShort
|
||||
private val kindName = this.name.split('_')
|
||||
.joinToString("") { it.toLowerCase().capitalize() }.decapitalize()
|
||||
|
||||
|
||||
val valueSelector = kindName // unsignedShort
|
||||
val initSelector = "initWith${kindName.capitalize()}:" // initWithUnsignedShort:
|
||||
val factorySelector = "numberWith${kindName.capitalize()}:" // numberWithUnsignedShort:
|
||||
|
||||
constructor(
|
||||
mappedKotlinClassId: ClassId?,
|
||||
objCPrimitiveTypeName: String
|
||||
) : this(mappedKotlinClassId, ObjCPrimitiveType(objCPrimitiveTypeName))
|
||||
|
||||
constructor(
|
||||
primitiveType: PrimitiveType,
|
||||
objCPrimitiveTypeName: String
|
||||
) : this(ClassId.topLevel(primitiveType.typeFqName), objCPrimitiveTypeName)
|
||||
|
||||
constructor(
|
||||
unsignedType: UnsignedType,
|
||||
objCPrimitiveTypeName: String
|
||||
) : this(unsignedType.classId, objCPrimitiveTypeName)
|
||||
|
||||
constructor(objCPrimitiveTypeName: String) : this(null, ObjCPrimitiveType(objCPrimitiveTypeName))
|
||||
}
|
||||
|
||||
+3
@@ -29,6 +29,9 @@ internal class ObjCExportNamer(val moduleDescriptor: ModuleDescriptor,
|
||||
val mutableSetName = "${topLevelNamePrefix}MutableSet"
|
||||
val mutableMapName = "${topLevelNamePrefix}MutableDictionary"
|
||||
|
||||
fun numberBoxName(descriptor: ClassDescriptor): String = "$topLevelNamePrefix${descriptor.name.asString()}"
|
||||
val kotlinNumberName = "${topLevelNamePrefix}Number"
|
||||
|
||||
private val methodSelectors = object : Mapping<FunctionDescriptor, String>() {
|
||||
|
||||
// Try to avoid clashing with critical NSObject instance methods:
|
||||
|
||||
@@ -134,7 +134,7 @@ class StdlibTests : TestProvider {
|
||||
print("MAP: \(k) - \(v)")
|
||||
}
|
||||
|
||||
var smd = StdlibMutableDictionary<NSString, NSNumber>()
|
||||
var smd = StdlibMutableDictionary<NSString, StdlibInt>()
|
||||
smd.setObject(333, forKey: "333" as NSString)
|
||||
try assertEquals(actual: smd.object(forKey: "333" as NSString) as! Int, expected: 333, "Add element to dict")
|
||||
|
||||
|
||||
@@ -32,6 +32,37 @@ val nanFloatVal: Float = Float.NaN
|
||||
val infDoubleVal: Double = Double.POSITIVE_INFINITY
|
||||
val infFloatVal: Float = Float.NEGATIVE_INFINITY
|
||||
|
||||
private fun <T> T.toNullable(): T? = this
|
||||
|
||||
fun box(booleanValue: Boolean) = booleanValue.toNullable()
|
||||
fun box(byteValue: Byte) = byteValue.toNullable()
|
||||
fun box(shortValue: Short) = shortValue.toNullable()
|
||||
fun box(intValue: Int) = intValue.toNullable()
|
||||
fun box(longValue: Long) = longValue.toNullable()
|
||||
fun box(uByteValue: UByte) = uByteValue.toNullable()
|
||||
fun box(uShortValue: UShort) = uShortValue.toNullable()
|
||||
fun box(uIntValue: UInt) = uIntValue.toNullable()
|
||||
fun box(uLongValue: ULong) = uLongValue.toNullable()
|
||||
fun box(floatValue: Float) = floatValue.toNullable()
|
||||
fun box(doubleValue: Double) = doubleValue.toNullable()
|
||||
|
||||
private inline fun <reified T> ensureEquals(actual: T?, expected: T) {
|
||||
if (actual !is T) error(T::class)
|
||||
if (actual != expected) error(T::class)
|
||||
}
|
||||
|
||||
fun ensureEqualBooleans(actual: Boolean?, expected: Boolean) = ensureEquals(actual, expected)
|
||||
fun ensureEqualBytes(actual: Byte?, expected: Byte) = ensureEquals(actual, expected)
|
||||
fun ensureEqualShorts(actual: Short?, expected: Short) = ensureEquals(actual, expected)
|
||||
fun ensureEqualInts(actual: Int?, expected: Int) = ensureEquals(actual, expected)
|
||||
fun ensureEqualLongs(actual: Long?, expected: Long) = ensureEquals(actual, expected)
|
||||
fun ensureEqualUBytes(actual: UByte?, expected: UByte) = ensureEquals(actual, expected)
|
||||
fun ensureEqualUShorts(actual: UShort?, expected: UShort) = ensureEquals(actual, expected)
|
||||
fun ensureEqualUInts(actual: UInt?, expected: UInt) = ensureEquals(actual, expected)
|
||||
fun ensureEqualULongs(actual: ULong?, expected: ULong) = ensureEquals(actual, expected)
|
||||
fun ensureEqualFloats(actual: Float?, expected: Float) = ensureEquals(actual, expected)
|
||||
fun ensureEqualDoubles(actual: Double?, expected: Double) = ensureEquals(actual, expected)
|
||||
|
||||
// Boolean
|
||||
val boolVal: Boolean = true
|
||||
val boolAnyVal: Any = false
|
||||
|
||||
@@ -91,6 +91,116 @@ func testDoubles() throws {
|
||||
try assertEquals(actual: Values.infFloatVal, expected: -Float.infinity, "-Inf float")
|
||||
}
|
||||
|
||||
func testNumbers() throws {
|
||||
try assertEquals(actual: ValuesBoolean(value: true).boolValue, expected: true)
|
||||
try assertEquals(actual: ValuesBoolean(value: false).intValue, expected: 0)
|
||||
try assertEquals(actual: ValuesBoolean(value: true), expected: true)
|
||||
try assertFalse(ValuesBoolean(value: false) as! Bool)
|
||||
|
||||
try assertEquals(actual: ValuesByte(value: -1).int8Value, expected: -1)
|
||||
try assertEquals(actual: ValuesByte(value: -1).int32Value, expected: -1)
|
||||
try assertEquals(actual: ValuesByte(value: -1).doubleValue, expected: -1.0)
|
||||
try assertEquals(actual: ValuesByte(value: -1), expected: NSNumber(value: Int64(-1)))
|
||||
try assertFalse(ValuesByte(value: -1) == NSNumber(value: -1.5))
|
||||
try assertEquals(actual: ValuesByte(value: -1), expected: -1)
|
||||
try assertTrue(ValuesByte(value: -1) == -1)
|
||||
try assertFalse(ValuesByte(value: -1) == 1)
|
||||
try assertEquals(actual: ValuesByte(value: -1) as! Int32, expected: -1)
|
||||
|
||||
try assertEquals(actual: ValuesShort(value: 111).int16Value, expected: 111)
|
||||
try assertEquals(actual: ValuesShort(value: -15) as! Int16, expected: -15)
|
||||
try assertEquals(actual: ValuesShort(value: 47), expected: 47)
|
||||
|
||||
try assertEquals(actual: ValuesInt(value: 99).int32Value, expected: 99)
|
||||
try assertEquals(actual: ValuesInt(value: -1) as! Int32, expected: -1)
|
||||
try assertEquals(actual: ValuesInt(value: 72), expected: 72)
|
||||
|
||||
try assertEquals(actual: ValuesLong(value: 65).int64Value, expected: 65)
|
||||
try assertEquals(actual: ValuesLong(value: 10000000000) as! Int64, expected: 10000000000)
|
||||
try assertEquals(actual: ValuesLong(value: 8), expected: 8)
|
||||
|
||||
try assertEquals(actual: ValuesUByte(value: 17).uint8Value, expected: 17)
|
||||
try assertEquals(actual: ValuesUByte(value: 42) as! UInt8, expected: 42)
|
||||
try assertEquals(actual: 88, expected: ValuesUByte(value: 88))
|
||||
|
||||
try assertEquals(actual: ValuesUShort(value: 40000).uint16Value, expected: 40000)
|
||||
try assertEquals(actual: ValuesUShort(value: 1) as! UInt16, expected: UInt16(1))
|
||||
try assertEquals(actual: ValuesUShort(value: 65000), expected: 65000)
|
||||
|
||||
try assertEquals(actual: ValuesUInt(value: 3).uint32Value, expected: 3)
|
||||
try assertEquals(actual: ValuesUInt(value: UInt32.max) as! UInt32, expected: UInt32.max)
|
||||
try assertEquals(actual: ValuesUInt(value: 2), expected: 2)
|
||||
|
||||
try assertEquals(actual: ValuesULong(value: 55).uint64Value, expected: 55)
|
||||
try assertEquals(actual: ValuesULong(value: 0) as! UInt64, expected: 0)
|
||||
try assertEquals(actual: ValuesULong(value: 7), expected: 7)
|
||||
|
||||
try assertEquals(actual: ValuesFloat(value: 1.0).floatValue, expected: 1.0)
|
||||
try assertEquals(actual: ValuesFloat(value: 22.0) as! Float, expected: 22)
|
||||
try assertEquals(actual: ValuesFloat(value: 41.0), expected: 41)
|
||||
try assertEquals(actual: ValuesFloat(value: -5.5), expected: -5.5)
|
||||
|
||||
try assertEquals(actual: ValuesDouble(value: 0.5).doubleValue, expected: 0.5)
|
||||
try assertEquals(actual: ValuesDouble(value: 45.0) as! Double, expected: 45)
|
||||
try assertEquals(actual: ValuesDouble(value: 89.0), expected: 89)
|
||||
try assertEquals(actual: ValuesDouble(value: -3.7), expected: -3.7)
|
||||
|
||||
Values.ensureEqualBooleans(actual: ValuesBoolean(value: true), expected: true)
|
||||
Values.ensureEqualBooleans(actual: false, expected: false)
|
||||
|
||||
Values.ensureEqualBytes(actual: ValuesByte(value: 42), expected: 42)
|
||||
Values.ensureEqualBytes(actual: -11, expected: -11)
|
||||
|
||||
Values.ensureEqualShorts(actual: ValuesShort(value: 256), expected: 256)
|
||||
Values.ensureEqualShorts(actual: -1, expected: -1)
|
||||
|
||||
Values.ensureEqualInts(actual: ValuesInt(value: 100000), expected: 100000)
|
||||
Values.ensureEqualInts(actual: -7, expected: -7)
|
||||
|
||||
Values.ensureEqualLongs(actual: ValuesLong(value: Int64.max), expected: Int64.max)
|
||||
Values.ensureEqualLongs(actual: 17, expected: 17)
|
||||
|
||||
Values.ensureEqualUBytes(actual: ValuesUByte(value: 6), expected: 6)
|
||||
Values.ensureEqualUBytes(actual: 255, expected: 255)
|
||||
|
||||
Values.ensureEqualUShorts(actual: ValuesUShort(value: 300), expected: 300)
|
||||
Values.ensureEqualUShorts(actual: 65535, expected: UInt16.max)
|
||||
|
||||
Values.ensureEqualUInts(actual: ValuesUInt(value: 70000), expected: 70000)
|
||||
Values.ensureEqualUInts(actual: 48, expected: 48)
|
||||
|
||||
Values.ensureEqualULongs(actual: ValuesULong(value: UInt64.max), expected: UInt64.max)
|
||||
Values.ensureEqualULongs(actual: 39, expected: 39)
|
||||
|
||||
Values.ensureEqualFloats(actual: ValuesFloat(value: 36.6), expected: 36.6)
|
||||
Values.ensureEqualFloats(actual: 49.5, expected: 49.5)
|
||||
Values.ensureEqualFloats(actual: 18, expected: 18.0)
|
||||
|
||||
Values.ensureEqualDoubles(actual: ValuesDouble(value: 12.34), expected: 12.34)
|
||||
Values.ensureEqualDoubles(actual: 56.78, expected: 56.78)
|
||||
Values.ensureEqualDoubles(actual: 3, expected: 3)
|
||||
|
||||
func checkBox<T: Equatable, B : NSObject>(_ value: T, _ boxFunction: (T) -> B?) throws {
|
||||
let box = boxFunction(value)!
|
||||
try assertEquals(actual: box as! T, expected: value)
|
||||
print(type(of: box))
|
||||
print(B.self)
|
||||
try assertTrue(box.isKind(of: B.self))
|
||||
}
|
||||
|
||||
try checkBox(true, Values.box)
|
||||
try checkBox(Int8(-1), Values.box)
|
||||
try checkBox(Int16(-2), Values.box)
|
||||
try checkBox(Int32(-3), Values.box)
|
||||
try checkBox(Int64(-4), Values.box)
|
||||
try checkBox(UInt8(5), Values.box)
|
||||
try checkBox(UInt16(6), Values.box)
|
||||
try checkBox(UInt32(7), Values.box)
|
||||
try checkBox(UInt64(8), Values.box)
|
||||
try checkBox(Float(8.7), Values.box)
|
||||
try checkBox(Double(9.4), Values.box)
|
||||
}
|
||||
|
||||
func testLists() throws {
|
||||
let numbersList = Values.numbersList
|
||||
let gold = [1, 2, 13]
|
||||
@@ -307,6 +417,7 @@ class ValuesTests : TestProvider {
|
||||
TestCase(name: "TestValues", method: withAutorelease(testVals)),
|
||||
TestCase(name: "TestVars", method: withAutorelease(testVars)),
|
||||
TestCase(name: "TestDoubles", method: withAutorelease(testDoubles)),
|
||||
TestCase(name: "TestNumbers", method: withAutorelease(testNumbers)),
|
||||
TestCase(name: "TestLists", method: withAutorelease(testLists)),
|
||||
TestCase(name: "TestLazyValues", method: withAutorelease(testLazyVal)),
|
||||
TestCase(name: "TestDelegatedProperties", method: withAutorelease(testDelegatedProp)),
|
||||
|
||||
@@ -0,0 +1,710 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if KONAN_OBJC_INTEROP
|
||||
|
||||
#import <Foundation/NSDictionary.h>
|
||||
#import <Foundation/NSError.h>
|
||||
#import <Foundation/NSException.h>
|
||||
#import <Foundation/NSString.h>
|
||||
|
||||
#import "ObjCExport.h"
|
||||
#import "Runtime.h"
|
||||
#import "Utils.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
OBJ_GETTER(Kotlin_boxBoolean, KBoolean value);
|
||||
OBJ_GETTER(Kotlin_boxByte, KByte value);
|
||||
OBJ_GETTER(Kotlin_boxShort, KShort value);
|
||||
OBJ_GETTER(Kotlin_boxInt, KInt value);
|
||||
OBJ_GETTER(Kotlin_boxLong, KLong value);
|
||||
OBJ_GETTER(Kotlin_boxUByte, KUByte value);
|
||||
OBJ_GETTER(Kotlin_boxUShort, KUShort value);
|
||||
OBJ_GETTER(Kotlin_boxUInt, KUInt value);
|
||||
OBJ_GETTER(Kotlin_boxULong, KULong value);
|
||||
OBJ_GETTER(Kotlin_boxFloat, KFloat value);
|
||||
OBJ_GETTER(Kotlin_boxDouble, KDouble value);
|
||||
|
||||
}
|
||||
|
||||
#pragma clang diagnostic ignored "-Wobjc-designated-initializers"
|
||||
|
||||
@interface KotlinNumber : NSNumber
|
||||
@end;
|
||||
|
||||
[[ noreturn ]] static void incorrectNumberInitialization(KotlinNumber* self, SEL _cmd) {
|
||||
[NSException raise:NSGenericException format:@"%@ can't be initialized with %s, use properly typed initialized",
|
||||
NSStringFromClass([self class]), sel_getName(_cmd)];
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
[[ noreturn ]] static void incorrectNumberFactory(Class self, SEL _cmd) {
|
||||
[NSException raise:NSGenericException format:@"%@ can't be created with %s, use properly typed factory",
|
||||
NSStringFromClass(self), sel_getName(_cmd)];
|
||||
|
||||
abort();
|
||||
}
|
||||
|
||||
@implementation KotlinNumber : NSNumber
|
||||
|
||||
- (NSNumber *)initWithBool:(BOOL)value { incorrectNumberInitialization(self, _cmd); }
|
||||
- (NSNumber *)initWithChar:(char)value { incorrectNumberInitialization(self, _cmd); }
|
||||
- (NSNumber *)initWithShort:(short)value { incorrectNumberInitialization(self, _cmd); }
|
||||
- (NSNumber *)initWithInt:(int)value { incorrectNumberInitialization(self, _cmd); }
|
||||
- (NSNumber *)initWithInteger:(NSInteger)value { incorrectNumberInitialization(self, _cmd); }
|
||||
- (NSNumber *)initWithLong:(long)value { incorrectNumberInitialization(self, _cmd); }
|
||||
- (NSNumber *)initWithLongLong:(long long)value { incorrectNumberInitialization(self, _cmd); }
|
||||
- (NSNumber *)initWithUnsignedChar:(unsigned char)value { incorrectNumberInitialization(self, _cmd); }
|
||||
- (NSNumber *)initWithUnsignedShort:(unsigned short)value { incorrectNumberInitialization(self, _cmd); }
|
||||
- (NSNumber *)initWithUnsignedInt:(unsigned int)value { incorrectNumberInitialization(self, _cmd); }
|
||||
- (NSNumber *)initWithUnsignedInteger:(NSUInteger)value { incorrectNumberInitialization(self, _cmd); }
|
||||
- (NSNumber *)initWithUnsignedLong:(unsigned long)value { incorrectNumberInitialization(self, _cmd); }
|
||||
- (NSNumber *)initWithUnsignedLongLong:(unsigned long long)value { incorrectNumberInitialization(self, _cmd); }
|
||||
- (NSNumber *)initWithFloat:(float)value { incorrectNumberInitialization(self, _cmd); }
|
||||
- (NSNumber *)initWithDouble:(double)value { incorrectNumberInitialization(self, _cmd); }
|
||||
|
||||
+ (NSNumber *)numberWithBool:(BOOL)value { incorrectNumberFactory(self, _cmd); }
|
||||
+ (NSNumber *)numberWithChar:(char)value { incorrectNumberFactory(self, _cmd); }
|
||||
+ (NSNumber *)numberWithShort:(short)value { incorrectNumberFactory(self, _cmd); }
|
||||
+ (NSNumber *)numberWithInt:(int)value { incorrectNumberFactory(self, _cmd); }
|
||||
+ (NSNumber *)numberWithInteger:(NSInteger)value { incorrectNumberFactory(self, _cmd); }
|
||||
+ (NSNumber *)numberWithLong:(long)value { incorrectNumberFactory(self, _cmd); }
|
||||
+ (NSNumber *)numberWithLongLong:(long long)value { incorrectNumberFactory(self, _cmd); }
|
||||
+ (NSNumber *)numberWithUnsignedChar:(unsigned char)value { incorrectNumberFactory(self, _cmd); }
|
||||
+ (NSNumber *)numberWithUnsignedShort:(unsigned short)value { incorrectNumberFactory(self, _cmd); }
|
||||
+ (NSNumber *)numberWithUnsignedInt:(unsigned int)value { incorrectNumberFactory(self, _cmd); }
|
||||
+ (NSNumber *)numberWithUnsignedLong:(unsigned long)value { incorrectNumberFactory(self, _cmd); }
|
||||
+ (NSNumber *)numberWithUnsignedInteger:(NSUInteger)value { incorrectNumberFactory(self, _cmd); }
|
||||
+ (NSNumber *)numberWithUnsignedLongLong:(unsigned long long)value { incorrectNumberFactory(self, _cmd); }
|
||||
+ (NSNumber *)numberWithFloat:(float)value { incorrectNumberFactory(self, _cmd); }
|
||||
+ (NSNumber *)numberWithDouble:(double)value { incorrectNumberFactory(self, _cmd); }
|
||||
|
||||
@end;
|
||||
|
||||
/*
|
||||
The code below is generated by:
|
||||
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
println(genBoolean())
|
||||
println(genInteger("Byte", "c", "char"))
|
||||
println(genInteger("Short", "s", "short"))
|
||||
println(genInteger("Int", "i", "int"))
|
||||
println(genInteger("Long", "q", "long long"))
|
||||
println(genInteger("UByte", "C", "unsigned char"))
|
||||
println(genInteger("UShort", "S", "unsigned short"))
|
||||
println(genInteger("UInt", "I", "unsigned int"))
|
||||
println(genInteger("ULong", "Q", "unsigned long long"))
|
||||
println(genFloating("Float", "f", "float"))
|
||||
println(genFloating("Double", "d", "double"))
|
||||
}
|
||||
|
||||
private fun genBoolean(): String = """
|
||||
@interface KotlinBoolean : KotlinNumber
|
||||
@end;
|
||||
|
||||
@implementation KotlinBoolean {
|
||||
BOOL value_;
|
||||
}
|
||||
|
||||
- (instancetype)initWithBool:(BOOL)value {
|
||||
self = [super init];
|
||||
value_ = value;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)numberWithBool:(BOOL)value {
|
||||
KotlinBoolean* result = [[self new] autorelease];
|
||||
result->value_ = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
- (BOOL)boolValue {
|
||||
return value_;
|
||||
}
|
||||
|
||||
- (char)charValue {
|
||||
return value_;
|
||||
}
|
||||
|
||||
- (const char *)objCType {
|
||||
return "c";
|
||||
}
|
||||
|
||||
-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT {
|
||||
RETURN_RESULT_OF(Kotlin_boxBoolean, value_);
|
||||
}
|
||||
|
||||
@end;
|
||||
|
||||
""".trimIndent()
|
||||
|
||||
private fun genInteger(
|
||||
name: String,
|
||||
encoding: String,
|
||||
cType: String,
|
||||
kind: String = getNSNumberKind(cType)
|
||||
) = """
|
||||
@interface Kotlin$name : KotlinNumber
|
||||
@end;
|
||||
|
||||
@implementation Kotlin$name {
|
||||
$cType value_;
|
||||
}
|
||||
|
||||
- (instancetype)initWith${kind.capitalize()}:($cType)value {
|
||||
self = [super init];
|
||||
value_ = value;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)numberWith${kind.capitalize()}:($cType)value {
|
||||
Kotlin$name* result = [[self new] autorelease];
|
||||
result->value_ = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Required to convert Swift integer literals.
|
||||
- (instancetype)initWithInteger:(NSInteger)value {
|
||||
self = [super init];
|
||||
value_ = value; // TODO: check fits.
|
||||
return self;
|
||||
}
|
||||
|
||||
- ($cType)${kind}Value {
|
||||
return value_;
|
||||
}
|
||||
|
||||
- (const char *)objCType {
|
||||
return "$encoding";
|
||||
}
|
||||
|
||||
-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT {
|
||||
RETURN_RESULT_OF(Kotlin_box$name, value_);
|
||||
}
|
||||
|
||||
@end;
|
||||
|
||||
""".trimIndent()
|
||||
|
||||
private fun getNSNumberKind(cType: String) =
|
||||
cType.split(' ').joinToString("") { it.capitalize() }.decapitalize()
|
||||
|
||||
private fun genFloating(
|
||||
name: String,
|
||||
encoding: String,
|
||||
cType: String,
|
||||
kind: String = getNSNumberKind(cType)
|
||||
): String = """
|
||||
@interface Kotlin$name : KotlinNumber
|
||||
@end;
|
||||
|
||||
@implementation Kotlin$name {
|
||||
$cType value_;
|
||||
}
|
||||
|
||||
- (instancetype)initWith${kind.capitalize()}:($cType)value {
|
||||
self = [super init];
|
||||
value_ = value;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)numberWith${kind.capitalize()}:($cType)value {
|
||||
Kotlin$name* result = [[self new] autorelease];
|
||||
result->value_ = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Required to convert Swift integer literals.
|
||||
- (instancetype)initWithInteger:(NSInteger)value {
|
||||
self = [super init];
|
||||
value_ = value; // TODO: check fits.
|
||||
return self;
|
||||
}
|
||||
${if (cType != "double") """
|
||||
// Required to convert Swift floating literals.
|
||||
- (instancetype)initWithDouble:(double)value {
|
||||
self = [super init];
|
||||
value_ = value; // TODO: check fits.
|
||||
return self;
|
||||
}
|
||||
""" else ""}
|
||||
- ($cType)${kind}Value {
|
||||
return value_;
|
||||
}
|
||||
|
||||
- (const char *)objCType {
|
||||
return "$encoding";
|
||||
}
|
||||
|
||||
-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT {
|
||||
RETURN_RESULT_OF(Kotlin_box$name, value_);
|
||||
}
|
||||
|
||||
@end;
|
||||
|
||||
""".trimIndent()
|
||||
*/
|
||||
|
||||
// TODO: consider generating it by compiler.
|
||||
|
||||
@interface KotlinBoolean : KotlinNumber
|
||||
@end;
|
||||
|
||||
@implementation KotlinBoolean {
|
||||
BOOL value_;
|
||||
}
|
||||
|
||||
- (instancetype)initWithBool:(BOOL)value {
|
||||
self = [super init];
|
||||
value_ = value;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)numberWithBool:(BOOL)value {
|
||||
KotlinBoolean* result = [[self new] autorelease];
|
||||
result->value_ = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
- (BOOL)boolValue {
|
||||
return value_;
|
||||
}
|
||||
|
||||
- (char)charValue {
|
||||
return value_;
|
||||
}
|
||||
|
||||
- (const char *)objCType {
|
||||
return "c";
|
||||
}
|
||||
|
||||
-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT {
|
||||
RETURN_RESULT_OF(Kotlin_boxBoolean, value_);
|
||||
}
|
||||
|
||||
@end;
|
||||
|
||||
@interface KotlinByte : KotlinNumber
|
||||
@end;
|
||||
|
||||
@implementation KotlinByte {
|
||||
char value_;
|
||||
}
|
||||
|
||||
- (instancetype)initWithChar:(char)value {
|
||||
self = [super init];
|
||||
value_ = value;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)numberWithChar:(char)value {
|
||||
KotlinByte* result = [[self new] autorelease];
|
||||
result->value_ = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Required to convert Swift integer literals.
|
||||
- (instancetype)initWithInteger:(NSInteger)value {
|
||||
self = [super init];
|
||||
value_ = value; // TODO: check fits.
|
||||
return self;
|
||||
}
|
||||
|
||||
- (char)charValue {
|
||||
return value_;
|
||||
}
|
||||
|
||||
- (const char *)objCType {
|
||||
return "c";
|
||||
}
|
||||
|
||||
-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT {
|
||||
RETURN_RESULT_OF(Kotlin_boxByte, value_);
|
||||
}
|
||||
|
||||
@end;
|
||||
|
||||
@interface KotlinShort : KotlinNumber
|
||||
@end;
|
||||
|
||||
@implementation KotlinShort {
|
||||
short value_;
|
||||
}
|
||||
|
||||
- (instancetype)initWithShort:(short)value {
|
||||
self = [super init];
|
||||
value_ = value;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)numberWithShort:(short)value {
|
||||
KotlinShort* result = [[self new] autorelease];
|
||||
result->value_ = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Required to convert Swift integer literals.
|
||||
- (instancetype)initWithInteger:(NSInteger)value {
|
||||
self = [super init];
|
||||
value_ = value; // TODO: check fits.
|
||||
return self;
|
||||
}
|
||||
|
||||
- (short)shortValue {
|
||||
return value_;
|
||||
}
|
||||
|
||||
- (const char *)objCType {
|
||||
return "s";
|
||||
}
|
||||
|
||||
-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT {
|
||||
RETURN_RESULT_OF(Kotlin_boxShort, value_);
|
||||
}
|
||||
|
||||
@end;
|
||||
|
||||
@interface KotlinInt : KotlinNumber
|
||||
@end;
|
||||
|
||||
@implementation KotlinInt {
|
||||
int value_;
|
||||
}
|
||||
|
||||
- (instancetype)initWithInt:(int)value {
|
||||
self = [super init];
|
||||
value_ = value;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)numberWithInt:(int)value {
|
||||
KotlinInt* result = [[self new] autorelease];
|
||||
result->value_ = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Required to convert Swift integer literals.
|
||||
- (instancetype)initWithInteger:(NSInteger)value {
|
||||
self = [super init];
|
||||
value_ = value; // TODO: check fits.
|
||||
return self;
|
||||
}
|
||||
|
||||
- (int)intValue {
|
||||
return value_;
|
||||
}
|
||||
|
||||
- (const char *)objCType {
|
||||
return "i";
|
||||
}
|
||||
|
||||
-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT {
|
||||
RETURN_RESULT_OF(Kotlin_boxInt, value_);
|
||||
}
|
||||
|
||||
@end;
|
||||
|
||||
@interface KotlinLong : KotlinNumber
|
||||
@end;
|
||||
|
||||
@implementation KotlinLong {
|
||||
long long value_;
|
||||
}
|
||||
|
||||
- (instancetype)initWithLongLong:(long long)value {
|
||||
self = [super init];
|
||||
value_ = value;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)numberWithLongLong:(long long)value {
|
||||
KotlinLong* result = [[self new] autorelease];
|
||||
result->value_ = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Required to convert Swift integer literals.
|
||||
- (instancetype)initWithInteger:(NSInteger)value {
|
||||
self = [super init];
|
||||
value_ = value; // TODO: check fits.
|
||||
return self;
|
||||
}
|
||||
|
||||
- (long long)longLongValue {
|
||||
return value_;
|
||||
}
|
||||
|
||||
- (const char *)objCType {
|
||||
return "q";
|
||||
}
|
||||
|
||||
-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT {
|
||||
RETURN_RESULT_OF(Kotlin_boxLong, value_);
|
||||
}
|
||||
|
||||
@end;
|
||||
|
||||
@interface KotlinUByte : KotlinNumber
|
||||
@end;
|
||||
|
||||
@implementation KotlinUByte {
|
||||
unsigned char value_;
|
||||
}
|
||||
|
||||
- (instancetype)initWithUnsignedChar:(unsigned char)value {
|
||||
self = [super init];
|
||||
value_ = value;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)numberWithUnsignedChar:(unsigned char)value {
|
||||
KotlinUByte* result = [[self new] autorelease];
|
||||
result->value_ = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Required to convert Swift integer literals.
|
||||
- (instancetype)initWithInteger:(NSInteger)value {
|
||||
self = [super init];
|
||||
value_ = value; // TODO: check fits.
|
||||
return self;
|
||||
}
|
||||
|
||||
- (unsigned char)unsignedCharValue {
|
||||
return value_;
|
||||
}
|
||||
|
||||
- (const char *)objCType {
|
||||
return "C";
|
||||
}
|
||||
|
||||
-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT {
|
||||
RETURN_RESULT_OF(Kotlin_boxUByte, value_);
|
||||
}
|
||||
|
||||
@end;
|
||||
|
||||
@interface KotlinUShort : KotlinNumber
|
||||
@end;
|
||||
|
||||
@implementation KotlinUShort {
|
||||
unsigned short value_;
|
||||
}
|
||||
|
||||
- (instancetype)initWithUnsignedShort:(unsigned short)value {
|
||||
self = [super init];
|
||||
value_ = value;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)numberWithUnsignedShort:(unsigned short)value {
|
||||
KotlinUShort* result = [[self new] autorelease];
|
||||
result->value_ = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Required to convert Swift integer literals.
|
||||
- (instancetype)initWithInteger:(NSInteger)value {
|
||||
self = [super init];
|
||||
value_ = value; // TODO: check fits.
|
||||
return self;
|
||||
}
|
||||
|
||||
- (unsigned short)unsignedShortValue {
|
||||
return value_;
|
||||
}
|
||||
|
||||
- (const char *)objCType {
|
||||
return "S";
|
||||
}
|
||||
|
||||
-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT {
|
||||
RETURN_RESULT_OF(Kotlin_boxUShort, value_);
|
||||
}
|
||||
|
||||
@end;
|
||||
|
||||
@interface KotlinUInt : KotlinNumber
|
||||
@end;
|
||||
|
||||
@implementation KotlinUInt {
|
||||
unsigned int value_;
|
||||
}
|
||||
|
||||
- (instancetype)initWithUnsignedInt:(unsigned int)value {
|
||||
self = [super init];
|
||||
value_ = value;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)numberWithUnsignedInt:(unsigned int)value {
|
||||
KotlinUInt* result = [[self new] autorelease];
|
||||
result->value_ = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Required to convert Swift integer literals.
|
||||
- (instancetype)initWithInteger:(NSInteger)value {
|
||||
self = [super init];
|
||||
value_ = value; // TODO: check fits.
|
||||
return self;
|
||||
}
|
||||
|
||||
- (unsigned int)unsignedIntValue {
|
||||
return value_;
|
||||
}
|
||||
|
||||
- (const char *)objCType {
|
||||
return "I";
|
||||
}
|
||||
|
||||
-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT {
|
||||
RETURN_RESULT_OF(Kotlin_boxUInt, value_);
|
||||
}
|
||||
|
||||
@end;
|
||||
|
||||
@interface KotlinULong : KotlinNumber
|
||||
@end;
|
||||
|
||||
@implementation KotlinULong {
|
||||
unsigned long long value_;
|
||||
}
|
||||
|
||||
- (instancetype)initWithUnsignedLongLong:(unsigned long long)value {
|
||||
self = [super init];
|
||||
value_ = value;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)numberWithUnsignedLongLong:(unsigned long long)value {
|
||||
KotlinULong* result = [[self new] autorelease];
|
||||
result->value_ = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Required to convert Swift integer literals.
|
||||
- (instancetype)initWithInteger:(NSInteger)value {
|
||||
self = [super init];
|
||||
value_ = value; // TODO: check fits.
|
||||
return self;
|
||||
}
|
||||
|
||||
- (unsigned long long)unsignedLongLongValue {
|
||||
return value_;
|
||||
}
|
||||
|
||||
- (const char *)objCType {
|
||||
return "Q";
|
||||
}
|
||||
|
||||
-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT {
|
||||
RETURN_RESULT_OF(Kotlin_boxULong, value_);
|
||||
}
|
||||
|
||||
@end;
|
||||
|
||||
@interface KotlinFloat : KotlinNumber
|
||||
@end;
|
||||
|
||||
@implementation KotlinFloat {
|
||||
float value_;
|
||||
}
|
||||
|
||||
- (instancetype)initWithFloat:(float)value {
|
||||
self = [super init];
|
||||
value_ = value;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)numberWithFloat:(float)value {
|
||||
KotlinFloat* result = [[self new] autorelease];
|
||||
result->value_ = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Required to convert Swift integer literals.
|
||||
- (instancetype)initWithInteger:(NSInteger)value {
|
||||
self = [super init];
|
||||
value_ = value; // TODO: check fits.
|
||||
return self;
|
||||
}
|
||||
|
||||
// Required to convert Swift floating literals.
|
||||
- (instancetype)initWithDouble:(double)value {
|
||||
self = [super init];
|
||||
value_ = value; // TODO: check fits.
|
||||
return self;
|
||||
}
|
||||
|
||||
- (float)floatValue {
|
||||
return value_;
|
||||
}
|
||||
|
||||
- (const char *)objCType {
|
||||
return "f";
|
||||
}
|
||||
|
||||
-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT {
|
||||
RETURN_RESULT_OF(Kotlin_boxFloat, value_);
|
||||
}
|
||||
|
||||
@end;
|
||||
|
||||
@interface KotlinDouble : KotlinNumber
|
||||
@end;
|
||||
|
||||
@implementation KotlinDouble {
|
||||
double value_;
|
||||
}
|
||||
|
||||
- (instancetype)initWithDouble:(double)value {
|
||||
self = [super init];
|
||||
value_ = value;
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)numberWithDouble:(double)value {
|
||||
KotlinDouble* result = [[self new] autorelease];
|
||||
result->value_ = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Required to convert Swift integer literals.
|
||||
- (instancetype)initWithInteger:(NSInteger)value {
|
||||
self = [super init];
|
||||
value_ = value; // TODO: check fits.
|
||||
return self;
|
||||
}
|
||||
|
||||
- (double)doubleValue {
|
||||
return value_;
|
||||
}
|
||||
|
||||
- (const char *)objCType {
|
||||
return "d";
|
||||
}
|
||||
|
||||
-(ObjHeader*)toKotlin:(ObjHeader**)OBJ_RESULT {
|
||||
RETURN_RESULT_OF(Kotlin_boxDouble, value_);
|
||||
}
|
||||
|
||||
@end;
|
||||
|
||||
#endif // KONAN_OBJC_INTEROP
|
||||
Reference in New Issue
Block a user