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
drop
ped. 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.