From e53c85885559144f3273cfa13a10c6531787d173 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Thu, 14 Apr 2022 15:47:49 +0100 Subject: [PATCH] Add NS.Block to allow for the creation of block-like lambdas in Odin --- vendor/darwin/Foundation/block_literal.odin | 67 +++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 vendor/darwin/Foundation/block_literal.odin diff --git a/vendor/darwin/Foundation/block_literal.odin b/vendor/darwin/Foundation/block_literal.odin new file mode 100644 index 000000000..19e9782e4 --- /dev/null +++ b/vendor/darwin/Foundation/block_literal.odin @@ -0,0 +1,67 @@ +package objc_Foundation + +import "core:intrinsics" + +Internal_Block_Literal_Base :: struct { + isa: ^intrinsics.objc_class, + flags: u32, + reserved: u32, + invoke: proc "c" (^Internal_Block_Literal), + descriptor: ^Block_Descriptor, +} + +Internal_Block_Literal :: struct { + using base: Internal_Block_Literal_Base, + // Imported Variables + user_proc: proc "c" (user_data: rawptr), + user_data: rawptr, +} + +Block_Descriptor :: struct { + reserved: uint, + size: uint, + copy_helper: proc "c" (dst, src: rawptr), + dispose_helper: proc "c" (src: rawptr), + signature: cstring, +} + +global_block_descriptor := Block_Descriptor{ + reserved = 0, + size = size_of(Internal_Block_Literal), +} + + +@(objc_class="NSConcreteGlobalBlock") +Block :: struct {using _: Object} + +@(objc_type=Block, objc_name="create", objc_is_class_method=true) +Block_create :: proc "c" (user_data: rawptr, user_proc: proc "c" (user_data: rawptr)) -> ^Block { + // Set to true on blocks that have captures (and thus are not true + // global blocks) but are known not to escape for various other + // reasons. For backward compatibility with old runtimes, whenever + // BLOCK_IS_NOESCAPE is set, BLOCK_IS_GLOBAL is set too. Copying a + // non-escaping block returns the original block and releasing such a + // block is a no-op, which is exactly how global blocks are handled. + BLOCK_IS_NOESCAPE :: (1 << 23)|BLOCK_IS_GLOBAL + + BLOCK_HAS_COPY_DISPOSE :: 1 << 25 + BLOCK_HAS_CTOR :: 1 << 26 // helpers have C++ code + BLOCK_IS_GLOBAL :: 1 << 28 + BLOCK_HAS_STRET :: 1 << 29 // IFF BLOCK_HAS_SIGNATURE + BLOCK_HAS_SIGNATURE :: 1 << 30 + + extraBytes :: size_of(Internal_Block_Literal) - size_of(Internal_Block_Literal_Base) + + cls := intrinsics.objc_find_class("NSConcreteGlobalBlock") + bl := (^Internal_Block_Literal)(AllocateObject(cls, extraBytes, nil)) + bl.isa = cls + bl.flags = BLOCK_IS_GLOBAL + bl.invoke = proc "c" (bl: ^Internal_Block_Literal) { + bl.user_proc(bl.user_data) + } + bl.descriptor = &global_block_descriptor + bl.user_proc = user_proc + bl.user_data = user_data + + return auto_cast bl +}