Built with Alectryon, running Coq+SerAPI v8.20.0+0.20.0. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑ Ctrl+↓ to navigate, Ctrl+πŸ–±οΈ to focus. On Mac, use ⌘ instead of Ctrl.
[Loading ML file ssrmatching_plugin.cmxs (using legacy method) ... done]
[Loading ML file ssreflect_plugin.cmxs (using legacy method) ... done]
[Loading ML file ring_plugin.cmxs (using legacy method) ... done]
[Loading ML file zify_plugin.cmxs (using legacy method) ... done]
[Loading ML file micromega_core_plugin.cmxs (using legacy method) ... done]
[Loading ML file micromega_plugin.cmxs (using legacy method) ... done]
[Loading ML file btauto_plugin.cmxs (using legacy method) ... done]
[Loading ML file ltac2_plugin.cmxs (using legacy method) ... done]
Serlib plugin: coq-core.plugins.ltac2_ltac1 is not available: serlib support is missing. Incremental checking for commands in this plugin will be impacted.
[Loading ML file ltac2_ltac1_plugin.cmxs (using legacy method) ... done]
(** * deletetree from the Separation Logic CACM paper by O'Hearn *) (** A tree will be a pointer to either None (represented InjL #()) or Some(l,r) (represented InjR (l, r)), where l and r are themselves trees. *) (** delete_tree is a version of the deletetree function from the paper, written in an OCaml-like language rather than the C code in the paper. *) Definition delete_tree: val := (* the rec: here starts a recursive function *) rec: "delete_tree" "x" := (* !"x" deferences the variable x (variables need to be quoted) *) match: !"x" with SOME "tree" => (* if this tree has children, delete them first. Recall the tree is just a tuple of the left and right child tree pointers. *) (let: "left" := Fst "tree" in let: "right" := Snd "tree" in "delete_tree" "left";; "delete_tree" "right";; (* then free the root pointer *) Free "x") | NONE => (* the way we've represented trees, even an empty tree is a pointer to a None, so free that, too *) Free "x" end. Section proof. Context `{!heapGS Ξ£}. Implicit Types (t l r:loc). (* You can ignore some magic that creates the recursive tree predicate. *) Definition tree_pre (tree: loc -d> iPropO Ξ£): loc -d> iPropO Ξ£ := (Ξ» t, t ↦ NONEV ∨ (βˆƒ l r, t ↦ SOMEV (#l, #r) βˆ— β–· tree l βˆ— β–· tree r))%I.
Ξ£: gFunctors
heapGS0: heapGS Ξ£

Contractive tree_pre
Ξ£: gFunctors
heapGS0: heapGS Ξ£

Contractive tree_pre
solve_contractive. Qed. Definition tree : loc β†’ iProp Ξ£ := fixpoint tree_pre. (** You can take the following as a definition for [tree], in terms of a recursive equation - the ⊣⊒ symbol means "equivalent". You can pretend β–·P is the same as P; this is a technicality required to write recursive definitions. *)
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t: loc

tree t ⊣⊒ t ↦ NONEV ∨ βˆƒ l r, t ↦ SOMEV (#l, #r) βˆ— β–· tree l βˆ— β–· tree r
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t: loc

tree t ⊣⊒ t ↦ NONEV ∨ βˆƒ l r, t ↦ SOMEV (#l, #r) βˆ— β–· tree l βˆ— β–· tree r
apply (fixpoint_unfold tree_pre). Qed.
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t: loc

tree t -βˆ— WP delete_tree #t {{ _, emp }}
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t: loc

tree t -βˆ— WP delete_tree #t {{ _, emp }}
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t: loc

"Ht" : tree t --------------------------------------βˆ— WP delete_tree #t {{ _, emp }}
(* First we should understand how Hoare logic proofs are encoded in Iris. In Iris the goal is going to be [WP e {{ Q }}], which is a separation logic predicate, not a Coq assertion. For intuition, keep in mind that {{P}} e {{Q}} is the same thing as P ⊒ WP e {{ Q }}. Then, you can think of the spec being proven as one where the precondition is all of the premises (the hypotheses) and the program and postcondition are in the goal. *) (* this is how we start a recursive proof: *)
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t: loc

"IH" : β–· βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Ht" : tree t --------------------------------------βˆ— WP delete_tree #t {{ _, emp }}
(* What we get from iLΓΆb is an assumption that delete_tree follows the specification. How is that possible? Couldn't we just use it right away and not have to any work? Indeed! That's why this assumption has the β–· (pronounced "later") in front. β–· P means we only get to know that P holds after one "step" within our function. This is enough to handle all the recursive calls but can't be used to just dismiss the whole proof (otherwise proofs would be easy but not very meaningful) *) (* We destruct the tree predicate into the two branches of the [∨], and carry out the proof separately in each case. *)
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t: loc

"IH" : β–· βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Ht" : t ↦ NONEV --------------------------------------βˆ— WP delete_tree #t {{ _, emp }}
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t: loc
"IH" : β–· βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Ht" : βˆƒ l r, t ↦ SOMEV (#l, #r) βˆ— β–· tree l βˆ— β–· tree r --------------------------------------βˆ— WP delete_tree #t {{ _, emp }}
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t: loc

"IH" : β–· βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Ht" : t ↦ NONEV --------------------------------------βˆ— WP delete_tree #t {{ _, emp }}
(* The first case corresponds to an empty tree, where t ↦ None. In that case the code reduces down to just executing a Free on the root pointer. *)
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t: loc

"IH" : βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Ht" : t ↦ NONEV --------------------------------------βˆ— WP match: ! #t with InjL <> => Free #t | InjR "tree" => let: "left" := Fst "tree" in let: "right" := Snd "tree" in delete_tree "left";; delete_tree "right";; Free #t end {{ _, emp }}
(* I won't go through the motions of using the frame rule and load/store/free axioms; there's a tactic for that *)
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t: loc

"IH" : βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Ht" : t ↦ NONEV --------------------------------------βˆ— WP Free #t {{ _, emp }}
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t: loc

"IH" : βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ |={⊀}=> emp
auto.
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t: loc

"IH" : β–· βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Ht" : βˆƒ l r, t ↦ SOMEV (#l, #r) βˆ— β–· tree l βˆ— β–· tree r --------------------------------------βˆ— WP delete_tree #t {{ _, emp }}
(* In the other case we need to further destruct [tree] to get out the left and right subtrees (both their root pointers and the corresponding [tree] predicates) *)
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t, l, r: loc

"IH" : β–· βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Ht" : t ↦ SOMEV (#l, #r) "Hl" : β–· tree l "Hr" : β–· tree r --------------------------------------βˆ— WP delete_tree #t {{ _, emp }}
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t, l, r: loc

"IH" : βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Ht" : t ↦ SOMEV (#l, #r) "Hl" : tree l "Hr" : tree r --------------------------------------βˆ— WP match: ! #t with InjL <> => Free #t | InjR "tree" => let: "left" := Fst "tree" in let: "right" := Snd "tree" in delete_tree "left";; delete_tree "right";; Free #t end {{ _, emp }}
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t, l, r: loc

"IH" : βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Ht" : t ↦ SOMEV (#l, #r) "Hl" : tree l "Hr" : tree r --------------------------------------βˆ— WP delete_tree #l;; delete_tree #r;; Free #t {{ _, emp }}
(* wp_bind is a tactic to apply the sequencing rule (it takes an argument to pick what should be sequenced, for example in e1;; e2;; e3 you can isolate (e1;;e2) if you want) *)
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t, l, r: loc

"IH" : βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Ht" : t ↦ SOMEV (#l, #r) "Hl" : tree l "Hr" : tree r --------------------------------------βˆ— WP delete_tree #l {{ v, WP v;; delete_tree #r;; Free #t {{ _, emp }} }}
(* The recursive calls make use of the inductive hypothesis "IH", which says any recursive calls to delete_tree can be assumed to satisfy this specification. *)
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t, l, r: loc

"IH" : βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Ht" : t ↦ SOMEV (#l, #r) "Hl" : tree l "Hr" : tree r --------------------------------------βˆ— WP delete_tree #l {{ v, ?Goal v }} βˆ— βˆ€ r0 : val, ?Goal r0 -βˆ— WP r0;; delete_tree #r;; Free #t {{ _, emp }}
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t, l, r: loc

"IH" : βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Hl" : tree l --------------------------------------βˆ— WP delete_tree #l {{ v, ?Goal v }}
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t, l, r: loc
"IH" : βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Ht" : t ↦ SOMEV (#l, #r) "Hr" : tree r --------------------------------------βˆ— βˆ€ r0 : val, ?Goal r0 -βˆ— WP r0;; delete_tree #r;; Free #t {{ _, emp }}
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t, l, r: loc

"IH" : βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Hl" : tree l --------------------------------------βˆ— WP delete_tree #l {{ v, ?Goal v }}
iApply ("IH" with "Hl").
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t, l, r: loc

"IH" : βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Ht" : t ↦ SOMEV (#l, #r) "Hr" : tree r --------------------------------------βˆ— βˆ€ r0 : val, (Ξ» _ : language.val heap_lang, emp) r0 -βˆ— WP r0;; delete_tree #r;; Free #t {{ _, emp }}
(* I'm naming the postcondition from the [delete_tree] specification "Hl" just to emphasize where it came from (it's an [emp] and thus unimportant, the separation logic equivalent of having a hypothesis [True]) *)
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t, l, r: loc
r0: val

"IH" : βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Ht" : t ↦ SOMEV (#l, #r) "Hr" : tree r "Hl" : emp --------------------------------------βˆ— WP delete_tree #r;; Free #t {{ _, emp }}
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t, l, r: loc
r0: val

"IH" : βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Ht" : t ↦ SOMEV (#l, #r) "Hr" : tree r "Hl" : emp --------------------------------------βˆ— WP delete_tree #r {{ v, WP v;; Free #t {{ _, emp }} }}
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t, l, r: loc
r0: val

"IH" : βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Ht" : t ↦ SOMEV (#l, #r) "Hr" : tree r "Hl" : emp --------------------------------------βˆ— WP delete_tree #r {{ v, ?Goal v }} βˆ— βˆ€ r1 : val, ?Goal r1 -βˆ— WP r1;; Free #t {{ _, emp }}
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t, l, r: loc
r0: val

"IH" : βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Hr" : tree r --------------------------------------βˆ— WP delete_tree #r {{ v, ?Goal v }}
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t, l, r: loc
r0: val
"IH" : βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Ht" : t ↦ SOMEV (#l, #r) "Hl" : emp --------------------------------------βˆ— βˆ€ r1 : val, ?Goal r1 -βˆ— WP r1;; Free #t {{ _, emp }}
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t, l, r: loc
r0: val

"IH" : βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Hr" : tree r --------------------------------------βˆ— WP delete_tree #r {{ v, ?Goal v }}
iApply ("IH" with "Hr").
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t, l, r: loc
r0: val

"IH" : βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Ht" : t ↦ SOMEV (#l, #r) "Hl" : emp --------------------------------------βˆ— βˆ€ r : val, (Ξ» _ : val, emp) r -βˆ— WP r;; Free #t {{ _, emp }}
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t, l, r: loc
r0, r1: val

"IH" : βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Ht" : t ↦ SOMEV (#l, #r) "Hl" : emp "Hr" : emp --------------------------------------βˆ— WP Free #t {{ _, emp }}
Ξ£: gFunctors
heapGS0: heapGS Ξ£
t, l, r: loc
r0, r1: val

"IH" : βˆ€ t, tree t -βˆ— WP delete_tree #t {{ _, emp }} --------------------------------------β–‘ "Hl" : emp "Hr" : emp --------------------------------------βˆ— |={⊀}=> emp
auto. Qed. End proof.