Theory J1WellType

(*  Title:      JinjaThreads/Compiler/J1WellType.thy
    Author:     Gerwin Klein, Andreas Lochbihler
*)

section ‹Type rules for the intermediate language›

theory J1WellType imports
  J1State
  "../Common/ExternalCallWF"
  "../Common/SemiType"
begin

declare Listn.lesub_list_impl_same_size[simp del] listE_length [simp del]

subsection "Well-Typedness"

type_synonym
  env1  = "ty list"   ― ‹type environment indexed by variable number›

inductive WT1 :: "'addr J1_prog  env1  'addr expr1  ty  bool" ("_,_ ⊢1 _ :: _"   [51,0,0,51] 50)
  and WTs1 :: "'addr J1_prog  env1  'addr expr1 list  ty list  bool" ("_,_ ⊢1 _ [::] _"   [51,0,0,51]50)
  for P :: "'addr J1_prog"
  where

  WT1New:
  "is_class P C  
  P,E ⊢1 new C :: Class C"

| WT1NewArray:
  " P,E ⊢1 e :: Integer; is_type P (T⌊⌉)  
  P,E ⊢1 newA Te :: T⌊⌉"

| WT1Cast:
  " P,E ⊢1 e :: T; P  U  T  P  T  U; is_type P U 
   P,E ⊢1 Cast U e :: U"

| WT1InstanceOf:
  " P,E ⊢1 e :: T; P  U  T  P  T  U; is_type P U; is_refT U 
   P,E ⊢1 e instanceof U :: Boolean"

| WT1Val:
  "typeof v = Some T 
  P,E ⊢1 Val v :: T"

| WT1Var:
  " E!V = T; V < size E  
  P,E ⊢1 Var V :: T"

| WT1BinOp:
  " P,E ⊢1 e1 :: T1; P,E ⊢1 e2 :: T2; P  T1«bop»T2 :: T 
   P,E ⊢1 e1«bop»e2 :: T"

| WT1LAss:
  " E!i = T;  i < size E; P,E ⊢1 e :: T';  P  T'  T 
   P,E ⊢1 i:=e :: Void"

| WT1AAcc:
  " P,E ⊢1 a :: T⌊⌉; P,E ⊢1 i :: Integer 
   P,E ⊢1 ai :: T"

| WT1AAss:
  " P,E ⊢1 a :: T⌊⌉; P,E ⊢1 i :: Integer; P,E ⊢1 e :: T'; P  T'  T 
   P,E ⊢1 ai := e :: Void"

| WT1ALength:
  "P,E ⊢1 a :: T⌊⌉  P,E ⊢1 a∙length :: Integer"

| WTFAcc1:
  " P,E ⊢1 e :: U; class_type_of' U = C; P  C sees F:T (fm) in D 
   P,E ⊢1 eF{D} :: T"

| WTFAss1:
  " P,E ⊢1 e1 :: U; class_type_of' U = C; P  C sees F:T (fm) in D;  P,E ⊢1 e2 :: T';  P  T'  T 
   P,E ⊢1 e1F{D} := e2 :: Void"

| WTCAS1:
  " P,E ⊢1 e1 :: U; class_type_of' U = C; P  C sees F:T (fm) in D; volatile fm; 
     P,E ⊢1 e2 :: T'; P  T'  T; P,E ⊢1 e3 :: T''; P  T''  T 
   P,E ⊢1 e1∙compareAndSwap(DF, e2, e3) :: Boolean"

| WT1Call:
  " P,E ⊢1 e :: U; class_type_of' U = C; P  C sees M:Ts  T = m in D;
     P,E ⊢1 es [::] Ts'; P  Ts' [≤] Ts 
   P,E ⊢1 eM(es) :: T"

| WT1Block:
  " is_type P T;  P,E@[T] ⊢1 e :: T'; case vo of None  True | v  T'. typeof v = T'  P  T'  T 
    P,E ⊢1 {V:T=vo; e} :: T'"

| WT1Synchronized:
  " P,E ⊢1 o' :: T; is_refT T; T  NT; P,E@[Class Object] ⊢1 e :: T' 
   P,E ⊢1 sync⇘V(o') e :: T'"

| WT1Seq:
  " P,E ⊢1 e1::T1;  P,E ⊢1 e2::T2 
    P,E ⊢1 e1;;e2 :: T2"

| WT1Cond:
  " P,E ⊢1 e :: Boolean;  P,E ⊢1 e1::T1;  P,E ⊢1 e2::T2; P  lub(T1,T2) = T 
   P,E ⊢1 if (e) e1 else e2 :: T"

| WT1While:
  " P,E ⊢1 e :: Boolean;  P,E ⊢1 c::T 
   P,E ⊢1 while (e) c :: Void"

| WT1Throw:
  " P,E ⊢1 e :: Class C; P  C * Throwable   
  P,E ⊢1 throw e :: Void"

| WT1Try:
  " P,E ⊢1 e1 :: T;  P,E@[Class C] ⊢1 e2 :: T; is_class P C 
   P,E ⊢1 try e1 catch(C V) e2 :: T"

| WT1Nil: "P,E ⊢1 [] [::] []"

| WT1Cons: " P,E ⊢1 e :: T; P,E ⊢1 es [::] Ts   P,E ⊢1 e#es [::] T#Ts"

declare WT1_WTs1.intros[intro!]
declare WT1Nil[iff]

inductive_cases WT1_WTs1_cases[elim!]:
  "P,E ⊢1 Val v :: T"
  "P,E ⊢1 Var i :: T"
  "P,E ⊢1 Cast D e :: T"
  "P,E ⊢1 e instanceof U :: T"
  "P,E ⊢1 i:=e :: T"
  "P,E ⊢1 {i:U=vo; e} :: T"
  "P,E ⊢1 e1;;e2 :: T"
  "P,E ⊢1 if (e) e1 else e2 :: T"
  "P,E ⊢1 while (e) c :: T"
  "P,E ⊢1 throw e :: T"
  "P,E ⊢1 try e1 catch(C i) e2 :: T"
  "P,E ⊢1 eF{D} :: T"
  "P,E ⊢1 e1F{D}:=e2 :: T"
  "P,E ⊢1 e∙compareAndSwap(DF, e', e'') :: T"
  "P,E ⊢1 e1 «bop» e2 :: T"
  "P,E ⊢1 new C :: T"
  "P,E ⊢1 newA T'e :: T"
  "P,E ⊢1 ai := e :: T"
  "P,E ⊢1 ai :: T"
  "P,E ⊢1 a∙length :: T"
  "P,E ⊢1 eM(es) :: T"
  "P,E ⊢1 sync⇘V(o') e :: T"
  "P,E ⊢1 insync⇘V(a) e :: T"
  "P,E ⊢1 [] [::] Ts"
  "P,E ⊢1 e#es [::] Ts"

lemma WTs1_same_size: "P,E ⊢1 es [::] Ts  size es = size Ts"
by (induct es arbitrary: Ts) auto

lemma WTs1_snoc_cases:
  assumes wt: "P,E ⊢1 es @ [e] [::] Ts"
  obtains T Ts' where "P,E ⊢1 es [::] Ts'" "P,E ⊢1 e :: T"
proof -
  from wt have "T Ts'. P,E ⊢1 es [::] Ts'  P,E ⊢1 e :: T"
    by(induct es arbitrary: Ts) auto
  thus thesis by(auto intro: that)
qed

lemma WTs1_append:
  assumes wt: "P,Env ⊢1 es @ es' [::] Ts"
  obtains Ts' Ts'' where "P,Env ⊢1 es [::] Ts'" "P,Env ⊢1 es' [::] Ts''"
proof -
  from wt have "Ts' Ts''. P,Env ⊢1 es [::] Ts'  P,Env ⊢1 es' [::] Ts''"
    by(induct es arbitrary: Ts) auto
  thus ?thesis by(auto intro: that)
qed

lemma WT1_not_contains_insync: "P,E ⊢1 e :: T  ¬ contains_insync e"
  and WTs1_not_contains_insyncs: "P,E ⊢1 es [::] Ts  ¬ contains_insyncs es"
by(induct rule: WT1_WTs1.inducts) auto

lemma WT1_expr_locks: "P,E ⊢1 e :: T  expr_locks e = (λa. 0)"
  and WTs1_expr_lockss: "P,E ⊢1 es [::] Ts  expr_lockss es = (λa. 0)"
by(induct rule: WT1_WTs1.inducts)(auto)

lemma assumes wf: "wf_prog wfmd P"
  shows WT1_unique: "P,E ⊢1 e :: T1  P,E ⊢1 e :: T2  T1 = T2" 
  and WTs1_unique: "P,E ⊢1 es [::] Ts1  P,E ⊢1 es [::] Ts2  Ts1 = Ts2"
apply(induct arbitrary: T2 and Ts2 rule:WT1_WTs1.inducts)
apply blast
apply blast
apply blast
apply blast
apply clarsimp
apply blast
apply(blast dest: WT_binop_fun)
apply blast
apply blast
apply blast
apply blast
apply (blast dest:sees_field_idemp sees_field_fun)
apply (blast dest: sees_field_fun)
apply blast

apply(erule WT1_WTs1_cases)
apply(simp)
apply (blast dest:sees_method_idemp sees_method_fun)

apply blast
apply blast
apply blast
apply(blast dest: is_lub_unique[OF wf])
apply blast
apply blast
apply blast
apply blast
apply blast
done

lemma assumes wf: "wf_prog p P"
  shows WT1_is_type: "P,E ⊢1 e :: T  set E  types P  is_type P T"
  and WTs1_is_type: "P,E ⊢1 es [::] Ts  set E  types P  set Ts  types P"
apply(induct rule:WT1_WTs1.inducts)
apply simp
apply simp
apply simp
apply simp
apply (simp add:typeof_lit_is_type)
apply (fastforce intro:nth_mem)
apply(simp add: WT_binop_is_type)
apply(simp)
apply(simp del: is_type_array add: is_type_ArrayD)
apply(simp)
apply(simp)
apply (simp add:sees_field_is_type[OF _ wf])
apply simp
apply simp
apply(fastforce dest!: sees_wf_mdecl[OF wf] simp:wf_mdecl_def)
apply(simp)
apply(simp add: is_class_Object[OF wf])
apply simp
apply(blast dest: is_lub_is_type[OF wf])
apply simp
apply simp
apply simp
apply simp
apply(simp)
done

lemma blocks1_WT:
  " P,Env @ Ts ⊢1 body :: T; set Ts  types P   P,Env ⊢1 blocks1 (length Env) Ts body :: T"
proof(induct n"length Env" Ts body arbitrary: Env rule: blocks1.induct)
  case 1 thus ?case by simp
next
  case (2 T' Ts e)
  note IH = Env'. Suc (length Env) = length Env'; P,Env' @ Ts ⊢1 e :: T; set Ts  types P 
               P,Env' ⊢1 blocks1 (length Env') Ts e :: T
  from set (T' # Ts)  types P have "set Ts  types P" "is_type P T'" by(auto)
  moreover from P,Env @ T' # Ts ⊢1 e :: T have "P,(Env @ [T']) @ Ts ⊢1 e :: T" by simp
  note IH[OF _ this]
  ultimately show ?case by auto
qed

lemma WT1_fv: " P,E ⊢1 e :: T;  e (length E); syncvars e   fv e  {0..<length E}"
  and WTs1_fvs: " P,E ⊢1 es [::] Ts; ℬs es (length E); syncvarss es   fvs es  {0..<length E}"
proof(induct rule: WT1_WTs1.inducts)
  case (WT1Synchronized E e1 T e2 T' V)
  note IH1 =  e1 (length E); syncvars e1  fv e1  {0..<length E}
  note IH2 =  e2 (length (E @ [Class Object])); syncvars e2  fv e2  {0..<length (E @ [Class Object])}
  from  (sync⇘V(e1) e2) (length E) have [simp]: "V = length E"
    and B1: " e1 (length E)" and B2: " e2 (Suc (length E))" by auto
  from syncvars (sync⇘V(e1) e2) have sync1: "syncvars e1" and sync2: "syncvars e2" and V: "V  fv e2" by auto
  have "fv e2  {0..<length E}"
  proof
    fix x
    assume x: "x  fv e2"
    with V have "x  length E" by auto
    moreover from IH2 B2 sync2 have "fv e2  {0..<Suc (length E)}" by auto
    with x have "x < Suc (length E)" by auto
    ultimately show "x  {0..<length E}" by auto
  qed
  with IH1[OF B1 sync1] show ?case by(auto)
next
  case (WT1Cond E e e1 T1 e2 T2 T)
  thus ?case by(auto del: subsetI)
qed fastforce+

end