Files
ww/test/wcc/data/r5913_offset_shift_nested/case.ww
Hojun-Cho 5abb1e6069 wwstage: port struct embedding; graduate #59.13
The last frontend-gap pin: wwstage had no Hare struct embedding
(struct { hash.hash, ... }), rejecting lib/crypto/sha256 at parse.

- parse.ww: the three member forms (named / anonymous struct / bare
  dotted-ident embed), consume-then-branch since this parser has no
  peek; embeds carry f.str == "" and the type in f.lhs.
- check.ww N_TSTRUCT flatten: promote the inner struct's flattened
  fields at base+src.offset (check.c:961-990); the embed is one
  nested-struct unit in the slot ladder; the resolved inner AST is
  planted on the TFIELD rhs for cgen.
- check.ww walkers: astoffset / exprtype N_DOT / #251 struct-lit
  field lookups descend embeds through shared helpers; the collision
  and non-struct-embed rejects live in validatestructfields (the
  once-per-decl diagnostic site).
- cgenutil.ww registerstruct: regfieldrun walks the AST against the
  flattened tfield cursor, descending embeds via the planted inner
  AST so promoted fieldinfo entries keep the inner field's own name
  and type node.
- wwi printers unchanged (both stages already emit nameless fields).

sha256_test compiles byte-identically end to end and its 6 tests
pass; 989_lib_byteid is now 44 id / 0 divergent / 0 wwreject.
Fixtures r5913_* (promoted rw, offset shift, anonymous embed,
two-level embed + promoted fn-ptr callee, three rejects); corpus pin
1485/2970.
2026-08-08 02:37:50 +09:00

38 lines
641 B
Plaintext

//ww:run-exit 42
package main;
// #59.13: fields declared after an embed sit at base+inner.size, the
// offset() fold sees promoted names, and promoted access works through
// a pointer receiver and a nested chain (o.p.y — promoted struct field
// then its own member).
type pos = struct {
x: i32,
y: i32,
};
type mid = struct {
p: pos,
tag: i32,
};
type outer = struct {
mid,
c: i32,
};
fn bump(o: *outer) void = {
o.tag += 1;
o.p.y = o.p.x + 2;
};
fn main() i32 = {
let o: outer;
o.p.x = 5;
o.tag = 9;
o.c = 20;
bump(&o);
let shift: i64 = offset(o.c) - offset(o.tag);
return o.p.y + o.tag + o.c + shift: i32 + 1;
};