You can create a new defining word by wrapping defining-time code around an existing defining word and putting the sequence in a colon definition.
For example, suppose that you have a word stats
that
gathers statistics about colon definitions given the xt of the
definition, and you want every colon definition in your application to
make a call to stats
. You can define and use a new version of
:
like this:
: stats ( xt -- ) DUP ." (Gathering statistics for " . ." )" ... ; \ other code : my: : latestxt postpone literal ['] stats compile, ; my: foo + - ;
When foo
is defined using my:
these steps occur:
my:
is executed.
:
within the definition (the one between my:
and
latestxt
) is executed, and does just what it always does; it parses
the input stream for a name, builds a dictionary header for the name
foo
and switches state
from interpret to compile.
latestxt
is executed. It puts the xt for the word that is
being defined – foo
– onto the stack.
postpone literal
is executed; this
causes the value on the stack to be compiled as a literal in the code
area of foo
.
['] stats
compiles a literal into the definition of
my:
. When compile,
is executed, that literal – the
execution token for stats
– is layed down in the code area of
foo
, following the literal17.
my:
is complete, and control
returns to the text interpreter. The text interpreter is in compile
state, so subsequent text + -
is compiled into the definition of
foo
and the ;
terminates the definition as always.
You can use see
to decompile a word that was defined using
my:
and see how it is different from a normal :
definition. For example:
: bar + - ; \ like foo but using : rather than my: see bar : bar + - ; see foo : foo `foo stats + - ;
`foo
is another way of writing ['] foo
.
Strictly speaking, the
mechanism that compile,
uses to convert an xt into something
in the code area is implementation-dependent. A threaded implementation
might spit out the execution token directly whilst another
implementation might spit out a native code sequence.