前回、[[Forthを作ってみる / 変数を実装する]]によって、変数の番地をスタックにPUSHできるようになった。 次は、変数の実体に対してアクセスできるようにする。 変数へのアクセスには、"@"と"!"を用いる。 @ 変数の値の参照 (addr -- x) ! 変数への値の代入 (x addr -- ) 変数yの値を参照するには、 y @ 変数yへ値5を代入するには、 5 y ! のように書く。 まず@の(実行時の)実装について考える。 プログラム実行時、@の中間コード(CODE_AT)が現れたら、 *すでにスタックに積まれているはずの、変数の番地addrを取り出す *その値は、var[ ]のインデックスであるので、var[addr]の値をスタックに積む 次に!の(実行時の)実装について考える。 プログラム実行時、!の中間コード(CODE_EXCL)が現れたら、 *すでにスタックに積まれているはずの、変数の番地addrを取り出す *すでにスタックに積まれているはずの、代入値valを取り出す *addrは、var[ ]のインデックスであるので、var[addr]にvalを代入する プログラムを書いてみよう。 コードに"@"と"!"が現れたときの処理をparse()に追加する。 } else if (strcmp(token, "@") == 0) { prog[parse_idx] = CODE_AT; parse_idx++; } else if (strcmp(token, "!") == 0) { prog[parse_idx] = CODE_EXCL; parse_idx++; 参照と代入の処理関数。 /** * 変数を参照し、スタックに積む */ void call_var_load(void) { /* 変数の番地を取り出す */ long addr = pop(); /* 変数の値をスタックに積む */ push(var[addr]); } /** * 変数に値を代入する */ void call_var_store(void) { /* 変数の番地を取り出す */ long addr = pop(); /* 代入値を取り出す */ long val = pop(); /* 変数に値を代入する */ var[addr] = val; } 関数ポインタ配列に上記関数を追加する。 void (*jump_table[])(void) = { /**< ワードのジャンプ先テーブル */ NULL, call_push, plus, print, word_if, word_else, word_then, call_do, call_loop, call_i, call_cr, call_word, proc_ret, call_dotquote, call_varadr, call_var_load, call_var_store }; テストコードで動作を確認する。 variable x 5 x ! x @ . cr variable y 10 y ! y @ . cr 実行する。 $ ./moiforth.exe testfile/test10 5 10 できた。 [ソースコード|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%EB2&file=moiforth%2D0%2E11%2Ezip&action=ATTACH] (2011.01.10) [[戻る|Forthを作ってみる]] [[前へ|Forthを作ってみる / 変数を実装する]] [[次へ|Forthを作ってみる / 最後に]] :Amazonリンク:[Thinking Forth|http://www.amazon.co.jp/gp/product/0976458705?ie=UTF8&tag=moi0e-22&linkCode=as2&camp=247&creative=7399&creativeASIN=0976458705] {{adsence}}