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