(*
* Copyright 2016 , Data61 , CSIRO
*
* This software may be distributed and modified according to the terms of
* the BSD 2 - Clause license . Note that NO WARRANTY is provided .
* See " LICENSE_BSD2 . txt " for details .
*
* @ TAG ( DATA61_BSD )
*)
section ‹ COMPLX small-step semantics›
theory SmallStep
imports Language
begin
text ‹ The procedure environment›
type_synonym ('s,'p,'f) body = "'p ==> ('s,'p,'f) com option"
text ‹ State types›
datatype ('s,'f) xstate = Normal 's | Fault 'f | Stuck
lemma rtrancl_mono_proof[mono]:
"(∧ a b. x a b ⟶ y a b) ==> rtranclp x a b ⟶ rtranclp y a b"
apply (rule impI, rotate_tac, induct rule: rtranclp.induct)
apply simp_all
apply (metis rtranclp.intros )
done
primrec redex:: "('s,'p,'f)com ==> ('s,'p,'f)com"
where
"redex Skip = Skip" |
"redex (Basic f) = (Basic f)" |
"redex (Spec r) = (Spec r)" |
"redex (Seq c1 c2 ) = redex c1 " |
"redex (Cond b c1 c2 ) = (Cond b c1 c2 )" |
"redex (While b c) = (While b c)" |
"redex (Call p) = (Call p)" |
"redex (DynCom d) = (DynCom d)" |
"redex (Guard f b c) = (Guard f b c)" |
"redex (Throw) = Throw" |
"redex (Catch c1 c2 ) = redex c1 " |
"redex (Await b c) = Await b c" |
"redex (Parallel cs) = Parallel cs"
subsection ‹ Small-Step Computation: ‹ Γ ⊨ (c, s) → (c', s')› ›
text ‹ The final configuration is either of the form ‹ (Skip,_)› for normal
, or @{term "(Throw,Normal s)"} in case the program was started in
@{term "Normal"} state and terminated abruptly. Explicit abrupt states are removed
the language definition and thus do not need to be propogated. ›
type_synonym ('s,'p,'f) config = "('s,'p,'f)com × ('s,'f) xstate"
definition final:: "('s,'p,'f) config ==> bool" where
"final cfg = (fst cfg=Skip ∨ (fst cfg=Throw ∧ (∃ s. snd cfg=Normal s)))"
primrec atom_com :: "🍋 ‹ ('s,'p,'f) body ==> › ('s, 'p, 'f) com ==> bool" where
"atom_com Skip = True" |
"atom_com (Basic f) = True" |
"atom_com (Spec r) = True" |
"atom_com (Seq c1 c2 ) = (atom_com c1 ∧ atom_com c2 )" |
"atom_com (Cond b c1 c2 ) = (atom_com c1 ∧ atom_com c2 )" |
"atom_com (While b c) = atom_com c" |
(* Change to atom_com (Call p) = atom_com (\<Theta> p)
Butow do we pass function body from step? *)
"atom_com (Call p) = False" |
"atom_com (DynCom f) = (∀ s::'s. atom_com (f s))" |
"atom_com (Guard f g c) = atom_com c" |
"atom_com Throw = True" |
"atom_com (Catch c1 c2 ) = (atom_com c1 ∧ atom_com c2 )" |
"atom_com (Parallel cs) = False" |
"atom_com (Await b c) = False"
inductive
"step" ::"[('s,'p,'f) body, ('s,'p,'f) config,('s,'p,'f) config] ==> bool"
(‹ _⊨ (_ → / _)› [81 ,81 ,81 ] 100 )
and "step_rtrancl" :: "[('s,'p,'f) body, ('s,'p,'f) config,('s,'p,'f) config] ==> bool"
(‹ _ ⊨ (_ → * / _)› [81 ,81 ,81 ] 100 )
for Γ::"('s,'p,'f) body"
where
"Γ ⊨ a → * b ≡ (step Γ)* * a b"
| Basic: "Γ ⊨ (Basic f,Normal s) → (Skip,Normal (f s))"
| Spec: "(s,t) ∈ r ==> Γ ⊨ (Spec r,Normal s) → (Skip,Normal t)"
| SpecStuck: "∀ t. (s,t) ∉ r ==> Γ ⊨ (Spec r,Normal s) → (Skip,Stuck)"
| Guard: "s∈ g ==> Γ ⊨ (Guard f g c,Normal s) → (c,Normal s)"
| GuardFault: "s∉ g ==> Γ ⊨ (Guard f g c,Normal s) → (Skip,Fault f)"
| Seq: "Γ ⊨ (c1 ,s) → (c1 ',s')
==>
Γ ⊨ (Seq c1 c2 ,s) → (Seq c1 ' c2 , s')"
| SeqSkip: "Γ ⊨ (Seq Skip c2 ,s) → (c2 , s)"
| SeqThrow: "Γ ⊨ (Seq Throw c2 ,Normal s) → (Throw, Normal s)"
| CondTrue: "s∈ b ==> Γ ⊨ (Cond b c1 c2 ,Normal s) → (c1 ,Normal s)"
| CondFalse: "s∉ b ==> Γ ⊨ (Cond b c1 c2 ,Normal s) → (c2 ,Normal s)"
| WhileTrue: "[ s∈ b]
==>
Γ ⊨ (While b c,Normal s) → (Seq c (While b c),Normal s)"
| WhileFalse: "[ s∉ b]
==>
Γ ⊨ (While b c,Normal s) → (Skip,Normal s)"
| Call: "Γ p=Some b ==>
Γ ⊨ (Call p,Normal s) → (b,Normal s)"
| CallUndefined: "Γ p=None ==>
Γ ⊨ (Call p,Normal s) → (Skip,Stuck)"
| DynCom: "Γ ⊨ (DynCom c,Normal s) → (c s,Normal s)"
| Catch: "[ Γ ⊨ (c1 ,s) → (c1 ',s')]
==>
Γ ⊨ (Catch c1 c2 ,s) → (Catch c1 ' c2 ,s')"
| CatchSkip: "Γ ⊨ (Catch Skip c2 ,s) → (Skip,s)"
| CatchThrow: "Γ ⊨ (Catch Throw c2 ,Normal s) → (c2 ,Normal s)"
| FaultProp: "[ c≠ Skip; redex c = c] ==> Γ ⊨ (c,Fault f) → (Skip,Fault f)"
| StuckProp: "[ c≠ Skip; redex c = c] ==> Γ ⊨ (c,Stuck) → (Skip,Stuck)"
| Parallel: "[ i < length cs; Γ ⊨ (cs!i, s) → (c', s') ]
==> Γ ⊨ (Parallel cs, s) → (Parallel (cs[i := c']), s')"
| ParSkip: "[ ∀ c ∈ set cs. c = Skip ] ==> Γ ⊨ (Parallel cs, s) → (Skip, s)"
(* If exception is thrown, the parallel execution may either abort
immediately (rule ParThrow) or keep executing (rule Parallel) *)
| ParThrow: "[ Throw ∈ set cs ] ==> Γ ⊨ (Parallel cs, s) → (Throw, s)"
| Await: "[ s ∈ b; Γ ⊨ (c, Normal s) → * (c', Normal s');
atom_com c; c' = Skip ∨ c' = Throw ]
==> Γ ⊨ (Await b c, Normal s) → (c', Normal s')"
| AwaitStuck:
"[ s ∈ b; Γ ⊨ (c, Normal s) → * (c', Stuck) ;
atom_com c]
==> Γ ⊨ (Await b c, Normal s) → (Skip, Stuck)"
| AwaitFault:
"[ s ∈ b; Γ ⊨ (c, Normal s) → * (c', Fault f) ;
atom_com c]
==> Γ ⊨ (Await b c, Normal s) → (Skip, Fault f)"
| AwaitNonAtom:
" ¬ atom_com c
==> Γ ⊨ (Await b c, Normal s) → (Skip, Stuck)"
lemmas step_induct = step.induct [of _ "(c,s)" "(c',s')" , split_format (complete), case_names
Basic Spec SpecStuck Guard GuardFault Seq SeqSkip SeqThrow CondTrue CondFalse
WhileTrue WhileFalse Call CallUndefined DynCom Catch CatchThrow CatchSkip
FaultProp StuckProp Parallel ParSkip Await, induct set]
text ‹ The execution of a command is blocked if it cannot make progress, but is not in a final
. It is the intention that ‹ ∃ cfg. Γ ⊨ (c, s) → cfg) ∨ final (c, s) ∨ blocked Γ c s› , but
do not prove this. ›
function (sequential) blocked :: "('s,'p,'f) body ==> ('s,'p,'f) com ==> ('s,'f)xstate ==> bool" where
"blocked Γ (Seq (Await b c1 ) c2 ) (Normal s) = (s ∉ b)"
| "blocked Γ (Catch (Await b c1 ) c2 ) (Normal s) = (s ∉ b)"
| "blocked Γ (Await b c) (Normal s) = (s ∉ b ∨ (∀ c' s'. Γ ⊨ (c, Normal s) → * (c', Normal s') ⟶ ¬ final (c', Normal s')))"
| "blocked Γ (Parallel cs) (Normal s) = (∀ t ∈ set cs. blocked Γ t (Normal s) ∨ final (t, Normal s))"
| "blocked Γ _ _ = False"
by (pat_completeness, auto)
inductive_cases step_elim_cases [cases set]:
"Γ ⊨ (Skip,s) → u"
"Γ ⊨ (Guard f g c,s) → u"
"Γ ⊨ (Basic f,s) → u"
"Γ ⊨ (Spec r,s) → u"
"Γ ⊨ (Seq c1 c2,s) → u"
"Γ ⊨ (Cond b c1 c2,s) → u"
"Γ ⊨ (While b c,s) → u"
"Γ ⊨ (Call p,s) → u"
"Γ ⊨ (DynCom c,s) → u"
"Γ ⊨ (Throw,s) → u"
"Γ ⊨ (Catch c1 c2,s) → u"
"Γ ⊨ (Parallel cs,s) → u"
"Γ ⊨ (Await b e,s) → u"
inductive_cases step_Normal_elim_cases [cases set]:
"Γ ⊨ (Skip,Normal s) → u"
"Γ ⊨ (Guard f g c,Normal s) → u"
"Γ ⊨ (Basic f,Normal s) → u"
"Γ ⊨ (Spec r,Normal s) → u"
"Γ ⊨ (Seq c1 c2,Normal s) → u"
"Γ ⊨ (Cond b c1 c2,Normal s) → u"
"Γ ⊨ (While b c,Normal s) → u"
"Γ ⊨ (Call p,Normal s) → u"
"Γ ⊨ (DynCom c,Normal s) → u"
"Γ ⊨ (Throw,Normal s) → u"
"Γ ⊨ (Catch c1 c2,Normal s) → u"
"Γ ⊨ (Parallel cs,Normal s) → u"
"Γ ⊨ (Await b e,Normal s) → u"
abbreviation
"step_trancl" :: "[('s,'p,'f) body, ('s,'p,'f) config,('s,'p,'f) config] ==> bool"
(‹ _⊨ (_ → + / _)› [81 ,81 ,81 ] 100 )
where
"Γ ⊨ cf0 → + cf1 ≡ (CONST step Γ)+ + cf0 cf1"
abbreviation
"step_n_trancl" :: "[('s,'p,'f) body, ('s,'p,'f) config,nat,('s,'p,'f) config] ==> bool"
(‹ _⊨ (_ → n_ / _)› [81 ,81 ,81 ,81 ] 100 )
where
"Γ ⊨ cf0 → nn cf1 ≡ (CONST step Γ ^^ n) cf0 cf1"
lemma no_step_final:
assumes step: "Γ ⊨ (c,s) → (c',s')"
shows "final (c,s) ==> P"
using step
by induct (auto simp add: final_def)
lemma no_step_final':
assumes step: "Γ ⊨ cfg → cfg'"
shows "final cfg ==> P"
using step
by (cases cfg, cases cfg') (auto intro: no_step_final)
lemma no_steps_final:
"Γ ⊨ v → * w ==> final v ==> w = v"
apply (cases v)
apply simp
apply (erule converse_rtranclpE)
apply simp
apply (erule (1 ) no_step_final')
done
lemma step_Fault:
assumes step: "Γ ⊨ (c, s) → (c', s')"
shows "∧ f. s=Fault f ==> s'=Fault f"
using step
by (induct) auto
lemma step_Stuck:
assumes step: "Γ ⊨ (c, s) → (c', s')"
shows "∧ f. s=Stuck ==> s'=Stuck"
using step
by (induct) auto
lemma SeqSteps:
assumes steps: "Γ ⊨ cfg1 → * cfg2 "
shows "∧ c1 s c1 ' s'. [ cfg1 = (c1 ,s);cfg2 =(c1 ',s')]
==> Γ ⊨ (Seq c1 c2 ,s) → * (Seq c1 ' c2 , s')"
using steps
proof (induct rule: converse_rtranclp_induct [case_names Refl Trans])
case Refl
thus ?case
by simp
next
case (Trans cfg1 cfg'')
have step: "Γ ⊨ cfg1 → cfg''" by fact
have steps: "Γ ⊨ cfg'' → * cfg2 " by fact
have cfg1 : "cfg1 = (c1 , s)" and cfg2 : "cfg2 = (c1 ', s')" by fact+
obtain c1 '' s'' where cfg'': "cfg''=(c1 '',s'')"
by (cases cfg'') auto
from step cfg1 cfg''
have "Γ ⊨ (c1 ,s) → (c1 '',s'')"
by simp
hence "Γ ⊨ (Seq c1 c2 ,s) → (Seq c1 '' c2 ,s'')"
by (rule step.Seq)
also from Trans.hyps (3 ) [OF cfg'' cfg2 ]
have "Γ ⊨ (Seq c1 '' c2 , s'') → * (Seq c1 ' c2 , s')" .
finally show ?case .
qed
lemma CatchSteps:
assumes steps: "Γ ⊨ cfg1 → * cfg2 "
shows "∧ c1 s c1 ' s'. [ cfg1 = (c1 ,s); cfg2 =(c1 ',s')]
==> Γ ⊨ (Catch c1 c2 ,s) → * (Catch c1 ' c2 , s')"
using steps
proof (induct rule: converse_rtranclp_induct [case_names Refl Trans])
case Refl
thus ?case
by simp
next
case (Trans cfg1 cfg'')
have step: "Γ ⊨ cfg1 → cfg''" by fact
have steps: "Γ ⊨ cfg'' → * cfg2 " by fact
have cfg1 : "cfg1 = (c1 , s)" and cfg2 : "cfg2 = (c1 ', s')" by fact+
obtain c1 '' s'' where cfg'': "cfg''=(c1 '',s'')"
by (cases cfg'') auto
from step cfg1 cfg''
have s: "Γ ⊨ (c1 ,s) → (c1 '',s'')"
by simp
hence "Γ ⊨ (Catch c1 c2 ,s) → (Catch c1 '' c2 ,s'')"
by (rule step.Catch)
also from Trans.hyps (3 ) [OF cfg'' cfg2 ]
have "Γ ⊨ (Catch c1 '' c2 , s'') → * (Catch c1 ' c2 , s')" .
finally show ?case .
qed
lemma steps_Fault: "Γ ⊨ (c, Fault f) → * (Skip, Fault f)"
proof (induct c)
case (Seq c1 c2 )
have steps_c1 : "Γ ⊨ (c1 , Fault f) → * (Skip, Fault f)" by fact
have steps_c2 : "Γ ⊨ (c2 , Fault f) → * (Skip, Fault f)" by fact
from SeqSteps [OF steps_c1 refl refl]
have "Γ ⊨ (Seq c1 c2 , Fault f) → * (Seq Skip c2 , Fault f)" .
also
have "Γ ⊨ (Seq Skip c2 , Fault f) → (c2 , Fault f)" by (rule SeqSkip)
also note steps_c2
finally show ?case by simp
next
case (Catch c1 c2 )
have steps_c1 : "Γ ⊨ (c1 , Fault f) → * (Skip, Fault f)" by fact
from CatchSteps [OF steps_c1 refl refl]
have "Γ ⊨ (Catch c1 c2 , Fault f) → * (Catch Skip c2 , Fault f)" .
also
have "Γ ⊨ (Catch Skip c2 , Fault f) → (Skip, Fault f)" by (rule CatchSkip)
finally show ?case by simp
qed (fastforce intro: step.intros )+
lemma steps_Stuck: "Γ ⊨ (c, Stuck) → * (Skip, Stuck)"
proof (induct c)
case (Seq c1 c2 )
have steps_c1 : "Γ ⊨ (c1 , Stuck) → * (Skip, Stuck)" by fact
have steps_c2 : "Γ ⊨ (c2 , Stuck) → * (Skip, Stuck)" by fact
from SeqSteps [OF steps_c1 refl refl]
have "Γ ⊨ (Seq c1 c2 , Stuck) → * (Seq Skip c2 , Stuck)" .
also
have "Γ ⊨ (Seq Skip c2 , Stuck) → (c2 , Stuck)" by (rule SeqSkip)
also note steps_c2
finally show ?case by simp
next
case (Catch c1 c2 )
have steps_c1 : "Γ ⊨ (c1 , Stuck) → * (Skip, Stuck)" by fact
from CatchSteps [OF steps_c1 refl refl]
have "Γ ⊨ (Catch c1 c2 , Stuck) → * (Catch Skip c2 , Stuck)" .
also
have "Γ ⊨ (Catch Skip c2 , Stuck) → (Skip, Stuck)" by (rule CatchSkip)
finally show ?case by simp
qed (fastforce intro: step.intros )+
lemma step_Fault_prop:
assumes step: "Γ ⊨ (c, s) → (c', s')"
shows "∧ f. s=Fault f ==> s'=Fault f"
using step
by (induct) auto
lemma step_Stuck_prop:
assumes step: "Γ ⊨ (c, s) → (c', s')"
shows "s=Stuck ==> s'=Stuck"
using step
by (induct) auto
lemma steps_Fault_prop:
assumes step: "Γ ⊨ (c, s) → * (c', s')"
shows "s=Fault f ==> s'=Fault f"
using step
proof (induct rule: converse_rtranclp_induct2 [case_names Refl Trans])
case Refl thus ?case by simp
next
case (Trans c s c'' s'')
thus ?case
by (auto intro: step_Fault_prop)
qed
lemma steps_Stuck_prop:
assumes step: "Γ ⊨ (c, s) → * (c', s')"
shows "s=Stuck ==> s'=Stuck"
using step
proof (induct rule: converse_rtranclp_induct2 [case_names Refl Trans])
case Refl thus ?case by simp
next
case (Trans c s c'' s'')
thus ?case
by (auto intro: step_Stuck_prop)
qed
end
Messung V0.5 in Prozent C=84 H=96 G=90
¤ Dauer der Verarbeitung: 0.11 Sekunden
¤
*© Formatika GbR, Deutschland