]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | //////////////////////////////////////////////////////////////////////////// |
2 | // lazy prelude.hpp | |
3 | // | |
4 | // Build lazy operations for Phoenix equivalents for FC++ | |
5 | // | |
6 | // These are equivalents of the Boost FC++ functoids in prelude.hpp | |
7 | // | |
8 | // Usage: All of these are functors which need various numbers of arguments. | |
9 | // Those can be supplied as real arguments or as Phoenix arguments. | |
10 | // Execution will happen when all the arguments are supplied. | |
11 | // e.g. | |
12 | // take(2,list)() or take(2,arg1)(list) | |
13 | // | |
14 | // Implemented so far: | |
15 | // | |
16 | // id (moved back to operators.hpp) | |
17 | // | |
18 | // A lot of what comes here uses the list type, so that will be needed first. | |
19 | // | |
20 | // Now that list<T> is available I can start to build things here. | |
21 | // | |
22 | // | |
23 | // until(pred,f,start) - if pred(start) is true, return start | |
24 | // apply value = f(start) | |
25 | // apply value = f(value) | |
26 | // until pred(value) is true | |
27 | // return value | |
28 | // | |
29 | // The predicate argument pred must be a lazy function taking one argument | |
30 | // and returning bool. | |
31 | // This can be a lazy function with an argument already. | |
32 | // This has to be declared before the call to until. | |
33 | // The type can be declated using Predicate as in this example: | |
34 | // | |
35 | // Predicate<int>::type f(greater(arg1,10)); | |
36 | // std::cout << until(f, inc, 1)() << std::endl; | |
37 | // | |
38 | // until2(pred,f,start,value2) - if pred(start,value2) is true, return start | |
39 | // apply value1 = f(start) | |
40 | // apply value1 = f(value1) | |
41 | // until pred(value1,value2) is true | |
42 | // return value1 | |
43 | // | |
44 | // NOTE: until2 has been defined because this code does not support | |
45 | // FC++ currying, so that a partial function cannot be passed | |
46 | // as an argument. This provides a way of passing a second parameter. | |
47 | // There is now the option to use Predicate<T> as shown above. | |
48 | // | |
49 | // odd(n) true if n is odd | |
50 | // even(n) true if n is even | |
51 | // | |
52 | // last(list) | |
53 | // all_but_last(list) | |
54 | // at(list,n) | |
55 | // length(list) | |
56 | // filter(pred,list) | |
57 | // iterate(function,value) | |
58 | // repeat(value) | |
59 | // take(n,list) | |
60 | // drop(n,list) | |
61 | // enum_from(x) | |
62 | // enum_from_to(x,y) | |
63 | // | |
64 | //////////////////////////////////////////////////////////////////////////// | |
65 | // Interdependence: | |
66 | // The old Boost FC++ has a set of headers which interelate and call each | |
67 | // other in a complicated way. I am going to document the interdependence | |
68 | // of the files here. I will then make sure that they are called correctly | |
69 | // starting from this file. John Fletcher. February 2015. | |
70 | //////////////////////////////////////////////////////////////////////////// | |
71 | // BoostFC++ header sequence: | |
72 | // | |
73 | // prelude.hpp -> list.hpp (optinally monad.hpp at end) | |
74 | // list.hpp -> reuse.hpp | |
75 | // reuse.hpp -> function.hpp | |
76 | // function.hpp -> ref_count.hpp operator.hpp | |
77 | // ref_count.hpp -> config.hpp boost headers and RefCountType definition | |
78 | // operator.hpp -> lambda.hpp | |
79 | // lambda.hpp -> full.hpp (use of lambda internals is optional) | |
80 | // full.hpp -> smart.hpp curry.hpp pre_lambda.hpp (optionally full4.hpp) | |
81 | // smart.hpp -> signature.hpp | |
82 | // curry.hpp -> signature.hpp | |
83 | // signature.hpp -> config.hpp | |
84 | // | |
85 | //////////////////////////////////////////////////////////////////////////// | |
86 | // Proposed order in lazy_prelude.hpp | |
87 | // on the basis that files need what they call. | |
88 | // | |
89 | // lazy_config.hpp (If needed)* probably not needed. | |
90 | // lazy_signature.hpp (If needed)* | |
91 | // lazy_smart.hpp (If needed)* | |
92 | // lazy_curry.hpp (If needed)* | |
93 | // lazy_full.hpp (If needed)* | |
94 | // lazy_operator.hpp (absorb definition of RefCountType) | |
95 | // lazy_function.hpp (may not now be needed) | |
96 | // lazy_reuse.hpp (implemented without use of FC++ functions) | |
97 | // lazy_list.hpp | |
98 | // | |
99 | // * file does not yet exist. | |
100 | //////////////////////////////////////////////////////////////////////////// | |
101 | // This is implemented such that no other lazy_ file calls other lazy_ files. | |
102 | // They do call their own external files, which may well be duplicates. | |
103 | // That can be sorted out later. | |
104 | //////////////////////////////////////////////////////////////////////////// | |
105 | // Notes: full and curry operations should be covered by Phoenix. | |
106 | // The lambda operations are quite different from Phoenix lambda | |
107 | // and will be omitted. | |
108 | // The implementation monad can be postponed. | |
109 | // Some of function and reuse are needed for the list type. | |
110 | // I will review later whether they are part of the external interface. | |
111 | // | |
112 | // John Fletcher February 2015. | |
113 | //////////////////////////////////////////////////////////////////////////// | |
114 | /*============================================================================= | |
115 | Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis | |
116 | Copyright (c) 2001-2007 Joel de Guzman | |
117 | Copyright (c) 2015 John Fletcher | |
118 | ||
119 | Distributed under the Boost Software License, Version 1.0. (See accompanying | |
120 | file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
121 | ==============================================================================*/ | |
122 | ||
123 | ||
124 | #ifndef BOOST_PHOENIX_FUNCTION_LAZY_PRELUDE | |
125 | #define BOOST_PHOENIX_FUNCTION_LAZY_PRELUDE | |
126 | ||
127 | #include <exception> | |
128 | #include <vector> | |
129 | #include <boost/phoenix/core.hpp> | |
130 | #include <boost/phoenix/function.hpp> | |
131 | #include <boost/phoenix/scope.hpp> | |
132 | #include <boost/phoenix/operator.hpp> | |
133 | #include <boost/phoenix/function/lazy_operator.hpp> | |
134 | #include <boost/phoenix/function/lazy_reuse.hpp> | |
135 | #include <boost/phoenix/function/lazy_list.hpp> | |
136 | ||
137 | //////////////////////////////////////////////////////////////////////////// | |
138 | // To come here, the Haskell Prelude things which need list<T>. | |
139 | // Things which do not need list<T> are in lazy_operator.hpp. | |
140 | //////////////////////////////////////////////////////////////////////////// | |
141 | ||
142 | namespace boost { | |
143 | ||
144 | namespace phoenix { | |
145 | ||
146 | // These are in fcpp namespace as they introduce an FC++ style. | |
147 | namespace fcpp { | |
148 | ||
149 | template <typename T> | |
150 | struct Predicate { | |
151 | typedef typename boost::function1<bool,T> fun1_bool_T; | |
152 | typedef typename boost::phoenix::function<fun1_bool_T> bool_F_T; | |
153 | typedef bool_F_T type; | |
154 | }; | |
155 | ||
156 | template <typename R> | |
157 | struct Function0 { | |
158 | typedef typename boost::function0<R> fun0_R; | |
159 | typedef typename boost::phoenix::function<fun0_R> R_F; | |
160 | typedef R_F type; | |
161 | }; | |
162 | ||
163 | template <typename R,typename A0> | |
164 | struct Function1 { | |
165 | typedef typename boost::function1<R,A0> fun1_R_A0; | |
166 | typedef typename boost::phoenix::function<fun1_R_A0> R_F_A0; | |
167 | typedef R_F_A0 type; | |
168 | }; | |
169 | ||
170 | template <typename R, typename A0, typename A1> | |
171 | struct Function2 { | |
172 | typedef typename boost::function2<R,A0,A1> fun2_R_A0_A1; | |
173 | typedef typename boost::phoenix::function<fun2_R_A0_A1> R_F_A0_A1; | |
174 | typedef R_F_A0_A1 type; | |
175 | }; | |
176 | ||
177 | } | |
178 | ||
179 | namespace impl { | |
180 | using fcpp::INV; | |
181 | using fcpp::VAR; | |
182 | using fcpp::reuser1; | |
183 | using fcpp::reuser2; | |
184 | using fcpp::reuser3; | |
185 | using boost::phoenix::arg_names::arg1; | |
186 | ||
187 | struct Pow { | |
188 | ||
189 | template <typename Sig> | |
190 | struct result; | |
191 | ||
192 | template <typename This, typename N, typename A0> | |
193 | struct result<This(N,A0)> | |
194 | : boost::remove_reference<A0> | |
195 | {}; | |
196 | ||
197 | template <typename N, typename A0> | |
198 | A0 operator()(N n, const A0 & a0, | |
199 | reuser2<INV,VAR,INV,Pow,N,A0> r = NIL ) const { | |
200 | if ( n <= 0 ) | |
201 | return A0(1); | |
202 | else if ( n==1 ) | |
203 | return a0; | |
204 | else { | |
205 | A0 a1 = r( Pow(), n-1, a0)(); | |
206 | return a0*a1; | |
207 | } | |
208 | } | |
209 | ||
210 | }; | |
211 | ||
212 | struct Apply { | |
213 | ||
214 | template <typename Sig> | |
215 | struct result; | |
216 | ||
217 | template <typename This, typename N, typename F,typename A0> | |
218 | struct result<This(N,F,A0)> | |
219 | : boost::remove_reference<A0> | |
220 | {}; | |
221 | ||
222 | template <typename N, typename F, typename A0> | |
223 | A0 operator()(N n, const F &f, const A0 & a0, | |
224 | reuser3<INV,VAR,INV,INV,Apply,N,F,A0> r = NIL ) const { | |
225 | if ( n <= 0 ) | |
226 | return a0; | |
227 | else if ( n==1 ) | |
228 | return f(arg1)(a0); | |
229 | else { | |
230 | A0 a1 = r( Apply(), n-1, f, a0)(); | |
231 | return f(a1)(); | |
232 | } | |
233 | } | |
234 | ||
235 | }; | |
236 | ||
237 | struct Odd { | |
238 | template <typename Sig> | |
239 | struct result; | |
240 | ||
241 | template <typename This, typename T> | |
242 | struct result<This(T)> | |
243 | { | |
244 | typedef bool type; | |
245 | }; | |
246 | ||
247 | template <class T> | |
248 | typename result<Odd(T)>::type operator()( const T& x ) const { | |
249 | return x%2==1; | |
250 | } | |
251 | }; | |
252 | ||
253 | struct Even { | |
254 | template <typename Sig> | |
255 | struct result; | |
256 | ||
257 | template <typename This, typename T> | |
258 | struct result<This(T)> | |
259 | { | |
260 | typedef bool type; | |
261 | }; | |
262 | ||
263 | template <class T> | |
264 | typename result<Even(T)>::type operator()( const T& x ) const { | |
265 | return x%2==0; | |
266 | } | |
267 | }; | |
268 | ||
269 | } | |
270 | typedef boost::phoenix::function<impl::Pow> Pow; | |
271 | typedef boost::phoenix::function<impl::Apply> Apply; | |
272 | typedef boost::phoenix::function<impl::Odd> Odd; | |
273 | typedef boost::phoenix::function<impl::Even> Even; | |
274 | Pow pow; | |
275 | Apply apply; | |
276 | Odd odd; | |
277 | Even even; | |
278 | ||
279 | namespace impl { | |
280 | using fcpp::INV; | |
281 | using fcpp::VAR; | |
282 | using fcpp::reuser1; | |
283 | using fcpp::reuser2; | |
284 | using fcpp::reuser3; | |
285 | using boost::phoenix::arg_names::arg1; | |
286 | ||
287 | // I cannot yet do currying to pass e.g. greater(9,arg1) | |
288 | // as a function. This can be done using Predicate<T>::type. | |
289 | struct Until { | |
290 | ||
291 | template <typename Sig> struct result; | |
292 | ||
293 | template <typename This, typename Pred, typename Unary, typename T> | |
294 | struct result<This(Pred,Unary,T)> | |
295 | : boost::remove_reference<T> {}; | |
296 | ||
297 | template <class Pred, class Unary, class T> | |
298 | T operator()( const Pred& p,const Unary& op,const T &start) const | |
299 | { | |
300 | T tmp = start; | |
301 | while( !p(tmp)() ) { | |
302 | tmp = apply(1,op,tmp)(); | |
303 | } | |
304 | return tmp; | |
305 | } | |
306 | ||
307 | }; | |
308 | ||
309 | struct Until2 { | |
310 | ||
311 | template <typename Sig> struct result; | |
312 | ||
313 | template <typename This, typename Binary, typename Unary, | |
314 | typename T, typename X> | |
315 | struct result<This(Binary,Unary,T,X)> | |
316 | : boost::remove_reference<T> {}; | |
317 | ||
318 | template <class Binary, class Unary, class T, class X> | |
319 | typename result<Until2(Binary,Unary,T,X)>::type | |
320 | operator()( const Binary& p, const Unary& op, const T & start, | |
321 | const X & check ) const | |
322 | { | |
323 | T tmp1 = start; | |
324 | T tmp2; | |
325 | while( !p(tmp1,check)() ) { | |
326 | tmp2 = apply(1,op,tmp1)(); | |
327 | tmp1 = tmp2; | |
328 | ||
329 | } | |
330 | return tmp1; | |
331 | } | |
332 | }; | |
333 | ||
334 | struct Last { | |
335 | template <typename Sig> struct result; | |
336 | ||
337 | template <typename This, typename L> | |
338 | struct result<This(L)> | |
339 | { | |
340 | typedef typename result_of::ListType<L>::value_type type; | |
341 | }; | |
342 | ||
343 | template <class L> | |
344 | typename result<Last(L)>::type | |
345 | operator()( const L& ll ) const { | |
346 | size_t x = 0; | |
347 | typename result_of::ListType<L>::delay_result_type l = delay(ll); | |
348 | while( !null( tail(l)() )() ) { | |
349 | l = tail(l)(); | |
350 | ++x; | |
351 | #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS | |
352 | if (x > BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH) | |
353 | break; | |
354 | #endif | |
355 | } | |
356 | #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS | |
357 | if (x > BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH) | |
358 | throw lazy_exception("Your list is too long!!"); | |
359 | #endif | |
360 | return head(l)(); | |
361 | } | |
362 | }; | |
363 | ||
364 | struct Init { | |
365 | ||
366 | template <typename Sig> struct result; | |
367 | ||
368 | template <typename This, typename L> | |
369 | struct result<This(L)> | |
370 | { | |
371 | typedef typename result_of::ListType<L>::force_result_type type; | |
372 | }; | |
373 | ||
374 | template <class L> | |
375 | typename result<Init(L)>::type | |
376 | operator()( const L& l, | |
377 | reuser1<INV,VAR,Init, | |
378 | typename result_of::ListType<L>::delay_result_type> | |
379 | r = NIL ) const { | |
380 | if( null( tail( l )() )() ) | |
381 | return NIL; | |
382 | else | |
383 | return cons( head(l)(), r( Init(), tail(l)() )() )(); | |
384 | } | |
385 | }; | |
386 | ||
387 | struct Length { | |
388 | template <typename Sig> struct result; | |
389 | ||
390 | template <typename This, typename L> | |
391 | struct result<This(L)> | |
392 | { | |
393 | typedef size_t type; | |
394 | }; | |
395 | ||
396 | template <class L> | |
397 | size_t operator()( const L& ll ) const { | |
398 | typename L::delay_result_type l = delay(ll); | |
399 | size_t x = 0; | |
400 | while( !null(l)() ) { | |
401 | l = tail(l); | |
402 | ++x; | |
403 | if (x > BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH) | |
404 | break; | |
405 | } | |
406 | #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS | |
407 | if (x > BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH) | |
408 | throw lazy_exception("Your list is too long!!"); | |
409 | #endif | |
410 | return x; | |
411 | } | |
412 | }; | |
413 | ||
414 | // at is Haskell's operator (!!) | |
415 | // This is zero indexed. at(l,0)() returns the first element. | |
416 | struct At { | |
417 | template <typename Sig> struct result; | |
418 | ||
419 | template <typename This, typename L, typename N> | |
420 | struct result<This(L,N)> | |
421 | { | |
422 | typedef typename result_of::ListType<L>::value_type type; | |
423 | }; | |
424 | ||
425 | template <class L> | |
426 | typename result<At(L,size_t)>::type | |
427 | operator()( L l, size_t n ) const { | |
428 | while( n!=0 ) { | |
429 | l = tail(l); | |
430 | --n; | |
431 | } | |
432 | return head(l)(); | |
433 | } | |
434 | }; | |
435 | ||
436 | template <class P,class L> | |
437 | struct FilterH | |
438 | { | |
439 | P p; | |
440 | L l; | |
441 | FilterH( const P& pp, const L& ll) : p(pp), l(ll) {} | |
442 | template <typename Sig> struct result; | |
443 | ||
444 | template <typename This, class PP, class LL> | |
445 | struct result<This(PP,LL)> | |
446 | { | |
447 | typedef typename boost::phoenix::result_of:: | |
448 | ListType<LL>::delay_result_type type; | |
449 | }; | |
450 | typename result<FilterH(P,L)>::type operator()() const { | |
451 | typedef typename result_of::ListType<L>:: | |
452 | delay_result_type result_type; | |
453 | typedef boost::function0<result_type> Fun2_R_P_L; | |
454 | typedef boost::phoenix::function<Fun2_R_P_L> FilterH_R_P_L; | |
455 | if (null(l)() ) | |
456 | return NIL; | |
457 | Fun2_R_P_L fun2_R_P_L = FilterH<P,L>(p,tail(l)); | |
458 | FilterH_R_P_L filterh_R_P_L(fun2_R_P_L); | |
459 | if( p(head(l))() ) | |
460 | return cons( head(l)(), filterh_R_P_L() ); | |
461 | else | |
462 | return filterh_R_P_L(); | |
463 | } | |
464 | }; | |
465 | ||
466 | struct Filter { | |
467 | template <typename Sig> struct result; | |
468 | ||
469 | template <typename This, typename P, typename L> | |
470 | struct result<This(P,L)> | |
471 | { | |
472 | typedef typename result_of::ListType<L>::delay_result_type | |
473 | type; | |
474 | }; | |
475 | ||
476 | template <class P, class L> | |
477 | typename result<Filter(P,L)>::type | |
478 | operator()( const P& p, const L& ll) const | |
479 | { | |
480 | typename result_of::ListType<L>::delay_result_type | |
481 | l = delay(ll); | |
482 | typedef typename result_of::ListType<L>:: | |
483 | delay_result_type result_type; | |
484 | typedef boost::function0<result_type> Fun2_R_P_L; | |
485 | typedef boost::phoenix::function<Fun2_R_P_L> FilterH_R_P_L; | |
486 | Fun2_R_P_L fun2_R_P_L = FilterH<P,L>(p,l); | |
487 | FilterH_R_P_L filterh_R_P_L(fun2_R_P_L); | |
488 | return filterh_R_P_L(); | |
489 | } | |
490 | }; | |
491 | ||
492 | template <class F,class T> | |
493 | struct IterateH | |
494 | { | |
495 | F f; | |
496 | T t; | |
497 | IterateH( const F& ff, const T& tt) : f(ff), t(tt) {} | |
498 | template <typename Sig> struct result; | |
499 | ||
500 | template <typename This,class F2,class T2> | |
501 | struct result<This(F2,T2)> | |
502 | { | |
503 | typedef typename boost::remove_reference<T2>::type TT; | |
504 | typedef typename boost::remove_const<TT>::type TTT; | |
505 | typedef typename UseList::template List<TTT>::type LType; | |
506 | typedef typename result_of::ListType<LType>:: | |
507 | delay_result_type type; | |
508 | }; | |
509 | ||
510 | typename result<IterateH(F,T)>::type operator()() const { | |
511 | typedef typename UseList::template List<T>::type LType; | |
512 | typedef typename result_of::ListType<LType>:: | |
513 | delay_result_type result_type; | |
514 | typedef boost::function0<result_type> Fun2_R_F_T; | |
515 | typedef boost::phoenix::function<Fun2_R_F_T> IterateH_R_F_T; | |
516 | Fun2_R_F_T fun2_R_F_T = IterateH<F,T>(f,f(t)()); | |
517 | IterateH_R_F_T iterateh_R_F_T(fun2_R_F_T); | |
518 | return cons( t, iterateh_R_F_T() ); | |
519 | } | |
520 | }; | |
521 | ||
522 | ||
523 | struct Iterate { | |
524 | // Note: this does always return an odd_list; iterate() takes no ListLike | |
525 | // parameter, and it requires that its result be lazy. | |
526 | template <typename Sig> struct result; | |
527 | ||
528 | template <typename This, typename F, typename T> | |
529 | struct result<This(F,T)> | |
530 | { | |
531 | typedef typename boost::remove_reference<T>::type TT; | |
532 | typedef typename boost::remove_const<TT>::type TTT; | |
533 | typedef typename UseList::template List<TTT>::type LType; | |
534 | typedef typename result_of::ListType<LType>:: | |
535 | delay_result_type type; | |
536 | }; | |
537 | ||
538 | template <class F, class T> | |
539 | typename result<Iterate(F,T)>::type operator() | |
540 | (const F& f, const T& t) const { | |
541 | typedef typename UseList::template List<T>::type LType; | |
542 | typedef typename result_of::ListType<LType>:: | |
543 | delay_result_type result_type; | |
544 | typedef boost::function0<result_type> Fun2_R_F_T; | |
545 | typedef boost::phoenix::function<Fun2_R_F_T> IterateH_R_F_T; | |
546 | Fun2_R_F_T fun2_R_F_T = IterateH<F,T>(f,f(t)()); | |
547 | IterateH_R_F_T iterateh_R_F_T(fun2_R_F_T); | |
548 | return iterateh_R_F_T(); | |
549 | } | |
550 | }; | |
551 | ||
552 | } | |
553 | ||
554 | typedef boost::phoenix::function<impl::Until> Until; | |
555 | typedef boost::phoenix::function<impl::Until2> Until2; | |
556 | typedef boost::phoenix::function<impl::Last> Last; | |
557 | typedef boost::phoenix::function<impl::Init> Init; | |
558 | typedef boost::phoenix::function<impl::Length> Length; | |
559 | typedef boost::phoenix::function<impl::At> At; | |
560 | typedef boost::phoenix::function<impl::Filter> Filter; | |
561 | typedef boost::phoenix::function<impl::Iterate> Iterate; | |
562 | Until until; | |
563 | Until2 until2; | |
564 | Last last; | |
565 | Init all_but_last; // renamed from init which is not available. | |
566 | Length length; | |
567 | At at_; //Renamed from at. | |
568 | Filter filter; | |
569 | Iterate iterate; | |
570 | ||
571 | namespace impl { | |
572 | ||
573 | struct Repeat { | |
574 | // See note for iterate() | |
575 | template <typename Sig> struct result; | |
576 | ||
577 | template <typename This, typename T> | |
578 | struct result<This(T)> | |
579 | { | |
580 | typedef typename boost::remove_reference<T>::type TT; | |
581 | typedef typename boost::remove_const<TT>::type TTT; | |
582 | typedef typename UseList::template List<TTT>::type LType; | |
583 | typedef typename result_of::ListType<LType>:: | |
584 | delay_result_type type; | |
585 | }; | |
586 | ||
587 | template <class T> | |
588 | typename result<Repeat(T)>::type operator()( const T& x) const | |
589 | { | |
590 | return iterate(id,x); | |
591 | } | |
592 | }; | |
593 | ||
594 | struct Take { | |
595 | ||
596 | template <typename Sig> struct result; | |
597 | ||
598 | template <typename This, typename N, typename L> | |
599 | struct result<This(N,L)> | |
600 | { | |
601 | typedef typename result_of::ListType<L>::force_result_type type; | |
602 | }; | |
603 | ||
604 | template <class N,class L> | |
605 | typename result<Take(N,L)>::type | |
606 | operator()( N n, const L& l, | |
607 | reuser2<INV,VAR,VAR,Take,N, | |
608 | typename result_of::ListType<L>::force_result_type> | |
609 | r = NIL | |
610 | ) const { | |
611 | if( n <= 0 || null(l)() ) | |
612 | return NIL; | |
613 | else { | |
614 | return cons( head(l)(), r( Take(), n-1, tail(l)() )() )(); | |
615 | } | |
616 | } | |
617 | }; | |
618 | ||
619 | struct Drop { | |
620 | template <typename Sig> struct result; | |
621 | ||
622 | template <typename This, typename Dummy, typename L> | |
623 | struct result<This(Dummy,L)> | |
624 | { | |
625 | typedef typename result_of::ListType<L>::delay_result_type type; | |
626 | }; | |
627 | ||
628 | template <class L> | |
629 | typename result<Drop(size_t,L)>::type | |
630 | operator()( size_t n, const L& ll ) const { | |
631 | typename L::delay_result_type l = delay(ll); | |
632 | while( n!=0 && !null(l)() ) { | |
633 | --n; | |
634 | l = tail(l)(); | |
635 | } | |
636 | return l; | |
637 | } | |
638 | }; | |
639 | ||
640 | template <class T> | |
641 | struct EFH | |
642 | { | |
643 | mutable T x; | |
644 | EFH( const T& xx) : x(xx) {} | |
645 | template <typename Sig> struct result; | |
646 | ||
647 | template <typename This, class TT> | |
648 | struct result<This(TT)> | |
649 | { | |
650 | typedef typename boost::phoenix::UseList::template | |
651 | List<TT>::type LType; | |
652 | typedef typename boost::phoenix::result_of:: | |
653 | ListType<LType>::delay_result_type type; | |
654 | }; | |
655 | typename result<EFH(T)>::type operator()() const { | |
656 | typedef typename UseList::template List<T>::type LType; | |
657 | typedef typename result_of::ListType<LType>:: | |
658 | delay_result_type result_type; | |
659 | typedef boost::function0<result_type> fun1_R_TTT; | |
660 | //std::cout << "EFH (" << x << ")" << std::endl; | |
661 | ++x; | |
662 | fun1_R_TTT efh_R_TTT = EFH<T>(x); | |
663 | typedef boost::phoenix::function<fun1_R_TTT> EFH_R_T; | |
664 | EFH_R_T efh_R_T(efh_R_TTT); | |
665 | #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS | |
666 | if (x > BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH) | |
667 | throw lazy_exception("Running away in EFH!!"); | |
668 | #endif | |
669 | return cons( x-1, efh_R_T() ); | |
670 | } | |
671 | }; | |
672 | ||
673 | struct Enum_from { | |
674 | template <typename Sig> struct result; | |
675 | ||
676 | template <typename This, typename T> | |
677 | struct result<This(T)> | |
678 | { | |
679 | typedef typename boost::remove_reference<T>::type TT; | |
680 | typedef typename boost::remove_const<TT>::type TTT; | |
681 | typedef typename UseList::template List<TTT>::type LType; | |
682 | typedef typename result_of::ListType<LType>:: | |
683 | delay_result_type type; | |
684 | }; | |
685 | ||
686 | template <class T> | |
687 | typename result<Enum_from(T)>::type operator() | |
688 | (const T & x) const | |
689 | { | |
690 | typedef typename boost::remove_reference<T>::type TT; | |
691 | typedef typename boost::remove_const<TT>::type TTT; | |
692 | typedef typename UseList::template List<T>::type LType; | |
693 | typedef typename result_of::ListType<LType>:: | |
694 | delay_result_type result_type; | |
695 | typedef boost::function0<result_type> fun1_R_TTT; | |
696 | fun1_R_TTT efh_R_TTT = EFH<TTT>(x); | |
697 | typedef boost::phoenix::function<fun1_R_TTT> EFH_R_T; | |
698 | EFH_R_T efh_R_T(efh_R_TTT); | |
699 | //std::cout << "enum_from (" << x << ")" << std::endl; | |
700 | return efh_R_T(); | |
701 | } | |
702 | }; | |
703 | ||
704 | template <class T> | |
705 | struct EFTH | |
706 | { | |
707 | mutable T x; | |
708 | T y; | |
709 | EFTH( const T& xx, const T& yy) : x(xx), y(yy) {} | |
710 | template <typename Sig> struct result; | |
711 | ||
712 | template <typename This, class TT> | |
713 | struct result<This(TT)> | |
714 | { | |
715 | typedef typename boost::phoenix::UseList::template | |
716 | List<TT>::type LType; | |
717 | typedef typename boost::phoenix::result_of:: | |
718 | ListType<LType>::delay_result_type type; | |
719 | }; | |
720 | typename result<EFTH(T)>::type operator()() const { | |
721 | typedef typename UseList::template List<T>::type LType; | |
722 | typedef typename result_of::ListType<LType>:: | |
723 | delay_result_type result_type; | |
724 | typedef boost::function0<result_type> fun1_R_TTT; | |
725 | //std::cout << "EFTH (" << x << ")" << std::endl; | |
726 | if (x > y ) return NIL; | |
727 | ++x; | |
728 | fun1_R_TTT efth_R_TTT = EFTH<T>(x,y); | |
729 | typedef boost::phoenix::function<fun1_R_TTT> EFTH_R_T; | |
730 | EFTH_R_T efth_R_T(efth_R_TTT); | |
731 | #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS | |
732 | if (x > BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH) | |
733 | throw lazy_exception("Running away in EFTH!!"); | |
734 | #endif | |
735 | return cons( x-1, efth_R_T() ); | |
736 | } | |
737 | }; | |
738 | ||
739 | struct Enum_from_to { | |
740 | template <typename Sig> struct result; | |
741 | ||
742 | template <typename This, typename T> | |
743 | struct result<This(T,T)> | |
744 | { | |
745 | typedef typename boost::remove_reference<T>::type TT; | |
746 | typedef typename boost::remove_const<TT>::type TTT; | |
747 | typedef typename UseList::template List<TTT>::type LType; | |
748 | typedef typename result_of::ListType<LType>:: | |
749 | delay_result_type type; | |
750 | }; | |
751 | ||
752 | template <class T> | |
753 | typename result<Enum_from(T,T)>::type operator() | |
754 | (const T & x, const T & y) const | |
755 | { | |
756 | typedef typename boost::remove_reference<T>::type TT; | |
757 | typedef typename boost::remove_const<TT>::type TTT; | |
758 | typedef typename UseList::template List<T>::type LType; | |
759 | typedef typename result_of::ListType<LType>:: | |
760 | delay_result_type result_type; | |
761 | typedef boost::function0<result_type> fun1_R_TTT; | |
762 | fun1_R_TTT efth_R_TTT = EFTH<TTT>(x,y); | |
763 | typedef boost::phoenix::function<fun1_R_TTT> EFTH_R_T; | |
764 | EFTH_R_T efth_R_T(efth_R_TTT); | |
765 | //std::cout << "enum_from (" << x << ")" << std::endl; | |
766 | return efth_R_T(); | |
767 | } | |
768 | }; | |
769 | ||
770 | } | |
771 | ||
772 | ||
773 | //BOOST_PHOENIX_ADAPT_CALLABLE(apply, impl::apply, 3) | |
774 | // Functors to be used in reuser will have to be defined | |
775 | // using boost::phoenix::function directly | |
776 | // in order to be able to be used as arguments. | |
777 | typedef boost::phoenix::function<impl::Repeat> Repeat; | |
778 | typedef boost::phoenix::function<impl::Take> Take; | |
779 | typedef boost::phoenix::function<impl::Drop> Drop; | |
780 | typedef boost::phoenix::function<impl::Enum_from> Enum_from; | |
781 | typedef boost::phoenix::function<impl::Enum_from_to> Enum_from_to; | |
782 | Repeat repeat; | |
783 | Take take; | |
784 | Drop drop; | |
785 | Enum_from enum_from; | |
786 | Enum_from_to enum_from_to; | |
787 | ||
788 | namespace fcpp { | |
789 | ||
790 | ||
791 | } | |
792 | ||
793 | } | |
794 | ||
795 | } | |
796 | ||
797 | ||
798 | #endif |