////////////////////////////////////////////////////////////////////////////
// lazy_list.hpp
//
// Build lazy operations for Phoenix equivalents for FC++
//
// These are equivalents of the Boost FC++ functoids in list.hpp
//
// Implemented so far:
//
// head tail null
//
// strict_list<T> and associated iterator.
//
// list<T> and odd_list<T>
//
// cons cat
//
// Comparisons between list and odd_list types and separately for strict_list.
//
// NOTES: There is a fix at the moment as I have not yet sorted out
//        how to get back the return type of a functor returning a list type.
//        For the moment I have fixed this as odd_list<T> at two locations,
//        one in list<T> and one in Cons. I am going to leave it like this
//        for now as reading the code, odd_list<T> seems to be correct.
//
//        I am also not happy at the details needed to detect types in Cons.
//
// I think the structure of this file is now complete.
// John Fletcher  February 2015.
//
////////////////////////////////////////////////////////////////////////////
/*=============================================================================
    Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis
    Copyright (c) 2001-2007 Joel de Guzman
    Copyright (c) 2015 John Fletcher

    Distributed under the Boost Software License, Version 1.0. (See accompanying
    file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/

///////////////////////////////////////////////////////////////////////
// This is from Boost FC++ list.hpp reimplemented without Fun0 or Full0
///////////////////////////////////////////////////////////////////////

/*
concept ListLike: Given a list representation type L

L<T> inherits ListLike and has
   // typedefs just show typical values
   typedef T value_type
   typedef L<T> force_result_type
   typedef L<T> delay_result_type
   typedef L<T> tail_result_type
   template <class UU> struct cons_rebind {
      typedef L<UU> type;        // force type
      typedef L<UU> delay_type;  // delay type
   };

   L()
   L( a_unique_type_for_nil )
   template <class F> L(F)       // F :: ()->L

   constructor: force_result_type( T, L<T> )
   template <class F>
   constructor: force_result_type( T, F )  // F :: ()->L

   template <class It>
   L( It, It )

   // FIX THIS instead of operator bool(), does Boost have something better?
   operator bool() const
   force_result_type force() const
   delay_result_type delay() const
   T head() const
   tail_result_type tail() const

   static const bool is_lazy;   // true if can represent infinite lists

   typedef const_iterator;
   typedef const_iterator iterator;  // ListLikes are immutable
   iterator begin() const
   iterator end() const
*/

//////////////////////////////////////////////////////////////////////
// End of section from Boost FC++ list.hpp
//////////////////////////////////////////////////////////////////////

#ifndef BOOST_PHOENIX_FUNCTION_LAZY_LIST
#define BOOST_PHOENIX_FUNCTION_LAZY_LIST

#include <boost/phoenix/core.hpp>
#include <boost/phoenix/function.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/function.hpp>
#include <boost/type_traits/type_with_alignment.hpp>
//#include "lazy_reuse.hpp"

namespace boost {

  namespace phoenix {

//////////////////////////////////////////////////////////////////////
// These are the list types being declared.
//////////////////////////////////////////////////////////////////////

   template <class T> class strict_list;
    namespace impl {
   template <class T> class list;
   template <class T> class odd_list;
    }
   // in ref_count.hpp in BoostFC++ now in lazy_operator.hpp
   //typedef unsigned int RefCountType;

//////////////////////////////////////////////////////////////////////
// a_unique_type_for_nil moved to lazy_operator.hpp.
//////////////////////////////////////////////////////////////////////


//////////////////////////////////////////////////////////////////////
// Distinguish lazy lists (list and odd_list) from strict_list.
//////////////////////////////////////////////////////////////////////

    namespace lazy {
      // Copied from Boost FC++ list.hpp
      template <class L, bool is_lazy> struct ensure_lazy_helper {};
      template <class L> struct ensure_lazy_helper<L,true> {
         static void requires_lazy_list_to_prevent_infinite_recursion() {}
      };
      template <class L>
      void ensure_lazy() {
        ensure_lazy_helper<L,L::is_lazy>::
        requires_lazy_list_to_prevent_infinite_recursion();
      }

    }

//////////////////////////////////////////////////////////////////////
// Provide remove reference for types defined for list types.
//////////////////////////////////////////////////////////////////////

    namespace result_of {

      template < typename L >
      class ListType
      {
      public:
        typedef typename boost::remove_reference<L>::type LType;
        typedef typename LType::value_type value_type;
        typedef typename LType::tail_result_type tail_result_type;
        typedef typename LType::force_result_type force_result_type;
        typedef typename LType::delay_result_type delay_result_type;
      };

      template <>
      class ListType<a_unique_type_for_nil>
      {
      public:
        typedef a_unique_type_for_nil LType;
        //typedef a_unique_type_for_nil value_type;
      };

      template <typename F, typename T>
      struct ResultType {
        typedef typename impl::odd_list<T> type;
      };
  
    }

//////////////////////////////////////////////////////////////////////
// ListLike is a property inherited by any list type to enable it to
// work with the functions being implemented in this file.
// It provides the check for the structure described above.
//////////////////////////////////////////////////////////////////////

   namespace listlike {

       struct ListLike {};   // This lets us use is_base_and_derived() to see
       // (at compile-time) what classes are user-defined lists.

 
       template <class L, bool is_lazy> struct ensure_lazy_helper {};
       template <class L> struct ensure_lazy_helper<L,true> {
           static void requires_lazy_list_to_prevent_infinite_recursion() {}
       };
       template <class L>
       void ensure_lazy() {
         ensure_lazy_helper<L,L::is_lazy>::
         requires_lazy_list_to_prevent_infinite_recursion();
       }

       template <class L, bool b>
       struct EnsureListLikeHelp {
           static void trying_to_call_a_list_function_on_a_non_list() {}
       };
       template <class L> struct EnsureListLikeHelp<L,false> { };
       template <class L>
       void EnsureListLike() {
          typedef typename result_of::ListType<L>::LType LType;
          EnsureListLikeHelp<L,boost::is_base_and_derived<ListLike,LType>::value>::
             trying_to_call_a_list_function_on_a_non_list();
       }

      template <class L>
      bool is_a_unique_type_for_nil(const L& /*l*/) {
         return false;
      }

      template <>
      bool is_a_unique_type_for_nil<a_unique_type_for_nil>
      (const a_unique_type_for_nil& /* n */) {
         return true;
      }

      template <class L>
      struct detect_nil {
        static const bool is_nil = false;
      };

      template <>
      struct detect_nil<a_unique_type_for_nil> {
       static const bool is_nil = true;
      };

      template <>
      struct detect_nil<a_unique_type_for_nil&> {
       static const bool is_nil = true;
      };

      template <>
      struct detect_nil<const a_unique_type_for_nil&> {
       static const bool is_nil = true;
      };
          
    }

//////////////////////////////////////////////////////////////////////
// Implement lazy functions for list types. cat and cons come later.
//////////////////////////////////////////////////////////////////////

#ifndef BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH
#define BOOST_PHOENIX_FUNCTION_MAX_LAZY_LIST_LENGTH 1000
#endif

    namespace impl {

      struct Head
      {
        template <typename Sig>
        struct result;

        template <typename This, typename L>
        struct result<This(L)>
        {
          typedef typename result_of::ListType<L>::value_type type;
        };

        template <typename L>
        typename result<Head(L)>::type
        operator()(const L & l) const
        {
          listlike::EnsureListLike<L>();
          return l.head();
        }

      };

      struct Tail
      {
        template <typename Sig>
        struct result;

        template <typename This, typename L>
        struct result<This(L)>
        {
          typedef typename result_of::ListType<L>::tail_result_type type;
        };

        template <typename L>
        typename result<Tail(L)>::type
        operator()(const L & l) const
        {
          listlike::EnsureListLike<L>();
          return l.tail();
        }

      };

      struct Null
      {
        template <typename Sig>
        struct result;

        template <typename This, typename L>
        struct result<This(L)>
        {
            typedef bool type;
        };

        template <typename L>
        typename result<Null(L)>::type
        //bool
        operator()(const L& l) const
        {
          listlike::EnsureListLike<L>();
          return !l;
        }

      };

      struct Delay {
        template <typename Sig>
        struct result;

        template <typename This, typename L>
        struct result<This(L)>
        {
          typedef typename result_of::ListType<L>::delay_result_type type;
        };

        template <typename L>
        typename result<Delay(L)>::type
        operator()(const L & l) const
        {
          listlike::EnsureListLike<L>();
          return l.delay();
        }

      };

      struct Force {
        template <typename Sig>
        struct result;

        template <typename This, typename L>
        struct result<This(L)>
        {
          typedef typename result_of::ListType<L>::force_result_type type;
        };

        template <typename L>
        typename result<Force(L)>::type
        operator()(const L & l) const
        {
          listlike::EnsureListLike<L>();
          return l.force();
        }

      };

    }
    //BOOST_PHOENIX_ADAPT_CALLABLE(head, impl::head, 1)
    //BOOST_PHOENIX_ADAPT_CALLABLE(tail, impl::tail, 1)
    //BOOST_PHOENIX_ADAPT_CALLABLE(null, impl::null, 1)
    typedef boost::phoenix::function<impl::Head> Head;
    typedef boost::phoenix::function<impl::Tail> Tail;
    typedef boost::phoenix::function<impl::Null> Null;
    typedef boost::phoenix::function<impl::Delay> Delay;
    typedef boost::phoenix::function<impl::Force> Force;
    Head head;
    Tail tail;
    Null null;
    Delay delay;
    Force force;

//////////////////////////////////////////////////////////////////////
// These definitions used for strict_list are imported from BoostFC++
// unchanged.
//////////////////////////////////////////////////////////////////////

namespace impl {
template <class T>
struct strict_cons : public boost::noncopyable {
   mutable RefCountType refC;
   T head;
   typedef boost::intrusive_ptr<strict_cons> tail_type;
   tail_type tail;
   strict_cons( const T& h, const tail_type& t ) : refC(0), head(h), tail(t) {}

};
template <class T>
void intrusive_ptr_add_ref( const strict_cons<T>* p ) {
   ++ (p->refC);
}
template <class T>
void intrusive_ptr_release( const strict_cons<T>* p ) {
   if( !--(p->refC) ) delete p;
}

template <class T>
class strict_list_iterator
: public std::iterator<std::input_iterator_tag,T,ptrdiff_t> {
   typedef boost::intrusive_ptr<strict_cons<T> > rep_type;
   rep_type l;
   bool is_nil;
   void advance() {
      l = l->tail;
      if( !l )
         is_nil = true;
   }
   class Proxy {  // needed for operator->
      const T x;
      friend class strict_list_iterator;
      Proxy( const T& xx ) : x(xx) {}
   public:
      const T* operator->() const { return &x; }
   };
public:
   strict_list_iterator() : l(), is_nil(true) {}
   explicit strict_list_iterator( const rep_type& ll ) : l(ll), is_nil(!ll) {}
   
   const T operator*() const { return l->head; }
   const Proxy operator->() const { return Proxy(l->head); }
   strict_list_iterator<T>& operator++() {
      advance();
      return *this;
   }
   const strict_list_iterator<T> operator++(int) {
      strict_list_iterator<T> i( *this );
      advance();
      return i;
   }
   bool operator==( const strict_list_iterator<T>& i ) const {
      return is_nil && i.is_nil;
   }
   bool operator!=( const strict_list_iterator<T>& i ) const {
      return ! this->operator==(i);
   }
};
}

//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////

   template <class T>
   class strict_list : public listlike::ListLike
   {
       typedef boost::intrusive_ptr<impl::strict_cons<T> > rep_type;
       rep_type rep;
       struct Make {};

       template <class Iter>
       static rep_type help( Iter a, const Iter& b ) {
           rep_type r;
           while( a != b ) {
              T x( *a );
              r = rep_type( new impl::strict_cons<T>( x, r ) );
              ++a;
           }
           return r;
       }

   public:
       static const bool is_lazy = false;

       typedef T value_type;
       typedef strict_list force_result_type;
       typedef strict_list delay_result_type;
       typedef strict_list tail_result_type;
       template <class UU> struct cons_rebind {
           typedef strict_list<UU> type;
           typedef strict_list<UU> delay_type;
       };
 

   strict_list( Make, const rep_type& r ) : rep(r) {}

   strict_list() : rep() {}

   strict_list( a_unique_type_for_nil ) : rep() {}

   template <class F>
   strict_list( const F& f ) : rep( f().rep ) {
     // I cannot do this yet.
     //functoid_traits<F>::template ensure_accepts<0>::args();
   }

   strict_list( const T& x, const strict_list& y )
      : rep( new impl::strict_cons<T>(x,y.rep) ) {}

   template <class F>
   strict_list( const T& x, const F& f )
      : rep( new impl::strict_cons<T>(x,f().rep) ) {}
   
     operator bool() const { return (bool)rep; }
   force_result_type force() const { return *this; }
   delay_result_type delay() const { return *this; }
   T head() const {
#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
      if( !*this )
         throw lazy_exception("Tried to take head() of empty strict_list");
#endif
      return rep->head;
   }
   tail_result_type tail() const {
#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
      if( !*this )
         throw lazy_exception("Tried to take tail() of empty strict_list");
#endif
      return strict_list(Make(),rep->tail);
   }

   template <class Iter>
   strict_list( const Iter& a, const Iter& b ) : rep( rep_type() ) {
      // How ironic.  We need to reverse the iterator range in order to
      // non-recursively build this!
      std::vector<T> tmp(a,b);
      rep = help( tmp.rbegin(), tmp.rend() );
   }

   // Since the strict_cons destructor can't call the strict_list
   // destructor, the "simple" iterative destructor is correct and
   // efficient.  Hurray.
   ~strict_list() { while(rep && (rep->refC == 1)) rep = rep->tail; }

   // The following helps makes strict_list almost an STL "container"
   typedef impl::strict_list_iterator<T> const_iterator;
   typedef const_iterator iterator;         // strict_list is immutable
   iterator begin() const { return impl::strict_list_iterator<T>( rep ); }
   iterator end() const   { return impl::strict_list_iterator<T>(); }

   };

    // All of these null head and tail are now non lazy using e.g. null(a)().
    // They need an extra () e.g. null(a)().
    template <class T>
    bool operator==( const strict_list<T>& a, a_unique_type_for_nil ) {
      return null(a)();
    }
    template <class T>
    bool operator==( a_unique_type_for_nil, const strict_list<T>& a ) {
      return null(a)();
    }
    template <class T>
    bool operator==( const strict_list<T>& a, const strict_list<T>& b ) {
        if( null(a)() && null(b)() )
            return true;
        if( null(a)() || null(b)() )
            return false;
        return (head(a)()==head(b)()) &&
            (tail(a)()==tail(b)());
    }

    template <class T>
    bool operator<( const strict_list<T>& a, const strict_list<T>& b ) {
      if( null(a)() && !null(b)() )  return true;
        if( null(b)() )                      return false;
        if( head(b)() < head(a)() )    return false;
        if( head(a)() < head(b)() )    return true;
        return (tail(a)() < tail(b)());
    }
    template <class T>
    bool operator<( const strict_list<T>&, a_unique_type_for_nil ) {
        return false;
    }
    template <class T>
    bool operator<( a_unique_type_for_nil, const strict_list<T>& b ) {
      return !(null(b)());
    }

//////////////////////////////////////////////////////////////////////
// Class list<T> is the primary interface to the user for lazy lists.
//////////////////////////////////////////////////////////////////////{
    namespace impl {
      using fcpp::INV;
      using fcpp::VAR;
      using fcpp::reuser2;

      struct CacheEmpty {};

      template <class T> class Cache;
      template <class T> class odd_list;
      template <class T> class list_iterator;
      template <class It, class T>
      struct ListItHelp2 /*: public c_fun_type<It,It,odd_list<T> >*/ {
        // This will need a return type.
        typedef odd_list<T> return_type;
        odd_list<T> operator()( It begin, const It& end,
          reuser2<INV,VAR,INV,ListItHelp2<It,T>,It,It> r = NIL ) const;
      };
      template <class U,class F> struct cvt;
      template <class T, class F, class R> struct ListHelp;
      template <class T> Cache<T>* xempty_helper();
      template <class T, class F, class L, bool b> struct ConsHelp2;

      struct ListRaw {};

      template <class T>
      class list : public listlike::ListLike
      {
        // never NIL, unless an empty odd_list
        boost::intrusive_ptr<Cache<T> > rep;

        template <class U> friend class Cache;
        template <class U> friend class odd_list;
        template <class TT, class F, class L, bool b> friend struct ConsHelp2;
        template <class U,class F> friend struct cvt;

        list( const boost::intrusive_ptr<Cache<T> >& p ) : rep(p) { }
        list( ListRaw, Cache<T>* p ) : rep(p) { }

        bool priv_isEmpty() const {
          return rep->cache().second.rep == Cache<T>::XNIL();
        }
        T priv_head() const {
#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
          if( priv_isEmpty() )
             throw lazy_exception("Tried to take head() of empty list");
#endif
          return rep->cache().first();
        }
        list<T> priv_tail() const {
#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
          if( priv_isEmpty() )
            throw lazy_exception("Tried to take tail() of empty list");
#endif
          return rep->cache().second;
        }


      public:
        static const bool is_lazy = true;

        typedef T value_type;
        typedef list tail_result_type;
        typedef odd_list<T> force_result_type;
        typedef list delay_result_type;
        template <class UU> struct cons_rebind {
           typedef odd_list<UU> type;
           typedef list<UU> delay_type;
        };

        list( a_unique_type_for_nil ) : rep( Cache<T>::XEMPTY() ) { }
        list() : rep( Cache<T>::XEMPTY() ) { }

        template <class F>  // works on both ()->odd_list and ()->list
        // At the moment this is fixed for odd_list<T>.
        // I need to do more work to get the general result.
        list( const F& f )
          : rep( ListHelp<T,F,odd_list<T> >()(f) ) { }
        //: rep( ListHelp<T,F,typename F::result_type>()(f) ) { }

        operator bool() const { return !priv_isEmpty(); }
        const force_result_type& force() const { return rep->cache(); }
        const delay_result_type& delay() const { return *this; }
        // Note: force returns a reference;
        // implicit conversion now returns a copy.
        operator odd_list<T>() const { return force(); }

        T head() const { return priv_head(); }
        tail_result_type tail() const { return priv_tail(); }

        // The following helps makes list almost an STL "container"
        typedef list_iterator<T> const_iterator;
        typedef const_iterator iterator;         // list is immutable
        iterator begin() const { return list_iterator<T>( *this ); }
        iterator end() const   { return list_iterator<T>(); }

        // end of list<T>
      };

//////////////////////////////////////////////////////////////////////
// Class odd_list<T> is not normally accessed by the user.
//////////////////////////////////////////////////////////////////////

      struct OddListDummyY {};

      template <class T>
      class odd_list : public listlike::ListLike
      {
      public:
        typedef
        typename boost::type_with_alignment<boost::alignment_of<T>::value>::type
        xfst_type;
      private:
        union { xfst_type fst; unsigned char dummy[sizeof(T)]; };

        const T& first() const {
           return *static_cast<const T*>(static_cast<const void*>(&fst));
        }
        T& first() {
           return *static_cast<T*>(static_cast<void*>(&fst));
        }
        list<T>  second;   // If XNIL, then this odd_list is NIL

        template <class U> friend class list;
        template <class U> friend class Cache;

        odd_list( OddListDummyY )
          : second( Cache<T>::XBAD() ) { }

        void init( const T& x ) {
           new (static_cast<void*>(&fst)) T(x);
        }

        bool fst_is_valid() const {
           if( second.rep != Cache<T>::XNIL() )
              if( second.rep != Cache<T>::XBAD() )
                 return true;
           return false;
        }

        bool priv_isEmpty() const { return second.rep == Cache<T>::XNIL(); }
        T priv_head() const {
#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
           if( priv_isEmpty() )
             throw lazy_exception("Tried to take head() of empty odd_list");
#endif
           return first();
        }

        list<T> priv_tail() const {
#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
           if( priv_isEmpty() )
             throw lazy_exception("Tried to take tail() of empty odd_list");
#endif
           return second;
        }

      public:
        static const bool is_lazy = true;

        typedef T value_type;
        typedef list<T> tail_result_type;
        typedef odd_list<T> force_result_type;
        typedef list<T> delay_result_type;
        template <class UU> struct cons_rebind {
          typedef odd_list<UU> type;
          typedef list<UU> delay_type;
        };

        odd_list() : second( Cache<T>::XNIL() ) { }
        odd_list( a_unique_type_for_nil ) : second( Cache<T>::XNIL() ) { }
        odd_list( const T& x, const list<T>& y ) : second(y) { init(x); }
        odd_list( const T& x, a_unique_type_for_nil ) : second(NIL) { init(x); }

        odd_list( const odd_list<T>& x ) : second(x.second) {
           if( fst_is_valid() ) {
              init( x.first() );
           }
        }

        template <class It>
        odd_list( It begin, const It& end )
          : second( begin==end ? Cache<T>::XNIL() :
             ( init(*begin++), list<T>( begin, end ) ) ) {}

        odd_list<T>& operator=( const odd_list<T>& x ) {
           if( this == &x ) return *this;
           if( fst_is_valid() ) {
             if( x.fst_is_valid() )
               first() = x.first();
             else
               first().~T();
           }
           else {
              if( x.fst_is_valid() )
                 init( x.first() );
           }
           second = x.second;
           return *this;
        }
      
       ~odd_list() {
          if( fst_is_valid() ) {
            first().~T();
          }
        }

        operator bool() const { return !priv_isEmpty(); }
        const force_result_type& force() const { return *this; }
        delay_result_type delay() const { return list<T>(*this); }

        T head() const { return priv_head(); }
        tail_result_type tail() const { return priv_tail(); }

        // The following helps makes odd_list almost an STL "container"
        typedef list_iterator<T> const_iterator;
        typedef const_iterator iterator;         // odd_list is immutable
        iterator begin() const { return list_iterator<T>( this->delay() ); }
        iterator end() const   { return list_iterator<T>(); }

        // end of odd_list<T>
      };

//////////////////////////////////////////////////////////////////////
// struct cvt
//////////////////////////////////////////////////////////////////////

      // This converts ()->list<T> to ()->odd_list<T>.
      // In other words, here is the 'extra work' done when using the
      // unoptimized interface.
      template <class U,class F>
      struct cvt /*: public c_fun_type<odd_list<U> >*/ {
        typedef odd_list<U> return_type;
        F f;
        cvt( const F& ff ) : f(ff) {}
        odd_list<U> operator()() const {
           list<U> l = f();
           return l.force();
        }
      };


//////////////////////////////////////////////////////////////////////
// Cache<T> and associated functions.
//////////////////////////////////////////////////////////////////////

// I malloc a RefCountType to hold the refCount and init it to 1 to ensure the
// refCount will never get to 0, so the destructor-of-global-object
// order at the end of the program is a non-issue.  In other words, the
// memory allocated here is only reclaimed by the operating system.
    template <class T>
    Cache<T>* xnil_helper() {
       void *p = std::malloc( sizeof(RefCountType) );
       *((RefCountType*)p) = 1;
       return static_cast<Cache<T>*>( p );
    }

    template <class T>
    Cache<T>* xnil_helper_nil() {
       Cache<T>* p = xnil_helper<T>();
       return p;
    }

    template <class T>
    Cache<T>* xnil_helper_bad() {
       Cache<T>* p = xnil_helper<T>();
       return p;
    }

    template <class T>
    Cache<T>* xempty_helper() {
       Cache<T>* p = new Cache<T>( CacheEmpty() );
       return p;
    }

    // This makes a boost phoenix function type with return type
    // odd_list<T>
    template <class T>
    struct fun0_type_helper{
       typedef boost::function0<odd_list<T> > fun_type;
       typedef boost::phoenix::function<fun_type> phx_type;
    };


      template <class T>
      struct make_fun0_odd_list {

        typedef typename fun0_type_helper<T>::fun_type fun_type;
        typedef typename fun0_type_helper<T>::phx_type phx_type;
        typedef phx_type result_type;

        template <class F>
        result_type operator()(const F& f) const
        {
            fun_type ff(f);
            phx_type g(ff);
            return g;
        }

        // Overload for the case where it is a boost phoenix function already.
        template <class F>
        typename boost::phoenix::function<F> operator()
          (const boost::phoenix::function<F>& f) const
        {
            return f;
        }

    };

    template <class T>
    class Cache : boost::noncopyable {
       mutable RefCountType refC;
       // This is the boost::function type
       typedef typename fun0_type_helper<T>::fun_type fun_odd_list_T;
       // This is the boost::phoenix::function type;
       typedef typename fun0_type_helper<T>::phx_type fun0_odd_list_T;
       mutable fun0_odd_list_T fxn;
       mutable odd_list<T>     val;
       // val.second.rep can be XBAD, XNIL, or a valid ptr
       //  - XBAD: val is invalid (fxn is valid)
       //  - XNIL: this is the empty list
       //  - anything else: val.first() is head, val.second is tail()

       // This functoid should never be called; it represents a
       // self-referent Cache, which should be impossible under the current
       // implementation.  Nonetheless, we need a 'dummy' function object to
       // represent invalid 'fxn's (val.second.rep!=XBAD), and this
       // implementation seems to be among the most reasonable.
       struct blackhole_helper /*: c_fun_type< odd_list<T> >*/ {
          typedef odd_list<T> return_type;
          odd_list<T> operator()() const {
#ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS
            throw lazy_exception("You have entered a black hole.");
#else
            return odd_list<T>();
#endif
          }
       };

       // Don't get rid of these XFOO() functions; they impose no overhead,
       // and provide a useful place to add debugging code for tracking down
       // before-main()-order-of-initialization problems.
       static const boost::intrusive_ptr<Cache<T> >& XEMPTY() {
          static boost::intrusive_ptr<Cache<T> > xempty( xempty_helper<T>() );
          return xempty;
       }
       static const boost::intrusive_ptr<Cache<T> >& XNIL() {
       // this list is nil
          static boost::intrusive_ptr<Cache<T> > xnil( xnil_helper_nil<T>() );
          return xnil;
       }

       static const boost::intrusive_ptr<Cache<T> >& XBAD() {
       // the pair is invalid; use fxn
          static boost::intrusive_ptr<Cache<T> > xbad( xnil_helper_bad<T>() );
          return xbad;
       }

       static fun0_odd_list_T /*<odd_list<T> >*/ the_blackhole;
       static fun0_odd_list_T& blackhole() {
         static fun0_odd_list_T the_blackhole;
         //( make_fun0_odd_list<T>()( blackhole_helper() ) );
         return the_blackhole;
       }

       odd_list<T>& cache() const {
         if( val.second.rep == XBAD() ) {
            val = fxn()();
            fxn = blackhole();
         }
         return val;
       }

       template <class U> friend class list;
       template <class U> friend class odd_list;
       template <class TT, class F, class L, bool b> friend struct ConsHelp2;
       template <class U,class F> friend struct cvt;
       template <class U, class F, class R> friend struct ListHelp;
       template <class U> friend Cache<U>* xempty_helper();

       Cache( CacheEmpty ) : refC(0), fxn(blackhole()), val() {}
       Cache( const odd_list<T>& x ) : refC(0), fxn(blackhole()), val(x) {}
       Cache( const T& x, const list<T>& l ) : refC(0),fxn(blackhole()),val(x,l)
          {}

       Cache( const fun0_odd_list_T& f )
         : refC(0), fxn(f), val( OddListDummyY() ) {}

       // f must be a boost phoenix function object?
       template <class F>
       Cache( const F& f )    // ()->odd_list
         : refC(0), fxn(make_fun0_odd_list<T>()(f)), val( OddListDummyY() ) {}

       // This is for ()->list<T> to ()->odd_list<T>
       struct CvtFxn {};
       template <class F>
       Cache( CvtFxn, const F& f )    // ()->list
         :  refC(0), fxn(make_fun0_odd_list<T>()(cvt<T,F>(f))), val( OddListDummyY() ) {}

       template <class X>
       friend void intrusive_ptr_add_ref( const Cache<X>* p );
       template <class X>
       friend void intrusive_ptr_release( const Cache<X>* p );
    };

    template <class T>
    void intrusive_ptr_add_ref( const Cache<T>* p ) {
        ++ (p->refC);
    }
    template <class T>
    void intrusive_ptr_release( const Cache<T>* p ) {
        if( !--(p->refC) ) delete p;
    }

//////////////////////////////////////////////////////////////////////
// Rest of list's stuff
//////////////////////////////////////////////////////////////////////

template <class T, class F> struct ListHelp<T,F,list<T> > {
   boost::intrusive_ptr<Cache<T> > operator()( const F& f ) const {
      return boost::intrusive_ptr<Cache<T> >
         (new Cache<T>(typename Cache<T>::CvtFxn(),f));
   }
};
template <class T, class F> struct ListHelp<T,F,odd_list<T> > {
   boost::intrusive_ptr<Cache<T> > operator()( const F& f ) const {
      return boost::intrusive_ptr<Cache<T> >(new Cache<T>(f));
   }
};

template <class T>
class list_iterator
: public std::iterator<std::input_iterator_tag,T,ptrdiff_t> {
   list<T> l;
   bool is_nil;
   void advance() {
      l = l.tail();
      if( !l )
         is_nil = true;
   }
   class Proxy {  // needed for operator->
      const T x;
      friend class list_iterator;
      Proxy( const T& xx ) : x(xx) {}
   public:
      const T* operator->() const { return &x; }
   };
public:
   list_iterator() : l(), is_nil(true) {}
   explicit list_iterator( const list<T>& ll ) : l(ll), is_nil(!ll) {}
   
   const T operator*() const { return l.head(); }
   const Proxy operator->() const { return Proxy(l.head()); }
   list_iterator<T>& operator++() {
      advance();
      return *this;
   }
   const list_iterator<T> operator++(int) {
      list_iterator<T> i( *this );
      advance();
      return i;
   }
   bool operator==( const list_iterator<T>& i ) const {
      return is_nil && i.is_nil;
   }
   bool operator!=( const list_iterator<T>& i ) const {
      return ! this->operator==(i);
   }
};


    } // namespace impl

  using impl::list;
  using impl::odd_list;
  using impl::list_iterator;

//////////////////////////////////////////////////////////////////////
// op== and op<, overloaded for all combos of list, odd_list, and NIL
//////////////////////////////////////////////////////////////////////
// All of these null head and tail are now non lazy using e.g. null(a)().
// They need an extra () e.g. null(a)().

// FIX THIS comparison operators can be implemented simpler with enable_if
template <class T>
bool operator==( const odd_list<T>& a, a_unique_type_for_nil ) {
  return null(a)();
}
template <class T>
bool operator==( const list<T>& a, a_unique_type_for_nil ) {
  return null(a)();
}
template <class T>
bool operator==( a_unique_type_for_nil, const odd_list<T>& a ) {
  return null(a)();
}
template <class T>
bool operator==( a_unique_type_for_nil, const list<T>& a ) {
  return null(a)();
}
template <class T>
bool operator==( const list<T>& a, const list<T>& b ) {
  if( null(a)() && null(b)() )
      return true;
  if( null(a)() || null(b)() )
      return false;
  return (head(a)()==head(b)()) && (tail(a)()==tail(b)());
}
template <class T>
bool operator==( const odd_list<T>& a, const odd_list<T>& b ) {
  if( null(a)() && null(b)() )
      return true;
  if( null(a)() || null(b)() )
      return false;
  return (head(a)()==head(b)()) && (tail(a)()==tail(b)());
}
template <class T>
bool operator==( const list<T>& a, const odd_list<T>& b ) {
  if( null(a)() && null(b)() )
      return true;
  if( null(a)() || null(b)() )
      return false;
  return (head(a)()==head(b)()) && (tail(a)()==tail(b)());
}
template <class T>
bool operator==( const odd_list<T>& a, const list<T>& b ) {
  if( null(a)() && null(b)() )
      return true;
  if( null(a)() || null(b)() )
      return false;
  return (head(a)()==head(b)()) && (tail(a)()==tail(b)());
}

template <class T>
bool operator<( const list<T>& a, const list<T>& b ) {
  if( null(a)() && !null(b)() )  return true;
  if( null(b)() )              return false;
  if( head(b)() < head(a)() )    return false;
  if( head(a)() < head(b)() )    return true;
  return (tail(a)() < tail(b)());
}
template <class T>
bool operator<( const odd_list<T>& a, const list<T>& b ) {
  if( null(a)() && !null(b)() )  return true;
  if( null(b)() )              return false;
  if( head(b)() < head(a)() )    return false;
  if( head(a)() < head(b)() )    return true;
  return (tail(a)() < tail(b)());
}
template <class T>
bool operator<( const list<T>& a, const odd_list<T>& b ) {
   if( null(a) && !null(b) )  return true;
   if( null(b) )              return false;
   if( head(b) < head(a) )    return false;
   if( head(a) < head(b) )    return true;
   return (tail(a) < tail(b));
}
template <class T>
bool operator<( const odd_list<T>& a, const odd_list<T>& b ) {
  if( null(a)() && !null(b)() )  return true;
  if( null(b)() )              return false;
  if( head(b)() < head(a)() )    return false;
  if( head(a)() < head(b)() )    return true;
  return (tail(a)() < tail(b)());
}
template <class T>
bool operator<( const odd_list<T>&, a_unique_type_for_nil ) {
   return false;
}
template <class T>
bool operator<( const list<T>&, a_unique_type_for_nil ) {
   return false;
}
template <class T>
bool operator<( a_unique_type_for_nil, const odd_list<T>& b ) {
  return !null(b)();
}
template <class T>
bool operator<( a_unique_type_for_nil, const list<T>& b ) {
  return !null(b)();
}

//////////////////////////////////////////////////////////////////////
// Implement cat and cons after the list types are defined.
//////////////////////////////////////////////////////////////////////
    namespace impl {
      using listlike::ListLike;

      template <class T, class F, class L>
      struct ConsHelp2<T,F,L,true>
      {
         typedef typename boost::remove_reference<T>::type TT;
         typedef typename L::force_result_type type;
         static type go( const TT& x, const F& f ) {
            return type( x, f );
         }
      };
      template <class T, class F>
      struct ConsHelp2<T,F,list<T>,true>
      {
         typedef typename boost::remove_reference<T>::type TT;
         typedef list<TT> L;
         typedef typename L::force_result_type type;
         static type go( const TT& x, const F& f ) {
            return odd_list<TT>(x, list<TT>(
            boost::intrusive_ptr<Cache<TT> >(new Cache<T>(
            typename Cache<TT>::CvtFxn(),f))));
         }
       };
       template <class T, class F>
       struct ConsHelp2<T,F,odd_list<T>,true>
       {
          typedef typename boost::remove_reference<T>::type TT;
          typedef odd_list<TT> L;
          typedef typename L::force_result_type type;
          static type go( const TT& x, const F& f ) {
              return odd_list<TT>(x, list<TT>( ListRaw(), new Cache<T>(f) ));
          }
       };
       template <class T, class F>
       struct ConsHelp2<T,F,a_unique_type_for_nil,false>
       {
          typedef typename boost::remove_reference<T>::type TT;
          typedef odd_list<TT> type;
          static type go( const TT& x, const F& f ) {
             return odd_list<TT>(x, list<TT>( ListRaw(), new Cache<T>(f) ));
          }
       };

       template <class T, class L, bool b> struct ConsHelp1 {
          typedef typename boost::remove_reference<T>::type TT;
          typedef typename L::force_result_type type;
          static type go( const TT& x, const L& l ) {
             return type(x,l);
          }
       };
      template <class T> struct ConsHelp1<T,a_unique_type_for_nil,false> {
        typedef typename boost::remove_reference<T>::type TT;
        typedef odd_list<TT> type;
        static type go( const TT& x, const a_unique_type_for_nil& n ) {
        return type(x,n);
        }
      };
      template <class T, class F> struct ConsHelp1<T,F,false> {
        // It's a function returning a list
        // This is the one I have not fixed yet....
        // typedef typename F::result_type L;
        // typedef typename result_of::template ListType<F>::result_type L;
        typedef odd_list<T> L;
        typedef ConsHelp2<T,F,L,boost::is_base_and_derived<ListLike,L>::value> help;
        typedef typename help::type type;
        static type go( const T& x, const F& f ) {
           return help::go(x,f);
        }
      };

      template <class T, class L, bool b>
      struct ConsHelp0;

      template <class T>
      struct ConsHelp0<T,a_unique_type_for_nil,true> {
        typedef typename boost::remove_reference<T>::type TT;
        typedef odd_list<T> type;
      };

      template <class T>
      struct ConsHelp0<const T &,const a_unique_type_for_nil &,true> {
        typedef typename boost::remove_reference<T>::type TT;
        typedef odd_list<TT> type;
      };

      template <class T>
      struct ConsHelp0<T &,a_unique_type_for_nil &,true> {
        typedef typename boost::remove_reference<T>::type TT;
        typedef odd_list<TT> type;
      };

      template <class T, class L>
      struct ConsHelp0<T,L,false> {
          // This removes any references from L for correct return type
          // identification.
           typedef typename boost::remove_reference<L>::type LType;
           typedef typename ConsHelp1<T,LType,
           boost::is_base_and_derived<ListLike,LType>::value>::type type;
      };

      /////////////////////////////////////////////////////////////////////
      // cons (t,l) - cons a value to the front of a list.
      // Note: The first arg,  t, must be a value.
      //       The second arg, l, can be a list or NIL
      //       or a function that returns a list.
      /////////////////////////////////////////////////////////////////////
      struct Cons
      {
        /* template <class T, class L> struct sig : public fun_type<
        typename ConsHelp1<T,L,
      boost::is_base_and_derived<ListLike,L>::value>::type> {};
        */
        template <typename Sig> struct result;

        template <typename This, typename T, typename L>
        struct result<This(T, L)>
        {
          typedef typename ConsHelp0<T,L,
          listlike::detect_nil<L>::is_nil>::type type;
        };

        template <typename This, typename T>
        struct result<This(T,a_unique_type_for_nil)>
        {
          typedef typename boost::remove_reference<T>::type TT;
          typedef odd_list<TT> type;
        };

        template <typename T, typename L>
        typename result<Cons(T,L)>::type
        operator()( const T& x, const L& l ) const {
           typedef typename result_of::ListType<L>::LType LType;
           typedef ConsHelp1<T,LType,
           boost::is_base_and_derived<ListLike,LType>::value> help;
           return help::go(x,l);
          }
      
        template <typename T>
        typename result<Cons(T,a_unique_type_for_nil)>::type
        operator()( const T& x, const a_unique_type_for_nil &n ) const {
           typedef typename result<Cons(T,a_unique_type_for_nil)>::type LL;
           typedef ConsHelp1<T,LL,
           boost::is_base_and_derived<ListLike,LL>::value> help;
           return help::go(x,n);
          }

      };
    }

    typedef boost::phoenix::function<impl::Cons> Cons;
    Cons cons;

    namespace impl {

      template <class L, class M, bool b>
      struct CatHelp0;

      template <class LL>
      struct CatHelp0<LL,a_unique_type_for_nil,true> {
        typedef typename result_of::template ListType<LL>::LType type;
      };

      template <class LL>
      struct CatHelp0<const LL &,const a_unique_type_for_nil &,true> {
        typedef typename result_of::template ListType<LL>::LType type;
        //typedef L type;
      };

      template <class LL>
      struct CatHelp0<LL &,a_unique_type_for_nil &,true> {
        typedef typename result_of::template ListType<LL>::LType type;
        //typedef L type;
      };

      template <class LL, class MM>
      struct CatHelp0<LL,MM,false> {
          // This removes any references from L for correct return type
          // identification.
        typedef typename result_of::template ListType<LL>::LType type;
        //    typedef typename ConsHelp1<T,LType,
        //   boost::is_base_and_derived<ListLike,LType>::value>::type type;
      };

      /////////////////////////////////////////////////////////////////////
      // cat (l,m) - concatenate lists.
      // Note: The first arg,  l, must be a list or NIL.
      //       The second arg, m, can be a list or NIL
      //       or a function that returns a list.
      /////////////////////////////////////////////////////////////////////
      struct Cat
      {
         template <class L, class M, bool b, class R>
         struct Helper /*: public c_fun_type<L,M,R>*/ {
           template <typename Sig> struct result;
           
           template <typename This>
           struct result<This(L,M)>
          {
             typedef typename result_of::ListType<L>::tail_result_type type;
          };

           typedef R return_type;
           R operator()( const L& l, const M& m,
             reuser2<INV,VAR,INV,Helper,
             typename result_of::template ListType<L>::tail_result_type,M>
             r = NIL ) const {
             if( null(l)() )
                return m().force();
             else
                return cons( head(l)(), r( Helper<L,M,b,R>(), tail(l), m )() );
         }
      };
          template <class L, class M, class R>
          struct Helper<L,M,true,R> /*: public c_fun_type<L,M,R>*/ {
           template <typename Sig> struct result;
           
           template <typename This>
           struct result<This(L,M)>
          {
             typedef typename result_of::ListType<L>::tail_result_type type;
          };
          typedef R return_type;
          R operator()( const L& l, const M& m,
             reuser2<INV,VAR,INV,Helper,
             typename result_of::template ListType<L>::tail_result_type,M>
             r = NIL ) const {
             if( null(l)() )
                return m.force();
             else
                return cons( head(l)(), r(Helper<L,M,true,R>(), tail(l), m )());
         }
      };
      template <class L, class R>
      struct Helper<L,a_unique_type_for_nil,false,R>
      /*: public c_fun_type<L,
        a_unique_type_for_nil,odd_list<typename L::value_type> > */
      {
        typedef odd_list<typename result_of::template ListType<L>::value_type> type;
        odd_list<typename result_of::template ListType<L>::value_type>
        operator()( const L& l, const a_unique_type_for_nil& ) const {
         return l;
        }
      };
   public:
        /*template <class L, class M> struct sig : public fun_type<
        typename RT<cons_type,typename L::value_type,M>::result_type>
      {}; */
   // Need to work out the return type here.
      template <typename Sig> struct result;

      template <typename This, typename L, typename M>
      struct result<This(L,M)>
      {
        typedef typename CatHelp0<L,M,
          listlike::detect_nil<M>::is_nil>::type type;
        // typedef typename result_of::ListType<L>::tail_result_type type;
      };
      
      template <typename This, typename L>
      struct result<This(L,a_unique_type_for_nil)>
      {
         typedef typename result_of::ListType<L>::tail_result_type type;
      };
      template <class L, class M>
      typename result<Cat(L,M)>::type operator()( const L& l, const M& m ) const
      {
         listlike::EnsureListLike<L>();
         return Helper<L,M,
         boost::is_base_and_derived<typename listlike::ListLike,M>::value,
                typename result<Cat(L,M)>::type>()(l,m);
      }

      template <class L>
      typename result<Cat(L,a_unique_type_for_nil)>::type operator()( const L& l, const a_unique_type_for_nil& /* n */ ) const
      {
         listlike::EnsureListLike<L>();
         return l;
      }
       
      };


    }

    typedef boost::phoenix::function<impl::Cat> Cat;
    Cat cat;


//////////////////////////////////////////////////////////////////////
// Handy functions for making list literals
//////////////////////////////////////////////////////////////////////
// Yes, these aren't functoids, they're just template functions.  I'm
// lazy and created these mostly to make it easily to make little lists
// in the sample code snippets that appear in papers.

struct UseList {
   template <class T> struct List { typedef list<T> type; };
};
struct UseOddList {
   template <class T> struct List { typedef odd_list<T> type; };
};
struct UseStrictList {
   template <class T> struct List { typedef strict_list<T> type; };
};

template <class Kind = UseList>
struct list_with {
   template <class T>
   typename Kind::template List<T>::type
   operator()( const T& a ) const {
      typename Kind::template List<T>::type l;
      l = cons( a, l );
      return l;
   }
   
   template <class T>
   typename Kind::template List<T>::type
   operator()( const T& a, const T& b ) const {
      typename Kind::template List<T>::type l;
      l = cons( b, l );
      l = cons( a, l );
      return l;
   }
   
   template <class T>
   typename Kind::template List<T>::type
   operator()( const T& a, const T& b, const T& c ) const {
      typename Kind::template List<T>::type l;
      l = cons( c, l );
      l = cons( b, l );
      l = cons( a, l );
      return l;
   }
   
   template <class T>
   typename Kind::template List<T>::type
   operator()( const T& a, const T& b, const T& c, const T& d ) const {
      typename Kind::template List<T>::type l;
      l = cons( d, l );
      l = cons( c, l );
      l = cons( b, l );
      l = cons( a, l );
      return l;
   }
   
   template <class T>
   typename Kind::template List<T>::type
   operator()( const T& a, const T& b, const T& c, const T& d,
               const T& e ) const {
      typename Kind::template List<T>::type l;
      l = cons( e, l );
      l = cons( d, l );
      l = cons( c, l );
      l = cons( b, l );
      l = cons( a, l );
      return l;
   }
};
//////////////////////////////////////////////////////////////////////

  }

}

#endif
