{-# OPTIONS --guardedness --sized-types #-}
open import Data.Product
open import Data.Empty
open import Data.Sum
open import Data.Vec
open import Data.List as List
open import Data.Unit
open import Data.Fin
open import Data.Bool renaming (Bool to 𝔹)
open import Relation.Unary using (_∈_; _⊆_;_∉_)
open import Relation.Binary.Construct.Closure.ReflexiveTransitive
open import Relation.Binary.PropositionalEquality
open import Relation.Nullary
open import Size
open import Codata.Thunk
open import is-lib.InfSys
open import Common using (Message)
module FairSubtyping-IS {𝕋 : Set} (message : Message 𝕋) where
open Message message
open import SessionType message
open import Session message
open import Transitions message
open import Convergence message
open import Divergence message
open import Discriminator message
open import Action message using (Action)
open import Subtyping message
open import FairSubtyping message as FS
open import HasTrace message
open import Compliance message
open import FairCompliance message
open import Trace message
open import FairCompliance-IS message
private
U : Set
U = SessionType × SessionType
data FSubIS-RN : Set where
nil-any end-def : FSubIS-RN
ii oo : FSubIS-RN
data FSubCOIS-RN : Set where
co-conv : FSubCOIS-RN
nil-any-r : FinMetaRule U
nil-any-r .Ctx = SessionType
nil-any-r .comp T =
[] ,
(nil , T)
end-def-r : FinMetaRule U
end-def-r .Ctx = Σ[ (T , S) ∈ SessionType × SessionType ] End T × Defined S
end-def-r .comp ((T , S) , _) =
[] ,
(T , S)
ii-r : MetaRule U
ii-r .Ctx = Σ[ (f , g) ∈ Continuation × Continuation ] dom f ⊆ dom g
ii-r .Pos ((f , _) , _) = Σ[ t ∈ 𝕋 ] t ∈ dom f
ii-r .prems ((f , g) , _) (t , _) = f t .force , g t .force
ii-r .conclu ((f , g) , _) = inp f , inp g
oo-r : MetaRule U
oo-r .Ctx = Σ[ (f , g) ∈ Continuation × Continuation ] dom g ⊆ dom f × Witness g
oo-r .Pos ((_ , g) , _) = Σ[ t ∈ 𝕋 ] t ∈ dom g
oo-r .prems ((f , g) , _) (t , _) = f t .force , g t .force
oo-r .conclu ((f , g) , _) = out f , out g
co-conv-r : FinMetaRule U
co-conv-r .Ctx = Σ[ (T , S) ∈ SessionType × SessionType ] T ↓ S
co-conv-r .comp ((T , S) , _) =
[] ,
(T , S)
FSubIS : IS U
FSubIS .Names = FSubIS-RN
FSubIS .rules nil-any = from nil-any-r
FSubIS .rules end-def = from end-def-r
FSubIS .rules ii = ii-r
FSubIS .rules oo = oo-r
FSubCOIS : IS U
FSubCOIS .Names = FSubCOIS-RN
FSubCOIS .rules co-conv = from co-conv-r
_≤F_ : SessionType → SessionType → Set
T ≤F S = FCoInd⟦ FSubIS , FSubCOIS ⟧ (T , S)
_≤Fᵢ_ : SessionType → SessionType → Set
T ≤Fᵢ S = Ind⟦ FSubIS ∪ FSubCOIS ⟧ (T , S)
_≤Fc_ : SessionType → SessionType → Set
T ≤Fc S = CoInd⟦ FSubIS ⟧ (T , S)
FSSpec-⊢ : U → Set
FSSpec-⊢ (T , S) = ∀{R} → R ⊢ T → R ⊢ S
spec-sound : ∀{T S} → FairSubtypingS T S → FSSpec-⊢ (T , S)
spec-sound fs fc = fc-complete (fs (fc-sound fc))
spec-complete : ∀{T S} → FSSpec-⊢ (T , S) → FairSubtypingS T S
spec-complete fs fc = fc-sound (fs (fc-complete fc))
≤Fᵢ->↓ : ∀{S T} → S ≤Fᵢ T → S ↓ T
≤Fᵢ->↓ (fold (inj₁ nil-any , _ , refl , _)) = nil-converges
≤Fᵢ->↓ (fold (inj₁ end-def , (_ , (end , def)) , refl , _)) = end-converges end def
≤Fᵢ->↓ (fold (inj₁ ii , _ , refl , pr)) = converge (pre-conv-inp-back λ x → ↓->preconv (≤Fᵢ->↓ (pr (_ , x))))
≤Fᵢ->↓ (fold (inj₁ oo , (_ , (incl , (t , ok-t))) , refl , pr)) =
converge
λ _ _ → [] , t , none , (_ , incl ok-t , step (out (incl ok-t)) refl) , (_ , ok-t , step (out ok-t) refl) , ≤Fᵢ->↓ (pr (t , ok-t))
≤Fᵢ->↓ (fold (inj₂ co-conv , (_ , conv) , refl , _)) = conv
SpecAux : U → Set
SpecAux (R , T) = Σ[ S ∈ SessionType ] S ≤F T × R ⊢ S
≤Fᵢ->defined : ∀{S T} → Defined S → S ≤Fᵢ T → Defined T
≤Fᵢ->defined def fs = conv->defined def (≤Fᵢ->↓ fs)
spec-bounded-rec : ∀{R S} T → T ≤Fᵢ S → R ⊢ T → R ⊢ᵢ S
spec-bounded-rec _ fs fc =
let _ , reds , succ = con-sound (≤Fᵢ->↓ fs) (fc-sound fc) in
maysucceed->⊢ᵢ reds succ
spec-bounded : SpecAux ⊆ λ (R , S) → R ⊢ᵢ S
spec-bounded (T , fs , fc) = spec-bounded-rec T (fcoind-to-ind fs) fc
spec-cons : SpecAux ⊆ ISF[ FCompIS ] SpecAux
spec-cons {(R , T)} (S , fs , fc) with fc .CoInd⟦_⟧.unfold
spec-cons {(R , T)} (S , fs , fc) | client-end , ((_ , (win , def)) , _) , refl , _ =
client-end , ((R , _) , (win , ≤Fᵢ->defined def (fcoind-to-ind fs))) , refl , λ ()
spec-cons {(out r , _)} ((inp f) , fs , fc) | oi , (((.r , .f) , wit-r) , _) , refl , pr with fs .CoInd⟦_⟧.unfold
... | end-def , (((.(inp f) , _) , (inp e , _)) , _) , refl , _ = ⊥-elim (e _ (proj₂ (fc->defined (pr wit-r))))
... | ii , (((.f , g) , _) , _) , refl , pr' = oi , (_ , wit-r) , refl , λ wit → _ , pr' (_ , proj₂ (fc->defined (pr wit))) , pr wit
spec-cons {(inp r , T)} (out f , fs , fc) | io , (((.r , .f) , wit-f) , _) , refl , pr with fs .CoInd⟦_⟧.unfold
... | end-def , (((.(out f) , _) , (out e , _)) , _) , refl , _ = ⊥-elim (e _ (proj₂ wit-f))
... | oo , (((.f , g) , (incl , wit-g)) , _) , refl , pr' = io , (_ , wit-g) , refl , λ wit → _ , pr' wit , pr (_ , incl (proj₂ wit))
spec-aux-sound : SpecAux ⊆ λ (R , S) → R ⊢ S
spec-aux-sound = bounded-coind[ FCompIS , FCompCOIS ] SpecAux spec-bounded spec-cons
fs-sound : ∀{T S} → T ≤F S → FSSpec-⊢ (T , S)
fs-sound {T} fs fc = spec-aux-sound (T , fs , fc)
≤Fc->sub : ∀{S T} → S ≤Fc T → ∀ {i} → Sub S T i
≤Fc->sub fs with fs .CoInd⟦_⟧.unfold
... | nil-any , _ , refl , _ = nil<:any
... | end-def , (_ , (end , def)) , refl , _ = end<:def end def
... | ii , ((f , g) , incl) , refl , pr = inp<:inp incl λ x → λ where .force → if-def x
where
if-def : (t : 𝕋) → ∀{i} → Sub (f t .force) (g t .force) i
if-def t with t ∈? f
... | yes ok-t = ≤Fc->sub (pr (_ , ok-t))
... | no no-t = subst (λ x → Sub x (g t .force) _) (sym (not-def->nil no-t)) nil<:any
... | oo , (_ , (incl , wit)) , refl , pr = out<:out wit incl λ ok-x → λ where .force → ≤Fc->sub (pr (_ , ok-x))
sub->≤Fc : ∀{S T} → (∀{i} → Sub S T i) → S ≤Fc T
CoInd⟦_⟧.unfold (sub->≤Fc fs) with fs
... | nil<:any = nil-any , _ , refl , λ ()
... | end<:def end def = end-def , (_ , (end , def)) , refl , λ ()
... | inp<:inp incl pr = ii , (_ , incl) , refl , λ (p , _) → sub->≤Fc (pr p .force)
... | out<:out wit incl pr = oo , (_ , (incl , wit)) , refl , λ (_ , ok) → sub->≤Fc (pr ok .force)
sample-cont-prem : ∀{f : Continuation}{t R} → R ⊢ f t .force
→ (pos : Σ[ p ∈ 𝕋 ] p ∈ dom (sample-cont t R nil)) → (sample-cont t R nil) (proj₁ pos) .force ⊢ f (proj₁ pos) .force
sample-cont-prem {f} {t} pr (p , ok-p) with p ?= t
... | yes refl = pr
sample-cont-prem {f} {t} pr (p , ()) | no ¬eq
sample-cont-prems : ∀{f : Continuation}{t} → t ∉ dom f
→ (pos : Σ[ p ∈ 𝕋 ] p ∈ dom f) → (sample-cont t nil win) (proj₁ pos) .force ⊢ f (proj₁ pos) .force
sample-cont-prems {f} {t} no-t (p , ok-p) with p ?= t
... | yes refl = ⊥-elim (no-t ok-p)
... | no ¬eq = win⊢def ok-p
sample-cont-prems' : ∀{f : Continuation}{t R} → R ⊢ f t .force
→ (pos : Σ[ p ∈ 𝕋 ] p ∈ dom f) → (sample-cont t R win) (proj₁ pos) .force ⊢ f (proj₁ pos) .force
sample-cont-prems' {f} {t} pr (p , ok-p) with p ?= t
... | yes refl = pr
... | no ¬eq = win⊢def ok-p
spec-inp->incl : ∀{f g} → FSSpec-⊢ (inp f , inp g) → dom f ⊆ dom g
spec-inp->incl {f} {g} fs {t} ok-t with fs (apply-fcoind oi ((sample-cont t win nil , f) , wit-cont out) (sample-cont-prem {f} {t} (win⊢def ok-t))) .CoInd⟦_⟧.unfold
... | client-end , ((_ , (out e , _)) , _) , refl , _ = ⊥-elim (e t (proj₂ (wit-cont out)))
... | oi , _ , refl , pr = proj₂ (fc->defined (pr (t , proj₂ (wit-cont out))))
spec-out->incl : ∀{f g} → FSSpec-⊢ (out f , out g) → Witness f → dom g ⊆ dom f
spec-out->incl {f} {g} fs wit {t} ok-t with t ∈? f
... | yes ok = ok
... | no no-t with (fs (apply-fcoind io ((sample-cont t nil win , f) , wit) (sample-cont-prems {f} {t} no-t))) .CoInd⟦_⟧.unfold
... | client-end , ((_ , (() , _)) , _) , refl , _
... | io , _ , refl , pr = ⊥-elim (cont-not-def (proj₁ (fc->defined (pr (t , ok-t)))))
spec-out->wit : ∀{f g} → Witness f → FSSpec-⊢ (out f , out g) → Witness g
spec-out->wit {f} {g} wit-f fs with Empty? g
... | inj₂ wit = wit
... | inj₁ e with (fs (apply-fcoind io ((full-cont win , f) , wit-f) λ (_ , ok) → win⊢def ok)) .CoInd⟦_⟧.unfold
... | client-end , ((_ , (() , _)) , _) , refl , _
... | io , ((_ , wit-g) , _) , refl , _ = ⊥-elim (e _ (proj₂ wit-g))
fsspec-cons : FSSpec-⊢ ⊆ ISF[ FSubIS ] FSSpec-⊢
fsspec-cons {nil , T} fs = nil-any , _ , refl , λ ()
fsspec-cons {inp f , nil} fs with (fs (apply-fcoind client-end ((win , _) , (Win-win , inp)) λ ())) .CoInd⟦_⟧.unfold
... | client-end , ((_ , (_ , ())) , _) , refl , _
fsspec-cons {inp f , inp g} fs = ii , ((f , g) , spec-inp->incl fs) , refl ,
λ (p , _) {R} fc-r-f →
let wit = wit-cont (proj₁ (fc->defined fc-r-f)) in
let fc-Or-Ig = fs (apply-fcoind oi ((sample-cont p R nil , f) , wit) (sample-cont-prem {f} {p} fc-r-f)) in
let fc-r-g = ⊢-after-out {sample-cont p R nil} {g} {p} (proj₂ wit) fc-Or-Ig in
subst (λ x → x ⊢ g p .force) (sym force-eq) fc-r-g
fsspec-cons {inp f , out g} fs with Empty? f
... | inj₁ e = end-def , (_ , (inp e , out)) , refl , λ ()
... | inj₂ (t , ok-t) with (fs (apply-fcoind oi ((sample-cont t win nil , f) , wit-cont out) (sample-cont-prem {f} {t} (win⊢def ok-t)))) .CoInd⟦_⟧.unfold
... | client-end , ((_ , (out e , out)) , _) , refl , _ = ⊥-elim (e t (proj₂ (wit-cont out)))
fsspec-cons {out f , nil} fs with (fs (apply-fcoind client-end ((win , _) , (Win-win , out)) λ ())) .CoInd⟦_⟧.unfold
... | client-end , ((_ , (_ , ())) , _) , refl , _
fsspec-cons {out f , inp g} fs with Empty? f
... | inj₁ e = end-def , (_ , (out e , inp)) , refl , λ ()
... | inj₂ (t , ok-t) with (fs (apply-fcoind io ((full-cont win , f) , (t , ok-t)) λ (_ , ok-p) → win⊢def ok-p)) .CoInd⟦_⟧.unfold
... | client-end , ((_ , (() , inp)) , _) , refl , _
fsspec-cons {out f , out g} fs with Empty? f
... | inj₁ e = end-def , (_ , (out e , out)) , refl , λ ()
... | inj₂ (t , ok-t) =
let wit-g = spec-out->wit (t , ok-t) fs in
let incl = spec-out->incl fs (t , ok-t) in
oo , ((f , g) , (incl , wit-g)) , refl , λ (p , ok-p) {R} fc-r-f →
let fc-Ir-Og = fs (apply-fcoind io ((sample-cont p R win , f) , (t , ok-t)) (sample-cont-prems' {f} {p} fc-r-f)) in
let fc-r-g = ⊢-after-in {sample-cont p R win} {g} {p} ok-p fc-Ir-Og in
subst (λ x → x ⊢ g p .force) (sym force-eq) fc-r-g
fsspec->sub : ∀{S T} → FSSpec-⊢ (S , T) → S ≤Fc T
fsspec->sub = coind[ FSubIS ] FSSpec-⊢ fsspec-cons
postulate
not-conv-div : ∀{T S} → ¬ T ↓ S → T ↑ S
fs-convergence : ∀{T S} → FairSubtypingS T S → T ↓ S
fs-convergence {T} {S} fs with Common.excluded-middle {T ↓ S}
fs-convergence {T} {S} fs | yes p = p
fs-convergence {T} {S} fs | no p =
let div = not-conv-div p in
let sub = ≤Fc->sub (fsspec->sub (spec-sound fs)) in
let d-comp = discriminator-compliant sub div in
let ¬d-comp = discriminator-not-compliant sub div in
⊥-elim (¬d-comp (fs d-comp))
fsspec-bounded : ∀{S T} → FSSpec-⊢ (S , T) → S ≤Fᵢ T
fsspec-bounded fs = apply-ind (inj₂ co-conv) (_ , (fs-convergence (spec-complete fs))) λ ()
fs-complete : ∀{S T} → FSSpec-⊢ (S , T) → S ≤F T
fs-complete = bounded-coind[ FSubIS , FSubCOIS ] FSSpec-⊢ fsspec-bounded fsspec-cons