368 lines
11 KiB
Plaintext
368 lines
11 KiB
Plaintext
|
/*=============================================================================
|
||
|
Copyright (c) 2005-2010 Joel de Guzman
|
||
|
Copyright (c) 2010 Eric Niebler
|
||
|
Copyright (c) 2010 Thomas Heller
|
||
|
Copyright (c) 2014 John Fletcher
|
||
|
|
||
|
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
||
|
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||
|
==============================================================================*/
|
||
|
#ifndef BOOST_PHOENIX_CORE_ACTOR_HPP
|
||
|
#define BOOST_PHOENIX_CORE_ACTOR_HPP
|
||
|
|
||
|
#include <boost/phoenix/core/limits.hpp>
|
||
|
|
||
|
#include <boost/is_placeholder.hpp>
|
||
|
#include <boost/mpl/identity.hpp>
|
||
|
#include <boost/mpl/eval_if.hpp>
|
||
|
#include <boost/phoenix/core/domain.hpp>
|
||
|
#include <boost/phoenix/core/environment.hpp>
|
||
|
#include <boost/phoenix/core/is_nullary.hpp>
|
||
|
#include <boost/phoenix/core/meta_grammar.hpp>
|
||
|
#include <boost/phoenix/support/iterate.hpp>
|
||
|
#include <boost/phoenix/support/vector.hpp>
|
||
|
#include <boost/proto/extends.hpp>
|
||
|
#include <boost/proto/make_expr.hpp>
|
||
|
#include <boost/utility/result_of.hpp>
|
||
|
#include <boost/mpl/void.hpp>
|
||
|
#include <cstring>
|
||
|
#ifndef BOOST_PHOENIX_NO_VARIADIC_ACTOR
|
||
|
# include <boost/mpl/if.hpp>
|
||
|
# include <boost/type_traits/is_reference.hpp>
|
||
|
# include <boost/phoenix/core/detail/index_sequence.hpp>
|
||
|
#endif
|
||
|
|
||
|
#ifdef BOOST_MSVC
|
||
|
#pragma warning(push)
|
||
|
#pragma warning(disable: 4522) // 'this' used in base member initializer list
|
||
|
#pragma warning(disable: 4510) // default constructor could not be generated
|
||
|
#pragma warning(disable: 4610) // can never be instantiated - user defined cons
|
||
|
#endif
|
||
|
|
||
|
namespace boost { namespace phoenix
|
||
|
{
|
||
|
template <typename Expr>
|
||
|
struct actor;
|
||
|
|
||
|
namespace detail
|
||
|
{
|
||
|
struct error_expecting_arguments
|
||
|
{
|
||
|
template <typename T>
|
||
|
error_expecting_arguments(T const&) {}
|
||
|
};
|
||
|
|
||
|
struct error_invalid_lambda_expr
|
||
|
{
|
||
|
template <typename T>
|
||
|
error_invalid_lambda_expr(T const&) {}
|
||
|
};
|
||
|
|
||
|
template <typename T>
|
||
|
struct result_type_deduction_helper
|
||
|
{
|
||
|
typedef T const & type;
|
||
|
};
|
||
|
|
||
|
template <typename T>
|
||
|
struct result_type_deduction_helper<T &>
|
||
|
{
|
||
|
typedef T & type;
|
||
|
};
|
||
|
|
||
|
template <typename T>
|
||
|
struct result_type_deduction_helper<T const &>
|
||
|
{
|
||
|
typedef T const & type;
|
||
|
};
|
||
|
|
||
|
struct do_assign
|
||
|
{
|
||
|
BOOST_PROTO_CALLABLE()
|
||
|
|
||
|
typedef void result_type;
|
||
|
|
||
|
template <typename T1, typename T2>
|
||
|
void operator()(T1 & t1, T2 const & t2) const
|
||
|
{
|
||
|
proto::value(t1) = proto::value(t2);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
#ifdef BOOST_PHOENIX_NO_VARIADIC_ACTOR
|
||
|
#include <boost/phoenix/core/detail/cpp03/assign.hpp>
|
||
|
#else
|
||
|
struct assign : proto::transform<assign>
|
||
|
{
|
||
|
typedef assign proto_grammer;
|
||
|
|
||
|
template <typename Expr, typename State, typename Data
|
||
|
, typename Indices = typename detail::make_index_sequence<proto::arity_of<Expr>::value>::type >
|
||
|
struct impl;
|
||
|
|
||
|
template <std::size_t>
|
||
|
struct proto_expr { typedef proto::_ type; };
|
||
|
|
||
|
template <std::size_t Index>
|
||
|
struct nth_assign
|
||
|
{
|
||
|
typedef
|
||
|
assign type(
|
||
|
proto::_child_c<Index>
|
||
|
, proto::call<proto::_child_c<Index>(proto::_state)>
|
||
|
)
|
||
|
;
|
||
|
};
|
||
|
|
||
|
template <typename Expr, typename State, typename Data>
|
||
|
struct impl<Expr, State, Data, detail::index_sequence<> >
|
||
|
: proto::when<
|
||
|
proto::terminal<proto::_>
|
||
|
, do_assign(proto::_, proto::_state)
|
||
|
>::template impl<Expr, State, Data>
|
||
|
{
|
||
|
};
|
||
|
|
||
|
template <typename Expr, typename State, typename Data
|
||
|
, std::size_t... Indices>
|
||
|
struct impl<Expr, State, Data, detail::index_sequence<Indices...> >
|
||
|
: proto::when<
|
||
|
proto::nary_expr<typename proto_expr<Indices>::type...>
|
||
|
, proto::and_<typename nth_assign<Indices>::type...>
|
||
|
>::template impl<Expr, State, Data>
|
||
|
{
|
||
|
};
|
||
|
};
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
namespace result_of
|
||
|
{
|
||
|
#ifdef BOOST_PHOENIX_NO_VARIADIC_ACTOR
|
||
|
// Bring in the result_of::actor<>
|
||
|
#include <boost/phoenix/core/detail/cpp03/actor_result_of.hpp>
|
||
|
#else
|
||
|
template <typename Expr, typename... A>
|
||
|
struct actor_impl
|
||
|
{
|
||
|
typedef
|
||
|
typename boost::phoenix::evaluator::impl<
|
||
|
Expr const&
|
||
|
, vector2<
|
||
|
typename vector_chooser<sizeof...(A) + 1>::
|
||
|
template apply<const ::boost::phoenix::actor<Expr> *, A...>::type&
|
||
|
, default_actions
|
||
|
> const &
|
||
|
, proto::empty_env
|
||
|
>::result_type
|
||
|
type;
|
||
|
};
|
||
|
|
||
|
template <typename Expr, typename... A>
|
||
|
struct actor : actor_impl<Expr, A...> {};
|
||
|
|
||
|
template <typename Expr>
|
||
|
struct nullary_actor_result : actor_impl<Expr> {};
|
||
|
#endif
|
||
|
|
||
|
template <typename Expr>
|
||
|
struct actor<Expr>
|
||
|
{
|
||
|
typedef
|
||
|
// avoid calling result_of::actor when this is false
|
||
|
typename mpl::eval_if_c<
|
||
|
result_of::is_nullary<Expr>::value
|
||
|
, nullary_actor_result<Expr>
|
||
|
, mpl::identity<detail::error_expecting_arguments>
|
||
|
>::type
|
||
|
type;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// actor
|
||
|
//
|
||
|
// The actor class. The main thing! In phoenix, everything is an actor
|
||
|
// This class is responsible for full function evaluation. Partial
|
||
|
// function evaluation involves creating a hierarchy of actor objects.
|
||
|
//
|
||
|
////////////////////////////////////////////////////////////////////////////
|
||
|
template <typename Expr>
|
||
|
struct actor
|
||
|
{
|
||
|
typedef typename
|
||
|
mpl::eval_if_c<
|
||
|
mpl::or_<
|
||
|
is_custom_terminal<Expr>
|
||
|
, mpl::bool_<is_placeholder<Expr>::value>
|
||
|
>::value
|
||
|
, proto::terminal<Expr>
|
||
|
, mpl::identity<Expr>
|
||
|
>::type
|
||
|
expr_type;
|
||
|
|
||
|
BOOST_PROTO_BASIC_EXTENDS(expr_type, actor<expr_type>, phoenix_domain)
|
||
|
|
||
|
// providing operator= to be assignable
|
||
|
actor& operator=(actor const& other)
|
||
|
{
|
||
|
detail::assign()(*this, other);
|
||
|
return *this;
|
||
|
}
|
||
|
actor& operator=(actor & other)
|
||
|
{
|
||
|
detail::assign()(*this, other);
|
||
|
return *this;
|
||
|
}
|
||
|
|
||
|
template <typename A0>
|
||
|
typename proto::result_of::make_expr<
|
||
|
proto::tag::assign
|
||
|
, phoenix_domain
|
||
|
, proto_base_expr
|
||
|
, A0
|
||
|
>::type const
|
||
|
operator=(A0 const & a0) const
|
||
|
{
|
||
|
return proto::make_expr<proto::tag::assign, phoenix_domain>(this->proto_expr_, a0);
|
||
|
}
|
||
|
|
||
|
template <typename A0>
|
||
|
typename proto::result_of::make_expr<
|
||
|
proto::tag::assign
|
||
|
, phoenix_domain
|
||
|
, proto_base_expr
|
||
|
, A0
|
||
|
>::type const
|
||
|
operator=(A0 & a0) const
|
||
|
{
|
||
|
return proto::make_expr<proto::tag::assign, phoenix_domain>(this->proto_expr_, a0);
|
||
|
}
|
||
|
|
||
|
template <typename A0>
|
||
|
typename proto::result_of::make_expr<
|
||
|
proto::tag::subscript
|
||
|
, phoenix_domain
|
||
|
, proto_base_expr
|
||
|
, A0
|
||
|
>::type const
|
||
|
operator[](A0 const & a0) const
|
||
|
{
|
||
|
return proto::make_expr<proto::tag::subscript, phoenix_domain>(this->proto_expr_, a0);
|
||
|
}
|
||
|
|
||
|
template <typename A0>
|
||
|
typename proto::result_of::make_expr<
|
||
|
proto::tag::subscript
|
||
|
, phoenix_domain
|
||
|
, proto_base_expr
|
||
|
, A0
|
||
|
>::type const
|
||
|
operator[](A0 & a0) const
|
||
|
{
|
||
|
return proto::make_expr<proto::tag::subscript, phoenix_domain>(this->proto_expr_, a0);
|
||
|
}
|
||
|
|
||
|
template <typename Sig>
|
||
|
struct result;
|
||
|
|
||
|
typename result_of::actor<proto_base_expr>::type
|
||
|
operator()()
|
||
|
{
|
||
|
typedef vector1<const actor<Expr> *> env_type;
|
||
|
env_type env = {this};
|
||
|
|
||
|
return phoenix::eval(*this, phoenix::context(env, default_actions()));
|
||
|
}
|
||
|
|
||
|
typename result_of::actor<proto_base_expr>::type
|
||
|
operator()() const
|
||
|
{
|
||
|
typedef vector1<const actor<Expr> *> env_type;
|
||
|
env_type env = {this};
|
||
|
|
||
|
return phoenix::eval(*this, phoenix::context(env, default_actions()));
|
||
|
}
|
||
|
|
||
|
template <typename Env>
|
||
|
typename evaluator::impl<
|
||
|
proto_base_expr const &
|
||
|
, typename result_of::context<
|
||
|
Env const &
|
||
|
, default_actions const &
|
||
|
>::type
|
||
|
, proto::empty_env
|
||
|
>::result_type
|
||
|
eval(Env const & env) const
|
||
|
{
|
||
|
return phoenix::eval(*this, phoenix::context(env, default_actions()));
|
||
|
}
|
||
|
|
||
|
#ifdef BOOST_PHOENIX_NO_VARIADIC_ACTOR
|
||
|
// Bring in the rest
|
||
|
#include <boost/phoenix/core/detail/cpp03/actor_operator.hpp>
|
||
|
#else
|
||
|
template <typename This, typename... A>
|
||
|
struct result<This(A...)>
|
||
|
: result_of::actor<
|
||
|
proto_base_expr
|
||
|
, typename mpl::if_<is_reference<A>, A, A const &>::type...
|
||
|
>
|
||
|
{};
|
||
|
|
||
|
template <typename... A>
|
||
|
typename result<actor(A...)>::type
|
||
|
operator()(A &&... a)
|
||
|
{
|
||
|
typedef
|
||
|
typename vector_chooser<sizeof...(A) + 1>::template apply<
|
||
|
const actor<Expr> *
|
||
|
, typename mpl::if_<is_reference<A>, A, A const &>::type...
|
||
|
>::type
|
||
|
env_type;
|
||
|
|
||
|
env_type env = {this, a...};
|
||
|
return phoenix::eval(*this, phoenix::context(env, default_actions()));
|
||
|
}
|
||
|
|
||
|
template <typename... A>
|
||
|
typename result<actor(A...)>::type
|
||
|
operator()(A &&... a) const
|
||
|
{
|
||
|
typedef
|
||
|
typename vector_chooser<sizeof...(A) + 1>::template apply<
|
||
|
const actor<Expr> *
|
||
|
, typename mpl::if_<is_reference<A>, A, A const &>::type...
|
||
|
>::type
|
||
|
env_type;
|
||
|
|
||
|
env_type env = {this, a...};
|
||
|
return phoenix::eval(*this, phoenix::context(env, default_actions()));
|
||
|
}
|
||
|
#endif
|
||
|
};
|
||
|
}}
|
||
|
|
||
|
namespace boost
|
||
|
{
|
||
|
// specialize boost::result_of to return the proper result type
|
||
|
template <typename Expr>
|
||
|
struct result_of<phoenix::actor<Expr>()>
|
||
|
: phoenix::result_of::actor<typename phoenix::actor<Expr>::proto_base_expr>
|
||
|
{};
|
||
|
|
||
|
template <typename Expr>
|
||
|
struct result_of<phoenix::actor<Expr> const()>
|
||
|
: phoenix::result_of::actor<typename phoenix::actor<Expr>::proto_base_expr>
|
||
|
{};
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef BOOST_MSVC
|
||
|
#pragma warning(pop)
|
||
|
#endif
|
||
|
|
||
|
#endif
|
||
|
|