metaSMT git
|
00001 #pragma once 00002 #include "frontend/Logic.hpp" 00003 #include "frontend/QF_BV.hpp" 00004 #include "support/SMT_Graph.hpp" 00005 #include "support/dot_SMT_Graph.hpp" 00006 #include "support/SMT_File_Writer.hpp" 00007 00008 #include <boost/proto/core.hpp> 00009 #include <boost/proto/context.hpp> 00010 #include <boost/proto/proto.hpp> 00011 #include <boost/proto/make_expr.hpp> 00012 #include <boost/tr1/unordered_map.hpp> 00013 #include <boost/tuple/tuple_comparison.hpp> 00014 00015 #include <iostream> 00016 #include <fstream> 00017 #include <sstream> 00018 #include <map> 00019 #include <exception> 00020 00021 namespace proto = boost::proto; 00022 00023 namespace metaSMT { 00024 00036 struct Graph_Context 00037 : proto::callable_context< Graph_Context, proto::null_context > 00038 { 00039 Graph_Context() 00040 { 00041 } 00042 00043 ~Graph_Context() { 00044 } 00045 00046 typedef SMT_Expression result_type; 00047 00048 result_type operator() (proto::tag::terminal, result_type const & expr ) { 00049 return expr; 00050 } 00051 00052 result_type operator() (proto::tag::terminal, logic::QF_BV::tag::var_tag const & tag ) { 00053 VariableLookupT::const_iterator ite 00054 = _variables.find(tag.id); 00055 if ( ite!= _variables.end() ) { 00056 return ite->second; 00057 } else { 00058 SMT_Expression ret = boost::add_vertex(_g); 00059 boost::put(boost::vertex_tag, _g, ret, tag); 00060 _variables.insert( std::make_pair(tag.id, ret) ); 00061 return ret; 00062 } 00063 } 00064 00065 result_type operator() (proto::tag::terminal, logic::Array::tag::array_var_tag const & tag ) { 00066 if ( tag.id == 0 ) { 00067 throw std::runtime_error("Uninitialized array variable"); 00068 } 00069 00070 VariableLookupT::const_iterator ite 00071 = _variables.find(tag.id); 00072 if ( ite!= _variables.end() ) { 00073 return ite->second; 00074 } else { 00075 SMT_Expression ret = boost::add_vertex(_g); 00076 boost::put(boost::vertex_tag, _g, ret, tag); 00077 _variables.insert( std::make_pair(tag.id, ret) ); 00078 return ret; 00079 } 00080 } 00081 00082 template<typename Upper, typename Lower, typename Expr> 00083 result_type operator() (logic::QF_BV::tag::extract_tag tag 00084 , Upper upper 00085 , Lower lower 00086 , Expr arg 00087 ) { 00088 result_type node = proto::eval(arg, *this); 00089 SMT_Expression ret = boost::add_vertex(_g); 00090 boost::put(boost::vertex_tag, _g, ret, tag); 00091 boost::put(boost::vertex_arg, _g, ret, 00092 boost::tuple<unsigned long, unsigned long>( 00093 proto::value(upper), proto::value(lower)) 00094 ); 00095 SMT_Edge e; bool b; 00096 boost::tie(e, b) = boost::add_edge(ret, node, _g); 00097 put(boost::edge_input, _g, e, 1); 00098 return ret; 00099 } 00100 00101 template<typename Width, typename Expr > 00102 result_type operator() (logic::QF_BV::tag::zero_extend_tag tag 00103 , Width width 00104 , Expr arg 00105 ) { 00106 result_type node = proto::eval(arg, *this); 00107 SMT_Expression ret = boost::add_vertex(_g); 00108 boost::put(boost::vertex_tag, _g, ret, tag); 00109 boost::put(boost::vertex_arg, _g, ret, 00110 proto::value(width) 00111 ); 00112 SMT_Edge e; bool b; 00113 boost::tie(e, b) = boost::add_edge(ret, node, _g); 00114 put(boost::edge_input, _g, e, 1); 00115 return ret; 00116 } 00117 00118 template<typename Width, typename Expr > 00119 result_type operator() (logic::QF_BV::tag::sign_extend_tag tag 00120 , Width width 00121 , Expr arg 00122 ) { 00123 result_type node = proto::eval(arg, *this); 00124 SMT_Expression ret = boost::add_vertex(_g); 00125 boost::put(boost::vertex_tag, _g, ret, tag); 00126 boost::put(boost::vertex_arg, _g, ret, 00127 proto::value(width) 00128 ); 00129 SMT_Edge e; bool b; 00130 boost::tie(e, b) = boost::add_edge(ret, node, _g); 00131 put(boost::edge_input, _g, e, 1); 00132 return ret; 00133 } 00134 00135 template<typename TagT> 00136 result_type operator() (proto::tag::terminal, TagT tag ) 00137 { 00138 Tag t1 (tag); 00139 Op0LookupT::const_iterator ite = _op0Lookup.find( t1 ); 00140 if( ite != _op0Lookup.end() ) { 00141 return ite->second; 00142 } 00143 SMT_Expression ret = boost::add_vertex(_g); 00144 boost::put(boost::vertex_tag, _g, ret, tag); 00145 _op0Lookup.insert( std::make_pair( t1, ret) ); 00146 return ret; 00147 } 00148 00149 template<typename TAG, typename Expr1, typename Expr2> 00150 result_type operator() (TAG tag, Expr1 e1, Expr2 e2) 00151 { 00152 Tag t1 (tag); 00153 result_type arg1 = proto::eval(e1, *this); 00154 result_type arg2 = proto::eval(e2, *this); 00155 Op2LookupT::const_iterator ite = 00156 _op2Lookup.find( boost::make_tuple(t1, arg1, arg2) ); 00157 if( ite != _op2Lookup.end() ) { 00158 return ite->second; 00159 } 00160 result_type ret = boost::add_vertex(_g); 00161 boost::put(boost::vertex_tag, _g, ret, tag); 00162 boost::add_edge(ret, arg1, _g); 00163 SMT_Edge e; bool b; 00164 boost::tie(e, b) = boost::add_edge(ret, arg2, _g); 00165 put(boost::edge_input, _g, e, 1); 00166 _op2Lookup.insert( std::make_pair( 00167 boost::make_tuple( t1, arg1, arg2 ), 00168 ret 00169 )); 00170 return ret; 00171 } 00172 00173 template<typename TAG, typename Expr1, typename Expr2, typename Expr3> 00174 result_type operator() (TAG tag, Expr1 e1, Expr2 e2, Expr3 e3) 00175 { 00176 Tag t1 (tag); 00177 result_type arg1 = proto::eval(e1, *this); 00178 result_type arg2 = proto::eval(e2, *this); 00179 result_type arg3 = proto::eval(e3, *this); 00180 Op3LookupT::const_iterator ite = 00181 _op3Lookup.find( boost::make_tuple(t1, arg1, arg2, arg3) ); 00182 if( ite != _op3Lookup.end() ) { 00183 return ite->second; 00184 } 00185 result_type ret = boost::add_vertex(_g); 00186 boost::put(boost::vertex_tag, _g, ret, tag); 00187 boost::add_edge(ret, arg1, _g); 00188 SMT_Edge e; bool b; 00189 boost::tie(e, b) = boost::add_edge(ret, arg2, _g); 00190 put(boost::edge_input, _g, e, 1); 00191 boost::tie(e, b) = boost::add_edge(ret, arg3, _g); 00192 put(boost::edge_input, _g, e, 2); 00193 _op3Lookup.insert( std::make_pair( 00194 boost::make_tuple( t1, arg1, arg2, arg3), 00195 ret 00196 )); 00197 return ret; 00198 } 00199 00200 00201 template< typename Expr1, typename Expr2> 00202 result_type operator() (logic::QF_BV::tag::bvuint_tag const & tag 00203 , Expr1 value 00204 , Expr2 bw 00205 ) { 00206 const unsigned long val = proto::value(value); 00207 const unsigned long width = proto::value(bw); 00208 00209 if(width==1) { 00210 // return bit0/1 00211 if (val == 1) { 00212 return (*this)(proto::tag::terminal(), logic::QF_BV::tag::bit1_tag()); 00213 } else { 00214 return (*this)(proto::tag::terminal(), logic::QF_BV::tag::bit0_tag()); 00215 } 00216 } 00217 00218 ConstantLookupT::const_iterator ite 00219 = _constants.find( boost::make_tuple(tag, val, width) ); 00220 if ( ite != _constants.end()) { 00221 return ite->second; 00222 } 00223 SMT_Expression ret = boost::add_vertex(_g); 00224 boost::put(boost::vertex_tag, _g, ret, tag); 00225 boost::put(boost::vertex_arg, _g, ret, boost::make_tuple( val, width) ); 00226 _constants.insert( std::make_pair( boost::make_tuple(tag, val, width), ret) ); 00227 return ret; 00228 } 00229 00230 template< typename Expr1, typename Expr2> 00231 result_type operator() (logic::QF_BV::tag::bvsint_tag const & tag 00232 , Expr1 value 00233 , Expr2 bw 00234 ) { 00235 const long val = proto::value(value); 00236 const unsigned long width = proto::value(bw); 00237 00238 if(width==1) { 00239 // return bit0/1 00240 if (val == 0) { 00241 return (*this)(proto::tag::terminal(), logic::QF_BV::tag::bit0_tag()); 00242 } else { 00243 return (*this)(proto::tag::terminal(), logic::QF_BV::tag::bit1_tag()); 00244 } 00245 } 00246 00247 ConstantLookupT::const_iterator ite 00248 = _constants.find( boost::make_tuple(tag, val, width) ); 00249 if ( ite != _constants.end()) { 00250 return ite->second; 00251 } 00252 SMT_Expression ret = boost::add_vertex(_g); 00253 boost::put(boost::vertex_tag, _g, ret, tag); 00254 boost::put(boost::vertex_arg, _g, ret, boost::make_tuple( val, width) ); 00255 _constants.insert( std::make_pair( boost::make_tuple(tag, val, width), ret) ); 00256 return ret; 00257 } 00258 00259 template< typename Expr1> 00260 result_type operator() (logic::QF_BV::tag::bvbin_tag tag 00261 , Expr1 value 00262 ) { 00263 const std::string val = proto::value(value); 00264 00265 if(val.size()==1) { 00266 // return bit0/1 00267 if (val[0] == '0') { 00268 return (*this)(proto::tag::terminal(), logic::QF_BV::tag::bit0_tag()); 00269 } else { 00270 return (*this)(proto::tag::terminal(), logic::QF_BV::tag::bit1_tag()); 00271 } 00272 } 00273 00274 ConstantLookupT::const_iterator ite 00275 = _constants.find( boost::make_tuple(tag, val) ); 00276 if ( ite != _constants.end()) { 00277 return ite->second; 00278 } 00279 SMT_Expression ret = boost::add_vertex(_g); 00280 boost::put(boost::vertex_tag, _g, ret, tag); 00281 boost::put(boost::vertex_arg, _g, ret, proto::value(value)); 00282 _constants.insert( std::make_pair( boost::make_tuple(tag, val), ret ) ); 00283 return ret; 00284 } 00285 00286 template< typename Expr1> 00287 result_type operator() (logic::QF_BV::tag::bvhex_tag tag 00288 , Expr1 value 00289 ) { 00290 const std::string val = proto::value(value); 00291 00292 ConstantLookupT::const_iterator ite 00293 = _constants.find( boost::make_tuple(tag, val) ); 00294 if ( ite != _constants.end()) { 00295 return ite->second; 00296 } 00297 SMT_Expression ret = boost::add_vertex(_g); 00298 boost::put(boost::vertex_tag, _g, ret, tag); 00299 boost::put(boost::vertex_arg, _g, ret, proto::value(value)); 00300 _constants.insert( std::make_pair( boost::make_tuple(tag, val), ret ) ); 00301 return ret; 00302 } 00303 00304 template< typename TAG, typename Expr1> 00305 result_type operator() (TAG tag, Expr1 const & e1) 00306 { 00307 result_type arg1 = proto::eval(e1, *this); 00308 Op1LookupT::const_iterator ite = 00309 _op1Lookup.find( boost::make_tuple(tag, arg1) ); 00310 if( ite != _op1Lookup.end() ) { 00311 return ite->second; 00312 } 00313 result_type ret = boost::add_vertex(_g); 00314 boost::put(boost::vertex_tag, _g, ret, tag); 00315 boost::add_edge(ret, arg1, _g); 00316 _op1Lookup.insert( std::make_pair( 00317 boost::make_tuple( tag, arg1 ), 00318 ret 00319 )); 00320 return ret; 00321 } 00322 00326 SMT_Graph const & graph() { return _g; } 00327 00328 template<typename Stream> 00329 void write_dot(Stream & out ){ 00330 ::metaSMT::write_dot(out, _g ); 00331 } 00332 00333 template<typename Stream> 00334 void write_smt(Stream & out, std::vector<SMT_Expression> const &assertions) { 00335 ::metaSMT::write_smt(out, _g, assertions); 00336 } 00337 00338 private: 00339 SMT_Graph _g; 00340 00341 private: 00342 typedef boost::variant < 00343 nil 00344 , boost::tuple< logic::QF_BV::tag::bvuint_tag, unsigned long , unsigned long > 00345 , boost::tuple< logic::QF_BV::tag::bvsint_tag, long , unsigned long > 00346 , boost::tuple< logic::QF_BV::tag::bvbin_tag, std::string > 00347 , boost::tuple< logic::QF_BV::tag::bvhex_tag, std::string > 00348 > ConstantOpT; 00349 00350 typedef std::tr1::unordered_map<unsigned, result_type> VariableLookupT; 00351 typedef std::map< ConstantOpT, result_type> ConstantLookupT; 00352 typedef std::map< Tag, result_type > Op0LookupT; 00353 typedef std::map< boost::tuple<Tag, result_type>, result_type > Op1LookupT; 00354 typedef std::map< boost::tuple<Tag, result_type, result_type>, result_type > Op2LookupT; 00355 typedef std::map< boost::tuple<Tag, result_type, result_type, result_type>, result_type > Op3LookupT; 00356 VariableLookupT _variables; 00357 ConstantLookupT _constants; 00358 Op0LookupT _op0Lookup; 00359 Op1LookupT _op1Lookup; 00360 Op2LookupT _op2Lookup; 00361 Op3LookupT _op3Lookup; 00362 00363 }; // Graph_Context 00364 00365 template <typename Expr> 00366 SMT_Expression evaluate( Graph_Context & ctx, Expr const & e ) { 00367 check(e); 00368 return proto::eval(e, ctx) ; 00369 } 00370 } // namespace metaSMT 00371 // vim: ft=cpp:ts=2:sw=2:expandtab