metaSMT 2
|
00001 #pragma once 00002 00003 #include "../support/SMT_Graph.hpp" 00004 #include "../tags/QF_BV.hpp" 00005 #include "../tags/Logics.hpp" 00006 #include "../impl/_var_id.hpp" 00007 #include "Logic.hpp" 00008 #include "Array.hpp" 00009 #include <boost/proto/core.hpp> 00010 #include <boost/type_traits/is_signed.hpp> 00011 #include <string> 00012 00013 00014 00015 namespace proto = boost::proto; 00016 00017 namespace metaSMT { 00018 00019 namespace logic { 00024 namespace QF_BV { 00025 00026 struct QF_BV_Grammar; 00027 00028 struct QF_BV_Unary_Function 00029 :proto::or_< 00030 proto::unary_expr<tag::bvnot_tag, QF_BV_Grammar> 00031 , proto::unary_expr<tag::bvneg_tag, QF_BV_Grammar> 00032 > 00033 {}; 00034 00035 struct QF_BV_Binary_Function 00036 : proto::or_< 00037 //logic 00038 proto::or_< 00039 proto::binary_expr<tag::bvand_tag, QF_BV_Grammar, QF_BV_Grammar> 00040 , proto::binary_expr<tag::bvnand_tag, QF_BV_Grammar, QF_BV_Grammar> 00041 , proto::binary_expr<tag::bvor_tag, QF_BV_Grammar, QF_BV_Grammar> 00042 , proto::binary_expr<tag::bvnor_tag, QF_BV_Grammar, QF_BV_Grammar> 00043 , proto::binary_expr<tag::bvxor_tag, QF_BV_Grammar, QF_BV_Grammar> 00044 , proto::binary_expr<tag::bvxnor_tag, QF_BV_Grammar, QF_BV_Grammar> 00045 , proto::binary_expr<tag::bvcomp_tag, QF_BV_Grammar, QF_BV_Grammar> 00046 > 00047 // arithmetic 00048 , proto::or_< 00049 proto::binary_expr<tag::bvadd_tag, QF_BV_Grammar, QF_BV_Grammar> 00050 , proto::binary_expr<tag::bvmul_tag, QF_BV_Grammar, QF_BV_Grammar> 00051 , proto::binary_expr<tag::bvsub_tag, QF_BV_Grammar, QF_BV_Grammar> 00052 , proto::binary_expr<tag::bvudiv_tag, QF_BV_Grammar, QF_BV_Grammar> 00053 , proto::binary_expr<tag::bvurem_tag, QF_BV_Grammar, QF_BV_Grammar> 00054 , proto::binary_expr<tag::bvsdiv_tag, QF_BV_Grammar, QF_BV_Grammar> 00055 , proto::binary_expr<tag::bvsrem_tag, QF_BV_Grammar, QF_BV_Grammar> 00056 > 00057 // extend 00058 , proto::or_< 00059 proto::binary_expr<tag::concat_tag, QF_BV_Grammar, QF_BV_Grammar> 00060 , proto::binary_expr<tag::extract_tag, QF_BV_Grammar, QF_BV_Grammar> 00061 , proto::binary_expr<tag::zero_extend_tag, QF_BV_Grammar, unsigned long> 00062 , proto::binary_expr<tag::sign_extend_tag, QF_BV_Grammar, unsigned long> 00063 > 00064 // shifting 00065 , proto::or_< 00066 proto::binary_expr<tag::bvshl_tag, QF_BV_Grammar, QF_BV_Grammar> 00067 , proto::binary_expr<tag::bvshr_tag, QF_BV_Grammar, QF_BV_Grammar> 00068 , proto::binary_expr<tag::bvashr_tag, QF_BV_Grammar, QF_BV_Grammar> 00069 > 00070 // Accept other expressions (e.g. array) 00071 , proto::_ 00072 > 00073 {}; 00074 00075 struct QF_BV_Binary_Predicate 00076 : proto::or_< 00077 //comparison 00078 proto::or_< 00079 proto::binary_expr<tag::bvslt_tag, QF_BV_Grammar, QF_BV_Grammar> 00080 , proto::binary_expr<tag::bvsgt_tag, QF_BV_Grammar, QF_BV_Grammar> 00081 , proto::binary_expr<tag::bvsle_tag, QF_BV_Grammar, QF_BV_Grammar> 00082 , proto::binary_expr<tag::bvsge_tag, QF_BV_Grammar, QF_BV_Grammar> 00083 , proto::binary_expr<tag::bvult_tag, QF_BV_Grammar, QF_BV_Grammar> 00084 , proto::binary_expr<tag::bvugt_tag, QF_BV_Grammar, QF_BV_Grammar> 00085 , proto::binary_expr<tag::bvule_tag, QF_BV_Grammar, QF_BV_Grammar> 00086 , proto::binary_expr<tag::bvuge_tag, QF_BV_Grammar, QF_BV_Grammar> 00087 > 00088 > 00089 {}; 00090 00091 struct QF_BV_BitVector_Constrant 00092 : proto::or_< 00093 proto::binary_expr < tag::bvuint_tag 00094 , proto::terminal< proto::convertible_to< unsigned long > > 00095 , proto::terminal< proto::convertible_to< unsigned long > > 00096 > 00097 , proto::binary_expr < tag::bvsint_tag 00098 , proto::terminal< proto::convertible_to< long > > 00099 , proto::terminal< proto::convertible_to< unsigned long > > 00100 > 00101 , proto::unary_expr < tag::bvbin_tag 00102 , proto::terminal< proto::convertible_to< std::string > > 00103 > 00104 , proto::unary_expr < tag::bvhex_tag 00105 , proto::terminal< proto::convertible_to< std::string > > 00106 > 00107 > 00108 {}; 00109 00110 00111 // real Grammar 00112 struct QF_BV_Grammar 00113 : proto::and_< 00114 proto::not_< proto::address_of< proto::_> >, 00115 proto::or_< 00116 proto::terminal< tag::bit0_tag > 00117 , proto::terminal< tag::bit1_tag > 00118 , proto::terminal< tag::var_tag > 00119 , proto::terminal< SMT_Expression > 00120 , QF_BV_BitVector_Constrant 00121 , QF_BV_Binary_Function 00122 , QF_BV_Binary_Predicate 00123 , QF_BV_Unary_Function 00124 > > 00125 {}; 00126 00127 template<typename Expr> 00128 struct QF_BV; 00129 00130 struct QF_BV_Domain 00131 : proto::domain<proto::generator<QF_BV>, QF_BV_Grammar> 00132 {}; 00133 00134 template<typename Expr> 00135 struct QF_BV 00136 : proto::extends<Expr, QF_BV<Expr>, QF_BV_Domain > 00137 { 00138 typedef proto::extends<Expr, QF_BV<Expr>, QF_BV_Domain > base_type; 00139 00140 QF_BV(Expr const & expr = Expr()) 00141 : base_type(expr) 00142 { 00143 } 00144 }; 00145 00146 template<typename Expr> 00147 void check (QF_BV<Expr> const & ) { 00148 BOOST_MPL_ASSERT((proto::matches<Expr, QF_BV_Grammar>)); 00149 } 00150 template<typename Expr> 00151 void check_not (QF_BV<Expr> const & ) { 00152 BOOST_MPL_ASSERT_NOT((proto::matches<Expr, QF_BV_Grammar>)); 00153 } 00154 00161 // expressions 00162 QF_BV<proto::terminal<tag::bit0_tag>::type > const bit0; // = {{{}}}; 00163 QF_BV<proto::terminal<tag::bit1_tag>::type > const bit1; // = {{{}}}; 00164 00165 00166 #define _QF_BV_BINARY_FUNCTION(NAME_, TAG_) \ 00167 template<typename E1, typename E2> \ 00168 typename proto::result_of::make_expr< TAG_, QF_BV_Domain, E1 const &, E2 const & >::type \ 00169 NAME_( E1 const& e1, E2 const & e2 ) \ 00170 { \ 00171 return proto::make_expr< TAG_, QF_BV_Domain >(boost::cref(e1), boost::cref(e2));\ 00172 } 00173 00174 // bitwise binary 00175 _QF_BV_BINARY_FUNCTION(bvand, tag::bvand_tag) 00176 _QF_BV_BINARY_FUNCTION(bvnand, tag::bvnand_tag) 00177 _QF_BV_BINARY_FUNCTION(bvor, tag::bvor_tag) 00178 _QF_BV_BINARY_FUNCTION(bvnor, tag::bvnor_tag) 00179 _QF_BV_BINARY_FUNCTION(bvxor, tag::bvxor_tag) 00180 _QF_BV_BINARY_FUNCTION(bvxnor, tag::bvxnor_tag) 00181 00182 _QF_BV_BINARY_FUNCTION(bvadd, tag::bvadd_tag) 00183 _QF_BV_BINARY_FUNCTION(bvmul, tag::bvmul_tag) 00184 _QF_BV_BINARY_FUNCTION(bvsub, tag::bvsub_tag) 00185 _QF_BV_BINARY_FUNCTION(bvudiv, tag::bvudiv_tag) 00186 _QF_BV_BINARY_FUNCTION(bvurem, tag::bvurem_tag) 00187 _QF_BV_BINARY_FUNCTION(bvsdiv, tag::bvsdiv_tag) 00188 _QF_BV_BINARY_FUNCTION(bvsrem, tag::bvsrem_tag) 00189 00190 _QF_BV_BINARY_FUNCTION(bvcomp, tag::bvcomp_tag) 00191 00192 _QF_BV_BINARY_FUNCTION(bvslt, tag::bvslt_tag) 00193 _QF_BV_BINARY_FUNCTION(bvsgt, tag::bvsgt_tag) 00194 _QF_BV_BINARY_FUNCTION(bvsle, tag::bvsle_tag) 00195 _QF_BV_BINARY_FUNCTION(bvsge, tag::bvsge_tag) 00196 00197 _QF_BV_BINARY_FUNCTION(bvult, tag::bvult_tag) 00198 _QF_BV_BINARY_FUNCTION(bvugt, tag::bvugt_tag) 00199 _QF_BV_BINARY_FUNCTION(bvule, tag::bvule_tag) 00200 _QF_BV_BINARY_FUNCTION(bvuge, tag::bvuge_tag) 00201 00202 _QF_BV_BINARY_FUNCTION(bvshl, tag::bvshl_tag) 00203 _QF_BV_BINARY_FUNCTION(bvshr, tag::bvshr_tag) 00204 _QF_BV_BINARY_FUNCTION(bvashr, tag::bvashr_tag) 00205 00206 00207 _QF_BV_BINARY_FUNCTION(concat, tag::concat_tag) 00208 00209 #undef _QF_BV_BINARY_FUNCTION 00210 00211 #define _QF_BV_UNARY_FUNCTION(NAME_, TAG_) \ 00212 template<typename E1> \ 00213 typename proto::result_of::make_expr< TAG_, QF_BV_Domain, E1 const &>::type \ 00214 NAME_( E1 const& e1) \ 00215 { \ 00216 return proto::make_expr< TAG_, QF_BV_Domain >(boost::cref(e1));\ 00217 } 00218 00219 // bitwise binary 00220 _QF_BV_UNARY_FUNCTION(bvnot, tag::bvnot_tag) 00221 _QF_BV_UNARY_FUNCTION(bvneg, tag::bvneg_tag) 00222 00223 #undef _QF_BV_UNARY_FUNCTION 00224 00225 // extract operator 00226 template< typename Expr> 00227 inline typename proto::result_of::make_expr< tag::extract_tag, QF_BV_Domain 00228 , unsigned long const & // from 00229 , unsigned long const & // length 00230 , Expr const & // Expr 00231 > ::type 00232 extract( unsigned long const & from, unsigned long const & width, Expr const & e) 00233 { 00234 return proto::make_expr< tag::extract_tag, QF_BV_Domain>(boost::cref(from), boost::cref(width), boost::cref(e)); 00235 } 00236 00237 // zero_extend operator 00238 template< typename Expr> 00239 inline typename proto::result_of::make_expr< tag::zero_extend_tag, QF_BV_Domain 00240 , unsigned long const & // length 00241 , Expr const & // Expr 00242 > ::type 00243 zero_extend ( unsigned long const & howMany, Expr const & e) 00244 { 00245 return proto::make_expr< tag::zero_extend_tag, QF_BV_Domain>( boost::cref(howMany), boost::cref(e)); 00246 } 00247 00248 // sign_extend operator 00249 template< typename Expr> 00250 inline typename proto::result_of::make_expr< tag::sign_extend_tag, QF_BV_Domain 00251 , unsigned long const & // length 00252 , Expr const & // Expr 00253 > ::type 00254 sign_extend ( unsigned long const & howMany, Expr const & e) 00255 { 00256 return proto::make_expr< tag::sign_extend_tag, QF_BV_Domain>( boost::cref(howMany), boost::cref(e)); 00257 } 00258 00259 // constant creation 00260 typedef proto::result_of::make_expr< tag::bvuint_tag, QF_BV_Domain 00261 , unsigned long 00262 , unsigned long 00263 > ::type bvuint_result_type; 00264 00265 inline bvuint_result_type 00266 bvuint( unsigned long const & value, unsigned long const & width ) 00267 { 00268 return proto::make_expr< tag::bvuint_tag, QF_BV_Domain>(value, width); 00269 } 00270 00271 typedef proto::result_of::make_expr< tag::bvsint_tag, QF_BV_Domain 00272 , long 00273 , unsigned long 00274 > ::type bvsint_result_type; 00275 00276 inline bvsint_result_type 00277 bvsint( long const & value, long unsigned const & width ) 00278 { 00279 return proto::make_expr< tag::bvsint_tag, QF_BV_Domain >( value, width); 00280 } 00281 00282 // bvint: bvuint/bvsint depending on the type of the variable... 00283 template< typename Integer > 00284 typename boost::enable_if< typename boost::mpl::and_< 00285 boost::is_integral<Integer>, 00286 boost::is_signed<Integer> 00287 >::type, 00288 bvsint_result_type >::type 00289 bvint( Integer value, unsigned long const & width ) 00290 { 00291 return proto::make_expr< tag::bvsint_tag, QF_BV_Domain >( (long) value, width); 00292 } 00293 00294 template< typename Integer > 00295 typename boost::enable_if< typename boost::mpl::and_< 00296 boost::is_integral<Integer>, 00297 boost::mpl::not_<boost::is_signed<Integer> > 00298 >::type, 00299 bvuint_result_type >::type 00300 bvint( Integer value, unsigned long const & width ) 00301 { 00302 return proto::make_expr< tag::bvuint_tag, QF_BV_Domain >( (unsigned long) value, width); 00303 } 00304 00305 00306 00307 inline proto::result_of::make_expr< tag::bvbin_tag, QF_BV_Domain 00308 , std::string const & 00309 > ::type 00310 bvbin( std::string const & value ) 00311 { 00312 return proto::make_expr< tag::bvbin_tag, QF_BV_Domain >(boost::cref(value)); 00313 } 00314 00315 inline proto::result_of::make_expr< tag::bvhex_tag, QF_BV_Domain 00316 , std::string const & 00317 > ::type 00318 bvhex( std::string const & value ) 00319 { 00320 return proto::make_expr< tag::bvhex_tag, QF_BV_Domain >(boost::cref(value)); 00321 } 00322 00323 00324 typedef 00325 proto::result_of::make_expr< proto::tag::terminal, QF_BV_Domain 00326 , tag::var_tag 00327 > ::type bitvector; 00328 00329 inline bitvector 00330 new_bitvector( unsigned width=1 ) 00331 { 00332 tag::var_tag tag; 00333 tag.id = impl::new_var_id(); 00334 tag.width= width; 00335 return proto::make_expr< proto::tag::terminal, QF_BV_Domain >( tag ); 00336 } 00337 00340 } // namespace QF_BV 00341 } // namepace logic 00342 } // namespace metaSMT 00343 00344 // vim: ft=cpp:ts=2:sw=2:expandtab