wcc+ww: //ww:module-reset boundary directive; package-less files keep module "" (#16 PREP-main)
Driver twins emit the line-comment directive only before package-less files (peekpackage==nil); both lexers tokenize it (TK_MODRESET, appended =87 so existing token values hold) and both parsers reset curmod — a package-less file's decls get module "" instead of inheriting the last bundled package (the sticky-curmod leak, task #11). Withdrawn alternative: injecting 'package main' flips non-entry symbols bare->main-prefixed (FFI-visible, broke 764). Codegen-neutral by proof: bare symbols preserved, both stages emit byte-identical asm for a directive-bearing combined. Transitional until strict-package rejects package-less files outright. Includes 737 bad-deep pin for the PREP-peek >2048 edge + 904/toktest rows for the new token.
This commit is contained in:
@@ -95,6 +95,23 @@ skipws(Lex *l)
|
||||
}
|
||||
if (c == '/' && lpeek(l, 1) == '/') {
|
||||
lget(l); lget(l); /* consume '//' */
|
||||
/* #16 option-B: the driver emits `//ww:module-reset`
|
||||
* before a package-less file's bytes; recognize the
|
||||
* whole-line directive (without consuming differently)
|
||||
* and flag it so lexnext emits TK_MODRESET. The body is
|
||||
* then skipped like any comment. Mirrors the removed
|
||||
* `// MODULE:` lexer directive. */
|
||||
{
|
||||
static const char dir[] = "ww:module-reset";
|
||||
size_t i = 0;
|
||||
while (dir[i] && lpeek(l, i) == dir[i])
|
||||
i++;
|
||||
if (dir[i] == '\0') {
|
||||
int nx = lpeek(l, i);
|
||||
if (nx == '\n' || nx < 0)
|
||||
l->modreset = 1;
|
||||
}
|
||||
}
|
||||
while ((c = lpeek(l, 0)) >= 0 && c != '\n')
|
||||
lget(l);
|
||||
continue;
|
||||
@@ -381,12 +398,15 @@ lexrune(Lex *l, Pos start)
|
||||
Tok
|
||||
lexnext(Lex *l)
|
||||
{
|
||||
if (!skipws(l)) {
|
||||
Pos p = lpos(l);
|
||||
Tok t = (Tok){ TK_EOF, p, "", 0, {0}, TK_NONE };
|
||||
int more = skipws(l);
|
||||
Pos start = lpos(l);
|
||||
/* A `//ww:module-reset` seen in the skipped run surfaces as its own
|
||||
* token before the next real one (#16 option-B boundary reset). */
|
||||
if (l->modreset) { l->modreset = 0; EMIT(TK_MODRESET); }
|
||||
if (!more) {
|
||||
Tok t = (Tok){ TK_EOF, start, "", 0, {0}, TK_NONE };
|
||||
return t;
|
||||
}
|
||||
Pos start = lpos(l);
|
||||
int c = lpeek(l, 0);
|
||||
|
||||
if (isidstart(c))
|
||||
|
||||
@@ -1363,6 +1363,19 @@ parsefile(Parser *p)
|
||||
p->curmod = name;
|
||||
continue;
|
||||
}
|
||||
/* `//ww:module-reset` — bundle boundary before a package-less
|
||||
* file. Reset curmod to NULL so the file's decls (and its own
|
||||
* `import os;`) are attributed to the primary module (""), not
|
||||
* the preceding bundled package. Codegen-neutral: NULL curmod
|
||||
* keeps bare symbols. (#16 option-B; closes task #11.)
|
||||
* Driver-emitted ONLY before package-less files; a hand-placed
|
||||
* directive after a mid-file `package` would strip subsequent
|
||||
* decls to bare — that usage is deliberate-only. */
|
||||
if (p->cur.kind == TK_MODRESET) {
|
||||
advance(p);
|
||||
p->curmod = NULL;
|
||||
continue;
|
||||
}
|
||||
Node *attrs = parseattrs(p);
|
||||
int exp = accept(p, TK_EXPORT);
|
||||
Node *d = NULL;
|
||||
|
||||
@@ -103,6 +103,7 @@ tokname(Tkind k)
|
||||
case TK_UNDER: return "_";
|
||||
case TK_ENUM: return "enum";
|
||||
case TK_MODULE: return "package";
|
||||
case TK_MODRESET: return "//ww:module-reset";
|
||||
|
||||
case TK_LPAREN: return "(";
|
||||
case TK_RPAREN: return ")";
|
||||
|
||||
@@ -180,6 +180,10 @@ typedef enum {
|
||||
TK_YIELD, /* `yield expr;` — value-return from a match arm */
|
||||
TK_ENUM, /* Hare-style `enum [storage] { ... }` type form */
|
||||
TK_MODULE, /* `module foo;` — directory-as-module declaration */
|
||||
TK_MODRESET, /* `//ww:module-reset` — driver bundle boundary: reset
|
||||
* curmod to NULL before a package-less file's bytes
|
||||
* (#16 option-B; the package-less-entry attribution fix
|
||||
* that replaces the withdrawn `package main` inject). */
|
||||
|
||||
TK_LAST /* sentinel for tables */
|
||||
} Tkind;
|
||||
@@ -207,6 +211,9 @@ struct Lex {
|
||||
i32 col;
|
||||
Arena *a; /* token-text arena */
|
||||
int errs;
|
||||
int modreset; /* a `//ww:module-reset` directive was seen in
|
||||
* the last skipped run; lexnext emits TK_MODRESET
|
||||
* before the next real token. */
|
||||
};
|
||||
|
||||
void lexinit(Lex*, Arena*, const char *file, const char *src, u64 len);
|
||||
|
||||
Reference in New Issue
Block a user