docs(asm): Phase 0.2 — document <name>.build sidecar; Phase 0 complete

CLAUDE.md §Testing + §Test-layout now describe the optional `<name>.build` JSON
config (aot + target keys, ir-only arch-gating, unknown-key-is-error) and list
it among the `expected/` files, replacing the stale standalone `.aot` marker
prose. Closes Phase 0 (corpus target-gating); next is Phase A (kw_asm keyword).
This commit is contained in:
agra
2026-06-15 18:20:33 +03:00
parent 0095584105
commit c92d11e748
2 changed files with 35 additions and 9 deletions

View File

@@ -431,10 +431,12 @@ After any compiler change:
- A test is still keyed off its `expected/<name>.exit` marker, so seed an
empty marker first for a brand-new example (see "Adding a feature").
`zig build test` is the only way to run the corpus — there is no standalone
shell runner (the legacy `tests/run_examples.sh` was removed). An
`expected/<name>.aot` marker switches an example from JIT `sx run` to a
`sx build` + execute flow (needed to exercise a C-ABI symbol exported FROM sx
a JIT-resident symbol is invisible to a dlopen'd C dylib).
shell runner (the legacy `tests/run_examples.sh` was removed). Per-example
build/run directives live in an optional `expected/<name>.build` **JSON** sidecar
(see "Test layout" below): `{ "aot": true }` switches an example from JIT `sx run`
to a `sx build` + execute flow (needed to exercise a C-ABI symbol exported FROM sx
— a JIT-resident symbol is invisible to a dlopen'd C dylib); `{ "target":
"x86_64-linux" }` threads `--target` and arch-gates the example.
### Test layout
@@ -453,6 +455,7 @@ split into three streams (no more merged `2>&1`) plus an optional IR snapshot:
<root>/expected/XXXX-category-name.stdout # normalized stdout
<root>/expected/XXXX-category-name.stderr # normalized stderr
<root>/expected/XXXX-category-name.ir # optional `sx ir` snapshot
<root>/expected/XXXX-category-name.build # optional JSON build/run directives
```
A test is any `<name>.sx` with an `expected/<name>.exit` marker. The runner
@@ -460,6 +463,20 @@ scans two roots: `examples/` (the feature suite) and `issues/` (pinned bug
repros). Multi-file tests keep companions (`.c`/`.h`, imported `.sx`, fixture
dirs) under the same `XXXX-` prefix.
The optional `<name>.build` JSON sidecar carries per-example directives
(unknown keys are a hard error — never silently ignored):
- `"aot": true` — build a native binary and execute it instead of JIT `sx run`.
- `"target": "<triple|shorthand>"` — thread `--target` into every `sx`
invocation and gate on the host. If the target's arch+os **match** the host,
the example runs normally; if they **mismatch** (e.g. `x86_64-linux` on an
aarch64 host), the runner switches to **ir-only** mode — it skips
run/build/exec and asserts only `.exit` + `.ir` + `.stderr` from
`sx ir --target` (`.stdout` is not asserted). An `.ir` snapshot is **required**
in ir-only mode (its absence is a loud failure). This is how arch-pinned
examples (e.g. x86_64 inline-asm) are tested on a non-matching dev host while
still running end-to-end on a matching CI runner.
### Snapshot integrity
**Never regenerate snapshots while tests are failing.** `-Dupdate-goldens` (and the legacy `--update`) blindly overwrite expected output with whatever the compiler produces — including error messages. If you regenerate during a broken state, the test suite will "pass" against garbage output and real regressions become invisible.