Chris@16: /*============================================================================= Chris@16: Phoenix V1.2.1 Chris@16: Copyright (c) 2001-2002 Joel de Guzman Chris@16: Chris@16: Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@16: file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: ==============================================================================*/ Chris@16: #ifndef PHOENIX_PRIMITIVES_HPP Chris@16: #define PHOENIX_PRIMITIVES_HPP Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: #include Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: namespace phoenix { Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // argument class Chris@16: // Chris@16: // Lazy arguments Chris@16: // Chris@16: // An actor base class that extracts and returns the Nth argument Chris@16: // from the argument list passed in the 'args' tuple in the eval Chris@16: // member function (see actor.hpp). There are some predefined Chris@16: // argument constants that can be used as actors (arg1..argN). Chris@16: // Chris@16: // The argument actor is a place-holder for the actual arguments Chris@16: // passed by the client. For example, wherever arg1 is seen placed Chris@16: // in a lazy function (see functions.hpp) or lazy operator (see Chris@16: // operators.hpp), this will be replaced by the actual first Chris@16: // argument in the actual function evaluation. Argument actors are Chris@16: // essentially lazy arguments. A lazy argument is a full actor in Chris@16: // its own right and can be evaluated through the actor's operator(). Chris@16: // Chris@16: // Example: Chris@16: // Chris@16: // char c = 'A'; Chris@16: // int i = 123; Chris@16: // const char* s = "Hello World"; Chris@16: // Chris@16: // cout << arg1(c) << ' '; Chris@16: // cout << arg1(i, s) << ' '; Chris@16: // cout << arg2(i, s) << ' '; Chris@16: // Chris@16: // will print out "A 123 Hello World" Chris@16: // Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct argument { Chris@16: Chris@16: template Chris@16: struct result { typedef typename tuple_element::type type; }; Chris@16: Chris@16: template Chris@16: typename tuple_element::type Chris@16: eval(TupleT const& args) const Chris@16: { Chris@16: return args[tuple_index()]; Chris@16: } Chris@16: }; Chris@16: Chris@16: ////////////////////////////////// Chris@16: actor > const arg1 = argument<0>(); Chris@16: actor > const arg2 = argument<1>(); Chris@16: actor > const arg3 = argument<2>(); Chris@16: Chris@16: #if PHOENIX_LIMIT > 3 Chris@16: actor > const arg4 = argument<3>(); Chris@16: actor > const arg5 = argument<4>(); Chris@16: actor > const arg6 = argument<5>(); Chris@16: Chris@16: #if PHOENIX_LIMIT > 6 Chris@16: actor > const arg7 = argument<6>(); Chris@16: actor > const arg8 = argument<7>(); Chris@16: actor > const arg9 = argument<8>(); Chris@16: Chris@16: #if PHOENIX_LIMIT > 9 Chris@16: actor > const arg10 = argument<9>(); Chris@16: actor > const arg11 = argument<10>(); Chris@16: actor > const arg12 = argument<11>(); Chris@16: Chris@16: #if PHOENIX_LIMIT > 12 Chris@16: actor > const arg13 = argument<12>(); Chris@16: actor > const arg14 = argument<13>(); Chris@16: actor > const arg15 = argument<14>(); Chris@16: Chris@16: #endif Chris@16: #endif Chris@16: #endif Chris@16: #endif Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // value class Chris@16: // Chris@16: // Lazy values Chris@16: // Chris@16: // A bound actual parameter is kept in a value class for deferred Chris@16: // access later when needed. A value object is immutable. Value Chris@16: // objects are typically created through the val(x) free function Chris@16: // which returns a value with T deduced from the type of x. x is Chris@16: // held in the value object by value. Chris@16: // Chris@16: // Lazy values are actors. As such, lazy values can be evaluated Chris@16: // through the actor's operator(). Such invocation gives the value's Chris@16: // identity. Example: Chris@16: // Chris@16: // cout << val(3)() << val("Hello World")(); Chris@16: // Chris@16: // prints out "3 Hello World" Chris@16: // Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct value { Chris@16: Chris@16: typedef typename boost::remove_reference::type plain_t; Chris@16: Chris@16: template Chris@16: struct result { typedef plain_t const type; }; Chris@16: Chris@16: value(plain_t val_) Chris@16: : val(val_) {} Chris@16: Chris@16: template Chris@16: plain_t const Chris@16: eval(TupleT const& /*args*/) const Chris@16: { Chris@16: return val; Chris@16: } Chris@16: Chris@16: plain_t val; Chris@16: }; Chris@16: Chris@16: ////////////////////////////////// Chris@16: template Chris@16: inline actor > const Chris@16: val(T v) Chris@16: { Chris@16: return value(v); Chris@16: } Chris@16: Chris@16: ////////////////////////////////// Chris@16: template Chris@16: void Chris@16: val(actor const& v); // This is undefined and not allowed. Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // Arbitrary types T are typically converted to a actor > Chris@16: // (see as_actor in actor.hpp). A specialization is also provided Chris@16: // for arrays. T[N] arrays are converted to actor >. Chris@16: // Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct as_actor { Chris@16: Chris@16: typedef actor > type; Chris@16: static type convert(T const& x) Chris@16: { return value(x); } Chris@16: }; Chris@16: Chris@16: ////////////////////////////////// Chris@16: template Chris@16: struct as_actor { Chris@16: Chris@16: typedef actor > type; Chris@16: static type convert(T const x[N]) Chris@16: { return value(x); } Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: // Chris@16: // variable class Chris@16: // Chris@16: // Lazy variables Chris@16: // Chris@16: // A bound actual parameter may also be held by non-const reference Chris@16: // in a variable class for deferred access later when needed. A Chris@16: // variable object is mutable, i.e. its referenced variable can be Chris@16: // modified. Variable objects are typically created through the Chris@16: // var(x) free function which returns a variable with T deduced Chris@16: // from the type of x. x is held in the value object by Chris@16: // reference. Chris@16: // Chris@16: // Lazy variables are actors. As such, lazy variables can be Chris@16: // evaluated through the actor's operator(). Such invocation gives Chris@16: // the variables's identity. Example: Chris@16: // Chris@16: // int i = 3; Chris@16: // char const* s = "Hello World"; Chris@16: // cout << var(i)() << var(s)(); Chris@16: // Chris@16: // prints out "3 Hello World" Chris@16: // Chris@16: // Another free function const_(x) may also be used. const_(x) creates Chris@16: // a variable object using a constant reference. Chris@16: // Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) Chris@16: #pragma warning(push) Chris@16: #pragma warning(disable:4512) //assignment operator could not be generated Chris@16: #endif Chris@16: Chris@16: template Chris@16: struct variable { Chris@16: Chris@16: template Chris@16: struct result { typedef T& type; }; Chris@16: Chris@16: variable(T& var_) Chris@16: : var(var_) {} Chris@16: Chris@16: template Chris@16: T& Chris@16: eval(TupleT const& /*args*/) const Chris@16: { Chris@16: return var; Chris@16: } Chris@16: Chris@16: T& var; Chris@16: }; Chris@16: Chris@16: #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400) Chris@16: #pragma warning(pop) Chris@16: #endif Chris@16: Chris@16: ////////////////////////////////// Chris@16: template Chris@16: inline actor > const Chris@16: var(T& v) Chris@16: { Chris@16: return variable(v); Chris@16: } Chris@16: Chris@16: ////////////////////////////////// Chris@16: template Chris@16: inline actor > const Chris@16: const_(T const& v) Chris@16: { Chris@16: return variable(v); Chris@16: } Chris@16: Chris@16: ////////////////////////////////// Chris@16: template Chris@16: void Chris@16: var(actor const& v); // This is undefined and not allowed. Chris@16: Chris@16: ////////////////////////////////// Chris@16: template Chris@16: void Chris@16: const_(actor const& v); // This is undefined and not allowed. Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: } // namespace phoenix Chris@16: Chris@16: #endif