1 //
2 // Copyright (c) 2000-2003 Brian McNamara and Yannis Smaragdakis
3 //
4 // Permission to use, copy, modify, distribute and sell this software
5 // and its documentation for any purpose is granted without fee,
6 // provided that the above copyright notice and this permission notice
7 // appear in all source code copies and supporting documentation. The
8 // software is provided "as is" without any express or implied
9 // warranty.
10 
11 #ifndef FCPP_FULL_DOT_H
12 #define FCPP_FULL_DOT_H
13 
14 #include "smart.h"
15 #include "curry.h"
16 #include "pre_lambda.h"
17 
18 namespace fcpp {
19 
20 //////////////////////////////////////////////////////////////////////
21 // Full functoids
22 //////////////////////////////////////////////////////////////////////
23 // Just as Curryable2/Curryable3 serve as wrappers which decorate
24 // functoids to give them 'curryability', FullN are wrappers to give
25 // functoids _all_ the 'features' that functoids can have.  The current
26 // "extra feature set" for functoids is
27 //   - curryability     (ability to call with fewer args)
28 //   - lambda-awareness (operator[] for use inside lambda)
29 //   - smartness        (inherited typedefs to answer introspective questions)
30 // The FullN classes just combine all of the features into one
31 // uber-wrapper which does it all.
32 
33 // Don't forget that any features added here need to be added to
34 // the indirect functoids in function.h, too.
35 // And also to the Uncurryable class in prelude.h.
36 // FIX THIS take a good look at Uncurry; it may have pre-dated smartness
37 // and can now be written more sanely...?
38 template <class F>
39 class Full0
40 : public SmartFunctoid0, public CFunType<typename RT<F>::ResultType> {
41    F f;
42 public:
Full0()43    Full0() : f() {}
Full0(const F & ff)44    Full0( const F& ff ) : f(ff) {}
45 #ifdef FCPP_ENABLE_LAMBDA
46    typedef Full0 This;
47    template <class A> typename fcpp_lambda::BracketCallable<This,A>::Result
48    operator[]( const A& a ) const
49    { return fcpp_lambda::BracketCallable<This,A>::go( *this, a ); }
50 #endif
operator()51    inline typename RT<F>::ResultType operator()() const {
52       return f();
53    }
54 };
55 
56 template <class F>
57 class Full1 : public SmartFunctoid1 {
58    F f;
59 public:
Full1()60    Full1() : f() {}
Full1(const F & ff)61    Full1( const F& ff ) : f(ff) {}
62 #ifdef FCPP_ENABLE_LAMBDA
63    typedef Full1 This;
64    template <class A> typename fcpp_lambda::BracketCallable<This,A>::Result
65    operator[]( const A& a ) const
66    { return fcpp_lambda::BracketCallable<This,A>::go( *this, a ); }
67 #endif
68    template <class T> struct Sig
69       : public FunType<typename RT<F,T>::Arg1Type,
70                        typename RT<F,T>::ResultType> {};
71    template <class T>
operator()72    inline typename Sig<T>::ResultType operator()( const T& x ) const {
73       return f(x);
74    }
75 };
76 
77 template <class F>
78 class Full2 : public SmartFunctoid2 {
79    F f;
80 public:
Full2()81    Full2() : f() {}
Full2(const F & ff)82    Full2( const F& ff ) : f(ff) {}
83 #ifdef FCPP_ENABLE_LAMBDA
84    typedef Full2 This;
85    template <class A> typename fcpp_lambda::BracketCallable<This,A>::Result
86    operator[]( const A& a ) const
87    { return fcpp_lambda::BracketCallable<This,A>::go( *this, a ); }
88 #endif
89 /////////////  copied from Curryable2; added impl:: to binders  //////
90    template <class X, class Y=void>
91    struct Sig
92    : public FunType<typename F::template Sig<X,Y>::Arg1Type,
93                     typename F::template Sig<X,Y>::Arg2Type,
94                     typename RT<F,X,Y>::ResultType> {};
95 
96    template <class X>
97    struct Sig<X,void> : public FunType<X,Full1<impl::binder1of2<F,X> > > {};
98 
99    template <class Y>
100    struct Sig<AutoCurryType,Y>
101    : public FunType<AutoCurryType,Y,Full1<impl::binder2of2<F,Y> > > {};
102 
103    template <class X>
104    struct Sig<X,AutoCurryType>
105    : public FunType<X,AutoCurryType,Full1<impl::binder1of2<F,X> > > {};
106 
107    template <class X>
108    typename Sig<X>::ResultType operator()( const X& x ) const {
109       return makeFull1( impl::binder1of2<F,X>(f,x) );
110    }
111    template <class X, class Y>
112    inline typename Sig<X,Y>::ResultType
113    operator()( const X& x, const Y& y ) const {
114       // need partial specialization, so defer to a class helper
115 return impl::Curryable2Helper<typename Sig<X,Y>::ResultType,F,X,Y>::go(f,x,y);
116    }
117 //////////////////////////////////////////////////////////////////////
118 };
119 
120 template <class F>
121 class Full3 : public SmartFunctoid3 {
122    F f;
123 public:
124    Full3() : f() {}
125    Full3( const F& ff ) : f(ff) {}
126 #ifdef FCPP_ENABLE_LAMBDA
127    typedef Full3 This;
128    template <class A> typename fcpp_lambda::BracketCallable<This,A>::Result
129    operator[]( const A& a ) const
130    { return fcpp_lambda::BracketCallable<This,A>::go( *this, a ); }
131 #endif
132 /////////////  copied from Curryable3; added impl:: to all binders  //
133    template <class X, class Y=void, class Z=void>
134    struct Sig
135    : public FunType<typename F::template Sig<X,Y,Z>::Arg1Type,
136                     typename F::template Sig<X,Y,Z>::Arg2Type,
137                     typename F::template Sig<X,Y,Z>::Arg3Type,
138                     typename RT<F,X,Y,Z>::ResultType> {};
139 
140    template <class X,class Y> struct Sig<X,Y,void>
141    : public FunType<X,Y,Full1<impl::binder1and2of3<F,X,Y> > > {};
142 
143    template <class X> struct Sig<X,AutoCurryType,void>
144    : public FunType<X,AutoCurryType,Full2<impl::binder1of3<F,X> > > {};
145 
146    template <class Y> struct Sig<AutoCurryType,Y,void>
147    : public FunType<AutoCurryType,Y,Full2<impl::binder2of3<F,Y> > > {};
148 
149    template <class X> struct Sig<X,void,void>
150    : public FunType<X,Full2<impl::binder1of3<F,X> > > {};
151 
152    template <class X> struct Sig<X,AutoCurryType,AutoCurryType>
153    : public FunType<X,AutoCurryType,AutoCurryType,
154                     Full2<impl::binder1of3<F,X> > > {};
155 
156    template <class Y> struct Sig<AutoCurryType,Y,AutoCurryType>
157    : public FunType<AutoCurryType,Y,AutoCurryType,
158                     Full2<impl::binder2of3<F,Y> > > {};
159 
160    template <class Z> struct Sig<AutoCurryType,AutoCurryType,Z>
161    : public FunType<AutoCurryType,AutoCurryType,Z,
162                     Full2<impl::binder3of3<F,Z> > > {};
163 
164    template <class X,class Z> struct Sig<X,AutoCurryType,Z>
165    : public FunType<X,AutoCurryType,Z,Full1<impl::binder1and3of3<F,X,Z> > > {};
166 
167    template <class Y,class Z> struct Sig<AutoCurryType,Y,Z>
168    : public FunType<AutoCurryType,Y,Z,Full1<impl::binder2and3of3<F,Y,Z> > > {};
169 
170    template <class X,class Y> struct Sig<X,Y,AutoCurryType>
171    : public FunType<X,Y,AutoCurryType,Full1<impl::binder1and2of3<F,X,Y> > > {};
172 
173    template <class X,class Y>
174    typename Sig<X,Y>::ResultType operator()( const X& x, const Y& y ) const {
175       // need partial specialization, so defer to a class helper
176 return impl::Curryable3Helper2<typename Sig<X,Y>::ResultType,F,X,Y>::go(f,x,y);
177    }
178    template <class X>
179    typename Sig<X>::ResultType operator()( const X& x ) const {
180       return makeFull2(impl::binder1of3<F,X>(f,x));
181    }
182 
183    template <class X, class Y, class Z>
184    inline typename Sig<X,Y,Z>::ResultType
185    operator()( const X& x, const Y& y, const Z& z ) const {
186       // need partial specialization, so defer to a class helper
187       return impl::Curryable3Helper<typename Sig<X,Y,Z>::ResultType,F,X,Y,Z>
188       ::go(f,x,y,z);
189    }
190 //////////////////////////////////////////////////////////////////////
191 };
192 
193 template <class F> Full0<F> makeFull0( const F& f ) { return Full0<F>(f); }
194 template <class F> Full1<F> makeFull1( const F& f ) { return Full1<F>(f); }
195 template <class F> Full2<F> makeFull2( const F& f ) { return Full2<F>(f); }
196 template <class F> Full3<F> makeFull3( const F& f ) { return Full3<F>(f); }
197 
198 //////////////////////////////////////////////////////////////////////
199 // Definitions of stuff heretofore put-off...
200 //////////////////////////////////////////////////////////////////////
201 // from curry.h:
202 typedef Full1<impl::Const> Const;
203 typedef Full2<impl::Bind1of1> Bind1of1;
204 
205 typedef Full2<impl::Bind1of2> Bind1of2;
206 typedef Full2<impl::Bind2of2> Bind2of2;
207 typedef Full3<impl::Bind1and2of2> Bind1and2of2;
208 
209 // FIX THIS? I never noticed: the only 4-arg functoid in the entire library
210 typedef impl::Bind1and2and3of3 Bind1and2and3of3;
211 
212 typedef Full3<impl::Bind1and2of3> Bind1and2of3;
213 typedef Full3<impl::Bind2and3of3> Bind2and3of3;
214 typedef Full3<impl::Bind1and3of3> Bind1and3of3;
215 typedef Full2<impl::Bind1of3> Bind1of3;
216 typedef Full2<impl::Bind2of3> Bind2of3;
217 typedef Full2<impl::Bind3of3> Bind3of3;
218 
219 FCPP_MAYBE_NAMESPACE_OPEN
220 FCPP_MAYBE_EXTERN Const const_;   // C++ keyword, so add trailing underscore
221 FCPP_MAYBE_EXTERN Bind1of1 bind1of1;
222 
223 FCPP_MAYBE_EXTERN Bind1of2 bind1of2;
224 FCPP_MAYBE_EXTERN Bind2of2 bind2of2;
225 FCPP_MAYBE_EXTERN Bind1and2of2 bind1and2of2;
226 
227 FCPP_MAYBE_EXTERN Bind1and2and3of3 bind1and2and3of3;
228 FCPP_MAYBE_EXTERN Bind1and2of3 bind1and2of3;
229 FCPP_MAYBE_EXTERN Bind2and3of3 bind2and3of3;
230 FCPP_MAYBE_EXTERN Bind1and3of3 bind1and3of3;
231 FCPP_MAYBE_EXTERN Bind1of3 bind1of3;
232 FCPP_MAYBE_EXTERN Bind2of3 bind2of3;
233 FCPP_MAYBE_EXTERN Bind3of3 bind3of3;
234 FCPP_MAYBE_NAMESPACE_CLOSE
235 
236 } // end namespace fcpp
237 
238 #endif
239