diff --git a/library/modules/std/objc_block.sx b/library/modules/std/objc_block.sx index 3c0b031..d9aaeb2 100644 --- a/library/modules/std/objc_block.sx +++ b/library/modules/std/objc_block.sx @@ -52,70 +52,14 @@ __sx_block_descriptor : BlockDescriptor = .{ size = 48, }; -// Per-signature invoke trampolines. Each one reads sx_env + sx_fn from -// its block_self argument and tail-calls the closure through a typed -// fn-ptr cast. One per Apple block signature we support. -// -// Adding a new signature: write a `__block_invoke_` trampoline -// matching the closure's calling convention and an -// `impl Into(Block) for Closure()` that points its `invoke` -// field at the trampoline. The `xx closure : Block` cast finds the -// impl via `Into` protocol dispatch. -// -// Signature: `void (^)(void)` — no args, no return. The single most -// common Apple block shape (UIView animation bodies, dispatch_async, etc). -__block_invoke_void :: (block_self: *Block) callconv(.c) { - // `sx_fn` is the closure trampoline — an sx-side function with the - // implicit __sx_ctx at slot 0 and env at slot 1. We're a callconv(.c) - // entry, so the call site needs ctx prepended; the typed fn-pointer - // type stays default-conv to enable that. - typed_fn : (*void) -> void = xx block_self.sx_fn; - typed_fn(block_self.sx_env); -} - -impl Into(Block) for Closure() -> void { - convert :: (self: Closure() -> void) -> Block { - .{ - isa = @_NSConcreteStackBlock, - flags = 0, - reserved = 0, - invoke = xx @__block_invoke_void, - descriptor = xx @__sx_block_descriptor, - sx_env = self.env, - sx_fn = self.fn_ptr, - }; - } -} - -// Signature: `void (^)(BOOL)` — UIView animation completion handlers and -// similar one-arg-bool callbacks. -__block_invoke_bool :: (block_self: *Block, arg0: bool) callconv(.c) { - typed_fn : (*void, bool) -> void = xx block_self.sx_fn; - typed_fn(block_self.sx_env, arg0); -} - -impl Into(Block) for Closure(bool) -> void { - convert :: (self: Closure(bool) -> void) -> Block { - .{ - isa = @_NSConcreteStackBlock, - flags = 0, - reserved = 0, - invoke = xx @__block_invoke_bool, - descriptor = xx @__sx_block_descriptor, - sx_env = self.env, - sx_fn = self.fn_ptr, - }; - } -} - -// Generic impl: covers any closure shape not handled by the -// hand-rolled per-signature impls above. The compiler +// Single generic impl covers every closure shape. The compiler // monomorphises this body per call shape; inside each mono, // `$args` is the bound pack of arg types and `$R` is the bound // return type. The `#insert` evaluates `build_block_convert` at // comptime and substitutes the resulting source — a nested // `callconv(.c)` trampoline + the Block literal that points its -// `invoke` slot at it. +// `invoke` slot at it. One impl in stdlib replaces every per- +// signature hand-rolled `__block_invoke_*` + `Into(Block)` pair. impl Into(Block) for Closure(..$args) -> $R { convert :: (self: Closure(..$args) -> $R) -> Block { #insert build_block_convert($args, $R);