6.11.10.6 Words with user-defined 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:

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.


Footnotes

(18)

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.