Skip to content

feat(formal): real-lift R2-loops — backward jumps (Loop/Br/BrIf) + while simulation (settles #601)#665

Merged
hyperpolymath merged 1 commit into
mainfrom
claude/lucid-cray-4a22dp-r2loops
Jun 27, 2026
Merged

feat(formal): real-lift R2-loops — backward jumps (Loop/Br/BrIf) + while simulation (settles #601)#665
hyperpolymath merged 1 commit into
mainfrom
claude/lucid-cray-4a22dp-r2loops

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Fourth rung of the real lift (formal/REAL-LIFT.adoc): structured control with backward jumps, and a source while whose lowering is proved correct — settling the #601 value-returning-tail question concretely. Axiom-free throughout.

Branch note: pushed to claude/lucid-cray-4a22dp-r2loops rather than claude/lucid-cray-4a22dp — the latter is still present at the merged #664 tip and is now protected against direct pushes (force/ff/delete all blocked), so a fresh branch was the only push path. Diff is against current main (post-#664), so it shows only the R2-loops changes.

What landed

Target IR (RealWasm.v)

  • Adds the faithful lib/wasm.ml structured-control instructions Block, Loop, Br k, BrIf k to instr (+ dead step1 arms). Zero blast radius — the proven wexec and RealCompile.compile_correct still compile unchanged.

R2-loops (new file RealLoop.v)

  • The R2 executor wexec : … → option (locals×stack) can't express "this code branched to label k", so it cannot run Br. R2-loops introduces a branch-aware executor cexec returning an outcome (ONormal / OBranch k / OTrap). It reuses the same fuel device R2 used for forward control: a Loop consumed by Br 0 re-enters by recursing with decremented fuel, so cexec stays a structural Fixpoint — definitional, so cbn/reflexivity/demos still compute (a real countdown while evaluates by reflexivity).
  • cexec_le_S / cexec_mono (more fuel never changes a Some) + cexec_app_normal (additive sequencing when the prefix ends Normal).
  • A mutual instr/list instr branchfree predicate is rejected by Coq's guard checker (list recursion only decreases on the spine), so instead of a wexec→cexec bridge over a flag, the R2 expression compiler is re-proved directly into cexec: cexec_compile (the cexec analogue of compile_correct).
  • Source statements SSkip / SSeq / SSet / SWhile with a fuel-indexed reference run_stmt (+ run_stmt_mono, run_stmt_length), and a lowering compile_stmt taking while to Block[Loop[<cond>; I32Eqz; BrIf 1; <body>; Br 0]].
  • cexec_loop — the loop-simulation lemma (induction on the while's fuel: cond-false unwinds with OBranch 1, caught by the Block; cond-true runs the body and re-enters via OBranch 0).
  • compile_stmt_correct — a terminating statement's lowering runs to the same locals, leaving the value stack empty (cexec … = Some (ONormal lo' [])). A while is a statement (unit tail); this is Face transformers disagree on trailing-statement lowering — greet compiles to 2 wasm classes #601 settled concretely — the expression tail would instead keep its value on the stack.

Verification

coqc 8.18, whole formal/ track re-audited against current main:

  • 19 files compile, 33 Print Assumptions reports, every one "Closed under the global context"zero axioms, no Admitted.

Docs

formal/REAL-LIFT.adoc (R2 row + §5 hard-parts + §8 status), formal/README.adoc (RealLoop row + "real lift R0 → R2-loops"), docs/PROOF-NEEDS.adoc (counts 18→19 / 31→33, K-1 row). _CoqProject / justfile / .hypatia-ignore wire RealLoop.v in.

Next

Rung R-mem (linear memory: load/store, tuples/arrays/records). for/break/continue and a general source-divergence model reuse this cexec.

Refs REAL-LIFT.adoc, docs/PROOF-NEEDS.adoc (K-1 row), #601.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KPG9mEQXFyA3k7NWAzMNMr


Generated by Claude Code

…(settles #601)

Fourth rung of the real lift (formal/REAL-LIFT.adoc): structured control with
**backward jumps**, and the source `while` whose lowering is proved correct —
settling the #601 value-returning-tail question concretely. Axiom-free.

Target IR (RealWasm.v):
  - adds the faithful lib/wasm.ml structured-control instructions `Block`,
    `Loop`, `Br k`, `BrIf k` to `instr` (+ dead `step1` arms). Zero blast radius:
    the proven `wexec` and `compile_correct` still compile unchanged.

R2-loops (new file RealLoop.v):
  - the R2 executor `wexec : … → option (locals×stack)` cannot express "this code
    branched to label k", so it cannot run `Br`. R2-loops introduces a
    **branch-aware** executor `cexec` returning an `outcome`
    (`ONormal`/`OBranch k`/`OTrap`). It reuses the very same fuel device R2 used
    for forward control: a `Loop` consumed by `Br 0` re-enters by recursing with
    decremented fuel, so `cexec` stays a structural `Fixpoint` (definitional —
    `cbn`/`reflexivity`/demos still compute; a real countdown `while` evaluates
    by `reflexivity`).
  - `cexec_le_S`/`cexec_mono` (more fuel never changes a `Some`) +
    `cexec_app_normal` (additive sequencing when the prefix ends `Normal`).
  - mutual `instr`/`list instr` recursion is rejected by Coq's guard checker
    (list recursion only decreases on the spine), so instead of a `branchfree`
    predicate the R2 expression compiler is re-proved directly into `cexec`:
    `cexec_compile` (the `cexec` analogue of `compile_correct`).
  - source statements `SSkip`/`SSeq`/`SSet`/`SWhile` with a fuel-indexed
    reference `run_stmt` (+ `run_stmt_mono`, `run_stmt_length`) and a lowering
    `compile_stmt` taking `while` to `Block[Loop[<cond>;I32Eqz;BrIf 1;<body>;
    Br 0]]`.
  - `cexec_loop` — the loop-simulation lemma (induction on the while's fuel:
    cond-false unwinds with `OBranch 1`, caught by the Block; cond-true runs the
    body and re-enters via `OBranch 0`).
  - `compile_stmt_correct` — a terminating statement's lowering runs to the same
    locals, leaving the value stack **empty** (`cexec … = Some (ONormal lo' [])`).
    A `while` is a statement (unit tail); this is #601 settled concretely — the
    expression tail instead keeps its value on the stack.

Whole formal/ track re-audited: **19 files, 33 `Print Assumptions` closure
reports, all "Closed under the global context" — zero axioms, no Admitted.**

Next rung **R-mem** (linear memory: load/store, tuples/arrays/records).
(`for`/`break`/`continue` + a general source-divergence model reuse this cexec.)

Refs REAL-LIFT.adoc, docs/PROOF-NEEDS.adoc (K-1 row), #601.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KPG9mEQXFyA3k7NWAzMNMr
@hyperpolymath hyperpolymath marked this pull request as ready for review June 27, 2026 19:46
@hyperpolymath hyperpolymath merged commit ea496bd into main Jun 27, 2026
16 of 17 checks passed
@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants