-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlocals.tex
593 lines (470 loc) · 20.5 KB
/
locals.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
% !TeX root = forth.tex
% !TeX spellcheck = en_US
% !TeX program = pdflatex
\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.
\pagebreak
\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} % I.13.6.2.1795 LOCALS|
\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}*] \textbf{:\}}
\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} % A.13.6.2.2550 {:
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} % I.13.6.2.2550 {:
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