src/HOL/Library/Old_SMT/old_smt_word.ML
author wenzelm
Wed Jun 17 11:03:05 2015 +0200 (2015-06-17)
changeset 60500 903bb1495239
parent 58825 2065f49da190
permissions -rw-r--r--
isabelle update_cartouches;
     1 (*  Title:      HOL/Library/Old_SMT/old_smt_word.ML
     2     Author:     Sascha Boehme, TU Muenchen
     3 
     4 SMT setup for words.
     5 *)
     6 
     7 structure Old_SMT_Word: sig end =
     8 struct
     9 
    10 open Word_Lib
    11 
    12 (* SMT-LIB logic *)
    13 
    14 fun smtlib_logic ts =
    15   if exists (Term.exists_type (Term.exists_subtype is_wordT)) ts
    16   then SOME "QF_AUFBV"
    17   else NONE
    18 
    19 
    20 (* SMT-LIB builtins *)
    21 
    22 local
    23   val smtlibC = Old_SMTLIB_Interface.smtlibC
    24 
    25   val wordT = @{typ "'a::len word"}
    26 
    27   fun index1 n i = n ^ "[" ^ string_of_int i ^ "]"
    28   fun index2 n i j = n ^ "[" ^ string_of_int i ^ ":" ^ string_of_int j ^ "]"
    29 
    30   fun word_typ (Type (@{type_name word}, [T])) =
    31         Option.map (index1 "BitVec") (try dest_binT T)
    32     | word_typ _ = NONE
    33 
    34   fun word_num (Type (@{type_name word}, [T])) i =
    35         Option.map (index1 ("bv" ^ string_of_int i)) (try dest_binT T)
    36     | word_num _ _ = NONE
    37 
    38   fun if_fixed pred m n T ts =
    39     let val (Us, U) = Term.strip_type T
    40     in
    41       if pred (U, Us) then
    42         SOME (n, length Us, ts, Term.list_comb o pair (Const (m, T)))
    43       else NONE
    44     end
    45 
    46   fun if_fixed_all m = if_fixed (forall (can dest_wordT) o (op ::)) m
    47   fun if_fixed_args m = if_fixed (forall (can dest_wordT) o snd) m
    48 
    49   fun add_word_fun f (t, n) =
    50     let val (m, _) = Term.dest_Const t
    51     in Old_SMT_Builtin.add_builtin_fun smtlibC (Term.dest_Const t, K (f m n)) end
    52 
    53   fun hd2 xs = hd (tl xs)
    54 
    55   fun mk_nat i = @{const nat} $ HOLogic.mk_number @{typ nat} i
    56 
    57   fun dest_nat (@{const nat} $ n) = snd (HOLogic.dest_number n)
    58     | dest_nat t = raise TERM ("not a natural number", [t])
    59 
    60   fun mk_shift c [t, u] = Const c $ t $ mk_nat (snd (HOLogic.dest_number u))
    61     | mk_shift c ts = raise TERM ("bad arguments", Const c :: ts)
    62 
    63   fun shift m n T ts =
    64     let val U = Term.domain_type T
    65     in
    66       (case (can dest_wordT U, try (dest_nat o hd2) ts) of
    67         (true, SOME i) =>
    68           SOME (n, 2, [hd ts, HOLogic.mk_number U i], mk_shift (m, T))
    69       | _ => NONE)   (* FIXME: also support non-numerical shifts *)
    70     end
    71 
    72   fun mk_extract c i ts = Term.list_comb (Const c, mk_nat i :: ts)
    73 
    74   fun extract m n T ts =
    75     let val U = Term.range_type (Term.range_type T)
    76     in
    77       (case (try (dest_nat o hd) ts, try dest_wordT U) of
    78         (SOME lb, SOME i) =>
    79           SOME (index2 n (i + lb - 1) lb, 1, tl ts, mk_extract (m, T) lb)
    80       | _ => NONE)
    81     end
    82 
    83   fun mk_extend c ts = Term.list_comb (Const c, ts)
    84 
    85   fun extend m n T ts =
    86     let val (U1, U2) = Term.dest_funT T
    87     in
    88       (case (try dest_wordT U1, try dest_wordT U2) of
    89         (SOME i, SOME j) =>
    90           if j-i >= 0 then SOME (index1 n (j-i), 1, ts, mk_extend (m, T))
    91           else NONE
    92       | _ => NONE)
    93     end
    94 
    95   fun mk_rotate c i ts = Term.list_comb (Const c, mk_nat i :: ts)
    96 
    97   fun rotate m n T ts =
    98     let val U = Term.domain_type (Term.range_type T)
    99     in
   100       (case (can dest_wordT U, try (dest_nat o hd) ts) of
   101         (true, SOME i) => SOME (index1 n i, 1, tl ts, mk_rotate (m, T) i)
   102       | _ => NONE)
   103     end
   104 in
   105 
   106 val setup_builtins =
   107   Old_SMT_Builtin.add_builtin_typ smtlibC (wordT, word_typ, word_num) #>
   108   fold (add_word_fun if_fixed_all) [
   109     (@{term "uminus :: 'a::len word => _"}, "bvneg"),
   110     (@{term "plus :: 'a::len word => _"}, "bvadd"),
   111     (@{term "minus :: 'a::len word => _"}, "bvsub"),
   112     (@{term "times :: 'a::len word => _"}, "bvmul"),
   113     (@{term "bitNOT :: 'a::len word => _"}, "bvnot"),
   114     (@{term "bitAND :: 'a::len word => _"}, "bvand"),
   115     (@{term "bitOR :: 'a::len word => _"}, "bvor"),
   116     (@{term "bitXOR :: 'a::len word => _"}, "bvxor"),
   117     (@{term "word_cat :: 'a::len word => _"}, "concat") ] #>
   118   fold (add_word_fun shift) [
   119     (@{term "shiftl :: 'a::len word => _ "}, "bvshl"),
   120     (@{term "shiftr :: 'a::len word => _"}, "bvlshr"),
   121     (@{term "sshiftr :: 'a::len word => _"}, "bvashr") ] #>
   122   add_word_fun extract
   123     (@{term "slice :: _ => 'a::len word => _"}, "extract") #>
   124   fold (add_word_fun extend) [
   125     (@{term "ucast :: 'a::len word => _"}, "zero_extend"),
   126     (@{term "scast :: 'a::len word => _"}, "sign_extend") ] #>
   127   fold (add_word_fun rotate) [
   128     (@{term word_rotl}, "rotate_left"),
   129     (@{term word_rotr}, "rotate_right") ] #>
   130   fold (add_word_fun if_fixed_args) [
   131     (@{term "less :: 'a::len word => _"}, "bvult"),
   132     (@{term "less_eq :: 'a::len word => _"}, "bvule"),
   133     (@{term word_sless}, "bvslt"),
   134     (@{term word_sle}, "bvsle") ]
   135 
   136 end
   137 
   138 
   139 (* setup *)
   140 
   141 val _ = 
   142   Theory.setup
   143     (Context.theory_map
   144       (Old_SMTLIB_Interface.add_logic (20, smtlib_logic) #> setup_builtins))
   145 
   146 end