wcc/check: #141 def-dim array as struct field — fold def in dim, shared arrayelen across 3 ww readers (both stages)
A def-dimensioned array [MAX]u8 used as a struct field was BOTH-WRONG: cstage
loud-rejected ("array length must be an integer literal"); wwstage silently
sized the dim to 0, so the next field overlapped it (frame-smash). The
reference is neither stage — it is Hare: accept + fold the def.
cstage: fold the def into the dim via eval_def_const. The fold needs def NAMES
visible when resolve_typedecl walks struct bodies, so a stub loop binds
def-name stubs (type=NULL, filled in place by the existing def loop) before
resolve_typedecl — this extends check_file's existing names-first USE+TYPEDECL
pass to DEFs; def-TYPE resolution stays in its original order, and the
kind-filtered type lookup (#225) keeps the SK_DEF stub out of type position.
wwstage: one shared arrayelen(c, rhs) (INTLIT -> uval; else evaldefconst;
else 0) routed through astsize / tinfofornode / checkarrlitfits.
Closes #13's def-dim cstage-reject half (the slice-repeat clause stays open).
Pin test/wcc/951 (5 rows incl a cross-module os.PATH_MAX dim + a ~4KB shape;
teeth = cstage loud-reject + ww frame-smash). cgen-first blocker for the
path::buffer arc (type buffer = struct{[MAX]u8, ...}).
This commit is contained in:
@@ -653,13 +653,19 @@ resolve_type(Checker *c, Node *n)
|
||||
case N_TSLICE:
|
||||
return type_slice(c->a, resolve_type(c, n->lhs));
|
||||
case N_TARRAY: {
|
||||
u64 len = 0;
|
||||
u64 len = 0, v;
|
||||
if (n->rhs == NULL) {
|
||||
/* `[_]T` — length inferred at the use site (currently
|
||||
* only `let x: [_]T = arrlit;`). Leave alen=0 as a
|
||||
* sentinel; clet patches it from the initialiser. */
|
||||
} else if (n->rhs->kind == N_INTLIT) {
|
||||
len = n->rhs->uval;
|
||||
} else if (eval_def_const(c, n->rhs, &v, 0)) {
|
||||
/* #141: a def-dimensioned `[MAX]u8`; fold the
|
||||
* const-expr dimension (the same machinery #133's
|
||||
* let-init fold uses). The err below stays for a
|
||||
* genuinely non-const rhs. */
|
||||
len = v;
|
||||
} else {
|
||||
err(c, n->pos, "array length must be an integer literal");
|
||||
}
|
||||
@@ -2716,6 +2722,29 @@ check_file(Checker *c, Node *file)
|
||||
}
|
||||
d->type = named;
|
||||
}
|
||||
/* #141: bind def NAMES before resolving type bodies, so a struct
|
||||
* field `[MAX]u8` whose dimension is a def-ref folds via
|
||||
* eval_def_const (which reads decl->rhs) when resolve_typedecl
|
||||
* walks the body below. The def's type is resolved in the
|
||||
* decl loop further down; only the name->decl binding is needed
|
||||
* here. A foldable stub carries type NULL until then. A duplicate
|
||||
* (prev already bound non-USE) is left for that loop to diagnose. */
|
||||
c->cur_mod = NULL;
|
||||
for (Node *d = file->list; d; d = d->next) {
|
||||
if (d->kind != N_DEF) continue;
|
||||
c->cur_mod = decl_mod(file, d);
|
||||
const char *mod = decl_mod(file, d);
|
||||
Sym *prev = scope_lookup_local(c->cur, d->str);
|
||||
if (prev && prev->kind == SK_USE) {
|
||||
prev->kind = SK_DEF; prev->decl = d;
|
||||
prev->use_alias = 1;
|
||||
if (mod && prev->mod == NULL) prev->mod = mod;
|
||||
} else if (prev == NULL) {
|
||||
scope_define_in_module(c->cur, d->str, mod,
|
||||
SK_DEF, NULL, d);
|
||||
}
|
||||
}
|
||||
c->cur_mod = NULL;
|
||||
for (Node *d = file->list; d; d = d->next) {
|
||||
if (d->kind != N_TYPEDECL) continue;
|
||||
resolve_typedecl(c, d);
|
||||
@@ -2733,7 +2762,11 @@ check_file(Checker *c, Node *file)
|
||||
d->type = t;
|
||||
Sym *prev = scope_lookup_local(c->cur, d->str);
|
||||
const char *mod = decl_mod(file, d);
|
||||
if (prev && prev->kind == SK_USE) {
|
||||
if (prev && prev->kind == SK_DEF && prev->decl == d) {
|
||||
/* #141: the foldable stub bound before type-body
|
||||
* resolution; fill in its now-resolved type. */
|
||||
prev->type = t;
|
||||
} else if (prev && prev->kind == SK_USE) {
|
||||
/* `use mod; ... def mod = ...;` — promote the
|
||||
* SK_USE to the def symbol but remember it was
|
||||
* also a module name so dotted qualifiers
|
||||
|
||||
Reference in New Issue
Block a user