(* Title: Jinja/J/WellTypeRT.thy ID: $Id: WellTypeRT.html 1910 2004-05-19 04:46:04Z kleing $ Author: Tobias Nipkow Copyright 2003 Technische Universitaet Muenchen *) header {* \isaheader{Runtime Well-typedness} *} theory WellTypeRT = WellType: consts WTrt :: "J_prog => (env × heap × expr × ty )set" WTrts:: "J_prog => (env × heap × expr list × ty list)set" (*<*) syntax (xsymbols) WTrt :: "[J_prog,env,heap,expr,ty] => bool" ("_,_,_ \<turnstile> _ : _" [51,51,51]50) WTrts:: "[J_prog,env,heap,expr list, ty list] => bool" ("_,_,_ \<turnstile> _ [:] _" [51,51,51]50) (*>*) translations "P,E,h \<turnstile> e : T" == "(E,h,e,T) ∈ WTrt P" "P,E,h \<turnstile> es[:]Ts" == "(E,h,es,Ts) ∈ WTrts P" inductive "WTrt P" "WTrts P" intros WTrtNew: "is_class P C ==> P,E,h \<turnstile> new C : Class C" WTrtCast: "[| P,E,h \<turnstile> e : T; is_refT T; is_class P C |] ==> P,E,h \<turnstile> Cast C e : Class C" WTrtVal: "typeofh v = Some T ==> P,E,h \<turnstile> Val v : T" WTrtVar: "E V = Some T ==> P,E,h \<turnstile> Var V : T" WTrtBinOp: "[| P,E,h \<turnstile> e1 : T1; P,E,h \<turnstile> e2 : T2; case bop of Eq => T = Boolean | Add => T1 = Integer ∧ T2 = Integer ∧ T = Integer |] ==> P,E,h \<turnstile> e1 «bop» e2 : T" WTrtLAss: "[| E V = Some T; P,E,h \<turnstile> e : T'; P \<turnstile> T' ≤ T |] ==> P,E,h \<turnstile> V:=e : Void" WTrtFAcc: "[| P,E,h \<turnstile> e : Class C; P \<turnstile> C has F:T in D |] ==> P,E,h \<turnstile> e\<bullet>F{D} : T" WTrtFAccNT: "P,E,h \<turnstile> e : NT ==> P,E,h \<turnstile> e\<bullet>F{D} : T" WTrtFAss: "[| P,E,h \<turnstile> e1 : Class C; P \<turnstile> C has F:T in D; P,E,h \<turnstile> e2 : T2; P \<turnstile> T2 ≤ T |] ==> P,E,h \<turnstile> e1\<bullet>F{D}:=e2 : Void" WTrtFAssNT: "[| P,E,h \<turnstile> e1:NT; P,E,h \<turnstile> e2 : T2 |] ==> P,E,h \<turnstile> e1\<bullet>F{D}:=e2 : Void" WTrtCall: "[| P,E,h \<turnstile> e : Class C; P \<turnstile> C sees M:Ts -> T = (pns,body) in D; P,E,h \<turnstile> es [:] Ts'; P \<turnstile> Ts' [≤] Ts |] ==> P,E,h \<turnstile> e\<bullet>M(es) : T" WTrtCallNT: "[| P,E,h \<turnstile> e : NT; P,E,h \<turnstile> es [:] Ts |] ==> P,E,h \<turnstile> e\<bullet>M(es) : T" WTrtBlock: "P,E(V\<mapsto>T),h \<turnstile> e : T' ==> P,E,h \<turnstile> {V:T; e} : T'" WTrtSeq: "[| P,E,h \<turnstile> e1:T1; P,E,h \<turnstile> e2:T2 |] ==> P,E,h \<turnstile> e1;;e2 : T2" WTrtCond: "[| P,E,h \<turnstile> e : Boolean; P,E,h \<turnstile> e1:T1; P,E,h \<turnstile> e2:T2; P \<turnstile> T1 ≤ T2 ∨ P \<turnstile> T2 ≤ T1; P \<turnstile> T1 ≤ T2 --> T = T2; P \<turnstile> T2 ≤ T1 --> T = T1 |] ==> P,E,h \<turnstile> if (e) e1 else e2 : T" WTrtWhile: "[| P,E,h \<turnstile> e : Boolean; P,E,h \<turnstile> c:T |] ==> P,E,h \<turnstile> while(e) c : Void" WTrtThrow: "[| P,E,h \<turnstile> e : Tr; is_refT Tr |] ==> P,E,h \<turnstile> throw e : T" WTrtTry: "[| P,E,h \<turnstile> e1 : T1; P,E(V \<mapsto> Class C),h \<turnstile> e2 : T2; P \<turnstile> T1 ≤ T2 |] ==> P,E,h \<turnstile> try e1 catch(C V) e2 : T2" -- "well-typed expression lists" WTrtNil: "P,E,h \<turnstile> [] [:] []" WTrtCons: "[| P,E,h \<turnstile> e : T; P,E,h \<turnstile> es [:] Ts |] ==> P,E,h \<turnstile> e#es [:] T#Ts" (*<*) declare WTrt_WTrts.intros[intro!] WTrtNil[iff] declare WTrtFAcc[rule del] WTrtFAccNT[rule del] WTrtFAss[rule del] WTrtFAssNT[rule del] WTrtCall[rule del] WTrtCallNT[rule del] lemmas WTrt_induct = WTrt_WTrts.induct[split_format (complete)] (*>*) subsection{*Easy consequences*} lemma [iff]: "(P,E,h \<turnstile> [] [:] Ts) = (Ts = [])" (*<*) apply(rule iffI) apply (auto elim: WTrt_WTrts.elims) done (*>*) lemma [iff]: "(P,E,h \<turnstile> e#es [:] T#Ts) = (P,E,h \<turnstile> e : T ∧ P,E,h \<turnstile> es [:] Ts)" (*<*) apply(rule iffI) apply (auto elim: WTrt_WTrts.elims) done (*>*) lemma [iff]: "(P,E,h \<turnstile> (e#es) [:] Ts) = (∃U Us. Ts = U#Us ∧ P,E,h \<turnstile> e : U ∧ P,E,h \<turnstile> es [:] Us)" (*<*) apply(rule iffI) apply (auto elim: WTrt_WTrts.elims) done (*>*) lemma [simp]: "∀Ts. (P,E,h \<turnstile> es1 @ es2 [:] Ts) = (∃Ts1 Ts2. Ts = Ts1 @ Ts2 ∧ P,E,h \<turnstile> es1 [:] Ts1 & P,E,h \<turnstile> es2[:]Ts2)" (*<*) apply(induct_tac es1) apply simp apply clarsimp apply(erule thin_rl) apply (rule iffI) apply clarsimp apply(rule exI)+ apply(rule conjI) prefer 2 apply blast apply simp apply fastsimp done (*>*) lemma [iff]: "P,E,h \<turnstile> Val v : T = (typeofh v = Some T)" (*<*) apply(rule iffI) apply (auto elim: WTrt_WTrts.elims) done (*>*) lemma [iff]: "P,E,h \<turnstile> Var v : T = (E v = Some T)" (*<*) apply(rule iffI) apply (auto elim: WTrt_WTrts.elims) done (*>*) lemma [iff]: "P,E,h \<turnstile> e1;;e2 : T2 = (∃T1. P,E,h \<turnstile> e1:T1 ∧ P,E,h \<turnstile> e2:T2)" (*<*) apply(rule iffI) apply (auto elim: WTrt_WTrts.elims) done (*>*) lemma [iff]: "P,E,h \<turnstile> {V:T; e} : T' = (P,E(V\<mapsto>T),h \<turnstile> e : T')" (*<*) apply(rule iffI) apply (auto elim: WTrt_WTrts.elims) done (*>*) (*<*) inductive_cases WTrt_elim_cases[elim!]: "P,E,h \<turnstile> v :=e : T" "P,E,h \<turnstile> if (e) e1 else e2 : T" "P,E,h \<turnstile> while(e) c : T" "P,E,h \<turnstile> throw e : T" "P,E,h \<turnstile> try e1 catch(C V) e2 : T" "P,E,h \<turnstile> Cast D e : T" "P,E,h \<turnstile> e\<bullet>F{D} : T" "P,E,h \<turnstile> e\<bullet>F{D} := v : T" "P,E,h \<turnstile> e1 «bop» e2 : T" "P,E,h \<turnstile> new C : T" "P,E,h \<turnstile> e\<bullet>M{D}(es) : T" (*>*) subsection{*Some interesting lemmas*} lemma WTrts_Val[simp]: "!!Ts. (P,E,h \<turnstile> map Val vs [:] Ts) = (map (typeofh) vs = map Some Ts)" (*<*) apply(induct vs) apply simp apply(case_tac Ts) apply simp apply simp done (*>*) lemma WTrts_same_length: "!!Ts. P,E,h \<turnstile> es [:] Ts ==> length es = length Ts" (*<*)by(induct es type:list)auto(*>*) lemma WTrt_env_mono: "P,E,h \<turnstile> e : T ==> (!!E'. E ⊆m E' ==> P,E',h \<turnstile> e : T)" and "P,E,h \<turnstile> es [:] Ts ==> (!!E'. E ⊆m E' ==> P,E',h \<turnstile> es [:] Ts)" (*<*) apply(induct rule: WTrt_induct) apply(simp add: WTrtNew) apply(fastsimp simp: WTrtCast) apply(fastsimp simp: WTrtVal) apply(simp add: WTrtVar map_le_def dom_def) apply(fastsimp simp add: WTrtBinOp) apply(force simp: map_le_def) apply(fastsimp simp: WTrtFAcc) apply(simp add: WTrtFAccNT) apply(fastsimp simp: WTrtFAss) apply(fastsimp simp: WTrtFAssNT) apply(fastsimp simp: WTrtCall) apply(fastsimp simp: WTrtCallNT) apply(simp add: WTrtNil) apply(simp add: WTrtCons) apply(fastsimp simp: map_le_def) apply(fastsimp) apply(fastsimp simp: WTrtSeq) apply(simp add: WTrtCond) apply(fastsimp simp: WTrtWhile) apply(fastsimp simp: WTrtThrow) apply(auto simp: WTrtTry map_le_def dom_def) done (*>*) lemma WTrt_hext_mono: "P,E,h \<turnstile> e : T ==> (!!h'. h \<unlhd> h' ==> P,E,h' \<turnstile> e : T)" and WTrts_hext_mono: "P,E,h \<turnstile> es [:] Ts ==> (!!h'. h \<unlhd> h' ==> P,E,h' \<turnstile> es [:] Ts)" (*<*) apply(induct rule: WTrt_induct) apply(simp add: WTrtNew) apply(fastsimp simp: WTrtCast) apply(fastsimp simp: WTrtVal dest:hext_typeof_mono) apply(simp add: WTrtVar) apply(fastsimp simp add: WTrtBinOp) apply(fastsimp simp add: WTrtLAss) apply(fast intro: WTrtFAcc) apply(simp add: WTrtFAccNT) apply(fastsimp simp: WTrtFAss del:WTrt_WTrts.intros WTrt_elim_cases) apply(fastsimp simp: WTrtFAssNT) apply(fastsimp simp: WTrtCall) apply(fastsimp simp: WTrtCallNT) apply(fastsimp) apply(fastsimp simp add: WTrtSeq) apply(fastsimp simp add: WTrtCond) apply(fastsimp simp add: WTrtWhile) apply(fastsimp simp add: WTrtThrow) apply(fastsimp simp: WTrtTry) apply(simp add: WTrtNil) apply(simp add: WTrtCons) done (*>*) lemma WT_implies_WTrt: "P,E \<turnstile> e :: T ==> P,E,h \<turnstile> e : T" and WTs_implies_WTrts: "P,E \<turnstile> es [::] Ts ==> P,E,h \<turnstile> es [:] Ts" (*<*) apply(induct rule: WT_WTs_induct) apply fast apply (fast) apply(fastsimp dest:typeof_lit_typeof) apply(simp) apply(fastsimp split:bop.splits) apply(fastsimp) apply(fastsimp simp: WTrtFAcc has_visible_field) apply(fastsimp simp: WTrtFAss dest: has_visible_field) apply(fastsimp simp: WTrtCall) apply(fastsimp) apply(fastsimp) apply(fastsimp) apply(fastsimp) apply(fastsimp) apply(fastsimp) apply(simp) apply(simp) done (*>*) end
lemmas WTrt_induct:
[| !!C E h. is_class P C ==> P1 E h (new C) (Class C); !!C E T e h. [| WTrt P E h e T; P1 E h e T; is_refT T; is_class P C |] ==> P1 E h (Cast C e) (Class C); !!E T h v. typeofh v = ⌊T⌋ ==> P1 E h (Val v) T; !!E T V h. E V = ⌊T⌋ ==> P1 E h (Var V) T; !!E T T1 T2 bop e1 e2 h. [| WTrt P E h e1 T1; P1 E h e1 T1; WTrt P E h e2 T2; P1 E h e2 T2; case bop of Eq => T = Boolean | Add => T1 = Integer & T2 = Integer & T = Integer |] ==> P1 E h (e1 «bop» e2) T; !!E T T' V e h. [| E V = ⌊T⌋; WTrt P E h e T'; P1 E h e T'; widen P T' T |] ==> P1 E h (V:=e) Void; !!C D E F T e h. [| WTrt P E h e (Class C); P1 E h e (Class C); P \<turnstile> C has F:T in D |] ==> P1 E h (e\<bullet>F{D}) T; !!D E F T e h. [| WTrt P E h e NT; P1 E h e NT |] ==> P1 E h (e\<bullet>F{D}) T; !!C D E F T T2 e1 e2 h. [| WTrt P E h e1 (Class C); P1 E h e1 (Class C); P \<turnstile> C has F:T in D; WTrt P E h e2 T2; P1 E h e2 T2; widen P T2 T |] ==> P1 E h (e1\<bullet>F{D} := e2) Void; !!D E F T2 e1 e2 h. [| WTrt P E h e1 NT; P1 E h e1 NT; WTrt P E h e2 T2; P1 E h e2 T2 |] ==> P1 E h (e1\<bullet>F{D} := e2) Void; !!C D E M T Ts Ts' body e es h pns. [| WTrt P E h e (Class C); P1 E h e (Class C); P \<turnstile> C sees M: Ts->T = (pns, body) in D; WTrts P E h es Ts'; P2 E h es Ts'; widens P Ts' Ts |] ==> P1 E h (e\<bullet>M(es)) T; !!E M T Ts e es h. [| WTrt P E h e NT; P1 E h e NT; WTrts P E h es Ts; P2 E h es Ts |] ==> P1 E h (e\<bullet>M(es)) T; !!E T T' V e h. [| WTrt P (E(V |-> T)) h e T'; P1 (E(V |-> T)) h e T' |] ==> P1 E h {V:T; e} T'; !!E T1 T2 e1 e2 h. [| WTrt P E h e1 T1; P1 E h e1 T1; WTrt P E h e2 T2; P1 E h e2 T2 |] ==> P1 E h (e1;; e2) T2; !!E T T1 T2 e e1 e2 h. [| WTrt P E h e Boolean; P1 E h e Boolean; WTrt P E h e1 T1; P1 E h e1 T1; WTrt P E h e2 T2; P1 E h e2 T2; widen P T1 T2 | widen P T2 T1; widen P T1 T2 --> T = T2; widen P T2 T1 --> T = T1 |] ==> P1 E h (if (e) e1 else e2) T; !!E T c e h. [| WTrt P E h e Boolean; P1 E h e Boolean; WTrt P E h c T; P1 E h c T |] ==> P1 E h (while (e) c) Void; !!E T Tr e h. [| WTrt P E h e Tr; P1 E h e Tr; is_refT Tr |] ==> P1 E h (throw e) T; !!C E T1 T2 V e1 e2 h. [| WTrt P E h e1 T1; P1 E h e1 T1; WTrt P (E(V |-> Class C)) h e2 T2; P1 (E(V |-> Class C)) h e2 T2; widen P T1 T2 |] ==> P1 E h (try e1 catch(C V) e2) T2; !!E h. P2 E h [] []; !!E T Ts e es h. [| WTrt P E h e T; P1 E h e T; WTrts P E h es Ts; P2 E h es Ts |] ==> P2 E h (e # es) (T # Ts) |] ==> (WTrt P xha xga xfa xea --> P1 xha xga xfa xea) & (WTrts P xda xca xba xaa --> P2 xda xca xba xaa)
lemma
WTrts P E h [] Ts = (Ts = [])
lemma
WTrts P E h (e # es) (T # Ts) = (WTrt P E h e T & WTrts P E h es Ts)
lemma
WTrts P E h (e # es) Ts = (EX U Us. Ts = U # Us & WTrt P E h e U & WTrts P E h es Us)
lemma
ALL Ts. WTrts P E h (es1 @ es2) Ts = (EX Ts1 Ts2. Ts = Ts1 @ Ts2 & WTrts P E h es1 Ts1 & WTrts P E h es2 Ts2)
lemma
WTrt P E h (Val v) T = (typeofh v = ⌊T⌋)
lemma
WTrt P E h (Var v) T = (E v = ⌊T⌋)
lemma
WTrt P E h (e1;; e2) T2 = (EX T1. WTrt P E h e1 T1 & WTrt P E h e2 T2)
lemma
WTrt P E h {V:T; e} T' = WTrt P (E(V |-> T)) h e T'
lemmas WTrt_elim_cases:
[| WTrt P E h (v:=e) T; !!Ta T'. [| E v = ⌊Ta⌋; WTrt P E h e T'; widen P T' Ta; T = Void |] ==> Pa |] ==> Pa
[| WTrt P E h (if (e) e1 else e2) T; !!T1 T2. [| WTrt P E h e Boolean; WTrt P E h e1 T1; WTrt P E h e2 T2; widen P T1 T2 | widen P T2 T1; widen P T1 T2 --> T = T2; widen P T2 T1 --> T = T1 |] ==> Pa |] ==> Pa
[| WTrt P E h (while (e) c) T; !!Ta. [| WTrt P E h e Boolean; WTrt P E h c Ta; T = Void |] ==> Pa |] ==> Pa
[| WTrt P E h (throw e) T; !!Tr. [| WTrt P E h e Tr; is_refT Tr |] ==> Pa |] ==> Pa
[| WTrt P E h (try e1 catch(C V) e2) T; !!T1. [| WTrt P E h e1 T1; WTrt P (E(V |-> Class C)) h e2 T; widen P T1 T |] ==> Pa |] ==> Pa
[| WTrt P E h (Cast D e) T; !!Ta. [| WTrt P E h e Ta; is_refT Ta; is_class P D; T = Class D |] ==> Pa |] ==> Pa
[| WTrt P E h (e\<bullet>F{D}) T; !!C. [| WTrt P E h e (Class C); P \<turnstile> C has F:T in D |] ==> Pa; WTrt P E h e NT ==> Pa |] ==> Pa
[| WTrt P E h (e\<bullet>F{D} := v) T; !!C Ta T2. [| WTrt P E h e (Class C); P \<turnstile> C has F:Ta in D; WTrt P E h v T2; widen P T2 Ta; T = Void |] ==> Pa; !!T2. [| WTrt P E h e NT; WTrt P E h v T2; T = Void |] ==> Pa |] ==> Pa
[| WTrt P E h (e1 «bop» e2) T; !!T1 T2. [| WTrt P E h e1 T1; WTrt P E h e2 T2; case bop of Eq => T = Boolean | Add => T1 = Integer & T2 = Integer & T = Integer |] ==> Pa |] ==> Pa
[| WTrt P E h (new C) T; [| is_class P C; T = Class C |] ==> Pa |] ==> Pa
[| WTrt P E h (e\<bullet>M {D}(es)) T; !!C Da Ts Ts' body pns. [| WTrt P E h e (Class C); P \<turnstile> C sees M {D}: Ts->T = (pns, body) in Da; WTrts P E h es Ts'; widens P Ts' Ts |] ==> Pa; !!Ts. [| WTrt P E h e NT; WTrts P E h es Ts |] ==> Pa |] ==> Pa
lemma WTrts_Val:
WTrts P E h (map Val vs) Ts = (map typeofh vs = map Some Ts)
lemma WTrts_same_length:
WTrts P E h es Ts ==> length es = length Ts
lemma WTrt_env_mono:
[| WTrt P E h e T; E ⊆m E' |] ==> WTrt P E' h e T
and
[| WTrts P E h es Ts; E ⊆m E' |] ==> WTrts P E' h es Ts
lemma WTrt_hext_mono:
[| WTrt P E h e T; h \<unlhd> h' |] ==> WTrt P E h' e T
and WTrts_hext_mono:
[| WTrts P E h es Ts; h \<unlhd> h' |] ==> WTrts P E h' es Ts
lemma WT_implies_WTrt:
WT P E e T ==> WTrt P E h e T
and WTs_implies_WTrts:
WTs P E es Ts ==> WTrts P E h es Ts