Theory SemanticPrimitives

theory SemanticPrimitives
imports Ast Ffi
chapter ‹Generated by Lem from ‹semantics/semanticPrimitives.lem›.›

theory "SemanticPrimitives" 

imports
  Main
  "HOL-Library.Datatype_Records"
  "LEM.Lem_pervasives"
  "LEM.Lem_list_extra"
  "LEM.Lem_string"
  "Lib"
  "Namespace"
  "Ast"
  "Ffi"
  "FpSem"
  "LEM.Lem_string_extra"

begin 

― ‹‹open import Pervasives››
― ‹‹open import Lib››
― ‹‹import List_extra››
― ‹‹import String››
― ‹‹import String_extra››
― ‹‹open import Ast››
― ‹‹open import Namespace››
― ‹‹open import Ffi››
― ‹‹open import FpSem››

― ‹‹ The type that a constructor builds is either a named datatype or an exception.
 * For exceptions, we also keep the module that the exception was declared in. ››
datatype tid_or_exn =
    TypeId " (modN, typeN) id0 "
  | TypeExn " (modN, conN) id0 "

― ‹‹val type_defs_to_new_tdecs : list modN -> type_def -> set tid_or_exn››
definition type_defs_to_new_tdecs  :: "(string)list ⇒((tvarN)list*string*(conN*(t)list)list)list ⇒(tid_or_exn)set "  where 
     " type_defs_to_new_tdecs mn tdefs = (
  List.set (List.map ( λx .  
  (case  x of (tvs,tn,ctors) => TypeId (mk_id mn tn) )) tdefs))"


datatype_record 'v sem_env =
  
 v ::" (modN, varN, 'v) namespace "
   
 c ::" (modN, conN, (nat * tid_or_exn)) namespace "
   


― ‹‹ Value forms ››
datatype v =
    Litv " lit "
  ― ‹‹ Constructor application. ››
  | Conv "  (conN * tid_or_exn)option " " v list "
  ― ‹‹ Function closures
     The environment is used for the free variables in the function ››
  | Closure " v sem_env " " varN " " exp0 "
  ― ‹‹ Function closure for recursive functions
   * See Closure and Letrec above
   * The last variable name indicates which function from the mutually
   * recursive bundle this closure value represents ››
  | Recclosure " v sem_env " " (varN * varN * exp0) list " " varN "
  | Loc " nat "
  | Vectorv " v list "

type_synonym env_ctor =" (modN, conN, (nat * tid_or_exn)) namespace "
type_synonym env_val =" (modN, varN, v) namespace "

definition Bindv  :: " v "  where 
     " Bindv = ( Conv (Some((''Bind''),TypeExn(Short(''Bind'')))) [])"


― ‹‹ The result of evaluation ››
datatype abort =
    Rtype_error
  | Rtimeout_error

datatype 'a error_result =
    Rraise " 'a " ― ‹‹ Should only be a value of type exn ››
  | Rabort " abort "

datatype( 'a, 'b) result =
    Rval " 'a "
  | Rerr " 'b error_result "

― ‹‹ Stores ››
datatype 'a store_v =
  ― ‹‹ A ref cell ››
    Refv " 'a "
  ― ‹‹ A byte array ››
  | W8array " 8 word list "
  ― ‹‹ An array of values ››
  | Varray " 'a list "

― ‹‹val store_v_same_type : forall 'a. store_v 'a -> store_v 'a -> bool››
definition store_v_same_type  :: " 'a store_v ⇒ 'a store_v ⇒ bool "  where 
     " store_v_same_type v1 v2 = (
  (case  (v1,v2) of
    (Refv _, Refv _) => True
  | (W8array _,W8array _) => True
  | (Varray _,Varray _) => True
  | _ => False
  ))"


― ‹‹ The nth item in the list is the value at location n ››
type_synonym 'a store =" ( 'a store_v) list "

― ‹‹val empty_store : forall 'a. store 'a››
definition empty_store  :: "('a store_v)list "  where 
     " empty_store = ( [])"


― ‹‹val store_lookup : forall 'a. nat -> store 'a -> maybe (store_v 'a)››
definition store_lookup  :: " nat ⇒('a store_v)list ⇒('a store_v)option "  where 
     " store_lookup l st = (
  if l < List.length st then
    Some (List.nth st l)
  else
    None )"


― ‹‹val store_alloc : forall 'a. store_v 'a -> store 'a -> store 'a * nat››
definition store_alloc  :: " 'a store_v ⇒('a store_v)list ⇒('a store_v)list*nat "  where 
     " store_alloc v2 st = (
  ((st @ [v2]), List.length st))"


― ‹‹val store_assign : forall 'a. nat -> store_v 'a -> store 'a -> maybe (store 'a)››
definition store_assign  :: " nat ⇒ 'a store_v ⇒('a store_v)list ⇒(('a store_v)list)option "  where 
     " store_assign n v2 st = (
  if (n < List.length st) ∧
     store_v_same_type (List.nth st n) v2
  then
    Some (List.list_update st n v2)
  else
    None )"


datatype_record 'ffi state =
  
 clock ::" nat "
   
 refs  ::" v store "
   
 ffi ::" 'ffi ffi_state "
   
 defined_types ::" tid_or_exn set "
   
 defined_mods ::" ( modN list) set "
   


― ‹‹ Other primitives ››
― ‹‹ Check that a constructor is properly applied ››
― ‹‹val do_con_check : env_ctor -> maybe (id modN conN) -> nat -> bool››
fun do_con_check  :: "((string),(string),(nat*tid_or_exn))namespace ⇒(((string),(string))id0)option ⇒ nat ⇒ bool "  where 
     " do_con_check cenv None l = ( True )"
|" do_con_check cenv (Some n) l = (
        (case  nsLookup cenv n of
            None => False
          | Some (l',ns) => l = l'
        ))"


― ‹‹val build_conv : env_ctor -> maybe (id modN conN) -> list v -> maybe v››
fun build_conv  :: "((string),(string),(nat*tid_or_exn))namespace ⇒(((string),(string))id0)option ⇒(v)list ⇒(v)option "  where 
     " build_conv envC None vs = (
        Some (Conv None vs))"
|" build_conv envC (Some id1) vs = (
        (case  nsLookup envC id1 of
            None => None
          | Some (len,t1) => Some (Conv (Some (id_to_n id1, t1)) vs)
        ))"


― ‹‹val lit_same_type : lit -> lit -> bool››
definition lit_same_type  :: " lit ⇒ lit ⇒ bool "  where 
     " lit_same_type l1 l2 = (
  (case  (l1,l2) of
      (IntLit _, IntLit _) => True
    | (Char _, Char _) => True
    | (StrLit _, StrLit _) => True
    | (Word8 _, Word8 _) => True
    | (Word64 _, Word64 _) => True
    | _ => False
  ))"


datatype 'a match_result =
    No_match
  | Match_type_error
  | Match " 'a "

― ‹‹val same_tid : tid_or_exn -> tid_or_exn -> bool››
fun  same_tid  :: " tid_or_exn ⇒ tid_or_exn ⇒ bool "  where 
     " same_tid (TypeId tn1) (TypeId tn2) = ( tn1 = tn2 )"
|" same_tid (TypeExn _) (TypeExn _) = ( True )"
|" same_tid _ _ = ( False )"


― ‹‹val same_ctor : conN * tid_or_exn -> conN * tid_or_exn -> bool››
fun  same_ctor  :: " string*tid_or_exn ⇒ string*tid_or_exn ⇒ bool "  where 
     " same_ctor (cn1, TypeExn mn1) (cn2, TypeExn mn2) = ( (cn1 = cn2) ∧ (mn1 = mn2))"
|" same_ctor (cn1, _) (cn2, _) = ( cn1 = cn2 )"


― ‹‹val ctor_same_type : maybe (conN * tid_or_exn) -> maybe (conN * tid_or_exn) -> bool››
definition ctor_same_type  :: "(string*tid_or_exn)option ⇒(string*tid_or_exn)option ⇒ bool "  where 
     " ctor_same_type c1 c2 = (
  (case  (c1,c2) of
      (None, None) => True
    | (Some (_,t1), Some (_,t2)) => same_tid t1 t2
    | _ => False
  ))"


― ‹‹ A big-step pattern matcher.  If the value matches the pattern, return an
 * environment with the pattern variables bound to the corresponding sub-terms
 * of the value; this environment extends the environment given as an argument.
 * No_match is returned when there is no match, but any constructors
 * encountered in determining the match failure are applied to the correct
 * number of arguments, and constructors in corresponding positions in the
 * pattern and value come from the same type.  Match_type_error is returned
 * when one of these conditions is violated ››
― ‹‹val pmatch : env_ctor -> store v -> pat -> v -> alist varN v -> match_result (alist varN v)››
function (sequential,domintros) 
pmatch_list  :: "((string),(string),(nat*tid_or_exn))namespace ⇒((v)store_v)list ⇒(pat)list ⇒(v)list ⇒(string*v)list ⇒((string*v)list)match_result "  
                   and
pmatch  :: "((string),(string),(nat*tid_or_exn))namespace ⇒((v)store_v)list ⇒ pat ⇒ v ⇒(string*v)list ⇒((string*v)list)match_result "  where 
     "
pmatch envC s Pany v' env = ( Match env )"
|"
pmatch envC s (Pvar x) v' env = ( Match ((x,v')# env))"
|"
pmatch envC s (Plit l) (Litv l') env = (
  if l = l' then
    Match env
  else if lit_same_type l l' then
    No_match
  else
    Match_type_error )"
|"
pmatch envC s (Pcon (Some n) ps) (Conv (Some (n', t')) vs) env = (
  (case  nsLookup envC n of
      Some (l, t1) =>
        if same_tid t1 t' ∧ (List.length ps = l) then
          if same_ctor (id_to_n n, t1) (n',t') then
            if List.length vs = l then
              pmatch_list envC s ps vs env
            else
              Match_type_error
          else
            No_match
        else
          Match_type_error
    | _ => Match_type_error
  ))"
|"
pmatch envC s (Pcon None ps) (Conv None vs) env = (
  if List.length ps = List.length vs then
    pmatch_list envC s ps vs env
  else
    Match_type_error )"
|"
pmatch envC s (Pref p) (Loc lnum) env = (
  (case  store_lookup lnum s of
      Some (Refv v2) => pmatch envC s p v2 env
    | Some _ => Match_type_error
    | None => Match_type_error
  ))"
|"
pmatch envC s (Ptannot p t1) v2 env = (
  pmatch envC s p v2 env )"
|"
pmatch envC _ _ _ env = ( Match_type_error )"
|"
pmatch_list envC s [] [] env = ( Match env )"
|"
pmatch_list envC s (p # ps) (v2 # vs) env = (
  (case  pmatch envC s p v2 env of
      No_match => No_match
    | Match_type_error => Match_type_error
    | Match env' => pmatch_list envC s ps vs env'
  ))"
|"
pmatch_list envC s _ _ env = ( Match_type_error )" 
by pat_completeness auto


― ‹‹ Bind each function of a mutually recursive set of functions to its closure ››
― ‹‹val build_rec_env : list (varN * varN * exp) -> sem_env v -> env_val -> env_val››
definition build_rec_env  :: "(varN*varN*exp0)list ⇒(v)sem_env ⇒((string),(string),(v))namespace ⇒((string),(string),(v))namespace "  where 
     " build_rec_env funs cl_env add_to_env = (
  List.foldr ( λx .  
  (case  x of
      (f,x,e) => λ env' .  nsBind f (Recclosure cl_env funs f) env'
  )) funs add_to_env )"


― ‹‹ Lookup in the list of mutually recursive functions ››
― ‹‹val find_recfun : forall 'a 'b. varN -> list (varN * 'a * 'b) -> maybe ('a * 'b)››
fun  find_recfun  :: " string ⇒(string*'a*'b)list ⇒('a*'b)option "  where 
     " find_recfun n ([]) = ( None )"
|" find_recfun n ((f,x,e) # funs) = (
        if f = n then
          Some (x,e)
        else
          find_recfun n funs )"


datatype eq_result =
    Eq_val " bool "
  | Eq_type_error

― ‹‹val do_eq : v -> v -> eq_result››
function (sequential,domintros) 
do_eq_list  :: "(v)list ⇒(v)list ⇒ eq_result "  
                   and
do_eq  :: " v ⇒ v ⇒ eq_result "  where 
     "
do_eq (Litv l1) (Litv l2) = (
  if lit_same_type l1 l2 then Eq_val (l1 = l2)
  else Eq_type_error )"
|"
do_eq (Loc l1) (Loc l2) = ( Eq_val (l1 = l2))"
|"
do_eq (Conv cn1 vs1) (Conv cn2 vs2) = (
  if (cn1 = cn2) ∧ (List.length vs1 = List.length vs2) then
    do_eq_list vs1 vs2
  else if ctor_same_type cn1 cn2 then
    Eq_val False
  else
    Eq_type_error )"
|"
do_eq (Vectorv vs1) (Vectorv vs2) = (
  if List.length vs1 = List.length vs2 then
    do_eq_list vs1 vs2
  else
    Eq_val False )"
|"
do_eq (Closure _ _ _) (Closure _ _ _) = ( Eq_val True )"
|"
do_eq (Closure _ _ _) (Recclosure _ _ _) = ( Eq_val True )"
|"
do_eq (Recclosure _ _ _) (Closure _ _ _) = ( Eq_val True )"
|"
do_eq (Recclosure _ _ _) (Recclosure _ _ _) = ( Eq_val True )"
|"
do_eq _ _ = ( Eq_type_error )"
|"
do_eq_list [] [] = ( Eq_val True )"
|"
do_eq_list (v1 # vs1) (v2 # vs2) = (
  (case  do_eq v1 v2 of
      Eq_type_error => Eq_type_error
    | Eq_val r =>
        if ¬ r then
          Eq_val False
        else
          do_eq_list vs1 vs2
  ))"
|"
do_eq_list _ _ = ( Eq_val False )" 
by pat_completeness auto


― ‹‹val prim_exn : conN -> v››
definition prim_exn  :: " string ⇒ v "  where 
     " prim_exn cn = ( Conv (Some (cn, TypeExn (Short cn))) [])"


― ‹‹ Do an application ››
― ‹‹val do_opapp : list v -> maybe (sem_env v * exp)››
fun do_opapp  :: "(v)list ⇒((v)sem_env*exp0)option "  where 
     " do_opapp ([Closure env n e, v2]) = (
      Some (( env (| v := (nsBind n v2(v   env)) |)), e))"
|" do_opapp ([Recclosure env funs n, v2]) = (
      if allDistinct (List.map ( λx .  
  (case  x of (f,x,e) => f )) funs) then
        (case  find_recfun n funs of
            Some (n,e) => Some (( env (| v := (nsBind n v2 (build_rec_env funs env(v   env))) |)), e)
          | None => None
        )
      else
        None )"
|" do_opapp _ = ( None )"


― ‹‹ If a value represents a list, get that list. Otherwise return Nothing ››
― ‹‹val v_to_list : v -> maybe (list v)››
function (sequential,domintros)  v_to_list  :: " v ⇒((v)list)option "  where 
     " v_to_list (Conv (Some (cn, TypeId (Short tn))) []) = (
  if (cn = (''nil'')) ∧ (tn = (''list'')) then
    Some []
  else
    None )"
|" v_to_list (Conv (Some (cn,TypeId (Short tn))) [v1,v2]) = (
  if (cn = (''::''))  ∧ (tn = (''list'')) then
    (case  v_to_list v2 of
        Some vs => Some (v1 # vs)
      | None => None
    )
  else
    None )"
|" v_to_list _ = ( None )" 
by pat_completeness auto


― ‹‹val v_to_char_list : v -> maybe (list char)››
function (sequential,domintros)  v_to_char_list  :: " v ⇒((char)list)option "  where 
     " v_to_char_list (Conv (Some (cn, TypeId (Short tn))) []) = (
  if (cn = (''nil'')) ∧ (tn = (''list'')) then
    Some []
  else
    None )"
|" v_to_char_list (Conv (Some (cn,TypeId (Short tn))) [Litv (Char c2),v2]) = (
  if (cn = (''::''))  ∧ (tn = (''list'')) then
    (case  v_to_char_list v2 of
        Some cs => Some (c2 # cs)
      | None => None
    )
  else
    None )"
|" v_to_char_list _ = ( None )" 
by pat_completeness auto


― ‹‹val vs_to_string : list v -> maybe string››
function (sequential,domintros)  vs_to_string  :: "(v)list ⇒(string)option "  where 
     " vs_to_string [] = ( Some (''''))"
|" vs_to_string (Litv(StrLit s1)# vs) = (
  (case  vs_to_string vs of
    Some s2 => Some (s1 @ s2)
  | _ => None
  ))"
|" vs_to_string _ = ( None )" 
by pat_completeness auto


― ‹‹val copy_array : forall 'a. list 'a * integer -> integer -> maybe (list 'a * integer) -> maybe (list 'a)››
fun copy_array  :: " 'a list*int ⇒ int ⇒('a list*int)option ⇒('a list)option "  where 
     " copy_array (src,srcoff) len d = (
  if (srcoff <( 0 :: int)) ∨ ((len <( 0 :: int)) ∨ (List.length src < nat (abs ( (srcoff + len))))) then None else
    (let copied = (List.take (nat (abs ( len))) (List.drop (nat (abs ( srcoff))) src)) in
    (case  d of
      Some (dst,dstoff) =>
        if (dstoff <( 0 :: int)) ∨ (List.length dst < nat (abs ( (dstoff + len)))) then None else
          Some ((List.take (nat (abs ( dstoff))) dst @
                copied) @
                List.drop (nat (abs ( (dstoff + len)))) dst)
    | None => Some copied
    )))"


― ‹‹val ws_to_chars : list word8 -> list char››
definition ws_to_chars  :: "(8 word)list ⇒(char)list "  where 
     " ws_to_chars ws = ( List.map (λ w .  (%n. char_of (n::nat))(unat w)) ws )"


― ‹‹val chars_to_ws : list char -> list word8››
definition chars_to_ws  :: "(char)list ⇒(8 word)list "  where 
     " chars_to_ws cs = ( List.map (λ c2 .  word_of_int(int(of_char c2))) cs )"


― ‹‹val opn_lookup : opn -> integer -> integer -> integer››
fun opn_lookup  :: " opn ⇒ int ⇒ int ⇒ int "  where 
     " opn_lookup Plus = ( (+))"
|" opn_lookup Minus = ( (-))"
|" opn_lookup Times = ( (*))"
|" opn_lookup Divide = ( (div))"
|" opn_lookup Modulo = ( (mod))"


― ‹‹val opb_lookup : opb -> integer -> integer -> bool››
fun opb_lookup  :: " opb ⇒ int ⇒ int ⇒ bool "  where 
     " opb_lookup Lt = ( (<))"
|" opb_lookup Gt = ( (>))"
|" opb_lookup Leq = ( (≤))"
|" opb_lookup Geq = ( (≥))"


― ‹‹val opw8_lookup : opw -> word8 -> word8 -> word8››
fun opw8_lookup  :: " opw ⇒ 8 word ⇒ 8 word ⇒ 8 word "  where 
     " opw8_lookup Andw = ( (AND) )"
|" opw8_lookup Orw = ( (OR) )"
|" opw8_lookup Xor = ( (XOR) )"
|" opw8_lookup Add = ( Groups.plus )"
|" opw8_lookup Sub = ( Groups.minus )"


― ‹‹val opw64_lookup : opw -> word64 -> word64 -> word64››
fun opw64_lookup  :: " opw ⇒ 64 word ⇒ 64 word ⇒ 64 word "  where 
     " opw64_lookup Andw = ( (AND) )"
|" opw64_lookup Orw = ( (OR) )"
|" opw64_lookup Xor = ( (XOR) )"
|" opw64_lookup Add = ( Groups.plus )"
|" opw64_lookup Sub = ( Groups.minus )"


― ‹‹val shift8_lookup : shift -> word8 -> nat -> word8››
fun shift8_lookup  :: " shift ⇒ 8 word ⇒ nat ⇒ 8 word "  where 
     " shift8_lookup Lsl = ( shiftl )"
|" shift8_lookup Lsr = ( shiftr )"
|" shift8_lookup Asr = ( sshiftr )"
|" shift8_lookup Ror = ( (% a b. word_rotr b a) )"


― ‹‹val shift64_lookup : shift -> word64 -> nat -> word64››
fun shift64_lookup  :: " shift ⇒ 64 word ⇒ nat ⇒ 64 word "  where 
     " shift64_lookup Lsl = ( shiftl )"
|" shift64_lookup Lsr = ( shiftr )"
|" shift64_lookup Asr = ( sshiftr )"
|" shift64_lookup Ror = ( (% a b. word_rotr b a) )"


― ‹‹val Boolv : bool -> v››
definition Boolv  :: " bool ⇒ v "  where 
     " Boolv b = ( if b
  then Conv (Some ((''true''), TypeId (Short (''bool'')))) []
  else Conv (Some ((''false''), TypeId (Short (''bool'')))) [])"


datatype exp_or_val =
    Exp " exp0 "
  | Val " v "

type_synonym( 'ffi, 'v) store_ffi =" 'v store * 'ffi ffi_state "

― ‹‹val do_app : forall 'ffi. store_ffi 'ffi v -> op -> list v -> maybe (store_ffi 'ffi v * result v v)››
fun do_app  :: "((v)store_v)list*'ffi ffi_state ⇒ op0 ⇒(v)list ⇒((((v)store_v)list*'ffi ffi_state)*((v),(v))result)option "  where 
     " do_app ((s:: v store),(t1:: 'ffi ffi_state)) op1 vs = (
  (case  (op1, vs) of
      (Opn op1, [Litv (IntLit n1), Litv (IntLit n2)]) =>
        if ((op1 = Divide) ∨ (op1 = Modulo)) ∧ (n2 =( 0 :: int)) then
          Some ((s,t1), Rerr (Rraise (prim_exn (''Div''))))
        else
          Some ((s,t1), Rval (Litv (IntLit (opn_lookup op1 n1 n2))))
    | (Opb op1, [Litv (IntLit n1), Litv (IntLit n2)]) =>
        Some ((s,t1), Rval (Boolv (opb_lookup op1 n1 n2)))
    | (Opw W8 op1, [Litv (Word8 w1), Litv (Word8 w2)]) =>
        Some ((s,t1), Rval (Litv (Word8 (opw8_lookup op1 w1 w2))))
    | (Opw W64 op1, [Litv (Word64 w1), Litv (Word64 w2)]) =>
        Some ((s,t1), Rval (Litv (Word64 (opw64_lookup op1 w1 w2))))
    | (FP_bop bop, [Litv (Word64 w1), Litv (Word64 w2)]) =>
        Some ((s,t1),Rval (Litv (Word64 (fp_bop bop w1 w2))))
    | (FP_uop uop, [Litv (Word64 w)]) =>
        Some ((s,t1),Rval (Litv (Word64 (fp_uop uop w))))
    | (FP_cmp cmp, [Litv (Word64 w1), Litv (Word64 w2)]) =>
        Some ((s,t1),Rval (Boolv (fp_cmp cmp w1 w2)))
    | (Shift W8 op1 n, [Litv (Word8 w)]) =>
        Some ((s,t1), Rval (Litv (Word8 (shift8_lookup op1 w n))))
    | (Shift W64 op1 n, [Litv (Word64 w)]) =>
        Some ((s,t1), Rval (Litv (Word64 (shift64_lookup op1 w n))))
    | (Equality, [v1, v2]) =>
        (case  do_eq v1 v2 of
            Eq_type_error => None
          | Eq_val b => Some ((s,t1), Rval (Boolv b))
        )
    | (Opassign, [Loc lnum, v2]) =>
        (case  store_assign lnum (Refv v2) s of
            Some s' => Some ((s',t1), Rval (Conv None []))
          | None => None
        )
    | (Opref, [v2]) =>
        (let (s',n) = (store_alloc (Refv v2) s) in
          Some ((s',t1), Rval (Loc n)))
    | (Opderef, [Loc n]) =>
        (case  store_lookup n s of
            Some (Refv v2) => Some ((s,t1),Rval v2)
          | _ => None
        )
    | (Aw8alloc, [Litv (IntLit n), Litv (Word8 w)]) =>
        if n <( 0 :: int) then
          Some ((s,t1), Rerr (Rraise (prim_exn (''Subscript''))))
        else
          (let (s',lnum) =
            (store_alloc (W8array (List.replicate (nat (abs ( n))) w)) s)
          in
            Some ((s',t1), Rval (Loc lnum)))
    | (Aw8sub, [Loc lnum, Litv (IntLit i)]) =>
        (case  store_lookup lnum s of
            Some (W8array ws) =>
              if i <( 0 :: int) then
                Some ((s,t1), Rerr (Rraise (prim_exn (''Subscript''))))
              else
                (let n = (nat (abs ( i))) in
                  if n ≥ List.length ws then
                    Some ((s,t1), Rerr (Rraise (prim_exn (''Subscript''))))
                  else
                    Some ((s,t1), Rval (Litv (Word8 (List.nth ws n)))))
          | _ => None
        )
    | (Aw8length, [Loc n]) =>
        (case  store_lookup n s of
            Some (W8array ws) =>
              Some ((s,t1),Rval (Litv(IntLit(int(List.length ws)))))
          | _ => None
         )
    | (Aw8update, [Loc lnum, Litv(IntLit i), Litv(Word8 w)]) =>
        (case  store_lookup lnum s of
          Some (W8array ws) =>
            if i <( 0 :: int) then
              Some ((s,t1), Rerr (Rraise (prim_exn (''Subscript''))))
            else
              (let n = (nat (abs ( i))) in
                if n ≥ List.length ws then
                  Some ((s,t1), Rerr (Rraise (prim_exn (''Subscript''))))
                else
                  (case  store_assign lnum (W8array (List.list_update ws n w)) s of
                      None => None
                    | Some s' => Some ((s',t1), Rval (Conv None []))
                  ))
        | _ => None
      )
    | (WordFromInt W8, [Litv(IntLit i)]) =>
        Some ((s,t1), Rval (Litv (Word8 (word_of_int i))))
    | (WordFromInt W64, [Litv(IntLit i)]) =>
        Some ((s,t1), Rval (Litv (Word64 (word_of_int i))))
    | (WordToInt W8, [Litv (Word8 w)]) =>
        Some ((s,t1), Rval (Litv (IntLit (int(unat w)))))
    | (WordToInt W64, [Litv (Word64 w)]) =>
        Some ((s,t1), Rval (Litv (IntLit (int(unat w)))))
    | (CopyStrStr, [Litv(StrLit str),Litv(IntLit off),Litv(IntLit len)]) =>
        Some ((s,t1),
        (case  copy_array ( str,off) len None of
          None => Rerr (Rraise (prim_exn (''Subscript'')))
        | Some cs => Rval (Litv(StrLit((cs))))
        ))
    | (CopyStrAw8, [Litv(StrLit str),Litv(IntLit off),Litv(IntLit len),
                    Loc dst,Litv(IntLit dstoff)]) =>
        (case  store_lookup dst s of
          Some (W8array ws) =>
            (case  copy_array ( str,off) len (Some(ws_to_chars ws,dstoff)) of
              None => Some ((s,t1), Rerr (Rraise (prim_exn (''Subscript''))))
            | Some cs =>
              (case  store_assign dst (W8array (chars_to_ws cs)) s of
                Some s' =>  Some ((s',t1), Rval (Conv None []))
              | _ => None
              )
            )
        | _ => None
        )
    | (CopyAw8Str, [Loc src,Litv(IntLit off),Litv(IntLit len)]) =>
      (case  store_lookup src s of
        Some (W8array ws) =>
        Some ((s,t1),
          (case  copy_array (ws,off) len None of
            None => Rerr (Rraise (prim_exn (''Subscript'')))
          | Some ws => Rval (Litv(StrLit((ws_to_chars ws))))
          ))
      | _ => None
      )
    | (CopyAw8Aw8, [Loc src,Litv(IntLit off),Litv(IntLit len),
                    Loc dst,Litv(IntLit dstoff)]) =>
      (case  (store_lookup src s, store_lookup dst s) of
        (Some (W8array ws), Some (W8array ds)) =>
          (case  copy_array (ws,off) len (Some(ds,dstoff)) of
            None => Some ((s,t1), Rerr (Rraise (prim_exn (''Subscript''))))
          | Some ws =>
              (case  store_assign dst (W8array ws) s of
                Some s' => Some ((s',t1), Rval (Conv None []))
              | _ => None
              )
          )
      | _ => None
      )
    | (Ord, [Litv (Char c2)]) =>
          Some ((s,t1), Rval (Litv(IntLit(int(of_char c2)))))
    | (Chr, [Litv (IntLit i)]) =>
        Some ((s,t1),
          (if (i <( 0 :: int)) ∨ (i >( 255 :: int)) then
            Rerr (Rraise (prim_exn (''Chr'')))
          else
            Rval (Litv(Char((%n. char_of (n::nat))(nat (abs ( i))))))))
    | (Chopb op1, [Litv (Char c1), Litv (Char c2)]) =>
        Some ((s,t1), Rval (Boolv (opb_lookup op1 (int(of_char c1)) (int(of_char c2)))))
    | (Implode, [v2]) =>
          (case  v_to_char_list v2 of
            Some ls =>
              Some ((s,t1), Rval (Litv (StrLit ( ls))))
          | None => None
          )
    | (Strsub, [Litv (StrLit str), Litv (IntLit i)]) =>
        if i <( 0 :: int) then
          Some ((s,t1), Rerr (Rraise (prim_exn (''Subscript''))))
        else
          (let n = (nat (abs ( i))) in
            if n ≥ List.length str then
              Some ((s,t1), Rerr (Rraise (prim_exn (''Subscript''))))
            else
              Some ((s,t1), Rval (Litv (Char (List.nth ( str) n)))))
    | (Strlen, [Litv (StrLit str)]) =>
        Some ((s,t1), Rval (Litv(IntLit(int(List.length str)))))
    | (Strcat, [v2]) =>
        (case  v_to_list v2 of
          Some vs =>
            (case  vs_to_string vs of
              Some str =>
                Some ((s,t1), Rval (Litv(StrLit str)))
            | _ => None
            )
        | _ => None
        )
    | (VfromList, [v2]) =>
          (case  v_to_list v2 of
              Some vs =>
                Some ((s,t1), Rval (Vectorv vs))
            | None => None
          )
    | (Vsub, [Vectorv vs, Litv (IntLit i)]) =>
        if i <( 0 :: int) then
          Some ((s,t1), Rerr (Rraise (prim_exn (''Subscript''))))
        else
          (let n = (nat (abs ( i))) in
            if n ≥ List.length vs then
              Some ((s,t1), Rerr (Rraise (prim_exn (''Subscript''))))
            else
              Some ((s,t1), Rval (List.nth vs n)))
    | (Vlength, [Vectorv vs]) =>
        Some ((s,t1), Rval (Litv (IntLit (int (List.length vs)))))
    | (Aalloc, [Litv (IntLit n), v2]) =>
        if n <( 0 :: int) then
          Some ((s,t1), Rerr (Rraise (prim_exn (''Subscript''))))
        else
          (let (s',lnum) =
            (store_alloc (Varray (List.replicate (nat (abs ( n))) v2)) s)
          in
            Some ((s',t1), Rval (Loc lnum)))
    | (AallocEmpty, [Conv None []]) =>
        (let (s',lnum) = (store_alloc (Varray []) s) in
          Some ((s',t1), Rval (Loc lnum)))
    | (Asub, [Loc lnum, Litv (IntLit i)]) =>
        (case  store_lookup lnum s of
            Some (Varray vs) =>
              if i <( 0 :: int) then
                Some ((s,t1), Rerr (Rraise (prim_exn (''Subscript''))))
              else
                (let n = (nat (abs ( i))) in
                  if n ≥ List.length vs then
                    Some ((s,t1), Rerr (Rraise (prim_exn (''Subscript''))))
                  else
                    Some ((s,t1), Rval (List.nth vs n)))
          | _ => None
        )
    | (Alength, [Loc n]) =>
        (case  store_lookup n s of
            Some (Varray ws) =>
              Some ((s,t1),Rval (Litv(IntLit(int(List.length ws)))))
          | _ => None
         )
    | (Aupdate, [Loc lnum, Litv (IntLit i), v2]) =>
        (case  store_lookup lnum s of
          Some (Varray vs) =>
            if i <( 0 :: int) then
              Some ((s,t1), Rerr (Rraise (prim_exn (''Subscript''))))
            else
              (let n = (nat (abs ( i))) in
                if n ≥ List.length vs then
                  Some ((s,t1), Rerr (Rraise (prim_exn (''Subscript''))))
                else
                  (case  store_assign lnum (Varray (List.list_update vs n v2)) s of
                      None => None
                    | Some s' => Some ((s',t1), Rval (Conv None []))
                  ))
        | _ => None
      )
    | (ConfigGC, [Litv (IntLit i), Litv (IntLit j)]) =>
        Some ((s,t1), Rval (Conv None []))
    | (FFI n, [Litv(StrLit conf), Loc lnum]) =>
        (case  store_lookup lnum s of
          Some (W8array ws) =>
            (case  call_FFI t1 n (List.map (λ c2 .  of_nat(of_char c2)) ( conf)) ws of
              (t', ws') =>
               (case  store_assign lnum (W8array ws') s of
                 Some s' => Some ((s', t'), Rval (Conv None []))
               | None => None
               )
            )
        | _ => None
        )
    | _ => None
  ))"


― ‹‹ Do a logical operation ››
― ‹‹val do_log : lop -> v -> exp -> maybe exp_or_val››
fun do_log  :: " lop ⇒ v ⇒ exp0 ⇒(exp_or_val)option "  where 
     " do_log And v2 e = ( 
  (case  v2 of
      Litv _ => None
    | Conv m l2 => (case  m of
                       None => None
                     | Some p => (case  p of
                                     (s1,t1) =>
                                 if(s1 = (''true'')) then
                                   ((case  t1 of
                                        TypeId i => (case  i of
                                                        Short s2 =>
                                                    if(s2 = (''bool'')) then
                                                      ((case  l2 of
                                                           [] => Some (Exp e)
                                                         | _ => None
                                                       )) else None
                                                      | Long _ _ => None
                                                    )
                                      | TypeExn _ => None
                                    )) else
                                   (
                                   if(s1 = (''false'')) then
                                     ((case  t1 of
                                          TypeId i2 => (case  i2 of
                                                           Short s4 =>
                                                       if(s4 = (''bool'')) then
                                                         ((case  l2 of
                                                              [] => Some
                                                                    (Val v2)
                                                            | _ => None
                                                          )) else None
                                                         | Long _ _ => 
                                                       None
                                                       )
                                        | TypeExn _ => None
                                      )) else None)
                                 )
                   )
    | Closure _ _ _ => None
    | Recclosure _ _ _ => None
    | Loc _ => None
    | Vectorv _ => None
  ) )"
|" do_log Or v2 e = ( 
  (case  v2 of
      Litv _ => None
    | Conv m0 l6 => (case  m0 of
                        None => None
                      | Some p0 => (case  p0 of
                                       (s8,t0) =>
                                   if(s8 = (''false'')) then
                                     ((case  t0 of
                                          TypeId i5 => (case  i5 of
                                                           Short s9 =>
                                                       if(s9 = (''bool'')) then
                                                         ((case  l6 of
                                                              [] => Some
                                                                    (Exp e)
                                                            | _ => None
                                                          )) else None
                                                         | Long _ _ => 
                                                       None
                                                       )
                                        | TypeExn _ => None
                                      )) else
                                     (
                                     if(s8 = (''true'')) then
                                       ((case  t0 of
                                            TypeId i8 => (case  i8 of
                                                             Short s11 =>
                                                         if(s11 = (''bool'')) then
                                                           ((case  l6 of
                                                                [] => 
                                                            Some (Val v2)
                                                              | _ => 
                                                            None
                                                            )) else None
                                                           | Long _ _ => 
                                                         None
                                                         )
                                          | TypeExn _ => None
                                        )) else None)
                                   )
                    )
    | Closure _ _ _ => None
    | Recclosure _ _ _ => None
    | Loc _ => None
    | Vectorv _ => None
  ) )"


― ‹‹ Do an if-then-else ››
― ‹‹val do_if : v -> exp -> exp -> maybe exp››
definition do_if  :: " v ⇒ exp0 ⇒ exp0 ⇒(exp0)option "  where 
     " do_if v2 e1 e2 = (
  if v2 = (Boolv True) then
    Some e1
  else if v2 = (Boolv False) then
    Some e2
  else
    None )"


― ‹‹ Semantic helpers for definitions ››

― ‹‹ Build a constructor environment for the type definition tds ››
― ‹‹val build_tdefs : list modN -> list (list tvarN * typeN * list (conN * list t)) -> env_ctor››
definition build_tdefs  :: "(string)list ⇒((tvarN)list*string*(string*(t)list)list)list ⇒((string),(string),(nat*tid_or_exn))namespace "  where 
     " build_tdefs mn tds = (
  alist_to_ns
    (List.rev
      (List.concat
        (List.map
          ( λx .  
  (case  x of
      (tvs, tn, condefs) =>
  List.map
    ( λx .  (case  x of
                        (conN, ts) =>
                    (conN, (List.length ts, TypeId (mk_id mn tn)))
                    )) condefs
  ))
          tds))))"


― ‹‹ Checks that no constructor is defined twice in a type ››
― ‹‹val check_dup_ctors : list (list tvarN * typeN * list (conN * list t)) -> bool››
definition check_dup_ctors  :: "((tvarN)list*string*(string*(t)list)list)list ⇒ bool "  where 
     " check_dup_ctors tds = (
  Lem_list.allDistinct ((let x2 = 
  ([]) in  List.foldr
   (λx .  (case  x of
                      (tvs, tn, condefs) => λ x2 .  List.foldr
                                                              (λx .  
                                                               (case  x of
                                                                   (n, ts) => 
                                                               λ x2 . 
                                                                 if True then
                                                                   n # x2
                                                                 else 
                                                                 x2
                                                               )) condefs 
                                                            x2
                  )) tds x2)))"


― ‹‹val combine_dec_result : forall 'a. sem_env v -> result (sem_env v) 'a -> result (sem_env v) 'a››
fun combine_dec_result  :: "(v)sem_env ⇒(((v)sem_env),'a)result ⇒(((v)sem_env),'a)result "  where 
     " combine_dec_result env (Rerr e) = ( Rerr e )"
|" combine_dec_result env (Rval env') = ( Rval (| v = (nsAppend(v   env')(v   env)), c = (nsAppend(c   env')(c   env)) |) )"


― ‹‹val extend_dec_env : sem_env v -> sem_env v -> sem_env v››
definition extend_dec_env  :: "(v)sem_env ⇒(v)sem_env ⇒(v)sem_env "  where 
     " extend_dec_env new_env env = (
  (| v = (nsAppend(v   new_env)(v   env)), c = (nsAppend(c   new_env)(c   env))  |) )"


― ‹‹val decs_to_types : list dec -> list typeN››
definition decs_to_types  :: "(dec)list ⇒(string)list "  where 
     " decs_to_types ds = (
  List.concat (List.map (λ d . 
        (case  d of
            Dtype locs tds => List.map ( λx .  
  (case  x of (tvs,tn,ctors) => tn )) tds
          | _ => [] ))
     ds))"


― ‹‹val no_dup_types : list dec -> bool››
definition no_dup_types  :: "(dec)list ⇒ bool "  where 
     " no_dup_types ds = (
  Lem_list.allDistinct (decs_to_types ds))"


― ‹‹val prog_to_mods : list top -> list (list modN)››
definition prog_to_mods  :: "(top0)list ⇒((string)list)list "  where 
     " prog_to_mods tops = (
  List.concat (List.map (λ top1 . 
        (case  top1 of
            Tmod mn _ _ => [[mn]]
          | _ => [] ))
     tops))"


― ‹‹val no_dup_mods : list top -> set (list modN) -> bool››
definition no_dup_mods  :: "(top0)list ⇒((modN)list)set ⇒ bool "  where 
     " no_dup_mods tops defined_mods2 = (
  Lem_list.allDistinct (prog_to_mods tops) ∧
  disjnt (List.set (prog_to_mods tops)) defined_mods2 )"


― ‹‹val prog_to_top_types : list top -> list typeN››
definition prog_to_top_types  :: "(top0)list ⇒(string)list "  where 
     " prog_to_top_types tops = (
  List.concat (List.map (λ top1 . 
        (case  top1 of
            Tdec d => decs_to_types [d]
          | _ => [] ))
     tops))"


― ‹‹val no_dup_top_types : list top -> set tid_or_exn -> bool››
definition no_dup_top_types  :: "(top0)list ⇒(tid_or_exn)set ⇒ bool "  where 
     " no_dup_top_types tops defined_types2 = (
  Lem_list.allDistinct (prog_to_top_types tops) ∧
  disjnt (List.set (List.map (λ tn .  TypeId (Short tn)) (prog_to_top_types tops))) defined_types2 )"

end