lang F1 4.2: (..F(Ts)) per-element type application in pack-shaped fields
packTypeElems now handles a parameterized spread operand F(Ts): for each pack element T_i it temporarily binds the pack name to T_i and resolves F(T_i), yielding (VL(T0), VL(T1), ...). Combined with parameterized-protocol value types, the canonical Combined struct field sources: (..VL(Ts)) now resolves to a tuple of real protocol values. End-to-end (examples/207): instantiate Combined(s64, s64, string), whole-store c.sources = (xx IntCell, xx StrCell), and per-element dispatch c.sources.0.get() / c.sources.1.get() all work. 242 examples + unit green.
This commit is contained in:
@@ -11221,7 +11221,36 @@ pub const Lowering = struct {
|
||||
/// `impl P(args) for elem` in `param_impl_map`). Null when not a pack spread.
|
||||
/// Caller owns the returned slice.
|
||||
fn packTypeElems(self: *Lowering, operand: *const Node) ?[]TypeId {
|
||||
if (self.pack_arg_types == null) return null;
|
||||
const pat = self.pack_arg_types orelse return null;
|
||||
// `..F(Ts)` — apply a parameterized type `F` to each pack element:
|
||||
// `(..VL(Ts))` → `(VL(T0), VL(T1), …)`. Per element, temporarily bind
|
||||
// the pack name to that single element type and resolve `F(elem)`.
|
||||
if (operand.data == .parameterized_type_expr) {
|
||||
const pt = operand.data.parameterized_type_expr;
|
||||
var pack_name_p: []const u8 = "";
|
||||
for (pt.args) |a| {
|
||||
const nm = switch (a.data) {
|
||||
.identifier => |id| id.name,
|
||||
.type_expr => |te| te.name,
|
||||
else => continue,
|
||||
};
|
||||
if (pat.contains(nm)) {
|
||||
pack_name_p = nm;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pack_name_p.len == 0) return null;
|
||||
const elems = pat.get(pack_name_p) orelse return null;
|
||||
if (self.type_bindings == null) return null;
|
||||
var out = std.ArrayList(TypeId).empty;
|
||||
for (elems) |ti| {
|
||||
const had = self.type_bindings.?.get(pack_name_p);
|
||||
self.type_bindings.?.put(pack_name_p, ti) catch {};
|
||||
out.append(self.alloc, self.resolveTypeWithBindings(operand)) catch return null;
|
||||
if (had) |h| self.type_bindings.?.put(pack_name_p, h) catch {} else _ = self.type_bindings.?.remove(pack_name_p);
|
||||
}
|
||||
return out.toOwnedSlice(self.alloc) catch null;
|
||||
}
|
||||
// In type position `xs` / `xs.T` parse to a (possibly dotted) type_expr
|
||||
// name; `field_access` covers any value-shaped form.
|
||||
var pack_name: []const u8 = "";
|
||||
|
||||
Reference in New Issue
Block a user