wcc/ww: serialize aggregate exported defs as value-less .wwi prototypes (BUG-2, #70)
The .wwi (separate-compile interface) producer could not serialize an
exported def whose initializer is a struct/array literal (N_STRUCTLIT/
N_ARRLIT) — `export def f64info: floatinfo = floatinfo{...}` aborted with
"unhandled const-expr node kind 15". Such a def is a DATA-global per the
#52 model, so its value lives once in the defining package's .o; the
interface needs only the type+symbol. Emit a value-less prototype
`export def X: T;` for aggregate-initializer defs; scalar fold-eligible
defs keep their value (the importer const-folds those). The parser gains
an optional-init arm so the importer can parse the prototype — value-less
`def X: T;` is now legal in any source, symmetric with the existing
bodyless-fn prototype `fn f();` (USER ruling: unconditional; a value-less
def with no defining .o is a loud undefined-symbol error at link, never
silent). Both stages; producer + parser fold into one commit (the
producer's output is unparseable without the parser arm).
M3-tail commit-6 prerequisite #2 (surfaced by the c6 scout). The
aggregate-def-field const-fold boundary is documented inline (#71). Gate
989_sepstructdef_run proves struct+array exported defs sep-build, link,
and run via external DATA refs, cs==ww, with a value-less .wwi.
This commit is contained in:
@@ -402,9 +402,24 @@ wwi_decl(FILE *of, Node *d)
|
||||
fputs(d->str, of);
|
||||
fputs(": ", of);
|
||||
wwi_type(of, d->lhs);
|
||||
fputs(" = ", of);
|
||||
wwi_expr(of, d->rhs);
|
||||
fputs(";\n", of);
|
||||
/* 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
|
||||
* importer registers the def by TYPE only (the DATA-suppression
|
||||
* if(sep_mode && imported)continue at cgen.c is already in place)
|
||||
* and field/element reads become external LEAQ refs the linker
|
||||
* fills. Boundary (rule 7): this gives up importer-side const-
|
||||
* fold of an aggregate def's FIELDS — a no-op, ww never folds
|
||||
* struct-literal field access, and an aggregate-def field
|
||||
* demanded in a const-fold context stays a LOUD error (task #71). */
|
||||
if (d->rhs && (d->rhs->kind == N_STRUCTLIT
|
||||
|| d->rhs->kind == N_ARRLIT)) {
|
||||
fputs(";\n", of);
|
||||
} else {
|
||||
fputs(" = ", of);
|
||||
wwi_expr(of, d->rhs);
|
||||
fputs(";\n", of);
|
||||
}
|
||||
break;
|
||||
case N_LET:
|
||||
fputs("export let ", of);
|
||||
|
||||
@@ -1284,8 +1284,13 @@ parsedef(Parser *p, int exp)
|
||||
n->str = expectident(p);
|
||||
expect(p, TK_COLON);
|
||||
n->lhs = parsetype(p);
|
||||
expect(p, TK_ASSIGN);
|
||||
n->rhs = parseexpr(p);
|
||||
/* A value-LESS `def X: T;` is an interface prototype (an aggregate-
|
||||
* init `.wwi` def whose DATA lives in the defining package — BUG-2 /
|
||||
* task #71), mirroring parsefn's bodyless-prototype arm. rhs stays
|
||||
* NULL; the checker's fold pass (`if (d->rhs)`) and cgen's emit_defs/
|
||||
* emit_lets (`d->rhs == NULL` continue) already expect this shape. */
|
||||
if (accept(p, TK_ASSIGN))
|
||||
n->rhs = parseexpr(p);
|
||||
expect(p, TK_SEMI);
|
||||
n->export = exp;
|
||||
return n;
|
||||
|
||||
Reference in New Issue
Block a user