If you want to do something that allocates memory from the dictionary or compiles code in the middle of a contiguous region of another dictionary allocation, or in the middle of a colon definition, that’s not possible with a single dictionary pointer, leading to complicated workarounds.
Gforth provides dictionary sections to address this problem. Each section has its own dictionary pointer, and allocating or compiling something in one section does not interrupt the contiguity of allocations in other sections. In this respect Gforth’s sections are similar to sections and segments in assembly languages.
One difference is that the most common usage of sections is as a stack
of sections, which is useful for building nested definitions or
dictionary-allocated data structures: Use next-section
for the
inner definition or data structure, switch back with
previous-section
.
A Gforth-specific property of sections is that words like
latest
(see Name token) and latestxt
(see Anonymous Definitions) refer to the most recent definition in
the current section. Quotations (see Quotations) and the implicit
quotation of does>
(see User-defined defining words using create) are in a different section than the containing definition, so
after the quotation ends (and the section is switched back), words
like latest
report the outer definition rather than the
quotation.
An example of such a usage of the section stack is:
create my2x2matrix next-section here 1 , 2 , previous-section , next-section here 3 , 4 , previous-section , \ now print my2x2matrix[0,1], i.e., "2": my2x2matrix 0 cells + @ 1 cells + @ .
This works also for allocating section memory while compiling a definition, or defining a definition during a contiguous region, e.g.:
create mydispatchtable next-section :noname ." foo" ; previous-section , next-section :noname ." bar" ; previous-section , \ now dispatch mydispatchtable[1] mydispatchtable 1 cells + @ execute
Note that the interpretation semantics of [:
(see Quotations) switches to the next section internally, so you
can write mydispatchtable
also as follows:
create mydispatchtable [: ." foo" ;] , [: ." bar" ;] ,
The interpretation semantics of does>
uses a separate section,
so the does>
does not end the contiguous region, and you can
define a word mydispatch
that includes the dispatch code, as
follows:
create mydispatch does> ( u -- ) ( u addr ) swap cells + @ execute ; [: ." foo" ;] , [: ." bar" ;] , 1 mydispatch \ prints "bar"
next-section
( – ) gforth-1.0 “next-section”
Switch to the next section in the section stack. If there is no such section yet, create it (with the size being a quarter of the size of the current section).
previous-section
( – ) gforth-1.0 “previous-section”
Switch to the previous section in the section stack. Throw an exception if there is no previous section.
The bottom section in the section stack has the size given with the
--dictionary-size
command-line parameter (see Invoking Gforth).
In addition to the stack of anonymous sections you can also have named sections that you define with:
extra-section
( usize "name" – ) gforth-1.0 “extra-section”
Define a new word name and create a section s with
usable size usize.
Name execution ( ... xt --
... )
: When calling name, the current section is c.
Switch the current section to be s, execute xt, then
switch the current section back to c.
As an example, here’s a variant of the my2x2matrix
definition:
4 cells extra-section myvec create my2x2matrix ' here myvec 1 ' , myvec 2 ' , myvec , ' here myvec 3 ' , myvec 4 ' , myvec ,
Currently a named section does not start a dictionary stack, and using
next-section
inside a named section throws an error.
You can show the existing sections with:
.sections
( – ) gforth-1.0 “.sections”
Show all the sections and their status.
At the time of this writing this outputs:
start size used name 7F884CE34000 4000 5D8 locals-headers > 7F883ECBF040 800000 A09A0 Forth 7F883EABE000 200000 7FE8 noname 7F883EA3D000 80000 7F0 noname 7F883EA1C000 20000 C8 noname 7F883EA13000 8000 58 noname
The lines are the different sections: First the named sections, then
the section stack, with the bottom of the stack (Forth
) shown
topmost with the name Forth
. The columns are the start address
of the section, the gross size (including section management
overhead), how much of the section is already used, and the name. All
numbers are in hexadecimal base. Note that not all of the remaining
size can be used for allot
ting memory, because room must be
left for the hold
buffer (see Formatted numeric output) and
for pad
(memory blocks
). The current section is marked
with the >
.