:}
" -- )
Parse ccc according to the following syntax:
:}
The following ambiguous conditions exist when:
:
", "[
", "^
";
:}
extends
over more than one line;
:}
is used more than once in a word.
Append the run-time semantics below.
Create locals for <arg>s and <val>s. <out>s are ignored.
<val> and <arg> names have the execution semantics given below.
Place the value currently assigned to name on the stack. An ambiguous condition exists when name is executed while in interpretation state.
Set name to the value x.
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.
: 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