Zen
A cross-platform functional programming language
|
00001 00007 #pragma once 00008 00009 #include "zrt.hpp" 00010 00012 namespace ztl { 00014 00016 template <typename ReturnT> 00017 class ClosureT : public zbl::Closure { 00018 protected: 00021 inline ClosureT(){} 00022 00023 private: 00027 inline ClosureT(const ClosureT& src) {unused(src);} 00028 00029 public: 00033 inline ReturnT& getValue() {return *_val;} 00034 00038 inline void setValue(const ReturnT& val) {_val.reset(new ReturnT(val));} 00039 00040 private: 00042 z::scopedptr<ReturnT> _val; 00043 }; 00044 00046 00048 template <typename ReturnT> 00049 class FunctionCallClosureT : public ClosureT<ReturnT> { 00050 }; 00051 00053 00055 class SharedClosureT : public zbl::Closure { 00056 protected: 00059 inline SharedClosureT(){} 00060 00061 private: 00065 inline SharedClosureT(const SharedClosureT& src) {unused(src);} 00066 }; 00067 00069 00071 class LoopClosureT : public zbl::Closure { 00072 protected: 00075 inline LoopClosureT(){} 00076 00077 private: 00081 inline LoopClosureT(const LoopClosureT& src) {unused(src);} 00082 }; 00083 00085 00087 template <typename ReturnT> 00088 class ReturnClosureT : public ClosureT<ReturnT> { 00089 protected: 00092 inline ReturnClosureT(){} 00093 }; 00094 00096 00098 template <typename ReturnT> 00099 class ContinuationT : public zbl::Continuation { 00100 public: 00101 typedef z::scopedptr<ContinuationT> Ptr; 00102 protected: 00105 inline ContinuationT() : Continuation(), _parent(0) {} 00106 00110 inline ContinuationT(const ContinuationT& src) : Continuation(src), _parent(0) {} 00111 00112 public: 00116 inline void setParent(ClosureT<ReturnT>& parent) {_parent = ptr(parent);} 00117 00118 private: 00122 virtual void setParent(zbl::Closure* parent) { 00123 ClosureT<ReturnT>* p = dynamic_cast< ClosureT<ReturnT>* >(parent); 00124 assert(p); 00125 ref(this).setParent(ref(p)); 00126 } 00127 00128 public: 00132 inline ContinuationT<ReturnT>* cloneT() const { 00133 zbl::Continuation::Ptr continuation; 00134 clone(continuation); 00135 return dynamic_cast<ContinuationT<ReturnT>* >(continuation.take()); 00136 } 00137 00138 #ifdef TRACE_RUN 00139 private: 00143 virtual zbl::Closure* getParent() const {return _parent;} 00144 #endif 00145 00146 public: 00150 inline void setReturn(const ReturnT& val) { 00151 if(_parent) 00152 ref(_parent).setValue(val); 00153 } 00154 00155 private: 00157 ClosureT<ReturnT>* _parent; 00158 }; 00159 00161 00163 template <typename ReturnT> 00164 class ContinuationListT : public z::queue<ztl::ContinuationT<ReturnT>*> { 00165 public: 00168 inline ~ContinuationListT(); 00169 00170 public: 00174 inline void take(ContinuationListT<ReturnT>& src); 00175 }; 00176 00178 00180 template <typename ReturnT> 00181 class RunContextT { 00182 public: 00185 inline RunContextT(zbl::Engine& engine) : _engine(engine) {} 00186 00187 public: 00192 inline ContinuationT<ReturnT>& append(ContinuationT<ReturnT>* continuation) { 00193 _continuationList.append(continuation); 00194 return ref(continuation); 00195 } 00196 00197 public: 00201 inline zbl::Engine& getEngine() {return _engine;} 00202 00206 inline bool hasContinuation() {return (_continuationList.size() > 0);} 00207 00211 inline void getContinuation(typename ztl::ContinuationT<ReturnT>::Ptr& continuation) {continuation.reset(_continuationList.deque());} 00212 00213 private: 00215 zbl::Engine& _engine; 00216 00218 ztl::ContinuationListT<ReturnT> _continuationList; 00219 }; 00220 00222 00233 template <typename srcT, typename rtnT, typename ctxT, typename contT> 00234 inline void adaptFunction(contT& cont, typename srcT::Impl::RunCtx& src, ctxT& dstCtx) { 00235 while(src.hasContinuation()) { 00236 typename ztl::ContinuationT<rtnT>::Ptr childSeq; 00237 src.getContinuation(childSeq); 00238 z::scopedptr<contT> parentSeq(new contT(cont)); 00239 childSeq->setParent(parentSeq->getFCall()); 00240 parentSeq->setChild(childSeq.take()); 00241 dstCtx.append(parentSeq.take()); 00242 } 00243 } 00244 00246 00250 template <typename srcT, typename rtnT> 00251 inline void adaptClosure(typename srcT::Impl::RunCtx& src, zbl::RunContext& dstCtx) { 00252 while(src.hasContinuation()) { 00253 typename ztl::ContinuationT<rtnT>::Ptr childSeq; 00254 src.getContinuation(childSeq); 00255 dstCtx.append(childSeq.take()); 00256 } 00257 } 00258 00260 00263 template <typename srcT, typename rtnT> 00264 inline void adaptNative(typename srcT::Impl::RunCtx& src) { 00265 zbl::RunContext rctx(src.getEngine()); 00266 adaptClosure<srcT, rtnT>(src, rctx); 00267 src.getEngine().enque(rctx); 00268 } 00269 00271 00273 template <typename T, typename ImplT> 00274 class TestFactoryT : public zbl::TestFactory { 00275 private: 00278 class TcontinuationT : public ContinuationT<int> { 00279 private: 00282 class _C_test : public FunctionCallClosureT<typename T::Return> { 00283 public: 00286 00287 inline _C_test(const z::string& name) : _name(name) {} 00288 00289 private: 00291 zbl::Linker _runner; 00292 00295 virtual zbl::Runner& getRunner() {return _runner;} 00296 00297 #ifdef TRACE_RUN 00298 private: 00302 virtual void trace(z::stream& os) const { 00303 os << "name=\"TestFactoryT::TcontinuationT::TClosure\", test=\"" << _name << "\""; 00304 } 00305 #endif 00306 00311 virtual zbl::Closure::Action::T runClosureWithCtx(zbl::RunContext& _ctx) { 00312 typename ImplT::RunCtx _pctx(_ctx.getEngine()); 00313 ImplT fcall; 00314 typename T::Return rv = fcall.run(_pctx); 00315 setValue(rv); 00316 ztl::adaptClosure<T, typename T::Return>(_pctx, _ctx); 00317 return zbl::Closure::Action::Next; 00318 } 00319 00320 public: 00322 const z::string& _name; 00323 }; 00324 00325 private: 00328 class _C_rtn : public ReturnClosureT<int> { 00329 public: 00335 inline _C_rtn(const z::string& name, zbl::TestResult& tr, _C_test& p_x) : _name(name), _tr(tr), x(p_x) {} 00336 00337 private: 00339 zbl::Linker _runner; 00340 00343 virtual zbl::Runner& getRunner() {return _runner;} 00344 00345 #ifdef TRACE_RUN 00346 private: 00350 virtual void trace(z::stream& os) const { 00351 os << "name=\"TestFactoryT::TcontinuationT::RClosure\", test=\"" << _name << "\""; 00352 } 00353 #endif 00354 00359 virtual Action::T runClosureWithCtx(zbl::RunContext& _ctx) { 00360 unused(_ctx); 00361 _tr.add(_name, x.getValue().passed); 00362 return Action::Next; 00363 } 00364 public: 00366 const z::string& _name; 00367 00369 zbl::TestResult& _tr; 00370 00372 _C_test& x; 00373 }; 00374 00378 virtual void clone(zbl::Continuation::Ptr& continuation) const { 00379 continuation.reset(new TcontinuationT(*this)); 00380 } 00381 00382 private: 00384 _C_test _test; 00385 00387 _C_rtn _rtn; 00388 00389 private: 00392 inline void init() {_closureList << ptr(_test) << ptr(_rtn);} 00393 00394 public: 00397 inline TcontinuationT(const z::string& name, zbl::TestResult& tr) : ContinuationT<int>(), _test(name), _rtn(name, tr, _test) {init();} 00398 00402 inline TcontinuationT(const TcontinuationT& src) : ContinuationT<int>(src), _test(src._rtn._name), _rtn(src._rtn._name, src._rtn._tr, _test) {init();} 00403 }; 00404 00405 public: 00409 inline TestFactoryT(const z::string& name) : TestFactory(name) {} 00410 00411 private: 00415 virtual zbl::Continuation* get() const {return new TcontinuationT(_name, ref(_tr));} 00416 }; 00417 } 00418 00420 template <typename rtnT> 00421 inline ztl::ContinuationListT<rtnT>::~ContinuationListT() { 00422 // The list should be empty at dtor time... 00423 if(ref(this).size() != 0) { 00424 throw z::exception(z::string::creator("Internal error: ContinuationListT should be empty in dtor").value()); 00425 } 00426 // but delete any remaining ones in Release build. 00427 while(ref(this).size() > 0) { 00429 } 00430 } 00431 00433 template <typename rtnT> 00434 inline void ztl::ContinuationListT<rtnT>::take(ContinuationListT<rtnT>& src) { 00435 while(src.size() > 0) { 00436 zbl::Continuation::Ptr ptr(src.deque()); 00437 ref(this).append(ptr.take()); 00438 } 00439 }