From iris.heap_lang Require Import proofmode notation assert. Definition null : loc := Loc 0. Definition miter : val := rec: "miter" "f" "p" := if: "p" = #null then #() else "f" !"p";; "miter" "f" !("p" +ₗ #1). Definition mlength : val := λ: "p", let: "r" := ref #0 in miter (λ: "x", "r" <- !"r" + #1) "p";; !"r". Definition msum : val := λ: "p", let: "r" := ref #0 in miter (λ: "x", "r" <- !"r" + "x") "p";; !"r". Section examples. Context `{!heapGS Σ}. Fixpoint Mlist (L : list Z) (p : loc) : iProp Σ := match L with | nil => ⌜ p = null ⌝ | x :: L' => ∃ p' : loc, ⌜ p ≠ null ⌝ ∗ p ↦ #x ∗ (p +ₗ 1) ↦ #p' ∗ Mlist L' p' end%I. Definition iter_spec_future (it : val) := ∀ (f : val) l (I : list Z → iProp Σ), (∀ x s, {{{ I (x :: s) }}} f #x {{{ RET #(); I s }}}) → ∀ p, {{{ Mlist l p ∗ I l }}} it f #p {{{ RET #(); Mlist l p ∗ I [] }}}. Lemma miter_correct : iter_spec_future miter. Proof. iIntros (f l I Hf p φ) "(Hp & i) ret". iInduction l as [ | x l ] "IH" forall (p). - iDestruct "Hp" as %->. wp_rec. wp_pures. iApply "ret". auto. - simpl Mlist at 3. iDestruct "Hp" as "(%p' & %Hp' & Hp & Hp1 & Hp')". wp_rec. wp_pures. case_bool_decide. congruence. wp_pures. wp_load. wp_apply (Hf with "i") as "i". wp_pures. wp_load. wp_apply ("IH" with "Hp' i") as "(Hp' & i)". iApply "ret". by iFrame. Qed. Definition iter_spec_past (it : val) := ∀ (f : val) l (I : list Z → iProp Σ), (∀ x k, {{{ I k }}} f #x {{{ RET #(); I (k ++ [x]) }}}) → ∀ p, {{{ Mlist l p ∗ I [] }}} it f #p {{{ RET #(); Mlist l p ∗ I l}}}. Lemma future_past it : iter_spec_future it → iter_spec_past it. Proof. iIntros (F f l I Hf p φ) "(Hp & i) ret". wp_apply (F f l (λ k, ∃ prefix, I prefix ∗ ⌜l = prefix ++ k⌝)%I with "[$Hp $i //]") as "(Hp & %s & i & ->)". - clear φ. iIntros (x k φ) "(%s & i & ->) ret". wp_apply (Hf with "i") as "i". iApply "ret". iFrame. iPureIntro. rewrite -app_assoc //. - iApply "ret". rewrite app_nil_r. iFrame. Qed. Lemma miter_correct_past : iter_spec_past miter. Proof. apply future_past, miter_correct. Qed. Definition Zsum := foldl Z.add 0%Z. Lemma msum_correct (p : loc) l : {{{ Mlist l p }}} msum #p {{{ RET #(Zsum l); Mlist l p }}}. Proof. iIntros (φ) "Hp ret". wp_lam. wp_alloc r. wp_pures. wp_apply (miter_correct_past _ _ (λ k, r ↦ #(Zsum k))%I with "[$]") as "(Hp & Hr)". 2: wp_load; by iApply "ret". clear φ p l. iIntros (x k φ) "Hr ret". wp_pures. wp_load. wp_store. iApply "ret". rewrite /Zsum foldl_app /= //. Qed. Lemma mlength_correct (p : loc) l : {{{ Mlist l p }}} mlength #p {{{ RET #(length l); Mlist l p }}}. Proof. iIntros (φ) "Hp ret". wp_lam. wp_alloc r. wp_pures. wp_apply (miter_correct_past _ _ (λ k, r ↦ #(length k))%I with "[$]") as "(Hp & Hr)". 2: wp_load; by iApply "ret". clear φ p l. iIntros (x k φ) "Hr ret". wp_pures. wp_load. wp_store. iApply "ret". rewrite /Zsum length_app /=. replace (length k + 1 : Z)%nat with (Z.of_nat (length k + 1)) by lia. auto. Qed. Lemma Zsum_cons x l : Zsum (x :: l) = (x + Zsum l)%Z. Proof. rewrite /Zsum /=. generalize 0%Z; induction l; intros z; rewrite /=. lia. rewrite -IHl. f_equal. lia. Qed. Lemma msum_correct_future (p : loc) l : {{{ Mlist l p }}} msum #p {{{ RET #(Zsum l); Mlist l p }}}. Proof. iIntros (φ) "Hp ret". wp_lam. wp_alloc r as "Hr". wp_pures. wp_apply (miter_correct _ _ (λ k, r ↦ #(Zsum l - Zsum k))%I with "[$Hp Hr]") as "(Hp & Hr)". 2: { by rewrite Z.sub_diag. } 2: wp_load; rewrite Z.sub_0_r; by iApply "ret". clear φ p. iIntros (x k φ) "Hr ret". wp_pures. wp_load. wp_store. iApply "ret". rewrite Zsum_cons. replace (Zsum l - (x + Zsum k) + x)%Z with (Zsum l - Zsum k)%Z by lia. auto. Qed. Lemma mlength_correct_future (p : loc) l : {{{ Mlist l p }}} mlength #p {{{ RET #(length l); Mlist l p }}}. Proof. iIntros (φ) "Hp ret". wp_lam. wp_alloc r as "Hr". wp_pures. wp_apply (miter_correct _ _ (λ k, r ↦ #(length l - length k))%I with "[$Hp Hr]") as "(Hp & Hr)". 2: { by rewrite Z.sub_diag. } 2: wp_load; rewrite Z.sub_0_r; by iApply "ret". clear φ p. iIntros (x k φ) "Hr ret". wp_pures. wp_load. wp_store. iApply "ret". replace (length l - S (length k) + 1)%Z with (length l - length k)%Z by lia. auto. Qed. Lemma example_only_future (p : loc) : {{{ Mlist [1; 2; 3; 4; 5; 6]%Z p }}} miter (λ: "x", assert: "x" < #7)%V #p {{{ RET #(); Mlist [1; 2; 3; 4; 5; 6]%Z p }}}. Proof. iIntros (φ) "Hp ret". wp_apply (miter_correct _ _ (λ k : list Z, ⌜Forall (Z.gt 7) k⌝)%I with "[$Hp]") as "(Hp & %)". 2: iPureIntro; repeat (lia || constructor). 2: by iApply "ret". clear φ p. iIntros (x k φ) "%Hr ret". wp_pures. wp_pures. inversion Hr; subst. iApply wp_assert. wp_pures. case_bool_decide. - iModIntro. iSplit; auto. iApply "ret"; auto. - lia. Qed. End examples.