1 ////////////////////////////////////////////////////////////////////////////
2 // lazy_list.hpp
3 //
4 // Build lazy operations for Phoenix equivalents for FC++
5 //
6 // These are equivalents of the Boost FC++ functoids in list.hpp
7 //
8 // Implemented so far:
9 //
10 // head tail null
11 //
12 // strict_list<T> and associated iterator.
13 //
14 // list<T> and odd_list<T>
15 //
16 // cons cat
17 //
18 // Comparisons between list and odd_list types and separately for strict_list.
19 //
20 // NOTES: There is a fix at the moment as I have not yet sorted out
21 //        how to get back the return type of a functor returning a list type.
22 //        For the moment I have fixed this as odd_list<T> at two locations,
23 //        one in list<T> and one in Cons. I am going to leave it like this
24 //        for now as reading the code, odd_list<T> seems to be correct.
25 //
26 //        I am also not happy at the details needed to detect types in Cons.
27 //
28 // I think the structure of this file is now complete.
29 // John Fletcher  February 2015.
30 //
31 ////////////////////////////////////////////////////////////////////////////
32 /*=============================================================================
33     Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis
34     Copyright (c) 2001-2007 Joel de Guzman
35     Copyright (c) 2015 John Fletcher
36 
37     Distributed under the Boost Software License, Version 1.0. (See accompanying
38     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
39 ==============================================================================*/
40 
41 ///////////////////////////////////////////////////////////////////////
42 // This is from Boost FC++ list.hpp reimplemented without Fun0 or Full0
43 ///////////////////////////////////////////////////////////////////////
44 
45 /*
46 concept ListLike: Given a list representation type L
47 
48 L<T> inherits ListLike and has
49    // typedefs just show typical values
50    typedef T value_type
51    typedef L<T> force_result_type
52    typedef L<T> delay_result_type
53    typedef L<T> tail_result_type
54    template <class UU> struct cons_rebind {
55       typedef L<UU> type;        // force type
56       typedef L<UU> delay_type;  // delay type
57    };
58 
59    L()
60    L( a_unique_type_for_nil )
61    template <class F> L(F)       // F :: ()->L
62 
63    constructor: force_result_type( T, L<T> )
64    template <class F>
65    constructor: force_result_type( T, F )  // F :: ()->L
66 
67    template <class It>
68    L( It, It )
69 
70    // FIX THIS instead of operator bool(), does Boost have something better?
71    operator bool() const
72    force_result_type force() const
73    delay_result_type delay() const
74    T head() const
75    tail_result_type tail() const
76 
77    static const bool is_lazy;   // true if can represent infinite lists
78 
79    typedef const_iterator;
80    typedef const_iterator iterator;  // ListLikes are immutable
81    iterator begin() const
82    iterator end() const
83 */
84 
85 //////////////////////////////////////////////////////////////////////
86 // End of section from Boost FC++ list.hpp
87 //////////////////////////////////////////////////////////////////////
88 
89 #ifndef BOOST_PHOENIX_FUNCTION_LAZY_LIST
90 #define BOOST_PHOENIX_FUNCTION_LAZY_LIST
91 
92 #include <boost/phoenix/core.hpp>
93 #include <boost/phoenix/function.hpp>
94 #include <boost/intrusive_ptr.hpp>
95 #include <boost/function.hpp>
96 #include <boost/type_traits/type_with_alignment.hpp>
97 //#include "lazy_reuse.hpp"
98 
99 namespace boost {
100 
101   namespace phoenix {
102 
103 //////////////////////////////////////////////////////////////////////
104 // These are the list types being declared.
105 //////////////////////////////////////////////////////////////////////
106 
107    template <class T> class strict_list;
108     namespace impl {
109    template <class T> class list;
110    template <class T> class odd_list;
111     }
112    // in ref_count.hpp in BoostFC++ now in lazy_operator.hpp
113    //typedef unsigned int RefCountType;
114 
115 //////////////////////////////////////////////////////////////////////
116 // a_unique_type_for_nil moved to lazy_operator.hpp.
117 //////////////////////////////////////////////////////////////////////
118 
119 
120 //////////////////////////////////////////////////////////////////////
121 // Distinguish lazy lists (list and odd_list) from strict_list.
122 //////////////////////////////////////////////////////////////////////
123 
124     namespace lazy {
125       // Copied from Boost FC++ list.hpp
126       template <class L, bool is_lazy> struct ensure_lazy_helper {};
127       template <class L> struct ensure_lazy_helper<L,true> {
requires_lazy_list_to_prevent_infinite_recursionboost::phoenix::lazy::ensure_lazy_helper128          static void requires_lazy_list_to_prevent_infinite_recursion() {}
129       };
130       template <class L>
ensure_lazy()131       void ensure_lazy() {
132         ensure_lazy_helper<L,L::is_lazy>::
133         requires_lazy_list_to_prevent_infinite_recursion();
134       }
135 
136     }
137 
138 //////////////////////////////////////////////////////////////////////
139 // Provide remove reference for types defined for list types.
140 //////////////////////////////////////////////////////////////////////
141 
142     namespace result_of {
143 
144       template < typename L >
145       class ListType
146       {
147       public:
148         typedef typename boost::remove_reference<L>::type LType;
149         typedef typename LType::value_type value_type;
150         typedef typename LType::tail_result_type tail_result_type;
151         typedef typename LType::force_result_type force_result_type;
152         typedef typename LType::delay_result_type delay_result_type;
153       };
154 
155       template <>
156       class ListType<a_unique_type_for_nil>
157       {
158       public:
159         typedef a_unique_type_for_nil LType;
160         //typedef a_unique_type_for_nil value_type;
161       };
162 
163       template <typename F, typename T>
164       struct ResultType {
165         typedef typename impl::odd_list<T> type;
166       };
167 
168     }
169 
170 //////////////////////////////////////////////////////////////////////
171 // ListLike is a property inherited by any list type to enable it to
172 // work with the functions being implemented in this file.
173 // It provides the check for the structure described above.
174 //////////////////////////////////////////////////////////////////////
175 
176    namespace listlike {
177 
178        struct ListLike {};   // This lets us use is_base_and_derived() to see
179        // (at compile-time) what classes are user-defined lists.
180 
181 
182        template <class L, bool is_lazy> struct ensure_lazy_helper {};
183        template <class L> struct ensure_lazy_helper<L,true> {
requires_lazy_list_to_prevent_infinite_recursionboost::phoenix::listlike::ensure_lazy_helper184            static void requires_lazy_list_to_prevent_infinite_recursion() {}
185        };
186        template <class L>
ensure_lazy()187        void ensure_lazy() {
188          ensure_lazy_helper<L,L::is_lazy>::
189          requires_lazy_list_to_prevent_infinite_recursion();
190        }
191 
192        template <class L, bool b>
193        struct EnsureListLikeHelp {
trying_to_call_a_list_function_on_a_non_listboost::phoenix::listlike::EnsureListLikeHelp194            static void trying_to_call_a_list_function_on_a_non_list() {}
195        };
196        template <class L> struct EnsureListLikeHelp<L,false> { };
197        template <class L>
EnsureListLike()198        void EnsureListLike() {
199           typedef typename result_of::ListType<L>::LType LType;
200           EnsureListLikeHelp<L,boost::is_base_and_derived<ListLike,LType>::value>::
201              trying_to_call_a_list_function_on_a_non_list();
202        }
203 
204       template <class L>
is_a_unique_type_for_nil(const L &)205       bool is_a_unique_type_for_nil(const L& /*l*/) {
206          return false;
207       }
208 
209       template <>
is_a_unique_type_for_nil(const a_unique_type_for_nil &)210       bool is_a_unique_type_for_nil<a_unique_type_for_nil>
211       (const a_unique_type_for_nil& /* n */) {
212          return true;
213       }
214 
215       template <class L>
216       struct detect_nil {
217         static const bool is_nil = false;
218       };
219 
220       template <>
221       struct detect_nil<a_unique_type_for_nil> {
222        static const bool is_nil = true;
223       };
224 
225       template <>
226       struct detect_nil<a_unique_type_for_nil&> {
227        static const bool is_nil = true;
228       };
229 
230       template <>
231       struct detect_nil<const a_unique_type_for_nil&> {
232        static const bool is_nil = true;
233       };
234 
235     }
236 
237 //////////////////////////////////////////////////////////////////////
238 // Implement lazy functions for list types. cat and cons come later.
239 //////////////////////////////////////////////////////////////////////
240 
241 #ifndef BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH
242 #define BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH 1000
243 #endif
244 
245     namespace impl {
246 
247       struct Head
248       {
249         template <typename Sig>
250         struct result;
251 
252         template <typename This, typename L>
253         struct result<This(L)>
254         {
255           typedef typename result_of::ListType<L>::value_type type;
256         };
257 
258         template <typename L>
259         typename result<Head(L)>::type
operator ()boost::phoenix::impl::Head260         operator()(const L & l) const
261         {
262           listlike::EnsureListLike<L>();
263           return l.head();
264         }
265 
266       };
267 
268       struct Tail
269       {
270         template <typename Sig>
271         struct result;
272 
273         template <typename This, typename L>
274         struct result<This(L)>
275         {
276           typedef typename result_of::ListType<L>::tail_result_type type;
277         };
278 
279         template <typename L>
280         typename result<Tail(L)>::type
operator ()boost::phoenix::impl::Tail281         operator()(const L & l) const
282         {
283           listlike::EnsureListLike<L>();
284           return l.tail();
285         }
286 
287       };
288 
289       struct Null
290       {
291         template <typename Sig>
292         struct result;
293 
294         template <typename This, typename L>
295         struct result<This(L)>
296         {
297             typedef bool type;
298         };
299 
300         template <typename L>
301         typename result<Null(L)>::type
302         //bool
operator ()boost::phoenix::impl::Null303         operator()(const L& l) const
304         {
305           listlike::EnsureListLike<L>();
306           return !l;
307         }
308 
309       };
310 
311       struct Delay {
312         template <typename Sig>
313         struct result;
314 
315         template <typename This, typename L>
316         struct result<This(L)>
317         {
318           typedef typename result_of::ListType<L>::delay_result_type type;
319         };
320 
321         template <typename L>
322         typename result<Delay(L)>::type
operator ()boost::phoenix::impl::Delay323         operator()(const L & l) const
324         {
325           listlike::EnsureListLike<L>();
326           return l.delay();
327         }
328 
329       };
330 
331       struct Force {
332         template <typename Sig>
333         struct result;
334 
335         template <typename This, typename L>
336         struct result<This(L)>
337         {
338           typedef typename result_of::ListType<L>::force_result_type type;
339         };
340 
341         template <typename L>
342         typename result<Force(L)>::type
operator ()boost::phoenix::impl::Force343         operator()(const L & l) const
344         {
345           listlike::EnsureListLike<L>();
346           return l.force();
347         }
348 
349       };
350 
351     }
352     //BOOST_PHOENIX_ADAPT_CALLABLE(head, impl::head, 1)
353     //BOOST_PHOENIX_ADAPT_CALLABLE(tail, impl::tail, 1)
354     //BOOST_PHOENIX_ADAPT_CALLABLE(null, impl::null, 1)
355     typedef boost::phoenix::function<impl::Head> Head;
356     typedef boost::phoenix::function<impl::Tail> Tail;
357     typedef boost::phoenix::function<impl::Null> Null;
358     typedef boost::phoenix::function<impl::Delay> Delay;
359     typedef boost::phoenix::function<impl::Force> Force;
360     Head head;
361     Tail tail;
362     Null null;
363     Delay delay;
364     Force force;
365 
366 //////////////////////////////////////////////////////////////////////
367 // These definitions used for strict_list are imported from BoostFC++
368 // unchanged.
369 //////////////////////////////////////////////////////////////////////
370 
371 namespace impl {
372 template <class T>
373 struct strict_cons : public boost::noncopyable {
374    mutable RefCountType refC;
375    T head;
376    typedef boost::intrusive_ptr<strict_cons> tail_type;
377    tail_type tail;
strict_consboost::phoenix::impl::strict_cons378    strict_cons( const T& h, const tail_type& t ) : refC(0), head(h), tail(t) {}
379 
380 };
381 template <class T>
intrusive_ptr_add_ref(const strict_cons<T> * p)382 void intrusive_ptr_add_ref( const strict_cons<T>* p ) {
383    ++ (p->refC);
384 }
385 template <class T>
intrusive_ptr_release(const strict_cons<T> * p)386 void intrusive_ptr_release( const strict_cons<T>* p ) {
387    if( !--(p->refC) ) delete p;
388 }
389 
390 template <class T>
391 class strict_list_iterator {
392    typedef boost::intrusive_ptr<strict_cons<T> > rep_type;
393    rep_type l;
394    bool is_nil;
advance()395    void advance() {
396       l = l->tail;
397       if( !l )
398          is_nil = true;
399    }
400    class Proxy {  // needed for operator->
401       const T x;
402       friend class strict_list_iterator;
Proxy(const T & xx)403       Proxy( const T& xx ) : x(xx) {}
404    public:
operator ->() const405       const T* operator->() const { return &x; }
406    };
407 public:
408    typedef std::input_iterator_tag iterator_category;
409    typedef T value_type;
410    typedef ptrdiff_t difference_type;
411    typedef T* pointer;
412    typedef T& reference;
413 
strict_list_iterator()414    strict_list_iterator() : l(), is_nil(true) {}
strict_list_iterator(const rep_type & ll)415    explicit strict_list_iterator( const rep_type& ll ) : l(ll), is_nil(!ll) {}
416 
operator *() const417    const T operator*() const { return l->head; }
operator ->() const418    const Proxy operator->() const { return Proxy(l->head); }
operator ++()419    strict_list_iterator<T>& operator++() {
420       advance();
421       return *this;
422    }
operator ++(int)423    const strict_list_iterator<T> operator++(int) {
424       strict_list_iterator<T> i( *this );
425       advance();
426       return i;
427    }
operator ==(const strict_list_iterator<T> & i) const428    bool operator==( const strict_list_iterator<T>& i ) const {
429       return is_nil && i.is_nil;
430    }
operator !=(const strict_list_iterator<T> & i) const431    bool operator!=( const strict_list_iterator<T>& i ) const {
432       return ! this->operator==(i);
433    }
434 };
435 }
436 
437 //////////////////////////////////////////////////////////////////////
438 //////////////////////////////////////////////////////////////////////
439 
440    template <class T>
441    class strict_list : public listlike::ListLike
442    {
443        typedef boost::intrusive_ptr<impl::strict_cons<T> > rep_type;
444        rep_type rep;
445        struct Make {};
446 
447        template <class Iter>
help(Iter a,const Iter & b)448        static rep_type help( Iter a, const Iter& b ) {
449            rep_type r;
450            while( a != b ) {
451               T x( *a );
452               r = rep_type( new impl::strict_cons<T>( x, r ) );
453               ++a;
454            }
455            return r;
456        }
457 
458    public:
459        static const bool is_lazy = false;
460 
461        typedef T value_type;
462        typedef strict_list force_result_type;
463        typedef strict_list delay_result_type;
464        typedef strict_list tail_result_type;
465        template <class UU> struct cons_rebind {
466            typedef strict_list<UU> type;
467            typedef strict_list<UU> delay_type;
468        };
469 
470 
strict_list(Make,const rep_type & r)471    strict_list( Make, const rep_type& r ) : rep(r) {}
472 
strict_list()473    strict_list() : rep() {}
474 
strict_list(a_unique_type_for_nil)475    strict_list( a_unique_type_for_nil ) : rep() {}
476 
477    template <class F>
strict_list(const F & f)478    strict_list( const F& f ) : rep( f().rep ) {
479      // I cannot do this yet.
480      //functoid_traits<F>::template ensure_accepts<0>::args();
481    }
482 
strict_list(const T & x,const strict_list & y)483    strict_list( const T& x, const strict_list& y )
484       : rep( new impl::strict_cons<T>(x,y.rep) ) {}
485 
486    template <class F>
strict_list(const T & x,const F & f)487    strict_list( const T& x, const F& f )
488       : rep( new impl::strict_cons<T>(x,f().rep) ) {}
489 
operator bool() const490      operator bool() const { return (bool)rep; }
force() const491    force_result_type force() const { return *this; }
delay() const492    delay_result_type delay() const { return *this; }
head() const493    T head() const {
494 #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
495       if( !*this )
496          throw lazy_exception("Tried to take head() of empty strict_list");
497 #endif
498       return rep->head;
499    }
tail() const500    tail_result_type tail() const {
501 #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
502       if( !*this )
503          throw lazy_exception("Tried to take tail() of empty strict_list");
504 #endif
505       return strict_list(Make(),rep->tail);
506    }
507 
508    template <class Iter>
strict_list(const Iter & a,const Iter & b)509    strict_list( const Iter& a, const Iter& b ) : rep( rep_type() ) {
510       // How ironic.  We need to reverse the iterator range in order to
511       // non-recursively build this!
512       std::vector<T> tmp(a,b);
513       rep = help( tmp.rbegin(), tmp.rend() );
514    }
515 
516    // Since the strict_cons destructor can't call the strict_list
517    // destructor, the "simple" iterative destructor is correct and
518    // efficient.  Hurray.
~strict_list()519    ~strict_list() { while(rep && (rep->refC == 1)) rep = rep->tail; }
520 
521    // The following helps makes strict_list almost an STL "container"
522    typedef impl::strict_list_iterator<T> const_iterator;
523    typedef const_iterator iterator;         // strict_list is immutable
begin() const524    iterator begin() const { return impl::strict_list_iterator<T>( rep ); }
end() const525    iterator end() const   { return impl::strict_list_iterator<T>(); }
526 
527    };
528 
529     // All of these null head and tail are now non lazy using e.g. null(a)().
530     // They need an extra () e.g. null(a)().
531     template <class T>
operator ==(const strict_list<T> & a,a_unique_type_for_nil)532     bool operator==( const strict_list<T>& a, a_unique_type_for_nil ) {
533       return null(a)();
534     }
535     template <class T>
operator ==(a_unique_type_for_nil,const strict_list<T> & a)536     bool operator==( a_unique_type_for_nil, const strict_list<T>& a ) {
537       return null(a)();
538     }
539     template <class T>
operator ==(const strict_list<T> & a,const strict_list<T> & b)540     bool operator==( const strict_list<T>& a, const strict_list<T>& b ) {
541         if( null(a)() && null(b)() )
542             return true;
543         if( null(a)() || null(b)() )
544             return false;
545         return (head(a)()==head(b)()) &&
546             (tail(a)()==tail(b)());
547     }
548 
549     template <class T>
operator <(const strict_list<T> & a,const strict_list<T> & b)550     bool operator<( const strict_list<T>& a, const strict_list<T>& b ) {
551       if( null(a)() && !null(b)() )  return true;
552         if( null(b)() )                      return false;
553         if( head(b)() < head(a)() )    return false;
554         if( head(a)() < head(b)() )    return true;
555         return (tail(a)() < tail(b)());
556     }
557     template <class T>
operator <(const strict_list<T> &,a_unique_type_for_nil)558     bool operator<( const strict_list<T>&, a_unique_type_for_nil ) {
559         return false;
560     }
561     template <class T>
operator <(a_unique_type_for_nil,const strict_list<T> & b)562     bool operator<( a_unique_type_for_nil, const strict_list<T>& b ) {
563       return !(null(b)());
564     }
565 
566 //////////////////////////////////////////////////////////////////////
567 // Class list<T> is the primary interface to the user for lazy lists.
568 //////////////////////////////////////////////////////////////////////{
569     namespace impl {
570       using fcpp::INV;
571       using fcpp::VAR;
572       using fcpp::reuser2;
573 
574       struct CacheEmpty {};
575 
576       template <class T> class Cache;
577       template <class T> class odd_list;
578       template <class T> class list_iterator;
579       template <class It, class T>
580       struct ListItHelp2 /*: public c_fun_type<It,It,odd_list<T> >*/ {
581         // This will need a return type.
582         typedef odd_list<T> return_type;
583         odd_list<T> operator()( It begin, const It& end,
584           reuser2<INV,VAR,INV,ListItHelp2<It,T>,It,It> r = NIL ) const;
585       };
586       template <class U,class F> struct cvt;
587       template <class T, class F, class R> struct ListHelp;
588       template <class T> Cache<T>* xempty_helper();
589       template <class T, class F, class L, bool b> struct ConsHelp2;
590 
591       struct ListRaw {};
592 
593       template <class T>
594       class list : public listlike::ListLike
595       {
596         // never NIL, unless an empty odd_list
597         boost::intrusive_ptr<Cache<T> > rep;
598 
599         template <class U> friend class Cache;
600         template <class U> friend class odd_list;
601         template <class TT, class F, class L, bool b> friend struct ConsHelp2;
602         template <class U,class F> friend struct cvt;
603 
list(const boost::intrusive_ptr<Cache<T>> & p)604         list( const boost::intrusive_ptr<Cache<T> >& p ) : rep(p) { }
list(ListRaw,Cache<T> * p)605         list( ListRaw, Cache<T>* p ) : rep(p) { }
606 
priv_isEmpty() const607         bool priv_isEmpty() const {
608           return rep->cache().second.rep == Cache<T>::XNIL();
609         }
priv_head() const610         T priv_head() const {
611 #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
612           if( priv_isEmpty() )
613              throw lazy_exception("Tried to take head() of empty list");
614 #endif
615           return rep->cache().first();
616         }
priv_tail() const617         list<T> priv_tail() const {
618 #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
619           if( priv_isEmpty() )
620             throw lazy_exception("Tried to take tail() of empty list");
621 #endif
622           return rep->cache().second;
623         }
624 
625 
626       public:
627         static const bool is_lazy = true;
628 
629         typedef T value_type;
630         typedef list tail_result_type;
631         typedef odd_list<T> force_result_type;
632         typedef list delay_result_type;
633         template <class UU> struct cons_rebind {
634            typedef odd_list<UU> type;
635            typedef list<UU> delay_type;
636         };
637 
list(a_unique_type_for_nil)638         list( a_unique_type_for_nil ) : rep( Cache<T>::XEMPTY() ) { }
list()639         list() : rep( Cache<T>::XEMPTY() ) { }
640 
641         template <class F>  // works on both ()->odd_list and ()->list
642         // At the moment this is fixed for odd_list<T>.
643         // I need to do more work to get the general result.
list(const F & f)644         list( const F& f )
645           : rep( ListHelp<T,F,odd_list<T> >()(f) ) { }
646         //: rep( ListHelp<T,F,typename F::result_type>()(f) ) { }
647 
operator bool() const648         operator bool() const { return !priv_isEmpty(); }
force() const649         const force_result_type& force() const { return rep->cache(); }
delay() const650         const delay_result_type& delay() const { return *this; }
651         // Note: force returns a reference;
652         // implicit conversion now returns a copy.
operator odd_list<T>() const653         operator odd_list<T>() const { return force(); }
654 
head() const655         T head() const { return priv_head(); }
tail() const656         tail_result_type tail() const { return priv_tail(); }
657 
658         // The following helps makes list almost an STL "container"
659         typedef list_iterator<T> const_iterator;
660         typedef const_iterator iterator;         // list is immutable
begin() const661         iterator begin() const { return list_iterator<T>( *this ); }
end() const662         iterator end() const   { return list_iterator<T>(); }
663 
664         // end of list<T>
665       };
666 
667 //////////////////////////////////////////////////////////////////////
668 // Class odd_list<T> is not normally accessed by the user.
669 //////////////////////////////////////////////////////////////////////
670 
671       struct OddListDummyY {};
672 
673       template <class T>
674       class odd_list : public listlike::ListLike
675       {
676       public:
677         typedef
678         typename boost::type_with_alignment<boost::alignment_of<T>::value>::type
679         xfst_type;
680       private:
681         union { xfst_type fst; unsigned char dummy[sizeof(T)]; };
682 
first() const683         const T& first() const {
684            return *static_cast<const T*>(static_cast<const void*>(&fst));
685         }
first()686         T& first() {
687            return *static_cast<T*>(static_cast<void*>(&fst));
688         }
689         list<T>  second;   // If XNIL, then this odd_list is NIL
690 
691         template <class U> friend class list;
692         template <class U> friend class Cache;
693 
odd_list(OddListDummyY)694         odd_list( OddListDummyY )
695           : second( Cache<T>::XBAD() ) { }
696 
init(const T & x)697         void init( const T& x ) {
698            new (static_cast<void*>(&fst)) T(x);
699         }
700 
fst_is_valid() const701         bool fst_is_valid() const {
702            if( second.rep != Cache<T>::XNIL() )
703               if( second.rep != Cache<T>::XBAD() )
704                  return true;
705            return false;
706         }
707 
priv_isEmpty() const708         bool priv_isEmpty() const { return second.rep == Cache<T>::XNIL(); }
priv_head() const709         T priv_head() const {
710 #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
711            if( priv_isEmpty() )
712              throw lazy_exception("Tried to take head() of empty odd_list");
713 #endif
714            return first();
715         }
716 
priv_tail() const717         list<T> priv_tail() const {
718 #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
719            if( priv_isEmpty() )
720              throw lazy_exception("Tried to take tail() of empty odd_list");
721 #endif
722            return second;
723         }
724 
725       public:
726         static const bool is_lazy = true;
727 
728         typedef T value_type;
729         typedef list<T> tail_result_type;
730         typedef odd_list<T> force_result_type;
731         typedef list<T> delay_result_type;
732         template <class UU> struct cons_rebind {
733           typedef odd_list<UU> type;
734           typedef list<UU> delay_type;
735         };
736 
odd_list()737         odd_list() : second( Cache<T>::XNIL() ) { }
odd_list(a_unique_type_for_nil)738         odd_list( a_unique_type_for_nil ) : second( Cache<T>::XNIL() ) { }
odd_list(const T & x,const list<T> & y)739         odd_list( const T& x, const list<T>& y ) : second(y) { init(x); }
odd_list(const T & x,a_unique_type_for_nil)740         odd_list( const T& x, a_unique_type_for_nil ) : second(NIL) { init(x); }
741 
odd_list(const odd_list<T> & x)742         odd_list( const odd_list<T>& x ) : second(x.second) {
743            if( fst_is_valid() ) {
744               init( x.first() );
745            }
746         }
747 
748         template <class It>
odd_list(It begin,const It & end)749         odd_list( It begin, const It& end )
750           : second( begin==end ? Cache<T>::XNIL() :
751              ( init(*begin++), list<T>( begin, end ) ) ) {}
752 
operator =(const odd_list<T> & x)753         odd_list<T>& operator=( const odd_list<T>& x ) {
754            if( this == &x ) return *this;
755            if( fst_is_valid() ) {
756              if( x.fst_is_valid() )
757                first() = x.first();
758              else
759                first().~T();
760            }
761            else {
762               if( x.fst_is_valid() )
763                  init( x.first() );
764            }
765            second = x.second;
766            return *this;
767         }
768 
~odd_list()769        ~odd_list() {
770           if( fst_is_valid() ) {
771             first().~T();
772           }
773         }
774 
operator bool() const775         operator bool() const { return !priv_isEmpty(); }
force() const776         const force_result_type& force() const { return *this; }
delay() const777         delay_result_type delay() const { return list<T>(*this); }
778 
head() const779         T head() const { return priv_head(); }
tail() const780         tail_result_type tail() const { return priv_tail(); }
781 
782         // The following helps makes odd_list almost an STL "container"
783         typedef list_iterator<T> const_iterator;
784         typedef const_iterator iterator;         // odd_list is immutable
begin() const785         iterator begin() const { return list_iterator<T>( this->delay() ); }
end() const786         iterator end() const   { return list_iterator<T>(); }
787 
788         // end of odd_list<T>
789       };
790 
791 //////////////////////////////////////////////////////////////////////
792 // struct cvt
793 //////////////////////////////////////////////////////////////////////
794 
795       // This converts ()->list<T> to ()->odd_list<T>.
796       // In other words, here is the 'extra work' done when using the
797       // unoptimized interface.
798       template <class U,class F>
799       struct cvt /*: public c_fun_type<odd_list<U> >*/ {
800         typedef odd_list<U> return_type;
801         F f;
cvtboost::phoenix::impl::cvt802         cvt( const F& ff ) : f(ff) {}
operator ()boost::phoenix::impl::cvt803         odd_list<U> operator()() const {
804            list<U> l = f();
805            return l.force();
806         }
807       };
808 
809 
810 //////////////////////////////////////////////////////////////////////
811 // Cache<T> and associated functions.
812 //////////////////////////////////////////////////////////////////////
813 
814 // I malloc a RefCountType to hold the refCount and init it to 1 to ensure the
815 // refCount will never get to 0, so the destructor-of-global-object
816 // order at the end of the program is a non-issue.  In other words, the
817 // memory allocated here is only reclaimed by the operating system.
818     template <class T>
xnil_helper()819     Cache<T>* xnil_helper() {
820        void *p = std::malloc( sizeof(RefCountType) );
821        *((RefCountType*)p) = 1;
822        return static_cast<Cache<T>*>( p );
823     }
824 
825     template <class T>
xnil_helper_nil()826     Cache<T>* xnil_helper_nil() {
827        Cache<T>* p = xnil_helper<T>();
828        return p;
829     }
830 
831     template <class T>
xnil_helper_bad()832     Cache<T>* xnil_helper_bad() {
833        Cache<T>* p = xnil_helper<T>();
834        return p;
835     }
836 
837     template <class T>
xempty_helper()838     Cache<T>* xempty_helper() {
839        Cache<T>* p = new Cache<T>( CacheEmpty() );
840        return p;
841     }
842 
843     // This makes a boost phoenix function type with return type
844     // odd_list<T>
845     template <class T>
846     struct fun0_type_helper{
847        typedef boost::function0<odd_list<T> > fun_type;
848        typedef boost::phoenix::function<fun_type> phx_type;
849     };
850 
851 
852       template <class T>
853       struct make_fun0_odd_list {
854 
855         typedef typename fun0_type_helper<T>::fun_type fun_type;
856         typedef typename fun0_type_helper<T>::phx_type phx_type;
857         typedef phx_type result_type;
858 
859         template <class F>
operator ()boost::phoenix::impl::make_fun0_odd_list860         result_type operator()(const F& f) const
861         {
862             fun_type ff(f);
863             phx_type g(ff);
864             return g;
865         }
866 
867         // Overload for the case where it is a boost phoenix function already.
868         template <class F>
operator ()boost::phoenix::impl::make_fun0_odd_list869         typename boost::phoenix::function<F> operator()
870           (const boost::phoenix::function<F>& f) const
871         {
872             return f;
873         }
874 
875     };
876 
877     template <class T>
878     class Cache : boost::noncopyable {
879        mutable RefCountType refC;
880        // This is the boost::function type
881        typedef typename fun0_type_helper<T>::fun_type fun_odd_list_T;
882        // This is the boost::phoenix::function type;
883        typedef typename fun0_type_helper<T>::phx_type fun0_odd_list_T;
884        mutable fun0_odd_list_T fxn;
885        mutable odd_list<T>     val;
886        // val.second.rep can be XBAD, XNIL, or a valid ptr
887        //  - XBAD: val is invalid (fxn is valid)
888        //  - XNIL: this is the empty list
889        //  - anything else: val.first() is head, val.second is tail()
890 
891        // This functoid should never be called; it represents a
892        // self-referent Cache, which should be impossible under the current
893        // implementation.  Nonetheless, we need a 'dummy' function object to
894        // represent invalid 'fxn's (val.second.rep!=XBAD), and this
895        // implementation seems to be among the most reasonable.
896        struct blackhole_helper /*: c_fun_type< odd_list<T> >*/ {
897           typedef odd_list<T> return_type;
operator ()boost::phoenix::impl::Cache::blackhole_helper898           odd_list<T> operator()() const {
899 #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
900             throw lazy_exception("You have entered a black hole.");
901 #else
902             return odd_list<T>();
903 #endif
904           }
905        };
906 
907        // Don't get rid of these XFOO() functions; they impose no overhead,
908        // and provide a useful place to add debugging code for tracking down
909        // before-main()-order-of-initialization problems.
XEMPTY()910        static const boost::intrusive_ptr<Cache<T> >& XEMPTY() {
911           static boost::intrusive_ptr<Cache<T> > xempty( xempty_helper<T>() );
912           return xempty;
913        }
XNIL()914        static const boost::intrusive_ptr<Cache<T> >& XNIL() {
915        // this list is nil
916           static boost::intrusive_ptr<Cache<T> > xnil( xnil_helper_nil<T>() );
917           return xnil;
918        }
919 
XBAD()920        static const boost::intrusive_ptr<Cache<T> >& XBAD() {
921        // the pair is invalid; use fxn
922           static boost::intrusive_ptr<Cache<T> > xbad( xnil_helper_bad<T>() );
923           return xbad;
924        }
925 
926        static fun0_odd_list_T /*<odd_list<T> >*/ the_blackhole;
blackhole()927        static fun0_odd_list_T& blackhole() {
928          static fun0_odd_list_T the_blackhole;
929          //( make_fun0_odd_list<T>()( blackhole_helper() ) );
930          return the_blackhole;
931        }
932 
cache() const933        odd_list<T>& cache() const {
934          if( val.second.rep == XBAD() ) {
935             val = fxn()();
936             fxn = blackhole();
937          }
938          return val;
939        }
940 
941        template <class U> friend class list;
942        template <class U> friend class odd_list;
943        template <class TT, class F, class L, bool b> friend struct ConsHelp2;
944        template <class U,class F> friend struct cvt;
945        template <class U, class F, class R> friend struct ListHelp;
946        template <class U> friend Cache<U>* xempty_helper();
947 
Cache(CacheEmpty)948        Cache( CacheEmpty ) : refC(0), fxn(blackhole()), val() {}
Cache(const odd_list<T> & x)949        Cache( const odd_list<T>& x ) : refC(0), fxn(blackhole()), val(x) {}
Cache(const T & x,const list<T> & l)950        Cache( const T& x, const list<T>& l ) : refC(0),fxn(blackhole()),val(x,l)
951           {}
952 
Cache(const fun0_odd_list_T & f)953        Cache( const fun0_odd_list_T& f )
954          : refC(0), fxn(f), val( OddListDummyY() ) {}
955 
956        // f must be a boost phoenix function object?
957        template <class F>
Cache(const F & f)958        Cache( const F& f )    // ()->odd_list
959          : refC(0), fxn(make_fun0_odd_list<T>()(f)), val( OddListDummyY() ) {}
960 
961        // This is for ()->list<T> to ()->odd_list<T>
962        struct CvtFxn {};
963        template <class F>
Cache(CvtFxn,const F & f)964        Cache( CvtFxn, const F& f )    // ()->list
965          :  refC(0), fxn(make_fun0_odd_list<T>()(cvt<T,F>(f))), val( OddListDummyY() ) {}
966 
967        template <class X>
968        friend void intrusive_ptr_add_ref( const Cache<X>* p );
969        template <class X>
970        friend void intrusive_ptr_release( const Cache<X>* p );
971     };
972 
973     template <class T>
intrusive_ptr_add_ref(const Cache<T> * p)974     void intrusive_ptr_add_ref( const Cache<T>* p ) {
975         ++ (p->refC);
976     }
977     template <class T>
intrusive_ptr_release(const Cache<T> * p)978     void intrusive_ptr_release( const Cache<T>* p ) {
979         if( !--(p->refC) ) delete p;
980     }
981 
982 //////////////////////////////////////////////////////////////////////
983 // Rest of list's stuff
984 //////////////////////////////////////////////////////////////////////
985 
986 template <class T, class F> struct ListHelp<T,F,list<T> > {
operator ()boost::phoenix::impl::ListHelp987    boost::intrusive_ptr<Cache<T> > operator()( const F& f ) const {
988       return boost::intrusive_ptr<Cache<T> >
989          (new Cache<T>(typename Cache<T>::CvtFxn(),f));
990    }
991 };
992 template <class T, class F> struct ListHelp<T,F,odd_list<T> > {
operator ()boost::phoenix::impl::ListHelp993    boost::intrusive_ptr<Cache<T> > operator()( const F& f ) const {
994       return boost::intrusive_ptr<Cache<T> >(new Cache<T>(f));
995    }
996 };
997 
998 template <class T>
999 class list_iterator {
1000    list<T> l;
1001    bool is_nil;
advance()1002    void advance() {
1003       l = l.tail();
1004       if( !l )
1005          is_nil = true;
1006    }
1007    class Proxy {  // needed for operator->
1008       const T x;
1009       friend class list_iterator;
Proxy(const T & xx)1010       Proxy( const T& xx ) : x(xx) {}
1011    public:
operator ->() const1012       const T* operator->() const { return &x; }
1013    };
1014 public:
1015    typedef std::input_iterator_tag iterator_category;
1016    typedef T value_type;
1017    typedef ptrdiff_t difference_type;
1018    typedef T* pointer;
1019    typedef T& reference;
1020 
list_iterator()1021    list_iterator() : l(), is_nil(true) {}
list_iterator(const list<T> & ll)1022    explicit list_iterator( const list<T>& ll ) : l(ll), is_nil(!ll) {}
1023 
operator *() const1024    const T operator*() const { return l.head(); }
operator ->() const1025    const Proxy operator->() const { return Proxy(l.head()); }
operator ++()1026    list_iterator<T>& operator++() {
1027       advance();
1028       return *this;
1029    }
operator ++(int)1030    const list_iterator<T> operator++(int) {
1031       list_iterator<T> i( *this );
1032       advance();
1033       return i;
1034    }
operator ==(const list_iterator<T> & i) const1035    bool operator==( const list_iterator<T>& i ) const {
1036       return is_nil && i.is_nil;
1037    }
operator !=(const list_iterator<T> & i) const1038    bool operator!=( const list_iterator<T>& i ) const {
1039       return ! this->operator==(i);
1040    }
1041 };
1042 
1043 
1044     } // namespace impl
1045 
1046   using impl::list;
1047   using impl::odd_list;
1048   using impl::list_iterator;
1049 
1050 //////////////////////////////////////////////////////////////////////
1051 // op== and op<, overloaded for all combos of list, odd_list, and NIL
1052 //////////////////////////////////////////////////////////////////////
1053 // All of these null head and tail are now non lazy using e.g. null(a)().
1054 // They need an extra () e.g. null(a)().
1055 
1056 // FIX THIS comparison operators can be implemented simpler with enable_if
1057 template <class T>
operator ==(const odd_list<T> & a,a_unique_type_for_nil)1058 bool operator==( const odd_list<T>& a, a_unique_type_for_nil ) {
1059   return null(a)();
1060 }
1061 template <class T>
operator ==(const list<T> & a,a_unique_type_for_nil)1062 bool operator==( const list<T>& a, a_unique_type_for_nil ) {
1063   return null(a)();
1064 }
1065 template <class T>
operator ==(a_unique_type_for_nil,const odd_list<T> & a)1066 bool operator==( a_unique_type_for_nil, const odd_list<T>& a ) {
1067   return null(a)();
1068 }
1069 template <class T>
operator ==(a_unique_type_for_nil,const list<T> & a)1070 bool operator==( a_unique_type_for_nil, const list<T>& a ) {
1071   return null(a)();
1072 }
1073 template <class T>
operator ==(const list<T> & a,const list<T> & b)1074 bool operator==( const list<T>& a, const list<T>& b ) {
1075   if( null(a)() && null(b)() )
1076       return true;
1077   if( null(a)() || null(b)() )
1078       return false;
1079   return (head(a)()==head(b)()) && (tail(a)()==tail(b)());
1080 }
1081 template <class T>
operator ==(const odd_list<T> & a,const odd_list<T> & b)1082 bool operator==( const odd_list<T>& a, const odd_list<T>& b ) {
1083   if( null(a)() && null(b)() )
1084       return true;
1085   if( null(a)() || null(b)() )
1086       return false;
1087   return (head(a)()==head(b)()) && (tail(a)()==tail(b)());
1088 }
1089 template <class T>
operator ==(const list<T> & a,const odd_list<T> & b)1090 bool operator==( const list<T>& a, const odd_list<T>& b ) {
1091   if( null(a)() && null(b)() )
1092       return true;
1093   if( null(a)() || null(b)() )
1094       return false;
1095   return (head(a)()==head(b)()) && (tail(a)()==tail(b)());
1096 }
1097 template <class T>
operator ==(const odd_list<T> & a,const list<T> & b)1098 bool operator==( const odd_list<T>& a, const list<T>& b ) {
1099   if( null(a)() && null(b)() )
1100       return true;
1101   if( null(a)() || null(b)() )
1102       return false;
1103   return (head(a)()==head(b)()) && (tail(a)()==tail(b)());
1104 }
1105 
1106 template <class T>
operator <(const list<T> & a,const list<T> & b)1107 bool operator<( const list<T>& a, const list<T>& b ) {
1108   if( null(a)() && !null(b)() )  return true;
1109   if( null(b)() )              return false;
1110   if( head(b)() < head(a)() )    return false;
1111   if( head(a)() < head(b)() )    return true;
1112   return (tail(a)() < tail(b)());
1113 }
1114 template <class T>
operator <(const odd_list<T> & a,const list<T> & b)1115 bool operator<( const odd_list<T>& a, const list<T>& b ) {
1116   if( null(a)() && !null(b)() )  return true;
1117   if( null(b)() )              return false;
1118   if( head(b)() < head(a)() )    return false;
1119   if( head(a)() < head(b)() )    return true;
1120   return (tail(a)() < tail(b)());
1121 }
1122 template <class T>
operator <(const list<T> & a,const odd_list<T> & b)1123 bool operator<( const list<T>& a, const odd_list<T>& b ) {
1124    if( null(a) && !null(b) )  return true;
1125    if( null(b) )              return false;
1126    if( head(b) < head(a) )    return false;
1127    if( head(a) < head(b) )    return true;
1128    return (tail(a) < tail(b));
1129 }
1130 template <class T>
operator <(const odd_list<T> & a,const odd_list<T> & b)1131 bool operator<( const odd_list<T>& a, const odd_list<T>& b ) {
1132   if( null(a)() && !null(b)() )  return true;
1133   if( null(b)() )              return false;
1134   if( head(b)() < head(a)() )    return false;
1135   if( head(a)() < head(b)() )    return true;
1136   return (tail(a)() < tail(b)());
1137 }
1138 template <class T>
operator <(const odd_list<T> &,a_unique_type_for_nil)1139 bool operator<( const odd_list<T>&, a_unique_type_for_nil ) {
1140    return false;
1141 }
1142 template <class T>
operator <(const list<T> &,a_unique_type_for_nil)1143 bool operator<( const list<T>&, a_unique_type_for_nil ) {
1144    return false;
1145 }
1146 template <class T>
operator <(a_unique_type_for_nil,const odd_list<T> & b)1147 bool operator<( a_unique_type_for_nil, const odd_list<T>& b ) {
1148   return !null(b)();
1149 }
1150 template <class T>
operator <(a_unique_type_for_nil,const list<T> & b)1151 bool operator<( a_unique_type_for_nil, const list<T>& b ) {
1152   return !null(b)();
1153 }
1154 
1155 //////////////////////////////////////////////////////////////////////
1156 // Implement cat and cons after the list types are defined.
1157 //////////////////////////////////////////////////////////////////////
1158     namespace impl {
1159       using listlike::ListLike;
1160 
1161       template <class T, class F, class L>
1162       struct ConsHelp2<T,F,L,true>
1163       {
1164          typedef typename boost::remove_reference<T>::type TT;
1165          typedef typename L::force_result_type type;
goboost::phoenix::impl::ConsHelp21166          static type go( const TT& x, const F& f ) {
1167             return type( x, f );
1168          }
1169       };
1170       template <class T, class F>
1171       struct ConsHelp2<T,F,list<T>,true>
1172       {
1173          typedef typename boost::remove_reference<T>::type TT;
1174          typedef list<TT> L;
1175          typedef typename L::force_result_type type;
goboost::phoenix::impl::ConsHelp21176          static type go( const TT& x, const F& f ) {
1177             return odd_list<TT>(x, list<TT>(
1178             boost::intrusive_ptr<Cache<TT> >(new Cache<T>(
1179             typename Cache<TT>::CvtFxn(),f))));
1180          }
1181        };
1182        template <class T, class F>
1183        struct ConsHelp2<T,F,odd_list<T>,true>
1184        {
1185           typedef typename boost::remove_reference<T>::type TT;
1186           typedef odd_list<TT> L;
1187           typedef typename L::force_result_type type;
goboost::phoenix::impl::ConsHelp21188           static type go( const TT& x, const F& f ) {
1189               return odd_list<TT>(x, list<TT>( ListRaw(), new Cache<T>(f) ));
1190           }
1191        };
1192        template <class T, class F>
1193        struct ConsHelp2<T,F,a_unique_type_for_nil,false>
1194        {
1195           typedef typename boost::remove_reference<T>::type TT;
1196           typedef odd_list<TT> type;
goboost::phoenix::impl::ConsHelp21197           static type go( const TT& x, const F& f ) {
1198              return odd_list<TT>(x, list<TT>( ListRaw(), new Cache<T>(f) ));
1199           }
1200        };
1201 
1202        template <class T, class L, bool b> struct ConsHelp1 {
1203           typedef typename boost::remove_reference<T>::type TT;
1204           typedef typename L::force_result_type type;
goboost::phoenix::impl::ConsHelp11205           static type go( const TT& x, const L& l ) {
1206              return type(x,l);
1207           }
1208        };
1209       template <class T> struct ConsHelp1<T,a_unique_type_for_nil,false> {
1210         typedef typename boost::remove_reference<T>::type TT;
1211         typedef odd_list<TT> type;
goboost::phoenix::impl::ConsHelp11212         static type go( const TT& x, const a_unique_type_for_nil& n ) {
1213         return type(x,n);
1214         }
1215       };
1216       template <class T, class F> struct ConsHelp1<T,F,false> {
1217         // It's a function returning a list
1218         // This is the one I have not fixed yet....
1219         // typedef typename F::result_type L;
1220         // typedef typename result_of::template ListType<F>::result_type L;
1221         typedef odd_list<T> L;
1222         typedef ConsHelp2<T,F,L,boost::is_base_and_derived<ListLike,L>::value> help;
1223         typedef typename help::type type;
goboost::phoenix::impl::ConsHelp11224         static type go( const T& x, const F& f ) {
1225            return help::go(x,f);
1226         }
1227       };
1228 
1229       template <class T, class L, bool b>
1230       struct ConsHelp0;
1231 
1232       template <class T>
1233       struct ConsHelp0<T,a_unique_type_for_nil,true> {
1234         typedef typename boost::remove_reference<T>::type TT;
1235         typedef odd_list<T> type;
1236       };
1237 
1238       template <class T>
1239       struct ConsHelp0<const T &,const a_unique_type_for_nil &,true> {
1240         typedef typename boost::remove_reference<T>::type TT;
1241         typedef odd_list<TT> type;
1242       };
1243 
1244       template <class T>
1245       struct ConsHelp0<T &,a_unique_type_for_nil &,true> {
1246         typedef typename boost::remove_reference<T>::type TT;
1247         typedef odd_list<TT> type;
1248       };
1249 
1250       template <class T, class L>
1251       struct ConsHelp0<T,L,false> {
1252           // This removes any references from L for correct return type
1253           // identification.
1254            typedef typename boost::remove_reference<L>::type LType;
1255            typedef typename ConsHelp1<T,LType,
1256            boost::is_base_and_derived<ListLike,LType>::value>::type type;
1257       };
1258 
1259       /////////////////////////////////////////////////////////////////////
1260       // cons (t,l) - cons a value to the front of a list.
1261       // Note: The first arg,  t, must be a value.
1262       //       The second arg, l, can be a list or NIL
1263       //       or a function that returns a list.
1264       /////////////////////////////////////////////////////////////////////
1265       struct Cons
1266       {
1267         /* template <class T, class L> struct sig : public fun_type<
1268         typename ConsHelp1<T,L,
1269       boost::is_base_and_derived<ListLike,L>::value>::type> {};
1270         */
1271         template <typename Sig> struct result;
1272 
1273         template <typename This, typename T, typename L>
1274         struct result<This(T, L)>
1275         {
1276           typedef typename ConsHelp0<T,L,
1277           listlike::detect_nil<L>::is_nil>::type type;
1278         };
1279 
1280         template <typename This, typename T>
1281         struct result<This(T,a_unique_type_for_nil)>
1282         {
1283           typedef typename boost::remove_reference<T>::type TT;
1284           typedef odd_list<TT> type;
1285         };
1286 
1287         template <typename T, typename L>
1288         typename result<Cons(T,L)>::type
operator ()boost::phoenix::impl::Cons1289         operator()( const T& x, const L& l ) const {
1290            typedef typename result_of::ListType<L>::LType LType;
1291            typedef ConsHelp1<T,LType,
1292            boost::is_base_and_derived<ListLike,LType>::value> help;
1293            return help::go(x,l);
1294           }
1295 
1296         template <typename T>
1297         typename result<Cons(T,a_unique_type_for_nil)>::type
operator ()boost::phoenix::impl::Cons1298         operator()( const T& x, const a_unique_type_for_nil &n ) const {
1299            typedef typename result<Cons(T,a_unique_type_for_nil)>::type LL;
1300            typedef ConsHelp1<T,LL,
1301            boost::is_base_and_derived<ListLike,LL>::value> help;
1302            return help::go(x,n);
1303           }
1304 
1305       };
1306     }
1307 
1308     typedef boost::phoenix::function<impl::Cons> Cons;
1309     Cons cons;
1310 
1311     namespace impl {
1312 
1313       template <class L, class M, bool b>
1314       struct CatHelp0;
1315 
1316       template <class LL>
1317       struct CatHelp0<LL,a_unique_type_for_nil,true> {
1318         typedef typename result_of::template ListType<LL>::LType type;
1319       };
1320 
1321       template <class LL>
1322       struct CatHelp0<const LL &,const a_unique_type_for_nil &,true> {
1323         typedef typename result_of::template ListType<LL>::LType type;
1324         //typedef L type;
1325       };
1326 
1327       template <class LL>
1328       struct CatHelp0<LL &,a_unique_type_for_nil &,true> {
1329         typedef typename result_of::template ListType<LL>::LType type;
1330         //typedef L type;
1331       };
1332 
1333       template <class LL, class MM>
1334       struct CatHelp0<LL,MM,false> {
1335           // This removes any references from L for correct return type
1336           // identification.
1337         typedef typename result_of::template ListType<LL>::LType type;
1338         //    typedef typename ConsHelp1<T,LType,
1339         //   boost::is_base_and_derived<ListLike,LType>::value>::type type;
1340       };
1341 
1342       /////////////////////////////////////////////////////////////////////
1343       // cat (l,m) - concatenate lists.
1344       // Note: The first arg,  l, must be a list or NIL.
1345       //       The second arg, m, can be a list or NIL
1346       //       or a function that returns a list.
1347       /////////////////////////////////////////////////////////////////////
1348       struct Cat
1349       {
1350          template <class L, class M, bool b, class R>
1351          struct Helper /*: public c_fun_type<L,M,R>*/ {
1352            template <typename Sig> struct result;
1353 
1354            template <typename This>
1355            struct result<This(L,M)>
1356           {
1357              typedef typename result_of::ListType<L>::tail_result_type type;
1358           };
1359 
1360            typedef R return_type;
operator ()boost::phoenix::impl::Cat::Helper1361            R operator()( const L& l, const M& m,
1362              reuser2<INV,VAR,INV,Helper,
1363              typename result_of::template ListType<L>::tail_result_type,M>
1364              r = NIL ) const {
1365              if( null(l)() )
1366                 return m().force();
1367              else
1368                 return cons( head(l)(), r( Helper<L,M,b,R>(), tail(l), m )() );
1369          }
1370       };
1371           template <class L, class M, class R>
1372           struct Helper<L,M,true,R> /*: public c_fun_type<L,M,R>*/ {
1373            template <typename Sig> struct result;
1374 
1375            template <typename This>
1376            struct result<This(L,M)>
1377           {
1378              typedef typename result_of::ListType<L>::tail_result_type type;
1379           };
1380           typedef R return_type;
operator ()boost::phoenix::impl::Cat::Helper1381           R operator()( const L& l, const M& m,
1382              reuser2<INV,VAR,INV,Helper,
1383              typename result_of::template ListType<L>::tail_result_type,M>
1384              r = NIL ) const {
1385              if( null(l)() )
1386                 return m.force();
1387              else
1388                 return cons( head(l)(), r(Helper<L,M,true,R>(), tail(l), m )());
1389          }
1390       };
1391       template <class L, class R>
1392       struct Helper<L,a_unique_type_for_nil,false,R>
1393       /*: public c_fun_type<L,
1394         a_unique_type_for_nil,odd_list<typename L::value_type> > */
1395       {
1396         typedef odd_list<typename result_of::template ListType<L>::value_type> type;
1397         odd_list<typename result_of::template ListType<L>::value_type>
operator ()boost::phoenix::impl::Cat::Helper1398         operator()( const L& l, const a_unique_type_for_nil& ) const {
1399          return l;
1400         }
1401       };
1402    public:
1403         /*template <class L, class M> struct sig : public fun_type<
1404         typename RT<cons_type,typename L::value_type,M>::result_type>
1405       {}; */
1406    // Need to work out the return type here.
1407       template <typename Sig> struct result;
1408 
1409       template <typename This, typename L, typename M>
1410       struct result<This(L,M)>
1411       {
1412         typedef typename CatHelp0<L,M,
1413           listlike::detect_nil<M>::is_nil>::type type;
1414         // typedef typename result_of::ListType<L>::tail_result_type type;
1415       };
1416 
1417       template <typename This, typename L>
1418       struct result<This(L,a_unique_type_for_nil)>
1419       {
1420          typedef typename result_of::ListType<L>::tail_result_type type;
1421       };
1422       template <class L, class M>
operator ()boost::phoenix::impl::Cat1423       typename result<Cat(L,M)>::type operator()( const L& l, const M& m ) const
1424       {
1425          listlike::EnsureListLike<L>();
1426          return Helper<L,M,
1427          boost::is_base_and_derived<typename listlike::ListLike,M>::value,
1428                 typename result<Cat(L,M)>::type>()(l,m);
1429       }
1430 
1431       template <class L>
operator ()boost::phoenix::impl::Cat1432       typename result<Cat(L,a_unique_type_for_nil)>::type operator()( const L& l, const a_unique_type_for_nil& /* n */ ) const
1433       {
1434          listlike::EnsureListLike<L>();
1435          return l;
1436       }
1437 
1438       };
1439 
1440 
1441     }
1442 
1443     typedef boost::phoenix::function<impl::Cat> Cat;
1444     Cat cat;
1445 
1446 
1447 //////////////////////////////////////////////////////////////////////
1448 // Handy functions for making list literals
1449 //////////////////////////////////////////////////////////////////////
1450 // Yes, these aren't functoids, they're just template functions.  I'm
1451 // lazy and created these mostly to make it easily to make little lists
1452 // in the sample code snippets that appear in papers.
1453 
1454 struct UseList {
1455    template <class T> struct List { typedef list<T> type; };
1456 };
1457 struct UseOddList {
1458    template <class T> struct List { typedef odd_list<T> type; };
1459 };
1460 struct UseStrictList {
1461    template <class T> struct List { typedef strict_list<T> type; };
1462 };
1463 
1464 template <class Kind = UseList>
1465 struct list_with {
1466    template <class T>
1467    typename Kind::template List<T>::type
operator ()boost::phoenix::list_with1468    operator()( const T& a ) const {
1469       typename Kind::template List<T>::type l;
1470       l = cons( a, l );
1471       return l;
1472    }
1473 
1474    template <class T>
1475    typename Kind::template List<T>::type
operator ()boost::phoenix::list_with1476    operator()( const T& a, const T& b ) const {
1477       typename Kind::template List<T>::type l;
1478       l = cons( b, l );
1479       l = cons( a, l );
1480       return l;
1481    }
1482 
1483    template <class T>
1484    typename Kind::template List<T>::type
operator ()boost::phoenix::list_with1485    operator()( const T& a, const T& b, const T& c ) const {
1486       typename Kind::template List<T>::type l;
1487       l = cons( c, l );
1488       l = cons( b, l );
1489       l = cons( a, l );
1490       return l;
1491    }
1492 
1493    template <class T>
1494    typename Kind::template List<T>::type
operator ()boost::phoenix::list_with1495    operator()( const T& a, const T& b, const T& c, const T& d ) const {
1496       typename Kind::template List<T>::type l;
1497       l = cons( d, l );
1498       l = cons( c, l );
1499       l = cons( b, l );
1500       l = cons( a, l );
1501       return l;
1502    }
1503 
1504    template <class T>
1505    typename Kind::template List<T>::type
operator ()boost::phoenix::list_with1506    operator()( const T& a, const T& b, const T& c, const T& d,
1507                const T& e ) const {
1508       typename Kind::template List<T>::type l;
1509       l = cons( e, l );
1510       l = cons( d, l );
1511       l = cons( c, l );
1512       l = cons( b, l );
1513       l = cons( a, l );
1514       return l;
1515    }
1516 };
1517 //////////////////////////////////////////////////////////////////////
1518 
1519   }
1520 
1521 }
1522 
1523 #endif
1524