From 56f6ae36819bb9d7ef946c195de165a9a2f99ac8 Mon Sep 17 00:00:00 2001 From: agra Date: Tue, 19 May 2026 21:06:53 +0300 Subject: [PATCH] =?UTF-8?q?ffi=201.33:=20uikit.sx=20final=20sweep=20?= =?UTF-8?q?=E2=80=94=20Phase=201D=20for=20uikit.sx=20complete?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Six remaining dispatch clusters migrated in one pass: - `uikit_setup_renderbuffer`: `renderbufferStorage:fromDrawable:` (BOOL). - `uikit_present_renderbuffer`: `presentRenderbuffer:` (BOOL, every frame). - `uikit_gl_view_tick`: `targetTimestamp` and `duration` reads (f64, every frame — three call sites total across the keyboard-anim path and the frame-closure path). - `uikit_compute_layer_pixel_size`: `bounds` (CGRect HFA). - `uikit_touch_location`: `locationInView:` (CGPoint HFA — first standalone `#objc_call(CGPoint)` exercise, structurally identical to the 2×f64 NSPoint already verified by ffi-objc-call-05). - `uikit_first_touch`: `anyObject` (*void). Net -15 lines. uikit.sx is now 839 lines — Phase 1D started at 937, so this is -98 cumulative across the migration. Zero `xx objc_msgSend` typed casts left in the file. iOS-sim chess regression smoke: launched chess, tapped a black pawn through the Simulator window, watched the move (d7→d5) play, then a second tap played d5→d4. The render loop, touch handlers, layout math, and the BOOL-returning EAGL presentation calls are all on the exercised path, so this is the strongest runtime verification any Phase 1D commit has had so far. 22 `sel_registerName` calls remain in the file, all legitimate: - `class_addMethod` IMP registrations (runtime class build-out). - SEL-as-arg to dispatch selectors that take a SEL value (`addObserver:selector:name:object:`, `displayLinkWithTarget:selector:`). A future `#objc_selector("foo")` literal would replace these, but it's not part of Phase 1. --- library/modules/platform/uikit.sx | 31 ++++++++----------------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/library/modules/platform/uikit.sx b/library/modules/platform/uikit.sx index e071c34..70d7497 100644 --- a/library/modules/platform/uikit.sx +++ b/library/modules/platform/uikit.sx @@ -590,9 +590,7 @@ uikit_setup_renderbuffer :: (plat: *UIKitPlatform) { glBindRenderbuffer(GL_RENDERBUFFER, plat.color_renderbuffer); - sel_renderbuffer_storage := sel_registerName("renderbufferStorage:fromDrawable:".ptr); - msg_o_u32_o : (*void, *void, u32, *void) -> u8 = xx objc_msgSend; - msg_o_u32_o(plat.gl_ctx, sel_renderbuffer_storage, GL_RENDERBUFFER, plat.gl_layer); + #objc_call(bool)(plat.gl_ctx, "renderbufferStorage:fromDrawable:", GL_RENDERBUFFER, plat.gl_layer); glBindFramebuffer(GL_FRAMEBUFFER, plat.framebuffer); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, plat.color_renderbuffer); @@ -624,9 +622,7 @@ uikit_setup_renderbuffer :: (plat: *UIKitPlatform) { uikit_present_renderbuffer :: (self: *UIKitPlatform) { inline if OS != .ios { return; } glBindRenderbuffer(GL_RENDERBUFFER, self.color_renderbuffer); - sel_present := sel_registerName("presentRenderbuffer:".ptr); - msg_ou : (*void, *void, u32) -> u8 = xx objc_msgSend; - msg_ou(self.gl_ctx, sel_present, GL_RENDERBUFFER); + #objc_call(bool)(self.gl_ctx, "presentRenderbuffer:", GL_RENDERBUFFER); } // ── SxGLView class ───────────────────────────────────────────────────────── @@ -651,9 +647,7 @@ uikit_gl_view_tick :: (self: *void, _cmd: *void, link: *void) callconv(.c) { // and keyboardLayoutGuide — none eliminated the lag without // cascade-breaking the GL view's frame. if plat.kb_animating { - sel_target_ts := sel_registerName("targetTimestamp".ptr); - msg_d2 : (*void, *void) -> f64 = xx objc_msgSend; - target_ts := msg_d2(link, sel_target_ts); + target_ts := #objc_call(f64)(link, "targetTimestamp"); elapsed := target_ts - plat.kb_anim_start; // Negative elapsed can happen if the just-fired willChangeFrame // set kb_anim_start to a wall time AFTER the tick already @@ -680,14 +674,11 @@ uikit_gl_view_tick :: (self: *void, _cmd: *void, link: *void) callconv(.c) { if !plat.has_frame_closure { return; } if !plat.gl_initialized { return; } - sel_dur := sel_registerName("duration".ptr); - sel_tts := sel_registerName("targetTimestamp".ptr); - msg_d : (*void, *void) -> f64 = xx objc_msgSend; - dur_d : f64 = msg_d(link, sel_dur); + dur_d := #objc_call(f64)(link, "duration"); plat.delta_time = xx dur_d; // Stash the targetTimestamp so begin_frame can hand it down to the // game in FrameContext for Metal presentDrawable:atTime:. - plat.last_target_ts = msg_d(link, sel_tts); + plat.last_target_ts = #objc_call(f64)(link, "targetTimestamp"); fn := plat.frame_closure; fn(); @@ -715,9 +706,7 @@ uikit_compute_layer_pixel_size :: (plat: *UIKitPlatform) { inline if OS != .ios { return; } if plat.gl_view == null { return; } - sel_bounds := sel_registerName("bounds".ptr); - msg_rect : (*void, *void) -> CGRect = xx objc_msgSend; - b := msg_rect(plat.gl_view, sel_bounds); + b := #objc_call(CGRect)(plat.gl_view, "bounds"); w_pts : f64 = b.width; h_pts : f64 = b.height; @@ -737,16 +726,12 @@ uikit_compute_layer_pixel_size :: (plat: *UIKitPlatform) { // Event into the platform's queue for the next poll_events drain. uikit_touch_location :: (touch: *void, view: *void) -> Point { - sel_location := sel_registerName("locationInView:".ptr); - msg_pt : (*void, *void, *void) -> CGPoint = xx objc_msgSend; - p := msg_pt(touch, sel_location, view); + p := #objc_call(CGPoint)(touch, "locationInView:", view); Point.{ x = xx p.x, y = xx p.y }; } uikit_first_touch :: (touches: *void) -> *void { - sel_any := sel_registerName("anyObject".ptr); - msg_o : (*void, *void) -> *void = xx objc_msgSend; - msg_o(touches, sel_any); + #objc_call(*void)(touches, "anyObject"); } uikit_gl_view_touches_began :: (self: *void, _cmd: *void, touches: *void, event: *void) callconv(.c) {