Forthには、スタックだけでなく、変数も利用できる。 文法はこうなる: variable hoge [[ANS Forthの規格|ANSI X3.215-1994 Programming Languages Forth]]には、"6.1.2410 VARIABLE"にその説明がある。 それによると、構文解析時には変数となる番地を割り当て、実行時にはその番地をスタックにPUSHする。 、、、すみません。今日は2010年12月28日。一年以上更新をサボっていました。 えーと、何をやっていたのか、すっかり忘れていますので、おさらい。 構文解析時: *"variable hoge"が現れたら、hogeを変数名テーブルに登録する *hogeと実際に保存される番地との関連付けが必要 *hogeがプログラム中に単独で現れたら、hogeに関連付けられた番地をスタックにPUSHするコードに置き換える 実行時: *hogeは番地をPUSHするコードになっているので、ただ実行するだけ 、、、おさらい終わり、、、 作ってみよう。 まず、どうすればいいだろう? 構文解析時にvariableを見つけたら、次にくる文字列は変数名である。 そこで、この時点で文字列と割り当てるメモリ領域の先頭番地を、変数名-アドレス変換テーブルに保存する。 これのための構造体を作ろうと思ったが、以前作ったワード名-番地変換テーブルの構造と同じだった。 /** * ワード名-処理番地の組 */ typedef struct word_proc_table { char word_pointer; /**< ワード名が登録されたヒープへの番地 */ char proc_pointer; /**< 登録された処理番地 */ } WORD_PROC_TABLE; そこで、名前を変更し、両方に使えるようにする。 /** * 名前-実体番地の組 */ typedef struct name_instance_pair { char name_pointer; /**< 名前が登録されている位置 */ char instance_pointer; /**< 実体が登録されている位置 */ } NAME_INSTANCE_PAIR; そして、変数領域を宣言する。 NAME_INSTANCE_PAIR var_table[100]; /**< 変数管理テーブル */ unsigned char var_table_head; /**< 変数管理テーブルの未使用位置の先頭 */ unsigned char var[100]; /**< 変数実体の格納領域 */ int var_pos; /**< 変数実体領域の未使用領域の先頭を指す */ char varname_heap[100]; /**< 変数名登録領域 */ unsigned char varname_heap_index; /**< 変数名登録領域の未使用領域の先頭を指す */ 構文解析時の処理。まず、variable。parse()に追加する。 } else if (strcmp(token, "variable") == 0) { /* 続くトークンを変数とする */ token = get_token(NULL); assoc_var_name(token); assoc_var_name()は、引数として渡されたトークン文字列と自動的に割り当てられた実体番地を、構造体配列var_table[]に登録する。 /** * 変数名と実体番地とを関連付ける */ void assoc_var_name(unsigned char *name) { /* 変数名をヒープ領域に登録する */ var_table[var_table_head].name_pointer = reg_var_name(name); /* 変数の割り当て番地を登録する */ var_table[var_table_head].instance_pointer = var_pos; var_pos += 2; /* 使っていない登録テーブルを先頭にする */ var_table_head++; } ワード内容に変数名が現れたら、変数の値が割り当てられた番地を埋め込む。 CODE_VARADRは、動作はCODE_PUSHと同じである。 同じくparse()に追加する。 get_var_address()は、トークンが登録されていなければ、-1を返す。 } else if ((adrs = get_var_address(token)) >= 0) { /* 変数の番地をスタックにPUSHする */ prog[parse_idx] = CODE_VARADR; prog[parse_idx + 1] = adrs; parse_idx += 2; 実行時の処理。 /** * 変数の番地をスタックに積む */ void call_varadr(void) { push(prog[prog_cnt]); prog_cnt++; } テストプログラム。コードが正しければ、var_table[ ].instance_pointerの値(変数の番地ではなく、var[]の添字)を表示するはず。 variable x x . cr variable y y . cr 実行してみる。 $ ./moiforth.exe testfile/test9 0 2 成功した。 [ソースコード|http://www.moi2.sakura.ne.jp/fswiki/wiki.cgi?page=Forth%A4%F2%BA%EE%A4%C3%A4%C6%A4%DF%A4%EB+%2F+%CA%D1%BF%F4%A4%F2%BC%C2%C1%F5%A4%B9%A4%EB&file=moiforth%2D0%2E10%2Ezip&action=ATTACH] 次回、変数の参照と代入を行う。 (2011.01.03) [[戻る|Forthを作ってみる]] [[前へ|Forthを作ってみる / 文字列を表示する]] [[次へ|Forthを作ってみる / 変数を実装する2]] {{adsence}}