import Capless.Type.Basic
import Capless.Weakening.Typing
import Capless.Weakening.Subcapturing
import Capless.Store
import Capless.Weakening.Subtyping

notation:50 "λ[X<:" S "]" t => Term.tlam S t

notation:50 "λ[X<:" S "]" t => Term.tlam S t

notation:40 "let" "x=" t " in " u => Term.letin t u

notation:40 "let" "x=" t " in " u => Term.letin t u

notation:40 "let" "(c,x)=" t " in " u => Term.letex t u

notation:40 "let" "(c,x)=" t " in " u => Term.letex t u

notation:40 "let" "X=" S " in " t => Term.bindt S t

notation:40 "let" "X=" S " in " t => Term.bindt S t

notation:40 "let" "c=" C " in " t => Term.bindc C t

notation:40 "let" "c=" C " in " t => Term.bindc C t

notation:50 "λ(x:" T ")" t => Term.lam T t

notation:50 "λ(x:" T ")" t => Term.lam T t

notation:50 "λ[c<:" B "]" t => Term.clam B t

notation:50 "λ[c<:" B "]" t => Term.clam B t

notation:50 Γ " ⊢ " E1 " <:e " E2 => ESubtyp Γ E1 E2

notation:50 Γ " ⊢ " E1 " <:e " E2 => ESubtyp Γ E1 E2

notation:50 Γ " ⊢ " T1 " <:s " T2 => SSubtyp Γ T1 T2

notation:50 Γ " ⊢ " T1 " <:s " T2 => SSubtyp Γ T1 T2

notation:50 Γ " ⊢ " T1 " <: " T2 => CSubtyp Γ T1 T2

notation:50 Γ " ⊢ " T1 " <: " T2 => CSubtyp Γ T1 T2

notation:40 Γ " ⊢ " t:80 " : " E " @ " C => Typed Γ t E C

notation:40 Γ " ⊢ " t:80 " : " E " @ " C => Typed Γ t E C

notation:50 Γ " ⊢ " C1 " <:c " C2 => Subcapt Γ C1 C2

notation:max "{x=" x "}" => CaptureSet.singleton x

notation:max "{x=" x "}" => CaptureSet.singleton x

notation:max "{c=" c "}" => CaptureSet.csingleton c

notation:max "{c=" c "}" => CaptureSet.csingleton c

notation:30 Γ ",x:" T => Context.var Γ T

notation:30 Γ ",x:" T => Context.var Γ T

macro "apply?" e:term : tactic => `(tactic| apply $e <;> try

macro "apply?" e:term : tactic => `(tactic| apply $e <;> try easy)

Cont.tweaken

def Cont.tweaken : Cont n m k -> Cont n (m+1) k
| Cont.none => Cont.none
| Cont.cons t cont => Cont.cons t.tweaken cont.tweaken
| Cont.conse t cont => Cont.conse t.tweaken cont.tweaken
| Cont.scope x cont => Cont.scope x cont.tweaken

Cont

inductive Cont : Nat -> Nat -> Nat -> Type where
| none : Cont n m k
| cons :
  (t : Term (n+1) m k) ->
  (cont : Cont n m k) ->
  Cont n m k
| conse :
  (t : Term (n+1) m (k+1)) ->
  (cont : Cont n m k) ->
  Cont n m k
| scope :
  (l : Fin n) ->
  Cont n m k ->
  Cont n m k

TypedCont

inductive TypedCont : Context n m k -> EType n m k -> Cont n m k -> EType n m k -> CaptureSet n k -> Prop where
| none :
  ESubtyp Γ E E' ->
  TypedCont Γ E Cont.none E' {}
| cons {Ct : CaptureSet n k} :
  Typed (Γ,x: T) t (EType.weaken E) Ct.weaken ->
  WellScoped Γ cont Ct ->
  TypedCont Γ E cont E' C ->
  TypedCont Γ (EType.type T) (Cont.cons t cont) E' (C ∪ Ct)
| conse {Ct : CaptureSet n k} :
  Typed ((Γ.cvar (CBinding.bound CBound.star)).var T) t (EType.weaken (EType.cweaken E)) Ct.cweaken.weaken ->
  WellScoped Γ cont Ct ->
  TypedCont Γ E cont E' C ->
  TypedCont Γ (EType.ex T) (Cont.conse t cont) E' (C ∪ Ct)
| scope :
  Context.LBound Γ x S ->
  TypedCont Γ (S^{}) cont E' C ->
  (Γ ⊢ T0 <: S^{}) ->
  TypedCont Γ (EType.type T0) (Cont.scope x cont) E' C

State

structure State (n : Nat) (m : Nat) (k : Nat) where
  σ : Store n m k
  cont : Cont n m k
  t : Term n m k

Term

inductive Term : Nat -> Nat -> Nat -> Type where

| var : Fin n -> Term n m k

| lam : CType n m k -> Term (n+1) m k -> Term n m k

| tlam : SType n m k -> Term n (m+1) k -> Term n m k

| clam : CBound n k -> Term n m (k+1) -> Term n m k

| pack : CaptureSet n k -> Fin n -> Term n m k

| app : Fin n -> Fin n -> Term n m k

| invoke : Fin n -> Fin n -> Term n m k

| tapp : Fin n -> Fin m -> Term n m k

| capp : Fin n -> Fin k -> Term n m k

| letin : Term n m k -> Term (n+1) m k -> Term n m k

| letex : Term n m k -> Term (n+1) m (k+1) -> Term n m k

| bindt : SType n m k -> Term n (m+1) k -> Term n m k

| bindc : CaptureSet n k -> Term n m (k+1) -> Term n m k

| boundary : SType n m k -> Term (n+1) m (k+1) -> Term n m k

Term.IsValue

@[aesop safe constructors]
inductive Term.IsValue : Term n m k -> Prop where
| lam : Term.IsValue (lam E t)
| tlam : Term.IsValue (tlam S t)
| clam : Term.IsValue (clam B t)
| pack : Term.IsValue (pack c x)

SType

inductive SType : Nat -> Nat -> Nat -> Type where
| top : SType n m k
| tvar : Fin m -> SType n m k
| forall : CType n m k -> EType (n+1) m k -> SType n m k
| tforall : SType n m k -> EType n (m+1) k -> SType n m k
| cforall : CBound n k -> EType n m (k+1) -> SType n m k
| box : CType n m k -> SType n m k
| label : SType n m k -> SType n m k

CBound

inductive CBound : Nat -> Nat -> Type where
| upper : CaptureSet n k -> CBound n k
| star : CBound n k

CaptureSet

inductive CaptureSet : Nat -> Nat -> Type where
| empty : CaptureSet n k
| union : CaptureSet n k -> CaptureSet n k -> CaptureSet n k
| singleton : Fin n -> CaptureSet n k
| csingleton : Fin k -> CaptureSet n k

CaptureSet.Subset

inductive CaptureSet.Subset : CaptureSet n k → CaptureSet n k → Prop where
| empty : Subset {} C
| rfl : Subset C C
| union_l :
  Subset C1 C ->
  Subset C2 C ->
  Subset (C1 ∪ C2) C
| union_rl :
  Subset C C1 ->
  Subset C (C1 ∪ C2)
| union_rr :
  Subset C C2 ->
  Subset C (C1 ∪ C2)

EType

inductive EType : Nat -> Nat -> Nat -> Type where
| ex : CType n m (k+1) -> EType n m k
| type : CType n m k -> EType n m k

CType

inductive CType : Nat -> Nat -> Nat -> Type where
| capt : CaptureSet n k -> SType n m k -> CType n m k

SType.tweaken

def SType.tweaken (S : SType n m k) : SType n (m+1) k :=
  S.trename FinFun.weaken

SType.trename

def SType.trename : SType n m k -> FinFun m m' -> SType n m' k
| SType.top, _ => SType.top
| SType.tvar X, f => SType.tvar (f X)
| SType.forall E1 E2, f => SType.forall (E1.trename f) (E2.trename f)
| SType.tforall S E, f => SType.tforall (S.trename f) (E.trename f.ext)
| SType.cforall B E, f => SType.cforall B (E.trename f)
| SType.box T, f => SType.box (T.trename f)
| SType.label S, f => SType.label (S.trename f)

CType.trename

def CType.trename : CType n m k -> FinFun m m' -> CType n m' k
| CType.capt C S, f => CType.capt C (S.trename f)

FinFun

def FinFun (n n' : Nat) : Type :=
  Fin n -> Fin n'

EType.trename

def EType.trename : EType n m k -> FinFun m m' -> EType n m' k
| EType.ex T, f => EType.ex (T.trename f)
| EType.type T, f => EType.type (T.trename f)

FinFun.ext

def FinFun.ext (f : FinFun n n') : FinFun (n+1) (n'+1) :=

FinFun.weaken

def FinFun.weaken : FinFun n (n+1) :=
  Fin.succ

Term.tweaken

def Term.tweaken (t : Term n m k) : Term n (m+1) k := t.trename FinFun.weaken

Term.trename

def Term.trename (t : Term n m k) (f : FinFun m m') : Term n m' k :=
  match t with
  | Term.var x => Term.var x
  | Term.lam E t => Term.lam (E.trename f) (t.trename f)
  | Term.tlam S t => Term.tlam (S.trename f) (t.trename f.ext)
  | Term.clam B t => Term.clam B (t.trename f)
  | Term.pack c x => Term.pack c x
  | Term.app x y => Term.app x y
  | Term.invoke x y => Term.invoke x y
  | Term.tapp x X => Term.tapp x (f X)
  | Term.capp x c => Term.capp x c
  | Term.letin t u => Term.letin (t.trename f) (u.trename f)
  | Term.letex t u => Term.letex (t.trename f) (u.trename f)
  | Term.bindt S t => Term.bindt (S.trename f) (t.trename f.ext)
  | Term.bindc c t => Term.bindc c (t.trename f)
  | Term.boundary S t => Term.boundary (S.trename f) (t.trename f)

TBinding.tweaken

def TBinding.tweaken (b : TBinding n m k) : TBinding n (m+1) k :=
  b.trename FinFun.weaken

TBinding.trename

def TBinding.trename (b : TBinding n m k) (f : FinFun m m') : TBinding n m' k :=
  match b with
  | bound S => bound (S.trename f)
  | inst S => inst (S.trename f)

EType.tweaken

def EType.tweaken (E : EType n m k) : EType n (m+1) k :=
  E.trename FinFun.weaken

CType.tweaken

def CType.tweaken (C : CType n m k) : CType n (m+1) k :=
  C.trename FinFun.weaken

Typed.tweaken

def Typed.tweaken
  (h : Typed Γ t E Ct) :
  Typed (Γ.tvar b) t.tweaken E.tweaken Ct :=

TVarMap.weaken

def TVarMap.weaken {Γ : Context n m k} :
  TVarMap Γ FinFun.weaken (Γ.tvar b) :=

SType.IsVar

inductive SType.IsVar : SType n m k -> Prop where
| tvar : SType.IsVar (SType.tvar X)

SSubtyp

inductive SSubtyp : Context n m k -> SType n m k -> SType n m k -> Prop where
| top :
  SSubtyp Γ S SType.top
| refl :
  SSubtyp Γ S S
| trans :
  SSubtyp Γ S1 S2 ->
  SSubtyp Γ S2 S3 ->
  SSubtyp Γ S1 S3
| tvar :
  Context.TBound Γ X (TBinding.bound S) ->
  SSubtyp Γ (SType.tvar X) S
| tinstl :
  Context.TBound Γ X (TBinding.inst S) ->
  SSubtyp Γ S (SType.tvar X)
| tinstr :
  Context.TBound Γ X (TBinding.inst S) ->
  SSubtyp Γ (SType.tvar X) S
| boxed :
  CSubtyp Γ T1 T2 ->
  SSubtyp Γ (□ T1) (□ T2)
| label :
  SSubtyp Γ S2 S1 ->
  SSubtyp Γ (Label[S1]) (Label[S2])
| xforall :
  CSubtyp Γ E2 E1 ->
  ESubtyp (Context.var Γ E2) F1 F2 ->
  SSubtyp Γ (SType.forall E1 F1) (SType.forall E2 F2)
| tforall :
  SSubtyp Γ S2 S1 ->
  ESubtyp (Context.tvar Γ (TBinding.bound S2)) E1 E2 ->
  SSubtyp Γ (SType.tforall S1 E1) (SType.tforall S2 E2)
| cforall :
  Subbound Γ B2 B1 ->
  ESubtyp (Context.cvar Γ (CBinding.bound B2)) E1 E2 ->
  SSubtyp Γ (SType.cforall B1 E1) (SType.cforall B2 E2)

Context

inductive Context : Nat -> Nat -> Nat -> Type where
| empty : Context 0 0 0
| var : Context n m k -> CType n m k -> Context (n+1) m k
| label : Context n m k -> SType n m k -> Context (n+1) m k
| tvar : Context n m k -> TBinding n m k -> Context n (m+1) k
| cvar : Context n m k -> CBinding n k -> Context n m (k+1)

CBinding

inductive CBinding : Nat -> Nat -> Type where
| bound : CBound n k -> CBinding n k
| inst : CaptureSet n k -> CBinding n k

TBinding

inductive TBinding : Nat -> Nat -> Nat -> Type where
| bound : SType n m k -> TBinding n m k
| inst : SType n m k -> TBinding n m k

Context.LBound

inductive Context.LBound : Context n m k -> Fin n -> SType n m k -> Prop where
| here : LBound (label Γ0 S) 0 S.weaken
| there_var :
  LBound Γ x S ->
  LBound (var Γ E) x.succ S.weaken
| there_tvar :
  LBound Γ x S ->
  LBound (tvar Γ b) x S.tweaken
| there_cvar :
  LBound Γ x S ->
  LBound (cvar Γ b) x S.cweaken
| there_label :
  LBound Γ x S ->
  LBound (label Γ S') x.succ S.weaken

Subcapt.tweaken

def Subcapt.tweaken
  (h : Γ ⊢ C1 <:c C2) :
  (Γ.tvar b) ⊢ C1 <:c C2 :=

WellScoped

inductive WellScoped : Context n m k -> Cont n m k -> CaptureSet n k -> Prop where
| empty :
  WellScoped Γ cont {}
| union :
  WellScoped Γ cont C1 ->
  WellScoped Γ cont C2 ->
  WellScoped Γ cont (C1 ∪ C2)
| singleton :
  Context.Bound Γ x (S^C) ->
  WellScoped Γ cont C ->
  WellScoped Γ cont {x=x}
| csingleton :
  Context.CBound Γ c (CBinding.inst C) ->
  WellScoped Γ cont C ->
  WellScoped Γ cont {c=c}
| cbound :
  Context.CBound Γ c (CBinding.bound (CBound.upper C)) ->
  WellScoped Γ cont C ->
  WellScoped Γ cont {c=c}
| label :
  Context.LBound Γ x S ->
  Cont.HasLabel cont x tail ->
  WellScoped Γ cont {x=x}

Context.Bound

inductive Context.Bound : Context n m k -> Fin n -> CType n m k -> Prop where
| here : Bound (var Γ0 E) 0 E.weaken
| there_var :
  Bound Γ x E ->
  Bound (var Γ E') (Fin.succ x) E.weaken
| there_tvar :
  Bound Γ x E ->
  Bound (tvar Γ b) x E.tweaken
| there_cvar :
  Bound Γ x E ->
  Bound (cvar Γ b) x E.cweaken
| there_label :
  Bound Γ x E ->
  Bound (label Γ S) (Fin.succ x) E.weaken

Context.CBound

inductive Context.CBound : Context n m k -> Fin k -> CBinding n k -> Prop where
| here : CBound (cvar Γ0 b) 0 b.cweaken
| there_var :
  CBound Γ x b ->
  CBound (var Γ E) x b.weaken
| there_tvar :
  CBound Γ x b ->
  CBound (tvar Γ b') x b
| there_cvar :
  CBound Γ x b ->
  CBound (cvar Γ b') (Fin.succ x) b.cweaken
| there_label :
  CBound Γ x b ->
  CBound (label Γ S) x b.weaken

Cont.HasLabel

inductive Cont.HasLabel : Cont n m k -> Fin n -> Cont n m k -> Prop where
| here :
  Cont.HasLabel (Cont.scope l tail) l tail
| there_val :
  Cont.HasLabel cont l tail ->
  Cont.HasLabel (Cont.cons t cont) l tail
| there_tval :
  Cont.HasLabel cont l tail ->
  Cont.HasLabel (Cont.conse t cont) l tail
| there_cval :
  Cont.HasLabel cont l tail ->
  Cont.HasLabel (Cont.scope l' cont) l tail
| there_label :
  Cont.HasLabel cont l tail ->
  Cont.HasLabel (Cont.scope l' cont) l tail

Store.LBound

inductive Store.LBound : Store n m k -> (Fin n) -> SType n m k -> Prop where
| here :
  Store.LBound (Store.label σ S) 0 S.weaken
| there_val :
  Store.LBound σ x S ->
  Store.LBound (Store.val σ t hv) x.succ S.weaken
| there_tval :
  Store.LBound σ x S ->
  Store.LBound (Store.tval σ S') x S.tweaken
| there_cval :
  Store.LBound σ x S ->
  Store.LBound (Store.cval σ C) x S.cweaken
| there_label :
  Store.LBound σ x S ->
  Store.LBound (Store.label σ S') x.succ S.weaken

Subcapt.weaken

def Subcapt.weaken
  (h : Γ ⊢ C1 <:c C2) :
  (Γ,x: T) ⊢ C1.weaken <:c C2.weaken :=

CBinding.rename

def CBinding.rename (b : CBinding n k) (f : FinFun n n') : CBinding n' k :=
  match b with
  | bound b0 => bound (b0.rename f)
  | inst C => inst (C.rename f)

TBinding.rename

def TBinding.rename (b : TBinding n m k) (f : FinFun n n') : TBinding n' m k :=
  match b with
  | bound S => bound (S.rename f)
  | inst S => inst (S.rename f)

SType.rename

def SType.rename : SType n m k -> FinFun n n' -> SType n' m k
| SType.top, _ => SType.top
| SType.tvar X, _ => SType.tvar X
| SType.forall E1 E2, f => SType.forall (E1.rename f) (E2.rename f.ext)
| SType.tforall S E, f => SType.tforall (S.rename f) (E.rename f)
| SType.cforall B E, f => SType.cforall (B.rename f) (E.rename f)
| SType.box T, f => SType.box (T.rename f)
| SType.label S, f => SType.label (S.rename f)

CType.rename

def CType.rename : CType n m k -> FinFun n n' -> CType n' m k
| CType.capt C S, f => CType.capt (C.rename f) (S.rename f)

CBound.rename

def CBound.rename (b : CBound n k) (f : FinFun n n') : CBound n' k :=
  match b with
  | upper C => upper (C.rename f)
  | star => star

EType.rename

def EType.rename : EType n m k -> FinFun n n' -> EType n' m k
| EType.ex T, f => EType.ex (T.rename f)
| EType.type T, f => EType.type (T.rename f)

CaptureSet.rename

@[simp]
def CaptureSet.rename (C : CaptureSet n k) (f : FinFun n n') : CaptureSet n' k :=
  match C with
  | empty => empty
  | union C1 C2 => (C1.rename f) ∪ (C2.rename f)
  | singleton x => {x=f x}
  | csingleton c => {c=c}

VarMap.weaken

def VarMap.weaken {Γ : Context n m k} :
  VarMap Γ FinFun.weaken (Γ.var T) :=

Typed

inductive Typed : Context n m k -> Term n m k -> EType n m k -> CaptureSet n k -> Prop where
| var :
  Context.Bound Γ x (S^C) ->
  Typed Γ (Term.var x) (S^{x=x}) {x=x}
| label :
  Context.LBound Γ x S ->
  Typed Γ (Term.var x) (Label[S]^{x=x}) {x=x}
| pack :
  Typed (Γ.cvar (CBinding.inst C)) (Term.var x) (EType.type T) {x=x} ->
  Typed Γ (Term.pack C x) (∃c.T) {}
| sub :
  Typed Γ t E1 C1 ->
  (Γ ⊢ C1 <:c C2) ->
  (Γ ⊢ E1 <:e E2) ->
  Typed Γ t E2 C2
| abs {C : CaptureSet n k} :
  Typed (Γ,x:T) t E (C.weaken ∪ {x=0}) ->
  Typed Γ (λ(x:T)t) ((∀(x:T)E)^C) {}
| tabs {C : CaptureSet n k} :
  Typed (Γ,X<:S) t E C ->
  Typed Γ (λ[X<:S]t) ((∀[X<:S]E)^C) {}
| cabs {C : CaptureSet n k} :
  Typed (Γ,c<:B) t E C.cweaken ->
  Typed Γ (λ[c<:B]t) ((∀[c<:B]E)^C) {}
| app :
  Typed Γ (Term.var x) (EType.type (∀(x:T)E)^C) {x=x} ->
  Typed Γ (Term.var y) T {x=y} ->
  Typed Γ (Term.app x y) (E.open y) ({x=x} ∪ {x=y})
| invoke :
  Typed Γ (Term.var x) (EType.type (Label[S])^C) {x=x} ->
  Typed Γ (Term.var y) (S^{}) {x=y} ->
  Typed Γ (Term.invoke x y) E ({x=x} ∪ {x=y})
| tapp :
  Typed Γ (Term.var x) (EType.type (∀[X<:SType.tvar X]E)^C) {x=x} ->
  Typed Γ (Term.tapp x X) (E.topen X) {x=x}
| capp :
  Typed Γ (Term.var x) (EType.type (∀[c<:CBound.upper {c=c}]E)^C) {x=x} ->
  Typed Γ (Term.capp x c) (E.copen c) {x=x}
| letin :
  Typed Γ t (EType.type T) C ->
  Typed (Γ,x: T) u E.weaken C.weaken ->
  Typed Γ (let x=t in u) E C
| letex :
  Typed Γ t (EType.ex T) C ->
  Typed ((Γ,c<:*),x: T) u E.cweaken.weaken C.cweaken.weaken ->
  Typed Γ (let (c,x)=t in u) E C
| bindt :
  Typed (Γ,X:=S) t E.tweaken C ->
  Typed Γ (let X=S in t) E C
| bindc :
  Typed (Γ,c:=C) t E.cweaken C0.cweaken ->
  Typed Γ (let c=C in t) E C0
| boundary {Γ : Context n m k} {S : SType n m k} :
  Typed
    ((Γ,c<:CBound.star),x: Label[S.cweaken]^{c=0})
    t
    (S.cweaken.weaken^{}) (C.cweaken.weaken ∪ {c=0} ∪ {x=0}) ->
  Typed Γ (boundary: S in t) (S^CaptureSet.empty) C

Subcapt

inductive Subcapt : Context n m k -> CaptureSet n k -> CaptureSet n k -> Prop where
| trans :
  Subcapt Γ C1 C2 ->
  Subcapt Γ C2 C3 ->
  Subcapt Γ C1 C3
| subset :
  C1 ⊆ C2 ->
  Subcapt Γ C1 C2
| union :
  Subcapt Γ C1 C3 ->
  Subcapt Γ C2 C3 ->
  Subcapt Γ (C1 ∪ C2) C3
| var :
  Context.Bound Γ x (CType.capt C S) ->
  Subcapt Γ {x=x} C
| cinstl :
  Context.CBound Γ c (CBinding.inst C) ->
  Subcapt Γ C {c=c}
| cinstr :
  Context.CBound Γ c (CBinding.inst C) ->
  Subcapt Γ {c=c} C
| cbound :
  Context.CBound Γ c (CBinding.bound (CBound.upper C)) ->
  Subcapt Γ {c=c} C

Term.rename

def Term.rename (t : Term n m k) (f : FinFun n n') : Term n' m k :=
  match t with
  | Term.var x => Term.var (f x)
  | Term.lam E t => Term.lam (E.rename f) (t.rename f.ext)
  | Term.tlam S t => Term.tlam (S.rename f) (t.rename f)
  | Term.clam B t => Term.clam (B.rename f) (t.rename f)
  | Term.pack C x => Term.pack (C.rename f) (f x)
  | Term.app x y => Term.app (f x) (f y)
  | Term.invoke x y => Term.invoke (f x) (f y)
  | Term.tapp x X => Term.tapp (f x) X
  | Term.capp x c => Term.capp (f x) c
  | Term.letin t u => Term.letin (t.rename f) (u.rename f.ext)
  | Term.letex t u => Term.letex (t.rename f) (u.rename f.ext)
  | Term.bindt S t => Term.bindt (S.rename f) (t.rename f)
  | Term.bindc c t => Term.bindc (c.rename f) (t.rename f)
  | Term.boundary S t => Term.boundary (S.rename f) (t.rename f.ext)

Term.weaken

def Term.weaken (t : Term n m k) : Term (n+1) m k := t.rename FinFun.weaken

CBound.weaken

def CBound.weaken (b : CBound n k) : CBound (n+1) k :=
  b.rename FinFun.weaken

EType.weaken

def EType.weaken (E : EType n m k) : EType (n+1) m k :=
  E.rename FinFun.weaken

CVarMap.weaken

def CVarMap.weaken {Γ : Context n m k} :
  CVarMap Γ FinFun.weaken (Γ.cvar b) :=

CaptureSet.weaken

def CaptureSet.weaken (C : CaptureSet n k) : CaptureSet (n+1) k :=
  C.rename FinFun.weaken

CType.weaken

def CType.weaken (C : CType n m k) : CType (n+1) m k :=
  C.rename FinFun.weaken

Cont.weaken

def Cont.weaken : Cont n m k -> Cont (n+1) m k
| Cont.none => Cont.none
| Cont.cons t cont => Cont.cons t.weaken1 cont.weaken
| Cont.conse t cont => Cont.conse t.weaken1 cont.weaken
| Cont.scope x cont => Cont.scope x.succ cont.weaken

def Term.weaken1 (t : Term (n+1) m k) : Term (n+2) m k :=
  t.rename FinFun.weaken.ext

TBinding.weaken

def TBinding.weaken (b : TBinding n m k) : TBinding (n+1) m k :=
  b.rename FinFun.weaken

CBinding.weaken

def CBinding.weaken (b : CBinding n k) : CBinding (n+1) k :=
  b.rename FinFun.weaken

def CaptureSet.weaken1 (C : CaptureSet (n+1) k) : CaptureSet (n+2) k :=
  C.rename FinFun.weaken.ext

SType.weaken

def SType.weaken (S : SType n m k) : SType (n+1) m k :=
  S.rename FinFun.weaken

def EType.weaken1 (E : EType (n+1) m k) : EType (n+2) m k :=
  E.rename FinFun.weaken.ext

CBinding.cweaken

def CBinding.cweaken (b : CBinding n k) : CBinding n (k+1) :=
  b.crename FinFun.weaken

CBinding.crename

def CBinding.crename (b : CBinding n k) (f : FinFun k k') : CBinding n k' :=
  match b with
  | bound b0 => bound (b0.crename f)
  | inst C => inst (C.crename f)

TBinding.crename

def TBinding.crename (b : TBinding n m k) (f : FinFun k k') : TBinding n m k' :=
  match b with
  | bound S => bound (S.crename f)
  | inst S => inst (S.crename f)

CBound.crename

def CBound.crename (b : CBound n k) (f : FinFun k k') : CBound n k' :=
  match b with
  | upper C => upper (C.crename f)
  | star => star

EType.crename

def EType.crename : EType n m k -> FinFun k k' -> EType n m k'
| EType.ex T, f => EType.ex (T.crename f.ext)
| EType.type T, f => EType.type (T.crename f)

CType.crename

def CType.crename : CType n m k -> FinFun k k' -> CType n m k'
| CType.capt C S, f => CType.capt (C.crename f) (S.crename f)

SType.crename

def SType.crename : SType n m k -> FinFun k k' -> SType n m k'
| SType.top, _ => SType.top
| SType.tvar X, _ => SType.tvar X
| SType.forall E1 E2, f => SType.forall (E1.crename f) (E2.crename f)
| SType.tforall S E, f => SType.tforall (S.crename f) (E.crename f)
| SType.cforall B E, f => SType.cforall (B.crename f) (E.crename f.ext)
| SType.box T, f => SType.box (T.crename f)
| SType.label S, f => SType.label (S.crename f)

CaptureSet.crename

@[simp]
def CaptureSet.crename (C : CaptureSet n k) (f : FinFun k k') : CaptureSet n k' :=
  match C with
  | empty => empty
  | union C1 C2 => (C1.crename f) ∪ (C2.crename f)
  | singleton x => {x=x}
  | csingleton c => {c=f c}

Typed.cweaken

def Typed.cweaken
  (h : Typed Γ t E Ct) :
  Typed (Γ.cvar b) t.cweaken E.cweaken Ct.cweaken :=

Term.cweaken

def Term.cweaken (t : Term n m k) : Term n m (k+1) := t.crename FinFun.weaken

Term.crename

def Term.crename (t : Term n m k) (f : FinFun k k') : Term n m k' :=
  match t with
  | Term.var x => Term.var x
  | Term.lam E t => Term.lam (E.crename f) (t.crename f)
  | Term.tlam S t => Term.tlam (S.crename f) (t.crename f)
  | Term.clam B t => Term.clam (B.crename f) (t.crename f.ext)
  | Term.pack C x => Term.pack (C.crename f) x
  | Term.app x y => Term.app x y
  | Term.invoke x y => Term.invoke x y
  | Term.tapp x X => Term.tapp x X
  | Term.capp x c => Term.capp x (f c)
  | Term.letin t u => Term.letin (t.crename f) (u.crename f)
  | Term.letex t u => Term.letex (t.crename f) (u.crename f.ext)
  | Term.bindt S t => Term.bindt (S.crename f) (t.crename f)
  | Term.bindc c t => Term.bindc (c.crename f) (t.crename f.ext)
  | Term.boundary S t => Term.boundary (S.crename f) (t.crename f.ext)

EType.cweaken

def EType.cweaken (E : EType n m k) : EType n m (k+1) :=
  E.crename FinFun.weaken

CType.cweaken

def CType.cweaken (C : CType n m k) : CType n m (k+1) :=
  C.crename FinFun.weaken

TBinding.cweaken

def TBinding.cweaken (b : TBinding n m k) : TBinding n m (k+1) :=
  b.crename FinFun.weaken

CaptureSet.cweaken

def CaptureSet.cweaken (C : CaptureSet n k) : CaptureSet n (k+1) :=
  C.crename FinFun.weaken

CBound.cweaken

def CBound.cweaken (b : CBound n k) : CBound n (k+1) :=
  b.crename FinFun.weaken

Cont.cweaken

def Cont.cweaken : Cont n m k -> Cont n m (k+1)
| Cont.none => Cont.none
| Cont.cons t cont => Cont.cons t.cweaken cont.cweaken
| Cont.conse t cont => Cont.conse t.cweaken1 cont.cweaken
| Cont.scope x cont => Cont.scope x cont.cweaken

def Term.cweaken1 (t : Term n m (k+1)) : Term n m (k+2) :=
  t.crename FinFun.weaken.ext

def CType.cweaken1 (T : CType n m (k+1)) : CType n m (k+2) :=
  T.crename FinFun.weaken.ext

def SType.cweaken1 (S : SType n m (k+1)) : SType n m (k+2) :=
  S.crename FinFun.weaken.ext

def CaptureSet.cweaken1 (C : CaptureSet n (k+1)) : CaptureSet n (k+2) :=
  C.crename FinFun.weaken.ext

def EType.cweaken1 (E : EType n m (k+1)) : EType n m (k+2) :=
  E.crename FinFun.weaken.ext

SType.cweaken

def SType.cweaken (S : SType n m k) : SType n m (k+1) :=
  S.crename FinFun.weaken

Subcapt.cweaken

def Subcapt.cweaken
  (h : Γ ⊢ C1 <:c C2) :
  (Γ.cvar b) ⊢ C1.cweaken <:c C2.cweaken :=

def TVarMap.weaken_ext {Γ : Context n m k} :
  TVarMap
    (Γ.var T)
    FinFun.weaken
    ((Γ.tvar b).var T.tweaken) :=

TVarMap.ext

def TVarMap.ext {Γ : Context n m k} {Δ : Context n m' k}
  (ρ : TVarMap Γ f Δ) (E : CType n m k) :
  TVarMap (Γ.var E) f (Δ.var (E.trename f)) :=

CVarMap

structure CVarMap (Γ : Context n m k) (f : FinFun k k') (Δ : Context n m k') where
  map : ∀ x E, Γ.Bound x E -> Δ.Bound x (E.crename f)
  tmap : ∀ X b, Γ.TBound X b -> Δ.TBound X (b.crename f)
  cmap : ∀ c b, Γ.CBound c b -> Δ.CBound (f c) (b.crename f)
  lmap : ∀ x S, Γ.LBound x S -> Δ.LBound x (S.crename f)

VarMap

structure VarMap (Γ : Context n m k) (f : FinFun n n') (Δ : Context n' m k) where
  map : ∀ x E, Γ.Bound x E -> Δ.Bound (f x) (E.rename f)
  tmap : ∀ X b, Γ.TBound X b -> Δ.TBound X (b.rename f)
  cmap : ∀ c b, Γ.CBound c b -> Δ.CBound c (b.rename f)
  lmap : ∀ x S, Γ.LBound x S -> Δ.LBound (f x) (S.rename f)

TVarMap

structure TVarMap (Γ : Context n m k) (f : FinFun m m') (Δ : Context n m' k) where
  map : ∀ x E, Γ.Bound x E -> Δ.Bound x (E.trename f)
  tmap : ∀ X b, Γ.TBound X b -> Δ.TBound (f X) (b.trename f)
  cmap : ∀ c b, Γ.CBound c b -> Δ.CBound c b
  lmap : ∀ x S, Γ.LBound x S -> Δ.LBound x (S.trename f)

def TVarMap.weaken_cext_ext {Γ : Context n m k} :
  TVarMap
    ((Γ.cvar (CBinding.bound B)).var T)
    FinFun.weaken
    (((Γ.tvar b).cvar (CBinding.bound B)).var T.tweaken) :=

TVarMap.cext

def TVarMap.cext {Γ : Context n m k} {Δ : Context n m' k}
  (ρ : TVarMap Γ f Δ) (b : CBinding n k) :
  TVarMap (Γ.cvar b) f (Δ.cvar b) :=

notation:50 "λ(x:" T ")" t => Term.lam T t

notation:50 "λ[X<:" S "]" t => Term.tlam S t

notation:50 "λ[c<:" B "]" t => Term.clam B t

notation:40 "let" "x=" t " in " u => Term.letin t u

notation:40 "let" "(c,x)=" t " in " u => Term.letex t u

notation:40 "let" "X=" S " in " t => Term.bindt S t

notation:40 "let" "c=" C " in " t => Term.bindc C t

notation:40 "boundary:" S " in " t => Term.boundary S t

notation:40 "boundary:" S " in " t => Term.boundary S t

notation:max "{x=" x "}" => CaptureSet.singleton x

notation:max "{c=" c "}" => CaptureSet.csingleton c

notation:50 Γ " ⊢ " T1 " <:s " T2 => SSubtyp Γ T1 T2

notation:30 Γ ",x:" T => Context.var Γ T

notation:30 Γ ",X<:" T => Context.tvar Γ (TBinding.bound T)

notation:30 Γ ",X<:" T => Context.tvar Γ (TBinding.bound T)

notation:30 Γ ",X:=" T => Context.tvar Γ (TBinding.inst T)

notation:30 Γ ",X:=" T => Context.tvar Γ (TBinding.inst T)

notation:30 Γ ",c<:" B => Context.cvar Γ (CBinding.bound B)

notation:30 Γ ",c<:" B => Context.cvar Γ (CBinding.bound B)

notation:30 Γ ",c<:*" => Context.cvar Γ (CBinding.bound CBou

notation:30 Γ ",c<:*" => Context.cvar Γ (CBinding.bound CBound.star)

notation:30 Γ ",c:=" C => Context.cvar Γ (CBinding.inst C)

notation:30 Γ ",c:=" C => Context.cvar Γ (CBinding.inst C)

notation:40 Γ " ⊢ " t:80 " : " E " @ " C => Typed Γ t E C

SType.top

notation "⊤" => SType.top

notation:50 "∀(x:" T ")" U => SType.forall T U

notation:50 "∀(x:" T ")" U => SType.forall T U

notation:50 "∀[X<:" S "]" T => SType.tforall S T

notation:50 "∀[X<:" S "]" T => SType.tforall S T

notation:50 "∀[c<:" B "]" T => SType.cforall B T

notation:50 "∀[c<:" B "]" T => SType.cforall B T

notation:max S " ^ " C => CType.capt C S

notation:max S " ^ " C => CType.capt C S

notation:40 "∃c." T => EType.ex T

notation:40 "Label[" S "]" => SType.label S

notation:40 "Label[" S "]" => SType.label S

notation:60 "□" T => SType.box T

notation:50 Γ " ⊢ " C1 " <:c " C2 => Subcapt Γ C1 C2

notation:50 Γ " ⊢ " C1 " <:c " C2 => Subcapt Γ C1 C2

CSubtyp.weaken

theorem CSubtyp.weaken
  (h : CSubtyp Γ E1 E2) :
  CSubtyp (Γ.var T) E1.weaken E2.weaken

Subbound.tweaken

theorem Subbound.tweaken
  (h : Subbound Γ B1 B2) :
  Subbound (Γ.tvar b) B1 B2

Subbound.weaken

theorem Subbound.weaken
  (h : Subbound Γ B1 B2) :
  Subbound (Γ.var b) B1.weaken B2.weaken

ESubtyp.weaken

theorem ESubtyp.weaken
  (h : ESubtyp Γ E1 E2) :
  ESubtyp (Γ.var T) E1.weaken E2.weaken

SSubtyp.tweaken

theorem SSubtyp.tweaken
  (h : SSubtyp Γ S1 S2) :
  SSubtyp (Γ.tvar b) S1.tweaken S2.tweaken

CSubtyp.tweaken

theorem CSubtyp.tweaken
  (h : CSubtyp Γ E1 E2) :
  CSubtyp (Γ.tvar b) E1.tweaken E2.tweaken

Typed.weaken

theorem Typed.weaken
  (h : Typed Γ t E Ct) :
  Typed (Γ.var T) t.weaken E.weaken Ct.weaken

SSubtyp.weaken

theorem SSubtyp.weaken
  (h : SSubtyp Γ S1 S2) :
  ∀ b, SSubtyp (Γ.var b) S1.weaken S2.weaken

ESubtyp.tweaken

theorem ESubtyp.tweaken
  (h : ESubtyp Γ E1 E2) :
  ESubtyp (Γ.tvar b) E1.tweaken E2.tweaken

theorem EType.trename_rename_comm (E : EType n m k) (f : FinFun n n') (g : FinFun m m') :
  (E.trename g).rename f = (E.rename f).trename g

theorem CType.trename_rename_comm (T : CType n m k) (f : FinFun n n') (g : FinFun m m') :
  (T.trename g).rename f = (T.rename f).trename g

theorem SType.trename_rename_comm (S : SType n m k) (f : FinFun n n') (g : FinFun m m') :
  (S.trename g).rename f = (S.rename f).trename g

CSubtyp.cweaken

theorem CSubtyp.cweaken
  (h : CSubtyp Γ E1 E2) :
  CSubtyp (Γ.cvar b) E1.cweaken E2.cweaken

Subbound.cweaken

theorem Subbound.cweaken
  (h : Subbound Γ B1 B2) :
  Subbound (Γ.cvar b) B1.cweaken B2.cweaken

ESubtyp.cweaken

theorem ESubtyp.cweaken
  (h : ESubtyp Γ E1 E2) :
  ESubtyp (Γ.cvar b) E1.cweaken E2.cweaken

theorem EType.crename_trename_comm (E : EType n m k) (f : FinFun k k') (g : FinFun m m') :
  (E.crename f).trename g = (E.trename g).crename f

theorem CType.crename_trename_comm (T : CType n m k) (f : FinFun k k') (g : FinFun m m') :
  (T.crename f).trename g = (T.trename g).crename f

theorem SType.crename_trename_comm (S : SType n m k) (f : FinFun k k') (g : FinFun m m') :
  (S.crename f).trename g = (S.trename g).crename f

SSubtyp.cweaken

theorem SSubtyp.cweaken
  (h : SSubtyp Γ S1 S2) :
  ∀ b, SSubtyp (Γ.cvar b) S1.cweaken S2.cweaken

theorem Typed.tweaken_ext {Γ : Context n m k}
  (h : Typed (Γ.var T) t E Ct) :
  Typed ((Γ.tvar b).var T.tweaken) t.tweaken E.tweaken Ct

theorem Typed.tweaken_cext_ext {Γ : Context n m k}
  (h : Typed ((Γ.cvar (CBinding.bound B)).var T) t E Ct) :
  Typed (((Γ.tvar b).cvar (CBinding.bound B)).var T.tweaken) t.tweaken E.tweaken Ct

theorem EType.tweaken_ex (T : CType n m (k+1)) :
  (EType.ex T).tweaken = EType.ex T.tweaken

theorem EType.tweaken_weaken (E : EType n m k) :
  E.weaken.tweaken = E.tweaken.weaken

theorem EType.tweaken_cweaken (E : EType n m k) :
  E.cweaken.tweaken = E.tweaken.cweaken

Capless.Cont.HasLabel.tweaken

theorem Cont.HasLabel.tweaken
  (h : Cont.HasLabel cont x tail) :
  Cont.HasLabel cont.tweaken x tail.tweaken

Capless.WellScoped.tweaken

theorem WellScoped.tweaken
  (h : WellScoped Γ cont Ct) :
  WellScoped (Γ.tvar b) cont.tweaken Ct

import Capless.Store

import Capless.Weakening.Typing

import Capless.Weakening.Subtyping

import Capless.Weakening.Subcapturing

namespace Capless

theorem TypedCont.tweaken
  (h : TypedCont Γ E t E' C0) :
  TypedCont (Γ.tvar S) E.tweaken t.tweaken E'.tweaken C0 :=

:= by
  induction h
  case none =>
    simp [Cont.tweaken]
    apply none
    apply? ESubtyp.tweaken
  case cons ht hs _ ih =>
    simp [Cont.tweaken]
    -- simp [EType.tweaken_type]
    apply cons
    { have ht1 := ht.tweaken_ext (b := S)
      rw [EType.tweaken_weaken] at ht1
      exact ht1 }
    { apply hs.tweaken }
    { exact ih }
  case conse ht hs _ ih =>
    simp [Cont.tweaken]
    simp [EType.tweaken_ex]
    apply conse
    { have ht1 := ht.tweaken_cext_ext (b := S)
      rw [EType.tweaken_weaken] at ht1
      rw [EType.tweaken_cweaken] at ht1
      exact ht1 }
    { apply hs.tweaken }
    { exact ih }
  case scope hb _ hs ih =>
    simp [Cont.tweaken]
    apply scope
    have hb1 := Context.LBound.there_tvar (b := S) hb
    exact hb1
    simp at ih
    apply ih
    have h := hs.tweaken (b:=S)
    aesop


theorem SType.crename_rename_comm (S : SType n m k) (f : FinFun n n') (g : FinFun k k') :
  (S.rename f).crename g = (S.crename g).rename f :=
  match S with
  | SType.top => by simp [SType.rename, SType.crename]
  | SType.tvar X => by simp [SType.rename, SType.crename]
  | SType.forall E1 E2 => by
    have ih1 := CType.crename_rename_comm E1 f g
    have ih2 := EType.crename_rename_comm E2 f.ext g
    simp [SType.rename, SType.crename, ih1, ih2]
  | SType.tforall S E => by
    have ih1 := SType.crename_rename_comm S f g
    have ih2 := EType.crename_rename_comm E f g
    simp [SType.rename, SType.crename, ih1, ih2]
  | SType.cforall B E => by
    have ih := EType.crename_rename_comm E f g.ext
    simp [SType.rename, CBound.crename_rename_comm, SType.crename, ih]
  | SType.box T => by
    have ih := CType.crename_rename_comm T f g
    simp [SType.rename, SType.crename, ih]
  | SType.label S => by
    have ih := SType.crename_rename_comm S f g
    simp [SType.rename, SType.crename, ih]

import Capless.Type.Renaming
import Capless.Type.Core
import Capless.CaptureSet

notation:max "{x=" x "}" => CaptureSet.singleton x

notation:max "{c=" c "}" => CaptureSet.csingleton c

CaptureSet.crename

@[simp]
def CaptureSet.crename (C : CaptureSet n k) (f : FinFun k k') : CaptureSet n k' :=
  match C with
  | empty => empty
  | union C1 C2 => (C1.crename f) ∪ (C2.crename f)
  | singleton x => {x=x}
  | csingleton c => {c=f c}

CaptureSet

inductive CaptureSet : Nat -> Nat -> Type where
| empty : CaptureSet n k
| union : CaptureSet n k -> CaptureSet n k -> CaptureSet n k
| singleton : Fin n -> CaptureSet n k
| csingleton : Fin k -> CaptureSet n k

FinFun

def FinFun (n n' : Nat) : Type :=
  Fin n -> Fin n'

SType

inductive SType : Nat -> Nat -> Nat -> Type where
| top : SType n m k
| tvar : Fin m -> SType n m k
| forall : CType n m k -> EType (n+1) m k -> SType n m k
| tforall : SType n m k -> EType n (m+1) k -> SType n m k
| cforall : CBound n k -> EType n m (k+1) -> SType n m k
| box : CType n m k -> SType n m k
| label : SType n m k -> SType n m k

FinFun.ext

def FinFun.ext (f : FinFun n n') : FinFun (n+1) (n'+1) :=

CBound.rename

def CBound.rename (b : CBound n k) (f : FinFun n n') : CBound n' k :=
  match b with
  | upper C => upper (C.rename f)
  | star => star

SType.rename

def SType.rename : SType n m k -> FinFun n n' -> SType n' m k
| SType.top, _ => SType.top
| SType.tvar X, _ => SType.tvar X
| SType.forall E1 E2, f => SType.forall (E1.rename f) (E2.rename f.ext)
| SType.tforall S E, f => SType.tforall (S.rename f) (E.rename f)
| SType.cforall B E, f => SType.cforall (B.rename f) (E.rename f)
| SType.box T, f => SType.box (T.rename f)
| SType.label S, f => SType.label (S.rename f)

CType.rename

def CType.rename : CType n m k -> FinFun n n' -> CType n' m k
| CType.capt C S, f => CType.capt (C.rename f) (S.rename f)

CType

inductive CType : Nat -> Nat -> Nat -> Type where
| capt : CaptureSet n k -> SType n m k -> CType n m k

EType.rename

def EType.rename : EType n m k -> FinFun n n' -> EType n' m k
| EType.ex T, f => EType.ex (T.rename f)
| EType.type T, f => EType.type (T.rename f)

EType

inductive EType : Nat -> Nat -> Nat -> Type where
| ex : CType n m (k+1) -> EType n m k
| type : CType n m k -> EType n m k

CaptureSet.rename

@[simp]
def CaptureSet.rename (C : CaptureSet n k) (f : FinFun n n') : CaptureSet n' k :=
  match C with
  | empty => empty
  | union C1 C2 => (C1.rename f) ∪ (C2.rename f)
  | singleton x => {x=f x}
  | csingleton c => {c=c}

CType.crename

def CType.crename : CType n m k -> FinFun k k' -> CType n m k'
| CType.capt C S, f => CType.capt (C.crename f) (S.crename f)

EType.crename

def EType.crename : EType n m k -> FinFun k k' -> EType n m k'
| EType.ex T, f => EType.ex (T.crename f.ext)
| EType.type T, f => EType.type (T.crename f)

CBound.crename

def CBound.crename (b : CBound n k) (f : FinFun k k') : CBound n k' :=
  match b with
  | upper C => upper (C.crename f)
  | star => star

SType.crename

def SType.crename : SType n m k -> FinFun k k' -> SType n m k'
| SType.top, _ => SType.top
| SType.tvar X, _ => SType.tvar X
| SType.forall E1 E2, f => SType.forall (E1.crename f) (E2.crename f)
| SType.tforall S E, f => SType.tforall (S.crename f) (E.crename f)
| SType.cforall B E, f => SType.cforall (B.crename f) (E.crename f.ext)
| SType.box T, f => SType.box (T.crename f)
| SType.label S, f => SType.label (S.crename f)

SType.top

notation "⊤" => SType.top

notation:50 "∀(x:" T ")" U => SType.forall T U

notation:50 "∀[X<:" S "]" T => SType.tforall S T

notation:50 "∀[c<:" B "]" T => SType.cforall B T

notation:max S " ^ " C => CType.capt C S

notation:40 "∃c." T => EType.ex T

notation:40 "Label[" S "]" => SType.label S

notation:60 "□" T => SType.box T

theorem CaptureSet.crename_rename_comm {C : CaptureSet n k} {f : FinFun n n'} {g : FinFun k k'} :
  (C.rename f).crename g = (C.crename g).rename f

theorem CBound.crename_rename_comm {b : CBound n k} :
  (b.crename f).rename g = (b.rename g).crename f

theorem EType.crename_rename_comm (E : EType n m k) (f : FinFun n n') (g : FinFun k k') :
  (E.rename f).crename g = (E.crename g).rename f

theorem CType.crename_rename_comm (C : CType n m k) (f : FinFun n n') (g : FinFun k k') :
  (C.rename f).crename g = (C.crename g).rename f

import Capless.Type.Core

import Capless.Type.Renaming

namespace Capless


theorem SType.rename_rename (S : SType n m k) (f : FinFun n n') (g : FinFun n' n'') :
  (S.rename f).rename g = S.rename (g ∘ f) :=
  match S with
  | SType.top => by simp [SType.rename]
  | SType.tvar X => by simp [SType.rename]
  | SType.forall E1 E2 => by
    have ih1 := CType.rename_rename E1 f g
    have ih2 := EType.rename_rename E2 f.ext g.ext
    simp [SType.rename, ih1, ih2, FinFun.ext_comp_ext]
  | SType.tforall S E => by
    have ih1 := SType.rename_rename S f g
    have ih2 := EType.rename_rename E f g
    simp [SType.rename, ih1, ih2]
  | SType.cforall B E => by
    have ih := EType.rename_rename E f g
    simp [SType.rename, CBound.rename_rename, ih]
  | SType.box T => by
    have ih := CType.rename_rename T f g
    simp [SType.rename, ih]
  | SType.label S => by
    have ih := SType.rename_rename S f g
    simp [SType.rename, ih]

import Capless.Basic
import Capless.Type.Renaming
import Capless.Type.Core
import Capless.CaptureSet

SType

inductive SType : Nat -> Nat -> Nat -> Type where
| top : SType n m k
| tvar : Fin m -> SType n m k
| forall : CType n m k -> EType (n+1) m k -> SType n m k
| tforall : SType n m k -> EType n (m+1) k -> SType n m k
| cforall : CBound n k -> EType n m (k+1) -> SType n m k
| box : CType n m k -> SType n m k
| label : SType n m k -> SType n m k

FinFun.ext

def FinFun.ext (f : FinFun n n') : FinFun (n+1) (n'+1) :=

CBound.rename

def CBound.rename (b : CBound n k) (f : FinFun n n') : CBound n' k :=
  match b with
  | upper C => upper (C.rename f)
  | star => star

SType.rename

def SType.rename : SType n m k -> FinFun n n' -> SType n' m k
| SType.top, _ => SType.top
| SType.tvar X, _ => SType.tvar X
| SType.forall E1 E2, f => SType.forall (E1.rename f) (E2.rename f.ext)
| SType.tforall S E, f => SType.tforall (S.rename f) (E.rename f)
| SType.cforall B E, f => SType.cforall (B.rename f) (E.rename f)
| SType.box T, f => SType.box (T.rename f)
| SType.label S, f => SType.label (S.rename f)

CType.rename

def CType.rename : CType n m k -> FinFun n n' -> CType n' m k
| CType.capt C S, f => CType.capt (C.rename f) (S.rename f)

CType

inductive CType : Nat -> Nat -> Nat -> Type where
| capt : CaptureSet n k -> SType n m k -> CType n m k

FinFun

def FinFun (n n' : Nat) : Type :=
  Fin n -> Fin n'

EType.rename

def EType.rename : EType n m k -> FinFun n n' -> EType n' m k
| EType.ex T, f => EType.ex (T.rename f)
| EType.type T, f => EType.type (T.rename f)

EType

inductive EType : Nat -> Nat -> Nat -> Type where
| ex : CType n m (k+1) -> EType n m k
| type : CType n m k -> EType n m k

CaptureSet.rename

@[simp]
def CaptureSet.rename (C : CaptureSet n k) (f : FinFun n n') : CaptureSet n' k :=
  match C with
  | empty => empty
  | union C1 C2 => (C1.rename f) ∪ (C2.rename f)
  | singleton x => {x=f x}
  | csingleton c => {c=c}

CaptureSet

inductive CaptureSet : Nat -> Nat -> Type where
| empty : CaptureSet n k
| union : CaptureSet n k -> CaptureSet n k -> CaptureSet n k
| singleton : Fin n -> CaptureSet n k
| csingleton : Fin k -> CaptureSet n k

notation:max "{x=" x "}" => CaptureSet.singleton x

notation:max "{c=" c "}" => CaptureSet.csingleton c

SType.top

notation "⊤" => SType.top

notation:50 "∀(x:" T ")" U => SType.forall T U

notation:50 "∀[X<:" S "]" T => SType.tforall S T

notation:50 "∀[c<:" B "]" T => SType.cforall B T

notation:max S " ^ " C => CType.capt C S

notation:40 "∃c." T => EType.ex T

notation:40 "Label[" S "]" => SType.label S

notation:60 "□" T => SType.box T

theorem CaptureSet.rename_rename {C : CaptureSet n k} :
  (C.rename f).rename g = C.rename (g ∘ f)

theorem FinFun.ext_comp_ext {f : FinFun n n'} {g : FinFun n' n''} :
  g.ext ∘ f.ext = FinFun.ext (g ∘ f)

theorem CBound.rename_rename {b : CBound n k} :
  (b.rename f).rename g = b.rename (g ∘ f)

theorem EType.rename_rename (E : EType n m k) (f : FinFun n n') (g : FinFun n' n'') :
  (E.rename f).rename g = E.rename (g ∘ f)

theorem CType.rename_rename (T : CType n m k) (f : FinFun n n') (g : FinFun n' n'') :
  (T.rename f).rename g = T.rename (g ∘ f)

import Capless.Type.Core

import Capless.Type.Renaming

namespace Capless

end


theorem SType.trename_rename_comm (S : SType n m k) (f : FinFun n n') (g : FinFun m m') :
  (S.trename g).rename f = (S.rename f).trename g :=
  match S with
  | SType.top => by simp [SType.trename, SType.rename]
  | SType.tvar X => by simp [SType.trename, SType.rename]
  | SType.forall E1 E2 => by
    have ih1 := CType.trename_rename_comm E1 f g
    have ih2 := EType.trename_rename_comm E2 f.ext g
    simp [SType.trename, SType.rename, ih1, ih2]
  | SType.tforall S E => by
    have ih1 := SType.trename_rename_comm S f g
    have ih2 := EType.trename_rename_comm E f g.ext
    simp [SType.trename, SType.rename, ih1, ih2]
  | SType.cforall B E => by
    have ih := EType.trename_rename_comm E f g
    simp [SType.trename, SType.rename, ih]
  | SType.box T => by
    have ih := CType.trename_rename_comm T f g
    simp [SType.trename, SType.rename, ih]
  | SType.label S => by
    have ih := SType.trename_rename_comm S f g
    simp [SType.trename, SType.rename, ih]

import Capless.Type.Renaming
import Capless.Type.Core

SType.trename

def SType.trename : SType n m k -> FinFun m m' -> SType n m' k
| SType.top, _ => SType.top
| SType.tvar X, f => SType.tvar (f X)
| SType.forall E1 E2, f => SType.forall (E1.trename f) (E2.trename f)
| SType.tforall S E, f => SType.tforall (S.trename f) (E.trename f.ext)
| SType.cforall B E, f => SType.cforall B (E.trename f)
| SType.box T, f => SType.box (T.trename f)
| SType.label S, f => SType.label (S.trename f)

CType.trename

def CType.trename : CType n m k -> FinFun m m' -> CType n m' k
| CType.capt C S, f => CType.capt C (S.trename f)

CType

inductive CType : Nat -> Nat -> Nat -> Type where
| capt : CaptureSet n k -> SType n m k -> CType n m k

FinFun

def FinFun (n n' : Nat) : Type :=
  Fin n -> Fin n'

EType.trename

def EType.trename : EType n m k -> FinFun m m' -> EType n m' k
| EType.ex T, f => EType.ex (T.trename f)
| EType.type T, f => EType.type (T.trename f)

EType

inductive EType : Nat -> Nat -> Nat -> Type where
| ex : CType n m (k+1) -> EType n m k
| type : CType n m k -> EType n m k

SType

inductive SType : Nat -> Nat -> Nat -> Type where
| top : SType n m k
| tvar : Fin m -> SType n m k
| forall : CType n m k -> EType (n+1) m k -> SType n m k
| tforall : SType n m k -> EType n (m+1) k -> SType n m k
| cforall : CBound n k -> EType n m (k+1) -> SType n m k
| box : CType n m k -> SType n m k
| label : SType n m k -> SType n m k

FinFun.ext

def FinFun.ext (f : FinFun n n') : FinFun (n+1) (n'+1) :=

CBound.rename

def CBound.rename (b : CBound n k) (f : FinFun n n') : CBound n' k :=
  match b with
  | upper C => upper (C.rename f)
  | star => star

SType.rename

def SType.rename : SType n m k -> FinFun n n' -> SType n' m k
| SType.top, _ => SType.top
| SType.tvar X, _ => SType.tvar X
| SType.forall E1 E2, f => SType.forall (E1.rename f) (E2.rename f.ext)
| SType.tforall S E, f => SType.tforall (S.rename f) (E.rename f)
| SType.cforall B E, f => SType.cforall (B.rename f) (E.rename f)
| SType.box T, f => SType.box (T.rename f)
| SType.label S, f => SType.label (S.rename f)

CType.rename

def CType.rename : CType n m k -> FinFun n n' -> CType n' m k
| CType.capt C S, f => CType.capt (C.rename f) (S.rename f)

EType.rename

def EType.rename : EType n m k -> FinFun n n' -> EType n' m k
| EType.ex T, f => EType.ex (T.rename f)
| EType.type T, f => EType.type (T.rename f)

CaptureSet.rename

@[simp]
def CaptureSet.rename (C : CaptureSet n k) (f : FinFun n n') : CaptureSet n' k :=
  match C with
  | empty => empty
  | union C1 C2 => (C1.rename f) ∪ (C2.rename f)
  | singleton x => {x=f x}
  | csingleton c => {c=c}

CaptureSet

inductive CaptureSet : Nat -> Nat -> Type where
| empty : CaptureSet n k
| union : CaptureSet n k -> CaptureSet n k -> CaptureSet n k
| singleton : Fin n -> CaptureSet n k
| csingleton : Fin k -> CaptureSet n k

notation:max "{x=" x "}" => CaptureSet.singleton x

notation:max "{c=" c "}" => CaptureSet.csingleton c

SType.top

notation "⊤" => SType.top

notation:50 "∀(x:" T ")" U => SType.forall T U

notation:50 "∀[X<:" S "]" T => SType.tforall S T

notation:50 "∀[c<:" B "]" T => SType.cforall B T

notation:max S " ^ " C => CType.capt C S

notation:40 "∃c." T => EType.ex T

notation:40 "Label[" S "]" => SType.label S

notation:60 "□" T => SType.box T

theorem List.getElem_append_left{α : Type u_1} {l₁ l₂ : List α} {i : Nat} (hn : i < l₁.length) :\n(l₁ ++ l₂)[i] = l₁[i]

theorem EType.trename_rename_comm (E : EType n m k) (f : FinFun n n') (g : FinFun m m') :
  (E.trename g).rename f = (E.rename f).trename g

theorem CType.trename_rename_comm (T : CType n m k) (f : FinFun n n') (g : FinFun m m') :
  (T.trename g).rename f = (T.rename f).trename g

import Capless.Type.Core

import Capless.Type.Renaming

namespace Capless

end

end


theorem SType.rename_id {S : SType n m k} :
  S.rename FinFun.id = S :=
  match S with
  | SType.top => by simp [SType.rename]
  | SType.tvar X => by simp [SType.rename]
  | SType.forall E1 E2 => by
    have ih1 := CType.rename_id (T := E1)
    have ih2 := EType.rename_id (E := E2)
    simp [SType.rename, FinFun.id_ext, ih1, ih2]
  | SType.tforall S E => by
    have ih1 := SType.rename_id (S := S)
    have ih2 := EType.rename_id (E := E)
    simp [SType.rename, ih1, ih2]
  | SType.cforall B E => by
    have ih := EType.rename_id (E := E)
    simp [SType.rename, CBound.rename_id, ih]
  | SType.box T => by
    have ih := CType.rename_id (T := T)
    simp [SType.rename, ih]
  | SType.label S => by
    have ih := SType.rename_id (S := S)
    simp [SType.rename, ih]

CType

inductive CType : Nat -> Nat -> Nat -> Type where
| capt : CaptureSet n k -> SType n m k -> CType n m k

FinFun

def FinFun (n n' : Nat) : Type :=
  Fin n -> Fin n'

CBound.rename

def CBound.rename (b : CBound n k) (f : FinFun n n') : CBound n' k :=
  match b with
  | upper C => upper (C.rename f)
  | star => star

EType

inductive EType : Nat -> Nat -> Nat -> Type where
| ex : CType n m (k+1) -> EType n m k
| type : CType n m k -> EType n m k

SType

inductive SType : Nat -> Nat -> Nat -> Type where
| top : SType n m k
| tvar : Fin m -> SType n m k
| forall : CType n m k -> EType (n+1) m k -> SType n m k
| tforall : SType n m k -> EType n (m+1) k -> SType n m k
| cforall : CBound n k -> EType n m (k+1) -> SType n m k
| box : CType n m k -> SType n m k
| label : SType n m k -> SType n m k

FinFun.ext

def FinFun.ext (f : FinFun n n') : FinFun (n+1) (n'+1) :=

FinFun.id

def FinFun.id : FinFun n n :=
  fun i => i

notation:max "{x=" x "}" => CaptureSet.singleton x

notation:max "{c=" c "}" => CaptureSet.csingleton c

SType.top

notation "⊤" => SType.top

notation:50 "∀(x:" T ")" U => SType.forall T U

notation:50 "∀[X<:" S "]" T => SType.tforall S T

notation:50 "∀[c<:" B "]" T => SType.cforall B T

notation:max S " ^ " C => CType.capt C S

notation:40 "∃c." T => EType.ex T

notation:40 "Label[" S "]" => SType.label S

notation:60 "□" T => SType.box T

theorem CaptureSet.rename_id {C : CaptureSet n k} :
  C.rename FinFun.id = C

theorem FinFun.id_ext :
  (FinFun.ext (n := n) id) = id

theorem CBound.rename_id {b : CBound n k} :
  b.rename FinFun.id = b

theorem EType.rename_id {E : EType n m k} :
  E.rename FinFun.id = E

theorem CType.rename_id {T : CType n m k} :
  T.rename FinFun.id = T

import Capless.Type.Core

import Capless.Type.Renaming

namespace Capless

end

end

end

end

end

end


CBound.crename

def CBound.crename (b : CBound n k) (f : FinFun k k') : CBound n k' :=
  match b with
  | upper C => upper (C.crename f)
  | star => star

EType.crename

def EType.crename : EType n m k -> FinFun k k' -> EType n m k'
| EType.ex T, f => EType.ex (T.crename f.ext)
| EType.type T, f => EType.type (T.crename f)

EType

inductive EType : Nat -> Nat -> Nat -> Type where
| ex : CType n m (k+1) -> EType n m k
| type : CType n m k -> EType n m k

FinFun.ext

def FinFun.ext (f : FinFun n n') : FinFun (n+1) (n'+1) :=

FinFun

def FinFun (n n' : Nat) : Type :=
  Fin n -> Fin n'

CType.crename

def CType.crename : CType n m k -> FinFun k k' -> CType n m k'
| CType.capt C S, f => CType.capt (C.crename f) (S.crename f)

CType

inductive CType : Nat -> Nat -> Nat -> Type where
| capt : CaptureSet n k -> SType n m k -> CType n m k

SType.crename

def SType.crename : SType n m k -> FinFun k k' -> SType n m k'
| SType.top, _ => SType.top
| SType.tvar X, _ => SType.tvar X
| SType.forall E1 E2, f => SType.forall (E1.crename f) (E2.crename f)
| SType.tforall S E, f => SType.tforall (S.crename f) (E.crename f)
| SType.cforall B E, f => SType.cforall (B.crename f) (E.crename f.ext)
| SType.box T, f => SType.box (T.crename f)
| SType.label S, f => SType.label (S.crename f)

SType

inductive SType : Nat -> Nat -> Nat -> Type where
| top : SType n m k
| tvar : Fin m -> SType n m k
| forall : CType n m k -> EType (n+1) m k -> SType n m k
| tforall : SType n m k -> EType n (m+1) k -> SType n m k
| cforall : CBound n k -> EType n m (k+1) -> SType n m k
| box : CType n m k -> SType n m k
| label : SType n m k -> SType n m k

CaptureSet.crename

@[simp]
def CaptureSet.crename (C : CaptureSet n k) (f : FinFun k k') : CaptureSet n k' :=
  match C with
  | empty => empty
  | union C1 C2 => (C1.crename f) ∪ (C2.crename f)
  | singleton x => {x=x}
  | csingleton c => {c=f c}

CaptureSet

inductive CaptureSet : Nat -> Nat -> Type where
| empty : CaptureSet n k
| union : CaptureSet n k -> CaptureSet n k -> CaptureSet n k
| singleton : Fin n -> CaptureSet n k
| csingleton : Fin k -> CaptureSet n k

FinFun.weaken

def FinFun.weaken : FinFun n (n+1) :=
  Fin.succ

CBound

inductive CBound : Nat -> Nat -> Type where
| upper : CaptureSet n k -> CBound n k
| star : CBound n k

CaptureSet.Subset

inductive CaptureSet.Subset : CaptureSet n k → CaptureSet n k → Prop where
| empty : Subset {} C
| rfl : Subset C C
| union_l :
  Subset C1 C ->
  Subset C2 C ->
  Subset (C1 ∪ C2) C
| union_rl :
  Subset C C1 ->
  Subset C (C1 ∪ C2)
| union_rr :
  Subset C C2 ->
  Subset C (C1 ∪ C2)

CType.cweaken

def CType.cweaken (C : CType n m k) : CType n m (k+1) :=
  C.crename FinFun.weaken

EType.cweaken

def EType.cweaken (E : EType n m k) : EType n m (k+1) :=
  E.crename FinFun.weaken

CaptureSet.cweaken

def CaptureSet.cweaken (C : CaptureSet n k) : CaptureSet n (k+1) :=
  C.crename FinFun.weaken

CBound.cweaken

def CBound.cweaken (b : CBound n k) : CBound n (k+1) :=
  b.crename FinFun.weaken

SType.cweaken

def SType.cweaken (S : SType n m k) : SType n m (k+1) :=
  S.crename FinFun.weaken

notation:max "{x=" x "}" => CaptureSet.singleton x

notation:max "{c=" c "}" => CaptureSet.csingleton c

SType.top

notation "⊤" => SType.top

notation:50 "∀(x:" T ")" U => SType.forall T U

notation:50 "∀[X<:" S "]" T => SType.tforall S T

notation:50 "∀[c<:" B "]" T => SType.cforall B T

notation:max S " ^ " C => CType.capt C S

notation:40 "∃c." T => EType.ex T

notation:40 "Label[" S "]" => SType.label S

notation:60 "□" T => SType.box T

theorem List.getElem_append_left{α : Type u_1} {l₁ l₂ : List α} {i : Nat} (hn : i < l₁.length) :\n(l₁ ++ l₂)[i] = l₁[i]

Capless.Context.LBound

theorem CBinding.eq_inst_cweaken_inv {b : CBinding n k}
  (h : CBinding.inst C = b.cweaken) :
  ∃ C0, b = CBinding.inst C0

import Capless.Type

import Capless.CaptureSet

namespace Capless

inductive TBinding : Nat -> Nat -> Nat -> Type where
| bound : SType n m k -> TBinding n m k
| inst : SType n m k -> TBinding n m k

inductive CBinding : Nat -> Nat -> Type where
| bound : CBound n k -> CBinding n k
| inst : CaptureSet n k -> CBinding n k

inductive Context : Nat -> Nat -> Nat -> Type where
| empty : Context 0 0 0
| var : Context n m k -> CType n m k -> Context (n+1) m k
| label : Context n m k -> SType n m k -> Context (n+1) m k
| tvar : Context n m k -> TBinding n m k -> Context n (m+1) k
| cvar : Context n m k -> CBinding n k -> Context n m (k+1)

notation:30 Γ ",x:" T => Context.var Γ T

notation:30 Γ ",X<:" T => Context.tvar Γ (TBinding.bound T)

notation:30 Γ ",X:=" T => Context.tvar Γ (TBinding.inst T)

notation:30 Γ ",c<:" B => Context.cvar Γ (CBinding.bound B)

notation:30 Γ ",c<:*" => Context.cvar Γ (CBinding.bound CBound.star)

notation:30 Γ ",c:=" C => Context.cvar Γ (CBinding.inst C)

def TBinding.crename (b : TBinding n m k) (f : FinFun k k') : TBinding n m k' :=
  match b with
  | bound S => bound (S.crename f)
  | inst S => inst (S.crename f)

def CBinding.crename (b : CBinding n k) (f : FinFun k k') : CBinding n k' :=
  match b with
  | bound b0 => bound (b0.crename f)
  | inst C => inst (C.crename f)

def TBinding.cweaken (b : TBinding n m k) : TBinding n m (k+1) :=
  b.crename FinFun.weaken

def CBinding.cweaken (b : CBinding n k) : CBinding n (k+1) :=
  b.crename FinFun.weaken

inductive Context.CBound : Context n m k -> Fin k -> CBinding n k -> Prop where
| here : CBound (cvar Γ0 b) 0 b.cweaken
| there_var :
  CBound Γ x b ->
  CBound (var Γ E) x b.weaken
| there_tvar :
  CBound Γ x b ->
  CBound (tvar Γ b') x b
| there_cvar :
  CBound Γ x b ->
  CBound (cvar Γ b') (Fin.succ x) b.cweaken
| there_label :
  CBound Γ x b ->
  CBound (label Γ S) x b.weaken

inductive Context.LBound : Context n m k -> Fin n -> SType n m k -> Prop where
| here : LBound (label Γ0 S) 0 S.weaken
| there_var :
  LBound Γ x S ->
  LBound (var Γ E) x.succ S.weaken
| there_tvar :
  LBound Γ x S ->
  LBound (tvar Γ b) x S.tweaken
| there_cvar :
  LBound Γ x S ->
  LBound (cvar Γ b) x S.cweaken
| there_label :
  LBound Γ x S ->
  LBound (label Γ S') x.succ S.weaken

theorem Context.cvar_bound_cvar_inst_inv' {Γ : Context n m k}
  (he1 : Γ' = Context.cvar Γ (CBinding.bound b0))
  (he2 : b' = CBinding.inst C)
  (hb : Context.CBound Γ' c b') :
  ∃ c0 C0, c = c0.succ ∧ C = C0.cweaken ∧ Context.CBound Γ c0 (CBinding.inst C0) :=

:= by
  cases hb <;> try (solve | cases he1)
  case here =>
    have h := CBinding.eq_inst_cweaken_inv (Eq.symm he2)
    have ⟨C0, h⟩ := h
    subst h; cases he1
  case there_cvar =>
    have ⟨C0, h⟩ := CBinding.eq_inst_cweaken_inv (Eq.symm he2)
    subst h; simp [CBinding.cweaken, CBinding.crename] at he2
    rename_i x0 _ _ _
    exists x0, C0; simp [CaptureSet.cweaken]; aesop


theorem SType.crename_crename (S : SType n m k) (f : FinFun k k') (g : FinFun k' k'') :
  (S.crename f).crename g = S.crename (g ∘ f) :=
  match S with
  | SType.top => by simp [SType.crename]
  | SType.tvar X => by simp [SType.crename]
  | SType.forall E1 E2 => by
    have ih1 := CType.crename_crename E1 f g
    have ih2 := EType.crename_crename E2 f g
    simp [SType.crename, ih1, ih2]
  | SType.tforall S E => by
    have ih1 := SType.crename_crename S f g
    have ih2 := EType.crename_crename E f g
    simp [SType.crename, ih1, ih2]
  | SType.cforall B E => by
    have ih := EType.crename_crename E f.ext g.ext
    simp [SType.crename, ih, FinFun.ext_comp_ext, CBound.crename_crename]
  | SType.box T => by
    have ih := CType.crename_crename T f g
    simp [SType.crename, ih]
  | SType.label S => by
    have ih := SType.crename_crename S f g
    simp [SType.crename, ih]

notation:max "{x=" x "}" => CaptureSet.singleton x

notation:max "{c=" c "}" => CaptureSet.csingleton c

SType

inductive SType : Nat -> Nat -> Nat -> Type where
| top : SType n m k
| tvar : Fin m -> SType n m k
| forall : CType n m k -> EType (n+1) m k -> SType n m k
| tforall : SType n m k -> EType n (m+1) k -> SType n m k
| cforall : CBound n k -> EType n m (k+1) -> SType n m k
| box : CType n m k -> SType n m k
| label : SType n m k -> SType n m k

FinFun.ext

def FinFun.ext (f : FinFun n n') : FinFun (n+1) (n'+1) :=

CType.crename

def CType.crename : CType n m k -> FinFun k k' -> CType n m k'
| CType.capt C S, f => CType.capt (C.crename f) (S.crename f)

CType

inductive CType : Nat -> Nat -> Nat -> Type where
| capt : CaptureSet n k -> SType n m k -> CType n m k

FinFun

def FinFun (n n' : Nat) : Type :=
  Fin n -> Fin n'

EType.crename

def EType.crename : EType n m k -> FinFun k k' -> EType n m k'
| EType.ex T, f => EType.ex (T.crename f.ext)
| EType.type T, f => EType.type (T.crename f)

EType

inductive EType : Nat -> Nat -> Nat -> Type where
| ex : CType n m (k+1) -> EType n m k
| type : CType n m k -> EType n m k

CBound.crename

def CBound.crename (b : CBound n k) (f : FinFun k k') : CBound n k' :=
  match b with
  | upper C => upper (C.crename f)
  | star => star

SType.crename

def SType.crename : SType n m k -> FinFun k k' -> SType n m k'
| SType.top, _ => SType.top
| SType.tvar X, _ => SType.tvar X
| SType.forall E1 E2, f => SType.forall (E1.crename f) (E2.crename f)
| SType.tforall S E, f => SType.tforall (S.crename f) (E.crename f)
| SType.cforall B E, f => SType.cforall (B.crename f) (E.crename f.ext)
| SType.box T, f => SType.box (T.crename f)
| SType.label S, f => SType.label (S.crename f)

CaptureSet.crename

@[simp]
def CaptureSet.crename (C : CaptureSet n k) (f : FinFun k k') : CaptureSet n k' :=
  match C with
  | empty => empty
  | union C1 C2 => (C1.crename f) ∪ (C2.crename f)
  | singleton x => {x=x}
  | csingleton c => {c=f c}

CaptureSet

inductive CaptureSet : Nat -> Nat -> Type where
| empty : CaptureSet n k
| union : CaptureSet n k -> CaptureSet n k -> CaptureSet n k
| singleton : Fin n -> CaptureSet n k
| csingleton : Fin k -> CaptureSet n k

SType.top

notation "⊤" => SType.top

notation:50 "∀(x:" T ")" U => SType.forall T U

notation:50 "∀[X<:" S "]" T => SType.tforall S T

notation:50 "∀[c<:" B "]" T => SType.cforall B T

notation:max S " ^ " C => CType.capt C S

notation:40 "∃c." T => EType.ex T

notation:40 "Label[" S "]" => SType.label S

notation:60 "□" T => SType.box T

theorem CaptureSet.crename_crename {C : CaptureSet n k} :
  (C.crename f).crename g = C.crename (g ∘ f)

theorem FinFun.ext_comp_ext {f : FinFun n n'} {g : FinFun n' n''} :
  g.ext ∘ f.ext = FinFun.ext (g ∘ f)

theorem CBound.crename_crename {b : CBound n k} :
  (b.crename f).crename g = b.crename (g ∘ f)

theorem EType.crename_crename (E : EType n m k) (f : FinFun k k') (g : FinFun k' k'') :
  (E.crename f).crename g = E.crename (g ∘ f)

theorem CType.crename_crename (T : CType n m k) (f : FinFun k k') (g : FinFun k' k'') :
  (T.crename f).crename g = T.crename (g ∘ f)

import Capless.Type.Core

import Capless.Type.Renaming

namespace Capless

end

end

end


theorem SType.crename_trename_comm (S : SType n m k) (f : FinFun k k') (g : FinFun m m') :
  (S.crename f).trename g = (S.trename g).crename f :=
  match S with
  | SType.top => by simp [SType.crename, SType.trename]
  | SType.tvar X => by simp [SType.crename, SType.trename]
  | SType.forall E1 E2 => by
    have ih1 := CType.crename_trename_comm E1 f g
    have ih2 := EType.crename_trename_comm E2 f g
    simp [SType.crename, SType.trename, ih1, ih2]
  | SType.tforall S E => by
    have ih1 := SType.crename_trename_comm S f g
    have ih2 := EType.crename_trename_comm E f g.ext
    simp [SType.crename, SType.trename, ih1, ih2]
  | SType.cforall B E => by
    have ih := EType.crename_trename_comm E f.ext g
    simp [SType.crename, SType.trename, ih]
  | SType.box T => by
    have ih := CType.crename_trename_comm T f g
    simp [SType.crename, SType.trename, ih]
  | SType.label S => by
    have ih := SType.crename_trename_comm S f g
    simp [SType.crename, SType.trename, ih]

notation:max "{x=" x "}" => CaptureSet.singleton x

notation:max "{c=" c "}" => CaptureSet.csingleton c

FinFun

def FinFun (n n' : Nat) : Type :=
  Fin n -> Fin n'

SType.trename

def SType.trename : SType n m k -> FinFun m m' -> SType n m' k
| SType.top, _ => SType.top
| SType.tvar X, f => SType.tvar (f X)
| SType.forall E1 E2, f => SType.forall (E1.trename f) (E2.trename f)
| SType.tforall S E, f => SType.tforall (S.trename f) (E.trename f.ext)
| SType.cforall B E, f => SType.cforall B (E.trename f)
| SType.box T, f => SType.box (T.trename f)
| SType.label S, f => SType.label (S.trename f)

CType.trename

def CType.trename : CType n m k -> FinFun m m' -> CType n m' k
| CType.capt C S, f => CType.capt C (S.trename f)

CType

inductive CType : Nat -> Nat -> Nat -> Type where
| capt : CaptureSet n k -> SType n m k -> CType n m k

EType.trename

def EType.trename : EType n m k -> FinFun m m' -> EType n m' k
| EType.ex T, f => EType.ex (T.trename f)
| EType.type T, f => EType.type (T.trename f)

EType

inductive EType : Nat -> Nat -> Nat -> Type where
| ex : CType n m (k+1) -> EType n m k
| type : CType n m k -> EType n m k

SType

inductive SType : Nat -> Nat -> Nat -> Type where
| top : SType n m k
| tvar : Fin m -> SType n m k
| forall : CType n m k -> EType (n+1) m k -> SType n m k
| tforall : SType n m k -> EType n (m+1) k -> SType n m k
| cforall : CBound n k -> EType n m (k+1) -> SType n m k
| box : CType n m k -> SType n m k
| label : SType n m k -> SType n m k

FinFun.ext

def FinFun.ext (f : FinFun n n') : FinFun (n+1) (n'+1) :=

CType.crename

def CType.crename : CType n m k -> FinFun k k' -> CType n m k'
| CType.capt C S, f => CType.capt (C.crename f) (S.crename f)

EType.crename

def EType.crename : EType n m k -> FinFun k k' -> EType n m k'
| EType.ex T, f => EType.ex (T.crename f.ext)
| EType.type T, f => EType.type (T.crename f)

CBound.crename

def CBound.crename (b : CBound n k) (f : FinFun k k') : CBound n k' :=
  match b with
  | upper C => upper (C.crename f)
  | star => star

SType.crename

def SType.crename : SType n m k -> FinFun k k' -> SType n m k'
| SType.top, _ => SType.top
| SType.tvar X, _ => SType.tvar X
| SType.forall E1 E2, f => SType.forall (E1.crename f) (E2.crename f)
| SType.tforall S E, f => SType.tforall (S.crename f) (E.crename f)
| SType.cforall B E, f => SType.cforall (B.crename f) (E.crename f.ext)
| SType.box T, f => SType.box (T.crename f)
| SType.label S, f => SType.label (S.crename f)

SType.top

notation "⊤" => SType.top

notation:50 "∀(x:" T ")" U => SType.forall T U

notation:50 "∀[X<:" S "]" T => SType.tforall S T

notation:50 "∀[c<:" B "]" T => SType.cforall B T

notation:max S " ^ " C => CType.capt C S

notation:40 "∃c." T => EType.ex T

notation:40 "Label[" S "]" => SType.label S

notation:60 "□" T => SType.box T

theorem List.getElem_append_left{α : Type u_1} {l₁ l₂ : List α} {i : Nat} (hn : i < l₁.length) :\n(l₁ ++ l₂)[i] = l₁[i]

theorem EType.crename_trename_comm (E : EType n m k) (f : FinFun k k') (g : FinFun m m') :
  (E.crename f).trename g = (E.trename g).crename f

theorem CType.crename_trename_comm (T : CType n m k) (f : FinFun k k') (g : FinFun m m') :
  (T.crename f).trename g = (T.trename g).crename f

import Capless.Type.Core

import Capless.Type.Renaming

namespace Capless

end

end

end

end


theorem SType.crename_id {S : SType n m k} :
  S.crename FinFun.id = S :=
  match S with
  | SType.top => by simp [SType.crename]
  | SType.tvar X => by simp [SType.crename]
  | SType.forall E1 E2 => by
    have ih1 := CType.crename_id (T := E1)
    have ih2 := EType.crename_id (E := E2)
    simp [SType.crename, ih1, ih2]
  | SType.tforall S E => by
    have ih1 := SType.crename_id (S := S)
    have ih2 := EType.crename_id (E := E)
    simp [SType.crename, ih1, ih2]
  | SType.cforall B E => by
    have ih := EType.crename_id (E := E)
    simp [SType.crename, CBound.crename_id, FinFun.id_ext, ih]
  | SType.box T => by
    have ih := CType.crename_id (T := T)
    simp [SType.crename, ih]
  | SType.label S => by
    have ih := SType.crename_id (S := S)
    simp [SType.crename, ih]

notation:max "{x=" x "}" => CaptureSet.singleton x

notation:max "{c=" c "}" => CaptureSet.csingleton c

EType

inductive EType : Nat -> Nat -> Nat -> Type where
| ex : CType n m (k+1) -> EType n m k
| type : CType n m k -> EType n m k

FinFun

def FinFun (n n' : Nat) : Type :=
  Fin n -> Fin n'

CType

inductive CType : Nat -> Nat -> Nat -> Type where
| capt : CaptureSet n k -> SType n m k -> CType n m k

SType

inductive SType : Nat -> Nat -> Nat -> Type where
| top : SType n m k
| tvar : Fin m -> SType n m k
| forall : CType n m k -> EType (n+1) m k -> SType n m k
| tforall : SType n m k -> EType n (m+1) k -> SType n m k
| cforall : CBound n k -> EType n m (k+1) -> SType n m k
| box : CType n m k -> SType n m k
| label : SType n m k -> SType n m k

CaptureSet.crename

@[simp]
def CaptureSet.crename (C : CaptureSet n k) (f : FinFun k k') : CaptureSet n k' :=
  match C with
  | empty => empty
  | union C1 C2 => (C1.crename f) ∪ (C2.crename f)
  | singleton x => {x=x}
  | csingleton c => {c=f c}

CaptureSet

inductive CaptureSet : Nat -> Nat -> Type where
| empty : CaptureSet n k
| union : CaptureSet n k -> CaptureSet n k -> CaptureSet n k
| singleton : Fin n -> CaptureSet n k
| csingleton : Fin k -> CaptureSet n k

FinFun.id

def FinFun.id : FinFun n n :=
  fun i => i

SType.top

notation "⊤" => SType.top

notation:50 "∀(x:" T ")" U => SType.forall T U

notation:50 "∀[X<:" S "]" T => SType.tforall S T

notation:50 "∀[c<:" B "]" T => SType.cforall B T

notation:max S " ^ " C => CType.capt C S

notation:40 "∃c." T => EType.ex T

notation:40 "Label[" S "]" => SType.label S

notation:60 "□" T => SType.box T

theorem CaptureSet.crename_id {C : CaptureSet n k} :
  C.crename FinFun.id = C

theorem FinFun.id_ext :
  (FinFun.ext (n := n) id) = id

theorem CBound.crename_id {b : CBound n k} :
  b.crename FinFun.id = b

theorem EType.crename_id {E : EType n m k} :
  E.crename FinFun.id = E

theorem CType.crename_id {T : CType n m k} :
  T.crename FinFun.id = T

import Capless.Type.Core

import Capless.Type.Renaming

namespace Capless

end

end

end

end

end

end

end

end


theorem SType.trename_trename (S : SType n m k) (f : FinFun m m') (g : FinFun m' m'') :
  (S.trename f).trename g = S.trename (g ∘ f) :=
  match S with
  | SType.top => by simp [SType.trename]
  | SType.tvar X => by simp [SType.trename]
  | SType.forall E1 E2 => by
    have ih1 := CType.trename_trename E1 f g
    have ih2 := EType.trename_trename E2 f g
    simp [SType.trename, ih1, ih2]
  | SType.tforall S E => by
    have ih1 := SType.trename_trename S f g
    have ih2 := EType.trename_trename E f.ext g.ext
    simp [SType.trename, ih1, ih2, FinFun.ext_comp_ext]
  | SType.cforall B E => by
    have ih := EType.trename_trename E f g
    simp [SType.trename, ih]
  | SType.box T => by
    have ih := CType.trename_trename T f g
    simp [SType.trename, ih]
  | SType.label S => by
    have ih := SType.trename_trename S f g
    simp [SType.trename, ih]

import Capless.Basic
import Capless.Type.Renaming
import Capless.Type.Core

SType.trename

def SType.trename : SType n m k -> FinFun m m' -> SType n m' k
| SType.top, _ => SType.top
| SType.tvar X, f => SType.tvar (f X)
| SType.forall E1 E2, f => SType.forall (E1.trename f) (E2.trename f)
| SType.tforall S E, f => SType.tforall (S.trename f) (E.trename f.ext)
| SType.cforall B E, f => SType.cforall B (E.trename f)
| SType.box T, f => SType.box (T.trename f)
| SType.label S, f => SType.label (S.trename f)

CType.trename

def CType.trename : CType n m k -> FinFun m m' -> CType n m' k
| CType.capt C S, f => CType.capt C (S.trename f)

CType

inductive CType : Nat -> Nat -> Nat -> Type where
| capt : CaptureSet n k -> SType n m k -> CType n m k

FinFun

def FinFun (n n' : Nat) : Type :=
  Fin n -> Fin n'

EType.trename

def EType.trename : EType n m k -> FinFun m m' -> EType n m' k
| EType.ex T, f => EType.ex (T.trename f)
| EType.type T, f => EType.type (T.trename f)

EType

inductive EType : Nat -> Nat -> Nat -> Type where
| ex : CType n m (k+1) -> EType n m k
| type : CType n m k -> EType n m k

FinFun.ext

def FinFun.ext (f : FinFun n n') : FinFun (n+1) (n'+1) :=

SType.top

notation "⊤" => SType.top

notation:50 "∀(x:" T ")" U => SType.forall T U

notation:50 "∀[X<:" S "]" T => SType.tforall S T

notation:50 "∀[c<:" B "]" T => SType.cforall B T

notation:max S " ^ " C => CType.capt C S

notation:40 "∃c." T => EType.ex T

notation:40 "Label[" S "]" => SType.label S

notation:60 "□" T => SType.box T

theorem FinFun.ext_comp_ext {f : FinFun n n'} {g : FinFun n' n''} :
  g.ext ∘ f.ext = FinFun.ext (g ∘ f)

theorem EType.trename_trename (E : EType n m k) (f : FinFun m m') (g : FinFun m' m'') :
  (E.trename f).trename g = E.trename (g ∘ f)

theorem CType.trename_trename (T : CType n m k) (f : FinFun m m') (g : FinFun m' m'') :
  (T.trename f).trename g = T.trename (g ∘ f)

import Capless.Type.Core

import Capless.Type.Renaming

namespace Capless

end

end

end

end

end


import Capless.Subcapturing.Basic
import Capless.Tactics
import Capless.Typing
import Capless.Subtyping.Basic
import Capless.Weakening.Typing
import Capless.Weakening.Subtyping
import Capless.Inversion.Subtyping
import Capless.Narrowing
import Capless.Weakening.Subcapturing
import Capless.Inversion.Context

notation:max "{x=" x "}" => CaptureSet.singleton x

notation:max "{c=" c "}" => CaptureSet.csingleton c

notation:30 Γ ",x:" T => Context.var Γ T

notation:50 Γ " ⊢ " E1 " <:e " E2 => ESubtyp Γ E1 E2

notation:50 Γ " ⊢ " E1 " <:e " E2 => ESubtyp Γ E1 E2

notation:50 Γ " ⊢ " T1 " <:s " T2 => SSubtyp Γ T1 T2

notation:50 Γ " ⊢ " T1 " <:s " T2 => SSubtyp Γ T1 T2

notation:50 Γ " ⊢ " T1 " <: " T2 => CSubtyp Γ T1 T2

notation:50 Γ " ⊢ " T1 " <: " T2 => CSubtyp Γ T1 T2

notation:40 Γ " ⊢ " t:80 " : " E " @ " C => Typed Γ t E C

notation:40 Γ " ⊢ " t:80 " : " E " @ " C => Typed Γ t E C

notation:50 Γ " ⊢ " C1 " <:c " C2 => Subcapt Γ C1 C2

notation:50 "λ[X<:" S "]" t => Term.tlam S t

notation:50 "λ[X<:" S "]" t => Term.tlam S t

notation:40 "let" "x=" t " in " u => Term.letin t u

notation:40 "let" "x=" t " in " u => Term.letin t u

notation:40 "let" "(c,x)=" t " in " u => Term.letex t u

notation:40 "let" "(c,x)=" t " in " u => Term.letex t u

notation:40 "let" "X=" S " in " t => Term.bindt S t

notation:40 "let" "X=" S " in " t => Term.bindt S t

notation:40 "let" "c=" C " in " t => Term.bindc C t

notation:40 "let" "c=" C " in " t => Term.bindc C t

notation:50 "λ(x:" T ")" t => Term.lam T t

notation:50 "λ(x:" T ")" t => Term.lam T t

notation:50 "λ[c<:" B "]" t => Term.clam B t

notation:50 "λ[c<:" B "]" t => Term.clam B t

notation:40 "Label[" S "]" => SType.label S

notation:60 "□" T => SType.box T

macro "apply?" e:term : tactic => `(tactic| apply $e <;> try

macro "apply?" e:term : tactic => `(tactic| apply $e <;> try easy)

macro "easy" : tactic => `(tactic| assumption)

macro "easy" : tactic => `(tactic| assumption)

notation:max "⟨" σ " | " cont " | " t "⟩" => State.mk σ cont

notation:max "⟨" σ " | " cont " | " t "⟩" => State.mk σ cont t

Subcapt.weaken

def Subcapt.weaken
  (h : Γ ⊢ C1 <:c C2) :
  (Γ,x: T) ⊢ C1.weaken <:c C2.weaken :=

CBinding.rename

def CBinding.rename (b : CBinding n k) (f : FinFun n n') : CBinding n' k :=
  match b with
  | bound b0 => bound (b0.rename f)
  | inst C => inst (C.rename f)

TBinding.rename

def TBinding.rename (b : TBinding n m k) (f : FinFun n n') : TBinding n' m k :=
  match b with
  | bound S => bound (S.rename f)
  | inst S => inst (S.rename f)

SType.rename

def SType.rename : SType n m k -> FinFun n n' -> SType n' m k
| SType.top, _ => SType.top
| SType.tvar X, _ => SType.tvar X
| SType.forall E1 E2, f => SType.forall (E1.rename f) (E2.rename f.ext)
| SType.tforall S E, f => SType.tforall (S.rename f) (E.rename f)
| SType.cforall B E, f => SType.cforall (B.rename f) (E.rename f)
| SType.box T, f => SType.box (T.rename f)
| SType.label S, f => SType.label (S.rename f)

CType.rename

def CType.rename : CType n m k -> FinFun n n' -> CType n' m k
| CType.capt C S, f => CType.capt (C.rename f) (S.rename f)

CType

inductive CType : Nat -> Nat -> Nat -> Type where
| capt : CaptureSet n k -> SType n m k -> CType n m k

FinFun

def FinFun (n n' : Nat) : Type :=
  Fin n -> Fin n'

CBound.rename

def CBound.rename (b : CBound n k) (f : FinFun n n') : CBound n' k :=
  match b with
  | upper C => upper (C.rename f)
  | star => star

EType.rename

def EType.rename : EType n m k -> FinFun n n' -> EType n' m k
| EType.ex T, f => EType.ex (T.rename f)
| EType.type T, f => EType.type (T.rename f)

EType

inductive EType : Nat -> Nat -> Nat -> Type where
| ex : CType n m (k+1) -> EType n m k
| type : CType n m k -> EType n m k

CaptureSet.rename

@[simp]
def CaptureSet.rename (C : CaptureSet n k) (f : FinFun n n') : CaptureSet n' k :=
  match C with
  | empty => empty
  | union C1 C2 => (C1.rename f) ∪ (C2.rename f)
  | singleton x => {x=f x}
  | csingleton c => {c=c}

CaptureSet

inductive CaptureSet : Nat -> Nat -> Type where
| empty : CaptureSet n k
| union : CaptureSet n k -> CaptureSet n k -> CaptureSet n k
| singleton : Fin n -> CaptureSet n k
| csingleton : Fin k -> CaptureSet n k

SType

inductive SType : Nat -> Nat -> Nat -> Type where
| top : SType n m k
| tvar : Fin m -> SType n m k
| forall : CType n m k -> EType (n+1) m k -> SType n m k
| tforall : SType n m k -> EType n (m+1) k -> SType n m k
| cforall : CBound n k -> EType n m (k+1) -> SType n m k
| box : CType n m k -> SType n m k
| label : SType n m k -> SType n m k

FinFun.ext

def FinFun.ext (f : FinFun n n') : FinFun (n+1) (n'+1) :=

VarMap.weaken

def VarMap.weaken {Γ : Context n m k} :
  VarMap Γ FinFun.weaken (Γ.var T) :=

Typed

inductive Typed : Context n m k -> Term n m k -> EType n m k -> CaptureSet n k -> Prop where
| var :
  Context.Bound Γ x (S^C) ->
  Typed Γ (Term.var x) (S^{x=x}) {x=x}
| label :
  Context.LBound Γ x S ->
  Typed Γ (Term.var x) (Label[S]^{x=x}) {x=x}
| pack :
  Typed (Γ.cvar (CBinding.inst C)) (Term.var x) (EType.type T) {x=x} ->
  Typed Γ (Term.pack C x) (∃c.T) {}
| sub :
  Typed Γ t E1 C1 ->
  (Γ ⊢ C1 <:c C2) ->
  (Γ ⊢ E1 <:e E2) ->
  Typed Γ t E2 C2
| abs {C : CaptureSet n k} :
  Typed (Γ,x:T) t E (C.weaken ∪ {x=0}) ->
  Typed Γ (λ(x:T)t) ((∀(x:T)E)^C) {}
| tabs {C : CaptureSet n k} :
  Typed (Γ,X<:S) t E C ->
  Typed Γ (λ[X<:S]t) ((∀[X<:S]E)^C) {}
| cabs {C : CaptureSet n k} :
  Typed (Γ,c<:B) t E C.cweaken ->
  Typed Γ (λ[c<:B]t) ((∀[c<:B]E)^C) {}
| app :
  Typed Γ (Term.var x) (EType.type (∀(x:T)E)^C) {x=x} ->
  Typed Γ (Term.var y) T {x=y} ->
  Typed Γ (Term.app x y) (E.open y) ({x=x} ∪ {x=y})
| invoke :
  Typed Γ (Term.var x) (EType.type (Label[S])^C) {x=x} ->
  Typed Γ (Term.var y) (S^{}) {x=y} ->
  Typed Γ (Term.invoke x y) E ({x=x} ∪ {x=y})
| tapp :
  Typed Γ (Term.var x) (EType.type (∀[X<:SType.tvar X]E)^C) {x=x} ->
  Typed Γ (Term.tapp x X) (E.topen X) {x=x}
| capp :
  Typed Γ (Term.var x) (EType.type (∀[c<:CBound.upper {c=c}]E)^C) {x=x} ->
  Typed Γ (Term.capp x c) (E.copen c) {x=x}
| letin :
  Typed Γ t (EType.type T) C ->
  Typed (Γ,x: T) u E.weaken C.weaken ->
  Typed Γ (let x=t in u) E C
| letex :
  Typed Γ t (EType.ex T) C ->
  Typed ((Γ,c<:*),x: T) u E.cweaken.weaken C.cweaken.weaken ->
  Typed Γ (let (c,x)=t in u) E C
| bindt :
  Typed (Γ,X:=S) t E.tweaken C ->
  Typed Γ (let X=S in t) E C
| bindc :
  Typed (Γ,c:=C) t E.cweaken C0.cweaken ->
  Typed Γ (let c=C in t) E C0
| boundary {Γ : Context n m k} {S : SType n m k} :
  Typed
    ((Γ,c<:CBound.star),x: Label[S.cweaken]^{c=0})
    t
    (S.cweaken.weaken^{}) (C.cweaken.weaken ∪ {c=0} ∪ {x=0}) ->
  Typed Γ (boundary: S in t) (S^CaptureSet.empty) C

Context

inductive Context : Nat -> Nat -> Nat -> Type where
| empty : Context 0 0 0
| var : Context n m k -> CType n m k -> Context (n+1) m k
| label : Context n m k -> SType n m k -> Context (n+1) m k
| tvar : Context n m k -> TBinding n m k -> Context n (m+1) k
| cvar : Context n m k -> CBinding n k -> Context n m (k+1)

Term

inductive Term : Nat -> Nat -> Nat -> Type where

| var : Fin n -> Term n m k

| lam : CType n m k -> Term (n+1) m k -> Term n m k

| tlam : SType n m k -> Term n (m+1) k -> Term n m k

| clam : CBound n k -> Term n m (k+1) -> Term n m k

| pack : CaptureSet n k -> Fin n -> Term n m k

| app : Fin n -> Fin n -> Term n m k

| invoke : Fin n -> Fin n -> Term n m k

| tapp : Fin n -> Fin m -> Term n m k

| capp : Fin n -> Fin k -> Term n m k

| letin : Term n m k -> Term (n+1) m k -> Term n m k

| letex : Term n m k -> Term (n+1) m (k+1) -> Term n m k

| bindt : SType n m k -> Term n (m+1) k -> Term n m k

| bindc : CaptureSet n k -> Term n m (k+1) -> Term n m k

| boundary : SType n m k -> Term (n+1) m (k+1) -> Term n m k

Subcapt

inductive Subcapt : Context n m k -> CaptureSet n k -> CaptureSet n k -> Prop where
| trans :
  Subcapt Γ C1 C2 ->
  Subcapt Γ C2 C3 ->
  Subcapt Γ C1 C3
| subset :
  C1 ⊆ C2 ->
  Subcapt Γ C1 C2
| union :
  Subcapt Γ C1 C3 ->
  Subcapt Γ C2 C3 ->
  Subcapt Γ (C1 ∪ C2) C3
| var :
  Context.Bound Γ x (CType.capt C S) ->
  Subcapt Γ {x=x} C
| cinstl :
  Context.CBound Γ c (CBinding.inst C) ->
  Subcapt Γ C {c=c}
| cinstr :
  Context.CBound Γ c (CBinding.inst C) ->
  Subcapt Γ {c=c} C
| cbound :
  Context.CBound Γ c (CBinding.bound (CBound.upper C)) ->
  Subcapt Γ {c=c} C

CBinding

inductive CBinding : Nat -> Nat -> Type where
| bound : CBound n k -> CBinding n k
| inst : CaptureSet n k -> CBinding n k

CBound

inductive CBound : Nat -> Nat -> Type where
| upper : CaptureSet n k -> CBound n k
| star : CBound n k

CaptureSet.Subset

inductive CaptureSet.Subset : CaptureSet n k → CaptureSet n k → Prop where
| empty : Subset {} C
| rfl : Subset C C
| union_l :
  Subset C1 C ->
  Subset C2 C ->
  Subset (C1 ∪ C2) C
| union_rl :
  Subset C C1 ->
  Subset C (C1 ∪ C2)
| union_rr :
  Subset C C2 ->
  Subset C (C1 ∪ C2)

TBinding

inductive TBinding : Nat -> Nat -> Nat -> Type where
| bound : SType n m k -> TBinding n m k
| inst : SType n m k -> TBinding n m k

FinFun.weaken

def FinFun.weaken : FinFun n (n+1) :=
  Fin.succ

Term.rename

def Term.rename (t : Term n m k) (f : FinFun n n') : Term n' m k :=
  match t with
  | Term.var x => Term.var (f x)
  | Term.lam E t => Term.lam (E.rename f) (t.rename f.ext)
  | Term.tlam S t => Term.tlam (S.rename f) (t.rename f)
  | Term.clam B t => Term.clam (B.rename f) (t.rename f)
  | Term.pack C x => Term.pack (C.rename f) (f x)
  | Term.app x y => Term.app (f x) (f y)
  | Term.invoke x y => Term.invoke (f x) (f y)
  | Term.tapp x X => Term.tapp (f x) X
  | Term.capp x c => Term.capp (f x) c
  | Term.letin t u => Term.letin (t.rename f) (u.rename f.ext)
  | Term.letex t u => Term.letex (t.rename f) (u.rename f.ext)
  | Term.bindt S t => Term.bindt (S.rename f) (t.rename f)
  | Term.bindc c t => Term.bindc (c.rename f) (t.rename f)
  | Term.boundary S t => Term.boundary (S.rename f) (t.rename f.ext)

CBinding.cweaken

def CBinding.cweaken (b : CBinding n k) : CBinding n (k+1) :=
  b.crename FinFun.weaken

CBinding.crename

def CBinding.crename (b : CBinding n k) (f : FinFun k k') : CBinding n k' :=
  match b with
  | bound b0 => bound (b0.crename f)
  | inst C => inst (C.crename f)

TBinding.crename

def TBinding.crename (b : TBinding n m k) (f : FinFun k k') : TBinding n m k' :=
  match b with
  | bound S => bound (S.crename f)
  | inst S => inst (S.crename f)

CBound.crename

def CBound.crename (b : CBound n k) (f : FinFun k k') : CBound n k' :=
  match b with
  | upper C => upper (C.crename f)
  | star => star

EType.crename

def EType.crename : EType n m k -> FinFun k k' -> EType n m k'
| EType.ex T, f => EType.ex (T.crename f.ext)
| EType.type T, f => EType.type (T.crename f)

CType.crename

def CType.crename : CType n m k -> FinFun k k' -> CType n m k'
| CType.capt C S, f => CType.capt (C.crename f) (S.crename f)

SType.crename

def SType.crename : SType n m k -> FinFun k k' -> SType n m k'
| SType.top, _ => SType.top
| SType.tvar X, _ => SType.tvar X
| SType.forall E1 E2, f => SType.forall (E1.crename f) (E2.crename f)
| SType.tforall S E, f => SType.tforall (S.crename f) (E.crename f)
| SType.cforall B E, f => SType.cforall (B.crename f) (E.crename f.ext)
| SType.box T, f => SType.box (T.crename f)
| SType.label S, f => SType.label (S.crename f)

CaptureSet.crename

@[simp]
def CaptureSet.crename (C : CaptureSet n k) (f : FinFun k k') : CaptureSet n k' :=
  match C with
  | empty => empty
  | union C1 C2 => (C1.crename f) ∪ (C2.crename f)
  | singleton x => {x=x}
  | csingleton c => {c=f c}

Term.weaken

def Term.weaken (t : Term n m k) : Term (n+1) m k := t.rename FinFun.weaken

Typed.cweaken

def Typed.cweaken
  (h : Typed Γ t E Ct) :
  Typed (Γ.cvar b) t.cweaken E.cweaken Ct.cweaken :=

Term.cweaken

def Term.cweaken (t : Term n m k) : Term n m (k+1) := t.crename FinFun.weaken

Term.crename

def Term.crename (t : Term n m k) (f : FinFun k k') : Term n m k' :=
  match t with
  | Term.var x => Term.var x
  | Term.lam E t => Term.lam (E.crename f) (t.crename f)
  | Term.tlam S t => Term.tlam (S.crename f) (t.crename f)
  | Term.clam B t => Term.clam (B.crename f) (t.crename f.ext)
  | Term.pack C x => Term.pack (C.crename f) x
  | Term.app x y => Term.app x y
  | Term.invoke x y => Term.invoke x y
  | Term.tapp x X => Term.tapp x X
  | Term.capp x c => Term.capp x (f c)
  | Term.letin t u => Term.letin (t.crename f) (u.crename f)
  | Term.letex t u => Term.letex (t.crename f) (u.crename f.ext)
  | Term.bindt S t => Term.bindt (S.crename f) (t.crename f)
  | Term.bindc c t => Term.bindc (c.crename f) (t.crename f.ext)
  | Term.boundary S t => Term.boundary (S.crename f) (t.crename f.ext)

CVarMap.weaken

def CVarMap.weaken {Γ : Context n m k} :
  CVarMap Γ FinFun.weaken (Γ.cvar b) :=

EType.cweaken

def EType.cweaken (E : EType n m k) : EType n m (k+1) :=
  E.crename FinFun.weaken

CType.cweaken

def CType.cweaken (C : CType n m k) : CType n m (k+1) :=
  C.crename FinFun.weaken

TBinding.cweaken

def TBinding.cweaken (b : TBinding n m k) : TBinding n m (k+1) :=
  b.crename FinFun.weaken

CaptureSet.cweaken

def CaptureSet.cweaken (C : CaptureSet n k) : CaptureSet n (k+1) :=
  C.crename FinFun.weaken

CBound.weaken

def CBound.weaken (b : CBound n k) : CBound (n+1) k :=
  b.rename FinFun.weaken

EType.weaken

def EType.weaken (E : EType n m k) : EType (n+1) m k :=
  E.rename FinFun.weaken

CBound.cweaken

def CBound.cweaken (b : CBound n k) : CBound n (k+1) :=
  b.crename FinFun.weaken

Context.IsTight

inductive Context.IsTight : Context n m k -> Prop where
| empty : Context.IsTight Context.empty
| var :
  Context.IsTight Γ ->
  Context.IsTight (Γ.var T)
| tvar :
  Context.IsTight Γ ->
  Context.IsTight (Γ.tvar (TBinding.inst S))
| cvar :
  Context.IsTight Γ ->
  Context.IsTight (Γ.cvar (CBinding.inst C))
| label :
  Context.IsTight Γ ->
  Context.IsTight (Γ.label S)

CaptureSet.weaken

def CaptureSet.weaken (C : CaptureSet n k) : CaptureSet (n+1) k :=
  C.rename FinFun.weaken

CType.weaken

def CType.weaken (C : CType n m k) : CType (n+1) m k :=
  C.rename FinFun.weaken

Cont.weaken

def Cont.weaken : Cont n m k -> Cont (n+1) m k
| Cont.none => Cont.none
| Cont.cons t cont => Cont.cons t.weaken1 cont.weaken
| Cont.conse t cont => Cont.conse t.weaken1 cont.weaken
| Cont.scope x cont => Cont.scope x.succ cont.weaken

Cont

inductive Cont : Nat -> Nat -> Nat -> Type where
| none : Cont n m k
| cons :
  (t : Term (n+1) m k) ->
  (cont : Cont n m k) ->
  Cont n m k
| conse :
  (t : Term (n+1) m (k+1)) ->
  (cont : Cont n m k) ->
  Cont n m k
| scope :
  (l : Fin n) ->
  Cont n m k ->
  Cont n m k

TypedCont

inductive TypedCont : Context n m k -> EType n m k -> Cont n m k -> EType n m k -> CaptureSet n k -> Prop where
| none :
  ESubtyp Γ E E' ->
  TypedCont Γ E Cont.none E' {}
| cons {Ct : CaptureSet n k} :
  Typed (Γ,x: T) t (EType.weaken E) Ct.weaken ->
  WellScoped Γ cont Ct ->
  TypedCont Γ E cont E' C ->
  TypedCont Γ (EType.type T) (Cont.cons t cont) E' (C ∪ Ct)
| conse {Ct : CaptureSet n k} :
  Typed ((Γ.cvar (CBinding.bound CBound.star)).var T) t (EType.weaken (EType.cweaken E)) Ct.cweaken.weaken ->
  WellScoped Γ cont Ct ->
  TypedCont Γ E cont E' C ->
  TypedCont Γ (EType.ex T) (Cont.conse t cont) E' (C ∪ Ct)
| scope :
  Context.LBound Γ x S ->
  TypedCont Γ (S^{}) cont E' C ->
  (Γ ⊢ T0 <: S^{}) ->
  TypedCont Γ (EType.type T0) (Cont.scope x cont) E' C

State

structure State (n : Nat) (m : Nat) (k : Nat) where
  σ : Store n m k
  cont : Cont n m k
  t : Term n m k

Term.IsValue

@[aesop safe constructors]
inductive Term.IsValue : Term n m k -> Prop where
| lam : Term.IsValue (lam E t)
| tlam : Term.IsValue (tlam S t)
| clam : Term.IsValue (clam B t)
| pack : Term.IsValue (pack c x)

def Term.weaken1 (t : Term (n+1) m k) : Term (n+2) m k :=
  t.rename FinFun.weaken.ext

TBinding.weaken

def TBinding.weaken (b : TBinding n m k) : TBinding (n+1) m k :=
  b.rename FinFun.weaken

CBinding.weaken

def CBinding.weaken (b : CBinding n k) : CBinding (n+1) k :=
  b.rename FinFun.weaken

def CaptureSet.weaken1 (C : CaptureSet (n+1) k) : CaptureSet (n+2) k :=
  C.rename FinFun.weaken.ext

SType.weaken

def SType.weaken (S : SType n m k) : SType (n+1) m k :=
  S.rename FinFun.weaken

def EType.weaken1 (E : EType (n+1) m k) : EType (n+2) m k :=
  E.rename FinFun.weaken.ext

Cont.cweaken

def Cont.cweaken : Cont n m k -> Cont n m (k+1)
| Cont.none => Cont.none
| Cont.cons t cont => Cont.cons t.cweaken cont.cweaken
| Cont.conse t cont => Cont.conse t.cweaken1 cont.cweaken
| Cont.scope x cont => Cont.scope x cont.cweaken

def Term.cweaken1 (t : Term n m (k+1)) : Term n m (k+2) :=
  t.crename FinFun.weaken.ext

def CType.cweaken1 (T : CType n m (k+1)) : CType n m (k+2) :=
  T.crename FinFun.weaken.ext

def SType.cweaken1 (S : SType n m (k+1)) : SType n m (k+2) :=
  S.crename FinFun.weaken.ext

def CaptureSet.cweaken1 (C : CaptureSet n (k+1)) : CaptureSet n (k+2) :=
  C.crename FinFun.weaken.ext

def EType.cweaken1 (E : EType n m (k+1)) : EType n m (k+2) :=
  E.crename FinFun.weaken.ext

SType.cweaken

def SType.cweaken (S : SType n m k) : SType n m (k+1) :=
  S.crename FinFun.weaken

TVarMap.weaken

def TVarMap.weaken {Γ : Context n m k} :
  TVarMap Γ FinFun.weaken (Γ.tvar b) :=

SType.IsVar

inductive SType.IsVar : SType n m k -> Prop where
| tvar : SType.IsVar (SType.tvar X)

SSubtyp

inductive SSubtyp : Context n m k -> SType n m k -> SType n m k -> Prop where
| top :
  SSubtyp Γ S SType.top
| refl :
  SSubtyp Γ S S
| trans :
  SSubtyp Γ S1 S2 ->
  SSubtyp Γ S2 S3 ->
  SSubtyp Γ S1 S3
| tvar :
  Context.TBound Γ X (TBinding.bound S) ->
  SSubtyp Γ (SType.tvar X) S
| tinstl :
  Context.TBound Γ X (TBinding.inst S) ->
  SSubtyp Γ S (SType.tvar X)
| tinstr :
  Context.TBound Γ X (TBinding.inst S) ->
  SSubtyp Γ (SType.tvar X) S
| boxed :
  CSubtyp Γ T1 T2 ->
  SSubtyp Γ (□ T1) (□ T2)
| label :
  SSubtyp Γ S2 S1 ->
  SSubtyp Γ (Label[S1]) (Label[S2])
| xforall :
  CSubtyp Γ E2 E1 ->
  ESubtyp (Context.var Γ E2) F1 F2 ->
  SSubtyp Γ (SType.forall E1 F1) (SType.forall E2 F2)
| tforall :
  SSubtyp Γ S2 S1 ->
  ESubtyp (Context.tvar Γ (TBinding.bound S2)) E1 E2 ->
  SSubtyp Γ (SType.tforall S1 E1) (SType.tforall S2 E2)
| cforall :
  Subbound Γ B2 B1 ->
  ESubtyp (Context.cvar Γ (CBinding.bound B2)) E1 E2 ->
  SSubtyp Γ (SType.cforall B1 E1) (SType.cforall B2 E2)

ESubtyp

inductive ESubtyp : Context n m k -> EType n m k -> EType n m k -> Prop where
| exist :
  CSubtyp (Context.cvar Γ (CBinding.bound CBound.star)) T1 T2 ->
  ESubtyp Γ (EType.ex T1) (EType.ex T2)
| type :
  CSubtyp Γ T1 T2 ->
  ESubtyp Γ (EType.type T1) (EType.type T2)

CSubtyp

inductive CSubtyp : Context n m k -> CType n m k -> CType n m k -> Prop where
| capt :
  (Γ ⊢ C1 <:c C2) ->
  SSubtyp Γ S1 S2 ->
  CSubtyp Γ (CType.capt C1 S1) (CType.capt C2 S2)

Subbound

inductive Subbound : Context n m k -> CBound n k -> CBound n k -> Prop where
| set :
  (Γ ⊢ C1 <:c C2) ->
  Subbound Γ (CBound.upper C1) (CBound.upper C2)
| star :
  Subbound Γ B CBound.star

Context.TBound

inductive Context.TBound : Context n m k -> Fin m -> TBinding n m k -> Prop where
| here : TBound (tvar Γ0 b) 0 b.tweaken
| there_var :
  TBound Γ x b ->
  TBound (var Γ E) x b.weaken
| there_tvar :
  TBound Γ x b ->
  TBound (tvar Γ b') (Fin.succ x) b.tweaken
| there_cvar :
  TBound Γ x b ->
  TBound (cvar Γ b') x b.cweaken
| there_label :
  TBound Γ x b ->
  TBound (label Γ S) x b.weaken

Context.LBound

inductive Context.LBound : Context n m k -> Fin n -> SType n m k -> Prop where
| here : LBound (label Γ0 S) 0 S.weaken
| there_var :
  LBound Γ x S ->
  LBound (var Γ E) x.succ S.weaken
| there_tvar :
  LBound Γ x S ->
  LBound (tvar Γ b) x S.tweaken
| there_cvar :
  LBound Γ x S ->
  LBound (cvar Γ b) x S.cweaken
| there_label :
  LBound Γ x S ->
  LBound (label Γ S') x.succ S.weaken

Subcapt.cweaken

def Subcapt.cweaken
  (h : Γ ⊢ C1 <:c C2) :
  (Γ.cvar b) ⊢ C1.cweaken <:c C2.cweaken :=

notation:50 "λ(x:" T ")" t => Term.lam T t

notation:50 "λ[X<:" S "]" t => Term.tlam S t

notation:50 "λ[c<:" B "]" t => Term.clam B t

notation:40 "let" "x=" t " in " u => Term.letin t u

notation:40 "let" "(c,x)=" t " in " u => Term.letex t u

notation:40 "let" "X=" S " in " t => Term.bindt S t

notation:40 "let" "c=" C " in " t => Term.bindc C t

notation:40 "boundary:" S " in " t => Term.boundary S t

notation:40 "boundary:" S " in " t => Term.boundary S t

notation:max "{x=" x "}" => CaptureSet.singleton x

notation:max "{x=" x "}" => CaptureSet.singleton x

notation:max "{c=" c "}" => CaptureSet.csingleton c

notation:max "{c=" c "}" => CaptureSet.csingleton c

notation:50 Γ " ⊢ " E1 " <:e " E2 => ESubtyp Γ E1 E2

notation:50 Γ " ⊢ " E1 " <:e " E2 => ESubtyp Γ E1 E2

notation:50 Γ " ⊢ " T1 " <:s " T2 => SSubtyp Γ T1 T2

notation:50 Γ " ⊢ " T1 " <:s " T2 => SSubtyp Γ T1 T2

notation:50 Γ " ⊢ " T1 " <: " T2 => CSubtyp Γ T1 T2

notation:50 Γ " ⊢ " T1 " <: " T2 => CSubtyp Γ T1 T2

notation:30 Γ ",x:" T => Context.var Γ T

notation:30 Γ ",x:" T => Context.var Γ T

notation:30 Γ ",X<:" T => Context.tvar Γ (TBinding.bound T)

notation:30 Γ ",X<:" T => Context.tvar Γ (TBinding.bound T)

notation:30 Γ ",X:=" T => Context.tvar Γ (TBinding.inst T)

notation:30 Γ ",X:=" T => Context.tvar Γ (TBinding.inst T)

notation:30 Γ ",c<:" B => Context.cvar Γ (CBinding.bound B)

notation:30 Γ ",c<:" B => Context.cvar Γ (CBinding.bound B)

notation:30 Γ ",c<:*" => Context.cvar Γ (CBinding.bound CBou

notation:30 Γ ",c<:*" => Context.cvar Γ (CBinding.bound CBound.star)

notation:30 Γ ",c:=" C => Context.cvar Γ (CBinding.inst C)

notation:30 Γ ",c:=" C => Context.cvar Γ (CBinding.inst C)

notation:40 Γ " ⊢ " t:80 " : " E " @ " C => Typed Γ t E C

notation:40 Γ " ⊢ " t:80 " : " E " @ " C => Typed Γ t E C

SType.top

notation "⊤" => SType.top

notation:50 "∀(x:" T ")" U => SType.forall T U

notation:50 "∀(x:" T ")" U => SType.forall T U

notation:50 "∀[X<:" S "]" T => SType.tforall S T

notation:50 "∀[X<:" S "]" T => SType.tforall S T

notation:50 "∀[c<:" B "]" T => SType.cforall B T

notation:50 "∀[c<:" B "]" T => SType.cforall B T

notation:max S " ^ " C => CType.capt C S

notation:max S " ^ " C => CType.capt C S

notation:40 "∃c." T => EType.ex T

notation:40 "Label[" S "]" => SType.label S

notation:40 "Label[" S "]" => SType.label S

notation:60 "□" T => SType.box T

notation:50 Γ " ⊢ " C1 " <:c " C2 => Subcapt Γ C1 C2

notation:50 Γ " ⊢ " C1 " <:c " C2 => Subcapt Γ C1 C2

ESubtyp.cweaken

theorem ESubtyp.cweaken
  (h : ESubtyp Γ E1 E2) :
  ESubtyp (Γ.cvar b) E1.cweaken E2.cweaken

CSubtyp.weaken

theorem CSubtyp.weaken
  (h : CSubtyp Γ E1 E2) :
  CSubtyp (Γ.var T) E1.weaken E2.weaken

SSubtyp.cweaken

theorem SSubtyp.cweaken
  (h : SSubtyp Γ S1 S2) :
  ∀ b, SSubtyp (Γ.cvar b) S1.cweaken S2.cweaken

Subbound.weaken

theorem Subbound.weaken
  (h : Subbound Γ B1 B2) :
  Subbound (Γ.var b) B1.weaken B2.weaken

ESubtyp.weaken

theorem ESubtyp.weaken
  (h : ESubtyp Γ E1 E2) :
  ESubtyp (Γ.var T) E1.weaken E2.weaken

Subbound.cweaken

theorem Subbound.cweaken
  (h : Subbound Γ B1 B2) :
  Subbound (Γ.cvar b) B1.cweaken B2.cweaken

ESubtyp.trans

theorem ESubtyp.trans
  (h1 : ESubtyp Γ E1 E2)
  (h2 : ESubtyp Γ E2 E3) :
  ESubtyp Γ E1 E3

CSubtyp.trans

theorem CSubtyp.trans
  (h1 : CSubtyp Γ T1 T2)
  (h2 : CSubtyp Γ T2 T3) :
  CSubtyp Γ T1 T3

ESubtyp.refl

theorem ESubtyp.refl :
  ESubtyp Γ E E

CSubtyp.refl

theorem CSubtyp.refl :
  CSubtyp Γ T T

Typed.weaken

theorem Typed.weaken
  (h : Typed Γ t E Ct) :
  Typed (Γ.var T) t.weaken E.weaken Ct.weaken

SSubtyp.weaken

theorem SSubtyp.weaken
  (h : SSubtyp Γ S1 S2) :
  ∀ b, SSubtyp (Γ.var b) S1.weaken S2.weaken

CSubtyp.cweaken

theorem CSubtyp.cweaken
  (h : CSubtyp Γ E1 E2) :
  CSubtyp (Γ.cvar b) E1.cweaken E2.cweaken

import Capless.Tactics

import Capless.Typing

import Capless.Subtyping.Basic

import Capless.Subcapturing.Basic

import Capless.Narrowing

import Capless.Weakening.Subcapturing

import Capless.Inversion.Context

import Capless.Inversion.Subtyping

namespace Capless

theorem Typed.letex_inv' {Γ : Context n m k}
  (he : t0 = Term.letex t u)
  (h : Typed Γ t0 E Ct0) :
  ∃ T E0,
    Typed Γ t (EType.ex T) Ct0 ∧
    Typed ((Γ.cvar (CBinding.bound CBound.star)).var T) u E0.cweaken.weaken Ct0.cweaken.weaken ∧
    ESubtyp Γ E0 E :=

:= by
  induction h <;> try (solve | cases he)
  case letex =>
    cases he
    repeat apply Exists.intro
    constructor; trivial
    constructor; trivial
    apply ESubtyp.refl
  case sub hs ih =>
    have ih := ih he
    obtain ⟨T, E0, ht, hu, hs0⟩ := ih
    have hs1 := ESubtyp.trans hs0 hs
    repeat apply Exists.intro
    repeat any_goals apply And.intro
    { apply Typed.sub
      easy
      easy
      apply ESubtyp.refl }
    { apply Typed.sub
      easy
      apply Subcapt.weaken; apply Subcapt.cweaken; easy
      apply ESubtyp.refl }
    { easy }


theorem SType.trename_id {S : SType n m k} :
  S.trename FinFun.id = S :=
  match S with
  | SType.top => by simp [SType.trename]
  | SType.tvar X => by simp [SType.trename, FinFun.id]
  | SType.forall E1 E2 => by
    have ih1 := CType.trename_id (T := E1)
    have ih2 := EType.trename_id (E := E2)
    simp [SType.trename, FinFun.id_ext, ih1, ih2]
  | SType.tforall S E => by
    have ih1 := SType.trename_id (S := S)
    have ih2 := EType.trename_id (E := E)
    simp [SType.trename, FinFun.id_ext, ih1, ih2]
  | SType.cforall B E => by
    have ih := EType.trename_id (E := E)
    simp [SType.trename, ih]
  | SType.box T => by
    have ih := CType.trename_id (T := T)
    simp [SType.trename, ih]
  | SType.label S => by
    have ih := SType.trename_id (S := S)
    simp [SType.trename, ih]

SType

inductive SType : Nat -> Nat -> Nat -> Type where
| top : SType n m k
| tvar : Fin m -> SType n m k
| forall : CType n m k -> EType (n+1) m k -> SType n m k
| tforall : SType n m k -> EType n (m+1) k -> SType n m k
| cforall : CBound n k -> EType n m (k+1) -> SType n m k
| box : CType n m k -> SType n m k
| label : SType n m k -> SType n m k

SType.trename

def SType.trename : SType n m k -> FinFun m m' -> SType n m' k
| SType.top, _ => SType.top
| SType.tvar X, f => SType.tvar (f X)
| SType.forall E1 E2, f => SType.forall (E1.trename f) (E2.trename f)
| SType.tforall S E, f => SType.tforall (S.trename f) (E.trename f.ext)
| SType.cforall B E, f => SType.cforall B (E.trename f)
| SType.box T, f => SType.box (T.trename f)
| SType.label S, f => SType.label (S.trename f)

CType.trename

def CType.trename : CType n m k -> FinFun m m' -> CType n m' k
| CType.capt C S, f => CType.capt C (S.trename f)

CType

inductive CType : Nat -> Nat -> Nat -> Type where
| capt : CaptureSet n k -> SType n m k -> CType n m k

FinFun

def FinFun (n n' : Nat) : Type :=
  Fin n -> Fin n'

EType.trename

def EType.trename : EType n m k -> FinFun m m' -> EType n m' k
| EType.ex T, f => EType.ex (T.trename f)
| EType.type T, f => EType.type (T.trename f)

EType

inductive EType : Nat -> Nat -> Nat -> Type where
| ex : CType n m (k+1) -> EType n m k
| type : CType n m k -> EType n m k

FinFun.ext

def FinFun.ext (f : FinFun n n') : FinFun (n+1) (n'+1) :=

FinFun.id

def FinFun.id : FinFun n n :=
  fun i => i

SType.top

notation "⊤" => SType.top

notation:50 "∀(x:" T ")" U => SType.forall T U

notation:50 "∀[X<:" S "]" T => SType.tforall S T

notation:50 "∀[c<:" B "]" T => SType.cforall B T

notation:max S " ^ " C => CType.capt C S

notation:40 "∃c." T => EType.ex T

notation:40 "Label[" S "]" => SType.label S

notation:60 "□" T => SType.box T

theorem FinFun.id_ext :
  (FinFun.ext (n := n) id) = id

theorem EType.trename_id {E : EType n m k} :
  E.trename FinFun.id = E

theorem CType.trename_id {T : CType n m k} :
  T.trename FinFun.id = T

import Capless.Type.Core

import Capless.Type.Renaming

namespace Capless

end

end

end

end

end

end

end