Switch symbol mangling from the import leaf clause to the full dotted import path for directory packages; single-file imports keep package-clause mangling (isdir-gate: imported<=>directory-import). The root build unit's fn main stays bare, every other top-level decl mangles, closing #31's duplicate-main hazard by construction (#32). Both stages, byte-identical. Single commit, not split: the bare rename (f244af3) is red on its own because it unmasks cross-module resolution gaps that do not reproduce pre-M1, so the fixes are intrinsic to making the rename correct. Included: wwstage fnret/fnparamslookupmod map import alias->path (#199b cross-module union-variant scrutinee resolved the wrong fn's union); cstage use_path prefers the referencing module's import for an ambiguous leaf alias (sha256 crypto.math vs strconv math). Tests table-driven: 989_m1mangle_run/_sym, 989_m1union_run (gate-visible per-arm exit codes + cs==ww byte-id).
This commit is contained in:
@@ -102,14 +102,38 @@ skipws(Lex *l)
|
||||
* then skipped like any comment. Mirrors the removed
|
||||
* `// MODULE:` lexer directive. */
|
||||
{
|
||||
static const char dir[] = "ww:module-reset";
|
||||
static const char pre[] = "ww:module";
|
||||
size_t i = 0;
|
||||
while (dir[i] && lpeek(l, i) == dir[i])
|
||||
while (pre[i] && lpeek(l, i) == pre[i])
|
||||
i++;
|
||||
if (dir[i] == '\0') {
|
||||
if (pre[i] == '\0') {
|
||||
int nx = lpeek(l, i);
|
||||
if (nx == '\n' || nx < 0)
|
||||
l->modreset = 1;
|
||||
if (nx == '-') {
|
||||
static const char rest[] = "-reset";
|
||||
size_t j = 0;
|
||||
while (rest[j] && lpeek(l, i + j) == rest[j])
|
||||
j++;
|
||||
if (rest[j] == '\0') {
|
||||
int af = lpeek(l, i + j);
|
||||
if (af == '\n' || af < 0)
|
||||
l->modreset = 1;
|
||||
}
|
||||
} else if (nx == ' ' || nx == '\t') {
|
||||
/* `//ww:module <path>` — M1 import boundary. */
|
||||
size_t k = i;
|
||||
while (lpeek(l, k) == ' '
|
||||
|| lpeek(l, k) == '\t')
|
||||
k++;
|
||||
size_t s = k;
|
||||
int ch;
|
||||
while ((ch = lpeek(l, k)) >= 0
|
||||
&& ch != '\n' && ch != '\r'
|
||||
&& ch != ' ' && ch != '\t')
|
||||
k++;
|
||||
if (k > s)
|
||||
l->modpath = astrndup(l->a,
|
||||
l->src + l->pos + s, k - s);
|
||||
}
|
||||
}
|
||||
}
|
||||
while ((c = lpeek(l, 0)) >= 0 && c != '\n')
|
||||
@@ -403,6 +427,13 @@ lexnext(Lex *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 (l->modpath) {
|
||||
const char *mp = l->modpath;
|
||||
l->modpath = NULL;
|
||||
Tok _t = (Tok){ TK_MODPATH, start, NULL, 0, {0}, TK_NONE };
|
||||
_t.text = mp; _t.tlen = strlen(mp);
|
||||
return _t;
|
||||
}
|
||||
if (!more) {
|
||||
Tok t = (Tok){ TK_EOF, start, "", 0, {0}, TK_NONE };
|
||||
return t;
|
||||
|
||||
Reference in New Issue
Block a user