Library Semantics

Require Export Syntax.

labels, agents


Inductive label : Set :=
| out : var label
| inp : var label
| tau : label
.

Definition fn_lab (l:label) : vars :=
  match l with
  | tau\{}
  | out a\{a}
  | inp a\{a}
  end.

Inductive abs : Set :=
| abs_def : proc1 abs
.

Definition asubst (F : abs) (P : proc0) : proc0 :=
  match F with
  | abs_def Qsubst Q P
  end.

Inductive conc : Set :=
| conc_def : nat proc0 proc0 conc
.

Inductive agent :=
| ag_proc : proc0 agent
| ag_abs : abs agent
| ag_conc : conc agent
.

Coercion ag_abs : abs >-> agent.
Coercion ag_conc : conc >-> agent.

Tactic Notation "destructA" constr(A) := destruct A as [|[]|[]].

Definition fn_agent A :=
  match A with
  | ag_proc Pfn P
  | ag_abs Fmatch F with | abs_def Pfn P end
  | ag_conc Cmatch C with | conc_def k P Qfn P \u fn Q end
  end.

Definition bn_agent A := match A with
| ag_proc Pbn P
| ag_abs Fmatch F with | abs_def Pbn P end
| ag_conc Cmatch C with | conc_def n P Q
    map_fset (fun kk-n) (filter_fset (fun kk n) (bn P \u bn Q)) end
end.

Definition is_agent A := match A with
| ag_proc Pis_proc P
| ag_abs Fmatch F with | abs_def Pis_proc P end
| ag_conc Cmatch C with | conc_def n P Q
                    ( k, k \in bn P \u bn Q k < n) end
end.

conc_wf checks that bn P has at least n bound names
Definition conc_wf C := match C with
| conc_def n P Q k, k < n k \in bn P
end.

Definition fmapN f F :=
  match F with | abs_def Pabs_def (mapN f P) end.

Definition cmapN f C :=
  match C with | conc_def n P Qconc_def n (mapN (liftN f n) P)(mapN (liftN f n) Q) end.

Definition amapN f A := match A with
| ag_proc Pag_proc (mapN f P)
| ag_abs FfmapN f F
| ag_conc CcmapN f C
end.


LTS


Definition conc_parl C P : conc :=
  match C with
  | conc_def k P' Qconc_def k P' (Q // (shiftN k P))
  end.

Definition conc_parr P C : conc :=
  match C with
  | conc_def k P' Qconc_def k P' ((shiftN k P) // Q)
  end.

Definition abs_parl F P : abs :=
  match F with
  | abs_def Qabs_def (Q // (shiftV P))
  end.

Definition abs_parr P F : abs :=
  match F with
  | abs_def Qabs_def ((shiftV P) // Q)
  end.

Definition parl A P : agent :=
  match A with
  | ag_abs Fag_abs (abs_parl F P)
  | ag_proc P'ag_proc (P' // P)
  | ag_conc Cag_conc (conc_parl C P)
  end.

Definition parr P A : agent :=
  match A with
  | ag_abs Fag_abs (abs_parr P F)
  | ag_proc P'ag_proc (P // P')
  | ag_conc Cag_conc (conc_parr P C)
  end.

Definition down k x := If (x k) then x else x-1.

Tactic Notation "simpl_down" := unfold down in *; intros_all; repeat (case_if; try omega).

Tactic Notation "simpl_name" := simpl_liftN; simpl_down; simpl_permut; intuition.

Definition conc_new (C:conc) : conc :=
  match C with
  | conc_def k P QIf k \in bn P then conc_def (S k) P Q
                                     else conc_def k (mapN (down k) P) (nu (mapN (permut k) Q))
  end.

Definition abs_new (F:abs) : abs :=
  match F with
  | abs_def Pabs_def (nu P)
  end.

Definition new (A: agent) : agent :=
  match A with
  | ag_abs Fag_abs (abs_new F)
  | ag_proc Pag_proc (nu P)
  | ag_conc Cag_conc (conc_new C)
  end.

Definition open_agent k (b : var) A :=
  match A with
  | ag_abs Fmatch F with | abs_def Pag_abs (abs_def (open k b P)) end
  | ag_proc Pag_proc (open k b P)
  | ag_conc Cmatch C with | conc_def k' P Q
                    ag_conc (conc_def k' (open (k+k') b P) (open (k+k') b Q)) end
  end.

Fixpoint genNu {V:Set} k (P:proc V) :=
  match k with
  | 0 ⇒ P
  | S k'nu (genNu k' P)
  end.

Lemma nu_genNu {V:Set}: (P:proc V) n, nu (genNu n P) = genNu n (nu P).
Proof.
  induction n; simpl; auto.
  intros; rewrite× <- IHn.
Qed.

Definition fshiftN k F := match F with
  | abs_def Pabs_def (shiftN k P)
  end.

Definition appr F C : proc0 :=
  match C with
  | conc_def k P QgenNu k (asubst (fshiftN k F) P // Q)
  end.

Definition appl C F : proc0 :=
  match C with
  | conc_def k P QgenNu k (Q // asubst (fshiftN k F) P)
  end.

Inductive lts: proc0 label agent Prop :=
| lts_out : (a:var) P Q, lts (a !(P) Q) (out a) (ag_conc (conc_def 0 P Q))
| lts_inp : (a:var) P, lts (a ? P) (inp a) (ag_abs (abs_def P))
| lts_parl : P Q l A, lts P l A lts (P // Q) l (parl A Q)
| lts_parr : P Q l A, lts P l A lts (Q // P) l (parr Q A)
| lts_new : L P l A,
    ( x, x \notin L x \notin fn_lab l lts (open 0 x P) l (open_agent 0 x A))
    lts (nu P) l (new A)
| lts_taul : P Q a F C, lts P (out a) (ag_conc C)
    lts Q (inp a) (ag_abs F) lts (P // Q) tau (ag_proc (appl C F))
| lts_taur : P Q a F C, lts Q (inp a) (ag_abs F)
    lts P (out a) (ag_conc C) lts (Q // P) tau (ag_proc (appr F C))
.

Hint Constructors lts:hopi.


*Tactics to generate fresh names

Ltac gather_vars V :=
  let A := gather_vars_with (fun x : varsx) in
  let B := gather_vars_with (fun x : var\{x}) in
  let C := gather_vars_with (fun x : labelfn_lab x) in
  let D := gather_vars_with (fun x : proc Vfn x) in
  let E := gather_vars_with (fun x : agentfn_agent x) in
  constr:(A \u B \u C \u D \u E).

The tactic pick_fresh_gen L x creates a new atom fresh from L and called x. Using the tactic gather_vars, we can automate the construction of L. The tactic pick_fresh x creates a new atom called x that is fresh for "everything" in the context.

Ltac pick_fresh_V V x :=
  let L := gather_vars V in (pick_fresh_gen L x).

Ltac pick_fresh_fset_V V L' x :=
  let L := gather_vars V in (pick_fresh_gen (L \u L') x).

Tactic Notation "pick_fresh" ident(x) := pick_fresh_V Empty_set x.


Basic LTS properties


Lemma lts_parl' : P Q l A A', lts P l A parl A Q = A' lts (P // Q) l A'.
Proof.
  intros; subst; eapply lts_parl; eassumption.
Qed.

Lemma lts_parr' : P Q l A A', lts P l A parr Q A = A' lts (Q // P) l A'.
Proof.
  intros; subst; eapply lts_parr; eassumption.
Qed.

Lemma lts_taul' : P A' Q a F C,
    lts P (out a) (ag_conc C) lts Q (inp a) (ag_abs F)
    ag_proc (appl C F) = A' lts (P // Q) tau A'.
Proof.
  intros. subst. eapply lts_taul; eassumption.
Qed.

Lemma lts_taur' : P A' Q a F C,
    lts P (out a) (ag_conc C) lts Q (inp a) (ag_abs F)
    ag_proc (appr F C) = A' lts (Q // P) tau A'.
Proof.
  intros; subst; eapply lts_taur; eassumption.
Qed.

Lemma lts_new' : L P l A A',
    ( x, x \notin L x \notin fn_lab l lts (open 0 x P) l (open_agent 0 x A))
    new A = A' lts (nu P) l A'.
Proof.
  intros; subst; eapply lts_new; eassumption.
Qed.

Hint Resolve lts_parl' lts_parr' lts_taul' lts_taur':hopi.

Lemma lts_tau_proc: P A, lts P tau A P', A = ag_proc P'.
Proof.
  introv Hlts. remember tau as l.
  induction Hlts; inverts Heql; eauto;
    try (destruct IHHlts; try reflexivity; subst; eexists; simpl; reflexivity).
    pick_fresh x.
    forwards*: H0 x.
    destruct H1 as [P']. destructA A; inversion H1.
    simpl; eexists; eauto.
Qed.

Lemma lts_inp_abs : P a A, lts P (inp a) A F, A = ag_abs F.
Proof.
  intros P a A Hlts. remember (inp a) as l.
  induction Hlts; inverts Heql; eauto;
    try (destruct IHHlts; try reflexivity; subst; eexists; simpl; auto).
    pick_fresh x. forwards*: H0 x.
    destruct H1 as [ [P''] ]. destructA A; inversion H1.
    simpl; eexists; eauto.
Qed.

Lemma lts_out_conc : P a A, lts P (out a) A C, A = ag_conc C.
Proof.
  intros P a A Hlts. remember (out a) as l.
  induction Hlts; inverts Heql; eauto;
    try (destruct IHHlts; try reflexivity; subst; eexists; simpl; auto).
    pick_fresh x.
    forwards*: H0 x.
    destruct H1 as [ [ k Q R ]]. destructA A; inverts H1.
    simpl. case_if; eexists; eauto.
Qed.