selfhost/cmd/wcc: drop snake_case from 119 cross-cutting identifiers

This commit is contained in:
2026-05-11 14:37:45 +09:00
parent fce0a54d62
commit 6204c4cd27
12 changed files with 3770 additions and 3770 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@
//
// The cgen routines in selfhost/cmd/wcc/cgen.ww write directly to
// fd 1 via os.write(1, ...). For -o, we open the output file and
// dup2 it onto fd 1 before invoking cg_file. This is the same trick
// dup2 it onto fd 1 before invoking cgfile. This is the same trick
// the bootstrap uses with shell redirection, just in-process.
use os;
@@ -123,8 +123,8 @@ export fn main(argc: i32, argv: **u8) i32 = {
let f: *node = parsefile(&ps);
let cg: cgen;
cgen_init(&cg, ar);
cg_file(&cg, f);
cgeninit(&cg, ar);
cgfile(&cg, f);
if (l.errs > 0) { return 1; };
return 0;

File diff suppressed because it is too large Load Diff

View File

@@ -32,56 +32,56 @@ type checker = struct {
verbose: i32, // when non-zero, log each unresolved name
};
// seed_primitives — install the built-in type names so `i32`, `str`,
// seedprimitives — install the built-in type names so `i32`, `str`,
// etc. can be looked up like ordinary symbols.
fn seed_primitives(c: *checker) void = {
scope_define(c.top, "void", SK_TYPE, c.tc.ty_void, nil);
scope_define(c.top, "bool", SK_TYPE, c.tc.ty_bool, nil);
scope_define(c.top, "rune", SK_TYPE, c.tc.ty_rune, nil);
scope_define(c.top, "i8", SK_TYPE, c.tc.ty_i8, nil);
scope_define(c.top, "i16", SK_TYPE, c.tc.ty_i16, nil);
scope_define(c.top, "i32", SK_TYPE, c.tc.ty_i32, nil);
scope_define(c.top, "i64", SK_TYPE, c.tc.ty_i64, nil);
scope_define(c.top, "u8", SK_TYPE, c.tc.ty_u8, nil);
scope_define(c.top, "u16", SK_TYPE, c.tc.ty_u16, nil);
scope_define(c.top, "u32", SK_TYPE, c.tc.ty_u32, nil);
scope_define(c.top, "u64", SK_TYPE, c.tc.ty_u64, nil);
scope_define(c.top, "int", SK_TYPE, c.tc.ty_int, nil);
scope_define(c.top, "uint", SK_TYPE, c.tc.ty_uint, nil);
scope_define(c.top, "uintptr", SK_TYPE, c.tc.ty_uintptr, nil);
scope_define(c.top, "f32", SK_TYPE, c.tc.ty_f32, nil);
scope_define(c.top, "f64", SK_TYPE, c.tc.ty_f64, nil);
scope_define(c.top, "str", SK_TYPE, c.tc.ty_str, nil);
fn seedprimitives(c: *checker) void = {
scopedefine(c.top, "void", SK_TYPE, c.tc.ty_void, nil);
scopedefine(c.top, "bool", SK_TYPE, c.tc.ty_bool, nil);
scopedefine(c.top, "rune", SK_TYPE, c.tc.ty_rune, nil);
scopedefine(c.top, "i8", SK_TYPE, c.tc.ty_i8, nil);
scopedefine(c.top, "i16", SK_TYPE, c.tc.ty_i16, nil);
scopedefine(c.top, "i32", SK_TYPE, c.tc.ty_i32, nil);
scopedefine(c.top, "i64", SK_TYPE, c.tc.ty_i64, nil);
scopedefine(c.top, "u8", SK_TYPE, c.tc.ty_u8, nil);
scopedefine(c.top, "u16", SK_TYPE, c.tc.ty_u16, nil);
scopedefine(c.top, "u32", SK_TYPE, c.tc.ty_u32, nil);
scopedefine(c.top, "u64", SK_TYPE, c.tc.ty_u64, nil);
scopedefine(c.top, "int", SK_TYPE, c.tc.ty_int, nil);
scopedefine(c.top, "uint", SK_TYPE, c.tc.ty_uint, nil);
scopedefine(c.top, "uintptr", SK_TYPE, c.tc.ty_uintptr, nil);
scopedefine(c.top, "f32", SK_TYPE, c.tc.ty_f32, nil);
scopedefine(c.top, "f64", SK_TYPE, c.tc.ty_f64, nil);
scopedefine(c.top, "str", SK_TYPE, c.tc.ty_str, nil);
// `nil`, `true`, `false` are keywords — handled at the lex/parser
// level, no symbol needed.
// `len`, `alloc`, `free` are pseudo-builtins; scope_define them so
// `len`, `alloc`, `free` are pseudo-builtins; scopedefine them so
// their use sites resolve. The actual semantics live in cgen.
scope_define(c.top, "len", SK_FN, nil, nil);
scope_define(c.top, "alloc", SK_FN, nil, nil);
scope_define(c.top, "free", SK_FN, nil, nil);
scopedefine(c.top, "len", SK_FN, nil, nil);
scopedefine(c.top, "alloc", SK_FN, nil, nil);
scopedefine(c.top, "free", SK_FN, nil, nil);
};
// install_decl — install the top-level decl's name into the top scope.
// installdecl — install the top-level decl's name into the top scope.
// We don't compute its type yet (that's the resolve pass) — just bind
// the name so forward references resolve.
fn install_decl(c: *checker, d: *node) void = {
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) { scope_define(c.top, nm, SK_USE, nil, d); return; };
if (k == N_DEF) { scope_define(c.top, nm, SK_DEF, nil, d); return; };
if (k == N_TYPEDECL) { scope_define(c.top, nm, SK_TYPE, nil, d); return; };
if (k == N_FNDECL) { scope_define(c.top, nm, SK_FN, nil, d); return; };
if (k == N_LET) { scope_define(c.top, nm, SK_VAR, nil, d); return; };
if (k == N_USE) { scopedefine(c.top, nm, SK_USE, nil, d); return; };
if (k == N_DEF) { scopedefine(c.top, nm, SK_DEF, nil, d); return; };
if (k == N_TYPEDECL) { scopedefine(c.top, nm, SK_TYPE, nil, d); return; };
if (k == N_FNDECL) { scopedefine(c.top, nm, SK_FN, nil, d); return; };
if (k == N_LET) { scopedefine(c.top, nm, SK_VAR, nil, d); return; };
};
// resolve_walk — recursive AST walk that, for every N_IDENT and
// resolvewalk — recursive AST walk that, for every N_IDENT and
// 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
// the C checker's collect-then-resolve flow within a function).
fn resolve_walk(c: *checker, n: *node) void = {
fn resolvewalk(c: *checker, n: *node) void = {
if (n == nil) { return; };
let k: i32 = n.kind;
@@ -91,7 +91,7 @@ fn resolve_walk(c: *checker, n: *node) void = {
if (k == N_IDENT) {
let nm: str = n.str;
if (nm.len > 0) {
let s: *sym = scope_lookup(c.cur, nm);
let s: *sym = scopelookup(c.cur, nm);
if (s == nil) {
c.nunresolved += 1;
if (c.verbose != 0) {
@@ -106,7 +106,7 @@ fn resolve_walk(c: *checker, n: *node) void = {
if (k == N_TNAME) {
let nm: str = n.str;
if (nm.len > 0) {
let s: *sym = scope_lookup(c.cur, nm);
let s: *sym = scopelookup(c.cur, nm);
if (s == nil) {
c.nunresolved += 1;
if (c.verbose != 0) {
@@ -121,89 +121,89 @@ fn resolve_walk(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 (n.lhs != nil) { resolve_walk(c, n.lhs); };
if (n.lhs != nil) { resolvewalk(c, n.lhs); };
let nm: str = n.str;
if (nm.len > 0) {
scope_define(c.cur, nm, SK_VAR, nil, n);
scopedefine(c.cur, nm, SK_VAR, nil, n);
};
if (n.body != nil) { resolve_walk(c, n.body); };
if (n.body != nil) { resolvewalk(c, n.body); };
return;
};
if (k == N_DOT) {
// Walk only the base; the .field name is a member, not a
// free identifier.
if (n.lhs != nil) { resolve_walk(c, n.lhs); };
if (n.lhs != nil) { resolvewalk(c, n.lhs); };
return;
};
if (k == N_FIELD) {
if (n.lhs != nil) { resolve_walk(c, n.lhs); };
if (n.lhs != nil) { resolvewalk(c, n.lhs); };
return;
};
if (k == N_TFIELD) {
if (n.lhs != nil) { resolve_walk(c, n.lhs); };
if (n.lhs != nil) { resolvewalk(c, n.lhs); };
return;
};
// Walk children (mirroring ast.ww's printer descent order).
if (n.attr != nil) { resolve_walk(c, n.attr); };
if (n.lhs != nil) { resolve_walk(c, n.lhs); };
if (n.rhs != nil) { resolve_walk(c, n.rhs); };
if (n.cond != nil) { resolve_walk(c, n.cond); };
if (n.body != nil) { resolve_walk(c, n.body); };
if (n.els != nil) { resolve_walk(c, n.els); };
if (n.attr != nil) { resolvewalk(c, n.attr); };
if (n.lhs != nil) { resolvewalk(c, n.lhs); };
if (n.rhs != nil) { resolvewalk(c, n.rhs); };
if (n.cond != nil) { resolvewalk(c, n.cond); };
if (n.body != nil) { resolvewalk(c, n.body); };
if (n.els != nil) { resolvewalk(c, n.els); };
if (n.list != nil) {
let m: *node = n.list;
for (m != nil) {
resolve_walk(c, m);
resolvewalk(c, m);
m = m.next;
};
};
// After walking children: a local `let X: T = init;` registers
// `X` so subsequent statements can resolve it. Top-level lets
// are installed in install_decl, so this duplicate install at
// the file scope just no-ops (scope_define returns nil on dup).
// are installed in installdecl, so this duplicate install at
// the file scope just no-ops (scopedefine returns nil on dup).
if (k == N_LET) {
let nm: str = n.str;
if (nm.len > 0) {
scope_define(c.cur, nm, SK_VAR, nil, n);
scopedefine(c.cur, nm, SK_VAR, nil, n);
};
};
};
// install_param — when entering a fn body, define its params in a
// fresh local scope.
fn install_params(c: *checker, params: *node) void = {
fn installparams(c: *checker, params: *node) void = {
let p: *node = params;
for (p != nil) {
if (p.kind == N_PARAM) {
let nm: str = p.str;
if (nm.len > 0) {
scope_define(c.cur, nm, SK_PARAM, nil, p);
scopedefine(c.cur, nm, SK_PARAM, nil, p);
};
};
p = p.next;
};
};
// resolve_fnbody — open a child scope for the fn, install its params,
// resolvefnbody — open a child scope for the fn, install its params,
// then walk the body. Local lets installed by walk_stmt (a future
// extension); for the current pass we just resolve-walk without
// per-statement scopes.
fn resolve_fnbody(c: *checker, fnnode: *node) void = {
fn resolvefnbody(c: *checker, fnnode: *node) void = {
let outer: *scope = c.cur;
c.cur = newscope(c.a, c.cur);
install_params(c, fnnode.list);
installparams(c, fnnode.list);
if (fnnode.body != nil) {
resolve_walk(c, fnnode.body);
resolvewalk(c, fnnode.body);
};
c.cur = outer;
};
export fn check_init(c: *checker, a: *arena, tc: *tctx) void = {
export fn checkinit(c: *checker, a: *arena, tc: *tctx) void = {
c.a = a;
c.tc = tc;
c.top = newscope(a, nil);
@@ -212,17 +212,17 @@ export fn check_init(c: *checker, a: *arena, tc: *tctx) void = {
c.nunresolved = 0;
c.errs = 0;
c.verbose = 0;
seed_primitives(c);
seedprimitives(c);
};
export fn check_file(c: *checker, file: *node) void = {
export fn checkfile(c: *checker, file: *node) void = {
if (file == nil) { return; };
if (file.kind != N_FILE) { return; };
// Pass 1: install all top-level names.
let d: *node = file.list;
for (d != nil) {
install_decl(c, d);
installdecl(c, d);
d = d.next;
};
@@ -231,16 +231,16 @@ export fn check_file(c: *checker, file: *node) void = {
for (d != nil) {
let k: i32 = d.kind;
if (k == N_FNDECL) {
if (d.lhs != nil) { resolve_walk(c, d.lhs); }; // return type
resolve_fnbody(c, d);
if (d.lhs != nil) { resolvewalk(c, d.lhs); }; // return type
resolvefnbody(c, d);
} else { if (k == N_DEF) {
if (d.lhs != nil) { resolve_walk(c, d.lhs); };
if (d.rhs != nil) { resolve_walk(c, d.rhs); };
if (d.lhs != nil) { resolvewalk(c, d.lhs); };
if (d.rhs != nil) { resolvewalk(c, d.rhs); };
} else { if (k == N_TYPEDECL) {
if (d.lhs != nil) { resolve_walk(c, d.lhs); };
if (d.lhs != nil) { resolvewalk(c, d.lhs); };
} else { if (k == N_LET) {
if (d.lhs != nil) { resolve_walk(c, d.lhs); };
if (d.rhs != nil) { resolve_walk(c, d.rhs); };
if (d.lhs != nil) { resolvewalk(c, d.lhs); };
if (d.rhs != nil) { resolvewalk(c, d.rhs); };
};};};};
d = d.next;
};

View File

@@ -64,14 +64,14 @@ fn lget(l: *lex) i32 = {
return c;
};
fn cur_pos(l: *lex, out: *pos) void = {
fn curpos(l: *lex, out: *pos) void = {
out.file = l.file;
out.line = l.line;
out.col = l.col;
};
// putuint — write `v` (signed, but always non-negative here) to fd 2
// in decimal. Standalone so err_at doesn't drag in fmt and create a
// in decimal. Standalone so errat doesn't drag in fmt and create a
// dependency cycle with strconv.
fn putuint(fd: i32, v: i32) void = {
let tmp: [16]u8;
@@ -89,7 +89,7 @@ fn putuint(fd: i32, v: i32) void = {
os.write(fd, buf.ptr, m: u64);
};
fn err_at(l: *lex, p: *pos, msg: str) void = {
fn errat(l: *lex, p: *pos, msg: str) void = {
let pf: str = p.file;
os.write(2, pf.ptr, pf.len: u64);
os.write(2, ":".ptr, 1u64);
@@ -128,8 +128,8 @@ fn skipws(l: *lex) bool = {
let x: i32 = lget(l);
if (x < 0) {
let cp: pos;
cur_pos(l, &cp);
err_at(l, &cp, "unterminated /* comment");
curpos(l, &cp);
errat(l, &cp, "unterminated /* comment");
return false;
};
if (prev == 42) {
@@ -200,13 +200,13 @@ fn escape(l: *lex, out: *i32) bool = {
if (hi < 0) { return false; };
if (lo < 0) { return false; };
if (!ascii.ishex(hi: u8)) {
let cp: pos; cur_pos(l, &cp);
err_at(l, &cp, "bad \\x escape");
let cp: pos; curpos(l, &cp);
errat(l, &cp, "bad \\x escape");
return false;
};
if (!ascii.ishex(lo: u8)) {
let cp: pos; cur_pos(l, &cp);
err_at(l, &cp, "bad \\x escape");
let cp: pos; curpos(l, &cp);
errat(l, &cp, "bad \\x escape");
return false;
};
let h: i32 = ascii.digitval(hi: u8);
@@ -214,13 +214,13 @@ fn escape(l: *lex, out: *i32) bool = {
*out = (h << 4) | lv;
return true;
};
let cp: pos; cur_pos(l, &cp);
err_at(l, &cp, "bad escape");
let cp: pos; curpos(l, &cp);
errat(l, &cp, "bad escape");
return false;
};
// scan_decimal_run — consume a run of decimal digits and underscores.
fn scan_decimal_run(l: *lex) void = {
// scandecimalrun — consume a run of decimal digits and underscores.
fn scandecimalrun(l: *lex) void = {
for (true) {
let c: i32 = lpeek(l, 0u64);
if (c < 0) { break; };
@@ -231,7 +231,7 @@ fn scan_decimal_run(l: *lex) void = {
};
};
fn scan_hex_run(l: *lex) void = {
fn scanhexrun(l: *lex) void = {
for (true) {
let c: i32 = lpeek(l, 0u64);
if (c < 0) { break; };
@@ -242,7 +242,7 @@ fn scan_hex_run(l: *lex) void = {
};
};
fn scan_bin_run(l: *lex) void = {
fn scanbinrun(l: *lex) void = {
for (true) {
let c: i32 = lpeek(l, 0u64);
if (c == 48) { lget(l); continue; };
@@ -252,7 +252,7 @@ fn scan_bin_run(l: *lex) void = {
};
};
fn scan_oct_run(l: *lex) void = {
fn scanoctrun(l: *lex) void = {
for (true) {
let c: i32 = lpeek(l, 0u64);
if (c < 48) { break; };
@@ -263,8 +263,8 @@ fn scan_oct_run(l: *lex) void = {
};
};
// scan_exp — consume the [eE][+-]?[0-9]+ tail of a float, if present.
fn scan_exp(l: *lex) void = {
// scanexp — consume the [eE][+-]?[0-9]+ tail of a float, if present.
fn scanexp(l: *lex) void = {
let e: i32 = lpeek(l, 0u64);
if (e != 101) { if (e != 69) { return; }; }; // 'e' or 'E'
lget(l);
@@ -293,41 +293,41 @@ fn lexnum(l: *lex, start: *pos, out: *tok) void = {
if (c0 == 48) { // '0'
if (c1 == 120) { // 'x'
lget(l); lget(l); base = 16; scan_hex_run(l);
lget(l); lget(l); base = 16; scanhexrun(l);
} else { if (c1 == 88) { // 'X'
lget(l); lget(l); base = 16; scan_hex_run(l);
lget(l); lget(l); base = 16; scanhexrun(l);
} else { if (c1 == 98) { // 'b'
lget(l); lget(l); base = 2; scan_bin_run(l);
lget(l); lget(l); base = 2; scanbinrun(l);
} else { if (c1 == 66) { // 'B'
lget(l); lget(l); base = 2; scan_bin_run(l);
lget(l); lget(l); base = 2; scanbinrun(l);
} else { if (c1 == 111) { // 'o'
lget(l); lget(l); base = 8; scan_oct_run(l);
lget(l); lget(l); base = 8; scanoctrun(l);
} else { if (c1 == 79) { // 'O'
lget(l); lget(l); base = 8; scan_oct_run(l);
lget(l); lget(l); base = 8; scanoctrun(l);
} else {
scan_decimal_run(l);
scandecimalrun(l);
if (lpeek(l, 0u64) == 46) {
let after: i32 = lpeek(l, 1u64);
if (after >= 48) {
if (after <= 57) {
isfloat = true;
lget(l);
scan_decimal_run(l);
scan_exp(l);
scandecimalrun(l);
scanexp(l);
};
};
};
};};};};};};
} else {
scan_decimal_run(l);
scandecimalrun(l);
if (lpeek(l, 0u64) == 46) {
let after: i32 = lpeek(l, 1u64);
if (after >= 48) {
if (after <= 57) {
isfloat = true;
lget(l);
scan_decimal_run(l);
scan_exp(l);
scandecimalrun(l);
scanexp(l);
};
};
};
@@ -352,7 +352,7 @@ fn lexnum(l: *lex, start: *pos, out: *tok) void = {
let ok: bool = false;
out.uval = parseint(digs, dn, base, &ok);
if (!ok) {
err_at(l, start, "bad integer literal");
errat(l, start, "bad integer literal");
out.kind = TK_ERR;
};
};
@@ -432,7 +432,7 @@ fn lexstr(l: *lex, start: *pos, out: *tok) void = {
for (true) {
let c: i32 = lpeek(l, 0u64);
if (c < 0) {
err_at(l, start, "unterminated string");
errat(l, start, "unterminated string");
out.kind = TK_ERR;
out.file = start.file;
out.line = start.line;
@@ -477,7 +477,7 @@ fn lexstr(l: *lex, start: *pos, out: *tok) void = {
fn lexrune(l: *lex, start: *pos, out: *tok) void = {
let c: i32 = lpeek(l, 0u64);
if (c < 0) {
err_at(l, start, "unterminated rune");
errat(l, start, "unterminated rune");
out.kind = TK_ERR;
out.file = start.file;
out.line = start.line;
@@ -493,7 +493,7 @@ fn lexrune(l: *lex, start: *pos, out: *tok) void = {
ch = lget(l);
};
if (lpeek(l, 0u64) != 39) {
err_at(l, start, "rune literal missing closing '");
errat(l, start, "rune literal missing closing '");
out.kind = TK_ERR;
out.file = start.file;
out.line = start.line;
@@ -509,16 +509,16 @@ fn lexrune(l: *lex, start: *pos, out: *tok) void = {
out.uval = ch: u64;
};
fn emit_simple(start: *pos, k: i32, out: *tok) void = {
fn emitsimple(start: *pos, k: i32, out: *tok) void = {
out.kind = k;
out.file = start.file;
out.line = start.line;
out.col = start.col;
};
// set_pos_from — copy file/line/col from a *pos into a tok. Used by
// setposfrom — copy file/line/col from a *pos into a tok. Used by
// the err-token path where we already have a pos.
fn set_pos_from(out: *tok, p: *pos) void = {
fn setposfrom(out: *tok, p: *pos) void = {
out.file = p.file;
out.line = p.line;
out.col = p.col;
@@ -541,11 +541,11 @@ export fn lexnext(l: *lex, out: *tok) void = {
out.tsuffix = empty;
if (!skipws(l)) {
let p: pos; cur_pos(l, &p);
emit_simple(&p, TK_EOF, out);
let p: pos; curpos(l, &p);
emitsimple(&p, TK_EOF, out);
return;
};
let start: pos; cur_pos(l, &start);
let start: pos; curpos(l, &start);
let c: i32 = lpeek(l, 0u64);
if (c >= 0) {
@@ -558,98 +558,98 @@ export fn lexnext(l: *lex, out: *tok) void = {
lget(l);
if (c == 40) { emit_simple(&start, TK_LPAREN, out); return; };
if (c == 41) { emit_simple(&start, TK_RPAREN, out); return; };
if (c == 123) { emit_simple(&start, TK_LBRACE, out); return; };
if (c == 125) { emit_simple(&start, TK_RBRACE, out); return; };
if (c == 91) { emit_simple(&start, TK_LBRACK, out); return; };
if (c == 93) { emit_simple(&start, TK_RBRACK, out); return; };
if (c == 44) { emit_simple(&start, TK_COMMA, out); return; };
if (c == 59) { emit_simple(&start, TK_SEMI, out); return; };
if (c == 58) { emit_simple(&start, TK_COLON, out); return; };
if (c == 64) { emit_simple(&start, TK_AT, out); return; };
if (c == 63) { emit_simple(&start, TK_QUESTION, out); return; };
if (c == 126) { emit_simple(&start, TK_TILDE, out); return; };
if (c == 40) { emitsimple(&start, TK_LPAREN, out); return; };
if (c == 41) { emitsimple(&start, TK_RPAREN, out); return; };
if (c == 123) { emitsimple(&start, TK_LBRACE, out); return; };
if (c == 125) { emitsimple(&start, TK_RBRACE, out); return; };
if (c == 91) { emitsimple(&start, TK_LBRACK, out); return; };
if (c == 93) { emitsimple(&start, TK_RBRACK, out); return; };
if (c == 44) { emitsimple(&start, TK_COMMA, out); return; };
if (c == 59) { emitsimple(&start, TK_SEMI, out); return; };
if (c == 58) { emitsimple(&start, TK_COLON, out); return; };
if (c == 64) { emitsimple(&start, TK_AT, out); return; };
if (c == 63) { emitsimple(&start, TK_QUESTION, out); return; };
if (c == 126) { emitsimple(&start, TK_TILDE, out); return; };
if (c == 46) { // '.'
if (lpeek(l, 0u64) == 46) {
if (lpeek(l, 1u64) == 46) {
lget(l); lget(l);
emit_simple(&start, TK_ELLIPSIS, out); return;
emitsimple(&start, TK_ELLIPSIS, out); return;
};
lget(l);
emit_simple(&start, TK_DOTDOT, out); return;
emitsimple(&start, TK_DOTDOT, out); return;
};
emit_simple(&start, TK_DOT, out); return;
emitsimple(&start, TK_DOT, out); return;
};
if (c == 43) {
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_PLUSEQ, out); return; };
emit_simple(&start, TK_PLUS, out); return;
if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_PLUSEQ, out); return; };
emitsimple(&start, TK_PLUS, out); return;
};
if (c == 45) {
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_MINUSEQ, out); return; };
if (lpeek(l, 0u64) == 62) { lget(l); emit_simple(&start, TK_ARROW, out); return; };
emit_simple(&start, TK_MINUS, out); return;
if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_MINUSEQ, out); return; };
if (lpeek(l, 0u64) == 62) { lget(l); emitsimple(&start, TK_ARROW, out); return; };
emitsimple(&start, TK_MINUS, out); return;
};
if (c == 42) {
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_STAREQ, out); return; };
emit_simple(&start, TK_STAR, out); return;
if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_STAREQ, out); return; };
emitsimple(&start, TK_STAR, out); return;
};
if (c == 47) {
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_SLASHEQ, out); return; };
emit_simple(&start, TK_SLASH, out); return;
if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_SLASHEQ, out); return; };
emitsimple(&start, TK_SLASH, out); return;
};
if (c == 37) {
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_PERCENTEQ, out); return; };
emit_simple(&start, TK_PERCENT, out); return;
if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_PERCENTEQ, out); return; };
emitsimple(&start, TK_PERCENT, out); return;
};
if (c == 38) {
if (lpeek(l, 0u64) == 38) { lget(l); emit_simple(&start, TK_AND, out); return; };
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_AMPEQ, out); return; };
emit_simple(&start, TK_AMP, out); return;
if (lpeek(l, 0u64) == 38) { lget(l); emitsimple(&start, TK_AND, out); return; };
if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_AMPEQ, out); return; };
emitsimple(&start, TK_AMP, out); return;
};
if (c == 124) {
if (lpeek(l, 0u64) == 124) { lget(l); emit_simple(&start, TK_OR, out); return; };
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_PIPEEQ, out); return; };
emit_simple(&start, TK_PIPE, out); return;
if (lpeek(l, 0u64) == 124) { lget(l); emitsimple(&start, TK_OR, out); return; };
if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_PIPEEQ, out); return; };
emitsimple(&start, TK_PIPE, out); return;
};
if (c == 94) {
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_CARETEQ, out); return; };
emit_simple(&start, TK_CARET, out); return;
if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_CARETEQ, out); return; };
emitsimple(&start, TK_CARET, out); return;
};
if (c == 61) {
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_EQ, out); return; };
if (lpeek(l, 0u64) == 62) { lget(l); emit_simple(&start, TK_FATARROW, out); return; };
emit_simple(&start, TK_ASSIGN, out); return;
if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_EQ, out); return; };
if (lpeek(l, 0u64) == 62) { lget(l); emitsimple(&start, TK_FATARROW, out); return; };
emitsimple(&start, TK_ASSIGN, out); return;
};
if (c == 33) {
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_NEQ, out); return; };
emit_simple(&start, TK_NOT, out); return;
if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_NEQ, out); return; };
emitsimple(&start, TK_NOT, out); return;
};
if (c == 60) {
if (lpeek(l, 0u64) == 60) {
lget(l);
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_LSHIFTEQ, out); return; };
emit_simple(&start, TK_LSHIFT, out); return;
if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_LSHIFTEQ, out); return; };
emitsimple(&start, TK_LSHIFT, out); return;
};
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_LE, out); return; };
if (lpeek(l, 0u64) == 45) { lget(l); emit_simple(&start, TK_LARROW, out); return; };
emit_simple(&start, TK_LT, out); return;
if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_LE, out); return; };
if (lpeek(l, 0u64) == 45) { lget(l); emitsimple(&start, TK_LARROW, out); return; };
emitsimple(&start, TK_LT, out); return;
};
if (c == 62) {
if (lpeek(l, 0u64) == 62) {
lget(l);
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_RSHIFTEQ, out); return; };
emit_simple(&start, TK_RSHIFT, out); return;
if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_RSHIFTEQ, out); return; };
emitsimple(&start, TK_RSHIFT, out); return;
};
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_GE, out); return; };
emit_simple(&start, TK_GT, out); return;
if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_GE, out); return; };
emitsimple(&start, TK_GT, out); return;
};
err_at(l, &start, "unexpected character");
errat(l, &start, "unexpected character");
out.kind = TK_ERR;
set_pos_from(out, &start);
setposfrom(out, &start);
let one: [1]u8;
one[0] = c: u8;
out.text = astrndup(l.a, one.ptr, 1u64);

View File

@@ -56,12 +56,12 @@ export fn parserinit(p: *parser, a: *arena, l: *lex) void = {
fn advance(p: *parser) void = { refill(p); };
fn accept_tok(p: *parser, k: i32) bool = {
fn accepttok(p: *parser, k: i32) bool = {
if (p.cur_kind == k) { advance(p); return true; };
return false;
};
fn err_msg(p: *parser, msg: str) void = {
fn errmsg(p: *parser, msg: str) void = {
let pre: str = "parse: ";
os.write(2, pre.ptr, pre.len: u64);
os.write(2, msg.ptr, msg.len: u64);
@@ -69,9 +69,9 @@ fn err_msg(p: *parser, msg: str) void = {
p.errs += 1;
};
fn expect_tok(p: *parser, k: i32, what: str) bool = {
fn expecttok(p: *parser, k: i32, what: str) bool = {
if (p.cur_kind == k) { advance(p); return true; };
err_msg(p, what);
errmsg(p, what);
return false;
};
@@ -79,7 +79,7 @@ fn expect_tok(p: *parser, k: i32, what: str) bool = {
// Returns the empty str on error (and advances to make progress).
fn expectident(p: *parser, into: *str) bool = {
if (p.cur_kind != TK_IDENT) {
err_msg(p, "expected identifier");
errmsg(p, "expected identifier");
advance(p);
return false;
};
@@ -116,14 +116,14 @@ fn parsetype(p: *parser) *node = {
};
let n: *node = newnode(p.a, N_TARRAY, pf, pl, pc);
n.rhs = parseexpr(p);
expect_tok(p, TK_RBRACK, "expected ']' in array type");
expecttok(p, TK_RBRACK, "expected ']' in array type");
n.lhs = parsetype(p);
return n;
};
if (p.cur_kind == TK_STRUCT) {
advance(p);
expect_tok(p, TK_LBRACE, "expected '{' after struct");
expecttok(p, TK_LBRACE, "expected '{' after struct");
let n: *node = newnode(p.a, N_TSTRUCT, pf, pl, pc);
let fhead: *node = nil;
let ftail: *node = nil;
@@ -136,13 +136,13 @@ fn parsetype(p: *parser) *node = {
let fid: str;
expectident(p, &fid);
f.str = fid;
expect_tok(p, TK_COLON, "expected ':' in field");
expecttok(p, TK_COLON, "expected ':' in field");
f.lhs = parsetype(p);
if (fhead == nil) { fhead = f; ftail = f; }
else { ftail.next = f; ftail = f; };
if (!accept_tok(p, TK_COMMA)) { break; };
if (!accepttok(p, TK_COMMA)) { break; };
};
expect_tok(p, TK_RBRACE, "expected '}' after struct fields");
expecttok(p, TK_RBRACE, "expected '}' after struct fields");
n.list = fhead;
return n;
};
@@ -160,7 +160,7 @@ fn parsetype(p: *parser) *node = {
// (T) or (T, T, ...) or (T | T | ...)
advance(p);
let first: *node = parsetype(p);
if (accept_tok(p, TK_PIPE)) {
if (accepttok(p, TK_PIPE)) {
let n: *node = newnode(p.a, N_TTAGGED, pf, pl, pc);
let head: *node = first;
let tail: *node = first;
@@ -168,14 +168,14 @@ fn parsetype(p: *parser) *node = {
let e: *node = parsetype(p);
tail.next = e;
tail = e;
if (!accept_tok(p, TK_PIPE)) { break; };
if (!accepttok(p, TK_PIPE)) { break; };
};
expect_tok(p, TK_RPAREN, "expected ')' in tagged-union type");
expecttok(p, TK_RPAREN, "expected ')' in tagged-union type");
n.list = head;
return n;
};
if (!accept_tok(p, TK_COMMA)) {
expect_tok(p, TK_RPAREN, "expected ')' after parenthesised type");
if (!accepttok(p, TK_COMMA)) {
expecttok(p, TK_RPAREN, "expected ')' after parenthesised type");
return first;
};
let n: *node = newnode(p.a, N_TTUPLE, pf, pl, pc);
@@ -185,28 +185,28 @@ fn parsetype(p: *parser) *node = {
let e: *node = parsetype(p);
tail.next = e;
tail = e;
if (!accept_tok(p, TK_COMMA)) { break; };
if (!accepttok(p, TK_COMMA)) { break; };
if (p.cur_kind == TK_RPAREN) { break; };
};
expect_tok(p, TK_RPAREN, "expected ')' in tuple type");
expecttok(p, TK_RPAREN, "expected ')' in tuple type");
n.list = head;
return n;
};
if (p.cur_kind == TK_FN) {
advance(p);
expect_tok(p, TK_LPAREN, "expected '(' after fn in type");
expecttok(p, TK_LPAREN, "expected '(' after fn in type");
let n: *node = newnode(p.a, N_TFN, pf, pl, pc);
// Anonymous-or-named params: parseparams handles named only;
// for fn-type expressions the C parser allows IDENT-less
// (anonymous) params. Stub: only named params for now.
n.list = parseparams(p);
expect_tok(p, TK_RPAREN, "expected ')' after fn type params");
expecttok(p, TK_RPAREN, "expected ')' after fn type params");
n.lhs = parsetype(p);
return n;
};
err_msg(p, "expected type");
errmsg(p, "expected type");
advance(p);
return newnode(p.a, N_TNAME, pf, pl, pc);
};
@@ -298,7 +298,7 @@ fn parseprimary(p: *parser) *node = {
advance(p);
let e: *node = parseexpr(p);
// Tuple literal: (a, b, ...)
if (accept_tok(p, TK_COMMA)) {
if (accepttok(p, TK_COMMA)) {
let t: *node = newnode(p.a, N_TUPLE, pf, pl, pc);
t.list = e;
let tail: *node = e;
@@ -307,12 +307,12 @@ fn parseprimary(p: *parser) *node = {
let en: *node = parseexpr(p);
tail.next = en;
tail = en;
if (!accept_tok(p, TK_COMMA)) { break; };
if (!accepttok(p, TK_COMMA)) { break; };
};
expect_tok(p, TK_RPAREN, "expected ')' in tuple");
expecttok(p, TK_RPAREN, "expected ')' in tuple");
return t;
};
expect_tok(p, TK_RPAREN, "expected ')'");
expecttok(p, TK_RPAREN, "expected ')'");
return e;
};
if (p.cur_kind == TK_IDENT) {
@@ -338,16 +338,16 @@ fn parseprimary(p: *parser) *node = {
let fpc: i32 = p.cur_col;
let id: str;
expectident(p, &id);
expect_tok(p, TK_ASSIGN, "expected '=' in struct lit field");
expecttok(p, TK_ASSIGN, "expected '=' in struct lit field");
let v: *node = parseexpr(p);
let f: *node = newnode(p.a, N_FIELD, fpf, fpl, fpc);
f.str = id;
f.lhs = v;
if (head == nil) { head = f; tail = f; }
else { tail.next = f; tail = f; };
if (!accept_tok(p, TK_COMMA)) { break; };
if (!accepttok(p, TK_COMMA)) { break; };
};
expect_tok(p, TK_RBRACE, "expected '}' after struct literal");
expecttok(p, TK_RBRACE, "expected '}' after struct literal");
s.list = head;
return s;
};
@@ -356,11 +356,11 @@ fn parseprimary(p: *parser) *node = {
if (p.cur_kind == TK_MATCH) {
// match (e) { case let v: T => stmt; case T => stmt; case => stmt; };
advance(p);
expect_tok(p, TK_LPAREN, "expected '(' after match");
expecttok(p, TK_LPAREN, "expected '(' after match");
let m: *node = newnode(p.a, N_MATCH, pf, pl, pc);
m.lhs = parseexpr(p);
expect_tok(p, TK_RPAREN, "expected ')' after match scrutinee");
expect_tok(p, TK_LBRACE, "expected '{' to open match body");
expecttok(p, TK_RPAREN, "expected ')' after match scrutinee");
expecttok(p, TK_LBRACE, "expected '{' to open match body");
let head: *node = nil;
let tail: *node = nil;
for (p.cur_kind == TK_CASE) {
@@ -374,21 +374,21 @@ fn parseprimary(p: *parser) *node = {
let id: str;
expectident(p, &id);
mc.str = id;
expect_tok(p, TK_COLON, "expected ':' after match binding");
expecttok(p, TK_COLON, "expected ':' after match binding");
mc.lhs = parsetype(p);
} else { if (p.cur_kind != TK_FATARROW) {
mc.lhs = parsetype(p);
};};
expect_tok(p, TK_FATARROW, "expected '=>' in match arm");
expecttok(p, TK_FATARROW, "expected '=>' in match arm");
mc.body = parsestmt(p);
if (head == nil) { head = mc; tail = mc; }
else { tail.next = mc; tail = mc; };
};
expect_tok(p, TK_RBRACE, "expected '}' after match body");
expecttok(p, TK_RBRACE, "expected '}' after match body");
m.list = head;
return m;
};
err_msg(p, "expected expression");
errmsg(p, "expected expression");
advance(p);
return newnode(p.a, N_NONE, pf, pl, pc);
};
@@ -402,7 +402,7 @@ fn parsearglist(p: *parser, close_kind: i32, head_out: **node) void = {
let e: *node = parseexpr(p);
if (head == nil) { head = e; tail = e; }
else { tail.next = e; tail = e; };
if (!accept_tok(p, TK_COMMA)) { break; };
if (!accepttok(p, TK_COMMA)) { break; };
if (p.cur_kind == close_kind) { break; };
};
*head_out = head;
@@ -421,7 +421,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = {
let arghead: *node = nil;
parsearglist(p, TK_RPAREN, &arghead);
n.list = arghead;
expect_tok(p, TK_RPAREN, "expected ')' after args");
expecttok(p, TK_RPAREN, "expected ')' after args");
cur = n;
continue;
};
@@ -435,7 +435,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = {
if (p.cur_kind != TK_RBRACK) {
n.cond = parseexpr(p);
};
expect_tok(p, TK_RBRACK, "expected ']' in slice");
expecttok(p, TK_RBRACK, "expected ']' in slice");
cur = n;
continue;
};
@@ -453,14 +453,14 @@ fn parsepostfix(p: *parser, lhs: *node) *node = {
if (p.cur_kind != TK_RBRACK) {
n.cond = parseexpr(p);
};
expect_tok(p, TK_RBRACK, "expected ']' in slice");
expecttok(p, TK_RBRACK, "expected ']' in slice");
cur = n;
continue;
};
let n: *node = newnode(p.a, N_INDEX, pf, pl, pc);
n.lhs = cur;
n.rhs = e;
expect_tok(p, TK_RBRACK, "expected ']' after index");
expecttok(p, TK_RBRACK, "expected ']' after index");
cur = n;
continue;
};
@@ -581,7 +581,7 @@ fn parseexpr(p: *parser) *node = {
// (single-cond C-style), expr-stmt, defer, break, continue. Switch
// and match arms are not yet wired; tuple-let / multi-let neither.
fn parselet_local(p: *parser) *node = {
fn parseletlocal(p: *parser) *node = {
let pf: str = p.cur_file;
let pl: i32 = p.cur_line;
let pc: i32 = p.cur_col;
@@ -590,13 +590,13 @@ fn parselet_local(p: *parser) *node = {
let id: str;
expectident(p, &id);
n.str = id;
if (accept_tok(p, TK_COLON)) {
if (accepttok(p, TK_COLON)) {
n.lhs = parsetype(p);
};
if (accept_tok(p, TK_ASSIGN)) {
if (accepttok(p, TK_ASSIGN)) {
n.rhs = parseexpr(p);
};
expect_tok(p, TK_SEMI, "expected ';' after let");
expecttok(p, TK_SEMI, "expected ';' after let");
return n;
};
@@ -604,7 +604,7 @@ fn parseblock(p: *parser) *node = {
let pf: str = p.cur_file;
let pl: i32 = p.cur_line;
let pc: i32 = p.cur_col;
expect_tok(p, TK_LBRACE, "expected '{' to open block");
expecttok(p, TK_LBRACE, "expected '{' to open block");
let blk: *node = newnode(p.a, N_BLOCK, pf, pl, pc);
let head: *node = nil;
let tail: *node = nil;
@@ -616,7 +616,7 @@ fn parseblock(p: *parser) *node = {
else { tail.next = s; tail = s; };
};
};
expect_tok(p, TK_RBRACE, "expected '}' to close block");
expecttok(p, TK_RBRACE, "expected '}' to close block");
blk.list = head;
return blk;
};
@@ -626,12 +626,12 @@ fn parseif(p: *parser) *node = {
let pl: i32 = p.cur_line;
let pc: i32 = p.cur_col;
advance(p); // past `if`
expect_tok(p, TK_LPAREN, "expected '(' after if");
expecttok(p, TK_LPAREN, "expected '(' after if");
let n: *node = newnode(p.a, N_IF, pf, pl, pc);
n.cond = parseexpr(p);
expect_tok(p, TK_RPAREN, "expected ')' after if condition");
expecttok(p, TK_RPAREN, "expected ')' after if condition");
n.body = parseblock(p);
if (accept_tok(p, TK_ELSE)) {
if (accepttok(p, TK_ELSE)) {
if (p.cur_kind == TK_IF) {
n.els = parseif(p);
} else {
@@ -646,7 +646,7 @@ fn parsefor(p: *parser) *node = {
let pl: i32 = p.cur_line;
let pc: i32 = p.cur_col;
advance(p); // past `for`
expect_tok(p, TK_LPAREN, "expected '(' after for");
expecttok(p, TK_LPAREN, "expected '(' after for");
let n: *node = newnode(p.a, N_FOR, pf, pl, pc);
// Three forms (matching C parser):
// for (cond) — only cond
@@ -657,14 +657,14 @@ fn parsefor(p: *parser) *node = {
// ';' it was cond. If we see two ';' total after init, post is
// next. Simpler: peek for `let` to decide init form.
if (p.cur_kind == TK_LET) {
n.lhs = parselet_local(p); // init (consumes its own ';')
n.lhs = parseletlocal(p); // init (consumes its own ';')
n.cond = parseexpr(p);
expect_tok(p, TK_SEMI, "expected ';' after for cond");
expecttok(p, TK_SEMI, "expected ';' after for cond");
n.rhs = parseexpr(p);
} else {
// Parse one expr. If next is ';', it's a 3-clause without init.
let first: *node = parseexpr(p);
if (accept_tok(p, TK_SEMI)) {
if (accepttok(p, TK_SEMI)) {
// cond ; post
n.cond = first;
n.rhs = parseexpr(p);
@@ -673,7 +673,7 @@ fn parsefor(p: *parser) *node = {
n.cond = first;
};
};
expect_tok(p, TK_RPAREN, "expected ')' after for");
expecttok(p, TK_RPAREN, "expected ')' after for");
n.body = parseblock(p);
return n;
};
@@ -689,18 +689,18 @@ fn parsestmt(p: *parser) *node = {
if (p.cur_kind == TK_LBRACE) {
let b: *node = parseblock(p);
expect_tok(p, TK_SEMI, "expected ';' after block");
expecttok(p, TK_SEMI, "expected ';' after block");
return b;
};
if (p.cur_kind == TK_LET) { return parselet_local(p); };
if (p.cur_kind == TK_LET) { return parseletlocal(p); };
if (p.cur_kind == TK_IF) {
let n: *node = parseif(p);
expect_tok(p, TK_SEMI, "expected ';' after if");
expecttok(p, TK_SEMI, "expected ';' after if");
return n;
};
if (p.cur_kind == TK_FOR) {
let n: *node = parsefor(p);
expect_tok(p, TK_SEMI, "expected ';' after for");
expecttok(p, TK_SEMI, "expected ';' after for");
return n;
};
if (p.cur_kind == TK_RETURN) {
@@ -714,7 +714,7 @@ fn parsestmt(p: *parser) *node = {
let t: *node = newnode(p.a, N_TUPLE, pf, pl, pc);
t.list = first;
let tail: *node = first;
for (accept_tok(p, TK_COMMA)) {
for (accepttok(p, TK_COMMA)) {
let e: *node = parseexpr(p);
tail.next = e;
tail = e;
@@ -724,24 +724,24 @@ fn parsestmt(p: *parser) *node = {
n.lhs = first;
};
};
expect_tok(p, TK_SEMI, "expected ';' after return");
expecttok(p, TK_SEMI, "expected ';' after return");
return n;
};
if (p.cur_kind == TK_DEFER) {
advance(p);
let n: *node = newnode(p.a, N_DEFER, pf, pl, pc);
n.lhs = parseexpr(p);
expect_tok(p, TK_SEMI, "expected ';' after defer");
expecttok(p, TK_SEMI, "expected ';' after defer");
return n;
};
if (p.cur_kind == TK_BREAK) {
advance(p);
expect_tok(p, TK_SEMI, "expected ';' after break");
expecttok(p, TK_SEMI, "expected ';' after break");
return newnode(p.a, N_BREAK, pf, pl, pc);
};
if (p.cur_kind == TK_CONTINUE) {
advance(p);
expect_tok(p, TK_SEMI, "expected ';' after continue");
expecttok(p, TK_SEMI, "expected ';' after continue");
return newnode(p.a, N_CONTINUE, pf, pl, pc);
};
// expression statement, or tuple-destructure multi-assign:
@@ -761,15 +761,15 @@ fn parsestmt(p: *parser) *node = {
tail.next = lv;
tail = lv;
};
expect_tok(p, TK_ASSIGN, "expected '=' after multi-assign lvalues");
expecttok(p, TK_ASSIGN, "expected '=' after multi-assign lvalues");
m.rhs = parseexpr(p);
m.list = head;
expect_tok(p, TK_SEMI, "expected ';' after multi-assign");
expecttok(p, TK_SEMI, "expected ';' after multi-assign");
return m;
};
let n: *node = newnode(p.a, N_EXPRSTMT, pf, pl, pc);
n.lhs = e;
expect_tok(p, TK_SEMI, "expected ';' after expression statement");
expecttok(p, TK_SEMI, "expected ';' after expression statement");
return n;
};
@@ -784,7 +784,7 @@ fn parseuse(p: *parser) *node = {
let id: str;
expectident(p, &id);
n.str = id;
expect_tok(p, TK_SEMI, "expected ';' after use");
expecttok(p, TK_SEMI, "expected ';' after use");
return n;
};
@@ -797,11 +797,11 @@ fn parsedef(p: *parser, exported: i32) *node = {
let id: str;
expectident(p, &id);
n.str = id;
expect_tok(p, TK_COLON, "expected ':' in def");
expecttok(p, TK_COLON, "expected ':' in def");
n.lhs = parsetype(p);
expect_tok(p, TK_ASSIGN, "expected '=' in def");
expecttok(p, TK_ASSIGN, "expected '=' in def");
n.rhs = parseexpr(p);
expect_tok(p, TK_SEMI, "expected ';' after def");
expecttok(p, TK_SEMI, "expected ';' after def");
n.exported = exported;
return n;
};
@@ -815,13 +815,13 @@ fn parselet(p: *parser, exported: i32) *node = {
let id: str;
expectident(p, &id);
n.str = id;
if (accept_tok(p, TK_COLON)) {
if (accepttok(p, TK_COLON)) {
n.lhs = parsetype(p);
};
if (accept_tok(p, TK_ASSIGN)) {
if (accepttok(p, TK_ASSIGN)) {
n.rhs = parseexpr(p);
};
expect_tok(p, TK_SEMI, "expected ';' after let");
expecttok(p, TK_SEMI, "expected ';' after let");
n.exported = exported;
return n;
};
@@ -838,11 +838,11 @@ fn parseattrs(p: *parser) *node = {
let id: str;
expectident(p, &id);
a.str = id;
expect_tok(p, TK_LPAREN, "expected '(' after attribute name");
expecttok(p, TK_LPAREN, "expected '(' after attribute name");
let arghead: *node = nil;
parsearglist(p, TK_RPAREN, &arghead);
a.list = arghead;
expect_tok(p, TK_RPAREN, "expected ')' after attribute args");
expecttok(p, TK_RPAREN, "expected ')' after attribute args");
if (head == nil) { head = a; tail = a; }
else { tail.next = a; tail = a; };
};
@@ -863,11 +863,11 @@ fn parseparams(p: *parser) *node = {
let id: str;
expectident(p, &id);
n.str = id;
expect_tok(p, TK_COLON, "expected ':' in parameter");
expecttok(p, TK_COLON, "expected ':' in parameter");
n.lhs = parsetype(p);
if (head == nil) { head = n; tail = n; }
else { tail.next = n; tail = n; };
if (!accept_tok(p, TK_COMMA)) { break; };
if (!accepttok(p, TK_COMMA)) { break; };
if (p.cur_kind == TK_RPAREN) { break; };
};
return head;
@@ -882,20 +882,20 @@ fn parsefn(p: *parser, exported: i32, attrs: *node) *node = {
let id: str;
expectident(p, &id);
n.str = id;
expect_tok(p, TK_LPAREN, "expected '(' after fn name");
expecttok(p, TK_LPAREN, "expected '(' after fn name");
n.list = parseparams(p);
expect_tok(p, TK_RPAREN, "expected ')' after params");
expecttok(p, TK_RPAREN, "expected ')' after params");
if (p.cur_kind != TK_ASSIGN) {
if (p.cur_kind != TK_SEMI) {
n.lhs = parsetype(p);
};
};
if (accept_tok(p, TK_ASSIGN)) {
if (accepttok(p, TK_ASSIGN)) {
n.body = parseblock(p);
expect_tok(p, TK_SEMI, "expected ';' after fn body");
expecttok(p, TK_SEMI, "expected ';' after fn body");
} else {
// Body-less fn: FFI declaration (`fn name(args) ret;`).
expect_tok(p, TK_SEMI, "expected ';' after fn header");
expecttok(p, TK_SEMI, "expected ';' after fn header");
};
n.exported = exported;
n.attr = attrs;
@@ -911,9 +911,9 @@ fn parsetypedecl(p: *parser, exported: i32) *node = {
let id: str;
expectident(p, &id);
n.str = id;
expect_tok(p, TK_ASSIGN, "expected '=' in type decl");
expecttok(p, TK_ASSIGN, "expected '=' in type decl");
n.lhs = parsetype(p);
expect_tok(p, TK_SEMI, "expected ';' after type decl");
expecttok(p, TK_SEMI, "expected ';' after type decl");
n.exported = exported;
return n;
};

View File

@@ -73,7 +73,7 @@ export fn streq(a: str, b: str) bool = {
return true;
};
export fn scope_lookup_local(s: *scope, name: str) *sym = {
export fn scopelookuplocal(s: *scope, name: str) *sym = {
if (s == nil) { return nil; };
let h: u64 = hashstr(name);
let bi: i32 = (h % (s.nbuckets: u64)): i32;
@@ -86,17 +86,17 @@ export fn scope_lookup_local(s: *scope, name: str) *sym = {
return nil;
};
export fn scope_lookup(s: *scope, name: str) *sym = {
export fn scopelookup(s: *scope, name: str) *sym = {
for (s != nil) {
let r: *sym = scope_lookup_local(s, name);
let r: *sym = scopelookuplocal(s, name);
if (r != nil) { return r; };
s = s.parent;
};
return nil;
};
export fn scope_define(s: *scope, name: str, k: i32, t: *tinfo, decl: *node) *sym = {
if (scope_lookup_local(s, name) != nil) { return nil; };
export fn scopedefine(s: *scope, name: str, k: i32, t: *tinfo, decl: *node) *sym = {
if (scopelookuplocal(s, name) != nil) { return nil; };
let sy: *sym = amalloc(s.a, 80u64): *sym;
sy.name = name;
sy.skind = k;

View File

@@ -134,7 +134,7 @@ type tok = struct {
// ---- keyword lookup ---------------------------------------------------
fn streq_n(a: *u8, b: str, n: i32) bool = {
fn streqn(a: *u8, b: str, n: i32) bool = {
if (b.len != n) { return false; };
let i: i32 = 0;
for (i < n) {
@@ -148,30 +148,30 @@ fn streq_n(a: *u8, b: str, n: i32) bool = {
// or TK_NONE if it's an ordinary identifier. Linear search over a
// small alphabetised list, matching cmd/wcc/tok.c.
export fn kwlookup(p: *u8, n: i32) i32 = {
if (streq_n(p, "as", n)) { return TK_AS; };
if (streq_n(p, "break", n)) { return TK_BREAK; };
if (streq_n(p, "case", n)) { return TK_CASE; };
if (streq_n(p, "chan", n)) { return TK_CHAN; };
if (streq_n(p, "continue", n)) { return TK_CONTINUE; };
if (streq_n(p, "def", n)) { return TK_DEF; };
if (streq_n(p, "defer", n)) { return TK_DEFER; };
if (streq_n(p, "else", n)) { return TK_ELSE; };
if (streq_n(p, "export", n)) { return TK_EXPORT; };
if (streq_n(p, "false", n)) { return TK_FALSE; };
if (streq_n(p, "fn", n)) { return TK_FN; };
if (streq_n(p, "for", n)) { return TK_FOR; };
if (streq_n(p, "if", n)) { return TK_IF; };
if (streq_n(p, "let", n)) { return TK_LET; };
if (streq_n(p, "match", n)) { return TK_MATCH; };
if (streq_n(p, "nil", n)) { return TK_NIL; };
if (streq_n(p, "proc", n)) { return TK_PROC; };
if (streq_n(p, "return", n)) { return TK_RETURN; };
if (streq_n(p, "static", n)) { return TK_STATIC; };
if (streq_n(p, "struct", n)) { return TK_STRUCT; };
if (streq_n(p, "switch", n)) { return TK_SWITCH; };
if (streq_n(p, "true", n)) { return TK_TRUE; };
if (streq_n(p, "type", n)) { return TK_TYPE; };
if (streq_n(p, "use", n)) { return TK_USE; };
if (streqn(p, "as", n)) { return TK_AS; };
if (streqn(p, "break", n)) { return TK_BREAK; };
if (streqn(p, "case", n)) { return TK_CASE; };
if (streqn(p, "chan", n)) { return TK_CHAN; };
if (streqn(p, "continue", n)) { return TK_CONTINUE; };
if (streqn(p, "def", n)) { return TK_DEF; };
if (streqn(p, "defer", n)) { return TK_DEFER; };
if (streqn(p, "else", n)) { return TK_ELSE; };
if (streqn(p, "export", n)) { return TK_EXPORT; };
if (streqn(p, "false", n)) { return TK_FALSE; };
if (streqn(p, "fn", n)) { return TK_FN; };
if (streqn(p, "for", n)) { return TK_FOR; };
if (streqn(p, "if", n)) { return TK_IF; };
if (streqn(p, "let", n)) { return TK_LET; };
if (streqn(p, "match", n)) { return TK_MATCH; };
if (streqn(p, "nil", n)) { return TK_NIL; };
if (streqn(p, "proc", n)) { return TK_PROC; };
if (streqn(p, "return", n)) { return TK_RETURN; };
if (streqn(p, "static", n)) { return TK_STATIC; };
if (streqn(p, "struct", n)) { return TK_STRUCT; };
if (streqn(p, "switch", n)) { return TK_SWITCH; };
if (streqn(p, "true", n)) { return TK_TRUE; };
if (streqn(p, "type", n)) { return TK_TYPE; };
if (streqn(p, "use", n)) { return TK_USE; };
return TK_NONE;
};
@@ -278,13 +278,13 @@ export fn tokname(k: i32) str = {
// fputq mirrors cmd/wcc/tok.c:fputq — quote the string with C-style
// escapes for \, ", \n, \t, \r and \xNN for other non-printables.
fn fputc_byte(fd: i32, b: u8) void = {
fn fputcbyte(fd: i32, b: u8) void = {
let buf: [1]u8;
buf[0] = b;
os.write(fd, buf.ptr, 1u64);
};
fn fputs_str(fd: i32, s: str) void = {
fn fputsstr(fd: i32, s: str) void = {
os.write(fd, s.ptr, s.len: u64);
};
@@ -303,24 +303,24 @@ fn fputhex2(fd: i32, b: u8) void = {
};
fn fputq(fd: i32, p: *u8, n: i32) void = {
fputc_byte(fd, 34u8); // '"'
fputcbyte(fd, 34u8); // '"'
let i: i32 = 0;
for (i < n) {
let c: u8 = p[i];
if (c == 92u8) { // '\\'
fputs_str(fd, "\\\\");
fputsstr(fd, "\\\\");
} else {
if (c == 34u8) { // '"'
fputs_str(fd, "\\\"");
fputsstr(fd, "\\\"");
} else {
if (c == 10u8) { // '\n'
fputs_str(fd, "\\n");
fputsstr(fd, "\\n");
} else {
if (c == 9u8) { // '\t'
fputs_str(fd, "\\t");
fputsstr(fd, "\\t");
} else {
if (c == 13u8) { // '\r'
fputs_str(fd, "\\r");
fputsstr(fd, "\\r");
} else {
if (c < 32u8) {
fputhex2(fd, c);
@@ -328,7 +328,7 @@ fn fputq(fd: i32, p: *u8, n: i32) void = {
if (c == 127u8) {
fputhex2(fd, c);
} else {
fputc_byte(fd, c);
fputcbyte(fd, c);
};
};
};
@@ -338,7 +338,7 @@ fn fputq(fd: i32, p: *u8, n: i32) void = {
};
i += 1;
};
fputc_byte(fd, 34u8);
fputcbyte(fd, 34u8);
};
// tokprint — write one token line to fd. Format must match
@@ -354,35 +354,35 @@ export fn tokprint(fd: i32, t: *tok) void = {
let tfile: str = t.file;
let ttext: str = t.text;
if (tfile.len > 0) {
fputs_str(fd, tfile);
fputsstr(fd, tfile);
} else {
fputs_str(fd, "<none>");
fputsstr(fd, "<none>");
};
fputc_byte(fd, 58u8); // ':'
fputcbyte(fd, 58u8); // ':'
let buf: [32]u8;
let n: i32 = strconv.i64toa(buf[0:32], t.line: i64);
os.write(fd, buf.ptr, n: u64);
fputc_byte(fd, 58u8);
fputcbyte(fd, 58u8);
n = strconv.i64toa(buf[0:32], t.col: i64);
os.write(fd, buf.ptr, n: u64);
fputc_byte(fd, 32u8); // ' '
fputs_str(fd, tokname(t.kind));
fputcbyte(fd, 32u8); // ' '
fputsstr(fd, tokname(t.kind));
if (t.kind == TK_IDENT) {
fputc_byte(fd, 32u8);
fputcbyte(fd, 32u8);
fputq(fd, ttext.ptr, ttext.len);
} else { if (t.kind == TK_STR) {
fputc_byte(fd, 32u8);
fputcbyte(fd, 32u8);
fputq(fd, ttext.ptr, ttext.len);
} else { if (t.kind == TK_ERR) {
fputc_byte(fd, 32u8);
fputcbyte(fd, 32u8);
fputq(fd, ttext.ptr, ttext.len);
} else { if (t.kind == TK_INT) {
fputc_byte(fd, 32u8);
fputcbyte(fd, 32u8);
n = strconv.u64toa(buf[0:32], t.uval);
os.write(fd, buf.ptr, n: u64);
} else { if (t.kind == TK_RUNE) {
fputc_byte(fd, 32u8);
fputcbyte(fd, 32u8);
n = strconv.u64toa(buf[0:32], t.uval);
os.write(fd, buf.ptr, n: u64);
};};};};};
@@ -390,5 +390,5 @@ export fn tokprint(fd: i32, t: *tok) void = {
// won't byte-match across implementations. Diff fixtures must
// be float-free until we implement a stable float formatter.
fputc_byte(fd, 10u8); // '\n'
fputcbyte(fd, 10u8); // '\n'
};

View File

@@ -153,7 +153,7 @@ export fn typesinit(c: *tctx, a: *arena) void = {
c.ty_untyped_nil = prim(a, TY_UNTYPED_NIL, "untyped_nil", 0u64, 1u64);
};
export fn type_ptr(a: *arena, sub: *tinfo) *tinfo = {
export fn typeptr(a: *arena, sub: *tinfo) *tinfo = {
let t: *tinfo = newtype(a, TY_PTR);
t.sub = sub;
t.size = 8u64;
@@ -161,7 +161,7 @@ export fn type_ptr(a: *arena, sub: *tinfo) *tinfo = {
return t;
};
export fn type_slice(a: *arena, sub: *tinfo) *tinfo = {
export fn typeslice(a: *arena, sub: *tinfo) *tinfo = {
let t: *tinfo = newtype(a, TY_SLICE);
t.sub = sub;
t.size = 24u64;
@@ -169,7 +169,7 @@ export fn type_slice(a: *arena, sub: *tinfo) *tinfo = {
return t;
};
export fn type_array(a: *arena, sub: *tinfo, n: u64) *tinfo = {
export fn typearray(a: *arena, sub: *tinfo, n: u64) *tinfo = {
let t: *tinfo = newtype(a, TY_ARRAY);
t.sub = sub;
t.alen = n;
@@ -182,7 +182,7 @@ export fn type_array(a: *arena, sub: *tinfo, n: u64) *tinfo = {
return t;
};
export fn type_chan(a: *arena, sub: *tinfo) *tinfo = {
export fn typechan(a: *arena, sub: *tinfo) *tinfo = {
let t: *tinfo = newtype(a, TY_CHAN);
t.sub = sub;
t.size = 8u64;
@@ -190,7 +190,7 @@ export fn type_chan(a: *arena, sub: *tinfo) *tinfo = {
return t;
};
export fn type_named(a: *arena, name: str, under: *tinfo) *tinfo = {
export fn typenamed(a: *arena, name: str, under: *tinfo) *tinfo = {
let t: *tinfo = newtype(a, TY_NAMED);
t.name = name;
t.under = under;
@@ -203,7 +203,7 @@ export fn type_named(a: *arena, name: str, under: *tinfo) *tinfo = {
// ---- predicates -------------------------------------------------------
export fn type_isint(t: *tinfo) bool = {
export fn typeisint(t: *tinfo) bool = {
if (t == nil) { return false; };
let k: i32 = t.kind;
if (k == TY_I8) { return true; };
@@ -220,26 +220,26 @@ export fn type_isint(t: *tinfo) bool = {
if (k == TY_RUNE){ return true; };
if (k == TY_UNTYPED_INT) { return true; };
if (k == TY_UNTYPED_RUNE) { return true; };
if (k == TY_NAMED) { return type_isint(t.under); };
if (k == TY_NAMED) { return typeisint(t.under); };
return false;
};
export fn type_isfloat(t: *tinfo) bool = {
export fn typeisfloat(t: *tinfo) bool = {
if (t == nil) { return false; };
let k: i32 = t.kind;
if (k == TY_F32) { return true; };
if (k == TY_F64) { return true; };
if (k == TY_UNTYPED_FLOAT) { return true; };
if (k == TY_NAMED) { return type_isfloat(t.under); };
if (k == TY_NAMED) { return typeisfloat(t.under); };
return false;
};
export fn type_isnum(t: *tinfo) bool = {
if (type_isint(t)) { return true; };
return type_isfloat(t);
export fn typeisnum(t: *tinfo) bool = {
if (typeisint(t)) { return true; };
return typeisfloat(t);
};
export fn type_isunsigned(t: *tinfo) bool = {
export fn typeisunsigned(t: *tinfo) bool = {
if (t == nil) { return false; };
let k: i32 = t.kind;
if (k == TY_U8) { return true; };
@@ -248,11 +248,11 @@ export fn type_isunsigned(t: *tinfo) bool = {
if (k == TY_U64) { return true; };
if (k == TY_UINT){ return true; };
if (k == TY_UINTPTR) { return true; };
if (k == TY_NAMED) { return type_isunsigned(t.under); };
if (k == TY_NAMED) { return typeisunsigned(t.under); };
return false;
};
export fn type_isuntyped(t: *tinfo) bool = {
export fn typeisuntyped(t: *tinfo) bool = {
if (t == nil) { return false; };
let k: i32 = t.kind;
if (k == TY_UNTYPED_INT) { return true; };
@@ -264,29 +264,29 @@ export fn type_isuntyped(t: *tinfo) bool = {
return false;
};
// type_eq — structural equality. Named types compare nominally.
export fn type_eq(a: *tinfo, b: *tinfo) bool = {
// typeeq — structural equality. Named types compare nominally.
export fn typeeq(a: *tinfo, b: *tinfo) bool = {
if (a == b) { return true; };
if (a == nil) { return false; };
if (b == nil) { return false; };
if (a.kind != b.kind) { return false; };
let k: i32 = a.kind;
if (k == TY_PTR) { return type_eq(a.sub, b.sub); };
if (k == TY_SLICE) { return type_eq(a.sub, b.sub); };
if (k == TY_CHAN) { return type_eq(a.sub, b.sub); };
if (k == TY_PTR) { return typeeq(a.sub, b.sub); };
if (k == TY_SLICE) { return typeeq(a.sub, b.sub); };
if (k == TY_CHAN) { return typeeq(a.sub, b.sub); };
if (k == TY_ARRAY) {
if (a.alen != b.alen) { return false; };
return type_eq(a.sub, b.sub);
return typeeq(a.sub, b.sub);
};
if (k == TY_FN) {
if (a.variadic != b.variadic) { return false; };
if (!type_eq(a.ret, b.ret)) { return false; };
if (!typeeq(a.ret, b.ret)) { return false; };
let pa: *tparam = a.params;
let pb: *tparam = b.params;
for (true) {
if (pa == nil) { if (pb == nil) { return true; }; return false; };
if (pb == nil) { return false; };
if (!type_eq(pa.type_, pb.type_)) { return false; };
if (!typeeq(pa.type_, pb.type_)) { return false; };
pa = pa.tnext;
pb = pb.tnext;
};
@@ -306,7 +306,7 @@ export fn type_eq(a: *tinfo, b: *tinfo) bool = {
if (na[i] != nb[i]) { return false; };
i += 1;
};
if (!type_eq(fa.type_, fb.type_)) { return false; };
if (!typeeq(fa.type_, fb.type_)) { return false; };
fa = fa.tnext;
fb = fb.tnext;
};
@@ -319,7 +319,7 @@ export fn type_eq(a: *tinfo, b: *tinfo) bool = {
for (true) {
if (pa == nil) { if (pb == nil) { return true; }; return false; };
if (pb == nil) { return false; };
if (!type_eq(pa.type_, pb.type_)) { return false; };
if (!typeeq(pa.type_, pb.type_)) { return false; };
pa = pa.tnext;
pb = pb.tnext;
};

File diff suppressed because it is too large Load Diff

View File

@@ -125,10 +125,10 @@ export fn main(argc: i32, argv: **u8) i32 = {
let tc: tctx;
typesinit(&tc, a);
let ck: checker;
check_init(&ck, a, &tc);
checkinit(&ck, a, &tc);
// Quiet by default; flip to 1 when debugging missing names.
ck.verbose = 0;
check_file(&ck, f);
checkfile(&ck, f);
// (close out the if-else chain — we'll close all braces below)
// "<file>: <resolved>/<resolved+unresolved> resolved"
os.write(1, argstr(path).ptr, argstrlen(path): u64);
@@ -147,8 +147,8 @@ export fn main(argc: i32, argv: **u8) i32 = {
parserinit(&ps, a, &l);
let f: *node = parsefile(&ps);
let cg: cgen;
cgen_init(&cg, a);
cg_file(&cg, f);
cgeninit(&cg, a);
cgfile(&cg, f);
};};};};
if (l.errs > 0) { return 1; };

View File

@@ -16,28 +16,28 @@ export fn main() i32 = {
if (s == nil) { return 2; };
let n1: str = "foo";
let r1: *sym = scope_define(s, n1, SK_VAR, nil, nil);
let r1: *sym = scopedefine(s, n1, SK_VAR, nil, nil);
if (r1 == nil) { return 3; };
let n2: str = "bar";
let r2: *sym = scope_define(s, n2, SK_TYPE, nil, nil);
let r2: *sym = scopedefine(s, n2, SK_TYPE, nil, nil);
if (r2 == nil) { return 4; };
// Duplicate define in same scope must fail.
let r3: *sym = scope_define(s, n1, SK_VAR, nil, nil);
let r3: *sym = scopedefine(s, n1, SK_VAR, nil, nil);
if (r3 != nil) { return 5; };
let l1: *sym = scope_lookup(s, n1);
let l1: *sym = scopelookup(s, n1);
if (l1 == nil) { return 6; };
if (l1.skind != SK_VAR) { return 7; };
let l2: *sym = scope_lookup(s, n2);
let l2: *sym = scopelookup(s, n2);
if (l2 == nil) { return 8; };
if (l2.skind != SK_TYPE) { return 9; };
// Not-found lookup returns nil.
let n3: str = "baz";
let l3: *sym = scope_lookup(s, n3);
let l3: *sym = scopelookup(s, n3);
if (l3 != nil) { return 10; };
freearena(a);