#ifndef __LAZY_H__ #define __LAZY_H__ #include "r.h" #include "assert.h" #include "delegate.h" #include #include #include "lambda_trait.h" // TODO: is case of simple function use typedef instead template class LazyBase { // _assert_subclass> public: virtual ~LazyBase() { } bool isEvaluated() const { return !val.isNull(); } void evaluate() { if (val.isNull()) { val = fun(); fun.free(); } } R get() { evaluate(); return val; } explicit LazyBase(Delegate fun) : fun(fun), val() { } friend R< LazyBase > Ref::mk< LazyBase >(); friend R< LazyBase > suspend(Int val); friend R< LazyBase > suspend(UInt val); template friend R< LazyBase > suspend(R val); template friend R< LazyBase > suspendP(R val); private: explicit LazyBase() : fun(), val() { } Delegate fun; R val; }; // specialize R definition for LazyBase to make lazy objects more useable template class R< LazyBase, true > : public R< LazyBase, false > { protected: // passing protected constructors inline R(int i) : R< LazyBase, false >(i) { } public: // passing public constructors inline R() : R< LazyBase, false>() { } template inline R(R< LazyBase, od >& o) : R< LazyBase, false>(o, 0) { _assert_subclass ERROR; } template inline R(R< LazyBase, od >&& o) : R< LazyBase, false>(o, 0) { _assert_subclass ERROR; } // passing operator= template inline R< LazyBase, true >& operator=(R< LazyBase, od >&& o) { R< LazyBase, false >::operator=(o); return *this; } template inline R< LazyBase, true >& operator=(R< LazyBase, od >& o) { R< LazyBase, false >::operator=(o); return *this; } // additional functionality inline T* operator->() { return &this->deref().get().deref(); } inline T& operator*() { return this->deref().get().deref(); } inline R getR() { return this->deref().get(); } // keep reference makeable with Ref::mk friend class Ref; }; template using Lazy = R< LazyBase >; template Lazy mkLazy(Delegate init) { return Ref::mk< LazyBase >(init); } /*template Lazy > mkLazy(typename FunBase::FunType fun) { return mkLazy(mkFun(fun)); }*/ template Lazy mkLazy(R (*fun)()) { return mkLazy(mkFun(fun)); } template R lazyVal(Lazy lval) { return lval.deref().get(); } template bool isEvaluated(R< LazyBase > lval) { return lval.deref().isEvaluated(); } template Lazy suspend(R val) { Lazy l = Ref::mk< LazyBase >(); l.deref().val = val; return l; } Lazy suspend(Int i) { auto l = Ref::mk< LazyBase >(); l.deref().val = Ref::mk(i); return l; } Lazy suspend(UInt i) { auto l = Ref::mk< LazyBase >(); l.deref().val = Ref::mk(i); return l; } template Lazy suspendP(R val) { Lazy l = Ref::mk< LazyBase >(); l.deref().val = val; return l; } template T& operator*(LazyBase& lval) { return *(lval.get()); } #include // moved to lazy_op.h /*template class LazyOp { private: static R inc_inner(Lazy i) { return Ref::mk(lazyVal(i).deref() + 1); } static R add_inner(Lazy a, Lazy b) { //std::cout << "adding : " << lazyVal(a).deref() << " + " << lazyVal(b).deref() << std::endl; return Ref::mk(lazyVal(a).deref() + lazyVal(b).deref()); } static R sqr_inner(Lazy x) { T val = lazyVal(x).deref(); return Ref::mk(val * val); } public: static Lazy inc(Lazy i) { auto fun = mkFun(&inc_inner, i); return mkLazy(fun); } static Lazy add(Lazy a, Lazy b) { auto fun = mkFun(&add_inner, a, b); return mkLazy(fun); } static Lazy sqr(Lazy x) { return mkLazy(mkFun(&sqr_inner, x)); } };*/ /*template class LazyOpR { public: typedef LazyBase LazyInt lazyOpR() { rAdd = Ref::mk< Funx2Base, Funx2Base::FunType, R, R >(LazyOp::, arg1, arg2); } ~lazyOpR() { } Funx2, LazyBase, LazyBase> rAdd; };*/ /**** function lazification ****/ /*template Delegate lazify(R (*fun)()) { return mkFun([] (decltype(fun) fun) { return mkLazy(mkFun([] (decltype(fun) fun) { return fun(); }, fun)); }, fun); }*/ /*template Delegate lazify(R (*fun) (R)) { return mkFun1([] (decltype(fun) fun, Lazy arg1) { return mkLazy(mkFun([] (decltype(fun) fun, Lazy arg1) { return fun(arg1.getR()); }, fun)); }, fun); }*/ template struct lazify_data; template struct lazify_data { typedef typename lambdatype::return_type return_type; typedef Delegate delegate_type; typedef Delegate> ldelegate_type; }; template struct lazify_data { typedef typename lambdatype::return_type return_type; typedef typename lambdatype::arg1_type arg1_type; typedef Delegate1 delegate_type; typedef Delegate1, LazyBase> ldelegate_type; }; template class Lazify; template class Lazify { public: static auto doLazify(TFun fun) -> typename TFunData::ldelegate_type { return mkLFun([] (typename TFunData::delegate_type fun) { return mkLazy(mkLFun([] (typename TFunData::delegate_type fun) { return fun(); }, fun)); }, mkLFun(fun)); } }; template class Lazify { public: static auto doLazify(TFun fun) -> typename TFunData::ldelegate_type { return mkLFun1([] (typename TFunData::delegate_type fun, Lazy arg1) { return mkLazy(mkLFun([] (typename TFunData::delegate_type fun, Lazy arg1) { return fun(arg1.getR()); }, fun, arg1)); }, mkLFun1(fun)); } }; template::arg_count, typename TFunData = lazify_data> auto lazify(TFun fun) -> typename TFunData::ldelegate_type { return Lazify::doLazify(fun); } #endif