@@ -1375,4 +1375,110 @@ theorem wasm_heap_adequacy_with_mem
13751375 (wasm_adequacy m st locals prog env Q σ hagree)
13761376 exact hbupd.trans bupd_elim
13771377
1378+ -- ── iProp trivialize / bridge ──────────────────────────────────────────────────
1379+
1380+ /-- Trivialize the iProp postcondition: any wp_wasm_iProp entails the Prop WP with
1381+ True postcondition. Proved by lfp induction: Ψ' s = wp_wasm_iProp s.{Φ:=⌜True⌝}.
1382+ Base cases close by `BI.pure_intro trivial`; step case closes by definitional
1383+ equality (Ψ' ignores the Φ field, so Ψ' {Φ=post} = Ψ' {Φ=⌜True⌝} = lfp {⌜True⌝}). -/
1384+ lemma wp_wasm_iProp_trivialize
1385+ {m : Module} {st : Store Unit} {locals : Locals} {prog : Program}
1386+ {env : HostEnv Unit} {post : Store Unit → List Value → IProp WasmHeapGF} :
1387+ wp_wasm_iProp m st locals prog env post ⊢
1388+ wp_wasm m st locals prog env (fun _ _ => True) := by
1389+ rw [wp_wasm_iProp_pure]
1390+ let Ψ' : LeibnizO WasmStateIProp → IProp WasmHeapGF :=
1391+ fun s => bi_least_fixpoint wp_wasm_iProp_F
1392+ ⟨{ m := s.car.m, st := s.car.st, locals := s.car.locals,
1393+ prog := s.car.prog, env := s.car.env,
1394+ Φ := fun _ _ => iprop% ⌜True⌝ }⟩
1395+ haveI hΨ' : OFE.NonExpansive Ψ' :=
1396+ ⟨fun _ _ _ H => (OFE.eq_of_eqv (OFE.discrete H)) ▸ OFE.Dist.rfl⟩
1397+ have hstep : ⊢ □ (∀ y : LeibnizO WasmStateIProp, wp_wasm_iProp_F Ψ' y -∗ Ψ' y) := by
1398+ iintro !> %s
1399+ obtain ⟨ws⟩ := s
1400+ rcases hprog : ws.prog with _ | ⟨instr, rest⟩
1401+ · -- prog = [] : postcondition → ⌜True⌝ trivially in affine BI
1402+ unfold wp_wasm_iProp_F Ψ'; simp only [LeibnizO.car, hprog]
1403+ iintro _H
1404+ iapply least_fixpoint_unfold_mpr
1405+ unfold wp_wasm_iProp_F; simp only [LeibnizO.car, hprog]
1406+ exact BI.pure_intro trivial
1407+ · by_cases h_ret : instr = Instruction.ret
1408+ · -- prog = .ret :: _ : same trivial close
1409+ subst h_ret
1410+ unfold wp_wasm_iProp_F Ψ'; simp only [LeibnizO.car, hprog]
1411+ iintro _H
1412+ iapply least_fixpoint_unfold_mpr
1413+ unfold wp_wasm_iProp_F; simp only [LeibnizO.car, hprog]
1414+ exact BI.pure_intro trivial
1415+ · -- prog = instr :: rest (instr ≠ .ret): Ψ' ignores Φ, so Hwp IS the goal
1416+ unfold wp_wasm_iProp_F Ψ'; simp only [LeibnizO.car, hprog]
1417+ iintro Hwp
1418+ iapply least_fixpoint_unfold_mpr
1419+ unfold wp_wasm_iProp_F; simp only [LeibnizO.car, hprog]
1420+ iexact Hwp
1421+ have hfp :
1422+ bi_least_fixpoint wp_wasm_iProp_F ⟨{ m, st, locals, prog, env, Φ := post }⟩ ⊢
1423+ Ψ' ⟨{ m, st, locals, prog, env, Φ := post }⟩ :=
1424+ BI.sep_elim_emp_valid_left hstep
1425+ (BI.wand_elim ((BI.wand_entails (least_fixpoint_iter (F := wp_wasm_iProp_F))).trans
1426+ (BI.forall_elim (⟨{ m, st, locals, prog, env, Φ := post }⟩ : LeibnizO WasmStateIProp))))
1427+ exact hfp
1428+
1429+ /-- iProp call bridge: from a function spec instance and a valid initial combined
1430+ assertion `⊢ genHeapInterp σ ∗ pre st`, extract Prop-level termination.
1431+
1432+ Takes the funcSatisfies spec instantiated at a specific (env={}, st, args=[]):
1433+ hspec : ⊢ pre st -∗ wp_wasm_iProp m st (f.toLocals []) f.body {} post
1434+
1435+ Proof chain:
1436+ hspec + h_init → ⊢ genHeapInterp σ ∗ wp_wasm_iProp ... post
1437+ wp_wasm_iProp_trivialize → ⊢ genHeapInterp σ ∗ wp_wasm ... True
1438+ wasm_adequacy + pure_soundness → wp_wasm_prop m st (f.toLocals []) f.body {} True
1439+ wp_wasm_prop_to_TerminatesWith → TerminatesWith {} m callid st [] (fun _ _ => True)
1440+
1441+ NOTE: `⊢ genHeapInterp σ ∗ pre st` is the CORRECT combined form (AUTH ∗ FRAG
1442+ together), obtainable via `genHeap_init` at allocation time. The form
1443+ `genHeapInterp σ ⊢ pre st` (AUTH ⊢ FRAG) is false in the genHeap RA model
1444+ and cannot serve as a hypothesis here.
1445+
1446+ NOTE: This theorem lives in Adequacy (not ModuleLinking) to avoid a circular
1447+ import: ModuleLinking imports Adequacy, so Adequacy cannot reference
1448+ `funcSatisfies`. Callers unpack `funcSatisfies` via `obtain ⟨f, hf, hspec⟩`
1449+ before calling this lemma. -/
1450+ theorem wp_wasm_iProp_call
1451+ {m : Module} {st : Store Unit} {callid : Nat}
1452+ {pre : Store Unit → IProp WasmHeapGF}
1453+ {post : Store Unit → List Value → IProp WasmHeapGF}
1454+ {f : Function} {σ : WasmHeapMap (Option UInt8)}
1455+ (hf : m.funcs[callid]? = some f)
1456+ (hspec : ⊢ pre st -∗
1457+ wp_wasm_iProp m st (f.toLocals []) f.body {} (fun st' vs => post st' vs))
1458+ (h_init : ⊢ genHeapInterp σ ∗ pre st)
1459+ (himp : m.imports[callid]? = none)
1460+ (h_noimports : m.imports.length = 0 )
1461+ (hresults : f.results.length = 0 ) :
1462+ TerminatesWith {} m callid st [] (fun _ _ => True) := by
1463+ -- Combine initial assertion with body spec
1464+ have hwp_init : ⊢ genHeapInterp σ ∗
1465+ wp_wasm_iProp m st (f.toLocals []) f.body {} (fun st' vs => post st' vs) :=
1466+ h_init.trans (BI.sep_mono_right (BI.wand_entails hspec))
1467+ -- Trivialize iProp postcondition to get Prop-level WP
1468+ have hwp_true : ⊢ genHeapInterp σ ∗ wp_wasm m st (f.toLocals []) f.body {} (fun _ _ => True) :=
1469+ hwp_init.trans (BI.sep_mono_right wp_wasm_iProp_trivialize)
1470+ -- Extract Prop-level wp_wasm_prop via adequacy
1471+ have hwp_prop : wp_wasm_prop m st (f.toLocals []) f.body {} (fun _ _ => True) :=
1472+ pure_soundness (hwp_true.trans (wasm_adequacy m st (f.toLocals []) f.body {} (fun _ _ => True) σ))
1473+ -- Convert to TerminatesWith
1474+ have h_adj : m.funcs[callid - m.imports.length]? = some f := by
1475+ rw [h_noimports, Nat.sub_zero]; exact hf
1476+ -- Convert hwp_prop: (args.take f.numParams).reverse for args=[] equals []
1477+ have hwp_prop' :
1478+ wp_wasm_prop m st
1479+ (f.toLocals (([] : List Value).take f.numParams).reverse)
1480+ f.body {} (fun _ _ => True) := by
1481+ simp only [List.take_nil, List.reverse_nil]; exact hwp_prop
1482+ exact wp_wasm_prop_to_TerminatesWith h_adj himp hresults (Nat.zero_le _) (fun _ _ h => h) hwp_prop'
1483+
13781484end Wasm.SepLogic
0 commit comments