closures.hpp 9.6 KB

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