%{ Progress and preservation for a language with n-ary tuples that have both a notion of width and depth subtyping. }% %{ == Syntax == }% %{ === Natural numbers === }% nat : type. z : nat. s : nat -> nat. %{ === Types === }% ty : type. tys : type. tys/nil : tys. tys/cons : ty -> tys -> tys. ty/tup : tys -> ty. ty/nat : ty. ty/int : ty. %{ ==== Type equality ==== }% tyeq : ty -> ty -> type. tyeq/refl : tyeq T T. tyseq : tys -> tys -> type. tyseq/refl : tyseq Ts Ts. tyseq-cong : tyeq T S -> tyseq Ts Ss -> tyseq (tys/cons T Ts) (tys/cons S Ss) -> type. - : tyseq-cong tyeq/refl tyseq/refl tyseq/refl. %mode tyseq-cong +A +B -C. %worlds () (tyseq-cong _ _ _). %total {} (tyseq-cong _ _ _). %{ === Terms === }% tm : type. tms : type. tms/nil : tms. tms/cons : tm -> tms -> tms. tm/tup : tms -> tm. tm/num : nat -> nat -> tm. tm/nadd : tm -> tm -> tm. tm/add : tm -> tm -> tm. tm/proj : tm -> nat -> tm. %{ === Abbreviations === }% %abbrev @ = tys/nil. %abbrev , = tys/cons. %infix right 10 ,. %abbrev # = tms/nil. %abbrev ; = tms/cons. %infix right 10 ;. %{ == Primitive operations == }% plus : nat -> nat -> nat -> type. plus/z : plus z N N. plus/s : plus N M P -> plus (s N) M (s P). projtm : tms -> nat -> tm -> type. projtm/z : projtm (E ; ES) z E. projtm/s : projtm ES N E -> projtm (E ; ES) (s N) E. projty : tys -> nat -> ty -> type. projty/z : projty (T , TS) z T. projty/s : projty TS N T -> projty (T , TS) (s N) T. %{ == Dynamic semantics == }% %{ === Values === }% v : tm -> type. vs : tms -> type. vs/nil : vs tms/nil. vs/cons : v E -> vs ES -> vs (tms/cons E ES). v/num : v (tm/num N+ N-). v/tup : v (tm/tup ES). %{ === Dynamics === }% step : tm -> tm -> type. steps : tms -> tms -> type. steps/s : step E E' -> steps (E ; ES) (E' ; ES). steps/v : v E -> steps ES ES' -> steps (E ; ES) (E ; ES'). step/nadd1 : step E1 E1' -> step (tm/nadd E1 E2) (tm/nadd E1' E2). step/nadd2 : v E1 -> step E2 E2' -> step (tm/nadd E1 E2) (tm/nadd E1 E2'). step/naddR : plus N1 N2 N3 -> step (tm/nadd (tm/num N1 z) (tm/num N2 z)) (tm/num N3 z). step/add1 : step E1 E1' -> step (tm/add E1 E2) (tm/add E1' E2). step/add2 : v E1 -> step E2 E2' -> step (tm/add E1 E2) (tm/add E1 E2'). step/addR : plus N1+ N2- N3+ -> plus N1- N2+ N3- -> step (tm/add (tm/num N1+ N1-) (tm/num N2+ N2-)) (tm/num N3+ N3-). step/tup : steps ES ES' -> step (tm/tup ES) (tm/tup ES'). step/proj1 : step E E' -> step (tm/proj E I) (tm/proj E' I'). step/projR : projtm ES I E -> vs ES -> step (tm/proj (tm/tup ES) I) E. %{ == Static semantics == }% %{ === Subtyping === }% <| : ty -> ty -> type. %infix none 10 <|. <<| : tys -> tys -> type. %infix none 10 <<|. subs/nil : TS <<| @. subs/cons: S <| T -> SS <<| TS -> (S , SS) <<| (T , TS). sub/nat : ty/nat <| ty/nat. sub/int : ty/int <| ty/int. sub/num : ty/nat <| ty/int. sub/tup : TS <<| SS -> (ty/tup TS) <| (ty/tup SS). %{ === Typing === }% of : tm -> ty -> type. ofs : tms -> tys -> type. %block gamma : some {T: ty} block {x: tm}{d: of x T}. ofs/nil : ofs # @. ofs/cons: of E T -> ofs ES TS -> ofs (E ; ES) (T , TS). of/tup : ofs ES TS -> of (tm/tup ES) (ty/tup TS). of/nat : of (tm/num N z) ty/nat. of/int : of (tm/num N+ N-) ty/int. of/nadd : of E1 ty/nat -> of E2 ty/nat -> of (tm/nadd E1 E2) ty/nat. of/add : of E1 ty/int -> of E2 ty/int -> of (tm/add E1 E2) ty/int. of/proj : projty TS N T -> of E (ty/tup TS) -> of (tm/proj E N) T. of/sub : S <| T -> of E S -> of E T. %{ == Properties of subtyping == }% %{ === Reflexivity === }% sub-refl : {T} T <| T -> type. subs-refl : {Ts} Ts <<| Ts -> type. %mode sub-refl +T -TSub. %mode subs-refl +Ts -TsSub. - : sub-refl ty/nat sub/nat. - : sub-refl ty/int sub/int. - : sub-refl (ty/tup Ts) (sub/tup TTs) <- subs-refl Ts TTs. - : subs-refl tys/nil subs/nil. - : subs-refl (tys/cons T TS) (subs/cons D DS) <- sub-refl T D <- subs-refl TS DS. %worlds () (sub-refl _ _) (subs-refl _ _). %total (A B) (sub-refl A _) (subs-refl B _). %{ === Transitivity === }% sub-trans : R <| S -> S <| T -> R <| T -> type. subs-trans : Rs <<| Ss -> Ss <<| Ts -> Rs <<| Ts -> type. %mode sub-trans +RS +ST -RT. %mode subs-trans +RSs +STs -RTs. - : sub-trans sub/nat S S. - : sub-trans S sub/int S. - : sub-trans (sub/tup RSs) (sub/tup STs) (sub/tup RTs) <- subs-trans RSs STs RTs. - : subs-trans _ subs/nil subs/nil. - : subs-trans (subs/cons RS RSs) (subs/cons ST STs) (subs/cons RT RTs) <- sub-trans RS ST RT <- subs-trans RSs STs RTs. %worlds () (subs-trans _ _ _) (sub-trans _ _ _). %total (A B) (subs-trans _ A _) (sub-trans _ B _). %{ == Preservation == }% %{ === Inversion === }% %{ The subtyping inversion theorem says that if (s1,...,sn) <: t, then t = (t1,...,tm) where m <= n. }% inv-sub : ty/tup SS <| T -> tyeq T (ty/tup TS) -> SS <<| TS -> type. - : inv-sub (sub/tup A) tyeq/refl A. %mode inv-sub +A -B -C. %worlds () (inv-sub _ _ _). %total {} (inv-sub _ _ _). %{ The typing inversion lemma says that if G |- (e1,...,en) : t, then for each ei in [1,n], G |- ei : si, t = (t1,...,tm), m %lt;= n, and for each ti in [1,m], si %lt;: ti. }% %{ We need a simple lemma to handle a little equality and call transitivity. }% inv-tup-lem : RS <<| SS -> tyeq S (ty/tup SS) -> S <| T -> tyeq T (ty/tup TS) -> RS <<| TS -> type. - : inv-tup-lem RS tyeq/refl (sub/tup ST) tyeq/refl RT <- subs-trans RS ST RT. %mode inv-tup-lem +A +B +C -D -E. %worlds () (inv-tup-lem _ _ _ _ _). %total {} (inv-tup-lem _ _ _ _ _). inv-tup : of (tm/tup ES) T -> ofs ES RS -> tyeq T (ty/tup TS) -> RS <<| TS -> type. - : inv-tup (of/tup (D: ofs ES SS)) D tyeq/refl DS <- subs-refl SS DS. - : inv-tup (of/sub (SUB : S <| T) (D: of (tm/tup ES) S)) Typs EqT Subs' <- inv-tup D (Typs: ofs ES RS) (EqS: tyeq S (ty/tup SS)) (Subs: RS <<| SS) <- inv-tup-lem Subs EqS SUB EqT Subs'. %mode inv-tup +A -B -C -D. %worlds (gamma) (inv-tup _ _ _ _). %total T (inv-tup T _ _ _).