Cでswitch-caseでhalt(yield)
昔どこかで__LINE__とswitchでhaltを実装してC言語内でスクリプト風に記述するというの読んだ事があるんだけど、いっくら探しても見つからないので思い出しながら書いてみた。
#define coroutine static unsigned int s_pc = 0;switch(s_pc) #define co_init case 0: s_pc = __LINE__ #define co_end s_pc = 0 #define halt() case __LINE__: if ( s_pc != __LINE__ ) { s_pc = __LINE__; return 0; } int co_func_a() { static int a = 0; coroutine { co_init; a++; printf("a=%d\n",a); halt(); a+=6; printf("a=%d\n",a); halt(); a=4; printf("a=%d\n",a); halt(); co_end; } return 1; } int co_func_b() { static int b = 0; coroutine { co_init; b=4; printf("b=%d\n",a); halt(); b*=2; printf("b=%d\n",b); halt(); co_end; } return 1; } int main() { int a_end = 0; int b_end = 0; while(1) { if ( !a_end ) a_end = co_func_a(); if ( !b_end ) b_end = co_func_b(); } return 0; }
あっれ〜?こんなんだっけ?
自動変数の値を保存出来ないし、
何よりco_func自体を複数登録できないし、
co_init/co_endって何よ!きもい!
あと__LINE__って最近はエディットコンティニュー用になってるらしく、
変数なのでそのままだとcase文に使えなかったりします。
なのでこれコンパイルしてません。
これじゃだめだな。
コンテキスト全部保存してもいいんだけど、
そこまでやるならプログラムカウンタとかも保存してしまえばこんな事しなくてもいいので却下。
それにスタックの内容全部コピーとか糞重いよね。
yield本気で実装するならスタック空間も分けた方がいいかも。
まぁめんどくさいからそこまでやらないけどというかそこまでやるなら自前スクリプト言語作った方がはええぜ。