lang F1 4.2 (core): generic struct pack type-param + (..$Ts) tuple field

A generic struct can take a pack type-param ..$Ts: []Type that binds the
remaining type args as a sequence, and a pack-shaped tuple field (..$Ts)
resolves to a tuple of those per-position types.

- parser/ast: accept a leading .. on a struct generic param; StructTypeParam
  gains is_variadic.
- registration: TemplateParam carries is_variadic (and is a type param).
- instantiateGenericStruct: a variadic type-param consumes the remaining args
  into pack_bindings + pack_arg_types (mangled into the name); restored after.
- resolveTypeWithBindings: a tuple-literal-as-type containing a pack spread
  (e.g. (..$Ts)) expands via packTypeElems.

Instantiate + correct per-position field types + whole-tuple store + element
read all work (examples/205). Not yet: protocol-applied field (..F(Ts)) (the
canonical (..VL(Ts)) shape) and nested element assignment b.pair.0 = v.
240 examples + unit green.
This commit is contained in:
agra
2026-05-30 02:30:49 +03:00
parent 82b46bc412
commit b48766d153
6 changed files with 99 additions and 6 deletions

View File

@@ -852,6 +852,13 @@ pub const Parser = struct {
try self.expect(.comma);
if (self.current.tag == .r_paren) break;
}
// Optional leading `..` — a pack type-param `..$Ts: []Type`
// (must be the last param; binds the remaining type args).
var is_variadic = false;
if (self.current.tag == .dot_dot) {
is_variadic = true;
self.advance();
}
// Expect $name : constraint
try self.expect(.dollar);
if (self.current.tag != .identifier) {
@@ -874,7 +881,7 @@ pub const Parser = struct {
}
}
const pc = try pc_list.toOwnedSlice(self.allocator);
try type_params.append(self.allocator, .{ .name = param_name, .constraint = constraint, .protocol_constraints = pc });
try type_params.append(self.allocator, .{ .name = param_name, .constraint = constraint, .protocol_constraints = pc, .is_variadic = is_variadic });
}
try self.expect(.r_paren);
}