diff --git a/thys/Jinja/J/BigStep.thy b/thys/Jinja/J/BigStep.thy --- a/thys/Jinja/J/BigStep.thy +++ b/thys/Jinja/J/BigStep.thy @@ -1,406 +1,422 @@ (* Title: Jinja/J/BigStep.thy Author: Tobias Nipkow Copyright 2003 Technische Universitaet Muenchen *) section \Big Step Semantics\ theory BigStep imports Expr State begin inductive eval :: "J_prog \ expr \ state \ expr \ state \ bool" ("_ \ ((1\_,/_\) \/ (1\_,/_\))" [51,0,0,0,0] 81) and evals :: "J_prog \ expr list \ state \ expr list \ state \ bool" ("_ \ ((1\_,/_\) [\]/ (1\_,/_\))" [51,0,0,0,0] 81) for P :: J_prog where New: "\ new_Addr h = Some a; P \ C has_fields FDTs; h' = h(a\(C,init_fields FDTs)) \ \ P \ \new C,(h,l)\ \ \addr a,(h',l)\" | NewFail: "new_Addr h = None \ P \ \new C, (h,l)\ \ \THROW OutOfMemory,(h,l)\" | Cast: "\ P \ \e,s\<^sub>0\ \ \addr a,(h,l)\; h a = Some(D,fs); P \ D \\<^sup>* C \ \ P \ \Cast C e,s\<^sub>0\ \ \addr a,(h,l)\" | CastNull: "P \ \e,s\<^sub>0\ \ \null,s\<^sub>1\ \ P \ \Cast C e,s\<^sub>0\ \ \null,s\<^sub>1\" | CastFail: "\ P \ \e,s\<^sub>0\\ \addr a,(h,l)\; h a = Some(D,fs); \ P \ D \\<^sup>* C \ \ P \ \Cast C e,s\<^sub>0\ \ \THROW ClassCast,(h,l)\" | CastThrow: "P \ \e,s\<^sub>0\ \ \throw e',s\<^sub>1\ \ P \ \Cast C e,s\<^sub>0\ \ \throw e',s\<^sub>1\" | Val: "P \ \Val v,s\ \ \Val v,s\" | BinOp: "\ P \ \e\<^sub>1,s\<^sub>0\ \ \Val v\<^sub>1,s\<^sub>1\; P \ \e\<^sub>2,s\<^sub>1\ \ \Val v\<^sub>2,s\<^sub>2\; binop(bop,v\<^sub>1,v\<^sub>2) = Some v \ \ P \ \e\<^sub>1 \bop\ e\<^sub>2,s\<^sub>0\\\Val v,s\<^sub>2\" | BinOpThrow1: "P \ \e\<^sub>1,s\<^sub>0\ \ \throw e,s\<^sub>1\ \ P \ \e\<^sub>1 \bop\ e\<^sub>2, s\<^sub>0\ \ \throw e,s\<^sub>1\" | BinOpThrow2: "\ P \ \e\<^sub>1,s\<^sub>0\ \ \Val v\<^sub>1,s\<^sub>1\; P \ \e\<^sub>2,s\<^sub>1\ \ \throw e,s\<^sub>2\ \ \ P \ \e\<^sub>1 \bop\ e\<^sub>2,s\<^sub>0\ \ \throw e,s\<^sub>2\" | Var: "l V = Some v \ P \ \Var V,(h,l)\ \ \Val v,(h,l)\" | LAss: "\ P \ \e,s\<^sub>0\ \ \Val v,(h,l)\; l' = l(V\v) \ \ P \ \V:=e,s\<^sub>0\ \ \unit,(h,l')\" | LAssThrow: "P \ \e,s\<^sub>0\ \ \throw e',s\<^sub>1\ \ P \ \V:=e,s\<^sub>0\ \ \throw e',s\<^sub>1\" | FAcc: "\ P \ \e,s\<^sub>0\ \ \addr a,(h,l)\; h a = Some(C,fs); fs(F,D) = Some v \ \ P \ \e\F{D},s\<^sub>0\ \ \Val v,(h,l)\" | FAccNull: "P \ \e,s\<^sub>0\ \ \null,s\<^sub>1\ \ P \ \e\F{D},s\<^sub>0\ \ \THROW NullPointer,s\<^sub>1\" | FAccThrow: "P \ \e,s\<^sub>0\ \ \throw e',s\<^sub>1\ \ P \ \e\F{D},s\<^sub>0\ \ \throw e',s\<^sub>1\" | FAss: "\ P \ \e\<^sub>1,s\<^sub>0\ \ \addr a,s\<^sub>1\; P \ \e\<^sub>2,s\<^sub>1\ \ \Val v,(h\<^sub>2,l\<^sub>2)\; h\<^sub>2 a = Some(C,fs); fs' = fs((F,D)\v); h\<^sub>2' = h\<^sub>2(a\(C,fs')) \ \ P \ \e\<^sub>1\F{D}:=e\<^sub>2,s\<^sub>0\ \ \unit,(h\<^sub>2',l\<^sub>2)\" | FAssNull: "\ P \ \e\<^sub>1,s\<^sub>0\ \ \null,s\<^sub>1\; P \ \e\<^sub>2,s\<^sub>1\ \ \Val v,s\<^sub>2\ \ \ P \ \e\<^sub>1\F{D}:=e\<^sub>2,s\<^sub>0\ \ \THROW NullPointer,s\<^sub>2\" | FAssThrow1: "P \ \e\<^sub>1,s\<^sub>0\ \ \throw e',s\<^sub>1\ \ P \ \e\<^sub>1\F{D}:=e\<^sub>2,s\<^sub>0\ \ \throw e',s\<^sub>1\" | FAssThrow2: "\ P \ \e\<^sub>1,s\<^sub>0\ \ \Val v,s\<^sub>1\; P \ \e\<^sub>2,s\<^sub>1\ \ \throw e',s\<^sub>2\ \ \ P \ \e\<^sub>1\F{D}:=e\<^sub>2,s\<^sub>0\ \ \throw e',s\<^sub>2\" | CallObjThrow: "P \ \e,s\<^sub>0\ \ \throw e',s\<^sub>1\ \ P \ \e\M(ps),s\<^sub>0\ \ \throw e',s\<^sub>1\" | CallParamsThrow: "\ P \ \e,s\<^sub>0\ \ \Val v,s\<^sub>1\; P \ \es,s\<^sub>1\ [\] \map Val vs @ throw ex # es',s\<^sub>2\ \ \ P \ \e\M(es),s\<^sub>0\ \ \throw ex,s\<^sub>2\" | CallNull: "\ P \ \e,s\<^sub>0\ \ \null,s\<^sub>1\; P \ \ps,s\<^sub>1\ [\] \map Val vs,s\<^sub>2\ \ \ P \ \e\M(ps),s\<^sub>0\ \ \THROW NullPointer,s\<^sub>2\" | Call: "\ P \ \e,s\<^sub>0\ \ \addr a,s\<^sub>1\; P \ \ps,s\<^sub>1\ [\] \map Val vs,(h\<^sub>2,l\<^sub>2)\; h\<^sub>2 a = Some(C,fs); P \ C sees M:Ts\T = (pns,body) in D; length vs = length pns; l\<^sub>2' = [this\Addr a, pns[\]vs]; P \ \body,(h\<^sub>2,l\<^sub>2')\ \ \e',(h\<^sub>3,l\<^sub>3)\ \ \ P \ \e\M(ps),s\<^sub>0\ \ \e',(h\<^sub>3,l\<^sub>2)\" | Block: "P \ \e\<^sub>0,(h\<^sub>0,l\<^sub>0(V:=None))\ \ \e\<^sub>1,(h\<^sub>1,l\<^sub>1)\ \ P \ \{V:T; e\<^sub>0},(h\<^sub>0,l\<^sub>0)\ \ \e\<^sub>1,(h\<^sub>1,l\<^sub>1(V:=l\<^sub>0 V))\" | Seq: "\ P \ \e\<^sub>0,s\<^sub>0\ \ \Val v,s\<^sub>1\; P \ \e\<^sub>1,s\<^sub>1\ \ \e\<^sub>2,s\<^sub>2\ \ \ P \ \e\<^sub>0;;e\<^sub>1,s\<^sub>0\ \ \e\<^sub>2,s\<^sub>2\" | SeqThrow: "P \ \e\<^sub>0,s\<^sub>0\ \ \throw e,s\<^sub>1\ \ P \ \e\<^sub>0;;e\<^sub>1,s\<^sub>0\\\throw e,s\<^sub>1\" | CondT: "\ P \ \e,s\<^sub>0\ \ \true,s\<^sub>1\; P \ \e\<^sub>1,s\<^sub>1\ \ \e',s\<^sub>2\ \ \ P \ \if (e) e\<^sub>1 else e\<^sub>2,s\<^sub>0\ \ \e',s\<^sub>2\" | CondF: "\ P \ \e,s\<^sub>0\ \ \false,s\<^sub>1\; P \ \e\<^sub>2,s\<^sub>1\ \ \e',s\<^sub>2\ \ \ P \ \if (e) e\<^sub>1 else e\<^sub>2,s\<^sub>0\ \ \e',s\<^sub>2\" | CondThrow: "P \ \e,s\<^sub>0\ \ \throw e',s\<^sub>1\ \ P \ \if (e) e\<^sub>1 else e\<^sub>2, s\<^sub>0\ \ \throw e',s\<^sub>1\" | WhileF: "P \ \e,s\<^sub>0\ \ \false,s\<^sub>1\ \ P \ \while (e) c,s\<^sub>0\ \ \unit,s\<^sub>1\" | WhileT: "\ P \ \e,s\<^sub>0\ \ \true,s\<^sub>1\; P \ \c,s\<^sub>1\ \ \Val v\<^sub>1,s\<^sub>2\; P \ \while (e) c,s\<^sub>2\ \ \e\<^sub>3,s\<^sub>3\ \ \ P \ \while (e) c,s\<^sub>0\ \ \e\<^sub>3,s\<^sub>3\" | WhileCondThrow: "P \ \e,s\<^sub>0\ \ \ throw e',s\<^sub>1\ \ P \ \while (e) c,s\<^sub>0\ \ \throw e',s\<^sub>1\" | WhileBodyThrow: "\ P \ \e,s\<^sub>0\ \ \true,s\<^sub>1\; P \ \c,s\<^sub>1\ \ \throw e',s\<^sub>2\\ \ P \ \while (e) c,s\<^sub>0\ \ \throw e',s\<^sub>2\" | Throw: "P \ \e,s\<^sub>0\ \ \addr a,s\<^sub>1\ \ P \ \throw e,s\<^sub>0\ \ \Throw a,s\<^sub>1\" | ThrowNull: "P \ \e,s\<^sub>0\ \ \null,s\<^sub>1\ \ P \ \throw e,s\<^sub>0\ \ \THROW NullPointer,s\<^sub>1\" | ThrowThrow: "P \ \e,s\<^sub>0\ \ \throw e',s\<^sub>1\ \ P \ \throw e,s\<^sub>0\ \ \throw e',s\<^sub>1\" | Try: "P \ \e\<^sub>1,s\<^sub>0\ \ \Val v\<^sub>1,s\<^sub>1\ \ P \ \try e\<^sub>1 catch(C V) e\<^sub>2,s\<^sub>0\ \ \Val v\<^sub>1,s\<^sub>1\" | TryCatch: "\ P \ \e\<^sub>1,s\<^sub>0\ \ \Throw a,(h\<^sub>1,l\<^sub>1)\; h\<^sub>1 a = Some(D,fs); P \ D \\<^sup>* C; P \ \e\<^sub>2,(h\<^sub>1,l\<^sub>1(V\Addr a))\ \ \e\<^sub>2',(h\<^sub>2,l\<^sub>2)\ \ \ P \ \try e\<^sub>1 catch(C V) e\<^sub>2,s\<^sub>0\ \ \e\<^sub>2',(h\<^sub>2,l\<^sub>2(V:=l\<^sub>1 V))\" | TryThrow: "\ P \ \e\<^sub>1,s\<^sub>0\ \ \Throw a,(h\<^sub>1,l\<^sub>1)\; h\<^sub>1 a = Some(D,fs); \ P \ D \\<^sup>* C \ \ P \ \try e\<^sub>1 catch(C V) e\<^sub>2,s\<^sub>0\ \ \Throw a,(h\<^sub>1,l\<^sub>1)\" | Nil: "P \ \[],s\ [\] \[],s\" | Cons: "\ P \ \e,s\<^sub>0\ \ \Val v,s\<^sub>1\; P \ \es,s\<^sub>1\ [\] \es',s\<^sub>2\ \ \ P \ \e#es,s\<^sub>0\ [\] \Val v # es',s\<^sub>2\" | ConsThrow: "P \ \e, s\<^sub>0\ \ \throw e', s\<^sub>1\ \ P \ \e#es, s\<^sub>0\ [\] \throw e' # es, s\<^sub>1\" (*<*) lemmas eval_evals_induct = eval_evals.induct [split_format (complete)] and eval_evals_inducts = eval_evals.inducts [split_format (complete)] inductive_cases eval_cases [cases set]: "P \ \Cast C e,s\ \ \e',s'\" "P \ \Val v,s\ \ \e',s'\" "P \ \e\<^sub>1 \bop\ e\<^sub>2,s\ \ \e',s'\" "P \ \V:=e,s\ \ \e',s'\" "P \ \e\F{D},s\ \ \e',s'\" "P \ \e\<^sub>1\F{D}:=e\<^sub>2,s\ \ \e',s'\" "P \ \e\M{D}(es),s\ \ \e',s'\" "P \ \{V:T;e\<^sub>1},s\ \ \e',s'\" "P \ \e\<^sub>1;;e\<^sub>2,s\ \ \e',s'\" "P \ \if (e) e\<^sub>1 else e\<^sub>2,s\ \ \e',s'\" "P \ \while (b) c,s\ \ \e',s'\" "P \ \throw e,s\ \ \e',s'\" "P \ \try e\<^sub>1 catch(C V) e\<^sub>2,s\ \ \e',s'\" inductive_cases evals_cases [cases set]: "P \ \[],s\ [\] \e',s'\" "P \ \e#es,s\ [\] \e',s'\" (*>*) subsection"Final expressions" definition final :: "'a exp \ bool" where "final e \ (\v. e = Val v) \ (\a. e = Throw a)" definition finals:: "'a exp list \ bool" where "finals es \ (\vs. es = map Val vs) \ (\vs a es'. es = map Val vs @ Throw a # es')" lemma [simp]: "final(Val v)" (*<*)by(simp add:final_def)(*>*) lemma [simp]: "final(throw e) = (\a. e = addr a)" (*<*)by(simp add:final_def)(*>*) lemma finalE: "\ final e; \v. e = Val v \ R; \a. e = Throw a \ R \ \ R" (*<*)by(auto simp:final_def)(*>*) lemma [iff]: "finals []" (*<*)by(simp add:finals_def)(*>*) lemma [iff]: "finals (Val v # es) = finals es" (*<*) -apply(clarsimp simp add: finals_def) -apply(rule iffI) - apply(erule disjE) - apply simp - apply(rule disjI2) - apply clarsimp - apply(case_tac vs) - apply simp - apply fastforce -apply(erule disjE) - apply clarsimp -apply(rule disjI2) -apply clarsimp -apply(rule_tac x = "v#vs" in exI) -apply simp -done +proof(rule iffI) + assume "finals (Val v # es)" + moreover { + fix vs a es' + assume "\vs a es'. es \ map Val vs @ Throw a # es'" + and "Val v # es = map Val vs @ Throw a # es'" + then have "\vs. es = map Val vs" by(case_tac vs; simp) + } + ultimately show "finals es" by(clarsimp simp add: finals_def) +next + assume "finals es" + moreover { + fix vs a es' + assume "es = map Val vs @ Throw a # es'" + then have "\vs' a' es''. Val v # map Val vs @ Throw a # es' = map Val vs' @ Throw a' # es''" + by(rule_tac x = "v#vs" in exI) simp + } + ultimately show "finals (Val v # es)" by(clarsimp simp add: finals_def) +qed (*>*) lemma finals_app_map[iff]: "finals (map Val vs @ es) = finals es" (*<*)by(induct_tac vs, auto)(*>*) lemma [iff]: "finals (map Val vs)" (*<*)using finals_app_map[of vs "[]"]by(simp)(*>*) lemma [iff]: "finals (throw e # es) = (\a. e = addr a)" (*<*) -apply(simp add:finals_def) -apply(rule iffI) - apply clarsimp - apply(case_tac vs) - apply simp - apply fastforce -apply clarsimp -apply(rule_tac x = "[]" in exI) -apply simp -done +proof(rule iffI) + assume "finals (throw e # es)" + moreover { + fix vs a es' + assume "throw e # es = map Val vs @ Throw a # es'" + then have "\a. e = addr a" by(case_tac vs; simp) + } + ultimately show "\a. e = addr a" by(clarsimp simp add: finals_def) +next + assume "\a. e = addr a" + moreover { + fix vs a es' + assume "e = addr a" + then have "\vs aa es'. Throw a # es = map Val vs @ Throw aa # es'" + by(rule_tac x = "[]" in exI) simp + } + ultimately show "finals (throw e # es)" by(clarsimp simp add: finals_def) +qed (*>*) lemma not_finals_ConsI: "\ final e \ \ finals(e#es)" - (*<*) -apply(clarsimp simp add:finals_def final_def) -apply(case_tac vs) -apply auto -done +(*<*) +proof - + assume "\ final e" + moreover { + fix vs a es' + assume "\v. e \ Val v" and "\a. e \ Throw a" + then have "e # es \ map Val vs @ Throw a # es'" by(case_tac vs; simp) + } + ultimately show ?thesis by(clarsimp simp add:finals_def final_def) +qed (*>*) lemma eval_final: "P \ \e,s\ \ \e',s'\ \ final e'" and evals_final: "P \ \es,s\ [\] \es',s'\ \ finals es'" (*<*)by(induct rule:eval_evals.inducts, simp_all)(*>*) lemma eval_lcl_incr: "P \ \e,(h\<^sub>0,l\<^sub>0)\ \ \e',(h\<^sub>1,l\<^sub>1)\ \ dom l\<^sub>0 \ dom l\<^sub>1" and evals_lcl_incr: "P \ \es,(h\<^sub>0,l\<^sub>0)\ [\] \es',(h\<^sub>1,l\<^sub>1)\ \ dom l\<^sub>0 \ dom l\<^sub>1" (*<*) proof (induct rule: eval_evals_inducts) case BinOp show ?case by(rule subset_trans)(rule BinOp.hyps)+ next case Call thus ?case by(simp del: fun_upd_apply) next case Seq show ?case by(rule subset_trans)(rule Seq.hyps)+ next case CondT show ?case by(rule subset_trans)(rule CondT.hyps)+ next case CondF show ?case by(rule subset_trans)(rule CondF.hyps)+ next case WhileT thus ?case by(blast) next case TryCatch thus ?case by(clarsimp simp:dom_def split:if_split_asm) blast next case Cons show ?case by(rule subset_trans)(rule Cons.hyps)+ next case Block thus ?case by(auto simp del:fun_upd_apply) qed auto (*>*) text\Only used later, in the small to big translation, but is already a good sanity check:\ lemma eval_finalId: "final e \ P \ \e,s\ \ \e,s\" (*<*)by (erule finalE) (iprover intro: eval_evals.intros)+(*>*) lemma eval_finalsId: assumes finals: "finals es" shows "P \ \es,s\ [\] \es,s\" (*<*) using finals proof (induct es type: list) case Nil show ?case by (rule eval_evals.intros) next case (Cons e es) have hyp: "finals es \ P \ \es,s\ [\] \es,s\" and finals: "finals (e # es)" by fact+ show "P \ \e # es,s\ [\] \e # es,s\" proof cases assume "final e" thus ?thesis proof (cases rule: finalE) fix v assume e: "e = Val v" have "P \ \Val v,s\ \ \Val v,s\" by (simp add: eval_finalId) moreover from finals e have "P \ \es,s\ [\] \es,s\" by(fast intro:hyp) ultimately have "P \ \Val v#es,s\ [\] \Val v#es,s\" by (rule eval_evals.intros) with e show ?thesis by simp next fix a assume e: "e = Throw a" have "P \ \Throw a,s\ \ \Throw a,s\" by (simp add: eval_finalId) hence "P \ \Throw a#es,s\ [\] \Throw a#es,s\" by (rule eval_evals.intros) with e show ?thesis by simp qed next assume "\ final e" with not_finals_ConsI finals have False by blast thus ?thesis .. qed qed (*>*) theorem eval_hext: "P \ \e,(h,l)\ \ \e',(h',l')\ \ h \ h'" and evals_hext: "P \ \es,(h,l)\ [\] \es',(h',l')\ \ h \ h'" (*<*) proof (induct rule: eval_evals_inducts) case New thus ?case by(fastforce intro!: hext_new intro:LeastI simp:new_Addr_def split:if_split_asm simp del:fun_upd_apply) next case BinOp thus ?case by (fast elim!:hext_trans) next case BinOpThrow2 thus ?case by(fast elim!: hext_trans) next case FAss thus ?case by(auto simp:sym[THEN hext_upd_obj] simp del:fun_upd_apply elim!: hext_trans) next case FAssNull thus ?case by (fast elim!:hext_trans) next case FAssThrow2 thus ?case by (fast elim!:hext_trans) next case CallParamsThrow thus ?case by(fast elim!: hext_trans) next case CallNull thus ?case by(fast elim!: hext_trans) next case Call thus ?case by(fast elim!: hext_trans) next case Seq thus ?case by(fast elim!: hext_trans) next case CondT thus ?case by(fast elim!: hext_trans) next case CondF thus ?case by(fast elim!: hext_trans) next case WhileT thus ?case by(fast elim!: hext_trans) next case WhileBodyThrow thus ?case by (fast elim!: hext_trans) next case TryCatch thus ?case by(fast elim!: hext_trans) next case Cons thus ?case by (fast intro: hext_trans) qed auto (*>*) end diff --git a/thys/Jinja/J/Expr.thy b/thys/Jinja/J/Expr.thy --- a/thys/Jinja/J/Expr.thy +++ b/thys/Jinja/J/Expr.thy @@ -1,104 +1,98 @@ (* Title: Jinja/J/Expr.thy Author: Tobias Nipkow Copyright 2003 Technische Universitaet Muenchen *) section \Expressions\ theory Expr imports "../Common/Exceptions" begin datatype bop = Eq | Add \ \names of binary operations\ datatype 'a exp = new cname \ \class instance creation\ | Cast cname "('a exp)" \ \type cast\ | Val val \ \value\ | BinOp "('a exp)" bop "('a exp)" ("_ \_\ _" [80,0,81] 80) \ \binary operation\ | Var 'a \ \local variable (incl. parameter)\ | LAss 'a "('a exp)" ("_:=_" [90,90]90) \ \local assignment\ | FAcc "('a exp)" vname cname ("_\_{_}" [10,90,99]90) \ \field access\ | FAss "('a exp)" vname cname "('a exp)" ("_\_{_} := _" [10,90,99,90]90) \ \field assignment\ | Call "('a exp)" mname "('a exp list)" ("_\_'(_')" [90,99,0] 90) \ \method call\ | Block 'a ty "('a exp)" ("'{_:_; _}") | Seq "('a exp)" "('a exp)" ("_;;/ _" [61,60]60) | Cond "('a exp)" "('a exp)" "('a exp)" ("if '(_') _/ else _" [80,79,79]70) | While "('a exp)" "('a exp)" ("while '(_') _" [80,79]70) | throw "('a exp)" | TryCatch "('a exp)" cname 'a "('a exp)" ("try _/ catch'(_ _') _" [0,99,80,79] 70) type_synonym expr = "vname exp" \ \Jinja expression\ type_synonym J_mb = "vname list \ expr" \ \Jinja method body: parameter names and expression\ type_synonym J_prog = "J_mb prog" \ \Jinja program\ text\The semantics of binary operators:\ fun binop :: "bop \ val \ val \ val option" where "binop(Eq,v\<^sub>1,v\<^sub>2) = Some(Bool (v\<^sub>1 = v\<^sub>2))" | "binop(Add,Intg i\<^sub>1,Intg i\<^sub>2) = Some(Intg(i\<^sub>1+i\<^sub>2))" | "binop(bop,v\<^sub>1,v\<^sub>2) = None" lemma [simp]: "(binop(Add,v\<^sub>1,v\<^sub>2) = Some v) = (\i\<^sub>1 i\<^sub>2. v\<^sub>1 = Intg i\<^sub>1 \ v\<^sub>2 = Intg i\<^sub>2 \ v = Intg(i\<^sub>1+i\<^sub>2))" -(*<*) -apply(cases v\<^sub>1) -apply auto -apply(cases v\<^sub>2) -apply auto -done -(*>*) +(*<*)by(cases v\<^sub>1; cases v\<^sub>2) auto(*>*) subsection "Syntactic sugar" abbreviation (input) InitBlock:: "'a \ ty \ 'a exp \ 'a exp \ 'a exp" ("(1'{_:_ := _;/ _})") where "InitBlock V T e1 e2 == {V:T; V := e1;; e2}" abbreviation unit where "unit == Val Unit" abbreviation null where "null == Val Null" abbreviation "addr a == Val(Addr a)" abbreviation "true == Val(Bool True)" abbreviation "false == Val(Bool False)" abbreviation Throw :: "addr \ 'a exp" where "Throw a == throw(Val(Addr a))" abbreviation THROW :: "cname \ 'a exp" where "THROW xc == Throw(addr_of_sys_xcpt xc)" subsection\Free Variables\ primrec fv :: "expr \ vname set" and fvs :: "expr list \ vname set" where "fv(new C) = {}" | "fv(Cast C e) = fv e" | "fv(Val v) = {}" | "fv(e\<^sub>1 \bop\ e\<^sub>2) = fv e\<^sub>1 \ fv e\<^sub>2" | "fv(Var V) = {V}" | "fv(LAss V e) = {V} \ fv e" | "fv(e\F{D}) = fv e" | "fv(e\<^sub>1\F{D}:=e\<^sub>2) = fv e\<^sub>1 \ fv e\<^sub>2" | "fv(e\M(es)) = fv e \ fvs es" | "fv({V:T; e}) = fv e - {V}" | "fv(e\<^sub>1;;e\<^sub>2) = fv e\<^sub>1 \ fv e\<^sub>2" | "fv(if (b) e\<^sub>1 else e\<^sub>2) = fv b \ fv e\<^sub>1 \ fv e\<^sub>2" | "fv(while (b) e) = fv b \ fv e" | "fv(throw e) = fv e" | "fv(try e\<^sub>1 catch(C V) e\<^sub>2) = fv e\<^sub>1 \ (fv e\<^sub>2 - {V})" | "fvs([]) = {}" | "fvs(e#es) = fv e \ fvs es" lemma [simp]: "fvs(es\<^sub>1 @ es\<^sub>2) = fvs es\<^sub>1 \ fvs es\<^sub>2" (*<*)by (induct es\<^sub>1 type:list) auto(*>*) lemma [simp]: "fvs(map Val vs) = {}" (*<*)by (induct vs) auto(*>*) end diff --git a/thys/Jinja/J/WellType.thy b/thys/Jinja/J/WellType.thy --- a/thys/Jinja/J/WellType.thy +++ b/thys/Jinja/J/WellType.thy @@ -1,235 +1,201 @@ (* Title: Jinja/J/WellType.thy Author: Tobias Nipkow Copyright 2003 Technische Universitaet Muenchen *) section \Well-typedness of Jinja expressions\ theory WellType imports "../Common/Objects" Expr begin type_synonym env = "vname \ ty" inductive WT :: "[J_prog,env, expr , ty ] \ bool" ("_,_ \ _ :: _" [51,51,51]50) and WTs :: "[J_prog,env, expr list, ty list] \ bool" ("_,_ \ _ [::] _" [51,51,51]50) for P :: J_prog where WTNew: "is_class P C \ P,E \ new C :: Class C" | WTCast: "\ P,E \ e :: Class D; is_class P C; P \ C \\<^sup>* D \ P \ D \\<^sup>* C \ \ P,E \ Cast C e :: Class C" | WTVal: "typeof v = Some T \ P,E \ Val v :: T" | WTVar: "E V = Some T \ P,E \ Var V :: T" (* WTBinOp: "\ P,E \ e\<^sub>1 :: T\<^sub>1; P,E \ e\<^sub>2 :: T\<^sub>2; case bop of Eq \ (P \ T\<^sub>1 \ T\<^sub>2 \ P \ T\<^sub>2 \ T\<^sub>1) \ T = Boolean | Add \ T\<^sub>1 = Integer \ T\<^sub>2 = Integer \ T = Integer \ \ P,E \ e\<^sub>1 \bop\ e\<^sub>2 :: T" *) | WTBinOpEq: "\ P,E \ e\<^sub>1 :: T\<^sub>1; P,E \ e\<^sub>2 :: T\<^sub>2; P \ T\<^sub>1 \ T\<^sub>2 \ P \ T\<^sub>2 \ T\<^sub>1 \ \ P,E \ e\<^sub>1 \Eq\ e\<^sub>2 :: Boolean" | WTBinOpAdd: "\ P,E \ e\<^sub>1 :: Integer; P,E \ e\<^sub>2 :: Integer \ \ P,E \ e\<^sub>1 \Add\ e\<^sub>2 :: Integer" | WTLAss: "\ E V = Some T; P,E \ e :: T'; P \ T' \ T; V \ this \ \ P,E \ V:=e :: Void" | WTFAcc: "\ P,E \ e :: Class C; P \ C sees F:T in D \ \ P,E \ e\F{D} :: T" | WTFAss: "\ P,E \ e\<^sub>1 :: Class C; P \ C sees F:T in D; P,E \ e\<^sub>2 :: T'; P \ T' \ T \ \ P,E \ e\<^sub>1\F{D}:=e\<^sub>2 :: Void" | WTCall: "\ P,E \ e :: Class C; P \ C sees M:Ts \ T = (pns,body) in D; P,E \ es [::] Ts'; P \ Ts' [\] Ts \ \ P,E \ e\M(es) :: T" | WTBlock: "\ is_type P T; P,E(V \ T) \ e :: T' \ \ P,E \ {V:T; e} :: T'" | WTSeq: "\ P,E \ e\<^sub>1::T\<^sub>1; P,E \ e\<^sub>2::T\<^sub>2 \ \ P,E \ e\<^sub>1;;e\<^sub>2 :: T\<^sub>2" | WTCond: "\ P,E \ e :: Boolean; P,E \ e\<^sub>1::T\<^sub>1; P,E \ e\<^sub>2::T\<^sub>2; P \ T\<^sub>1 \ T\<^sub>2 \ P \ T\<^sub>2 \ T\<^sub>1; P \ T\<^sub>1 \ T\<^sub>2 \ T = T\<^sub>2; P \ T\<^sub>2 \ T\<^sub>1 \ T = T\<^sub>1 \ \ P,E \ if (e) e\<^sub>1 else e\<^sub>2 :: T" | WTWhile: "\ P,E \ e :: Boolean; P,E \ c::T \ \ P,E \ while (e) c :: Void" | WTThrow: "P,E \ e :: Class C \ P,E \ throw e :: Void" | WTTry: "\ P,E \ e\<^sub>1 :: T; P,E(V \ Class C) \ e\<^sub>2 :: T; is_class P C \ \ P,E \ try e\<^sub>1 catch(C V) e\<^sub>2 :: T" \ \well-typed expression lists\ | WTNil: "P,E \ [] [::] []" | WTCons: "\ P,E \ e :: T; P,E \ es [::] Ts \ \ P,E \ e#es [::] T#Ts" (*<*) (* lemmas [intro!] = WTNew WTCast WTVal WTVar WTBinOp WTLAss WTFAcc WTFAss WTCall WTBlock WTSeq WTWhile WTThrow WTTry WTNil WTCons lemmas [intro] = WTCond1 WTCond2 *) declare WT_WTs.intros[intro!] (* WTNil[iff] *) lemmas WT_WTs_induct = WT_WTs.induct [split_format (complete)] and WT_WTs_inducts = WT_WTs.inducts [split_format (complete)] (*>*) lemma [iff]: "(P,E \ [] [::] Ts) = (Ts = [])" -(*<*) -apply(rule iffI) -apply (auto elim: WTs.cases) -done -(*>*) +(*<*)by (rule iffI) (auto elim: WTs.cases)(*>*) lemma [iff]: "(P,E \ e#es [::] T#Ts) = (P,E \ e :: T \ P,E \ es [::] Ts)" -(*<*) -apply(rule iffI) -apply (auto elim: WTs.cases) -done -(*>*) +(*<*)by (rule iffI) (auto elim: WTs.cases)(*>*) lemma [iff]: "(P,E \ (e#es) [::] Ts) = (\U Us. Ts = U#Us \ P,E \ e :: U \ P,E \ es [::] Us)" -(*<*) -apply(rule iffI) -apply (auto elim: WTs.cases) -done -(*>*) +(*<*)by (rule iffI) (auto elim: WTs.cases)(*>*) lemma [iff]: "\Ts. (P,E \ es\<^sub>1 @ es\<^sub>2 [::] Ts) = (\Ts\<^sub>1 Ts\<^sub>2. Ts = Ts\<^sub>1 @ Ts\<^sub>2 \ P,E \ es\<^sub>1 [::] Ts\<^sub>1 \ P,E \ es\<^sub>2[::]Ts\<^sub>2)" (*<*) -apply(induct es\<^sub>1 type:list) - 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 fastforce -done +proof(induct es\<^sub>1 type:list) + case (Cons a list) + let ?lhs = "(\U Us. Ts = U # Us \ P,E \ a :: U \ + (\Ts\<^sub>1 Ts\<^sub>2. Us = Ts\<^sub>1 @ Ts\<^sub>2 \ P,E \ list [::] Ts\<^sub>1 \ P,E \ es\<^sub>2 [::] Ts\<^sub>2))" + let ?rhs = "(\Ts\<^sub>1 Ts\<^sub>2. Ts = Ts\<^sub>1 @ Ts\<^sub>2 \ + (\U Us. Ts\<^sub>1 = U # Us \ P,E \ a :: U \ P,E \ list [::] Us) \ P,E \ es\<^sub>2 [::] Ts\<^sub>2)" + { assume ?lhs + then have ?rhs by (auto intro: Cons_eq_appendI) + } + moreover { + assume ?rhs + then have ?lhs by fastforce + } + ultimately have "?lhs = ?rhs" by(rule iffI) + then show ?case by (clarsimp simp: Cons) +qed simp (*>*) lemma [iff]: "P,E \ Val v :: T = (typeof v = Some T)" -(*<*) -apply(rule iffI) -apply (auto elim: WT.cases) -done -(*>*) +(*<*)proof(rule iffI) qed (auto elim: WT.cases)(*>*) lemma [iff]: "P,E \ Var V :: T = (E V = Some T)" -(*<*) -apply(rule iffI) -apply (auto elim: WT.cases) -done -(*>*) +(*<*)proof(rule iffI) qed (auto elim: WT.cases)(*>*) lemma [iff]: "P,E \ e\<^sub>1;;e\<^sub>2 :: T\<^sub>2 = (\T\<^sub>1. P,E \ e\<^sub>1::T\<^sub>1 \ P,E \ e\<^sub>2::T\<^sub>2)" -(*<*) -apply(rule iffI) -apply (auto elim: WT.cases) -done -(*>*) +(*<*)proof(rule iffI) qed (auto elim: WT.cases)(*>*) lemma [iff]: "(P,E \ {V:T; e} :: T') = (is_type P T \ P,E(V\T) \ e :: T')" -(*<*) -apply(rule iffI) -apply (auto elim: WT.cases) -done -(*>*) +(*<*)proof(rule iffI) qed (auto elim: WT.cases)(*>*) (*<*) inductive_cases WT_elim_cases[elim!]: "P,E \ V :=e :: T" "P,E \ if (e) e\<^sub>1 else e\<^sub>2 :: T" "P,E \ while (e) c :: T" "P,E \ throw e :: T" "P,E \ try e\<^sub>1 catch(C V) e\<^sub>2 :: T" "P,E \ Cast D e :: T" "P,E \ a\F{D} :: T" "P,E \ a\F{D} := v :: T" "P,E \ e\<^sub>1 \bop\ e\<^sub>2 :: T" "P,E \ new C :: T" "P,E \ e\M(ps) :: T" (*>*) lemma wt_env_mono: "P,E \ e :: T \ (\E'. E \\<^sub>m E' \ P,E' \ e :: T)" and "P,E \ es [::] Ts \ (\E'. E \\<^sub>m E' \ P,E' \ es [::] Ts)" (*<*) -apply(induct rule: WT_WTs_inducts) -apply(simp add: WTNew) -apply(fastforce simp: WTCast) -apply(fastforce simp: WTVal) -apply(simp add: WTVar map_le_def dom_def) -apply(fastforce simp: WTBinOpEq) -apply(fastforce simp: WTBinOpAdd) -apply(force simp:map_le_def) -apply(fastforce simp: WTFAcc) -apply(fastforce simp: WTFAss del:WT_WTs.intros WT_elim_cases) -apply(fastforce simp: WTCall) -apply(fastforce simp: map_le_def WTBlock) -apply(fastforce simp: WTSeq) -apply(fastforce simp: WTCond) -apply(fastforce simp: WTWhile) -apply(fastforce simp: WTThrow) -apply(fastforce simp: WTTry map_le_def dom_def) -apply(simp add: WTNil) -apply(simp add: WTCons) -done +proof(induct rule: WT_WTs_inducts) + case WTVar then show ?case by(simp add: map_le_def dom_def) +next + case WTLAss then show ?case by(force simp:map_le_def) +qed fastforce+ (*>*) lemma WT_fv: "P,E \ e :: T \ fv e \ dom E" and "P,E \ es [::] Ts \ fvs es \ dom E" (*<*) -apply(induct rule:WT_WTs.inducts) -apply(simp_all del: fun_upd_apply) -apply fast+ -done +proof(induct rule:WT_WTs.inducts) + case WTVar then show ?case by fastforce +next + case WTLAss then show ?case by fastforce +next + case WTBlock then show ?case by fastforce +next + case WTTry then show ?case by fastforce +qed simp_all end (*>*) diff --git a/thys/Jinja/J/WellTypeRT.thy b/thys/Jinja/J/WellTypeRT.thy --- a/thys/Jinja/J/WellTypeRT.thy +++ b/thys/Jinja/J/WellTypeRT.thy @@ -1,317 +1,243 @@ (* Title: Jinja/J/WellTypeRT.thy Author: Tobias Nipkow Copyright 2003 Technische Universitaet Muenchen *) section \Runtime Well-typedness\ theory WellTypeRT imports WellType begin inductive WTrt :: "J_prog \ heap \ env \ expr \ ty \ bool" and WTrts :: "J_prog \ heap \ env \ expr list \ ty list \ bool" and WTrt2 :: "[J_prog,env,heap,expr,ty] \ bool" ("_,_,_ \ _ : _" [51,51,51]50) and WTrts2 :: "[J_prog,env,heap,expr list, ty list] \ bool" ("_,_,_ \ _ [:] _" [51,51,51]50) for P :: J_prog and h :: heap where "P,E,h \ e : T \ WTrt P h E e T" | "P,E,h \ es[:]Ts \ WTrts P h E es Ts" | WTrtNew: "is_class P C \ P,E,h \ new C : Class C" | WTrtCast: "\ P,E,h \ e : T; is_refT T; is_class P C \ \ P,E,h \ Cast C e : Class C" | WTrtVal: "typeof\<^bsub>h\<^esub> v = Some T \ P,E,h \ Val v : T" | WTrtVar: "E V = Some T \ P,E,h \ Var V : T" (* WTrtBinOp: "\ P,E,h \ e\<^sub>1 : T\<^sub>1; P,E,h \ e\<^sub>2 : T\<^sub>2; case bop of Eq \ T = Boolean | Add \ T\<^sub>1 = Integer \ T\<^sub>2 = Integer \ T = Integer \ \ P,E,h \ e\<^sub>1 \bop\ e\<^sub>2 : T" *) | WTrtBinOpEq: "\ P,E,h \ e\<^sub>1 : T\<^sub>1; P,E,h \ e\<^sub>2 : T\<^sub>2 \ \ P,E,h \ e\<^sub>1 \Eq\ e\<^sub>2 : Boolean" | WTrtBinOpAdd: "\ P,E,h \ e\<^sub>1 : Integer; P,E,h \ e\<^sub>2 : Integer \ \ P,E,h \ e\<^sub>1 \Add\ e\<^sub>2 : Integer" | WTrtLAss: "\ E V = Some T; P,E,h \ e : T'; P \ T' \ T \ \ P,E,h \ V:=e : Void" | WTrtFAcc: "\ P,E,h \ e : Class C; P \ C has F:T in D \ \ P,E,h \ e\F{D} : T" | WTrtFAccNT: "P,E,h \ e : NT \ P,E,h \ e\F{D} : T" | WTrtFAss: "\ P,E,h \ e\<^sub>1 : Class C; P \ C has F:T in D; P,E,h \ e\<^sub>2 : T\<^sub>2; P \ T\<^sub>2 \ T \ \ P,E,h \ e\<^sub>1\F{D}:=e\<^sub>2 : Void" | WTrtFAssNT: "\ P,E,h \ e\<^sub>1:NT; P,E,h \ e\<^sub>2 : T\<^sub>2 \ \ P,E,h \ e\<^sub>1\F{D}:=e\<^sub>2 : Void" | WTrtCall: "\ P,E,h \ e : Class C; P \ C sees M:Ts \ T = (pns,body) in D; P,E,h \ es [:] Ts'; P \ Ts' [\] Ts \ \ P,E,h \ e\M(es) : T" | WTrtCallNT: "\ P,E,h \ e : NT; P,E,h \ es [:] Ts \ \ P,E,h \ e\M(es) : T" | WTrtBlock: "P,E(V\T),h \ e : T' \ P,E,h \ {V:T; e} : T'" | WTrtSeq: "\ P,E,h \ e\<^sub>1:T\<^sub>1; P,E,h \ e\<^sub>2:T\<^sub>2 \ \ P,E,h \ e\<^sub>1;;e\<^sub>2 : T\<^sub>2" | WTrtCond: "\ P,E,h \ e : Boolean; P,E,h \ e\<^sub>1:T\<^sub>1; P,E,h \ e\<^sub>2:T\<^sub>2; P \ T\<^sub>1 \ T\<^sub>2 \ P \ T\<^sub>2 \ T\<^sub>1; P \ T\<^sub>1 \ T\<^sub>2 \ T = T\<^sub>2; P \ T\<^sub>2 \ T\<^sub>1 \ T = T\<^sub>1 \ \ P,E,h \ if (e) e\<^sub>1 else e\<^sub>2 : T" | WTrtWhile: "\ P,E,h \ e : Boolean; P,E,h \ c:T \ \ P,E,h \ while(e) c : Void" | WTrtThrow: "\ P,E,h \ e : T\<^sub>r; is_refT T\<^sub>r \ \ P,E,h \ throw e : T" | WTrtTry: "\ P,E,h \ e\<^sub>1 : T\<^sub>1; P,E(V \ Class C),h \ e\<^sub>2 : T\<^sub>2; P \ T\<^sub>1 \ T\<^sub>2 \ \ P,E,h \ try e\<^sub>1 catch(C V) e\<^sub>2 : T\<^sub>2" \ \well-typed expression lists\ | WTrtNil: "P,E,h \ [] [:] []" | WTrtCons: "\ P,E,h \ e : T; P,E,h \ es [:] Ts \ \ P,E,h \ 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)] and WTrt_inducts = WTrt_WTrts.inducts [split_format (complete)] (*>*) subsection\Easy consequences\ lemma [iff]: "(P,E,h \ [] [:] Ts) = (Ts = [])" -(*<*) -apply(rule iffI) -apply (auto elim: WTrts.cases) -done -(*>*) +(*<*)by(rule iffI) (auto elim: WTrts.cases)(*>*) lemma [iff]: "(P,E,h \ e#es [:] T#Ts) = (P,E,h \ e : T \ P,E,h \ es [:] Ts)" -(*<*) -apply(rule iffI) -apply (auto elim: WTrts.cases) -done -(*>*) +(*<*)by(rule iffI) (auto elim: WTrts.cases)(*>*) lemma [iff]: "(P,E,h \ (e#es) [:] Ts) = (\U Us. Ts = U#Us \ P,E,h \ e : U \ P,E,h \ es [:] Us)" -(*<*) -apply(rule iffI) -apply (auto elim: WTrts.cases) -done -(*>*) +(*<*)by(rule iffI) (auto elim: WTrts.cases)(*>*) lemma [simp]: "\Ts. (P,E,h \ es\<^sub>1 @ es\<^sub>2 [:] Ts) = (\Ts\<^sub>1 Ts\<^sub>2. Ts = Ts\<^sub>1 @ Ts\<^sub>2 \ P,E,h \ es\<^sub>1 [:] Ts\<^sub>1 & P,E,h \ es\<^sub>2[:]Ts\<^sub>2)" (*<*) -apply(induct_tac es\<^sub>1) - 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 fastforce -done +proof(induct es\<^sub>1) + case (Cons a list) + let ?lhs = "\Ts. (\U Us. Ts = U # Us \ P,E,h \ a : U \ + (\Ts\<^sub>1 Ts\<^sub>2. Us = Ts\<^sub>1 @ Ts\<^sub>2 \ P,E,h \ list [:] Ts\<^sub>1 \ P,E,h \ es\<^sub>2 [:] Ts\<^sub>2))" + let ?rhs = "\Ts. (\Ts\<^sub>1 Ts\<^sub>2. Ts = Ts\<^sub>1 @ Ts\<^sub>2 \ + (\U Us. Ts\<^sub>1 = U # Us \ P,E,h \ a : U \ P,E,h \ list [:] Us) \ P,E,h \ es\<^sub>2 [:] Ts\<^sub>2)" + { fix Ts assume "?lhs Ts" + then have "?rhs Ts" by (auto intro: Cons_eq_appendI) + } + moreover { + fix Ts assume "?rhs Ts" + then have "?lhs Ts" by fastforce + } + ultimately have "\Ts. ?lhs Ts = ?rhs Ts" by(rule iffI) + then show ?case by (clarsimp simp: Cons) +qed simp (*>*) lemma [iff]: "P,E,h \ Val v : T = (typeof\<^bsub>h\<^esub> v = Some T)" -(*<*) -apply(rule iffI) -apply (auto elim: WTrt.cases) -done -(*>*) +(*<*)proof(rule iffI) qed (auto elim: WTrt.cases)(*>*) lemma [iff]: "P,E,h \ Var v : T = (E v = Some T)" -(*<*) -apply(rule iffI) -apply (auto elim: WTrt.cases) -done -(*>*) +(*<*)proof(rule iffI) qed (auto elim: WTrt.cases)(*>*) lemma [iff]: "P,E,h \ e\<^sub>1;;e\<^sub>2 : T\<^sub>2 = (\T\<^sub>1. P,E,h \ e\<^sub>1:T\<^sub>1 \ P,E,h \ e\<^sub>2:T\<^sub>2)" -(*<*) -apply(rule iffI) -apply (auto elim: WTrt.cases) -done -(*>*) +(*<*)proof(rule iffI) qed (auto elim: WTrt.cases)(*>*) lemma [iff]: "P,E,h \ {V:T; e} : T' = (P,E(V\T),h \ e : T')" -(*<*) -apply(rule iffI) -apply (auto elim: WTrt.cases) -done -(*>*) +(*<*)proof(rule iffI) qed (auto elim: WTrt.cases)(*>*) + (*<*) inductive_cases WTrt_elim_cases[elim!]: "P,E,h \ v :=e : T" "P,E,h \ if (e) e\<^sub>1 else e\<^sub>2 : T" "P,E,h \ while(e) c : T" "P,E,h \ throw e : T" "P,E,h \ try e\<^sub>1 catch(C V) e\<^sub>2 : T" "P,E,h \ Cast D e : T" "P,E,h \ e\F{D} : T" "P,E,h \ e\F{D} := v : T" "P,E,h \ e\<^sub>1 \bop\ e\<^sub>2 : T" "P,E,h \ new C : T" "P,E,h \ e\M{D}(es) : T" (*>*) subsection\Some interesting lemmas\ lemma WTrts_Val[simp]: "\Ts. (P,E,h \ map Val vs [:] Ts) = (map (typeof\<^bsub>h\<^esub>) vs = map Some Ts)" (*<*) -apply(induct vs) - apply simp -apply(case_tac Ts) - apply simp -apply simp -done +proof(induct vs) + case (Cons a vs) + then show ?case by(case_tac Ts; simp) +qed simp (*>*) lemma WTrts_same_length: "\Ts. P,E,h \ es [:] Ts \ length es = length Ts" (*<*)by(induct es type:list)auto(*>*) lemma WTrt_env_mono: "P,E,h \ e : T \ (\E'. E \\<^sub>m E' \ P,E',h \ e : T)" and "P,E,h \ es [:] Ts \ (\E'. E \\<^sub>m E' \ P,E',h \ es [:] Ts)" (*<*) -apply(induct rule: WTrt_inducts) -apply(simp add: WTrtNew) -apply(fastforce simp: WTrtCast) -apply(fastforce simp: WTrtVal) -apply(simp add: WTrtVar map_le_def dom_def) -apply(fastforce simp add: WTrtBinOpEq) -apply(fastforce simp add: WTrtBinOpAdd) -apply(force simp: map_le_def) -apply(fastforce simp: WTrtFAcc) -apply(simp add: WTrtFAccNT) -apply(fastforce simp: WTrtFAss) -apply(fastforce simp: WTrtFAssNT) -apply(fastforce simp: WTrtCall) -apply(fastforce simp: WTrtCallNT) -apply(simp add: WTrtNil) -apply(simp add: WTrtCons) -apply(fastforce simp: map_le_def) -apply(fastforce) -apply(fastforce simp: WTrtSeq) -apply(fastforce simp: WTrtWhile) -apply(fastforce simp: WTrtThrow) -apply(auto simp: WTrtTry map_le_def dom_def) -done +proof(induct rule: WTrt_inducts) + case WTrtVar then show ?case by(simp add: map_le_def dom_def) +next + case WTrtLAss then show ?case by(force simp:map_le_def) +qed(fastforce intro: WTrt_WTrts.intros)+ (*>*) lemma WTrt_hext_mono: "P,E,h \ e : T \ h \ h' \ P,E,h' \ e : T" and WTrts_hext_mono: "P,E,h \ es [:] Ts \ h \ h' \ P,E,h' \ es [:] Ts" (*<*) -apply(induct rule: WTrt_inducts) -apply(simp add: WTrtNew) -apply(fastforce simp: WTrtCast) -apply(fastforce simp: WTrtVal dest:hext_typeof_mono) -apply(simp add: WTrtVar) -apply(fastforce simp add: WTrtBinOpEq) -apply(fastforce simp add: WTrtBinOpAdd) -apply(fastforce simp add: WTrtLAss) -apply(fast intro: WTrtFAcc) -apply(simp add: WTrtFAccNT) -apply(fastforce simp: WTrtFAss del:WTrt_WTrts.intros WTrt_elim_cases) -apply(fastforce simp: WTrtFAssNT) -apply(fastforce simp: WTrtCall) -apply(fastforce simp: WTrtCallNT) -apply(fastforce) -apply(fastforce simp add: WTrtSeq) -apply(fastforce simp add: WTrtCond) -apply(fastforce simp add: WTrtWhile) -apply(fastforce simp add: WTrtThrow) -apply(fastforce simp: WTrtTry) -apply(simp add: WTrtNil) -apply(simp add: WTrtCons) -done +proof(induct rule: WTrt_inducts) + case WTrtVal then show ?case by(simp add: hext_typeof_mono) +qed(fastforce intro: WTrt_WTrts.intros)+ (*>*) lemma WT_implies_WTrt: "P,E \ e :: T \ P,E,h \ e : T" and WTs_implies_WTrts: "P,E \ es [::] Ts \ P,E,h \ es [:] Ts" (*<*) -apply(induct rule: WT_WTs_inducts) -apply fast -apply (fast) -apply(fastforce dest:typeof_lit_typeof) -apply(simp) -apply(fastforce) -apply(fastforce) -apply(fastforce) -apply(fastforce simp: WTrtFAcc has_visible_field) -apply(fastforce simp: WTrtFAss dest: has_visible_field) -apply(fastforce simp: WTrtCall) -apply(fastforce) -apply(fastforce) -apply(fastforce simp: WTrtCond) -apply(fastforce) -apply(fastforce) -apply(fastforce) -apply(simp) -apply(simp) -done +proof(induct rule: WT_WTs_inducts) + case WTVal then show ?case by(fastforce dest: typeof_lit_typeof) +next + case WTFAcc + then show ?case by(fastforce simp: WTrtFAcc has_visible_field) +next + case WTFAss + then show ?case by(fastforce simp: WTrtFAss dest: has_visible_field) +qed(fastforce intro: WTrt_WTrts.intros)+ (*>*) end diff --git a/thys/JinjaDCI/J/Expr.thy b/thys/JinjaDCI/J/Expr.thy --- a/thys/JinjaDCI/J/Expr.thy +++ b/thys/JinjaDCI/J/Expr.thy @@ -1,572 +1,579 @@ (* Title: JinjaDCI/J/Expr.thy Author: Tobias Nipkow, Susannah Mansky Copyright 2003 Technische Universitaet Muenchen, 2019-20 UIUC Based on the Jinja theory J/Expr.thy by Tobias Nipkow *) section \ Expressions \ theory Expr imports "../Common/Exceptions" begin datatype bop = Eq | Add \ \names of binary operations\ datatype 'a exp = new cname \ \class instance creation\ | Cast cname "('a exp)" \ \type cast\ | Val val \ \value\ | BinOp "('a exp)" bop "('a exp)" ("_ \_\ _" [80,0,81] 80) \ \binary operation\ | Var 'a \ \local variable (incl. parameter)\ | LAss 'a "('a exp)" ("_:=_" [90,90]90) \ \local assignment\ | FAcc "('a exp)" vname cname ("_\_{_}" [10,90,99]90) \ \field access\ | SFAcc cname vname cname ("_\\<^sub>s_{_}" [10,90,99]90) \ \static field access\ | FAss "('a exp)" vname cname "('a exp)" ("_\_{_} := _" [10,90,99,90]90) \ \field assignment\ | SFAss cname vname cname "('a exp)" ("_\\<^sub>s_{_} := _" [10,90,99,90]90) \ \static field assignment\ | Call "('a exp)" mname "('a exp list)" ("_\_'(_')" [90,99,0] 90) \ \method call\ | SCall cname mname "('a exp list)" ("_\\<^sub>s_'(_')" [90,99,0] 90) \ \static method call\ | Block 'a ty "('a exp)" ("'{_:_; _}") | Seq "('a exp)" "('a exp)" ("_;;/ _" [61,60]60) | Cond "('a exp)" "('a exp)" "('a exp)" ("if '(_') _/ else _" [80,79,79]70) | While "('a exp)" "('a exp)" ("while '(_') _" [80,79]70) | throw "('a exp)" | TryCatch "('a exp)" cname 'a "('a exp)" ("try _/ catch'(_ _') _" [0,99,80,79] 70) | INIT cname "cname list" bool "('a exp)" ("INIT _ '(_,_') \ _" [60,60,60,60] 60) \ \internal initialization command: class, list of superclasses to initialize, preparation flag; command on hold\ | RI cname "('a exp)" "cname list" "('a exp)" ("RI '(_,_') ; _ \ _" [60,60,60,60] 60) \ \running of the initialization procedure for class with expression, classes still to initialize command on hold\ type_synonym expr = "vname exp" \ \Jinja expression\ type_synonym J_mb = "vname list \ expr" \ \Jinja method body: parameter names and expression\ type_synonym J_prog = "J_mb prog" \ \Jinja program\ type_synonym init_stack = "expr list \ bool" \ \Stack of expressions waiting on initialization in small step; indicator boolean True if current expression has been init checked\ text\The semantics of binary operators: \ fun binop :: "bop \ val \ val \ val option" where "binop(Eq,v\<^sub>1,v\<^sub>2) = Some(Bool (v\<^sub>1 = v\<^sub>2))" | "binop(Add,Intg i\<^sub>1,Intg i\<^sub>2) = Some(Intg(i\<^sub>1+i\<^sub>2))" | "binop(bop,v\<^sub>1,v\<^sub>2) = None" lemma [simp]: "(binop(Add,v\<^sub>1,v\<^sub>2) = Some v) = (\i\<^sub>1 i\<^sub>2. v\<^sub>1 = Intg i\<^sub>1 \ v\<^sub>2 = Intg i\<^sub>2 \ v = Intg(i\<^sub>1+i\<^sub>2))" -(*<*) -apply(cases v\<^sub>1) -apply auto -apply(cases v\<^sub>2) -apply auto -done -(*>*) +(*<*)by(cases v\<^sub>1; cases v\<^sub>2) auto(*>*) lemma map_Val_throw_eq: "map Val vs @ throw ex # es = map Val vs' @ throw ex' # es' \ ex = ex'" -apply(induct vs arbitrary: vs') - apply(case_tac vs', auto)+ -done +(*<*)by(induct vs arbitrary: vs'; case_tac vs') auto(*>*) lemma map_Val_nthrow_neq: "map Val vs = map Val vs' @ throw ex' # es' \ False" -apply(induct vs arbitrary: vs') - apply(case_tac vs', auto)+ -done +(*<*)by(induct vs arbitrary: vs'; case_tac vs') auto(*>*) lemma map_Val_eq: "map Val vs = map Val vs' \ vs = vs'" -apply(induct vs arbitrary: vs') - apply(case_tac vs', auto)+ -done +(*<*)by(induct vs arbitrary: vs'; case_tac vs') auto(*>*) lemma init_rhs_neq [simp]: "e \ INIT C (Cs,b) \ e" proof - have "size e \ size (INIT C (Cs,b) \ e)" by auto then show ?thesis by fastforce qed lemma init_rhs_neq' [simp]: "INIT C (Cs,b) \ e \ e" proof - have "size e \ size (INIT C (Cs,b) \ e)" by auto then show ?thesis by fastforce qed lemma ri_rhs_neq [simp]: "e \ RI(C,e');Cs \ e" proof - have "size e \ size (RI(C,e');Cs \ e)" by auto then show ?thesis by fastforce qed lemma ri_rhs_neq' [simp]: "RI(C,e');Cs \ e \ e" proof - have "size e \ size (RI(C,e');Cs \ e)" by auto then show ?thesis by fastforce qed subsection "Syntactic sugar" abbreviation (input) InitBlock:: "'a \ ty \ 'a exp \ 'a exp \ 'a exp" ("(1'{_:_ := _;/ _})") where "InitBlock V T e1 e2 == {V:T; V := e1;; e2}" abbreviation unit where "unit == Val Unit" abbreviation null where "null == Val Null" abbreviation "addr a == Val(Addr a)" abbreviation "true == Val(Bool True)" abbreviation "false == Val(Bool False)" abbreviation Throw :: "addr \ 'a exp" where "Throw a == throw(Val(Addr a))" abbreviation THROW :: "cname \ 'a exp" where "THROW xc == Throw(addr_of_sys_xcpt xc)" subsection\Free Variables\ primrec fv :: "expr \ vname set" and fvs :: "expr list \ vname set" where "fv(new C) = {}" | "fv(Cast C e) = fv e" | "fv(Val v) = {}" | "fv(e\<^sub>1 \bop\ e\<^sub>2) = fv e\<^sub>1 \ fv e\<^sub>2" | "fv(Var V) = {V}" | "fv(LAss V e) = {V} \ fv e" | "fv(e\F{D}) = fv e" | "fv(C\\<^sub>sF{D}) = {}" | "fv(e\<^sub>1\F{D}:=e\<^sub>2) = fv e\<^sub>1 \ fv e\<^sub>2" | "fv(C\\<^sub>sF{D}:=e\<^sub>2) = fv e\<^sub>2" | "fv(e\M(es)) = fv e \ fvs es" | "fv(C\\<^sub>sM(es)) = fvs es" | "fv({V:T; e}) = fv e - {V}" | "fv(e\<^sub>1;;e\<^sub>2) = fv e\<^sub>1 \ fv e\<^sub>2" | "fv(if (b) e\<^sub>1 else e\<^sub>2) = fv b \ fv e\<^sub>1 \ fv e\<^sub>2" | "fv(while (b) e) = fv b \ fv e" | "fv(throw e) = fv e" | "fv(try e\<^sub>1 catch(C V) e\<^sub>2) = fv e\<^sub>1 \ (fv e\<^sub>2 - {V})" | "fv(INIT C (Cs,b) \ e) = fv e" | "fv(RI (C,e);Cs \ e') = fv e \ fv e'" | "fvs([]) = {}" | "fvs(e#es) = fv e \ fvs es" lemma [simp]: "fvs(es\<^sub>1 @ es\<^sub>2) = fvs es\<^sub>1 \ fvs es\<^sub>2" (*<*)by (induct es\<^sub>1 type:list) auto(*>*) lemma [simp]: "fvs(map Val vs) = {}" (*<*)by (induct vs) auto(*>*) subsection\Accessing expression constructor arguments\ fun val_of :: "'a exp \ val option" where "val_of (Val v) = Some v" | "val_of _ = None" lemma val_of_spec: "val_of e = Some v \ e = Val v" proof(cases e) qed(auto) fun lass_val_of :: "'a exp \ ('a \ val) option" where "lass_val_of (V:=Val v) = Some (V, v)" | "lass_val_of _ = None" lemma lass_val_of_spec: assumes "lass_val_of e = \a\" shows "e = (fst a:=Val (snd a))" using assms proof(cases e) case (LAss V e') then show ?thesis using assms proof(cases e')qed(auto) qed(auto) fun map_vals_of :: "'a exp list \ val list option" where "map_vals_of (e#es) = (case val_of e of Some v \ (case map_vals_of es of Some vs \ Some (v#vs) | _ \ None) | _ \ None)" | "map_vals_of [] = Some []" lemma map_vals_of_spec: "map_vals_of es = Some vs \ es = map Val vs" proof(induct es arbitrary: vs) qed(auto simp: val_of_spec) lemma map_vals_of_Vals[simp]: "map_vals_of (map Val vs) = \vs\" by(induct vs, auto) lemma map_vals_of_throw[simp]: "map_vals_of (map Val vs @ throw e # es') = None" by(induct vs, auto) fun bool_of :: "'a exp \ bool option" where "bool_of true = Some True" | "bool_of false = Some False" | "bool_of _ = None" lemma bool_of_specT: assumes "bool_of e = Some True" shows "e = true" proof - have "bool_of e = Some True" by fact then show ?thesis proof(cases e) case (Val x3) with assms show ?thesis proof(cases x3) case (Bool x) with assms Val show ?thesis proof(cases x)qed(auto) qed(simp_all) qed(auto) qed lemma bool_of_specF: assumes "bool_of e = Some False" shows "e = false" proof - have "bool_of e = Some False" by fact then show ?thesis proof(cases e) case (Val x3) with assms show ?thesis proof(cases x3) case (Bool x) with assms Val show ?thesis proof(cases x)qed(auto) qed(simp_all) qed(auto) qed fun throw_of :: "'a exp \ 'a exp option" where "throw_of (throw e') = Some e'" | "throw_of _ = None" lemma throw_of_spec: "throw_of e = Some e' \ e = throw e'" proof(cases e) qed(auto) fun init_exp_of :: "'a exp \ 'a exp option" where "init_exp_of (INIT C (Cs,b) \ e) = Some e" | "init_exp_of (RI(C,e');Cs \ e) = Some e" | "init_exp_of _ = None" lemma init_exp_of_neq [simp]: "init_exp_of e = \e'\ \ e' \ e" by(cases e, auto) lemma init_exp_of_neq'[simp]: "init_exp_of e = \e'\ \ e \ e'" by(cases e, auto) subsection\Class initialization\ text \ This section defines a few functions that return information about an expression's current initialization status. \ \ \ True if expression contains @{text INIT}, @{text RI}, or a call to a static method @{term clinit} \ primrec sub_RI :: "'a exp \ bool" and sub_RIs :: "'a exp list \ bool" where "sub_RI(new C) = False" | "sub_RI(Cast C e) = sub_RI e" | "sub_RI(Val v) = False" | "sub_RI(e\<^sub>1 \bop\ e\<^sub>2) = (sub_RI e\<^sub>1 \ sub_RI e\<^sub>2)" | "sub_RI(Var V) = False" | "sub_RI(LAss V e) = sub_RI e" | "sub_RI(e\F{D}) = sub_RI e" | "sub_RI(C\\<^sub>sF{D}) = False" | "sub_RI(e\<^sub>1\F{D}:=e\<^sub>2) = (sub_RI e\<^sub>1 \ sub_RI e\<^sub>2)" | "sub_RI(C\\<^sub>sF{D}:=e\<^sub>2) = sub_RI e\<^sub>2" | "sub_RI(e\M(es)) = (sub_RI e \ sub_RIs es)" | "sub_RI(C\\<^sub>sM(es)) = (M = clinit \ sub_RIs es)" | "sub_RI({V:T; e}) = sub_RI e" | "sub_RI(e\<^sub>1;;e\<^sub>2) = (sub_RI e\<^sub>1 \ sub_RI e\<^sub>2)" | "sub_RI(if (b) e\<^sub>1 else e\<^sub>2) = (sub_RI b \ sub_RI e\<^sub>1 \ sub_RI e\<^sub>2)" | "sub_RI(while (b) e) = (sub_RI b \ sub_RI e)" | "sub_RI(throw e) = sub_RI e" | "sub_RI(try e\<^sub>1 catch(C V) e\<^sub>2) = (sub_RI e\<^sub>1 \ sub_RI e\<^sub>2)" | "sub_RI(INIT C (Cs,b) \ e) = True" | "sub_RI(RI (C,e);Cs \ e') = True" | "sub_RIs([]) = False" | "sub_RIs(e#es) = (sub_RI e \ sub_RIs es)" lemmas sub_RI_sub_RIs_induct = sub_RI.induct sub_RIs.induct lemma nsub_RIs_def[simp]: "\sub_RIs es \ \e \ set es. \sub_RI e" by(induct es, auto) lemma sub_RI_base: "e = INIT C (Cs, b) \ e' \ e = RI(C,e\<^sub>0);Cs \ e' \ sub_RI e" by(cases e, auto) lemma nsub_RI_Vals[simp]: "\sub_RIs (map Val vs)" by(induct vs, auto) lemma lass_val_of_nsub_RI: "lass_val_of e = \a\ \ \sub_RI e" by(drule lass_val_of_spec, simp) \ \ is not currently initializing class @{text C'} (point past checking flag) \ primrec not_init :: "cname \ 'a exp \ bool" and not_inits :: "cname \ 'a exp list \ bool" where "not_init C' (new C) = True" | "not_init C' (Cast C e) = not_init C' e" | "not_init C' (Val v) = True" | "not_init C' (e\<^sub>1 \bop\ e\<^sub>2) = (not_init C' e\<^sub>1 \ not_init C' e\<^sub>2)" | "not_init C' (Var V) = True" | "not_init C' (LAss V e) = not_init C' e" | "not_init C' (e\F{D}) = not_init C' e" | "not_init C' (C\\<^sub>sF{D}) = True" | "not_init C' (e\<^sub>1\F{D}:=e\<^sub>2) = (not_init C' e\<^sub>1 \ not_init C' e\<^sub>2)" | "not_init C' (C\\<^sub>sF{D}:=e\<^sub>2) = not_init C' e\<^sub>2" | "not_init C' (e\M(es)) = (not_init C' e \ not_inits C' es)" | "not_init C' (C\\<^sub>sM(es)) = not_inits C' es" | "not_init C' ({V:T; e}) = not_init C' e" | "not_init C' (e\<^sub>1;;e\<^sub>2) = (not_init C' e\<^sub>1 \ not_init C' e\<^sub>2)" | "not_init C' (if (b) e\<^sub>1 else e\<^sub>2) = (not_init C' b \ not_init C' e\<^sub>1 \ not_init C' e\<^sub>2)" | "not_init C' (while (b) e) = (not_init C' b \ not_init C' e)" | "not_init C' (throw e) = not_init C' e" | "not_init C' (try e\<^sub>1 catch(C V) e\<^sub>2) = (not_init C' e\<^sub>1 \ not_init C' e\<^sub>2)" | "not_init C' (INIT C (Cs,b) \ e) = ((b \ Cs = Nil \ C' \ hd Cs) \ C' \ set(tl Cs) \ not_init C' e)" | "not_init C' (RI (C,e);Cs \ e') = (C' \ set (C#Cs) \ not_init C' e \ not_init C' e')" | "not_inits C' ([]) = True" | "not_inits C' (e#es) = (not_init C' e \ not_inits C' es)" lemma not_inits_def'[simp]: "not_inits C es \ \e \ set es. not_init C e" by(induct es, auto) lemma nsub_RIs_not_inits_aux: "\e \ set es. \sub_RI e \ not_init C e \ \sub_RIs es \ not_inits C es" by(induct es, auto) lemma nsub_RI_not_init: "\sub_RI e \ not_init C e" proof(induct e) qed(auto intro: nsub_RIs_not_inits_aux) lemma nsub_RIs_not_inits: "\sub_RIs es \ not_inits C es" -apply(rule nsub_RIs_not_inits_aux) - apply(simp_all add: nsub_RI_not_init) -done +by(rule nsub_RIs_not_inits_aux) (simp_all add: nsub_RI_not_init) subsection\Subexpressions\ \ \ all strictly smaller subexpressions; does not include self \ primrec subexp :: "'a exp \ 'a exp set" and subexps :: "'a exp list \ 'a exp set" where "subexp(new C) = {}" | "subexp(Cast C e) = {e} \ subexp e" | "subexp(Val v) = {}" | "subexp(e\<^sub>1 \bop\ e\<^sub>2) = {e\<^sub>1, e\<^sub>2} \ subexp e\<^sub>1 \ subexp e\<^sub>2" | "subexp(Var V) = {}" | "subexp(LAss V e) = {e} \ subexp e" | "subexp(e\F{D}) = {e} \ subexp e" | "subexp(C\\<^sub>sF{D}) = {}" | "subexp(e\<^sub>1\F{D}:=e\<^sub>2) = {e\<^sub>1, e\<^sub>2} \ subexp e\<^sub>1 \ subexp e\<^sub>2" | "subexp(C\\<^sub>sF{D}:=e\<^sub>2) = {e\<^sub>2} \subexp e\<^sub>2" | "subexp(e\M(es)) = {e} \ set es \ subexp e \ subexps es" | "subexp(C\\<^sub>sM(es)) = set es \ subexps es" | "subexp({V:T; e}) = {e} \ subexp e" | "subexp(e\<^sub>1;;e\<^sub>2) = {e\<^sub>1, e\<^sub>2} \ subexp e\<^sub>1 \ subexp e\<^sub>2" | "subexp(if (b) e\<^sub>1 else e\<^sub>2) = {b, e\<^sub>1, e\<^sub>2} \ subexp b \ subexp e\<^sub>1 \ subexp e\<^sub>2" | "subexp(while (b) e) = {b, e} \ subexp b \ subexp e" | "subexp(throw e) = {e} \ subexp e" | "subexp(try e\<^sub>1 catch(C V) e\<^sub>2) = {e\<^sub>1, e\<^sub>2} \ subexp e\<^sub>1 \ subexp e\<^sub>2" | "subexp(INIT C (Cs,b) \ e) = {e} \ subexp e" | "subexp(RI (C,e);Cs \ e') = {e, e'} \ subexp e \ subexp e'" | "subexps([]) = {}" | "subexps(e#es) = {e} \ subexp e \ subexps es" lemmas subexp_subexps_induct = subexp.induct subexps.induct abbreviation subexp_of :: "'a exp \ 'a exp \ bool" where "subexp_of e e' \ e \ subexp e'" lemma subexp_size_le: "(e' \ subexp e \ size e' < size e) \ (e' \ subexps es \ size e' < size_list size es)" proof(induct rule: subexp_subexps.induct) case Call:11 then show ?case using not_less_eq size_list_estimation by fastforce next case SCall:12 then show ?case using not_less_eq size_list_estimation by fastforce qed(auto) lemma subexps_def2: "subexps es = set es \ (\e \ set es. subexp e)" by(induct es, auto) \ \ strong induction \ lemma shows subexp_induct[consumes 1]: "(\e. subexp e = {} \ R e) \ (\e. (\e'. e' \ subexp e \ R e') \ R e) \ (\es. (\e'. e' \ subexps es \ R e') \ Rs es) \ (\e'. e' \ subexp e \ R e') \ R e" and subexps_induct[consumes 1]: "(\es. subexps es = {} \ Rs es) \ (\e. (\e'. e' \ subexp e \ R e') \ R e) \ (\es. (\e'. e' \ subexps es \ R e') \ Rs es) \ (\e'. e' \ subexps es \ R e') \ Rs es" proof(induct rule: subexp_subexps_induct) case (Cast x1 x2) then have "(\e'. subexp_of e' x2 \ R e') \ R x2" by fast then have "(\e'. subexp_of e' (Cast x1 x2) \ R e')" by auto then show ?case using Cast.prems(2) by fast next case (BinOp x1 x2 x3) then have "(\e'. subexp_of e' x1 \ R e') \ R x1" and "(\e'. subexp_of e' x3 \ R e') \ R x3" by fast+ then have "(\e'. subexp_of e' (x1 \x2\ x3) \ R e')" by auto then show ?case using BinOp.prems(2) by fast next case (LAss x1 x2) then have "(\e'. subexp_of e' x2 \ R e') \ R x2" by fast then have "(\e'. subexp_of e' (LAss x1 x2) \ R e')" by auto then show ?case using LAss.prems(2) by fast next case (FAcc x1 x2 x3) then have "(\e'. subexp_of e' x1 \ R e') \ R x1" by fast then have "(\e'. subexp_of e' (x1\x2{x3}) \ R e')" by auto then show ?case using FAcc.prems(2) by fast next case (FAss x1 x2 x3 x4) then have "(\e'. subexp_of e' x1 \ R e') \ R x1" and "(\e'. subexp_of e' x4 \ R e') \ R x4" by fast+ then have "(\e'. subexp_of e' (x1\x2{x3} := x4) \ R e')" by auto then show ?case using FAss.prems(2) by fast next case (SFAss x1 x2 x3 x4) then have "(\e'. subexp_of e' x4 \ R e') \ R x4" by fast then have "(\e'. subexp_of e' (x1\\<^sub>sx2{x3} := x4) \ R e')" by auto then show ?case using SFAss.prems(2) by fast next case (Call x1 x2 x3) then have "(\e'. subexp_of e' x1 \ R e') \ R x1" and "(\e'. e' \ subexps x3 \ R e') \ Rs x3" by fast+ then have "(\e'. subexp_of e' (x1\x2(x3)) \ R e')" using subexps_def2 by auto then show ?case using Call.prems(2) by fast next case (SCall x1 x2 x3) then have "(\e'. e' \ subexps x3 \ R e') \ Rs x3" by fast then have "(\e'. subexp_of e' (x1\\<^sub>sx2(x3)) \ R e')" using subexps_def2 by auto then show ?case using SCall.prems(2) by fast next case (Block x1 x2 x3) then have "(\e'. subexp_of e' x3 \ R e') \ R x3" by fast then have "(\e'. subexp_of e' {x1:x2; x3} \ R e')" by auto then show ?case using Block.prems(2) by fast next case (Seq x1 x2) then have "(\e'. subexp_of e' x1 \ R e') \ R x1" and "(\e'. subexp_of e' x2 \ R e') \ R x2" by fast+ then have "(\e'. subexp_of e' (x1;; x2) \ R e')" by auto then show ?case using Seq.prems(2) by fast next case (Cond x1 x2 x3) then have "(\e'. subexp_of e' x1 \ R e') \ R x1" and "(\e'. subexp_of e' x2 \ R e') \ R x2" and "(\e'. subexp_of e' x3 \ R e') \ R x3" by fast+ then have "(\e'. subexp_of e' (if (x1) x2 else x3) \ R e')" by auto then show ?case using Cond.prems(2) by fast next case (While x1 x2) then have "(\e'. subexp_of e' x1 \ R e') \ R x1" and "(\e'. subexp_of e' x2 \ R e') \ R x2" by fast+ then have "(\e'. subexp_of e' (while (x1) x2) \ R e')" by auto then show ?case using While.prems(2) by fast next case (throw x) then have "(\e'. subexp_of e' x \ R e') \ R x" by fast then have "(\e'. subexp_of e' (throw x) \ R e')" by auto then show ?case using throw.prems(2) by fast next case (TryCatch x1 x2 x3 x4) then have "(\e'. subexp_of e' x1 \ R e') \ R x1" and "(\e'. subexp_of e' x4 \ R e') \ R x4" by fast+ then have "(\e'. subexp_of e' (try x1 catch(x2 x3) x4) \ R e')" by auto then show ?case using TryCatch.prems(2) by fast next case (INIT x1 x2 x3 x4) then have "(\e'. subexp_of e' x4 \ R e') \ R x4" by fast then have "(\e'. subexp_of e' (INIT x1 (x2,x3) \ x4) \ R e')" by auto then show ?case using INIT.prems(2) by fast next case (RI x1 x2 x3 x4) then have "(\e'. subexp_of e' x2 \ R e') \ R x2" and "(\e'. subexp_of e' x4 \ R e') \ R x4" by fast+ then have "(\e'. subexp_of e' (RI (x1,x2) ; x3 \ x4) \ R e')" by auto then show ?case using RI.prems(2) by fast next case (Cons_exp x1 x2) then have "(\e'. subexp_of e' x1 \ R e') \ R x1" and "(\e'. e' \ subexps x2 \ R e') \ Rs x2" by fast+ then have "(\e'. e' \ subexps (x1 # x2) \ R e')" using subexps_def2 by auto then show ?case using Cons_exp.prems(3) by fast qed(auto) subsection"Final expressions" (* these definitions and most of the lemmas were in BigStep.thy in the original Jinja *) definition final :: "'a exp \ bool" where "final e \ (\v. e = Val v) \ (\a. e = Throw a)" definition finals:: "'a exp list \ bool" where "finals es \ (\vs. es = map Val vs) \ (\vs a es'. es = map Val vs @ Throw a # es')" lemma [simp]: "final(Val v)" (*<*)by(simp add:final_def)(*>*) lemma [simp]: "final(throw e) = (\a. e = addr a)" (*<*)by(simp add:final_def)(*>*) lemma finalE: "\ final e; \v. e = Val v \ R; \a. e = Throw a \ R \ \ R" (*<*)by(auto simp:final_def)(*>*) lemma final_fv[iff]: "final e \ fv e = {}" by (auto simp: final_def) lemma finalsE: "\ finals es; \vs. es = map Val vs \ R; \vs a es'. es = map Val vs @ Throw a # es' \ R \ \ R" (*<*)by(auto simp:finals_def)(*>*) lemma [iff]: "finals []" (*<*)by(simp add:finals_def)(*>*) lemma [iff]: "finals (Val v # es) = finals es" (*<*) -apply(clarsimp simp add: finals_def) -apply(rule iffI) - apply(erule disjE) - apply simp - apply(rule disjI2) - apply clarsimp - apply(case_tac vs) - apply simp - apply fastforce -apply(erule disjE) - apply clarsimp -apply(rule disjI2) -apply clarsimp -apply(rule_tac x = "v#vs" in exI) -apply simp -done +proof(rule iffI) + assume "finals (Val v # es)" + moreover { + fix vs a es' + assume "\vs a es'. es \ map Val vs @ Throw a # es'" + and "Val v # es = map Val vs @ Throw a # es'" + then have "\vs. es = map Val vs" by(case_tac vs; simp) + } + ultimately show "finals es" by(clarsimp simp add: finals_def) +next + assume "finals es" + moreover { + fix vs a es' + assume "es = map Val vs @ Throw a # es'" + then have "\vs' a' es''. Val v # map Val vs @ Throw a # es' = map Val vs' @ Throw a' # es''" + by(rule_tac x = "v#vs" in exI) simp + } + ultimately show "finals (Val v # es)" by(clarsimp simp add: finals_def) +qed (*>*) lemma finals_app_map[iff]: "finals (map Val vs @ es) = finals es" (*<*)by(induct_tac vs, auto)(*>*) lemma [iff]: "finals (map Val vs)" (*<*)using finals_app_map[of vs "[]"]by(simp)(*>*) lemma [iff]: "finals (throw e # es) = (\a. e = addr a)" (*<*) -apply(simp add:finals_def) -apply(rule iffI) - apply clarsimp - apply(case_tac vs) - apply simp - apply fastforce -apply clarsimp -apply(rule_tac x = "[]" in exI) -apply simp -done +proof(rule iffI) + assume "finals (throw e # es)" + moreover { + fix vs a es' + assume "throw e # es = map Val vs @ Throw a # es'" + then have "\a. e = addr a" by(case_tac vs; simp) + } + ultimately show "\a. e = addr a" by(clarsimp simp add: finals_def) +next + assume "\a. e = addr a" + moreover { + fix vs a es' + assume "e = addr a" + then have "\vs aa es'. Throw a # es = map Val vs @ Throw aa # es'" + by(rule_tac x = "[]" in exI) simp + } + ultimately show "finals (throw e # es)" by(clarsimp simp add: finals_def) +qed (*>*) lemma not_finals_ConsI: "\ final e \ \ finals(e#es)" - (*<*) -apply(clarsimp simp add:finals_def final_def) -apply(case_tac vs) -apply auto -done +(*<*) +proof - + assume "\ final e" + moreover { + fix vs a es' + assume "\v. e \ Val v" and "\a. e \ Throw a" + then have "e # es \ map Val vs @ Throw a # es'" by(case_tac vs; simp) + } + ultimately show ?thesis by(clarsimp simp add:finals_def final_def) +qed (*>*) lemma not_finals_ConsI2: "e = Val v \ \ finals es \ \ finals(e#es)" - (*<*) -apply(clarsimp simp add:finals_def final_def) -apply(case_tac vs) -apply auto -done +(*<*) +proof - + assume [simp]: "e = Val v" and "\ finals es" + moreover { + fix vs a es' + assume "\vs. es \ map Val vs" and "\vs a es'. es \ map Val vs @ Throw a # es'" + then have "e # es \ map Val vs @ Throw a # es'" by(case_tac vs; simp) + } + ultimately show ?thesis by(clarsimp simp add:finals_def final_def) +qed (*>*) end diff --git a/thys/JinjaDCI/J/SmallStep.thy b/thys/JinjaDCI/J/SmallStep.thy --- a/thys/JinjaDCI/J/SmallStep.thy +++ b/thys/JinjaDCI/J/SmallStep.thy @@ -1,634 +1,646 @@ (* Title: JinjaDCI/J/SmallStep.thy Author: Tobias Nipkow, Susannah Mansky Copyright 2003 Technische Universitaet Muenchen, 2019-20 UIUC Based on the Jinja theory J/SmallStep.thy by Tobias Nipkow *) section \ Small Step Semantics \ theory SmallStep imports Expr State WWellForm begin fun blocks :: "vname list * ty list * val list * expr \ expr" where "blocks(V#Vs, T#Ts, v#vs, e) = {V:T := Val v; blocks(Vs,Ts,vs,e)}" |"blocks([],[],[],e) = e" lemmas blocks_induct = blocks.induct[split_format (complete)] lemma [simp]: "\ size vs = size Vs; size Ts = size Vs \ \ fv(blocks(Vs,Ts,vs,e)) = fv e - set Vs" (*<*) by (induct rule:blocks_induct) auto (*>*) lemma sub_RI_blocks_body[iff]: "length vs = length pns \ length Ts = length pns \ sub_RI (blocks (pns, Ts, vs, body)) \ sub_RI body" proof(induct pns arbitrary: Ts vs) case Nil then show ?case by simp next case Cons then show ?case by(cases vs; cases Ts) auto qed definition assigned :: "'a \ 'a exp \ bool" where "assigned V e \ \v e'. e = (V := Val v;; e')" \ \ expression is okay to go the right side of @{text INIT} or @{text "RI \"} or to have indicator Boolean be True (in latter case, given that class is also verified initialized) \ fun icheck :: "'m prog \ cname \ 'a exp \ bool" where "icheck P C' (new C) = (C' = C)" | "icheck P D' (C\\<^sub>sF{D}) = ((D' = D) \ (\T. P \ C has F,Static:T in D))" | "icheck P D' (C\\<^sub>sF{D}:=(Val v)) = ((D' = D) \ (\T. P \ C has F,Static:T in D))" | "icheck P D (C\\<^sub>sM(es)) = ((\vs. es = map Val vs) \ (\Ts T m. P \ C sees M,Static:Ts\T = m in D))" | "icheck P _ _ = False" lemma nicheck_SFAss_nonVal: "val_of e\<^sub>2 = None \ \icheck P C' (C\\<^sub>sF{D} := (e\<^sub>2::'a exp))" by(rule notI, cases e\<^sub>2, auto) inductive_set red :: "J_prog \ ((expr \ state \ bool) \ (expr \ state \ bool)) set" and reds :: "J_prog \ ((expr list \ state \ bool) \ (expr list \ state \ bool)) set" and red' :: "J_prog \ expr \ state \ bool \ expr \ state \ bool \ bool" ("_ \ ((1\_,/_,/_\) \/ (1\_,/_,/_\))" [51,0,0,0,0,0,0] 81) and reds' :: "J_prog \ expr list \ state \ bool \ expr list \ state \ bool \ bool" ("_ \ ((1\_,/_,/_\) [\]/ (1\_,/_,/_\))" [51,0,0,0,0,0,0] 81) for P :: J_prog where "P \ \e,s,b\ \ \e',s',b'\ \ ((e,s,b), e',s',b') \ red P" | "P \ \es,s,b\ [\] \es',s',b'\ \ ((es,s,b), es',s',b') \ reds P" | RedNew: "\ new_Addr h = Some a; P \ C has_fields FDTs; h' = h(a\blank P C) \ \ P \ \new C, (h,l,sh), True\ \ \addr a, (h',l,sh), False\" | RedNewFail: "\ new_Addr h = None; is_class P C \ \ P \ \new C, (h,l,sh), True\ \ \THROW OutOfMemory, (h,l,sh), False\" | NewInitDoneRed: "sh C = Some (sfs, Done) \ P \ \new C, (h,l,sh), False\ \ \new C, (h,l,sh), True\" | NewInitRed: "\ \sfs. sh C = Some (sfs, Done); is_class P C \ \ P \ \new C,(h,l,sh),False\ \ \INIT C ([C],False) \ new C,(h,l,sh),False\" | CastRed: "P \ \e,s,b\ \ \e',s',b'\ \ P \ \Cast C e, s, b\ \ \Cast C e', s', b'\" | RedCastNull: "P \ \Cast C null, s, b\ \ \null,s,b\" | RedCast: "\ h a = Some(D,fs); P \ D \\<^sup>* C \ \ P \ \Cast C (addr a), (h,l,sh), b\ \ \addr a, (h,l,sh), b\" | RedCastFail: "\ h a = Some(D,fs); \ P \ D \\<^sup>* C \ \ P \ \Cast C (addr a), (h,l,sh), b\ \ \THROW ClassCast, (h,l,sh), b\" | BinOpRed1: "P \ \e,s,b\ \ \e',s',b'\ \ P \ \e \bop\ e\<^sub>2, s, b\ \ \e' \bop\ e\<^sub>2, s', b'\" | BinOpRed2: "P \ \e,s,b\ \ \e',s',b'\ \ P \ \(Val v\<^sub>1) \bop\ e, s, b\ \ \(Val v\<^sub>1) \bop\ e', s', b'\" | RedBinOp: "binop(bop,v\<^sub>1,v\<^sub>2) = Some v \ P \ \(Val v\<^sub>1) \bop\ (Val v\<^sub>2), s, b\ \ \Val v,s,b\" | RedVar: "l V = Some v \ P \ \Var V,(h,l,sh),b\ \ \Val v,(h,l,sh),b\" | LAssRed: "P \ \e,s,b\ \ \e',s',b'\ \ P \ \V:=e,s,b\ \ \V:=e',s',b'\" | RedLAss: "P \ \V:=(Val v), (h,l,sh), b\ \ \unit, (h,l(V\v),sh), b\" | FAccRed: "P \ \e,s,b\ \ \e',s',b'\ \ P \ \e\F{D}, s, b\ \ \e'\F{D}, s', b'\" | RedFAcc: "\ h a = Some(C,fs); fs(F,D) = Some v; P \ C has F,NonStatic:t in D \ \ P \ \(addr a)\F{D}, (h,l,sh), b\ \ \Val v,(h,l,sh),b\" | RedFAccNull: "P \ \null\F{D}, s, b\ \ \THROW NullPointer, s, b\" | RedFAccNone: "\ h a = Some(C,fs); \(\b t. P \ C has F,b:t in D) \ \ P \ \(addr a)\F{D},(h,l,sh),b\ \ \THROW NoSuchFieldError,(h,l,sh),b\" | RedFAccStatic: "\ h a = Some(C,fs); P \ C has F,Static:t in D \ \ P \ \(addr a)\F{D},(h,l,sh),b\ \ \THROW IncompatibleClassChangeError,(h,l,sh),b\" | RedSFAcc: "\ P \ C has F,Static:t in D; sh D = Some (sfs,i); sfs F = Some v \ \ P \ \C\\<^sub>sF{D},(h,l,sh),True\ \ \Val v,(h,l,sh),False\" | SFAccInitDoneRed: "\ P \ C has F,Static:t in D; sh D = Some (sfs,Done) \ \ P \ \C\\<^sub>sF{D},(h,l,sh),False\ \ \C\\<^sub>sF{D},(h,l,sh),True\" | SFAccInitRed: "\ P \ C has F,Static:t in D; \sfs. sh D = Some (sfs,Done) \ \ P \ \C\\<^sub>sF{D},(h,l,sh),False\ \ \INIT D ([D],False) \ C\\<^sub>sF{D},(h,l,sh),False\" | RedSFAccNone: "\(\b t. P \ C has F,b:t in D) \ P \ \C\\<^sub>sF{D},(h,l,sh),b\ \ \THROW NoSuchFieldError,(h,l,sh),False\" | RedSFAccNonStatic: "P \ C has F,NonStatic:t in D \ P \ \C\\<^sub>sF{D},(h,l,sh),b\ \ \THROW IncompatibleClassChangeError,(h,l,sh),False\" | FAssRed1: "P \ \e,s,b\ \ \e',s',b'\ \ P \ \e\F{D}:=e\<^sub>2, s, b\ \ \e'\F{D}:=e\<^sub>2, s', b'\" | FAssRed2: "P \ \e,s,b\ \ \e',s',b'\ \ P \ \Val v\F{D}:=e, s, b\ \ \Val v\F{D}:=e', s', b'\" | RedFAss: "\ P \ C has F,NonStatic:t in D; h a = Some(C,fs) \ \ P \ \(addr a)\F{D}:=(Val v), (h,l,sh), b\ \ \unit, (h(a \ (C,fs((F,D) \ v))),l,sh), b\" | RedFAssNull: "P \ \null\F{D}:=Val v, s, b\ \ \THROW NullPointer, s, b\" | RedFAssNone: "\ h a = Some(C,fs); \(\b t. P \ C has F,b:t in D) \ \ P \ \(addr a)\F{D}:=(Val v),(h,l,sh),b\ \ \THROW NoSuchFieldError,(h,l,sh),b\" | RedFAssStatic: "\ h a = Some(C,fs); P \ C has F,Static:t in D \ \ P \ \(addr a)\F{D}:=(Val v),(h,l,sh),b\ \ \THROW IncompatibleClassChangeError,(h,l,sh),b\" | SFAssRed: "P \ \e,s,b\ \ \e',s',b'\ \ P \ \C\\<^sub>sF{D}:=e, s, b\ \ \C\\<^sub>sF{D}:=e', s', b'\" | RedSFAss: "\ P \ C has F,Static:t in D; sh D = Some(sfs,i); sfs' = sfs(F\v); sh' = sh(D\(sfs',i)) \ \ P \ \C\\<^sub>sF{D}:=(Val v),(h,l,sh),True\ \ \unit,(h,l,sh'),False\" | SFAssInitDoneRed: "\ P \ C has F,Static:t in D; sh D = Some(sfs,Done) \ \ P \ \C\\<^sub>sF{D}:=(Val v),(h,l,sh),False\ \ \C\\<^sub>sF{D}:=(Val v),(h,l,sh),True\" | SFAssInitRed: "\ P \ C has F,Static:t in D; \sfs. sh D = Some(sfs,Done) \ \ P \ \C\\<^sub>sF{D}:=(Val v),(h,l,sh),False\ \ \INIT D ([D],False)\ C\\<^sub>sF{D}:=(Val v),(h,l,sh),False\" | RedSFAssNone: "\(\b t. P \ C has F,b:t in D) \ P \ \C\\<^sub>sF{D}:=(Val v),s,b\ \ \THROW NoSuchFieldError,s,False\" | RedSFAssNonStatic: "P \ C has F,NonStatic:t in D \ P \ \C\\<^sub>sF{D}:=(Val v),s,b\ \ \THROW IncompatibleClassChangeError,s,False\" | CallObj: "P \ \e,s,b\ \ \e',s',b'\ \ P \ \e\M(es),s,b\ \ \e'\M(es),s',b'\" | CallParams: "P \ \es,s,b\ [\] \es',s',b'\ \ P \ \(Val v)\M(es),s,b\ \ \(Val v)\M(es'),s',b'\" | RedCall: "\ h a = Some(C,fs); P \ C sees M,NonStatic:Ts\T = (pns,body) in D; size vs = size pns; size Ts = size pns \ \ P \ \(addr a)\M(map Val vs), (h,l,sh), b\ \ \blocks(this#pns, Class D#Ts, Addr a#vs, body), (h,l,sh), b\" | RedCallNull: "P \ \null\M(map Val vs),s,b\ \ \THROW NullPointer,s,b\" | RedCallNone: "\ h a = Some(C,fs); \(\b Ts T m D. P \ C sees M,b:Ts\T = m in D) \ \ P \ \(addr a)\M(map Val vs),(h,l,sh),b\ \ \THROW NoSuchMethodError,(h,l,sh),b\" | RedCallStatic: "\ h a = Some(C,fs); P \ C sees M,Static:Ts\T = m in D \ \ P \ \(addr a)\M(map Val vs),(h,l,sh),b\ \ \THROW IncompatibleClassChangeError,(h,l,sh),b\" | SCallParams: "P \ \es,s,b\ [\] \es',s',b'\ \ P \ \C\\<^sub>sM(es),s,b\ \ \C\\<^sub>sM(es'),s',b'\" | RedSCall: "\ P \ C sees M,Static:Ts\T = (pns,body) in D; length vs = length pns; size Ts = size pns \ \ P \ \C\\<^sub>sM(map Val vs),s,True\ \ \blocks(pns, Ts, vs, body), s, False\" | SCallInitDoneRed: "\ P \ C sees M,Static:Ts\T = (pns,body) in D; sh D = Some(sfs,Done) \ (M = clinit \ sh D = Some(sfs,Processing)) \ \ P \ \C\\<^sub>sM(map Val vs),(h,l,sh), False\ \ \C\\<^sub>sM(map Val vs),(h,l,sh), True\" | SCallInitRed: "\ P \ C sees M,Static:Ts\T = (pns,body) in D; \sfs. sh D = Some(sfs,Done); M \ clinit \ \ P \ \C\\<^sub>sM(map Val vs),(h,l,sh), False\ \ \INIT D ([D],False) \ C\\<^sub>sM(map Val vs),(h,l,sh),False\" | RedSCallNone: "\ \(\b Ts T m D. P \ C sees M,b:Ts\T = m in D) \ \ P \ \C\\<^sub>sM(map Val vs),s,b\ \ \THROW NoSuchMethodError,s,False\" | RedSCallNonStatic: "\ P \ C sees M,NonStatic:Ts\T = m in D \ \ P \ \C\\<^sub>sM(map Val vs),s,b\ \ \THROW IncompatibleClassChangeError,s,False\" | BlockRedNone: "\ P \ \e, (h,l(V:=None),sh), b\ \ \e', (h',l',sh'), b'\; l' V = None; \ assigned V e \ \ P \ \{V:T; e}, (h,l,sh), b\ \ \{V:T; e'}, (h',l'(V := l V),sh'), b'\" | BlockRedSome: "\ P \ \e, (h,l(V:=None),sh), b\ \ \e', (h',l',sh'), b'\; l' V = Some v;\ assigned V e \ \ P \ \{V:T; e}, (h,l,sh), b\ \ \{V:T := Val v; e'}, (h',l'(V := l V),sh'), b'\" | InitBlockRed: "\ P \ \e, (h,l(V\v),sh), b\ \ \e', (h',l',sh'), b'\; l' V = Some v' \ \ P \ \{V:T := Val v; e}, (h,l,sh), b\ \ \{V:T := Val v'; e'}, (h',l'(V := l V),sh'), b'\" | RedBlock: "P \ \{V:T; Val u}, s, b\ \ \Val u, s, b\" | RedInitBlock: "P \ \{V:T := Val v; Val u}, s, b\ \ \Val u, s, b\" | SeqRed: "P \ \e,s,b\ \ \e',s',b'\ \ P \ \e;;e\<^sub>2, s, b\ \ \e';;e\<^sub>2, s', b'\" | RedSeq: "P \ \(Val v);;e\<^sub>2, s, b\ \ \e\<^sub>2, s, b\" | CondRed: "P \ \e,s,b\ \ \e',s',b'\ \ P \ \if (e) e\<^sub>1 else e\<^sub>2, s, b\ \ \if (e') e\<^sub>1 else e\<^sub>2, s', b'\" | RedCondT: "P \ \if (true) e\<^sub>1 else e\<^sub>2, s, b\ \ \e\<^sub>1, s, b\" | RedCondF: "P \ \if (false) e\<^sub>1 else e\<^sub>2, s, b\ \ \e\<^sub>2, s, b\" | RedWhile: "P \ \while(b) c, s, b'\ \ \if(b) (c;;while(b) c) else unit, s, b'\" | ThrowRed: "P \ \e,s,b\ \ \e',s',b'\ \ P \ \throw e, s, b\ \ \throw e', s', b'\" | RedThrowNull: "P \ \throw null, s, b\ \ \THROW NullPointer, s, b\" | TryRed: "P \ \e,s,b\ \ \e',s',b'\ \ P \ \try e catch(C V) e\<^sub>2, s, b\ \ \try e' catch(C V) e\<^sub>2, s', b'\" | RedTry: "P \ \try (Val v) catch(C V) e\<^sub>2, s, b\ \ \Val v, s, b\" | RedTryCatch: "\ hp s a = Some(D,fs); P \ D \\<^sup>* C \ \ P \ \try (Throw a) catch(C V) e\<^sub>2, s, b\ \ \{V:Class C := addr a; e\<^sub>2}, s, b\" | RedTryFail: "\ hp s a = Some(D,fs); \ P \ D \\<^sup>* C \ \ P \ \try (Throw a) catch(C V) e\<^sub>2, s, b\ \ \Throw a, s, b\" | ListRed1: "P \ \e,s,b\ \ \e',s',b'\ \ P \ \e#es,s,b\ [\] \e'#es,s',b'\" | ListRed2: "P \ \es,s,b\ [\] \es',s',b'\ \ P \ \Val v # es,s,b\ [\] \Val v # es',s',b'\" \ \Initialization procedure\ | RedInit: "\sub_RI e \ P \ \INIT C (Nil,b) \ e,s,b'\ \ \e,s,icheck P C e\" | InitNoneRed: "sh C = None \ P \ \INIT C' (C#Cs,False) \ e,(h,l,sh),b\ \ \INIT C' (C#Cs,False) \ e,(h,l,sh(C \ (sblank P C, Prepared))),b\" | RedInitDone: "sh C = Some(sfs,Done) \ P \ \INIT C' (C#Cs,False) \ e,(h,l,sh),b\ \ \INIT C' (Cs,True) \ e,(h,l,sh),b\" | RedInitProcessing: "sh C = Some(sfs,Processing) \ P \ \INIT C' (C#Cs,False) \ e,(h,l,sh),b\ \ \INIT C' (Cs,True) \ e,(h,l,sh),b\" | RedInitError: "sh C = Some(sfs,Error) \ P \ \INIT C' (C#Cs,False) \ e,(h,l,sh),b\ \ \RI (C,THROW NoClassDefFoundError);Cs \ e,(h,l,sh),b\" | InitObjectRed: "\ sh C = Some(sfs,Prepared); C = Object; sh' = sh(C \ (sfs,Processing)) \ \ P \ \INIT C' (C#Cs,False) \ e,(h,l,sh),b\ \ \INIT C' (C#Cs,True) \ e,(h,l,sh'),b\" | InitNonObjectSuperRed: "\ sh C = Some(sfs,Prepared); C \ Object; class P C = Some (D,r); sh' = sh(C \ (sfs,Processing)) \ \ P \ \INIT C' (C#Cs,False) \ e,(h,l,sh),b\ \ \INIT C' (D#C#Cs,False) \ e,(h,l,sh'),b\" | RedInitRInit: "P \ \INIT C' (C#Cs,True) \ e,(h,l,sh),b\ \ \RI (C,C\\<^sub>sclinit([]));Cs \ e,(h,l,sh),b\" | RInitRed: "P \ \e,s,b\ \ \e',s',b'\ \ P \ \RI (C,e);Cs \ e\<^sub>0, s, b\ \ \RI (C,e');Cs \ e\<^sub>0, s', b'\" | RedRInit: "\ sh C = Some (sfs, i); sh' = sh(C \ (sfs,Done)); C' = last(C#Cs) \ \ P \ \RI (C, Val v);Cs \ e, (h,l,sh), b\ \ \INIT C' (Cs,True) \ e, (h,l,sh'), b\" \ \Exception propagation\ | CastThrow: "P \ \Cast C (throw e), s, b\ \ \throw e, s, b\" | BinOpThrow1: "P \ \(throw e) \bop\ e\<^sub>2, s, b\ \ \throw e, s, b\" | BinOpThrow2: "P \ \(Val v\<^sub>1) \bop\ (throw e), s, b\ \ \throw e, s, b\" | LAssThrow: "P \ \V:=(throw e), s, b\ \ \throw e, s, b\" | FAccThrow: "P \ \(throw e)\F{D}, s, b\ \ \throw e, s, b\" | FAssThrow1: "P \ \(throw e)\F{D}:=e\<^sub>2, s, b\ \ \throw e, s, b\" | FAssThrow2: "P \ \Val v\F{D}:=(throw e), s, b\ \ \throw e, s, b\" | SFAssThrow: "P \ \C\\<^sub>sF{D}:=(throw e), s, b\ \ \throw e, s, b\" | CallThrowObj: "P \ \(throw e)\M(es), s, b\ \ \throw e, s, b\" | CallThrowParams: "\ es = map Val vs @ throw e # es' \ \ P \ \(Val v)\M(es), s, b\ \ \throw e, s, b\" | SCallThrowParams: "\ es = map Val vs @ throw e # es' \ \ P \ \C\\<^sub>sM(es), s, b\ \ \throw e, s, b\" | BlockThrow: "P \ \{V:T; Throw a}, s, b\ \ \Throw a, s, b\" | InitBlockThrow: "P \ \{V:T := Val v; Throw a}, s, b\ \ \Throw a, s, b\" | SeqThrow: "P \ \(throw e);;e\<^sub>2, s, b\ \ \throw e, s, b\" | CondThrow: "P \ \if (throw e) e\<^sub>1 else e\<^sub>2, s, b\ \ \throw e, s, b\" | ThrowThrow: "P \ \throw(throw e), s, b\ \ \throw e, s, b\" | RInitInitThrow: "\ sh C = Some(sfs,i); sh' = sh(C \ (sfs,Error)) \ \ P \ \RI (C,Throw a);D#Cs \ e,(h,l,sh),b\ \ \RI (D,Throw a);Cs \ e,(h,l,sh'),b\" | RInitThrow: "\ sh C = Some(sfs, i); sh' = sh(C \ (sfs,Error)) \ \ P \ \RI (C,Throw a);Nil \ e,(h,l,sh),b\ \ \Throw a,(h,l,sh'),b\" (*<*) lemmas red_reds_induct = red_reds.induct [split_format (complete)] and red_reds_inducts = red_reds.inducts [split_format (complete)] inductive_cases [elim!]: "P \ \V:=e,s,b\ \ \e',s',b'\" "P \ \e1;;e2,s,b\ \ \e',s',b'\" (*>*) subsection\ The reflexive transitive closure \ abbreviation Step :: "J_prog \ expr \ state \ bool \ expr \ state \ bool \ bool" ("_ \ ((1\_,/_,/_\) \*/ (1\_,/_,/_\))" [51,0,0,0,0,0,0] 81) where "P \ \e,s,b\ \* \e',s',b'\ \ ((e,s,b), e',s',b') \ (red P)\<^sup>*" abbreviation Steps :: "J_prog \ expr list \ state \ bool \ expr list \ state \ bool \ bool" ("_ \ ((1\_,/_,/_\) [\]*/ (1\_,/_,/_\))" [51,0,0,0,0,0,0] 81) where "P \ \es,s,b\ [\]* \es',s',b'\ \ ((es,s,b), es',s',b') \ (reds P)\<^sup>*" lemmas converse_rtrancl_induct3 = converse_rtrancl_induct [of "(ax, ay, az)" "(bx, by, bz)", split_format (complete), consumes 1, case_names refl step] lemma converse_rtrancl_induct_red[consumes 1]: assumes "P \ \e,(h,l,sh),b\ \* \e',(h',l',sh'),b'\" and "\e h l sh b. R e h l sh b e h l sh b" and "\e\<^sub>0 h\<^sub>0 l\<^sub>0 sh\<^sub>0 b\<^sub>0 e\<^sub>1 h\<^sub>1 l\<^sub>1 sh\<^sub>1 b\<^sub>1 e' h' l' sh' b'. \ P \ \e\<^sub>0,(h\<^sub>0,l\<^sub>0,sh\<^sub>0),b\<^sub>0\ \ \e\<^sub>1,(h\<^sub>1,l\<^sub>1,sh\<^sub>1),b\<^sub>1\; R e\<^sub>1 h\<^sub>1 l\<^sub>1 sh\<^sub>1 b\<^sub>1 e' h' l' sh' b' \ \ R e\<^sub>0 h\<^sub>0 l\<^sub>0 sh\<^sub>0 b\<^sub>0 e' h' l' sh' b'" shows "R e h l sh b e' h' l' sh' b'" (*<*) proof - { fix s s' assume reds: "P \ \e,s,b\ \* \e',s',b'\" and base: "\e s b. R e (hp s) (lcl s) (shp s) b e (hp s) (lcl s) (shp s) b" and red\<^sub>1: "\e\<^sub>0 s\<^sub>0 b\<^sub>0 e\<^sub>1 s\<^sub>1 b\<^sub>1 e' s' b'. \ P \ \e\<^sub>0,s\<^sub>0,b\<^sub>0\ \ \e\<^sub>1,s\<^sub>1,b\<^sub>1\; R e\<^sub>1 (hp s\<^sub>1) (lcl s\<^sub>1) (shp s\<^sub>1) b\<^sub>1 e' (hp s') (lcl s') (shp s') b' \ \ R e\<^sub>0 (hp s\<^sub>0) (lcl s\<^sub>0) (shp s\<^sub>0) b\<^sub>0 e' (hp s') (lcl s') (shp s') b'" from reds have "R e (hp s) (lcl s) (shp s) b e' (hp s') (lcl s') (shp s') b'" proof (induct rule:converse_rtrancl_induct3) case refl show ?case by(rule base) next case step thus ?case by(blast intro:red\<^sub>1) qed } with assms show ?thesis by fastforce qed (*>*) subsection\Some easy lemmas\ lemma [iff]: "\ P \ \[],s,b\ [\] \es',s',b'\" (*<*)by(blast elim: reds.cases)(*>*) lemma [iff]: "\ P \ \Val v,s,b\ \ \e',s',b'\" (*<*)by(fastforce elim: red.cases)(*>*) lemma val_no_step: "val_of e = \v\ \ \ P \ \e,s,b\ \ \e',s',b'\" (*<*)by(drule val_of_spec, simp)(*>*) lemma [iff]: "\ P \ \Throw a,s,b\ \ \e',s',b'\" (*<*)by(fastforce elim: red.cases)(*>*) lemma map_Vals_no_step [iff]: "\ P \ \map Val vs,s,b\ [\] \es',s',b'\" (*<*) -apply(induct vs arbitrary: es', simp) -apply(rule notI) -apply(erule reds.cases, auto) -done +proof(induct vs arbitrary: es') + case (Cons a vs) + { assume "P \ \map Val (a # vs),s,b\ [\] \es',s',b'\" + then have False by(rule reds.cases) (insert Cons, auto) + } + then show ?case by clarsimp +qed simp (*>*) lemma vals_no_step: "map_vals_of es = \vs\ \ \ P \ \es,s,b\ [\] \es',s',b'\" (*<*)by(drule map_vals_of_spec, simp)(*>*) lemma vals_throw_no_step [iff]: "\ P \ \map Val vs @ Throw a # es,s,b\ [\] \es',s',b'\" (*<*) -apply(induct vs arbitrary: es', auto) -apply(erule reds.cases, auto) -apply(erule reds.cases, auto) -done +proof(induct vs arbitrary: es') + case Nil + { assume "P \ \Throw a # es,s,b\ [\] \es',s',b'\" + then have False by(rule reds.cases) (insert Cons, auto) + } + then show ?case by clarsimp +next + case (Cons a' vs') + { assume "P \ \map Val (a'#vs') @ Throw a # es,s,b\ [\] \es',s',b'\" + then have False by(rule reds.cases) (insert Cons, auto) + } + then show ?case by clarsimp +qed (*>*) lemma lass_val_of_red: "\ lass_val_of e = \a\; P \ \e,(h, l, sh),b\ \ \e',(h', l', sh'),b'\ \ \ e' = unit \ h' = h \ l' = l(fst a\snd a) \ sh' = sh \ b = b'" (*<*)by(drule lass_val_of_spec, auto)(*>*) lemma final_no_step [iff]: "final e \ \ P \ \e,s,b\ \ \e',s',b'\" (*<*)by(erule finalE, simp+)(*>*) lemma finals_no_step [iff]: "finals es \ \ P \ \es,s,b\ [\] \es',s',b'\" (*<*)by(erule finalsE, simp+)(*>*) lemma reds_final_same: "P \ \e,s,b\ \* \e',s',b'\ \ final e \ e = e' \ s = s' \ b = b'" proof(induct rule:converse_rtrancl_induct3) case refl show ?case by simp next case (step e0 s0 b0 e1 s1 b1) show ?case proof(rule finalE[OF step.prems(1)]) fix v assume "e0 = Val v" then show ?thesis using step by simp next fix a assume "e0 = Throw a" then show ?thesis using step by simp qed qed lemma reds_throw: "P \ \e,s,b\ \* \e',s',b'\ \ (\e\<^sub>t. throw_of e = \e\<^sub>t\ \ \e\<^sub>t'. throw_of e' = \e\<^sub>t'\)" proof(induct rule:converse_rtrancl_induct3) case refl then show ?case by simp next case (step e0 s0 b0 e1 s1 b1) then show ?case by(auto elim: red.cases) qed lemma red_hext_incr: "P \ \e,(h,l,sh),b\ \ \e',(h',l',sh'),b'\ \ h \ h'" and reds_hext_incr: "P \ \es,(h,l,sh),b\ [\] \es',(h',l',sh'),b'\ \ h \ h'" (*<*) proof(induct rule:red_reds_inducts) case RedNew thus ?case by(fastforce dest:new_Addr_SomeD simp:hext_def split:if_splits) next case RedFAss thus ?case by(simp add:hext_def split:if_splits) qed simp_all (*>*) lemma red_lcl_incr: "P \ \e,(h\<^sub>0,l\<^sub>0,sh\<^sub>0),b\ \ \e',(h\<^sub>1,l\<^sub>1,sh\<^sub>1),b'\ \ dom l\<^sub>0 \ dom l\<^sub>1" and reds_lcl_incr: "P \ \es,(h\<^sub>0,l\<^sub>0,sh\<^sub>0),b\ [\] \es',(h\<^sub>1,l\<^sub>1,sh\<^sub>1),b'\ \ dom l\<^sub>0 \ dom l\<^sub>1" (*<*)by(induct rule: red_reds_inducts)(auto simp del:fun_upd_apply)(*>*) lemma red_lcl_add: "P \ \e,(h,l,sh),b\ \ \e',(h',l',sh'),b'\ \ (\l\<^sub>0. P \ \e,(h,l\<^sub>0++l,sh),b\ \ \e',(h',l\<^sub>0++l',sh'),b'\)" and reds_lcl_add: "P \ \es,(h,l,sh),b\ [\] \es',(h',l',sh'),b'\ \ (\l\<^sub>0. P \ \es,(h,l\<^sub>0++l,sh),b\ [\] \es',(h',l\<^sub>0++l',sh'),b'\)" (*<*) proof (induct rule:red_reds_inducts) case RedCast thus ?case by(fastforce intro:red_reds.intros) next case RedCastFail thus ?case by(force intro:red_reds.intros) next case RedFAcc thus ?case by(fastforce intro:red_reds.intros) next case RedCall thus ?case by(fastforce intro:red_reds.intros) next case (InitBlockRed e h l V v sh b e' h' l' sh' b' v' T l\<^sub>0) have IH: "\l\<^sub>0. P \ \e,(h, l\<^sub>0 ++ l(V \ v), sh),b\ \ \e',(h', l\<^sub>0 ++ l', sh'),b'\" and l'V: "l' V = Some v'" by fact+ from IH have IH': "P \ \e,(h, (l\<^sub>0 ++ l)(V \ v), sh),b\ \ \e',(h', l\<^sub>0 ++ l', sh'),b'\" by simp have "(l\<^sub>0 ++ l')(V := (l\<^sub>0 ++ l) V) = l\<^sub>0 ++ l'(V := l V)" by(rule ext)(simp add:map_add_def) with red_reds.InitBlockRed[OF IH'] l'V show ?case by(simp del:fun_upd_apply) next case (BlockRedNone e h l V sh b e' h' l' sh' b' T l\<^sub>0) have IH: "\l\<^sub>0. P \ \e,(h, l\<^sub>0 ++ l(V := None), sh),b\ \ \e',(h', l\<^sub>0 ++ l', sh'),b'\" and l'V: "l' V = None" and unass: "\ assigned V e" by fact+ have "l\<^sub>0(V := None) ++ l(V := None) = (l\<^sub>0 ++ l)(V := None)" by(simp add:fun_eq_iff map_add_def) hence IH': "P \ \e,(h, (l\<^sub>0++l)(V := None), sh),b\ \ \e',(h', l\<^sub>0(V := None) ++ l', sh'),b'\" using IH[of "l\<^sub>0(V := None)"] by simp have "(l\<^sub>0(V := None) ++ l')(V := (l\<^sub>0 ++ l) V) = l\<^sub>0 ++ l'(V := l V)" by(simp add:fun_eq_iff map_add_def) with red_reds.BlockRedNone[OF IH' _ unass] l'V show ?case by(simp add: map_add_def) next case (BlockRedSome e h l V sh b e' h' l' sh' b' v T l\<^sub>0) have IH: "\l\<^sub>0. P \ \e,(h, l\<^sub>0 ++ l(V := None), sh),b\ \ \e',(h', l\<^sub>0 ++ l', sh'),b'\" and l'V: "l' V = Some v" and unass: "\ assigned V e" by fact+ have "l\<^sub>0(V := None) ++ l(V := None) = (l\<^sub>0 ++ l)(V := None)" by(simp add:fun_eq_iff map_add_def) hence IH': "P \ \e,(h, (l\<^sub>0++l)(V := None), sh),b\ \ \e',(h', l\<^sub>0(V := None) ++ l', sh'),b'\" using IH[of "l\<^sub>0(V := None)"] by simp have "(l\<^sub>0(V := None) ++ l')(V := (l\<^sub>0 ++ l) V) = l\<^sub>0 ++ l'(V := l V)" by(simp add:fun_eq_iff map_add_def) with red_reds.BlockRedSome[OF IH' _ unass] l'V show ?case by(simp add:map_add_def) next case RedTryCatch thus ?case by(fastforce intro:red_reds.intros) next case RedTryFail thus ?case by(force intro!:red_reds.intros) qed (simp_all add:red_reds.intros) (*>*) lemma Red_lcl_add: assumes "P \ \e,(h,l,sh), b\ \* \e',(h',l',sh'), b'\" shows "P \ \e,(h,l\<^sub>0++l,sh),b\ \* \e',(h',l\<^sub>0++l',sh'),b'\" (*<*) using assms proof(induct rule:converse_rtrancl_induct_red) case 1 thus ?case by simp next case 2 thus ?case by (blast dest: red_lcl_add intro: converse_rtrancl_into_rtrancl) qed (*>*) lemma assumes wf: "wwf_J_prog P" shows red_proc_pres: "P \ \e,(h,l,sh),b\ \ \e',(h',l',sh'),b'\ \ not_init C e \ sh C = \(sfs, Processing)\ \ not_init C e' \ (\sfs'. sh' C = \(sfs', Processing)\)" and reds_proc_pres: "P \ \es,(h,l,sh),b\ [\] \es',(h',l',sh'),b'\ \ not_inits C es \ sh C = \(sfs, Processing)\ \ not_inits C es' \ (\sfs'. sh' C = \(sfs', Processing)\)" (*<*) proof(induct rule:red_reds_inducts) case RedCall then show ?case using sees_wwf_nsub_RI[OF wf RedCall.hyps(2)] sub_RI_blocks_body nsub_RI_not_init by auto next case RedSCall then show ?case using sees_wwf_nsub_RI[OF wf RedSCall.hyps(1)] sub_RI_blocks_body nsub_RI_not_init by auto next case (RedInitDone sh C sfs C' Cs e h l b) then show ?case by(cases Cs, auto) next case (RedInitProcessing sh C sfs C' Cs e h l b) then show ?case by(cases Cs, auto) next case (RedRInit sh C sfs i sh' C' Cs v e h l b) then show ?case by(cases Cs, auto) next case (CallThrowParams es vs e es' v M h l sh b) then show ?case by(auto dest: not_inits_def') next case (SCallThrowParams es vs e es' C M h l sh b) then show ?case by(auto dest: not_inits_def') qed(auto) end diff --git a/thys/JinjaDCI/J/WWellForm.thy b/thys/JinjaDCI/J/WWellForm.thy --- a/thys/JinjaDCI/J/WWellForm.thy +++ b/thys/JinjaDCI/J/WWellForm.thy @@ -1,42 +1,40 @@ (* Title: JinjaDCI/J/WWellForm.thy Author: Tobias Nipkow, Susannah Mansky Copyright 2003 Technische Universitaet Muenchen, 2019-20 UIUC Based on the Jinja theory J/WWellForm.thy by Tobias Nipkow *) section \ Weak well-formedness of Jinja programs \ theory WWellForm imports "../Common/WellForm" Expr begin definition wwf_J_mdecl :: "J_prog \ cname \ J_mb mdecl \ bool" where "wwf_J_mdecl P C \ \(M,b,Ts,T,(pns,body)). length Ts = length pns \ distinct pns \ \sub_RI body \ (case b of NonStatic \ this \ set pns \ fv body \ {this} \ set pns | Static \ fv body \ set pns)" lemma wwf_J_mdecl_NonStatic[simp]: "wwf_J_mdecl P C (M,NonStatic,Ts,T,pns,body) = (length Ts = length pns \ distinct pns \ \sub_RI body \ this \ set pns \ fv body \ {this} \ set pns)" (*<*)by(simp add:wwf_J_mdecl_def)(*>*) lemma wwf_J_mdecl_Static[simp]: "wwf_J_mdecl P C (M,Static,Ts,T,pns,body) = (length Ts = length pns \ distinct pns \ \sub_RI body \ fv body \ set pns)" (*<*)by(simp add:wwf_J_mdecl_def)(*>*) abbreviation wwf_J_prog :: "J_prog \ bool" where "wwf_J_prog \ wf_prog wwf_J_mdecl" lemma sees_wwf_nsub_RI: "\ wwf_J_prog P; P \ C sees M,b : Ts\T = (pns, body) in D \ \ \sub_RI body" -apply(drule sees_wf_mdecl, simp) -apply(unfold wwf_J_mdecl_def wf_mdecl_def, simp) -done +(*<*)by(auto dest!: sees_wf_mdecl simp: wwf_J_mdecl_def wf_mdecl_def)(*>*) end diff --git a/thys/JinjaDCI/J/WellType.thy b/thys/JinjaDCI/J/WellType.thy --- a/thys/JinjaDCI/J/WellType.thy +++ b/thys/JinjaDCI/J/WellType.thy @@ -1,255 +1,219 @@ (* Title: JinjaDCI/J/WellType.thy Author: Tobias Nipkow, Susannah Mansky Copyright 2003 Technische Universitaet Muenchen, 2019-20 UIUC Based on the Jinja theory J/WellType.thy by Tobias Nipkow *) section \ Well-typedness of Jinja expressions \ theory WellType imports "../Common/Objects" Expr begin type_synonym env = "vname \ ty" inductive WT :: "[J_prog,env, expr , ty ] \ bool" ("_,_ \ _ :: _" [51,51,51]50) and WTs :: "[J_prog,env, expr list, ty list] \ bool" ("_,_ \ _ [::] _" [51,51,51]50) for P :: J_prog where WTNew: "is_class P C \ P,E \ new C :: Class C" | WTCast: "\ P,E \ e :: Class D; is_class P C; P \ C \\<^sup>* D \ P \ D \\<^sup>* C \ \ P,E \ Cast C e :: Class C" | WTVal: "typeof v = Some T \ P,E \ Val v :: T" | WTVar: "E V = Some T \ P,E \ Var V :: T" | WTBinOpEq: "\ P,E \ e\<^sub>1 :: T\<^sub>1; P,E \ e\<^sub>2 :: T\<^sub>2; P \ T\<^sub>1 \ T\<^sub>2 \ P \ T\<^sub>2 \ T\<^sub>1 \ \ P,E \ e\<^sub>1 \Eq\ e\<^sub>2 :: Boolean" | WTBinOpAdd: "\ P,E \ e\<^sub>1 :: Integer; P,E \ e\<^sub>2 :: Integer \ \ P,E \ e\<^sub>1 \Add\ e\<^sub>2 :: Integer" | WTLAss: "\ E V = Some T; P,E \ e :: T'; P \ T' \ T; V \ this \ \ P,E \ V:=e :: Void" | WTFAcc: "\ P,E \ e :: Class C; P \ C sees F,NonStatic:T in D \ \ P,E \ e\F{D} :: T" | WTSFAcc: "\ P \ C sees F,Static:T in D \ \ P,E \ C\\<^sub>sF{D} :: T" | WTFAss: "\ P,E \ e\<^sub>1 :: Class C; P \ C sees F,NonStatic:T in D; P,E \ e\<^sub>2 :: T'; P \ T' \ T \ \ P,E \ e\<^sub>1\F{D}:=e\<^sub>2 :: Void" | WTSFAss: "\ P \ C sees F,Static:T in D; P,E \ e\<^sub>2 :: T'; P \ T' \ T \ \ P,E \ C\\<^sub>sF{D}:=e\<^sub>2 :: Void" | WTCall: "\ P,E \ e :: Class C; P \ C sees M,NonStatic:Ts \ T = (pns,body) in D; P,E \ es [::] Ts'; P \ Ts' [\] Ts \ \ P,E \ e\M(es) :: T" | WTSCall: "\ P \ C sees M,Static:Ts \ T = (pns,body) in D; P,E \ es [::] Ts'; P \ Ts' [\] Ts; M \ clinit \ \ P,E \ C\\<^sub>sM(es) :: T" | WTBlock: "\ is_type P T; P,E(V \ T) \ e :: T' \ \ P,E \ {V:T; e} :: T'" | WTSeq: "\ P,E \ e\<^sub>1::T\<^sub>1; P,E \ e\<^sub>2::T\<^sub>2 \ \ P,E \ e\<^sub>1;;e\<^sub>2 :: T\<^sub>2" | WTCond: "\ P,E \ e :: Boolean; P,E \ e\<^sub>1::T\<^sub>1; P,E \ e\<^sub>2::T\<^sub>2; P \ T\<^sub>1 \ T\<^sub>2 \ P \ T\<^sub>2 \ T\<^sub>1; P \ T\<^sub>1 \ T\<^sub>2 \ T = T\<^sub>2; P \ T\<^sub>2 \ T\<^sub>1 \ T = T\<^sub>1 \ \ P,E \ if (e) e\<^sub>1 else e\<^sub>2 :: T" | WTWhile: "\ P,E \ e :: Boolean; P,E \ c::T \ \ P,E \ while (e) c :: Void" | WTThrow: "P,E \ e :: Class C \ P,E \ throw e :: Void" | WTTry: "\ P,E \ e\<^sub>1 :: T; P,E(V \ Class C) \ e\<^sub>2 :: T; is_class P C \ \ P,E \ try e\<^sub>1 catch(C V) e\<^sub>2 :: T" \ \well-typed expression lists\ | WTNil: "P,E \ [] [::] []" | WTCons: "\ P,E \ e :: T; P,E \ es [::] Ts \ \ P,E \ e#es [::] T#Ts" (*<*) declare WT_WTs.intros[intro!] (* WTNil[iff] *) lemmas WT_WTs_induct = WT_WTs.induct [split_format (complete)] and WT_WTs_inducts = WT_WTs.inducts [split_format (complete)] (*>*) lemma init_nwt [simp]:"\P,E \ INIT C (Cs,b) \ e :: T" by(auto elim:WT.cases) lemma ri_nwt [simp]:"\P,E \ RI(C,e);Cs \ e' :: T" by(auto elim:WT.cases) lemma [iff]: "(P,E \ [] [::] Ts) = (Ts = [])" -(*<*) -apply(rule iffI) -apply (auto elim: WTs.cases) -done -(*>*) +(*<*)by (rule iffI) (auto elim: WTs.cases)(*>*) lemma [iff]: "(P,E \ e#es [::] T#Ts) = (P,E \ e :: T \ P,E \ es [::] Ts)" -(*<*) -apply(rule iffI) -apply (auto elim: WTs.cases) -done -(*>*) +(*<*)by (rule iffI) (auto elim: WTs.cases)(*>*) lemma [iff]: "(P,E \ (e#es) [::] Ts) = (\U Us. Ts = U#Us \ P,E \ e :: U \ P,E \ es [::] Us)" -(*<*) -apply(rule iffI) -apply (auto elim: WTs.cases) -done -(*>*) +(*<*)by (rule iffI) (auto elim: WTs.cases)(*>*) lemma [iff]: "\Ts. (P,E \ es\<^sub>1 @ es\<^sub>2 [::] Ts) = (\Ts\<^sub>1 Ts\<^sub>2. Ts = Ts\<^sub>1 @ Ts\<^sub>2 \ P,E \ es\<^sub>1 [::] Ts\<^sub>1 \ P,E \ es\<^sub>2[::]Ts\<^sub>2)" (*<*) -apply(induct es\<^sub>1 type:list) - 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 fastforce -done +proof(induct es\<^sub>1 type:list) + case (Cons a list) + let ?lhs = "(\U Us. Ts = U # Us \ P,E \ a :: U \ + (\Ts\<^sub>1 Ts\<^sub>2. Us = Ts\<^sub>1 @ Ts\<^sub>2 \ P,E \ list [::] Ts\<^sub>1 \ P,E \ es\<^sub>2 [::] Ts\<^sub>2))" + let ?rhs = "(\Ts\<^sub>1 Ts\<^sub>2. Ts = Ts\<^sub>1 @ Ts\<^sub>2 \ + (\U Us. Ts\<^sub>1 = U # Us \ P,E \ a :: U \ P,E \ list [::] Us) \ P,E \ es\<^sub>2 [::] Ts\<^sub>2)" + { assume ?lhs + then have ?rhs by (auto intro: Cons_eq_appendI) + } + moreover { + assume ?rhs + then have ?lhs by fastforce + } + ultimately have "?lhs = ?rhs" by(rule iffI) + then show ?case by (clarsimp simp: Cons) +qed simp (*>*) lemma [iff]: "P,E \ Val v :: T = (typeof v = Some T)" -(*<*) -apply(rule iffI) -apply (auto elim: WT.cases) -done -(*>*) +(*<*)proof(rule iffI) qed (auto elim: WT.cases)(*>*) lemma [iff]: "P,E \ Var V :: T = (E V = Some T)" -(*<*) -apply(rule iffI) -apply (auto elim: WT.cases) -done -(*>*) +(*<*)proof(rule iffI) qed (auto elim: WT.cases)(*>*) lemma [iff]: "P,E \ e\<^sub>1;;e\<^sub>2 :: T\<^sub>2 = (\T\<^sub>1. P,E \ e\<^sub>1::T\<^sub>1 \ P,E \ e\<^sub>2::T\<^sub>2)" -(*<*) -apply(rule iffI) -apply (auto elim: WT.cases) -done -(*>*) +(*<*)proof(rule iffI) qed (auto elim: WT.cases)(*>*) lemma [iff]: "(P,E \ {V:T; e} :: T') = (is_type P T \ P,E(V\T) \ e :: T')" -(*<*) -apply(rule iffI) -apply (auto elim: WT.cases) -done -(*>*) +(*<*)proof(rule iffI) qed (auto elim: WT.cases)(*>*) (*<*) inductive_cases WT_elim_cases[elim!]: "P,E \ V :=e :: T" "P,E \ if (e) e\<^sub>1 else e\<^sub>2 :: T" "P,E \ while (e) c :: T" "P,E \ throw e :: T" "P,E \ try e\<^sub>1 catch(C V) e\<^sub>2 :: T" "P,E \ Cast D e :: T" "P,E \ a\F{D} :: T" "P,E \ C\\<^sub>sF{D} :: T" "P,E \ a\F{D} := v :: T" "P,E \ C\\<^sub>sF{D} := v :: T" "P,E \ e\<^sub>1 \bop\ e\<^sub>2 :: T" "P,E \ new C :: T" "P,E \ e\M(ps) :: T" "P,E \ C\\<^sub>sM(ps) :: T" (*>*) lemma wt_env_mono: "P,E \ e :: T \ (\E'. E \\<^sub>m E' \ P,E' \ e :: T)" and "P,E \ es [::] Ts \ (\E'. E \\<^sub>m E' \ P,E' \ es [::] Ts)" (*<*) -apply(induct rule: WT_WTs_inducts) -apply(simp add: WTNew) -apply(fastforce simp: WTCast) -apply(fastforce simp: WTVal) -apply(simp add: WTVar map_le_def dom_def) -apply(fastforce simp: WTBinOpEq) -apply(fastforce simp: WTBinOpAdd) -apply(force simp:map_le_def) -apply(fastforce simp: WTFAcc) -apply(fastforce) -apply(fastforce simp: WTFAss del:WT_WTs.intros WT_elim_cases) -apply(fastforce) -apply(fastforce simp: WTCall) -apply(fastforce) -apply(fastforce simp: map_le_def WTBlock) -apply(fastforce simp: WTSeq) -apply(fastforce simp: WTCond) -apply(fastforce simp: WTWhile) -apply(fastforce simp: WTThrow) -apply(fastforce simp: WTTry map_le_def dom_def) -apply(simp add: WTNil) -apply(simp add: WTCons) -done +proof(induct rule: WT_WTs_inducts) + case WTVar then show ?case by(simp add: map_le_def dom_def) +next + case WTLAss then show ?case by(force simp:map_le_def) +qed fastforce+ (*>*) lemma WT_fv: "P,E \ e :: T \ fv e \ dom E" and "P,E \ es [::] Ts \ fvs es \ dom E" (*<*) -apply(induct rule:WT_WTs.inducts) -apply(simp_all del: fun_upd_apply) -apply fast+ -done +proof(induct rule:WT_WTs.inducts) + case WTVar then show ?case by fastforce +next + case WTLAss then show ?case by fastforce +next + case WTBlock then show ?case by fastforce +next + case WTTry then show ?case by fastforce +qed simp_all +(*>*) lemma WT_nsub_RI: "P,E \ e :: T \ \sub_RI e" and WTs_nsub_RIs: "P,E \ es [::] Ts \ \sub_RIs es" -proof(induct rule: WT_WTs.inducts) qed(simp_all) +(*<*)proof(induct rule: WT_WTs.inducts) qed(simp_all) end (*>*) diff --git a/thys/JinjaDCI/J/WellTypeRT.thy b/thys/JinjaDCI/J/WellTypeRT.thy --- a/thys/JinjaDCI/J/WellTypeRT.thy +++ b/thys/JinjaDCI/J/WellTypeRT.thy @@ -1,353 +1,293 @@ (* Title: JinjaDCI/J/WellTypeRT.thy Author: Tobias Nipkow, Susannah Mansky Copyright 2003 Technische Universitaet Muenchen, 2019-20 UIUC Based on the Jinja theory J/WellTypeRT.thy by Tobias Nipkow *) section \ Runtime Well-typedness \ theory WellTypeRT imports WellType begin inductive WTrt :: "J_prog \ heap \ sheap \ env \ expr \ ty \ bool" and WTrts :: "J_prog \ heap \ sheap \ env \ expr list \ ty list \ bool" and WTrt2 :: "[J_prog,env,heap,sheap,expr,ty] \ bool" ("_,_,_,_ \ _ : _" [51,51,51,51]50) and WTrts2 :: "[J_prog,env,heap,sheap,expr list, ty list] \ bool" ("_,_,_,_ \ _ [:] _" [51,51,51,51]50) for P :: J_prog and h :: heap and sh :: sheap where "P,E,h,sh \ e : T \ WTrt P h sh E e T" | "P,E,h,sh \ es[:]Ts \ WTrts P h sh E es Ts" | WTrtNew: "is_class P C \ P,E,h,sh \ new C : Class C" | WTrtCast: "\ P,E,h,sh \ e : T; is_refT T; is_class P C \ \ P,E,h,sh \ Cast C e : Class C" | WTrtVal: "typeof\<^bsub>h\<^esub> v = Some T \ P,E,h,sh \ Val v : T" | WTrtVar: "E V = Some T \ P,E,h,sh \ Var V : T" | WTrtBinOpEq: "\ P,E,h,sh \ e\<^sub>1 : T\<^sub>1; P,E,h,sh \ e\<^sub>2 : T\<^sub>2 \ \ P,E,h,sh \ e\<^sub>1 \Eq\ e\<^sub>2 : Boolean" | WTrtBinOpAdd: "\ P,E,h,sh \ e\<^sub>1 : Integer; P,E,h,sh \ e\<^sub>2 : Integer \ \ P,E,h,sh \ e\<^sub>1 \Add\ e\<^sub>2 : Integer" | WTrtLAss: "\ E V = Some T; P,E,h,sh \ e : T'; P \ T' \ T \ \ P,E,h,sh \ V:=e : Void" | WTrtFAcc: "\ P,E,h,sh \ e : Class C; P \ C has F,NonStatic:T in D \ \ P,E,h,sh \ e\F{D} : T" | WTrtFAccNT: "P,E,h,sh \ e : NT \ P,E,h,sh \ e\F{D} : T" | WTrtSFAcc: "\ P \ C has F,Static:T in D \ \ P,E,h,sh \ C\\<^sub>sF{D} : T" | WTrtFAss: "\ P,E,h,sh \ e\<^sub>1 : Class C; P \ C has F,NonStatic:T in D; P,E,h,sh \ e\<^sub>2 : T\<^sub>2; P \ T\<^sub>2 \ T \ \ P,E,h,sh \ e\<^sub>1\F{D}:=e\<^sub>2 : Void" | WTrtFAssNT: "\ P,E,h,sh \ e\<^sub>1:NT; P,E,h,sh \ e\<^sub>2 : T\<^sub>2 \ \ P,E,h,sh \ e\<^sub>1\F{D}:=e\<^sub>2 : Void" | WTrtSFAss: "\ P,E,h,sh \ e\<^sub>2 : T\<^sub>2; P \ C has F,Static:T in D; P \ T\<^sub>2 \ T \ \ P,E,h,sh \ C\\<^sub>sF{D}:=e\<^sub>2 : Void" | WTrtCall: "\ P,E,h,sh \ e : Class C; P \ C sees M,NonStatic:Ts \ T = (pns,body) in D; P,E,h,sh \ es [:] Ts'; P \ Ts' [\] Ts \ \ P,E,h,sh \ e\M(es) : T" | WTrtCallNT: "\ P,E,h,sh \ e : NT; P,E,h,sh \ es [:] Ts \ \ P,E,h,sh \ e\M(es) : T" | WTrtSCall: "\ P \ C sees M,Static:Ts \ T = (pns,body) in D; P,E,h,sh \ es [:] Ts'; P \ Ts' [\] Ts; M = clinit \ sh D = \(sfs,Processing)\ \ es = map Val vs \ \ P,E,h,sh \ C\\<^sub>sM(es) : T" | WTrtBlock: "P,E(V\T),h,sh \ e : T' \ P,E,h,sh \ {V:T; e} : T'" | WTrtSeq: "\ P,E,h,sh \ e\<^sub>1:T\<^sub>1; P,E,h,sh \ e\<^sub>2:T\<^sub>2 \ \ P,E,h,sh \ e\<^sub>1;;e\<^sub>2 : T\<^sub>2" | WTrtCond: "\ P,E,h,sh \ e : Boolean; P,E,h,sh \ e\<^sub>1:T\<^sub>1; P,E,h,sh \ e\<^sub>2:T\<^sub>2; P \ T\<^sub>1 \ T\<^sub>2 \ P \ T\<^sub>2 \ T\<^sub>1; P \ T\<^sub>1 \ T\<^sub>2 \ T = T\<^sub>2; P \ T\<^sub>2 \ T\<^sub>1 \ T = T\<^sub>1 \ \ P,E,h,sh \ if (e) e\<^sub>1 else e\<^sub>2 : T" | WTrtWhile: "\ P,E,h,sh \ e : Boolean; P,E,h,sh \ c:T \ \ P,E,h,sh \ while(e) c : Void" | WTrtThrow: "\ P,E,h,sh \ e : T\<^sub>r; is_refT T\<^sub>r \ \ P,E,h,sh \ throw e : T" | WTrtTry: "\ P,E,h,sh \ e\<^sub>1 : T\<^sub>1; P,E(V \ Class C),h,sh \ e\<^sub>2 : T\<^sub>2; P \ T\<^sub>1 \ T\<^sub>2 \ \ P,E,h,sh \ try e\<^sub>1 catch(C V) e\<^sub>2 : T\<^sub>2" | WTrtInit: "\ P,E,h,sh \ e : T; \C' \ set (C#Cs). is_class P C'; \sub_RI e; \C' \ set (tl Cs). \sfs. sh C' = \(sfs,Processing)\; b \ (\C' \ set Cs. \sfs. sh C' = \(sfs,Processing)\); distinct Cs; supercls_lst P Cs \ \ P,E,h,sh \ INIT C (Cs, b) \ e : T" | WTrtRI: "\ P,E,h,sh \ e : T; P,E,h,sh \ e' : T'; \C' \ set (C#Cs). is_class P C'; \sub_RI e'; \C' \ set (C#Cs). not_init C' e; \C' \ set Cs. \sfs. sh C' = \(sfs,Processing)\; \sfs. sh C = \(sfs, Processing)\ \ (sh C = \(sfs, Error)\ \ e = THROW NoClassDefFoundError); distinct (C#Cs); supercls_lst P (C#Cs) \ \ P,E,h,sh \ RI(C, e);Cs \ e' : T'" \ \well-typed expression lists\ | WTrtNil: "P,E,h,sh \ [] [:] []" | WTrtCons: "\ P,E,h,sh \ e : T; P,E,h,sh \ es [:] Ts \ \ P,E,h,sh \ e#es [:] T#Ts" (*<*) declare WTrt_WTrts.intros[intro!] WTrtNil[iff] declare WTrtFAcc[rule del] WTrtFAccNT[rule del] WTrtSFAcc[rule del] WTrtFAss[rule del] WTrtFAssNT[rule del] WTrtSFAss[rule del] WTrtCall[rule del] WTrtCallNT[rule del] WTrtSCall[rule del] lemmas WTrt_induct = WTrt_WTrts.induct [split_format (complete)] and WTrt_inducts = WTrt_WTrts.inducts [split_format (complete)] (*>*) subsection\Easy consequences\ lemma [iff]: "(P,E,h,sh \ [] [:] Ts) = (Ts = [])" -(*<*) -apply(rule iffI) -apply (auto elim: WTrts.cases) -done -(*>*) +(*<*)by(rule iffI) (auto elim: WTrts.cases)(*>*) lemma [iff]: "(P,E,h,sh \ e#es [:] T#Ts) = (P,E,h,sh \ e : T \ P,E,h,sh \ es [:] Ts)" -(*<*) -apply(rule iffI) -apply (auto elim: WTrts.cases) -done -(*>*) +(*<*)by(rule iffI) (auto elim: WTrts.cases)(*>*) lemma [iff]: "(P,E,h,sh \ (e#es) [:] Ts) = (\U Us. Ts = U#Us \ P,E,h,sh \ e : U \ P,E,h,sh \ es [:] Us)" -(*<*) -apply(rule iffI) -apply (auto elim: WTrts.cases) -done -(*>*) +(*<*)by(rule iffI) (auto elim: WTrts.cases)(*>*) lemma [simp]: "\Ts. (P,E,h,sh \ es\<^sub>1 @ es\<^sub>2 [:] Ts) = (\Ts\<^sub>1 Ts\<^sub>2. Ts = Ts\<^sub>1 @ Ts\<^sub>2 \ P,E,h,sh \ es\<^sub>1 [:] Ts\<^sub>1 & P,E,h,sh \ es\<^sub>2[:]Ts\<^sub>2)" (*<*) -apply(induct_tac es\<^sub>1) - 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 fastforce -done +proof(induct es\<^sub>1) + case (Cons a list) + let ?lhs = "\Ts. (\U Us. Ts = U # Us \ P,E,h,sh \ a : U \ + (\Ts\<^sub>1 Ts\<^sub>2. Us = Ts\<^sub>1 @ Ts\<^sub>2 \ P,E,h,sh \ list [:] Ts\<^sub>1 \ P,E,h,sh \ es\<^sub>2 [:] Ts\<^sub>2))" + let ?rhs = "\Ts. (\Ts\<^sub>1 Ts\<^sub>2. Ts = Ts\<^sub>1 @ Ts\<^sub>2 \ + (\U Us. Ts\<^sub>1 = U # Us \ P,E,h,sh \ a : U \ P,E,h,sh \ list [:] Us) \ P,E,h,sh \ es\<^sub>2 [:] Ts\<^sub>2)" + { fix Ts assume "?lhs Ts" + then have "?rhs Ts" by (auto intro: Cons_eq_appendI) + } + moreover { + fix Ts assume "?rhs Ts" + then have "?lhs Ts" by fastforce + } + ultimately have "\Ts. ?lhs Ts = ?rhs Ts" by(rule iffI) + then show ?case by (clarsimp simp: Cons) +qed simp (*>*) lemma [iff]: "P,E,h,sh \ Val v : T = (typeof\<^bsub>h\<^esub> v = Some T)" -(*<*) -apply(rule iffI) -apply (auto elim: WTrt.cases) -done -(*>*) +(*<*)proof(rule iffI) qed (auto elim: WTrt.cases)(*>*) lemma [iff]: "P,E,h,sh \ Var v : T = (E v = Some T)" -(*<*) -apply(rule iffI) -apply (auto elim: WTrt.cases) -done -(*>*) +(*<*)proof(rule iffI) qed (auto elim: WTrt.cases)(*>*) lemma [iff]: "P,E,h,sh \ e\<^sub>1;;e\<^sub>2 : T\<^sub>2 = (\T\<^sub>1. P,E,h,sh \ e\<^sub>1:T\<^sub>1 \ P,E,h,sh \ e\<^sub>2:T\<^sub>2)" -(*<*) -apply(rule iffI) -apply (auto elim: WTrt.cases) -done -(*>*) +(*<*)proof(rule iffI) qed (auto elim: WTrt.cases)(*>*) lemma [iff]: "P,E,h,sh \ {V:T; e} : T' = (P,E(V\T),h,sh \ e : T')" -(*<*) -apply(rule iffI) -apply (auto elim: WTrt.cases) -done -(*>*) +(*<*)proof(rule iffI) qed (auto elim: WTrt.cases)(*>*) + (*<*) inductive_cases WTrt_elim_cases[elim!]: "P,E,h,sh \ v :=e : T" "P,E,h,sh \ if (e) e\<^sub>1 else e\<^sub>2 : T" "P,E,h,sh \ while(e) c : T" "P,E,h,sh \ throw e : T" "P,E,h,sh \ try e\<^sub>1 catch(C V) e\<^sub>2 : T" "P,E,h,sh \ Cast D e : T" "P,E,h,sh \ e\F{D} : T" "P,E,h,sh \ C\\<^sub>sF{D} : T" "P,E,h,sh \ e\F{D} := v : T" "P,E,h,sh \ C\\<^sub>sF{D} := v : T" "P,E,h,sh \ e\<^sub>1 \bop\ e\<^sub>2 : T" "P,E,h,sh \ new C : T" "P,E,h,sh \ e\M{D}(es) : T" "P,E,h,sh \ C\\<^sub>sM{D}(es) : T" "P,E,h,sh \ INIT C (Cs,b) \ e : T" "P,E,h,sh \ RI(C,e);Cs \ e' : T" (*>*) subsection\Some interesting lemmas\ lemma WTrts_Val[simp]: "\Ts. (P,E,h,sh \ map Val vs [:] Ts) = (map (typeof\<^bsub>h\<^esub>) vs = map Some Ts)" (*<*) -apply(induct vs) - apply simp -apply(case_tac Ts) - apply simp -apply simp -done +proof(induct vs) + case (Cons a vs) + then show ?case by(case_tac Ts; simp) +qed simp (*>*) lemma WTrts_same_length: "\Ts. P,E,h,sh \ es [:] Ts \ length es = length Ts" (*<*)by(induct es type:list)auto(*>*) lemma WTrt_env_mono: "P,E,h,sh \ e : T \ (\E'. E \\<^sub>m E' \ P,E',h,sh \ e : T)" and "P,E,h,sh \ es [:] Ts \ (\E'. E \\<^sub>m E' \ P,E',h,sh \ es [:] Ts)" (*<*) proof(induct rule: WTrt_inducts) - case (WTrtVar E V T) - then show ?case by(simp add: WTrtVar map_le_def dom_def) + case WTrtVar then show ?case by(simp add: map_le_def dom_def) next - case (WTrtLAss E V T e T') - then show ?case by(force simp: map_le_def) + case WTrtLAss then show ?case by(force simp:map_le_def) qed(fastforce intro: WTrt_WTrts.intros)+ (*>*) lemma WTrt_hext_mono: "P,E,h,sh \ e : T \ h \ h' \ P,E,h',sh \ e : T" and WTrts_hext_mono: "P,E,h,sh \ es [:] Ts \ h \ h' \ P,E,h',sh \ es [:] Ts" (*<*) -apply(induct rule: WTrt_inducts) -apply(simp add: WTrtNew) -apply(fastforce simp: WTrtCast) -apply(fastforce simp: WTrtVal dest:hext_typeof_mono) -apply(simp add: WTrtVar) -apply(fastforce simp add: WTrtBinOpEq) -apply(fastforce simp add: WTrtBinOpAdd) -apply(fastforce simp add: WTrtLAss) -apply(fast intro: WTrtFAcc) -apply(simp add: WTrtFAccNT) -apply(fast intro: WTrtSFAcc) -apply(fastforce simp: WTrtFAss del:WTrt_WTrts.intros WTrt_elim_cases) -apply(fastforce simp: WTrtFAssNT) -apply(fastforce simp: WTrtSFAss del:WTrt_WTrts.intros WTrt_elim_cases) -apply(fastforce simp: WTrtCall) -apply(fastforce simp: WTrtCallNT) -using WTrtSCall apply blast -apply(fastforce) -apply(fastforce simp add: WTrtSeq) -apply(fastforce simp add: WTrtCond) -apply(fastforce simp add: WTrtWhile) -apply(fastforce simp add: WTrtThrow) -apply(fastforce simp: WTrtTry) -apply(simp add: WTrtInit) -apply(simp add: WTrtRI) -apply(simp add: WTrtNil) -apply(simp add: WTrtCons) -done +proof(induct rule: WTrt_inducts) + case WTrtVal then show ?case by(simp add: hext_typeof_mono) +qed(fastforce intro: WTrt_WTrts.intros)+ (*>*) lemma WTrt_shext_mono: "P,E,h,sh \ e : T \ sh \\<^sub>s sh' \ \sub_RI e \ P,E,h,sh' \ e : T" and WTrts_shext_mono: "P,E,h,sh \ es [:] Ts \ sh \\<^sub>s sh' \ \sub_RIs es \ P,E,h,sh' \ es [:] Ts" (*<*) by(induct rule: WTrt_inducts) (auto simp add: WTrt_WTrts.intros) (*>*) lemma WTrt_hext_shext_mono: "P,E,h,sh \ e : T \ h \ h' \ sh \\<^sub>s sh' \ \sub_RI e \ P,E,h',sh' \ e : T" by(auto intro: WTrt_hext_mono WTrt_shext_mono) lemma WTrts_hext_shext_mono: "P,E,h,sh \ es [:] Ts \ h \ h' \ sh \\<^sub>s sh' \ \sub_RIs es \ P,E,h',sh' \ es [:] Ts" by(auto intro: WTrts_hext_mono WTrts_shext_mono) lemma WT_implies_WTrt: "P,E \ e :: T \ P,E,h,sh \ e : T" and WTs_implies_WTrts: "P,E \ es [::] Ts \ P,E,h,sh \ es [:] Ts" (*<*) -apply(induct rule: WT_WTs_inducts) -apply fast -apply (fast) -apply(fastforce dest:typeof_lit_typeof) -apply(simp) -apply(fastforce) -apply(fastforce) -apply(fastforce) -apply(meson WTrtFAcc has_visible_field) -apply(meson WTrtSFAcc has_visible_field) -apply(meson WTrtFAss has_visible_field) -apply(meson WTrtSFAss has_visible_field) -apply(fastforce simp: WTrtCall) -apply(fastforce simp: WTrtSCall) -apply(fastforce) -apply(fastforce) -apply(fastforce simp: WTrtCond) -apply(fastforce) -apply(fastforce) -apply(fastforce) -apply(simp) -apply(simp) -done +proof(induct rule: WT_WTs_inducts) + case WTVal then show ?case by(fastforce dest: typeof_lit_typeof) +next + case WTFAcc + then show ?case by(fastforce simp: WTrtFAcc has_visible_field) +next + case WTSFAcc + then show ?case by(fastforce simp: WTrtSFAcc has_visible_field) +next + case WTFAss + then show ?case by(fastforce simp: WTrtFAss dest: has_visible_field) +next + case WTSFAss + then show ?case by(fastforce simp: WTrtSFAss dest: has_visible_field) +qed(fastforce intro: WTrt_WTrts.intros)+ (*>*) end