annotate DEPENDENCIES/generic/include/boost/proto/transform/when.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 ///////////////////////////////////////////////////////////////////////////////
Chris@16 2 /// \file when.hpp
Chris@16 3 /// Definition of when transform.
Chris@16 4 //
Chris@16 5 // Copyright 2008 Eric Niebler. Distributed under the Boost
Chris@16 6 // Software License, Version 1.0. (See accompanying file
Chris@16 7 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@16 8
Chris@16 9 #ifndef BOOST_PROTO_TRANSFORM_WHEN_HPP_EAN_10_29_2007
Chris@16 10 #define BOOST_PROTO_TRANSFORM_WHEN_HPP_EAN_10_29_2007
Chris@16 11
Chris@16 12 #include <boost/preprocessor/cat.hpp>
Chris@16 13 #include <boost/preprocessor/repetition/enum_params.hpp>
Chris@16 14 #include <boost/preprocessor/repetition/enum_trailing_params.hpp>
Chris@16 15 #include <boost/preprocessor/iteration/iterate.hpp>
Chris@16 16 #include <boost/mpl/at.hpp>
Chris@16 17 #include <boost/mpl/if.hpp>
Chris@16 18 #include <boost/mpl/map.hpp>
Chris@16 19 #include <boost/mpl/eval_if.hpp>
Chris@16 20 #include <boost/proto/proto_fwd.hpp>
Chris@16 21 #include <boost/proto/traits.hpp>
Chris@16 22 #include <boost/proto/transform/call.hpp>
Chris@16 23 #include <boost/proto/transform/make.hpp>
Chris@16 24 #include <boost/proto/transform/impl.hpp>
Chris@16 25 #include <boost/proto/transform/env.hpp>
Chris@16 26
Chris@101 27 #if defined(_MSC_VER)
Chris@16 28 # pragma warning(push)
Chris@16 29 # pragma warning(disable : 4714) // function 'xxx' marked as __forceinline not inlined
Chris@16 30 #endif
Chris@16 31
Chris@16 32 namespace boost { namespace proto
Chris@16 33 {
Chris@16 34 namespace detail
Chris@16 35 {
Chris@16 36 template<typename Grammar, typename R, typename Fun>
Chris@16 37 struct when_impl
Chris@16 38 : transform<when<Grammar, Fun> >
Chris@16 39 {
Chris@16 40 typedef Grammar first;
Chris@16 41 typedef Fun second;
Chris@16 42 typedef typename Grammar::proto_grammar proto_grammar;
Chris@16 43
Chris@16 44 // Note: do not evaluate is_callable<R> in this scope.
Chris@16 45 // R may be an incomplete type at this point.
Chris@16 46
Chris@16 47 template<typename Expr, typename State, typename Data>
Chris@16 48 struct impl : transform_impl<Expr, State, Data>
Chris@16 49 {
Chris@16 50 // OK to evaluate is_callable<R> here. R should be compete by now.
Chris@16 51 typedef
Chris@16 52 typename mpl::if_c<
Chris@16 53 is_callable<R>::value
Chris@16 54 , proto::call<Fun> // "R" is a function to call
Chris@16 55 , proto::make<Fun> // "R" is an object to construct
Chris@16 56 >::type
Chris@16 57 which;
Chris@16 58
Chris@16 59 typedef typename which::template impl<Expr, State, Data>::result_type result_type;
Chris@16 60
Chris@16 61 /// Evaluate <tt>R(A0,A1,...)</tt> as a transform either with
Chris@16 62 /// <tt>call\<\></tt> or with <tt>make\<\></tt> depending on
Chris@16 63 /// whether <tt>is_callable\<R\>::value</tt> is \c true or
Chris@16 64 /// \c false.
Chris@16 65 ///
Chris@16 66 /// \param e The current expression
Chris@16 67 /// \param s The current state
Chris@16 68 /// \param d An arbitrary data
Chris@16 69 /// \pre <tt>matches\<Expr, Grammar\>::value</tt> is \c true
Chris@16 70 /// \return <tt>which()(e, s, d)</tt>
Chris@16 71 BOOST_FORCEINLINE
Chris@16 72 result_type operator ()(
Chris@16 73 typename impl::expr_param e
Chris@16 74 , typename impl::state_param s
Chris@16 75 , typename impl::data_param d
Chris@16 76 ) const
Chris@16 77 {
Chris@16 78 return typename which::template impl<Expr, State, Data>()(e, s, d);
Chris@16 79 }
Chris@16 80 };
Chris@16 81 };
Chris@16 82 }
Chris@16 83
Chris@16 84 /// \brief A grammar element and a PrimitiveTransform that associates
Chris@16 85 /// a transform with the grammar.
Chris@16 86 ///
Chris@16 87 /// Use <tt>when\<\></tt> to override a grammar's default transform
Chris@16 88 /// with a custom transform. It is for used when composing larger
Chris@16 89 /// transforms by associating smaller transforms with individual
Chris@16 90 /// rules in your grammar, as in the following transform which
Chris@16 91 /// counts the number of terminals in an expression.
Chris@16 92 ///
Chris@16 93 /// \code
Chris@16 94 /// // Count the terminals in an expression tree.
Chris@16 95 /// // Must be invoked with initial state == mpl::int_<0>().
Chris@16 96 /// struct CountLeaves
Chris@16 97 /// : or_<
Chris@16 98 /// when<terminal<_>, mpl::next<_state>()>
Chris@16 99 /// , otherwise<fold<_, _state, CountLeaves> >
Chris@16 100 /// >
Chris@16 101 /// {};
Chris@16 102 /// \endcode
Chris@16 103 ///
Chris@16 104 /// In <tt>when\<G, T\></tt>, when \c T is a class type it is a
Chris@16 105 /// PrimitiveTransform and the following equivalencies hold:
Chris@16 106 ///
Chris@16 107 /// <tt>boost::result_of\<when\<G,T\>(E,S,V)\>::type</tt> is the same as
Chris@16 108 /// <tt>boost::result_of\<T(E,S,V)\>::type</tt>.
Chris@16 109 ///
Chris@16 110 /// <tt>when\<G,T\>()(e,s,d)</tt> is the same as
Chris@16 111 /// <tt>T()(e,s,d)</tt>.
Chris@16 112 template<typename Grammar, typename PrimitiveTransform /*= Grammar*/>
Chris@16 113 struct when
Chris@16 114 : PrimitiveTransform
Chris@16 115 {
Chris@16 116 typedef Grammar first;
Chris@16 117 typedef PrimitiveTransform second;
Chris@16 118 typedef typename Grammar::proto_grammar proto_grammar;
Chris@16 119 };
Chris@16 120
Chris@16 121 /// \brief A specialization that treats function pointer Transforms as
Chris@16 122 /// if they were function type Transforms.
Chris@16 123 ///
Chris@16 124 /// This specialization requires that \c Fun is actually a function type.
Chris@16 125 ///
Chris@16 126 /// This specialization is required for nested transforms such as
Chris@16 127 /// <tt>when\<G, T0(T1(_))\></tt>. In C++, functions that are used as
Chris@16 128 /// parameters to other functions automatically decay to funtion
Chris@16 129 /// pointer types. In other words, the type <tt>T0(T1(_))</tt> is
Chris@16 130 /// indistinguishable from <tt>T0(T1(*)(_))</tt>. This specialization
Chris@16 131 /// is required to handle these nested function pointer type transforms
Chris@16 132 /// properly.
Chris@16 133 template<typename Grammar, typename Fun>
Chris@16 134 struct when<Grammar, Fun *>
Chris@16 135 : when<Grammar, Fun>
Chris@16 136 {};
Chris@16 137
Chris@16 138 /// \brief Syntactic sugar for <tt>when\<_, Fun\></tt>, for use
Chris@16 139 /// in grammars to handle all the cases not yet handled.
Chris@16 140 ///
Chris@16 141 /// Use <tt>otherwise\<T\></tt> in your grammars as a synonym for
Chris@16 142 /// <tt>when\<_, T\></tt> as in the following transform which
Chris@16 143 /// counts the number of terminals in an expression.
Chris@16 144 ///
Chris@16 145 /// \code
Chris@16 146 /// // Count the terminals in an expression tree.
Chris@16 147 /// // Must be invoked with initial state == mpl::int_<0>().
Chris@16 148 /// struct CountLeaves
Chris@16 149 /// : or_<
Chris@16 150 /// when<terminal<_>, mpl::next<_state>()>
Chris@16 151 /// , otherwise<fold<_, _state, CountLeaves> >
Chris@16 152 /// >
Chris@16 153 /// {};
Chris@16 154 /// \endcode
Chris@16 155 template<typename Fun>
Chris@16 156 struct otherwise
Chris@16 157 : when<_, Fun>
Chris@16 158 {};
Chris@16 159
Chris@16 160 namespace envns_
Chris@16 161 {
Chris@16 162 // Define the transforms global
Chris@16 163 BOOST_PROTO_DEFINE_ENV_VAR(transforms_type, transforms);
Chris@16 164 }
Chris@16 165
Chris@16 166 using envns_::transforms;
Chris@16 167
Chris@16 168 /// \brief This specialization uses the Data parameter as a collection
Chris@16 169 /// of transforms that can be indexed by the specified rule.
Chris@16 170 ///
Chris@16 171 /// Use <tt>when\<T, external_transform\></tt> in your code when you would like
Chris@16 172 /// to define a grammar once and use it to evaluate expressions with
Chris@16 173 /// many different sets of transforms. The transforms are found by
Chris@16 174 /// using the Data parameter as a map from rules to transforms.
Chris@16 175 ///
Chris@16 176 /// See \c action_map for an example.
Chris@16 177 template<typename Grammar>
Chris@16 178 struct when<Grammar, external_transform>
Chris@16 179 : proto::transform<when<Grammar, external_transform> >
Chris@16 180 {
Chris@16 181 typedef Grammar first;
Chris@16 182 typedef external_transform second;
Chris@16 183 typedef typename Grammar::proto_grammar proto_grammar;
Chris@16 184
Chris@16 185 template<typename Expr, typename State, typename Data>
Chris@16 186 struct impl
Chris@16 187 : remove_reference<
Chris@16 188 typename mpl::eval_if_c<
Chris@16 189 proto::result_of::has_env_var<Data, transforms_type>::value
Chris@16 190 , proto::result_of::env_var<Data, transforms_type>
Chris@16 191 , proto::result_of::env_var<Data, data_type>
Chris@16 192 >::type
Chris@16 193 >::type::template when<Grammar>::template impl<Expr, State, Data>
Chris@16 194 {};
Chris@16 195 };
Chris@16 196
Chris@16 197 /// \brief For defining a map of Rule/Transform pairs for use with
Chris@16 198 /// <tt>when\<T, external_transform\></tt> to make transforms external to the grammar
Chris@16 199 ///
Chris@16 200 /// The following code defines a grammar with a couple of external transforms.
Chris@16 201 /// It also defines an action_map that maps from rules to transforms. It then
Chris@16 202 /// passes that transforms map at the Data parameter to the grammar. In this way,
Chris@16 203 /// the behavior of the grammar can be modified post-hoc by passing a different
Chris@16 204 /// action_map.
Chris@16 205 ///
Chris@16 206 /// \code
Chris@16 207 /// struct int_terminal
Chris@16 208 /// : proto::terminal<int>
Chris@16 209 /// {};
Chris@16 210 ///
Chris@16 211 /// struct char_terminal
Chris@16 212 /// : proto::terminal<char>
Chris@16 213 /// {};
Chris@16 214 ///
Chris@16 215 /// struct my_grammar
Chris@16 216 /// : proto::or_<
Chris@16 217 /// proto::when< int_terminal, proto::external_transform >
Chris@16 218 /// , proto::when< char_terminal, proto::external_transform >
Chris@16 219 /// , proto::when<
Chris@16 220 /// proto::plus< my_grammar, my_grammar >
Chris@16 221 /// , proto::fold< _, int(), my_grammar >
Chris@16 222 /// >
Chris@16 223 /// >
Chris@16 224 /// {};
Chris@16 225 ///
Chris@16 226 /// struct my_transforms
Chris@16 227 /// : proto::external_transforms<
Chris@16 228 /// proto::when<int_terminal, print(proto::_value)>
Chris@16 229 /// , proto::when<char_terminal, print(proto::_value)>
Chris@16 230 /// >
Chris@16 231 /// {};
Chris@16 232 ///
Chris@16 233 /// proto::literal<int> i(1);
Chris@16 234 /// proto::literal<char> c('a');
Chris@16 235 /// my_transforms trx;
Chris@16 236 ///
Chris@16 237 /// // Evaluate "i+c" using my_grammar with the specified transforms:
Chris@16 238 /// my_grammar()(i + c, 0, trx);
Chris@16 239 /// \endcode
Chris@16 240 template<BOOST_PP_ENUM_PARAMS_WITH_A_DEFAULT(BOOST_MPL_LIMIT_MAP_SIZE, typename T, mpl::na)>
Chris@16 241 struct external_transforms
Chris@16 242 {
Chris@16 243 typedef mpl::map<BOOST_PP_ENUM_PARAMS(BOOST_MPL_LIMIT_MAP_SIZE, T)> map_type;
Chris@16 244
Chris@16 245 template<typename Rule>
Chris@16 246 struct when
Chris@16 247 : proto::when<_, typename mpl::at<map_type, Rule>::type>
Chris@16 248 {};
Chris@16 249 };
Chris@16 250
Chris@16 251 // Other specializations of proto::when are generated by the preprocessor...
Chris@16 252 #include <boost/proto/transform/detail/when.hpp>
Chris@16 253
Chris@16 254 /// INTERNAL ONLY
Chris@16 255 ///
Chris@16 256 template<typename Grammar, typename Transform>
Chris@16 257 struct is_callable<when<Grammar, Transform> >
Chris@16 258 : mpl::true_
Chris@16 259 {};
Chris@16 260
Chris@16 261 }} // namespace boost::proto
Chris@16 262
Chris@101 263 #if defined(_MSC_VER)
Chris@16 264 # pragma warning(pop)
Chris@16 265 #endif
Chris@16 266
Chris@16 267 #endif