(* 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.
(******************************************************************************)
(* noaliasR :                                                                 *)
(*    lemma automated with Canonical Structures to prove/rewrite expressions  *)
(*    with the form                                                           *)
(*      x1 != x2                                                              *)
(*    for x1, x2 : ptr. Usage:                                                *)
(*      rewrite/apply: (noaliasR D)                                           *)
(*    where D : def h, and exists expressions h1 h2 in h, where               *)
(*    hi = xi :-> vi for i in [1,2] and some v1 v2                            *)
(*                                                                            *)
(* The lemma uses several structures. They are defined in different modules.  *)
(* - The module Scan stores in a list all the pointers in h                   *)
(* - The module Search finds a pointer in a list                              *)
(* - The module Search2 finds for two distinct pointers in a list             *)
(* - The module NoAlias combines the above to prove our goal                  *)
(******************************************************************************)
(* Collect pointers in a heap *)
Module Scan.
Section ScanSection.
(* The algorithm is defined as follows: - if the heap is h1 :+ h2, then recurse over h1 and h2 and concatenate the results. - if the heap is x :-> v, then return [x] - otherwise, return [] *)
(* Structure to control the flow of the algorithm *)
Structure tagged_heap := Tag {untag : heap}.
Local Coercion untag : tagged_heap >-> heap.
Definition default_tag := Tag.
Definition ptr_tag := default_tag.
Canonical Structure union_tag h := ptr_tag h.
Definition axiom h s :=
def h -> uniq s /\ forall x, x \in s -> x \in dom h.
(* Main structure *)
Structure form s := Form {heap_of : tagged_heap; _ : axiom heap_of s}.
Local Coercion heap_of : form >-> tagged_heap.

(* Specifications: *)
Lemma union_pf s1 s2 (h1 : form s1) (h2 : form s2) :
axiom (union_tag (h1 :+ h2)) (s1 ++ s2).