The new Gforth word header is object-oriented and supports the following methods (method selectors):
method overrider field execute set-execute >cfa opt-compile, set-optimizer >hmcompile, defer! set-to >hmto defer@ set-defer@ >hmdefer@ >hmextra name>interpret set->int >hm>int name>compile set->comp >hm>comp name>string set-name>string >hm>string name>link set-name>link >hm>link
Many of these words are not stable Gforth words, but Gforth has stable higher-level words that we mention below.
Setter words change the most recent definition (which does not include completed quotations or closures).
execute method is actually stored in the
in the header rather than in the header-methods table for performance
reasons; also it is implemented through a native-code address, while
the other methods are implemented by calling an xt. The high-level
way to set this method is
set-execute( ca – ) gforth-1.0 “Changes”
jumps to the native code at ca. Also changes the
compile, implementation to the most general (and
slowest) one. Call
set-optimizer afterwards if you want
a more efficient implementation.
To get a code address for use with
set-execute, you can use
>code-address, See Threading Words.
There is also
set-does> (see User-defined Defining Words),
which takes an xt.
Moreover, there are the low-level
definer!, See Threading Words.
opt-compile, method is what
compile, does on most
Gforth engines (
, instead). You can
define a more efficient implementation of
compile, for the
current word with
set-optimizer. Note that the end result must
be equivalent to
postpone literal postpone execute.
set-optimizer( xt – ) gforth-1.0 “set-optimizer”
Changes the current word such that
executes xt (with the same stack contents as passed to
compile,. Note that
compile, must be consistent
execute, so you must use
to install a more efficient implementation of the same
As an example of the use of
set-optimizer, consider the
following definition of
: constant ( n "name" -- ; name: -- n ) create , ['] @ set-does> ; 5 constant five : foo five ; see foo
The Forth system does not know that the value of a constant must not
be changed, and just sees a
created word (which can be changed
foo first pushes the body address of
five and then fetches from there. With
the definition of
constant can be optimized as follows:
: constant ( n "name" -- ; name: -- n ) create , ['] @ set-does> [: >body @ postpone literal ;] set-optimizer ;
foo contains the literal 5 rather than a call to
set-optimizer themselves in order to ensure that
compile, agree, so if you want to add your own optimizer,
you should add it afterwards.
(to) method implements
for words defined with
defer and similar words, but it is also
the core of
to. The general stack effect of the
(to) method is
( val xt -- ), where
xt identifies the word stored into, and val is the value (of
appropriate type) stored there.
(to)( val xt – ) gforth-1.0 “paren-to”
xt is of a value like word name. Stores val
E.g., one can implement
fvalue as follows:
: fvalue-to ( r xt -- ) >body f! ; : fvalue ( r -- ) create f, ['] f@ set-does> ['] fvalue-to set-to ; 5e fvalue foo : bar foo 1e f+ to foo ; see bar
You can improve the generated code with
: compile-fvalue-to ( xt-value-to -- ) drop ]] >body f! [[ ; : fvalue-to ( r xt -- ) >body f! ; ' compile-fvalue-to set-optimizer : fvalue ( 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
In practice Gforth has a few additional twists to implement, e.g.,
Set-defer@ allows to implement variants of the
(see Deferred Words) method for
>hmextra field is used for cases where additional data
needs to be stored in the header methods table. In particular, it
stores the xt passed to
set-does>) and the code address behind
The methods above all consume an xt, not an nt, but the override words
work on the most recent definition. This means that if you use, e.g.,
set-optimizer on a synonym, the effect will probably not be
what you intended: When
compile,ing the xt of the word, the
opt-compile, implementation of the original word will be used,
not the freshly-set one of the synonym.
The following methods consume an nt.
name>interpret method is implemented as noop for most
words, except synonyms and similar words.
name>compile method produces the compilation semantics of
the nt. By changing it with
set->comp, you can change the
compilation semantics, but it’s not as simple as just pushing the xt
of the desired compilation semantics, because of the stack effect of
name>compile. Generally you should avoid changing the
compilation semantics, and if you do, use a higher-level word like
interpret/compile:, See Combined Words.
immediate?( nt – flag ) gforth-1.0 “immediate?”
true if the word nt has non-default compilation semantics (that’s not quite according to the definition of immediacy, but many people mean that when they call a word “immediate”).
Name>link are methods in order to make
it possible to eliminate the name,
from noname headers, but still produce meaningful results when using
these words. You will typically not change the implementations of
these methods except with
noname, but we still have