// issue-0028: Feature — make protocol boxes assignable to an optional // type so callers can spell "no GPU bound" as `?GPU = null` instead of // the verbose `T = ---; has_T: bool` pattern. // // ── Current pattern (verbose) ───────────────────────────────────────────── // // gpu: GPU = ---; // has_gpu: bool = false; // ... // if self.has_gpu { self.gpu.create_shader(...); } // // ── Proposed pattern ────────────────────────────────────────────────────── // // gpu: ?GPU = null; // ... // if self.gpu != null { self.gpu.create_shader(...); } // // ── Where the verbose pattern lives today ───────────────────────────────── // // library/modules/ui/renderer.sx — UIRenderer.gpu + has_gpu // library/modules/ui/glyph_cache.sx — GlyphCache.gpu + has_gpu // library/modules/ui/pipeline.sx — UIPipeline.gpu + has_gpu (+ set_gpu) // library/modules/platform/uikit.sx — UIKitPlatform.frame_closure + // has_frame_closure (Closure type, // same pattern but on a closure) // // ── Implementation sketch ───────────────────────────────────────────────── // // Protocol boxes are 2-pointer structs ({vtable, ctx} or {ctx, fn_ptrs...} // depending on the inline-vs-vtable shape — see src/ir/lower.zig // `buildProtocolValue` ~7800-7869). `?T` for these can use `vtable_ptr == // null` (or `ctx == null`, depending on layout choice) as the "none" // sentinel — no extra storage needed. This matches the existing // optional-closure handling at src/ir/emit_llvm.zig where `?Closure` uses // `fn_ptr == null` as none. // // Approach: // 1. Extend `?T` type construction to accept T being a protocol type. // Files: src/ir/types.zig + src/ir/lower.zig (type-resolution). // 2. Implement `optional_wrap` / `optional_unwrap` / // `optional_has_value` for protocol-typed payloads in // src/ir/emit_llvm.zig — model after the closure-optional path. // 3. Keep the existing `T = ---; has_T: bool` pattern working — the // new `?T` is additive, not a replacement. Don't churn existing // files (uikit.sx's frame_closure pattern stays). // // ── Syntax constraint ───────────────────────────────────────────────────── // // `?T` syntax already exists for primitives + pointers. Extending to // protocols is a type-system change; no new surface syntax needed. #import "modules/std.sx"; main :: () -> s32 { 0; }