parse: enforce strict-package — reject package-less files (#24a)
Flip the soft-default to a hard "missing package clause" error symmetrically in both stages (cmd/wcc/parse.c + lib/ww/syntax/parse.ww): the first real decl of a primary section with empty pathmod/resetmod and no seen clause is now rejected. Closes the documented soft-default divergence (the 63-wrapper carve-out). The gate flip can't be split from the migration it breaks, so this is one atomic commit: ~80 test/wcc wrappers gain `package main;` via a shared wwtestpkg.h helper, 6 data fixtures plus 17 asm-grep assertions update for the bare->main.<leaf> root-helper mangle shift, and rt/ declares `package rt;` with @symbol pinning the bare rt_ensure/rt_malloc linker names. Root mangling narrows: the executable entry `main` stays bare (existing carve-out), but root helper symbols become main.X. The #84 cluster is rewritten to assert main.run distinct from aa.run/test.run; its cgen fix and bare machinery are retained — still load-bearing for package-less module-reset deps. New table-driven test 782_strict_package.c (6 rows, both stages). Retiring //ww:module-reset is deferred to #24b: it is load-bearing (clears the .wwi pathmod so the body's package clause asserts), not a vestige; fusing its removal here would be a silent mismatch. All byte-id gates green; full make test reports "all 335 tests passed".
This commit is contained in:
@@ -1407,18 +1407,16 @@ parsefile(Parser *p)
|
||||
Pos pp = { p->l->file, 1, 1 };
|
||||
Node *file = newnode(p->a, N_FILE, pp);
|
||||
Node *head = NULL, *tail = NULL;
|
||||
int sawpackage = 0;
|
||||
while (p->cur.kind != TK_EOF) {
|
||||
/* `package foo;` — directory-as-module declaration. Each
|
||||
* .ww file's section in a concatenated stream begins with
|
||||
* one; a single-file or fragment input may omit it (curmod
|
||||
* stays NULL and decls are treated as primary).
|
||||
*
|
||||
* Retained divergence from brief: the strict missing-`package`
|
||||
* error was softened to silent-default to keep 63 inline-source
|
||||
* test wrappers (200_parse, 100_lex, 300_check, ...) parsing.
|
||||
* See task #23 for the wrapper migration that unblocks the
|
||||
* strict check. Rule 7 + rule 8 documentation. */
|
||||
/* `package foo;` — directory-as-module declaration. Every
|
||||
* primary section opens with one (`package main;` for an
|
||||
* executable); a missing clause on the first real decl is a
|
||||
* hard error (strict-package, #24a). Imported (pathmod) and
|
||||
* sep primary-reset (resetmod) regions carry identity
|
||||
* out-of-band and are exempt. */
|
||||
if (p->cur.kind == TK_MODULE) {
|
||||
sawpackage = 1;
|
||||
advance(p);
|
||||
const char *name = expectident(p);
|
||||
expect(p, TK_SEMI);
|
||||
@@ -1457,6 +1455,7 @@ parsefile(Parser *p)
|
||||
* leaf `package` clause, and are flagged imported (gates the
|
||||
* root-only bare-`main` rule, #32). */
|
||||
if (p->cur.kind == TK_MODPATH) {
|
||||
sawpackage = 0;
|
||||
p->pathmod = p->cur.text;
|
||||
p->curmod = p->cur.text;
|
||||
p->resetmod = NULL;
|
||||
@@ -1472,6 +1471,7 @@ parsefile(Parser *p)
|
||||
* directive after a mid-file `package` would strip subsequent
|
||||
* decls to bare — that usage is deliberate-only. */
|
||||
if (p->cur.kind == TK_MODRESET) {
|
||||
sawpackage = 0;
|
||||
/* #57: a path-carrying reset (sep primary body) mangles
|
||||
* decls on the dotted path so definer == importer, but
|
||||
* leaves imported==0 (curmod set, pathmod NULL) so -c
|
||||
@@ -1498,6 +1498,16 @@ parsefile(Parser *p)
|
||||
}
|
||||
continue;
|
||||
}
|
||||
/* strict-package: a primary section's first real decl must be
|
||||
* preceded by a `package` clause. Imported (pathmod) and sep
|
||||
* primary-reset (resetmod) regions carry identity out-of-band,
|
||||
* so they are exempt. Wording mirrors Go's missing-`package`
|
||||
* diagnostic (rule 5; Hare has no clause to port). */
|
||||
if (p->pathmod == NULL && p->resetmod == NULL && !sawpackage) {
|
||||
errorf(p->cur.pos, "missing package clause");
|
||||
p->errs++;
|
||||
sawpackage = 1;
|
||||
}
|
||||
Node *attrs = parseattrs(p);
|
||||
int exp = accept(p, TK_EXPORT);
|
||||
Node *d = NULL;
|
||||
|
||||
Reference in New Issue
Block a user