In addition to the variable-flavoured fields that produce an address
(see Standard Structures), Gforth also provides varue-flavoured
fields. Like all fields, varue-flavoured fields consume the start
address of the struct, but they produce their value and you can apply
to
, +to
and addr
on them. E.g., we can do
something like the intlist
definition (see Standard Structures):
0 value: intlist>next ( intlista -- intlista1 ) value: intlist>val ( intlista -- n ) constant intlista ( -- u )
This means that there are the following ways of accessing
intlist>val
:
intlist>val ( intlista -- n ) ->intlist>val ( n intlista -- ) \ aka to intlist>val +>intlist>val ( n intlista -- ) \ aka +to intlist>val addr intlist>val ( intlista -- addr )
And here’s the earlier example (see Standard Structures) rewritten
to use intlista
:
intlista allocate throw constant my-intlista1 0 my-intlista1 to intlist>next 5 my-intlista1 to intlist>val intlista allocate throw constant my-intlista2 my-intlista1 my-intlista2 to intlist>next 7 my-intlista2 to intlist>val : intlista-sum ( intlista -- n ) \ "intlista" is a pointer to the first element of a linked list \ "n" is the sum of the intlist>val fields in the linked list 0 BEGIN ( intlista1 n1 ) over WHILE ( list1 n1 ) over intlist>val + swap intlist>next swap REPEAT nip ; my-intlista2 intlista-sum . \ prints "12"
Depending on the type of the field, the value can be something different than a single cell.
value:
( u1 "name" – u2 ) gforth-experimental “value:”
Name is a varue-flavoured field; in-memory-size: cell; on-stack: cell
cvalue:
( u1 "name" – u2 ) gforth-experimental “cvalue:”
Name is a varue-flavoured field; in-memory-size: char; on-stack: unsigned cell
wvalue:
( u1 "name" – u2 ) gforth-experimental “wvalue:”
Name is a varue-flavoured field; in-memory-size: 16 bits; on-stack: unsigned cell
lvalue:
( u1 "name" – u2 ) gforth-experimental “lvalue:”
Name is a varue-flavoured field; in-memory-size: 32 bits; on-stack: unsigned cell
scvalue:
( u1 "name" – u2 ) gforth-experimental “scvalue:”
Name is a varue-flavoured field; in-memory-size: char; on-stack: signed cell
swvalue:
( u1 "name" – u2 ) gforth-experimental “swvalue:”
Name is a varue-flavoured field; in-memory-size: 16 bits; on-stack: signed cell
slvalue:
( u1 "name" – u2 ) gforth-experimental “slvalue:”
Name is a varue-flavoured field; in-memory-size: 32 bits; on-stack: signed cell
2value:
( u1 "name" – u2 ) gforth-experimental “2value:”
Name is a varue-flavoured field; in-memory-size: 2 cells;
on-stack: 2 cells; +to
performs double-cell addition
(d+
).
fvalue:
( u1 "name" – u2 ) gforth-experimental “fvalue:”
Name is a varue-flavoured field; in-memory-size: float; on-stack: float
sfvalue:
( u1 "name" – u2 ) gforth-experimental “sfvalue:”
Name is a varue-flavoured field; in-memory-size: 32-bit float; on-stack: float
dfvalue:
( u1 "name" – u2 ) gforth-experimental “dfvalue:”
Name is a varue-flavoured field; in-memory-size: 64-bit float; on-stack: float
zvalue:
( u1 "name" – u2 ) gforth-experimental “zvalue:”
Name is a varue-flavoured field; in-memory-size: 2 floats;
on-stack: 2 floats; +to
performs componentwise addition.
$value:
( u1 "name" – u2 ) gforth-experimental “$value:”
Name is a varue-flavoured field; in-memory-size: cell;
on-stack: c-addr u (see $tring words); ( c-addr u ) +to
name
appends c-addr u to the string in the field.
Gforth also has field words for dealing with dynamically-sized arrays.
A field for such an array contains just a cell that points to the
actual data, and this cell has to be set to 0 before accessing the
array the first time. When accessing the field (without operator, or
with to
or +to
), there has to be the index and the
structure address on the stack, with the structure address on top.
Any further items consumed by to
or +to
are below the
index on the stack. The array expands to the size given by the
maximum access; any unset elements are 0; for $value[]
accessing them produces a 0-length (i.e., empty) string.
Here is a usage example:
0 value[]: bla>x[] $value[]: bla>$y[] constant bla bla allocate throw constant mybla mybla bla erase \ set all fields to 0 5 2 mybla to bla>x[] \ access at index 2 7 0 mybla to bla>x[] \ access at index 0 2 mybla bla>x[] . \ prints "5" 3 mybla bla>x[] . \ prints "0" "foo" 2 mybla to bla>$y[] \ access at index 2 "bla" 1 mybla to bla>$y[] \ access at index 1 "bar" 2 mybla +to bla>$y[] \ access at index 2 0 mybla bla>$y[] . . \ prints "0 0" 1 mybla bla>$y[] type \ prints "bla" 2 mybla bla>$y[] type \ prints "foobar"
value[]:
( u1 "name" – u2 ) gforth-experimental “value[]:”
$value[]:
( u1 "name" – u2 ) gforth-experimental “$value[]:”
Finally, you can define defer-flavoured fields. Here is a usage example:
0 defer: foo'bar constant foo foo allocate throw constant my-foo :noname ." test" ; my-foo is foo'bar my-foo foo'bar \ prints "test" my-foo addr foo'bar @ execute \ prints "test" my-foo action-of foo'bar execute \ prints "test" my-foo `foo'bar defer execute \ prints "test" :noname ." test1" ; my-foo `foo'bar defer! my-foo foo'bar \ prints "test1"
defer:
( u1 "name" – u2 ) gforth-experimental “defer:”
Name is a defer-flavoured field
For documentation of is
, action-of
, defer@
,
defer!
, see See Deferred Words. Note however, that when
used on defer-flavoured fields, all these words consume the start
address of the structure, unlike for words defined with defer
.