% !TeX root = forth.tex
% !TeX spellcheck = en_US

\chapter{The optional Locals word set} % 13
\wordlist{local}

\section{Introduction} % 13.1
\label{locals:intro}

\section{Additional terms and notation} % 13.2

None.

\section{Additional usage requirements} % 13.3

\subsection{Locals} % 13.3.1

A local is a data object whose execution semantics shall return its
value, whose scope shall be limited to the definition in which it is
declared, and whose use in a definition shall not preclude reentrancy
or recursion.

\subsection{Environmental queries} % 13.3.2

Append table \ref{local:env} to table \ref{table:env}.

See: \xref[3.2.6 Environmental queries]{usage:env}.

\begin{table}[h]
  \begin{center}
	\caption{Environmental Query Strings}
	\label{local:env}
	\begin{tabular}{p{9em}rcp{0.42\textwidth}}
		\hline\hline
		\multicolumn{2}{l}{String \hfill Value data type} & Constant? & Meaning \\
		\hline
		\texttt{\#LOCALS}		& \emph{n}	& yes
			& maximum number of local variables in a definition \\
		\hline\hline
	\end{tabular}
  \end{center}
\end{table}

\subsection{Processing locals} % 13.3.3
\label{local:locals}

To support the locals word set, a system shall provide a mechanism
to receive the messages defined by \word{LOCAL} and respond as
described here.

During the compilation of a definition after \word[core]{:} (colon),
\word[core]{:NONAME}, or \word[core]{DOES}, a program may begin
sending local identifier messages to the system. The process shall
begin when the first message is sent. The process shall end when the
``last local'' message is sent. The system shall keep track of the
names, order, and number of identifiers contained in the complete
sequence.

\subsubsection{Compilation semantics} % 13.3.3.1

The system, upon receipt of a sequence of local-identifier messages,
shall take the following actions at compile time:
\begin{enumerate}
\item Create temporary dictionary entries for each of the
	identifiers passed to \word{LOCAL}, such that each identifier
	will behave as a \emph{local}. These temporary dictionary
	entries shall vanish at the end of the definition, denoted by
	\word[core]{;} (semicolon), \word[tools]{;CODE}, or
	\word[core]{DOES}. The system need not maintain these
	identifiers in the same way it does other dictionary entries
	as long as they can be found by normal dictionary searching
	processes. Furthermore, if the Search-Order word set is present,
	local identifiers shall always be searched before any of the
	word lists in any definable search order, and none of the
	Search-Order words shall change the locals' privileged position
	in the search order. Local identifiers may reside in mass storage.

\item For each identifier passed to \word{LOCAL}, the system shall
	generate an appropriate code sequence that does the following at
	execution time:
	\begin{enumerate}
	\item Allocate a storage resource adequate to contain the value
		of a local. The storage shall be allocated in a way that
		does not preclude re-entrancy or recursion in the definition
		using the local.
	\item Initialize the value using the top item on the data stack.
		If more than one local is declared, the top item on the
		stack shall be moved into the first local identified, the
		next item shall be moved into the second, and so on.
	\end{enumerate}

	The storage resource may be the return stack or may be
	implemented in other ways, such as in registers. The storage
	resource shall not be the data stack. Use of locals shall not
	restrict use of the data stack before or after the point of
	declaration.

\item Arrange that any of the legitimate methods of terminating
	execution of a definition, specifically \word[core]{;}
	(semicolon), \word[tools]{;CODE}, \word[core]{DOES} or
	\word[core]{EXIT}, will release the storage resource allocated
	for the locals, if any, declared in that definition.
	\word[core]{ABORT} shall release all local storage resources,
	and \word[exception]{CATCH} / \word[exception]{THROW} (if
	implemented) shall release such resources for all definitions
	whose execution is being terminated.

\item Separate sets of locals may be declared in defining words
	before \word[core]{DOES} for use by the defining word, and
	after \word[core]{DOES} for use by the word defined.
\end{enumerate}

A system implementing the Locals word set shall support the
declaration of at least sixteen locals in a definition.


\subsubsection{Syntax restrictions} % 13.3.3.2
\label{locals:rules}

Immediate words in a program may use \word{LOCAL} to implement
syntaxes for local declarations with the following restrictions:

\begin{enumerate}
\item A program shall not compile any executable code into the
	current definition between the time \word{LOCAL} is executed
	to identify the first local for that definition and the time of
	sending the single required ``last local'' message;

\item The position in program source at which the sequence of
	\word{LOCAL} messages is sent, referred to here as the point
	at which locals are declared, shall not lie within the scope of
	any control structure;

\item Locals shall not be declared until values previously placed on
	the return stack within the definition have been removed;

\item After a definition's locals have been declared, a program may
	place data on the return stack. However, if this is done,
	locals shall not be accessed until those values have been
	removed from the return stack;

\item Words that return execution tokens, such as \word[core]{'}
	(tick), \word[core]{[']}, or \word[core]{FIND}, shall not be
	used with local names;

\item A program that declares more than sixteen locals in a single
	definition has an environmental dependency;

\item Locals may be accessed or updated within control structures,
	including do-loops;

\item Local names shall not be referenced by \word[core]{POSTPONE}
	and \word[core]{[COMPILE]}.
\end{enumerate}

See: \xref[3.4 The Forth text interpreter]{usage:command}.


\section{Additional documentation requirements} % 13.4

\subsection{System documentation} % 13.4.1

\subsubsection{Implementation-defined options} % 13.4.1.1
\begin{itemize}
\item maximum number of locals in a definition
	(\xref[13.3.3 Processing locals]{local:locals},
	 \wref{local:LOCALS}{LOCALS|}).
\end{itemize}

\subsubsection{Ambiguous conditions} % 13.4.1.2
\label{locals:ambiguous}
\begin{itemize}
\item executing a named \emph{local} while in interpretation state
	(\wref{local:LOCAL}{(LOCAL)});
\item a local name ends in ``\texttt{:}'', ``\texttt{[}'', ``\texttt{\textasciicircum}'';
\item a local name is a single non-alphabetic character;
\item the text between \word{b:} and \texttt{:\}} extends over more than one line;
\item \word{b:} \ldots\ \texttt{:\}} is used more than once in a word.
\end{itemize}

\subsubsection{Other system documentation} % 13.4.1.3
\begin{itemize}
\item no additional requirements.
\end{itemize}

\subsection{Program documentation} % 13.4.2

\subsubsection{Environmental dependencies} % 13.4.2.1
\label{locals:environment}
\begin{itemize}
\item declaring more than sixteen locals in a single definition
	(\xref[13.3.3 Processing locals]{local:locals}).
\end{itemize}

\subsubsection{Other program documentation} % 13.4.2.2
\begin{itemize}
\item no additional requirements.
\end{itemize}


\section{Compliance and labeling} % 13.5

\subsection{Forth-\snapshot{} systems} % 13.5.1

The phrase ``Providing the Locals word set'' shall be appended to
the label of any Standard System that provides all of the Locals
word set.

The phrase ``Providing \emph{name(s)} from the Locals Extensions
word set'' shall be appended to the label of any Standard System
that provides portions of the Locals Extensions word set.

The phrase ``Providing the Locals Extensions word set'' shall be
appended to the label of any Standard System that provides all of
the Locals and Locals Extensions word sets.

\subsection{Forth-\snapshot{} programs} % 13.5.2

The phrase ``Requiring the Locals word set'' shall be appended to
the label of Standard Programs that require the system to provide
the Locals word set.

The phrase ``Requiring \emph{name(s)} from the Locals Extensions
word set'' shall be appended to the label of Standard Programs that
require the system to provide portions of the Locals Extensions word
set.

The phrase ``Requiring the Locals Extensions word set'' shall be
appended to the label of Standard Programs that require the system
to provide all of the Locals and Locals Extensions word sets.


\section{Glossary} % 13.6

\subsection{Locals words} % 13.6.1

\enlargethispage{4ex}
\begin{worddef}[LOCAL]{0086}{(LOCAL)}[paren-local-paren]
\interpret
	Interpretation semantics for this word are undefined.

\execute
	\stack{c-addr u}{}

	When executed during compilation, \word{LOCAL} passes a
	message to the system that has one of two meanings. If \param{u}
	is non-zero, the message identifies a new \emph{local} whose
	definition name is given by the string of characters identified
	by \param{c-addr u}. If \param{u} is zero, the message is ``last
	local'' and \param{c-addr} has no significance.

	The result of executing \word{LOCAL} during compilation of a
	definition is to create a set of named local identifiers, each
	of which is a definition name, that only have execution
	semantics within the scope of that definition's source.

\execute[local]
	\stack{}{x}

	Push the local's value, \param{x}, onto the stack. The local's
	value is initialized as described in \xref[13.3.3 Processing
	locals]{local:locals} and may be changed by preceding the local's
	name with \word{TO}. An ambiguous condition exists when local is
	executed while in interpretation state.

\runtime[\word{TO} \param{local}] \stack{x}{}

	Assign the value \param{x} to the local value \param{local}.

\note
	This word does not have special compilation semantics in the
	usual sense because it provides access to a system capability
	for use by other user-defined words that do have them. However,
	the locals facility as a whole and the sequence of messages
	passed defines specific usage rules with semantic implications
	that are described in detail in section
	\xref[13.3.3 Processing locals]{local:locals}.

\note
	This word is not intended for direct use in a definition to
	declare that definition's locals. It is instead used by system
	or user compiling words. These compiling words in turn define
	their own syntax, and may be used directly in definitions to
	declare locals. In this context, the syntax for \word{LOCAL}
	is defined in terms of a sequence of compile-time messages and
	is described in detail in section \xref[13.3.3 Processing
	locals]{local:locals}.

\see \xref[3.4 The Forth text interpreter]{usage:command} and
	\wref{core:TO}{TO}.
\end{worddef}


\subsection{Locals extension words} % 13.6.2
\extended

\begin{worddef}[LOCALS]{1795}{LOCALS|}[locals-bar]
\interpret
	Interpretation semantics for this word are undefined.

\compile
	\stack{"<spaces>name_1" "<spaces>name_2" {\ldots} "<spaces>name_n" "|"}{}

	Create up to eight local identifiers by repeatedly skipping
	leading spaces, parsing \param{name}, and executing
	\wref{local:LOCAL}{(LOCAL)}. The list of locals to be defined
	is terminated by \param{|}. Append the run-time semantics given
	below to the current definition.

\runtime
	\stack{x_n {\ldots} x_2 x_1}{}

	Initialize up to eight local identifiers as described in
	\wref{local:LOCAL}{(LOCAL)}, each of which takes as its
	initial value the top stack item, removing it from the stack.
	Identifier \param{name_1} is initialized with \param{x_1},
	identifier \param{name_2} with \param{x_2}, etc. When invoked,
	each local will return its value. The value of a local may be
	changed using \wref{core:TO}{TO}.

\note This word is obsolescent and is included as a concession to
	existing implementations.

	\begin{implement}
	\word{:} \word{LOCALS} \word{p} "name{\ldots}name |" -{}- ) \\
	\tab \word{BEGIN} \\
	\tab~ \word{BL} \word{WORD} ~ \word{COUNT} \word{OVER} \word{C@} \\
	\tab~ \word{[CHAR]} | \word{-} \word{OVER} 1 \word{-} \word{OR} ~ \word{WHILE} \\
	\tab~ \word[local]{LOCAL} \\
	\tab \word{REPEAT} \word{2DROP} ~ 0 0 \word{LOCAL} \\
	\word{;} \word{IMMEDIATE}
	\end{implement}

\end{worddef}

% -------------------------------------------------------------------

\begin{worddef}[b:]{2550}{\brace:}[brace-colon][X:enhanced-locals]
\interpret
	Interpretation semantics for this word are undefined.

\compile
	\stack{i*x "<spaces>ccc \texttt{:\}}"}{}

	Parse \param{ccc} according to the following syntax:
	\begin{center}
		\word{b:} \arg{arg}* [\textbf{\textbar} \arg{val}*] [\textbf{--\,--} \arg{out}*] \verb":}"
	\end{center}
	where \arg{arg}, \arg{val} and \arg{out} are local names, and
	\param{i} is the number of \arg{arg} names given.

	The following ambiguous conditions exist when:
	\begin{itemize}
	\item a local name ends in ``\texttt{:}'', ``\texttt{[}'', ``\texttt{\textasciicircum}'';
	\item a local name is a single non-alphabetic character;
	\item the text between \word{b:} and \texttt{:\}} extends
			over more than one line;
	\item \word{b:} \ldots\ \texttt{:\}} is used more than once in a word.
	\end{itemize}

	Append the run-time semantics below. 

\runtime
	\stack{x_1 \ldots\ x_n}{}

	Create locals for \arg{arg}s and \arg{val}s. \arg{out}s are ignored.

	\begin{list}{}{
		\setlength{\leftmargin}{2.6em}
		\setlength{\labelwidth}{2.4em}
	}
	\item[\arg{arg}] names are initialized from the data stack, with the
		top of the stack being assigned to the right most \arg{arg} name.

	\item[\arg{val}] names are uninitialized.
	\end{list}

	\arg{val} and \arg{arg} names have the execution semantics
		given below.

\execute[name]
	\stack{}{x}

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

\runtime[\word{TO} \param{name}]
	\stack{x}{}

	Set \param{name} to the value \param{x}.

\see \xref[2.2 Notation]{notation:BNF},
	\wref{core:VALUE}{},
	\wref{core:TO}{},
	\rref{local:b:}{}.

	\begin{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 \word{LOCAL} and \linebreak[1] \word{LOCALS} also provide some form of the
		\{ \ldots\ \} notation; however, the phrase \{ \ldots \} conflicts with
		other systems.  The \word{b:} \ldots\ \texttt{:\}} 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
		`\texttt{\textbar}'.  The definition of locals is terminated by
		`\texttt{-{}-}' or `\texttt{:\}}'.

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

		The `\texttt{\textbar}' (ASCII \$7C) character is widely used as the
		separator between local arguments and local values.  Some implementations
		have used `\texttt{\bs}' (ASCII \$5C) or `\texttt{\textbrokenbar}' (\$A6).
		Systems are free to continue to provide these alternative separators.
		However, only the recognition of the `\texttt{\textbar}' separator is
		mandatory. Therefore portable programs must use the `\texttt{\textbar}'
		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
		`\texttt{:}' (colon),
		`\texttt{[}' (open bracket), or
		`\texttt{\textasciicircum}' (caret) are reserved.
	\end{rationale}

	\begin{implement}
12345 \word{CONSTANT} undefined-value

\word{:} match-or-end? \word{p} c-addr1 u1 c-addr2 u2 -{}- f ) \\
\tab\,2 \word{PICK} \word{0=} \word{toR} \word[string]{COMPARE} \word{0=} \word{Rfrom} \word{OR} \word{;}

\word{:} scan-args \\
\tab\,\word{bs} 0 c-addr1 u1 -{}- c-addr1 u1 ... c-addrn un n c-addrn+1 un+1\\
\tab\,\word{BEGIN} \\
\tab[2]	\word{2DUP} \word{Sq} |"   ~match-or-end? \word{0=} \word{WHILE} \\
\tab[2]	\word{2DUP} \word{Sq} -{}-" match-or-end? \word{0=} \word{WHILE} \\
\tab[2]	\word{2DUP} \word{Sq} :\}"  match-or-end? \word{0=} \word{WHILE} \\
\tab[2]	\word{ROT} \word{1+} \word{PARSE-NAME} \\
\tab\,\word{AGAIN} \word{THEN} \word{THEN} \word{THEN} \word{;}

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

\word{:} scan-end \word{p} c-addr1 u1 -{}- c-addr2 u2 ) \\
\tab\,\word{BEGIN} \\
\tab[2]	\word{2DUP} \word{Sq} :\}" match-or-end? \word{0=} \word{WHILE} \\
\tab[2]	\word{2DROP} \word{PARSE-NAME} \\
\tab\,\word{REPEAT} \word{;}

\word{:} define-locals \word{p} c-addr1 u1 ... c-addrn un n -{}- ) \\
\tab\,0 \word{qDO} \\
\tab[2]	\word{LOCAL} \\
\tab\,\word{LOOP} \\
\tab\,0 0 \word{LOCAL} \word{;}

\word{:} \{: \word{p} -{}- ) \\
\tab\,0 \word{PARSE-NAME} \\
\tab\,scan-args scan-locals scan-end \\
\tab\,\word{2DROP} define-locals \\
\word{;} \word{IMMEDIATE}
	\end{implement}
\end{worddef}

\endinput


Reference Implementation

0 [if]
BUILDLV    c-addr u +n mode
When executed during compilation, BUILDLV passes a message to the
system identifying a new local argument whose definition name is
given by the string of characters identified by c-addr u. The size
of the data item is given by +n address units, and the mode
identifies the construction required as follows:
   0 - finish construction of initialisation and data storage
       allocation code. C-addr and u are ignored. +n is 0
       (other values are reserved for future use).
   1 - identify a local argument, +n = cell
   2 - identify a local value, +n = cell
   3+ - reserved for future use
   -ve - implementation specific values

The result of executing BUILDLV during compilation of a definition
is to create a set of named local arguments and values, each of
which is a definition name, that only have execution semantics
within the scope of that definition's source.

Note that it is often useful to accumulate and store the size of
locals storage (0=none), so that compilers for EXIT can easily
determine if locals clean up code is required.
[then]

VARIABLE #LVS   \ -- addr
\ Holds size of locals storage required.

: BUILDLV	\ c-addr u +n mode --
\ Dummy for testing
   OVER #LVS +!
   CR 2SWAP TYPE  SPACE  SWAP . .
;

: TOKEN         \ -- caddr u
\ Get the next space delimited token from the input stream.
\ Can be extended to permit multiple line declarations.
   PARSE-NAME
;

: LTERM?        \ caddr u -- flag
\ Return true if the string caddr/u is "--" or ":}"
   2DUP S" --" COMPARE 0= >R
   S" :}" COMPARE 0=  R> OR
;

: LSEP?         \ caddr u -- flag
\ Return true if the string caddr/u is the separator between
\ local arguments and local values or buffers.
   2DUP S" |" COMPARE 0= >R
   S" \" COMPARE 0=  R> OR
;

: {:            \ --
\ Parse the locals declaration up to the closing ":}".
   0 #LVS !                              \ indicate no locals yet
   0 >R                                  \ indicate arguments
   BEGIN
     TOKEN 2DUP LTERM? 0=
   WHILE                                 \ -- caddr len
     2DUP LSEP? IF                       \ if '|'
       R> DROP  1 >R                     \ change to vars and buffers
     ELSE
       R@ 0= IF                          \ argument?
         CELL 1
       ELSE                              \ value
         CELL 2
       THEN
       BUILDLV
     THEN
   REPEAT
   BEGIN
     S" :}" COMPARE
    WHILE
     TOKEN
   REPEAT
   0 0 0 0 BUILDLV
   R> DROP
; IMMEDIATE
Test Cases

: LT1  {: a b | c -- f :}
   CR ." Hello1 " CR  a  ;
T{ 3 4 LT1 -> 3 }T \ Outputs Hello1

: LT2  {: a | b c e :}
   CR ." Hello2 " CR  ;
T{ 3 LT2 -> }T \ Outputs Hello2

: LT3  {: a b c -- :}
   CR ." Hello3 " CR  ;
T{ 3 4 5 LT3 -> }T \ Outputs Hello3

: LT4  {: a b c :}
   CR ." Hello4 " CR  ;
T{ 3 4 5 LT4 -> }T \ Outputs Hello4

: LT5  {: a | b c d -- e f g :}
   CR ." Hello5 " CR
   a 2* to b  b 2* to c  c 2* to d
   b c d  ;
T{ 3 LT5 -> 6 12 24 }T \ Outputs Hello5
