@@ -10,6 +10,156 @@ The interpreter is deliberately optimized for **simplicity of reasoning, not exe
1010
1111Lean toolchain is pinned in ` lean-toolchain ` .
1212
13+ ## Iris migration (` iris ` branch only)
14+
15+ > ** Temporary branch-scoped notice.** This section must exist only on the
16+ > ` iris ` integration branch and branches created from ` iris ` during the
17+ > migration. It overrides conflicting guidance elsewhere in this file,
18+ > especially guidance to preserve the current big-step interpreter's shape.
19+ > Before merging the completed migration into ` main ` , remove this notice or
20+ > update it to describe the new permanent architecture.
21+
22+ The purpose of the ` iris ` branch is to integrate
23+ [ iris-lean] ( https://github.com/leanprover-community/iris-lean ) and migrate the
24+ reference Wasm interpreter from its current fuel-bounded big-step semantics to
25+ small-step semantics suitable for Iris.
26+
27+ The migration is complete when:
28+
29+ - The interpreter is fully expressed using small-step semantics in the form
30+ expected by iris-lean.
31+ - Every currently supported Wasm feature and test remains covered, with no
32+ semantic regressions.
33+ - Differential testing remains possible. In particular, there must still be an
34+ executable, fuel-bounded way to run Wasm code, built by iterating the
35+ executable small-step function rather than by maintaining a second semantics.
36+ - All required iris-lean language and proof-mode instances are implemented, so
37+ downstream proofs can use iris-lean directly.
38+ - Existing proofs and theorem statements need not retain their exact shape.
39+ Nevertheless, preserve the intent and coverage of existing examples whenever
40+ possible, rewriting them against the new semantics rather than silently
41+ deleting them.
42+
43+ The intended split between an Iris expression and state is approximately:
44+
45+ ``` lean
46+ inductive Expr
47+ | running : ThreadState → Expr
48+ | done : List WasmVal → Expr
49+ | trapped : TrapReason → Expr
50+ deriving BEq, Repr
51+
52+ structure Store where
53+ functions : Array Function
54+ memories : Array Memory
55+ globals : Array Global
56+ tables : Array Table
57+ deriving BEq, Repr
58+ ```
59+
60+ Treat this as an architectural guide, not a requirement to preserve these exact
61+ names. ` Expr ` contains the whole per-execution ` ThreadState ` , not merely the
62+ remaining instruction list. ` Store ` contains the shared runtime resources.
63+ Keep that ownership boundary explicit when adding fields: thread-local control
64+ and operand state belongs in ` ThreadState ` ; resources observed or mutated
65+ through the runtime store belong in ` Store ` .
66+
67+ For convenient executable interpretation, package the Iris expression and
68+ state together, while keeping the relational semantics authoritative:
69+
70+ ``` lean
71+ /- Convenient packaging for the executable interpreter. The Iris adapter will
72+ split this back into its `Expr` and `State` arguments. -/
73+ structure Config where
74+ expr : Expr
75+ store : Store
76+ deriving BEq, Repr
77+
78+ inductive Step : Config → Config → Prop where
79+ -- Full definition of all valid transitions.
80+
81+ def step? : Config → Option Config
82+ | ⟨.running thread, store⟩ => stepRunning? thread store
83+ | ⟨.done _, _⟩ => none
84+ | ⟨.trapped _, _⟩ => none
85+
86+ theorem step?_sound {config config' : Config} :
87+ step? config = some config' → Step config config' := by
88+ sorry
89+
90+ theorem step?_complete {config config' : Config} :
91+ Step config config' → step? config = some config' := by
92+ sorry
93+
94+ theorem step_sound {config config' : Config} :
95+ step? config = some config' → Step config config' :=
96+ step?_sound
97+
98+ theorem step_complete {config config' : Config} :
99+ Step config config' → step? config = some config' :=
100+ step?_complete
101+
102+ theorem step_iff {config config' : Config} :
103+ step? config = some config' ↔ Step config config' :=
104+ ⟨step_sound, step_complete⟩
105+ ```
106+
107+ The exact iris-lean adapter must follow the API of the pinned iris-lean
108+ dependency. Implement every required instance from this ` Expr ` /` Store ` split
109+ and prove it against ` Step ` ; do not introduce a parallel Iris-only transition
110+ relation.
111+
112+ Use instruction-level granularity as the default: one ` Step ` should normally
113+ execute one Wasm instruction. Administrative transitions may execute no Wasm
114+ instruction when they expose or remove control frames, prepare or return from a
115+ function call, propagate a trap, or otherwise reorganize the machine so the
116+ next instruction can run. Prefer small, explicit administrative transitions
117+ over hiding multi-stage control behavior inside a single large step. A
118+ transition may perform the atomic state effects intrinsic to its instruction;
119+ do not split an instruction solely to mirror implementation helper functions.
120+ Document intentional exceptions and keep the granularity consistent across
121+ related instructions.
122+
123+ For now, assume the Wasm semantics implemented here is deterministic, as
124+ required by ` step? : Config → Option Config ` and ` step?_complete ` . Whenever a
125+ feature appears nondeterministic—or depends on unspecified host behavior,
126+ scheduling, external input, or an arbitrary choice—flag it before implementing
127+ the transition. Record whether the behavior can be made deterministic by an
128+ explicit input or policy in ` Store ` . If genuine nondeterminism is required,
129+ stop and decide how to represent executable successor choices and adapt the
130+ Iris semantics and correspondence theorem; never choose an outcome silently.
131+
132+ During the migration:
133+
134+ - Pin iris-lean to a known revision. Upgrade it intentionally, recording any
135+ adapter or instance changes required by the new API.
136+ - Treat the instruction and administrative-step policy above as the default
137+ Iris atomicity boundary. Review deviations explicitly; do not change
138+ granularity merely to make the executable runner more convenient.
139+ - Make the relational ` Step ` and executable ` step? ` correspond in every PR.
140+ A new transition is incomplete until both sides and their soundness and
141+ completeness proofs agree.
142+ - State and preserve invariants at transition boundaries, including stack
143+ typing, index validity, store-extension/ownership properties, and the
144+ distinction between normal completion and traps.
145+ - Keep ` .done ` and ` .trapped ` terminal. Out-of-fuel belongs to the executable
146+ runner's result, not to ` Expr ` or the semantic relation.
147+ - Add regression or differential tests while porting each instruction family.
148+ Where feasible, compare the new runner with the old interpreter until the old
149+ implementation is removed.
150+ - Keep migration PRs reviewable and layered: introduce representation and
151+ compatibility lemmas first, then port coherent instruction families and
152+ their examples. Do not remove the old path before equivalent coverage exists.
153+ - Build every affected package in dependency order. A successful build remains
154+ the test criterion throughout the transition.
155+
156+ iris-lean does not currently provide total-execution reasoning for this
157+ integration. Iris proofs therefore establish behavior conditional on reaching
158+ completion; they do not establish termination. This loss of total-correctness
159+ claims is accepted during the migration. Keep termination-sensitive theorem
160+ intent documented so it can be restored if total reasoning becomes available,
161+ and do not describe a partial-correctness result as a termination proof.
162+
13163## Repository layout
14164
15165Three Lake packages in a monorepo, forming a strict dependency chain:
0 commit comments