6.11.10.7 User-defined compile,

You can also change the implementation of compile, for a word, with

set-optimizer ( xt –  ) gforth-1.0 “set-optimizer”

Changes the current word such that compile,ing it executes xt (with the same stack contents as passed to compile,). Note that compile, must be consistent with execute, so you must use set-optimizer only to install a more efficient implementation of the same behaviour.

opt: ( compilation – colon-sys2 ; run-time – nest-sys  ) gforth-1.0 “opt:”

Starts a nameless colon definition; when it is complete, this colon definition will become the compile, implementation of the latest word (before the opt:).

Note that the resulting compile, must still be equivalent to postpone literal postpone execute, so set-optimizer is useful for efficiency, not for changing the behaviour. There is nothing that prevents you from shooting yourself in the foot, however. You can check whether your uses of set-optimizer are correct by comparing the results when you use it with the results you get when you disable your uses by first defining

: set-optimizer drop ;

As an example of the use of set-optimizer, we can enhance myconstant3 as follows.

: myconstant4 ( n "name" -- ; name: -- n )
  create ,
  ['] @ set-does>
  [: >body @ postpone literal ;] set-optimizer
;

The only change is the addition of the set-optimizer line. When you define a constant and compile it:

5 myconstant4 five
: foo five ;

the compiled five in foo is now compiled to the literal 5 instead of a generic invocation of five. The quotation has the same stack effect as compile,: ( xt -- ). The passed xt belongs to the compile,d word, i.e., five in the example. In the example the xt is first converted to the body address, then the value 5 at that place is fetched, and that value is compiled with the postpone literal (see Literals).

This use of set-optimizer assumes that the user does not change the value of a constant with, e.g., 6 ' five >body !. While five has been defined with create, that is an implementation detail of CONSTANT, and if you don’t document it, the user must not rely on it. And if you use set-optimizer in a way that assumes that the body does not change (like is done here), you must not document that create is used; and conversely, if you document it, you have to write the compile, implementation such that it can deal with changing bodies.

Note that the call to set-optimizer has to be performed after the call to set-does> (or does>, because set-does> overwrites the compile, implementation itself.

We can also apply set-optimizer to individual words rather than inside a defining word like constant. In this case, the xt of the word passed to optimizer is usually unnecessary and is dropped. As an simple example, let’s define a word that is inlined when being compiled:

: compile-my2dup ( xt -- )
  drop ]] over over [[ ;

: my2dup over over ;
' compile-my2dup set-optimizer

: foo my2dup ;
see my2dup

An alternative way to define my2dup is:

: my2dup over over ;
opt: drop ]] over over [[ ;

Opt: starts an anonymous definition that is then (internally) attached to my2dup with set-optimize.

Finally an even more convenient way to write this is to use inline: (see Inline Definitions), but it is limited to inlining.

The engine gforth-itc uses , for compile, in nearly all cases and set-optimizer usually has no effect there.