header {* \isaheader{Small Step Semantics} *}
theory SmallStep imports
Expr
State
"../Common/ExternalCall"
begin
consts blocks :: "'a list * ty list * val list * ('a,'b) exp => ('a,'b) exp"
recdef blocks "measure(λ(Vs,Ts,vs,e). size Vs)"
"blocks(V#Vs, T#Ts, v#vs, e) = {V:T=⌊v⌋; blocks(Vs,Ts,vs,e)}"
"blocks([],[],[],e) = e"
lemma [simp]:
"[| size vs = size Vs; size Ts = size Vs |] ==> fv(blocks(Vs,Ts,vs,e)) = fv e - set Vs"
apply(induct rule:blocks.induct)
apply simp_all
apply blast
done
lemma expr_locks_blocks:
"[| length vs = length pns; length Ts = length pns |]
==> expr_locks (blocks (pns, Ts, vs, e)) = expr_locks e"
by(induct pns Ts vs e rule: blocks.induct)(auto)
types
J_thread_action = "(addr,thread_id,expr × locals,heap,addr,obs_event option) thread_action"
translations
"J_thread_action" <= (type) "(nat,nat,expr × (message_string \<rightharpoonup> val),heap,nat,obs_event option) thread_action"
definition extNTA2J :: "J_prog => (cname × mname × addr) => expr × locals"
where "extNTA2J P = (λ(C, M, a). let (D,Ts,T,pns,body) = method P C M
in ({this:Class D=⌊Addr a⌋; body}, empty))"
lemma extNTA2J_iff [simp]:
"extNTA2J P (C, M, a) = ({this:Class (fst (method P C M))=⌊Addr a⌋; snd (snd (snd (snd (method P C M))))}, empty)"
by(simp add: extNTA2J_def split_beta)
abbreviation extTA2J :: "J_prog => external_thread_action => J_thread_action"
where "extTA2J P ≡ convert_extTA (extNTA2J P)"
primrec extRet2J :: "val + addr => ('a, 'b) exp"
where
"extRet2J (Inl v) = Val v"
| "extRet2J (Inr a) = Throw a"
text{* Locking mechanism:
The expression on which the thread is synchronized is evaluated first to a value.
If this expression evaluates to null, a null pointer expression is thrown.
If this expression evaluates to an address, a lock must be obtained on this address, the
sync expression is rewritten to insync.
For insync expressions, the body expression may be evaluated.
If the body expression is only a value or a thrown exception, the lock is released and
the synchronized expression reduces to the body's expression. This is the normal Java semantics,
not the one as presented in LNCS 1523, Cenciarelli/Knapp/Reus/Wirsing. There
the expression on which the thread synchronized is evaluated except for the last step.
If the thread can obtain the lock on the object immediately after the last evaluation step, the evaluation is
done and the lock acquired. If the lock cannot be obtained, the evaluation step is discarded. If another thread
changes the evaluation result of this last step, the thread then will try to synchronize on the new object. *}
inductive red :: "(external_thread_action => (addr,thread_id,'x,heap,addr,obs_event option) thread_action) => J_prog =>
expr => (heap × locals) => (addr,thread_id,'x,heap,addr,obs_event option) thread_action => expr => (heap × locals) => bool"
("_,_ \<turnstile> ((1〈_,/_〉) -_->/ (1〈_,/_〉))" [51,51,0,0,0,0,0] 81)
and reds :: "(external_thread_action => (addr,thread_id,'x,heap,addr,obs_event option) thread_action) => J_prog =>
expr list => (heap × locals) => (addr,thread_id,'x,heap,addr,obs_event option) thread_action => expr list => (heap × locals) => bool"
("_,_ \<turnstile> ((1〈_,/_〉) [-_->]/ (1〈_,/_〉))" [51,51,0,0,0,0,0] 81)
for extTA :: "external_thread_action => (addr,thread_id,'x,heap,addr,obs_event option) thread_action" and P :: J_prog
where
RedNew:
"[| new_Addr h = Some a; P \<turnstile> C has_fields FDTs; h' = h(a\<mapsto>(Obj C (init_fields FDTs))) |]
==> extTA,P \<turnstile> 〈new C, (h, l)〉 -ε-> 〈addr a, (h', l)〉"
| RedNewFail:
"new_Addr (hp s) = None ==>
extTA,P \<turnstile> 〈new C, s〉 -ε-> 〈THROW OutOfMemory, s〉"
| NewArrayRed:
"extTA,P \<turnstile> 〈e, s〉 -ta-> 〈e', s'〉 ==> extTA,P \<turnstile> 〈newA T⌊e⌉, s〉 -ta-> 〈newA T⌊e'⌉, s'〉"
| RedNewArray:
"[| new_Addr h = Some a; i ≥ 0; h' = h(a \<mapsto> (Arr T (replicate (nat i) (default_val T)))) |]
==> extTA,P \<turnstile> 〈newA T⌊Val (Intg i)⌉, (h, l)〉 -ε-> 〈addr a, (h', l)〉"
| RedNewArrayNegative:
"i < 0 ==> extTA,P \<turnstile> 〈newA T⌊Val (Intg i)⌉, s〉 -ε-> 〈THROW NegativeArraySize, s〉"
| RedNewArrayFail:
"[| new_Addr h = None; i ≥ 0 |]
==> extTA,P \<turnstile> 〈newA T⌊Val (Intg i)⌉, (h, l)〉 -ε-> 〈THROW OutOfMemory, (h, l)〉"
| CastRed:
"extTA,P \<turnstile> 〈e, s〉 -ta-> 〈e', s'〉 ==> extTA,P \<turnstile> 〈Cast C e, s〉 -ta-> 〈Cast C e', s'〉"
| RedCast:
"[| typeofhp s v = ⌊U⌋; P \<turnstile> U ≤ T |]
==> extTA,P \<turnstile> 〈Cast T (Val v), s〉 -ε-> 〈Val v, s〉"
| RedCastFail:
"[| typeofhp s v = ⌊U⌋; ¬ P \<turnstile> U ≤ T |]
==> extTA,P \<turnstile> 〈Cast T (Val v), s〉 -ε-> 〈THROW ClassCast, s〉"
| BinOpRed1:
"extTA,P \<turnstile> 〈e, s〉 -ta-> 〈e', s'〉 ==> extTA,P \<turnstile> 〈e «bop» e2, s〉 -ta-> 〈e' «bop» e2, s'〉"
| BinOpRed2:
"extTA,P \<turnstile> 〈e, s〉 -ta-> 〈e', s'〉 ==> extTA,P \<turnstile> 〈(Val v) «bop» e, s〉 -ta-> 〈(Val v) «bop» e', s'〉"
| RedBinOp:
"binop bop v1 v2 = Some v ==>
extTA,P \<turnstile> 〈(Val v1) «bop» (Val v2), s〉 -ε-> 〈Val v, s〉"
| RedVar:
"lcl s V = Some v ==>
extTA,P \<turnstile> 〈Var V, s〉 -ε-> 〈Val v, s〉"
| LAssRed:
"extTA,P \<turnstile> 〈e, s〉 -ta-> 〈e', s'〉 ==> extTA,P \<turnstile> 〈V:=e, s〉 -ta-> 〈V:=e', s'〉"
| RedLAss:
"extTA,P \<turnstile> 〈V:=(Val v), (h, l)〉 -ε-> 〈unit, (h, l(V \<mapsto> v))〉"
| AAccRed1:
"extTA,P \<turnstile> 〈a, s〉 -ta-> 〈a', s'〉 ==> extTA,P \<turnstile> 〈a⌊i⌉, s〉 -ta-> 〈a'⌊i⌉, s'〉"
| AAccRed2:
"extTA,P \<turnstile> 〈i, s〉 -ta-> 〈i', s'〉 ==> extTA,P \<turnstile> 〈(Val a)⌊i⌉, s〉 -ta-> 〈(Val a)⌊i'⌉, s'〉"
| RedAAccNull:
"extTA,P \<turnstile> 〈null⌊Val i⌉, s〉 -ε-> 〈THROW NullPointer, s〉"
| RedAAccBounds:
"[| hp s a = Some(Arr T el); i < 0 ∨ i ≥ int (length el) |]
==> extTA,P \<turnstile> 〈(addr a)⌊Val (Intg i)⌉, s〉 -ε-> 〈THROW ArrayIndexOutOfBounds, s〉"
| RedAAcc:
"[| hp s a = Some(Arr T el); i ≥ 0; i < int (length el) |]
==> extTA,P \<turnstile> 〈(addr a)⌊Val (Intg i)⌉, s〉 -ε-> 〈Val (el ! nat i), s〉"
| AAssRed1:
"extTA,P \<turnstile> 〈a, s〉 -ta-> 〈a', s'〉 ==> extTA,P \<turnstile> 〈a⌊i⌉ := e, s〉 -ta-> 〈a'⌊i⌉ := e, s'〉"
| AAssRed2:
"extTA,P \<turnstile> 〈i, s〉 -ta-> 〈i', s'〉 ==> extTA,P \<turnstile> 〈(Val a)⌊i⌉ := e, s〉 -ta-> 〈(Val a)⌊i'⌉ := e, s'〉"
| AAssRed3:
"extTA,P \<turnstile> 〈(e::expr), s〉 -ta-> 〈e', s'〉 ==> extTA,P \<turnstile> 〈(Val a)⌊Val i⌉ := e, s〉 -ta-> 〈(Val a)⌊Val i⌉ := e', s'〉"
| RedAAssNull:
"extTA,P \<turnstile> 〈null⌊Val i⌉ := (Val e::expr), s〉 -ε-> 〈THROW NullPointer, s〉"
| RedAAssBounds:
"[| hp s a = Some(Arr T el); i < 0 ∨ i ≥ int (length el) |]
==> extTA,P \<turnstile> 〈(addr a)⌊Val (Intg i)⌉ := (Val e::expr), s〉 -ε-> 〈THROW ArrayIndexOutOfBounds, s〉"
| RedAAssStore:
"[| hp s a = Some(Arr T el); i ≥ 0; i < int (length el); typeofhp s w = ⌊U⌋; ¬ (P \<turnstile> U ≤ T) |]
==> extTA,P \<turnstile> 〈(addr a)⌊Val (Intg i)⌉ := (Val w::expr), s〉 -ε-> 〈THROW ArrayStore, s〉"
| RedAAss:
"[| h a = Some(Arr T el); i ≥ 0; i < int (length el); typeofh w = Some U; P \<turnstile> U ≤ T;
h' = h(a \<mapsto> (Arr T (el[nat i := w]))) |]
==> extTA,P \<turnstile> 〈(addr a)⌊Val (Intg i)⌉ := Val w::expr, (h, l)〉 -ε-> 〈unit, (h', l)〉"
| ALengthRed:
"extTA,P \<turnstile> 〈a, s〉 -ta-> 〈a', s'〉 ==> extTA,P \<turnstile> 〈a•length, s〉 -ta-> 〈a'•length, s'〉"
| RedALength:
"hp s a = ⌊Arr T el⌋ ==> extTA,P \<turnstile> 〈addr a•length, s〉 -ε-> 〈Val (Intg (int (length el))), s〉"
| RedALengthNull:
"extTA,P \<turnstile> 〈null•length, s〉 -ε-> 〈THROW NullPointer, s〉"
| FAccRed:
"extTA,P \<turnstile> 〈e, s〉 -ta-> 〈e', s'〉 ==> extTA,P \<turnstile> 〈e•F{D}, s〉 -ta-> 〈e'•F{D}, s'〉"
| RedFAcc:
"[| hp s a = Some(Obj C fs); fs(F,D) = Some v |]
==> extTA,P \<turnstile> 〈(addr a)•F{D}, s〉 -ε-> 〈Val v, s〉"
| RedFAccNull:
"extTA,P \<turnstile> 〈null•F{D}, s〉 -ε-> 〈THROW NullPointer, s〉"
| FAssRed1:
"extTA,P \<turnstile> 〈e, s〉 -ta-> 〈e', s'〉 ==> extTA,P \<turnstile> 〈e•F{D}:=e2, s〉 -ta-> 〈e'•F{D}:=e2, s'〉"
| FAssRed2:
"extTA,P \<turnstile> 〈(e::expr), s〉 -ta-> 〈e', s'〉 ==> extTA,P \<turnstile> 〈Val v•F{D}:=e, s〉 -ta-> 〈Val v•F{D}:=e', s'〉"
| RedFAss:
"h a = Some(Obj C fs) ==>
extTA,P \<turnstile> 〈(addr a)•F{D}:=(Val v :: expr), (h, l)〉 -ε-> 〈unit, (h(a \<mapsto> (Obj C (fs((F,D) \<mapsto> v)))), l)〉"
| RedFAssNull:
"extTA,P \<turnstile> 〈null•F{D}:=Val v::expr, s〉 -ε-> 〈THROW NullPointer, s〉"
| CallObj:
"extTA,P \<turnstile> 〈e, s〉 -ta-> 〈e', s'〉 ==> extTA,P \<turnstile> 〈e•M(es), s〉 -ta-> 〈e'•M(es), s'〉"
| CallParams:
"extTA,P \<turnstile> 〈es, s〉 [-ta->] 〈es',s'〉 ==>
extTA,P \<turnstile> 〈(Val v)•M(es),s〉 -ta-> 〈(Val v)•M(es'),s'〉"
| RedCall:
"[| hp s a = ⌊Obj C fs⌋; ¬ is_external_call P (Class C) M; P \<turnstile> C sees M:Ts->T = (pns,body) in D;
size vs = size pns; size Ts = size pns |]
==> extTA,P \<turnstile> 〈(addr a)•M(map Val vs), s〉 -ε-> 〈blocks(this#pns, Class D#Ts, Addr a#vs, body), s〉"
| RedCallExternal:
"[| typeofhp s (Addr a) = ⌊T⌋; is_external_call P T M; P \<turnstile> 〈a•M(vs), hp s〉 -ta->ext 〈va, h'〉;
ta' = extTA ta; e' = extRet2J va; s' = (h', lcl s) |]
==> extTA,P \<turnstile> 〈(addr a)•M(map Val vs), s〉 -ta'-> 〈e', s'〉"
| RedCallNull:
"extTA,P \<turnstile> 〈null•M(map Val vs), s〉 -ε-> 〈THROW NullPointer, s〉"
| BlockRed:
"extTA,P \<turnstile> 〈e, (h, l(V:=vo))〉 -ta-> 〈e', (h', l')〉
==> extTA,P \<turnstile> 〈{V:T=vo; e}, (h, l)〉 -ta-> 〈{V:T=l' V; e'}, (h', l'(V := l V))〉"
| RedBlock:
"extTA,P \<turnstile> 〈{V:T=vo; Val u}, s〉 -ε-> 〈Val u, s〉"
| SynchronizedRed1:
"extTA,P \<turnstile> 〈o', s〉 -ta-> 〈o'', s'〉 ==> extTA,P \<turnstile> 〈sync(o') e, s〉 -ta-> 〈sync(o'') e, s'〉"
| SynchronizedNull:
"extTA,P \<turnstile> 〈sync(null) e, s〉 -ε-> 〈THROW NullPointer, s〉"
| LockSynchronized:
"hp s a = ⌊arrobj⌋ ==> extTA,P \<turnstile> 〈sync(addr a) e, s〉 -ε\<lbrace>l Lock->a \<rbrace>\<lbrace>oSynchronization a\<rbrace>-> 〈insync(a) e, s〉"
| SynchronizedRed2:
"extTA,P \<turnstile> 〈e, s〉 -ta-> 〈e', s'〉 ==> extTA,P \<turnstile> 〈insync(a) e, s〉 -ta-> 〈insync(a) e', s'〉"
| UnlockSynchronized:
"extTA,P \<turnstile> 〈insync(a) (Val v), s〉 -ε\<lbrace>l Unlock->a \<rbrace>\<lbrace>oSynchronization a\<rbrace>-> 〈Val v, s〉"
| SeqRed:
"extTA,P \<turnstile> 〈e, s〉 -ta-> 〈e', s'〉 ==> extTA,P \<turnstile> 〈e;;e2, s〉 -ta-> 〈e';;e2, s'〉"
| RedSeq:
"extTA,P \<turnstile> 〈(Val v);;e, s〉 -ε-> 〈e, s〉"
| CondRed:
"extTA,P \<turnstile> 〈b, s〉 -ta-> 〈b', s'〉 ==> extTA,P \<turnstile> 〈if (b) e1 else e2, s〉 -ta-> 〈if (b') e1 else e2, s'〉"
| RedCondT:
"extTA,P \<turnstile> 〈if (true) e1 else e2, s〉 -ε-> 〈e1, s〉"
| RedCondF:
"extTA,P \<turnstile> 〈if (false) e1 else e2, s〉 -ε-> 〈e2, s〉"
| RedWhile:
"extTA,P \<turnstile> 〈while(b) c, s〉 -ε-> 〈if (b) (c;;while(b) c) else unit, s〉"
| ThrowRed:
"extTA,P \<turnstile> 〈e, s〉 -ta-> 〈e', s'〉 ==> extTA,P \<turnstile> 〈throw e, s〉 -ta-> 〈throw e', s'〉"
| RedThrowNull:
"extTA,P \<turnstile> 〈throw null, s〉 -ε-> 〈THROW NullPointer, s〉"
| TryRed:
"extTA,P \<turnstile> 〈e, s〉 -ta-> 〈e', s'〉 ==> extTA,P \<turnstile> 〈try e catch(C V) e2, s〉 -ta-> 〈try e' catch(C V) e2, s'〉"
| RedTry:
"extTA,P \<turnstile> 〈try (Val v) catch(C V) e2, s〉 -ε-> 〈Val v, s〉"
| RedTryCatch:
"[| hp s a = Some(Obj D fs); P \<turnstile> D \<preceq>* C |]
==> extTA,P \<turnstile> 〈try (Throw a) catch(C V) e2, s〉 -ε-> 〈{V:Class C=⌊Addr a⌋; e2}, s〉"
| RedTryFail:
"[| hp s a = Some(Obj D fs); ¬ P \<turnstile> D \<preceq>* C |]
==> extTA,P \<turnstile> 〈try (Throw a) catch(C V) e2, s〉 -ε-> 〈Throw a, s〉"
| ListRed1:
"extTA,P \<turnstile> 〈e,s〉 -ta-> 〈e',s'〉 ==>
extTA,P \<turnstile> 〈e#es,s〉 [-ta->] 〈e'#es,s'〉"
| ListRed2:
"extTA,P \<turnstile> 〈es,s〉 [-ta->] 〈es',s'〉 ==>
extTA,P \<turnstile> 〈Val v # es,s〉 [-ta->] 〈Val v # es',s'〉"
-- "Exception propagation"
| NewArrayThrow: "extTA,P \<turnstile> 〈newA T⌊Throw a⌉, s〉 -ε-> 〈Throw a, s〉"
| CastThrow: "extTA,P \<turnstile> 〈Cast C (Throw a), s〉 -ε-> 〈Throw a, s〉"
| BinOpThrow1: "extTA,P \<turnstile> 〈(Throw a) «bop» e2, s〉 -ε-> 〈Throw a, s〉"
| BinOpThrow2: "extTA,P \<turnstile> 〈(Val v1) «bop» (Throw a), s〉 -ε-> 〈Throw a, s〉"
| LAssThrow: "extTA,P \<turnstile> 〈V:=(Throw a), s〉 -ε-> 〈Throw a, s〉"
| AAccThrow1: "extTA,P \<turnstile> 〈(Throw a)⌊i⌉, s〉 -ε-> 〈Throw a, s〉"
| AAccThrow2: "extTA,P \<turnstile> 〈(Val v)⌊Throw a⌉, s〉 -ε-> 〈Throw a, s〉"
| AAssThrow1: "extTA,P \<turnstile> 〈(Throw a)⌊i⌉ := e, s〉 -ε-> 〈Throw a, s〉"
| AAssThrow2: "extTA,P \<turnstile> 〈(Val v)⌊Throw a⌉ := e, s〉 -ε-> 〈Throw a, s〉"
| AAssThrow3: "extTA,P \<turnstile> 〈(Val v)⌊Val i⌉ := Throw a :: expr, s〉 -ε-> 〈Throw a, s〉"
| ALengthThrow: "extTA,P \<turnstile> 〈(Throw a)•length, s〉 -ε-> 〈Throw a, s〉"
| FAccThrow: "extTA,P \<turnstile> 〈(Throw a)•F{D}, s〉 -ε-> 〈Throw a, s〉"
| FAssThrow1: "extTA,P \<turnstile> 〈(Throw a)•F{D}:=e2, s〉 -ε-> 〈Throw a, s〉"
| FAssThrow2: "extTA,P \<turnstile> 〈Val v•F{D}:=(Throw a::expr), s〉 -ε-> 〈Throw a, s〉"
| CallThrowObj: "extTA,P \<turnstile> 〈(Throw a)•M(es), s〉 -ε-> 〈Throw a, s〉"
| CallThrowParams: "[| es = map Val vs @ Throw a # es' |] ==> extTA,P \<turnstile> 〈(Val v)•M(es), s〉 -ε-> 〈Throw a, s〉"
| BlockThrow: "extTA,P \<turnstile> 〈{V:T=vo; Throw a}, s〉 -ε-> 〈Throw a, s〉"
| SynchronizedThrow1: "extTA,P \<turnstile> 〈sync(Throw a) e, s〉 -ε-> 〈Throw a, s〉"
| SynchronizedThrow2: "extTA,P \<turnstile> 〈insync(a) Throw ad, s〉 -ε\<lbrace>l Unlock->a \<rbrace>\<lbrace>oSynchronization a\<rbrace>-> 〈Throw ad, s〉"
| SeqThrow: "extTA,P \<turnstile> 〈(Throw a);;e2, s〉 -ε-> 〈Throw a, s〉"
| CondThrow: "extTA,P \<turnstile> 〈if (Throw a) e1 else e2, s〉 -ε-> 〈Throw a, s〉"
| ThrowThrow: "extTA,P \<turnstile> 〈throw(Throw a), s〉 -ε-> 〈Throw a, s〉"
inductive_cases red_cases:
"extTA,P \<turnstile> 〈new C, s〉 -ta-> 〈e', s'〉"
"extTA,P \<turnstile> 〈newA T⌊e⌉, s〉 -ta-> 〈e', s'〉"
"extTA,P \<turnstile> 〈Cast T e, s〉 -ta-> 〈e', s'〉"
"extTA,P \<turnstile> 〈e «bop» e', s〉 -ta-> 〈e'', s'〉"
"extTA,P \<turnstile> 〈Var V, s〉 -ta-> 〈e', s'〉"
"extTA,P \<turnstile> 〈V:=e, s〉 -ta-> 〈e', s'〉"
"extTA,P \<turnstile> 〈a⌊i⌉, s〉 -ta-> 〈e', s'〉"
"extTA,P \<turnstile> 〈a⌊i⌉ := e, s〉 -ta-> 〈e', s'〉"
"extTA,P \<turnstile> 〈a•length, s〉 -ta-> 〈e', s'〉"
"extTA,P \<turnstile> 〈e•F{D}, s〉 -ta-> 〈e', s'〉"
"extTA,P \<turnstile> 〈e•F{D} := e', s〉 -ta-> 〈e'', s'〉"
"extTA,P \<turnstile> 〈e•M(es), s〉 -ta-> 〈e', s'〉"
"extTA,P \<turnstile> 〈{V:T=vo; e}, s〉 -ta-> 〈e', s'〉"
"extTA,P \<turnstile> 〈sync(o') e, s〉 -ta-> 〈e', s'〉"
"extTA,P \<turnstile> 〈insync(a) e, s〉 -ta-> 〈e', s'〉"
"extTA,P \<turnstile> 〈e;;e', s〉 -ta-> 〈e'', s'〉"
"extTA,P \<turnstile> 〈if (b) e1 else e2, s 〉 -ta-> 〈e', s'〉"
"extTA,P \<turnstile> 〈while (b) e, s 〉 -ta-> 〈e', s'〉"
"extTA,P \<turnstile> 〈throw e, s 〉 -ta-> 〈e', s'〉"
"extTA,P \<turnstile> 〈try e catch(C V) e', s〉 -ta-> 〈e'', s'〉"
inductive_cases reds_cases:
"extTA,P \<turnstile> 〈e # es, s〉 [-ta->] 〈es', s'〉"
abbreviation red' :: "J_prog => expr => (heap × locals) => J_thread_action => expr => (heap × locals) => bool"
("_ \<turnstile> ((1〈_,/_〉) -_->/ (1〈_,/_〉))" [51,0,0,0,0,0] 81)
where "red' P ≡ red (extTA2J P) P"
abbreviation reds' :: "J_prog => expr list => (heap × locals) => J_thread_action => expr list => (heap × locals) => bool"
("_ \<turnstile> ((1〈_,/_〉) [-_->]/ (1〈_,/_〉))" [51,0,0,0,0,0] 81)
where "reds' P ≡ reds (extTA2J P) P"
subsection{* The reflexive transitive closure *}
abbreviation
Step :: "(external_thread_action => (addr,thread_id,'x,heap,addr,obs_event option) thread_action) => J_prog =>
expr => (heap × locals) => ((addr,thread_id,'x,heap,addr,obs_event option) thread_action) list =>
expr => (heap × locals) => bool"
("_,_ \<turnstile> ((1〈_,/_〉) -_->*/ (1〈_,/_〉))" [51,51,0,0,0,0,0] 81)
where
"extTA,P \<turnstile> 〈e, s〉 -ta->* 〈e', s'〉 == rtrancl3p (λ(e, s) ta (e', s'). extTA,P \<turnstile> 〈e, s〉 -ta-> 〈e', s'〉) (e,s) ta (e',s')"
lemmas Step_induct = rtrancl3p.induct[where r = "λ(e, s) ta (e', s'). extTA,P \<turnstile> 〈e, s〉 -ta-> 〈e', s'〉", split_format (complete), simplified, consumes 1, case_names refl step]
subsection{*Some easy lemmas*}
lemma [iff]:
"¬ extTA,P \<turnstile> 〈Val v, s〉 -ta-> 〈e', s'〉"
by(fastsimp elim:red.cases)
lemma red_no_val [dest]:
"[| extTA,P \<turnstile> 〈e, s〉 -tas-> 〈e', s'〉; is_val e |] ==> False"
by(auto)
lemma [iff]: "¬ extTA,P \<turnstile> 〈Throw a, s〉 -ta-> 〈e', s'〉"
by(fastsimp elim: red_cases)
lemma reds_preserves_len:
"extTA,P \<turnstile> 〈es, s〉 [-ta->] 〈es', s'〉 ==> length es' = length es"
by(induct es arbitrary: es')(auto elim: reds.cases)
lemma red_hext_incr: "extTA,P \<turnstile> 〈e, s〉 -ta-> 〈e', s'〉 ==> hp s \<unlhd> hp s'"
and reds_hext_incr: "extTA,P \<turnstile> 〈es, s〉 [-ta->] 〈es', s'〉 ==> hp s \<unlhd> hp s'"
proof(induct rule:red_reds.inducts)
case (RedNew C FDTs a h h' l) thus ?case by(auto dest: new_Addr_SomeD intro: hext_new simp del: fun_upd_apply)
next
case RedNewArray thus ?case by(auto dest: new_Addr_SomeD intro: hext_new simp del: fun_upd_apply)
next
case RedAAss thus ?case by(fastsimp dest:new_Addr_SomeD simp:hext_def split:if_splits)
next
case RedFAss thus ?case by(fastsimp simp add:hext_def split:if_splits)
next
case RedCallExternal thus ?case by(auto intro: red_external_hext)
qed fastsimp+
lemma red_lcl_incr: "extTA,P \<turnstile> 〈e, s〉 -ta-> 〈e', s'〉 ==> dom (lcl s) ⊆ dom (lcl s')"
and reds_lcl_incr: "extTA,P \<turnstile> 〈es, s〉 [-ta->] 〈es', s'〉 ==> dom (lcl s) ⊆ dom (lcl s')"
apply(induct rule:red_reds.inducts)
apply(auto simp del: fun_upd_apply split: split_if_asm)
done
lemma red_lcl_add_aux:
"extTA,P \<turnstile> 〈e, s〉 -ta-> 〈e', s'〉 ==> extTA,P \<turnstile> 〈e, (hp s, l0 ++ lcl s)〉 -ta-> 〈e', (hp s', l0 ++ lcl s')〉"
and reds_lcl_add_aux:
"extTA,P \<turnstile> 〈es, s〉 [-ta->] 〈es', s'〉 ==> extTA,P \<turnstile> 〈es, (hp s, l0 ++ lcl s)〉 [-ta->] 〈es', (hp s', l0 ++ lcl s')〉"
proof (induct arbitrary: l0 and l0 rule:red_reds.inducts)
case (BlockRed e h x V vo ta e' h' x' T)
note IH = `!!l0. extTA,P \<turnstile> 〈e,(hp (h, x(V := vo)), l0 ++ lcl (h, x(V := vo)))〉 -ta-> 〈e',(hp (h', x'), l0 ++ lcl (h', x'))〉`[simplified]
have lrew: "!!x x'. x(V := vo) ++ x'(V := vo) = (x ++ x')(V := vo)"
by(simp add:expand_fun_eq map_add_def)
have lrew1: "!!X X' X'' vo. (X(V := vo) ++ X')(V := (X ++ X'') V) = X ++ X'(V := X'' V)"
by(simp add: expand_fun_eq map_add_def)
have lrew2: "!!X X'. (X(V := None) ++ X') V = X' V"
by(simp add: map_add_def)
show ?case
proof(cases vo)
case None
from IH[of "l0(V := vo)"]
show ?thesis
apply(simp del: fun_upd_apply add: lrew)
apply(drule red_reds.BlockRed)
by(simp only: lrew1 None lrew2)
next
case (Some v)
with `extTA,P \<turnstile> 〈e,(h, x(V := vo))〉 -ta-> 〈e',(h', x')〉`
have "x' V ≠ None"
by -(drule red_lcl_incr, auto split: split_if_asm)
with IH[of "l0(V := vo)"]
show ?thesis
apply(clarsimp simp del: fun_upd_apply simp add: lrew)
apply(drule red_reds.BlockRed)
by(simp add: lrew1 Some del: fun_upd_apply)
qed
next
case (RedTryFail s a D fs C V e2 l0) thus ?case
by(auto intro: red_reds.RedTryFail)
qed(fastsimp intro:red_reds.intros simp del: fun_upd_apply)+
lemma red_lcl_add: "extTA,P \<turnstile> 〈e, (h, l)〉 -ta-> 〈e', (h', l')〉 ==> extTA,P \<turnstile> 〈e, (h, l0 ++ l)〉 -ta-> 〈e', (h', l0 ++ l')〉"
and reds_lcl_add: "extTA,P \<turnstile> 〈es, (h, l)〉 [-ta->] 〈es', (h', l')〉 ==> extTA,P \<turnstile> 〈es, (h, l0 ++ l)〉 [-ta->] 〈es', (h', l0 ++ l')〉"
by(auto dest:red_lcl_add_aux reds_lcl_add_aux)
lemma Step_lcl_add:
"extTA,P \<turnstile> 〈e, (h, l)〉 -ta->* 〈e', (h', l')〉 ==> extTA,P \<turnstile> 〈e, (h, l0 ++ l)〉 -ta->* 〈e', (h', l0 ++ l')〉"
proof(induct rule: Step_induct)
case refl thus ?case by(auto intro: rtrancl3p.intros)
next
case (step e h l ta e' h' l' las tas cas was obs e'' h'' l'')
have IH: "extTA,P \<turnstile> 〈e,(h, l0 ++ l)〉 -ta->* 〈e',(h', l0 ++ l')〉"
and red: "extTA,P \<turnstile> 〈e',(h', l')〉 -(las, tas, cas, was, obs)-> 〈e'',(h'', l'')〉" by fact+
from red have "extTA,P \<turnstile> 〈e',(h', l0 ++ l')〉 -(las, tas, cas, was, obs)-> 〈e'',(h'', l0 ++ l'')〉" by(rule red_lcl_add)
with IH show ?case by(auto elim: rtrancl3p_step)
qed
lemma reds_no_val [dest]:
"[| extTA,P \<turnstile> 〈es, s〉 [-ta->] 〈es', s'〉; is_vals es |] ==> False"
apply(induct es arbitrary: s ta es' s')
apply(blast elim: reds.cases)
apply(erule reds.cases)
apply(auto, blast)
done
lemma red_no_Throw [dest!]:
"extTA,P \<turnstile> 〈Throw a, s〉 -ta-> 〈e', s'〉 ==> False"
by(auto elim!: red_cases)
lemma red_lcl_sub:
"[| extTA,P \<turnstile> 〈e, s〉 -ta-> 〈e', s'〉; fv e ⊆ W |] ==> extTA,P \<turnstile> 〈e, (hp s, (lcl s)|`W)〉 -ta-> 〈e', (hp s', (lcl s')|`W)〉"
and reds_lcl_sub:
"[| extTA,P \<turnstile> 〈es, s〉 [-ta->] 〈es', s'〉; fvs es ⊆ W |] ==> extTA,P \<turnstile> 〈es, (hp s, (lcl s)|`W)〉 [-ta->] 〈es', (hp s', (lcl s')|`W)〉"
proof(induct arbitrary: W and W rule: red_reds.inducts)
case (RedLAss V v h l W)
have "extTA,P \<turnstile> 〈V:=Val v,(h, l |` W)〉 -ε-> 〈unit,(h, (l |`W)(V \<mapsto> v))〉"
by(rule red_reds.RedLAss)
with RedLAss show ?case by(simp del: fun_upd_apply)
next
case (BlockRed e h x V vo ta e' h' x' T)
have IH: "!!W. fv e ⊆ W ==> extTA,P \<turnstile> 〈e,(hp (h, x(V := vo)), lcl (h, x(V := vo)) |` W)〉 -ta-> 〈e',(hp (h', x'), lcl (h', x') |` W)〉" by fact
from `fv {V:T=vo; e} ⊆ W` have fve: "fv e ⊆ insert V W" by auto
show ?case
proof(cases "V ∈ W")
case True
with fve have "fv e ⊆ W" by auto
from True IH[OF this] have "extTA,P \<turnstile> 〈e,(h, (x |` W )(V := vo))〉 -ta-> 〈e',(h', x' |` W)〉" by(simp)
with True have "extTA,P \<turnstile> 〈{V:T=vo; e},(h, x |` W)〉 -ta-> 〈{V:T=x' V; e'},(h', (x' |` W)(V := x V))〉"
by -(drule red_reds.BlockRed[where T=T], simp)
with True show ?thesis by(simp del: fun_upd_apply)
next
case False
with IH[OF fve] have "extTA,P \<turnstile> 〈e,(h, (x |` W)(V := vo))〉 -ta-> 〈e',(h', x' |` insert V W)〉" by(simp)
with False have "extTA,P \<turnstile> 〈{V:T=vo; e},(h, x |` W)〉 -ta-> 〈{V:T=x' V; e'},(h', (x' |` W))〉"
by -(drule red_reds.BlockRed[where T=T],simp)
with False show ?thesis by(simp del: fun_upd_apply)
qed
next
case RedTryFail thus ?case by(auto intro: red_reds.RedTryFail)
qed(fastsimp intro: red_reds.intros)+
lemma red_notfree_unchanged: "[| extTA,P \<turnstile> 〈e, s〉 -ta-> 〈e', s'〉; V ∉ fv e |] ==> lcl s' V = lcl s V"
and reds_notfree_unchanged: "[| extTA,P \<turnstile> 〈es, s〉 [-ta->] 〈es', s'〉; V ∉ fvs es |] ==> lcl s' V = lcl s V"
apply(induct rule: red_reds.inducts)
apply(fastsimp)+
done
lemma red_dom_lcl: "extTA,P \<turnstile> 〈e, s〉 -ta-> 〈e', s'〉 ==> dom (lcl s') ⊆ dom (lcl s) ∪ fv e"
and reds_dom_lcl: "extTA,P \<turnstile> 〈es, s〉 [-ta->] 〈es', s'〉 ==> dom (lcl s') ⊆ dom (lcl s) ∪ fvs es"
proof (induct rule:red_reds.inducts)
case (BlockRed e h x V vo ta e' h' x' T)
thus ?case by(clarsimp)(fastsimp split:split_if_asm)
qed auto
subsection {* Final expressions *}
inductive final :: "('a,'b) exp => bool" where
"final (Val v)"
| "final (Throw a)"
declare final.cases [elim]
declare final.intros[simp]
lemmas finalE[consumes 1, case_names Val Throw] = final.cases
lemma final_iff: "final e <-> (∃v. e = Val v) ∨ (∃a. e = Throw a)"
by(auto)
lemma final_locks: "final e ==> expr_locks e l = 0"
by(auto elim: finalE)
constdefs
finals:: "('a,'b) exp list => bool"
"finals es ≡ (∃vs. es = map Val vs) ∨ (∃vs a es'. es = map Val vs @ Throw a # es')"
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 fastsimp
apply(rule disjI2)
apply clarsimp
apply(case_tac vs)
apply simp
apply fastsimp
apply(erule disjE)
apply clarsimp
apply(rule_tac x="v#vs" in exI)
apply(simp)
apply(rule disjI2)
apply clarsimp
apply(rule_tac x = "v#vs" in exI)
apply simp
done
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(erule disjE)
apply(fastsimp)
apply clarsimp
apply(case_tac vs)
apply simp
apply fastsimp
apply clarsimp
apply(rule_tac x = "[]" in exI)
apply simp
apply(erule_tac x="[]" in allE)
apply(fastsimp)
done
lemma not_finals_ConsI: "¬ final e ==> ¬ finals(e#es)"
apply(clarsimp simp add:finals_def final_iff)
apply(rule conjI)
apply(fastsimp)
apply(clarsimp)
apply(case_tac vs)
apply auto
done
end