(* Definition of the protocols, including coherence predicate, tags,
   messages and transitions.  *)

Definition getLocal (n : nid) (d : dstatelet) : heap :=
  match find n (dstate d) with
  | Some h => h
  | None => Unit
  end.Notation protocol_soup  := (soup (TaggedMessage)).Structure mixin_of (coh : Pred dstatelet) := Mixin {
    _   : forall d, coh d -> valid (dstate d);
    _   : forall d, coh d -> valid (dsoup d);
    _   : forall d, coh d -> dom (dstate d) =i nodes d;
}.Structure mixin_of (coh : Pred dstatelet) := Mixin {
    _   : forall d, coh d -> valid (dstate d);
    _   : forall d, coh d -> valid (dsoup d);
    _   : forall d, coh d -> dom (dstate d) =i nodes d;
}.Notation class_of := mixin_of (only parsing).Structure cohpred : Type := Pack {sort : dstatelet -> Prop;
                                  _ : class_of nodes sort}.Structure cohpred : Type := Pack {sort : dstatelet -> Prop;
                                  _ : class_of nodes sort}.Structure cohpred : Type := Pack {sort : dstatelet -> Prop;
                                  _ : class_of nodes sort}.Definition pack c := @Pack T c.Definition cohpred := cohpred.Definition CohPredMixin := Mixin.Definition CohPred T m := (@pack T m).Notation "[ 'cohPredMixin' 'of' T ]" := (class _ : mixin_of T)
  (at level 0, format "[ 'cohPredMixin'  'of'  T ]") : form_scope.Notation "[ 'cohpred' 'of' T 'for' C ]" := (@clone T C _ (erefl _) id)
  (at level 0, format "[ 'cohpred'  'of'  T  'for'  C ]") : form_scope.Notation "[ 'cohpred' 'of' T ]" := (@clone T _ _ (erefl _) id)
  (at level 0, format "[ 'cohpred'  'of'  T ]") : form_scope.Canonical cohpred_PredType := mkPredType (@sort nodes).Notation lstate := heap%type.Definition send_step_t (send_safe : nid -> nid -> dstatelet -> seq nat -> Prop) :=
  forall (this to : nid) (d : dstatelet)
         (msg : seq nat) (pf : send_safe this to d msg),
    option lstate.Structure receive_trans := ReceiveTrans
    {
      t_rcv : nat;

      msg_wf : forall d, coh d -> nid -> nid -> TaggedMessage -> bool;

      (* The semantics ensures the "well-formedness" of a message
         being reveived. The following transition, defined as a total
         function, is only executed if m satisfies the msg_wf
         check. However, we still need the coherence passed in order
         to provide facilities for dependently-typed programming.  *)
      receive_step : receive_step_t;

      (* Receiving preserves coherence *)
      r_step_coh : r_step_coh_t msg_wf t_rcv receive_step
    }.Structure receive_trans := ReceiveTrans
    {
      t_rcv : nat;

      msg_wf : forall d, coh d -> nid -> nid -> TaggedMessage -> bool;

      (* The semantics ensures the "well-formedness" of a message
         being reveived. The following transition, defined as a total
         function, is only executed if m satisfies the msg_wf
         check. However, we still need the coherence passed in order
         to provide facilities for dependently-typed programming.  *)
      receive_step : receive_step_t;

      (* Receiving preserves coherence *)
      r_step_coh : r_step_coh_t msg_wf t_rcv receive_step
    }.Structure receive_trans := ReceiveTrans
    {
      t_rcv : nat;

      msg_wf : forall d, coh d -> nid -> nid -> TaggedMessage -> bool;

      (* The semantics ensures the "well-formedness" of a message
         being reveived. The following transition, defined as a total
         function, is only executed if m satisfies the msg_wf
         check. However, we still need the coherence passed in order
         to provide facilities for dependently-typed programming.  *)
      receive_step : receive_step_t;

      (* Receiving preserves coherence *)
      r_step_coh : r_step_coh_t msg_wf t_rcv receive_step
    }.Structure receive_trans := ReceiveTrans
    {
      t_rcv : nat;

      msg_wf : forall d, coh d -> nid -> nid -> TaggedMessage -> bool;

      (* The semantics ensures the "well-formedness" of a message
         being reveived. The following transition, defined as a total
         function, is only executed if m satisfies the msg_wf
         check. However, we still need the coherence passed in order
         to provide facilities for dependently-typed programming.  *)
      receive_step : receive_step_t;

      (* Receiving preserves coherence *)
      r_step_coh : r_step_coh_t msg_wf t_rcv receive_step
    }.Structure receive_trans := ReceiveTrans
    {
      t_rcv : nat;

      msg_wf : forall d, coh d -> nid -> nid -> TaggedMessage -> bool;

      (* The semantics ensures the "well-formedness" of a message
         being reveived. The following transition, defined as a total
         function, is only executed if m satisfies the msg_wf
         check. However, we still need the coherence passed in order
         to provide facilities for dependently-typed programming.  *)
      receive_step : receive_step_t;

      (* Receiving preserves coherence *)
      r_step_coh : r_step_coh_t msg_wf t_rcv receive_step
    }.Structure receive_trans := ReceiveTrans
    {
      t_rcv : nat;

      msg_wf : forall d, coh d -> nid -> nid -> TaggedMessage -> bool;

      (* The semantics ensures the "well-formedness" of a message
         being reveived. The following transition, defined as a total
         function, is only executed if m satisfies the msg_wf
         check. However, we still need the coherence passed in order
         to provide facilities for dependently-typed programming.  *)
      receive_step : receive_step_t;

      (* Receiving preserves coherence *)
      r_step_coh : r_step_coh_t msg_wf t_rcv receive_step
    }.Definition SendTrans := SendTrans.Definition send_trans := send_trans.Definition ReceiveTrans := ReceiveTrans.Definition receive_trans := receive_trans.Definition t_snd := t_snd.Definition send_safe := send_safe.Definition send_step := send_step.Definition send_step_t := send_step_t.Definition s_safe_coh := s_safe_coh.Definition s_safe_in := s_safe_in.Definition s_safe_def := s_safe_def.Definition s_step_coh := s_step_coh.Definition s_step_coh_t := s_step_coh_t.Definition t_rcv := t_rcv.Definition msg_wf := msg_wf.Definition receive_step := receive_step.Definition receive_step_t := receive_step_t.Definition r_step_coh := r_step_coh.Definition r_step_coh_t := r_step_coh_t.Definition snd_tags {nodes} {coh : cohpred nodes}
           (sts : seq (send_trans coh)) := 
  map (@t_snd nodes _) sts.Definition rcv_tags {nodes} {coh : cohpred nodes} (sts : seq (receive_trans coh)) :=
  map (@t_rcv nodes _) sts.Structure protocol := Protocol {
  nodes: dstatelet -> pred nid;
  plab : Label;                        
  coh : cohpred nodes ;
  snd_trans : seq (send_trans coh);
  rcv_trans : seq (receive_trans coh);

  (* All transition tags are unique *)
  snd_uniq : uniq (snd_tags snd_trans);
  rcv_uniq : uniq (rcv_tags rcv_trans);
}.Structure protocol := Protocol {
  nodes: dstatelet -> pred nid;
  plab : Label;                        
  coh : cohpred nodes ;
  snd_trans : seq (send_trans coh);
  rcv_trans : seq (receive_trans coh);

  (* All transition tags are unique *)
  snd_uniq : uniq (snd_tags snd_trans);
  rcv_uniq : uniq (rcv_tags rcv_trans);
}.Structure protocol := Protocol {
  nodes: dstatelet -> pred nid;
  plab : Label;                        
  coh : cohpred nodes ;
  snd_trans : seq (send_trans coh);
  rcv_trans : seq (receive_trans coh);

  (* All transition tags are unique *)
  snd_uniq : uniq (snd_tags snd_trans);
  rcv_uniq : uniq (rcv_tags rcv_trans);
}.Structure protocol := Protocol {
  nodes: dstatelet -> pred nid;
  plab : Label;                        
  coh : cohpred nodes ;
  snd_trans : seq (send_trans coh);
  rcv_trans : seq (receive_trans coh);

  (* All transition tags are unique *)
  snd_uniq : uniq (snd_tags snd_trans);
  rcv_uniq : uniq (rcv_tags rcv_trans);
}.Structure protocol := Protocol {
  nodes: dstatelet -> pred nid;
  plab : Label;                        
  coh : cohpred nodes ;
  snd_trans : seq (send_trans coh);
  rcv_trans : seq (receive_trans coh);

  (* All transition tags are unique *)
  snd_uniq : uniq (snd_tags snd_trans);
  rcv_uniq : uniq (rcv_tags rcv_trans);
}.Structure protocol := Protocol {
  nodes: dstatelet -> pred nid;
  plab : Label;                        
  coh : cohpred nodes ;
  snd_trans : seq (send_trans coh);
  rcv_trans : seq (receive_trans coh);

  (* All transition tags are unique *)
  snd_uniq : uniq (snd_tags snd_trans);
  rcv_uniq : uniq (rcv_tags rcv_trans);
}.Structure protocol := Protocol {
  nodes: dstatelet -> pred nid;
  plab : Label;                        
  coh : cohpred nodes ;
  snd_trans : seq (send_trans coh);
  rcv_trans : seq (receive_trans coh);

  (* All transition tags are unique *)
  snd_uniq : uniq (snd_tags snd_trans);
  rcv_uniq : uniq (rcv_tags rcv_trans);
}.Structure protocol := Protocol {
  nodes: dstatelet -> pred nid;
  plab : Label;                        
  coh : cohpred nodes ;
  snd_trans : seq (send_trans coh);
  rcv_trans : seq (receive_trans coh);

  (* All transition tags are unique *)
  snd_uniq : uniq (snd_tags snd_trans);
  rcv_uniq : uniq (rcv_tags rcv_trans);
}.Structure protocol := Protocol {
  nodes: dstatelet -> pred nid;
  plab : Label;                        
  coh : cohpred nodes ;
  snd_trans : seq (send_trans coh);
  rcv_trans : seq (receive_trans coh);

  (* All transition tags are unique *)
  snd_uniq : uniq (snd_tags snd_trans);
  rcv_uniq : uniq (rcv_tags rcv_trans);
}.Definition protocol := protocol.Definition Protocol := Protocol.Definition plab := plab.Definition nodes := nodes.Definition coh := coh.Definition snd_trans := snd_trans.Definition rcv_trans := rcv_trans.(* Tags for transitions *)
Definition snd_tags p := snd_tags (snd_trans p).Definition rcv_tags p := rcv_tags (rcv_trans p).Definition snd_uniq := snd_uniq.Definition rcv_uniq := rcv_uniq.Definition cohMT d := d = empty_dstatelet.

Lemma pred0v2 d: cohMT d -> valid (dsoup d).