Theory SVMSemantics

Up to index of Isabelle/HOL/SafeImp

theory SVMSemantics
imports SVMState HaskellLib
begin

(*  Title:      Safe Virtual Machine Semantics
    Author:     Ricardo Pe~na
    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
                            Val v#[]             => Left (h,k0,pc,S)
                          | Val v#Cont (k0,l)#S' => Right (h,k0,(l,0),Val 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 Left (h,k0,pc,S))"

  "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 (IntT i)#Val (IntT i')#S' => 
                            let v = execOp oper (IntT i) (IntT i') 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) =>
                                    if j ≤ snd h then 
                                       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)
                                    else Left (h,k0,pc,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'''