TinySCHEME のソースを読む -2 シンボル、環境
TinySCHEME のソースを読む -1 セルの構造
TinySCHEME のソースを読む -2 シンボル、環境
TinySCHEME のソースを読む -3 TinySCHEME の処理エンジン
TinySCHEME のソースを読む -4 トップレベルからの処理の流れ
TinySCHEME のソースを読む -5 define の例
tsdbg TinyScheme 用デバッグ extension
Symbol をどう表現するか
Symbol は、T_SYMBOL を _flag にしたセルと、T_STRING を _flag にしたセルの、二つのセルで表現される。T_SYMBOL セルの car 部が、T_STRING セルを指すようになっている。( 尚、T_SYMBOL セルの cdr 部は使われない。)
ただ、この表記は冗長なので、以後、セルを図で表す場合は以下のように省略して表記する:
TinySCHEME は、シンボル名を oblist (後述する) という hash テーブルで管理する。
また、T_SYMBOL セル自体は、シンボルの値というものを持たない。シンボルの値は、環境を表現する envir というセルが管理する。envir についても後述する。
oblist, vector
oblist シンボル名を管理するための hash テーブルである。実際は vector を使っており、同じ hash 値のものはリストになる。vector の要素数は 461 で固定され、増えることは無い。
vector は 1005 行目 mk_vector() によって作られる。vector は連続したセルを配列のように使い、全部で 1 + 要素数 / 2 のセルを使う。
先頭のセルは T_VECTOR セルで、要素数を数字で持つ。先頭のセル以降は、vector に格納するデータを"指す"ために使われる。これらのデータを指すために、car 部と cdr 部をそれぞれ使うことが出来るので、データのために vector が使うセルは要素数 / 2 で済む。
my-sum と name は共に hash 値が 4 で、oblist に登録されている例:
oblist に対するインターフェースは、(初期化などを除くと)以下の二つである:
pointer oblist_add_by_name(scheme *sc, const char *name); pointer oblist_find_by_name(scheme *sc, const char *name);
環境, envir
TinySCHEME は環境を sc->envir で表現する。sc->envir は、現在の環境を示す T_ENVIRONMENT のセルと、その環境に属する slot のリストから成る。slot とは、シンボルとシンボルの値をそれぞれ car 部/ cdr 部に持つ cons セルである。
T_ENVIRONMENT のセルの car 部には slot のリストが格納され、envir の cdr 部には直前の環境が入る。
以下の例は、sc->envir の指す環境に、(define name "hal") と (define number 666) で定義された slog が含まれていることを示す:
global_env はグローバル環境を表す hash テーブルである。構造は oblist と全く同一である。
envir と oblist の関係
envir と oblist の関係を図にすると、以下のようになる。
この例では、二つの異なる環境に x が定義され、それぞれ値が違うが指しているシンボルは一つである:
envir に対するインターフェース
global_env が初期化されるのは、4594 行目である:
new_frame_in_env(sc, sc->NIL); sc->global_env = sc->envir;
new_frame_in_env() は、二つ目の引数が NIL の場合、要素数 461 の vector を作り、vector のセルを car 部にした cons セルを作り、envir に代入する。envir に対するインターフェースは以下である:
static void new_frame_in_env( scheme *sc, pointer old_env ); // 新しい環境を作り、envir に代入する。 // old_env が NIL の場合は envir の初期化 // そうでない場合、old_env が新しい envir の cdr 部へ入る static INLINE void new_slot_spec_in_env( scheme *sc, pointer env, pointer variable, pointer value ); // 環境 env に、シンボル variable と値 value から成る slot を作り、追加する static INLINE void new_slot_in_env( scheme *sc, pointer variable, pointer value ); // new_slot_spec_in_env() のラッパー static pointer find_slot_in_env( scheme *sc, pointer env, pointer hdl, int all ); // 環境 env から、シンボル hdl を探して slot を返す。all が 1 の場合は、env をさかのぼって検索を行う // シンボル hdl が環境 env に無い場合は NIL が戻る static INLINE void set_slot_in_env( scheme *sc, pointer slot, pointer value ); // slot に value を代入する // この関数は、find_slot_in_env() で slot を取得してから、セットで呼ばれる static INLINE pointer slot_value_in_env( pointer slot ); // slot の値を返す