Library Labels

Require Import SfLib.
Require Import LibTactics.
Require Import NameSet.

Inductive label : Set :=
  | l_tau: label
  | l_in: namelabel
  | l_out: namelabel
  .

Delimit Scope label_scope with label.
Bind Scope label_scope with label.

Module Notation.
  Notation "'τ'" := (l_tau) (no associativity) : label_scope.
  Notation "a !" := (l_out a) (no associativity, at level 20, p at level 21, format "a !") : label_scope.
  Notation "a ?" := (l_in a) (no associativity, at level 20, p at level 21, format "a ?") : label_scope.
End Notation.

Definition fnl l : nameset := match l with
  | l_tauNameSet.empty
  | l_in aNameSet.singleton a
  | l_out aNameSet.singleton a
  end.

Definition bnl l := match l with
  | l_tauNameSet.empty
  | l_in aNameSet.empty
  | l_out aNameSet.empty
  end.

Definition nl l := NameSet.union (fnl l) (bnl l).

  Lemma label_eq_dec: (l1 l2: label) , {l1=l2}+{l1l2}.
  Proof. repeat decide equality. Qed.

  Lemma label_tau_deq: l, {l=l_tau}+{ll_tau}.
  Proof. intros; eapply label_eq_dec; eauto. Qed.

  Lemma label_eq (l1 l2: label): {l1=l2}+{l1l2}.
  Proof. decide equality; apply name_eq. Qed.

  Fixpoint interleaving {A:Type} (part: list (sum unit unit)) (l1 l2: list A) := match part with
  | inl tt::partmatch l1 with
    | a::l1a::interleaving part l1 l2
    | _l2
    end
  | inr tt::partmatch l2 with
    | a::l2a::interleaving part l1 l2
    | _l1
    end
  | _l1++l2
  end.

  Lemma interleaving_r_nil: {A:Type} lp la1,
    interleaving lp la1 (@nil A) = la1.
  Proof.
    induction lp; simpl; intros; auto.
    apply app_nil_r.
    destruct a; destruct u; auto. destruct la1; auto.
    congruence.
  Qed.

  Lemma interleaving_l_nil: {A:Type} lp l2,
    @interleaving A lp nil l2 = l2.
  Proof.
    induction lp; intros; simpl; auto.
    destruct a; destruct u; auto; destruct l2; auto; congruence.
  Qed.

  Lemma interleaving_com: {A:Type} lp l1 l2,
    (length lp = length l1 + length l2)%nat
    @interleaving A (map (fun pmatch p with inl ttinr tt | inr ttinl tt end) lp) l1 l2 = interleaving lp l2 l1.
  Proof.
    induction lp; intros; auto.
    destruct l1; destruct l2; simpl; auto; try solve [false; simpl in H; omega].
    destruct a; destruct u.
    destruct l1; destruct l2; simpl in *; auto.
    rewrite interleaving_l_nil; rewrite interleaving_r_nil; auto.
    rewrite IHlp; auto. simpl in ×. omega.
    destruct l1; destruct l2; simpl in *; auto.
    rewrite IHlp; auto.
    rewrite IHlp; auto.
  Qed.

  Lemma interleaving_app: {A:Type} l1 l2,
    @interleaving A (map (fun _inl tt) l1 ++ map (fun _inr tt) l2) l1 l2 = l1++l2.
  Proof. induction l1; simpl; intros; auto; f_equal; auto; apply interleaving_l_nil. Qed.