From c92d11e7484f7e1f67a9fdb64d0f457c42766117 Mon Sep 17 00:00:00 2001 From: agra Date: Mon, 15 Jun 2026 18:20:33 +0300 Subject: [PATCH] =?UTF-8?q?docs(asm):=20Phase=200.2=20=E2=80=94=20document?= =?UTF-8?q?=20.build=20sidecar;=20Phase=200=20complete?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CLAUDE.md §Testing + §Test-layout now describe the optional `.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). --- CLAUDE.md | 25 +++++++++++++++++++++---- current/CHECKPOINT-ASM.md | 19 ++++++++++++++----- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index e3f3023..4f000c7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -431,10 +431,12 @@ After any compiler change: - A test is still keyed off its `expected/.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/.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/.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: /expected/XXXX-category-name.stdout # normalized stdout /expected/XXXX-category-name.stderr # normalized stderr /expected/XXXX-category-name.ir # optional `sx ir` snapshot +/expected/XXXX-category-name.build # optional JSON build/run directives ``` A test is any `.sx` with an `expected/.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 `.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": ""` — 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. diff --git a/current/CHECKPOINT-ASM.md b/current/CHECKPOINT-ASM.md index 9123daf..0c2fae5 100644 --- a/current/CHECKPOINT-ASM.md +++ b/current/CHECKPOINT-ASM.md @@ -6,7 +6,13 @@ commit, one step at a time per the cadence rule (no commit may both add a test and make it pass). ## Last completed step -**0.1** — corpus runner **ir-only branch** for cross-target examples. Replaced +**0.2** — docs: CLAUDE.md §Testing + §Test-layout now document the +`.build` JSON sidecar (`aot` + `target` keys, ir-only arch-gating, +unknown-key-is-error) and list it alongside the other `expected/` files, +replacing the stale standalone `.aot` marker prose. Docs-only — no build impact. +**Phase 0 COMPLETE.** + +Prior: **0.1** — corpus runner **ir-only branch** for cross-target examples. Replaced 0.0's loud placeholder bail: when `cfg.target` doesn't match the host (`ir_only`), `sweepRoot` skips run/build/exec and verifies via `sx ir --target` only — asserting `.exit` (ir cmd) + `.ir` (normalized stdout) + `.stderr`, never @@ -30,10 +36,11 @@ in LLVM@19 `Core.h`; ERR-stream `extractvalue`→tuple in `emit_llvm.zig:726-927 lib-less `extern`, 60 sites; `--target` a global CLI flag). ## Next step -**0.2** — docs: update CLAUDE.md §"Testing"/§"Test layout" to document the -`.build` JSON config (`aot` + `target` keys, ir-only gating) replacing the -standalone `.aot` marker prose (~lines 435, 492). Then Phase A (`kw_asm` keyword + -lex test). See `PLAN-ASM.md` Phase 0 / Phase A. +**A.0** (Phase A — first compiler code) — add the `kw_asm` keyword: `Token.Tag` +entry + keyword `StaticStringMap` in `src/token.zig`, plus a unit lex test +(`asm → kw_asm`). `volatile`/`clobbers` stay out of the global table +(contextual). This is a **lock** commit (behavior-locking passing test). Then A.1 +(parse `asm { … }` → `AsmExpr`, lowering bails loudly). See `PLAN-ASM.md` Phase A. ## Log - (init) Plan + design doc written; ASM stream opened. @@ -44,6 +51,8 @@ lex test). See `PLAN-ASM.md` Phase 0 / Phase A. - (0.1) ir-only branch: cross-target examples verify via `sx ir --target` only (exit+ir+stderr, no stdout; `.ir` required). Locked with 1639 fixture; verified corrupt-.ir → mismatch and missing-.ir → loud failure. `zig build test` green. +- (0.2) docs: CLAUDE.md documents `.build` JSON sidecar (aot + target + + ir-only gating), replacing stale `.aot` marker prose. **Phase 0 COMPLETE.** ## Known issues None yet.