Gforth allows you to define combined words – words that have an arbitrary combination of interpretation and compilation semantics (some people call them NDCS words, and mean words with non-default and non-immediate compilation semantics).
interpret/compile:
( interp-xt comp-xt "name" – ) gforth-0.2 “interpret/compile:”
This feature was introduced for implementing TO
and S"
. I
recommend that you do not define such words, as cute as they may be:
they make it hard to get at both parts of the word in some contexts.
E.g., assume you want to get an execution token for the compilation
part. Instead, define two words, one that embodies the interpretation
part, and one that embodies the compilation part. Once you have done
that, you can define a combined word with interpret/compile:
for
the convenience of your users.
A typical usage example is:
: s"-int ( -- c-addr u ) '"' parse save-mem ; : s"-comp ( -- ; run-time: -- c-addr u ) '"' parse postpone sliteral ; ' s"-int ' s"-comp interpret/compile: s"
Some people are not happy with the looks of the definition above, so Gforth also provides additional ways to write this kind of definition:
set-compsem
( xt – ) gforth-experimental “set-compsem”
change compilation semantics of the last defined word
compsem:
( – ) gforth-experimental “compsem:”
Changes the compilation semantics of the current definition to
perform the definition starting at the compsem:
.
intsem:
( – ) gforth-experimental “intsem:”
The current definition’s compilation semantics are changed to
perform its execution semantics (the word becomes immediate).
Then its interpretation semantics are changed to perform the
definition starting at the intsem:
. Note that if you
then call immediate
, the compilation semantics are
changed to perform the word’s new interpretation semantics.
Note that there are and should be only few combined words, ideally
none, and their definitions don’t need to be pretty (on the contrary,
their uglyness may provide a warning that “here be dragons”). So
our recommendation is to use interpret/compile:
.
It is a bad idea to try to use combined words for optimization of
words with default compilation semantics: Gforth has a better
mechanism for that (set-optimizer
and opt:
,
see User-defined compile,
), [compile]
treats
combined words as having non-default compilation semantics, and the
intended optimization does not happen when the combined word is ticked
and compile,
d.
Some people try to use state-smart
words to emulate combined words (words are state-smart if they check
STATE
during execution). E.g., they would try to code
s"
like this:
: foobar STATE @ IF ( compilation state ) comp-s" ELSE int-s" THEN ; immediate
Although this works if s"
is only processed by the text
interpreter, it does not work in other contexts (like '
or
POSTPONE
). E.g., ' foobar
will produce an execution
token for a state-smart word, not for the interpretation semantics of
the original foobar
; when you execute this execution token
(directly with EXECUTE
or indirectly through COMPILE,
)
in compile state, the result will not be what you expected (i.e., it
will not call int-s"
). State-smart words are a bad idea. Simply
don’t write them23! Gforth provides
better alternatives: interpret/compile:
and set->comp
for implementing combined words, and set-optimizer
for
implementing optimizations of words with default compilation
semantics.
For a more detailed discussion of this
topic, see M. Anton Ertl,
State
-smartness—Why
it is Evil and How to Exorcise it, EuroForth ’98.