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 CREATE
d.
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 create
d 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
.