source: liblaziness/lazy.h @ 16

Last change on this file since 16 was 4, checked in by artyom, 13 years ago

liblaziness

File size: 6.9 KB
Line 
1#ifndef __LAZY_H__
2#define __LAZY_H__
3#include "r.h"
4#include "assert.h"
5#include "delegate.h"
6#include <functional>
7#include <utility>
8#include "lambda_trait.h"
9
10// TODO: is case of simple function use typedef instead
11template <typename T>
12class LazyBase
13{
14//      _assert_subclass<TInit, DelegateBase<T>>
15public:
16        virtual ~LazyBase() { }
17        bool isEvaluated() const
18        {
19                return !val.isNull();
20        }
21        void evaluate()
22        {
23                if (val.isNull())
24                {
25                        val = fun();
26                        fun.free();
27                }
28        }
29        R<T> get()
30        {
31                evaluate();
32                return val;
33        }
34        explicit LazyBase(Delegate<T> fun) : fun(fun), val() { }
35        friend R< LazyBase<T> > Ref::mk< LazyBase<T> >();
36        friend R< LazyBase<Int> > suspend(Int val);
37        friend R< LazyBase<UInt> > suspend(UInt val);
38        template <typename U> friend R< LazyBase<U> > suspend(R<U> val);
39        template <typename U, typename V> friend R< LazyBase<U> > suspendP(R<V> val);
40private:
41        explicit LazyBase() : fun(), val() { }
42
43        Delegate<T> fun;
44        R<T> val;
45};
46
47// specialize R definition for LazyBase to make lazy objects more useable
48template <typename T>
49class R< LazyBase<T>, true > : public R< LazyBase<T>, false >
50{
51        protected:
52                // passing protected constructors
53                inline R(int i) : R< LazyBase<T>, false >(i) { }
54        public:
55                // passing public constructors
56                inline R() : R< LazyBase<T>, false>() { }
57                template<typename U, bool od> inline R(R< LazyBase<U>, od >& o) : R< LazyBase<T>, false>(o, 0) { _assert_subclass<U, T> ERROR; }
58                template<typename U, bool od> inline R(R< LazyBase<U>, od >&& o) : R< LazyBase<T>, false>(o, 0) { _assert_subclass<U, T> ERROR; }
59                // passing operator=
60                template<typename U, bool od> inline R< LazyBase<T>, true >& operator=(R< LazyBase<U>, od >&& o) { R< LazyBase<T>, false >::operator=(o); return *this; }
61                template<typename U, bool od> inline R< LazyBase<T>, true >& operator=(R< LazyBase<U>, od >& o) { R< LazyBase<T>, false >::operator=(o); return *this; }
62                // additional functionality
63                inline T* operator->() { return &this->deref().get().deref(); }
64                inline T& operator*() { return this->deref().get().deref(); }
65                inline R<T> getR() { return this->deref().get(); }
66                // keep reference makeable with Ref::mk
67                friend class Ref;
68};
69
70template<typename T>
71using Lazy = R< LazyBase<T> >;
72
73template<typename T>
74Lazy<T> mkLazy(Delegate<T> init)
75{
76        return Ref::mk< LazyBase<T> >(init);
77}
78
79/*template <typename T, typename TReal>
80Lazy<T, TReal, FunBase<T, TReal> > mkLazy(typename FunBase<T, TReal>::FunType fun)
81{
82        return mkLazy(mkFun(fun));
83}*/
84
85template <typename T>
86Lazy<T> mkLazy(R<T> (*fun)())
87{
88        return mkLazy<T>(mkFun(fun));
89}
90
91template <typename T>
92R<T> lazyVal(Lazy<T> lval)
93{
94        return lval.deref().get();
95}
96
97template <typename T>
98bool isEvaluated(R< LazyBase<T> > lval)
99{
100        return lval.deref().isEvaluated();
101}
102
103template <typename T>
104Lazy<T> suspend(R<T> val)
105{
106        Lazy<T> l = Ref::mk< LazyBase<T> >();
107        l.deref().val = val;
108        return l;
109}
110
111Lazy<Int> suspend(Int i)
112{
113        auto l = Ref::mk< LazyBase<Int> >();
114        l.deref().val = Ref::mk<Int, Int>(i);
115        return l;
116}
117
118Lazy<UInt> suspend(UInt i)
119{
120        auto l = Ref::mk< LazyBase<UInt> >();
121        l.deref().val = Ref::mk<UInt, UInt>(i);
122        return l;
123}
124
125template <typename U, typename V>
126Lazy<U> suspendP(R<V> val)
127{
128        Lazy<U> l = Ref::mk< LazyBase<U> >();
129        l.deref().val = val;
130        return l;
131}
132
133template <typename T>
134T& operator*(LazyBase<T>& lval)
135{
136        return *(lval.get());
137}
138
139#include <iostream>
140
141
142// moved to lazy_op.h
143/*template <typename T>
144class LazyOp
145{
146        private:
147                static R<T> inc_inner(Lazy<T> i)
148                {
149                        return Ref::mk<T, T>(lazyVal(i).deref() + 1);
150                }
151                static R<T> add_inner(Lazy<T> a, Lazy<T> b)
152                {
153                        //std::cout << "adding : " << lazyVal(a).deref() << " + " << lazyVal(b).deref() << std::endl;
154                        return Ref::mk<T, T>(lazyVal(a).deref() + lazyVal(b).deref());
155                }
156                static R<T> sqr_inner(Lazy<T> x)
157                {
158                        T val = lazyVal(x).deref();
159                        return Ref::mk<T, T>(val * val);
160                }
161        public:
162                static Lazy<T> inc(Lazy<T> i)
163                {
164                        auto fun = mkFun(&inc_inner, i);
165                        return mkLazy<T>(fun);
166                }
167                static Lazy<T> add(Lazy<T> a, Lazy<T> b)
168                {
169                        auto fun = mkFun(&add_inner, a, b);
170                        return mkLazy<T>(fun);
171                }
172                static Lazy<T> sqr(Lazy<T> x)
173                {
174                        return mkLazy<T>(mkFun(&sqr_inner, x));
175                }
176};*/
177
178/*template <typename T>
179class LazyOpR
180{
181        public:
182                typedef LazyBase<Int> LazyInt
183                lazyOpR()
184                {
185                        rAdd = Ref::mk< Funx2Base<LazyInt, LazyInt, LazyInt>, Funx2Base<LazyInt, LazyInt, LazyInt>::FunType, R<LazyInt>, R<LazyInt> >(LazyOp::, arg1, arg2);
186                }
187                ~lazyOpR() { }
188
189                Funx2<LazyBase<Int>, LazyBase<Int>, LazyBase<Int>> rAdd;
190};*/
191
192/**** function lazification ****/
193/*template<typename T>
194Delegate<T> lazify(R<T> (*fun)())
195{
196        return mkFun([] (decltype(fun) fun) {
197                return mkLazy(mkFun([] (decltype(fun) fun) {
198                        return fun();
199                }, fun));
200        }, fun);
201}*/
202
203/*template<typename T, typename T1>
204Delegate<T> lazify(R<T> (*fun) (R<T1>))
205{
206        return mkFun1([] (decltype(fun) fun, Lazy<T1> arg1) {
207                return mkLazy(mkFun([] (decltype(fun) fun, Lazy<T1> arg1) {
208                        return fun(arg1.getR());
209                }, fun));
210        }, fun);
211}*/
212
213template<typename TFun, int arg_count>
214struct lazify_data;
215
216template<typename TFun>
217struct lazify_data<TFun, 0>
218{
219        typedef typename lambdatype<TFun>::return_type return_type;
220        typedef Delegate<typename return_type::etype> delegate_type;
221        typedef Delegate<LazyBase<typename return_type::etype>> ldelegate_type;
222};
223
224template<typename TFun>
225struct lazify_data<TFun, 1>
226{
227        typedef typename lambdatype<TFun>::return_type return_type;
228        typedef typename lambdatype<TFun>::arg1_type arg1_type;
229        typedef Delegate1<typename return_type::etype, typename arg1_type::etype> delegate_type;
230        typedef Delegate1<LazyBase<typename return_type::etype>, LazyBase<typename arg1_type::etype>> ldelegate_type;
231};
232
233template<typename TFun, int arg_count, typename TFunData>
234class Lazify;
235
236template<typename TFun, typename TFunData>
237class Lazify<TFun, 0, TFunData>
238{
239        public:
240                static auto doLazify(TFun fun) -> typename TFunData::ldelegate_type
241                {
242                        return mkLFun([] (typename TFunData::delegate_type fun) {
243                                return mkLazy(mkLFun([] (typename TFunData::delegate_type fun) {
244                                        return fun();
245                                }, fun));
246                        }, mkLFun(fun));
247                }
248};
249
250template<typename TFun, typename TFunData>
251class Lazify<TFun, 1, TFunData>
252{
253        public:
254                static auto doLazify(TFun fun) -> typename TFunData::ldelegate_type
255                {
256                        return mkLFun1([] (typename TFunData::delegate_type fun, Lazy<typename TFunData::arg1_type::etype> arg1) {
257                                return mkLazy(mkLFun([] (typename TFunData::delegate_type fun, Lazy<typename TFunData::arg1_type::etype> arg1) {
258                                        return fun(arg1.getR());
259                                }, fun, arg1));
260                        }, mkLFun1(fun));
261                }
262};
263
264template<typename TFun, int arg_count = lambdatype<TFun>::arg_count, typename TFunData = lazify_data<TFun, arg_count>>
265auto lazify(TFun fun) -> typename TFunData::ldelegate_type
266{
267        return Lazify<TFun, arg_count, TFunData>::doLazify(fun);
268}
269
270#endif
Note: See TracBrowser for help on using the repository browser.