Sprout/sprout/breed/expr.hpp

478 lines
15 KiB
C++
Raw Normal View History

#ifndef SPROUT_BREED_EXPR_HPP
#define SPROUT_BREED_EXPR_HPP
#include <cstddef>
#include <type_traits>
#include <sprout/config.hpp>
#include <sprout/utility/pack.hpp>
#include <sprout/tuple/tuple.hpp>
#include <sprout/breed/breed_fwd.hpp>
#include <sprout/breed/args.hpp>
#include <sprout/breed/traits.hpp>
namespace sprout {
namespace breed {
namespace detail {
struct not_a_valid_type {
private:
SPROUT_CONSTEXPR not_a_valid_type() {}
};
template<typename Tag, typename Arg>
struct address_of_hack {
public:
typedef sprout::breed::detail::not_a_valid_type type;
};
template<typename Expr>
struct address_of_hack<sprout::breed::tag::address_of, Expr&> {
typedef Expr* type;
};
template<typename T, typename Expr, typename Arg>
SPROUT_CONSTEXPR Expr make_terminal(T const& t, Expr*, sprout::breed::term<Arg> const*) {
return Expr(t);
}
template<typename T, typename Expr, typename Arg, std::size_t N>
SPROUT_CONSTEXPR Expr make_terminal(T const (&t)[N], Expr const*, sprout::breed::term<Arg[N]> const*) {
return throw "Sorry, not implemented.", Expr();
}
template<typename T, typename U>
struct same_cv {
public:
typedef U type;
};
template<typename T, typename U>
struct same_cv<T const, U> {
public:
typedef U const type;
};
} // namespace detail
namespace result_of {
namespace detail {
template<typename Expr, typename Domain, typename... Args>
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<Args, Domain>::type...
>
>::type type;
public:
static SPROUT_CONSTEXPR type const call(
Expr const& e,
Args const&... args
) const
{
return type(
e,
sprout::breed::as_child<Domain>(args)...
);
}
};
} // namespace detail
//
// funop
//
template<typename Sig, typename This, typename Domain>
struct funop;
template<typename Expr, typename... Args, typename This, typename Domain>
struct funop<Expr(Args...), This, Domain>
: public sprout::breed::result_of::detail::funop_impl<
typename sprout::breed::detail::same_cv<Expr, This>::type,
Domain,
typename std::remove_reference<Args>::type...
>
{};
} // namespace result_of
namespace exprns_ {
//
// basic_expr
//
template<typename Tag, typename Arg>
struct basic_expr<Tag, term<Arg>, 0> {
public:
SPROUT_STATIC_CONSTEXPR long breed_arity_c = 0;
public:
typedef Tag breed_tag;
typedef std::integral_constant<long, breed_arity_c> breed_arity;
typedef basic_expr breed_base_expr;
typedef sprout::breed::term<Arg> 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<long N>
struct breed_child
: public sprout::tppack_at<N, Arg>
{};
public:
template<typename A>
static SPROUT_CONSTEXPR basic_expr make(A const& arg) {
return sprout::breed::detail::make_terminal(
arg,
static_cast<basic_expr const*>(0),
static_cast<breed_args const*>(0)
);
}
private:
sprout::tuples::tuple<Arg> children_;
public:
SPROUT_CONSTEXPR explicit basic_expr(Arg const& arg)
: children_(arg)
{}
template<long N>
SPROUT_CONSTEXPR typename breed_child<N>::type const& child() const {
return sprout::tuples::get<N>(children_);
}
template<long N>
typename breed_child<N>::type const& child() {
return sprout::tuples::get<N>(children_);
}
SPROUT_CONSTEXPR basic_expr const& breed_base() const {
return *this;
}
basic_expr& breed_base() {
return *this;
}
};
template<typename Tag, typename... Args>
struct basic_expr<Tag, sprout::breed::list<Args...>, sizeof...(Args)> {
public:
SPROUT_STATIC_CONSTEXPR long breed_arity_c = sizeof...(Args);
public:
typedef Tag breed_tag;
typedef std::integral_constant<long, breed_arity_c> breed_arity;
typedef basic_expr breed_base_expr;
typedef sprout::breed::list<Args...> 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<long N>
struct breed_child
: public sprout::tppack_at<N, Args...>
{};
public:
template<typename... As>
static SPROUT_CONSTEXPR basic_expr make(As const&... args) {
return basic_expr(args...);
}
private:
sprout::tuples::tuple<Args...> children_;
public:
SPROUT_CONSTEXPR explicit basic_expr(Args const&... args)
: children_(args...)
{}
template<long N>
SPROUT_CONSTEXPR typename breed_child<N>::type const& child() const {
return sprout::tuples::get<N>(children_);
}
template<long N>
typename breed_child<N>::type const& child() {
return sprout::tuples::get<N>(children_);
}
SPROUT_CONSTEXPR basic_expr const& breed_base() const {
return *this;
}
basic_expr& breed_base() {
return *this;
}
};
//
// expr
//
template<typename Tag, typename Arg>
struct expr<Tag, sprout::breed::term<Arg>, 0> {
public:
SPROUT_STATIC_CONSTEXPR long breed_arity_c = 0;
public:
typedef Tag breed_tag;
typedef std::integral_constant<long, breed_arity_c> breed_arity;
typedef expr breed_base_expr;
typedef sprout::breed::term<Arg> breed_args;
typedef basic_expr<Tag, breed_args, 0> 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<long N>
struct breed_child
: public sprout::tppack_at<N, Arg>
{};
template<typename Sig>
struct result {
public:
typedef typename sprout::breed::result_of::funop<
Sig,
expr,
sprout::breed::default_domain
>::type type;
};
public:
template<typename A>
static SPROUT_CONSTEXPR expr make(A const& arg) {
return sprout::breed::detail::make_terminal(
arg,
static_cast<expr const*>(0),
static_cast<breed_args const*>(0)
);
}
private:
sprout::tuples::tuple<Arg> children_;
public:
SPROUT_CONSTEXPR explicit expr(Arg const& arg)
: children_(arg)
{}
template<long N>
SPROUT_CONSTEXPR typename breed_child<N>::type const& child() const {
return sprout::tuples::get<N>(children_);
}
template<long N>
typename breed_child<N>::type const& child() {
return sprout::tuples::get<N>(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<expr const&, expr const&>,
2
> operator=(expr const& arg) const {
return sprout::breed::expr<
sprout::breed::tag::assign,
sprout::breed::list<expr const&, expr const&>,
2
>(*this, arg);
}
template<typename A>
SPROUT_CONSTEXPR sprout::breed::expr<
sprout::breed::tag::assign,
sprout::breed::list<expr const&, typename sprout::breed::result_of::as_child<A const>::type>,
2
> operator=(A const& arg) const {
return sprout::breed::expr<
sprout::breed::tag::assign,
sprout::breed::list<expr const&, typename sprout::breed::result_of::as_child<A const>::type>,
2
>(*this, sprout::breed::as_child(arg));
}
template<typename A>
sprout::breed::expr<
sprout::breed::tag::assign,
sprout::breed::list<expr const&, typename sprout::breed::result_of::as_child<A>::type>,
2
> operator=(A& arg) const {
return sprout::breed::expr<
sprout::breed::tag::assign,
sprout::breed::list<expr const&, typename sprout::breed::result_of::as_child<A>::type>,
2
>(*this, sprout::breed::as_child(arg));
}
template<typename A>
SPROUT_CONSTEXPR sprout::breed::expr<
sprout::breed::tag::subscript,
sprout::breed::list<expr const&, typename sprout::breed::result_of::as_child<A const>::type>,
2
> operator[](A const& arg) const {
return sprout::breed::expr<
sprout::breed::tag::subscript,
sprout::breed::list<expr const&, typename sprout::breed::result_of::as_child<A const>::type>,
2
>(*this, sprout::breed::as_child(arg));
}
template<typename A>
sprout::breed::expr<
sprout::breed::tag::subscript,
sprout::breed::list<expr const&, typename sprout::breed::result_of::as_child<A>::type>,
2
> operator[](A& arg) const {
return sprout::breed::expr<
sprout::breed::tag::subscript,
sprout::breed::list<expr const&, typename sprout::breed::result_of::as_child<A>::type>,
2
>(*this, sprout::breed::as_child(arg));
}
template<typename... As>
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<typename Tag, typename... Args>
struct expr<Tag, sprout::breed::list<Args...>, sizeof...(Args)> {
public:
SPROUT_STATIC_CONSTEXPR long breed_arity_c = sizeof...(Args);
public:
typedef Tag breed_tag;
typedef std::integral_constant<long, breed_arity_c> breed_arity;
typedef expr breed_base_expr;
typedef sprout::breed::list<Args...> breed_args;
typedef basic_expr<Tag, breed_args, 0> 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<long N>
struct breed_child
: public sprout::tppack_at<N, Args...>
{};
template<typename Sig>
struct result {
public:
typedef typename sprout::breed::result_of::funop<
Sig,
expr,
sprout::breed::default_domain
>::type type;
};
public:
template<typename... As>
static SPROUT_CONSTEXPR basic_expr make(As const&... args) {
return basic_expr(args...);
}
private:
sprout::tuples::tuple<Arg> children_;
public:
SPROUT_CONSTEXPR explicit basic_expr(Args const&... args)
: children_(args...)
{}
template<long N>
SPROUT_CONSTEXPR typename breed_child<N>::type const& child() const {
return sprout::tuples::get<N>(children_);
}
template<long N>
typename breed_child<N>::type const& child() {
return sprout::tuples::get<N>(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<expr const&, expr const&>,
2
> operator=(expr const& arg) const {
return sprout::breed::expr<
sprout::breed::tag::assign,
sprout::breed::list<expr const&, expr const&>,
2
>(*this, arg);
}
template<typename A>
SPROUT_CONSTEXPR sprout::breed::expr<
sprout::breed::tag::assign,
sprout::breed::list<expr const&, typename sprout::breed::result_of::as_child<A const>::type>,
2
> operator=(A const& arg) const {
return sprout::breed::expr<
sprout::breed::tag::assign,
sprout::breed::list<expr const&, typename sprout::breed::result_of::as_child<A const>::type>,
2
>(*this, sprout::breed::as_child(arg));
}
template<typename A>
sprout::breed::expr<
sprout::breed::tag::assign,
sprout::breed::list<expr const&, typename sprout::breed::result_of::as_child<A>::type>,
2
> operator=(A& arg) const {
return sprout::breed::expr<
sprout::breed::tag::assign,
sprout::breed::list<expr const&, typename sprout::breed::result_of::as_child<A>::type>,
2
>(*this, sprout::breed::as_child(arg));
}
template<typename A>
SPROUT_CONSTEXPR sprout::breed::expr<
sprout::breed::tag::subscript,
sprout::breed::list<expr const&, typename sprout::breed::result_of::as_child<A const>::type>,
2
> operator[](A const& arg) const {
return sprout::breed::expr<
sprout::breed::tag::subscript,
sprout::breed::list<expr const&, typename sprout::breed::result_of::as_child<A const>::type>,
2
>(*this, sprout::breed::as_child(arg));
}
template<typename A>
sprout::breed::expr<
sprout::breed::tag::subscript,
sprout::breed::list<expr const&, typename sprout::breed::result_of::as_child<A>::type>,
2
> operator[](A& arg) const {
return sprout::breed::expr<
sprout::breed::tag::subscript,
sprout::breed::list<expr const&, typename sprout::breed::result_of::as_child<A>::type>,
2
>(*this, sprout::breed::as_child(arg));
}
template<typename... As>
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<typename Expr>
struct unexpr
: public Expr
{
public:
SPROUT_BREED_UNEXPR();
public:
SPROUT_CONSTEXPR explicit unexpr(Expr const& e)
: Expr(e)
{}
using Expr::operator=;
};
} // namespace breed
} // namespace sprout
#endif // #ifndef SPROUT_BREED_EXPR_HPP