ffi M4.A: stdlib NSObject + autoreleasepool helper + extends rooting
Declare `NSObject` in std/objc.sx as `#foreign #objc_class("NSObject")`
with the canonical instance + class-method surface every Obj-C class
inherits: `retain`/`release`/`autorelease`/`new`/`alloc`/`init`/
`description`/`hash`/`isEqual_`/`isKindOfClass_`/`respondsToSelector_`/
`class`. Root the foreign-class hierarchy in uikit.sx at NSObject by
adding `#extends NSObject;` to every previously-unrooted declaration
(NSValue, NSNumber, NSDictionary, NSSet, NSNotification, NSBundle,
NSNotificationCenter, NSRunLoop, CADisplayLink, CALayer, EAGLContext,
UIScreen, UIResponder) plus deeper chain fixes (NSMutableDictionary
extends NSDictionary; UIWindow extends UIView; UIViewController
extends UIResponder). After this, M2.3's extends-chain walk finds
`retain`/`release` on any UIKit-typed value:
view := UIView.alloc().init();
defer view.release(); // canonical sx idiom — no language magic
Plus `autoreleasepool(body: Closure())` stdlib helper that wraps
`body` in `objc_autoreleasePoolPush` / `defer objc_autoreleasePoolPop`.
Required for Foundation factory returns; closure-call frame is real
cost so hot loops should inline the push/defer-pop pattern manually.
Smoke test `ffi-objc-arc-01-autoreleasepool.sx` exercises both
patterns; refresh of two IR snapshots picks up the new stdlib decls
appearing in test outputs that include `modules/std/objc.sx`.
185/185 example tests pass; chess on iOS-sim green.
This commit is contained in:
@@ -93,3 +93,50 @@ c_string :: (ns: *void) -> [*]u8 {
|
||||
fn_ptr : (*void, *void) -> [*]u8 callconv(.c) = xx objc_msgSend;
|
||||
return fn_ptr(ns, sel);
|
||||
}
|
||||
|
||||
// ─── NSObject (Phase 4 / M4.A) ───────────────────────────────────────────
|
||||
// Root of every Obj-C class hierarchy. Apple's runtime supplies the IMPs;
|
||||
// sx declares the method surface so user code can write
|
||||
// `defer view.release();` and `view.retain()` directly instead of going
|
||||
// through `objc_msgSend` casts. M2.3's `#extends`-aware dispatch finds
|
||||
// these methods automatically once a class roots its `#extends` chain at
|
||||
// NSObject (foreign classes in uikit.sx etc. add `#extends NSObject;` to
|
||||
// inherit the surface).
|
||||
//
|
||||
// `release` is NOT a reserved keyword in sx — modern clang ARC bans
|
||||
// user-source calls to it (the ARC compiler emits them automatically), but
|
||||
// sx isn't under clang ARC. Calling `view.release()` here is equivalent to
|
||||
// pre-ARC Obj-C source code: dispatches through the runtime, decrements the
|
||||
// refcount, fires `-dealloc` at zero.
|
||||
NSObject :: #foreign #objc_class("NSObject") {
|
||||
alloc :: () -> *NSObject;
|
||||
init :: (self: *Self) -> *NSObject;
|
||||
new :: () -> *NSObject; // shorthand for [[Cls alloc] init]
|
||||
retain :: (self: *Self) -> *Self;
|
||||
release :: (self: *Self);
|
||||
autorelease :: (self: *Self) -> *Self;
|
||||
class :: () -> *void; // metaclass query — `Cls.class()`
|
||||
description :: (self: *Self) -> *void; // returns *NSString
|
||||
hash :: (self: *Self) -> u64;
|
||||
isEqual_ :: (self: *Self, other: *void) -> BOOL;
|
||||
isKindOfClass_ :: (self: *Self, cls: *void) -> BOOL;
|
||||
respondsToSelector_ :: (self: *Self, sel: *void) -> BOOL;
|
||||
}
|
||||
|
||||
// ─── Autoreleasepool (M4.A) ──────────────────────────────────────────────
|
||||
// Foundation factory methods (`NSString.stringWithUTF8String:`,
|
||||
// `[NSArray array]`, ...) return autoreleased objects — valid until the
|
||||
// current pool drains. Wrap such code in `autoreleasepool(() => { ... })`
|
||||
// so the pool drains deterministically at block end.
|
||||
//
|
||||
// Stdlib helper, not a language keyword. The closure call adds a frame —
|
||||
// for hot loops, inline the push/defer-pop pattern manually.
|
||||
|
||||
objc_autoreleasePoolPush :: () -> *void #foreign objc;
|
||||
objc_autoreleasePoolPop :: (pool: *void) #foreign objc;
|
||||
|
||||
autoreleasepool :: (body: Closure()) {
|
||||
pool := objc_autoreleasePoolPush();
|
||||
defer objc_autoreleasePoolPop(pool);
|
||||
body();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user