|
| 1 | +#ifndef __generator_hpp__ |
| 2 | +#define __generator_hpp__ |
| 3 | + |
| 4 | +//| |
| 5 | +//| micro generator/coroutine/continuation for C++ |
| 6 | +//| author: Andrew Fedoniouk @ sciter.com |
| 7 | +//| idea borrowed from: "coroutines in C" by Simon Tatham, |
| 8 | +//| http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html |
| 9 | +//| |
| 10 | + |
| 11 | +namespace generator |
| 12 | +{ |
| 13 | + //++ coroutine, generator, continuation for C++ |
| 14 | + |
| 15 | + struct instance |
| 16 | + { |
| 17 | + protected: |
| 18 | + int _line; |
| 19 | + public: |
| 20 | + instance() { rewind(); } |
| 21 | + void rewind() { _line = 0; } // restart the generator |
| 22 | + |
| 23 | + private: |
| 24 | + instance( const instance& ); // non-copyable |
| 25 | + instance& instance=( const instance& ); // non-assignable |
| 26 | + }; |
| 27 | + |
| 28 | + // Declaration |
| 29 | + #define $generator(NAME) struct NAME : public generator::instance |
| 30 | + |
| 31 | + // Start of generator's body, value[s] emmiter. |
| 32 | + // Shall end with $stop and contain at least one $emit[n] |
| 33 | + #define $emit(T) bool operator()(T& _rv) { switch(_line) { case 0:; |
| 34 | + #define $emit2(T1,T2) bool operator()(T1& _rv1, T2& _rv2) { switch(_line) { case 0:; |
| 35 | + #define $emit4(T1,T2,T3) bool operator()(T1& _rv1, T2& _rv2, T3& _rv3 ) { switch(_line) { case 0:; |
| 36 | + #define $emit4(T1,T2,T3,T4) bool operator()(T1& _rv1, T2& _rv2, T3& _rv3, T4& _rv4 ) { switch(_line) { case 0:; |
| 37 | + |
| 38 | + // yields next value(s) |
| 39 | + #define $yield(V) { _line=__LINE__; _rv = (V); return true; case __LINE__: _line=__LINE__; } |
| 40 | + #define $yield2(V1,V2) { _line=__LINE__; _rv1 = (V1); _rv2 = (V2); return true; case __LINE__: _line=__LINE__; } |
| 41 | + #define $yield3(V1,V2,V3) { _line=__LINE__; _rv1 = (V1); _rv2 = (V2); _rv3 = (V3); return true; case __LINE__: _line=__LINE__; } |
| 42 | + #define $yield4(V1,V2,V3,V4) { _line=__LINE__; _rv1 = (V1); _rv2 = (V2); _rv3 = (V3); _rv4 = (V4); return true; case __LINE__: _line=__LINE__; } |
| 43 | + |
| 44 | + // end of value[s] emmiter |
| 45 | + #define $stop } _line = 0; return false; } |
| 46 | + |
| 47 | + //-- coroutine, generator, continuation for C++ |
| 48 | + |
| 49 | +} |
| 50 | + |
| 51 | +#endif |
0 commit comments