Forth系言語にはIMMEDIATEワードという概念があります。これはおそらくForth環境特有の性質から導かれたものと思われます。他のプログラミング言語に慣れ親しんだひとからすれば、極めてわかりにくいものであるようです。
結論から行ってしまえば、IMMEDIATEワードとは、コンパイル状態であってもその定義内容を実行することになっているワードのことです。問題は、このような機構がなぜ必要になり、また、何の役に立つのかです。
まずMopsはインタープリタです。つまり、すべてのソースコードは、Mopsにロードされたとき、インタープリタで解釈され、実行されているのです。大事な点は、コードのコンパイルもまた、インタープリタによるコードの解釈実行として行われるということです。
Mopsのインタープリタには、コンパイル(Compilation)状態と実行(Execution)状態があります。この"状態"の違いに応じて同じワードが別様に解釈されうるのです。それぞれの状態に対応したあるワードの解釈は、それぞれそのワードの、コンピレーションセマンティクス(Compilation Semantics)/エグゼキューションセマンティクス(Execution Semantics)と呼ばれます。セマンティクスとは、ここでは「意味」、あるいは、「その内容としての働き」という意味です。
私達は、通常、ワードやメソッドを定義している際には、そのワードの実行状態でのセマンティクスを定義しています。しかし、その定義をMopsにロードする時点にも、そのワードはある意味「解釈/実行」されているわけです。このときの実行内容は各ワードのコンパイル状態でのセマンティクスになります。
簡単なワードで説明してみます。例えば、"DUP"というワードはトップスタックアイテムの値をコピーして更にスタックの上に積むという動作をする、と理解されています。他方、ワード定義の中で"DUP"と書いた場合、その定義をロードするときに"DUP"を読み込んだ時点でも、"DUP"はある意味、解釈され実行されています。ですが、その時点では"DUP"はスタックアイテムをコピーするわけではありません。定義の中に"DUP"を含む当のワードが実行されるまで、"DUP"の普通の意味での実行は遅延されます。その"DUP"を含むワードがどこかから呼び出され、あるいは解釈実行されたときに、その中の"DUP"に当たる部分に来たところで、はじめて、この"DUP"の動作が実行されるわけです。つまり、"DUP"のコンパイル状態でのセマンティクスはスタックアイテムのコピーではない、ということです。では、ワード定義内の"DUP"の「ある意味での解釈実行」とは何でしょうか。これが、"DUP"のコンパイル状態でのセマンティクスと呼ばれるものです。その内容は"DUP"を実行時に実現できるようなコードをそこにコンパイルするということなのです。
大抵のワードのコンパイル状態でのセマンティクスは、そのワードの呼び出しをコンパイルする、ということになります。つまり、そのワードを実行のために呼び出すためのコードを、その部分に書き込むわけです(但し、
インライン定義されたワードが呼び出されたときは、呼び出しをコンパイルするのとは違って、その場所に内容コード自体が書き込まれますが、当面はこれは無視してもかまいせん。)。
上の話からもわかるように、コンパイル状態でのワードの動作は、結局のところ、コンパイラが行うべき動作なわけです。Mopsでは、コンパイラの動作もまたMopsワードで定義されているのです(Forth系は全てそうだと思います)。つまり、コンパイラの動作を定義するのがコンパイル状態でのワードの動作であるということです。
さてImmediateワードですが、これは、コンパイル状態での動作が、自分の呼び出しをコンパイルするということではなくて、定義によって決められているワードのことです。Immediateワードはコンパイル状態でも固有の動作を持つのです。Mopsでは、普通、Immediateワードの実行状態でのセマンティクスは、コンパイル状態でのそれと同じです。
さらに、次のように定義終了の直後にIMMEDIATEと書くことで、Immediateワードを自分で定義することができます。
: MyImmediateWord ........ ; IMMEDIATE
つまり、このことによって、私達はMopsのコンパイラを拡張していることになるのです。標語的にいえば、全てのワード定義はインタープリタの拡張ですが、Immediateワードの定義はコンパイラの拡張でもある、ということになります。
関連項目:
最終更新:2018年12月25日 14:37