Next: , Previous: , Up: Forth Tutorial   [Contents][Index]


3.31 Defining Words

これまでに出てきた :createvariable は定義ワードです。 これらは他のワードを定義します。 Constant はもう一つの定義ワードです:

5 constant foo
foo .

variableconstant でも接頭辞 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