(* Copyright (C) 2012  G. Gonthier, B. Ziliani, A. Nanevski, D. Dreyer  This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.  You should have received a copy of the GNU General Public License along with this program.  If not, see <http://www.gnu.org/licenses/>. *)
From mathcomp
From LemmaOverloading
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
(* Same as noalias but with Coq Type Classes. *)
(* Scan *)
Definition scan_axiom h s :=
def h -> uniq s /\ forall x, x \in s -> x \in dom h.
Class Scan (h : heap) :=
{ seq_of : seq ptr ;
scan : scan_axiom h seq_of }.
Program Instance scan_union h1 h2 (f1 : Scan h1) (f2 : Scan h2) :
Scan (h1:+h2) | 2 := {| seq_of := @seq_of _ f1 ++ @seq_of _ f2 |}.
Next Obligation.
case: f1 f2=>s1 /= sc1 [s2 /= sc2] D.
case/(_ (defUnl D)): sc1=>U1 H1; case/(_ (defUnr D)): sc2=>U2 H2.
split=>[|x]; last first.
- rewrite mem_cat; case/orP; [move/H1 | move/H2];
by rewrite domUn !inE /= D => -> //=; rewrite orbT.
rewrite cat_uniq U1 U2 andbT -all_predC.
apply/allP=>x; move/H2=>H3; apply: (introN idP); move/H1=>H4.
by case: defUn D=>// _ _; move/(_ _ H4); rewrite H3.
Qed.
Program Instance scan_ptr A x (v : A) : Scan (x:->v) | 1 := {| seq_of :=  [:: x] |}.
Next Obligation.
rewrite /scan_axiom /= defPt => D; split=>//.
by move=>y; rewrite inE; move/eqP=>->; rewrite domPt inE /= eq_refl D.
Qed.
Program Instance scan_default h : Scan h | 10 := {| seq_of := [::] |}.
Next Obligation.
by move=>_; split.
Qed.
Program Instance search_recurse x y s (f : Search x s) : Search x (y :: s) | 5.
Next Obligation.
by case: f; rewrite inE=>->; rewrite orbT.
Qed.
Example ex_find (x y z : ptr) : x \in [:: z; x; y].
Program Instance search2_foundy x y s (f : Search x s) : Search2 x y (y :: s).
Next Obligation.
case: f=>H1; rewrite /search2_axiom !inE eq_refl.
by rewrite H1 orbT; split=>//; case/andP=>H2 _; case: eqP H1 H2=>// -> ->.
Qed.
Program Instance search2_foundz x y z s (f : Search2 x y s) : Search2 x y (z :: s) | 1.
Next Obligation.
case: f=>[[H1 H2 H3]].
rewrite /search2_axiom /= !inE /= H1 H2 !orbT; split=>//.
by case/andP=>_; apply: H3.
Qed.

Lemma find2E x y s (f : Search2 x y s) : uniq s -> x != y.