to
etc. ¶When you define a word x, you can set its execution semantics
with set-does>
(see User-defined defining words using create) or set-execute
(see Header methods). But you can
also change the semantics of
to x \ aka ->x +to x \ aka +>x action-of x \ aka `x defer@ is x \ aka `x defer! addr x
This is all achieved through a common mechanism described in this
section. As an example, let’s define dvalue
(it behaves in
Gforth exactly like 2value
, see Values). The code is as
follows, explained below:
: d+! ( d addr -- ) dup >r 2@ d+ r> 2! ; \ to +to action-of is addr to-table: d!-table 2! d+! n/a n/a [noop] ' >body d!-table to-class: dvalue-to : dvalue ( d "name" -- ) create 2, ['] 2@ set-does> ['] dvalue-to set-to ; #5. dvalue x #2. +to x x d. \ prints 7
First, we define the support word d+!
.
Next, we define d!-table
, a table of the various to
-like
actions.
For actions that are not supported, we put n/a
in the table,
and when you try to use, e.g., is x
, exception -21 (unsupported
operation) is thrown.
For the to
and +to
actions, we have to provide words
with the stack effect ( d addr -- )
, where addr is the
address where the data of the value-flavoured word is stored. For
addr
(only supported for addressable:
words), we have to
provide a word with the stack effect ( addr1 -- addr2 )
; in the
usual case, both addresses are the same, and we can just provide
[noop]
. For the general case, see the description of
to-table:
below.
Next, the defining word to-class:
combines the d!-table
with the address-computation word >body
, resulting in the
definition of dvalue-to
.18 The address-computation word has the stack effect (
... xt -- addr )
. When invoking +to x
, the xt of x
is
pushed and then the address-computation word (>body
) is called;
the result is the address that is then passed on to d+!
(from
d!-table
).
For dvalue
that’s all, but in other cases, e.g.,
value-flavoured fields (see Value-Flavoured and Defer-Flavoured Fields), additional stack items can be consumed by the
address-computation word, and those have to be provided by the user as
stack-top values when invoking, e.g., to field
.
Next, we have the definition of dvalue
, which is a
straightforward create
...set-does>
word that also tells
name with set-to
how it should behave for to
etc.
Finally, we use dvalue
to define x
and use it. The line
using +to
exercises the set-to
mechanism:
#2. +to x
performs
#2. ' x >body d+!
The >body
is the address-computation word given in the
definition of dvalue-to
, and the d+!
is the +to
entry in d!-table
.
These are the words mentioned above:
to-table:
( "name" "to-word" "+to-word" "addr-word" "action-of-word" "is-word" – ) gforth-experimental “to-table-colon”
Create a table name with entries for TO
, +TO
,
ACTION-OF
, IS
, and ADDR
. The words for
these entries are called with xt on the stack, where xt
belongs to the word behind to
(or +to
etc.). Use
n/a
to mark unsupported operations. Default entries
operations can be left away at the end of the line; the default
is for the addr
entry is [noop]
while the default
for the other entries is n/a
.
The stack effects of the actions are:
to
and +to
action: ( value addr -- )
, where
value has the appropriate type (e.g., a double-cell in our
dvalue
example).
action-of
action: ( addr -- xt )
is
action: ( xt addr -- )
addr
action: ( addr1 -- addr2 )
The addr input parameter in all these cases is the address of the memory where the value of the xt is stored.
The default mechanism means that d!-table
could instead have
been defined as follows:
\ to +to action-of is addr to-table: d!-table 2! d+!
n/a
( – ) gforth-experimental “not-available”
This word can be ticked, but throws an “Operation not supported” exception on interpretation and compilation. Use this for methods etc. that aren’t supported.
[noop]
( – ) gforth-experimental “bracket-noop”
Does nothing, both when executed and when compiled.
to-class:
( xt table "name" – ) gforth-experimental “to-class-colon”
Create a to-class implementation name, where xt
( ... xt -- addr )
computes the address to access the
data, and table (created with to-table:
) contains
the words for accessing it.
>uvalue
( xt – addr ) gforth-internal “to-uvalue”
Xt is the xt of a word x defined with uvalue
;
addr is the address of the data of x in the current
task. This word is useful for building, e.g., uvalue
.
Do not use it to circumvent that you cannot get the address of
a uvalue with addr
; in the future Gforth may perform
optimizations that assume that uvalues can only be accessed
through their name.
set-to
( to-xt – ) gforth-1.0 “set-to”
Changes the implementations of the to-class methods of the most recently defined word to come from the to-class that has the xt to-xt.
The same to-table is often combined with different address computation words (e.g., for global values, user values, value-flavoured fields and locals), that’s why the definition of the to-table is separated from the definition of the to-class.