ステート(続)
さて、次は ldo に進もうかと思ったが、その前に lua_State の構造の理解が必須だと思ったので先にそれを解説する。
先週は lua_State の初期化を見た。今週はまず、 lua_State の内部データを眺める。
struct lua_State { CommonHeader; StkId top; /* first free slot in the stack */ StkId base; /* base of current function */ global_State *l_G; CallInfo *ci; /* call info for current function */ StkId stack_last; /* last free slot in the stack */ StkId stack; /* stack base */ int stacksize; CallInfo *end_ci; /* points after end of ci array*/ CallInfo *base_ci; /* array of CallInfo's */ unsigned short size_ci; /* size of array `base_ci' */ unsigned short nCcalls; /* number of nested C calls */ lu_byte hookmask; lu_byte allowhook; lu_byte hookinit; int basehookcount; int hookcount; lua_Hook hook; TObject _gt; /* table of globals */ GCObject *openupval; /* list of open upvalues in this stack */ GCObject *gclist; struct lua_longjmp *errorJmp; /* current error recover point */ ptrdiff_t errfunc; /* current error handling function (stack index) */ };
いろいろある。 StkId というのはこれまで明示的に説明を避けてきたが、ようするに TObject* の別名である。ここではこの StkId と、 CallInfo に着目しよう。
lua はもともとスタックマシンだった。今でもスタックをもとに計算をしている(実際にはVMコードはレジスタマシン)。このスタックを意味するのが stack、stack_last、top、base、stacksizeである。
stack はスタックの始点、stack_lastはスタックの終点、 stacksize はスタックの大きさとなる。で、実際のスタックの利用を示しているのが base と top だ。コメントにもあるように、 base は「現在の関数呼出し」のときのベースになるスタック地点を保存する。それに対して top はスタックが積まれるごとに線型に増えていく値である。関数から戻るときには、 base から top までをクリアすればスタックが空になる、とかいった風情になるのだろう。
CallInfo も似たような構造を持つ。 CallInfo はそもそも関数呼出し情報を保持するデータ構造で、新しく関数が呼び出されると CallInfo にデータが積まれる。 end_ci が終点のポインタ、 size_ci がコールスタックの大きさ、 nCcalls は C 関数呼出しの回数である。