From fb8a5399f1d3ac6acc9c61e765cbc49d9162437e Mon Sep 17 00:00:00 2001 From: agra Date: Sat, 30 May 2026 18:01:27 +0300 Subject: [PATCH] objc: remove ns_string/c_string helpers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ns_string's only caller was impl Into(*NSString) for string, so +stringWithUTF8String: is inlined there. c_string's one use (NSBundle.resourcePath in uikit) becomes rsrc.UTF8String() with resourcePath retyped *NSString. ffi-objc-call-06 and ffi-objc-dsl-07 .ir snapshots regenerated — they only drop the now-absent extern declares. --- library/modules/platform/uikit.sx | 4 +- library/modules/std/objc.sx | 40 ++++++------------- .../expected/ffi-objc-call-06-sret-return.ir | 6 --- .../ffi-objc-dsl-07-mangling-table.ir | 8 +--- 4 files changed, 16 insertions(+), 42 deletions(-) diff --git a/library/modules/platform/uikit.sx b/library/modules/platform/uikit.sx index 45e2785..bae9331 100644 --- a/library/modules/platform/uikit.sx +++ b/library/modules/platform/uikit.sx @@ -99,7 +99,7 @@ NSNotification :: #foreign #objc_class("NSNotification") { NSBundle :: #foreign #objc_class("NSBundle") { #extends NSObject; mainBundle :: () -> *NSBundle; - resourcePath :: (self: *Self) -> *void; + resourcePath :: (self: *Self) -> *NSString; } NSNotificationCenter :: #foreign #objc_class("NSNotificationCenter") { @@ -810,7 +810,7 @@ uikit_chdir_to_bundle :: () { bundle := NSBundle.mainBundle(); rsrc := bundle.resourcePath(); if rsrc == null { return; } - chdir(c_string(rsrc)); + chdir(rsrc.UTF8String()); } // ── SxGLView class ───────────────────────────────────────────────────────── diff --git a/library/modules/std/objc.sx b/library/modules/std/objc.sx index 5e3a43b..9cfa028 100644 --- a/library/modules/std/objc.sx +++ b/library/modules/std/objc.sx @@ -5,7 +5,7 @@ // argument and return shape. The idiom: // // msg_fn : (recv: *void, sel: *void, arg: [*]u8) -> *void = xx objc_msgSend; -// result := msg_fn(receiver, selector, c_string); +// result := msg_fn(receiver, selector, c_str); // ─── Obj-C primitive type aliases ─────────────────────────────────────── // Named stand-ins for the three opaque Obj-C runtime types. They all @@ -74,26 +74,6 @@ objc_registerClassPair :: (cls: *void) -> // NSLog takes an NSString format; the variadic tail is not exposed here. NSLog :: (fmt: *NSString) #foreign; -// ─── Convenience helpers ──────────────────────────────────────────────── -// These hide the typed-fn-pointer cast for the most common shapes. They -// re-register selectors per call — if you're in a tight loop, cache the SEL. - -// Wrap a C string in an autoreleased NSString. -ns_string :: (s: [*]u8) -> *void { - cls := objc_getClass("NSString".ptr); - sel := sel_registerName("stringWithUTF8String:".ptr); - fn_ptr : (*void, *void, [*]u8) -> *void callconv(.c) = xx objc_msgSend; - return fn_ptr(cls, sel, s); -} - -// View an NSString's bytes as a C string. The returned pointer's lifetime is -// tied to the NSString; don't free it. -c_string :: (ns: *void) -> [*]u8 { - sel := sel_registerName("UTF8String".ptr); - 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 @@ -124,20 +104,24 @@ NSObject :: #foreign #objc_class("NSObject") { } // ─── NSString ──────────────────────────────────────────────────────────── -// Foundation's immutable string. `ns_string` builds an autoreleased instance -// from a C string; the `Into` impl lets a string literal flow into any -// `*NSString` slot via `xx`, e.g. `dict.objectForKey(xx "SomeKey")`. +// Foundation's immutable string. `UTF8String` views the bytes as a C string +// whose lifetime is tied to the NSString (don't free it). The `Into` impl +// lets a string literal flow into any `*NSString` slot via `xx`, e.g. +// `dict.objectForKey(xx "SomeKey")`. NSString :: #foreign #objc_class("NSString") { #extends NSObject; UTF8String :: (self: *Self) -> [*]u8; } -// `self.ptr` must be NUL-terminated. String literals are; an arbitrary -// substring/built `string` may not be, so only pass literals (or otherwise -// NUL-terminated slices) through this conversion. +// Wraps the bytes in an autoreleased NSString via `+stringWithUTF8String:`. +// `self.ptr` must be NUL-terminated — string literals are; an arbitrary +// sliced/built `string` may not be. impl Into(*NSString) for string { convert :: (self: string) -> *NSString { - return xx ns_string(self.ptr); + cls := objc_getClass("NSString".ptr); + sel := sel_registerName("stringWithUTF8String:".ptr); + msg : (*void, *void, [*]u8) -> *void callconv(.c) = xx objc_msgSend; + return xx msg(cls, sel, self.ptr); } } diff --git a/tests/expected/ffi-objc-call-06-sret-return.ir b/tests/expected/ffi-objc-call-06-sret-return.ir index 72a71e1..e525419 100644 --- a/tests/expected/ffi-objc-call-06-sret-return.ir +++ b/tests/expected/ffi-objc-call-06-sret-return.ir @@ -1945,12 +1945,6 @@ declare void @objc_registerClassPair(ptr) #0 ; Function Attrs: nounwind declare void @NSLog(ptr) #0 -; Function Attrs: nounwind -declare ptr @ns_string(ptr, ptr) #0 - -; Function Attrs: nounwind -declare ptr @c_string(ptr, ptr) #0 - ; Function Attrs: nounwind declare ptr @objc_autoreleasePoolPush() #0 diff --git a/tests/expected/ffi-objc-dsl-07-mangling-table.ir b/tests/expected/ffi-objc-dsl-07-mangling-table.ir index a909fed..191dd95 100644 --- a/tests/expected/ffi-objc-dsl-07-mangling-table.ir +++ b/tests/expected/ffi-objc-dsl-07-mangling-table.ir @@ -792,12 +792,6 @@ declare void @objc_registerClassPair(ptr) #0 ; Function Attrs: nounwind declare void @NSLog(ptr) #0 -; Function Attrs: nounwind -declare ptr @ns_string(ptr, ptr) #0 - -; Function Attrs: nounwind -declare ptr @c_string(ptr, ptr) #0 - ; Function Attrs: nounwind declare ptr @objc_autoreleasePoolPush() #0 @@ -960,3 +954,5 @@ entry: store ptr %selN, ptr @OBJC_SELECTOR_REFERENCES_actualSelectorName, align 8 ret void } + +