os/ossrv/ossrv_pub/boost_apis/boost/lambda/closures.hpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/*=============================================================================
sl@0
     2
    Adaptable closures
sl@0
     3
sl@0
     4
    Phoenix V0.9
sl@0
     5
    Copyright (c) 2001-2002 Joel de Guzman
sl@0
     6
sl@0
     7
    Distributed under the Boost Software License, Version 1.0. (See
sl@0
     8
    accompanying file LICENSE_1_0.txt or copy at
sl@0
     9
    http://www.boost.org/LICENSE_1_0.txt)
sl@0
    10
sl@0
    11
    URL: http://spirit.sourceforge.net/
sl@0
    12
sl@0
    13
==============================================================================*/
sl@0
    14
#ifndef PHOENIX_CLOSURES_HPP
sl@0
    15
#define PHOENIX_CLOSURES_HPP
sl@0
    16
sl@0
    17
///////////////////////////////////////////////////////////////////////////////
sl@0
    18
#include "boost/lambda/core.hpp"
sl@0
    19
///////////////////////////////////////////////////////////////////////////////
sl@0
    20
namespace boost {
sl@0
    21
namespace lambda {
sl@0
    22
sl@0
    23
///////////////////////////////////////////////////////////////////////////////
sl@0
    24
//
sl@0
    25
//  Adaptable closures
sl@0
    26
//
sl@0
    27
//      The framework will not be complete without some form of closures
sl@0
    28
//      support. Closures encapsulate a stack frame where local
sl@0
    29
//      variables are created upon entering a function and destructed
sl@0
    30
//      upon exiting. Closures provide an environment for local
sl@0
    31
//      variables to reside. Closures can hold heterogeneous types.
sl@0
    32
//
sl@0
    33
//      Phoenix closures are true hardware stack based closures. At the
sl@0
    34
//      very least, closures enable true reentrancy in lambda functions.
sl@0
    35
//      A closure provides access to a function stack frame where local
sl@0
    36
//      variables reside. Modeled after Pascal nested stack frames,
sl@0
    37
//      closures can be nested just like nested functions where code in
sl@0
    38
//      inner closures may access local variables from in-scope outer
sl@0
    39
//      closures (accessing inner scopes from outer scopes is an error
sl@0
    40
//      and will cause a run-time assertion failure).
sl@0
    41
//
sl@0
    42
//      There are three (3) interacting classes:
sl@0
    43
//
sl@0
    44
//      1) closure:
sl@0
    45
//
sl@0
    46
//      At the point of declaration, a closure does not yet create a
sl@0
    47
//      stack frame nor instantiate any variables. A closure declaration
sl@0
    48
//      declares the types and names[note] of the local variables. The
sl@0
    49
//      closure class is meant to be subclassed. It is the
sl@0
    50
//      responsibility of a closure subclass to supply the names for
sl@0
    51
//      each of the local variable in the closure. Example:
sl@0
    52
//
sl@0
    53
//          struct my_closure : closure<int, string, double> {
sl@0
    54
//
sl@0
    55
//              member1 num;        // names the 1st (int) local variable
sl@0
    56
//              member2 message;    // names the 2nd (string) local variable
sl@0
    57
//              member3 real;       // names the 3rd (double) local variable
sl@0
    58
//          };
sl@0
    59
//
sl@0
    60
//          my_closure clos;
sl@0
    61
//
sl@0
    62
//      Now that we have a closure 'clos', its local variables can be
sl@0
    63
//      accessed lazily using the dot notation. Each qualified local
sl@0
    64
//      variable can be used just like any primitive actor (see
sl@0
    65
//      primitives.hpp). Examples:
sl@0
    66
//
sl@0
    67
//          clos.num = 30
sl@0
    68
//          clos.message = arg1
sl@0
    69
//          clos.real = clos.num * 1e6
sl@0
    70
//
sl@0
    71
//      The examples above are lazily evaluated. As usual, these
sl@0
    72
//      expressions return composite actors that will be evaluated
sl@0
    73
//      through a second function call invocation (see operators.hpp).
sl@0
    74
//      Each of the members (clos.xxx) is an actor. As such, applying
sl@0
    75
//      the operator() will reveal its identity:
sl@0
    76
//
sl@0
    77
//          clos.num() // will return the current value of clos.num
sl@0
    78
//
sl@0
    79
//      *** [note] Acknowledgement: Juan Carlos Arevalo-Baeza (JCAB)
sl@0
    80
//      introduced and initilally implemented the closure member names
sl@0
    81
//      that uses the dot notation.
sl@0
    82
//
sl@0
    83
//      2) closure_member
sl@0
    84
//
sl@0
    85
//      The named local variables of closure 'clos' above are actually
sl@0
    86
//      closure members. The closure_member class is an actor and
sl@0
    87
//      conforms to its conceptual interface. member1..memberN are
sl@0
    88
//      predefined typedefs that correspond to each of the listed types
sl@0
    89
//      in the closure template parameters.
sl@0
    90
//
sl@0
    91
//      3) closure_frame
sl@0
    92
//
sl@0
    93
//      When a closure member is finally evaluated, it should refer to
sl@0
    94
//      an actual instance of the variable in the hardware stack.
sl@0
    95
//      Without doing so, the process is not complete and the evaluated
sl@0
    96
//      member will result to an assertion failure. Remember that the
sl@0
    97
//      closure is just a declaration. The local variables that a
sl@0
    98
//      closure refers to must still be instantiated.
sl@0
    99
//
sl@0
   100
//      The closure_frame class does the actual instantiation of the
sl@0
   101
//      local variables and links these variables with the closure and
sl@0
   102
//      all its members. There can be multiple instances of
sl@0
   103
//      closure_frames typically situated in the stack inside a
sl@0
   104
//      function. Each closure_frame instance initiates a stack frame
sl@0
   105
//      with a new set of closure local variables. Example:
sl@0
   106
//
sl@0
   107
//          void foo()
sl@0
   108
//          {
sl@0
   109
//              closure_frame<my_closure> frame(clos);
sl@0
   110
//              /* do something */
sl@0
   111
//          }
sl@0
   112
//
sl@0
   113
//      where 'clos' is an instance of our closure 'my_closure' above.
sl@0
   114
//      Take note that the usage above precludes locally declared
sl@0
   115
//      classes. If my_closure is a locally declared type, we can still
sl@0
   116
//      use its self_type as a paramater to closure_frame:
sl@0
   117
//
sl@0
   118
//          closure_frame<my_closure::self_type> frame(clos);
sl@0
   119
//
sl@0
   120
//      Upon instantiation, the closure_frame links the local variables
sl@0
   121
//      to the closure. The previous link to another closure_frame
sl@0
   122
//      instance created before is saved. Upon destruction, the
sl@0
   123
//      closure_frame unlinks itself from the closure and relinks the
sl@0
   124
//      preceding closure_frame prior to this instance.
sl@0
   125
//
sl@0
   126
//      The local variables in the closure 'clos' above is default
sl@0
   127
//      constructed in the stack inside function 'foo'. Once 'foo' is
sl@0
   128
//      exited, all of these local variables are destructed. In some
sl@0
   129
//      cases, default construction is not desirable and we need to
sl@0
   130
//      initialize the local closure variables with some values. This
sl@0
   131
//      can be done by passing in the initializers in a compatible
sl@0
   132
//      tuple. A compatible tuple is one with the same number of
sl@0
   133
//      elements as the destination and where each element from the
sl@0
   134
//      destination can be constructed from each corresponding element
sl@0
   135
//      in the source. Example:
sl@0
   136
//
sl@0
   137
//          tuple<int, char const*, int> init(123, "Hello", 1000);
sl@0
   138
//          closure_frame<my_closure> frame(clos, init);
sl@0
   139
//
sl@0
   140
//      Here now, our closure_frame's variables are initialized with
sl@0
   141
//      int: 123, char const*: "Hello" and int: 1000.
sl@0
   142
//
sl@0
   143
///////////////////////////////////////////////////////////////////////////////
sl@0
   144
sl@0
   145
sl@0
   146
sl@0
   147
///////////////////////////////////////////////////////////////////////////////
sl@0
   148
//
sl@0
   149
//  closure_frame class
sl@0
   150
//
sl@0
   151
///////////////////////////////////////////////////////////////////////////////
sl@0
   152
template <typename ClosureT>
sl@0
   153
class closure_frame : public ClosureT::tuple_t {
sl@0
   154
sl@0
   155
public:
sl@0
   156
sl@0
   157
    closure_frame(ClosureT& clos)
sl@0
   158
    : ClosureT::tuple_t(), save(clos.frame), frame(clos.frame)
sl@0
   159
    { clos.frame = this; }
sl@0
   160
sl@0
   161
    template <typename TupleT>
sl@0
   162
    closure_frame(ClosureT& clos, TupleT const& init)
sl@0
   163
    : ClosureT::tuple_t(init), save(clos.frame), frame(clos.frame)
sl@0
   164
    { clos.frame = this; }
sl@0
   165
sl@0
   166
    ~closure_frame()
sl@0
   167
    { frame = save; }
sl@0
   168
sl@0
   169
private:
sl@0
   170
sl@0
   171
    closure_frame(closure_frame const&);            // no copy
sl@0
   172
    closure_frame& operator=(closure_frame const&); // no assign
sl@0
   173
sl@0
   174
    closure_frame* save;
sl@0
   175
    closure_frame*& frame;
sl@0
   176
};
sl@0
   177
sl@0
   178
///////////////////////////////////////////////////////////////////////////////
sl@0
   179
//
sl@0
   180
//  closure_member class
sl@0
   181
//
sl@0
   182
///////////////////////////////////////////////////////////////////////////////
sl@0
   183
template <int N, typename ClosureT>
sl@0
   184
class closure_member {
sl@0
   185
sl@0
   186
public:
sl@0
   187
sl@0
   188
    typedef typename ClosureT::tuple_t tuple_t;
sl@0
   189
sl@0
   190
    closure_member()
sl@0
   191
    : frame(ClosureT::closure_frame_ref()) {}
sl@0
   192
sl@0
   193
    template <typename TupleT>
sl@0
   194
    struct sig {
sl@0
   195
sl@0
   196
        typedef typename detail::tuple_element_as_reference<
sl@0
   197
            N, typename ClosureT::tuple_t
sl@0
   198
        >::type type;
sl@0
   199
    };
sl@0
   200
sl@0
   201
    template <class Ret, class A, class B, class C>
sl@0
   202
    //    typename detail::tuple_element_as_reference
sl@0
   203
    //        <N, typename ClosureT::tuple_t>::type
sl@0
   204
    Ret
sl@0
   205
    call(A&, B&, C&) const
sl@0
   206
    {
sl@0
   207
        assert(frame);
sl@0
   208
        return boost::tuples::get<N>(*frame);
sl@0
   209
    }
sl@0
   210
sl@0
   211
sl@0
   212
private:
sl@0
   213
sl@0
   214
    typename ClosureT::closure_frame_t*& frame;
sl@0
   215
};
sl@0
   216
sl@0
   217
///////////////////////////////////////////////////////////////////////////////
sl@0
   218
//
sl@0
   219
//  closure class
sl@0
   220
//
sl@0
   221
///////////////////////////////////////////////////////////////////////////////
sl@0
   222
template <
sl@0
   223
    typename T0 = null_type,
sl@0
   224
    typename T1 = null_type,
sl@0
   225
    typename T2 = null_type,
sl@0
   226
    typename T3 = null_type,
sl@0
   227
    typename T4 = null_type
sl@0
   228
>
sl@0
   229
class closure {
sl@0
   230
sl@0
   231
public:
sl@0
   232
sl@0
   233
    typedef tuple<T0, T1, T2, T3, T4> tuple_t;
sl@0
   234
    typedef closure<T0, T1, T2, T3, T4> self_t;
sl@0
   235
    typedef closure_frame<self_t> closure_frame_t;
sl@0
   236
sl@0
   237
                            closure()
sl@0
   238
                            : frame(0)      { closure_frame_ref(&frame); }
sl@0
   239
    closure_frame_t&        context()       { assert(frame); return frame; }
sl@0
   240
    closure_frame_t const&  context() const { assert(frame); return frame; }
sl@0
   241
sl@0
   242
    typedef lambda_functor<closure_member<0, self_t> > member1;
sl@0
   243
    typedef lambda_functor<closure_member<1, self_t> > member2;
sl@0
   244
    typedef lambda_functor<closure_member<2, self_t> > member3;
sl@0
   245
    typedef lambda_functor<closure_member<3, self_t> > member4;
sl@0
   246
    typedef lambda_functor<closure_member<4, self_t> > member5;
sl@0
   247
sl@0
   248
private:
sl@0
   249
sl@0
   250
    closure(closure const&);            // no copy
sl@0
   251
    closure& operator=(closure const&); // no assign
sl@0
   252
sl@0
   253
    template <int N, typename ClosureT>
sl@0
   254
    friend struct closure_member;
sl@0
   255
sl@0
   256
    template <typename ClosureT>
sl@0
   257
    friend class closure_frame;
sl@0
   258
sl@0
   259
    static closure_frame_t*&
sl@0
   260
    closure_frame_ref(closure_frame_t** frame_ = 0)
sl@0
   261
    {
sl@0
   262
        static closure_frame_t** frame = 0;
sl@0
   263
        if (frame_ != 0)
sl@0
   264
            frame = frame_;
sl@0
   265
        return *frame;
sl@0
   266
    }
sl@0
   267
sl@0
   268
    closure_frame_t* frame;
sl@0
   269
};
sl@0
   270
sl@0
   271
}}
sl@0
   272
   //  namespace 
sl@0
   273
sl@0
   274
#endif