wcc: @test marker attributes + runner

Hare-style `@test fn check_foo() void = { ... }` now parses. The
attribute is recognised by making the args list optional in
parseattrs: `@symbol("rt_syscall")` still requires the parens;
`@test` doesn't. Same change mirrored in lib/ww/parse/decl.ww.

The runner (test/wcc/910_at_test.c) scans a fixture for
`@test fn IDENT(`, synthesises a wrapper `main()` that calls each
test fn, builds it via `ww run`, and asserts exit 0. A failing
@test would either explicitly call abort or trip a runtime trap
(div-by-zero, etc.) and the whole driver exits non-zero.

The 910_at_test target sits alongside the existing C-side test
binaries; `make test` now runs 20 tests instead of 19.

Fixture: test/wcc/data/attest_pass.ww exercises two passing tests
(simple arithmetic and a match-with-yield).
This commit is contained in:
2026-05-12 03:14:20 +09:00
parent 404705b6fd
commit 906e17b128
7 changed files with 228 additions and 18 deletions

View File

@@ -2793,11 +2793,14 @@ fn parseattrs(p: *parser) *node = {
let id: str;
expectident(p, &id);
a.str = id;
expecttok(p, TK_LPAREN, "expected '(' after attribute name");
let arghead: *node = nil;
parsearglist(p, TK_RPAREN, &arghead);
a.list = arghead;
expecttok(p, TK_RPAREN, "expected ')' after attribute args");
// `@name(args...)` for FFI-style attrs; `@name` for marker-
// only attrs like @test (no parens).
if (accepttok(p, TK_LPAREN)) {
let arghead: *node = nil;
parsearglist(p, TK_RPAREN, &arghead);
a.list = arghead;
expecttok(p, TK_RPAREN, "expected ')' after attribute args");
};
if (head == nil) { head = a; tail = a; }
else { tail.next = a; tail = a; };
};

View File

@@ -2793,11 +2793,14 @@ fn parseattrs(p: *parser) *node = {
let id: str;
expectident(p, &id);
a.str = id;
expecttok(p, TK_LPAREN, "expected '(' after attribute name");
let arghead: *node = nil;
parsearglist(p, TK_RPAREN, &arghead);
a.list = arghead;
expecttok(p, TK_RPAREN, "expected ')' after attribute args");
// `@name(args...)` for FFI-style attrs; `@name` for marker-
// only attrs like @test (no parens).
if (accepttok(p, TK_LPAREN)) {
let arghead: *node = nil;
parsearglist(p, TK_RPAREN, &arghead);
a.list = arghead;
expecttok(p, TK_RPAREN, "expected ')' after attribute args");
};
if (head == nil) { head = a; tail = a; }
else { tail.next = a; tail = a; };
};