Theory Operational

(*<*)
theory Operational
  imports Typing
begin
  (*>*)

chapter ‹Operational Semantics›

text ‹ Here we define the operational semantics in terms of a small-step reduction relation. ›

section ‹Reduction Rules›

text ‹ The store for mutable variables ›
type_synonym δ = "(u*v) list"

nominal_function update_d :: "δ  u  v  δ" where
  "update_d [] _ _ = []"
| "update_d ((u',v')#δ) u v = (if u = u' then ((u,v)#δ) else ((u',v')# (update_d δ u v)))"
  by(auto,simp add: eqvt_def update_d_graph_aux_def ,metis neq_Nil_conv old.prod.exhaust)
nominal_termination (eqvt) by lexicographic_order

text ‹ Relates constructor to the branch in the case and binding variable and statement ›
inductive find_branch :: "dc  branch_list   branch_s   bool" where
  find_branch_finalI:  "dc' = dc                                   find_branch dc' (AS_final (AS_branch dc x s ))  (AS_branch dc x s)"
| find_branch_branch_eqI: "dc' = dc                                find_branch dc' (AS_cons  (AS_branch dc x s) css)    (AS_branch dc x s)"
| find_branch_branch_neqI:  " dc  dc'; find_branch dc' css cs   find_branch dc' (AS_cons  (AS_branch dc x s) css) cs"
equivariance find_branch
nominal_inductive find_branch .

inductive_cases find_branch_elims[elim!]:
  "find_branch dc (AS_final cs') cs"
  "find_branch dc (AS_cons cs' css) cs"

nominal_function lookup_branch :: "dc  branch_list  branch_s option" where
  "lookup_branch dc (AS_final (AS_branch dc' x s)) = (if dc = dc' then (Some (AS_branch dc' x s)) else None)"
| "lookup_branch dc (AS_cons (AS_branch dc' x s) css) = (if dc = dc' then (Some (AS_branch dc' x s)) else lookup_branch dc css)"
       apply(auto,simp add: eqvt_def lookup_branch_graph_aux_def)
  by(metis neq_Nil_conv old.prod.exhaust s_branch_s_branch_list.strong_exhaust)
nominal_termination (eqvt) by lexicographic_order

text ‹ Reduction rules ›
inductive reduce_stmt :: "Φ  δ  s  δ  s  bool"  (‹ _    _ , _    _ , _ [50, 50, 50] 50)  where
  reduce_if_trueI:  " Φ  δ, AS_if [L_true]v s1 s2  δ, s1 "
| reduce_if_falseI: " Φ  δ, AS_if [L_false]v s1 s2  δ, s2 "
| reduce_let_valI:  " Φ  δ, AS_let x (AE_val v)  s  δ, s[x::=v]sv"  
| reduce_let_plusI: " Φ   δ, AS_let x (AE_op Plus ((V_lit (L_num n1))) ((V_lit (L_num n2))))  s  
                           δ, AS_let x (AE_val (V_lit (L_num ( (( n1)+(n2)))))) s  "  
| reduce_let_leqI:  "b = (if (n1  n2) then L_true else L_false)  
             Φ    δ,  AS_let x  ((AE_op LEq (V_lit (L_num n1)) (V_lit (L_num n2)))) s  
                                                          δ, AS_let x  (AE_val (V_lit b)) s"  
| reduce_let_eqI:  "b = (if (n1 = n2) then L_true else L_false)  
             Φ    δ,  AS_let x  ((AE_op Eq (V_lit n1) (V_lit n2))) s  
                                                          δ, AS_let x  (AE_val (V_lit b)) s"  
| reduce_let_appI:  "Some (AF_fundef f (AF_fun_typ_none (AF_fun_typ z b c τ s'))) = lookup_fun Φ f   
             Φ    δ, AS_let x  ((AE_app f v)) s  δ,  AS_let2 x τ[z::=v]τv s'[z::=v]sv s "     
| reduce_let_appPI:  "Some (AF_fundef f (AF_fun_typ_some bv (AF_fun_typ z b c τ s'))) = lookup_fun Φ f   
             Φ    δ, AS_let x  ((AE_appP f b' v)) s  δ,  AS_let2 x τ[bv::=b']τb[z::=v]τv s'[bv::=b']sb[z::=v]sv s "  
| reduce_let_fstI:  "Φ  δ, AS_let x (AE_fst (V_pair v1 v2))  s  δ, AS_let x (AE_val v1)  s"
| reduce_let_sndI:  "Φ  δ, AS_let x (AE_snd (V_pair v1 v2))  s  δ, AS_let x (AE_val v2)  s"
| reduce_let_concatI:  "Φ  δ, AS_let x (AE_concat (V_lit (L_bitvec v1))  (V_lit (L_bitvec v2)))  s  
                            δ, AS_let x (AE_val (V_lit (L_bitvec (v1@v2))))  s"
| reduce_let_splitI: " split n v (v1 , v2 )   Φ  δ, AS_let x (AE_split (V_lit (L_bitvec v))  (V_lit (L_num n)))  s  
                            δ, AS_let x (AE_val (V_pair (V_lit (L_bitvec v1)) (V_lit (L_bitvec v2))))  s"
| reduce_let_lenI:  "Φ  δ, AS_let x (AE_len (V_lit (L_bitvec v)))  s  
                              δ, AS_let x (AE_val (V_lit (L_num (int (List.length v)))))  s"
| reduce_let_mvar:  "(u,v)  set δ   Φ  δ, AS_let x (AE_mvar u)  s  δ, AS_let x (AE_val v) s " 
| reduce_assert1I: "Φ  δ, AS_assert c (AS_val v)  δ, AS_val v" 
| reduce_assert2I:  " Φ   δ, s    δ', s'  Φ   δ, AS_assert c s   δ', AS_assert c s'"  
| reduce_varI: "atom u  δ   Φ    δ, AS_var u τ v s    ((u,v)#δ) , s"
| reduce_assignI: "  Φ    δ, AS_assign u v    update_d δ u v , AS_val (V_lit L_unit)"
| reduce_seq1I: "Φ     δ, AS_seq (AS_val (V_lit L_unit )) s   δ, s"
| reduce_seq2I: "s1  AS_val v ; Φ    δ, s1   δ', s1'   
                          Φ    δ, AS_seq s1 s2   δ', AS_seq s1' s2"
| reduce_let2_valI:  "Φ    δ, AS_let2 x t (AS_val v) s  δ, s[x::=v]sv" 
| reduce_let2I:  " Φ   δ, s1    δ', s1'  Φ   δ, AS_let2 x t s1 s2   δ', AS_let2 x t s1' s2"  

| reduce_caseI:  " Some (AS_branch dc x' s') = lookup_branch dc cs    Φ   δ, AS_match (V_cons tyid dc v) cs   δ, s'[x'::=v]sv "
| reduce_whileI: " atom x  (s1,s2); atom z  x   
                    Φ    δ, AS_while s1 s2   
            δ, AS_let2 x ( z : B_bool | TRUE ) s1 (AS_if (V_var x) (AS_seq s2 (AS_while s1 s2))  (AS_val (V_lit L_unit))) "

equivariance reduce_stmt
nominal_inductive reduce_stmt .

inductive_cases reduce_stmt_elims[elim!]:
  "Φ  δ, AS_if (V_lit L_true) s1 s2  δ , s1"
  "Φ  δ, AS_if (V_lit L_false) s1 s2  δ,s2"
  "Φ  δ, AS_let x (AE_val v)  s  δ,s'"
  "Φ  δ, AS_let x  (AE_op Plus ((V_lit (L_num n1))) ((V_lit (L_num n2))))  s  
            δ, AS_let x  (AE_val (V_lit (L_num ( (( n1)+(n2)))))) s "
  "Φ  δ, AS_let x  ((AE_op LEq (V_lit (L_num n1)) (V_lit (L_num n2)))) s  δ, AS_let x  (AE_val (V_lit b)) s"
  "Φ  δ, AS_let x  ((AE_app f v)) s  δ, AS_let2 x τ (subst_sv s' x v ) s "  
  "Φ  δ, AS_let x  ((AE_len v)) s  δ, AS_let x  v' s "  
  "Φ  δ, AS_let x  ((AE_concat v1 v2)) s  δ, AS_let x  v' s " 
  "Φ  δ, AS_seq s1 s2   δ' ,s'"
  "Φ  δ, AS_let x  ((AE_appP  f b v)) s  δ, AS_let2 x τ (subst_sv s' z v) s "  
  "Φ  δ, AS_let x  ((AE_split v1 v2)) s  δ, AS_let x  v' s " 
  "Φ  δ, AS_assert c s   δ, s' "
  "Φ  δ, AS_let x  ((AE_op Eq (V_lit (n1)) (V_lit (n2)))) s  δ, AS_let x  (AE_val (V_lit b)) s"

inductive reduce_stmt_many :: "Φ  δ  s  δ  s  bool"    (‹_   _ , _ *   _ , _ [50, 50, 50] 50)  where  
  reduce_stmt_many_oneI:  "Φ  δ, s  δ', s'   Φ  δ  , s * δ', s' "
| reduce_stmt_many_manyI:  " Φ  δ, s    δ', s' ; Φ   δ', s' * δ'', s''   Φ   δ, s * δ'', s''"

nominal_function  convert_fds :: "fun_def list  (f*fun_def) list" where
  "convert_fds [] = []"
| "convert_fds ((AF_fundef f (AF_fun_typ_none (AF_fun_typ x b c τ s)))#fs) = ((f,AF_fundef f (AF_fun_typ_none (AF_fun_typ x b c τ s)))#convert_fds fs)"
| "convert_fds ((AF_fundef f (AF_fun_typ_some bv (AF_fun_typ x b c τ s)))#fs) = ((f,AF_fundef f (AF_fun_typ_some bv (AF_fun_typ x b c τ s)))#convert_fds fs)"
  apply(auto)
  apply (simp add: eqvt_def convert_fds_graph_aux_def )
  using fun_def.exhaust fun_typ.exhaust fun_typ_q.exhaust neq_Nil_conv 
  by metis
nominal_termination (eqvt) by lexicographic_order

nominal_function  convert_tds :: "type_def list  (f*type_def) list" where
  "convert_tds [] = []"
| "convert_tds ((AF_typedef s dclist)#fs) = ((s,AF_typedef s dclist)#convert_tds fs)"
| "convert_tds ((AF_typedef_poly s bv dclist)#fs) = ((s,AF_typedef_poly s bv dclist)#convert_tds fs)"
  apply(auto)
  apply (simp add: eqvt_def convert_tds_graph_aux_def )
  by (metis type_def.exhaust neq_Nil_conv)
nominal_termination (eqvt) by lexicographic_order

inductive reduce_prog :: "p  v  bool" where
  " reduce_stmt_many Φ [] s δ (AS_val v)    reduce_prog (AP_prog Θ Φ [] s) v"

section ‹Reduction Typing›

text ‹ Checks that the store is consistent with @{typ Δ}
inductive delta_sim :: "Θ  δ  Δ  bool" ( ‹_   _  _ › [50,50] 50 )  where
  delta_sim_nilI:  "Θ  []  []Δ "
| delta_sim_consI: " Θ  δ  Δ ; Θ ; {||} ; GNil  v  τ ; u  fst ` set δ     Θ  ((u,v)#δ)  ((u,τ)#ΔΔ)" 

equivariance delta_sim
nominal_inductive delta_sim .

inductive_cases delta_sim_elims[elim!]:
  "Θ  []  []Δ"
  "Θ  ((u,v)#ds)  (u,τ) #Δ D"
  "Θ  ((u,v)#ds)  D"

text ‹A typing judgement that combines typing of the statement, the store and the condition that definitions are well-typed›
inductive config_type ::  "Θ  Φ  Δ  δ  s  τ   bool"   (‹_ ; _ ; _   _ , _  _ › [50, 50, 50] 50)  where 
  config_typeI: " Θ ; Φ ; {||} ; GNil ; Δ  s  τ; 
                ( fd  set Φ. Θ ; Φ  fd) ;
                Θ   δ  Δ 
                 Θ ; Φ ; Δ   δ  , s   τ"
equivariance config_type
nominal_inductive config_type .

inductive_cases config_type_elims [elim!]:
  " Θ ; Φ  ; Δ   δ  , s   τ"

nominal_function δ_of  :: "var_def list  δ" where
  "δ_of [] = []"
| "δ_of ((AV_def u t v)#vs) = (u,v) #  (δ_of vs)" 
  apply auto
  using  eqvt_def δ_of_graph_aux_def neq_Nil_conv old.prod.exhaust apply force
  using  eqvt_def δ_of_graph_aux_def neq_Nil_conv old.prod.exhaust 
  by (metis var_def.strong_exhaust)
nominal_termination (eqvt) by lexicographic_order

inductive config_type_prog :: "p  τ  bool"  (  _  _›) where
  "
  Θ ; Φ ; Δ_of 𝒢   δ_of 𝒢  , s   τ
     AP_prog Θ Φ 𝒢 s  τ"

inductive_cases config_type_prog_elims [elim!]:
  "   AP_prog Θ Φ 𝒢 s  τ"

end