metaSMT 2
metaSMT/Graph_Context.hpp
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines