selfhost/cmd/wcc: stamp e.type_ for N_INDEX (A.6.1.4)
Port cstage cmd/wcc/check.c:870-894 to exprtype. indexresult yields the resolved element tnode for slice/array, u8 for str, T for *[N]T (decay) and *T (generic), and []T for *[]T (no decay, mirrors the Hare-faithful rule at check.c:883-885). The arm stamps e.type_ via tinfofornode same shape as the A.6.1.3 BIN/UN pattern. Phase 1 A.6 step 4 of 6 — slot the indexing result type into the mandatory post-checker invariant. Cgenutil still derives index stride from AST shape (indexbaseesz, elemsizeofc, indexvaluetnode); A.6.3 will collapse those onto the now-stamped N_INDEX type_. Verified 132/132 incl. 995_self_rebuild byte-identity.
This commit is contained in:
@@ -8271,10 +8271,36 @@ fn unoptype(c: *checker, e: *node) *node = {
|
||||
return nil;
|
||||
};
|
||||
|
||||
// indexresult — derive the result tnode of an N_INDEX expression.
|
||||
// Mirrors cstage cmd/wcc/check.c:870-894. Slice/array → elem; str →
|
||||
// u8; `*[N]T` decays to T (pointer-to-array); `*[]T` does NOT decay
|
||||
// (yields []T via the generic *U → U fallback — Hare-faithful, a
|
||||
// pointer-to-slice is a 1D array of slices, not of T); generic *T → T.
|
||||
fn indexresult(c: *checker, e: *node) *node = {
|
||||
let basetn: *node = exprtype(c, e.lhs, nil);
|
||||
let _idx: *node = exprtype(c, e.rhs, nil);
|
||||
let u: *node = resolvealias(c, unwrapbang(basetn));
|
||||
if (u == nil) { return nil; };
|
||||
if (u.kind == nkind.N_TSLICE) { return u.lhs; };
|
||||
if (u.kind == nkind.N_TARRAY) { return u.lhs; };
|
||||
if (u.kind == nkind.N_TNAME) {
|
||||
if (streq(u.str, "str")) { return mktname(c, "u8"); };
|
||||
};
|
||||
if (u.kind == nkind.N_TPTR) {
|
||||
let inner: *node = u.lhs;
|
||||
let iu: *node = resolvealias(c, unwrapbang(inner));
|
||||
if (iu != nil && iu.kind == nkind.N_TARRAY) {
|
||||
return iu.lhs;
|
||||
};
|
||||
return inner;
|
||||
};
|
||||
return nil;
|
||||
};
|
||||
|
||||
// exprtype — best-effort type-AST inference for an expression
|
||||
// node. Handles literals, identifiers, calls, casts, binary/unary
|
||||
// ops; returns nil for shapes we don't statically know (struct
|
||||
// field access into non-primitive types, etc).
|
||||
// ops, indexing; returns nil for shapes we don't statically know
|
||||
// (struct field access into non-primitive types, etc).
|
||||
// `hint`: optional declared-type AST passed by the caller (let
|
||||
// target, assign target). nil = "no hint, derive from self". Threaded
|
||||
// for use by A.6.1's STRUCTLIT/ARRLIT arms which can't self-type and
|
||||
@@ -8361,6 +8387,11 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = {
|
||||
e.type_ = tinfofornode(c, tn): *void;
|
||||
return tn;
|
||||
};
|
||||
if (k == nkind.N_INDEX) {
|
||||
let tn: *node = indexresult(c, e);
|
||||
e.type_ = tinfofornode(c, tn): *void;
|
||||
return tn;
|
||||
};
|
||||
if (k == nkind.N_CAST) {
|
||||
// `expr: T` — explicit cast; the type expr is e.rhs. Mirrors
|
||||
// cstage cmd/wcc/check.c:737 `n->type = resolve_type(c, n->rhs)`.
|
||||
|
||||
@@ -1339,10 +1339,36 @@ fn unoptype(c: *checker, e: *node) *node = {
|
||||
return nil;
|
||||
};
|
||||
|
||||
// indexresult — derive the result tnode of an N_INDEX expression.
|
||||
// Mirrors cstage cmd/wcc/check.c:870-894. Slice/array → elem; str →
|
||||
// u8; `*[N]T` decays to T (pointer-to-array); `*[]T` does NOT decay
|
||||
// (yields []T via the generic *U → U fallback — Hare-faithful, a
|
||||
// pointer-to-slice is a 1D array of slices, not of T); generic *T → T.
|
||||
fn indexresult(c: *checker, e: *node) *node = {
|
||||
let basetn: *node = exprtype(c, e.lhs, nil);
|
||||
let _idx: *node = exprtype(c, e.rhs, nil);
|
||||
let u: *node = resolvealias(c, unwrapbang(basetn));
|
||||
if (u == nil) { return nil; };
|
||||
if (u.kind == nkind.N_TSLICE) { return u.lhs; };
|
||||
if (u.kind == nkind.N_TARRAY) { return u.lhs; };
|
||||
if (u.kind == nkind.N_TNAME) {
|
||||
if (streq(u.str, "str")) { return mktname(c, "u8"); };
|
||||
};
|
||||
if (u.kind == nkind.N_TPTR) {
|
||||
let inner: *node = u.lhs;
|
||||
let iu: *node = resolvealias(c, unwrapbang(inner));
|
||||
if (iu != nil && iu.kind == nkind.N_TARRAY) {
|
||||
return iu.lhs;
|
||||
};
|
||||
return inner;
|
||||
};
|
||||
return nil;
|
||||
};
|
||||
|
||||
// exprtype — best-effort type-AST inference for an expression
|
||||
// node. Handles literals, identifiers, calls, casts, binary/unary
|
||||
// ops; returns nil for shapes we don't statically know (struct
|
||||
// field access into non-primitive types, etc).
|
||||
// ops, indexing; returns nil for shapes we don't statically know
|
||||
// (struct field access into non-primitive types, etc).
|
||||
// `hint`: optional declared-type AST passed by the caller (let
|
||||
// target, assign target). nil = "no hint, derive from self". Threaded
|
||||
// for use by A.6.1's STRUCTLIT/ARRLIT arms which can't self-type and
|
||||
@@ -1429,6 +1455,11 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = {
|
||||
e.type_ = tinfofornode(c, tn): *void;
|
||||
return tn;
|
||||
};
|
||||
if (k == nkind.N_INDEX) {
|
||||
let tn: *node = indexresult(c, e);
|
||||
e.type_ = tinfofornode(c, tn): *void;
|
||||
return tn;
|
||||
};
|
||||
if (k == nkind.N_CAST) {
|
||||
// `expr: T` — explicit cast; the type expr is e.rhs. Mirrors
|
||||
// cstage cmd/wcc/check.c:737 `n->type = resolve_type(c, n->rhs)`.
|
||||
|
||||
@@ -8271,10 +8271,36 @@ fn unoptype(c: *checker, e: *node) *node = {
|
||||
return nil;
|
||||
};
|
||||
|
||||
// indexresult — derive the result tnode of an N_INDEX expression.
|
||||
// Mirrors cstage cmd/wcc/check.c:870-894. Slice/array → elem; str →
|
||||
// u8; `*[N]T` decays to T (pointer-to-array); `*[]T` does NOT decay
|
||||
// (yields []T via the generic *U → U fallback — Hare-faithful, a
|
||||
// pointer-to-slice is a 1D array of slices, not of T); generic *T → T.
|
||||
fn indexresult(c: *checker, e: *node) *node = {
|
||||
let basetn: *node = exprtype(c, e.lhs, nil);
|
||||
let _idx: *node = exprtype(c, e.rhs, nil);
|
||||
let u: *node = resolvealias(c, unwrapbang(basetn));
|
||||
if (u == nil) { return nil; };
|
||||
if (u.kind == nkind.N_TSLICE) { return u.lhs; };
|
||||
if (u.kind == nkind.N_TARRAY) { return u.lhs; };
|
||||
if (u.kind == nkind.N_TNAME) {
|
||||
if (streq(u.str, "str")) { return mktname(c, "u8"); };
|
||||
};
|
||||
if (u.kind == nkind.N_TPTR) {
|
||||
let inner: *node = u.lhs;
|
||||
let iu: *node = resolvealias(c, unwrapbang(inner));
|
||||
if (iu != nil && iu.kind == nkind.N_TARRAY) {
|
||||
return iu.lhs;
|
||||
};
|
||||
return inner;
|
||||
};
|
||||
return nil;
|
||||
};
|
||||
|
||||
// exprtype — best-effort type-AST inference for an expression
|
||||
// node. Handles literals, identifiers, calls, casts, binary/unary
|
||||
// ops; returns nil for shapes we don't statically know (struct
|
||||
// field access into non-primitive types, etc).
|
||||
// ops, indexing; returns nil for shapes we don't statically know
|
||||
// (struct field access into non-primitive types, etc).
|
||||
// `hint`: optional declared-type AST passed by the caller (let
|
||||
// target, assign target). nil = "no hint, derive from self". Threaded
|
||||
// for use by A.6.1's STRUCTLIT/ARRLIT arms which can't self-type and
|
||||
@@ -8361,6 +8387,11 @@ fn exprtype(c: *checker, e: *node, hint: *node) *node = {
|
||||
e.type_ = tinfofornode(c, tn): *void;
|
||||
return tn;
|
||||
};
|
||||
if (k == nkind.N_INDEX) {
|
||||
let tn: *node = indexresult(c, e);
|
||||
e.type_ = tinfofornode(c, tn): *void;
|
||||
return tn;
|
||||
};
|
||||
if (k == nkind.N_CAST) {
|
||||
// `expr: T` — explicit cast; the type expr is e.rhs. Mirrors
|
||||
// cstage cmd/wcc/check.c:737 `n->type = resolve_type(c, n->rhs)`.
|
||||
|
||||
Reference in New Issue
Block a user