English · Українська · Deutsch
There is a single test: tests/conformance_test.rs. It is a blind adapter — one fixed parse → macro-expand → compile → assemble → simulate → decode → compare pipeline that runs against every fixture unmodified, rather than a bespoke check per fixture. This mirrors fpga-lisp's First Blind Fixture discipline: no fixture-specific branches are allowed inside the adapter itself.
Fixtures are not owned by this repo — they live in the sibling my-lisp repository at tests/fixtures/conformance.my, one alist per line: ((expr . "(quote radio)") (expected . "radio") (tier . 1)), or for fixtures that must fail statically or at runtime, ((expr . "...") (error . "Arity") (tier . 1)).
Pipeline, in order:
- Filter — only lines tagged
(tier . 1)run today;3.0-bearing fixtures are skipped (fpga-lisp's ISA has no inexact/rational tag yet — plan item 25, not started). - Parse —
cml::parser::parse. - Macro-expand —
cml::macros::MacroExpanderruns before anything else touches the AST;defmacronever reaches the compiler. - Static-error check —
static_errorclassifies arity/unknown-symbol failures the compiler's front end can see without running anything. If the fixture expects one of these, the test asserts the match and stops there. - Compile —
cml::compiler::Compilerlowers the expanded AST to fpga-lisp assembly text. - Assemble — shells out to
python3 ../fpga-lisp/assembler.py, producing a.bin. - Simulate — copies the
.bininto fpga-lisp'sfpga/sim/and runsvvp tb_cml_e2e.vvp +bin_file=...(requires Icarus Verilog); this testbench is fpga-lisp's general-purpose E2E harness, not tied to a single milestone. - Decode — reads
RESULT_TAG/RESULT_VAL/RESULT_ERROR/HEAP:...lines from the simulator's stdout and canonically decodes atoms, fixnums, proper lists, and dotted lists from the heap. - Compare — asserts the decoded result (or
RESULT_ERROR) against the fixture'sexpected/errorfield.
Run it locally:
cargo test --test conformance_testThis requires, checked out as siblings of this repo (matching the .github/workflows/ci.yml layout):
../my-lisp— providestests/fixtures/conformance.my../fpga-lisp— providesassembler.pyand the compiledtb_cml_e2e.vvptestbenchpython3andiverilogonPATH
CI (.github/workflows/ci.yml) checks out both siblings fresh on every push/PR to master, so a missing local toolchain (no iverilog, no sibling checkouts) is not a blocker for landing a change — it only blocks local verification. See ecosystem-status.md for the running log of what has and hasn't been machine-verified this way.
Є один тест: tests/conformance_test.rs. Це сліпий адаптер — один незмінний конвеєр parse → macro-expand → compile → assemble → simulate → decode → compare, що прогонить кожну фікстуру без модифікацій, а не окрема перевірка під кожну фікстуру. Це дзеркалить дисципліну fpga-lisp "First Blind Fixture": усередині самого адаптера не допускаються гілки під конкретну фікстуру.
Фікстури не належать цьому репозиторію — вони живуть у сусідньому my-lisp за шляхом tests/fixtures/conformance.my, по одному alist на рядок: ((expr . "(quote radio)") (expected . "radio") (tier . 1)), або для фікстур, що мають статично чи в рантаймі впасти: ((expr . "...") (error . "Arity") (tier . 1)).
Конвеєр по кроках:
- Фільтр — сьогодні прогоняються лише рядки з тегом
(tier . 1); фікстури з3.0пропускаються (в ISA fpga-lisp ще немає inexact/rational тегу — пункт 25 плану, ще не почато). - Parse —
cml::parser::parse. - Macro-expand —
cml::macros::MacroExpanderвиконується перш, ніж будь-що інше торкнеться AST;defmacroніколи не доходить до компілятора. - Перевірка статичних помилок —
static_errorкласифікує помилки арності/невідомого символу, які front-end бачить без виконання. Якщо фікстура очікує саме це — тест звіряє й зупиняється тут. - Compile —
cml::compiler::Compilerзнижує розгорнутий AST в текст асемблера fpga-lisp. - Assemble — викликає
python3 ../fpga-lisp/assembler.py, отримуючи.bin. - Simulate — копіює
.binуfpga/sim/fpga-lisp і запускаєvvp tb_cml_e2e.vvp +bin_file=...(потрібен Icarus Verilog); цей testbench — загальний E2E-стенд fpga-lisp, не прив'язаний до конкретного milestone. - Decode — читає рядки
RESULT_TAG/RESULT_VAL/RESULT_ERROR/HEAP:...зі stdout симулятора й канонічно декодує atoms, fixnums, proper lists і dotted lists із heap. - Compare — звіряє декодований результат (чи
RESULT_ERROR) з полемexpected/errorфікстури.
Запуск локально:
cargo test --test conformance_testЦе вимагає, як сусідні репозиторії поряд із цим (той самий layout, що й у .github/workflows/ci.yml):
../my-lisp— надаєtests/fixtures/conformance.my../fpga-lisp— надаєassembler.pyі зібраний testbenchtb_cml_e2e.vvppython3іiverilogуPATH
CI (.github/workflows/ci.yml) заново чекаутить обидва сусідні репо при кожному push/PR у master, тож відсутність локального інструментарію (немає iverilog, немає сусідніх чекаутів) не блокує зміну — блокує лише локальну перевірку. Див. ecosystem-status.md — журнал того, що й коли було machine-verified у такий спосіб.
Es gibt einen Test: tests/conformance_test.rs. Es ist ein blinder Adapter — eine feste Pipeline parse → macro-expand → compile → assemble → simulate → decode → compare, die für jede Fixture unverändert läuft, statt einer maßgeschneiderten Prüfung pro Fixture. Das spiegelt die "First Blind Fixture"-Disziplin von fpga-lisp: Innerhalb des Adapters selbst sind keine Fixture-spezifischen Verzweigungen erlaubt.
Fixtures gehören nicht zu diesem Repository — sie liegen im benachbarten my-lisp-Repository unter tests/fixtures/conformance.my, eine Alist pro Zeile: ((expr . "(quote radio)") (expected . "radio") (tier . 1)), oder für Fixtures, die statisch oder zur Laufzeit fehlschlagen müssen: ((expr . "...") (error . "Arity") (tier . 1)).
Pipeline, der Reihe nach:
- Filter — heute laufen nur Zeilen mit Tag
(tier . 1); Fixtures mit3.0werden übersprungen (fpga-lisps ISA hat noch kein inexact/rational-Tag — Planpunkt 25, noch nicht begonnen). - Parse —
cml::parser::parse. - Macro-expand —
cml::macros::MacroExpanderläuft, bevor irgendetwas anderes den AST berührt;defmacroerreicht den Compiler nie. - Statische Fehlerprüfung —
static_errorklassifiziert Stelligkeits-/Unbekanntes-Symbol-Fehler, die das Frontend ohne Ausführung erkennt. Erwartet die Fixture genau das, prüft der Test hier und stoppt. - Compile —
cml::compiler::Compilersenkt den expandierten AST zu fpga-lisp-Assemblertext ab. - Assemble — ruft
python3 ../fpga-lisp/assembler.pyauf und erzeugt eine.bin. - Simulate — kopiert die
.binin fpga-lispsfpga/sim/und führtvvp tb_cml_e2e.vvp +bin_file=...aus (benötigt Icarus Verilog); dieser Testbench ist fpga-lisps universeller E2E-Prüfstand, nicht an einen einzelnen Meilenstein gebunden. - Decode — liest
RESULT_TAG/RESULT_VAL/RESULT_ERROR/HEAP:...-Zeilen aus der stdout des Simulators und dekodiert Atome, Fixnums, echte Listen und Dotted Lists kanonisch aus dem Heap. - Compare — vergleicht das dekodierte Ergebnis (oder
RESULT_ERROR) mit demexpected/error-Feld der Fixture.
Lokal ausführen:
cargo test --test conformance_testDies erfordert, als Geschwister dieses Repos ausgecheckt (gleiches Layout wie .github/workflows/ci.yml):
../my-lisp— lieferttests/fixtures/conformance.my../fpga-lisp— liefertassembler.pyund den gebauten Testbenchtb_cml_e2e.vvppython3undiverilogimPATH
CI (.github/workflows/ci.yml) checkt beide Geschwister-Repos bei jedem Push/PR nach master frisch aus — ein fehlendes lokales Toolchain (kein iverilog, keine Geschwister-Checkouts) blockiert also keine Änderung, nur die lokale Verifikation. Siehe ecosystem-status.md für das laufende Protokoll, was auf diese Weise wann machine-verified wurde.