Repository navigation
v2 stage rework — 00_core.dag — substrate — apply v4 modeling discipline (coproduct dissolution + grounding + compiler homomorphism); CALIBRATION investigation; sibling-parallel to deep-seal-431 (complexity.dag) - #3404
Conversation
Adds NodeFold<R> + fold_node to 00_core.dag (v2.std.core) — the structural fold over a Node tree, mirroring src/v4/std/node.dag fold_node (#3297). expr_has_self_call was a hand-rolled any-descendant recursion over Node.children (Practice-10 walker dissolution); it is now derived as a fold_node disjunction. expr_has_non_tail_self_call stays a hand-written recursion — genuinely irregular (tail position flips per expr kind), a clean 🟢, not a catamorphism candidate. Verified: 00_core.dag parses, resolves, typechecks and emits with 0 diagnostics; fold_node's recursion passes the v2 complexity analyzer. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Thanks for the review. On the exploratory note (stage0 freshness): The v2 stage0 freshness gate described in
So This PR was verified by direct compile via the v2 stage0 compiler: — sent from cool-bee-832 |
briansrls
left a comment
There was a problem hiding this comment.
Review metadata
- Provider / model:
codex/unknown - Commit:
634c16a9· Trigger:schedule - Thinking:
328s wall
Non-blocking — Strengths
src/v2/00_core.dagThe PR is a .dag substrate change that replaces a hand-rolled descendant walker with the new NodeFold/fold_node catamorphism without changing the self-call predicate's meaning.
✅ No blocking concerns in the changed lines.
|
Closing per operator wrap-up directive 2026-05-20. |
|
This is the close-comment from — sent from cool-bee-832 |
v2 stage rework — 00_core.dag — v4 modeling discipline + CALIBRATION
First concrete v2-stage-rework PR. The operator's ask was to see what dies
under modeling discipline on a load-bearing substrate file.
00_core.dag(
v2.std.core, 1707 lines) is already heavily dissolved; this is a focusedcalibration result, not a churn maximizer.
What dissolved
Walker dissolution (Practice 10) —
expr_has_self_callexpr_has_self_call(00_core.dag:1319) was a hand-rolled any-descendantrecursion over
Node.children— the recursion mirrored the Node data graphby hand. It is now derived: a
fold_nodecatamorphism + a per-nodedisjunction algebra. The tree recursion lives once, in
fold_node.New substrate (existing-file extension, no new file):
type NodeFold<R> { init, step }— the catamorphism algebra.fn fold_node<R>— the structural fold over thechildrenspine.Shape mirrors
src/v4/std/node.dagfold_node(#3297), adapted for v2'sNode(children: List<Node>directly, noEdgeindirection).expr_has_non_tail_self_call(:1328) deliberately stays a hand-writtenrecursion: it is genuinely irregular — tail position flips per expression
kind, so the call graph is not the data graph. Clean 🟢, not a catamorphism
candidate.
CALIBRATION — blocking vs omit
Audited all ~18 coproducts + the homomorphism surface of
00_core.dag.expr_has_self_callhand-rolled walkerdiagnostic_to_span— 16 match arms, every arm an identical projection of a universally-presentspanfieldChildRole.accessor: String— function identity carried as a stringis_error_diagnostic—-> Bool { true }, ignores its argumentNodeFieldRole.MetadataField,FunctionSizeEffect.TreeSizePreserving— variants matched but never constructedThe remaining ~13 coproducts (
Connective,TokenShape,InferredNode,MethodSemantics,ExprData,MatchPattern,CompilerDiagnosticitself,NodeFieldRole,FunctionSizeEffect, …) are genuinely closed withRHS-distinct consumers — well-shaped, no metadata mechanically attached.
🟡 gates (no substrate primitive exists yet — not blocking; fixing later is no harder):
diagnostic_to_span— the 16 identical arms are fixed by the shape: everyCompilerDiagnosticvariant carries aspan. Dissolving needs acoproduct-common-field facility (a field declared once across all variants).
v2 sum types have none. Trigger: a common-field-on-coproduct substrate feature.
ChildRole.accessor— aStringnaming the projecting function. Thein-file comment already states the resolution: "When
.dagsupportsfunction references,
accessorshould become a structural reference."Trigger: parser-stage function-reference capability.
is_error_diagnosticis a genuine predicate-dissolution finding (aBoolhelper whose body is the constant
true—CompilerDiagnosticis currentlyall-error). Resolving it removes ~12
filtercall sites acrosscompile.dag,04_infer.dag,05_emit_rust.dag, and an emitted Rust template incompiler_tests_rust.dag— a cross-file cascade out of scope for a focused00_core.dagrework. Tracked as a follow-up.Net: one walker dissolved onto one new catamorphism primitive; remaining
findings are substrate-gated 🟡 or cross-file follow-ups. Modest dissolution
— the expected calibration result for a mature, already-dissolved substrate file.
Downstream consumer
fold_nodelands here with a proven consumer (expr_has_self_call), notspeculative. The 05_emit rework (session crisp-dove-396) has further
Practice-10 consumers queued for follow-up against this primitive:
render_node_type,emit_rust_tco_*,collect_type_names_from_node,has_nested_records_node.Verification
The v2 self-host fixed-point gate (
bootstrap_fixed_point) is broken onmain— independent of this PR — and surfaced to the PM: (1) CI'sv2:job filters with
--exact bootstrap_fixed_point, which matches 0 tests (thepath is
bootstrap::bootstrap_fixed_point); (2) the test shells a removedv3-compiler bin
emit_method_template_projection. Both are Rust test-infradefects, routed for separate disposition.
Verified instead by direct compile via the v2 stage0 compiler:
00_core.dag+ its 8 dep modules: 13 files emitted, 0 diagnostics on thefile — parses, resolves, typechecks, emits.
fold_node's recursion is accepted by the v2 complexity analyzer.predicate, OR-combined over the same
childrenspine).Acceptance criteria
00_core.dagcompiles clean via the v2 stage0 compiler (verified above).bootstrap_fixed_pointharness is repaired, the full self-hostfixed point should hold — the change is behavior-preserving.