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