diff --git a/library/modules/std/objc_block.sx b/library/modules/std/objc_block.sx index 9c9825b..b9e5c78 100644 --- a/library/modules/std/objc_block.sx +++ b/library/modules/std/objc_block.sx @@ -52,52 +52,17 @@ __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. +// M5.A — `xx closure : Block` casts are handled by the compiler. +// For every closure signature seen at a cast site, the compiler +// synthesises: +// 1. A C-ABI trampoline `__block_invoke_` matching Apple's +// `__block_literal.invoke` calling convention. +// 2. Inline Block-struct construction at the cast site, with +// `invoke` pointing at the synthesised trampoline and +// `sx_env`/`sx_fn` taken from the closure value. // -// 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, - }; - } -} +// User-facing surface: `xx my_closure : Block` for ANY closure +// signature. No per-signature stdlib boilerplate. The shared +// infrastructure above (`Block`, `BlockDescriptor`, +// `_NSConcreteStackBlock`, `__sx_block_descriptor`) is referenced +// by the synthesised code; users only need to `#import` this module.