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 // 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 // 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. // the bootstrap uses with shell redirection, just in-process.
use os; use os;
@@ -123,8 +123,8 @@ export fn main(argc: i32, argv: **u8) i32 = {
let f: *node = parsefile(&ps); let f: *node = parsefile(&ps);
let cg: cgen; let cg: cgen;
cgen_init(&cg, ar); cgeninit(&cg, ar);
cg_file(&cg, f); cgfile(&cg, f);
if (l.errs > 0) { return 1; }; if (l.errs > 0) { return 1; };
return 0; 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 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. // etc. can be looked up like ordinary symbols.
fn seed_primitives(c: *checker) void = { fn seedprimitives(c: *checker) void = {
scope_define(c.top, "void", SK_TYPE, c.tc.ty_void, nil); scopedefine(c.top, "void", SK_TYPE, c.tc.ty_void, nil);
scope_define(c.top, "bool", SK_TYPE, c.tc.ty_bool, nil); scopedefine(c.top, "bool", SK_TYPE, c.tc.ty_bool, nil);
scope_define(c.top, "rune", SK_TYPE, c.tc.ty_rune, nil); scopedefine(c.top, "rune", SK_TYPE, c.tc.ty_rune, nil);
scope_define(c.top, "i8", SK_TYPE, c.tc.ty_i8, nil); scopedefine(c.top, "i8", SK_TYPE, c.tc.ty_i8, nil);
scope_define(c.top, "i16", SK_TYPE, c.tc.ty_i16, nil); scopedefine(c.top, "i16", SK_TYPE, c.tc.ty_i16, nil);
scope_define(c.top, "i32", SK_TYPE, c.tc.ty_i32, nil); scopedefine(c.top, "i32", SK_TYPE, c.tc.ty_i32, nil);
scope_define(c.top, "i64", SK_TYPE, c.tc.ty_i64, nil); scopedefine(c.top, "i64", SK_TYPE, c.tc.ty_i64, nil);
scope_define(c.top, "u8", SK_TYPE, c.tc.ty_u8, nil); scopedefine(c.top, "u8", SK_TYPE, c.tc.ty_u8, nil);
scope_define(c.top, "u16", SK_TYPE, c.tc.ty_u16, nil); scopedefine(c.top, "u16", SK_TYPE, c.tc.ty_u16, nil);
scope_define(c.top, "u32", SK_TYPE, c.tc.ty_u32, nil); scopedefine(c.top, "u32", SK_TYPE, c.tc.ty_u32, nil);
scope_define(c.top, "u64", SK_TYPE, c.tc.ty_u64, nil); scopedefine(c.top, "u64", SK_TYPE, c.tc.ty_u64, nil);
scope_define(c.top, "int", SK_TYPE, c.tc.ty_int, nil); scopedefine(c.top, "int", SK_TYPE, c.tc.ty_int, nil);
scope_define(c.top, "uint", SK_TYPE, c.tc.ty_uint, nil); scopedefine(c.top, "uint", SK_TYPE, c.tc.ty_uint, nil);
scope_define(c.top, "uintptr", SK_TYPE, c.tc.ty_uintptr, nil); scopedefine(c.top, "uintptr", SK_TYPE, c.tc.ty_uintptr, nil);
scope_define(c.top, "f32", SK_TYPE, c.tc.ty_f32, nil); scopedefine(c.top, "f32", SK_TYPE, c.tc.ty_f32, nil);
scope_define(c.top, "f64", SK_TYPE, c.tc.ty_f64, nil); scopedefine(c.top, "f64", SK_TYPE, c.tc.ty_f64, nil);
scope_define(c.top, "str", SK_TYPE, c.tc.ty_str, nil); scopedefine(c.top, "str", SK_TYPE, c.tc.ty_str, nil);
// `nil`, `true`, `false` are keywords — handled at the lex/parser // `nil`, `true`, `false` are keywords — handled at the lex/parser
// level, no symbol needed. // 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. // their use sites resolve. The actual semantics live in cgen.
scope_define(c.top, "len", SK_FN, nil, nil); scopedefine(c.top, "len", SK_FN, nil, nil);
scope_define(c.top, "alloc", SK_FN, nil, nil); scopedefine(c.top, "alloc", SK_FN, nil, nil);
scope_define(c.top, "free", 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 // We don't compute its type yet (that's the resolve pass) — just bind
// the name so forward references resolve. // 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; }; if (d == nil) { return; };
let k: i32 = d.kind; let k: i32 = d.kind;
let nm: str = d.str; let nm: str = d.str;
if (k == N_USE) { scope_define(c.top, nm, SK_USE, nil, d); return; }; if (k == N_USE) { scopedefine(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_DEF) { scopedefine(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_TYPEDECL) { scopedefine(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_FNDECL) { scopedefine(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_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 // N_TNAME seen, looks up the name and bumps the resolved/unresolved
// counters. Local lets are installed in the current scope as soon as // counters. Local lets are installed in the current scope as soon as
// their init/type expressions have been walked (forward use of a let // their init/type expressions have been walked (forward use of a let
// before its declaration would resolve to nothing — same semantics as // before its declaration would resolve to nothing — same semantics as
// the C checker's collect-then-resolve flow within a function). // 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; }; if (n == nil) { return; };
let k: i32 = n.kind; let k: i32 = n.kind;
@@ -91,7 +91,7 @@ fn resolve_walk(c: *checker, n: *node) void = {
if (k == N_IDENT) { if (k == N_IDENT) {
let nm: str = n.str; let nm: str = n.str;
if (nm.len > 0) { if (nm.len > 0) {
let s: *sym = scope_lookup(c.cur, nm); let s: *sym = scopelookup(c.cur, nm);
if (s == nil) { if (s == nil) {
c.nunresolved += 1; c.nunresolved += 1;
if (c.verbose != 0) { if (c.verbose != 0) {
@@ -106,7 +106,7 @@ fn resolve_walk(c: *checker, n: *node) void = {
if (k == N_TNAME) { if (k == N_TNAME) {
let nm: str = n.str; let nm: str = n.str;
if (nm.len > 0) { if (nm.len > 0) {
let s: *sym = scope_lookup(c.cur, nm); let s: *sym = scopelookup(c.cur, nm);
if (s == nil) { if (s == nil) {
c.nunresolved += 1; c.nunresolved += 1;
if (c.verbose != 0) { 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` // `match (e) { case let v: T => stmt; ... }` — the binding `v`
// is declared by the case arm and visible inside its body. // is declared by the case arm and visible inside its body.
if (k == N_MCASE) { 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; let nm: str = n.str;
if (nm.len > 0) { 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; return;
}; };
if (k == N_DOT) { if (k == N_DOT) {
// Walk only the base; the .field name is a member, not a // Walk only the base; the .field name is a member, not a
// free identifier. // free identifier.
if (n.lhs != nil) { resolve_walk(c, n.lhs); }; if (n.lhs != nil) { resolvewalk(c, n.lhs); };
return; return;
}; };
if (k == N_FIELD) { if (k == N_FIELD) {
if (n.lhs != nil) { resolve_walk(c, n.lhs); }; if (n.lhs != nil) { resolvewalk(c, n.lhs); };
return; return;
}; };
if (k == N_TFIELD) { if (k == N_TFIELD) {
if (n.lhs != nil) { resolve_walk(c, n.lhs); }; if (n.lhs != nil) { resolvewalk(c, n.lhs); };
return; return;
}; };
// Walk children (mirroring ast.ww's printer descent order). // Walk children (mirroring ast.ww's printer descent order).
if (n.attr != nil) { resolve_walk(c, n.attr); }; if (n.attr != nil) { resolvewalk(c, n.attr); };
if (n.lhs != nil) { resolve_walk(c, n.lhs); }; if (n.lhs != nil) { resolvewalk(c, n.lhs); };
if (n.rhs != nil) { resolve_walk(c, n.rhs); }; if (n.rhs != nil) { resolvewalk(c, n.rhs); };
if (n.cond != nil) { resolve_walk(c, n.cond); }; if (n.cond != nil) { resolvewalk(c, n.cond); };
if (n.body != nil) { resolve_walk(c, n.body); }; if (n.body != nil) { resolvewalk(c, n.body); };
if (n.els != nil) { resolve_walk(c, n.els); }; if (n.els != nil) { resolvewalk(c, n.els); };
if (n.list != nil) { if (n.list != nil) {
let m: *node = n.list; let m: *node = n.list;
for (m != nil) { for (m != nil) {
resolve_walk(c, m); resolvewalk(c, m);
m = m.next; m = m.next;
}; };
}; };
// After walking children: a local `let X: T = init;` registers // After walking children: a local `let X: T = init;` registers
// `X` so subsequent statements can resolve it. Top-level lets // `X` so subsequent statements can resolve it. Top-level lets
// are installed in install_decl, so this duplicate install at // are installed in installdecl, so this duplicate install at
// the file scope just no-ops (scope_define returns nil on dup). // the file scope just no-ops (scopedefine returns nil on dup).
if (k == N_LET) { if (k == N_LET) {
let nm: str = n.str; let nm: str = n.str;
if (nm.len > 0) { 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 // install_param — when entering a fn body, define its params in a
// fresh local scope. // fresh local scope.
fn install_params(c: *checker, params: *node) void = { fn installparams(c: *checker, params: *node) void = {
let p: *node = params; let p: *node = params;
for (p != nil) { for (p != nil) {
if (p.kind == N_PARAM) { if (p.kind == N_PARAM) {
let nm: str = p.str; let nm: str = p.str;
if (nm.len > 0) { if (nm.len > 0) {
scope_define(c.cur, nm, SK_PARAM, nil, p); scopedefine(c.cur, nm, SK_PARAM, nil, p);
}; };
}; };
p = p.next; 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 // then walk the body. Local lets installed by walk_stmt (a future
// extension); for the current pass we just resolve-walk without // extension); for the current pass we just resolve-walk without
// per-statement scopes. // per-statement scopes.
fn resolve_fnbody(c: *checker, fnnode: *node) void = { fn resolvefnbody(c: *checker, fnnode: *node) void = {
let outer: *scope = c.cur; let outer: *scope = c.cur;
c.cur = newscope(c.a, c.cur); c.cur = newscope(c.a, c.cur);
install_params(c, fnnode.list); installparams(c, fnnode.list);
if (fnnode.body != nil) { if (fnnode.body != nil) {
resolve_walk(c, fnnode.body); resolvewalk(c, fnnode.body);
}; };
c.cur = outer; 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.a = a;
c.tc = tc; c.tc = tc;
c.top = newscope(a, nil); c.top = newscope(a, nil);
@@ -212,17 +212,17 @@ export fn check_init(c: *checker, a: *arena, tc: *tctx) void = {
c.nunresolved = 0; c.nunresolved = 0;
c.errs = 0; c.errs = 0;
c.verbose = 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 == nil) { return; };
if (file.kind != N_FILE) { return; }; if (file.kind != N_FILE) { return; };
// Pass 1: install all top-level names. // Pass 1: install all top-level names.
let d: *node = file.list; let d: *node = file.list;
for (d != nil) { for (d != nil) {
install_decl(c, d); installdecl(c, d);
d = d.next; d = d.next;
}; };
@@ -231,16 +231,16 @@ export fn check_file(c: *checker, file: *node) void = {
for (d != nil) { for (d != nil) {
let k: i32 = d.kind; let k: i32 = d.kind;
if (k == N_FNDECL) { if (k == N_FNDECL) {
if (d.lhs != nil) { resolve_walk(c, d.lhs); }; // return type if (d.lhs != nil) { resolvewalk(c, d.lhs); }; // return type
resolve_fnbody(c, d); resolvefnbody(c, d);
} else { if (k == N_DEF) { } else { if (k == N_DEF) {
if (d.lhs != nil) { resolve_walk(c, d.lhs); }; if (d.lhs != nil) { resolvewalk(c, d.lhs); };
if (d.rhs != nil) { resolve_walk(c, d.rhs); }; if (d.rhs != nil) { resolvewalk(c, d.rhs); };
} else { if (k == N_TYPEDECL) { } 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) { } else { if (k == N_LET) {
if (d.lhs != nil) { resolve_walk(c, d.lhs); }; if (d.lhs != nil) { resolvewalk(c, d.lhs); };
if (d.rhs != nil) { resolve_walk(c, d.rhs); }; if (d.rhs != nil) { resolvewalk(c, d.rhs); };
};};};}; };};};};
d = d.next; d = d.next;
}; };

View File

@@ -64,14 +64,14 @@ fn lget(l: *lex) i32 = {
return c; return c;
}; };
fn cur_pos(l: *lex, out: *pos) void = { fn curpos(l: *lex, out: *pos) void = {
out.file = l.file; out.file = l.file;
out.line = l.line; out.line = l.line;
out.col = l.col; out.col = l.col;
}; };
// putuint — write `v` (signed, but always non-negative here) to fd 2 // 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. // dependency cycle with strconv.
fn putuint(fd: i32, v: i32) void = { fn putuint(fd: i32, v: i32) void = {
let tmp: [16]u8; let tmp: [16]u8;
@@ -89,7 +89,7 @@ fn putuint(fd: i32, v: i32) void = {
os.write(fd, buf.ptr, m: u64); 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; let pf: str = p.file;
os.write(2, pf.ptr, pf.len: u64); os.write(2, pf.ptr, pf.len: u64);
os.write(2, ":".ptr, 1u64); os.write(2, ":".ptr, 1u64);
@@ -128,8 +128,8 @@ fn skipws(l: *lex) bool = {
let x: i32 = lget(l); let x: i32 = lget(l);
if (x < 0) { if (x < 0) {
let cp: pos; let cp: pos;
cur_pos(l, &cp); curpos(l, &cp);
err_at(l, &cp, "unterminated /* comment"); errat(l, &cp, "unterminated /* comment");
return false; return false;
}; };
if (prev == 42) { if (prev == 42) {
@@ -200,13 +200,13 @@ fn escape(l: *lex, out: *i32) bool = {
if (hi < 0) { return false; }; if (hi < 0) { return false; };
if (lo < 0) { return false; }; if (lo < 0) { return false; };
if (!ascii.ishex(hi: u8)) { if (!ascii.ishex(hi: u8)) {
let cp: pos; cur_pos(l, &cp); let cp: pos; curpos(l, &cp);
err_at(l, &cp, "bad \\x escape"); errat(l, &cp, "bad \\x escape");
return false; return false;
}; };
if (!ascii.ishex(lo: u8)) { if (!ascii.ishex(lo: u8)) {
let cp: pos; cur_pos(l, &cp); let cp: pos; curpos(l, &cp);
err_at(l, &cp, "bad \\x escape"); errat(l, &cp, "bad \\x escape");
return false; return false;
}; };
let h: i32 = ascii.digitval(hi: u8); let h: i32 = ascii.digitval(hi: u8);
@@ -214,13 +214,13 @@ fn escape(l: *lex, out: *i32) bool = {
*out = (h << 4) | lv; *out = (h << 4) | lv;
return true; return true;
}; };
let cp: pos; cur_pos(l, &cp); let cp: pos; curpos(l, &cp);
err_at(l, &cp, "bad escape"); errat(l, &cp, "bad escape");
return false; return false;
}; };
// scan_decimal_run — consume a run of decimal digits and underscores. // scandecimalrun — consume a run of decimal digits and underscores.
fn scan_decimal_run(l: *lex) void = { fn scandecimalrun(l: *lex) void = {
for (true) { for (true) {
let c: i32 = lpeek(l, 0u64); let c: i32 = lpeek(l, 0u64);
if (c < 0) { break; }; 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) { for (true) {
let c: i32 = lpeek(l, 0u64); let c: i32 = lpeek(l, 0u64);
if (c < 0) { break; }; 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) { for (true) {
let c: i32 = lpeek(l, 0u64); let c: i32 = lpeek(l, 0u64);
if (c == 48) { lget(l); continue; }; 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) { for (true) {
let c: i32 = lpeek(l, 0u64); let c: i32 = lpeek(l, 0u64);
if (c < 48) { break; }; 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. // scanexp — consume the [eE][+-]?[0-9]+ tail of a float, if present.
fn scan_exp(l: *lex) void = { fn scanexp(l: *lex) void = {
let e: i32 = lpeek(l, 0u64); let e: i32 = lpeek(l, 0u64);
if (e != 101) { if (e != 69) { return; }; }; // 'e' or 'E' if (e != 101) { if (e != 69) { return; }; }; // 'e' or 'E'
lget(l); lget(l);
@@ -293,41 +293,41 @@ fn lexnum(l: *lex, start: *pos, out: *tok) void = {
if (c0 == 48) { // '0' if (c0 == 48) { // '0'
if (c1 == 120) { // 'x' 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' } 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' } 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' } 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' } 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' } else { if (c1 == 79) { // 'O'
lget(l); lget(l); base = 8; scan_oct_run(l); lget(l); lget(l); base = 8; scanoctrun(l);
} else { } else {
scan_decimal_run(l); scandecimalrun(l);
if (lpeek(l, 0u64) == 46) { if (lpeek(l, 0u64) == 46) {
let after: i32 = lpeek(l, 1u64); let after: i32 = lpeek(l, 1u64);
if (after >= 48) { if (after >= 48) {
if (after <= 57) { if (after <= 57) {
isfloat = true; isfloat = true;
lget(l); lget(l);
scan_decimal_run(l); scandecimalrun(l);
scan_exp(l); scanexp(l);
}; };
}; };
}; };
};};};};};}; };};};};};};
} else { } else {
scan_decimal_run(l); scandecimalrun(l);
if (lpeek(l, 0u64) == 46) { if (lpeek(l, 0u64) == 46) {
let after: i32 = lpeek(l, 1u64); let after: i32 = lpeek(l, 1u64);
if (after >= 48) { if (after >= 48) {
if (after <= 57) { if (after <= 57) {
isfloat = true; isfloat = true;
lget(l); lget(l);
scan_decimal_run(l); scandecimalrun(l);
scan_exp(l); scanexp(l);
}; };
}; };
}; };
@@ -352,7 +352,7 @@ fn lexnum(l: *lex, start: *pos, out: *tok) void = {
let ok: bool = false; let ok: bool = false;
out.uval = parseint(digs, dn, base, &ok); out.uval = parseint(digs, dn, base, &ok);
if (!ok) { if (!ok) {
err_at(l, start, "bad integer literal"); errat(l, start, "bad integer literal");
out.kind = TK_ERR; out.kind = TK_ERR;
}; };
}; };
@@ -432,7 +432,7 @@ fn lexstr(l: *lex, start: *pos, out: *tok) void = {
for (true) { for (true) {
let c: i32 = lpeek(l, 0u64); let c: i32 = lpeek(l, 0u64);
if (c < 0) { if (c < 0) {
err_at(l, start, "unterminated string"); errat(l, start, "unterminated string");
out.kind = TK_ERR; out.kind = TK_ERR;
out.file = start.file; out.file = start.file;
out.line = start.line; 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 = { fn lexrune(l: *lex, start: *pos, out: *tok) void = {
let c: i32 = lpeek(l, 0u64); let c: i32 = lpeek(l, 0u64);
if (c < 0) { if (c < 0) {
err_at(l, start, "unterminated rune"); errat(l, start, "unterminated rune");
out.kind = TK_ERR; out.kind = TK_ERR;
out.file = start.file; out.file = start.file;
out.line = start.line; out.line = start.line;
@@ -493,7 +493,7 @@ fn lexrune(l: *lex, start: *pos, out: *tok) void = {
ch = lget(l); ch = lget(l);
}; };
if (lpeek(l, 0u64) != 39) { 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.kind = TK_ERR;
out.file = start.file; out.file = start.file;
out.line = start.line; out.line = start.line;
@@ -509,16 +509,16 @@ fn lexrune(l: *lex, start: *pos, out: *tok) void = {
out.uval = ch: u64; 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.kind = k;
out.file = start.file; out.file = start.file;
out.line = start.line; out.line = start.line;
out.col = start.col; 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. // 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.file = p.file;
out.line = p.line; out.line = p.line;
out.col = p.col; out.col = p.col;
@@ -541,11 +541,11 @@ export fn lexnext(l: *lex, out: *tok) void = {
out.tsuffix = empty; out.tsuffix = empty;
if (!skipws(l)) { if (!skipws(l)) {
let p: pos; cur_pos(l, &p); let p: pos; curpos(l, &p);
emit_simple(&p, TK_EOF, out); emitsimple(&p, TK_EOF, out);
return; return;
}; };
let start: pos; cur_pos(l, &start); let start: pos; curpos(l, &start);
let c: i32 = lpeek(l, 0u64); let c: i32 = lpeek(l, 0u64);
if (c >= 0) { if (c >= 0) {
@@ -558,98 +558,98 @@ export fn lexnext(l: *lex, out: *tok) void = {
lget(l); lget(l);
if (c == 40) { emit_simple(&start, TK_LPAREN, out); return; }; if (c == 40) { emitsimple(&start, TK_LPAREN, out); return; };
if (c == 41) { emit_simple(&start, TK_RPAREN, out); return; }; if (c == 41) { emitsimple(&start, TK_RPAREN, out); return; };
if (c == 123) { emit_simple(&start, TK_LBRACE, out); return; }; if (c == 123) { emitsimple(&start, TK_LBRACE, out); return; };
if (c == 125) { emit_simple(&start, TK_RBRACE, out); return; }; if (c == 125) { emitsimple(&start, TK_RBRACE, out); return; };
if (c == 91) { emit_simple(&start, TK_LBRACK, out); return; }; if (c == 91) { emitsimple(&start, TK_LBRACK, out); return; };
if (c == 93) { emit_simple(&start, TK_RBRACK, out); return; }; if (c == 93) { emitsimple(&start, TK_RBRACK, out); return; };
if (c == 44) { emit_simple(&start, TK_COMMA, out); return; }; if (c == 44) { emitsimple(&start, TK_COMMA, out); return; };
if (c == 59) { emit_simple(&start, TK_SEMI, out); return; }; if (c == 59) { emitsimple(&start, TK_SEMI, out); return; };
if (c == 58) { emit_simple(&start, TK_COLON, out); return; }; if (c == 58) { emitsimple(&start, TK_COLON, out); return; };
if (c == 64) { emit_simple(&start, TK_AT, out); return; }; if (c == 64) { emitsimple(&start, TK_AT, out); return; };
if (c == 63) { emit_simple(&start, TK_QUESTION, out); return; }; if (c == 63) { emitsimple(&start, TK_QUESTION, out); return; };
if (c == 126) { emit_simple(&start, TK_TILDE, out); return; }; if (c == 126) { emitsimple(&start, TK_TILDE, out); return; };
if (c == 46) { // '.' if (c == 46) { // '.'
if (lpeek(l, 0u64) == 46) { if (lpeek(l, 0u64) == 46) {
if (lpeek(l, 1u64) == 46) { if (lpeek(l, 1u64) == 46) {
lget(l); lget(l); lget(l); lget(l);
emit_simple(&start, TK_ELLIPSIS, out); return; emitsimple(&start, TK_ELLIPSIS, out); return;
}; };
lget(l); 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 (c == 43) {
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_PLUSEQ, out); return; }; if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_PLUSEQ, out); return; };
emit_simple(&start, TK_PLUS, out); return; emitsimple(&start, TK_PLUS, out); return;
}; };
if (c == 45) { if (c == 45) {
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_MINUSEQ, out); return; }; if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_MINUSEQ, out); return; };
if (lpeek(l, 0u64) == 62) { lget(l); emit_simple(&start, TK_ARROW, out); return; }; if (lpeek(l, 0u64) == 62) { lget(l); emitsimple(&start, TK_ARROW, out); return; };
emit_simple(&start, TK_MINUS, out); return; emitsimple(&start, TK_MINUS, out); return;
}; };
if (c == 42) { if (c == 42) {
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_STAREQ, out); return; }; if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_STAREQ, out); return; };
emit_simple(&start, TK_STAR, out); return; emitsimple(&start, TK_STAR, out); return;
}; };
if (c == 47) { if (c == 47) {
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_SLASHEQ, out); return; }; if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_SLASHEQ, out); return; };
emit_simple(&start, TK_SLASH, out); return; emitsimple(&start, TK_SLASH, out); return;
}; };
if (c == 37) { if (c == 37) {
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_PERCENTEQ, out); return; }; if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_PERCENTEQ, out); return; };
emit_simple(&start, TK_PERCENT, out); return; emitsimple(&start, TK_PERCENT, out); return;
}; };
if (c == 38) { if (c == 38) {
if (lpeek(l, 0u64) == 38) { lget(l); emit_simple(&start, TK_AND, out); return; }; if (lpeek(l, 0u64) == 38) { lget(l); emitsimple(&start, TK_AND, out); return; };
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_AMPEQ, out); return; }; if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_AMPEQ, out); return; };
emit_simple(&start, TK_AMP, out); return; emitsimple(&start, TK_AMP, out); return;
}; };
if (c == 124) { if (c == 124) {
if (lpeek(l, 0u64) == 124) { lget(l); emit_simple(&start, TK_OR, out); return; }; if (lpeek(l, 0u64) == 124) { lget(l); emitsimple(&start, TK_OR, out); return; };
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_PIPEEQ, out); return; }; if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_PIPEEQ, out); return; };
emit_simple(&start, TK_PIPE, out); return; emitsimple(&start, TK_PIPE, out); return;
}; };
if (c == 94) { if (c == 94) {
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_CARETEQ, out); return; }; if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_CARETEQ, out); return; };
emit_simple(&start, TK_CARET, out); return; emitsimple(&start, TK_CARET, out); return;
}; };
if (c == 61) { if (c == 61) {
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_EQ, out); return; }; if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_EQ, out); return; };
if (lpeek(l, 0u64) == 62) { lget(l); emit_simple(&start, TK_FATARROW, out); return; }; if (lpeek(l, 0u64) == 62) { lget(l); emitsimple(&start, TK_FATARROW, out); return; };
emit_simple(&start, TK_ASSIGN, out); return; emitsimple(&start, TK_ASSIGN, out); return;
}; };
if (c == 33) { if (c == 33) {
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_NEQ, out); return; }; if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_NEQ, out); return; };
emit_simple(&start, TK_NOT, out); return; emitsimple(&start, TK_NOT, out); return;
}; };
if (c == 60) { if (c == 60) {
if (lpeek(l, 0u64) == 60) { if (lpeek(l, 0u64) == 60) {
lget(l); lget(l);
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_LSHIFTEQ, out); return; }; if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_LSHIFTEQ, out); return; };
emit_simple(&start, TK_LSHIFT, 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) == 61) { lget(l); emitsimple(&start, TK_LE, out); return; };
if (lpeek(l, 0u64) == 45) { lget(l); emit_simple(&start, TK_LARROW, out); return; }; if (lpeek(l, 0u64) == 45) { lget(l); emitsimple(&start, TK_LARROW, out); return; };
emit_simple(&start, TK_LT, out); return; emitsimple(&start, TK_LT, out); return;
}; };
if (c == 62) { if (c == 62) {
if (lpeek(l, 0u64) == 62) { if (lpeek(l, 0u64) == 62) {
lget(l); lget(l);
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_RSHIFTEQ, out); return; }; if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_RSHIFTEQ, out); return; };
emit_simple(&start, TK_RSHIFT, out); return; emitsimple(&start, TK_RSHIFT, out); return;
}; };
if (lpeek(l, 0u64) == 61) { lget(l); emit_simple(&start, TK_GE, out); return; }; if (lpeek(l, 0u64) == 61) { lget(l); emitsimple(&start, TK_GE, out); return; };
emit_simple(&start, TK_GT, out); return; emitsimple(&start, TK_GT, out); return;
}; };
err_at(l, &start, "unexpected character"); errat(l, &start, "unexpected character");
out.kind = TK_ERR; out.kind = TK_ERR;
set_pos_from(out, &start); setposfrom(out, &start);
let one: [1]u8; let one: [1]u8;
one[0] = c: u8; one[0] = c: u8;
out.text = astrndup(l.a, one.ptr, 1u64); 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 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; }; if (p.cur_kind == k) { advance(p); return true; };
return false; return false;
}; };
fn err_msg(p: *parser, msg: str) void = { fn errmsg(p: *parser, msg: str) void = {
let pre: str = "parse: "; let pre: str = "parse: ";
os.write(2, pre.ptr, pre.len: u64); os.write(2, pre.ptr, pre.len: u64);
os.write(2, msg.ptr, msg.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; 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; }; if (p.cur_kind == k) { advance(p); return true; };
err_msg(p, what); errmsg(p, what);
return false; 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). // Returns the empty str on error (and advances to make progress).
fn expectident(p: *parser, into: *str) bool = { fn expectident(p: *parser, into: *str) bool = {
if (p.cur_kind != TK_IDENT) { if (p.cur_kind != TK_IDENT) {
err_msg(p, "expected identifier"); errmsg(p, "expected identifier");
advance(p); advance(p);
return false; return false;
}; };
@@ -116,14 +116,14 @@ fn parsetype(p: *parser) *node = {
}; };
let n: *node = newnode(p.a, N_TARRAY, pf, pl, pc); let n: *node = newnode(p.a, N_TARRAY, pf, pl, pc);
n.rhs = parseexpr(p); 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); n.lhs = parsetype(p);
return n; return n;
}; };
if (p.cur_kind == TK_STRUCT) { if (p.cur_kind == TK_STRUCT) {
advance(p); 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 n: *node = newnode(p.a, N_TSTRUCT, pf, pl, pc);
let fhead: *node = nil; let fhead: *node = nil;
let ftail: *node = nil; let ftail: *node = nil;
@@ -136,13 +136,13 @@ fn parsetype(p: *parser) *node = {
let fid: str; let fid: str;
expectident(p, &fid); expectident(p, &fid);
f.str = fid; f.str = fid;
expect_tok(p, TK_COLON, "expected ':' in field"); expecttok(p, TK_COLON, "expected ':' in field");
f.lhs = parsetype(p); f.lhs = parsetype(p);
if (fhead == nil) { fhead = f; ftail = f; } if (fhead == nil) { fhead = f; ftail = f; }
else { ftail.next = 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; n.list = fhead;
return n; return n;
}; };
@@ -160,7 +160,7 @@ fn parsetype(p: *parser) *node = {
// (T) or (T, T, ...) or (T | T | ...) // (T) or (T, T, ...) or (T | T | ...)
advance(p); advance(p);
let first: *node = parsetype(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 n: *node = newnode(p.a, N_TTAGGED, pf, pl, pc);
let head: *node = first; let head: *node = first;
let tail: *node = first; let tail: *node = first;
@@ -168,14 +168,14 @@ fn parsetype(p: *parser) *node = {
let e: *node = parsetype(p); let e: *node = parsetype(p);
tail.next = e; tail.next = e;
tail = 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; n.list = head;
return n; return n;
}; };
if (!accept_tok(p, TK_COMMA)) { if (!accepttok(p, TK_COMMA)) {
expect_tok(p, TK_RPAREN, "expected ')' after parenthesised type"); expecttok(p, TK_RPAREN, "expected ')' after parenthesised type");
return first; return first;
}; };
let n: *node = newnode(p.a, N_TTUPLE, pf, pl, pc); 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); let e: *node = parsetype(p);
tail.next = e; tail.next = e;
tail = e; tail = e;
if (!accept_tok(p, TK_COMMA)) { break; }; if (!accepttok(p, TK_COMMA)) { break; };
if (p.cur_kind == TK_RPAREN) { 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; n.list = head;
return n; return n;
}; };
if (p.cur_kind == TK_FN) { if (p.cur_kind == TK_FN) {
advance(p); 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); let n: *node = newnode(p.a, N_TFN, pf, pl, pc);
// Anonymous-or-named params: parseparams handles named only; // Anonymous-or-named params: parseparams handles named only;
// for fn-type expressions the C parser allows IDENT-less // for fn-type expressions the C parser allows IDENT-less
// (anonymous) params. Stub: only named params for now. // (anonymous) params. Stub: only named params for now.
n.list = parseparams(p); 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); n.lhs = parsetype(p);
return n; return n;
}; };
err_msg(p, "expected type"); errmsg(p, "expected type");
advance(p); advance(p);
return newnode(p.a, N_TNAME, pf, pl, pc); return newnode(p.a, N_TNAME, pf, pl, pc);
}; };
@@ -298,7 +298,7 @@ fn parseprimary(p: *parser) *node = {
advance(p); advance(p);
let e: *node = parseexpr(p); let e: *node = parseexpr(p);
// Tuple literal: (a, b, ...) // 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); let t: *node = newnode(p.a, N_TUPLE, pf, pl, pc);
t.list = e; t.list = e;
let tail: *node = e; let tail: *node = e;
@@ -307,12 +307,12 @@ fn parseprimary(p: *parser) *node = {
let en: *node = parseexpr(p); let en: *node = parseexpr(p);
tail.next = en; tail.next = en;
tail = 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; return t;
}; };
expect_tok(p, TK_RPAREN, "expected ')'"); expecttok(p, TK_RPAREN, "expected ')'");
return e; return e;
}; };
if (p.cur_kind == TK_IDENT) { if (p.cur_kind == TK_IDENT) {
@@ -338,16 +338,16 @@ fn parseprimary(p: *parser) *node = {
let fpc: i32 = p.cur_col; let fpc: i32 = p.cur_col;
let id: str; let id: str;
expectident(p, &id); 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 v: *node = parseexpr(p);
let f: *node = newnode(p.a, N_FIELD, fpf, fpl, fpc); let f: *node = newnode(p.a, N_FIELD, fpf, fpl, fpc);
f.str = id; f.str = id;
f.lhs = v; f.lhs = v;
if (head == nil) { head = f; tail = f; } if (head == nil) { head = f; tail = f; }
else { tail.next = 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; s.list = head;
return s; return s;
}; };
@@ -356,11 +356,11 @@ fn parseprimary(p: *parser) *node = {
if (p.cur_kind == TK_MATCH) { if (p.cur_kind == TK_MATCH) {
// match (e) { case let v: T => stmt; case T => stmt; case => stmt; }; // match (e) { case let v: T => stmt; case T => stmt; case => stmt; };
advance(p); 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); let m: *node = newnode(p.a, N_MATCH, pf, pl, pc);
m.lhs = parseexpr(p); m.lhs = parseexpr(p);
expect_tok(p, TK_RPAREN, "expected ')' after match scrutinee"); expecttok(p, TK_RPAREN, "expected ')' after match scrutinee");
expect_tok(p, TK_LBRACE, "expected '{' to open match body"); expecttok(p, TK_LBRACE, "expected '{' to open match body");
let head: *node = nil; let head: *node = nil;
let tail: *node = nil; let tail: *node = nil;
for (p.cur_kind == TK_CASE) { for (p.cur_kind == TK_CASE) {
@@ -374,21 +374,21 @@ fn parseprimary(p: *parser) *node = {
let id: str; let id: str;
expectident(p, &id); expectident(p, &id);
mc.str = 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); mc.lhs = parsetype(p);
} else { if (p.cur_kind != TK_FATARROW) { } else { if (p.cur_kind != TK_FATARROW) {
mc.lhs = parsetype(p); 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); mc.body = parsestmt(p);
if (head == nil) { head = mc; tail = mc; } if (head == nil) { head = mc; tail = mc; }
else { tail.next = 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; m.list = head;
return m; return m;
}; };
err_msg(p, "expected expression"); errmsg(p, "expected expression");
advance(p); advance(p);
return newnode(p.a, N_NONE, pf, pl, pc); 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); let e: *node = parseexpr(p);
if (head == nil) { head = e; tail = e; } if (head == nil) { head = e; tail = e; }
else { tail.next = 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; }; if (p.cur_kind == close_kind) { break; };
}; };
*head_out = head; *head_out = head;
@@ -421,7 +421,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = {
let arghead: *node = nil; let arghead: *node = nil;
parsearglist(p, TK_RPAREN, &arghead); parsearglist(p, TK_RPAREN, &arghead);
n.list = arghead; n.list = arghead;
expect_tok(p, TK_RPAREN, "expected ')' after args"); expecttok(p, TK_RPAREN, "expected ')' after args");
cur = n; cur = n;
continue; continue;
}; };
@@ -435,7 +435,7 @@ fn parsepostfix(p: *parser, lhs: *node) *node = {
if (p.cur_kind != TK_RBRACK) { if (p.cur_kind != TK_RBRACK) {
n.cond = parseexpr(p); n.cond = parseexpr(p);
}; };
expect_tok(p, TK_RBRACK, "expected ']' in slice"); expecttok(p, TK_RBRACK, "expected ']' in slice");
cur = n; cur = n;
continue; continue;
}; };
@@ -453,14 +453,14 @@ fn parsepostfix(p: *parser, lhs: *node) *node = {
if (p.cur_kind != TK_RBRACK) { if (p.cur_kind != TK_RBRACK) {
n.cond = parseexpr(p); n.cond = parseexpr(p);
}; };
expect_tok(p, TK_RBRACK, "expected ']' in slice"); expecttok(p, TK_RBRACK, "expected ']' in slice");
cur = n; cur = n;
continue; continue;
}; };
let n: *node = newnode(p.a, N_INDEX, pf, pl, pc); let n: *node = newnode(p.a, N_INDEX, pf, pl, pc);
n.lhs = cur; n.lhs = cur;
n.rhs = e; n.rhs = e;
expect_tok(p, TK_RBRACK, "expected ']' after index"); expecttok(p, TK_RBRACK, "expected ']' after index");
cur = n; cur = n;
continue; continue;
}; };
@@ -581,7 +581,7 @@ fn parseexpr(p: *parser) *node = {
// (single-cond C-style), expr-stmt, defer, break, continue. Switch // (single-cond C-style), expr-stmt, defer, break, continue. Switch
// and match arms are not yet wired; tuple-let / multi-let neither. // 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 pf: str = p.cur_file;
let pl: i32 = p.cur_line; let pl: i32 = p.cur_line;
let pc: i32 = p.cur_col; let pc: i32 = p.cur_col;
@@ -590,13 +590,13 @@ fn parselet_local(p: *parser) *node = {
let id: str; let id: str;
expectident(p, &id); expectident(p, &id);
n.str = id; n.str = id;
if (accept_tok(p, TK_COLON)) { if (accepttok(p, TK_COLON)) {
n.lhs = parsetype(p); n.lhs = parsetype(p);
}; };
if (accept_tok(p, TK_ASSIGN)) { if (accepttok(p, TK_ASSIGN)) {
n.rhs = parseexpr(p); n.rhs = parseexpr(p);
}; };
expect_tok(p, TK_SEMI, "expected ';' after let"); expecttok(p, TK_SEMI, "expected ';' after let");
return n; return n;
}; };
@@ -604,7 +604,7 @@ fn parseblock(p: *parser) *node = {
let pf: str = p.cur_file; let pf: str = p.cur_file;
let pl: i32 = p.cur_line; let pl: i32 = p.cur_line;
let pc: i32 = p.cur_col; 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 blk: *node = newnode(p.a, N_BLOCK, pf, pl, pc);
let head: *node = nil; let head: *node = nil;
let tail: *node = nil; let tail: *node = nil;
@@ -616,7 +616,7 @@ fn parseblock(p: *parser) *node = {
else { tail.next = s; tail = s; }; 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; blk.list = head;
return blk; return blk;
}; };
@@ -626,12 +626,12 @@ fn parseif(p: *parser) *node = {
let pl: i32 = p.cur_line; let pl: i32 = p.cur_line;
let pc: i32 = p.cur_col; let pc: i32 = p.cur_col;
advance(p); // past `if` 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); let n: *node = newnode(p.a, N_IF, pf, pl, pc);
n.cond = parseexpr(p); 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); n.body = parseblock(p);
if (accept_tok(p, TK_ELSE)) { if (accepttok(p, TK_ELSE)) {
if (p.cur_kind == TK_IF) { if (p.cur_kind == TK_IF) {
n.els = parseif(p); n.els = parseif(p);
} else { } else {
@@ -646,7 +646,7 @@ fn parsefor(p: *parser) *node = {
let pl: i32 = p.cur_line; let pl: i32 = p.cur_line;
let pc: i32 = p.cur_col; let pc: i32 = p.cur_col;
advance(p); // past `for` 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); let n: *node = newnode(p.a, N_FOR, pf, pl, pc);
// Three forms (matching C parser): // Three forms (matching C parser):
// for (cond) — only cond // 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 // ';' it was cond. If we see two ';' total after init, post is
// next. Simpler: peek for `let` to decide init form. // next. Simpler: peek for `let` to decide init form.
if (p.cur_kind == TK_LET) { 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); 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); n.rhs = parseexpr(p);
} else { } else {
// Parse one expr. If next is ';', it's a 3-clause without init. // Parse one expr. If next is ';', it's a 3-clause without init.
let first: *node = parseexpr(p); let first: *node = parseexpr(p);
if (accept_tok(p, TK_SEMI)) { if (accepttok(p, TK_SEMI)) {
// cond ; post // cond ; post
n.cond = first; n.cond = first;
n.rhs = parseexpr(p); n.rhs = parseexpr(p);
@@ -673,7 +673,7 @@ fn parsefor(p: *parser) *node = {
n.cond = first; n.cond = first;
}; };
}; };
expect_tok(p, TK_RPAREN, "expected ')' after for"); expecttok(p, TK_RPAREN, "expected ')' after for");
n.body = parseblock(p); n.body = parseblock(p);
return n; return n;
}; };
@@ -689,18 +689,18 @@ fn parsestmt(p: *parser) *node = {
if (p.cur_kind == TK_LBRACE) { if (p.cur_kind == TK_LBRACE) {
let b: *node = parseblock(p); let b: *node = parseblock(p);
expect_tok(p, TK_SEMI, "expected ';' after block"); expecttok(p, TK_SEMI, "expected ';' after block");
return b; 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) { if (p.cur_kind == TK_IF) {
let n: *node = parseif(p); let n: *node = parseif(p);
expect_tok(p, TK_SEMI, "expected ';' after if"); expecttok(p, TK_SEMI, "expected ';' after if");
return n; return n;
}; };
if (p.cur_kind == TK_FOR) { if (p.cur_kind == TK_FOR) {
let n: *node = parsefor(p); let n: *node = parsefor(p);
expect_tok(p, TK_SEMI, "expected ';' after for"); expecttok(p, TK_SEMI, "expected ';' after for");
return n; return n;
}; };
if (p.cur_kind == TK_RETURN) { 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); let t: *node = newnode(p.a, N_TUPLE, pf, pl, pc);
t.list = first; t.list = first;
let tail: *node = first; let tail: *node = first;
for (accept_tok(p, TK_COMMA)) { for (accepttok(p, TK_COMMA)) {
let e: *node = parseexpr(p); let e: *node = parseexpr(p);
tail.next = e; tail.next = e;
tail = e; tail = e;
@@ -724,24 +724,24 @@ fn parsestmt(p: *parser) *node = {
n.lhs = first; n.lhs = first;
}; };
}; };
expect_tok(p, TK_SEMI, "expected ';' after return"); expecttok(p, TK_SEMI, "expected ';' after return");
return n; return n;
}; };
if (p.cur_kind == TK_DEFER) { if (p.cur_kind == TK_DEFER) {
advance(p); advance(p);
let n: *node = newnode(p.a, N_DEFER, pf, pl, pc); let n: *node = newnode(p.a, N_DEFER, pf, pl, pc);
n.lhs = parseexpr(p); n.lhs = parseexpr(p);
expect_tok(p, TK_SEMI, "expected ';' after defer"); expecttok(p, TK_SEMI, "expected ';' after defer");
return n; return n;
}; };
if (p.cur_kind == TK_BREAK) { if (p.cur_kind == TK_BREAK) {
advance(p); 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); return newnode(p.a, N_BREAK, pf, pl, pc);
}; };
if (p.cur_kind == TK_CONTINUE) { if (p.cur_kind == TK_CONTINUE) {
advance(p); 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); return newnode(p.a, N_CONTINUE, pf, pl, pc);
}; };
// expression statement, or tuple-destructure multi-assign: // expression statement, or tuple-destructure multi-assign:
@@ -761,15 +761,15 @@ fn parsestmt(p: *parser) *node = {
tail.next = lv; tail.next = lv;
tail = 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.rhs = parseexpr(p);
m.list = head; m.list = head;
expect_tok(p, TK_SEMI, "expected ';' after multi-assign"); expecttok(p, TK_SEMI, "expected ';' after multi-assign");
return m; return m;
}; };
let n: *node = newnode(p.a, N_EXPRSTMT, pf, pl, pc); let n: *node = newnode(p.a, N_EXPRSTMT, pf, pl, pc);
n.lhs = e; n.lhs = e;
expect_tok(p, TK_SEMI, "expected ';' after expression statement"); expecttok(p, TK_SEMI, "expected ';' after expression statement");
return n; return n;
}; };
@@ -784,7 +784,7 @@ fn parseuse(p: *parser) *node = {
let id: str; let id: str;
expectident(p, &id); expectident(p, &id);
n.str = id; n.str = id;
expect_tok(p, TK_SEMI, "expected ';' after use"); expecttok(p, TK_SEMI, "expected ';' after use");
return n; return n;
}; };
@@ -797,11 +797,11 @@ fn parsedef(p: *parser, exported: i32) *node = {
let id: str; let id: str;
expectident(p, &id); expectident(p, &id);
n.str = id; n.str = id;
expect_tok(p, TK_COLON, "expected ':' in def"); expecttok(p, TK_COLON, "expected ':' in def");
n.lhs = parsetype(p); n.lhs = parsetype(p);
expect_tok(p, TK_ASSIGN, "expected '=' in def"); expecttok(p, TK_ASSIGN, "expected '=' in def");
n.rhs = parseexpr(p); n.rhs = parseexpr(p);
expect_tok(p, TK_SEMI, "expected ';' after def"); expecttok(p, TK_SEMI, "expected ';' after def");
n.exported = exported; n.exported = exported;
return n; return n;
}; };
@@ -815,13 +815,13 @@ fn parselet(p: *parser, exported: i32) *node = {
let id: str; let id: str;
expectident(p, &id); expectident(p, &id);
n.str = id; n.str = id;
if (accept_tok(p, TK_COLON)) { if (accepttok(p, TK_COLON)) {
n.lhs = parsetype(p); n.lhs = parsetype(p);
}; };
if (accept_tok(p, TK_ASSIGN)) { if (accepttok(p, TK_ASSIGN)) {
n.rhs = parseexpr(p); n.rhs = parseexpr(p);
}; };
expect_tok(p, TK_SEMI, "expected ';' after let"); expecttok(p, TK_SEMI, "expected ';' after let");
n.exported = exported; n.exported = exported;
return n; return n;
}; };
@@ -838,11 +838,11 @@ fn parseattrs(p: *parser) *node = {
let id: str; let id: str;
expectident(p, &id); expectident(p, &id);
a.str = 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; let arghead: *node = nil;
parsearglist(p, TK_RPAREN, &arghead); parsearglist(p, TK_RPAREN, &arghead);
a.list = 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; } if (head == nil) { head = a; tail = a; }
else { tail.next = a; tail = a; }; else { tail.next = a; tail = a; };
}; };
@@ -863,11 +863,11 @@ fn parseparams(p: *parser) *node = {
let id: str; let id: str;
expectident(p, &id); expectident(p, &id);
n.str = id; n.str = id;
expect_tok(p, TK_COLON, "expected ':' in parameter"); expecttok(p, TK_COLON, "expected ':' in parameter");
n.lhs = parsetype(p); n.lhs = parsetype(p);
if (head == nil) { head = n; tail = n; } if (head == nil) { head = n; tail = n; }
else { tail.next = 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; }; if (p.cur_kind == TK_RPAREN) { break; };
}; };
return head; return head;
@@ -882,20 +882,20 @@ fn parsefn(p: *parser, exported: i32, attrs: *node) *node = {
let id: str; let id: str;
expectident(p, &id); expectident(p, &id);
n.str = 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); 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_ASSIGN) {
if (p.cur_kind != TK_SEMI) { if (p.cur_kind != TK_SEMI) {
n.lhs = parsetype(p); n.lhs = parsetype(p);
}; };
}; };
if (accept_tok(p, TK_ASSIGN)) { if (accepttok(p, TK_ASSIGN)) {
n.body = parseblock(p); n.body = parseblock(p);
expect_tok(p, TK_SEMI, "expected ';' after fn body"); expecttok(p, TK_SEMI, "expected ';' after fn body");
} else { } else {
// Body-less fn: FFI declaration (`fn name(args) ret;`). // 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.exported = exported;
n.attr = attrs; n.attr = attrs;
@@ -911,9 +911,9 @@ fn parsetypedecl(p: *parser, exported: i32) *node = {
let id: str; let id: str;
expectident(p, &id); expectident(p, &id);
n.str = 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); n.lhs = parsetype(p);
expect_tok(p, TK_SEMI, "expected ';' after type decl"); expecttok(p, TK_SEMI, "expected ';' after type decl");
n.exported = exported; n.exported = exported;
return n; return n;
}; };

View File

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

View File

@@ -134,7 +134,7 @@ type tok = struct {
// ---- keyword lookup --------------------------------------------------- // ---- 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; }; if (b.len != n) { return false; };
let i: i32 = 0; let i: i32 = 0;
for (i < n) { 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 // or TK_NONE if it's an ordinary identifier. Linear search over a
// small alphabetised list, matching cmd/wcc/tok.c. // small alphabetised list, matching cmd/wcc/tok.c.
export fn kwlookup(p: *u8, n: i32) i32 = { export fn kwlookup(p: *u8, n: i32) i32 = {
if (streq_n(p, "as", n)) { return TK_AS; }; if (streqn(p, "as", n)) { return TK_AS; };
if (streq_n(p, "break", n)) { return TK_BREAK; }; if (streqn(p, "break", n)) { return TK_BREAK; };
if (streq_n(p, "case", n)) { return TK_CASE; }; if (streqn(p, "case", n)) { return TK_CASE; };
if (streq_n(p, "chan", n)) { return TK_CHAN; }; if (streqn(p, "chan", n)) { return TK_CHAN; };
if (streq_n(p, "continue", n)) { return TK_CONTINUE; }; if (streqn(p, "continue", n)) { return TK_CONTINUE; };
if (streq_n(p, "def", n)) { return TK_DEF; }; if (streqn(p, "def", n)) { return TK_DEF; };
if (streq_n(p, "defer", n)) { return TK_DEFER; }; if (streqn(p, "defer", n)) { return TK_DEFER; };
if (streq_n(p, "else", n)) { return TK_ELSE; }; if (streqn(p, "else", n)) { return TK_ELSE; };
if (streq_n(p, "export", n)) { return TK_EXPORT; }; if (streqn(p, "export", n)) { return TK_EXPORT; };
if (streq_n(p, "false", n)) { return TK_FALSE; }; if (streqn(p, "false", n)) { return TK_FALSE; };
if (streq_n(p, "fn", n)) { return TK_FN; }; if (streqn(p, "fn", n)) { return TK_FN; };
if (streq_n(p, "for", n)) { return TK_FOR; }; if (streqn(p, "for", n)) { return TK_FOR; };
if (streq_n(p, "if", n)) { return TK_IF; }; if (streqn(p, "if", n)) { return TK_IF; };
if (streq_n(p, "let", n)) { return TK_LET; }; if (streqn(p, "let", n)) { return TK_LET; };
if (streq_n(p, "match", n)) { return TK_MATCH; }; if (streqn(p, "match", n)) { return TK_MATCH; };
if (streq_n(p, "nil", n)) { return TK_NIL; }; if (streqn(p, "nil", n)) { return TK_NIL; };
if (streq_n(p, "proc", n)) { return TK_PROC; }; if (streqn(p, "proc", n)) { return TK_PROC; };
if (streq_n(p, "return", n)) { return TK_RETURN; }; if (streqn(p, "return", n)) { return TK_RETURN; };
if (streq_n(p, "static", n)) { return TK_STATIC; }; if (streqn(p, "static", n)) { return TK_STATIC; };
if (streq_n(p, "struct", n)) { return TK_STRUCT; }; if (streqn(p, "struct", n)) { return TK_STRUCT; };
if (streq_n(p, "switch", n)) { return TK_SWITCH; }; if (streqn(p, "switch", n)) { return TK_SWITCH; };
if (streq_n(p, "true", n)) { return TK_TRUE; }; if (streqn(p, "true", n)) { return TK_TRUE; };
if (streq_n(p, "type", n)) { return TK_TYPE; }; if (streqn(p, "type", n)) { return TK_TYPE; };
if (streq_n(p, "use", n)) { return TK_USE; }; if (streqn(p, "use", n)) { return TK_USE; };
return TK_NONE; 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 // fputq mirrors cmd/wcc/tok.c:fputq — quote the string with C-style
// escapes for \, ", \n, \t, \r and \xNN for other non-printables. // 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; let buf: [1]u8;
buf[0] = b; buf[0] = b;
os.write(fd, buf.ptr, 1u64); 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); 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 = { fn fputq(fd: i32, p: *u8, n: i32) void = {
fputc_byte(fd, 34u8); // '"' fputcbyte(fd, 34u8); // '"'
let i: i32 = 0; let i: i32 = 0;
for (i < n) { for (i < n) {
let c: u8 = p[i]; let c: u8 = p[i];
if (c == 92u8) { // '\\' if (c == 92u8) { // '\\'
fputs_str(fd, "\\\\"); fputsstr(fd, "\\\\");
} else { } else {
if (c == 34u8) { // '"' if (c == 34u8) { // '"'
fputs_str(fd, "\\\""); fputsstr(fd, "\\\"");
} else { } else {
if (c == 10u8) { // '\n' if (c == 10u8) { // '\n'
fputs_str(fd, "\\n"); fputsstr(fd, "\\n");
} else { } else {
if (c == 9u8) { // '\t' if (c == 9u8) { // '\t'
fputs_str(fd, "\\t"); fputsstr(fd, "\\t");
} else { } else {
if (c == 13u8) { // '\r' if (c == 13u8) { // '\r'
fputs_str(fd, "\\r"); fputsstr(fd, "\\r");
} else { } else {
if (c < 32u8) { if (c < 32u8) {
fputhex2(fd, c); fputhex2(fd, c);
@@ -328,7 +328,7 @@ fn fputq(fd: i32, p: *u8, n: i32) void = {
if (c == 127u8) { if (c == 127u8) {
fputhex2(fd, c); fputhex2(fd, c);
} else { } else {
fputc_byte(fd, c); fputcbyte(fd, c);
}; };
}; };
}; };
@@ -338,7 +338,7 @@ fn fputq(fd: i32, p: *u8, n: i32) void = {
}; };
i += 1; i += 1;
}; };
fputc_byte(fd, 34u8); fputcbyte(fd, 34u8);
}; };
// tokprint — write one token line to fd. Format must match // 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 tfile: str = t.file;
let ttext: str = t.text; let ttext: str = t.text;
if (tfile.len > 0) { if (tfile.len > 0) {
fputs_str(fd, tfile); fputsstr(fd, tfile);
} else { } else {
fputs_str(fd, "<none>"); fputsstr(fd, "<none>");
}; };
fputc_byte(fd, 58u8); // ':' fputcbyte(fd, 58u8); // ':'
let buf: [32]u8; let buf: [32]u8;
let n: i32 = strconv.i64toa(buf[0:32], t.line: i64); let n: i32 = strconv.i64toa(buf[0:32], t.line: i64);
os.write(fd, buf.ptr, n: u64); os.write(fd, buf.ptr, n: u64);
fputc_byte(fd, 58u8); fputcbyte(fd, 58u8);
n = strconv.i64toa(buf[0:32], t.col: i64); n = strconv.i64toa(buf[0:32], t.col: i64);
os.write(fd, buf.ptr, n: u64); os.write(fd, buf.ptr, n: u64);
fputc_byte(fd, 32u8); // ' ' fputcbyte(fd, 32u8); // ' '
fputs_str(fd, tokname(t.kind)); fputsstr(fd, tokname(t.kind));
if (t.kind == TK_IDENT) { if (t.kind == TK_IDENT) {
fputc_byte(fd, 32u8); fputcbyte(fd, 32u8);
fputq(fd, ttext.ptr, ttext.len); fputq(fd, ttext.ptr, ttext.len);
} else { if (t.kind == TK_STR) { } else { if (t.kind == TK_STR) {
fputc_byte(fd, 32u8); fputcbyte(fd, 32u8);
fputq(fd, ttext.ptr, ttext.len); fputq(fd, ttext.ptr, ttext.len);
} else { if (t.kind == TK_ERR) { } else { if (t.kind == TK_ERR) {
fputc_byte(fd, 32u8); fputcbyte(fd, 32u8);
fputq(fd, ttext.ptr, ttext.len); fputq(fd, ttext.ptr, ttext.len);
} else { if (t.kind == TK_INT) { } else { if (t.kind == TK_INT) {
fputc_byte(fd, 32u8); fputcbyte(fd, 32u8);
n = strconv.u64toa(buf[0:32], t.uval); n = strconv.u64toa(buf[0:32], t.uval);
os.write(fd, buf.ptr, n: u64); os.write(fd, buf.ptr, n: u64);
} else { if (t.kind == TK_RUNE) { } else { if (t.kind == TK_RUNE) {
fputc_byte(fd, 32u8); fputcbyte(fd, 32u8);
n = strconv.u64toa(buf[0:32], t.uval); n = strconv.u64toa(buf[0:32], t.uval);
os.write(fd, buf.ptr, n: u64); 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 // won't byte-match across implementations. Diff fixtures must
// be float-free until we implement a stable float formatter. // 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); 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); let t: *tinfo = newtype(a, TY_PTR);
t.sub = sub; t.sub = sub;
t.size = 8u64; t.size = 8u64;
@@ -161,7 +161,7 @@ export fn type_ptr(a: *arena, sub: *tinfo) *tinfo = {
return t; 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); let t: *tinfo = newtype(a, TY_SLICE);
t.sub = sub; t.sub = sub;
t.size = 24u64; t.size = 24u64;
@@ -169,7 +169,7 @@ export fn type_slice(a: *arena, sub: *tinfo) *tinfo = {
return t; 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); let t: *tinfo = newtype(a, TY_ARRAY);
t.sub = sub; t.sub = sub;
t.alen = n; t.alen = n;
@@ -182,7 +182,7 @@ export fn type_array(a: *arena, sub: *tinfo, n: u64) *tinfo = {
return t; 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); let t: *tinfo = newtype(a, TY_CHAN);
t.sub = sub; t.sub = sub;
t.size = 8u64; t.size = 8u64;
@@ -190,7 +190,7 @@ export fn type_chan(a: *arena, sub: *tinfo) *tinfo = {
return t; 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); let t: *tinfo = newtype(a, TY_NAMED);
t.name = name; t.name = name;
t.under = under; t.under = under;
@@ -203,7 +203,7 @@ export fn type_named(a: *arena, name: str, under: *tinfo) *tinfo = {
// ---- predicates ------------------------------------------------------- // ---- predicates -------------------------------------------------------
export fn type_isint(t: *tinfo) bool = { export fn typeisint(t: *tinfo) bool = {
if (t == nil) { return false; }; if (t == nil) { return false; };
let k: i32 = t.kind; let k: i32 = t.kind;
if (k == TY_I8) { return true; }; 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_RUNE){ return true; };
if (k == TY_UNTYPED_INT) { return true; }; if (k == TY_UNTYPED_INT) { return true; };
if (k == TY_UNTYPED_RUNE) { 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; return false;
}; };
export fn type_isfloat(t: *tinfo) bool = { export fn typeisfloat(t: *tinfo) bool = {
if (t == nil) { return false; }; if (t == nil) { return false; };
let k: i32 = t.kind; let k: i32 = t.kind;
if (k == TY_F32) { return true; }; if (k == TY_F32) { return true; };
if (k == TY_F64) { return true; }; if (k == TY_F64) { return true; };
if (k == TY_UNTYPED_FLOAT) { 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; return false;
}; };
export fn type_isnum(t: *tinfo) bool = { export fn typeisnum(t: *tinfo) bool = {
if (type_isint(t)) { return true; }; if (typeisint(t)) { return true; };
return type_isfloat(t); return typeisfloat(t);
}; };
export fn type_isunsigned(t: *tinfo) bool = { export fn typeisunsigned(t: *tinfo) bool = {
if (t == nil) { return false; }; if (t == nil) { return false; };
let k: i32 = t.kind; let k: i32 = t.kind;
if (k == TY_U8) { return true; }; 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_U64) { return true; };
if (k == TY_UINT){ return true; }; if (k == TY_UINT){ return true; };
if (k == TY_UINTPTR) { 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; return false;
}; };
export fn type_isuntyped(t: *tinfo) bool = { export fn typeisuntyped(t: *tinfo) bool = {
if (t == nil) { return false; }; if (t == nil) { return false; };
let k: i32 = t.kind; let k: i32 = t.kind;
if (k == TY_UNTYPED_INT) { return true; }; if (k == TY_UNTYPED_INT) { return true; };
@@ -264,29 +264,29 @@ export fn type_isuntyped(t: *tinfo) bool = {
return false; return false;
}; };
// type_eq — structural equality. Named types compare nominally. // typeeq — structural equality. Named types compare nominally.
export fn type_eq(a: *tinfo, b: *tinfo) bool = { export fn typeeq(a: *tinfo, b: *tinfo) bool = {
if (a == b) { return true; }; if (a == b) { return true; };
if (a == nil) { return false; }; if (a == nil) { return false; };
if (b == nil) { return false; }; if (b == nil) { return false; };
if (a.kind != b.kind) { return false; }; if (a.kind != b.kind) { return false; };
let k: i32 = a.kind; let k: i32 = a.kind;
if (k == TY_PTR) { return type_eq(a.sub, b.sub); }; if (k == TY_PTR) { return typeeq(a.sub, b.sub); };
if (k == TY_SLICE) { return type_eq(a.sub, b.sub); }; if (k == TY_SLICE) { return typeeq(a.sub, b.sub); };
if (k == TY_CHAN) { return type_eq(a.sub, b.sub); }; if (k == TY_CHAN) { return typeeq(a.sub, b.sub); };
if (k == TY_ARRAY) { if (k == TY_ARRAY) {
if (a.alen != b.alen) { return false; }; 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 (k == TY_FN) {
if (a.variadic != b.variadic) { return false; }; 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 pa: *tparam = a.params;
let pb: *tparam = b.params; let pb: *tparam = b.params;
for (true) { for (true) {
if (pa == nil) { if (pb == nil) { return true; }; return false; }; if (pa == nil) { if (pb == nil) { return true; }; return false; };
if (pb == nil) { 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; pa = pa.tnext;
pb = pb.tnext; pb = pb.tnext;
}; };
@@ -306,7 +306,7 @@ export fn type_eq(a: *tinfo, b: *tinfo) bool = {
if (na[i] != nb[i]) { return false; }; if (na[i] != nb[i]) { return false; };
i += 1; i += 1;
}; };
if (!type_eq(fa.type_, fb.type_)) { return false; }; if (!typeeq(fa.type_, fb.type_)) { return false; };
fa = fa.tnext; fa = fa.tnext;
fb = fb.tnext; fb = fb.tnext;
}; };
@@ -319,7 +319,7 @@ export fn type_eq(a: *tinfo, b: *tinfo) bool = {
for (true) { for (true) {
if (pa == nil) { if (pb == nil) { return true; }; return false; }; if (pa == nil) { if (pb == nil) { return true; }; return false; };
if (pb == nil) { 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; pa = pa.tnext;
pb = pb.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; let tc: tctx;
typesinit(&tc, a); typesinit(&tc, a);
let ck: checker; let ck: checker;
check_init(&ck, a, &tc); checkinit(&ck, a, &tc);
// Quiet by default; flip to 1 when debugging missing names. // Quiet by default; flip to 1 when debugging missing names.
ck.verbose = 0; ck.verbose = 0;
check_file(&ck, f); checkfile(&ck, f);
// (close out the if-else chain — we'll close all braces below) // (close out the if-else chain — we'll close all braces below)
// "<file>: <resolved>/<resolved+unresolved> resolved" // "<file>: <resolved>/<resolved+unresolved> resolved"
os.write(1, argstr(path).ptr, argstrlen(path): u64); 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); parserinit(&ps, a, &l);
let f: *node = parsefile(&ps); let f: *node = parsefile(&ps);
let cg: cgen; let cg: cgen;
cgen_init(&cg, a); cgeninit(&cg, a);
cg_file(&cg, f); cgfile(&cg, f);
};};};}; };};};};
if (l.errs > 0) { return 1; }; if (l.errs > 0) { return 1; };

View File

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