@@ -889,4 +889,110 @@ theorem wp_wasm_prop_to_TerminatesWith
889889 | ReturnCall fid st' vs => rw [hexec] at hwp_fuel; exact hwp_fuel.elim
890890 | Throwing tag targs st' s' => rw [hexec] at hwp_fuel; exact hwp_fuel.elim
891891
892+ -- ── iProp trivialize / bridge ──────────────────────────────────────────────────
893+
894+ /-- Trivialize the iProp postcondition: any wp_wasm_iProp entails the Prop WP with
895+ True postcondition. Proved by lfp induction: Ψ' s = wp_wasm_iProp s.{Φ:=⌜True⌝}.
896+ Base cases close by `BI.pure_intro trivial`; step case closes by definitional
897+ equality (Ψ' ignores the Φ field, so Ψ' {Φ=post} = Ψ' {Φ=⌜True⌝} = lfp {⌜True⌝}). -/
898+ lemma wp_wasm_iProp_trivialize
899+ {m : Module} {st : Store Unit} {locals : Locals} {prog : Program}
900+ {env : HostEnv Unit} {post : Store Unit → List Value → IProp WasmHeapGF} :
901+ wp_wasm_iProp m st locals prog env post ⊢
902+ wp_wasm m st locals prog env (fun _ _ => True) := by
903+ rw [wp_wasm_iProp_pure]
904+ let Ψ' : LeibnizO WasmStateIProp → IProp WasmHeapGF :=
905+ fun s => bi_least_fixpoint wp_wasm_iProp_F
906+ ⟨{ m := s.car.m, st := s.car.st, locals := s.car.locals,
907+ prog := s.car.prog, env := s.car.env,
908+ Φ := fun _ _ => iprop% ⌜True⌝ }⟩
909+ haveI hΨ' : OFE.NonExpansive Ψ' :=
910+ ⟨fun _ _ _ H => (OFE.eq_of_eqv (OFE.discrete H)) ▸ OFE.Dist.rfl⟩
911+ have hstep : ⊢ □ (∀ y : LeibnizO WasmStateIProp, wp_wasm_iProp_F Ψ' y -∗ Ψ' y) := by
912+ iintro !> %s
913+ obtain ⟨ws⟩ := s
914+ rcases hprog : ws.prog with _ | ⟨instr, rest⟩
915+ · -- prog = [] : postcondition → ⌜True⌝ trivially in affine BI
916+ unfold wp_wasm_iProp_F Ψ'; simp only [LeibnizO.car, hprog]
917+ iintro _H
918+ iapply least_fixpoint_unfold_mpr
919+ unfold wp_wasm_iProp_F; simp only [LeibnizO.car, hprog]
920+ exact BI.pure_intro trivial
921+ · by_cases h_ret : instr = Instruction.ret
922+ · -- prog = .ret :: _ : same trivial close
923+ subst h_ret
924+ unfold wp_wasm_iProp_F Ψ'; simp only [LeibnizO.car, hprog]
925+ iintro _H
926+ iapply least_fixpoint_unfold_mpr
927+ unfold wp_wasm_iProp_F; simp only [LeibnizO.car, hprog]
928+ exact BI.pure_intro trivial
929+ · -- prog = instr :: rest (instr ≠ .ret): Ψ' ignores Φ, so Hwp IS the goal
930+ unfold wp_wasm_iProp_F Ψ'; simp only [LeibnizO.car, hprog]
931+ iintro Hwp
932+ iapply least_fixpoint_unfold_mpr
933+ unfold wp_wasm_iProp_F; simp only [LeibnizO.car, hprog]
934+ iexact Hwp
935+ have hfp :
936+ bi_least_fixpoint wp_wasm_iProp_F ⟨{ m, st, locals, prog, env, Φ := post }⟩ ⊢
937+ Ψ' ⟨{ m, st, locals, prog, env, Φ := post }⟩ :=
938+ BI.sep_elim_emp_valid_left hstep
939+ (BI.wand_elim ((BI.wand_entails (least_fixpoint_iter (F := wp_wasm_iProp_F))).trans
940+ (BI.forall_elim (⟨{ m, st, locals, prog, env, Φ := post }⟩ : LeibnizO WasmStateIProp))))
941+ exact hfp
942+
943+ /-- iProp call bridge: from a function spec instance and a valid initial combined
944+ assertion `⊢ genHeapInterp σ ∗ pre st`, extract Prop-level termination.
945+
946+ Takes the funcSatisfies spec instantiated at a specific (env={}, st, args=[]):
947+ hspec : ⊢ pre st -∗ wp_wasm_iProp m st (f.toLocals []) f.body {} post
948+
949+ Proof chain:
950+ hspec + h_init → ⊢ genHeapInterp σ ∗ wp_wasm_iProp ... post
951+ wp_wasm_iProp_trivialize → ⊢ genHeapInterp σ ∗ wp_wasm ... True
952+ wasm_adequacy + pure_soundness → wp_wasm_prop m st (f.toLocals []) f.body {} True
953+ wp_wasm_prop_to_TerminatesWith → TerminatesWith {} m callid st [] (fun _ _ => True)
954+
955+ NOTE: `⊢ genHeapInterp σ ∗ pre st` is the CORRECT combined form (AUTH ∗ FRAG
956+ together), obtainable via `genHeap_init` at allocation time. The form
957+ `genHeapInterp σ ⊢ pre st` (AUTH ⊢ FRAG) is false in the genHeap RA model
958+ and cannot serve as a hypothesis here.
959+
960+ NOTE: This theorem lives in Adequacy (not ModuleLinking) to avoid a circular
961+ import: ModuleLinking imports Adequacy, so Adequacy cannot reference
962+ `funcSatisfies`. Callers unpack `funcSatisfies` via `obtain ⟨f, hf, hspec⟩`
963+ before calling this lemma. -/
964+ theorem wp_wasm_iProp_call
965+ {m : Module} {st : Store Unit} {callid : Nat}
966+ {pre : Store Unit → IProp WasmHeapGF}
967+ {post : Store Unit → List Value → IProp WasmHeapGF}
968+ {f : Function} {σ : WasmHeapMap (Option UInt8)}
969+ (hf : m.funcs[callid]? = some f)
970+ (hspec : ⊢ pre st -∗
971+ wp_wasm_iProp m st (f.toLocals []) f.body {} (fun st' vs => post st' vs))
972+ (h_init : ⊢ genHeapInterp σ ∗ pre st)
973+ (himp : m.imports[callid]? = none)
974+ (h_noimports : m.imports.length = 0 )
975+ (hresults : f.results.length = 0 ) :
976+ TerminatesWith {} m callid st [] (fun _ _ => True) := by
977+ -- Combine initial assertion with body spec
978+ have hwp_init : ⊢ genHeapInterp σ ∗
979+ wp_wasm_iProp m st (f.toLocals []) f.body {} (fun st' vs => post st' vs) :=
980+ h_init.trans (BI.sep_mono_right (BI.wand_entails hspec))
981+ -- Trivialize iProp postcondition to get Prop-level WP
982+ have hwp_true : ⊢ genHeapInterp σ ∗ wp_wasm m st (f.toLocals []) f.body {} (fun _ _ => True) :=
983+ hwp_init.trans (BI.sep_mono_right wp_wasm_iProp_trivialize)
984+ -- Extract Prop-level wp_wasm_prop via adequacy
985+ have hwp_prop : wp_wasm_prop m st (f.toLocals []) f.body {} (fun _ _ => True) :=
986+ pure_soundness (hwp_true.trans (wasm_adequacy m st (f.toLocals []) f.body {} (fun _ _ => True) σ))
987+ -- Convert to TerminatesWith
988+ have h_adj : m.funcs[callid - m.imports.length]? = some f := by
989+ rw [h_noimports, Nat.sub_zero]; exact hf
990+ -- Convert hwp_prop: (args.take f.numParams).reverse for args=[] equals []
991+ have hwp_prop' :
992+ wp_wasm_prop m st
993+ (f.toLocals (([] : List Value).take f.numParams).reverse)
994+ f.body {} (fun _ _ => True) := by
995+ simp only [List.take_nil, List.reverse_nil]; exact hwp_prop
996+ exact wp_wasm_prop_to_TerminatesWith h_adj himp hresults (Nat.zero_le _) (fun _ _ h => h) hwp_prop'
997+
892998end Wasm.SepLogic
0 commit comments