Browse Source

Add NS.Block to allow for the creation of block-like lambdas in Odin

gingerBill 3 years ago
parent
commit
e53c858855
1 changed files with 67 additions and 0 deletions
  1. 67 0
      vendor/darwin/Foundation/block_literal.odin

+ 67 - 0
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
+}