commit fa9eb5967ef6ac61d3711e3687f7b2ffdbaf8767
parent 2eb0c7d9d788f25032944b92823867115b2402d7
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Thu, 23 Apr 2026 14:32:34 -0700
docs/M1M-IMPL.md: reconcile with post-Phase-1 state
Update the implementation sketch to match what's now on disk:
- m1pp.M1 description reflects the P1v2 port landing in Phase 1.
- Manual-run example and Phase 0 blurb use
localhost/distroless-busybox:latest (built from Containerfile.busybox)
instead of the old localhost/lispcc:aarch64 alpine alias.
- Oracle-compare commands and the Supported Features / Phase 7 / Phase
10 bullets use .M1pp instead of the old .M1M extension, matching the
fixture rename and the p1/*.M1pp sources.
- Layer 9 pseudo-code advances s.pos += 24 (matching the 24-byte Token
record laid out in Core Data Structures) instead of the old 32.
Diffstat:
1 file changed, 21 insertions(+), 18 deletions(-)
diff --git a/docs/M1M-IMPL.md b/docs/M1M-IMPL.md
@@ -10,9 +10,11 @@ macro expander.
- `m1pp/m1pp.c` — C oracle. Behaviorally authoritative.
Each phase below names the oracle entry points to lift from.
-- `m1pp/m1pp.M1` — port target. Currently has only the lexer
- skeleton and `%macro` structural skipping in the legacy P1 ISA.
- Phase 1 rewrites it on P1v2; Phases 2–9 extend it.
+- `m1pp/m1pp.M1` — port target, on P1v2 as of Phase 1. Runtime
+ shell, lexer, pass-through emit, and structural `%macro` skip
+ land in Phase 1. Phases 2–10 extend it to real macro storage,
+ expansion, paste, the expression evaluator, builtins, and
+ `%select`.
- `m1pp/build.sh`, `m1pp/test.sh` — build / run / diff a P1v2 .M1
into a runnable aarch64 binary. See `docs/M1M-IMPL.md` Phase 0.
- `tests/m1pp/` — per-phase fixtures. Two shapes, selected by
@@ -42,12 +44,12 @@ make test-m1pp
sh m1pp/test.sh 01-passthrough
# Run a built binary manually in the aarch64 container.
-# `localhost/lispcc:aarch64` is a local tag created by m1pp/build.sh on
-# first run, aliased to the digest-pinned alpine arm64 image; see the
-# Makefile for the canonical pin.
+# `localhost/distroless-busybox:latest` is a local tag built by
+# m1pp/build.sh on first run from Containerfile.busybox (distroless-static
+# + the busybox binary from another distroless layer, both digest-pinned).
podman run --rm --pull=never --platform linux/arm64 \
-v "$PWD":/work -w /work \
- localhost/lispcc:aarch64 \
+ localhost/distroless-busybox:latest \
./build/m1pp/<name> <argv...>
# Regenerate P1v2 DEFINE tables after touching p1/*.py:
@@ -55,8 +57,8 @@ python3 p1/p1_gen.py --arch aarch64 build/p1v2
# Build the C oracle + compare its output to the M1 build:
cc m1pp/m1pp.c -o build/m1pp/m1pp-oracle
-./build/m1pp/m1pp-oracle <input.M1M> /tmp/out-c
-./build/m1pp/<fixture> <input.M1M> /tmp/out-m1 # run via podman as above
+./build/m1pp/m1pp-oracle <input.M1pp> /tmp/out-c
+./build/m1pp/m1pp <input.M1pp> /tmp/out-m1 # run via podman as above
diff /tmp/out-c /tmp/out-m1
# Discover undefined P1 tokens without running M0 (catches typos that
@@ -81,7 +83,7 @@ sh lint.sh build/p1v2/aarch64/p1_aarch64.M1 m1pp/m1pp.M1
### Supported Features
-The target expander supports the features required by `p1/*.M1M`:
+The target expander supports the features required by `p1/*.M1pp`:
- `%macro NAME(a, b)` / `%endm`
- `%NAME(x, y)` function-like expansion with recursive rescanning
@@ -97,7 +99,7 @@ The program should be structured as a small compiler pipeline:
1. Runtime shell
Read `argv[1]` into `input_buf`, lex into `source_tokens`, process
tokens through the macro engine, write `output_buf` to `argv[2]`.
- This part mostly exists.
+ Done in Phase 1.
2. Lexer
Keep the current C-compatible tokenizer:
@@ -432,7 +434,7 @@ process_tokens:
if tok.kind == NEWLINE:
emit_newline()
- s.pos += 32
+ s.pos += 24 # one Token record
s.line_start = 1
continue
@@ -445,7 +447,7 @@ process_tokens:
continue
emit_token(tok)
- s.pos += 32
+ s.pos += 24
s.line_start = 0
```
@@ -465,9 +467,9 @@ symbol name.
- [x] **Phase 0 — Build/run/diff infra under `m1pp/`.**
`m1pp/build.sh <source.M1> <out>` lints against the P1v2 DEFINE
table, prunes unused DEFINEs, runs M0 + hex2-0 with the aarch64
- ELF header inside the alpine container, and deposits a runnable
- binary. `m1pp/test.sh` walks fixtures in `tests/m1pp/` and picks
- mode by extension: `.M1` fixtures are built and run stand-alone;
+ ELF header inside the distroless-busybox container, and deposits
+ a runnable binary. `m1pp/test.sh` walks fixtures in `tests/m1pp/`
+ and picks mode by extension: `.M1` fixtures are built and run stand-alone;
`.M1pp` fixtures are fed to a one-time build of `m1pp/m1pp.M1` as
input, and the produced output file is diffed. Wired into
`make test-m1pp`. Phase 0 fixture: `tests/m1pp/00-hello.M1` — a
@@ -520,7 +522,7 @@ symbol name.
- [ ] **Phase 7 — Integer atoms + S-expression evaluator.**
Integer-token parsing; explicit expression-frame stack; all
operators from the oracle; macro-in-expression composition (the
- required path for `p1/aarch64.M1M`).
+ required path for `p1/P1-aarch64.M1pp`).
Oracle: `parse_int_token`, `expr_op_code`, `apply_expr_op`,
`eval_expr_atom`, `eval_expr_range`, `skip_expr_newlines`.
@@ -535,7 +537,8 @@ symbol name.
Oracle: `expand_builtin_call` (the `%select` case).
- [ ] **Phase 10 — Full-parity + malformed-input smoke tests.**
- Run `tests/m1pp/full-parity.M1M` against the M1 implementation;
+ Run `tests/m1pp/_full-parity.M1pp` against the M1 implementation
+ (unpark by dropping the `_` prefix);
add malformed fixtures (unterminated macro, wrong arg count, bad
paste, bad expression, bad builtin arity) requiring non-zero
exit. Then run combined `p1/P1-aarch64.M1pp + p1/P1.M1pp` through