lazy_list.hpp 48 KB

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