If you want the words defined with your defining words to behave differently from words defined with standard defining words, you can write your defining word like this:
: def-word ( "name" -- ) CREATE code1 DOES> ( ... -- ... ) code2 ; def-word name
This fragment defines a defining word def-word
and then
executes it. When def-word
executes, it CREATE
s a new
word name, and executes the code code1. The code code2
is not executed at this time. The word name is sometimes called a
child of def-word
.
When you execute name, the address of the body of name is
pushed on the data stack and code2 is executed. The address of
the body of name is the address HERE
returns immediately
after the CREATE
, i.e., the address a create
d word
returns by default).
You can understand the behaviour of def-word
and
name
by considering the following definitions:
: def-word1 ( "name" -- ) CREATE code1 ; : action1 ( ... -- ... ) code2 ; def-word1 name1
Using name1 action1
is equivalent to using name
.
You can use def-word
to define a set of child words that behave
similarly; they all have a common run-time behaviour determined by
code2. Typically, the code1 sequence builds a data area in the
body of the child word. The structure of the data is common to all
children of def-word
, but the data values are specific – and
private – to each child word.
As an example, here’s how you can define myconstant2
with
does>
:
: myconstant2 ( w "name" -- ) create , does> ( -- w ) @ ;
Here create
defines a word name, then ,
stores w
in name’s data area, then the does>
changes name’s
behaviour and returns to the caller of myconstant2
: When
name is invoked, the new behaviour first pushes the address of the
data area (as before), but then also performs the code after the
does>
. In the present case, this code fetches the value of the
constant from the data area.
The stack effect besides the does
reflects the stack effect of
name execution, not the stack effect of the code after the
does>
(this is not common practice yet but we still recommend
it).
Does>
splits the definition into two subdefinitions and has a
number of disadvantages. Alternatively, Gforth allows you to provide
the second part as an execution token by using set-does>
. So
the general scheme is:
: def-word ( "name" -- ; name execution: ... -- ... ) create code1 xt-code2 set-does> code3 ;
The difference from the definition using does>
is that on
name execution, after pushing the data address, xt-code2 is
execute
d, rather than calling the code after the does>.
This also allows putting code3 in def-word; this is
particularly relevant when you want to also use set-optimizer
(see User-defined compile,
) on the defined word, because
does>
/set-does>
calls set-optimizer
itself, so
using set-optimizer
before does>
/set-does>
has no
effect.
Here xt-code2 could be the xt of an existing word, or it could be provided through a quotation (see Quotations).
Another advantage of set-does>
is that the result is a little
more efficient if the execution token passed to it is that of a
primitive. This advantages comes to fruition in:
: myconstant3 ( w "name" -- ; name execution: -- w ) create , ['] @ set-does> ;
During name execution, after pushing the body address of name,
@
is executed.
The efficiency advantage shows up in the comparisons of compiled code size (see User-defined defining words with colon definitions); the execution time also benefits.