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