lib/ww,wcc: consolidate frontend into one syntax package (Go-compiler model, #74)
The ww compiler frontend was split across packages lex (lex+tok), ww
(ast+sym+typ), and parse — mirroring Hare's ref/hare/hare/{ast,lex,parse}.
That split's only payoff is third-party reuse, which ww has zero of: the
frontend is consumed by exactly one client, the wcc backend. The split's
cost is a wide cross-package export surface — every fn over a sibling
package's type must export it, and under separate compilation that
re-triggers check_exported_type, plus a phantom `import tok;` (tok lives
in package lex). Consolidate into ONE package lib/ww/syntax/, modelled on
Go's cmd/compile/internal/syntax. The 9 files move in (package syntax);
the intra-frontend mutual references become same-package; wcc and the
tool mains import syntax. No cstage C change (the C frontend mangles from
the source package clause). Internal data shapes (AST kinds, token model,
lexer/parser state) still mirror ref/hare/hare per rule 6/12 — only the
module decomposition collapses; the stdlib is untouched.
USER-approved (#74); spec .ai/rob-frontend-reorg.md (drew2 fidelity-
confirmed). Rule-6 carve-out documented in CLAUDE.md. Dissolves the tok
phantom import; collapses the intra-frontend export sprawl. Byte-id
rebaseline (lex.X/parse.X/ww.X -> syntax.X); cs==ww held. The residual
syntax->wcc export surface (10 types) + the unqualified-ref question are
separate follow-ups (#72/#75).
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
// lib/ww/ast.ww — port of cmd/wcc/ast.c (Node defs + printer).
|
||||
// lib/ww/syntax/ast.ww — port of cmd/wcc/ast.c (Node defs + printer).
|
||||
//
|
||||
// Status: AST printer is fully ported. Constructor `newnode` is here.
|
||||
// The parser (parse.ww) is currently minimal — see its file header.
|
||||
@@ -7,11 +7,10 @@
|
||||
// by value (8 *node pointers + 2 strs + a few ints), so callers always
|
||||
// hand around `*node`. Only `newnode` allocates and returns a *node.
|
||||
|
||||
package ww;
|
||||
package syntax;
|
||||
|
||||
import os;
|
||||
import strconv;
|
||||
import tok;
|
||||
|
||||
// ---- Nkind ------------------------------------------------------------
|
||||
//
|
||||
@@ -1,6 +1,6 @@
|
||||
// asttest — functional-equivalence pin for [[nkname]] after the
|
||||
// if-ladder → switch fold (struct fold S2). Run with
|
||||
// `ww run lib/ww/asttest.ww`.
|
||||
// `ww run -I lib/ww lib/ww/syntax/asttest.ww`.
|
||||
//
|
||||
// nkname is checked against every nkind value (the full ladder the
|
||||
// switch replaced) plus the out-of-band fallback ("?"). A failing row
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
package main;
|
||||
|
||||
import ast;
|
||||
import syntax;
|
||||
|
||||
|
||||
fn checkname(k: nkind, want: str) void = {
|
||||
@@ -1,10 +1,9 @@
|
||||
// lib/ww/parse/decl.ww — declaration parsing, split out of parse.ww.
|
||||
// lib/ww/syntax/decl.ww — declaration parsing, split out of parse.ww.
|
||||
|
||||
package parse;
|
||||
package syntax;
|
||||
|
||||
import os;
|
||||
import strings;
|
||||
import tok;
|
||||
|
||||
// `import encoding.utf8;` — the driver resolves the dotted path to
|
||||
// a directory; only the leaf (`utf8`) is needed downstream as the
|
||||
@@ -1,9 +1,8 @@
|
||||
// lib/ww/parse/expr.ww — expression parsing, split out of parse.ww.
|
||||
// lib/ww/syntax/expr.ww — expression parsing, split out of parse.ww.
|
||||
|
||||
package parse;
|
||||
package syntax;
|
||||
|
||||
import os;
|
||||
import tok;
|
||||
|
||||
// streqlocal — str-to-str compare. Inlined here to avoid a cross-
|
||||
// module `use sym;` for one call site.
|
||||
@@ -1,4 +1,4 @@
|
||||
// lib/ww/lex/lex.ww — port of cmd/wcc/lex.c.
|
||||
// lib/ww/syntax/lex.ww — port of cmd/wcc/lex.c.
|
||||
//
|
||||
// The DFA, the helpers, and the order of decisions all mirror the C
|
||||
// version exactly. The 990_selfhost test diffs the resulting token
|
||||
@@ -11,10 +11,8 @@
|
||||
// in shape, not in observable behaviour. Token kind values stay
|
||||
// numerically identical.
|
||||
|
||||
package lex;
|
||||
package syntax;
|
||||
|
||||
// Sibling import (tok) auto-resolves via task #22 dir-enum when
|
||||
// callers `import lex;` (which dir-enums lib/ww/lex/).
|
||||
import os;
|
||||
import ascii;
|
||||
import strings;
|
||||
@@ -1,4 +1,4 @@
|
||||
// lib/ww/parse/parse.ww — port of cmd/wcc/parse.c (entry + plumbing).
|
||||
// lib/ww/syntax/parse.ww — port of cmd/wcc/parse.c (entry + plumbing).
|
||||
//
|
||||
// Split into Hare-style submodule: parse.ww (here) holds the parser
|
||||
// struct, lexer plumbing, parsetype, parsefile (entry). Expression,
|
||||
@@ -10,14 +10,12 @@
|
||||
// stores the current token as flat primitive fields rather than a
|
||||
// nested `tok` struct; `refill` copies a freshly lexed token in.
|
||||
|
||||
package parse;
|
||||
package syntax;
|
||||
|
||||
// Sibling imports (expr, stmt, decl) auto-resolve via task #22
|
||||
// dir-enum when callers `import parse;` (which dir-enums
|
||||
// lib/ww/parse/).
|
||||
// Sibling files (expr, stmt, decl) are the same `package syntax`,
|
||||
// auto-resolved via task #22 dir-enum of lib/ww/syntax/.
|
||||
import os;
|
||||
import strings;
|
||||
import tok;
|
||||
|
||||
type parser = struct {
|
||||
l: *lex,
|
||||
@@ -1,9 +1,8 @@
|
||||
// lib/ww/parse/stmt.ww — statement parsing, split out of parse.ww.
|
||||
// lib/ww/syntax/stmt.ww — statement parsing, split out of parse.ww.
|
||||
|
||||
package parse;
|
||||
package syntax;
|
||||
|
||||
import os;
|
||||
import tok;
|
||||
|
||||
fn parseletlocal(p: *parser) *node = {
|
||||
let pf = p.curfile;
|
||||
@@ -1,10 +1,10 @@
|
||||
// lib/ww/sym.ww — port of cmd/wcc/sym.c.
|
||||
// lib/ww/syntax/sym.ww — port of cmd/wcc/sym.c.
|
||||
//
|
||||
// Per-scope hashtable, chained to the parent. Lookup walks up.
|
||||
// Plan 9 / Hare flavoured. Duplicate definitions in the same scope
|
||||
// return nil; the caller flags the error.
|
||||
|
||||
package ww;
|
||||
package syntax;
|
||||
|
||||
// Symbol kinds — must stay numerically aligned with cmd/wcc/ww.h Skind.
|
||||
type skind = enum i32 {
|
||||
@@ -108,11 +108,10 @@ export fn scopelookup(s: *scope, name: str) *sym = {
|
||||
// Same FNV bucket + hashnext chain + parent walk as scopelookup, with
|
||||
// an `skind == SK_TYPE` filter. Used to disambiguate the bare-TNAME
|
||||
// vs imported-module-bareword collision: when scopelookup returns the
|
||||
// SK_USE sym for a leaf that ALSO names a type (e.g. `tok` struct
|
||||
// declared in lib/ww/lex/tok.ww with `package lex;` while
|
||||
// `import tok;` registers a same-name SK_USE), the resolver needs
|
||||
// the type entry — the struct's mod may differ from the leaf (lex/tok
|
||||
// pair) so scopelookupinmodule(c, leaf, leaf) won't find it.
|
||||
// SK_USE sym for a leaf that ALSO names a type (a same-name `import X;`
|
||||
// SK_USE shadowing a struct X declared in another module), the resolver
|
||||
// needs the type entry — the struct's mod may differ from the leaf so
|
||||
// scopelookupinmodule(c, leaf, leaf) won't find it.
|
||||
//
|
||||
// #58/#50: within each scope, Pass-1 prefers an SK_TYPE whose `sym.mod`
|
||||
// matches `mod`; Pass-2 falls back to the first SK_TYPE regardless of
|
||||
@@ -1,4 +1,4 @@
|
||||
// lib/ww/lex/tok.ww — port of cmd/wcc/tok.c plus the Tkind /
|
||||
// lib/ww/syntax/tok.ww — port of cmd/wcc/tok.c plus the Tkind /
|
||||
// Tok / Pos shapes from cmd/wcc/ww.h.
|
||||
//
|
||||
// Token kind values must stay numerically equal to the C side: the
|
||||
@@ -9,7 +9,7 @@
|
||||
// Bottom of file: tokprint, which emits one token per line in a
|
||||
// format identical to cmd/wcc/tok.c:tokprint().
|
||||
|
||||
package lex;
|
||||
package syntax;
|
||||
|
||||
import os;
|
||||
import strconv;
|
||||
@@ -1,7 +1,7 @@
|
||||
// toktest — functional-equivalence pin for [[tokname]], [[kwlookup]]
|
||||
// (struct fold S1) and [[tokprint]]/fputq (struct fold S9, the
|
||||
// if-ladder → switch folds in tok.ww).
|
||||
// Run with `ww run -I lib/ww/lex lib/ww/lex/toktest.ww`.
|
||||
// Run with `ww run -I lib/ww lib/ww/syntax/toktest.ww`.
|
||||
//
|
||||
// tokname is checked against every tkind value (the full ladder the
|
||||
// switch replaced, plus the unknown-kind fallback); kwlookup is
|
||||
@@ -22,8 +22,7 @@
|
||||
package main;
|
||||
|
||||
import os;
|
||||
import tok;
|
||||
import lex;
|
||||
import syntax;
|
||||
|
||||
|
||||
fn checkname(k: tkind, want: str) void = {
|
||||
@@ -1,4 +1,4 @@
|
||||
// lib/ww/typ.ww — port of cmd/wcc/type.c.
|
||||
// lib/ww/syntax/typ.ww — port of cmd/wcc/type.c.
|
||||
//
|
||||
// Status: full structural port. The C version uses module-globals for
|
||||
// the primitive types (tyvoid, tyi32, …); ww doesn't have writable
|
||||
@@ -6,7 +6,7 @@
|
||||
// the checker passes around explicitly. typesinit fills the tctx
|
||||
// once per program.
|
||||
|
||||
package ww;
|
||||
package syntax;
|
||||
|
||||
import os;
|
||||
|
||||
Reference in New Issue
Block a user