6.11.10.4 The gory details of CREATE..DOES>

DOES> ( compilation colon-sys1 – colon-sys2  ) core “does”

Changes the current word such that it pushes its body address and then calls the code behind the does>. Also changes the compile, implementation accordingly. Call set-optimizer afterwards if you want a more efficient implementation.

You can put the does>-part in a different definition than the create part. This allows us to, e.g., select among different DOES>-parts:

: does1 
DOES> ( ... -- ... )
    code1 ;

: does2
DOES> ( ... -- ... )
    code2 ;

: def-word ( ... -- ... )
    create ...
    IF
       does1
    ELSE
       does2
    THEN ;

In this example, the selection of whether to use does1 or does2 is made at definition-time, i.e., at the time when the child word is CREATEd.

Note that the property of does> to end the definition makes it necessary to introduce extra definitions does1 and does2. You can avoid that with set-does>:

: def-word ( ... -- ... )
    create ...
    IF
       [: code1 ;] set-does>
    ELSE
       [: code2 ;] set-does>
    THEN ;
set-does> ( xt –  ) gforth-1.0 “set-does>”

Changes the current word such that it pushes its body address and then executes xt. Also changes the compile, implementation accordingly. Call set-optimizer afterwards if you want a more efficient implementation.

In a standard program you can apply a DOES>-part only if the last word was defined with CREATE. In Gforth, the DOES>-part will override the behaviour of the last word defined in any case. In a standard program, you can use DOES> only in a colon definition. In Gforth, you can also use it in interpretation state, in a kind of one-shot mode; for example:

CREATE name ( ... -- ... )
  initialization
DOES>
  code ;

is equivalent to the standard:

:noname
DOES>
    code ;
CREATE name EXECUTE ( ... -- ... )
    initialization

Gforth also supports quotations in interpreted code, and quotations save and restore the current definition, so you can also write the example above also as:

CREATE name ( ... -- ... )
  initialization
[: code ;] set-does>
>body ( xt – a-addr  ) core “to-body”

a-addr is the address of the body (aka parameter field or data field) of the word represented by xt

You can access the data area of a created word with >body, including words where the behaviour has been changed with does>/set-does>. So if you know that five has been defined with, e.g., myconstant3 (see User-defined defining words using create), you can change its value with

7 ' five >body !

and performing five will then push 7. By contrast, for words defined with myconstant (defined using :, see User-defined defining words with colon definitions) you cannot change the value in this way.

However, if a word uses set-optimizer (see User-defined compile,) for a more efficient implementation of the compiled code for a word, in many cases the compiled code does not read data from the body of this word, and in that case changing the data by using >body will not have the desired effect. So looking at the source code of a defining word and seeing create is not enough to conclude that you can change the data and it will affect all existing uses. An example of that is myconstant4 (see User-defined compile,).

So it’s a good idea to document whether the intention behind a defining word using create is that it’s data should be changeable through >body.