POSTPONE

大雑把にいえば、POSTPONEは、IMMEDIATEの逆、といえます。もっとも構文は違います。

POSTPONEは、その次にくるワード(一つ)について、その呼び出しをコンパイルする、というワードです。ですからPOSTPONEはコンパイル状態でしか利用しません。そして、特に、IMMEDIATEワードの定義の中で重要になります。

あまり意味のない例ですが、その動作の説明を例で示しましょう。例えば、
: greeting ( -- ) ." Hello Everybody!" cr  ; immediate
というコードを書いたとします。このgreetingを何かのワードの定義で呼び出すとどうなるでしょうか。結果は、それをコンパイルしているときに、Hello Everybody!のメッセージが、Mopsウィンドウにプリントされます。例えば、
: myword1 greeting ;<ENTER>
とすれば


のような結果になります。myword1自体には実行コードはありません。

これに対して、
: myword2 POSTPONE greeting ;<ENTER>
としたとします。このときは、コンパイルの時点ではメッセージはプリントしません。


しかし、myword2を実行すれば、メッセージがプリントされます。


つまりPOSTPONEはImmediateワードを普通のワードと同じようにコンパイルするワードです。POSTPONEは上の例のように、コンパイルのためではないワードでも使うこともできます。しかし、これは、コンパイラ拡張用のワードと考えるのが自然です。具体的には次のような局面で役に立ちます。

POSTPONEがもっとも威力を発揮するのは、IMMEDIATEワードの定義であるワードをPOSTPONEするときであると思われます。 例えば、ある目的でコンパイラ拡張用のImmediateワードIMMEDWORDを定義したとします。IMMEDIATEワードは、何かのワードのコンパイル中に呼び出され、実行されることが予定されているわけですが、このとき、IMMEDWORDが、例えばワード"POSTDWORD"のPOSTPONEを内容として含んでいると、その実行の時点にPOSTDWORDの呼び出しを その場にコンパイルすることになります。かなりややこしいですが、そのようにPOSTPONEされたワードは、ちょうど"<BUILDS - DOES>"対のDOES>以下に書くコードと同じように、別のワードに内容として追加されるコードとなるのです。
: POSTDWORD   [コード]  ;
: IMMEDWORD   ... POSTPONE POSTDWORD ... ;  IMMEDIATE

: SPECIALWORD  IMMEDWORD  [CODE]  ;

\  このようにすると、SPECIALWORDはコンパイル時にIMMEDWORDの内容(「...」部分に該当)
\  であるコードが実行されて特殊コンパイルされるが、
\  加えてその内容である[CODE]部分の先頭には、POSTDWORDが追加されることになる。
\  つまり、特殊コンパイル部分を度外視すれば、SPECIALWORDの内容は、

: SPECIALWORD  POSTDWORD  [CODE]  ; 
\  とするのに等しくなる。

この技巧は、毎度毎度表立っては書きたくないような、呼び出し前後のローレベルの定型処理コードを追加するのに利用できます。これは、ローレベルのメモリーやレジスタの操作に関するコントロール力を保持したつつも、それを適宜抽象化して、通常のプログラミングにおいてはハイレベルなコードを書く、ということを可能にしているのです。


関連項目:



最終更新:2022年02月13日 18:35