(** A representation predicate.  Two things:
    -We assert the existence of an abstract representation [x] of the module state
    using [ghostp sh loc x].
    -This abstract representation is related to the heap layout via the
    representation invariant [R]. *)

Definition rep {A: Type} (r: ident) (x: A) (R: ident -> A -> environ -> mpred) : environ -> mpred :=
  fun rho => (EX sh: Share.t, EX loc: address, ghostp sh loc x) * R r x rho.(** An abstract specification in usual Hoare style. *)

Record aspec {A: Type} := mk_aspec
  { Pspec: A -> environ -> Prop
  ; Qspec: A -> environ -> val -> Prop }.(** An abstract specification in usual Hoare style. *)

Record aspec {A: Type} := mk_aspec
  { Pspec: A -> environ -> Prop
  ; Qspec: A -> environ -> val -> Prop }.(** An abstract specification in usual Hoare style. *)

Record aspec {A: Type} := mk_aspec
  { Pspec: A -> environ -> Prop
  ; Qspec: A -> environ -> val -> Prop }.(** An abstract specification in usual Hoare style. *)

Record aspec {A: Type} := mk_aspec
  { Pspec: A -> environ -> Prop
  ; Qspec: A -> environ -> val -> Prop }.Definition rspec_init (r: ident) (init: A) : unit -> environ -> mpred :=
  fun tt rho => rep r init R rho.Definition init_rspec (r: ident) (init: A) : funspec :=
  mk_funspec (argsig,Tvoid) cc_default unit TT (rspec_init r init * TT).Definition rspec (r: ident) : funspec :=
  mk_funspec (argsig,retty) cc_default unit (rspec_pre r) (rspec_post r).Definition nonvoid (ty: type) := match ty with Tvoid => False | _ => True end.Definition nonvoidty := {ty: type | nonvoid ty}.Definition get_nonvoidty : nonvoidty -> type := @proj1_sig _ nonvoid.(** A module is:
    -An existentially quantified representation invariant
    -A module initialization function, for establishing the invariant initially, and
    -A set of rfuns. *)

Record module (Delta: tycontext) (A: Type) (r: ident) := mk_module
  { Rinv: ident -> A -> environ -> mpred
  ; module_init: init_rfun Delta Rinv r
  ; methods: list (rfun Delta Rinv r) }.(** A module is:
    -An existentially quantified representation invariant
    -A module initialization function, for establishing the invariant initially, and
    -A set of rfuns. *)

Record module (Delta: tycontext) (A: Type) (r: ident) := mk_module
  { Rinv: ident -> A -> environ -> mpred
  ; module_init: init_rfun Delta Rinv r
  ; methods: list (rfun Delta Rinv r) }.(** A module is:
    -An existentially quantified representation invariant
    -A module initialization function, for establishing the invariant initially, and
    -A set of rfuns. *)

Record module (Delta: tycontext) (A: Type) (r: ident) := mk_module
  { Rinv: ident -> A -> environ -> mpred
  ; module_init: init_rfun Delta Rinv r
  ; methods: list (rfun Delta Rinv r) }.(** A module is:
    -An existentially quantified representation invariant
    -A module initialization function, for establishing the invariant initially, and
    -A set of rfuns. *)

Record module (Delta: tycontext) (A: Type) (r: ident) := mk_module
  { Rinv: ident -> A -> environ -> mpred
  ; module_init: init_rfun Delta Rinv r
  ; methods: list (rfun Delta Rinv r) }.(** A module is:
    -An existentially quantified representation invariant
    -A module initialization function, for establishing the invariant initially, and
    -A set of rfuns. *)

Record module (Delta: tycontext) (A: Type) (r: ident) := mk_module
  { Rinv: ident -> A -> environ -> mpred
  ; module_init: init_rfun Delta Rinv r
  ; methods: list (rfun Delta Rinv r) }.Definition identlist_of_module : list ident :=
  map (fun x => f_id (R:=Rinv my_module) x) my_module.(methods).Definition exported (id: ident) := id_in_list id identlist_of_module.Definition xident := {id: ident | exported id=true}.Definition get_ident : xident -> ident := @proj1_sig _ (fun id => exported id=true).Fixpoint rfun_of_ident (id: ident) (l: list (rfun Delta my_module.(Rinv) r))
  : option (rfun Delta my_module.(Rinv) r) :=
  match l with
    nil   => None
  | f::l' => if eq_dec id f.(f_id) then Some f else rfun_of_ident id l'
  end.Definition rfun_of_xident (id: xident) := rfun_of_ident id my_module.(methods).

(* Specifications: *)
Lemma rfun_of_xident_some id : exists f, rfun_of_xident id = Some f.
Lemma rfun_of_xident_eq {id f} : rfun_of_xident id = Some f -> f.(f_id) = id.