ffi M5.A.next.1b: parser accepts ..$args as a variadic-pack param
Extends parseParams in src/parser.zig:1558 to recognize a leading `..` before the optional `$` sigil and the parameter name. The old `args: ..T` form (variadic marker after the colon) still works — both paths set the same `is_variadic` flag. A pack declaration `..$args` parses as: - `is_variadic = true` (from the leading `..`) - `is_comptime = true` (from the `$` sigil) - `type_expr = inferred_type` (no `:` annotation) The no-colon branch now propagates `is_variadic` and `is_comptime` onto the Param struct so later slices (type rep, impl matching, monomorphisation) can read both flags from the parsed AST without re-deriving from token sequence. `examples/150-pack-parse.sx` flips from rejecting-with-error to positive parse smoke. No semantic effect yet — `foo` is declared but never instantiated. 191/191 example tests + `zig build test` green.
This commit is contained in:
@@ -1,14 +1,14 @@
|
|||||||
// Variadic heterogeneous type packs — `..$args` — parse lockin.
|
// Variadic heterogeneous type packs — `..$args` — parse smoke.
|
||||||
//
|
//
|
||||||
// First slice of the pack feature: the parser does not yet accept
|
// First positive slice of the pack feature: the parser accepts
|
||||||
// `..$args` (variadic-marker + comptime sigil + name, no type
|
// `..$args` (variadic marker + comptime sigil + name) as a
|
||||||
// annotation). This test pins the current parse-rejection so the
|
// parameter declaration. No semantic effect yet — the function
|
||||||
// next commit's parser change is visible as a behavior shift.
|
// is declared but never instantiated; main exists so the example
|
||||||
|
// has runnable output.
|
||||||
//
|
//
|
||||||
// Expected next commit: parser accepts `..$args` and this test
|
// Next slices: type-system representation of the pack, impl
|
||||||
// either flips to a successful parse (compile error from later
|
// matching for `Closure(..$args) -> $R`, runtime indexing
|
||||||
// passes that haven't been wired up yet) or is replaced by a
|
// (`args[$i]`), and the `#insert build_x($args, ...)` pattern.
|
||||||
// positive test.
|
|
||||||
|
|
||||||
#import "modules/std.sx";
|
#import "modules/std.sx";
|
||||||
|
|
||||||
@@ -17,6 +17,6 @@ foo :: (..$args) -> s64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
main :: () -> s32 {
|
main :: () -> s32 {
|
||||||
print("never reached\n");
|
print("pack parse ok\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1563,6 +1563,15 @@ pub const Parser = struct {
|
|||||||
try self.expect(.comma);
|
try self.expect(.comma);
|
||||||
if (self.current.tag == .r_paren) break;
|
if (self.current.tag == .r_paren) break;
|
||||||
}
|
}
|
||||||
|
// Leading `..` marks a variadic param at the binding site
|
||||||
|
// (e.g., `..$args` heterogeneous pack, or future homogeneous
|
||||||
|
// `..args: []$T`). The old `args: ..T` form keeps its marker
|
||||||
|
// after the colon (handled below).
|
||||||
|
var is_variadic = false;
|
||||||
|
if (self.current.tag == .dot_dot) {
|
||||||
|
is_variadic = true;
|
||||||
|
self.advance();
|
||||||
|
}
|
||||||
var is_ct_param = false;
|
var is_ct_param = false;
|
||||||
if (self.current.tag == .dollar) {
|
if (self.current.tag == .dollar) {
|
||||||
is_ct_param = true;
|
is_ct_param = true;
|
||||||
@@ -1577,12 +1586,17 @@ pub const Parser = struct {
|
|||||||
// Optional type annotation: if no ':', infer type from context
|
// Optional type annotation: if no ':', infer type from context
|
||||||
if (self.current.tag != .colon) {
|
if (self.current.tag != .colon) {
|
||||||
const inferred_node = try self.createNode(param_name_span.start, .{ .inferred_type = {} });
|
const inferred_node = try self.createNode(param_name_span.start, .{ .inferred_type = {} });
|
||||||
try params.append(self.allocator, .{ .name = param_name, .name_span = param_name_span, .type_expr = inferred_node });
|
try params.append(self.allocator, .{ .name = param_name, .name_span = param_name_span, .type_expr = inferred_node, .is_variadic = is_variadic, .is_comptime = is_ct_param });
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
self.advance(); // consume ':'
|
self.advance(); // consume ':'
|
||||||
const is_variadic = self.current.tag == .dot_dot;
|
// Old syntax keeps the variadic marker after the colon
|
||||||
if (is_variadic) self.advance();
|
// (`args: ..T`). Accept it even if a leading `..` already
|
||||||
|
// appeared — both forms set the same flag.
|
||||||
|
if (self.current.tag == .dot_dot) {
|
||||||
|
is_variadic = true;
|
||||||
|
self.advance();
|
||||||
|
}
|
||||||
const param_type = try self.parseTypeExpr();
|
const param_type = try self.parseTypeExpr();
|
||||||
var is_comptime_param = false;
|
var is_comptime_param = false;
|
||||||
if (is_ct_param and param_type.data == .type_expr) {
|
if (is_ct_param and param_type.data == .type_expr) {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
1
|
0
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
/Users/agra/projects/sx/examples/150-pack-parse.sx:15:9: error: expected parameter name
|
pack parse ok
|
||||||
|
|||||||
Reference in New Issue
Block a user