Next: , Previous: , Up: User-defined Defining Words   [Contents][Index]


6.10.10.7 User-defined 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 ! などして定数の値を変更しないことを前提としています。 fivecreate で定義されていますが、 これは 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 を読み取るコード(fvalueset-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-optimizerconstantfvalue のような定義ワード内ではなく、 個々のワードに適用することもできます。 この場合、 オプティマイザに渡されるワードの xt は通常は不要であり、 compile-fvalue-to のように drop されます。

エンジン gforth-itccompile,, を使用するので、 そこでは set-optimizer は効果ありません。


Next: Creating from a prototype, Previous: User-defined to and defer@, Up: User-defined Defining Words   [Contents][Index]