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:
@@ -298,6 +298,11 @@ enum_to_string :: (u: $T) -> string {
|
|||||||
result;
|
result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
optional_to_string :: (o: $T) -> string {
|
||||||
|
if o == null { return "null"; }
|
||||||
|
return any_to_string(o!);
|
||||||
|
}
|
||||||
|
|
||||||
any_to_string :: (val: Any) -> string {
|
any_to_string :: (val: Any) -> string {
|
||||||
result := "<?>";
|
result := "<?>";
|
||||||
type := type_of(val);
|
type := type_of(val);
|
||||||
@@ -313,6 +318,7 @@ any_to_string :: (val: Any) -> string {
|
|||||||
case array: result = array_to_string(cast(type) val);
|
case array: result = array_to_string(cast(type) val);
|
||||||
case slice: result = slice_to_string(cast(type) val);
|
case slice: result = slice_to_string(cast(type) val);
|
||||||
case pointer: result = pointer_to_string(cast(type) val);
|
case pointer: result = pointer_to_string(cast(type) val);
|
||||||
|
case optional: result = optional_to_string(cast(type) val);
|
||||||
case type: { s : string = xx val; result = s; }
|
case type: { s : string = xx val; result = s; }
|
||||||
}
|
}
|
||||||
result;
|
result;
|
||||||
|
|||||||
@@ -9491,7 +9491,7 @@ pub const Lowering = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Dynamic categories: scan TypeTable for matching types
|
// 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"))
|
const cat: ?Category = if (std.mem.eql(u8, name, "struct"))
|
||||||
.@"struct"
|
.@"struct"
|
||||||
else if (std.mem.eql(u8, name, "enum") or std.mem.eql(u8, name, "union"))
|
else if (std.mem.eql(u8, name, "enum") or std.mem.eql(u8, name, "union"))
|
||||||
@@ -9504,6 +9504,8 @@ pub const Lowering = struct {
|
|||||||
.pointer
|
.pointer
|
||||||
else if (std.mem.eql(u8, name, "vector"))
|
else if (std.mem.eql(u8, name, "vector"))
|
||||||
.vector
|
.vector
|
||||||
|
else if (std.mem.eql(u8, name, "optional"))
|
||||||
|
.optional
|
||||||
else
|
else
|
||||||
null;
|
null;
|
||||||
|
|
||||||
@@ -9517,6 +9519,7 @@ pub const Lowering = struct {
|
|||||||
.array => info == .array,
|
.array => info == .array,
|
||||||
.pointer => info == .pointer or info == .many_pointer,
|
.pointer => info == .pointer or info == .many_pointer,
|
||||||
.vector => info == .vector,
|
.vector => info == .vector,
|
||||||
|
.optional => info == .optional,
|
||||||
};
|
};
|
||||||
if (matches) {
|
if (matches) {
|
||||||
tags.append(self.alloc, @intCast(idx)) catch {};
|
tags.append(self.alloc, @intCast(idx)) catch {};
|
||||||
|
|||||||
@@ -892,5 +892,3 @@ declare ptr @object_getClass(ptr)
|
|||||||
declare ptr @objc_getProtocol(ptr)
|
declare ptr @objc_getProtocol(ptr)
|
||||||
|
|
||||||
declare i8 @class_addProtocol(ptr, ptr)
|
declare i8 @class_addProtocol(ptr, ptr)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -953,5 +953,3 @@ entry:
|
|||||||
store ptr %selN, ptr @OBJC_SELECTOR_REFERENCES_actualSelectorName, align 8
|
store ptr %selN, ptr @OBJC_SELECTOR_REFERENCES_actualSelectorName, align 8
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user