はじめに
「forthはディクショナリー(辞書)にワード(コマンド)をコンパイルする
と言いますけれども、それは 他のコンパイル言語や、 インタープリター言語の一括コンパイル機能とも異なります。
今回は、どう違うのかを説明しておきます。
ワードを実行する。
1 2 + .
すると結果は 3 で、これは 1 と 2 を数値としてデータスタックに格納し、 + を実行し、 . を実行したわけです。
全く意味ないですけども、これをワード three にしてみましょう。
: three ( -- ) 1 2 + ;
この時、 : が「実行」され、はテキスト・インタープリター(外部インタープリター)のコンパイルモードをONにします。そして、 : が次の単語を切り出して、ディクショナリーに新しいワードのヘッダを生成します。
そして次の ( はコメントなので 対の ) まで無視されます。
1 と 2 は数値なのですが、コンパイルモードOFF(インタープリターモード)ではスタックに積みますが、コンパイルモードONの時は 1 と 2 を、 この新しいワードの「実行時」に当該の数値をスタックに積む命令(ワード)と当該の数値をディクショナリーに書き込みます。
続けて + の「コンパイル時の機能」が実行されます。 + のコンパイル時の機能は、 + の実行時の機能をディクショナリに書き込む事です。
そして . の 「コンパイル時の機能」が実行されます。 . のコンパイル時の機能は . の実行時の機能をディクショナリに書き込む事です。
最後の ; は コンパイルモードをOFFにしてインタープリターモードに戻ります。
コンパイラ言語との違い
コンパイラ言語では記述した各機能はコンパイラによって実行ファイルに変換されます。基本的に実行ファイルが実行されるまで各機能は実行されることはありません。
一方、 forth の ワード(コマンド) は インタープリター時もコンパイル時も、 とにかく実行されます。
そうです、 ワード(コマンド)は基本的にどれも、コンパイル時の機能とインタープリター時の機能を持っているのです。
forth のコンパイルというのは全体を統括する凄い賢いコンパイラが全てをコントロールするのではなくて、個々のワードが動いて、結果としてディクショナリーにコンパイルされるのです。
インタープリター言語との違い
インタープリター言語にもコンパイルユーティリティーがついていたり、高速化できるキャッシュを自動作成するようなのもあります。
譬えば Emacs Lisp はバイトコンパイル出来ますし、 python は .pyc ファイルを生成します。
しかし forth はこれらとは違って外部のユーティリティー等で一括コンパイルという仕組みを持ちません。
前述したように各ワードがそれぞれ動くのです。
コンパイル中に(定数)計算とかする
他の言語でも編集初期化等で定数計算させる事があります。
int a=1+2;
forth でも同様に可能で、もっと柔軟にできます。
というのも、明示的にコンパイル・モードとインタプリタ・モードを切り替えるワード(コマンド)も用意されているからです。
注意
逆に言うと「今、 このワードはどういう状態にあるか、コンパイル・モードかインタープリターモードか」を意識してコーディングするようにしてください。
今回はここまで。