selfhost: graduate N_* defs to nkind enum

This commit is contained in:
2026-05-12 04:54:23 +09:00
parent d20674a5ad
commit 3affe01705
13 changed files with 2007 additions and 1995 deletions

View File

@@ -10,7 +10,7 @@
// `i32`, `str`, `*u8` etc. resolve.
// 2. Walks the file's top-level decls (use/def/type/fn/let) and
// installs Sym entries for each.
// 3. Recursively walks fn bodies; for every N_IDENT used as an
// 3. Recursively walks fn bodies; for every nkind.N_IDENT used as an
// expression or as a type name, looks it up and counts the
// resolved vs. unresolved.
// 4. Returns a summary the caller (wwdump -r) prints; the test
@@ -70,15 +70,15 @@ fn installdecl(c: *checker, d: *node) void = {
if (d == nil) { return; };
let k: i32 = d.kind;
let nm: str = d.str;
if (k == N_USE) { scopedefine(c.top, nm, skind.SK_USE, nil, d); return; };
if (k == N_DEF) { scopedefine(c.top, nm, skind.SK_DEF, nil, d); return; };
if (k == N_TYPEDECL) { scopedefine(c.top, nm, skind.SK_TYPE, nil, d); return; };
if (k == N_FNDECL) { scopedefine(c.top, nm, skind.SK_FN, nil, d); return; };
if (k == N_LET) { scopedefine(c.top, nm, skind.SK_VAR, nil, d); return; };
if (k == nkind.N_USE) { scopedefine(c.top, nm, skind.SK_USE, nil, d); return; };
if (k == nkind.N_DEF) { scopedefine(c.top, nm, skind.SK_DEF, nil, d); return; };
if (k == nkind.N_TYPEDECL) { scopedefine(c.top, nm, skind.SK_TYPE, nil, d); return; };
if (k == nkind.N_FNDECL) { scopedefine(c.top, nm, skind.SK_FN, nil, d); return; };
if (k == nkind.N_LET) { scopedefine(c.top, nm, skind.SK_VAR, nil, d); return; };
};
// resolvewalk — recursive AST walk that, for every N_IDENT and
// N_TNAME seen, looks up the name and bumps the resolved/unresolved
// resolvewalk — recursive AST walk that, for every nkind.N_IDENT and
// nkind.N_TNAME seen, looks up the name and bumps the resolved/unresolved
// counters. Local lets are installed in the current scope as soon as
// their init/type expressions have been walked (forward use of a let
// before its declaration would resolve to nothing — same semantics as
@@ -91,17 +91,17 @@ fn resolvewalk(c: *checker, n: *node) void = {
// Typed checks fire on the way down so the scrutinee/operand
// is examined before the arm bodies install new bindings.
if (k == N_MATCH) { checkmatchexhaust(c, n); };
if (k == N_TRYPROP) { checktryprop(c, n); };
if (k == N_TYPETEST) { checkisas(c, n); };
if (k == N_TYPEASSERT) { checkisas(c, n); };
if (k == N_LET) { checkletassign(c, n); };
if (k == N_RETURN) { checkretassign(c, n); };
if (k == nkind.N_MATCH) { checkmatchexhaust(c, n); };
if (k == nkind.N_TRYPROP) { checktryprop(c, n); };
if (k == nkind.N_TYPETEST) { checkisas(c, n); };
if (k == nkind.N_TYPEASSERT) { checkisas(c, n); };
if (k == nkind.N_LET) { checkletassign(c, n); };
if (k == nkind.N_RETURN) { checkretassign(c, n); };
// `use IDENT;` — name is a module label, not a free ident.
if (k == N_USE) { return; };
if (k == nkind.N_USE) { return; };
if (k == N_IDENT) {
if (k == nkind.N_IDENT) {
let nm: str = n.str;
if (nm.len > 0) {
let s: *sym = scopelookup(c.cur, nm);
@@ -116,7 +116,7 @@ fn resolvewalk(c: *checker, n: *node) void = {
};
};
if (k == N_TNAME) {
if (k == nkind.N_TNAME) {
let nm: str = n.str;
if (nm.len > 0) {
let s: *sym = scopelookup(c.cur, nm);
@@ -155,7 +155,7 @@ fn resolvewalk(c: *checker, n: *node) void = {
// `match (e) { case let v: T => stmt; ... }` — the binding `v`
// is declared by the case arm and visible inside its body.
if (k == N_MCASE) {
if (k == nkind.N_MCASE) {
if (n.lhs != nil) { resolvewalk(c, n.lhs); };
let nm: str = n.str;
if (nm.len > 0) {
@@ -165,19 +165,19 @@ fn resolvewalk(c: *checker, n: *node) void = {
return;
};
if (k == N_DOT) {
if (k == nkind.N_DOT) {
// Walk only the base; the .field name is a member, not a
// free identifier.
if (n.lhs != nil) { resolvewalk(c, n.lhs); };
return;
};
if (k == N_FIELD) {
if (k == nkind.N_FIELD) {
if (n.lhs != nil) { resolvewalk(c, n.lhs); };
return;
};
if (k == N_TFIELD) {
if (k == nkind.N_TFIELD) {
if (n.lhs != nil) { resolvewalk(c, n.lhs); };
return;
};
@@ -201,7 +201,7 @@ fn resolvewalk(c: *checker, n: *node) void = {
// `X` so subsequent statements can resolve it. Top-level lets
// are installed in installdecl, so this duplicate install at
// the file scope just no-ops (scopedefine returns nil on dup).
if (k == N_LET) {
if (k == nkind.N_LET) {
let nm: str = n.str;
if (nm.len > 0) {
scopedefine(c.cur, nm, skind.SK_VAR, nil, n);
@@ -217,21 +217,21 @@ fn resolvewalk(c: *checker, n: *node) void = {
// needs to enforce: tagged-union exhaustiveness, ? subset
// propagation, and !-flag semantics.
// unwrapbang — strip an N_TBANG wrapper; leaves other nodes alone.
// unwrapbang — strip an nkind.N_TBANG wrapper; leaves other nodes alone.
fn unwrapbang(n: *node) *node = {
if (n == nil) { return nil; };
if (n.kind == N_TBANG) { return n.lhs; };
if (n.kind == nkind.N_TBANG) { return n.lhs; };
return n;
};
// resolvealias — if n is an N_TNAME pointing at a typedecl, return
// resolvealias — if n is an nkind.N_TNAME pointing at a typedecl, return
// the typedecl's body (possibly recursively). Pass-through for any
// other node. The chain stops once we hit a non-N_TNAME node or a
// other node. The chain stops once we hit a non-nkind.N_TNAME node or a
// name we can't resolve.
fn resolvealias(c: *checker, n: *node) *node = {
let cur: *node = n;
for (cur != nil) {
if (cur.kind != N_TNAME) { return cur; };
if (cur.kind != nkind.N_TNAME) { return cur; };
let s: *sym = scopelookup(c.cur, cur.str);
if (s == nil) { return cur; };
if (s.skind != skind.SK_TYPE) { return cur; };
@@ -254,10 +254,10 @@ fn typeeqast(a: *node, b: *node) bool = {
if (bb == nil) { return false; };
if (aa.kind != bb.kind) { return false; };
let k: i32 = aa.kind;
if (k == N_TNAME) { return streq(aa.str, bb.str); };
if (k == N_TPTR) { return typeeqast(aa.lhs, bb.lhs); };
if (k == N_TSLICE){ return typeeqast(aa.lhs, bb.lhs); };
if (k == N_TCHAN) { return typeeqast(aa.lhs, bb.lhs); };
if (k == nkind.N_TNAME) { return streq(aa.str, bb.str); };
if (k == nkind.N_TPTR) { return typeeqast(aa.lhs, bb.lhs); };
if (k == nkind.N_TSLICE){ return typeeqast(aa.lhs, bb.lhs); };
if (k == nkind.N_TCHAN) { return typeeqast(aa.lhs, bb.lhs); };
// Conservative: anything else (struct/fn/tagged/tuple/array)
// fails the cheap check. Selfhost code doesn't currently rely
// on equality at these shapes for the targeted checks.
@@ -265,18 +265,18 @@ fn typeeqast(a: *node, b: *node) bool = {
};
// varianterr — does this variant carry the `!` mark? Either
// the variant itself is N_TBANG or it's an alias whose typedecl
// the variant itself is nkind.N_TBANG or it's an alias whose typedecl
// body is `!T`. Mirrors C check.c's iserror-after-NAMED rule.
fn varianterr(c: *checker, v: *node) bool = {
if (v == nil) { return false; };
if (v.kind == N_TBANG) { return true; };
if (v.kind == N_TNAME) {
if (v.kind == nkind.N_TBANG) { return true; };
if (v.kind == nkind.N_TNAME) {
let s: *sym = scopelookup(c.cur, v.str);
if (s != nil) {
if (s.skind == skind.SK_TYPE) {
if (s.decl != nil) {
if (s.decl.lhs != nil) {
if (s.decl.lhs.kind == N_TBANG) {
if (s.decl.lhs.kind == nkind.N_TBANG) {
return true;
};
};
@@ -288,7 +288,7 @@ fn varianterr(c: *checker, v: *node) bool = {
};
// taggedhaserr — true iff any variant of `n` (assumed
// N_TTAGGED) is `!`-marked. Picks the explicit-flag semantics over
// nkind.N_TTAGGED) is `!`-marked. Picks the explicit-flag semantics over
// the legacy "first variant = success" rule.
fn taggedhaserr(c: *checker, n: *node) bool = {
let v: *node = n.list;
@@ -312,26 +312,26 @@ fn iserrvariant(c: *checker, tagged: *node, v: *node) bool = {
};
// scruttype — resolve the type expression for a match's
// scrutinee. Handles N_IDENT (look up local/param's declared
// type) and N_DOT (struct-field access). Returns nil if we
// scrutinee. Handles nkind.N_IDENT (look up local/param's declared
// type) and nkind.N_DOT (struct-field access). Returns nil if we
// can't statically determine the type. Used by exhaustiveness.
fn scruttype(c: *checker, e: *node) *node = {
if (e == nil) { return nil; };
if (e.kind == N_IDENT) {
if (e.kind == nkind.N_IDENT) {
let s: *sym = scopelookup(c.cur, e.str);
if (s == nil) { return nil; };
if (s.decl == nil) { return nil; };
// For N_LET / N_PARAM: declared type is decl.lhs.
// For nkind.N_LET / nkind.N_PARAM: declared type is decl.lhs.
return s.decl.lhs;
};
return nil;
};
// mktname — fabricate an N_TNAME node with str = `nm`. Used by
// mktname — fabricate an nkind.N_TNAME node with str = `nm`. Used by
// exprtype to return primitive type nodes for literal
// expressions. The arena keeps them around as long as the checker.
fn mktname(c: *checker, nm: str) *node = {
let n: *node = newnode(c.a, N_TNAME, "", 0, 0);
let n: *node = newnode(c.a, nkind.N_TNAME, "", 0, 0);
n.str = nm;
return n;
};
@@ -343,31 +343,31 @@ fn mktname(c: *checker, nm: str) *node = {
fn exprtype(c: *checker, e: *node) *node = {
if (e == nil) { return nil; };
let k: i32 = e.kind;
if (k == N_INTLIT) { return mktname(c, "untyped_int"); };
if (k == N_FLOATLIT) { return mktname(c, "untyped_float"); };
if (k == N_STRLIT) { return mktname(c, "str"); };
if (k == N_RUNELIT) { return mktname(c, "rune"); };
if (k == N_TRUE) { return mktname(c, "bool"); };
if (k == N_FALSE) { return mktname(c, "bool"); };
if (k == N_VOIDLIT) { return mktname(c, "void"); };
if (k == N_NIL) { return mktname(c, "untyped_nil"); };
if (k == N_IDENT) {
if (k == nkind.N_INTLIT) { return mktname(c, "untyped_int"); };
if (k == nkind.N_FLOATLIT) { return mktname(c, "untyped_float"); };
if (k == nkind.N_STRLIT) { return mktname(c, "str"); };
if (k == nkind.N_RUNELIT) { return mktname(c, "rune"); };
if (k == nkind.N_TRUE) { return mktname(c, "bool"); };
if (k == nkind.N_FALSE) { return mktname(c, "bool"); };
if (k == nkind.N_VOIDLIT) { return mktname(c, "void"); };
if (k == nkind.N_NIL) { return mktname(c, "untyped_nil"); };
if (k == nkind.N_IDENT) {
let s: *sym = scopelookup(c.cur, e.str);
if (s == nil) { return nil; };
if (s.decl == nil) { return nil; };
return s.decl.lhs;
};
if (k == N_CAST) {
if (k == nkind.N_CAST) {
// `expr: T` — explicit cast; the type expr is e.rhs.
return e.rhs;
};
if (k == N_CALL) {
if (k == nkind.N_CALL) {
let callee: *node = e.lhs;
if (callee == nil) { return nil; };
let nm: str;
nm.ptr = nil; nm.len = 0;
if (callee.kind == N_IDENT) { nm = callee.str; };
if (callee.kind == N_DOT) { nm = callee.str; };
if (callee.kind == nkind.N_IDENT) { nm = callee.str; };
if (callee.kind == nkind.N_DOT) { nm = callee.str; };
if (nm.len == 0) { return nil; };
let s: *sym = scopelookup(c.cur, nm);
if (s == nil) { return nil; };
@@ -375,13 +375,13 @@ fn exprtype(c: *checker, e: *node) *node = {
if (s.decl == nil) { return nil; };
return s.decl.lhs; // fn-decl's lhs is the return type
};
if (k == N_TRYPROP) {
if (k == nkind.N_TRYPROP) {
// success unwrap: the success-variant type of operand's
// tagged union.
let opt: *node = exprtype(c, e.lhs);
let ou: *node = resolvealias(c, unwrapbang(opt));
if (ou == nil) { return nil; };
if (ou.kind != N_TTAGGED) { return nil; };
if (ou.kind != nkind.N_TTAGGED) { return nil; };
// Hare semantics: success = first non-error variant if
// any !-flag is present; else first variant.
if (taggedhaserr(c, ou)) {
@@ -394,11 +394,11 @@ fn exprtype(c: *checker, e: *node) *node = {
};
return ou.list;
};
if (k == N_TYPEASSERT) {
if (k == nkind.N_TYPEASSERT) {
// `e as T` → T
return e.rhs;
};
if (k == N_TYPETEST) {
if (k == nkind.N_TYPETEST) {
// `e is T` → bool
return mktname(c, "bool");
};
@@ -410,25 +410,25 @@ fn exprtype(c: *checker, e: *node) *node = {
// through without needing real type inference.
fn isuntypedint(t: *node) bool = {
if (t == nil) { return false; };
if (t.kind != N_TNAME) { return false; };
if (t.kind != nkind.N_TNAME) { return false; };
return streq(t.str, "untyped_int");
};
fn isuntypedfloat(t: *node) bool = {
if (t == nil) { return false; };
if (t.kind != N_TNAME) { return false; };
if (t.kind != nkind.N_TNAME) { return false; };
return streq(t.str, "untyped_float");
};
fn isuntypednil(t: *node) bool = {
if (t == nil) { return false; };
if (t.kind != N_TNAME) { return false; };
if (t.kind != nkind.N_TNAME) { return false; };
return streq(t.str, "untyped_nil");
};
fn isnumerictname(t: *node) bool = {
if (t == nil) { return false; };
if (t.kind != N_TNAME) { return false; };
if (t.kind != nkind.N_TNAME) { return false; };
let s: str = t.str;
if (streq(s, "i8")) { return true; };
if (streq(s, "i16")) { return true; };
@@ -449,7 +449,7 @@ fn isnumerictname(t: *node) bool = {
fn isstrtname(t: *node) bool = {
if (t == nil) { return false; };
if (t.kind != N_TNAME) { return false; };
if (t.kind != nkind.N_TNAME) { return false; };
return streq(t.str, "str");
};
@@ -474,7 +474,7 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = {
if (isuntypedint(su)) {
if (isnumerictname(du)) { return true; };
// (T | ...) tagged: only OK if some variant accepts untyped_int.
if (du.kind == N_TTAGGED) {
if (du.kind == nkind.N_TTAGGED) {
let v: *node = du.list;
for (v != nil) {
let vu: *node = resolvealias(c, unwrapbang(v));
@@ -487,7 +487,7 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = {
return true;
};
// Known non-numeric primitive: confidently wrong.
if (du.kind == N_TNAME) {
if (du.kind == nkind.N_TNAME) {
if (streq(du.str, "bool")) { return false; };
if (streq(du.str, "void")) { return false; };
if (streq(du.str, "str")) { return false; };
@@ -498,7 +498,7 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = {
};
if (isuntypedfloat(su)) {
if (isnumerictname(du)) { return true; };
if (du.kind == N_TNAME) {
if (du.kind == nkind.N_TNAME) {
if (streq(du.str, "bool")) { return false; };
if (streq(du.str, "void")) { return false; };
if (streq(du.str, "str")) { return false; };
@@ -508,17 +508,17 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = {
};
if (isuntypednil(su)) {
// nil → ptr/slice/chan/fn/nullable
if (du.kind == N_TPTR) { return true; };
if (du.kind == N_TSLICE) { return true; };
if (du.kind == N_TCHAN) { return true; };
if (du.kind == N_TFN) { return true; };
if (du.kind == nkind.N_TPTR) { return true; };
if (du.kind == nkind.N_TSLICE) { return true; };
if (du.kind == nkind.N_TCHAN) { return true; };
if (du.kind == nkind.N_TFN) { return true; };
// nullable `(*T | void)` — already accepted by typeeqast
// when matched whole; nil is OK there too.
if (du.kind == N_TTAGGED) {
if (du.kind == nkind.N_TTAGGED) {
let v: *node = du.list;
for (v != nil) {
if (v.kind == N_TPTR) { return true; };
if (v.kind == N_TSLICE){ return true; };
if (v.kind == nkind.N_TPTR) { return true; };
if (v.kind == nkind.N_TSLICE){ return true; };
v = v.next;
};
};
@@ -526,7 +526,7 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = {
return true;
};
// Tagged-union variant inclusion: src is one of dst's variants.
if (du.kind == N_TTAGGED && su.kind != N_TTAGGED) {
if (du.kind == nkind.N_TTAGGED && su.kind != nkind.N_TTAGGED) {
let v: *node = du.list;
for (v != nil) {
let vu: *node = resolvealias(c, unwrapbang(v));
@@ -541,13 +541,13 @@ fn isassignable(c: *checker, dst: *node, src: *node, confident: *bool) bool = {
// (don't be confident) — common when forwarding a fallible
// return through another fn with the same shape but possibly
// a different surface spelling.
if (du.kind == N_TTAGGED && su.kind == N_TTAGGED) {
if (du.kind == nkind.N_TTAGGED && su.kind == nkind.N_TTAGGED) {
*confident = false;
return true;
};
// Two known primitives with different names are confidently
// incompatible. `i32 ↔ bool`, `str ↔ i32`, etc.
if (du.kind == N_TNAME && su.kind == N_TNAME) {
if (du.kind == nkind.N_TNAME && su.kind == nkind.N_TNAME) {
let known_d: bool = isnumerictname(du) || isstrtname(du);
if (!known_d) { if (streq(du.str, "bool")) { known_d = true; }; };
if (!known_d) { if (streq(du.str, "void")) { known_d = true; }; };
@@ -587,7 +587,7 @@ fn casecovers(c: *checker, cs: *node, want: *node) bool = {
fn errmatchvariant(c: *checker, n: *node, vname: *node) void = {
os.write(2, "match: variant not handled".ptr, 26u64);
if (vname != nil) {
if (vname.kind == N_TNAME) {
if (vname.kind == nkind.N_TNAME) {
os.write(2, " (".ptr, 2u64);
os.write(2, vname.str.ptr, vname.str.len: u64);
os.write(2, ")".ptr, 1u64);
@@ -612,7 +612,7 @@ fn casevariantin(tagged: *node, pat: *node) bool = {
fn errbadcase(c: *checker, pat: *node) void = {
os.write(2, "case: not a variant of scrutinee".ptr, 32u64);
if (pat != nil) {
if (pat.kind == N_TNAME) {
if (pat.kind == nkind.N_TNAME) {
os.write(2, " (".ptr, 2u64);
os.write(2, pat.str.ptr, pat.str.len: u64);
os.write(2, ")".ptr, 1u64);
@@ -628,7 +628,7 @@ fn checkmatchexhaust(c: *checker, n: *node) void = {
let st: *node = scruttype(c, n.lhs);
let u: *node = resolvealias(c, unwrapbang(st));
if (u == nil) { return; };
if (u.kind != N_TTAGGED) { return; };
if (u.kind != nkind.N_TTAGGED) { return; };
// Validity: every `case T` pattern (and multi-pattern alts)
// must name a variant of u. Catches typos and dead arms that
// the dispatch would never reach.
@@ -684,12 +684,12 @@ fn errnotassign(c: *checker, dst: *node, src: *node, where: str) void = {
os.write(2, where.ptr, where.len: u64);
os.write(2, ": not assignable".ptr, 16u64);
if (src != nil) {
if (src.kind == N_TNAME) {
if (src.kind == nkind.N_TNAME) {
os.write(2, " (".ptr, 2u64);
os.write(2, src.str.ptr, src.str.len: u64);
os.write(2, " → ".ptr, 5u64);
if (dst != nil) {
if (dst.kind == N_TNAME) {
if (dst.kind == nkind.N_TNAME) {
os.write(2, dst.str.ptr, dst.str.len: u64);
};
};
@@ -741,7 +741,7 @@ fn checkisas(c: *checker, n: *node) void = {
let st: *node = scruttype(c, n.lhs);
let u: *node = resolvealias(c, unwrapbang(st));
if (u == nil) { return; };
if (u.kind != N_TTAGGED) {
if (u.kind != nkind.N_TTAGGED) {
os.write(2, "is/as: operand is not a tagged union\n".ptr, 37u64);
c.errs += 1;
return;
@@ -750,7 +750,7 @@ fn checkisas(c: *checker, n: *node) void = {
if (want == nil) { return; };
if (!casevariantin(u, want)) {
os.write(2, "is/as: not a variant of operand".ptr, 31u64);
if (want.kind == N_TNAME) {
if (want.kind == nkind.N_TNAME) {
os.write(2, " (".ptr, 2u64);
os.write(2, want.str.ptr, want.str.len: u64);
os.write(2, ")".ptr, 1u64);
@@ -764,26 +764,26 @@ fn checkisas(c: *checker, n: *node) void = {
//
// For `expr?`, the operand's error subset must be a subset of the
// enclosing fn's return-type variants. Mirrors C check.c. Operand
// is N_TRYPROP; its lhs is the value-bearing expr; we look at the
// expr's *declared* type for N_IDENT/N_CALL cases.
// is nkind.N_TRYPROP; its lhs is the value-bearing expr; we look at the
// expr's *declared* type for nkind.N_IDENT/nkind.N_CALL cases.
fn exprtypeoftry(c: *checker, e: *node) *node = {
if (e == nil) { return nil; };
if (e.kind == N_IDENT) {
if (e.kind == nkind.N_IDENT) {
let s: *sym = scopelookup(c.cur, e.str);
if (s == nil) { return nil; };
if (s.decl == nil) { return nil; };
return s.decl.lhs;
};
if (e.kind == N_CALL) {
// callee return type lookup: callee is e.lhs (N_IDENT or
// N_DOT). We need the fn-decl's lhs (return-type AST).
if (e.kind == nkind.N_CALL) {
// callee return type lookup: callee is e.lhs (nkind.N_IDENT or
// nkind.N_DOT). We need the fn-decl's lhs (return-type AST).
let callee: *node = e.lhs;
if (callee == nil) { return nil; };
let nm: str;
nm.ptr = nil; nm.len = 0;
if (callee.kind == N_IDENT) { nm = callee.str; };
if (callee.kind == N_DOT) { nm = callee.str; };
if (callee.kind == nkind.N_IDENT) { nm = callee.str; };
if (callee.kind == nkind.N_DOT) { nm = callee.str; };
if (nm.len == 0) { return nil; };
let s: *sym = scopelookup(c.cur, nm);
if (s == nil) { return nil; };
@@ -799,7 +799,7 @@ fn checktryprop(c: *checker, n: *node) void = {
let t: *node = exprtypeoftry(c, n.lhs);
let u: *node = resolvealias(c, unwrapbang(t));
if (u == nil) { return; };
if (u.kind != N_TTAGGED) { return; };
if (u.kind != nkind.N_TTAGGED) { return; };
// Does the operand have any error variants?
let haserr: bool = false;
let v: *node = u.list;
@@ -816,7 +816,7 @@ fn checktryprop(c: *checker, n: *node) void = {
c.errs += 1;
return;
};
if (r.kind != N_TTAGGED) {
if (r.kind != nkind.N_TTAGGED) {
os.write(2, "?: enclosing fn return is not tagged\n".ptr, 37u64);
c.errs += 1;
return;
@@ -846,7 +846,7 @@ fn checktryprop(c: *checker, n: *node) void = {
fn installparams(c: *checker, params: *node) void = {
let p: *node = params;
for (p != nil) {
if (p.kind == N_PARAM) {
if (p.kind == nkind.N_PARAM) {
let nm: str = p.str;
if (nm.len > 0) {
scopedefine(c.cur, nm, skind.SK_PARAM, nil, p);
@@ -888,7 +888,7 @@ export fn checkinit(c: *checker, a: *arena, tc: *tctx) void = {
export fn checkfile(c: *checker, file: *node) void = {
if (file == nil) { return; };
if (file.kind != N_FILE) { return; };
if (file.kind != nkind.N_FILE) { return; };
// Pass 1: install all top-level names.
let d: *node = file.list;
@@ -901,15 +901,15 @@ export fn checkfile(c: *checker, file: *node) void = {
d = file.list;
for (d != nil) {
let k: i32 = d.kind;
if (k == N_FNDECL) {
if (k == nkind.N_FNDECL) {
if (d.lhs != nil) { resolvewalk(c, d.lhs); }; // return type
resolvefnbody(c, d);
} else { if (k == N_DEF) {
} else { if (k == nkind.N_DEF) {
if (d.lhs != nil) { resolvewalk(c, d.lhs); };
if (d.rhs != nil) { resolvewalk(c, d.rhs); };
} else { if (k == N_TYPEDECL) {
} else { if (k == nkind.N_TYPEDECL) {
if (d.lhs != nil) { resolvewalk(c, d.lhs); };
} else { if (k == N_LET) {
} else { if (k == nkind.N_LET) {
if (d.lhs != nil) { resolvewalk(c, d.lhs); };
if (d.rhs != nil) { resolvewalk(c, d.rhs); };
};};};};