//////////////////////////////////////////////////////////////////////////// // 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 and associated iterator. // // list and odd_list // // 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 at two locations, // one in list and one in Cons. I am going to leave it like this // for now as reading the code, odd_list 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 inherits ListLike and has // typedefs just show typical values typedef T value_type typedef L force_result_type typedef L delay_result_type typedef L tail_result_type template struct cons_rebind { typedef L type; // force type typedef L delay_type; // delay type }; L() L( a_unique_type_for_nil ) template L(F) // F :: ()->L constructor: force_result_type( T, L ) template constructor: force_result_type( T, F ) // F :: ()->L template 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 #include #include #include #include //#include "lazy_reuse.hpp" namespace boost { namespace phoenix { ////////////////////////////////////////////////////////////////////// // These are the list types being declared. ////////////////////////////////////////////////////////////////////// template class strict_list; namespace impl { template class list; template 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 struct ensure_lazy_helper {}; template struct ensure_lazy_helper { static void requires_lazy_list_to_prevent_infinite_recursion() {} }; template void ensure_lazy() { ensure_lazy_helper:: 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::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 { public: typedef a_unique_type_for_nil LType; //typedef a_unique_type_for_nil value_type; }; template struct ResultType { typedef typename impl::odd_list 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 struct ensure_lazy_helper {}; template struct ensure_lazy_helper { static void requires_lazy_list_to_prevent_infinite_recursion() {} }; template void ensure_lazy() { ensure_lazy_helper:: requires_lazy_list_to_prevent_infinite_recursion(); } template struct EnsureListLikeHelp { static void trying_to_call_a_list_function_on_a_non_list() {} }; template struct EnsureListLikeHelp { }; template void EnsureListLike() { typedef typename result_of::ListType::LType LType; EnsureListLikeHelp::value>:: trying_to_call_a_list_function_on_a_non_list(); } template bool is_a_unique_type_for_nil(const L& /*l*/) { return false; } template <> bool is_a_unique_type_for_nil (const a_unique_type_for_nil& /* n */) { return true; } template struct detect_nil { static const bool is_nil = false; }; template <> struct detect_nil { static const bool is_nil = true; }; template <> struct detect_nil { static const bool is_nil = true; }; template <> struct detect_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 struct result; template struct result { typedef typename result_of::ListType::value_type type; }; template typename result::type operator()(const L & l) const { listlike::EnsureListLike(); return l.head(); } }; struct Tail { template struct result; template struct result { typedef typename result_of::ListType::tail_result_type type; }; template typename result::type operator()(const L & l) const { listlike::EnsureListLike(); return l.tail(); } }; struct Null { template struct result; template struct result { typedef bool type; }; template typename result::type //bool operator()(const L& l) const { listlike::EnsureListLike(); return !l; } }; struct Delay { template struct result; template struct result { typedef typename result_of::ListType::delay_result_type type; }; template typename result::type operator()(const L & l) const { listlike::EnsureListLike(); return l.delay(); } }; struct Force { template struct result; template struct result { typedef typename result_of::ListType::force_result_type type; }; template typename result::type operator()(const L & l) const { listlike::EnsureListLike(); 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 Head; typedef boost::phoenix::function Tail; typedef boost::phoenix::function Null; typedef boost::phoenix::function Delay; typedef boost::phoenix::function 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 struct strict_cons : public boost::noncopyable { mutable RefCountType refC; T head; typedef boost::intrusive_ptr tail_type; tail_type tail; strict_cons( const T& h, const tail_type& t ) : refC(0), head(h), tail(t) {} }; template void intrusive_ptr_add_ref( const strict_cons* p ) { ++ (p->refC); } template void intrusive_ptr_release( const strict_cons* p ) { if( !--(p->refC) ) delete p; } template class strict_list_iterator : public std::iterator { typedef boost::intrusive_ptr > 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& operator++() { advance(); return *this; } const strict_list_iterator operator++(int) { strict_list_iterator i( *this ); advance(); return i; } bool operator==( const strict_list_iterator& i ) const { return is_nil && i.is_nil; } bool operator!=( const strict_list_iterator& i ) const { return ! this->operator==(i); } }; } ////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////// template class strict_list : public listlike::ListLike { typedef boost::intrusive_ptr > rep_type; rep_type rep; struct Make {}; template 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( 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 struct cons_rebind { typedef strict_list type; typedef strict_list delay_type; }; strict_list( Make, const rep_type& r ) : rep(r) {} strict_list() : rep() {} strict_list( a_unique_type_for_nil ) : rep() {} template strict_list( const F& f ) : rep( f().rep ) { // I cannot do this yet. //functoid_traits::template ensure_accepts<0>::args(); } strict_list( const T& x, const strict_list& y ) : rep( new impl::strict_cons(x,y.rep) ) {} template strict_list( const T& x, const F& f ) : rep( new impl::strict_cons(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 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 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 const_iterator; typedef const_iterator iterator; // strict_list is immutable iterator begin() const { return impl::strict_list_iterator( rep ); } iterator end() const { return impl::strict_list_iterator(); } }; // 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 bool operator==( const strict_list& a, a_unique_type_for_nil ) { return null(a)(); } template bool operator==( a_unique_type_for_nil, const strict_list& a ) { return null(a)(); } template bool operator==( const strict_list& a, const strict_list& 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 bool operator<( const strict_list& a, const strict_list& 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 bool operator<( const strict_list&, a_unique_type_for_nil ) { return false; } template bool operator<( a_unique_type_for_nil, const strict_list& b ) { return !(null(b)()); } ////////////////////////////////////////////////////////////////////// // Class list 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 Cache; template class odd_list; template class list_iterator; template struct ListItHelp2 /*: public c_fun_type >*/ { // This will need a return type. typedef odd_list return_type; odd_list operator()( It begin, const It& end, reuser2,It,It> r = NIL ) const; }; template struct cvt; template struct ListHelp; template Cache* xempty_helper(); template struct ConsHelp2; struct ListRaw {}; template class list : public listlike::ListLike { // never NIL, unless an empty odd_list boost::intrusive_ptr > rep; template friend class Cache; template friend class odd_list; template friend struct ConsHelp2; template friend struct cvt; list( const boost::intrusive_ptr >& p ) : rep(p) { } list( ListRaw, Cache* p ) : rep(p) { } bool priv_isEmpty() const { return rep->cache().second.rep == Cache::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 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 force_result_type; typedef list delay_result_type; template struct cons_rebind { typedef odd_list type; typedef list delay_type; }; list( a_unique_type_for_nil ) : rep( Cache::XEMPTY() ) { } list() : rep( Cache::XEMPTY() ) { } template // works on both ()->odd_list and ()->list // At the moment this is fixed for odd_list. // I need to do more work to get the general result. list( const F& f ) : rep( ListHelp >()(f) ) { } //: rep( ListHelp()(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() 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 const_iterator; typedef const_iterator iterator; // list is immutable iterator begin() const { return list_iterator( *this ); } iterator end() const { return list_iterator(); } // end of list }; ////////////////////////////////////////////////////////////////////// // Class odd_list is not normally accessed by the user. ////////////////////////////////////////////////////////////////////// struct OddListDummyY {}; template class odd_list : public listlike::ListLike { public: typedef typename boost::type_with_alignment::value>::type xfst_type; private: union { xfst_type fst; unsigned char dummy[sizeof(T)]; }; const T& first() const { return *static_cast(static_cast(&fst)); } T& first() { return *static_cast(static_cast(&fst)); } list second; // If XNIL, then this odd_list is NIL template friend class list; template friend class Cache; odd_list( OddListDummyY ) : second( Cache::XBAD() ) { } void init( const T& x ) { new (static_cast(&fst)) T(x); } bool fst_is_valid() const { if( second.rep != Cache::XNIL() ) if( second.rep != Cache::XBAD() ) return true; return false; } bool priv_isEmpty() const { return second.rep == Cache::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 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 tail_result_type; typedef odd_list force_result_type; typedef list delay_result_type; template struct cons_rebind { typedef odd_list type; typedef list delay_type; }; odd_list() : second( Cache::XNIL() ) { } odd_list( a_unique_type_for_nil ) : second( Cache::XNIL() ) { } odd_list( const T& x, const list& y ) : second(y) { init(x); } odd_list( const T& x, a_unique_type_for_nil ) : second(NIL) { init(x); } odd_list( const odd_list& x ) : second(x.second) { if( fst_is_valid() ) { init( x.first() ); } } template odd_list( It begin, const It& end ) : second( begin==end ? Cache::XNIL() : ( init(*begin++), list( begin, end ) ) ) {} odd_list& operator=( const odd_list& 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(*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 const_iterator; typedef const_iterator iterator; // odd_list is immutable iterator begin() const { return list_iterator( this->delay() ); } iterator end() const { return list_iterator(); } // end of odd_list }; ////////////////////////////////////////////////////////////////////// // struct cvt ////////////////////////////////////////////////////////////////////// // This converts ()->list to ()->odd_list. // In other words, here is the 'extra work' done when using the // unoptimized interface. template struct cvt /*: public c_fun_type >*/ { typedef odd_list return_type; F f; cvt( const F& ff ) : f(ff) {} odd_list operator()() const { list l = f(); return l.force(); } }; ////////////////////////////////////////////////////////////////////// // Cache 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 Cache* xnil_helper() { void *p = std::malloc( sizeof(RefCountType) ); *((RefCountType*)p) = 1; return static_cast*>( p ); } template Cache* xnil_helper_nil() { Cache* p = xnil_helper(); return p; } template Cache* xnil_helper_bad() { Cache* p = xnil_helper(); return p; } template Cache* xempty_helper() { Cache* p = new Cache( CacheEmpty() ); return p; } // This makes a boost phoenix function type with return type // odd_list template struct fun0_type_helper{ typedef boost::function0 > fun_type; typedef boost::phoenix::function phx_type; }; template struct make_fun0_odd_list { typedef typename fun0_type_helper::fun_type fun_type; typedef typename fun0_type_helper::phx_type phx_type; typedef phx_type result_type; template 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 typename boost::phoenix::function operator() (const boost::phoenix::function& f) const { return f; } }; template class Cache : boost::noncopyable { mutable RefCountType refC; // This is the boost::function type typedef typename fun0_type_helper::fun_type fun_odd_list_T; // This is the boost::phoenix::function type; typedef typename fun0_type_helper::phx_type fun0_odd_list_T; mutable fun0_odd_list_T fxn; mutable odd_list 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 >*/ { typedef odd_list return_type; odd_list operator()() const { #ifndef BOOST_PHOENIX_NO_LAZY_EXCEPTIONS throw lazy_exception("You have entered a black hole."); #else return odd_list(); #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 >& XEMPTY() { static boost::intrusive_ptr > xempty( xempty_helper() ); return xempty; } static const boost::intrusive_ptr >& XNIL() { // this list is nil static boost::intrusive_ptr > xnil( xnil_helper_nil() ); return xnil; } static const boost::intrusive_ptr >& XBAD() { // the pair is invalid; use fxn static boost::intrusive_ptr > xbad( xnil_helper_bad() ); return xbad; } static fun0_odd_list_T /* >*/ the_blackhole; static fun0_odd_list_T& blackhole() { static fun0_odd_list_T the_blackhole; //( make_fun0_odd_list()( blackhole_helper() ) ); return the_blackhole; } odd_list& cache() const { if( val.second.rep == XBAD() ) { val = fxn()(); fxn = blackhole(); } return val; } template friend class list; template friend class odd_list; template friend struct ConsHelp2; template friend struct cvt; template friend struct ListHelp; template friend Cache* xempty_helper(); Cache( CacheEmpty ) : refC(0), fxn(blackhole()), val() {} Cache( const odd_list& x ) : refC(0), fxn(blackhole()), val(x) {} Cache( const T& x, const list& 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 Cache( const F& f ) // ()->odd_list : refC(0), fxn(make_fun0_odd_list()(f)), val( OddListDummyY() ) {} // This is for ()->list to ()->odd_list struct CvtFxn {}; template Cache( CvtFxn, const F& f ) // ()->list : refC(0), fxn(make_fun0_odd_list()(cvt(f))), val( OddListDummyY() ) {} template friend void intrusive_ptr_add_ref( const Cache* p ); template friend void intrusive_ptr_release( const Cache* p ); }; template void intrusive_ptr_add_ref( const Cache* p ) { ++ (p->refC); } template void intrusive_ptr_release( const Cache* p ) { if( !--(p->refC) ) delete p; } ////////////////////////////////////////////////////////////////////// // Rest of list's stuff ////////////////////////////////////////////////////////////////////// template struct ListHelp > { boost::intrusive_ptr > operator()( const F& f ) const { return boost::intrusive_ptr > (new Cache(typename Cache::CvtFxn(),f)); } }; template struct ListHelp > { boost::intrusive_ptr > operator()( const F& f ) const { return boost::intrusive_ptr >(new Cache(f)); } }; template class list_iterator : public std::iterator { list 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& ll ) : l(ll), is_nil(!ll) {} const T operator*() const { return l.head(); } const Proxy operator->() const { return Proxy(l.head()); } list_iterator& operator++() { advance(); return *this; } const list_iterator operator++(int) { list_iterator i( *this ); advance(); return i; } bool operator==( const list_iterator& i ) const { return is_nil && i.is_nil; } bool operator!=( const list_iterator& 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 bool operator==( const odd_list& a, a_unique_type_for_nil ) { return null(a)(); } template bool operator==( const list& a, a_unique_type_for_nil ) { return null(a)(); } template bool operator==( a_unique_type_for_nil, const odd_list& a ) { return null(a)(); } template bool operator==( a_unique_type_for_nil, const list& a ) { return null(a)(); } template bool operator==( const list& a, const list& 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 bool operator==( const odd_list& a, const odd_list& 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 bool operator==( const list& a, const odd_list& 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 bool operator==( const odd_list& a, const list& 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 bool operator<( const list& a, const list& 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 bool operator<( const odd_list& a, const list& 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 bool operator<( const list& a, const odd_list& 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 bool operator<( const odd_list& a, const odd_list& 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 bool operator<( const odd_list&, a_unique_type_for_nil ) { return false; } template bool operator<( const list&, a_unique_type_for_nil ) { return false; } template bool operator<( a_unique_type_for_nil, const odd_list& b ) { return !null(b)(); } template bool operator<( a_unique_type_for_nil, const list& b ) { return !null(b)(); } ////////////////////////////////////////////////////////////////////// // Implement cat and cons after the list types are defined. ////////////////////////////////////////////////////////////////////// namespace impl { using listlike::ListLike; template struct ConsHelp2 { typedef typename boost::remove_reference::type TT; typedef typename L::force_result_type type; static type go( const TT& x, const F& f ) { return type( x, f ); } }; template struct ConsHelp2,true> { typedef typename boost::remove_reference::type TT; typedef list L; typedef typename L::force_result_type type; static type go( const TT& x, const F& f ) { return odd_list(x, list( boost::intrusive_ptr >(new Cache( typename Cache::CvtFxn(),f)))); } }; template struct ConsHelp2,true> { typedef typename boost::remove_reference::type TT; typedef odd_list L; typedef typename L::force_result_type type; static type go( const TT& x, const F& f ) { return odd_list(x, list( ListRaw(), new Cache(f) )); } }; template struct ConsHelp2 { typedef typename boost::remove_reference::type TT; typedef odd_list type; static type go( const TT& x, const F& f ) { return odd_list(x, list( ListRaw(), new Cache(f) )); } }; template struct ConsHelp1 { typedef typename boost::remove_reference::type TT; typedef typename L::force_result_type type; static type go( const TT& x, const L& l ) { return type(x,l); } }; template struct ConsHelp1 { typedef typename boost::remove_reference::type TT; typedef odd_list type; static type go( const TT& x, const a_unique_type_for_nil& n ) { return type(x,n); } }; template struct ConsHelp1 { // 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::result_type L; typedef odd_list L; typedef ConsHelp2::value> help; typedef typename help::type type; static type go( const T& x, const F& f ) { return help::go(x,f); } }; template struct ConsHelp0; template struct ConsHelp0 { typedef typename boost::remove_reference::type TT; typedef odd_list type; }; template struct ConsHelp0 { typedef typename boost::remove_reference::type TT; typedef odd_list type; }; template struct ConsHelp0 { typedef typename boost::remove_reference::type TT; typedef odd_list type; }; template struct ConsHelp0 { // This removes any references from L for correct return type // identification. typedef typename boost::remove_reference::type LType; typedef typename ConsHelp1::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 struct sig : public fun_type< typename ConsHelp1::value>::type> {}; */ template struct result; template struct result { typedef typename ConsHelp0::is_nil>::type type; }; template struct result { typedef typename boost::remove_reference::type TT; typedef odd_list type; }; template typename result::type operator()( const T& x, const L& l ) const { typedef typename result_of::ListType::LType LType; typedef ConsHelp1::value> help; return help::go(x,l); } template typename result::type operator()( const T& x, const a_unique_type_for_nil &n ) const { typedef typename result::type LL; typedef ConsHelp1::value> help; return help::go(x,n); } }; } typedef boost::phoenix::function Cons; Cons cons; namespace impl { template struct CatHelp0; template struct CatHelp0 { typedef typename result_of::template ListType::LType type; }; template struct CatHelp0 { typedef typename result_of::template ListType::LType type; //typedef L type; }; template struct CatHelp0 { typedef typename result_of::template ListType::LType type; //typedef L type; }; template struct CatHelp0 { // This removes any references from L for correct return type // identification. typedef typename result_of::template ListType::LType type; // typedef typename ConsHelp1::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 struct Helper /*: public c_fun_type*/ { template struct result; template struct result { typedef typename result_of::ListType::tail_result_type type; }; typedef R return_type; R operator()( const L& l, const M& m, reuser2::tail_result_type,M> r = NIL ) const { if( null(l)() ) return m().force(); else return cons( head(l)(), r( Helper(), tail(l), m )() ); } }; template struct Helper /*: public c_fun_type*/ { template struct result; template struct result { typedef typename result_of::ListType::tail_result_type type; }; typedef R return_type; R operator()( const L& l, const M& m, reuser2::tail_result_type,M> r = NIL ) const { if( null(l)() ) return m.force(); else return cons( head(l)(), r(Helper(), tail(l), m )()); } }; template struct Helper /*: public c_fun_type > */ { typedef odd_list::value_type> type; odd_list::value_type> operator()( const L& l, const a_unique_type_for_nil& ) const { return l; } }; public: /*template struct sig : public fun_type< typename RT::result_type> {}; */ // Need to work out the return type here. template struct result; template struct result { typedef typename CatHelp0::is_nil>::type type; // typedef typename result_of::ListType::tail_result_type type; }; template struct result { typedef typename result_of::ListType::tail_result_type type; }; template typename result::type operator()( const L& l, const M& m ) const { listlike::EnsureListLike(); return Helper::value, typename result::type>()(l,m); } template typename result::type operator()( const L& l, const a_unique_type_for_nil& /* n */ ) const { listlike::EnsureListLike(); return l; } }; } typedef boost::phoenix::function 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 struct List { typedef list type; }; }; struct UseOddList { template struct List { typedef odd_list type; }; }; struct UseStrictList { template struct List { typedef strict_list type; }; }; template struct list_with { template typename Kind::template List::type operator()( const T& a ) const { typename Kind::template List::type l; l = cons( a, l ); return l; } template typename Kind::template List::type operator()( const T& a, const T& b ) const { typename Kind::template List::type l; l = cons( b, l ); l = cons( a, l ); return l; } template typename Kind::template List::type operator()( const T& a, const T& b, const T& c ) const { typename Kind::template List::type l; l = cons( c, l ); l = cons( b, l ); l = cons( a, l ); return l; } template typename Kind::template List::type operator()( const T& a, const T& b, const T& c, const T& d ) const { typename Kind::template List::type l; l = cons( d, l ); l = cons( c, l ); l = cons( b, l ); l = cons( a, l ); return l; } template typename Kind::template List::type operator()( const T& a, const T& b, const T& c, const T& d, const T& e ) const { typename Kind::template List::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