compiler: support package test runtime aliases
This commit is contained in:
@@ -28,6 +28,7 @@ main(int argc, char **argv)
|
|||||||
const char *src = NULL;
|
const char *src = NULL;
|
||||||
const char *out = NULL;
|
const char *out = NULL;
|
||||||
const char *wwiout = NULL; /* -I <out.wwi>: M2 export-data producer */
|
const char *wwiout = NULL; /* -I <out.wwi>: M2 export-data producer */
|
||||||
|
const char *testsupport = NULL;
|
||||||
int testmode = 0;
|
int testmode = 0;
|
||||||
int sepmode = 0; /* -c: #22 M3 separate-compile / primary-
|
int sepmode = 0; /* -c: #22 M3 separate-compile / primary-
|
||||||
* only codegen (emit imported==0 decls
|
* only codegen (emit imported==0 decls
|
||||||
@@ -40,6 +41,12 @@ main(int argc, char **argv)
|
|||||||
wwiout = argv[++i];
|
wwiout = argv[++i];
|
||||||
} else if (strcmp(a, "-T") == 0) {
|
} else if (strcmp(a, "-T") == 0) {
|
||||||
testmode = 1;
|
testmode = 1;
|
||||||
|
} else if (strcmp(a, "--test-support-module") == 0) {
|
||||||
|
if (i + 1 >= argc) {
|
||||||
|
fputs("w6c: --test-support-module requires arg\n", stderr);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
testsupport = argv[++i];
|
||||||
} else if (strcmp(a, "-c") == 0) {
|
} else if (strcmp(a, "-c") == 0) {
|
||||||
sepmode = 1;
|
sepmode = 1;
|
||||||
} else if (a[0] == '-') {
|
} else if (a[0] == '-') {
|
||||||
@@ -56,6 +63,12 @@ main(int argc, char **argv)
|
|||||||
fputs("usage: w6c [-T] [-c] [-I out.wwi] [-o out.s] file.ww\n", stderr);
|
fputs("usage: w6c [-T] [-c] [-I out.wwi] [-o out.s] file.ww\n", stderr);
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
if (testsupport != NULL && (!sepmode
|
||||||
|
|| (strcmp(testsupport, "test") != 0
|
||||||
|
&& strcmp(testsupport, "__wwtest") != 0))) {
|
||||||
|
fputs("w6c: invalid --test-support-module\n", stderr);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
char *buf;
|
char *buf;
|
||||||
u64 len;
|
u64 len;
|
||||||
@@ -72,11 +85,13 @@ main(int argc, char **argv)
|
|||||||
|
|
||||||
lexinit(&l, a, src, buf, len);
|
lexinit(&l, a, src, buf, len);
|
||||||
parserinit(&p, a, &l);
|
parserinit(&p, a, &l);
|
||||||
|
p.testmodule = testsupport;
|
||||||
Node *file = parsefile(&p);
|
Node *file = parsefile(&p);
|
||||||
if (l.errs || p.errs) return 1;
|
if (l.errs || p.errs) return 1;
|
||||||
|
|
||||||
check_init(&c, a);
|
check_init(&c, a);
|
||||||
c.is_test = testmode;
|
c.is_test = testmode;
|
||||||
|
if (testsupport != NULL) c.test_module = testsupport;
|
||||||
c.sep_mode = sepmode;
|
c.sep_mode = sepmode;
|
||||||
check_file(&c, file);
|
check_file(&c, file);
|
||||||
if (c.errs) return 1;
|
if (c.errs) return 1;
|
||||||
|
|||||||
@@ -1483,7 +1483,7 @@ cexpr(Checker *c, Node *n)
|
|||||||
if (fs)
|
if (fs)
|
||||||
return n->type = fs->type;
|
return n->type = fs->type;
|
||||||
/* A bare `w6c -T` intentionally leaves the
|
/* A bare `w6c -T` intentionally leaves the
|
||||||
* compiler-generated test.run hook external; the
|
* compiler-generated support.run hook external; the
|
||||||
* ordinary driver supplies lib/test. This is the only
|
* ordinary driver supplies lib/test. This is the only
|
||||||
* missing direct member that is not a package export
|
* missing direct member that is not a package export
|
||||||
* error. */
|
* error. */
|
||||||
@@ -2843,6 +2843,7 @@ check_init(Checker *c, Arena *a)
|
|||||||
memset(c, 0, sizeof *c);
|
memset(c, 0, sizeof *c);
|
||||||
c->a = a;
|
c->a = a;
|
||||||
c->is_test = 0; /* #15: caller (w6c main) sets it after init */
|
c->is_test = 0; /* #15: caller (w6c main) sets it after init */
|
||||||
|
c->test_module = "test";
|
||||||
typesinit(a);
|
typesinit(a);
|
||||||
c->top = newscope(a, NULL);
|
c->top = newscope(a, NULL);
|
||||||
c->cur = c->top;
|
c->cur = c->top;
|
||||||
@@ -3120,20 +3121,19 @@ check_file(Checker *c, Node *file)
|
|||||||
if (file == NULL || file->kind != N_FILE) return;
|
if (file == NULL || file->kind != N_FILE) return;
|
||||||
c->file = file;
|
c->file = file;
|
||||||
|
|
||||||
/* #80: under -T, PREPEND the synth `use test;` BEFORE pass 1 so decl_mod
|
/* Under -T, prepend the dispatcher support import before pass 1 so
|
||||||
* (called per-decl during install) sees a matching `use test` when it
|
* decl_mod keys the runner under the selected support module. A pure
|
||||||
* keys lib/test's `run` — keying it under module="test", not "". A pure
|
|
||||||
* ORDER fix: the synth N_USE was appended AFTER install (below), too late
|
* ORDER fix: the synth N_USE was appended AFTER install (below), too late
|
||||||
* for decl_mod, so `run` keyed under "" — leaving the synth `test.run`
|
* for decl_mod, so `run` keyed under "" — leaving the qualified call
|
||||||
* ty_err (the E1 bridge) and colliding with a user root `fn run` (also
|
* ty_err (the E1 bridge) and colliding with a user root `fn run` (also
|
||||||
* module=""). Decoupled from cgen: the symbol mangle keys off d->module
|
* module=""). Decoupled from cgen: the symbol mangle keys off d->module
|
||||||
* (the //ww:module directive, mod_collect), NOT this scope keying — cgen
|
* (the //ww:module directive, mod_collect), NOT this scope keying — cgen
|
||||||
* already emits the correct CALL test.run. wwstage twin in check.ww. */
|
* already emits the qualified call. wwstage twin in check.ww. */
|
||||||
if (c->is_test) {
|
if (c->is_test) {
|
||||||
Node *usenode = newnode(c->a, N_USE, file->pos);
|
Node *usenode = newnode(c->a, N_USE, file->pos);
|
||||||
usenode->str = "test";
|
usenode->str = c->test_module;
|
||||||
usenode->strlen = 4;
|
usenode->strlen = strlen(c->test_module);
|
||||||
usenode->usepath = "test";
|
usenode->usepath = c->test_module;
|
||||||
usenode->next = file->list;
|
usenode->next = file->list;
|
||||||
file->list = usenode;
|
file->list = usenode;
|
||||||
}
|
}
|
||||||
@@ -3506,21 +3506,18 @@ check_file(Checker *c, Node *file)
|
|||||||
scope_define_in_module(c->cur, tab->str, NULL, SK_VAR,
|
scope_define_in_module(c->cur, tab->str, NULL, SK_VAR,
|
||||||
tt, tab);
|
tt, tab);
|
||||||
|
|
||||||
/* return test.run(__wwtests);
|
/* Return support.run(__wwtests).
|
||||||
* QUALIFIED, not bare `run`: under the sep producer
|
* QUALIFIED, not bare `run`: under the sep producer the
|
||||||
* lib/test is a real imported package, so the call must
|
* toolchain test runtime is a real imported package. The
|
||||||
* carry the `test` module qualifier (N_DOT base ident
|
* selected module is normally `test`, or the reserved alias
|
||||||
* `test`, member `run`). The combined path tags the
|
* chosen by the package driver when user source owns `test`.
|
||||||
* auto-bundled lib/test `//ww:module test` too, so the
|
* The base ident resolves through the synthetic N_USE. */
|
||||||
* qualified form resolves+mangles identically there
|
|
||||||
* (test.run either way) — byte-neutral. The base ident
|
|
||||||
* resolves through a synthetic N_USE injected below. */
|
|
||||||
Node *arg = newnode(c->a, N_IDENT, fp);
|
Node *arg = newnode(c->a, N_IDENT, fp);
|
||||||
arg->str = "__wwtests";
|
arg->str = "__wwtests";
|
||||||
Node *call = newnode(c->a, N_CALL, fp);
|
Node *call = newnode(c->a, N_CALL, fp);
|
||||||
Node *dot = newnode(c->a, N_DOT, fp);
|
Node *dot = newnode(c->a, N_DOT, fp);
|
||||||
dot->lhs = newnode(c->a, N_IDENT, fp);
|
dot->lhs = newnode(c->a, N_IDENT, fp);
|
||||||
dot->lhs->str = "test";
|
dot->lhs->str = c->test_module;
|
||||||
dot->str = "run";
|
dot->str = "run";
|
||||||
c->synth_test_run = dot;
|
c->synth_test_run = dot;
|
||||||
call->lhs = dot;
|
call->lhs = dot;
|
||||||
@@ -3528,11 +3525,11 @@ check_file(Checker *c, Node *file)
|
|||||||
Node *ret = newnode(c->a, N_RETURN, fp);
|
Node *ret = newnode(c->a, N_RETURN, fp);
|
||||||
ret->lhs = call;
|
ret->lhs = call;
|
||||||
body->list = ret;
|
body->list = ret;
|
||||||
/* #80: the synth `use test;` (the N_DOT base qualifier +
|
/* The synthetic support use (the N_DOT base qualifier plus
|
||||||
* the use_path source mapping `test`→its path) is now
|
* its use_path source mapping) is now
|
||||||
* PREPENDED before pass 1 at the top of check_file, so
|
* PREPENDED before pass 1 at the top of check_file, so
|
||||||
* decl_mod keys lib/test's `run` under "test" and the synth
|
* decl_mod keys the runtime's `run` under the selected module
|
||||||
* `test.run` type-resolves. Pass 1's N_USE arm installs it
|
* and the synthesized call type-resolves. Pass 1 installs it
|
||||||
* (SK_USE). */
|
* (SK_USE). */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1571,7 +1571,11 @@ parsefile(Parser *p)
|
|||||||
p->pathmod ? p->pathmod : p->resetmod;
|
p->pathmod ? p->pathmod : p->resetmod;
|
||||||
const char *dot = strrchr(active, '.');
|
const char *dot = strrchr(active, '.');
|
||||||
const char *last = dot ? dot + 1 : active;
|
const char *last = dot ? dot + 1 : active;
|
||||||
if (strcmp(name, last) != 0) {
|
int testsupport = p->testmodule != NULL
|
||||||
|
&& strcmp(p->testmodule, "__wwtest") == 0
|
||||||
|
&& strcmp(active, "__wwtest") == 0
|
||||||
|
&& strcmp(name, "test") == 0;
|
||||||
|
if (strcmp(name, last) != 0 && !testsupport) {
|
||||||
errorf(p->cur.pos,
|
errorf(p->cur.pos,
|
||||||
"package %s does not match import path %s",
|
"package %s does not match import path %s",
|
||||||
name, active);
|
name, active);
|
||||||
|
|||||||
@@ -379,6 +379,8 @@ struct Parser {
|
|||||||
* bare-main rule stay intact), and the in-file
|
* bare-main rule stay intact), and the in-file
|
||||||
* `package` clause asserts (leaf == last
|
* `package` clause asserts (leaf == last
|
||||||
* component) instead of overwriting curmod. */
|
* component) instead of overwriting curmod. */
|
||||||
|
const char *testmodule; /* hidden package-driver alias for toolchain
|
||||||
|
* `package test`; NULL outside that compile */
|
||||||
};
|
};
|
||||||
|
|
||||||
void parserinit(Parser*, Arena*, Lex*);
|
void parserinit(Parser*, Arena*, Lex*);
|
||||||
@@ -588,9 +590,10 @@ struct Checker {
|
|||||||
int errs;
|
int errs;
|
||||||
int is_test; /* #15: `w6c -T` — collect @test fns + synth
|
int is_test; /* #15: `w6c -T` — collect @test fns + synth
|
||||||
* the entry; loud-reject a user main. */
|
* the entry; loud-reject a user main. */
|
||||||
|
const char *test_module; /* generated dispatcher support qualifier */
|
||||||
int sep_mode; /* -c package compilation: imported interfaces are
|
int sep_mode; /* -c package compilation: imported interfaces are
|
||||||
* present, so absent members are hard export errors. */
|
* present, so absent members are hard export errors. */
|
||||||
Node *synth_test_run; /* exact compiler-generated test.run DOT;
|
Node *synth_test_run; /* exact compiler-generated support.run DOT;
|
||||||
* its unresolved external hook is intentional */
|
* its unresolved external hook is intentional */
|
||||||
Node *alloc_octx; /* #3/B': the one empty `alloc([], n)` call node
|
Node *alloc_octx; /* #3/B': the one empty `alloc([], n)` call node
|
||||||
* that has let-declared slice context this walk;
|
* that has let-declared slice context this walk;
|
||||||
|
|||||||
@@ -46,6 +46,9 @@ export type parser = struct {
|
|||||||
// rule stay intact), and the in-file `package` clause asserts (leaf ==
|
// rule stay intact), and the in-file `package` clause asserts (leaf ==
|
||||||
// last component) instead of overwriting curmod. "" means inactive.
|
// last component) instead of overwriting curmod. "" means inactive.
|
||||||
resetmod: str,
|
resetmod: str,
|
||||||
|
// Hidden package-driver alias for the toolchain `package test` source.
|
||||||
|
// Empty outside that one separate-compilation edge.
|
||||||
|
testmodule: str,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn refill(p: *parser) void = {
|
fn refill(p: *parser) void = {
|
||||||
@@ -67,6 +70,7 @@ export fn parserinit(p: *parser, l: *lex) void = {
|
|||||||
p.nocast = 0;
|
p.nocast = 0;
|
||||||
p.pathmod = "";
|
p.pathmod = "";
|
||||||
p.resetmod = "";
|
p.resetmod = "";
|
||||||
|
p.testmodule = "";
|
||||||
refill(p);
|
refill(p);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -611,7 +615,11 @@ export fn parsefile(p: *parser) *node = {
|
|||||||
let (pre, post) = strings.rcut(active, ".");
|
let (pre, post) = strings.rcut(active, ".");
|
||||||
let last: str = post;
|
let last: str = post;
|
||||||
if (post.len == 0) { last = active; };
|
if (post.len == 0) { last = active; };
|
||||||
if (strings.compare(name, last) != 0) {
|
let testsupport: bool = strings.compare(
|
||||||
|
p.testmodule, "__wwtest") == 0
|
||||||
|
&& strings.compare(active, "__wwtest") == 0
|
||||||
|
&& strings.compare(name, "test") == 0;
|
||||||
|
if (strings.compare(name, last) != 0 && !testsupport) {
|
||||||
errmsg(p, "package does not match import path");
|
errmsg(p, "package does not match import path");
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ export fn main(argc: i32, argv: **u8) i32 = {
|
|||||||
let src: *u8 = nil;
|
let src: *u8 = nil;
|
||||||
let out: *u8 = nil;
|
let out: *u8 = nil;
|
||||||
let wwiout: *u8 = nil; // -I <out.wwi>: M2 export-data producer
|
let wwiout: *u8 = nil; // -I <out.wwi>: M2 export-data producer
|
||||||
|
let testsupport: *u8 = nil;
|
||||||
let testmode: i32 = 0i32; // #15: `-T` test-mode
|
let testmode: i32 = 0i32; // #15: `-T` test-mode
|
||||||
let sepmode: i32 = 0i32; // -c: #22 M3 separate-compile / primary-
|
let sepmode: i32 = 0i32; // -c: #22 M3 separate-compile / primary-
|
||||||
// only codegen (emit imported==0 decls
|
// only codegen (emit imported==0 decls
|
||||||
@@ -92,6 +93,14 @@ export fn main(argc: i32, argv: **u8) i32 = {
|
|||||||
wwiout = argv[i];
|
wwiout = argv[i];
|
||||||
} else { if (cstreq(a, "-T")) {
|
} else { if (cstreq(a, "-T")) {
|
||||||
testmode = 1i32;
|
testmode = 1i32;
|
||||||
|
} else { if (cstreq(a, "--test-support-module")) {
|
||||||
|
i += 1;
|
||||||
|
if (i >= argc) {
|
||||||
|
let m: str = "w6c: --test-support-module requires arg\n";
|
||||||
|
os.write(2, m.ptr, m.len: u64);
|
||||||
|
return 2;
|
||||||
|
};
|
||||||
|
testsupport = argv[i];
|
||||||
} else { if (cstreq(a, "-c")) {
|
} else { if (cstreq(a, "-c")) {
|
||||||
sepmode = 1i32;
|
sepmode = 1i32;
|
||||||
} else { if (a[0u64] == 45u8) {
|
} else { if (a[0u64] == 45u8) {
|
||||||
@@ -105,7 +114,7 @@ export fn main(argc: i32, argv: **u8) i32 = {
|
|||||||
return 2;
|
return 2;
|
||||||
};
|
};
|
||||||
src = a;
|
src = a;
|
||||||
}; }; }; }; };
|
}; }; }; }; }; };
|
||||||
i += 1;
|
i += 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -114,6 +123,13 @@ export fn main(argc: i32, argv: **u8) i32 = {
|
|||||||
os.write(2, m.ptr, m.len: u64);
|
os.write(2, m.ptr, m.len: u64);
|
||||||
return 2;
|
return 2;
|
||||||
};
|
};
|
||||||
|
if (testsupport != nil && (sepmode == 0
|
||||||
|
|| (!cstreq(testsupport, "test")
|
||||||
|
&& !cstreq(testsupport, "__wwtest")))) {
|
||||||
|
let m: str = "w6c: invalid --test-support-module\n";
|
||||||
|
os.write(2, m.ptr, m.len: u64);
|
||||||
|
return 2;
|
||||||
|
};
|
||||||
|
|
||||||
let buf: *u8;
|
let buf: *u8;
|
||||||
let blen: u64;
|
let blen: u64;
|
||||||
@@ -155,6 +171,7 @@ export fn main(argc: i32, argv: **u8) i32 = {
|
|||||||
|
|
||||||
let ps: parser;
|
let ps: parser;
|
||||||
parserinit(&ps, &l);
|
parserinit(&ps, &l);
|
||||||
|
if (testsupport != nil) { ps.testmodule = pathstr(testsupport); };
|
||||||
let f: *node = parsefile(&ps);
|
let f: *node = parsefile(&ps);
|
||||||
// Gate cgen on parse-stage errors. Mirrors cmd/w6c/main.c's
|
// Gate cgen on parse-stage errors. Mirrors cmd/w6c/main.c's
|
||||||
// `if (l.errs || p.errs) return 1;` — broken AST otherwise reaches
|
// `if (l.errs || p.errs) return 1;` — broken AST otherwise reaches
|
||||||
@@ -172,6 +189,7 @@ export fn main(argc: i32, argv: **u8) i32 = {
|
|||||||
let ck: checker;
|
let ck: checker;
|
||||||
checkinit(&ck, &tc);
|
checkinit(&ck, &tc);
|
||||||
ck.istest = testmode;
|
ck.istest = testmode;
|
||||||
|
if (testsupport != nil) { ck.testmodule = pathstr(testsupport); };
|
||||||
ck.sepmode = sepmode;
|
ck.sepmode = sepmode;
|
||||||
checkfile(&ck, f);
|
checkfile(&ck, f);
|
||||||
if (ck.errs > 0) { return 1; };
|
if (ck.errs > 0) { return 1; };
|
||||||
|
|||||||
@@ -20,9 +20,10 @@ type checker = struct {
|
|||||||
// twin (c->matcharms)
|
// twin (c->matcharms)
|
||||||
istest: i32, // #15: `w6c_ww -T` — collect @test fns +
|
istest: i32, // #15: `w6c_ww -T` — collect @test fns +
|
||||||
// synth the entry; loud-reject a user main.
|
// synth the entry; loud-reject a user main.
|
||||||
|
testmodule: str, // generated dispatcher support qualifier
|
||||||
sepmode: i32, // -c package compilation: imported interfaces are
|
sepmode: i32, // -c package compilation: imported interfaces are
|
||||||
// present, so absent members are hard export errors.
|
// present, so absent members are hard export errors.
|
||||||
synthtestrun: *syntax.node, // exact generated test.run DOT; its
|
synthtestrun: *syntax.node, // exact generated support.run DOT; its
|
||||||
// unresolved external hook is intentional
|
// unresolved external hook is intentional
|
||||||
verbose: i32, // when non-zero, log each unresolved name
|
verbose: i32, // when non-zero, log each unresolved name
|
||||||
fnret: *syntax.node, // enclosing fn's return type AST (for `?`)
|
fnret: *syntax.node, // enclosing fn's return type AST (for `?`)
|
||||||
@@ -361,7 +362,7 @@ fn packageaccesserr(c: *checker, e: *syntax.node, pkg: str, member: str,
|
|||||||
c.errs += 1;
|
c.errs += 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A bare `w6c -T` leaves the compiler-generated test.run hook external;
|
// A bare `w6c -T` leaves the compiler-generated support.run hook external;
|
||||||
// the ordinary driver supplies lib/test. No user-written missing member is
|
// the ordinary driver supplies lib/test. No user-written missing member is
|
||||||
// exempt from package export checking.
|
// exempt from package export checking.
|
||||||
fn synthesizedtestrun(c: *checker, e: *syntax.node) bool = {
|
fn synthesizedtestrun(c: *checker, e: *syntax.node) bool = {
|
||||||
@@ -7480,6 +7481,7 @@ export fn checkinit(c: *checker, tc: *syntax.tctx) void = {
|
|||||||
c.nunresolved = 0;
|
c.nunresolved = 0;
|
||||||
c.errs = 0;
|
c.errs = 0;
|
||||||
c.istest = 0i32; // #15: caller (w6c main) sets it after init
|
c.istest = 0i32; // #15: caller (w6c main) sets it after init
|
||||||
|
c.testmodule = "test";
|
||||||
c.sepmode = 0i32; // caller (w6c main) sets it from -c
|
c.sepmode = 0i32; // caller (w6c main) sets it from -c
|
||||||
c.synthtestrun = nil;
|
c.synthtestrun = nil;
|
||||||
c.verbose = 0;
|
c.verbose = 0;
|
||||||
@@ -7496,20 +7498,19 @@ export fn checkfile(c: *checker, file: *syntax.node) void = {
|
|||||||
if (file.kind != syntax.nkind.N_FILE) { return; };
|
if (file.kind != syntax.nkind.N_FILE) { return; };
|
||||||
c.file = file;
|
c.file = file;
|
||||||
|
|
||||||
// #80: under -T, PREPEND the synth `use test;` BEFORE Pass 1 so declmod
|
// Under -T, prepend the dispatcher support import before Pass 1 so
|
||||||
// (called per-decl during install) sees a matching `use test` when it
|
// declmod keys the runner under the selected support module. This is a
|
||||||
// keys lib/test's `run` — keying it under mod="test", not "". This is a
|
|
||||||
// pure ORDER fix: the synth N_USE was appended AFTER install (below),
|
// pure ORDER fix: the synth N_USE was appended AFTER install (below),
|
||||||
// too late for declmod, so `run` keyed under "" — leaving the synth
|
// too late for declmod, so `run` keyed under "" — leaving the qualified
|
||||||
// `test.run` ty_err (the E1 bridge) and colliding with a user root
|
// call ty_err (the E1 bridge) and colliding with a user root
|
||||||
// `fn run` (also mod=""). Decoupled from cgen: the symbol mangle keys
|
// `fn run` (also mod=""). Decoupled from cgen: the symbol mangle keys
|
||||||
// off d.module (the //ww:module directive, cgen mod_collect), NOT this
|
// off d.module (the //ww:module directive, cgen mod_collect), NOT this
|
||||||
// scope keying — cgen already emits the correct CALL test.run. Twin of
|
// scope keying — cgen already emits the qualified call. Twin of
|
||||||
// cstage cmd/wcc/check.c.
|
// cstage cmd/wcc/check.c.
|
||||||
if (c.istest != 0) {
|
if (c.istest != 0) {
|
||||||
let usenode: *syntax.node = syntax.newnode(syntax.nkind.N_USE, file.file, file.line, file.col);
|
let usenode: *syntax.node = syntax.newnode(syntax.nkind.N_USE, file.file, file.line, file.col);
|
||||||
usenode.str = "test";
|
usenode.str = c.testmodule;
|
||||||
usenode.usepath = "test";
|
usenode.usepath = c.testmodule;
|
||||||
usenode.next = file.list;
|
usenode.next = file.list;
|
||||||
file.list = usenode;
|
file.list = usenode;
|
||||||
};
|
};
|
||||||
@@ -7719,16 +7720,14 @@ export fn checkfile(c: *checker, file: *syntax.node) void = {
|
|||||||
let arg: *syntax.node = syntax.newnode(syntax.nkind.N_IDENT, pf, pl, pc);
|
let arg: *syntax.node = syntax.newnode(syntax.nkind.N_IDENT, pf, pl, pc);
|
||||||
arg.str = "__wwtests";
|
arg.str = "__wwtests";
|
||||||
let call: *syntax.node = syntax.newnode(syntax.nkind.N_CALL, pf, pl, pc);
|
let call: *syntax.node = syntax.newnode(syntax.nkind.N_CALL, pf, pl, pc);
|
||||||
// QUALIFIED test.run (N_DOT base ident `test`, member `run`):
|
// Qualified support.run (N_DOT base ident + member `run`):
|
||||||
// the sep producer sees lib/test as a real imported package,
|
// the sep producer sees the toolchain test runtime as a real
|
||||||
// so the call must carry the module qualifier; the combined
|
// imported package. Its selected module is normally `test`, or
|
||||||
// path tags auto-bundled lib/test `//ww:module test` too, so
|
// the reserved alias when user source owns that identity. The
|
||||||
// it resolves+mangles identically (test.run). Cstage twin:
|
// base ident binds through the synthetic N_USE.
|
||||||
// cmd/wcc/check.c synth. The base ident binds through the
|
|
||||||
// synth N_USE below.
|
|
||||||
let dot: *syntax.node = syntax.newnode(syntax.nkind.N_DOT, pf, pl, pc);
|
let dot: *syntax.node = syntax.newnode(syntax.nkind.N_DOT, pf, pl, pc);
|
||||||
let did: *syntax.node = syntax.newnode(syntax.nkind.N_IDENT, pf, pl, pc);
|
let did: *syntax.node = syntax.newnode(syntax.nkind.N_IDENT, pf, pl, pc);
|
||||||
did.str = "test";
|
did.str = c.testmodule;
|
||||||
dot.lhs = did;
|
dot.lhs = did;
|
||||||
dot.str = "run";
|
dot.str = "run";
|
||||||
c.synthtestrun = dot;
|
c.synthtestrun = dot;
|
||||||
@@ -7737,11 +7736,9 @@ export fn checkfile(c: *checker, file: *syntax.node) void = {
|
|||||||
let ret: *syntax.node = syntax.newnode(syntax.nkind.N_RETURN, pf, pl, pc);
|
let ret: *syntax.node = syntax.newnode(syntax.nkind.N_RETURN, pf, pl, pc);
|
||||||
ret.lhs = call;
|
ret.lhs = call;
|
||||||
body.list = ret;
|
body.list = ret;
|
||||||
// #80: the synth `use test;` (the N_DOT base qualifier + the
|
// The synthetic support use is prepended before Pass 1, so
|
||||||
// usepathfor source mapping `test`→its path) is now PREPENDED
|
// declmod keys the runtime's `run` under the selected module and
|
||||||
// before Pass 1 at the top of checkfile, so declmod keys
|
// the synthesized call type-resolves. Pass 1 installs the use.
|
||||||
// lib/test's `run` under "test" and the synth `test.run`
|
|
||||||
// type-resolves. It is installed (SK_USE) by Pass 1's N_USE arm.
|
|
||||||
};
|
};
|
||||||
let m: *syntax.node = syntax.newnode(syntax.nkind.N_FNDECL, pf, pl, pc);
|
let m: *syntax.node = syntax.newnode(syntax.nkind.N_FNDECL, pf, pl, pc);
|
||||||
m.str = "main";
|
m.str = "main";
|
||||||
|
|||||||
Reference in New Issue
Block a user