You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
## What
Completes the statement-execution relation by adding the four
**control-flow
forms** (`if`/`loop`/`attempt`/`consent`) to `StmtExec`, with **faithful
lexical
scoping** (the option-A choice — the Rust `Environment{bindings,
parent}`
discipline): on block exit, the names a block *declared* are rolled back
to their
entry values, while assignments to *enclosing* variables persist.
## Scope machinery
| Definition / lemma | Role |
|---|---|
| `declaredVarsOf` / `declaredVars` | the names a statement / block
declares (top-level `varDecl`s) |
| `restoreVars names ρpre ρpost` | roll declared names back to entry
values; keep everything else (incl. outer mutations) |
| `stmt_ctx_off_declared` / `ctx_agrees_off_declared` | statics: the
type context is unchanged off the declared names |
| `store_wellTyped_restore` | the restored store is well typed against
the outer `Γ` |
## New `StmtExec` rules
- `ifTrue` / `ifFalse` — run the taken branch, restore its declarations.
- `loopDone` / `loopStep` — **`loopStep` recurses on the *restored*
store**, so outer-variable mutations carry across iterations while
declarations re-scope each pass.
- `attemptOk` (selective restore) / `attemptErr` (restore entry `ρ`, per
op-sem `[B-Attempt-Err]`).
- `consentGrant` / `consentDeny`.
## Preservation — now the full mutual induction
`stmt_exec_preservation` / `stmts_exec_preservation` are upgraded from
the
simple-only versions to cover all forms, proved via the **`StmtExec.rec`
mutual
recursor**. Two reasons the recursor (not `induction` + `cases`) was
required:
1. Lean's `induction` tactic doesn't support mutual inductives.
2. The loop's recursion is *same-statement* (smaller derivation,
identical AST), so it's **non-AST-structural** — only
derivation-structural elimination via the recursor closes it.
The control-flow cases bridge `stmts_exec_preservation` (giving
`StoreWellTyped Γ₁ ρb`) back to the outer `Γ` via
`ctx_agrees_off_declared` + `store_wellTyped_restore`.
## Faithfulness — demonstrated by running programs
Two smoke tests that actually execute and distinguish this model from a
naive whole-store restore:
- `if true { remember y = 0 }` from the empty store → **empty store**
(block-local `y` does *not* escape).
- `if true { x = 1 }` with outer `x` → **`x = 1` persists** through the
block.
## Verification
- `lean docs/proofs/verification/WokeLang.lean` exits 0 (Lean 4.30.0,
Mathlib-free, single-file).
- Hole-free: scoping lemmas depend only on `propext`; the preservation
theorems use the classical kernel base (`propext`, `Classical.choice`,
`Quot.sound`). No `sorryAx`.
## Documented divergences (honest, in-file)
- **`loop` is bool/while-guarded**, inheriting the merged
`StmtWellTyped.loop : … .bool` premise, whereas the interpreters use a
**counted-`int`** loop. Deferred — changing it edits merged statics.
- `consent`/`attempt` abstract the permission oracle and the result
channel (`hname` unused).
- Early exit (return/break/continue) is unmodeled.
- This is a **preservation-only** result — no statement-progress or
determinism claim.
## Note
An adversarial review workflow (faithfulness vs Rust, non-vacuity,
scoping edge-cases, honesty) is running; any confirmed findings will be
folded in as follow-up commits before merge.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
https://claude.ai/code/session_015oyMquf4daB6hMhmqB1wAL
---
_Generated by [Claude
Code](https://claude.ai/code/session_015oyMquf4daB6hMhmqB1wAL)_
Co-authored-by: Claude <noreply@anthropic.com>
0 commit comments