Next: User-defined defining words using CREATE, Previous: User-defined Defining Words, Up: User-defined Defining Words
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 literal1.
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.
[1] 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.