summaryrefslogtreecommitdiff
path: root/boost/phoenix/function/lazy_reuse.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'boost/phoenix/function/lazy_reuse.hpp')
-rw-r--r--boost/phoenix/function/lazy_reuse.hpp242
1 files changed, 242 insertions, 0 deletions
diff --git a/boost/phoenix/function/lazy_reuse.hpp b/boost/phoenix/function/lazy_reuse.hpp
new file mode 100644
index 0000000000..cef2ded820
--- /dev/null
+++ b/boost/phoenix/function/lazy_reuse.hpp
@@ -0,0 +1,242 @@
+////////////////////////////////////////////////////////////////////////////
+// lazy_reuse.hpp
+//
+// Build lazy operations for Phoenix equivalents for FC++
+//
+// These are equivalents of the Boost FC++ functoids in reuse.hpp
+//
+// Implemented so far:
+//
+// reuser1 (not yet tested)
+// reuser2 (not yet tested)
+// reuser3
+//
+// NOTE: It has been possible to simplify the operation of this code.
+// It now makes no use of boost::function or old FC++ code.
+//
+// The functor type F must be an operator defined with
+// boost::phoenix::function.
+// See the example Apply in lazy_prelude.hpp
+//
+////////////////////////////////////////////////////////////////////////////
+/*=============================================================================
+ 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)
+==============================================================================*/
+
+#ifndef BOOST_PHOENIX_FUNCTION_LAZY_REUSE
+#define BOOST_PHOENIX_FUNCTION_LAZY_REUSE
+
+#include <boost/phoenix/core.hpp>
+#include <boost/phoenix/function.hpp>
+#include <boost/intrusive_ptr.hpp>
+
+
+namespace boost {
+
+ namespace phoenix {
+
+ namespace fcpp {
+
+//////////////////////////////////////////////////////////////////////
+// Original FC++ comment:
+// "Reuser"s are effectively special-purpose versions of curry() that
+// enable recursive list functoids to reuse the thunk of the curried
+// recursive call. See
+// http://www.cc.gatech.edu/~yannis/fc++/New/reusers.html
+// for a more detailed description.
+//////////////////////////////////////////////////////////////////////
+
+// For efficiency, we mark parameters as either "VAR"iant or "INV"ariant.
+struct INV {};
+struct VAR {};
+
+template <class V, class X> struct Maybe_Var_Inv;
+template <class X>
+struct Maybe_Var_Inv<VAR,X> {
+ static void remake( X& x, const X& val ) {
+ x.~X();
+ new (&x) X(val);
+ }
+ static X clone( const X& x ) { return X(x); }
+};
+template <class X>
+struct Maybe_Var_Inv<INV,X> {
+ static void remake( X&, const X& ) {}
+ static const X& clone( const X& x ) { return x; }
+};
+
+/////////////////////////////////////////////////////////////////////
+// ThunkImpl is an implementation of Fun0Impl for this use.
+/////////////////////////////////////////////////////////////////////
+
+template <class Result>
+class ThunkImpl
+{
+ mutable RefCountType refC;
+public:
+ ThunkImpl() : refC(0) {}
+ virtual Result operator()() const =0;
+ virtual ~ThunkImpl() {}
+ template <class X>
+ friend void intrusive_ptr_add_ref( const ThunkImpl<X>* p );
+ template <class X>
+ friend void intrusive_ptr_release( const ThunkImpl<X>* p );
+};
+
+template <class T>
+void intrusive_ptr_add_ref( const ThunkImpl<T>* p ) {
+ ++ (p->refC);
+}
+template <class T>
+void intrusive_ptr_release( const ThunkImpl<T>* p ) {
+ if( !--(p->refC) ) delete p;
+}
+
+//////////////////////////////////////////////////////////////////////
+// reuser1 is needed in list<T> operations
+//////////////////////////////////////////////////////////////////////
+
+template <class V1, class V2, class F, class X>
+struct reuser1;
+
+template <class V1, class V2, class F, class X, class R>
+struct Thunk1 : public ThunkImpl<R> {
+ mutable F f;
+ mutable X x;
+ Thunk1( const F& ff, const X& xx ) : f(ff), x(xx) {}
+ void init( const F& ff, const X& xx ) const {
+ Maybe_Var_Inv<V1,F>::remake( f, ff );
+ Maybe_Var_Inv<V2,X>::remake( x, xx );
+ }
+ R operator()() const {
+ return Maybe_Var_Inv<V1,F>::clone(f)(
+ Maybe_Var_Inv<V2,X>::clone(x),
+ reuser1<V1,V2,F,X>(this) );
+ }
+};
+
+template <class V1, class V2, class F, class X>
+struct reuser1 {
+ typedef typename F::template result<F(X)>::type R;
+ typedef typename boost::phoenix::function<R> fun0_type;
+ typedef Thunk1<V1,V2,F,X,R> M;
+ typedef M result_type;
+ boost::intrusive_ptr<const M> ref;
+ reuser1(a_unique_type_for_nil) {}
+ reuser1(const M* m) : ref(m) {}
+ M operator()( const F& f, const X& x ) {
+ if( !ref ) ref = boost::intrusive_ptr<const M>( new M(f,x) );
+ else ref->init(f,x);
+ return *ref;
+ }
+ void iter( const F& f, const X& x ) {
+ if( ref ) ref->init(f,x);
+ }
+};
+
+//////////////////////////////////////////////////////////////////////
+// reuser2 is needed in list<T>
+//////////////////////////////////////////////////////////////////////
+
+template <class V1, class V2, class V3, class F, class X, class Y>
+struct reuser2;
+
+template <class V1, class V2, class V3, class F, class X, class Y, class R>
+struct Thunk2 : public ThunkImpl<R> {
+ mutable F f;
+ mutable X x;
+ mutable Y y;
+ Thunk2( const F& ff, const X& xx, const Y& yy ) : f(ff), x(xx), y(yy) {}
+ void init( const F& ff, const X& xx, const Y& yy ) const {
+ Maybe_Var_Inv<V1,F>::remake( f, ff );
+ Maybe_Var_Inv<V2,X>::remake( x, xx );
+ Maybe_Var_Inv<V3,Y>::remake( y, yy );
+ }
+ R operator()() const {
+ return Maybe_Var_Inv<V1,F>::clone(f)(
+ Maybe_Var_Inv<V2,X>::clone(x),
+ Maybe_Var_Inv<V3,Y>::clone(y),
+ reuser2<V1,V2,V3,F,X,Y>(this) );
+ }
+};
+
+template <class V1, class V2, class V3, class F, class X, class Y>
+struct reuser2 {
+ typedef typename F::template result<F(X,Y)>::type R;
+ typedef Thunk2<V1,V2,V3,F,X,Y,R> M;
+ typedef M result_type;
+ boost::intrusive_ptr<const M> ref;
+ reuser2(a_unique_type_for_nil) {}
+ reuser2(const M* m) : ref(m) {}
+ M operator()( const F& f, const X& x, const Y& y ) {
+ if( !ref ) ref = boost::intrusive_ptr<const M>( new M(f,x,y) );
+ else ref->init(f,x,y);
+ return *ref;
+ }
+ void iter( const F& f, const X& x, const Y& y ) {
+ if( ref ) ref->init(f,x,y);
+ }
+};
+
+//////////////////////////////////////////////////////////////////////
+// reuser3
+//////////////////////////////////////////////////////////////////////
+
+template <class V1, class V2, class V3, class V4,
+ class F, class X, class Y, class Z>
+struct reuser3;
+
+template <class V1, class V2, class V3, class V4,
+ class F, class X, class Y, class Z, class R>
+struct Thunk3 : public ThunkImpl<R> {
+ mutable F f;
+ mutable X x;
+ mutable Y y;
+ mutable Z z;
+ Thunk3( const F& ff, const X& xx, const Y& yy, const Z& zz )
+ : f(ff), x(xx), y(yy), z(zz) {}
+ void init( const F& ff, const X& xx, const Y& yy, const Z& zz ) const {
+ Maybe_Var_Inv<V1,F>::remake( f, ff );
+ Maybe_Var_Inv<V2,X>::remake( x, xx );
+ Maybe_Var_Inv<V3,Y>::remake( y, yy );
+ Maybe_Var_Inv<V4,Z>::remake( z, zz );
+ }
+ R operator()() const {
+ return Maybe_Var_Inv<V1,F>::clone(f)(
+ Maybe_Var_Inv<V2,X>::clone(x),
+ Maybe_Var_Inv<V3,Y>::clone(y),
+ Maybe_Var_Inv<V4,Z>::clone(z),
+ reuser3<V1,V2,V3,V4,F,X,Y,Z>(this) );
+ }
+};
+
+template <class V1, class V2, class V3, class V4,
+ class F, class X, class Y, class Z>
+struct reuser3 {
+ typedef typename F::template result<F(X,Y,Z)>::type R;
+ typedef Thunk3<V1,V2,V3,V4,F,X,Y,Z,R> M;
+ typedef M result_type;
+ boost::intrusive_ptr<const M> ref;
+ reuser3(a_unique_type_for_nil) {}
+ reuser3(const M* m) : ref(m) {}
+ M operator()( const F& f, const X& x, const Y& y, const Z& z ) {
+ if( !ref ) ref = boost::intrusive_ptr<const M>( new M(f,x,y,z) );
+ else ref->init(f,x,y,z);
+ return *ref;
+ }
+ void iter( const F& f, const X& x, const Y& y, const Z& z ) {
+ if( ref ) ref->init(f,x,y,z);
+ }
+};
+
+ }
+
+ }
+}
+
+#endif