ffi any_to_string handles optionals — make-green
Closes the optional-through-Any gap that test 178 pinned. Stdlib (`library/modules/std.sx`): - New `optional_to_string :: (o: $T) -> string` returns `"null"` when the optional is None, otherwise recurses through `any_to_string` on the unwrapped inner value. Per-shape monomorphisation re-emits this for each concrete `?T`. - `any_to_string` grows a `case optional:` arm that dispatches through `cast(type) val` (same shape as `case struct:` etc.). The cast picks up the dynamic optional type from the Any tag. Compiler (`src/ir/lower.zig`): - `resolveTypeCategoryTags` recognises "optional" as a dynamic category, scanning the TypeTable for `info == .optional`. The type-switch dispatch then routes any ?T tag into the optional arm. IR snapshots regenerated where the optional addition shifted constant pool / string numbering: 142, ffi-objc-call-06, ffi-objc-dsl-07. 218/218 (test 178 included). The variadic auto-unwrap in `packVariadicCallArgs` stays in place — direct `print(opt)` calls still flow through it. The new arm closes the gap for struct fields, slice elements, and any other path that boxes an optional before stringifying.
This commit is contained in:
@@ -9491,7 +9491,7 @@ pub const Lowering = struct {
|
||||
}
|
||||
|
||||
// Dynamic categories: scan TypeTable for matching types
|
||||
const Category = enum { @"struct", @"enum", @"union", slice, array, pointer, vector };
|
||||
const Category = enum { @"struct", @"enum", @"union", slice, array, pointer, vector, optional };
|
||||
const cat: ?Category = if (std.mem.eql(u8, name, "struct"))
|
||||
.@"struct"
|
||||
else if (std.mem.eql(u8, name, "enum") or std.mem.eql(u8, name, "union"))
|
||||
@@ -9504,6 +9504,8 @@ pub const Lowering = struct {
|
||||
.pointer
|
||||
else if (std.mem.eql(u8, name, "vector"))
|
||||
.vector
|
||||
else if (std.mem.eql(u8, name, "optional"))
|
||||
.optional
|
||||
else
|
||||
null;
|
||||
|
||||
@@ -9517,6 +9519,7 @@ pub const Lowering = struct {
|
||||
.array => info == .array,
|
||||
.pointer => info == .pointer or info == .many_pointer,
|
||||
.vector => info == .vector,
|
||||
.optional => info == .optional,
|
||||
};
|
||||
if (matches) {
|
||||
tags.append(self.alloc, @intCast(idx)) catch {};
|
||||
|
||||
Reference in New Issue
Block a user