Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 10:02:38

0001 // Copyright (C) 2016-2018 T. Zachary Laine
0002 //
0003 // Distributed under the Boost Software License, Version 1.0. (See
0004 // accompanying file LICENSE_1_0.txt or copy at
0005 // http://www.boost.org/LICENSE_1_0.txt)
0006 #ifndef BOOST_YAP_PRINT_HPP_INCLUDED
0007 #define BOOST_YAP_PRINT_HPP_INCLUDED
0008 
0009 #include <boost/yap/algorithm_fwd.hpp>
0010 
0011 #include <boost/hana/for_each.hpp>
0012 #include <boost/type_index.hpp>
0013 #include <iostream>
0014 
0015 
0016 namespace boost { namespace yap {
0017 
0018     /** Returns the <code>char const *</code> string for the spelling of the
0019         C++ operator associated with \a kind.  It returns the special values
0020         "ref" and "term" for the non-operator kinds
0021         <code>expr_kind::expr_ref</code> amd <code>expr_kind::terminal</code>,
0022         respectively.*/
0023     inline constexpr char const * op_string(expr_kind kind)
0024     {
0025         switch (kind) {
0026         case expr_kind::expr_ref: return "ref";
0027 
0028         case expr_kind::terminal: return "term";
0029 
0030         case expr_kind::unary_plus: return "+";
0031         case expr_kind::negate: return "-";
0032         case expr_kind::dereference: return "*";
0033         case expr_kind::complement: return "~";
0034         case expr_kind::address_of: return "&";
0035         case expr_kind::logical_not: return "!";
0036         case expr_kind::pre_inc: return "++";
0037         case expr_kind::pre_dec: return "--";
0038         case expr_kind::post_inc: return "++(int)";
0039         case expr_kind::post_dec: return "--(int)";
0040 
0041         case expr_kind::shift_left: return "<<";
0042         case expr_kind::shift_right: return ">>";
0043         case expr_kind::multiplies: return "*";
0044         case expr_kind::divides: return "/";
0045         case expr_kind::modulus: return "%";
0046         case expr_kind::plus: return "+";
0047         case expr_kind::minus: return "-";
0048         case expr_kind::less: return "<";
0049         case expr_kind::greater: return ">";
0050         case expr_kind::less_equal: return "<=";
0051         case expr_kind::greater_equal: return ">=";
0052         case expr_kind::equal_to: return "==";
0053         case expr_kind::not_equal_to: return "!=";
0054         case expr_kind::logical_or: return "||";
0055         case expr_kind::logical_and: return "&&";
0056         case expr_kind::bitwise_and: return "&";
0057         case expr_kind::bitwise_or: return "|";
0058         case expr_kind::bitwise_xor: return "^";
0059         case expr_kind::comma: return ",";
0060         case expr_kind::mem_ptr: return "->*";
0061         case expr_kind::assign: return "=";
0062         case expr_kind::shift_left_assign: return "<<=";
0063         case expr_kind::shift_right_assign: return ">>=";
0064         case expr_kind::multiplies_assign: return "*=";
0065         case expr_kind::divides_assign: return "/=";
0066         case expr_kind::modulus_assign: return "%=";
0067         case expr_kind::plus_assign: return "+=";
0068         case expr_kind::minus_assign: return "-=";
0069         case expr_kind::bitwise_and_assign: return "&=";
0070         case expr_kind::bitwise_or_assign: return "|=";
0071         case expr_kind::bitwise_xor_assign: return "^=";
0072         case expr_kind::subscript: return "[]";
0073 
0074         case expr_kind::if_else: return "?:";
0075 
0076         case expr_kind::call: return "()";
0077 
0078         default: return "** ERROR: UNKNOWN OPERATOR! **";
0079         }
0080     }
0081 
0082     namespace detail {
0083 
0084         inline std::ostream & print_kind(std::ostream & os, expr_kind kind)
0085         {
0086             return os << op_string(kind);
0087         }
0088 
0089         template<typename T, typename = void_t<>>
0090         struct printer
0091         {
0092             std::ostream & operator()(std::ostream & os, T const &)
0093             {
0094                 return os << "<<unprintable-value>>";
0095             }
0096         };
0097 
0098         template<typename T>
0099         struct printer<
0100             T,
0101             void_t<decltype(
0102                 std::declval<std::ostream &>() << std::declval<T const &>())>>
0103         {
0104             std::ostream & operator()(std::ostream & os, T const & x)
0105             {
0106                 return os << x;
0107             }
0108         };
0109 
0110         template<typename T>
0111         inline std::ostream & print_value(std::ostream & os, T const & x)
0112         {
0113             return printer<T>{}(os, x);
0114         }
0115 
0116         template<long long I>
0117         inline std::ostream & print_value(std::ostream & os, hana::llong<I>)
0118         {
0119             return os << I << "_p";
0120         }
0121 
0122         template<typename T>
0123         std::ostream & print_type(std::ostream & os, hana::tuple<T> const &)
0124         {
0125             os << typeindex::type_id<T>().pretty_name();
0126             if (std::is_const<std::remove_reference_t<T>>::value)
0127                 os << " const";
0128             if (std::is_volatile<std::remove_reference_t<T>>::value)
0129                 os << " volatile";
0130             if (std::is_lvalue_reference<T>::value)
0131                 os << " &";
0132             if (std::is_rvalue_reference<T>::value)
0133                 os << " &&";
0134             return os;
0135         }
0136 
0137         template<typename T>
0138         bool is_const_expr_ref(T const &)
0139         {
0140             return false;
0141         }
0142         template<typename T, template<expr_kind, class> class expr_template>
0143         bool is_const_expr_ref(
0144             expr_template<expr_kind::expr_ref, hana::tuple<T const *>> const &)
0145         {
0146             return true;
0147         }
0148 
0149 #ifdef BOOST_NO_CONSTEXPR_IF
0150 
0151         template<expr_kind Kind>
0152         struct print_impl
0153         {
0154             template<typename Expr>
0155             std::ostream & operator()(
0156                 std::ostream & os,
0157                 Expr const & expr,
0158                 int indent,
0159                 char const * indent_str,
0160                 bool is_ref = false,
0161                 bool is_const_ref = false)
0162             {
0163                 for (int i = 0; i < indent; ++i) {
0164                     os << indent_str;
0165                 }
0166 
0167                 os << "expr<";
0168                 ::boost::yap::detail::print_kind(os, Expr::kind);
0169                 os << ">";
0170                 if (is_const_ref)
0171                     os << " const &";
0172                 else if (is_ref)
0173                     os << " &";
0174                 os << "\n";
0175                 hana::for_each(
0176                     expr.elements,
0177                     [&os, indent, indent_str](auto const & element) {
0178                         using element_type = decltype(element);
0179                         constexpr expr_kind kind =
0180                             detail::remove_cv_ref_t<element_type>::kind;
0181                         print_impl<kind>{}(os, element, indent + 1, indent_str);
0182                     });
0183 
0184                 return os;
0185             }
0186         };
0187 
0188         template<>
0189         struct print_impl<expr_kind::expr_ref>
0190         {
0191             template<typename Expr>
0192             std::ostream & operator()(
0193                 std::ostream & os,
0194                 Expr const & expr,
0195                 int indent,
0196                 char const * indent_str,
0197                 bool is_ref = false,
0198                 bool is_const_ref = false)
0199             {
0200                 using ref_type = decltype(::boost::yap::deref(expr));
0201                 constexpr expr_kind ref_kind =
0202                     detail::remove_cv_ref_t<ref_type>::kind;
0203                 print_impl<ref_kind>{}(
0204                     os,
0205                     ::boost::yap::deref(expr),
0206                     indent,
0207                     indent_str,
0208                     true,
0209                     ::boost::yap::detail::is_const_expr_ref(expr));
0210                 return os;
0211             }
0212         };
0213 
0214         template<>
0215         struct print_impl<expr_kind::terminal>
0216         {
0217             template<typename Expr>
0218             std::ostream & operator()(
0219                 std::ostream & os,
0220                 Expr const & expr,
0221                 int indent,
0222                 char const * indent_str,
0223                 bool is_ref = false,
0224                 bool is_const_ref = false)
0225             {
0226                 for (int i = 0; i < indent; ++i) {
0227                     os << indent_str;
0228                 }
0229 
0230                 os << "term<";
0231                 ::boost::yap::detail::print_type(os, expr.elements);
0232                 os << ">[=";
0233                 ::boost::yap::detail::print_value(
0234                     os, ::boost::yap::value(expr));
0235                 os << "]";
0236                 if (is_const_ref)
0237                     os << " const &";
0238                 else if (is_ref)
0239                     os << " &";
0240                 os << "\n";
0241 
0242                 return os;
0243             }
0244         };
0245 
0246 #else
0247 
0248         template<typename Expr>
0249         std::ostream & print_impl(
0250             std::ostream & os,
0251             Expr const & expr,
0252             int indent,
0253             char const * indent_str,
0254             bool is_ref = false,
0255             bool is_const_ref = false)
0256         {
0257             if constexpr (Expr::kind == expr_kind::expr_ref) {
0258                 print_impl(
0259                     os,
0260                     ::boost::yap::deref(expr),
0261                     indent,
0262                     indent_str,
0263                     true,
0264                     ::boost::yap::detail::is_const_expr_ref(expr));
0265             } else {
0266                 for (int i = 0; i < indent; ++i) {
0267                     os << indent_str;
0268                 }
0269 
0270                 if constexpr (Expr::kind == expr_kind::terminal) {
0271                     os << "term<";
0272                     ::boost::yap::detail::print_type(os, expr.elements);
0273                     os << ">[=";
0274                     ::boost::yap::detail::print_value(
0275                         os, ::boost::yap::value(expr));
0276                     os << "]";
0277                     if (is_const_ref)
0278                         os << " const &";
0279                     else if (is_ref)
0280                         os << " &";
0281                     os << "\n";
0282                 } else {
0283                     os << "expr<";
0284                     ::boost::yap::detail::print_kind(os, Expr::kind);
0285                     os << ">";
0286                     if (is_const_ref)
0287                         os << " const &";
0288                     else if (is_ref)
0289                         os << " &";
0290                     os << "\n";
0291                     hana::for_each(
0292                         expr.elements,
0293                         [&os, indent, indent_str](auto const & element) {
0294                             ::boost::yap::detail::print_impl(
0295                                 os, element, indent + 1, indent_str);
0296                         });
0297                 }
0298             }
0299 
0300             return os;
0301         }
0302 
0303 #endif // BOOST_NO_CONSTEXPR_IF
0304     }
0305 
0306     /** Prints expression \a expr to stream \a os.  Returns \a os. */
0307     template<typename Expr>
0308     std::ostream & print(std::ostream & os, Expr const & expr)
0309     {
0310 #ifdef BOOST_NO_CONSTEXPR_IF
0311         return detail::print_impl<detail::remove_cv_ref_t<Expr>::kind>{}(
0312             os, expr, 0, "    ");
0313 #else
0314         return detail::print_impl(os, expr, 0, "    ");
0315 #endif
0316     }
0317 
0318 }}
0319 
0320 #endif