wcc: add the opaque abstract type (kind + UNDEFINED sentinel + name-binding) (#108)
#108 sub-fold (a): TY_OPAQUE exists, is name-bindable, and carries an UNDEFINED size sentinel. Mirrors the #85 `size` fold pattern at every site, both stages (rule-10). opaque is abstract + UNSIZED: prim()'d with size=align=SIZE_UNDEFINED (NOT 0 — a 0 would let a bare `let x: opaque` fabricate a 0-byte local), mirroring harec builtin_type_opaque (ref/harec/src/types.c:1446). ww had no incomplete-size sentinel, so this fold ADDS one: cstage `#define SIZE_UNDEFINED ((u64)-1)` (== harec types.h:58 (size_t)-1) and wwstage `def SIZE_UNDEFINED: u64 = 18446744073709551615`. Legal only behind indirection: `*opaque` (8B ptr) and `[]opaque` (24B slice header) construct correctly because type_ptr/type_slice (and the wwstage typeptr/typeslice) size themselves independent of the element. opaque is deliberately absent from is-int/unsigned/num/float and from the size-classification switches (let_emit_size / tupleelemslot / fieldslotsize) on both stages — it only reaches those as TY_PTR/TY_SLICE. The use-restriction GUARDS (reject bare opaque / size(opaque) / opaque field / [N]opaque / []opaque-indexing), assignability, and cgen-verify are the separate sub-folds (b)/(c)/(d) — NOT here. opaque is unused by the bootstrap, so 990-997 stay byte-identical (inert, like #85). Regenerates the w6c/wwdump combined.ww (typ.ww + check.ww embedded). New probe 960_opaque_decl_run exercises `*opaque` and `[]opaque` (.len/.ptr) behind indirection.
This commit is contained in:
@@ -6411,8 +6411,15 @@ type tykind = enum i32 {
|
||||
// against cmd/wcc/ww.h.
|
||||
TY_ENUM = 35,
|
||||
TY_SIZE = 36, // #85 fold-1; mirrors TY_UINTPTR (8/8 amd64)
|
||||
TY_OPAQUE = 37, // #108(a); abstract + unsized, behind indirection only
|
||||
};
|
||||
|
||||
// #108(a): unsized sentinel for abstract types (tinfo.size / .align).
|
||||
// Mirrors harec SIZE_UNDEFINED = (size_t)-1 (ref/harec/include/types.h
|
||||
// :58) and cstage cmd/wcc/ww.h; not 0, so a bare opaque local can't
|
||||
// fabricate a 0-byte slot. Value == U64_MAX.
|
||||
def SIZE_UNDEFINED: u64 = 18446744073709551615;
|
||||
|
||||
// ---- tinfo / tfield / tparam -----------------------------------------
|
||||
|
||||
type tfield = struct {
|
||||
@@ -6513,6 +6520,7 @@ type tctx = struct {
|
||||
tyuint: *tinfo,
|
||||
tyuintptr: *tinfo,
|
||||
tysize: *tinfo,
|
||||
tyopaque: *tinfo,
|
||||
tyf32: *tinfo,
|
||||
tyf64: *tinfo,
|
||||
tystr: *tinfo,
|
||||
@@ -6578,6 +6586,10 @@ export fn typesinit(c: *tctx) void = {
|
||||
c.tystr.sub = c.tyu8; // str IS []u8: element is u8 (Phase 2 F1)
|
||||
c.tyerr = prim(tykind.TY_ERR, "<err>", 0u64, 1u64);
|
||||
c.tynever = prim(tykind.TY_NEVER, "never", 0u64, 1u64);
|
||||
// #108(a): abstract + unsized. SIZE_UNDEFINED (not 0) blocks a bare
|
||||
// `let x: opaque` 0-byte slot; legal only behind indirection.
|
||||
// Mirrors cstage type.c ty_opaque (harec types.c:1446).
|
||||
c.tyopaque = prim(tykind.TY_OPAQUE, "opaque", SIZE_UNDEFINED, SIZE_UNDEFINED);
|
||||
|
||||
c.tyuntypedint = prim(tykind.TY_UNTYPED_INT, "untyped_int", 0u64, 1u64);
|
||||
c.tyuntypedfloat = prim(tykind.TY_UNTYPED_FLOAT, "untyped_float", 0u64, 1u64);
|
||||
@@ -8438,6 +8450,7 @@ fn tinfofornode(c: *checker, n: *node) *tinfo = {
|
||||
if (streq(nm, "uint")) { r = c.tc.tyuint; };
|
||||
if (streq(nm, "uintptr")) { r = c.tc.tyuintptr; };
|
||||
if (streq(nm, "size")) { r = c.tc.tysize; }; // #85 fold-2
|
||||
if (streq(nm, "opaque")) { r = c.tc.tyopaque; }; // #108(a)
|
||||
if (streq(nm, "f32")) { r = c.tc.tyf32; };
|
||||
if (streq(nm, "f64")) { r = c.tc.tyf64; };
|
||||
if (streq(nm, "str")) { r = c.tc.tystr; };
|
||||
|
||||
Reference in New Issue
Block a user