diff --git a/sketch.cpp b/sketch.cpp index b0818ed..f59f573 100644 --- a/sketch.cpp +++ b/sketch.cpp @@ -3,8 +3,14 @@ #include #include +// For printing +#include +#include +#include + + +#define BOOST_PROTO17_STREAM_OPERATORS // TODO: For testing. -// TODO: Pretty printer. // TODO: Verbose debugging mode for matching. // TODO: Proto-style "Fuzzy and Exact Matches of Terminals". @@ -203,6 +209,106 @@ namespace boost { namespace proto17 { } + namespace detail { + + inline std::ostream & print_impl (std::ostream & os, expr_kind kind) + { + switch (kind) { + case expr_kind::plus: return os << "+"; + case expr_kind::minus: return os << "-"; + // TODO + default: return os << "** ERROR: UNKNOWN OPERATOR! **"; + } + } + + template + auto print_object (std::ostream & os, T const & x) -> decltype(os << x) + { return os << x; } + + inline std::ostream & print_object (std::ostream & os, ...) + { return os << "<>"; } + + template + std::ostream & print_type (std::ostream & os) + { + os << typeindex::type_id().pretty_name(); + if (std::is_const_v) + os << " const"; + if (std::is_volatile_v) + os << " volatile"; + using no_cv_t = std::remove_cv_t; + if (std::is_lvalue_reference_v) + os << " &"; + if (std::is_rvalue_reference_v) + os << " &&"; + return os; + } + + template + std::ostream & print_impl ( + std::ostream & os, + terminal const & term, + int indent, + char const * indent_str) + { + for (int i = 0; i < indent; ++i) { + os << indent_str; + } + os << "term<"; + print_type(os); + os << ">[="; + print_object(os, term.value); + os << "]\n"; + return os; + } + + template + std::ostream & print_impl ( + std::ostream & os, + expression const & expr, + int indent, + char const * indent_str) + { + if constexpr (Kind == expr_kind::terminal) { + using namespace hana::literals; + static_assert(hana::size(expr.elements) == 1_c, ""); + static_assert(is_terminal(hana::typeid_(expr.elements[0_c])), ""); + print_impl(os, expr.elements[0_c]); + } else { + for (int i = 0; i < indent; ++i) { + os << indent_str; + } + os << "expr<"; + print_impl(os, Kind); + os << ">\n"; + hana::for_each(expr.elements, [&os, indent, indent_str](auto const & element) { + print_impl(os, element, indent + 1, indent_str); + }); + } + + return os; + } + + } + + template + std::ostream & print (std::ostream & os, terminal const & term) + { return detail::print_impl(os, term, 0, " "); } + + template + std::ostream & print (std::ostream & os, expression const & expr) + { return detail::print_impl(os, expr, 0, " "); } + +#if defined(BOOST_PROTO17_STREAM_OPERATORS) + template + std::ostream & operator<< (std::ostream & os, terminal const & term) + { return detail::print_impl(os, term, 0, " "); } + + template + std::ostream & operator<< (std::ostream & os, expression const & expr) + { return detail::print_impl(os, expr, 0, " "); } +#endif + namespace detail { inline bool matches (...) @@ -974,6 +1080,42 @@ void term_plus_expr () } } +void print () +{ + term unity{1.0}; + int i_ = 42; + term i{std::move(i_)}; + bp17::expression< + bp17::expr_kind::plus, + term &, + term + > expr = unity + std::move(i); + bp17::expression< + bp17::expr_kind::plus, + term &, + bp17::expression< + bp17::expr_kind::plus, + term &, + term + > + > unevaluated_expr = unity + std::move(expr); + + bp17::print(std::cout, unity); + bp17::print(std::cout, expr); + bp17::print(std::cout, unevaluated_expr); + + struct thing {}; + term a_thing{{}}; + bp17::print(std::cout, a_thing); + +#if defined(BOOST_PROTO17_STREAM_OPERATORS) + std::cout << unity; + std::cout << expr; + std::cout << unevaluated_expr; + std::cout << a_thing; +#endif +} + int main () { term_plus_x(); @@ -981,6 +1123,8 @@ int main () term_plus_term(); term_plus_expr(); + print(); + #if 0 // TODO { bp17::terminal unity{1.0};