6.26.1 Gforth locals

Gforth locals are a superset of standard locals. Locals can be defined with

{: local1 local2 ... -- comment :}

or

{: local1 local2 ... :}

or

{: local1 local2 ... | ulocal0 ulocal1 -- comment :}

E.g.,

: max {: n1 n2 -- n3 :}
 n1 n2 > if
   n1
 else
   n2
 endif ;

The locals definition {: n1 n2 -- n3 :} consumes two cells at run-time, and, as one would expect, puts the top-of-stack in n2 and the second stack item in n1. The part behind the -- is just a comment. The occurences of the locals n1 and n2 push the respective value on the stack.

The similarity of locals definitions with stack comments is intended. A locals definition often replaces the stack comment of a word. The order of the locals corresponds to the order in a stack comment and everything after the -- is really a comment.

The name of the local may be preceded by a type specifier, e.g., F: for a floating point value:

: CX* {: F: Ar F: Ai F: Br F: Bi -- Cr Ci :}
\ complex multiplication
 Ar Br f* Ai Bi f* f-
 Ar Bi f* Ai Br f* f+ ;

Gforth currently supports cells (W:, W^), doubles (D:, D^), floats (F:, F^), characters (C:, C^), and xts (xt:) in several flavours:

value-flavoured

(see Values) You define a value-flavoured local with no type specifier (equivalent to W:), with W:, D:, F: or C:. When later using the name of a value-flavoured local on its own, it pushes the value of the local. You can also change a value-flavoured local x with TO x, ->x, +TO x or +>x. Also, if you put addressable: in front of the locals definition, you can get the address of x with ADDR x or '>x (see How long do locals live?).

variable-flavoured

(see Variables) A variable-flavoured local (defined with W^, D^, F^, C^) produces its address (see How long do locals live?). E.g., the standard word emit can be defined in terms of type like this:

: emit {: C^ char* -- :}
    char* 1 type ;

In addition, if you define a local whose name ends in a [, used only without type specifier, the result is a variable-flavoured local, with the size given between the local name and ]. The size is given by a piece of Forth code that is interpreted and must have the stack effect ( -- u ), where u is the size of the local in bytes. If such a local occurs in front of |, it is initialized by copying u bytes from an address given on the stack. If such a local occurs behind |, it is uninitialized. The square bracket [ is part of the defined name. E.g., the emit example above can also be coded as:

: emit ( c -- )
    {: | char[ 1 chars ] :} 
    char[ c! char[ 1 type ;
defer-flavoured

(see Deferred Words) You define a defer-flavoured local x with XT: x, and the stack item that you store there (e.g., when the local is initialized from the stack at its definition) must be an execution token. When you later use x on its own, the execution token stored in the local is executed. You can get the xt out of x with ACTION-OF x or @>x and change the execution token stored in x with IS x or =>x. If you defined x with addressable: xt: x, you can use addr x or '>x to get the address where the xt is stored (see How long do locals live?).

E.g., the standard word execute can be defined with a defer-flavoured local like this:

: execute {: xt: x -- :}
  x ;

A local without type specifier is a W: local, unless its name ends in [; in that case it’s a variable-flavoured local. You can also leave away the w: if you use addressable:.

All flavours of locals are initialized with values from the data or (for FP locals) FP stack, with the exception being locals defined behind |: Gforth initializes the locals behind | to 0 or 0e, with the uninitialized [-ending exception noted above; some Forth systems leave all locals behind | uninitialized.

Gforth allows defining locals everywhere in a colon definition, but as a consequence, some locals are not visible (and live) everywhere in the colon definition (see Where are locals visible by name?).