annotate DEPENDENCIES/generic/include/boost/phoenix/function/lazy_reuse.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents f46d142149f5
children
rev   line source
Chris@102 1 ////////////////////////////////////////////////////////////////////////////
Chris@102 2 // lazy_reuse.hpp
Chris@102 3 //
Chris@102 4 // Build lazy operations for Phoenix equivalents for FC++
Chris@102 5 //
Chris@102 6 // These are equivalents of the Boost FC++ functoids in reuse.hpp
Chris@102 7 //
Chris@102 8 // Implemented so far:
Chris@102 9 //
Chris@102 10 // reuser1 (not yet tested)
Chris@102 11 // reuser2 (not yet tested)
Chris@102 12 // reuser3
Chris@102 13 //
Chris@102 14 // NOTE: It has been possible to simplify the operation of this code.
Chris@102 15 // It now makes no use of boost::function or old FC++ code.
Chris@102 16 //
Chris@102 17 // The functor type F must be an operator defined with
Chris@102 18 // boost::phoenix::function.
Chris@102 19 // See the example Apply in lazy_prelude.hpp
Chris@102 20 //
Chris@102 21 ////////////////////////////////////////////////////////////////////////////
Chris@102 22 /*=============================================================================
Chris@102 23 Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis
Chris@102 24 Copyright (c) 2001-2007 Joel de Guzman
Chris@102 25 Copyright (c) 2015 John Fletcher
Chris@102 26
Chris@102 27 Distributed under the Boost Software License, Version 1.0. (See accompanying
Chris@102 28 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Chris@102 29 ==============================================================================*/
Chris@102 30
Chris@102 31 #ifndef BOOST_PHOENIX_FUNCTION_LAZY_REUSE
Chris@102 32 #define BOOST_PHOENIX_FUNCTION_LAZY_REUSE
Chris@102 33
Chris@102 34 #include <boost/phoenix/core.hpp>
Chris@102 35 #include <boost/phoenix/function.hpp>
Chris@102 36 #include <boost/intrusive_ptr.hpp>
Chris@102 37
Chris@102 38
Chris@102 39 namespace boost {
Chris@102 40
Chris@102 41 namespace phoenix {
Chris@102 42
Chris@102 43 namespace fcpp {
Chris@102 44
Chris@102 45 //////////////////////////////////////////////////////////////////////
Chris@102 46 // Original FC++ comment:
Chris@102 47 // "Reuser"s are effectively special-purpose versions of curry() that
Chris@102 48 // enable recursive list functoids to reuse the thunk of the curried
Chris@102 49 // recursive call. See
Chris@102 50 // http://www.cc.gatech.edu/~yannis/fc++/New/reusers.html
Chris@102 51 // for a more detailed description.
Chris@102 52 //////////////////////////////////////////////////////////////////////
Chris@102 53
Chris@102 54 // For efficiency, we mark parameters as either "VAR"iant or "INV"ariant.
Chris@102 55 struct INV {};
Chris@102 56 struct VAR {};
Chris@102 57
Chris@102 58 template <class V, class X> struct Maybe_Var_Inv;
Chris@102 59 template <class X>
Chris@102 60 struct Maybe_Var_Inv<VAR,X> {
Chris@102 61 static void remake( X& x, const X& val ) {
Chris@102 62 x.~X();
Chris@102 63 new (&x) X(val);
Chris@102 64 }
Chris@102 65 static X clone( const X& x ) { return X(x); }
Chris@102 66 };
Chris@102 67 template <class X>
Chris@102 68 struct Maybe_Var_Inv<INV,X> {
Chris@102 69 static void remake( X&, const X& ) {}
Chris@102 70 static const X& clone( const X& x ) { return x; }
Chris@102 71 };
Chris@102 72
Chris@102 73 /////////////////////////////////////////////////////////////////////
Chris@102 74 // ThunkImpl is an implementation of Fun0Impl for this use.
Chris@102 75 /////////////////////////////////////////////////////////////////////
Chris@102 76
Chris@102 77 template <class Result>
Chris@102 78 class ThunkImpl
Chris@102 79 {
Chris@102 80 mutable RefCountType refC;
Chris@102 81 public:
Chris@102 82 ThunkImpl() : refC(0) {}
Chris@102 83 virtual Result operator()() const =0;
Chris@102 84 virtual ~ThunkImpl() {}
Chris@102 85 template <class X>
Chris@102 86 friend void intrusive_ptr_add_ref( const ThunkImpl<X>* p );
Chris@102 87 template <class X>
Chris@102 88 friend void intrusive_ptr_release( const ThunkImpl<X>* p );
Chris@102 89 };
Chris@102 90
Chris@102 91 template <class T>
Chris@102 92 void intrusive_ptr_add_ref( const ThunkImpl<T>* p ) {
Chris@102 93 ++ (p->refC);
Chris@102 94 }
Chris@102 95 template <class T>
Chris@102 96 void intrusive_ptr_release( const ThunkImpl<T>* p ) {
Chris@102 97 if( !--(p->refC) ) delete p;
Chris@102 98 }
Chris@102 99
Chris@102 100 //////////////////////////////////////////////////////////////////////
Chris@102 101 // reuser1 is needed in list<T> operations
Chris@102 102 //////////////////////////////////////////////////////////////////////
Chris@102 103
Chris@102 104 template <class V1, class V2, class F, class X>
Chris@102 105 struct reuser1;
Chris@102 106
Chris@102 107 template <class V1, class V2, class F, class X, class R>
Chris@102 108 struct Thunk1 : public ThunkImpl<R> {
Chris@102 109 mutable F f;
Chris@102 110 mutable X x;
Chris@102 111 Thunk1( const F& ff, const X& xx ) : f(ff), x(xx) {}
Chris@102 112 void init( const F& ff, const X& xx ) const {
Chris@102 113 Maybe_Var_Inv<V1,F>::remake( f, ff );
Chris@102 114 Maybe_Var_Inv<V2,X>::remake( x, xx );
Chris@102 115 }
Chris@102 116 R operator()() const {
Chris@102 117 return Maybe_Var_Inv<V1,F>::clone(f)(
Chris@102 118 Maybe_Var_Inv<V2,X>::clone(x),
Chris@102 119 reuser1<V1,V2,F,X>(this) );
Chris@102 120 }
Chris@102 121 };
Chris@102 122
Chris@102 123 template <class V1, class V2, class F, class X>
Chris@102 124 struct reuser1 {
Chris@102 125 typedef typename F::template result<F(X)>::type R;
Chris@102 126 typedef typename boost::phoenix::function<R> fun0_type;
Chris@102 127 typedef Thunk1<V1,V2,F,X,R> M;
Chris@102 128 typedef M result_type;
Chris@102 129 boost::intrusive_ptr<const M> ref;
Chris@102 130 reuser1(a_unique_type_for_nil) {}
Chris@102 131 reuser1(const M* m) : ref(m) {}
Chris@102 132 M operator()( const F& f, const X& x ) {
Chris@102 133 if( !ref ) ref = boost::intrusive_ptr<const M>( new M(f,x) );
Chris@102 134 else ref->init(f,x);
Chris@102 135 return *ref;
Chris@102 136 }
Chris@102 137 void iter( const F& f, const X& x ) {
Chris@102 138 if( ref ) ref->init(f,x);
Chris@102 139 }
Chris@102 140 };
Chris@102 141
Chris@102 142 //////////////////////////////////////////////////////////////////////
Chris@102 143 // reuser2 is needed in list<T>
Chris@102 144 //////////////////////////////////////////////////////////////////////
Chris@102 145
Chris@102 146 template <class V1, class V2, class V3, class F, class X, class Y>
Chris@102 147 struct reuser2;
Chris@102 148
Chris@102 149 template <class V1, class V2, class V3, class F, class X, class Y, class R>
Chris@102 150 struct Thunk2 : public ThunkImpl<R> {
Chris@102 151 mutable F f;
Chris@102 152 mutable X x;
Chris@102 153 mutable Y y;
Chris@102 154 Thunk2( const F& ff, const X& xx, const Y& yy ) : f(ff), x(xx), y(yy) {}
Chris@102 155 void init( const F& ff, const X& xx, const Y& yy ) const {
Chris@102 156 Maybe_Var_Inv<V1,F>::remake( f, ff );
Chris@102 157 Maybe_Var_Inv<V2,X>::remake( x, xx );
Chris@102 158 Maybe_Var_Inv<V3,Y>::remake( y, yy );
Chris@102 159 }
Chris@102 160 R operator()() const {
Chris@102 161 return Maybe_Var_Inv<V1,F>::clone(f)(
Chris@102 162 Maybe_Var_Inv<V2,X>::clone(x),
Chris@102 163 Maybe_Var_Inv<V3,Y>::clone(y),
Chris@102 164 reuser2<V1,V2,V3,F,X,Y>(this) );
Chris@102 165 }
Chris@102 166 };
Chris@102 167
Chris@102 168 template <class V1, class V2, class V3, class F, class X, class Y>
Chris@102 169 struct reuser2 {
Chris@102 170 typedef typename F::template result<F(X,Y)>::type R;
Chris@102 171 typedef Thunk2<V1,V2,V3,F,X,Y,R> M;
Chris@102 172 typedef M result_type;
Chris@102 173 boost::intrusive_ptr<const M> ref;
Chris@102 174 reuser2(a_unique_type_for_nil) {}
Chris@102 175 reuser2(const M* m) : ref(m) {}
Chris@102 176 M operator()( const F& f, const X& x, const Y& y ) {
Chris@102 177 if( !ref ) ref = boost::intrusive_ptr<const M>( new M(f,x,y) );
Chris@102 178 else ref->init(f,x,y);
Chris@102 179 return *ref;
Chris@102 180 }
Chris@102 181 void iter( const F& f, const X& x, const Y& y ) {
Chris@102 182 if( ref ) ref->init(f,x,y);
Chris@102 183 }
Chris@102 184 };
Chris@102 185
Chris@102 186 //////////////////////////////////////////////////////////////////////
Chris@102 187 // reuser3
Chris@102 188 //////////////////////////////////////////////////////////////////////
Chris@102 189
Chris@102 190 template <class V1, class V2, class V3, class V4,
Chris@102 191 class F, class X, class Y, class Z>
Chris@102 192 struct reuser3;
Chris@102 193
Chris@102 194 template <class V1, class V2, class V3, class V4,
Chris@102 195 class F, class X, class Y, class Z, class R>
Chris@102 196 struct Thunk3 : public ThunkImpl<R> {
Chris@102 197 mutable F f;
Chris@102 198 mutable X x;
Chris@102 199 mutable Y y;
Chris@102 200 mutable Z z;
Chris@102 201 Thunk3( const F& ff, const X& xx, const Y& yy, const Z& zz )
Chris@102 202 : f(ff), x(xx), y(yy), z(zz) {}
Chris@102 203 void init( const F& ff, const X& xx, const Y& yy, const Z& zz ) const {
Chris@102 204 Maybe_Var_Inv<V1,F>::remake( f, ff );
Chris@102 205 Maybe_Var_Inv<V2,X>::remake( x, xx );
Chris@102 206 Maybe_Var_Inv<V3,Y>::remake( y, yy );
Chris@102 207 Maybe_Var_Inv<V4,Z>::remake( z, zz );
Chris@102 208 }
Chris@102 209 R operator()() const {
Chris@102 210 return Maybe_Var_Inv<V1,F>::clone(f)(
Chris@102 211 Maybe_Var_Inv<V2,X>::clone(x),
Chris@102 212 Maybe_Var_Inv<V3,Y>::clone(y),
Chris@102 213 Maybe_Var_Inv<V4,Z>::clone(z),
Chris@102 214 reuser3<V1,V2,V3,V4,F,X,Y,Z>(this) );
Chris@102 215 }
Chris@102 216 };
Chris@102 217
Chris@102 218 template <class V1, class V2, class V3, class V4,
Chris@102 219 class F, class X, class Y, class Z>
Chris@102 220 struct reuser3 {
Chris@102 221 typedef typename F::template result<F(X,Y,Z)>::type R;
Chris@102 222 typedef Thunk3<V1,V2,V3,V4,F,X,Y,Z,R> M;
Chris@102 223 typedef M result_type;
Chris@102 224 boost::intrusive_ptr<const M> ref;
Chris@102 225 reuser3(a_unique_type_for_nil) {}
Chris@102 226 reuser3(const M* m) : ref(m) {}
Chris@102 227 M operator()( const F& f, const X& x, const Y& y, const Z& z ) {
Chris@102 228 if( !ref ) ref = boost::intrusive_ptr<const M>( new M(f,x,y,z) );
Chris@102 229 else ref->init(f,x,y,z);
Chris@102 230 return *ref;
Chris@102 231 }
Chris@102 232 void iter( const F& f, const X& x, const Y& y, const Z& z ) {
Chris@102 233 if( ref ) ref->init(f,x,y,z);
Chris@102 234 }
Chris@102 235 };
Chris@102 236
Chris@102 237 }
Chris@102 238
Chris@102 239 }
Chris@102 240 }
Chris@102 241
Chris@102 242 #endif