13.6.2.2550
{:
brace-colon
LOCAL EXT
Interpretation:
Interpretation semantics for this word are undefined.

Compilation:
( i * x "<spaces>ccc :}" -- )

Parse ccc according to the following syntax:

{: <arg>* [| <val>*] [– – <out>*] :}
where <arg>, <val> and <out> are local names, and i is the number of <arg> names given.

The following ambiguous conditions exist when:

  • a local name ends in ":", "[", "^";
  • a local name is a single non-alphabetic character;
  • the text between {: and :} extends over more than one line;
  • {: ... :} is used more than once in a word.

Append the run-time semantics below.

Run-time:
( x1 ... xn -- )

Create locals for <arg>s and <val>s. <out>s are ignored.

  1. names are initialized from the data stack, with the top of the stack being assigned to the right most <arg> name.

  2. names are uninitialized.

<val> and <arg> names have the execution semantics given below.

name Execution:
( -- x )

Place the value currently assigned to name on the stack. An ambiguous condition exists when name is executed while in interpretation state.

TO name Run-time:
( x -- )

Set name to the value x.

Rationale:
The Forth 94 Technical Committee was unable to identify any common practice for locals. It provided a way to define locals and a method of parsing them in the hope that a common practice would emerge.

Since then, common practice has emerged. Most implementations that provide (LOCAL) and LOCALS| also provide some form of the { ... } notation; however, the phrase { ... } conflicts with other systems. The {: ... :} notation is a compromise to avoid name conflicts.

The notation provides for different kinds of local: those that are initialized from the data stack at run-time, uninitialized locals, and outputs. Initialized locals are separated from uninitialized locals by `|'. The definition of locals is terminated by `--' or `:}'.

All text between `--' and `:}' is ignored. This eases documentation by allowing a complete stack comment in the locals definition.

The `|' (ASCII $7C) character is widely used as the separator between local arguments and local values. Some implementations have used `\' (ASCII $5C) or `¦' ($A6). Systems are free to continue to provide these alternative separators. However, only the recognition of the `|' separator is mandatory. Therefore portable programs must use the `|' separator.

A number of systems extend the locals notation in various ways. Some of these extensions may emerge as common practice. This standard has reserved the notation used by these extensions to avoid difficulties when porting code to these systems. In particular local names ending in `:' (colon), `[' (open bracket), or `^' (caret) are reserved.

Implementation:
12345 CONSTANT undefined-value

: match-or-end? ( c-addr1 u1 c-addr2 u2 -- f )
   2 PICK 0= >R COMPARE 0= R> OR ;

: scan-args
   \ 0 c-addr1 u1 -- c-addr1 u1 ... c-addrn un n c-addrn+1 un+1
   BEGIN
     2DUP S" |" match-or-end? 0= WHILE
     2DUP S" --" match-or-end? 0= WHILE
     2DUP S" :}" match-or-end? 0= WHILE
     ROT 1+ PARSE-NAME
   AGAIN THEN THEN THEN ;

: scan-locals
   \ n c-addr1 u1 -- c-addr1 u1 ... c-addrn un n c-addrn+1 un+1
   2DUP S" |" COMPARE 0= 0= IF
     EXIT
   THEN
   2DROP PARSE-NAME
   BEGIN
     2DUP S" --" match-or-end? 0= WHILE
     2DUP S" :}" match-or-end? 0= WHILE
     ROT 1+ PARSE-NAME
     POSTPONE undefined-value
   AGAIN THEN THEN ;

: scan-end ( c-addr1 u1 -- c-addr2 u2 )
   BEGIN
     2DUP S" :}" match-or-end? 0= WHILE
     2DROP PARSE-NAME
   REPEAT ;

: define-locals ( c-addr1 u1 ... c-addrn un n -- )
   0 ?DO
     (LOCAL)
   LOOP
   0 0 (LOCAL) ;

: {: ( -- )
   0 PARSE-NAME
   scan-args scan-locals scan-end
   2DROP define-locals
; IMMEDIATE