mirror of
https://github.com/bolero-MURAKAMI/Sprout
synced 2024-11-12 21:09:01 +00:00
477 lines
15 KiB
C++
477 lines
15 KiB
C++
#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:
|
|
explicit SPROUT_CONSTEXPR 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:
|
|
explicit SPROUT_CONSTEXPR 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:
|
|
explicit SPROUT_CONSTEXPR 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:
|
|
explicit SPROUT_CONSTEXPR 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:
|
|
explicit SPROUT_CONSTEXPR unexpr(Expr const& e)
|
|
: Expr(e)
|
|
{}
|
|
using Expr::operator=;
|
|
};
|
|
} // namespace breed
|
|
} // namespace sprout
|
|
|
|
#endif // #ifndef SPROUT_BREED_EXPR_HPP
|