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;
|
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
|
// exprtype — best-effort type-AST inference for an expression
|
||||||
// node. Handles literals, identifiers, calls, casts, binary/unary
|
// node. Handles literals, identifiers, calls, casts, binary/unary
|
||||||
// ops; returns nil for shapes we don't statically know (struct
|
// ops, indexing; returns nil for shapes we don't statically know
|
||||||
// field access into non-primitive types, etc).
|
// (struct field access into non-primitive types, etc).
|
||||||
// `hint`: optional declared-type AST passed by the caller (let
|
// `hint`: optional declared-type AST passed by the caller (let
|
||||||
// target, assign target). nil = "no hint, derive from self". Threaded
|
// 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
|
// 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;
|
e.type_ = tinfofornode(c, tn): *void;
|
||||||
return tn;
|
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) {
|
if (k == nkind.N_CAST) {
|
||||||
// `expr: T` — explicit cast; the type expr is e.rhs. Mirrors
|
// `expr: T` — explicit cast; the type expr is e.rhs. Mirrors
|
||||||
// cstage cmd/wcc/check.c:737 `n->type = resolve_type(c, n->rhs)`.
|
// 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;
|
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
|
// exprtype — best-effort type-AST inference for an expression
|
||||||
// node. Handles literals, identifiers, calls, casts, binary/unary
|
// node. Handles literals, identifiers, calls, casts, binary/unary
|
||||||
// ops; returns nil for shapes we don't statically know (struct
|
// ops, indexing; returns nil for shapes we don't statically know
|
||||||
// field access into non-primitive types, etc).
|
// (struct field access into non-primitive types, etc).
|
||||||
// `hint`: optional declared-type AST passed by the caller (let
|
// `hint`: optional declared-type AST passed by the caller (let
|
||||||
// target, assign target). nil = "no hint, derive from self". Threaded
|
// 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
|
// 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;
|
e.type_ = tinfofornode(c, tn): *void;
|
||||||
return tn;
|
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) {
|
if (k == nkind.N_CAST) {
|
||||||
// `expr: T` — explicit cast; the type expr is e.rhs. Mirrors
|
// `expr: T` — explicit cast; the type expr is e.rhs. Mirrors
|
||||||
// cstage cmd/wcc/check.c:737 `n->type = resolve_type(c, n->rhs)`.
|
// 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;
|
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
|
// exprtype — best-effort type-AST inference for an expression
|
||||||
// node. Handles literals, identifiers, calls, casts, binary/unary
|
// node. Handles literals, identifiers, calls, casts, binary/unary
|
||||||
// ops; returns nil for shapes we don't statically know (struct
|
// ops, indexing; returns nil for shapes we don't statically know
|
||||||
// field access into non-primitive types, etc).
|
// (struct field access into non-primitive types, etc).
|
||||||
// `hint`: optional declared-type AST passed by the caller (let
|
// `hint`: optional declared-type AST passed by the caller (let
|
||||||
// target, assign target). nil = "no hint, derive from self". Threaded
|
// 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
|
// 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;
|
e.type_ = tinfofornode(c, tn): *void;
|
||||||
return tn;
|
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) {
|
if (k == nkind.N_CAST) {
|
||||||
// `expr: T` — explicit cast; the type expr is e.rhs. Mirrors
|
// `expr: T` — explicit cast; the type expr is e.rhs. Mirrors
|
||||||
// cstage cmd/wcc/check.c:737 `n->type = resolve_type(c, n->rhs)`.
|
// cstage cmd/wcc/check.c:737 `n->type = resolve_type(c, n->rhs)`.
|
||||||
|
|||||||
Reference in New Issue
Block a user