トップ 差分 一覧 Farm ソース 検索 ヘルプ RSS ログイン

Forthを作ってみる / 変数を実装する2

前回、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

できた。

ソースコード

(2011.01.10)

戻る 前へ 次へ

Amazonリンク
Thinking Forth
moiforth-0.11.zip