lex: clear pending modpath on module-reset, fix empty-module stale-modpath miscompile (#9)

BUG-A #9: when an empty/export-less inlined module body produces `//ww:module <p>` immediately followed by `//ww:module-reset` in one skipws run, lexnext drained TK_MODRESET first then emitted the STALE TK_MODPATH past the reset boundary, re-binding pathmod=<p> so the root `package main` was validated against <p> -> wrong reject. Fix clears the pending modpath at the reset-RECOGNITION site in skipws (NOT lexnext drain): cstage l->modpath=NULL after both l->modreset=1 (cmd/wcc/lex.c); selfhost l.modpathset=0 after all three l.modreset=1 (lib/ww/syntax/lex.ww). Symmetric (rule-10): identical token streams, bootstrap byte-id holds. The normal RESET-then-PATH boundary is unaffected (clear is a no-op when no path is pending). Pin: test/wcc/989_modresetadj_run.c feeds the raw composed adjacency to w6c+w6c_ww (accept + byte-id), red-path-proven (reverting a clear reddens it). A separate wwi-producer defect surfaced (decl-less .wwi defaults to 'package main') filed as #11; not touched here.
This commit is contained in:
2026-06-22 19:49:57 +09:00
parent 99b98b9b1b
commit c0383274d1
4 changed files with 226 additions and 3 deletions

View File

@@ -117,6 +117,9 @@ skipws(Lex *l)
int af = lpeek(l, i + j);
if (af == '\n' || af < 0) {
l->modreset = 1;
l->modpath = NULL; /* #9: a reset supersedes a path opened
* earlier in this skipws run (empty/
* export-less inlined module body) */
} else if (af == ' '
|| af == '\t') {
/* `//ww:module-reset <path>`
@@ -136,6 +139,7 @@ skipws(Lex *l)
&& dch != '\t')
k++;
l->modreset = 1;
l->modpath = NULL; /* #9: see above — clear pending path */
if (k > s)
l->modresetpath =
astrndup(l->a,