compile,
¶以下を使用して、 とあるワードのための compile,
の実装を変更することもできます
set-optimizer
( xt – ) gforth-1.0 “set-optimizer”
compile,
で xt execute するように現在のワードを変更します(compile,
に渡されたものと同じスタック内容を使用)。 注意: compile,
は execute
とスタック内容が一致している必要があるため、 set-optimizer
は同じ振る舞いの、
より効率的な実装をインストールする場合にのみ使用しなければならないことに注意してください。
opt:
( compilation – colon-sys2 ; run-time – nest-sys ) gforth-1.0 “opt:”
名前無しのコロン定義を開始します。 完了すると、 このコロン定義は(opt:
の前の)最新のワードの compile,
の実装になります。
注意: 結果として得られる compile,
は、 依然として postpone literal postpone
execute
と同等である必要があることに注意してください。 そのため、 set-optimizer
は、
振る舞いを変更するためではなく、 効率化のために役立てるものです。 しかし、 あなたが自分の足を撃つことを妨げるものは何もありません。 あなたが
set-optimizer
を使用したときの結果と、 最初に以下を定義して使用を無効にしたときに得られる結果を比較することで、
set-optimizer
の使用が正しいかどうかを確認できます。
: set-optimizer drop ;
set-optimizer
の使用例として、 上記の CONSTANT
の定義の 1 つを以下のように拡張できます。
: CONSTANT ( n "name" -- ; name: -- n ) create , ['] @ set-does> [: >body @ postpone literal ;] set-optimizer ;
唯一の変更は、 set-optimizer
行の追加です。 あなたが定数を定義してコンパイルすると、 以下のようになります:
5 constant five : foo five ;
foo
内のコンパイル済み five
は、 five
の一般的な呼び出しではなく、 literal 5
とコンパイルされるようになりました。 引用(quotation)には、 compile,
と同じスタック効果があり、 それは
( xt -- )
です。 渡された xt は compile,
されたワード、 つまりこの例では five
に属します。 この例では、 まず xt が本体アドレスに変換され、 次にその場所の値 5 が取り出され、 その値が postpone
literal
でコンパイルされます(see Literals)。
この set-optimizer
の使用は、 ユーザーが、 例えば 6 ' five >body !
などして定数の値を変更しないことを前提としています。 five
は create
で定義されていますが、 これは
CONSTANT
の実装の詳細であり、 それを文書化しない場合、 ユーザーはそれに依存してはなりません。 また、
本体(body)が変更されないことを前提とした方法で set-optimizer
を使用する場合、 (ここで行われているように)
create
が使用されていることを文書化してはなりません。 逆に、 それを文書化する場合は、 本体の変更を処理できるように
compile,
実装を記述する必要があります。
もう一つの例は、 前述の fvalue
の例をさらに最適化したものです:
: compile-fvalue-to ( xt-value-to -- ) drop ]] >body f! [[ ; : fvalue-to ( r xt -- ) >body f! ; ' compile-fvalue-to set-optimizer : fvalue ( r "name" -- ; name: -- r ) create f, ['] f@ set-does> [: >body ]] literal f@ [[ ;] set-optimizer ['] fvalue-to set-to ; 5e fvalue foo : bar foo 1e f+ to foo ; see bar
bar
のコードを以前の定義のコードと比較します。 ここでは、 fvalue を読み取るコード(fvalue
の
set-optimizer
より)と、 fvalue を書き込むコード(fvalue-to
に適用された
set-optimizer
より)の両方の最適化が見られます。 fvalue は(定数とは異なり)変化する可能性があるため、
(fvalue
内部の)読み取り部分が、 アドレスと、 実行時に実行される f@
をコンパイルします。
fvalue-to
の場合、 compile,
の実装は基本的に、 fvalue
によってインラインで実行されるコードをコンパイルするだけです。 to
のコンパイル機能(compilation
semantics)は、アドレスをリテラルとしてコンパイルしてから、 (to)
の実装(つまり、
fvalue-to
)をコンパイルします。 この処理では、 >body
が最適化されて削除されます。
実際には、 Gforth の fvalue
は、 たとえば +TO
をサポートするなど、
いくつかの追加の工夫が含まれています。
注意: set-optimizer
の呼び出しは、 set-does>
(または does>
の呼び出しの後に実行する必要があることに注意してください。 なぜなら、 set-does>
は compile,
の実装それ自体を上書きするからです。
fvalue-to
の例でわかるように、 set-optimizer
を constant
や
fvalue
のような定義ワード内ではなく、 個々のワードに適用することもできます。 この場合、 オプティマイザに渡されるワードの xt
は通常は不要であり、 compile-fvalue-to
のように drop
されます。
エンジン gforth-itc
は compile,
に ,
を使用するので、 そこでは
set-optimizer
は効果ありません。