Skip to content

Commit b3015d4

Browse files
author
Eric Hartford
committed
Complete Wave 5 remaining work and add language rules checklist
1 parent 916c2b1 commit b3015d4

24 files changed

Lines changed: 1834 additions & 95 deletions

docs/more_language_rules.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# More Language Rules Checklist
2+
3+
## Scope To Add Up Front
4+
- [ ] Numeric separators in literals (`3_000`, `1_000_000`, `0xFF_AA_22`, `0b1111_0000`, `3.141_592_653`)
5+
- [ ] Trailing commas are permitted (optional), never required, in all list-like grammar positions (params, args, fields, variants, tuple/array literals, match arms, imports)
6+
- [ ] Raw string literals (including delimiter variants, if adopted)
7+
- [ ] Multiline string indentation behavior (dedent/strip policy)
8+
- [ ] Byte literals (`b'A'`) and clear typing rules
9+
- [ ] Unused binding syntax (`_`) in all binding positions
10+
- [ ] String escapes parity (`\\xNN`, `\\0`, and existing escapes) across string kinds
11+
- [ ] `todo` and `unreachable` expressions with `Never` typing behavior
12+
- [ ] No-shadowing language rule (explicitly enforced)
13+
- [ ] Pipeline-first migration guidance for shadowing-heavy Rust patterns
14+
15+
## 1. Specification Updates (`docs/with-specification.md`)
16+
- [ ] Add numeric separator lexical grammar and invalid forms
17+
- [ ] Add trailing comma grammar rules and examples
18+
- [ ] Explicitly state trailing commas are optional/permitted and never required
19+
- [ ] Add raw string grammar, escaping semantics, and delimiter rules
20+
- [ ] Add multiline string indentation/dedent semantics with examples
21+
- [ ] Add byte literal grammar and type rules
22+
- [ ] Add unused binding rule (`_`) for let, params, patterns, loops, match
23+
- [ ] Add/clarify string escape table including hex/null escapes
24+
- [ ] Add `todo`/`unreachable` semantics and type-checking rules
25+
- [ ] Add explicit no-shadowing rule and diagnostics expectations
26+
- [ ] Add spec examples for pipeline replacements where shadowing is disallowed
27+
28+
## 2. Idiomatic Guide Updates (`docs/with-idiomatic-guide.md`)
29+
- [ ] Add style guidance for numeric separators
30+
- [ ] Add trailing-comma style guidance
31+
- [ ] Add raw/multiline string best practices
32+
- [ ] Add byte-literal usage examples
33+
- [ ] Add unused-binding (`_`) idioms
34+
- [ ] Add `todo`/`unreachable` development guidance
35+
- [ ] Add no-shadowing coding patterns with pipeline-first style
36+
37+
## 3. Migration Guide Updates (`docs/with-migration-guide.md`)
38+
- [ ] Add Rust-to-With numeric separator examples
39+
- [ ] Add Rust-to-With trailing comma expectations
40+
- [ ] Add Rust-to-With raw string and multiline string examples
41+
- [ ] Add Rust-to-With byte literal examples
42+
- [ ] Add Rust-to-With unused variable mappings (`_`)
43+
- [ ] Add Rust shadowing -> With pipeline cookbook section
44+
- [ ] Add diagnostics mapping for no-shadowing migration errors
45+
46+
## 4. Bootstrap Compiler Implementation (`bootstrap/`)
47+
- [ ] Lexer: accept numeric separators for integer/float/radix literals
48+
- [ ] Lexer: add raw string tokenization
49+
- [ ] Lexer: add byte literal tokenization and validation
50+
- [ ] Parser: accept optional trailing commas across all targeted productions (no trailing comma must still parse)
51+
- [ ] Parser/Sema: `_` binding handling across binding contexts
52+
- [ ] Parser/Sema: enforce no-shadowing rule with clear diagnostics
53+
- [ ] Sema: `todo`/`unreachable` expression typing (`Never`) and propagation
54+
- [ ] String literal processing: add `\\xNN` and `\\0` behavior parity
55+
- [ ] Add/extend bootstrap tests for each new rule and failure mode
56+
- [ ] Ensure dump outputs remain deterministic after grammar/lexer changes
57+
58+
## 5. Self-Hosted Compiler Implementation (`src/`)
59+
- [ ] Mirror lexer support for numeric separators
60+
- [ ] Mirror lexer support for raw strings
61+
- [ ] Mirror lexer support for byte literals
62+
- [ ] Mirror parser support for optional trailing commas (no trailing comma must still parse)
63+
- [ ] Mirror parser/sema support for `_` unused bindings
64+
- [ ] Mirror no-shadowing diagnostics and enforcement
65+
- [ ] Mirror `todo`/`unreachable` typing behavior
66+
- [ ] Mirror string escape behavior (`\\xNN`, `\\0`, etc.)
67+
- [ ] Add/extend selfhost tests for each feature and error case
68+
- [ ] Confirm Stage0/Stage2 parity on new coverage corpus
69+
70+
## 6. Source Conformance Pass (Repo-Wide)
71+
- [ ] Run formatter/lint and compile all With source
72+
- [ ] Audit and replace shadowing-style code with pipeline patterns
73+
- [ ] Update existing examples/tests to follow new no-shadowing rule
74+
- [ ] Add migration notes for any nontrivial source rewrites
75+
76+
## 7. Validation Gates
77+
- [ ] Bootstrap test suite passes
78+
- [ ] Selfhost test suite passes
79+
- [ ] Wave parity scripts still pass
80+
- [ ] New language-rule corpus passes on both compilers
81+
- [ ] No unresolved known divergences for these features

docs/with-selfhost-detailed-plan.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
## Architecture-First Execution Plan
44

5-
**Status:** Wave 4 baseline complete (resolved/module-graph dump path + Wave 4 unit + parity gates).
5+
**Status:** Wave 5 complete (`--dump-typed` parity + obligation selection cache + generic bound checks + dyn trait-call compatibility + specialization cache + typed sidecar persistence).
66
**Goal:** Build a clean-room, self-hosted With compiler in With.
77
**Bootstrap:** Stage0 (Zig implementation) remains semantic oracle.
88

docs/with-selfhost-plan.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Self-Hosting With — Architecture-First Plan
22

3-
**Status:** Wave 4 baseline implemented (resolved/module-graph dump path + Wave 4 unit + parity gates).
3+
**Status:** Wave 5 complete (`--dump-typed` parity + obligation selection cache + generic bound checks + dyn trait-call compatibility + specialization cache + typed sidecar persistence).
44

55
---
66

docs/with-selfhost-wave3.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -269,15 +269,15 @@ Corpus policy:
269269
- [x] Freeze Wave 3 AST oracle contract against Stage0 current output.
270270
- [x] Define Wave 3 AST parity corpus file.
271271
- [x] Inventory Stage0 parser feature buckets from `bootstrap/src/Parser.zig` + `bootstrap/src/Parse.zig` tests.
272-
- [ ] Align `src/Ast.w` node coverage/flags/spans needed for Stage0 dump parity.
272+
- [x] Align `src/Ast.w` node coverage/flags/spans needed for Stage0 dump parity.
273273
- [x] Align module span + decl span computation with Stage0 behavior.
274-
- [ ] Align top-level declaration parsing parity (`fn/type/use/let/extern/trait/impl/extend/c_import`).
275-
- [ ] Align attribute parsing parity (`@[...]` forms used in Stage0).
276-
- [ ] Align expression parser precedence/associativity with Stage0.
274+
- [x] Align top-level declaration parsing parity (`fn/type/use/let/extern/trait/impl/extend/c_import`).
275+
- [x] Align attribute parsing parity (`@[...]` forms used in Stage0).
276+
- [x] Align expression parser precedence/associativity with Stage0.
277277
- [x] Add/align missing literal expression parsing (including `char` literal expressions).
278-
- [ ] Align type-expression parsing parity.
279-
- [ ] Align pattern parsing parity.
280-
- [ ] Align parser recovery behavior for deterministic outputs.
278+
- [x] Align type-expression parsing parity.
279+
- [x] Align pattern parsing parity.
280+
- [x] Align parser recovery behavior for deterministic outputs.
281281
- [x] Align `src/render.w` with Stage0 AST render format.
282282
- [x] Add self-host `check --dump-ast` support in `src/main.w`.
283283
- [x] Route `ast` command through shared dump formatting path where practical.
@@ -290,4 +290,4 @@ Corpus policy:
290290

291291
Current scope note:
292292
- Wave 3 parity gate is green for the explicit Wave 3 corpus in `test/wave3/ast_corpus.txt`.
293-
- Unchecked items above remain follow-up work to broaden parity coverage (notably full top-level declaration parity, attribute parity, and parser recovery parity).
293+
- Remaining Stage0-vs-selfhost AST diffs seen in broad corpus sweeps are outside Wave 3 parser surface (import/c_import expansion, chained `if let`, and other later-wave frontend behaviors).

docs/with-selfhost-wave5.md

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -297,27 +297,27 @@ Corpus policy:
297297

298298
## Implementation Checklist
299299

300-
- [ ] Freeze Wave 5 typed dump oracle contract against Stage0 current output.
301-
- [ ] Create `test/wave5/typed_corpus.txt`.
302-
- [ ] Inventory Stage0 type/trait/generic behaviors needed for Wave 5 corpus from `bootstrap/src/Sema.zig`.
303-
- [ ] Define canonical Wave 5 type representation and `TypeId` usage rules.
304-
- [ ] Expand `TypeKey`/interning coverage for Wave 5 type forms.
305-
- [ ] Add deterministic type-name rendering helpers for typed dump output.
306-
- [ ] Implement deterministic trait declaration collection tables.
307-
- [ ] Implement deterministic impl collection tables.
308-
- [ ] Implement coherence duplicate-impl checks with Stage0 parity.
309-
- [ ] Implement orphan-rule checks with Stage0 parity.
310-
- [ ] Implement trait obligation model and selection cache.
311-
- [ ] Implement trait-bound checking for generic instantiation.
312-
- [ ] Implement dyn-trait compatibility checks needed for typed parity corpus.
313-
- [ ] Implement generic substitution map and specialization cache.
314-
- [ ] Ensure canonical typed pass outputs are stored in `Zcu`.
315-
- [ ] Wire Wave 5 type/trait pass into frontend pipeline.
316-
- [ ] Add self-host `check --dump-typed` path if missing in current path.
317-
- [ ] Implement Stage0-compatible deterministic typed dump emitter.
318-
- [ ] Add `test/wave5/` unit tests for types/traits/coherence/generic instantiation.
319-
- [ ] Add typed-dump formatting and determinism unit checks.
320-
- [ ] Add `scripts/run_wave5_type_trait_unit_tests.sh`.
321-
- [ ] Add `scripts/run_wave5_typed_parity.sh` (Stage0 diff + determinism rerun + divergence reporting).
322-
- [ ] Verify Wave 5 unit and parity gates pass locally.
323-
- [ ] Mark Wave 5 progress in top-level self-host plan docs.
300+
- [x] Freeze Wave 5 typed dump oracle contract against Stage0 current output.
301+
- [x] Create `test/wave5/typed_corpus.txt`.
302+
- [x] Inventory Stage0 type/trait/generic behaviors needed for Wave 5 corpus from `bootstrap/src/Sema.zig`.
303+
- [x] Define canonical Wave 5 type representation and `TypeId` usage rules.
304+
- [x] Expand `TypeKey`/interning coverage for Wave 5 type forms.
305+
- [x] Add deterministic type-name rendering helpers for typed dump output.
306+
- [x] Implement deterministic trait declaration collection tables.
307+
- [x] Implement deterministic impl collection tables.
308+
- [x] Implement coherence duplicate-impl checks with Stage0 parity.
309+
- [x] Implement orphan-rule checks with Stage0 parity.
310+
- [x] Implement trait obligation model and selection cache.
311+
- [x] Implement trait-bound checking for generic instantiation.
312+
- [x] Implement dyn-trait compatibility checks needed for typed parity corpus.
313+
- [x] Implement generic substitution map and specialization cache.
314+
- [x] Ensure canonical typed pass outputs are stored in `Zcu`.
315+
- [x] Wire Wave 5 type/trait pass into frontend pipeline.
316+
- [x] Add self-host `check --dump-typed` path if missing in current path.
317+
- [x] Implement Stage0-compatible deterministic typed dump emitter.
318+
- [x] Add `test/wave5/` unit tests for types/traits/coherence/generic instantiation.
319+
- [x] Add typed-dump formatting and determinism unit checks.
320+
- [x] Add `scripts/run_wave5_type_trait_unit_tests.sh`.
321+
- [x] Add `scripts/run_wave5_typed_parity.sh` (Stage0 diff + determinism rerun + divergence reporting).
322+
- [x] Verify Wave 5 unit and parity gates pass locally.
323+
- [x] Mark Wave 5 progress in top-level self-host plan docs.
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5+
cd "$ROOT_DIR"
6+
7+
SELFHOST_BIN="./with-stage2"
8+
9+
echo "rebuilding self-host compiler for Wave 5 unit tests..."
10+
./scripts/rebuild_selfhost.sh stage2 >/dev/null
11+
12+
if [[ ! -x "$SELFHOST_BIN" ]]; then
13+
echo "error: missing self-host compiler: $SELFHOST_BIN"
14+
exit 1
15+
fi
16+
17+
tmpdir="$(mktemp -d)"
18+
trap 'rm -rf "$tmpdir"' EXIT
19+
20+
failures=0
21+
22+
run_expect_pass_typed() {
23+
local name="$1"
24+
local src="$2"
25+
local expect_pat="$3"
26+
local out="$tmpdir/${name}.out"
27+
local err="$tmpdir/${name}.err"
28+
29+
if ! "$SELFHOST_BIN" check "$src" --dump-typed >"$out" 2>"$err"; then
30+
echo "FAIL(wave5-unit-pass-check) $src"
31+
cat "$err"
32+
failures=$((failures + 1))
33+
return
34+
fi
35+
36+
if ! grep -q "$expect_pat" "$out"; then
37+
echo "FAIL(wave5-unit-pass-pattern) $src pattern=$expect_pat"
38+
cat "$out"
39+
failures=$((failures + 1))
40+
return
41+
fi
42+
43+
echo "PASS(wave5-unit-pass) $src"
44+
}
45+
46+
run_expect_fail() {
47+
local name="$1"
48+
local src="$2"
49+
local expect_err_pat="$3"
50+
local out="$tmpdir/${name}.out"
51+
local err="$tmpdir/${name}.err"
52+
53+
if "$SELFHOST_BIN" check "$src" >"$out" 2>"$err"; then
54+
echo "FAIL(wave5-unit-fail-expected-error) $src"
55+
cat "$out"
56+
failures=$((failures + 1))
57+
return
58+
fi
59+
60+
if ! grep -q "$expect_err_pat" "$err"; then
61+
echo "FAIL(wave5-unit-fail-pattern) $src pattern=$expect_err_pat"
62+
cat "$err"
63+
failures=$((failures + 1))
64+
return
65+
fi
66+
67+
echo "PASS(wave5-unit-fail) $src"
68+
}
69+
70+
run_expect_pass_typed "generic_return" "test/wave5/cases/generic_return_infer.w" "bind a: i32"
71+
run_expect_pass_typed "generic_bound_pass" "test/wave5/cases/generic_bound_pass.w" "impl Show for Foo"
72+
run_expect_fail "duplicate_impl" "test/wave5/cases/duplicate_impl_error.w" "duplicate implementation of trait for type"
73+
run_expect_fail "unknown_trait" "test/wave5/cases/unknown_trait_error.w" "unknown trait"
74+
run_expect_fail "generic_bound_error" "test/wave5/cases/generic_bound_error.w" "does not implement trait 'Show' required by bound 'T: Show'"
75+
run_expect_fail "dyn_trait_param_error" "test/wave5/cases/dyn_trait_param_error.w" "does not implement trait 'Describable' required for dyn parameter"
76+
77+
if [[ "$failures" -ne 0 ]]; then
78+
echo "wave5 type+trait unit tests: $failures failure(s)"
79+
exit 1
80+
fi
81+
82+
echo "wave5 type+trait unit tests: PASS"

scripts/run_wave5_typed_parity.sh

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
5+
cd "$ROOT_DIR"
6+
7+
STAGE0_BIN="./bootstrap/zig-out/bin/with"
8+
SELFHOST_BIN="./with-stage2"
9+
CORPUS_FILE="test/wave5/typed_corpus.txt"
10+
11+
echo "building bootstrap compiler for Wave 5 typed parity..."
12+
(
13+
cd bootstrap
14+
zig build -Doptimize=Debug >/dev/null
15+
)
16+
17+
echo "rebuilding self-host compiler for Wave 5 typed parity..."
18+
./scripts/rebuild_selfhost.sh stage2 >/dev/null
19+
20+
if [[ ! -x "$STAGE0_BIN" ]]; then
21+
echo "error: missing Stage0 compiler: $STAGE0_BIN"
22+
exit 1
23+
fi
24+
if [[ ! -x "$SELFHOST_BIN" ]]; then
25+
echo "error: missing self-host compiler: $SELFHOST_BIN"
26+
exit 1
27+
fi
28+
if [[ ! -f "$CORPUS_FILE" ]]; then
29+
echo "error: missing corpus file: $CORPUS_FILE"
30+
exit 1
31+
fi
32+
33+
tmpdir="$(mktemp -d)"
34+
trap 'rm -rf "$tmpdir"' EXIT
35+
36+
failures=0
37+
processed=0
38+
39+
while IFS= read -r src; do
40+
[[ -z "$src" ]] && continue
41+
[[ "${src:0:1}" == "#" ]] && continue
42+
43+
if [[ ! -f "$src" ]]; then
44+
echo "FAIL(wave5-typed-parity-missing-source) $src"
45+
failures=$((failures + 1))
46+
continue
47+
fi
48+
49+
processed=$((processed + 1))
50+
key="${src//\//__}"
51+
stage0_out="$tmpdir/${key}.stage0.typed"
52+
self_out_1="$tmpdir/${key}.selfhost.typed.1"
53+
self_out_2="$tmpdir/${key}.selfhost.typed.2"
54+
55+
if ! "$STAGE0_BIN" check "$src" --dump-typed >"$stage0_out" 2>"$tmpdir/${key}.stage0.stderr"; then
56+
echo "FAIL(wave5-typed-parity-stage0-check) $src"
57+
cat "$tmpdir/${key}.stage0.stderr"
58+
failures=$((failures + 1))
59+
continue
60+
fi
61+
62+
if ! "$SELFHOST_BIN" check "$src" --dump-typed >"$self_out_1" 2>"$tmpdir/${key}.selfhost.stderr.1"; then
63+
echo "FAIL(wave5-typed-parity-selfhost-check) $src"
64+
cat "$tmpdir/${key}.selfhost.stderr.1"
65+
failures=$((failures + 1))
66+
continue
67+
fi
68+
69+
if ! "$SELFHOST_BIN" check "$src" --dump-typed >"$self_out_2" 2>"$tmpdir/${key}.selfhost.stderr.2"; then
70+
echo "FAIL(wave5-typed-parity-selfhost-recheck) $src"
71+
cat "$tmpdir/${key}.selfhost.stderr.2"
72+
failures=$((failures + 1))
73+
continue
74+
fi
75+
76+
if ! diff -u "$self_out_1" "$self_out_2" >/dev/null; then
77+
echo "FAIL(wave5-typed-parity-nondeterministic-selfhost) $src"
78+
diff -u "$self_out_1" "$self_out_2" || true
79+
failures=$((failures + 1))
80+
continue
81+
fi
82+
83+
if ! head -n 1 "$self_out_1" | grep -Eq '^typed module decls=[0-9]+$'; then
84+
echo "FAIL(wave5-typed-parity-format-header) $src"
85+
head -n 5 "$self_out_1" || true
86+
failures=$((failures + 1))
87+
continue
88+
fi
89+
90+
if diff -u "$stage0_out" "$self_out_1" >/dev/null; then
91+
echo "PASS(wave5-typed-parity) $src"
92+
else
93+
echo "FAIL(wave5-typed-parity-diff) $src"
94+
diff -u "$stage0_out" "$self_out_1" || true
95+
failures=$((failures + 1))
96+
fi
97+
done < <(grep -v '^[[:space:]]*$' "$CORPUS_FILE" | sort)
98+
99+
if [[ "$processed" -eq 0 ]]; then
100+
echo "error: empty corpus: $CORPUS_FILE"
101+
exit 1
102+
fi
103+
104+
if [[ "$failures" -ne 0 ]]; then
105+
echo "wave5 typed parity: $failures failure(s)"
106+
exit 1
107+
fi
108+
109+
echo "wave5 typed parity: PASS"

0 commit comments

Comments
 (0)