(**************************************************************************)
(*                                                                        *)
(*  This file is part of WP plug-in of Frama-C.                           *)
(*                                                                        *)
(*  Copyright (C) 2007-2018                                               *)
(*    CEA (Commissariat a l'energie atomique et aux energies              *)
(*         alternatives)                                                  *)
(*                                                                        *)
(*  you can redistribute it and/or modify it under the terms of the GNU   *)
(*  Lesser General Public License as published by the Free Software       *)
(*  Foundation, version 2.1.                                              *)
(*                                                                        *)
(*  It 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 Lesser General Public License for more details.                   *)
(*                                                                        *)
(*  See the GNU Lesser General Public License version 2.1                 *)
(*  for more details (enclosed in the file licenses/LGPLv2.1).            *)
(*                                                                        *)
(**************************************************************************)

(* This file is generated by Why3's Coq-realize driver *)
(* Beware! Only edit allowed sections below    *)
Require Import BuiltIn.
Require BuiltIn.
Require bool.Bool.
Require int.Int.
Require map.Map.

Require Import ZArith.
Require Import Qedlib.

(* Why3 assumption *)
Inductive addr :=
  | mk_addr : Z -> Z -> addr.
Axiom addr_WhyType : WhyType addr.
Existing Instance addr_WhyType.

(* Why3 assumption *)
Definition offset (v:addr): Z := match v with
  | (mk_addr x x1) => x1
  end.

(* Why3 assumption *)
Definition base (v:addr): Z := match v with
  | (mk_addr x x1) => x
  end.

(* Why3 goal *)
Definition addr_le: addr -> addr -> Prop.
  exact (fun (p q : addr) => ((base p = base q) /\ (offset p <= offset q)%Z)).
Defined.

(* Why3 goal *)
Definition addr_lt: addr -> addr -> Prop.
  exact (fun (p q : addr) => (base p = base q) /\ (offset p < offset q)%Z).
Defined.

(* Why3 goal *)
Definition addr_le_bool: addr -> addr -> bool.
  exact (fun (p q : addr) =>
           andb (Zeq_bool (base p) (base q)) (Zle_bool (offset p) (offset q))).
Defined.

(* Why3 goal *)
Definition addr_lt_bool: addr -> addr -> bool.
  exact (fun (p q : addr) =>
           andb (Zeq_bool (base p) (base q)) (Zlt_bool (offset p) (offset q))).
Defined.

(* Why3 goal *)
Lemma addr_le_def : forall (p:addr) (q:addr), ((base p) = (base q)) ->
  ((addr_le p q) <-> ((offset p) <= (offset q))%Z).
Proof.
  unfold addr_le.
  intuition.
Qed.

(* Why3 goal *)
Lemma addr_lt_def : forall (p:addr) (q:addr), ((base p) = (base q)) ->
  ((addr_lt p q) <-> ((offset p) < (offset q))%Z).
Proof.
  unfold addr_lt.
  intuition.
Qed.

(* Why3 goal *)
Lemma addr_le_bool_def : forall (p:addr) (q:addr), (addr_le p q) <->
  ((addr_le_bool p q) = true).
Proof.
  unfold addr_le. unfold addr_le_bool.
  intros. split; intro H.
  destruct H as [H0 H1].
  rewrite Zeq_is_eq_bool in H0.
  apply Zle_imp_le_bool in H1.
  rewrite H0. rewrite H1.
  compute;reflexivity.
  symmetry in H.
  apply Bool.andb_true_eq in H.
  destruct H as [H1 H2].
  split;[apply Zeq_bool_eq|apply Zle_bool_imp_le];symmetry; assumption.
Qed.

(* Why3 goal *)
Lemma addr_lt_bool_def : forall (p:addr) (q:addr), (addr_lt p q) <->
  ((addr_lt_bool p q) = true).
Proof.
  unfold addr_lt. unfold addr_lt_bool.
  intros. split; intro H.
  destruct H as [H0 H1].
  rewrite Zeq_is_eq_bool in H0.
  rewrite Zlt_is_lt_bool in H1.
  rewrite H0. rewrite H1.
  compute;reflexivity.
  symmetry in H.
  apply Bool.andb_true_eq in H.
  destruct H as [H1 H2].
  split;[apply Zeq_bool_eq|rewrite Zlt_is_lt_bool];symmetry; assumption.
Qed.

(* Why3 assumption *)
Definition null: addr := (mk_addr 0%Z 0%Z).

(* Why3 assumption *)
Definition global (b:Z): addr := (mk_addr b 0%Z).

(* Why3 assumption *)
Definition shift (p:addr) (k:Z): addr := (mk_addr (base p)
  ((offset p) + k)%Z).

(* Why3 assumption *)
Definition included (p:addr) (a:Z) (q:addr) (b:Z): Prop := (0%Z < a)%Z ->
  ((0%Z <= b)%Z /\ (((base p) = (base q)) /\ (((offset q) <= (offset p))%Z /\
  (((offset p) + a)%Z <= ((offset q) + b)%Z)%Z))).

(* Why3 assumption *)
Definition separated (p:addr) (a:Z) (q:addr) (b:Z): Prop := (a <= 0%Z)%Z \/
  ((b <= 0%Z)%Z \/ ((~ ((base p) = (base q))) \/
  ((((offset q) + b)%Z <= (offset p))%Z \/
  (((offset p) + a)%Z <= (offset q))%Z))).

(* Why3 assumption *)
Definition eqmem {a:Type} {a_WT:WhyType a} (m1:(map.Map.map addr a))
  (m2:(map.Map.map addr a)) (p:addr) (a1:Z): Prop := forall (q:addr),
  (included q 1%Z p a1) -> ((map.Map.get m1 q) = (map.Map.get m2 q)).

(* Why3 goal *)
Definition havoc: forall {a:Type} {a_WT:WhyType a}, (map.Map.map addr a) ->
  (map.Map.map addr a) -> addr -> Z -> (map.Map.map addr a).
Admitted.

Definition fhavoc {A : Type}
  (m : farray addr A)
  (w : farray addr A) (p:addr) (n:Z) : (farray addr A) :=
  {| whytype1 := whytype1 m;
     whytype2 := whytype2 m;
     access := @havoc _ (whytype2 m) m w p n |}.

(* Why3 assumption *)
Definition valid_rw (m:(map.Map.map Z Z)) (p:addr) (n:Z): Prop :=
  (0%Z < n)%Z -> ((0%Z < (base p))%Z /\ ((0%Z <= (offset p))%Z /\
  (((offset p) + n)%Z <= (map.Map.get m (base p)))%Z)).

(* Why3 assumption *)
Definition valid_rd (m:(map.Map.map Z Z)) (p:addr) (n:Z): Prop :=
  (0%Z < n)%Z -> ((~ (0%Z = (base p))) /\ ((0%Z <= (offset p))%Z /\
  (((offset p) + n)%Z <= (map.Map.get m (base p)))%Z)).

(* Why3 assumption *)
Definition invalid (m:(map.Map.map Z Z)) (p:addr) (n:Z): Prop :=
  (0%Z < n)%Z -> (((map.Map.get m (base p)) <= (offset p))%Z \/
  (((offset p) + n)%Z <= 0%Z)%Z).

(* Why3 goal *)
Lemma valid_rw_rd : forall (m:(map.Map.map Z Z)), forall (p:addr),
  forall (n:Z), (valid_rw m p n) -> (valid_rd m p n).
Proof.
  intros m p n.
  unfold valid_rw. unfold valid_rd.
  intuition (auto with zarith).
Qed.

(* Why3 goal *)
Lemma valid_string : forall (m:(map.Map.map Z Z)), forall (p:addr),
  ((base p) < 0%Z)%Z -> (((0%Z <= (offset p))%Z /\
  ((offset p) < (map.Map.get m (base p)))%Z) -> ((valid_rd m p 1%Z) /\
  ~ (valid_rw m p 1%Z))).
Proof.
  intros m p.
  unfold valid_rd. unfold valid_rw.
  intuition (auto with zarith).
Qed.

Lemma separated_neq : forall p a q b p' q',
  separated p a q b ->
  included p' 1 p a ->
  included q' 1 q b ->
  p' <> q'.
Proof.
  intros p a q b p' q' SEP InP InQ EQ.
  unfold separated in SEP.
  unfold included in InP,InQ.
  case_lt 0%Z a.
  case_lt 0%Z b.
  intros BPOS APOS.
  generalize InP ; clear InP.
  intro H ; elim H ; clear H ; auto with zarith.
  intro H. clear H.
  intro H ; elim H ; clear H.
  intro BaseP.
  intro H ; elim H ; clear H.
  intros InP1 InP2.
  generalize InQ ; clear InQ.
  intro H ; elim H ; clear H ; auto with zarith.
  intro H. clear H.
  intro H ; elim H ; clear H.
  intro BaseQ.
  intro H ; elim H ; clear H.
  intros InQ1 InQ2.
  generalize SEP ; clear SEP.
  intro H ; elim H ; clear H ; auto with zarith.
  intro H ; elim H ; clear H ; auto with zarith.
  intro H ; elim H ; clear H ; auto with zarith.
  rewrite <- EQ in BaseQ.
  rewrite BaseP in BaseQ.
  contradiction.
  rewrite <- EQ in InQ1,InQ2.
  omega.
Qed.

(* Why3 goal *)
Lemma separated_1 : forall (p:addr) (q:addr), forall (a:Z) (b:Z) (i:Z) (j:Z),
  (separated p a q b) -> ((((offset p) <= i)%Z /\
  (i < ((offset p) + a)%Z)%Z) -> ((((offset q) <= j)%Z /\
  (j < ((offset q) + b)%Z)%Z) -> ~ ((mk_addr (base p) i) = (mk_addr (base q)
  j)))).
Admitted.

(* Why3 goal *)
Definition region: Z -> Z.
Admitted.

(* Why3 goal *)
Definition linked: (map.Map.map Z Z) -> Prop.
Admitted.

(* Why3 goal *)
Definition sconst: (map.Map.map addr Z) -> Prop.
Admitted.

(* Why3 assumption *)
Definition framed (m:(map.Map.map addr addr)): Prop := forall (p:addr),
  ((region (base (map.Map.get m p))) <= 0%Z)%Z.

(* Why3 goal *)
Lemma separated_included : forall (p:addr) (q:addr), forall (a:Z) (b:Z),
  (0%Z < a)%Z -> ((0%Z < b)%Z -> ((separated p a q b) -> ~ (included p a q
  b))).
Proof.
intros p q a b h1 h2 h3.
  unfold separated. unfold included. unfold not.
  intuition.
Admitted.

(*
Lemma separated_region : forall p a q b,
  region (base p) <> region (base q) -> separated p a q b.
Proof.
  intros p a q b RDIFF.
  unfold separated.
  right. right. left.
  intuition.
  apply RDIFF. rewrite H. auto.
Qed.
*)

(* Why3 goal *)
Lemma included_trans : forall (p:addr) (q:addr) (r:addr), forall (a:Z) (b:Z)
  (c:Z), (included p a q b) -> ((included q b r c) -> (included p a r c)).
Proof.
  intros p a q b r c.
  unfold included. intuition.
Qed.

(* Why3 goal *)
Lemma separated_trans : forall (p:addr) (q:addr) (r:addr), forall (a:Z) (b:Z)
  (c:Z), (included p a q b) -> ((separated q b r c) -> (separated p a r c)).
Proof.
  intros p a q b r c.
Admitted.

(* Why3 goal *)
Lemma separated_sym : forall (p:addr) (q:addr), forall (a:Z) (b:Z),
  (separated p a q b) <-> (separated q b p a).
Proof.
  intros p q a b.
  unfold separated. intuition.
Qed.

(* Why3 goal *)
Lemma eqmem_included : forall {a:Type} {a_WT:WhyType a},
  forall (m1:(map.Map.map addr a)) (m2:(map.Map.map addr a)), forall (p:addr)
  (q:addr), forall (a1:Z) (b:Z), (included p a1 q b) -> ((eqmem m1 m2 q b) ->
  (eqmem m1 m2 p a1)).
Proof.
  intros a a_WT m1 m2 p q a1 b h1 h2.
Admitted.

(* Why3 goal *)
Lemma eqmem_sym : forall {a:Type} {a_WT:WhyType a}, forall (m1:(map.Map.map
  addr a)) (m2:(map.Map.map addr a)), forall (p:addr), forall (a1:Z), (eqmem
  m1 m2 p a1) -> (eqmem m2 m1 p a1).
Proof.
  intros A m1 m2 p a. unfold eqmem.
Admitted.

(* Why3 goal *)
Lemma havoc_access : forall {a:Type} {a_WT:WhyType a},
  forall (m0:(map.Map.map addr a)) (m1:(map.Map.map addr a)), forall (q:addr)
  (p:addr), forall (a1:Z), ((separated q 1%Z p a1) -> ((map.Map.get (havoc m0
  m1 p a1) q) = (map.Map.get m1 q))) /\ ((~ (separated q 1%Z p a1)) ->
  ((map.Map.get (havoc m0 m1 p a1) q) = (map.Map.get m0 q))).
Proof.
  intros a a_WT m0 m1 q p a1.
Admitted.

(* Why3 goal *)
Definition int_of_addr: addr -> Z.
Admitted.

(* Why3 goal *)
Definition addr_of_int: Z -> addr.
Admitted.

(* Why3 goal *)
Definition base_offset: Z -> Z.
Admitted.

(* Why3 goal *)
Definition base_index: Z -> Z.
Admitted.

(* Why3 goal *)
Lemma int_of_addr_bijection : forall (a:Z),
  ((int_of_addr (addr_of_int a)) = a).
Admitted.

(* Why3 goal *)
Lemma addr_of_int_bijection : forall (p:addr),
  ((addr_of_int (int_of_addr p)) = p).
Admitted.

(* Why3 goal *)
Lemma addr_of_null : ((int_of_addr null) = 0%Z).
Admitted.

(* Why3 goal *)
Lemma base_offset_zero : ((base_offset 0%Z) = 0%Z).
Admitted.

(* Why3 goal *)
Lemma base_offset_inj : forall (i:Z), ((base_index (base_offset i)) = i).
Admitted.

(* Why3 goal *)
Lemma base_offset_monotonic : forall (i:Z) (j:Z), (i < j)%Z ->
  ((base_offset i) < (base_offset j))%Z.
Admitted.

