Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/boost/phoenix/function/lazy_reuse.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 ////////////////////////////////////////////////////////////////////////////
0002 // lazy_reuse.hpp
0003 //
0004 // Build lazy operations for Phoenix equivalents for FC++
0005 //
0006 // These are equivalents of the Boost FC++ functoids in reuse.hpp
0007 //
0008 // Implemented so far:
0009 //
0010 // reuser1
0011 // reuser2
0012 // reuser3
0013 // reuser4 (not yet tested)
0014 //
0015 // NOTE: It has been possible to simplify the operation of this code.
0016 //       It now makes no use of boost::function or old FC++ code.
0017 //
0018 //       The functor type F must be an operator defined with
0019 //       boost::phoenix::function.
0020 //       See the example Apply in lazy_prelude.hpp
0021 //
0022 ////////////////////////////////////////////////////////////////////////////
0023 /*=============================================================================
0024     Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis
0025     Copyright (c) 2001-2007 Joel de Guzman
0026     Copyright (c) 2015 John Fletcher
0027 
0028     Distributed under the Boost Software License, Version 1.0. (See accompanying
0029     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0030 ==============================================================================*/
0031 
0032 #ifndef BOOST_PHOENIX_FUNCTION_LAZY_REUSE
0033 #define BOOST_PHOENIX_FUNCTION_LAZY_REUSE
0034 
0035 #include <boost/phoenix/core.hpp>
0036 #include <boost/phoenix/function.hpp>
0037 #include <boost/intrusive_ptr.hpp>
0038 
0039 
0040 namespace boost {
0041 
0042   namespace phoenix {
0043 
0044     namespace fcpp {
0045 
0046 //////////////////////////////////////////////////////////////////////
0047 // Original FC++ comment:
0048 // "Reuser"s are effectively special-purpose versions of curry() that
0049 // enable recursive list functoids to reuse the thunk of the curried
0050 // recursive call.  See
0051 //    http://www.cc.gatech.edu/~yannis/fc++/New/reusers.html
0052 // for a more detailed description.
0053 //////////////////////////////////////////////////////////////////////
0054 
0055 // For efficiency, we mark parameters as either "VAR"iant or "INV"ariant.
0056 struct INV {};
0057 struct VAR {};
0058 
0059 template <class V, class X> struct Maybe_Var_Inv;
0060 template <class X>
0061 struct Maybe_Var_Inv<VAR,X> {
0062    static void remake( X& x, const X& val ) {
0063       x.~X();
0064       new (&x) X(val);
0065    }
0066    static X clone( const X& x ) { return X(x); }
0067 };
0068 template <class X>
0069 struct Maybe_Var_Inv<INV,X> {
0070    static void remake( X&, const X& ) {}
0071    static const X& clone( const X& x ) { return x; }
0072 };
0073 
0074 /////////////////////////////////////////////////////////////////////
0075 // ThunkImpl is an implementation of Fun0Impl for this use.
0076 /////////////////////////////////////////////////////////////////////
0077 
0078 template <class Result>
0079 class ThunkImpl
0080 {
0081    mutable RefCountType refC;
0082 public:
0083    ThunkImpl() : refC(0) {}
0084    virtual Result operator()() const =0;
0085    virtual ~ThunkImpl() {}
0086    template <class X>
0087    friend void intrusive_ptr_add_ref( const ThunkImpl<X>* p );
0088    template <class X>
0089    friend void intrusive_ptr_release( const ThunkImpl<X>* p );
0090 };
0091 
0092 template <class T>
0093 void intrusive_ptr_add_ref( const ThunkImpl<T>* p ) {
0094    ++ (p->refC);
0095 }
0096 template <class T>
0097 void intrusive_ptr_release( const ThunkImpl<T>* p ) {
0098    if( !--(p->refC) ) delete p;
0099 }
0100 
0101 //////////////////////////////////////////////////////////////////////
0102 // reuser1 is needed in list<T> operations
0103 //////////////////////////////////////////////////////////////////////
0104 
0105 template <class V1, class V2, class F, class X>
0106 struct reuser1;
0107 
0108 template <class V1, class V2, class F, class X, class R>
0109 struct Thunk1 : public ThunkImpl<R> {
0110    mutable F f;
0111    mutable X x;
0112    Thunk1( const F& ff, const X& xx ) : f(ff), x(xx) {}
0113    void init( const F& ff, const X& xx ) const {
0114       Maybe_Var_Inv<V1,F>::remake( f, ff );
0115       Maybe_Var_Inv<V2,X>::remake( x, xx );
0116    }
0117    R operator()() const {
0118       return Maybe_Var_Inv<V1,F>::clone(f)(
0119          Maybe_Var_Inv<V2,X>::clone(x),
0120          reuser1<V1,V2,F,X>(this) );
0121    }
0122 };
0123 
0124 template <class V1, class V2, class F, class X>
0125 struct reuser1 {
0126    typedef typename F::template result<F(X)>::type R;
0127    typedef typename boost::phoenix::function<R> fun0_type;
0128    typedef Thunk1<V1,V2,F,X,R> M;
0129    typedef M result_type;
0130    boost::intrusive_ptr<const M> ref;
0131    reuser1(a_unique_type_for_nil) {}
0132    reuser1(const M* m) : ref(m) {}
0133    M operator()( const F& f, const X& x ) {
0134       if( !ref )   ref = boost::intrusive_ptr<const M>( new M(f,x) );
0135       else         ref->init(f,x);
0136       return *ref;
0137    }
0138    void iter( const F& f, const X& x ) {
0139       if( ref )    ref->init(f,x);
0140    }
0141 };
0142 
0143 //////////////////////////////////////////////////////////////////////
0144 // reuser2 is needed in list<T>
0145 //////////////////////////////////////////////////////////////////////
0146 
0147 template <class V1, class V2, class V3, class F, class X, class Y>
0148 struct reuser2;
0149 
0150 template <class V1, class V2, class V3, class F, class X, class Y, class R>
0151 struct Thunk2 : public ThunkImpl<R> {
0152    mutable F f;
0153    mutable X x;
0154    mutable Y y;
0155    Thunk2( const F& ff, const X& xx, const Y& yy ) : f(ff), x(xx), y(yy) {}
0156    void init( const F& ff, const X& xx, const Y& yy ) const {
0157       Maybe_Var_Inv<V1,F>::remake( f, ff );
0158       Maybe_Var_Inv<V2,X>::remake( x, xx );
0159       Maybe_Var_Inv<V3,Y>::remake( y, yy );
0160    }
0161    R operator()() const {
0162       return Maybe_Var_Inv<V1,F>::clone(f)(
0163          Maybe_Var_Inv<V2,X>::clone(x),
0164          Maybe_Var_Inv<V3,Y>::clone(y),
0165          reuser2<V1,V2,V3,F,X,Y>(this) );
0166    }
0167 };
0168 
0169 template <class V1, class V2, class V3, class F, class X, class Y>
0170 struct reuser2 {
0171    typedef typename F::template result<F(X,Y)>::type R;
0172    typedef Thunk2<V1,V2,V3,F,X,Y,R> M;
0173    typedef M result_type;
0174    boost::intrusive_ptr<const M> ref;
0175    reuser2(a_unique_type_for_nil) {}
0176    reuser2(const M* m) : ref(m) {}
0177    M operator()( const F& f, const X& x, const Y& y ) {
0178       if( !ref )   ref = boost::intrusive_ptr<const M>( new M(f,x,y) );
0179       else         ref->init(f,x,y);
0180       return *ref;
0181    }
0182    void iter( const F& f, const X& x, const Y& y ) {
0183       if( ref )    ref->init(f,x,y);
0184    }
0185 };
0186 
0187 //////////////////////////////////////////////////////////////////////
0188 // reuser3
0189 //////////////////////////////////////////////////////////////////////
0190 
0191 template <class V1, class V2, class V3, class V4,
0192           class F, class X, class Y, class Z>
0193 struct reuser3;
0194 
0195 template <class V1, class V2, class V3, class V4,
0196           class F, class X, class Y, class Z, class R>
0197 struct Thunk3 : public ThunkImpl<R> {
0198    mutable F f;
0199    mutable X x;
0200    mutable Y y;
0201    mutable Z z;
0202    Thunk3( const F& ff, const X& xx, const Y& yy, const Z& zz )
0203       : f(ff), x(xx), y(yy), z(zz) {}
0204    void init( const F& ff, const X& xx, const Y& yy, const Z& zz ) const {
0205       Maybe_Var_Inv<V1,F>::remake( f, ff );
0206       Maybe_Var_Inv<V2,X>::remake( x, xx );
0207       Maybe_Var_Inv<V3,Y>::remake( y, yy );
0208       Maybe_Var_Inv<V4,Z>::remake( z, zz );
0209    }
0210    R operator()() const {
0211       return Maybe_Var_Inv<V1,F>::clone(f)(
0212          Maybe_Var_Inv<V2,X>::clone(x),
0213          Maybe_Var_Inv<V3,Y>::clone(y),
0214          Maybe_Var_Inv<V4,Z>::clone(z),
0215          reuser3<V1,V2,V3,V4,F,X,Y,Z>(this) );
0216    }
0217 };
0218 
0219 template <class V1, class V2, class V3, class V4,
0220           class F, class X, class Y, class Z>
0221 struct reuser3 {
0222    typedef typename F::template result<F(X,Y,Z)>::type R;
0223    typedef Thunk3<V1,V2,V3,V4,F,X,Y,Z,R> M;
0224    typedef M result_type;
0225    boost::intrusive_ptr<const M> ref;
0226    reuser3(a_unique_type_for_nil) {}
0227    reuser3(const M* m) : ref(m) {}
0228    M operator()( const F& f, const X& x, const Y& y, const Z& z ) {
0229       if( !ref )   ref = boost::intrusive_ptr<const M>( new M(f,x,y,z) );
0230       else         ref->init(f,x,y,z);
0231       return *ref;
0232    }
0233    void iter( const F& f, const X& x, const Y& y, const Z& z ) {
0234       if( ref )    ref->init(f,x,y,z);
0235    }
0236 };
0237 //////////////////////////////////////////////////////////////////////
0238 // reuser4
0239 //////////////////////////////////////////////////////////////////////
0240 
0241       template <class V1, class V2, class V3, class V4, class V5,
0242                 class F, class W, class X, class Y, class Z>
0243 struct reuser4;
0244 
0245       template <class V1, class V2, class V3, class V4, class V5,
0246                 class F, class W, class X, class Y, class Z, class R>
0247 struct Thunk4 : public ThunkImpl<R> {
0248       mutable F f;
0249       mutable W w;
0250       mutable X x;
0251       mutable Y y;
0252       mutable Z z;
0253       Thunk4( const F& ff, const W& ww, const X& xx, const Y& yy, const Z& zz )
0254             : f(ff), w(ww), x(xx), y(yy), z(zz) {}
0255    void init( const F& ff, const W& ww, const X& xx, const Y& yy, const Z& zz ) const {
0256       Maybe_Var_Inv<V1,F>::remake( f, ff );
0257       Maybe_Var_Inv<V2,W>::remake( w, ww );
0258       Maybe_Var_Inv<V3,X>::remake( x, xx );
0259       Maybe_Var_Inv<V4,Y>::remake( y, yy );
0260       Maybe_Var_Inv<V5,Z>::remake( z, zz );
0261    }
0262    R operator()() const {
0263       return Maybe_Var_Inv<V1,F>::clone(f)(
0264          Maybe_Var_Inv<V2,W>::clone(w),
0265          Maybe_Var_Inv<V3,X>::clone(x),
0266          Maybe_Var_Inv<V4,Y>::clone(y),
0267          Maybe_Var_Inv<V5,Z>::clone(z),
0268          reuser4<V1,V2,V3,V4,V5,F,W,X,Y,Z>(this) );
0269    }
0270 };
0271 
0272       template <class V1, class V2, class V3, class V4, class V5,
0273                 class F, class W, class X, class Y, class Z>
0274       struct reuser4 {
0275         typedef typename F::template result<F(W,X,Y,Z)>::type R;
0276         typedef Thunk4<V1,V2,V3,V4,V5,F,W,X,Y,Z,R> M;
0277         typedef M result_type;
0278         boost::intrusive_ptr<const M> ref;
0279         reuser4(a_unique_type_for_nil) {}
0280         reuser4(const M* m) : ref(m) {}
0281    M operator()( const F& f, const W& w, const X& x, const Y& y, const Z& z ) {
0282       if( !ref )   ref = boost::intrusive_ptr<const M>( new M(f,w,x,y,z) );
0283       else         ref->init(f,w,x,y,z);
0284       return *ref;
0285    }
0286    void iter( const F& f, const W& w, const X& x, const Y& y, const Z& z ) {
0287       if( ref )    ref->init(f,w,x,y,z);
0288    }
0289       };
0290 
0291     }
0292 
0293   }
0294 }
0295 
0296 #endif