build: pass direct exports to package compilers
This commit is contained in:
110
cmd/w6c/main.c
110
cmd/w6c/main.c
@@ -22,6 +22,41 @@ slurp(const char *path, char **outbuf, u64 *outlen)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct importin {
|
||||
const char *path;
|
||||
const char *file;
|
||||
char *buf;
|
||||
u64 len;
|
||||
};
|
||||
|
||||
static Node *
|
||||
parseinput(Arena *a, const char *file, char *buf, u64 len,
|
||||
const char *mod, const char *testsupport, int *bad)
|
||||
{
|
||||
Lex l;
|
||||
Parser p;
|
||||
lexinit(&l, a, file, buf, len);
|
||||
parserinit(&p, a, &l);
|
||||
p.testmodule = testsupport;
|
||||
if (mod != NULL) {
|
||||
p.pathmod = mod;
|
||||
p.curmod = mod;
|
||||
}
|
||||
Node *f = parsefile(&p);
|
||||
*bad = l.errs || p.errs;
|
||||
return f;
|
||||
}
|
||||
|
||||
static void
|
||||
appendnodes(Node **head, Node **tail, Node *list)
|
||||
{
|
||||
if (list == NULL) return;
|
||||
if (*head == NULL) *head = list;
|
||||
else (*tail)->next = list;
|
||||
while (list->next != NULL) list = list->next;
|
||||
*tail = list;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@@ -31,8 +66,14 @@ main(int argc, char **argv)
|
||||
const char *testsupport = NULL;
|
||||
int testmode = 0;
|
||||
int sepmode = 0; /* -c: #22 M3 separate-compile / primary-
|
||||
* only codegen (emit imported==0 decls
|
||||
* only; treat `.wwi` deps as external) */
|
||||
* only codegen (emit imported==0 decls
|
||||
* only; treat `.wwi` deps as external) */
|
||||
struct importin *imports = calloc((size_t)argc, sizeof *imports);
|
||||
if (imports == NULL) {
|
||||
fputs("w6c: out of memory\n", stderr);
|
||||
return 1;
|
||||
}
|
||||
int nimports = 0;
|
||||
for (int i = 1; i < argc; i++) {
|
||||
const char *a = argv[i];
|
||||
if (strcmp(a, "-o") == 0 && i + 1 < argc) {
|
||||
@@ -49,6 +90,14 @@ main(int argc, char **argv)
|
||||
testsupport = argv[++i];
|
||||
} else if (strcmp(a, "-c") == 0) {
|
||||
sepmode = 1;
|
||||
} else if (strcmp(a, "--import") == 0) {
|
||||
if (i + 2 >= argc) {
|
||||
fputs("w6c: --import requires path and file\n", stderr);
|
||||
return 2;
|
||||
}
|
||||
imports[nimports].path = argv[++i];
|
||||
imports[nimports].file = argv[++i];
|
||||
nimports++;
|
||||
} else if (a[0] == '-') {
|
||||
fprintf(stderr, "w6c: unknown flag %s\n", a);
|
||||
return 2;
|
||||
@@ -60,9 +109,24 @@ main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
if (src == NULL) {
|
||||
fputs("usage: w6c [-T] [-c] [-I out.wwi] [-o out.s] file.ww\n", stderr);
|
||||
fputs("usage: w6c [-T] [-c] [-I out.wwi] "
|
||||
"[--import path dep.wwi]... [-o out.s] file.ww\n", stderr);
|
||||
return 2;
|
||||
}
|
||||
if (nimports > 0 && !sepmode) {
|
||||
fputs("w6c: --import requires -c\n", stderr);
|
||||
return 2;
|
||||
}
|
||||
for (int i = 0; i < nimports; i++) {
|
||||
if (imports[i].path[0] == '\0') {
|
||||
fputs("w6c: --import path is empty\n", stderr);
|
||||
return 2;
|
||||
}
|
||||
if (i > 0 && strcmp(imports[i-1].path, imports[i].path) >= 0) {
|
||||
fputs("w6c: --import paths must be sorted and unique\n", stderr);
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
if (testsupport != NULL && (!sepmode
|
||||
|| (strcmp(testsupport, "test") != 0
|
||||
&& strcmp(testsupport, "__wwtest") != 0))) {
|
||||
@@ -70,24 +134,38 @@ main(int argc, char **argv)
|
||||
return 2;
|
||||
}
|
||||
|
||||
Arena *a = newarena();
|
||||
Checker c;
|
||||
Cg cg;
|
||||
|
||||
Node *head = NULL, *tail = NULL;
|
||||
for (int i = 0; i < nimports; i++) {
|
||||
if (slurp(imports[i].file, &imports[i].buf,
|
||||
&imports[i].len) < 0) {
|
||||
fprintf(stderr, "w6c: import %s: cannot read %s\n",
|
||||
imports[i].path, imports[i].file);
|
||||
return 1;
|
||||
}
|
||||
int bad = 0;
|
||||
Node *f = parseinput(a, imports[i].file, imports[i].buf,
|
||||
imports[i].len, imports[i].path, testsupport, &bad);
|
||||
if (bad) return 1;
|
||||
appendnodes(&head, &tail, f->list);
|
||||
}
|
||||
|
||||
char *buf;
|
||||
u64 len;
|
||||
if (slurp(src, &buf, &len) < 0) {
|
||||
fprintf(stderr, "w6c: %s: cannot read\n", src);
|
||||
return 1;
|
||||
}
|
||||
|
||||
Arena *a = newarena();
|
||||
Lex l;
|
||||
Parser p;
|
||||
Checker c;
|
||||
Cg cg;
|
||||
|
||||
lexinit(&l, a, src, buf, len);
|
||||
parserinit(&p, a, &l);
|
||||
p.testmodule = testsupport;
|
||||
Node *file = parsefile(&p);
|
||||
if (l.errs || p.errs) return 1;
|
||||
int bad = 0;
|
||||
Node *file = parseinput(a, src, buf, len, NULL, testsupport, &bad);
|
||||
if (bad) return 1;
|
||||
if (head != NULL) {
|
||||
tail->next = file->list;
|
||||
file->list = head;
|
||||
}
|
||||
|
||||
check_init(&c, a);
|
||||
c.is_test = testmode;
|
||||
@@ -128,6 +206,8 @@ main(int argc, char **argv)
|
||||
|
||||
if (of != stdout) fclose(of);
|
||||
freearena(a);
|
||||
for (int i = 0; i < nimports; i++) free(imports[i].buf);
|
||||
free(imports);
|
||||
free(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
* wwi.c — `.wwi` export-data producer (w6c -I): a re-parseable ww-prototype
|
||||
* rendering of a package's EXPORTED surface. Since the sep-compile flip
|
||||
* (epic #22) this is the LIVE import path — the driver runs one `w6c -c -I`
|
||||
* per package and feeds each dep's `.wwi` to its importers as import scope;
|
||||
* the combined.ww amalgamator is gone.
|
||||
* per package and feeds each dep's `.wwi` to its importers through a separate
|
||||
* canonical `--import` input; the combined.ww amalgamator is gone.
|
||||
*
|
||||
* Specs: .ai/rob-M2-spec.md (producer) + .ai/drew-M2-checkexported.md
|
||||
* (check_exported_type). Two load-bearing choices follow them:
|
||||
|
||||
Reference in New Issue
Block a user