Zen
A cross-platform functional programming language
|
00001 00005 #pragma once 00006 00007 //#define TRACE_RUN 00008 //#define TRACE_JOIN 00009 00010 #ifdef TRACE_RUN 00011 00012 #define TRACE_FUNCTION(s) zbl::Tracer _t_(z::string(s));unused(_t_) 00013 #else 00014 00015 #define TRACE_FUNCTION(s) 00016 #endif 00017 00019 namespace zbl { 00021 00024 z::stream& dlog(); 00025 00029 z::stream& mlog(); 00030 00034 z::stream& wlog(); 00035 00039 z::stream& elog(); 00040 00042 00044 class Tracer { 00045 public: 00048 inline Tracer(const z::string& fname) : _fname(fname) {qDebug() << ">" << _fname;} 00049 00052 inline ~Tracer() {qDebug() << "<" << _fname;} 00053 00054 private: 00056 const z::string _fname; 00057 }; 00058 00060 00062 class Runner { 00063 protected: 00066 inline Runner(){} 00067 00068 public: 00071 virtual ~Runner(){} 00072 00073 public: 00077 virtual bool enterRun() = 0; 00078 00082 virtual bool leaveRun() = 0; 00083 }; 00084 00086 00088 class Linker : public Runner { 00089 public: 00092 inline Linker(){} 00093 00096 virtual ~Linker(){} 00097 00098 private: 00102 virtual bool enterRun(); 00103 00107 virtual bool leaveRun(); 00108 }; 00109 00111 00113 class Joiner : public Runner { 00114 public: 00117 Joiner(); 00118 00122 Joiner(const Joiner& src); 00123 00126 virtual ~Joiner(); 00127 00128 #if defined(TRACE_RUN) || defined(TRACE_JOIN) 00129 public: 00134 virtual void trace(z::stream& os, const z::string& fn) const; 00135 00139 inline void trace(z::stream& os) const { 00140 trace(os, z::string("")); 00141 } 00142 #endif 00143 public: 00147 virtual bool enterRun(); 00148 00152 virtual bool leaveRun(); 00153 00154 private: 00156 class Impl; 00157 00159 Impl* _impl; 00160 }; 00161 00163 00165 class RunContext; 00166 00168 00170 class Closure { 00171 public: 00174 struct Action { 00176 enum T { 00177 Noop, 00178 Next, 00179 Loop, 00180 }; 00181 }; 00182 00183 protected: 00186 inline Closure() {} 00187 00188 public: 00192 virtual Runner& getRunner() = 0; 00193 00194 public: 00199 virtual Action::T runClosureWithCtx(zbl::RunContext& _ctx) = 0; 00200 00201 #ifdef TRACE_RUN 00202 public: 00206 virtual void trace(z::stream& os) const = 0; 00207 00212 inline void trace(const z::string& level, z::stream& os) const { 00213 os << level << "C:{this:" << this << ", "; 00214 //os << "type:" << typeid(ref(this)).name() << ", "; 00215 trace(os); 00216 os << "}" << endl; 00217 } 00218 #endif 00219 }; 00220 00222 00224 class Continuation { 00225 public: 00227 typedef z::scopedptr<zbl::Continuation> Ptr; 00228 00230 typedef z::list<Runner*> JoinerList; 00231 00232 protected: 00235 inline Continuation() : _idx(0), _child(0) { 00236 } 00237 00241 inline Continuation(const Continuation& src) : _idx(src._idx), _child(0) { 00242 } 00243 00244 public: 00247 virtual ~Continuation() { 00248 } 00249 00250 public: 00255 inline bool goNext(const Closure::Action::T& action); 00256 00260 inline Closure& getCurrentClosure(); 00261 00262 public: 00266 virtual void setParent(Closure* parent) = 0; 00267 00268 #ifdef TRACE_RUN 00269 private: 00273 virtual Closure* getParent() const = 0; 00274 00275 public: 00280 inline void trace(const z::string& level, z::stream& os) const { 00281 os << level << "S:{this=" << this << ", idx=" << _idx << ", parent=" << getParent() << "}" << endl; 00282 for(z::list<Closure*>::iterator it(_closureList); !it.end(); ++it) { 00283 ref(*it).trace(level + " ", os); 00284 } 00285 } 00286 #endif 00287 public: 00292 Closure::Action::T run(zbl::RunContext& _ctx); 00293 00294 public: 00298 virtual void clone(zbl::Continuation::Ptr& continuation) const = 0; 00299 00300 public: 00304 inline bool hasChild() {return (0 != _child);} 00305 00309 inline void setChild(Continuation* child) { 00310 assert(_child == 0); 00311 _child = child; 00312 } 00313 00317 inline void getChild(zbl::Continuation::Ptr& continuation) { 00318 continuation.reset(_child); 00319 _child = 0; 00320 } 00321 00322 public: 00326 inline JoinerList& getJoinerList() {return _joinerList;} 00327 00328 protected: 00330 int _idx; 00331 00333 z::list<Closure*> _closureList; 00334 00336 JoinerList _joinerList; 00337 00338 private: 00340 Continuation* _child; 00341 }; 00342 00344 00346 class ContinuationList : public z::queue<zbl::Continuation*> {}; 00347 00349 00351 class Engine; 00352 00354 00356 class RunContext { 00357 public: 00360 inline RunContext(Engine& engine) : _engine(engine) {} 00361 00362 private: 00366 inline RunContext(const RunContext& src) : _engine(src._engine) {} 00367 00368 public: 00372 inline zbl::Engine& getEngine() {return _engine;} 00373 00377 inline void append(Continuation* continuation) {_list.append(continuation);} 00378 00382 inline bool hasContinuation() {return (_list.size() > 0);} 00383 00387 inline void getContinuation(zbl::Continuation::Ptr& continuation) {continuation.reset(_list.deque());} 00388 00389 private: 00391 Engine& _engine; 00392 00394 ContinuationList _list; 00395 }; 00396 00398 00400 class Fiber { 00401 public: 00403 typedef z::scopedptr<Fiber> Ptr; 00404 00405 public: 00408 inline Fiber() { 00409 } 00410 00413 inline ~Fiber() { 00414 if(_continuationList.size() > 0) { 00415 throw z::exception(z::string::creator("Internal error: _continuationList should be empty in Fiber::dtor").value()); 00416 } 00417 } 00418 00419 public: 00424 zbl::Closure::Action::T run(zbl::RunContext& _ctx); 00425 00430 bool next(const Closure::Action::T& action); 00431 00435 void clone(zbl::Fiber::Ptr& fiber) const; 00436 00437 #ifdef TRACE_RUN 00438 public: 00443 inline void trace(const z::string& level, z::stream& os) const { 00444 os << level << "F:{this=" << this << "}" << endl; 00445 for(z::stack<Continuation*>::iterator it(_continuationList); !it.end(); ++it) { 00446 ref(*it).trace(level + " ", os); 00447 } 00448 } 00449 #endif 00450 00451 public: 00456 Continuation* pushContinuation(Continuation::Ptr& continuation); 00457 00462 bool popContinuation(Continuation::Ptr& continuation); 00463 00468 Continuation* addContinuation(Continuation::Ptr& continuation); 00469 00470 private: 00472 z::stack<Continuation*> _continuationList; 00473 }; 00474 00476 00478 class TestResult { 00479 public: 00482 inline TestResult() : _passed(0), _total(0) {} 00483 00484 public: 00489 void add(const z::string& name, const int& passed); 00490 00493 void writeSummary(); 00494 00495 private: 00497 z::dict<z::string, int> _result; 00498 00499 private: 00501 int _passed; 00502 00504 int _total; 00505 }; 00506 00508 00510 class TestFactory { 00511 protected: 00514 inline TestFactory(const z::string& name) : _tr(0), _name(name), _next(0) { 00515 _next = _head; 00516 _head = this; 00517 } 00518 00519 public: 00523 inline void setTestResult(TestResult& tr) {_tr = ptr(tr);} 00524 00525 public: 00529 inline const z::string& getName() const {return _name;} 00530 00531 public: 00533 virtual Continuation* get() const = 0; 00534 00535 protected: 00537 TestResult* _tr; 00538 00540 const z::string _name; 00541 00542 public: 00544 static TestFactory* _head; 00545 00547 TestFactory* _next; 00548 }; 00549 00551 00553 class Engine { 00554 public: 00556 enum Mode { 00557 mNone, 00558 mHelp, 00559 mRun, 00560 mTest, 00561 }; 00562 00563 public: 00568 Engine(int argc, char* argv[]); 00569 00572 ~Engine(); 00573 00574 public: 00578 const Mode& getMode() const; 00579 00580 public: 00586 int init(int argc, char* argv[]); 00587 00591 int exit(); 00592 00596 int pump(); 00597 00598 public: 00602 void enque(RunContext& ctx); 00603 00607 void registerOnExit(Continuation* continuation); 00608 00609 private: 00611 class Impl; 00612 00614 Impl* _impl; 00615 }; 00616 }