6.11.4 Gforth structs

Gforth has had structs before the standard had them; they are a little different, and you can still use them. One benefit of the Gforth structs is that they propagate knowledge of alignment requirements, so if you build the nested structure (see Standard Structures), you do not need to look inside intlist to find out the proper alignment, and you also do not need to mention alignment at all. Instead, this example would look like:

struct
  cell% field intlist-next
  cell% field intlist-val
end-struct intlist%

struct
  char%    field nested-foo
  intlist% field nested-bar
end-struct nested%

The fields are variable-flavoured, i.e., they work in the same way as those defined with field:, +field etc.

A disadvantage of the Gforth structs is that, with the standard going for something else, you need to learn additional material to write and understand code that uses them. Another disadvantage of the Gforth structs is that they do not support value-flavoured or defer-flavoured fields. On the balance, in our opinion the disadvantages now outweigh the advantages, so we recommend using the standard structure words (see Standard Structures). Nevertheless, here is the documentation for Gforth’s structs.

The list and intlist example looks like this with Gforth structs:

struct
  cell% field list-next
end-struct list%

list%
  cell% field intlist-val
end-struct intlist%

Intlist% contains information about size and alignment, and you use %size to get the size, e.g., for allocation:

intlist% %size allocate throw constant my-intlist1

A shorthand for that is

intlist% %alloc constant my-intlist1

The fields behave the same way, so the rest of the example works as with standard structures.

In addition to specifying single cells with cell%, you can also specify an array of, e.g., 10 cells like this:

  cell% 10 * field bla-blub
  \ equivalent to the standard:
  \ aligned 10 cells +field bla-blub

You can use cell% 10 * not just with field, but also in other places where an alignment and size is expected, e.g., with %alloc.

%align ( align size –  ) gforth-0.4 “%align”

Align the data space pointer to the alignment align.

%alignment ( align size – align  ) gforth-0.4 “%alignment”

The alignment of the structure.

%alloc ( align size – addr  ) gforth-0.4 “%alloc”

Allocate size address units with alignment align, giving a data block at addr; throw an ior code if not successful.

%allocate ( align size – addr ior  ) gforth-0.4 “%allocate”

Allocate size address units with alignment align, similar to allocate.

%allot ( align size – addr  ) gforth-0.4 “%allot”

Allot size address units of data space with alignment align; the resulting block of data is found at addr.

cell% ( – align size  ) gforth-0.4 “cell%”
char% ( – align size  ) gforth-0.4 “char%”
dfloat% ( – align size  ) gforth-0.4 “dfloat%”
double% ( – align size  ) gforth-0.4 “double%”
end-struct ( align size "name" –  ) gforth-0.2 “end-struct”

Define a structure/type descriptor name with alignment align and size size1 (size rounded up to be a multiple of align).
name execution: – align size1

field ( align1 offset1 align size "name" –  align2 offset2  ) gforth-0.2 “field”

Create a field name with offset offset1, and the type given by align size. offset2 is the offset of the next field, and align2 is the alignment of all fields.
name execution: addr1addr2.
addr2=addr1+offset1

float% ( – align size  ) gforth-0.4 “float%”
sfloat% ( – align size  ) gforth-0.4 “sfloat%”
%size ( align size – size  ) gforth-0.4 “%size”

The size of the structure.

struct ( – align size  ) gforth-0.2 “struct”

An empty structure, used to start a structure definition.