w6c: preserve grouped and qualified types in wwi
This commit is contained in:
@@ -45,11 +45,20 @@ static Sym *
|
||||
wwi_typesym(Checker *c, const char *nm)
|
||||
{
|
||||
if (nm == NULL) return NULL;
|
||||
Sym *s = scope_lookup_type(c->cur, NULL, nm);
|
||||
if (s == NULL) {
|
||||
const char *dot = strrchr(nm, '.');
|
||||
if (dot)
|
||||
s = scope_lookup_type(c->cur, NULL, dot + 1);
|
||||
const char *dot = strrchr(nm, '.');
|
||||
Sym *s = NULL;
|
||||
if (dot) {
|
||||
size_t n = (size_t)(dot - nm);
|
||||
for (Node *u = c->file->list; u; u = u->next) {
|
||||
if (u->kind != N_USE || !wwi_primary(u) || u->str == NULL
|
||||
|| strlen(u->str) != n || strncmp(u->str, nm, n) != 0)
|
||||
continue;
|
||||
const char *mod = u->usepath ? u->usepath : u->str;
|
||||
s = scope_lookup_in_module(c->cur, mod, dot + 1);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
s = scope_lookup_type(c->cur, NULL, nm);
|
||||
}
|
||||
if (s && s->kind == SK_TYPE)
|
||||
return s;
|
||||
@@ -338,9 +347,11 @@ wwi_expr(FILE *of, Node *e)
|
||||
* as the plain int 1114111). */
|
||||
case N_RUNELIT: wwi_rune(of, e->uval); break;
|
||||
case N_BIN:
|
||||
fputc('(', of);
|
||||
wwi_expr(of, e->lhs);
|
||||
fprintf(of, " %s ", tokname(e->op));
|
||||
wwi_expr(of, e->rhs);
|
||||
fputc(')', of);
|
||||
break;
|
||||
case N_UN:
|
||||
fputs(tokname(e->op), of);
|
||||
|
||||
@@ -74,20 +74,34 @@ fn wquote(fd: i32, s: str) void = {
|
||||
|
||||
fn wwitypesym(c: *checker, nm: str) *syntax.sym = {
|
||||
let empty: str;
|
||||
let s: *syntax.sym = syntax.scopelookuptype(c.cur, empty, nm);
|
||||
if (s == nil) {
|
||||
let dotidx: i32 = -1;
|
||||
let i: i32 = 0;
|
||||
for (i < nm.len) {
|
||||
if (nm[i] == 46u8) { dotidx = i; };
|
||||
i += 1;
|
||||
};
|
||||
if (dotidx >= 0) {
|
||||
let leaf: str;
|
||||
leaf.ptr = nm.ptr + ((dotidx + 1): u64);
|
||||
leaf.len = nm.len - dotidx - 1;
|
||||
s = syntax.scopelookuptype(c.cur, empty, leaf);
|
||||
let dotidx: i32 = -1;
|
||||
let i: i32 = 0;
|
||||
for (i < nm.len) {
|
||||
if (nm[i] == 46u8) { dotidx = i; };
|
||||
i += 1;
|
||||
};
|
||||
let s: *syntax.sym = nil;
|
||||
if (dotidx >= 0) {
|
||||
let head: str;
|
||||
head.ptr = nm.ptr;
|
||||
head.len = dotidx;
|
||||
let leaf: str;
|
||||
leaf.ptr = nm.ptr + ((dotidx + 1): u64);
|
||||
leaf.len = nm.len - dotidx - 1;
|
||||
let u: *syntax.node = c.file.list;
|
||||
for (u != nil) {
|
||||
if (u.kind == syntax.nkind.N_USE && wwiprimary(u)) {
|
||||
if (syntax.streq(u.str, head)) {
|
||||
let mod: str = u.usepath;
|
||||
if (mod.len == 0) { mod = u.str; };
|
||||
s = syntax.scopelookupinmodule(c.cur, mod, leaf);
|
||||
break;
|
||||
};
|
||||
};
|
||||
u = u.next;
|
||||
};
|
||||
} else {
|
||||
s = syntax.scopelookuptype(c.cur, empty, nm);
|
||||
};
|
||||
if (s == nil) { return nil; };
|
||||
if (s.skind != syntax.skind.SK_TYPE) { return nil; };
|
||||
@@ -279,11 +293,13 @@ fn wwiexpr(fd: i32, e: *syntax.node) void = {
|
||||
// `0x10ffff: rune` emits as the plain int 1114111).
|
||||
wwirune(fd, e.uval);
|
||||
} else { if (e.kind == syntax.nkind.N_BIN) {
|
||||
wputb(fd, '(');
|
||||
wwiexpr(fd, e.lhs);
|
||||
wputb(fd, 32u8);
|
||||
wputs(fd, syntax.tokname(e.op));
|
||||
wputb(fd, 32u8);
|
||||
wwiexpr(fd, e.rhs);
|
||||
wputb(fd, ')');
|
||||
} else { if (e.kind == syntax.nkind.N_UN) {
|
||||
wputs(fd, syntax.tokname(e.op));
|
||||
wwiexpr(fd, e.lhs);
|
||||
|
||||
@@ -132,6 +132,7 @@ fn m2positive(pkg: str) void = {
|
||||
"export def NEG: i32 = -7;\n",
|
||||
"export let counter: i32;\n",
|
||||
"export let grid: [4]i32;\n",
|
||||
"export let grouped: [(1 + 2) * 3]u8;\n",
|
||||
"export fn apply(f: fn(x: i32) i32, n: i32) i32;\n",
|
||||
"export fn risky() !i32;\n",
|
||||
"export fn matrix() [LIMIT]u8;\n",
|
||||
@@ -152,6 +153,10 @@ fn m2positive(pkg: str) void = {
|
||||
fail("synth",
|
||||
"cs.wwi != ww.wwi (const-expr / decl-kind unparse diverges)");
|
||||
};
|
||||
if (!testenv.has(testenv.readfile(cs),
|
||||
"export let grouped: [((1 + 2) * 3)]u8;")) {
|
||||
fail("synth", ".wwi changed grouped array-dimension semantics");
|
||||
};
|
||||
// #47: the @symbol attribute must survive the round-trip verbatim.
|
||||
if (!testenv.has(testenv.readfile(cs),
|
||||
"@symbol(\"rt_ext\") export fn ext")) {
|
||||
@@ -164,6 +169,43 @@ fn m2positive(pkg: str) void = {
|
||||
testenv.clean(td);
|
||||
};
|
||||
|
||||
@test fn m2qualified() void = {
|
||||
let td: str = testenv.fresh();
|
||||
let src: str = strings.concat(
|
||||
"//ww:module a.dep\n",
|
||||
"package dep;\n",
|
||||
"export type Clash = struct { x: i32 };\n",
|
||||
"//ww:module-reset\n",
|
||||
"package root;\n",
|
||||
"import a.dep;\n",
|
||||
"type Clash = struct { y: i32 };\n",
|
||||
"export fn use(x: dep.Clash) i32;\n");
|
||||
let p: str = strings.concat(td, "/qualified.ww");
|
||||
testenv.writefile(p, src);
|
||||
let cs: str = strings.concat(td, "/cs.wwi");
|
||||
let ws: str = strings.concat(td, "/ww.wwi");
|
||||
let cav: []str = [testenv.driver("w6c"), "-I", cs, p];
|
||||
if (!runok(td, "w6c", cav)) {
|
||||
fail("qualified", "w6c confused dep.Clash with private Clash");
|
||||
};
|
||||
let wav: []str = [testenv.driver("w6c_ww"), "-I", ws, p];
|
||||
if (!runok(td, "w6c_ww", wav)) {
|
||||
fail("qualified", "w6c_ww confused dep.Clash with private Clash");
|
||||
};
|
||||
if (!testenv.same(testenv.readfile(cs), testenv.readfile(ws))) {
|
||||
fail("qualified", "cs.wwi != ww.wwi");
|
||||
};
|
||||
if (!testenv.has(testenv.readfile(cs),
|
||||
"export fn use(x: dep.Clash) i32;")) {
|
||||
fail("qualified", ".wwi dropped the qualified signature");
|
||||
};
|
||||
let dav: []str = [testenv.driver("wwdump"), "-a", cs];
|
||||
if (!runok(td, "wwdump", dav)) {
|
||||
fail("qualified", "emitted .wwi does not re-parse");
|
||||
};
|
||||
testenv.clean(td);
|
||||
};
|
||||
|
||||
// #48 gate: the lib/types limit constants are `export def`s. Produce
|
||||
// types.wwi on both stages directly from the real lib source, assert
|
||||
// byte-id + re-parse + that the exported limits actually appear (a
|
||||
|
||||
Reference in New Issue
Block a user