packages feed

liquid-fixpoint-0.2.2.0: external/fixpoint/theories.ml

(*
 * Copyright © 2009 The Regents of the University of California. All rights reserved. 
 *
 * Permission is hereby granted, without written agreement and without 
 * license or royalty fees, to use, copy, modify, and distribute this 
 * software and its documentation for any purpose, provided that the 
 * above copyright notice and the following two paragraphs appear in 
 * all copies of this software. 
 * 
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 
 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 
 * IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY 
 * OF SUCH DAMAGE. 
 * 
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
 * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 
 * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION 
 * TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
 *)

module So = Ast.Sort
module Sy = Ast.Symbol

open ProverArch
open FixMisc.Ops

(***************************************************************************)
(********************* NAMES (independent of SMT) **************************)
(***************************************************************************)

(********************* Sets ************************************************)

let set_tycon  = So.tycon "Set_Set"
let t_set a    = So.t_app set_tycon [a]

(* API *)
let emp0 = ( Sy.of_string "Set_empty"
           , So.t_func 1 [So.t_int; t_set (So.t_generic 0)] )

let emp = ( Sy.of_string "Set_emp"
          , So.t_func 1 [t_set (So.t_generic 0); So.t_bool] )

let sng = ( Sy.of_string "Set_sng"
          , So.t_func 1 [So.t_generic 0; t_set (So.t_generic 0)] )

let mem = ( Sy.of_string "Set_mem"
          , So.t_func 1 [So.t_generic 0; t_set (So.t_generic 0); So.t_bool] )

let cup = ( Sy.of_string "Set_cup"
          , So.t_func 1 [t_set (So.t_generic 0); t_set (So.t_generic 0); t_set (So.t_generic 0)])

let cap = ( Sy.of_string "Set_cap"
          , So.t_func 1 [t_set (So.t_generic 0); t_set (So.t_generic 0); t_set (So.t_generic 0)])

let dif = ( Sy.of_string "Set_dif"
          , So.t_func 1 [t_set (So.t_generic 0); t_set (So.t_generic 0); t_set (So.t_generic 0)])

let sub = ( Sy.of_string "Set_sub" 
          , So.t_func 1 [t_set (So.t_generic 0); t_set (So.t_generic 0); So.t_bool] )

(********************* Maps ************************************************)

let map_tycon  = So.tycon "Map_t"

let t_map k v  = So.t_app map_tycon [k; v]

let select     = let k = So.t_generic 0 in
                 let v = So.t_generic 1 in
                 ( Sy.of_string "Map_select"
                 , So.t_func 2 [t_map k v; k; v] )

let store      = let k = So.t_generic 0 in
                 let v = So.t_generic 1 in
                 ( Sy.of_string "Map_store"
                 , So.t_func 2 [t_map k v; k; v; t_map k v] )



(********************* Maps ************************************************)

let bv_tycon     = So.tycon "BitVec"
let sz32_tycon   = So.tycon "Size32"
let sz64_tycon   = So.tycon "Size64"
let t_bv a       = So.t_app bv_tycon [a]

let bv_binop op  = let k = So.t_generic 0 in
                   ( Sy.of_string op 
                   , So.t_func 1 [t_bv k; t_bv k; t_bv k] ) 

let bvand        = bv_binop "bvand"
let bvor         = bv_binop "bvor"

                 
(********************* All Theories ****************************************)
(** WARNING: DO NOT PUT INSIDE MakeTheory; adds SMT dependency *************)
(***************************************************************************)

(* API *)
let is_interp t = List.mem t [set_tycon; map_tycon; sz32_tycon; sz64_tycon; bv_tycon]

(* API *)
let interp_syms _ 
  = []
    |> (!Constants.set_theory <?> (++) [emp0  ; emp; sng; mem; cup; cap; dif; sub])
    |> (!Constants.map_theory <?> (++) [select; store])
    |> (!Constants.bit_theory <?> (++) [bvand ; bvor])


(***************************************************************************)
(***************************************************************************)
(***************************************************************************)

module MakeTheory(SMT : SMTSOLVER): 
  (THEORY with type context = SMT.context 
          and  type sort    = SMT.sort
          and  type ast     = SMT.ast) 
  = struct 

type context = SMT.context
type sort    = SMT.sort
type ast     = SMT.ast


type appDef  = { sy_name  : Sy.t
               ; sy_sort  : So.t
               ; sy_emb   : SMT.context -> SMT.sort list -> SMT.ast list -> SMT.ast
               }

type sortDef = { so_name  : Ast.Sort.tycon
               ; so_arity : int
               ; so_emb   : SMT.context -> SMT.sort list -> SMT.sort 
               }

(* API *)
let sort_name d = d.so_name
let sym_name d  = d.sy_name
let sym_sort d  = d.sy_sort

(***************************************************************************)
(********* Wrappers Around Z3 Constructors For Last-Minute Checking ********)
(***************************************************************************)

let app_sort_arity def = match So.func_of_t def.sy_sort with
  | Some (n,_,_) -> n
  | None         -> assertf "Theories: app with non-function symbol %s" 
                    (Sy.to_string def.sy_name)

let check_app_arities def tArgs eArgs = match So.func_of_t def.sy_sort with
  | Some (n, ts,_) 
     -> asserts (n = List.length tArgs)  
          "Theories: app with mismatched sorts %s" (Sy.to_string def.sy_name);
        asserts (List.length ts = List.length eArgs) 
          "Theories: app with mismatched args %s" (Sy.to_string def.sy_name) 
  | None         
     -> assertf "Theories: app with non-function symbol %s" 
          (Sy.to_string def.sy_name)


(* API *)
let mk_thy_app def c ts es = 
  check_app_arities def ts es;
  def.sy_emb c ts es

(* API *)
let mk_thy_sort def c ts = 
  asserts (List.length ts = def.so_arity) 
    "Theories: app with mismatched sorts %s" (So.tycon_string def.so_name);
  def.so_emb c ts 


(** Theory of Sets *********************************************************)


let set_t : sortDef = 
  { so_name  = set_tycon 
  ; so_arity = 1 
  ; so_emb   = fun c -> function 
                 [t] -> SMT.mkSetSort c t
                 | _ -> assertf "Set_set: type mismatch"
  }  

let set_empty : appDef  = 
  { sy_name  = fst emp0
  ; sy_sort  = snd emp0 
  ; sy_emb   = fun c ts es -> match ts, es with
                 | [t], [_] -> SMT.mkEmptySet c t
                 | _        -> assertf "Set_empty: type mismatch"
  }

let set_emp : appDef  = 
  { sy_name  = fst emp 
  ; sy_sort  = snd emp 
  ; sy_emb   = fun c ts es -> match ts, es with
                 | [t], [e] -> SMT.mkRel c Ast.Eq e (SMT.mkEmptySet c t)
                 | _        -> assertf "Set_emp: type mismatch"
  }

let set_sng : appDef  = 
  { sy_name = fst sng 
  ; sy_sort = snd sng  
  ; sy_emb  = fun c ts es -> match ts, es with
                 | [t], [e] -> SMT.mkSetAdd c (SMT.mkEmptySet c t) e
                 | _        -> assertf "Set_sng: type mismatch"
  }


let set_mem : appDef  = 
  { sy_name = fst mem 
  ; sy_sort = snd mem
  ; sy_emb  = fun c ts es -> match ts, es with
                 | [_], [e;es] -> SMT.mkSetMem c e es 
                 | _           -> assertf "Set_mem: type mismatch"
  }

let set_cup : appDef  = 
  { sy_name = fst cup 
  ; sy_sort = snd cup
  ; sy_emb  = fun c ts es -> match ts, es with
                 | [t], [e1;e2] -> SMT.mkSetCup c e1 e2
                 | _            -> assertf "Set_cup: type mismatch"
  }

let set_cap : appDef  = 
  { sy_name = fst cap 
  ; sy_sort = snd cap 
  ; sy_emb  = fun c ts es -> match ts, es with
                 | [t], [e1;e2] -> SMT.mkSetCap  c e1 e2
                 | _            -> assertf "Set_cap: type mismatch"
  }

let set_dif : appDef  = 
  { sy_name = fst dif 
  ; sy_sort = snd dif
  ; sy_emb  = fun c ts es -> match ts, es with
                 | [t], [e1;e2] -> SMT.mkSetDif c e1 e2 
                 | _            -> assertf "Set_dif: type mismatch"
  }

let set_sub : appDef =
  { sy_name = fst sub 
  ; sy_sort = snd sub
  ; sy_emb  = fun c ts es -> match ts, es with
                 | [t], [e1;e2] -> SMT.mkSetSub c e1 e2 
                 | _            -> assertf "Set_dif: type mismatch"
  }

(* API *)
let theory_set 
  = ([ set_t ]
    ,[ set_emp 
     ; set_empty 
     ; set_sng 
     ; set_mem 
     ; set_cup 
     ; set_cap 
     ; set_dif 
     ; set_sub ])

(** Theory of Maps *********************************************************)

let map_t : sortDef = 
  { so_name  = map_tycon 
  ; so_arity = 2 
  ; so_emb   = fun c -> function 
                 | [k; v] -> SMT.mkMapSort c k v 
                 | _      -> assertf "Map_t: type mismatch"
  }  

let map_select : appDef  = 
  { sy_name = fst select 
  ; sy_sort = snd select 
  ; sy_emb  = fun c ts es -> match ts, es with
                 | [_; _], [m; k] -> SMT.mkMapSelect c m k 
                 | _           -> assertf "Map_select: type mismatch"
  }

let map_store : appDef  = 
  { sy_name = fst store 
  ; sy_sort = snd store 
  ; sy_emb  = fun c ts es -> match ts, es with
                 | [_; _], [m; k; v] -> SMT.mkMapStore c m k v 
                 | _           -> assertf "Map_store: type mismatch"
  }

(* API *)
let theory_map
  = ([map_t], [map_select; map_store])

(** Theory of Bitvectors ***************************************************)

let size32_t : sortDef =
  { so_name  = sz32_tycon 
  ; so_arity = 1 
  ; so_emb   = fun c -> function 
                 | [_] -> SMT.mkSizeSort c 32 
                 | _   -> assertf "Map_t: type mismatch"
  }  

let size64_t : sortDef =
  { so_name  = sz64_tycon 
  ; so_arity = 1 
  ; so_emb   = fun c   -> function 
                 | [_] -> SMT.mkSizeSort c 64 
                 | _   -> assertf "Map_t: type mismatch"
  }  
    
let bit_t : sortDef =
  { so_name  = bv_tycon 
  ; so_arity = 1 
  ; so_emb   = fun c -> function 
                 | [n] -> SMT.mkBitSort c n 
                 | _   -> assertf "BitVector: type mismatch"
  }  

let bit_and : appDef  = 
  { sy_name = fst bvand 
  ; sy_sort = snd bvand  
  ; sy_emb  = fun c ts es -> match ts, es with
                 | [_], [x; y] -> SMT.mkBitAnd c x y 
                 | _           -> assertf "bit_and: type mismatch"
  }

let bit_or : appDef  = 
  { sy_name = fst bvor
  ; sy_sort = snd bvor
  ; sy_emb  = fun c ts es -> match ts, es with
                 | [_], [x; y] -> SMT.mkBitOr c x y 
                 | _           -> assertf "bit_or: type mismatch"
  }

(* API *)
let theory_bit
  = ([size32_t; size64_t; bit_t], [bit_and; bit_or])
    
(** Theory Composition *****************************************************)

(* API *)
let theories () = 
  let add_thy (t1,s1) (t2,s2) = (t1 ++ t2, s1 ++ s2) in
  ([], [])
  |> (!Constants.set_theory <?> add_thy theory_set)
  |> (!Constants.map_theory <?> add_thy theory_map)
  |> (!Constants.bit_theory <?> add_thy theory_bit)

end