これまでに出てきた : や create や variable は定義ワードです。
これらは他のワードを定義します。 Constant はもう一つの定義ワードです:
5 constant foo foo .
variable や constant でも接頭辞 2 (2倍長セル) や f (浮動小数点)
を使用することができます。
あなた独自の定義ワードを定義することもできます。 例:
: variable ( "name" -- ) create 0 , ;
また、 単にアドレスを生成する以外のことを行うワードを作成する定義ワードを定義することもできます:
: constant ( n "name" -- ) create , does> ( -- n ) ( addr ) @ ; 5 constant foo foo .
上記の constant の定義は does> で終了します。 つまり、 does> は ;
を置き換えるのですが、 他のことも行います。 最後に定義されたワードを変更して、 ワード本体(body)のアドレスをプッシュし、 呼び出されるたびに
does> の後のコードを実行します。
上の例では、 constant は , を使用して foo の本体に 5 を格納します。
foo が実行されると、 本体のアドレスがスタックにプッシュされ、 (does> の後のコードにより、)そこから 5
がフェッチされます。
does> の脇のスタック・コメントは、 does> の後のコードのスタック効果ではなく、
定義されたワードのスタック効果です(違いは、 does> の後のコードは does>
の脇のスタック・コメントには書いてない、 ワード本体(body)のアドレスを期待している点です)。
これらの定義ワードを使用すると、 (他の)定義ワードが関係する場合にファクタリングを行うことができます。 たとえば、 フィールド・オフセットは常にアドレスに加算するものですが、 その代わりに以下を定義します
2 cells constant offset-field1
この offset-field1 は以下のように使います
( addr ) offset-field1 +
ここで、 あなたは以下のような定義ワードをを定義できます
: simple-field ( n "name" -- ) create , does> ( n1 -- n1+n ) ( addr ) @ + ;
フィールド・オフセットの定義と使用は以下のようになります:
2 cells simple-field field1 create mystruct 4 cells allot mystruct .s field1 .s drop
does> の後のコードを実行せずに、 そのワードで何かをしたい場合は、 >body ( xt -- addr )
を使用すれば create したワードの本体(body)にアクセスできます:
: value ( n "name" -- ) create , does> ( -- n1 ) @ ; : to ( n "name" -- ) ' >body ! ; 5 value foo foo . 7 to foo foo .
研究課題(assignment): (
abortの XT の先頭に、) XT を格納するワードを作成する、defer ( "name" -- )を定義し、 実行時に XT をexecuteで実行するようにしてみましょう。 間接再帰はdeferの応用の 1 つです。
こちらも参照ください: User-defined Defining Words