ww: add file-scoped import aliases
This commit is contained in:
@@ -104,24 +104,41 @@ fn wwiusepath(c: *checker, owner: str, source: i32, alias: str) str = {
|
||||
return empty;
|
||||
};
|
||||
|
||||
fn wwidirectmodvisible(c: *checker, owner: str, source: i32, mod: str) bool = {
|
||||
if (mod.len == 0) { return false; };
|
||||
let u: *syntax.node = c.file.list;
|
||||
for (u != nil) {
|
||||
if (u.kind == syntax.nkind.N_USE && u.sourceid == source) {
|
||||
let same: bool = false;
|
||||
if (owner.len == 0) {
|
||||
same = u.imported == 0;
|
||||
} else {
|
||||
same = u.imported != 0 && wwimodeq(u.nmod, owner);
|
||||
};
|
||||
let path: str = u.str;
|
||||
if (u.usepath.len > 0) { path = u.usepath; };
|
||||
if (same && syntax.streq(path, mod)) { return true; };
|
||||
};
|
||||
u = u.next;
|
||||
// Canonical export spelling depends only on path identity, never on the
|
||||
// source alias or imported declared package name.
|
||||
fn wwicanonicalalias(fd: i32, path: str) void = {
|
||||
wputs(fd, "__wwi_");
|
||||
let i: i32 = 0;
|
||||
for (i < path.len) {
|
||||
let hi: u8 = path[i] >> 4u8;
|
||||
let lo: u8 = path[i] & 15u8;
|
||||
if (hi < 10u8) { wputb(fd, hi + 48u8); }
|
||||
else { wputb(fd, hi - 10u8 + 97u8); };
|
||||
if (lo < 10u8) { wputb(fd, lo + 48u8); }
|
||||
else { wputb(fd, lo - 10u8 + 97u8); };
|
||||
i += 1;
|
||||
};
|
||||
return false;
|
||||
};
|
||||
|
||||
fn wwiname(c: *checker, fd: i32, owner: str, source: i32, name: str) void = {
|
||||
let dotidx: i32 = -1;
|
||||
let i: i32 = 0;
|
||||
for (i < name.len) { if (name[i] == 46u8) { dotidx = i; }; i += 1; };
|
||||
if (dotidx >= 0) {
|
||||
let head: str;
|
||||
head.ptr = name.ptr;
|
||||
head.len = dotidx;
|
||||
let path: str = wwiusepath(c, owner, source, head);
|
||||
if (path.len > 0) {
|
||||
wwicanonicalalias(fd, path);
|
||||
let tail: str;
|
||||
tail.ptr = name.ptr + (dotidx: u64);
|
||||
tail.len = name.len - dotidx;
|
||||
wputs(fd, tail);
|
||||
return;
|
||||
};
|
||||
};
|
||||
wputs(fd, name);
|
||||
};
|
||||
|
||||
fn wwitypesym(c: *checker, owner: str, source: i32, nm: str) *syntax.sym = {
|
||||
@@ -145,22 +162,6 @@ fn wwitypesym(c: *checker, owner: str, source: i32, nm: str) *syntax.sym = {
|
||||
};
|
||||
} else {
|
||||
s = syntax.scopelookuptype(c.cur, owner, nm);
|
||||
if (s == nil) {
|
||||
let p: *syntax.scope = c.cur;
|
||||
for (p != nil && s == nil) {
|
||||
let b: *syntax.sym = p.first;
|
||||
for (b != nil) {
|
||||
if (b.skind == syntax.skind.SK_TYPE
|
||||
&& syntax.streq(b.name, nm)
|
||||
&& wwidirectmodvisible(c, owner, source, b.mod)) {
|
||||
s = b;
|
||||
break;
|
||||
};
|
||||
b = b.snext;
|
||||
};
|
||||
p = p.parent;
|
||||
};
|
||||
};
|
||||
};
|
||||
if (s == nil) { return nil; };
|
||||
if (s.skind != syntax.skind.SK_TYPE) { return nil; };
|
||||
@@ -307,15 +308,20 @@ fn wwirune(fd: i32, cp: u64) void = {
|
||||
wputb(fd, '\'');
|
||||
};
|
||||
|
||||
fn wwiexpr(fd: i32, e: *syntax.node) void = {
|
||||
fn wwiexpr(c: *checker, fd: i32, owner: str, source: i32,
|
||||
e: *syntax.node) void = {
|
||||
if (e == nil) { return; };
|
||||
if (e.kind == syntax.nkind.N_INTLIT) {
|
||||
wputs(fd, strconv.u64tos(e.uval, strconv.base.DEC));
|
||||
if (e.tsuffix.len > 0) { wputs(fd, e.tsuffix); };
|
||||
} else { if (e.kind == syntax.nkind.N_IDENT || e.kind == syntax.nkind.N_TNAME) {
|
||||
wputs(fd, e.str);
|
||||
wwiname(c, fd, owner, source, e.str);
|
||||
} else { if (e.kind == syntax.nkind.N_DOT) {
|
||||
wwiexpr(fd, e.lhs);
|
||||
if (e.lhs != nil && e.lhs.kind == syntax.nkind.N_IDENT) {
|
||||
let path: str = wwiusepath(c, owner, source, e.lhs.str);
|
||||
if (path.len > 0) { wwicanonicalalias(fd, path); }
|
||||
else { wwiexpr(c, fd, owner, source, e.lhs); };
|
||||
} else { wwiexpr(c, fd, owner, source, e.lhs); };
|
||||
wputb(fd, '.');
|
||||
wputs(fd, e.str);
|
||||
} else { if (e.kind == syntax.nkind.N_TRUE) {
|
||||
@@ -334,20 +340,20 @@ fn wwiexpr(fd: i32, e: *syntax.node) void = {
|
||||
wwirune(fd, e.uval);
|
||||
} else { if (e.kind == syntax.nkind.N_BIN) {
|
||||
wputb(fd, '(');
|
||||
wwiexpr(fd, e.lhs);
|
||||
wwiexpr(c, fd, owner, source, e.lhs);
|
||||
wputb(fd, 32u8);
|
||||
wputs(fd, syntax.tokname(e.op));
|
||||
wputb(fd, 32u8);
|
||||
wwiexpr(fd, e.rhs);
|
||||
wwiexpr(c, fd, owner, source, e.rhs);
|
||||
wputb(fd, ')');
|
||||
} else { if (e.kind == syntax.nkind.N_UN) {
|
||||
wputs(fd, syntax.tokname(e.op));
|
||||
wwiexpr(fd, e.lhs);
|
||||
wwiexpr(c, fd, owner, source, e.lhs);
|
||||
} else { if (e.kind == syntax.nkind.N_CAST) {
|
||||
wputb(fd, '(');
|
||||
wwiexpr(fd, e.lhs);
|
||||
wwiexpr(c, fd, owner, source, e.lhs);
|
||||
wputs(fd, ": ");
|
||||
wwitype(fd, e.rhs);
|
||||
wwitype(c, fd, owner, source, e.rhs);
|
||||
wputb(fd, ')');
|
||||
} else {
|
||||
wputs(2, "wwi: unhandled const-expr node kind\n");
|
||||
@@ -355,7 +361,8 @@ fn wwiexpr(fd: i32, e: *syntax.node) void = {
|
||||
};};};};};};};};};};};
|
||||
};
|
||||
|
||||
fn wwiparam(fd: i32, p: *syntax.node) void = {
|
||||
fn wwiparam(c: *checker, fd: i32, owner: str, source: i32,
|
||||
p: *syntax.node) void = {
|
||||
if (syntax.streq(p.str, "...")) { // C-style FFI `...`
|
||||
wputs(fd, "...");
|
||||
return;
|
||||
@@ -368,52 +375,57 @@ fn wwiparam(fd: i32, p: *syntax.node) void = {
|
||||
// in place to `[]T` (lhs becomes N_TSLICE); cstage leaves lhs == T.
|
||||
// Peel the inserted slice so both stages emit the surface `T...`.
|
||||
if (p.op == syntax.tkind.TK_ELLIPSIS && p.lhs != nil && p.lhs.kind == syntax.nkind.N_TSLICE) {
|
||||
wwitype(fd, p.lhs.lhs);
|
||||
wwitype(c, fd, owner, source, p.lhs.lhs);
|
||||
} else {
|
||||
wwitype(fd, p.lhs);
|
||||
wwitype(c, fd, owner, source, p.lhs);
|
||||
};
|
||||
if (p.op == syntax.tkind.TK_ELLIPSIS) { // Hare `T...` variadic
|
||||
wputs(fd, "...");
|
||||
};
|
||||
};
|
||||
|
||||
fn wwitype(fd: i32, t: *syntax.node) void = {
|
||||
fn wwitype(c: *checker, fd: i32, owner: str, source: i32,
|
||||
t: *syntax.node) void = {
|
||||
if (t == nil) { // absent return type spells void
|
||||
wputs(fd, "void");
|
||||
return;
|
||||
};
|
||||
// rule-10: unwrap the wwstage-only N_TPARAM tuple-element wrapper
|
||||
// (ast.ww:101) so the unparse matches cstage's pristine type-AST.
|
||||
if (t.kind == syntax.nkind.N_TPARAM) { wwitype(fd, t.lhs); return; };
|
||||
if (t.kind == syntax.nkind.N_TPARAM) {
|
||||
wwitype(c, fd, owner, source, t.lhs); return;
|
||||
};
|
||||
if (t.kind == syntax.nkind.N_TNAME) {
|
||||
if (t.str.len > 0) { wputs(fd, t.str); } else { wputs(fd, "void"); };
|
||||
if (t.str.len > 0) { wwiname(c, fd, owner, source, t.str); }
|
||||
else { wputs(fd, "void"); };
|
||||
} else { if (t.kind == syntax.nkind.N_TPTR) {
|
||||
wputb(fd, '*');
|
||||
wwitype(fd, t.lhs);
|
||||
wwitype(c, fd, owner, source, t.lhs);
|
||||
} else { if (t.kind == syntax.nkind.N_TSLICE) {
|
||||
wputs(fd, "[]");
|
||||
wwitype(fd, t.lhs);
|
||||
wwitype(c, fd, owner, source, t.lhs);
|
||||
} else { if (t.kind == syntax.nkind.N_TARRAY) {
|
||||
wputb(fd, '[');
|
||||
if (t.rhs != nil) { wwiexpr(fd, t.rhs); } else { wputb(fd, '_'); };
|
||||
if (t.rhs != nil) { wwiexpr(c, fd, owner, source, t.rhs); }
|
||||
else { wputb(fd, '_'); };
|
||||
wputb(fd, ']');
|
||||
wwitype(fd, t.lhs);
|
||||
wwitype(c, fd, owner, source, t.lhs);
|
||||
} else { if (t.kind == syntax.nkind.N_TBANG) {
|
||||
wputb(fd, '!');
|
||||
wwitype(fd, t.lhs);
|
||||
wwitype(c, fd, owner, source, t.lhs);
|
||||
} else { if (t.kind == syntax.nkind.N_TCHAN) {
|
||||
wputs(fd, "chan ");
|
||||
wwitype(fd, t.lhs);
|
||||
wwitype(c, fd, owner, source, t.lhs);
|
||||
} else { if (t.kind == syntax.nkind.N_TFN) {
|
||||
wputs(fd, "fn(");
|
||||
let p: *syntax.node = t.list;
|
||||
for (p != nil) {
|
||||
if (p != t.list) { wputs(fd, ", "); };
|
||||
wwiparam(fd, p);
|
||||
wwiparam(c, fd, owner, source, p);
|
||||
p = p.next;
|
||||
};
|
||||
wputs(fd, ") ");
|
||||
wwitype(fd, t.lhs);
|
||||
wwitype(c, fd, owner, source, t.lhs);
|
||||
} else { if (t.kind == syntax.nkind.N_TSTRUCT) {
|
||||
// re-emit `@packed` so the flag round-trips through
|
||||
// sep-compile (harec unparse/type.ha:122-126).
|
||||
@@ -429,7 +441,7 @@ fn wwitype(fd: i32, t: *syntax.node) void = {
|
||||
wputs(fd, f.str);
|
||||
wputs(fd, ": ");
|
||||
};
|
||||
wwitype(fd, f.lhs);
|
||||
wwitype(c, fd, owner, source, f.lhs);
|
||||
f = f.next;
|
||||
};
|
||||
wputs(fd, " }");
|
||||
@@ -438,7 +450,7 @@ fn wwitype(fd: i32, t: *syntax.node) void = {
|
||||
let e: *syntax.node = t.list;
|
||||
for (e != nil) {
|
||||
if (e != t.list) { wputs(fd, ", "); };
|
||||
wwitype(fd, e);
|
||||
wwitype(c, fd, owner, source, e);
|
||||
e = e.next;
|
||||
};
|
||||
wputb(fd, ')');
|
||||
@@ -451,14 +463,14 @@ fn wwitype(fd: i32, t: *syntax.node) void = {
|
||||
// the consumer's type-store flattens
|
||||
// (ref/hare/hare/unparse/type.ha:290-300).
|
||||
if (e.op == syntax.tkind.TK_ELLIPSIS) { wputs(fd, "..."); };
|
||||
wwitype(fd, e);
|
||||
wwitype(c, fd, owner, source, e);
|
||||
e = e.next;
|
||||
};
|
||||
wputb(fd, ')');
|
||||
} else { if (t.kind == syntax.nkind.N_TENUM) {
|
||||
wputs(fd, "enum ");
|
||||
if (t.lhs != nil) {
|
||||
wwitype(fd, t.lhs);
|
||||
wwitype(c, fd, owner, source, t.lhs);
|
||||
wputb(fd, 32u8);
|
||||
};
|
||||
wputs(fd, "{ ");
|
||||
@@ -468,7 +480,7 @@ fn wwitype(fd: i32, t: *syntax.node) void = {
|
||||
wputs(fd, m.str);
|
||||
if (m.lhs != nil) {
|
||||
wputs(fd, " = ");
|
||||
wwiexpr(fd, m.lhs);
|
||||
wwiexpr(c, fd, owner, source, m.lhs);
|
||||
};
|
||||
m = m.next;
|
||||
};
|
||||
@@ -489,7 +501,7 @@ fn wwiattrrelevant(nm: str) bool = {
|
||||
return syntax.streq(nm, "symbol") || syntax.streq(nm, "test");
|
||||
};
|
||||
|
||||
fn wwiattrs(fd: i32, d: *syntax.node) void = {
|
||||
fn wwiattrs(c: *checker, fd: i32, owner: str, d: *syntax.node) void = {
|
||||
let a: *syntax.node = d.attr;
|
||||
for (a != nil) {
|
||||
if (a.kind == syntax.nkind.N_ATTR && wwiattrrelevant(a.str)) {
|
||||
@@ -500,7 +512,7 @@ fn wwiattrs(fd: i32, d: *syntax.node) void = {
|
||||
let arg: *syntax.node = a.list;
|
||||
for (arg != nil) {
|
||||
if (arg != a.list) { wputs(fd, ", "); };
|
||||
wwiexpr(fd, arg);
|
||||
wwiexpr(c, fd, owner, d.sourceid, arg);
|
||||
arg = arg.next;
|
||||
};
|
||||
wputb(fd, ')');
|
||||
@@ -511,9 +523,9 @@ fn wwiattrs(fd: i32, d: *syntax.node) void = {
|
||||
};
|
||||
};
|
||||
|
||||
fn wwidecl(fd: i32, d: *syntax.node) void = {
|
||||
fn wwidecl(c: *checker, fd: i32, owner: str, d: *syntax.node) void = {
|
||||
if (d.kind == syntax.nkind.N_FNDECL) {
|
||||
wwiattrs(fd, d);
|
||||
wwiattrs(c, fd, owner, d);
|
||||
if (d.exported != 0) { wputs(fd, "export fn "); }
|
||||
else { wputs(fd, "fn "); };
|
||||
wputs(fd, d.str);
|
||||
@@ -521,25 +533,25 @@ fn wwidecl(fd: i32, d: *syntax.node) void = {
|
||||
let p: *syntax.node = d.list;
|
||||
for (p != nil) {
|
||||
if (p != d.list) { wputs(fd, ", "); };
|
||||
wwiparam(fd, p);
|
||||
wwiparam(c, fd, owner, d.sourceid, p);
|
||||
p = p.next;
|
||||
};
|
||||
wputs(fd, ") ");
|
||||
wwitype(fd, d.lhs);
|
||||
wwitype(c, fd, owner, d.sourceid, d.lhs);
|
||||
wputs(fd, ";\n");
|
||||
} else { if (d.kind == syntax.nkind.N_TYPEDECL) {
|
||||
if (d.exported != 0) { wputs(fd, "export type "); }
|
||||
else { wputs(fd, "type "); };
|
||||
wputs(fd, d.str);
|
||||
wputs(fd, " = ");
|
||||
wwitype(fd, d.lhs);
|
||||
wwitype(c, fd, owner, d.sourceid, d.lhs);
|
||||
wputs(fd, ";\n");
|
||||
} else { if (d.kind == syntax.nkind.N_DEF) {
|
||||
if (d.exported != 0) { wputs(fd, "export def "); }
|
||||
else { wputs(fd, "def "); };
|
||||
wputs(fd, d.str);
|
||||
wputs(fd, ": ");
|
||||
wwitype(fd, d.lhs);
|
||||
wwitype(c, fd, owner, d.sourceid, d.lhs);
|
||||
// An aggregate initializer (N_STRUCTLIT/N_ARRLIT) is a DATA-global
|
||||
// (#52): emit a value-LESS prototype `export def X: T;`. The
|
||||
// defining package's own .o emits the struct/array DATA; the
|
||||
@@ -554,7 +566,7 @@ fn wwidecl(fd: i32, d: *syntax.node) void = {
|
||||
wputs(fd, ";\n");
|
||||
} else {
|
||||
wputs(fd, " = ");
|
||||
wwiexpr(fd, d.rhs);
|
||||
wwiexpr(c, fd, owner, d.sourceid, d.rhs);
|
||||
wputs(fd, ";\n");
|
||||
};
|
||||
} else { if (d.kind == syntax.nkind.N_LET) {
|
||||
@@ -566,7 +578,7 @@ fn wwidecl(fd: i32, d: *syntax.node) void = {
|
||||
wputs(2, "wwi: exported let has no declared type\n");
|
||||
os.exit(1);
|
||||
};
|
||||
wwitype(fd, d.lhs);
|
||||
wwitype(c, fd, owner, d.sourceid, d.lhs);
|
||||
wputs(fd, ";\n");
|
||||
};};};};
|
||||
};
|
||||
@@ -671,16 +683,6 @@ fn wwifactvaluesym(c: *checker, owner: str, source: i32,
|
||||
};
|
||||
p = p.parent;
|
||||
};
|
||||
p = c.top;
|
||||
for (p != nil) {
|
||||
let s: *syntax.sym = p.first;
|
||||
for (s != nil) {
|
||||
if (s.skind == syntax.skind.SK_DEF && syntax.streq(s.name, name)
|
||||
&& wwidirectmodvisible(c, owner, source, s.mod)) { return s; };
|
||||
s = s.snext;
|
||||
};
|
||||
p = p.parent;
|
||||
};
|
||||
return nil;
|
||||
};
|
||||
|
||||
@@ -929,7 +931,8 @@ fn wwiemitimports(fd: i32, file: *syntax.node, owner: str, source: i32,
|
||||
let i: i32 = 0;
|
||||
for (i < nuse) {
|
||||
if (previous.len == 0 || !syntax.streq(previous, paths[i])) {
|
||||
wputs(fd, "import "); wputs(fd, paths[i]); wputs(fd, ";\n");
|
||||
wputs(fd, "import "); wwicanonicalalias(fd, paths[i]);
|
||||
wputb(fd, 32u8); wputs(fd, paths[i]); wputs(fd, ";\n");
|
||||
previous = paths[i];
|
||||
};
|
||||
i += 1;
|
||||
@@ -995,7 +998,8 @@ fn wwiemitprimarysection(c: *checker, fd: i32, file: *syntax.node,
|
||||
let i: i32 = 0;
|
||||
for (i < fs.nprivate) {
|
||||
if (fs.privatenodes[i].sourceid == source) {
|
||||
wwidecl(fd, fs.privatenodes[i]);
|
||||
let primaryowner: str;
|
||||
wwidecl(c, fd, primaryowner, fs.privatenodes[i]);
|
||||
};
|
||||
i += 1;
|
||||
};
|
||||
@@ -1004,13 +1008,19 @@ fn wwiemitprimarysection(c: *checker, fd: i32, file: *syntax.node,
|
||||
for (d != nil) {
|
||||
if (wwiprimary(d) && d.sourceid == source
|
||||
&& d.kind == syntax.nkind.N_FNDECL && d.exported == 0
|
||||
&& wwihasattr(d, "test")) { wwidecl(fd, d); };
|
||||
&& wwihasattr(d, "test")) {
|
||||
let primaryowner: str;
|
||||
wwidecl(c, fd, primaryowner, d);
|
||||
};
|
||||
d = d.next;
|
||||
};
|
||||
};
|
||||
i = 0;
|
||||
for (i < nexports) {
|
||||
if (exports[i].sourceid == source) { wwidecl(fd, exports[i]); };
|
||||
if (exports[i].sourceid == source) {
|
||||
let primaryowner: str;
|
||||
wwidecl(c, fd, primaryowner, exports[i]);
|
||||
};
|
||||
i += 1;
|
||||
};
|
||||
};
|
||||
@@ -1134,23 +1144,13 @@ fn wwiemit(c: *checker, file: *syntax.node, path: str) i32 = {
|
||||
if (lastmod.len == 0 || !syntax.streq(lastmod, mod)
|
||||
|| lastsource != source) {
|
||||
wputs(fd, "//ww:module "); wputs(fd, mod); wputs(fd, "\n");
|
||||
let factpkg: str = fs.factnodes[fi].pkgname;
|
||||
if (factpkg.len == 0) {
|
||||
let dotidx: i32 = -1;
|
||||
let mi: i32 = 0;
|
||||
for (mi < mod.len) { if (mod[mi] == 46u8) { dotidx = mi; }; mi += 1; };
|
||||
factpkg = mod;
|
||||
if (dotidx >= 0) {
|
||||
factpkg.ptr = mod.ptr + ((dotidx + 1): u64);
|
||||
factpkg.len = mod.len - dotidx - 1;
|
||||
};
|
||||
};
|
||||
wputs(fd, "package "); wputs(fd, factpkg); wputs(fd, ";\n");
|
||||
wputs(fd, "package "); wwicanonicalalias(fd, mod);
|
||||
wputs(fd, ";\n");
|
||||
wwiemitimports(fd, file, mod, source, true);
|
||||
lastmod = mod;
|
||||
lastsource = source;
|
||||
};
|
||||
wwidecl(fd, fs.factnodes[fi]);
|
||||
wwidecl(c, fd, mod, fs.factnodes[fi]);
|
||||
fi += 1;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user