Up to index of Isabelle/HOL/SafeImp
theory SVMSemantics(* Title: Safe Virtual Machine Semantics
Author: Ricardo Peņa
Copyright: March 2008, Universidad Complutense de Madrid
*)
header {* Semantics of the SVM instructions *}
theory SVMSemantics
imports SVMState HaskellLib
begin
text{*
\begin{itemize}
\item 'execSVMInst' executes a single SafeImp instruction in a state and
gives another state.
\item 'execSVM' executes the next SafeImp instruction in a
SVM program.
\item 'execOp' operates two basic values with an operator.
\end{itemize}
*}
consts
execSVMInst :: "[SafeInstr,ConstructorTableFun,Heap,Region,PC,Stack]
=> (SVMState,SVMState) Either"
consts
item2Stack :: "Region => Stack => Item => StackObject"
item2Val :: "Stack => Item => Val"
text{* Auxiliary functions for BUILDENV and BUILDCLS *}
fun stackOffset :: "Stack => nat => StackObject" (infix "!+" 110 ) where
"(so # S) !+ 0 = so"
| "(Val v # S) !+ n = S !+ (n - 1)"
| "(Reg r # S) !+ n = S !+ (n - 1)"
| "(Cont c # S) !+ n = S !+ (n - 2)"
primrec
"item2Stack k S (ItemConst v) = Val v"
"item2Stack k S (ItemVar off) = S !+off"
"item2Stack k S ItemRegSelf = Reg k"
primrec
"item2Val S (ItemConst v) = v"
"item2Val S (ItemVar off) = (case S !+ off of Val v => v)"
-- "We use fun here for full pattern matching"
constdefs
execSVM :: "SafeImpProg => SVMState => (SVMState,SVMState) Either"
"execSVM prog state == (
case prog of ((code,cnt),q,ct,st) =>
case state of (h,k0,(l,i),S) =>
let codef = map_of code
in execSVMInst (fst(the (codef l))!i) (map_of ct) h k0 (l,i) S)"
consts
execSVM_N :: "SafeImpProg => SVMState => nat => SVMState"
primrec
"execSVM_N prog s 0 = s "
"execSVM_N prog s (Suc n) = (case execSVM prog s of
Right s' => execSVM_N prog s' n)"
text{* Function {\sl execSVMInst} executes a single SVM instruction. If it
is POPCONT and there is no continuation in the stack, it returns the
current state with the constructor Left. Otherwise, it returns the next
state with the constructor Right. *}
primrec
"execSVMInst DECREGION ct h k0 pc S = Right (h \<down> k0,k0,incrPC pc,S)"
"execSVMInst POPCONT ct h k0 pc S = (case S of
v#[] => Left (h,k0,pc,S)
| v#Cont (k0,l)#S' => Right (h,k0,(l,0),v#S'))"
"execSVMInst (PUSHCONT p)ct h k0 pc S = Right (h,snd h,incrPC pc,Cont (k0,p)#S)"
"execSVMInst COPY ct h k0 pc S = (case S of
Val (Loc b)#Reg j#S' =>
if j ≤ snd h then
let pair = copy h j b in
case pair of (h',b') =>
Right (h',k0,incrPC pc,Val (Loc b')#S')
else arbitrary)"
"execSVMInst REUSE ct h k0 pc S = (case S of
Val (Loc b)#S' =>
case h of (hm,k) =>
let cell = the (hm b);
b' = getFresh hm in
Right ((hm(b:=None)(b'\<mapsto> cell),k),
k0,incrPC pc,Val (Loc b')#S'))"
"execSVMInst (CALL p) ct h k0 pc S = (case h of
(hm,k) => Right ((hm,k+1),k0,(p,0),S))"
"execSVMInst (PRIMOP oper) ct h k0 pc S = (case S of
Val v1#Val v2#S' =>
let v = execOp oper v1 v2 in
Right (h,k0,incrPC pc,Val v#S'))"
"execSVMInst (MATCH l ps) ct h k0 pc S = (case S!+l of Val (Loc b) =>
case (fst h) b of
Some (j,C,vs) =>
case ct C of
Some (_,r,_) =>
Right (h,k0,(ps!r,0),(map Val vs) @ S))"
"execSVMInst (MATCHD l ps) ct h k0 pc S = (case S!+l of Val (Loc b) =>
case (fst h) b of
Some (j,C,vs) =>
case ct C of
Some (_,r,_) =>
let h' = ((fst h)(b:= None), snd h) in
Right (h',k0,(ps!r,0),(map Val vs) @ S))"
"execSVMInst (MATCHN l v m ps) ct h k0 pc S = (case S!+l of
Val (IntT i) =>
let r = (nat i)- v;
p = if r ≥ 0 ∧ r ≤ m - 1
then ps!r
else ps!m
in Right (h,k0,(p,0),S)
| Val (BoolT b) =>
let p = if ¬ b then ps!0 else ps!1
in Right (h,k0,(p,0),S))"
"execSVMInst (BUILDENV is) ct h k0 pc S =
(let bs = map (item2Stack (snd h) S) is
in Right (h,k0,incrPC pc,bs @ S))"
"execSVMInst (BUILDCLS C is i) ct h k0 pc S =
(case item2Stack (snd h) S i of
Reg j => case h of
(hm,k) =>
let vs = map (item2Val S) is;
b = getFresh hm;
h' = (hm (b \<mapsto> (j,C,vs)),k)
in Right (h',k0,incrPC pc,Val (Loc b)#S))"
"execSVMInst (SLIDE m n) ct h k0 pc S = Right (h,k0,incrPC pc,take m S @ drop (m+n) S)"
text{* We convert function {\sl execSVM} into a reflexive transitive
relation. Also, we define an inductive relation {\sl execSVMBalanced}
giving us the list of all the states reachable from an initial one so that
the stack does not decrease more than a given amount n. The list is given
in reverse order.*}
constdefs
execSVMAll :: "[SafeImpProg,SVMState,SVMState] => bool"
("_\<turnstile> _ -svm-> _" [61,61,61]60)
"P \<turnstile> s -svm-> s' ≡ (s,s') ∈ {(s,t) . execSVM P s = Right t}^*"
fun
diffStack :: "SVMState => SVMState => nat => int"
where
"diffStack (h',k0',pc',S') (h,k0,pc,S) m = (
let n = length S;
n' = length S'
in int m + (int n' - int n))"
fun instrSVM :: "SafeImpProg => SVMState => SafeInstr"
where
"instrSVM ((code,cnt),q,ct,st) (h,k0,(l,i),S) = fst(the (map_of code l))!i"
inductive
execSVMBalanced :: "[SafeImpProg,SVMState,nat list,SVMState list,nat list] => bool"
("_\<turnstile>_ , _ -svm-> _ , _" [61,61,61,61,61]60)
where
init: "P \<turnstile> s, n#ns -svm-> [s], n#ns"
| step: "[| P \<turnstile> s, n#ns -svm-> s'#ss, m#ms;
execSVM P s' = Right s'';
m' = nat (diffStack s'' s' m);
m' ≥ 0;
ms' = (if pushcont (instrSVM P s') then 0#m#ms
else if popcont (instrSVM P s') ∧ ms=m''#ms'' then (Suc m'')#ms''
else m'#ms)|]
==>
P \<turnstile> s, n#ns -svm-> s''#s'#ss, ms'"
lemma popcont_neq_pushcont:
"popcont (instrSVM P s) ==> ¬pushcont (instrSVM P s)"
by (case_tac "instrSVM P s",simp_all)
lemma execSVMBalanced_n_step_aux [rule_format]:
" P \<turnstile> s'', n''#ns'' -svm-> sss , n'''#ns''' --> (∀ s''' ss'' ss. sss = s'''#ss'' -->
P \<turnstile> s', n'#ns' -svm-> s'' # ss', n''#ns'' -->
ss = ss'' @ ss' -->
P \<turnstile> s', n'#ns' -svm-> s'''# ss, n'''#ns''')"
apply (rule impI)
apply (erule execSVMBalanced.induct) apply simp
apply (rule allI)+
apply (erule_tac x="s'a" in allE)
apply (erule_tac x="ss" in allE)
apply (erule_tac x="ss @ ss'" in allE)
apply (rule impI)+
apply simp
apply (elim conjE)
apply (rule conjI) apply (rule impI) apply (rule conjI) apply (rule impI)
apply simp
apply (erule conjE) apply (frule popcont_neq_pushcont) apply simp
apply (rule impI)
apply simp
apply (drule_tac t="ss''" in sym) apply simp
apply (rule execSVMBalanced.step) apply simp apply simp apply simp apply simp apply simp
apply (rule conjI) apply simp apply simp
apply (rule impI) apply (rule conjI) apply (rule impI)
apply simp
apply (drule_tac t="ss''" in sym) apply simp
apply (rule execSVMBalanced.step) apply simp apply simp apply simp apply simp apply simp
apply (rule impI)
apply simp
apply (drule_tac t="ss''" in sym) apply simp
apply (rule execSVMBalanced.step) apply simp apply simp apply simp apply simp
apply (split split_if_asm) apply simp apply simp
apply (rule impI) apply (elim conjE)
apply (rule conjI) apply simp apply auto
done
lemma execSVMBalanced_n_step:
"[|P \<turnstile> s', n'#ns' -svm-> s'' # ss', n''#ns'';
P \<turnstile> s'', n''#ns'' -svm-> s'''# ss'', n'''#ns''';
ss = ss'' @ ss'|]
==> P \<turnstile> s', n'#ns' -svm-> s'''# ss, n'''#ns'''"
apply (rule execSVMBalanced_n_step_aux)
apply simp_all
done
end
lemma popcont_neq_pushcont:
popcont (instrSVM P s) ==> ¬ pushcont (instrSVM P s)
lemma execSVMBalanced_n_step_aux:
[| P\<turnstile>s'' , n'' # ns'' -svm-> sss , n''' # ns'''; sss = s''' # ss'';
P\<turnstile>s' , n' # ns' -svm-> s'' # ss' , n'' # ns''; ss = ss'' @ ss' |]
==> P\<turnstile>s' , n' # ns' -svm-> s''' # ss , n''' # ns'''
lemma execSVMBalanced_n_step:
[| P\<turnstile>s' , n' # ns' -svm-> s'' # ss' , n'' # ns'';
P\<turnstile>s'' , n'' # ns'' -svm-> s''' # ss'' , n''' # ns''';
ss = ss'' @ ss' |]
==> P\<turnstile>s' , n' # ns' -svm-> s''' # ss , n''' # ns'''