既存の定義ワードを定義時(defining-time)コードで取り囲み、 その取り囲んだ一連のコードをコロン定義に入れることで、 新しい定義ワードを作成できます。
たとえば、 定義の xt を指定してコロン定義に関する統計を収集するワード stats
があり、
アプリケーション内のすべてのコロン定義で stats
を呼び出す必要があるとします。 これには、 以下のように :
の新しいバージョンを定義して使用できます:
: stats ( xt -- ) DUP ." (Gathering statistics for " . ." )" ... ; \ other code : my: : latestxt postpone literal ['] stats compile, ; my: foo + - ;
my:
を使用して foo
を定義する場合、 以下のステップが実行されます:
my:
が実行されます。
:
(my:
と latestxt
の間にあるもの) が実行され、 :
として、
いつもと同じことを行います。 名前を得るために入力ストリームをパースし、 名前 foo
のディクショナリー・ヘッダーを構築し、
state
をインタープリター状態からコンパイル状態に切り替えます。
latestxt
というワードが実行されます。 定義中のワード(foo
)の xt をスタックに置きます。
postpone literal
によって生成されたコードが実行されます。 これにより、 スタック上の値(foo
の
xt)が foo
のコード領域にリテラルとしてコンパイルされます。
['] stats
は、 my:
の定義時に、 リテラルを my:
の定義内にコンパイルします(訳注:
そして、 my:
の実行時は stats
の xt をスタックに積みます)。 そして、
compile,
が実行されると、 foo
のコード領域に、 上記に続けて stats
の xt
をコンパイルします15。
my:
の実行が完了し、 制御がテキスト・インタープリターに戻ります。
テキスト・インタープリターはコンパイル状態にあるため、 後続のテキスト + -
は foo
の定義にコンパイルされ、
いつものように ;
によって定義が終了します。
see
を使用すると、 my:
を使用して定義されたワードを逆コンパイルし、 それが通常の :
定義とどのように異なるかを確認できます。 例:
: bar + - ; \ like foo but using : rather than my: see bar : bar + - ; see foo : foo `foo stats + - ;
`foo
は ['] foo
を記述する別の方法です。
厳密に言えば、 compile,
が xt
をコード領域内の何かに変換するために使用するメカニズムは実装に依存します。 スレッド実装は実行トークンを直接吐き出す場合がありますが、
別の実装はネイティブ・コード・シーケンスを吐き出す場合があります