Repository navigation
docs: mutual recursion lowering prereq + bootstrap.dag dissolution scope - #467
Conversation
…solution scope Follow-up to #464. Two additions: 1. §2.4 in SELF_HOSTING.md: mutual recursion lowering as named prereq for complexity port and general language completeness. v3 detects cycles (compute_mutually_recursive) but currently rejects them. The bounded-descend lowering (SCC-ordered, bounded by |SCC| × |children|) is the missing step. Once lowering produces this, complexity reads Loop.bound from the substrate — no Tarjan's in complexity. Testing: SCC sizes 2-5. 2. ROADMAP Track 17b + M2: expanded mutual recursion → Loop lowering with n-way SCC details. Prereq linkage to complexity port and general language completeness. ROADMAP Track 17b authority note narrowed in #464 to separate stage-contract vocabulary (superseded by pipeline) from schema- migration vocabulary (ChangeClassification, BootstrapStrategy — survives as load-bearing types for §10's patch pipeline). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
ChatGPT ReviewI only had the uploaded patch for Principle audit. 1. Fail-closed. Mostly satisfied. The new text is directionally good because it explicitly says current v3 still rejects mutual recursion and treats the missing lowering as the gap, which is consistent with the fail-closed rule in the lowering table ( 2. Illegal states unrepresentable. Satisfied. The doc does the right high-level thing by routing mutual recursion back into existing bounded primitives ( 3. Facts flow forward. This is the one place I have a real concern. In 4. Coproduct dissolution. Satisfied. I don’t see the diff introducing a new substrate coproduct or a new special-case enum family; it is trying to dissolve mutual recursion into existing bounded forms, which is the right lens ( 5. Single-authority metadata. Satisfied. The mutual-recursion note is good where it says complexity should read the lowered structure instead of reconstructing SCCs itself (diff:66-78). And the broader bootstrap-authority story remains aligned with the current roadmap note that pipeline signatures are the stage-contract authority, while only schema-migration vocabulary survives in 6. API-level enforcement over convention. Mostly satisfied, but the same structural gap from principle 3 leaks here too. “Lower to Loop nodes” is a good target, but “replace calls with the next function in SCC order” is still prose-level convention unless the doc names the exact substrate fact that preserves original call targets. As written, two implementers could both “follow the doc” and produce different semantics. For a design doc, that is too loose on the one place that matters ( 7. LOOP HEALTH. This round is making real forward progress: the ROADMAP hunk usefully promotes mutual-recursion lowering from an implicit thesis consequence to an explicit prerequisite for the complexity port, and the current roadmap’s bootstrap note keeps dissolution scope narrower instead of reopening a second authority ( Design question. What exact substrate fact preserves the original intra-SCC call graph after lowering? That is the structural crux here. The thesis only commits that mutual recursion lowers to a bounded form; it does not license throwing away the actual call topology. If the implementation keeps only “SCC membership + deterministic order + next-function link,” complexity may get a cheap bound, but execution, equivalence, and any later lens that cares about branch shape will be forced to reconstruct or will silently compute over a different program. I’d keep the “this is a prereq” claim, but rewrite the algorithm sketch so it commits only to preserving SCC structure in substrate form, not to a ring-walk encoding unless that encoding is proved semantics-preserving for nontrivial SCCs. Verdict. REQUEST_CHANGES The ROADMAP clarification looks good, and the bootstrap-authority direction is consistent with the current roadmap note. But |
briansrls
left a comment
There was a problem hiding this comment.
codex · gpt-5.4 · 2befd9f1
BLOCKING (2)
Root Cause
src/v3/ROADMAP.mdThe current reject-only helper throws away SCC structure as soon as it detects a cycle -> track a structured SCC-lowering prerequisite, not just "replace rejection with Loop nodes."src/v3/SELF_HOSTING.mdThe new self-hosting rationale blurs stage-internal helper recursion with pipeline-stage composition -> scope mutual recursion to user programs or stage-local helpers, not stage boundaries.
Non-blocking — Improvements (fix in-PR if easy, else defer to roadmap)
src/v3/SELF_HOSTING.mdThe replacement line for "## Section 3. Stage 1 - emit.dag" is mojibaked in the diff; restore the dash before merge.
| - Recursive functions → `Loop` lowering | ||
| - Recursive functions → `Loop` lowering (includes n-way mutual | ||
| recursion → bounded `descend` over SCC-ordered nodes). v3's | ||
| `lower.rs` already detects mutual recursion via |
There was a problem hiding this comment.
BLOCKING: This roadmap item understates the missing work: compute_mutually_recursive only yields a flat membership set, so the SCC partition/order fact still gets dropped before the lowering->complexity boundary (FACTS FLOW FORWARD).
| v2 pattern we're dissolving) | ||
| - General language completeness — any `.dag` program with mutual | ||
| recursion should compile, not fail at lowering | ||
| - Self-hosting — the compiler's own pipeline stages may be |
There was a problem hiding this comment.
BLOCKING: Treating lower<->infer as a likely mutual-recursion case contradicts Section 2.1's pipeline-as-DAG contract and the thesis's explicit dependency flow; stage composition should stay acyclic.
|
BLOCKING (2) Root Cause
Non-blocking — Improvements (fix in-PR if easy, else defer to roadmap)
|
Three fixes from ChatGPT + Codex review on #467: 1. SCC lowering preserves real call topology. Removed the ring-walk encoding sketch (steps 2-4) that would drop actual call graph edges. Replaced with: Transform.target edges in SCC bodies point at REAL callee declarations; the Loop wraps the SCC with a shared descent bound but the body preserves the original call structure. Named the exact substrate fact that must survive lowering. 2. Scoped mutual recursion to user programs / stage-local helpers. Pipeline stages calling each other across stage boundaries is a COMPOSITION concern handled by §2.1's pipeline declaration, not mutual recursion lowering. Removed the misleading "lower calls infer" example. 3. Fixed mojibake in §3 heading (replacement characters → em dash). 4. Added negative test fixture requirement: SCC with no shared descent measure should fail closed with a diagnostic, not compile with an unbounded loop. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
Follow-up to #464. Two doc additions:
§2.4 in SELF_HOSTING.md — mutual recursion lowering as a named prereq for the complexity port and general language completeness. v3's
lower.rsalready detects cycles (compute_mutually_recursive) but currently rejects them. The bounded-descend lowering (SCC-ordered, bounded by |SCC| × |children|) is the missing step. Once lowering produces bounded Loop nodes, complexity readsLoop.boundfrom the substrate — no Tarjan's in complexity, no SCC reconstruction. Testing scope: SCC sizes 2-5.v3 ROADMAP.md M2 — expanded "Recursive functions → Loop lowering" with n-way mutual recursion details and prereq linkage to complexity port and general language completeness.
Supersedes #465 which had merge conflicts from #464's squash merge.
Test plan
🤖 Generated with Claude Code