(* Title: HOL/Bali/Eval.thy Author: David von Oheimb
*)
subsection \<open>Operational evaluation (big-step) semantics of Java expressions and
statements \<close>
theory Eval imports State DeclConcepts begin
text\<open>
improvements over Java Specification 1.0: \begin{itemize} \item dynamic method lookup does not need to consider the return type
(cf.15.11.4.4) \item throw raises a NullPointer exception if a null reference is given, and
each throw of a standard exception yield a fresh exception object
(was not specified) \item if there is not enough memory even to allocate an OutOfMemory exception,
evaluation/execution fails, i.e. simply stops (was not specified) \item array assignment checks lhs (and may throw exceptions) before evaluating
rhs \item fixed exact positions of class initializations
(immediate at first active use) \end{itemize}
design issues: \begin{itemize} \item evaluation vs. (single-step) transition semantics
evaluation semantics chosen, because: \begin{itemize} \item[++] less verbose and therefore easier to read (and to handle in proofs) \item[+] more abstract \item[+] intermediate values (appearing in recursive rules) need not be
stored explicitly, e.g. no call body construct or stack of invocation
frames containing local variables and return addresses for method calls
needed \item[+] convenient rule induction for subject reduction theorem \item[-] no interleaving (for parallelism) can be described \item[-] stating a property of infinite executions requires the meta-level
argument that this property holds for any finite prefixes of it
(e.g. stopped using a counter that is decremented to zero andthen
throwing an exception) \end{itemize} \item unified evaluation for variables, expressions, expression lists,
statements \item the value entry in statement rules is redundant \item the value entry in rules is irrelevant in case of exceptions, but its full
inclusion helps to make the rule structure independent of exception occurrence. \item as irrelevant value entries are ignored, it does not matter if they are
unique. For simplicity, (fixed) arbitrary values are preferred over "free" values. \item the rule format is such that the start state may contain an exception. \begin{itemize} \item[++] faciliates exception handling \item[+] symmetry \end{itemize} \item the rules are defined carefully in order to be applicable even in not
type-correct situations (yielding undefined values),
e.g. \<open>the_Addr (Val (Bool b)) = undefined\<close>. \begin{itemize} \item[++] fewer rules \item[-] less readable because of auxiliary functions like \<open>the_Addr\<close> \end{itemize}
Alternative: "defensive" evaluation throwing some InternalError exception incase of (impossible, for correct programs) type mismatches \item there is exactly one rule per syntactic construct \begin{itemize} \item[+] no redundancy in case distinctions \end{itemize} \item halloc fails iff there is no free heap address. When there is
only one free heap address left, it returns an OutOfMemory exception. In this way it is guaranteed that when an OutOfMemory exception is thrown for
the first time, there is a free location on the heap to allocate it. \item the allocation of objects that represent standard exceptions is deferred
until execution of any enclosing catch clause, which is transparent to
the program. \begin{itemize} \item[-] requires an auxiliary execution relation \item[++] avoids copies of allocation code and awkward case distinctions
(whether there is enough memory to allocate the exception) in
evaluation rules \end{itemize} \item unfortunately \<open>new_Addr\<close> is not directly executable because of
Hilbert operator. \end{itemize}
simplifications: \begin{itemize} \item local variables are initialized with default values
(no definite assignment) \item garbage collection not considered, therefore also no finalizers \item stack overflow and memory overflow during class initialization not
modelled \item exceptions in initializations not replaced by ExceptionInInitializerError \end{itemize} \<close>
type_synonym vvar = "val \ (val \ state \ state)" type_synonym vals = "(val, vvar, val list) sum3" translations
(type) "vvar" <= (type) "val \ (val \ state \ state)"
(type) "vals" <= (type) "(val, vvar, val list) sum3"
text\<open>To avoid redundancy and to reduce the number of rules, there is only
one evaluation rule for each syntactic term. This isalso true for variables
(e.g. see the rules below for\<open>LVar\<close>, \<open>FVar\<close> and \<open>AVar\<close>).
So evaluation of a variable must capture both possible further uses:
read (rule \<open>Acc\<close>) or write (rule \<open>Ass\<close>) to the variable.
Therefor a variable evaluates to a special value\<^term>\<open>vvar\<close>, which is
a pair, consisting of the current value (for later read access) and an update function (for later write access). Because
during assignment to an array variable an exception may occur if the types
don't match, the update function is very generic: it transforms the
full state. This generic update function causes some technical trouble during
some proofs (e.g. type safety, correctness of definite assignment). There we
need to prove some additional invariant on this update functionto prove the
assignment correct, since the update function could potentially alter the whole
state in an arbitrary manner. This invariant must be carried around through
the whole induction.
So for future approaches it may be better not to take
such a generic update function, but only to store the address and the kind
of variable (array (+ element type), local variable or field) for later
assignment. \<close>
definition
assign :: "('a \ state \ state) \ 'a \ state \ state" where "assign f v = (\(x,s). let (x',s') = (if x = None then f v else id) (x,s) in (x',if x' = None then s' else s))"
(* lemma assign_Norm_Norm [simp]: "f v \<lparr>abrupt=None,store=s\<rparr> = \<lparr>abrupt=None,store=s'\<rparr> \<Longrightarrow> assign f v \<lparr>abrupt=None,store=s\<rparr> = \<lparr>abrupt=None,store=s'\<rparr>" by (simp add: assign_def Let_def)
*)
lemma assign_Norm_Norm [simp]: "f v (Norm s) = Norm s' \ assign f v (Norm s) = Norm s'" by (simp add: assign_def Let_def)
(* lemma assign_Norm_Some [simp]: "\<lbrakk>abrupt (f v \<lparr>abrupt=None,store=s\<rparr>) = Some y\<rbrakk> \<Longrightarrow> assign f v \<lparr>abrupt=None,store=s\<rparr> = \<lparr>abrupt=Some y,store =s\<rparr>" by (simp add: assign_def Let_def split_beta)
*)
lemma assign_Norm_Some [simp]: "\abrupt (f v (Norm s)) = Some y\ \<Longrightarrow> assign f v (Norm s) = (Some y,s)" by (simp add: assign_def Let_def split_beta)
lemma assign_Some [simp]: "assign f v (Some x,s) = (Some x,s)" by (simp add: assign_def Let_def split_beta)
lemma assign_Some1 [simp]: "\ normal s \ assign f v s = s" by (auto simp add: assign_def Let_def split_beta)
lemma assign_supd [simp]: "assign (\v. supd (f v)) v (x,s)
= (x, if x = None then f v s else s)" apply auto done
lemma assign_raise_if [simp]: "assign (\v (x,s). ((raise_if (b s v) xcpt) x, f v s)) v (x, s) =
(raise_if (b s v) xcpt x, if x=None \<and> \<not>b s v then f v s else s)" apply (case_tac "x = None") apply auto done
(* lemma assign_raise_if [simp]: "assign (\<lambda>v s. \<lparr>abrupt=(raise_if (b (store s) v) xcpt) (abrupt s), store = f v (store s)\<rparr>) v s = \<lparr>abrupt=raise_if (b (store s) v) xcpt (abrupt s), store= if (abrupt s)=None \<and> \<not>b (store s) v then f v (store s) else (store s)\<rparr>" apply (case_tac "abrupt s = None") apply auto done
*)
definition
init_comp_ty :: "ty \ stmt" where"init_comp_ty T = (if (\C. T = Class C) then Init (the_Class T) else Skip)"
definition
invocation_class :: "inv_mode \ st \ val \ ref_ty \ qtname" where "invocation_class m s a' statT =
(case m of
Static \<Rightarrow> if (\<exists> statC. statT = ClassT statC) then the_Class (RefT statT)
else Object
| SuperM \<Rightarrow> the_Class (RefT statT)
| IntVir \<Rightarrow> obj_class (lookup_obj s a'))"
definition
invocation_declclass :: "prog \ inv_mode \ st \ val \ ref_ty \ sig \ qtname" where "invocation_declclass G m s a' statT sig =
declclass (the (dynlookup G statT
(invocation_class m s a' statT)
sig))"
lemma invocation_class_IntVir [simp]: "invocation_class IntVir s a' statT = obj_class (lookup_obj s a')" by (simp add: invocation_class_def)
lemma dynclass_SuperM [simp]: "invocation_class SuperM s a' statT = the_Class (RefT statT)" by (simp add: invocation_class_def)
lemma invocation_class_Static [simp]: "invocation_class Static s a' statT = (if (\ statC. statT = ClassT statC) then the_Class (RefT statT)
else Object)" by (simp add: invocation_class_def)
definition
init_lvars :: "prog \ qtname \ sig \ inv_mode \ val \ val list \ state \ state" where "init_lvars G C sig mode a' pvs =
(\<lambda>(x,s). let m = mthd (the (methd G C sig));
l = \<lambda> k.
(case k of
EName e \<Rightarrow> (case e of
VNam v \<Rightarrow> (Map.empty ((pars m)[\<mapsto>]pvs)) v
| Res \<Rightarrow> None)
| This \<Rightarrow> (if mode=Static then None else Some a')) in set_lvars l (if mode = Static then x else np a' x,s))"
lemma init_lvars_def2: \<comment> \<open>better suited for simplification\<close> "init_lvars G C sig mode a' pvs (x,s) =
set_lvars
(\<lambda> k.
(case k of
EName e \<Rightarrow> (case e of
VNam v \<Rightarrow> (Map.empty ((pars (mthd (the (methd G C sig))))[\<mapsto>]pvs)) v
| Res \<Rightarrow> None)
| This \<Rightarrow> (if mode=Static then None else Some a')))
(if mode = Static then x else np a' x,s)" apply (unfold init_lvars_def) apply (simp (no_asm) add: Let_def) done
definition
body :: "prog \ qtname \ sig \ expr" where "body G C sig =
(let m = the (methd G C sig) in Body (declclass m) (stmt (mbody (mthd m))))"
lemma body_def2: \<comment> \<open>better suited for simplification\<close> "body G C sig = Body (declclass (the (methd G C sig)))
(stmt (mbody (mthd (the (methd G C sig)))))" apply (unfold body_def Let_def) apply auto done
subsubsection "variables"
definition
lvar :: "lname \ st \ vvar" where"lvar vn s = (the (locals s vn), \v. supd (lupd(vn\v)))"
definition
fvar :: "qtname \ bool \ vname \ val \ state \ vvar \ state" where "fvar C stat fn a' s =
(let (oref,xf) = if stat then (Stat C,id)
else (Heap (the_Addr a'),np a');
n = Inl (fn,C);
f = (\<lambda>v. supd (upd_gobj oref n v)) in ((the (values (the (globs (store s) oref)) n),f),abupd xf s))"
definition
avar :: "prog \ val \ val \ state \ vvar \ state" where "avar G i' a' s =
(let oref = Heap (the_Addr a');
i = the_Intg i';
n = Inr i;
(T,k,cs) = the_Arr (globs (store s) oref);
f = (\<lambda>v (x,s). (raise_if (\<not>G,s\<turnstile>v fits T)
ArrStore x
,upd_gobj oref n v s)) in ((the (cs n),f),abupd (raise_if (\<not>i in_bounds k) IndOutBound \<circ> np a') s))"
lemma fvar_def2: \<comment> \<open>better suited for simplification\<close> "fvar C stat fn a' s =
((the
(values
(the (globs (store s) (if stat then Stat C else Heap (the_Addr a'))))
(Inl (fn,C)))
,(\<lambda>v. supd (upd_gobj (if stat then Stat C else Heap (the_Addr a'))
(Inl (fn,C))
v)))
,abupd (if stat then id else np a') s) " apply (unfold fvar_def) apply (simp (no_asm) add: Let_def split_beta) done
definition
check_field_access :: "prog \ qtname \ qtname \ vname \ bool \ val \ state \ state" where "check_field_access G accC statDeclC fn stat a' s =
(let oref = if stat then Stat statDeclC
else Heap (the_Addr a');
dynC = case oref of
Heap a \<Rightarrow> obj_class (the (globs (store s) oref))
| Stat C \<Rightarrow> C;
f = (the (table_of (DeclConcepts.fields G dynC) (fn,statDeclC))) in abupd
(error_if (\<not> G\<turnstile>Field fn (statDeclC,f) in dynC dyn_accessible_from accC)
AccessViolation)
s)"
definition
check_method_access :: "prog \ qtname \ ref_ty \ inv_mode \ sig \ val \ state \ state" where "check_method_access G accC statT mode sig a' s =
(let invC = invocation_class mode (store s) a' statT;
dynM = the (dynlookup G statT invC sig) in abupd
(error_if (\<not> G\<turnstile>Methd sig dynM in invC dyn_accessible_from accC)
AccessViolation)
s)"
subsubsection "evaluation judgments"
inductive
halloc :: "[prog,state,obj_tag,loc,state]\bool" (\_\_ \halloc _\_\ _\[61,61,61,61,61]60) for G::prog where\<comment> \<open>allocating objects on the heap, cf. 12.5\<close>
| New: "\new_Addr (heap s) = Some a;
(x,oi') = (if atleast_free (heap s) (Suc (Suc 0)) then (None,oi)
else (Some (Xcpt (Loc a)),CInst (SXcpt OutOfMemory)))\<rbrakk> \<Longrightarrow>
G\<turnstile>Norm s \<midarrow>halloc oi\<succ>a\<rightarrow> (x,init_obj G oi' (Heap a) s)"
inductive sxalloc :: "[prog,state,state]\bool" (\_\_ \sxalloc\ _\[61,61,61]60) for G::prog where\<comment> \<open>allocating exception objects for
standard exceptions (other than OutOfMemory)\<close>
inductive
eval :: "[prog,state,term,vals,state]\bool" (\_\_ \_\\ '(_, _')\ [61,61,80,0,0]60) and exec ::"[prog,state,stmt ,state]\bool"(\_\_ \_\ _\ [61,61,65, 61]60) and evar ::"[prog,state,var ,vvar,state]\bool"(\_\_ \_=\_\ _\[61,61,90,61,61]60) and eval'::"[prog,state,expr ,val ,state]\bool"(\_\_ \_-\_\ _\[61,61,80,61,61]60) and evals::"[prog,state,expr list ,
val list ,state]\<Rightarrow>bool"(\<open>_\<turnstile>_ \<midarrow>_\<doteq>\<succ>_\<rightarrow> _\<close>[61,61,61,61,61]60) for G::prog where
\<comment> \<open>A continue jump from the while body \<^term>\<open>c\<close> is handled by
this rule. If a continue jump with the proper label was invoked inside \<^term>\<open>c\<close> this label (Cont l) is deleted out of the abrupt component of
the state before the iterative evaluation of the while statement.
A break jump is handled by the Lab Statement \<open>Lab l (while\<dots>)\<close>.\<close>
| Loop: "\G\Norm s0 \e-\b\ s1; if the_Bool b then (G\<turnstile>s1 \<midarrow>c\<rightarrow> s2 \<and>
G\<turnstile>(abupd (absorb (Cont l)) s2) \<midarrow>l\<bullet> While(e) c\<rightarrow> s3)
else s3 = s1\<rbrakk> \<Longrightarrow>
G\<turnstile>Norm s0 \<midarrow>l\<bullet> While(e) c\<rightarrow> s3"
\<comment> \<open>cf. 14.18.2\<close>
| Fin: "\G\Norm s0 \c1\ (x1,s1);
G\<turnstile>Norm s1 \<midarrow>c2\<rightarrow> s2;
s3=(if (\<exists> err. x1=Some (Error err)) then (x1,s1)
else abupd (abrupt_if (x1\<noteq>None) x1) s2) \<rbrakk> \<Longrightarrow>
G\<turnstile>Norm s0 \<midarrow>c1 Finally c2\<rightarrow> s3" \<comment> \<open>cf. 12.4.2, 8.5\<close>
| Init: "\the (class G C) = c; if inited C (globs s0) then s3 = Norm s0
else (G\<turnstile>Norm (init_class_obj G C s0) \<midarrow>(if C = Object then Skip else Init (super c))\<rightarrow> s1 \<and>
G\<turnstile>set_lvars Map.empty s1 \<midarrow>init c\<rightarrow> s2 \<and> s3 = restore_lvars s1 s2)\<rbrakk> \<Longrightarrow>
G\<turnstile>Norm s0 \<midarrow>Init C\<rightarrow> s3" \<comment> \<open>This class initialisation rule is a little bit inaccurate. Look at the
exact sequence:
(1) The current class object (the static fields) are initialised
(\<open>init_class_obj\<close>),
(2) the superclasses are initialised,
(3) the static initialiser of the current classis invoked.
More precisely we should expect another ordering, namely 2 1 3.
But we can't just naively toggle 1 and 2. By calling \<open>init_class_obj\<close>
before initialising the superclasses, we also implicitly record that
we have started to initialise the current class (by setting an valuefor the class object). This becomes
crucial for the completeness proof of the axiomatic semantics \<open>AxCompl.thy\<close>. Static initialisation requires an induction on
the number of classes not yet initialised (or to be more precise, classes were the initialisation has not yet begun).
So we could first assign a dummy valueto the class before
superclass initialisation and afterwards set the correct values.
But as long as we don't take memory overflow into account
when allocating class objects, we can leave things as they are for
convenience.\<close> \<comment> \<open>evaluation of expressions\<close>
\<comment> \<open>The interplay of \<^term>\<open>Call\<close>, \<^term>\<open>Methd\<close> and \<^term>\<open>Body\<close>:
Method invocation is split up into these three rules: \begin{itemize} \item [\<^term>\<open>Call\<close>] Calculates the target address and evaluates the
arguments of the method, andthen performs dynamic
or static lookup of the method, corresponding to the
call mode. Then the \<^term>\<open>Methd\<close> rule is evaluated
on the calculated declarationclass of the method
invocation. \item [\<^term>\<open>Methd\<close>] A syntactic bridge for the folded method body.
It is used by the axiomatic semantics to add the
proper hypothesis for recursive calls of the method. \item [\<^term>\<open>Body\<close>] An extra syntactic entity for the unfolded method
body was introduced to properly trigger class
initialisation. Without class initialisation we
could just evaluate the body statement. \end{itemize}\<close> \<comment> \<open>cf. 15.11.4.1, 15.11.4.2, 15.11.4.4, 15.11.4.5\<close>
| Call: "\G\Norm s0 \e-\a'\ s1; G\s1 \args\\vs\ s2;
D = invocation_declclass G mode (store s2) a' statT \name=mn,parTs=pTs\;
s3=init_lvars G D \<lparr>name=mn,parTs=pTs\<rparr> mode a' vs s2;
s3' = check_method_access G accC statT mode \name=mn,parTs=pTs\ a' s3;
G\<turnstile>s3' \<midarrow>Methd D \<lparr>name=mn,parTs=pTs\<rparr>-\<succ>v\<rightarrow> s4\<rbrakk> \<Longrightarrow>
G\<turnstile>Norm s0 \<midarrow>{accC,statT,mode}e\<cdot>mn({pTs}args)-\<succ>v\<rightarrow> (restore_lvars s2 s4)" \<comment> \<open>The accessibility check is after \<^term>\<open>init_lvars\<close>, to keep it simple. \<^term>\<open>init_lvars\<close> already tests for the absence of a null-pointer
reference incase of an instance method invocation.\<close>
| Methd: "\G\Norm s0 \body G D sig-\v\ s1\ \
G\<turnstile>Norm s0 \<midarrow>Methd D sig-\<succ>v\<rightarrow> s1"
| Body: "\G\Norm s0 \Init D\ s1; G\s1 \c\ s2;
s3 = (if (\<exists> l. abrupt s2 = Some (Jump (Break l)) \<or>
abrupt s2 = Some (Jump (Cont l))) then abupd (\<lambda> x. Some (Error CrossMethodJump)) s2
else s2)\<rbrakk> \<Longrightarrow>
G\<turnstile>Norm s0 \<midarrow>Body D c-\<succ>the (locals (store s2) Result) \<rightarrow>abupd (absorb Ret) s3" \<comment> \<open>cf. 14.15, 12.4.1\<close> \<comment> \<open>We filter out a break/continue in \<^term>\<open>s2\<close>, so that we can proof
definite assignment
correct, without the need of conformance of the state. By this the
different parts of the typesafety proof can be disentangled a little.\<close>
\<comment> \<open>cf. 15.10.1, 12.4.1\<close>
| FVar: "\G\Norm s0 \Init statDeclC\ s1; G\s1 \e-\a\ s2;
(v,s2') = fvar statDeclC stat fn a s2;
s3 = check_field_access G accC statDeclC fn stat a s2' \ \
G\<turnstile>Norm s0 \<midarrow>{accC,statDeclC,stat}e..fn=\<succ>v\<rightarrow> s3" \<comment> \<open>The accessibility check is after \<^term>\<open>fvar\<close>, to keep it simple. \<^term>\<open>fvar\<close> already tests for the absence of a null-pointer reference incase of an instance field\<close>
\<comment> \<open>cf. 15.12.1, 15.25.1\<close>
| AVar: "\G\ Norm s0 \e1-\a\ s1; G\s1 \e2-\i\ s2;
(v,s2') = avar G i a s2\ \
G\<turnstile>Norm s0 \<midarrow>e1.[e2]=\<succ>v\<rightarrow> s2'"
\<comment> \<open>evaluation of expression lists\<close>
inductive_cases eval_elim_cases [cases set]: "G\(Some xc,s) \t \\ (v, s')" "G\Norm s \In1r Skip \\ (x, s')" "G\Norm s \In1r (Jmp j) \\ (x, s')" "G\Norm s \In1r (l\ c) \\ (x, s')" "G\Norm s \In3 ([]) \\ (v, s')" "G\Norm s \In3 (e#es) \\ (v, s')" "G\Norm s \In1l (Lit w) \\ (v, s')" "G\Norm s \In1l (UnOp unop e) \\ (v, s')" "G\Norm s \In1l (BinOp binop e1 e2) \\ (v, s')" "G\Norm s \In2 (LVar vn) \\ (v, s')" "G\Norm s \In1l (Cast T e) \\ (v, s')" "G\Norm s \In1l (e InstOf T) \\ (v, s')" "G\Norm s \In1l (Super) \\ (v, s')" "G\Norm s \In1l (Acc va) \\ (v, s')" "G\Norm s \In1r (Expr e) \\ (x, s')" "G\Norm s \In1r (c1;; c2) \\ (x, s')" "G\Norm s \In1l (Methd C sig) \\ (x, s')" "G\Norm s \In1l (Body D c) \\ (x, s')" "G\Norm s \In1l (e0 ? e1 : e2) \\ (v, s')" "G\Norm s \In1r (If(e) c1 Else c2) \\ (x, s')" "G\Norm s \In1r (l\ While(e) c) \\ (x, s')" "G\Norm s \In1r (c1 Finally c2) \\ (x, s')" "G\Norm s \In1r (Throw e) \\ (x, s')" "G\Norm s \In1l (NewC C) \\ (v, s')" "G\Norm s \In1l (New T[e]) \\ (v, s')" "G\Norm s \In1l (Ass va e) \\ (v, s')" "G\Norm s \In1r (Try c1 Catch(tn vn) c2) \\ (x, s')" "G\Norm s \In2 ({accC,statDeclC,stat}e..fn) \\ (v, s')" "G\Norm s \In2 (e1.[e2]) \\ (v, s')" "G\Norm s \In1l ({accC,statT,mode}e\mn({pT}p)) \\ (v, s')" "G\Norm s \In1r (Init C) \\ (x, s')" declare not_None_eq [simp] (* IntDef.Zero_def [simp] *) declare split_paired_All [simp] split_paired_Ex [simp] declaration\<open>K (Simplifier.map_ss (fn ss => ss |> Simplifier.add_loop ("split_all_tac", split_all_tac)))\<close> declare if_split [split] if_split_asm [split]
option.split [split] option.split_asm [split]
lemma eval_Inj_elim: "G\s \t\\ (w,s') \<Longrightarrow> case t of
In1 ec \<Rightarrow> (case ec of
Inl e \<Rightarrow> (\<exists>v. w = In1 v)
| Inr c \<Rightarrow> w = \<diamondsuit>)
| In2 e \<Rightarrow> (\<exists>v. w = In2 v)
| In3 e \<Rightarrow> (\<exists>v. w = In3 v)" apply (erule eval_cases) apply auto apply (induct_tac "t") apply (rename_tac a, induct_tac "a") apply auto done
text\<open>The following simplification procedures set up the proper injections of
terms and their corresponding values in the evaluation relation:
E.g. an expression
(injection \<^term>\<open>In1l\<close> into terms) always evaluates to ordinary values
(injection \<^term>\<open>In1\<close> into generalised values \<^term>\<open>vals\<close>). \<close>
text\<open>\<open>Callee\<close>,\<open>InsInitE\<close>, \<open>InsInitV\<close>, \<open>FinA\<close> are only
used in smallstep semantics, not in the bigstep semantics. So their is no
valid evaluation of these terms \<close>
lemma eval_Callee: "G\Norm s\Callee l e-\v\ s' = False" proof - have False if eval: "G\s \t\\ (v,s')" and normal: "normal s" and callee: "t=In1l (Callee l e)" for s t v s' using that by induct auto thenshow ?thesis by (cases s') fastforce qed
lemma eval_InsInitE: "G\Norm s\InsInitE c e-\v\ s' = False" proof - have"False" if eval: "G\s \t\\ (v,s')" and normal: "normal s" and callee: "t=In1l (InsInitE c e)" for s t v s' using that by induct auto thenshow ?thesis by (cases s') fastforce qed
lemma eval_InsInitV: "G\Norm s\InsInitV c w=\v\ s' = False" proof - have"False" if eval: "G\s \t\\ (v,s')" and normal: "normal s" and callee: "t=In2 (InsInitV c w)" for s t v s' using that by induct auto thenshow ?thesis by (cases s') fastforce qed
lemma eval_FinA: "G\Norm s\FinA a c\ s' = False" proof - have"False" if eval: "G\s \t\\ (v,s')" and normal: "normal s" and callee: "t=In1r (FinA a c)" for s t v s' using that by induct auto thenshow ?thesis by (cases s') fastforce qed
lemma eval_no_abrupt_lemma: "\s s'. G\s \t\\ (w,s') \ normal s' \ normal s" by (erule eval_cases, auto)
lemma CondI: "\s1. \G\s \e-\b\ s1; G\s1 \(if the_Bool b then e1 else e2)-\v\ s2\ \
G\<turnstile>s \<midarrow>e ? e1 : e2-\<succ>(if normal s1 then v else undefined)\<rightarrow> s2" apply (case_tac "s", case_tac "a = None") by (auto intro!: eval.Cond)
lemma IfI: "\G\s \e-\v\ s1; G\s1 \(if the_Bool v then c1 else c2)\ s2\ \<Longrightarrow> G\<turnstile>s \<midarrow>If(e) c1 Else c2\<rightarrow> s2" apply (case_tac "s", case_tac "a = None") by (auto intro!: eval.If)
lemma MethdI: "G\s \body G C sig-\v\ s' \<Longrightarrow> G\<turnstile>s \<midarrow>Methd C sig-\<succ>v\<rightarrow> s'" apply (case_tac "s", case_tac "a = None") by (auto intro!: eval.Methd)
lemma eval_Call: "\G\Norm s0 \e-\a'\ s1; G\s1 \ps\\pvs\ s2;
D = invocation_declclass G mode (store s2) a' statT \name=mn,parTs=pTs\;
s3 = init_lvars G D \<lparr>name=mn,parTs=pTs\<rparr> mode a' pvs s2;
s3' = check_method_access G accC statT mode \name=mn,parTs=pTs\ a' s3;
G\<turnstile>s3'\<midarrow>Methd D \<lparr>name=mn,parTs=pTs\<rparr>-\<succ> v\<rightarrow> s4;
s4' = restore_lvars s2 s4\ \
G\<turnstile>Norm s0 \<midarrow>{accC,statT,mode}e\<cdot>mn({pTs}ps)-\<succ>v\<rightarrow> s4'" apply (drule eval.Call, assumption) apply (rule HOL.refl) apply simp+ done
lemma eval_Init: "\if inited C (globs s0) then s3 = Norm s0
else G\<turnstile>Norm (init_class_obj G C s0) \<midarrow>(if C = Object then Skip else Init (super (the (class G C))))\<rightarrow> s1 \<and>
G\<turnstile>set_lvars Map.empty s1 \<midarrow>(init (the (class G C)))\<rightarrow> s2 \<and>
s3 = restore_lvars s1 s2\<rbrakk> \<Longrightarrow>
G\<turnstile>Norm s0 \<midarrow>Init C\<rightarrow> s3" apply (rule eval.Init) apply auto done
lemma init_done: "initd C s \ G\s \Init C\ s" apply (case_tac "s", simp) apply (case_tac "a") apply safe apply (rule eval_Init) apply auto done
lemma halloc_xcpt [dest!]: "\s'. G\(Some xc,s) \halloc oi\a\ s' \ s'=(Some xc,s)" apply (erule_tac halloc_elim_cases) by auto
(* G\<turnstile>(x,(h,l)) \<midarrow>e\<succ>v\<rightarrow> (x',(h',l'))) \<Longrightarrow> l This = l' This" G\<turnstile>(x,(h,l)) \<midarrow>s \<rightarrow> (x',(h',l'))) \<Longrightarrow> l This = l' This"
*)
lemma eval_Methd: "G\s \In1l(body G C sig)\\ (w,s') \<Longrightarrow> G\<turnstile>s \<midarrow>In1l(Methd C sig)\<succ>\<rightarrow> (w,s')" apply (case_tac "s") apply (case_tac "a") apply clarsimp+ apply (erule eval.Methd) apply (drule eval_abrupt_lemma) apply force done
lemma eval_Body: "\G\Norm s0 \Init D\ s1; G\s1 \c\ s2;
res=the (locals (store s2) Result);
s3 = (if (\<exists> l. abrupt s2 = Some (Jump (Break l)) \<or>
abrupt s2 = Some (Jump (Cont l))) then abupd (\<lambda> x. Some (Error CrossMethodJump)) s2
else s2);
s4=abupd (absorb Ret) s3\<rbrakk> \<Longrightarrow>
G\<turnstile>Norm s0 \<midarrow>Body D c-\<succ>res\<rightarrow>s4" by (auto elim: eval.Body)
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.49Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.