: name ( ... -- ... ) word1 word2 word3 ;
name
というワードを作成し、 実行時に word1 word2 word3
を実行します。 name
は
定義(コロン定義)((colon) definition) です。
上記の説明はやや表面的です。 コロン定義の簡単な例については、 Your first Forth definition を参照してください。 関連する問題の一部についての詳細な説明については、 See Interpretation and Compilation Semantics を参照してください。
:
( "name" – colon-sys ) core “colon”
;
( compilation colon-sys – ; run-time nest-sys – ) core “semicolon”
最終的には自動インライン化を実行する予定ですが、 今のところは以下のようにしてインライン化を実行できます
inline:
( "name" – inline:-sys ) gforth-experimental “inline-colon”
インライン・コロン定義を開始します。 inline:
と ;inline
の間のコードは、
インライン化するコードを(実行するのではなく)コンパイルする必要がありますが、 結果の定義 name は、
インライン化されたコードを実行するコロン定義です。 コンパイルするコードはスタック効果が( -- )
(スタックの深さが変わらない)である必要があることに注意してください。 さもないと、 Gforth が name
のコロン定義を作成しようとしたときにエラーが発生します。
;inline
( inline:-sys – ) gforth-experimental “semi-inline”
inline:
で始まるインライン定義を終了します
例として、 インライン化されたワードを定義し、 以下のようにして使います
inline: my2dup ( a b -- a b a b ) ]] over over [[ ;inline #1. my2dup d. d. : foo my2dup ; #1. foo d. d. see foo
インライン・ワードはマクロ(see Macros)に関連しています。 マクロとの違いは、マクロには即時コンパイル機能(immediate
compilation semantics)があるのに対し、 inline:
で定義されたワードにはデフォルトのコンパイル機能(compilation semantics)があることです。 つまり、
通常はコロン定義内でのみマクロを使用しますが、 inline:
ワードは対話的(interpretively)にも使用できることを意味します。 しかしそれは、 inline:
ワードとしては実行できないいくつかのことをマクロでは実行できることも意味します。 例:
\ Doesn't work: \ inline: endif ]] then [[ ;inline \ Instead, write a macro: : endif ]] then [[ ; immediate
逆に、 非即時コロン定義(non-immediate colon definitions)として問題ないワードについては、
非即時コロン定義として定義するか、 (最大限のパフォーマンスが必要な場合) inline:
ワードとして定義します。
それらをマクロとして定義しないでください。 対話的(interpretively)に適切に使用できなくなります:
: another2dup ]] over over [[ ; immediate \ Doesn't work: \ #1. another2dup d. d.
なぜ inline:
と ;inline
の間にコンパイル・コードを書かなければならないのか疑問に思われるかもしれません。
これは、 上記の my2dup
のようなインライン・ワードの実装が以下のように動作するためです:
: compile-my2dup ( xt -- ) drop ]] over over [[ ; : my2dup [ 0 compile-my2dup ] ; ' compile-my2dup set-optimizer
DROP
や 0
があるのは、 compile-my2dup
が my2dup
ための
compile,
の実装であり、 compile,
は xt を期待する為です(see User-defined compile,
)。