mirror of
https://github.com/odin-lang/Odin.git
synced 2026-02-18 17:08:21 +00:00
Add more objc attributes
This commit is contained in:
@@ -3,26 +3,40 @@ package objc_Foundation
|
||||
import "core:intrinsics"
|
||||
|
||||
@(objc_class="NSArray")
|
||||
Array :: struct($T: typeid) where intrinsics.type_is_pointer(T), intrinsics.type_is_subtype_of(T, ^Object) {
|
||||
using _: Copying(Array(T)),
|
||||
Array :: struct {
|
||||
using _: Copying(Array),
|
||||
}
|
||||
|
||||
Array_initWithObjects :: proc(self: ^$A/Array($T), objects: [^]^Object, count: UInteger) -> ^A {
|
||||
return msgSend(^A, "initWithObjects:count:", objects, count)
|
||||
@(objc_type=Array, objc_class_name="alloc")
|
||||
Array_alloc :: proc() -> ^Array {
|
||||
return msgSend(^Array, Array, "alloc")
|
||||
}
|
||||
|
||||
Array_initWithCoder :: proc(self: ^$A/Array($T), coder: ^Coder) -> ^A {
|
||||
return msgSend(^A, "initWithCoder:", coder)
|
||||
@(objc_type=Array, objc_name="init")
|
||||
Array_init :: proc(self: ^Array) -> ^Array {
|
||||
return msgSend(^Array, self, "init")
|
||||
}
|
||||
|
||||
Array_objectAtIndex :: proc(self: ^Array($T), index: UInteger) -> ^Object {
|
||||
@(objc_type=Array, objc_name="initWithObjects")
|
||||
Array_initWithObjects :: proc(self: ^Array, objects: [^]^Object, count: UInteger) -> ^Array {
|
||||
return msgSend(^Array, self, "initWithObjects:count:", objects, count)
|
||||
}
|
||||
|
||||
@(objc_type=Array, objc_name="initWithCoder")
|
||||
Array_initWithCoder :: proc(self: ^Array, coder: ^Coder) -> ^Array {
|
||||
return msgSend(^Array, self, "initWithCoder:", coder)
|
||||
}
|
||||
|
||||
@(objc_type=Array, objc_name="object")
|
||||
Array_object :: proc(self: ^Array, index: UInteger) -> ^Object {
|
||||
return msgSend(^Object, self, "objectAtIndex:", index)
|
||||
}
|
||||
|
||||
Array_object :: proc(self: ^Array($T), index: UInteger) -> T {
|
||||
return (T)(Array_objectAtIndex(self, index))
|
||||
@(objc_type=Array, objc_name="objectAs")
|
||||
Array_objectAs :: proc(self: ^Array, index: UInteger, $T: typeid) -> T where intrinsics.type_is_pointer(T), intrinsics.type_is_subtype_of(T, ^Object) {
|
||||
return (T)(Array_object(self, index))
|
||||
}
|
||||
|
||||
Array_count :: proc(self: ^Array($T)) -> UInteger {
|
||||
@(objc_type=Array, objc_name="count")
|
||||
Array_count :: proc(self: ^Array) -> UInteger {
|
||||
return msgSend(UInteger, self, "count")
|
||||
}
|
||||
|
||||
@@ -3,12 +3,25 @@ package objc_Foundation
|
||||
@(objc_class="NSAutoreleasePool")
|
||||
AutoreleasePool :: struct {using _: Object}
|
||||
|
||||
@(objc_type=AutoreleasePool, objc_class_name="alloc")
|
||||
AutoreleasePool_alloc :: proc() -> ^AutoreleasePool {
|
||||
return msgSend(^AutoreleasePool, AutoreleasePool, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=AutoreleasePool, objc_name="init")
|
||||
AutoreleasePool_init :: proc(self: ^AutoreleasePool) -> ^AutoreleasePool {
|
||||
return msgSend(^AutoreleasePool, self, "init")
|
||||
}
|
||||
|
||||
@(objc_type=AutoreleasePool, objc_name="drain")
|
||||
AutoreleasePool_drain :: proc(self: ^AutoreleasePool) {
|
||||
msgSend(nil, self, "drain")
|
||||
}
|
||||
@(objc_type=AutoreleasePool, objc_name="addObject")
|
||||
AutoreleasePool_addObject :: proc(self: ^AutoreleasePool, obj: ^Object) {
|
||||
msgSend(nil, self, "addObject:", obj)
|
||||
}
|
||||
@(objc_type=AutoreleasePool, objc_name="showPools")
|
||||
AutoreleasePool_showPools :: proc(self: ^AutoreleasePool, obj: ^Object) {
|
||||
msgSend(nil, self, "showPools")
|
||||
}
|
||||
@@ -16,5 +29,5 @@ AutoreleasePool_showPools :: proc(self: ^AutoreleasePool, obj: ^Object) {
|
||||
|
||||
@(deferred_out=AutoreleasePool_drain)
|
||||
scoped_autoreleasepool :: proc() -> ^AutoreleasePool {
|
||||
return init(alloc(AutoreleasePool))
|
||||
return AutoreleasePool.alloc()->init()
|
||||
}
|
||||
@@ -3,98 +3,120 @@ package objc_Foundation
|
||||
@(objc_class="NSBundle")
|
||||
Bundle :: struct { using _: Object }
|
||||
|
||||
@(objc_type=Bundle, objc_class_name="mainBundle")
|
||||
Bundle_mainBundle :: proc() -> ^Bundle {
|
||||
return msgSend(^Bundle, Bundle, "mainBundle")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_class_name="bundleWithPath")
|
||||
Bundle_bundleWithPath :: proc(path: ^String) -> ^Bundle {
|
||||
return msgSend(^Bundle, Bundle, "bundleWithPath:", path)
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_class_name="bundleWithURL")
|
||||
Bundle_bundleWithURL :: proc(url: ^URL) -> ^Bundle {
|
||||
return msgSend(^Bundle, Bundle, "bundleWithUrl:", url)
|
||||
}
|
||||
Bundle_bundle :: proc{
|
||||
Bundle_bundleWithPath,
|
||||
Bundle_bundleWithURL,
|
||||
|
||||
|
||||
@(objc_type=Bundle, objc_class_name="alloc")
|
||||
Bundle_alloc :: proc() -> ^Bundle {
|
||||
return msgSend(^Bundle, Bundle, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="init")
|
||||
Bundle_init :: proc(self: ^Bundle) -> ^Bundle {
|
||||
return msgSend(^Bundle, self, "init")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="initWithPath")
|
||||
Bundle_initWithPath :: proc(self: ^Bundle, path: ^String) -> ^Bundle {
|
||||
return msgSend(^Bundle, self, "initWithPath:", path)
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="initWithURL")
|
||||
Bundle_initWithURL :: proc(self: ^Bundle, url: ^URL) -> ^Bundle {
|
||||
return msgSend(^Bundle, self, "initWithUrl:", url)
|
||||
}
|
||||
Bundle_init :: proc{
|
||||
Bundle_initWithPath,
|
||||
Bundle_initWithURL,
|
||||
}
|
||||
|
||||
|
||||
Bundle_allBundles :: proc() -> (all: ^Array(^Bundle)) {
|
||||
@(objc_type=Bundle, objc_name="allBundles")
|
||||
Bundle_allBundles :: proc() -> (all: ^Array) {
|
||||
return msgSend(type_of(all), Bundle, "allBundles")
|
||||
}
|
||||
|
||||
Bundle_allFrameworks :: proc() -> (all: ^Array(^Object)) {
|
||||
@(objc_type=Bundle, objc_name="allFrameworks")
|
||||
Bundle_allFrameworks :: proc() -> (all: ^Array) {
|
||||
return msgSend(type_of(all), Bundle, "allFrameworks")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="load")
|
||||
Bundle_load :: proc(self: ^Bundle) -> BOOL {
|
||||
return msgSend(BOOL, self, "load")
|
||||
}
|
||||
@(objc_type=Bundle, objc_name="unload")
|
||||
Bundle_unload :: proc(self: ^Bundle) -> BOOL {
|
||||
return msgSend(BOOL, self, "unload")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="isLoaded")
|
||||
Bundle_isLoaded :: proc(self: ^Bundle) -> BOOL {
|
||||
return msgSend(BOOL, self, "isLoaded")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="preflightAndReturnError")
|
||||
Bundle_preflightAndReturnError :: proc(self: ^Bundle) -> (ok: BOOL, error: ^Error) {
|
||||
ok = msgSend(BOOL, self, "preflightAndReturnError:", &error)
|
||||
return
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="loadAndReturnError")
|
||||
Bundle_loadAndReturnError :: proc(self: ^Bundle) -> (ok: BOOL, error: ^Error) {
|
||||
ok = msgSend(BOOL, self, "loadAndReturnError:", &error)
|
||||
return
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="bundleURL")
|
||||
Bundle_bundleURL :: proc(self: ^Bundle) -> ^URL {
|
||||
return msgSend(^URL, self, "bundleURL")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="resourceURL")
|
||||
Bundle_resourceURL :: proc(self: ^Bundle) -> ^URL {
|
||||
return msgSend(^URL, self, "resourceURL")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="executableURL")
|
||||
Bundle_executableURL :: proc(self: ^Bundle) -> ^URL {
|
||||
return msgSend(^URL, self, "executableURL")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="URLForAuxiliaryExecutable")
|
||||
Bundle_URLForAuxiliaryExecutable :: proc(self: ^Bundle, executableName: ^String) -> ^URL {
|
||||
return msgSend(^URL, self, "URLForAuxiliaryExecutable:", executableName)
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="privateFrameworksURL")
|
||||
Bundle_privateFrameworksURL :: proc(self: ^Bundle) -> ^URL {
|
||||
return msgSend(^URL, self, "privateFrameworksURL")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="sharedFrameworksURL")
|
||||
Bundle_sharedFrameworksURL :: proc(self: ^Bundle) -> ^URL {
|
||||
return msgSend(^URL, self, "sharedFrameworksURL")
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Bundle, objc_name="sharedSupportURL")
|
||||
Bundle_sharedSupportURL :: proc(self: ^Bundle) -> ^URL {
|
||||
return msgSend(^URL, self, "sharedSupportURL")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="builtInPlugInsURL")
|
||||
Bundle_builtInPlugInsURL :: proc(self: ^Bundle) -> ^URL {
|
||||
return msgSend(^URL, self, "builtInPlugInsURL")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="appStoreReceiptURL")
|
||||
Bundle_appStoreReceiptURL :: proc(self: ^Bundle) -> ^URL {
|
||||
return msgSend(^URL, self, "appStoreReceiptURL")
|
||||
}
|
||||
@@ -102,60 +124,74 @@ Bundle_appStoreReceiptURL :: proc(self: ^Bundle) -> ^URL {
|
||||
|
||||
|
||||
|
||||
@(objc_type=Bundle, objc_name="bundlePath")
|
||||
Bundle_bundlePath :: proc(self: ^Bundle) -> ^String {
|
||||
return msgSend(^String, self, "bundlePath")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="resourcePath")
|
||||
Bundle_resourcePath :: proc(self: ^Bundle) -> ^String {
|
||||
return msgSend(^String, self, "resourcePath")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="executablePath")
|
||||
Bundle_executablePath :: proc(self: ^Bundle) -> ^String {
|
||||
return msgSend(^String, self, "executablePath")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="PathForAuxiliaryExecutable")
|
||||
Bundle_PathForAuxiliaryExecutable :: proc(self: ^Bundle, executableName: ^String) -> ^String {
|
||||
return msgSend(^String, self, "PathForAuxiliaryExecutable:", executableName)
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="privateFrameworksPath")
|
||||
Bundle_privateFrameworksPath :: proc(self: ^Bundle) -> ^String {
|
||||
return msgSend(^String, self, "privateFrameworksPath")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="sharedFrameworksPath")
|
||||
Bundle_sharedFrameworksPath :: proc(self: ^Bundle) -> ^String {
|
||||
return msgSend(^String, self, "sharedFrameworksPath")
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Bundle, objc_name="sharedSupportPath")
|
||||
Bundle_sharedSupportPath :: proc(self: ^Bundle) -> ^String {
|
||||
return msgSend(^String, self, "sharedSupportPath")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="builtInPlugInsPath")
|
||||
Bundle_builtInPlugInsPath :: proc(self: ^Bundle) -> ^String {
|
||||
return msgSend(^String, self, "builtInPlugInsPath")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="appStoreReceiptPath")
|
||||
Bundle_appStoreReceiptPath :: proc(self: ^Bundle) -> ^String {
|
||||
return msgSend(^String, self, "appStoreReceiptPath")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="bundleIdentifier")
|
||||
Bundle_bundleIdentifier :: proc(self: ^Bundle) -> ^String {
|
||||
return msgSend(^String, self, "bundleIdentifier")
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Bundle, objc_name="infoDictionary")
|
||||
Bundle_infoDictionary :: proc(self: ^Bundle) -> ^Dictionary {
|
||||
return msgSend(^Dictionary, self, "infoDictionary")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="localizedInfoDictionary")
|
||||
Bundle_localizedInfoDictionary :: proc(self: ^Bundle) -> ^Dictionary {
|
||||
return msgSend(^Dictionary, self, "localizedInfoDictionary")
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="objectForInfoDictionaryKey")
|
||||
Bundle_objectForInfoDictionaryKey :: proc(self: ^Bundle, key: ^String) -> ^Object {
|
||||
return msgSend(^Object, self, "objectForInfoDictionaryKey:", key)
|
||||
}
|
||||
|
||||
@(objc_type=Bundle, objc_name="localizedStringForKey")
|
||||
Bundle_localizedStringForKey :: proc(self: ^Bundle, key: ^String, value: ^String = nil, tableName: ^String = nil) -> ^String {
|
||||
return msgSend(^String, self, "localizedStringForKey:value:table:", key, value, tableName)
|
||||
}
|
||||
|
||||
@@ -3,10 +3,22 @@ package objc_Foundation
|
||||
@(objc_class="NSData")
|
||||
Data :: struct {using _: Copying(Data)}
|
||||
|
||||
@(objc_type=Data, objc_class_name="alloc")
|
||||
Data_alloc :: proc() -> ^Data {
|
||||
return msgSend(^Data, Data, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=Data, objc_name="init")
|
||||
Data_init :: proc(self: ^Data) -> ^Data {
|
||||
return msgSend(^Data, self, "init")
|
||||
}
|
||||
|
||||
@(objc_type=Data, objc_name="mutableBytes")
|
||||
Data_mutableBytes :: proc(self: ^Data) -> rawptr {
|
||||
return msgSend(rawptr, self, "mutableBytes")
|
||||
}
|
||||
|
||||
@(objc_type=Data, objc_name="length")
|
||||
Data_length :: proc(self: ^Data) -> UInteger {
|
||||
return msgSend(UInteger, self, "length")
|
||||
}
|
||||
@@ -3,6 +3,18 @@ package objc_Foundation
|
||||
@(objc_class="NSDate")
|
||||
Date :: struct {using _: Copying(Date)}
|
||||
|
||||
@(objc_type=Date, objc_class_name="alloc")
|
||||
Date_alloc :: proc() -> ^Date {
|
||||
return msgSend(^Date, Date, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=Date, objc_name="init")
|
||||
Date_init :: proc(self: ^Date) -> ^Date {
|
||||
return msgSend(^Date, self, "init")
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Date, objc_name="dateWithTimeIntervalSinceNow")
|
||||
Date_dateWithTimeIntervalSinceNow :: proc(secs: TimeInterval) -> ^Date {
|
||||
return msgSend(^Date, Date, "dateWithTimeIntervalSinceNow:", secs)
|
||||
}
|
||||
@@ -3,31 +3,49 @@ package objc_Foundation
|
||||
@(objc_class="NSDictionary")
|
||||
Dictionary :: struct {using _: Copying(Dictionary)}
|
||||
|
||||
@(objc_type=Dictionary, objc_class_name="dictionary")
|
||||
Dictionary_dictionary :: proc() -> ^Dictionary {
|
||||
return msgSend(^Dictionary, Dictionary, "dictionary")
|
||||
}
|
||||
|
||||
@(objc_type=Dictionary, objc_class_name="dictionaryWithObject")
|
||||
Dictionary_dictionaryWithObject :: proc(object: ^Object, forKey: ^Object) -> ^Dictionary {
|
||||
return msgSend(^Dictionary, Dictionary, "dictionaryWithObject:forKey:", object, forKey)
|
||||
}
|
||||
|
||||
@(objc_type=Dictionary, objc_class_name="dictionaryWithObjects")
|
||||
Dictionary_dictionaryWithObjects :: proc(objects: [^]^Object, forKeys: [^]^Object, count: UInteger) -> ^Dictionary {
|
||||
return msgSend(^Dictionary, Dictionary, "dictionaryWithObjects:forKeys:count", objects, forKeys, count)
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Dictionary, objc_class_name="alloc")
|
||||
Dictionary_alloc :: proc() -> ^Dictionary {
|
||||
return msgSend(^Dictionary, Dictionary, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=Dictionary, objc_name="init")
|
||||
Dictionary_init :: proc(self: ^Dictionary) -> ^Dictionary {
|
||||
return msgSend(^Dictionary, self, "init")
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Dictionary, objc_name="initWithObjects")
|
||||
Dictionary_initWithObjects :: proc(self: ^Dictionary, objects: [^]^Object, forKeys: [^]^Object, count: UInteger) -> ^Dictionary {
|
||||
return msgSend(^Dictionary, self, "initWithObjects:forKeys:count", objects, forKeys, count)
|
||||
}
|
||||
|
||||
@(objc_type=Dictionary, objc_name="objectForKey")
|
||||
Dictionary_objectForKey :: proc(self: ^Dictionary, key: ^Object) -> ^Object {
|
||||
return msgSend(^Dictionary, self, "objectForKey:", key)
|
||||
}
|
||||
|
||||
@(objc_type=Dictionary, objc_name="count")
|
||||
Dictionary_count :: proc(self: ^Dictionary) -> UInteger {
|
||||
return msgSend(UInteger, self, "count")
|
||||
}
|
||||
|
||||
@(objc_type=Dictionary, objc_name="keyEnumerator")
|
||||
Dictionary_keyEnumerator :: proc(self: ^Dictionary, $KeyType: typeid) -> (enumerator: ^Enumerator(KeyType)) {
|
||||
return msgSend(type_of(enumerator), self, "keyEnumerator")
|
||||
}
|
||||
|
||||
@@ -18,6 +18,19 @@ Enumerator :: struct($T: typeid) where intrinsics.type_is_pointer(T), intrinsics
|
||||
using _: FastEnumeration,
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=FastEnumeration, objc_class_name="alloc")
|
||||
FastEnumeration_alloc :: proc() -> ^FastEnumeration {
|
||||
return msgSend(^FastEnumeration, FastEnumeration, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=FastEnumeration, objc_name="init")
|
||||
FastEnumeration_init :: proc(self: ^FastEnumeration) -> ^FastEnumeration {
|
||||
return msgSend(^FastEnumeration, self, "init")
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=FastEnumeration, objc_name="countByEnumerating")
|
||||
FastEnumeration_countByEnumerating :: proc(self: ^FastEnumeration, state: ^FastEnumerationState, buffer: [^]^Object, len: UInteger) -> UInteger {
|
||||
return msgSend(UInteger, self, "countByEnumeratingWithState:objects:count:", state, buffer, len)
|
||||
}
|
||||
@@ -26,7 +39,7 @@ Enumerator_nextObject :: proc(self: ^$E/Enumerator($T)) -> T {
|
||||
return msgSend(T, self, "nextObject")
|
||||
}
|
||||
|
||||
Enumerator_allObjects :: proc(self: ^$E/Enumerator($T)) -> (all: Array(T)) {
|
||||
Enumerator_allObjects :: proc(self: ^$E/Enumerator($T)) -> (all: ^Array) {
|
||||
return msgSend(type_of(all), self, "allObjects")
|
||||
}
|
||||
|
||||
|
||||
@@ -31,38 +31,58 @@ foreign Foundation {
|
||||
@(objc_class="NSError")
|
||||
Error :: struct { using _: Copying(Error) }
|
||||
|
||||
|
||||
@(objc_type=Error, objc_class_name="alloc")
|
||||
Error_alloc :: proc() -> ^Error {
|
||||
return msgSend(^Error, Error, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=Error, objc_name="init")
|
||||
Error_init :: proc(self: ^Error) -> ^Error {
|
||||
return msgSend(^Error, self, "init")
|
||||
}
|
||||
|
||||
@(objc_type=Error, objc_class_name="errorWithDomain")
|
||||
Error_errorWithDomain :: proc(domain: ErrorDomain, code: Integer, userInfo: ^Dictionary) -> ^Error {
|
||||
return msgSend(^Error, Error, "errorWithDomain:code:userInfo:", domain, code, userInfo)
|
||||
}
|
||||
|
||||
@(objc_type=Error, objc_name="initWithDomain")
|
||||
Error_initWithDomain :: proc(self: ^Error, domain: ErrorDomain, code: Integer, userInfo: ^Dictionary) -> ^Error {
|
||||
return msgSend(^Error, self, "initWithDomain:code:userInfo:", domain, code, userInfo)
|
||||
}
|
||||
|
||||
@(objc_type=Error, objc_name="code")
|
||||
Error_code :: proc(self: ^Error) -> Integer {
|
||||
return msgSend(Integer, self, "code")
|
||||
}
|
||||
|
||||
@(objc_type=Error, objc_name="domain")
|
||||
Error_domain :: proc(self: ^Error) -> ErrorDomain {
|
||||
return msgSend(ErrorDomain, self, "domain")
|
||||
}
|
||||
|
||||
@(objc_type=Error, objc_name="userInfo")
|
||||
Error_userInfo :: proc(self: ^Error) -> ^Dictionary {
|
||||
return msgSend(^Dictionary, self, "userInfo")
|
||||
}
|
||||
|
||||
@(objc_type=Error, objc_name="localizedDescription")
|
||||
Error_localizedDescription :: proc(self: ^Error) -> ^String {
|
||||
return msgSend(^String, self, "localizedDescription")
|
||||
}
|
||||
|
||||
Error_localizedRecoveryOptions :: proc(self: ^Error) -> (options: ^Array(^Object)) {
|
||||
@(objc_type=Error, objc_name="localizedRecoveryOptions")
|
||||
Error_localizedRecoveryOptions :: proc(self: ^Error) -> (options: ^Array) {
|
||||
return msgSend(type_of(options), self, "localizedRecoveryOptions")
|
||||
}
|
||||
|
||||
@(objc_type=Error, objc_name="localizedRecoverySuggestion")
|
||||
Error_localizedRecoverySuggestion :: proc(self: ^Error) -> ^String {
|
||||
return msgSend(^String, self, "localizedRecoverySuggestion")
|
||||
}
|
||||
|
||||
@(objc_type=Error, objc_name="localizedFailureReason")
|
||||
Error_localizedFailureReason :: proc(self: ^Error) -> ^String {
|
||||
return msgSend(^String, self, "localizedFailureReason")
|
||||
}
|
||||
@@ -12,18 +12,42 @@ Locking_unlock :: proc(self: ^Locking($T)) {
|
||||
@(objc_class="NSCondition")
|
||||
Condition :: struct {using _: Locking(Condition) }
|
||||
|
||||
|
||||
@(objc_type=Condition, objc_class_name="alloc")
|
||||
Condition_alloc :: proc() -> ^Condition {
|
||||
return msgSend(^Condition, Condition, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=Condition, objc_name="init")
|
||||
Condition_init :: proc(self: ^Condition) -> ^Condition {
|
||||
return msgSend(^Condition, self, "init")
|
||||
}
|
||||
|
||||
@(objc_type=Condition, objc_name="wait")
|
||||
Condition_wait :: proc(self: ^Condition) {
|
||||
msgSend(nil, self, "wait")
|
||||
}
|
||||
|
||||
@(objc_type=Condition, objc_name="waitUntilDate")
|
||||
Condition_waitUntilDate :: proc(self: ^Condition, limit: ^Date) -> BOOL {
|
||||
return msgSend(BOOL, self, "waitUntilDate:", limit)
|
||||
}
|
||||
|
||||
@(objc_type=Condition, objc_name="signal")
|
||||
Condition_signal :: proc(self: ^Condition) {
|
||||
msgSend(nil, self, "signal")
|
||||
}
|
||||
|
||||
@(objc_type=Condition, objc_name="broadcast")
|
||||
Condition_broadcast :: proc(self: ^Condition) {
|
||||
msgSend(nil, self, "broadcast")
|
||||
}
|
||||
|
||||
@(objc_type=Condition, objc_name="lock")
|
||||
Condition_lock :: proc(self: ^Condition) {
|
||||
msgSend(nil, self, "lock")
|
||||
}
|
||||
@(objc_type=Condition, objc_name="unlock")
|
||||
Condition_unlock :: proc(self: ^Condition) {
|
||||
msgSend(nil, self, "unlock")
|
||||
}
|
||||
@@ -3,14 +3,29 @@ package objc_Foundation
|
||||
@(objc_class="NSNotification")
|
||||
Notification :: struct{using _: Object}
|
||||
|
||||
|
||||
@(objc_type=Notification, objc_class_name="alloc")
|
||||
Notification_alloc :: proc() -> ^Notification {
|
||||
return msgSend(^Notification, Notification, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=Notification, objc_name="init")
|
||||
Notification_init :: proc(self: ^Notification) -> ^Notification {
|
||||
return msgSend(^Notification, self, "init")
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Notification, objc_name="name")
|
||||
Notification_name :: proc(self: ^Notification) -> ^String {
|
||||
return msgSend(^String, self, "name")
|
||||
}
|
||||
|
||||
@(objc_type=Notification, objc_name="object")
|
||||
Notification_object :: proc(self: ^Notification) -> ^Object {
|
||||
return msgSend(^Object, self, "object")
|
||||
}
|
||||
|
||||
@(objc_type=Notification, objc_name="userInfo")
|
||||
Notification_userInfo :: proc(self: ^Notification) -> ^Dictionary {
|
||||
return msgSend(^Dictionary, self, "userInfo")
|
||||
}
|
||||
@@ -8,35 +8,53 @@ import "core:c"
|
||||
@(objc_class="NSValue")
|
||||
Value :: struct{using _: Copying(Value)}
|
||||
|
||||
@(objc_type=Value, objc_class_name="alloc")
|
||||
Value_alloc :: proc() -> ^Value {
|
||||
return msgSend(^Value, Value, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=Value, objc_name="init")
|
||||
Value_init :: proc(self: ^Value) -> ^Value {
|
||||
return msgSend(^Value, self, "init")
|
||||
}
|
||||
|
||||
@(objc_type=Value, objc_class_name="valueWithBytes")
|
||||
Value_valueWithBytes :: proc(value: rawptr, type: cstring) -> ^Value {
|
||||
return msgSend(^Value, Value, "valueWithBytes:objCType:", value, type)
|
||||
}
|
||||
|
||||
@(objc_type=Value, objc_class_name="valueWithPointer")
|
||||
Value_valueWithPointer :: proc(pointer: rawptr) -> ^Value {
|
||||
return msgSend(^Value, Value, "valueWithPointer:", pointer)
|
||||
}
|
||||
|
||||
@(objc_type=Value, objc_name="initWithBytes")
|
||||
Value_initWithBytes :: proc(self: ^Value, value: rawptr, type: cstring) -> ^Value {
|
||||
return msgSend(^Value, self, "initWithBytes:objCType:", value, type)
|
||||
}
|
||||
|
||||
Value_initWithCoder :: proc(coder: ^Coder) -> ^Value {
|
||||
return msgSend(^Value, Value, "initWithCoder:", coder)
|
||||
@(objc_type=Value, objc_name="initWithCoder")
|
||||
Value_initWithCoder :: proc(self: ^Value, coder: ^Coder) -> ^Value {
|
||||
return msgSend(^Value, self, "initWithCoder:", coder)
|
||||
}
|
||||
|
||||
@(objc_type=Value, objc_name="getValue")
|
||||
Value_getValue :: proc(self: ^Value, value: rawptr, size: UInteger) {
|
||||
msgSend(nil, self, "getValue:size:", value, size)
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Value, objc_name="objCType")
|
||||
Value_objCType :: proc(self: ^Value) -> cstring {
|
||||
return msgSend(cstring, self, "objCType")
|
||||
}
|
||||
|
||||
@(objc_type=Value, objc_name="isEqualToValue")
|
||||
Value_isEqualToValue :: proc(self, other: ^Value) -> BOOL {
|
||||
return msgSend(BOOL, self, "isEqualToValue:", other)
|
||||
}
|
||||
|
||||
@(objc_type=Value, objc_name="pointerValue")
|
||||
Value_pointerValue :: proc(self: ^Value) -> rawptr {
|
||||
return msgSend(rawptr, self, "pointerValue")
|
||||
}
|
||||
@@ -46,19 +64,29 @@ Value_pointerValue :: proc(self: ^Value) -> rawptr {
|
||||
Number :: struct{using _: Copying(Number), using _: Value}
|
||||
|
||||
|
||||
Number_numberWithI8 :: proc(value: i8) -> ^Number { return msgSend(^Number, Number, "numberWithChar:", value) }
|
||||
Number_numberWithU8 :: proc(value: u8) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedChar:", value) }
|
||||
Number_numberWithI16 :: proc(value: i16) -> ^Number { return msgSend(^Number, Number, "numberWithShort:", value) }
|
||||
Number_numberWithU16 :: proc(value: u16) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedShort:", value) }
|
||||
Number_numberWithI32 :: proc(value: i32) -> ^Number { return msgSend(^Number, Number, "numberWithInt:", value) }
|
||||
Number_numberWithU32 :: proc(value: u32) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedInt:", value) }
|
||||
Number_numberWithInt :: proc(value: int) -> ^Number { return msgSend(^Number, Number, "numberWithLong:", value) }
|
||||
Number_numberWithUint :: proc(value: uint) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedLong:", value) }
|
||||
Number_numberWithU64 :: proc(value: u64) -> ^Number { return msgSend(^Number, Number, "numberWithLongLong:", value) }
|
||||
Number_numberWithI64 :: proc(value: i64) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedLongLong:", value) }
|
||||
Number_numberWithF32 :: proc(value: f32) -> ^Number { return msgSend(^Number, Number, "numberWithFloat:", value) }
|
||||
Number_numberWithF64 :: proc(value: f64) -> ^Number { return msgSend(^Number, Number, "numberWithDouble:", value) }
|
||||
Number_numberWithBool :: proc(value: BOOL) -> ^Number { return msgSend(^Number, Number, "numberWithBool:", value) }
|
||||
@(objc_type=Number, objc_class_name="alloc")
|
||||
Number_alloc :: proc() -> ^Number {
|
||||
return msgSend(^Number, Number, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=Number, objc_name="init")
|
||||
Number_init :: proc(self: ^Number) -> ^Number {
|
||||
return msgSend(^Number, self, "init")
|
||||
}
|
||||
|
||||
@(objc_type=Number, objc_class_name="numberWithI8") Number_numberWithI8 :: proc(value: i8) -> ^Number { return msgSend(^Number, Number, "numberWithChar:", value) }
|
||||
@(objc_type=Number, objc_class_name="numberWithU8") Number_numberWithU8 :: proc(value: u8) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedChar:", value) }
|
||||
@(objc_type=Number, objc_class_name="numberWithI16") Number_numberWithI16 :: proc(value: i16) -> ^Number { return msgSend(^Number, Number, "numberWithShort:", value) }
|
||||
@(objc_type=Number, objc_class_name="numberWithU16") Number_numberWithU16 :: proc(value: u16) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedShort:", value) }
|
||||
@(objc_type=Number, objc_class_name="numberWithI32") Number_numberWithI32 :: proc(value: i32) -> ^Number { return msgSend(^Number, Number, "numberWithInt:", value) }
|
||||
@(objc_type=Number, objc_class_name="numberWithU32") Number_numberWithU32 :: proc(value: u32) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedInt:", value) }
|
||||
@(objc_type=Number, objc_class_name="numberWithInt") Number_numberWithInt :: proc(value: int) -> ^Number { return msgSend(^Number, Number, "numberWithLong:", value) }
|
||||
@(objc_type=Number, objc_class_name="numberWithUint") Number_numberWithUint :: proc(value: uint) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedLong:", value) }
|
||||
@(objc_type=Number, objc_class_name="numberWithU64") Number_numberWithU64 :: proc(value: u64) -> ^Number { return msgSend(^Number, Number, "numberWithLongLong:", value) }
|
||||
@(objc_type=Number, objc_class_name="numberWithI64") Number_numberWithI64 :: proc(value: i64) -> ^Number { return msgSend(^Number, Number, "numberWithUnsignedLongLong:", value) }
|
||||
@(objc_type=Number, objc_class_name="numberWithF32") Number_numberWithF32 :: proc(value: f32) -> ^Number { return msgSend(^Number, Number, "numberWithFloat:", value) }
|
||||
@(objc_type=Number, objc_class_name="numberWithF64") Number_numberWithF64 :: proc(value: f64) -> ^Number { return msgSend(^Number, Number, "numberWithDouble:", value) }
|
||||
@(objc_type=Number, objc_class_name="numberWithBool") Number_numberWithBool :: proc(value: BOOL) -> ^Number { return msgSend(^Number, Number, "numberWithBool:", value) }
|
||||
|
||||
Number_number :: proc{
|
||||
Number_numberWithI8,
|
||||
@@ -76,62 +104,49 @@ Number_number :: proc{
|
||||
Number_numberWithBool,
|
||||
}
|
||||
|
||||
Number_initWithI8 :: proc(self: ^Number, value: i8) -> ^Number { return msgSend(^Number, self, "initWithChar:", value) }
|
||||
Number_initWithU8 :: proc(self: ^Number, value: u8) -> ^Number { return msgSend(^Number, self, "initWithUnsignedChar:", value) }
|
||||
Number_initWithI16 :: proc(self: ^Number, value: i16) -> ^Number { return msgSend(^Number, self, "initWithShort:", value) }
|
||||
Number_initWithU16 :: proc(self: ^Number, value: u16) -> ^Number { return msgSend(^Number, self, "initWithUnsignedShort:", value) }
|
||||
Number_initWithI32 :: proc(self: ^Number, value: i32) -> ^Number { return msgSend(^Number, self, "initWithInt:", value) }
|
||||
Number_initWithU32 :: proc(self: ^Number, value: u32) -> ^Number { return msgSend(^Number, self, "initWithUnsignedInt:", value) }
|
||||
Number_initWithInt :: proc(self: ^Number, value: int) -> ^Number { return msgSend(^Number, self, "initWithLong:", value) }
|
||||
Number_initWithUint :: proc(self: ^Number, value: uint) -> ^Number { return msgSend(^Number, self, "initWithUnsignedLong:", value) }
|
||||
Number_initWithU64 :: proc(self: ^Number, value: u64) -> ^Number { return msgSend(^Number, self, "initWithLongLong:", value) }
|
||||
Number_initWithI64 :: proc(self: ^Number, value: i64) -> ^Number { return msgSend(^Number, self, "initWithUnsignedLongLong:", value) }
|
||||
Number_initWithF32 :: proc(self: ^Number, value: f32) -> ^Number { return msgSend(^Number, self, "initWithFloat:", value) }
|
||||
Number_initWithF64 :: proc(self: ^Number, value: f64) -> ^Number { return msgSend(^Number, self, "initWithDouble:", value) }
|
||||
Number_initWithBool :: proc(self: ^Number, value: BOOL) -> ^Number { return msgSend(^Number, self, "initWithBool:", value) }
|
||||
@(objc_type=Number, objc_name="initWithI8") Number_initWithI8 :: proc(self: ^Number, value: i8) -> ^Number { return msgSend(^Number, self, "initWithChar:", value) }
|
||||
@(objc_type=Number, objc_name="initWithU8") Number_initWithU8 :: proc(self: ^Number, value: u8) -> ^Number { return msgSend(^Number, self, "initWithUnsignedChar:", value) }
|
||||
@(objc_type=Number, objc_name="initWithI16") Number_initWithI16 :: proc(self: ^Number, value: i16) -> ^Number { return msgSend(^Number, self, "initWithShort:", value) }
|
||||
@(objc_type=Number, objc_name="initWithU16") Number_initWithU16 :: proc(self: ^Number, value: u16) -> ^Number { return msgSend(^Number, self, "initWithUnsignedShort:", value) }
|
||||
@(objc_type=Number, objc_name="initWithI32") Number_initWithI32 :: proc(self: ^Number, value: i32) -> ^Number { return msgSend(^Number, self, "initWithInt:", value) }
|
||||
@(objc_type=Number, objc_name="initWithU32") Number_initWithU32 :: proc(self: ^Number, value: u32) -> ^Number { return msgSend(^Number, self, "initWithUnsignedInt:", value) }
|
||||
@(objc_type=Number, objc_name="initWithInt") Number_initWithInt :: proc(self: ^Number, value: int) -> ^Number { return msgSend(^Number, self, "initWithLong:", value) }
|
||||
@(objc_type=Number, objc_name="initWithUint") Number_initWithUint :: proc(self: ^Number, value: uint) -> ^Number { return msgSend(^Number, self, "initWithUnsignedLong:", value) }
|
||||
@(objc_type=Number, objc_name="initWithU64") Number_initWithU64 :: proc(self: ^Number, value: u64) -> ^Number { return msgSend(^Number, self, "initWithLongLong:", value) }
|
||||
@(objc_type=Number, objc_name="initWithI64") Number_initWithI64 :: proc(self: ^Number, value: i64) -> ^Number { return msgSend(^Number, self, "initWithUnsignedLongLong:", value) }
|
||||
@(objc_type=Number, objc_name="initWithF32") Number_initWithF32 :: proc(self: ^Number, value: f32) -> ^Number { return msgSend(^Number, self, "initWithFloat:", value) }
|
||||
@(objc_type=Number, objc_name="initWithF64") Number_initWithF64 :: proc(self: ^Number, value: f64) -> ^Number { return msgSend(^Number, self, "initWithDouble:", value) }
|
||||
@(objc_type=Number, objc_name="initWithBool") Number_initWithBool :: proc(self: ^Number, value: BOOL) -> ^Number { return msgSend(^Number, self, "initWithBool:", value) }
|
||||
|
||||
|
||||
Number_init :: proc{
|
||||
Number_initWithI8,
|
||||
Number_initWithU8,
|
||||
Number_initWithI16,
|
||||
Number_initWithU16,
|
||||
Number_initWithI32,
|
||||
Number_initWithU32,
|
||||
Number_initWithInt,
|
||||
Number_initWithUint,
|
||||
Number_initWithU64,
|
||||
Number_initWithI64,
|
||||
Number_initWithF32,
|
||||
Number_initWithF64,
|
||||
Number_initWithBool,
|
||||
@(objc_type=Number, objc_name="i8Value") Number_i8Value :: proc(self: ^Number) -> i8 { return msgSend(i8, self, "charValue") }
|
||||
@(objc_type=Number, objc_name="u8Value") Number_u8Value :: proc(self: ^Number) -> u8 { return msgSend(u8, self, "unsignedCharValue") }
|
||||
@(objc_type=Number, objc_name="i16Value") Number_i16Value :: proc(self: ^Number) -> i16 { return msgSend(i16, self, "shortValue") }
|
||||
@(objc_type=Number, objc_name="u16Value") Number_u16Value :: proc(self: ^Number) -> u16 { return msgSend(u16, self, "unsignedShortValue") }
|
||||
@(objc_type=Number, objc_name="i32Value") Number_i32Value :: proc(self: ^Number) -> i32 { return msgSend(i32, self, "intValue") }
|
||||
@(objc_type=Number, objc_name="u32Value") Number_u32Value :: proc(self: ^Number) -> u32 { return msgSend(u32, self, "unsignedIntValue") }
|
||||
@(objc_type=Number, objc_name="intValue") Number_intValue :: proc(self: ^Number) -> int { return msgSend(int, self, "longValue") }
|
||||
@(objc_type=Number, objc_name="uintValue") Number_uintValue :: proc(self: ^Number) -> uint { return msgSend(uint, self, "unsignedLongValue") }
|
||||
@(objc_type=Number, objc_name="u64Value") Number_u64Value :: proc(self: ^Number) -> u64 { return msgSend(u64, self, "longLongValue") }
|
||||
@(objc_type=Number, objc_name="i64Value") Number_i64Value :: proc(self: ^Number) -> i64 { return msgSend(i64, self, "unsignedLongLongValue") }
|
||||
@(objc_type=Number, objc_name="f32Value") Number_f32Value :: proc(self: ^Number) -> f32 { return msgSend(f32, self, "floatValue") }
|
||||
@(objc_type=Number, objc_name="f64Value") Number_f64Value :: proc(self: ^Number) -> f64 { return msgSend(f64, self, "doubleValue") }
|
||||
@(objc_type=Number, objc_name="boolValue") Number_boolValue :: proc(self: ^Number) -> BOOL { return msgSend(BOOL, self, "boolValue") }
|
||||
@(objc_type=Number, objc_name="integerValue") Number_integerValue :: proc(self: ^Number) -> Integer { return msgSend(Integer, self, "integerValue") }
|
||||
@(objc_type=Number, objc_name="uintegerValue") Number_uintegerValue :: proc(self: ^Number) -> UInteger { return msgSend(UInteger, self, "unsignedIntegerValue") }
|
||||
@(objc_type=Number, objc_name="stringValue") Number_stringValue :: proc(self: ^Number) -> ^String { return msgSend(^String, self, "stringValue") }
|
||||
|
||||
@(objc_type=Number, objc_name="compare")
|
||||
Number_compare :: proc(self, other: ^Number) -> ComparisonResult {
|
||||
return msgSend(ComparisonResult, self, "compare:", other)
|
||||
}
|
||||
|
||||
Number_i8Value :: proc(self: ^Number) -> i8 { return msgSend(i8, self, "charValue") }
|
||||
Number_u8Value :: proc(self: ^Number) -> u8 { return msgSend(u8, self, "unsignedCharValue") }
|
||||
Number_i16Value :: proc(self: ^Number) -> i16 { return msgSend(i16, self, "shortValue") }
|
||||
Number_u16Value :: proc(self: ^Number) -> u16 { return msgSend(u16, self, "unsignedShortValue") }
|
||||
Number_i32Value :: proc(self: ^Number) -> i32 { return msgSend(i32, self, "intValue") }
|
||||
Number_u32Value :: proc(self: ^Number) -> u32 { return msgSend(u32, self, "unsignedIntValue") }
|
||||
Number_intValue :: proc(self: ^Number) -> int { return msgSend(int, self, "longValue") }
|
||||
Number_uintValue :: proc(self: ^Number) -> uint { return msgSend(uint, self, "unsignedLongValue") }
|
||||
Number_u64Value :: proc(self: ^Number) -> u64 { return msgSend(u64, self, "longLongValue") }
|
||||
Number_i64Value :: proc(self: ^Number) -> i64 { return msgSend(i64, self, "unsignedLongLongValue") }
|
||||
Number_f32Value :: proc(self: ^Number) -> f32 { return msgSend(f32, self, "floatValue") }
|
||||
Number_f64Value :: proc(self: ^Number) -> f64 { return msgSend(f64, self, "doubleValue") }
|
||||
Number_boolValue :: proc(self: ^Number) -> BOOL { return msgSend(BOOL, self, "boolValue") }
|
||||
Number_integerValue :: proc(self: ^Number) -> Integer { return msgSend(Integer, self, "integerValue") }
|
||||
Number_uintegerValue :: proc(self: ^Number) -> UInteger { return msgSend(UInteger, self, "unsignedIntegerValue") }
|
||||
Number_stringValue :: proc(self: ^Number) -> ^String { return msgSend(^String, self, "stringValue") }
|
||||
|
||||
Number_compare :: proc(a, b: ^Number) -> ComparisonResult {
|
||||
return msgSend(ComparisonResult, a, "compare:", b)
|
||||
}
|
||||
|
||||
Number_isEqualToNumber :: proc(a, b: ^Number) -> BOOL {
|
||||
return msgSend(BOOL, a, "isEqualToNumber:", b)
|
||||
@(objc_type=Number, objc_name="isEqualToNumber")
|
||||
Number_isEqualToNumber :: proc(self, other: ^Number) -> BOOL {
|
||||
return msgSend(BOOL, self, "isEqualToNumber:", other)
|
||||
}
|
||||
|
||||
@(objc_type=Number, objc_name="descriptionWithLocale")
|
||||
Number_descriptionWithLocale :: proc(self: ^Number, locale: ^Object) -> ^String {
|
||||
return msgSend(^String, self, "descriptionWithLocale:", locale)
|
||||
}
|
||||
@@ -27,37 +27,45 @@ alloc :: proc($T: typeid) -> ^T where intrinsics.type_is_subtype_of(T, Object) {
|
||||
init :: proc(self: ^$T) -> ^T where intrinsics.type_is_subtype_of(T, Object) {
|
||||
return msgSend(^T, self, "init")
|
||||
}
|
||||
retain :: proc(self: ^$T) -> ^T where intrinsics.type_is_subtype_of(T, Object) {
|
||||
return msgSend(^T, self, "retain")
|
||||
}
|
||||
release :: proc(self: ^$T) where intrinsics.type_is_subtype_of(T, Object) {
|
||||
msgSend(nil, self, "release")
|
||||
}
|
||||
autorelease :: proc(self: ^$T) where intrinsics.type_is_subtype_of(T, Object) {
|
||||
msgSend(nil, self, "autorelease")
|
||||
}
|
||||
retainCount :: proc(self: ^$T) -> UInteger where intrinsics.type_is_subtype_of(T, Object) {
|
||||
return msgSend(UInteger, self, "retainCount")
|
||||
}
|
||||
|
||||
|
||||
copy :: proc(self: ^Copying($T)) -> ^T where intrinsics.type_is_subtype_of(T, Object) {
|
||||
return msgSend(^T, self, "copy")
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Object, objc_name="retain")
|
||||
retain :: proc(self: ^Object) {
|
||||
_ = msgSend(^Object, self, "retain")
|
||||
}
|
||||
@(objc_type=Object, objc_name="release")
|
||||
release :: proc(self: ^Object) {
|
||||
msgSend(nil, self, "release")
|
||||
}
|
||||
@(objc_type=Object, objc_name="autorelease")
|
||||
autorelease :: proc(self: ^Object) {
|
||||
msgSend(nil, self, "autorelease")
|
||||
}
|
||||
@(objc_type=Object, objc_name="retainCount")
|
||||
retainCount :: proc(self: ^Object) -> UInteger {
|
||||
return msgSend(UInteger, self, "retainCount")
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=Object, objc_name="hash")
|
||||
hash :: proc(self: ^Object) -> UInteger {
|
||||
return msgSend(UInteger, self, "hash")
|
||||
}
|
||||
|
||||
@(objc_type=Object, objc_name="isEqual")
|
||||
isEqual :: proc(self, pObject: ^Object) -> BOOL {
|
||||
return msgSend(BOOL, self, "isEqual:", pObject)
|
||||
}
|
||||
|
||||
@(objc_type=Object, objc_name="description")
|
||||
description :: proc(self: ^Object) -> ^String {
|
||||
return msgSend(^String, self, "description")
|
||||
}
|
||||
|
||||
@(objc_type=Object, objc_name="debugDescription")
|
||||
debugDescription :: proc(self: ^Object) -> ^String {
|
||||
if msgSendSafeCheck(self, intrinsics.objc_selector_name("debugDescription")) {
|
||||
return msgSend(^String, self, "debugDescription")
|
||||
|
||||
@@ -59,54 +59,78 @@ MakeConstantString :: proc "c" (#const c: cstring) -> ^String {
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=String, objc_class_name="alloc")
|
||||
String_alloc :: proc() -> ^String {
|
||||
return msgSend(^String, String, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="init")
|
||||
String_init :: proc(self: ^String) -> ^String {
|
||||
return msgSend(^String, self, "init")
|
||||
}
|
||||
|
||||
|
||||
@(objc_type=String, objc_name="initWithString")
|
||||
String_initWithString :: proc(self: ^String, other: ^String) -> ^String {
|
||||
return msgSend(^String, self, "initWithString:", other)
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="initWithCString")
|
||||
String_initWithCString :: proc(self: ^String, pString: cstring, encoding: StringEncoding) -> ^String {
|
||||
return msgSend(^String, self, "initWithCstring:encoding:", pString, encoding)
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="initWithBytesNoCopy")
|
||||
String_initWithBytesNoCopy :: proc(self: ^String, pBytes: rawptr, length: UInteger, encoding: StringEncoding, freeWhenDone: bool) -> ^String {
|
||||
return msgSend(^String, self, "initWithBytesNoCopy:length:encoding:freeWhenDone:", pBytes, length, encoding, freeWhenDone)
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="initWithOdinString")
|
||||
String_initWithOdinString :: proc(self: ^String, str: string) -> ^String {
|
||||
return String_initWithBytesNoCopy(self, raw_data(str), UInteger(len(str)), .UTF8, false)
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="characterAtIndex")
|
||||
String_characterAtIndex :: proc(self: ^String, index: UInteger) -> unichar {
|
||||
return msgSend(unichar, self, "characterAtIndex:", index)
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="length")
|
||||
String_length :: proc(self: ^String) -> UInteger {
|
||||
return msgSend(UInteger, self, "length")
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="cStringUsingEncoding")
|
||||
String_cStringUsingEncoding :: proc(self: ^String, encoding: StringEncoding) -> cstring {
|
||||
return msgSend(cstring, self, "cStringUsingEncoding:", encoding)
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="UTF8String")
|
||||
String_UTF8String :: proc(self: ^String) -> cstring {
|
||||
return msgSend(cstring, self, "UTF8String")
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="OdinString")
|
||||
String_OdinString :: proc(self: ^String) -> string {
|
||||
return string(String_UTF8String(self))
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="maximumLengthOfBytesUsingEncoding")
|
||||
String_maximumLengthOfBytesUsingEncoding :: proc(self: ^String, encoding: StringEncoding) -> UInteger {
|
||||
return msgSend(UInteger, self, "maximumLengthOfBytesUsingEncoding:", encoding)
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="lengthOfBytesUsingEncoding")
|
||||
String_lengthOfBytesUsingEncoding :: proc(self: ^String, encoding: StringEncoding) -> UInteger {
|
||||
return msgSend(UInteger, self, "lengthOfBytesUsingEncoding:", encoding)
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="isEqualToString")
|
||||
String_isEqualToString :: proc(self, other: ^String) -> BOOL {
|
||||
return msgSend(BOOL, self, "isEqualToString:", other)
|
||||
}
|
||||
|
||||
@(objc_type=String, objc_name="rangeOfString")
|
||||
String_rangeOfString :: proc(self, other: ^String, options: StringCompareOptions) -> Range {
|
||||
return msgSend(Range, self, "rangeOfString:options:", other, options)
|
||||
}
|
||||
@@ -3,6 +3,18 @@ package objc_Foundation
|
||||
@(objc_class="NSURL")
|
||||
URL :: struct{using _: Copying(URL)}
|
||||
|
||||
|
||||
@(objc_type=URL, objc_class_name="alloc")
|
||||
URL_alloc :: proc() -> ^URL {
|
||||
return msgSend(^URL, URL, "alloc")
|
||||
}
|
||||
|
||||
@(objc_type=URL, objc_name="init")
|
||||
URL_init :: proc(self: ^URL) -> ^URL {
|
||||
return msgSend(^URL, self, "init")
|
||||
}
|
||||
|
||||
|
||||
URL_initWithString :: proc(self: ^URL, value: ^String) -> ^URL {
|
||||
return msgSend(^URL, self, "initWithString:", value)
|
||||
}
|
||||
|
||||
@@ -287,15 +287,13 @@ bool check_builtin_objc_procedure(CheckerContext *c, Operand *operand, Ast *call
|
||||
Operand self = {};
|
||||
check_expr_or_type(c, &self, ce->args[1]);
|
||||
if (self.mode == Addressing_Type) {
|
||||
if (!internal_check_is_assignable_to(self.type, t_objc_object)) {
|
||||
if (!is_type_objc_object(self.type)) {
|
||||
gbString t = type_to_string(self.type);
|
||||
error(self.expr, "'%.*s' expected a type or value derived from intrinsics.objc_object, got type %s", LIT(builtin_name), t);
|
||||
gb_string_free(t);
|
||||
return false;
|
||||
}
|
||||
if (!(self.type->kind == Type_Named &&
|
||||
self.type->Named.type_name != nullptr &&
|
||||
self.type->Named.type_name->TypeName.objc_class_name != "")) {
|
||||
if (!has_type_got_objc_class_attribute(self.type)) {
|
||||
gbString t = type_to_string(self.type);
|
||||
error(self.expr, "'%.*s' expected a named type with the attribute @(obj_class=<string>) , got type %s", LIT(builtin_name), t);
|
||||
gb_string_free(t);
|
||||
@@ -306,7 +304,7 @@ bool check_builtin_objc_procedure(CheckerContext *c, Operand *operand, Ast *call
|
||||
} else if (!is_operand_value(self) || !check_is_assignable_to(c, &self, t_objc_id)) {
|
||||
gbString e = expr_to_string(self.expr);
|
||||
gbString t = type_to_string(self.type);
|
||||
error(self.expr, "'%.*s'3 expected a type or value derived from intrinsics.objc_object, got '%s' of type %s %d", LIT(builtin_name), e, t, self.type->kind);
|
||||
error(self.expr, "'%.*s' expected a type or value derived from intrinsics.objc_object, got '%s' of type %s %d", LIT(builtin_name), e, t, self.type->kind);
|
||||
gb_string_free(t);
|
||||
gb_string_free(e);
|
||||
return false;
|
||||
|
||||
@@ -340,6 +340,10 @@ void check_type_decl(CheckerContext *ctx, Entity *e, Ast *init_expr, Type *def)
|
||||
check_decl_attributes(ctx, decl->attributes, type_decl_attribute, &ac);
|
||||
if (e->kind == Entity_TypeName && ac.objc_class != "") {
|
||||
e->TypeName.objc_class_name = ac.objc_class;
|
||||
|
||||
if (type_size_of(e->type) > 0) {
|
||||
error(e->token, "@(objc_class) marked type must be of zero size");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -822,6 +826,65 @@ void check_proc_decl(CheckerContext *ctx, Entity *e, DeclInfo *d) {
|
||||
}
|
||||
e->Procedure.optimization_mode = cast(ProcedureOptimizationMode)ac.optimization_mode;
|
||||
|
||||
if (ac.objc_name.len || ac.objc_class_name.len || ac.objc_type) {
|
||||
if (ac.objc_class_name.len && ac.objc_name.len) {
|
||||
error(e->token, "@(objc_class_name) and @(objc_name) may not be allowed at the same time");
|
||||
} else if (ac.objc_type == nullptr) {
|
||||
if (ac.objc_name.len) {
|
||||
error(e->token, "@(objc_name) requires that @(objc_type) to be set");
|
||||
} else {
|
||||
error(e->token, "@(objc_class_name) requires that @(objc_type) to be set");
|
||||
}
|
||||
} else {
|
||||
Type *t = ac.objc_type;
|
||||
if (t->kind == Type_Named) {
|
||||
Entity *tn = t->Named.type_name;
|
||||
|
||||
GB_ASSERT(tn->kind == Entity_TypeName);
|
||||
|
||||
if (tn->scope != e->scope) {
|
||||
error(e->token, "@(objc_name) and @(objc_class_name) attributes may only be applied to procedures and types within the same scope");
|
||||
} else {
|
||||
mutex_lock(&global_type_name_objc_metadata_mutex);
|
||||
defer (mutex_unlock(&global_type_name_objc_metadata_mutex));
|
||||
|
||||
if (!tn->TypeName.objc_metadata) {
|
||||
tn->TypeName.objc_metadata = create_type_name_obj_c_metadata();
|
||||
}
|
||||
auto *md = tn->TypeName.objc_metadata;
|
||||
mutex_lock(md->mutex);
|
||||
defer (mutex_unlock(md->mutex));
|
||||
|
||||
if (ac.objc_name.len) {
|
||||
bool ok = true;
|
||||
for (TypeNameObjCMetadataEntry const &entry : md->value_entries) {
|
||||
if (entry.name == ac.objc_name) {
|
||||
error(e->token, "Previous declaration of @(objc_name=\"%.*s\")", LIT(ac.objc_name));
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
array_add(&md->value_entries, TypeNameObjCMetadataEntry{ac.objc_name, e});
|
||||
}
|
||||
} else {
|
||||
bool ok = true;
|
||||
for (TypeNameObjCMetadataEntry const &entry : md->type_entries) {
|
||||
if (entry.name == ac.objc_class_name) {
|
||||
error(e->token, "Previous declaration of @(objc_class_name=\"%.*s\")", LIT(ac.objc_class_name));
|
||||
ok = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ok) {
|
||||
array_add(&md->type_entries, TypeNameObjCMetadataEntry{ac.objc_class_name, e});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
switch (e->Procedure.optimization_mode) {
|
||||
case ProcedureOptimizationMode_None:
|
||||
|
||||
@@ -325,6 +325,8 @@ void add_polymorphic_record_entity(CheckerContext *ctx, Ast *node, Type *named_t
|
||||
named_type->Named.type_name = e;
|
||||
GB_ASSERT(original_type->kind == Type_Named);
|
||||
e->TypeName.objc_class_name = original_type->Named.type_name->TypeName.objc_class_name;
|
||||
// TODO(bill): Is this even correct? Or should the metadata be copied?
|
||||
e->TypeName.objc_metadata = original_type->Named.type_name->TypeName.objc_metadata;
|
||||
|
||||
mutex_lock(&ctx->info->gen_types_mutex);
|
||||
auto *found_gen_types = map_get(&ctx->info->gen_types, original_type);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
void check_expr(CheckerContext *c, Operand *operand, Ast *expression);
|
||||
void check_expr_or_type(CheckerContext *c, Operand *operand, Ast *expression, Type *type_hint=nullptr);
|
||||
void add_comparison_procedures_for_fields(CheckerContext *c, Type *t);
|
||||
|
||||
Type *check_type(CheckerContext *ctx, Ast *e);
|
||||
|
||||
bool is_operand_value(Operand o) {
|
||||
switch (o.mode) {
|
||||
@@ -2740,6 +2740,14 @@ ExactValue check_decl_attribute_value(CheckerContext *c, Ast *value) {
|
||||
return ev;
|
||||
}
|
||||
|
||||
Type *check_decl_attribute_type(CheckerContext *c, Ast *value) {
|
||||
if (value != nullptr) {
|
||||
return check_type(c, value);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
#define ATTRIBUTE_USER_TAG_NAME "tag"
|
||||
|
||||
|
||||
@@ -3039,6 +3047,46 @@ DECL_ATTRIBUTE_PROC(proc_decl_attribute) {
|
||||
error(elem, "Expected a string for '%.*s'", LIT(name));
|
||||
}
|
||||
return true;
|
||||
} else if (name == "objc_name") {
|
||||
ExactValue ev = check_decl_attribute_value(c, value);
|
||||
if (ev.kind == ExactValue_String) {
|
||||
if (string_is_valid_identifier(ev.value_string)) {
|
||||
ac->objc_name = ev.value_string;
|
||||
} else {
|
||||
error(elem, "Invalid identifier for '%.*s', got '%.*s'", LIT(name), LIT(ev.value_string));
|
||||
}
|
||||
} else {
|
||||
error(elem, "Expected a string value for '%.*s'", LIT(name));
|
||||
}
|
||||
return true;
|
||||
} else if (name == "objc_class_name") {
|
||||
ExactValue ev = check_decl_attribute_value(c, value);
|
||||
if (ev.kind == ExactValue_String) {
|
||||
if (string_is_valid_identifier(ev.value_string)) {
|
||||
ac->objc_class_name = ev.value_string;
|
||||
} else {
|
||||
error(elem, "Invalid identifier for '%.*s', got '%.*s'", LIT(name), LIT(ev.value_string));
|
||||
}
|
||||
} else {
|
||||
error(elem, "Expected a string value for '%.*s'", LIT(name));
|
||||
}
|
||||
return true;
|
||||
} else if (name == "objc_type") {
|
||||
if (value == nullptr) {
|
||||
error(elem, "Expected a type for '%.*s'", LIT(name));
|
||||
} else {
|
||||
Type *objc_type = check_type(c, value);
|
||||
if (objc_type != nullptr) {
|
||||
if (!has_type_got_objc_class_attribute(objc_type)) {
|
||||
gbString t = type_to_string(objc_type);
|
||||
error(value, "'%.*s' expected a named type with the attribute @(obj_class=<string>), got type %s", LIT(name), t);
|
||||
gb_string_free(t);
|
||||
} else {
|
||||
ac->objc_type = objc_type;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -107,7 +107,6 @@ struct AttributeContext {
|
||||
String thread_local_model;
|
||||
String deprecated_message;
|
||||
String warning_message;
|
||||
String objc_class;
|
||||
DeferredProcedure deferred_procedure;
|
||||
bool is_export : 1;
|
||||
bool is_static : 1;
|
||||
@@ -119,6 +118,11 @@ struct AttributeContext {
|
||||
bool init : 1;
|
||||
bool set_cold : 1;
|
||||
u32 optimization_mode; // ProcedureOptimizationMode
|
||||
|
||||
String objc_class;
|
||||
String objc_name;
|
||||
String objc_class_name;
|
||||
Type * objc_type;
|
||||
};
|
||||
|
||||
AttributeContext make_attribute_context(String link_prefix) {
|
||||
|
||||
@@ -122,6 +122,28 @@ enum ProcedureOptimizationMode : u32 {
|
||||
ProcedureOptimizationMode_Speed,
|
||||
};
|
||||
|
||||
|
||||
BlockingMutex global_type_name_objc_metadata_mutex;
|
||||
|
||||
struct TypeNameObjCMetadataEntry {
|
||||
String name;
|
||||
Entity *entity;
|
||||
};
|
||||
struct TypeNameObjCMetadata {
|
||||
BlockingMutex *mutex;
|
||||
Array<TypeNameObjCMetadataEntry> type_entries;
|
||||
Array<TypeNameObjCMetadataEntry> value_entries;
|
||||
};
|
||||
|
||||
TypeNameObjCMetadata *create_type_name_obj_c_metadata() {
|
||||
TypeNameObjCMetadata *md = gb_alloc_item(permanent_allocator(), TypeNameObjCMetadata);
|
||||
md->mutex = gb_alloc_item(permanent_allocator(), BlockingMutex);
|
||||
mutex_init(md->mutex);
|
||||
array_init(&md->type_entries, heap_allocator());
|
||||
array_init(&md->value_entries, heap_allocator());
|
||||
return md;
|
||||
}
|
||||
|
||||
// An Entity is a named "thing" in the language
|
||||
struct Entity {
|
||||
EntityKind kind;
|
||||
@@ -187,6 +209,7 @@ struct Entity {
|
||||
String ir_mangled_name;
|
||||
bool is_type_alias;
|
||||
String objc_class_name;
|
||||
TypeNameObjCMetadata *objc_metadata;
|
||||
} TypeName;
|
||||
struct {
|
||||
u64 tags;
|
||||
|
||||
@@ -3320,7 +3320,12 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
|
||||
|
||||
Type *type = base_type(tav.type);
|
||||
if (tav.mode == Addressing_Type) { // Addressing_Type
|
||||
GB_PANIC("Unreachable");
|
||||
Selection sel = lookup_field(tav.type, selector, true);
|
||||
if (sel.pseudo_field) {
|
||||
GB_ASSERT(sel.entity->kind == Entity_Procedure);
|
||||
return lb_addr(lb_find_value_from_entity(p->module, sel.entity));
|
||||
}
|
||||
GB_PANIC("Unreachable %.*s", LIT(selector));
|
||||
}
|
||||
|
||||
if (se->swizzle_count > 0) {
|
||||
@@ -3347,6 +3352,10 @@ lbAddr lb_build_addr(lbProcedure *p, Ast *expr) {
|
||||
|
||||
Selection sel = lookup_field(type, selector, false);
|
||||
GB_ASSERT(sel.entity != nullptr);
|
||||
if (sel.pseudo_field) {
|
||||
GB_ASSERT(sel.entity->kind == Entity_Procedure);
|
||||
return lb_addr(lb_find_value_from_entity(p->module, sel.entity));
|
||||
}
|
||||
|
||||
{
|
||||
lbAddr addr = lb_build_addr(p, se->expr);
|
||||
|
||||
32
src/main.cpp
32
src/main.cpp
@@ -585,37 +585,6 @@ void usage(String argv0) {
|
||||
print_usage_line(1, "e.g. odin build -help");
|
||||
}
|
||||
|
||||
|
||||
bool string_is_valid_identifier(String str) {
|
||||
if (str.len <= 0) return false;
|
||||
|
||||
isize rune_count = 0;
|
||||
|
||||
isize w = 0;
|
||||
isize offset = 0;
|
||||
while (offset < str.len) {
|
||||
Rune r = 0;
|
||||
w = utf8_decode(str.text, str.len, &r);
|
||||
if (r == GB_RUNE_INVALID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rune_count == 0) {
|
||||
if (!rune_is_letter(r)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!rune_is_letter(r) && !rune_is_digit(r)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
rune_count += 1;
|
||||
offset += w;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
enum BuildFlagKind {
|
||||
BuildFlag_Invalid,
|
||||
|
||||
@@ -2447,6 +2416,7 @@ int main(int arg_count, char const **arg_ptr) {
|
||||
virtual_memory_init();
|
||||
mutex_init(&fullpath_mutex);
|
||||
mutex_init(&hash_exact_value_mutex);
|
||||
mutex_init(&global_type_name_objc_metadata_mutex);
|
||||
|
||||
init_string_buffer_memory();
|
||||
init_string_interner();
|
||||
|
||||
@@ -781,3 +781,34 @@ i32 unquote_string(gbAllocator a, String *s_, u8 quote=0, bool has_carriage_retu
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool string_is_valid_identifier(String str) {
|
||||
if (str.len <= 0) return false;
|
||||
|
||||
isize rune_count = 0;
|
||||
|
||||
isize w = 0;
|
||||
isize offset = 0;
|
||||
while (offset < str.len) {
|
||||
Rune r = 0;
|
||||
w = utf8_decode(str.text, str.len, &r);
|
||||
if (r == GB_RUNE_INVALID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (rune_count == 0) {
|
||||
if (!rune_is_letter(r)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!rune_is_letter(r) && !rune_is_digit(r)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
rune_count += 1;
|
||||
offset += w;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -393,6 +393,7 @@ struct Selection {
|
||||
bool indirect; // Set if there was a pointer deref anywhere down the line
|
||||
u8 swizzle_count; // maximum components = 4
|
||||
u8 swizzle_indices; // 2 bits per component, representing which swizzle index
|
||||
bool pseudo_field;
|
||||
};
|
||||
Selection empty_selection = {0};
|
||||
|
||||
@@ -2782,6 +2783,7 @@ Selection lookup_field_from_index(Type *type, i64 index) {
|
||||
}
|
||||
|
||||
Entity *scope_lookup_current(Scope *s, String const &name);
|
||||
bool has_type_got_objc_class_attribute(Type *t);
|
||||
|
||||
Selection lookup_field_with_selection(Type *type_, String field_name, bool is_type, Selection sel, bool allow_blank_ident) {
|
||||
GB_ASSERT(type_ != nullptr);
|
||||
@@ -2794,9 +2796,40 @@ Selection lookup_field_with_selection(Type *type_, String field_name, bool is_ty
|
||||
bool is_ptr = type != type_;
|
||||
sel.indirect = sel.indirect || is_ptr;
|
||||
|
||||
Type *original_type = type;
|
||||
|
||||
type = base_type(type);
|
||||
|
||||
if (is_type) {
|
||||
if (has_type_got_objc_class_attribute(original_type) && original_type->kind == Type_Named) {
|
||||
Entity *e = original_type->Named.type_name;
|
||||
GB_ASSERT(e->kind == Entity_TypeName);
|
||||
if (e->TypeName.objc_metadata) {
|
||||
auto *md = e->TypeName.objc_metadata;
|
||||
mutex_lock(md->mutex);
|
||||
defer (mutex_unlock(md->mutex));
|
||||
for (TypeNameObjCMetadataEntry const &entry : md->type_entries) {
|
||||
GB_ASSERT(entry.entity->kind == Entity_Procedure);
|
||||
if (entry.name == field_name) {
|
||||
sel.entity = entry.entity;
|
||||
sel.pseudo_field = true;
|
||||
return sel;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (type->kind == Type_Struct) {
|
||||
for_array(i, type->Struct.fields) {
|
||||
Entity *f = type->Struct.fields[i];
|
||||
if (f->flags&EntityFlag_Using) {
|
||||
sel = lookup_field_with_selection(f->type, field_name, is_type, sel, allow_blank_ident);
|
||||
if (sel.entity) {
|
||||
return sel;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_type_enum(type)) {
|
||||
// NOTE(bill): These may not have been added yet, so check in case
|
||||
for_array(i, type->Enum.fields) {
|
||||
@@ -2843,6 +2876,24 @@ Selection lookup_field_with_selection(Type *type_, String field_name, bool is_ty
|
||||
} else if (type->kind == Type_Union) {
|
||||
|
||||
} else if (type->kind == Type_Struct) {
|
||||
if (has_type_got_objc_class_attribute(original_type) && original_type->kind == Type_Named) {
|
||||
Entity *e = original_type->Named.type_name;
|
||||
GB_ASSERT(e->kind == Entity_TypeName);
|
||||
if (e->TypeName.objc_metadata) {
|
||||
auto *md = e->TypeName.objc_metadata;
|
||||
mutex_lock(md->mutex);
|
||||
defer (mutex_unlock(md->mutex));
|
||||
for (TypeNameObjCMetadataEntry const &entry : md->value_entries) {
|
||||
GB_ASSERT(entry.entity->kind == Entity_Procedure);
|
||||
if (entry.name == field_name) {
|
||||
sel.entity = entry.entity;
|
||||
sel.pseudo_field = true;
|
||||
return sel;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for_array(i, type->Struct.fields) {
|
||||
Entity *f = type->Struct.fields[i];
|
||||
if (f->kind != Entity_Variable || (f->flags & EntityFlag_Field) == 0) {
|
||||
@@ -3792,6 +3843,17 @@ bool is_type_subtype_of(Type *src, Type *dst) {
|
||||
}
|
||||
|
||||
|
||||
bool has_type_got_objc_class_attribute(Type *t) {
|
||||
return t->kind == Type_Named && t->Named.type_name != nullptr && t->Named.type_name->TypeName.objc_class_name != "";
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool is_type_objc_object(Type *t) {
|
||||
bool internal_check_is_assignable_to(Type *src, Type *dst);
|
||||
|
||||
return internal_check_is_assignable_to(t, t_objc_object);
|
||||
}
|
||||
|
||||
Type *get_struct_field_type(Type *t, isize index) {
|
||||
t = base_type(type_deref(t));
|
||||
|
||||
Reference in New Issue
Block a user