これまでに出てきた :
や 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