#ifndef SPROUT_BREED_EXPR_HPP #define SPROUT_BREED_EXPR_HPP #include #include #include #include #include #include #include #include namespace sprout { namespace breed { namespace detail { struct not_a_valid_type { private: SPROUT_CONSTEXPR not_a_valid_type() {} }; template struct address_of_hack { public: typedef sprout::breed::detail::not_a_valid_type type; }; template struct address_of_hack { typedef Expr* type; }; template SPROUT_CONSTEXPR Expr make_terminal(T const& t, Expr*, sprout::breed::term const*) { return Expr(t); } template SPROUT_CONSTEXPR Expr make_terminal(T const (&t)[N], Expr const*, sprout::breed::term const*) { return throw "Sorry, not implemented.", Expr(); } template struct same_cv { public: typedef U type; }; template struct same_cv { public: typedef U const type; }; } // namespace detail namespace result_of { namespace detail { template struct funop_impl { public: typedef typename sprout::breed::base_expr< Domain, sprout::breed::tag::function, sprout::breed::list< Expr const&, typename sprout::breed::result_of::as_child::type... > >::type type; public: static SPROUT_CONSTEXPR type const call( Expr const& e, Args const&... args ) const { return type( e, sprout::breed::as_child(args)... ); } }; } // namespace detail // // funop // template struct funop; template struct funop : public sprout::breed::result_of::detail::funop_impl< typename sprout::breed::detail::same_cv::type, Domain, typename std::remove_reference::type... > {}; } // namespace result_of namespace exprns_ { // // basic_expr // template struct basic_expr, 0> { public: SPROUT_STATIC_CONSTEXPR long breed_arity_c = 0; public: typedef Tag breed_tag; typedef std::integral_constant breed_arity; typedef basic_expr breed_base_expr; typedef sprout::breed::term breed_args; typedef basic_expr breed_grammar; typedef sprout::breed::basic_default_domain breed_domain; typedef sprout::breed::default_generator breed_generator; typedef sprout::breed::tag::breed_expr fusion_tag; typedef basic_expr breed_derived_expr; typedef void breed_is_expr_; typedef sprout::breed::detail::not_a_valid_type address_of_hack_type_; public: template struct breed_child : public sprout::tppack_at {}; public: template static SPROUT_CONSTEXPR basic_expr make(A const& arg) { return sprout::breed::detail::make_terminal( arg, static_cast(0), static_cast(0) ); } private: sprout::tuples::tuple children_; public: explicit SPROUT_CONSTEXPR basic_expr(Arg const& arg) : children_(arg) {} template SPROUT_CONSTEXPR typename breed_child::type const& child() const { return sprout::tuples::get(children_); } template typename breed_child::type const& child() { return sprout::tuples::get(children_); } SPROUT_CONSTEXPR basic_expr const& breed_base() const { return *this; } basic_expr& breed_base() { return *this; } }; template struct basic_expr, sizeof...(Args)> { public: SPROUT_STATIC_CONSTEXPR long breed_arity_c = sizeof...(Args); public: typedef Tag breed_tag; typedef std::integral_constant breed_arity; typedef basic_expr breed_base_expr; typedef sprout::breed::list breed_args; typedef basic_expr breed_grammar; typedef sprout::breed::basic_default_domain breed_domain; typedef sprout::breed::default_generator breed_generator; typedef sprout::breed::tag::breed_expr fusion_tag; typedef basic_expr breed_derived_expr; typedef void breed_is_expr_; typedef sprout::breed::detail::not_a_valid_type address_of_hack_type_; public: template struct breed_child : public sprout::tppack_at {}; public: template static SPROUT_CONSTEXPR basic_expr make(As const&... args) { return basic_expr(args...); } private: sprout::tuples::tuple children_; public: explicit SPROUT_CONSTEXPR basic_expr(Args const&... args) : children_(args...) {} template SPROUT_CONSTEXPR typename breed_child::type const& child() const { return sprout::tuples::get(children_); } template typename breed_child::type const& child() { return sprout::tuples::get(children_); } SPROUT_CONSTEXPR basic_expr const& breed_base() const { return *this; } basic_expr& breed_base() { return *this; } }; // // expr // template struct expr, 0> { public: SPROUT_STATIC_CONSTEXPR long breed_arity_c = 0; public: typedef Tag breed_tag; typedef std::integral_constant breed_arity; typedef expr breed_base_expr; typedef sprout::breed::term breed_args; typedef basic_expr breed_grammar; typedef sprout::breed::basic_default_domain breed_domain; typedef sprout::breed::default_generator breed_generator; typedef sprout::breed::tag::breed_expr fusion_tag; typedef expr breed_derived_expr; typedef void proto_is_expr_; typedef sprout::breed::detail::not_a_valid_type address_of_hack_type_; public: template struct breed_child : public sprout::tppack_at {}; template struct result { public: typedef typename sprout::breed::result_of::funop< Sig, expr, sprout::breed::default_domain >::type type; }; public: template static SPROUT_CONSTEXPR expr make(A const& arg) { return sprout::breed::detail::make_terminal( arg, static_cast(0), static_cast(0) ); } private: sprout::tuples::tuple children_; public: explicit SPROUT_CONSTEXPR expr(Arg const& arg) : children_(arg) {} template SPROUT_CONSTEXPR typename breed_child::type const& child() const { return sprout::tuples::get(children_); } template typename breed_child::type const& child() { return sprout::tuples::get(children_); } SPROUT_CONSTEXPR expr const& breed_base() const { return *this; } expr& breed_base() { return *this; } SPROUT_CONSTEXPR sprout::breed::expr< sprout::breed::tag::assign, sprout::breed::list, 2 > operator=(expr const& arg) const { return sprout::breed::expr< sprout::breed::tag::assign, sprout::breed::list, 2 >(*this, arg); } template SPROUT_CONSTEXPR sprout::breed::expr< sprout::breed::tag::assign, sprout::breed::list::type>, 2 > operator=(A const& arg) const { return sprout::breed::expr< sprout::breed::tag::assign, sprout::breed::list::type>, 2 >(*this, sprout::breed::as_child(arg)); } template sprout::breed::expr< sprout::breed::tag::assign, sprout::breed::list::type>, 2 > operator=(A& arg) const { return sprout::breed::expr< sprout::breed::tag::assign, sprout::breed::list::type>, 2 >(*this, sprout::breed::as_child(arg)); } template SPROUT_CONSTEXPR sprout::breed::expr< sprout::breed::tag::subscript, sprout::breed::list::type>, 2 > operator[](A const& arg) const { return sprout::breed::expr< sprout::breed::tag::subscript, sprout::breed::list::type>, 2 >(*this, sprout::breed::as_child(arg)); } template sprout::breed::expr< sprout::breed::tag::subscript, sprout::breed::list::type>, 2 > operator[](A& arg) const { return sprout::breed::expr< sprout::breed::tag::subscript, sprout::breed::list::type>, 2 >(*this, sprout::breed::as_child(arg)); } template SPROUT_CONSTEXPR typename sprout::breed::result_of::funop< expr(As const&...), expr, sprout::breed::default_domain >::type operator()(As const&... args) const { return sprout::breed::result_of::funop< expr(As const&...), expr, sprout::breed::default_domain >::call(*this, args...); } }; template struct expr, sizeof...(Args)> { public: SPROUT_STATIC_CONSTEXPR long breed_arity_c = sizeof...(Args); public: typedef Tag breed_tag; typedef std::integral_constant breed_arity; typedef expr breed_base_expr; typedef sprout::breed::list breed_args; typedef basic_expr breed_grammar; typedef sprout::breed::basic_default_domain breed_domain; typedef sprout::breed::default_generator breed_generator; typedef sprout::breed::tag::breed_expr fusion_tag; typedef expr breed_derived_expr; typedef void proto_is_expr_; typedef sprout::breed::detail::not_a_valid_type address_of_hack_type_; public: template struct breed_child : public sprout::tppack_at {}; template struct result { public: typedef typename sprout::breed::result_of::funop< Sig, expr, sprout::breed::default_domain >::type type; }; public: template static SPROUT_CONSTEXPR basic_expr make(As const&... args) { return basic_expr(args...); } private: sprout::tuples::tuple children_; public: explicit SPROUT_CONSTEXPR basic_expr(Args const&... args) : children_(args...) {} template SPROUT_CONSTEXPR typename breed_child::type const& child() const { return sprout::tuples::get(children_); } template typename breed_child::type const& child() { return sprout::tuples::get(children_); } SPROUT_CONSTEXPR basic_expr const& breed_base() const { return *this; } basic_expr& breed_base() { return *this; } SPROUT_CONSTEXPR sprout::breed::expr< sprout::breed::tag::assign, sprout::breed::list, 2 > operator=(expr const& arg) const { return sprout::breed::expr< sprout::breed::tag::assign, sprout::breed::list, 2 >(*this, arg); } template SPROUT_CONSTEXPR sprout::breed::expr< sprout::breed::tag::assign, sprout::breed::list::type>, 2 > operator=(A const& arg) const { return sprout::breed::expr< sprout::breed::tag::assign, sprout::breed::list::type>, 2 >(*this, sprout::breed::as_child(arg)); } template sprout::breed::expr< sprout::breed::tag::assign, sprout::breed::list::type>, 2 > operator=(A& arg) const { return sprout::breed::expr< sprout::breed::tag::assign, sprout::breed::list::type>, 2 >(*this, sprout::breed::as_child(arg)); } template SPROUT_CONSTEXPR sprout::breed::expr< sprout::breed::tag::subscript, sprout::breed::list::type>, 2 > operator[](A const& arg) const { return sprout::breed::expr< sprout::breed::tag::subscript, sprout::breed::list::type>, 2 >(*this, sprout::breed::as_child(arg)); } template sprout::breed::expr< sprout::breed::tag::subscript, sprout::breed::list::type>, 2 > operator[](A& arg) const { return sprout::breed::expr< sprout::breed::tag::subscript, sprout::breed::list::type>, 2 >(*this, sprout::breed::as_child(arg)); } template SPROUT_CONSTEXPR typename sprout::breed::result_of::funop< expr(As const&...), expr, sprout::breed::default_domain >::type operator()(As const&... args) const { return sprout::breed::result_of::funop< expr(As const&...), expr, sprout::breed::default_domain >::call(*this, args...); } }; } // namespace exprns_ // // unexpr // template struct unexpr : public Expr { public: SPROUT_BREED_UNEXPR(); public: explicit SPROUT_CONSTEXPR unexpr(Expr const& e) : Expr(e) {} using Expr::operator=; }; } // namespace breed } // namespace sprout #endif // #ifndef SPROUT_BREED_EXPR_HPP