w6c+selfhost: cross-module same-leaf type disambiguation via Sym.mod
This commit is contained in:
@@ -64,18 +64,42 @@ fn seedprimitives(c: *checker) void = {
|
||||
scopedefine(c.top, "append", skind.SK_FN, nil, nil);
|
||||
};
|
||||
|
||||
// declmod — module-tag stamp for a top-level decl.
|
||||
//
|
||||
// The driver concatenates imported sources before the primary file and
|
||||
// emits `// MODULE: foo` directives the lexer pins onto each decl's
|
||||
// `module` field. We treat a decl as "imported" iff its module
|
||||
// directive matches some `use IDENT;` bareword in this compilation
|
||||
// unit. Primary-file decls return "" so they coexist (mod="") with
|
||||
// imported decls of the same leaf name in scopelookupinmodule.
|
||||
fn declmod(file: *node, d: *node) str = {
|
||||
let empty: str;
|
||||
if (d == nil) { return empty; };
|
||||
if (d.module.len == 0) { return empty; };
|
||||
if (file == nil) { return empty; };
|
||||
let u: *node = file.list;
|
||||
for (u != nil) {
|
||||
if (u.kind == nkind.N_USE) {
|
||||
if (streq(u.str, d.module)) { return d.module; };
|
||||
};
|
||||
u = u.next;
|
||||
};
|
||||
return empty;
|
||||
};
|
||||
|
||||
// installdecl — install the top-level decl's name into the top scope.
|
||||
// We don't compute its type yet (that's the resolve pass) — just bind
|
||||
// the name so forward references resolve.
|
||||
fn installdecl(c: *checker, d: *node) void = {
|
||||
fn installdecl(c: *checker, file: *node, d: *node) void = {
|
||||
if (d == nil) { return; };
|
||||
let k: nkind = d.kind;
|
||||
let nm: str = d.str;
|
||||
let mod: str = declmod(file, d);
|
||||
if (k == nkind.N_USE) { scopedefine(c.top, nm, skind.SK_USE, nil, d); return; };
|
||||
if (k == nkind.N_DEF) { scopedefine(c.top, nm, skind.SK_DEF, nil, d); return; };
|
||||
if (k == nkind.N_TYPEDECL) { scopedefine(c.top, nm, skind.SK_TYPE, nil, d); return; };
|
||||
if (k == nkind.N_FNDECL) { scopedefine(c.top, nm, skind.SK_FN, nil, d); return; };
|
||||
if (k == nkind.N_LET) { scopedefine(c.top, nm, skind.SK_VAR, nil, d); return; };
|
||||
if (k == nkind.N_DEF) { scopedefineinmodule(c.top, nm, mod, skind.SK_DEF, nil, d); return; };
|
||||
if (k == nkind.N_TYPEDECL) { scopedefineinmodule(c.top, nm, mod, skind.SK_TYPE, nil, d); return; };
|
||||
if (k == nkind.N_FNDECL) { scopedefineinmodule(c.top, nm, mod, skind.SK_FN, nil, d); return; };
|
||||
if (k == nkind.N_LET) { scopedefineinmodule(c.top, nm, mod, skind.SK_VAR, nil, d); return; };
|
||||
};
|
||||
|
||||
// resolvewalk — recursive AST walk that, for every nkind.N_IDENT and
|
||||
@@ -122,8 +146,10 @@ fn resolvewalk(c: *checker, n: *node) void = {
|
||||
if (nm.len > 0) {
|
||||
let s: *sym = scopelookup(c.cur, nm);
|
||||
// `pkg.Type` — strip the last dot prefix and look up
|
||||
// the leaf if `pkg` is a use-imported name. Mirrors
|
||||
// cmd/wcc/check.c resolve_typename.
|
||||
// the leaf with a mod filter so same-leaf-name types
|
||||
// from different imports (`bufio.stream` vs
|
||||
// `io.stream`) disambiguate to the right one.
|
||||
// Mirrors cmd/wcc/check.c resolve_typename.
|
||||
if (s == nil) {
|
||||
let dot: i32 = nm.len - 1;
|
||||
for (dot >= 0) {
|
||||
@@ -139,7 +165,7 @@ fn resolvewalk(c: *checker, n: *node) void = {
|
||||
let leaf: str;
|
||||
leaf.ptr = nm.ptr + (dot + 1): u64;
|
||||
leaf.len = nm.len - (dot + 1);
|
||||
s = scopelookup(c.cur, leaf);
|
||||
s = scopelookupinmodule(c.cur, head, leaf);
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -927,7 +953,7 @@ export fn checkfile(c: *checker, file: *node) void = {
|
||||
// Pass 1: install all top-level names.
|
||||
let d: *node = file.list;
|
||||
for (d != nil) {
|
||||
installdecl(c, d);
|
||||
installdecl(c, file, d);
|
||||
d = d.next;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user