Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

RfD: Enhanced local variable syntax

46 views
Skip to first unread message

Peter Knaggs

unread,
Jul 11, 2007, 12:55:06 PM7/11/07
to forth200x
Stephen Pelc - 7 June 2007

20070607 Wordsmithing. Corrected reference implementation.
20060822 Added explanatory text.
Corrected reference implementation.
Updated ambiguous conditions.

Problem
=======
1) The current LOCALS| ... | notation explicitly forces all locals
to be initialised from the data stack.
2) The current LOCALS| ... | notation defines locals in reverse
order to the normal stack notation.
3) When programming large applications, especially those interfacing
with a host operating system, there is a frequent need for temporary
buffers.
4) Current implementations show that creation and destruction of
local buffers are much faster than using ALLOCATE (14.6.1.0707)
and FREE (14.6.1.1605).

Solution
========
Base version
------------
The following syntax for local arguments and local variables is
proposed. The sequence:

{ ni1 ni2 ... | lv1 lv2 ... -- o1 o2 ... }

defines local arguments, local variables, and outputs. The local
arguments are automatically initialised from the data stack on
entry, the rightmost being taken from the top of the data stack.
Local arguments and local variables can be referenced by name within
the word during compilation. The output names are dummies to allow
a complete stack comment to be generated.

The items between { and | are local arguments.
The items between | and -- are local variables or buffers.
The items between -- and } are outputs for formal comments only.

The outputs are provided in the notation so that complete stack
comments can be produced. However, all text between -- and } is
ignored. The facility is there to permit the notation to form a
complete stack comment. This eases documentation and current
users of the notation like this facility.

Local arguments and variables return their values when referenced,
and must be preceded by TO to perform a store.

Local buffers may be defined in the form:

arr[ <expr> ]

Any name ending in the '[' character will be treated as a buffer,
the expression up to the terminating ']' will be interpreted to
provide the size of the buffer. Local buffers only return their base
address, all operators such as TO generate an ambiguous condition.

In the example below, a and b are local arguments, a+b and a*b are
local variables, and arr[ is a 10 byte local buffer.

: foo { a b | a+b a*b arr[ 10 ] -- }
a b + to a+b
a b * to a*b
cr a+b . a*b .
arr[ 10 erase
s" Hello" arr[ swap cmove
;

Local types
-----------
Some current Forth systems use indicators to define local variables
of sizes other than a cell. It is proposed that any name ending in a ':'
(colon) be reserved for this use.

: foo { a b | F: f1 F: f2 -- c }
...
;

Discussion
==========
The '|' (ASCII 0x7C) character is widely used as the separator
between local arguments and local variables. Other characters
accepted in current Forth implementations are '\' (ASCII 0x5C) and
'Ś' (ASCII 0xA6).. Since the ANS standard is defined in terms of
7 bit ASCII, and with regard to internationalisation, we propose only
to consider the '|' and '\' characters further. Only recognition of
the '|' separator is mandatory.

The use of local types is contentious as they only become useful
if TO is available for these. In practice, some current systems
permit TO to be used with floats (children of FVALUE) and other
data types. Such systems often provide additional operators such
as +TO (add from stack to item) for children of VALUE and FVALUE.
Standardisation of operators with (for example) floats needs to
be done before the local types extension can be incorporated into
Forth200x. Apart from forcing allocation of buffer space, no
additional functionality is provided by local types that cannot
be obtained using local buffers. More preparatory standardisation
needs to be done before local types can be standardised.

Apart from { (brace) itself, the proposal introduces one new
word BUILDLV. The definition of this word is designed for future
enhancements, e.g. more local data types, without having to
introduce more new words.

It has been noted that one widely used implementation uses brace
for multi line comments. However, inspection of the vendor's code
shows that this use only occurs during interpretation. The
interpretation semantics of brace in this proposal are undefined
in order for that implementation to coexist with this proposal.


Proposal
========

13.3 and 13.4
Add "and BUILDLV" where (LOCAL) is referenced.

13.6.2.xxxx {
brace LOCAL EXT

Interpretation: Interpretation semantics for this word are undefined.

Compilation:
( "<spaces>arg1" ... "<spaces>argn" | "<spaces>lv1" ... "<spaces>lvn" -- )

Create up to eight local arguments by repeatedly skipping leading
spaces, parsing arg, and executing 13.6.2.yyyy BUILDLV. The list of
local arguments to be defined is terminated by "|", "--" or "}".
Append the run-time semantics for local arguments given below to the
current definition. If a space delimited '|' is encountered, create
up to eight local variables or buffers by repeatedly skipping
leading spaces, parsing lv, and executing 13.6.2.yyyy BUILDLV. The
list of local variables and buffers to be defined is terminated by
"--" or "}". Append the run-time semantics for local variables and
local buffers given below to the current definition. If "--" has
been encountered, further text between "--" and } is ignored.

Local buffers have names that end in the '[' character. They define
their size by parsing the text string up to the next ']' character,
and passing that string to 7.6.1.1360 EVALUATE to obtain the size
of the storage in address units.

Local argument run-time: ( x1 ... xn -- )
Local variable run-time: ( -- )
Local buffer run-time: ( -- )

Initialize up to eight local arguments as described in 13.6.2.yyyy
BUILDLV. Local argument arg1 is initialized with x1, arg2 with x2 up
to argn from xn, which is on the top of the data stack. When
invoked, each local argument will return its value. The value
of a local argument may be changed using 13.6.1.2295 TO.

Initialize up to eight local variables or local buffers as described
in 13.6.2.yyyy BUILDLV. The initial contents of local variables and
local buffers are undefined. When invoked, each local variable
returns its value. The value of a local variable may be changed
using 13.6.1.2295 TO. The size of a local variable is a cell.
When invoked, each local buffer will return its address. The user
may make no assumption about the order and contiguity of local
variables and buffers in memory.

Ambiguous conditions:
a) The { ... } text extends over more than one line.
b) The expression for local buffer size does not return a single
cell.
c) { ... } is declared more than once in a word.
d) Parsing units '|', ']', '--' and '}' are not white space delimited.

13.6.2.yyyy BUILDLV
build-l-v LOCAL EXT

Interpretation: Interpretation semantics for this word are undefined.

Execution: ( 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 variable, +n = cell
3 - identify a local buffer, +n = storage required.
4+ - 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, variables and/or
buffers, each of which is a definition name, that only have
execution semantics within the scope of that definition's source.

local argument execution: ( -- x )
Push the local argument's value, x, onto the stack. The local
argument's value is initialized as described in 13.6.2.xxxx { and may be
changed by preceding the local argument's name with TO.

local variable execution: ( -- x )
Push the local variable's value, x, onto the stack. The local
variable is not initialised. The local variable's value may be
changed by preceding the local variable's name with TO.

local buffer execution: ( -- a-addr )
Push the local buffer's address, a-addr, onto the stack. The address
is aligned as in 3.3.3.1. The contents of the buffer are not
initialised.

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 13.3.3 Processing 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 BUILDLV is defined in terms
of a sequence of compile-time messages and is described in detail
in section 13.3.3 Processing locals.

Note: The LOCAL EXT word set modifies the syntax and semantics of
6.2.2295 TO as defined in the Core Extensions word set.

See: 3.4 The Forth text interpreter

Ambiguous conditions:
a local argument, variable or buffer is executed while in
interpretation state.


Reference implementation
=========================
(currently untested)

: TOKEN \ -- caddr u
\ Get the next space delimited token from the input stream.
BL PARSE
;

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

: LBSIZE \ -- +n
\ Parse up to the terminating ']' and EVALUATE the expression
\ not including the terminating ']'.
POSTPONE [ [CHAR] ] PARSE EVALUATE ]
;

: LB? \ caddr u -- flag
\ Return true if the last character of the string is '['.
+ 1 CHARS - C@ [CHAR] [ =
;

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

: { ( -- )
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 \ variable or buffer
LB?
IF LBSIZE 3 ELSE CELL 2 THEN
THEN
BUILDLV
THEN
REPEAT
BEGIN
S" }" COMPARE
WHILE
TOKEN
REPEAT
0 0 0 0 BUILDLV
R> DROP
; IMMEDIATE

Anton Ertl

unread,
Jul 14, 2007, 9:58:59 AM7/14/07
to
Peter Knaggs <pkn...@bournemouth.ac.uk> writes:
>Stephen Pelc - 7 June 2007
>'Ś' (ASCII 0xA6)

That's not an ASCII character, it's Latin-1.

>Only recognition of
>the '|' separator is mandatory.

Good.

>The use of local types is contentious as they only become useful
>if TO is available for these.

Not really; I generally use locals (including FP locals) without using
TO.

Also, extending TO to support FP locals is easy with the proposed
rewording of TO.

> In practice, some current systems
>permit TO to be used with floats (children of FVALUE) and other
>data types. Such systems often provide additional operators such
>as +TO (add from stack to item) for children of VALUE and FVALUE.
>Standardisation of operators with (for example) floats needs to
>be done before the local types extension can be incorporated into
>Forth200x.

If by "operator" you mean words like +TO, let the proponent of such
a word worry about that.

If you mean operators like TO, and you don't want to propose it, don't
do it; I'm sure Marcel Hendrix will step up. If you want to propose
TO for FP locals, I don't see any hurdle.

>Apart from { (brace) itself, the proposal introduces one new
>word BUILDLV. The definition of this word is designed for future
>enhancements, e.g. more local data types, without having to
>introduce more new words.

The intention behind BUILDLV is good, but I find the design extremely
ugly (see, e.g., <2006Aug2...@mips.complang.tuwien.ac.at> for a
detailed critique). Moreover, I don't think it buys much, if
anything: nobody is going to use it, just as almost nobody is
currently using "(LOCAL)". So while one could design a cleaner
replacement for BUILDLV, I don't think it is worth the effort, and the
proposal will be more attractive to implementors and not any less
attractive to programmers if you just leave BUILDLV and its
replacement away.

- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.forth200x.org/forth200x.html
EuroForth 2007: http://www.complang.tuwien.ac.at/anton/euroforth2007/

Bruce McFarling

unread,
Jul 14, 2007, 5:27:15 PM7/14/07
to
On Jul 11, 12:55 pm, Peter Knaggs <pkna...@bournemouth.ac.uk> wrote:

Local variables are not local variables, they are unintitialized local
values. Returning an address for them to be used as actual local
variables would eliminate the question of TO altogether.

Ed

unread,
Jul 15, 2007, 12:44:32 AM7/15/07
to

"Peter Knaggs" <pkn...@bournemouth.ac.uk> wrote in message news:46950B6A...@bournemouth.ac.uk...

> Stephen Pelc - 7 June 2007
>
> ...

> Apart from { (brace) itself, the proposal introduces one new
> word BUILDLV. The definition of this word is designed for future
> enhancements, e.g. more local data types, without having to
> introduce more new words.
> ...

I would suggest there is no necessity to have BUILDLV as a word
within the standard. The standard only needs to define the syntax
used by local variables. BUILDLV has to do with implementation.

> Any name ending in the '[' character will be treated as a buffer,
> the expression up to the terminating ']' will be interpreted to
> provide the size of the buffer.

> ...

As others previously noted, embedding an operator [ within a
name is contrary to forth's simple parsing. There must be a
better way.

Coos Haak

unread,
Jul 15, 2007, 5:55:19 AM7/15/07
to
Op Sun, 15 Jul 2007 14:44:32 +1000 schreef Ed:

> As others previously noted, embedding an operator [ within a
> name is contrary to forth's simple parsing. There must be a
> better way.

I can't follow you. The word would be parsed, perform its semantics and set
STATE to zero. ; follows exactly the same recipe.

--
Coos

CHForth, 16 bit DOS applications
http://home.hccnet.nl/j.j.haak/forth.html

Ed

unread,
Jul 15, 2007, 10:40:16 PM7/15/07
to

"Coos Haak" <chf...@hccnet.nl> wrote in message news:iynuqnpgen7w$.c7vdhnd2ofx9.dlg@40tude.net...

> Op Sun, 15 Jul 2007 14:44:32 +1000 schreef Ed:
>
> > As others previously noted, embedding an operator [ within a
> > name is contrary to forth's simple parsing. There must be a
> > better way.
>
> I can't follow you. The word would be parsed, perform its semantics and set
> STATE to zero. ; follows exactly the same recipe.

The proposal calls for locals buffer names to be defined in the form:

bufname[

where [ is stripped off, leaving the actual name 'bufname'

That's contrary to forth practice where names are space delimited.
The first time I saw this syntax being used, I thought there existed
a word in the dictionary called 'bufname[' but try as I might I could
not find it.

IMO one of the nicest features of forth is it's simple syntax:
names or numbers separated by spaces. Let's keep it that way.

Jerry Avins

unread,
Jul 15, 2007, 11:36:56 PM7/15/07
to
Ed wrote:

...

> As others previously noted, embedding an operator [ within a
> name is contrary to forth's simple parsing. There must be a
> better way.

Others? Which others? '[' is a character like any other. It would be
pointless, even silly, to define
: ][ ( -- ) ." Look Ma, an Apple II!" CR ;
but it should work an any Forth system.

Jerry
--
Engineering is the art of making what you want from things you can get.
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

Jerry Avins

unread,
Jul 15, 2007, 11:40:35 PM7/15/07
to
Ed wrote:

...

> IMO one of the nicest features of forth is it's simple syntax:
> names or numbers separated by spaces. Let's keep it that way.

I apparently misunderstood again. Yes: Let's keep it that way.

Jerry
--
L'etat n'a pas besoin des savants: Robespierre, on Lavoisier's death.
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

Gerry

unread,
Jul 16, 2007, 2:53:14 AM7/16/07
to

I agree. I remember pointing this out last year. A standard should be
precise in its use of terminology. Up to now I believe that the word
variable in Forth means an object that leaves its address on the stack
when invoked. Indeed the standard states in 2.1

" Variable: a named region of data space located and accessed by its
memory address."

The proposed local variables do not do that and so should be called
local values.

I know this is nit picking but a standard needs its nits to be picked.

Gerry

Anton Ertl

unread,
Jul 16, 2007, 4:25:25 AM7/16/07
to
Gerry <ge...@jackson9000.fsnet.co.uk> writes:
>" Variable: a named region of data space located and accessed by its
>memory address."
>
>The proposed local variables do not do that and so should be called
>local values.

Forth-94 just calls them "locals", except in 13.3.2, where "local
variables" occurs. "Local value" does not occur (at least not in
Chapter 13).

Gerry

unread,
Jul 17, 2007, 6:46:16 AM7/17/07
to
On 16 Jul, 09:25, an...@mips.complang.tuwien.ac.at (Anton Ertl) wrote:
> Gerry <ge...@jackson9000.fsnet.co.uk> writes:
> >" Variable: a named region of data space located and accessed by its
> >memory address."
>
> >The proposed local variables do not do that and so should be called
> >local values.
>
> Forth-94 just calls them "locals", except in 13.3.2, where "local
> variables" occurs. "Local value" does not occur (at least not in
> Chapter 13).
>

Yes it looks like the original technical committee recognised the
problem of using the term local variables and avoided it except for
the 1 slip up that you noted. I don't know what you could call them
except local values which does sound a bit awkward.

Gerry


Peter Knaggs

unread,
Jul 21, 2007, 5:40:31 AM7/21/07
to

What syntax would you like, I can think of two alternatives:

20 buffer: bufname or bufname [ 20 ALLOT ]

both of which would make the parsing of locals considerably more complex.

As we are talking about a standard, we have to consider what already
exists, not what we would like to exist. There are systems out there
which have been using the bufname[ 20 ] format for many years.

--
Peter Knaggs

Andrew Haley

unread,
Jul 21, 2007, 6:14:34 AM7/21/07
to
Peter Knaggs <pkn...@bournemouth.ac.uk> wrote:
> Stephen Pelc - 7 June 2007

> 20070607 Wordsmithing. Corrected reference implementation.
> 20060822 Added explanatory text.
> Corrected reference implementation.
> Updated ambiguous conditions.

> Problem
> =======
> 1) The current LOCALS| ... | notation explicitly forces all locals
> to be initialised from the data stack.
> 2) The current LOCALS| ... | notation defines locals in reverse
> order to the normal stack notation.
> 3) When programming large applications, especially those interfacing
> with a host operating system, there is a frequent need for temporary
> buffers.
> 4) Current implementations show that creation and destruction of
> local buffers are much faster than using ALLOCATE (14.6.1.0707)
> and FREE (14.6.1.1605).

Most of this proposal makes good sense, but items 3 and 4 make no
sense at all. We can already use ALLOT to create local buffers, and
Forth stacks are usually (traditionally?) too small to be used for
such things. Also, forcing buffer names to have a special syntax is
very non-Forth. So what is the application use for these words? Do
they have one?

Andrew.

Marcel Hendrix

unread,
Jul 21, 2007, 6:20:50 AM7/21/07
to
Peter Knaggs <pkn...@bournemouth.ac.uk> writes Re: RfD: Enhanced local variable syntax
[..]

> What syntax would you like, I can think of two alternatives:

> 20 buffer: bufname or bufname [ 20 ALLOT ]

> both of which would make the parsing of locals considerably more complex.

What's wrong with your last one?

Let's see ..

bufname buffer 20
or
bufname [] 20

or bufname [ 20 CELLS ]

.. where buffer, [] or [ is recognized by LOCALS| and executed instead of made
into a local. The BUFFER modifier word would then simply modify the allocation
size of the latest local.

I don't see that '[' would make the locals parser 'considerably more complex.'

-marcel

Elizabeth D Rather

unread,
Jul 21, 2007, 2:41:35 PM7/21/07
to
Peter Knaggs wrote:
> Ed wrote:
...

>> IMO one of the nicest features of forth is it's simple syntax:
>> names or numbers separated by spaces. Let's keep it that way.
>
> What syntax would you like, I can think of two alternatives:
>
> 20 buffer: bufname or bufname [ 20 ALLOT ]
>
> both of which would make the parsing of locals considerably more complex.
>
> As we are talking about a standard, we have to consider what already
> exists, not what we would like to exist. There are systems out there
> which have been using the bufname[ 20 ] format for many years.

Horrors, not 'buffer:' since that name is used in Open Firmware, FORTH,
Inc. products, OTA, and probably others as equivalent to:

: BUFFER: ( n -- ) CREATE ALLOT ;

Trivial syntactic sugar, to be sure, but widely used and very popular.

Cheers,
Elizabeth

--
==================================================
Elizabeth D. Rather (US & Canada) 800-55-FORTH
FORTH Inc. +1 310-491-3356
5155 W. Rosecrans Ave. #1018 Fax: +1 310-978-9454
Hawthorne, CA 90250
http://www.forth.com

"Forth-based products and Services for real-time
applications since 1973."
==================================================

Ed

unread,
Jul 22, 2007, 12:09:55 AM7/22/07
to

"Peter Knaggs" <pkn...@bournemouth.ac.uk> wrote in message news:46a1d492$0$1616$ed26...@ptn-nntp-reader02.plus.net...

> Ed wrote:
> > "Coos Haak" <chf...@hccnet.nl> wrote in message news:iynuqnpgen7w$.c7vdhnd2ofx9.dlg@40tude.net...
> >> Op Sun, 15 Jul 2007 14:44:32 +1000 schreef Ed:
> >>
> >>> As others previously noted, embedding an operator [ within a
> >>> name is contrary to forth's simple parsing. There must be a
> >>> better way.
> >> I can't follow you. The word would be parsed, perform its semantics and set
> >> STATE to zero. ; follows exactly the same recipe.
> >
> > The proposal calls for locals buffer names to be defined in the form:
> >
> > bufname[
> >
> > where [ is stripped off, leaving the actual name 'bufname'
> >
> > That's contrary to forth practice where names are space delimited.
> > The first time I saw this syntax being used, I thought there existed
> > a word in the dictionary called 'bufname[' but try as I might I could
> > not find it.
> >
> > IMO one of the nicest features of forth is it's simple syntax:
> > names or numbers separated by spaces. Let's keep it that way.
>
> What syntax would you like, I can think of two alternatives:
>
> 20 buffer: bufname or bufname [ 20 ALLOT ]
>
> both of which would make the parsing of locals considerably more complex.

Assuming there is clear support for such a change (and this needs to
be established) any syntax that follows forth norms should suffice.
Name last is simple and commonplace in forth, so perhaps:

[ alignment/size ] name

Given the parser is already looking for a delimiter/operator e.g. -- }
then adding [ should not be difficult?

> As we are talking about a standard, we have to consider what already
> exists, not what we would like to exist. There are systems out there
> which have been using the bufname[ 20 ] format for many years.

IMO standards have an obligation to choose best practice because
all forth users are affected, including forth users of the future.

Ed

unread,
Jul 23, 2007, 7:00:35 AM7/23/07
to

"Ed" <nos...@invalid.com> wrote in message news:f7uled$mf$1...@news-01.bur.connect.com.au...
> ...

> Assuming there is clear support for such a change (and this needs to
> be established) any syntax that follows forth norms should suffice.
> Name last is simple and commonplace in forth, so perhaps:
>
> [ alignment/size ] name
>
> Given the parser is already looking for a delimiter/operator e.g. -- }
> then adding [ should not be difficult?

Not difficult as it turns out. Here are the changes to the reference
implementation needed to implement this scheme (also untested :)

: LB? \ caddr u -- flag

S" [" COMPARE 0=
;

\ changes to definition {
ELSE \ variable or buffer
2DUP LB?
IF 2DROP LBSIZE TOKEN ROT 3 ELSE CELL 2 THEN
THEN

Alex McDonald

unread,
Jul 23, 2007, 8:35:31 AM7/23/07
to
On Jul 11, 5:55 pm, Peter Knaggs <pkna...@bournemouth.ac.uk> wrote:
> Stephen Pelc - 7 June 2007
>
> 20070607 Wordsmithing. Corrected reference implementation.
> 20060822 Added explanatory text.
> Corrected reference implementation.
> Updated ambiguous conditions.
>
> Problem
> =======
> 1) The current LOCALS| ... | notation explicitly forces all locals
> to be initialised from the data stack.
> 2) The current LOCALS| ... | notation defines locals in reverse
> order to the normal stack notation.
> 3) When programming large applications, especially those interfacing
> with a host operating system, there is a frequent need for temporary
> buffers.
> 4) Current implementations show that creation and destruction of
> local buffers are much faster than using ALLOCATE (14.6.1.0707)
> and FREE (14.6.1.1605).
>

[snipped]

This RfD and the solutions discussed elsewhere in this thread lead me
to conclude that, as LOCALS (both { and LOCALS|) already demand an
alternative parse to the traditional Forth parse of find and compile,
neither is amenable to further simple expansion due to the
increasingly bizarre extensions of syntax being put forward. I would
prefer to see a straightforward and clean parse based, as far as is
possible, on the current Forth model, and not a parse that /by design/
requires alternative meanings or special syntaxes for standard Forth
words that are not available outside of LOCALS use (i.e. [ n ] ARR or
ARR[ n ] for CREATE ARR n ALLOT; or f: for FLOAT values).

I realise that Win32Forth is guilty of the use of trailing : for OOP
class methods, and [ ] for late binding; that's a feature of NEON/MOPS
that I, for one, dislike, as it makes complex something that should be
simple. This proposal on a NEON/MOPS system would allow

: f: { f: seconds | } seconds f: rocket ;

Three seperate meanings of f: (a word, a float definition and a method
invocation respectively). Even on simpler, non-NEON/MOPS systems,
there would be two meanings. Best not to repeat that mistake.

I believe { } needs abandoned as a standards proposal, or fixed in its
current usage, and some other design should take its place. I can't
support this RfD in its current form, nor the alternative proposals it
has spawned.

--
Regards
Alex McDonald

Anton Ertl

unread,
Jul 23, 2007, 8:56:15 AM7/23/07
to
Alex McDonald <bl...@rivadpm.com> writes:
>This RfD and the solutions discussed elsewhere in this thread lead me
>to conclude that, as LOCALS (both { and LOCALS|) already demand an
>alternative parse to the traditional Forth parse of find and compile,
>neither is amenable to further simple expansion due to the
>increasingly bizarre extensions of syntax being put forward. I would
>prefer to see a straightforward and clean parse based, as far as is
>possible, on the current Forth model, and not a parse that /by design/
>requires alternative meanings or special syntaxes for standard Forth
>words that are not available outside of LOCALS use (i.e. [ n ] ARR or
>ARR[ n ] for CREATE ARR n ALLOT; or f: for FLOAT values).
>
>I realise that Win32Forth is guilty of the use of trailing : for OOP
>class methods, and [ ] for late binding; that's a feature of NEON/MOPS
>that I, for one, dislike, as it makes complex something that should be
>simple.

One difference is that the Neon stuff can occur anywhere in Forth
code, whereas Stephen's funky buffer syntax can only occur inside a
locals definition, i.e., between { and }. And there syntax is treated
non-uniformly already, as all occuring words are defined, except },
--, and | (and the situation with LOCALS| is similar).

I think the Neon stuff is a mistake, because AFAIK one cannot tick or
POSTPONE the words ending in ":".

In that sense locals are a mistake irrespective of syntax, because you
cannot tick or POSTPONE a local. However, since locals are just a
convenience for stuff that one can also do without too much ado in
other ways (i.e., using the stacks), this has not turned out to be a
problem (I never find myself wishing that I could tick or POSTPONE a
local).

Concerning the { syntax, one can POSTPONE { itself; this is a parsing
word, so if one cannot also POSTPONE the stuff it parses, that's
nothing unusual.

> This proposal on a NEON/MOPS system would allow
>
>: f: { f: seconds | } seconds f: rocket ;

Actually the present proposal does not cover FP locals and does not
propose "f:". It's surprising that the heaviest user of FP locals I
know (Marcel Hendrix) has not complained about that, but maybe his
plan is to stay away from "{" anyway; he seems to enjoy defining the
locals in the wrong order.

>Three seperate meanings of f: (a word, a float definition and a method
>invocation respectively). Even on simpler, non-NEON/MOPS systems,
>there would be two meanings. Best not to repeat that mistake.

However, assuming that we get f: eventually: That's not so unusual,
and not a problem, so I don't see it as a mistake. E.g., I can also
write:

: SWAP SWAP ;

and the two occurences of SWAP have different meanings.

>I believe { } needs abandoned as a standards proposal, or fixed in its
>current usage, and some other design should take its place.

Given the present relatively wide acceptance of {, standardizing that
is probably the best chance we have of getting more featureful locals
(e.g., FP locals). I don't think there is a realistic chance that
another syntax will succeed if { fails. And certainly not if no one
makes a proposal for such an alternative syntax.

Marcel Hendrix

unread,
Jul 23, 2007, 1:02:48 PM7/23/07
to
an...@mips.complang.tuwien.ac.at (Anton Ertl) writes Re: RfD: Enhanced local variable syntax
[..]

> Actually the present proposal does not cover FP locals and does not
> propose "f:". It's surprising that the heaviest user of FP locals I
> know (Marcel Hendrix) has not complained about that, but maybe his
> plan is to stay away from "{" anyway; he seems to enjoy defining the
> locals in the wrong order.

No, I will implement '{', why should I resist that?

AFAIK, at the moment '{' is not standard, so I am amazed to get such heavy
flak each time I for once decide to use a standard Forth construct :-)

[ I do not complain that F: is missing in the proposal because I do not
like the looks of it. I remember how to use things by reconstructing how
they work (This means I never learned to tie my shoelaces properly because
the Kindergarten teacher didn't succeed in explaining the mathematics,
the WHY, of this fantastic trick to me). For me, there is no logic in the '{'
proposal because local initializers must be popped off the stack, which
means the logical arrangement of names is first-local-connects-to-TOS.
Floats are on a different stack, so they shouldn't mix with integer locals.
Besides that, I have many more types of locals (complex, double-double,
long integer, strings). I could start using '{', but it wouldn't make
my code portable. ]

In eForth64 I have now added the line:

: PARAMS| ( "names |" -- )
lp@ @ >S
['] (LOCAL) 1 MAKE-LOCALS
S> INIT-LOCALS2, ; IMMEDIATE

... and as soon as the standard is final I will do a SYNONYM (or something)
and create a '{' for those programmers that absolutely need it.

-marcel

Anton Ertl

unread,
Jul 23, 2007, 4:09:11 PM7/23/07
to
m...@iae.nl (Marcel Hendrix) writes:
>an...@mips.complang.tuwien.ac.at (Anton Ertl) writes Re: RfD: Enhanced local variable syntax
>[..]
>[ I do not complain that F: is missing in the proposal because I do not
> like the looks of it.

Would you like to have standard FP locals? Then this is a chance to
get them.

> For me, there is no logic in the '{'
> proposal because local initializers must be popped off the stack, which
> means the logical arrangement of names is first-local-connects-to-TOS.

The logic is that the locals are in the same order as in the standard
stack notation, i.e., TOS is rightmost.

> Floats are on a different stack, so they shouldn't mix with integer locals.

Even if you have a separate FP stack, there is no reason not to mix
the FP locals definitions with the cell locals definitions. Do you
think that there should be apartheid between FPs and cells in the rest
of the code? E.g., don't have any words that perform both integer and
FP operations?

> Besides that, I have many more types of locals (complex, double-double,
> long integer, strings).

You could suggest additional types for the proposal.

> I could start using '{', but it wouldn't make
> my code portable. ]

If you use { and F:, this at least makes your code portable to Gforth,
whereas FLOCALS| is not portable anywhere.

>In eForth64 I have now added the line:
>
>: PARAMS| ( "names |" -- )
> lp@ @ >S
> ['] (LOCAL) 1 MAKE-LOCALS
> S> INIT-LOCALS2, ; IMMEDIATE
>
>... and as soon as the standard is final I will do a SYNONYM (or something)
>and create a '{' for those programmers that absolutely need it.

Will the SYNONYM ensure that the closing word is "}", and that "|" and
"--" do what they should?

Alex McDonald

unread,
Jul 24, 2007, 9:39:37 AM7/24/07
to
On Jul 23, 1:56 pm, an...@mips.complang.tuwien.ac.at (Anton Ertl)
wrote:

> Alex McDonald <b...@rivadpm.com> writes:
> >This RfD and the solutions discussed elsewhere in this thread lead me
> >to conclude that, as LOCALS (both { and LOCALS|) already demand an
> >alternative parse to the traditional Forth parse of find and compile,
> >neither is amenable to further simple expansion due to the
> >increasingly bizarre extensions of syntax being put forward. I would
> >prefer to see a straightforward and clean parse based, as far as is
> >possible, on the current Forth model, and not a parse that /by design/
> >requires alternative meanings or special syntaxes for standard Forth
> >words that are not available outside of LOCALS use (i.e. [ n ] ARR or
> >ARR[ n ] for CREATE ARR n ALLOT; or f: for FLOAT values).
>
> >I realise that Win32Forth is guilty of the use of trailing : for OOP
> >class methods, and [ ] for late binding; that's a feature of NEON/MOPS
> >that I, for one, dislike, as it makes complex something that should be
> >simple.
>
> One difference is that the Neon stuff can occur anywhere in Forth
> code, whereas Stephen's funky buffer syntax can only occur inside a
> locals definition, i.e., between { and }. And there syntax is treated
> non-uniformly already, as all occuring words are defined, except },
> --, and | (and the situation with LOCALS| is similar).

Ye, but adding to the problem inside { } appears to be a mistake. The
funky buffer allocations and the reservation for words ending in : are
adding syntactic sugar to CREATE ALLOT and VALUE/FVALUE and friends.
It's as though we're proposing a completely separate language in its
own local universe that we escape into through { } .

>
> I think the Neon stuff is a mistake, because AFAIK one cannot tick or
> POSTPONE the words ending in ":".
>
> In that sense locals are a mistake irrespective of syntax, because you
> cannot tick or POSTPONE a local. However, since locals are just a
> convenience for stuff that one can also do without too much ado in
> other ways (i.e., using the stacks), this has not turned out to be a
> problem (I never find myself wishing that I could tick or POSTPONE a
> local).
>
> Concerning the { syntax, one can POSTPONE { itself; this is a parsing
> word, so if one cannot also POSTPONE the stuff it parses, that's
> nothing unusual.
>
> > This proposal on a NEON/MOPS system would allow
>
> >: f: { f: seconds | } seconds f: rocket ;
>
> Actually the present proposal does not cover FP locals and does not
> propose "f:". It's surprising that the heaviest user of FP locals I
> know (Marcel Hendrix) has not complained about that, but maybe his
> plan is to stay away from "{" anyway; he seems to enjoy defining the
> locals in the wrong order.

Order notwithstanding, the proposal reserves words terminating in :
for types.

>
> >Three seperate meanings of f: (a word, a float definition and a method
> >invocation respectively). Even on simpler, non-NEON/MOPS systems,
> >there would be two meanings. Best not to repeat that mistake.
>
> However, assuming that we get f: eventually: That's not so unusual,
> and not a problem, so I don't see it as a mistake. E.g., I can also
> write:
>
> : SWAP SWAP ;
>
> and the two occurences of SWAP have different meanings.

The three F:s have quite separate meanings; and syntax, given that two
of them parse. My example is contrived; but reserving /any/ character
in Forth and assigning meaning to it is just not on, imho. It seems
daft to assign semantics to syntax. Win32Forth has already committed
this mistake; and at least your second SWAP SWAPs, and is clear in its
intention.

>
> >I believe { } needs abandoned as a standards proposal, or fixed in its
> >current usage, and some other design should take its place.
>
> Given the present relatively wide acceptance of {, standardizing that
> is probably the best chance we have of getting more featureful locals
> (e.g., FP locals). I don't think there is a realistic chance that
> another syntax will succeed if { fails. And certainly not if no one
> makes a proposal for such an alternative syntax.

I'm not smart enough to do it, although I see it needs to be done.

Don't take it from this a request for a veto. It's right that a simple
majority should suffice to carry an RfD.

Alex McDonald

unread,
Jul 24, 2007, 10:58:08 AM7/24/07
to
On Jul 24, 2:39 pm, Alex McDonald <b...@rivadpm.com> wrote:

>
> Don't take it from this a request for a veto. It's right that a simple
> majority should suffice to carry an RfD.

I meant CfV, not the RfD stages.

--
Regards
Alex McDonald

Elizabeth D Rather

unread,
Jul 24, 2007, 1:57:09 PM7/24/07
to
Alex McDonald wrote:
...

> Don't take it from this a request for a veto. It's right that a simple
> majority should suffice to carry an RfD.

[Accepting your correction that you mean a CfV] No, it's not right.
ANSI and ISO rules all require "consensus", which means far more than a
simple majority.

During the Forth94 process we required all proposals that had more than
2 'no' votes to go back to committee for resolution. Broad consensus is
required to ensure that there really will be widespread support for a
feature or rule and that all viewpoints have been considered. The only
issue on which the Forth94 TC failed to get consensus was locals: we
struggled with them for years, and ended up deadlocked on the issue of
the order in which things were removed from the stack. By one vote we
chose to follow the only existing widespread usage (MacForth) and folks
have been unhappy ever since.

No proposal that doesn't have really broad consensus should be adopted.

Alex McDonald

unread,
Jul 24, 2007, 6:34:08 PM7/24/07
to
> Hawthorne, CA 90250http://www.forth.com

>
> "Forth-based products and Services for real-time
> applications since 1973."
> ==================================================

It's nice you think that my opinion has some standing. But I'm not the
entire Win32Forth community, and I don't stand by proxy for them; it's
just my personal opinion. I'll readily defer to those with greater
knowledge and understanding of the issues.

--
Regards
Alex McDonald

Stephen Pelc

unread,
Jul 24, 2007, 7:07:58 PM7/24/07
to
On Tue, 24 Jul 2007 06:39:37 -0700, Alex McDonald <bl...@rivadpm.com>
wrote:

>> Given the present relatively wide acceptance of {, standardizing that
>> is probably the best chance we have of getting more featureful locals
>> (e.g., FP locals). I don't think there is a realistic chance that
>> another syntax will succeed if { fails. And certainly not if no one
>> makes a proposal for such an alternative syntax.
>
>I'm not smart enough to do it, although I see it needs to be done.
>
>Don't take it from this a request for a veto. It's right that a simple
>majority should suffice to carry an RfD.

I'll read that as CfV.

Given the howls, how about if I split the proposal into two
1) The stuff that covers { a b | c d -- }
2) Extensions in LOCALS EXT EXT or LOCALS PRACTICAL EXT.

This way existing common practice has a chance of formal acceptance,
and discussion of buffers and types can continue for another ten
years.

Stephen


--
Stephen Pelc, steph...@mpeforth.com
MicroProcessor Engineering Ltd - More Real, Less Time
133 Hill Lane, Southampton SO15 5AF, England
tel: +44 (0)23 8063 1441, fax: +44 (0)23 8033 9691
web: http://www.mpeforth.com - free VFX Forth downloads

Alex McDonald

unread,
Jul 25, 2007, 4:26:03 AM7/25/07
to
On Jul 25, 12:07 am, stephen...@mpeforth.com (Stephen Pelc) wrote:
> On Tue, 24 Jul 2007 06:39:37 -0700, Alex McDonald <b...@rivadpm.com>

> wrote:
>
> >> Given the present relatively wide acceptance of {, standardizing that
> >> is probably the best chance we have of getting more featureful locals
> >> (e.g., FP locals). I don't think there is a realistic chance that
> >> another syntax will succeed if { fails. And certainly not if no one
> >> makes a proposal for such an alternative syntax.
>
> >I'm not smart enough to do it, although I see it needs to be done.
>
> >Don't take it from this a request for a veto. It's right that a simple
> >majority should suffice to carry an RfD.
>
> I'll read that as CfV.
>
> Given the howls, how about if I split the proposal into two
> 1) The stuff that covers { a b | c d -- }
> 2) Extensions in LOCALS EXT EXT or LOCALS PRACTICAL EXT.
>
> This way existing common practice has a chance of formal acceptance,
> and discussion of buffers and types can continue for another ten
> years.

Sighs. I didn't mean to extend the discussion out to infinity. Mark me
up for "abstain".

>
> Stephen
>
> --
> Stephen Pelc, stephen...@mpeforth.com


> MicroProcessor Engineering Ltd - More Real, Less Time
> 133 Hill Lane, Southampton SO15 5AF, England
> tel:+44 (0)23 8063 1441, fax: +44 (0)23 8033 9691
> web:http://www.mpeforth.com- free VFX Forth downloads

--
Regards
Alex McDonald

Alex McDonald

unread,
Jul 25, 2007, 6:46:47 AM7/25/07
to
On Jul 11, 5:55 pm, Peter Knaggs <pkna...@bournemouth.ac.uk> wrote:

[snipped]

Given that I complained, here's an alternative;

As per Stephen Pelc's suggestion, standardise { a b | c d -- } syntax.

Now for my thoughts. Here's a local-less word that uses global vals/
vars.

10 value a
variable b 20 b !
: foo ( a b -- )
b !
to a
... ;

Two issues; scope and recursion.

Scope
-----

The global variables have whole program scope, and aren't private to
the word. Locals provide a convenient way of reducing the scope to the
word. Anton has I believe implemented locals to reduce scope even
further, to the block level, but I'm going to ignore that and limit
the discussion to word level scope. Plus, global scope of simple names
is likely to cause problems in included code, where the name is in
danger of being duplicately defined, since there's no include scope in
Forth (in fact, no include in ANS Forth as it stands anyhow).

Recursion
---------

Being global, there is only a single instance of a; the storage for a
is not private to the function.

Suggestion
----------

Create a local scope equivalent of (minimally) VALUE and VARIABLE. The
example above would become

: foo ( a b -- )
[ local-variable b ] b !
[ 0 local-value a ] to a
[ 10 local-value c ]
... ;

or

: foo ( a b -- )
[ local-variable b
0 local-value a
10 local-value c ]
b ! to a
... ;


1. a b and c only have scope in foo.
2. c is local, but is not populated from the stack.
3. Items are moved explicitly from the stack to wherever the local
storage lives.

Alternatively, this (although I've not thought this one through) which
requires variable and value to understand that they are being locally
declared inside : ;

: foo ( a b -- )
[ variable b
0 value a
10 value c ]
b ! to a
... ;

Advantages
----------

1. No special case parsing for { } LOCALS| |
2. Standard compilation techniques
3. Local words follow the structure of the global equivalents
4. No arguments over stack order as with { } and LOCALS| |
5. (possibly) No new words

Downsides
---------

There are bound to be several.

--
Regards
Alex McDonald

Gerry

unread,
Jul 25, 2007, 9:01:56 AM7/25/07
to

This last alternative is very similar to what I've implemented in my
own system and it seems to work well. I've also include constants,
2variable, etc and n sized variables that can be used for buffers,
arrays and so on. Also to get commonality throughout my system the
same words can be used in classes, structures etc. That helps to
reduce the proliferation of new words such as we are currently getting
in Forth 200X e.g. with the structures proposal. A downside is that it
makes the compiler more complex but that is where the complexity ought
to be.

I've extended it to a block level within words as well.

> Advantages
> ----------
>
> 1. No special case parsing for { } LOCALS| |
> 2. Standard compilation techniques
> 3. Local words follow the structure of the global equivalents
> 4. No arguments over stack order as with { } and LOCALS| |
> 5. (possibly) No new words
>
> Downsides
> ---------
>
> There are bound to be several.
>
> --
> Regards
> Alex McDonald


Gerry


Marcel Hendrix

unread,
Jul 25, 2007, 3:38:46 PM7/25/07
to
Alex McDonald <bl...@rivadpm.com> writes Re: RfD: Enhanced local variable syntax
[..]

> : foo ( a b -- )
> [ local-variable b ] b !
> [ 0 local-value a ] to a
> [ 10 local-value c ]
> ... ;

I like the concept, but there are some issues.

1. Note that you are nesting compilation here, which IIRC is expressly
forbidden in the standard.
2. Internally there will have to be branches around the compiled code/headers
(inefficient)
3. Explicit initialization, which is left to the programmer. And it is in
the wrong stack-order :-)
4. Complicated word-smithery needed to explain what is and what is not allowed
inside the brackets.
5. What happens when I do foo foo foo (call the word multiple times, the syntax
suggests that only the first one predictably initializes the locals.)
6. Can I use the value of already defined locals to define the next one(s)?

[ b local-value a ] to a

-marcel

Alex McDonald

unread,
Jul 25, 2007, 5:26:05 PM7/25/07
to
On 25 Jul, 20:38, m...@iae.nl (Marcel Hendrix) wrote:
> Alex McDonald <b...@rivadpm.com> writes Re: RfD: Enhanced local variable syntax

> [..]
>
> > : foo ( a b -- )
> > [ local-variable b ] b !
> > [ 0 local-value a ] to a
> > [ 10 local-value c ]
> > ... ;
>
> I like the concept, but there are some issues.

I suspected as much!

>
> 1. Note that you are nesting compilation here, which IIRC is expressly
> forbidden in the standard.

Not really; there's the issue with LOCALS| | and { } of "declaring"
values with (LOCALS), which on the face of it is nested compilation,
so any Forth that can cope with { a } can also cope with [ variable
a ] as long as variable knows it is being invoked in a local context.
Extending this to other types should be trivial.

> 2. Internally there will have to be branches around the compiled code/headers
> (inefficient)

As per 1; same issue with { }.

> 3. Explicit initialization, which is left to the programmer. And it is in
> the wrong stack-order :-)

:-) indeed. There are other "advantages". LOCALS| | and { }
unconditionally move from the stack to locals storage; this method
allows

: foo ( a b -- ) [ variable a ] if a ! ... else drop ;

of which this

: foo ( a b -- ) if { a -- } ... then ;

is the equivalent (if it's allowed by the RfD; I think so).

> 4. Complicated word-smithery needed to explain what is and what is not allowed
> inside the brackets.

Usual rules, with additions. Anything that can normally be done
between [ ] while compiling a word, as it's interpretation mode; [ ]
aren't overloaded. Add variable, value, and other local-sensitive
defining words to the list.

So

: foo [ variable a 10 ] postpone literal a ! ;

> 5. What happens when I do foo foo foo (call the word multiple times, the syntax
> suggests that only the first one predictably initializes the locals.)

Mot sure what you mean here. As the word's locals have no external
effect, and each invocation should initialise, I can't see that this

: foo { a -- } 10 to a . ;

would be any different to

: foo ( n -- ) drop [ 10 value a ] a . ;

foo foo foo should produce 10 10 10 in both cases. value's code (local
variety, not global) is compiled in the context of foo.

> 6. Can I use the value of already defined locals to define the next one(s)?
>
> [ b local-value a ] to a

That assumes that b is visible in the scope of [ ]; if the rules were
such that b only has scope during compilation of foo, then b would not
be found.

However, if b is in scope during [ ]

: foo [ 10 value b ] b 3 + [ b value a ] a . ;

then foo produces 10, as when [ b value a ] is generated the value of
b is 10; not 13. I can see that being an issue if an optimising
compiler were to change to

: foo [ 13 value b ] [ b value a ] a . ;

>
> -marcel

--
Regards
Alex McDonald

Alex McDonald

unread,
Jul 25, 2007, 5:46:59 PM7/25/07
to

correction:
: foo ( a b -- ) [ 0 value a ] if to a ... else drop then ;

Actually, now I'm wondering what the RfD says about

: foo { a b -- } a [ b ] ... ;

Does the local b get found or not? The same rules apply, so I suspect
the answer should be; no, local variables are either not findable
during interpretation, or the result of executing a local is
ambiguous. b only has valid compilation semantics.

Gerry

unread,
Jul 25, 2007, 6:15:02 PM7/25/07
to
On 25 Jul, 22:26, Alex McDonald <b...@rivadpm.com> wrote:

In my implementation I took the decision that the stack depth had to
remain the same at [ and ], also all variables and values are loaded
from the data stack at run time as in ANS Forth locals as they don't
exist (except as a name) at compile time. So the [ 13 value b ] above
fails to compile as the 13 is left on the stack. I can't remember
offhand whether I had a good reason for this rule about the stack
depth or whether it was an arbitrary decision. I suspect I had a good
reason as the condition is checked.

It doesn't really matter for this discussion but I actually used {...}
instead of [...] as you are suggesting.

Gerry

Anton Ertl

unread,
Jul 26, 2007, 5:30:56 AM7/26/07
to
Alex McDonald <bl...@rivadpm.com> writes:
>Actually, now I'm wondering what the RfD says about
>
>: foo { a b -- } a [ b ] ... ;
>
>Does the local b get found or not?

I don't think it says anything about that. That part should not
change from Forth-94. Now, looking in Chapter 13 of Forth-94, it says:

|An ambiguous condition exists when local is executed while in
|interpretation state.

Testing this on Gforth:

: foo { b } compiled
[ b
:2: Interpreting a compile-only word
[ >>>b<<<


: bar locals| b | compiled
[ b
:5: Interpreting a compile-only word
[ >>>b<<<

Anton Ertl

unread,
Jul 26, 2007, 5:37:02 AM7/26/07
to
Alex McDonald <bl...@rivadpm.com> writes:
>(in fact, no include in ANS Forth as it stands anyhow).

INCLUDE is specified in X:required.

The parsing of { and LOCALS| is not a big issue. See
<http://www.complang.tuwien.ac.at/forth/anslocal.fs> for an
implementation of {.

>2. Standard compilation techniques

Sorry, I don't see that these would be any more standard than for any
other locals syntax.

>4. No arguments over stack order as with { } and LOCALS| |

That's right, one cannot initialize the locals from the stack with
this syntax. Wait, that's also possible with {:

{ | a c -- }

So no advantage for this syntax there, only the disadvantage.

>5. (possibly) No new words

If you add a locals-defining VALUE and VARIABLE, that's still new
words, you have just overloaded them onto existing names, which is a
bad idea, as we have seen several times.

>Downsides
>---------
>
>There are bound to be several.

1) This syntax is incredibly verbose. Consider a simple word like:

: append { addr1 u1 addr2 u2 -- addr u }
addr1 u1 u2 + dup { u } resize throw { addr }
addr2 addr u1 + u2 move
addr u ;

With this syntax this would turn into:

: append ( addr1 u1 addr2 u2 -- addr u )
[ 0 local-value addr1
0 local-value u1
0 local-value addr2
0 local-value u2
0 local-value u
0 local-value addr ]
to u2 to addr2 to u1 to addr1
addr1 u1 u2 + dup to u resize throw to addr
addr2 addr u1 + u2 move
addr u ;

It really hurts to factor words, if every factor becomes such a
monster. By contrast, with { the stack effect description is also
used as locals definition, so defining the locals costs no additional
typing and no additional code lines (which at least have a readability
cost).

2) This syntax does not allow initialization from the run-time stack,
which leads to requiring strings of TOs in backwards order, which is
error-prone (risk of forgetting a TO or getting the order wrong) and
has additional maintainence costs.

Each of these far outweighs the advantages.

Anton Ertl

unread,
Jul 26, 2007, 6:21:04 AM7/26/07
to
Alex McDonald <bl...@rivadpm.com> writes:
>Ye, but adding to the problem inside { } appears to be a mistake. The
>funky buffer allocations and the reservation for words ending in : are
>adding syntactic sugar to CREATE ALLOT and VALUE/FVALUE and friends.
>It's as though we're proposing a completely separate language in its
>own local universe that we escape into through { } .

True. But at least the simple version of that sublanguage that
Stephen will propose now is already well-known to Forth programmers:
It's the same sublanguage as used for stack effect comments.

Hmm, one solution for the problem of dealing with types is to use the
same approach as is taken in stack effect comments: base the types on
the start of the name of the local:

r: float
d ud: double
n u w x addr c-addr: cell
c: char

However, since there are existing implementations where every name is
treated as a cell, this will probably break existing code (one would
have to check how much). Also, I guess that a number of people would
be unhappy with such a Fortran-like approach; Forth has always allowed
free choice of names.

So my approach has been to have some special names that specify the
type of the following local: D: and F: for doubles, and floats
respectively. I think this is not a big deviation from the stack
effect syntax and should be acceptable.

Concerning local buffers, yes, this has little to do with stack
effects syntax, so one might just as well do them outside { } as
inside. But OTOH, there exists an implementation already that does it
inside, so unless there is a significant disadvantage of doing it that
way, we should standardize on it. If you want to do it outside
instead, demonstrate the advantage!

As for variable-flavoured locals instead of value-flavoured locals, I
once thought it useful, so I implemented it in Gforth, but it turns
out that I almost never use it. If we have local buffers, they
subsume variable-flavoured locals. Here's one of the two cases where
I used a variable-flavoured local:

: write-cell { w^ w file-id -- ior }
\ write a cell to the file
w cell file-id write-file ;

>Order notwithstanding, the proposal reserves words terminating in :
>for types.

>> >: f: { f: seconds | } seconds f: rocket ;
...


>> >Three seperate meanings of f: (a word, a float definition and a method
>> >invocation respectively). Even on simpler, non-NEON/MOPS systems,
>> >there would be two meanings. Best not to repeat that mistake.
>>
>> However, assuming that we get f: eventually: That's not so unusual,
>> and not a problem, so I don't see it as a mistake. E.g., I can also
>> write:
>>
>> : SWAP SWAP ;
>>
>> and the two occurences of SWAP have different meanings.
>
>The three F:s have quite separate meanings; and syntax, given that two
>of them parse. My example is contrived; but reserving /any/ character
>in Forth and assigning meaning to it is just not on, imho. It seems
>daft to assign semantics to syntax. Win32Forth has already committed
>this mistake; and at least your second SWAP SWAPs, and is clear in its
>intention.

And the second F: F:s, and is clear in its intention. The third one
is Win32Forth's own fault and has nothing to do with locals, so it's a
red herring.

If you want an example with a parsing word, I can give you that, too:

: [compile] [compile] [compile] ;

Each of the three occurences of "[compile]" has a different meaning,
and the second one parses.

BTW, F: is not a parsing word, { is.

Stephen Pelc

unread,
Jul 26, 2007, 9:52:15 AM7/26/07
to
On Thu, 26 Jul 2007 10:21:04 GMT, an...@mips.complang.tuwien.ac.at
(Anton Ertl) wrote:

>However, since there are existing implementations where every name is
>treated as a cell, this will probably break existing code (one would
>have to check how much). Also, I guess that a number of people would
>be unhappy with such a Fortran-like approach; Forth has always allowed
>free choice of names.
>
>So my approach has been to have some special names that specify the
>type of the following local: D: and F: for doubles, and floats
>respectively. I think this is not a big deviation from the stack
>effect syntax and should be acceptable.
>
>Concerning local buffers, yes, this has little to do with stack
>effects syntax, so one might just as well do them outside { } as
>inside. But OTOH, there exists an implementation already that does it
>inside, so unless there is a significant disadvantage of doing it that
>way, we should standardize on it. If you want to do it outside
>instead, demonstrate the advantage!

Thank you, Anton. Good stuff.

If we have free choice of names, then we must have type indicators.
F: and friends tell the compiler how to process the local value
whose name follows. All that is required for the brace notation base
specification is to state that an ambiguous condition occurs for
names ending in ':'.

MPE's current local buffer notation merely indicates that a buffer
address is returned. To maintain free name choice, we need to
indicate to the compiler that the following name is a buffer of
a certain size. Experience tells us that expressions are essential.
Expressions need a terminator, so let's use ] as before.
So we need a buffer indicator, e.g. b[ ... ] or some such.
All that is required for the brace notation base specification
is to state that an ambiguous condition occurs for names ending
in '['.

Note that making these ambiguous conditions, no existing
implementation is disenfranchised.

MPE notation:
: foo { a b | buff[ const cells ] -- }

New notation:
: foo { a b | b[ const cells ] buff -- }

Naturally, since the MPE notation involves less typing (grin) I
prefer it.

Stephen


--
Stephen Pelc, steph...@mpeforth.com


MicroProcessor Engineering Ltd - More Real, Less Time
133 Hill Lane, Southampton SO15 5AF, England
tel: +44 (0)23 8063 1441, fax: +44 (0)23 8033 9691

Peter Fälth

unread,
Jul 26, 2007, 11:38:18 AM7/26/07
to
On Jul 26, 12:21 pm, an...@mips.complang.tuwien.ac.at (Anton Ertl)
wrote:
In my forth I have the following syntax for local buffers

n lbuffer: name
where n is the number of bytes to reserve. This works very well with
the
stuctures proposal. An example from my sockets implementation shows it

structure: sockaddr
2 chars field: family
2 chars field: port
4 chars field: addr
8 chars field: zero
;structure

: connect-socket ( addr port family sid -- ior )
sockaddr lbuffer: sock
sock sockaddr erase
swap sock family w! \ store AF_INET
swap htons sock port w! \ store port
swap sock addr ! \ store addr
sockaddr sock rot (connect) ; \ connect

I find the local buffer useful when interfacing with Windows or Linux
system calls.
I think this is very simple and when you do not use locals at the same
time
much clearer also.
I seldom use locals, when I do I have a simple syntax. An example
shows it.

: silly ( n n - n )
local a
local b
0 local result
a b + to result
result ;

It gives some more typing but it is easy to see what is done.

regards
Peter Fälth

Ed

unread,
Jul 26, 2007, 11:57:17 AM7/26/07
to

"Stephen Pelc" <steph...@mpeforth.com> wrote in message news:46a8a39c....@192.168.0.50...
> ...

> MPE's current local buffer notation merely indicates that a buffer
> address is returned. To maintain free name choice, we need to
> indicate to the compiler that the following name is a buffer of
> a certain size. Experience tells us that expressions are essential.
> Expressions need a terminator, so let's use ] as before.
> So we need a buffer indicator, e.g. b[ ... ] or some such.
> All that is required for the brace notation base specification
> is to state that an ambiguous condition occurs for names ending
> in '['.
>
> Note that making these ambiguous conditions, no existing
> implementation is disenfranchised.
>
> MPE notation:
> : foo { a b | buff[ const cells ] -- }
>
> New notation:
> : foo { a b | b[ const cells ] buff -- }
>
> Naturally, since the MPE notation involves less typing (grin) I
> prefer it.

For the latter, why not simply: [ const cells ] buff

It's hard to imagine what else [ is likely to be used for
in a locals definition other than for buffers.

Alex McDonald

unread,
Jul 26, 2007, 1:13:31 PM7/26/07
to
On Jul 26, 10:37 am, an...@mips.complang.tuwien.ac.at (Anton Ertl)
wrote:

But it's due to get a lot more complex. There are already 3 parts
parsed by { ; they are -- | and }. Now we have F: (possibly a whole
zoo of trailing:) and trailing[ ].

>
> >2. Standard compilation techniques
>
> Sorry, I don't see that these would be any more standard than for any
> other locals syntax.

In the sense that the problem is reducible to standard parse-compile-
or-execute functionality, should the syntax be chosen to be more Forth-
like.

>
> >4. No arguments over stack order as with { } and LOCALS| |
>
> That's right, one cannot initialize the locals from the stack with
> this syntax. Wait, that's also possible with {:
>
> { | a c -- }
>
> So no advantage for this syntax there, only the disadvantage.

True; for this pass of the suggestion. This is all helping. However,
as I indicated in my original post, my brain isn't big enough for this
and I need more time to think it through.

>
> >5. (possibly) No new words
>
> If you add a locals-defining VALUE and VARIABLE, that's still new
> words, you have just overloaded them onto existing names, which is a
> bad idea, as we have seen several times.

Stephen proposes the same for ] ; it really can't mean "enter
compilation state", can it?

I suppose it's only pleasing if you're used to Fortran. But I have yet
to see an argument that suggests

0 value null
1 value one
2 value 2

or even the monstrous variable where var would do are necessarily
unsuitable because they're verbose. Otherwise there'd have been an RfD
for

vars{ a b c d } vals{ 10 e 20 f 30 g }

(Or perhaps there has been, and I missed it.)

I do accept the point that locals that look like stack effects are
neat and easily read. I'm trying to envisage an alternative that has
the same expressive power but doesn't need parsed because it's a local
language.

>
> 2) This syntax does not allow initialization from the run-time stack,
> which leads to requiring strings of TOs in backwards order, which is
> error-prone (risk of forgetting a TO or getting the order wrong) and
> has additional maintainence costs.

That's a big downside. Thinking cap on.

Alex McDonald

unread,
Jul 26, 2007, 1:15:01 PM7/26/07
to
On Jul 26, 11:21 am, an...@mips.complang.tuwien.ac.at (Anton Ertl)

wrote:
> Alex McDonald <b...@rivadpm.com> writes:

>
> BTW, F: is not a parsing word, { is.

I know, and therein lies my complaint.

Alex McDonald

unread,
Jul 26, 2007, 1:19:51 PM7/26/07
to

How do you handle interpretation state after buff[ , as interpretation
state between buff[ ] will have the ] throw you back into compilation
state, something you presumably don't want to happen?

>
> New notation:
> : foo { a b | b[ const cells ] buff -- }
>
> Naturally, since the MPE notation involves less typing (grin) I
> prefer it.
>
> Stephen
>
> --

> Stephen Pelc, stephen...@mpeforth.com


> MicroProcessor Engineering Ltd - More Real, Less Time
> 133 Hill Lane, Southampton SO15 5AF, England
> tel: +44 (0)23 8063 1441, fax: +44 (0)23 8033 9691

Alex McDonald

unread,
Jul 26, 2007, 1:32:44 PM7/26/07
to

OK, worked it out; a parse evaluate loop until ] then check for a
stack difference of one?

>
>
>
> > New notation:
> > : foo { a b | b[ const cells ] buff -- }
>
> > Naturally, since the MPE notation involves less typing (grin) I
> > prefer it.
>
> > Stephen
>
> > --
> > Stephen Pelc, stephen...@mpeforth.com
> > MicroProcessor Engineering Ltd - More Real, Less Time
> > 133 Hill Lane, Southampton SO15 5AF, England
> > tel:+44 (0)23 8063 1441, fax: +44 (0)23 8033 9691

> > web:http://www.mpeforth.com-free VFX Forth downloads
>
> --
> Regards
> Alex McDonald


Ed

unread,
Jul 26, 2007, 11:39:47 PM7/26/07
to

"Stephen Pelc" <steph...@mpeforth.com> wrote in message news:46a8a39c....@192.168.0.50...
> ...
> MPE's current local buffer notation merely indicates that a buffer
> address is returned. To maintain free name choice, we need to
> indicate to the compiler that the following name is a buffer of
> a certain size. Experience tells us that expressions are essential.
> Expressions need a terminator, so let's use ] as before.
> So we need a buffer indicator, e.g. b[ ... ] or some such.
> All that is required for the brace notation base specification
> is to state that an ambiguous condition occurs for names ending
> in '['.
>
> Note that making these ambiguous conditions, no existing
> implementation is disenfranchised.
>
> MPE notation:
> : foo { a b | buff[ const cells ] -- }
>
> New notation:
> : foo { a b | b[ const cells ] buff -- }
>
> Naturally, since the MPE notation involves less typing (grin) I
> prefer it.

BTW the two notations aren't mutually exclusive, so MPE
could employ both. See below.

If MPE notation isn't needed then BL WORD COUNT
can replace PARSE-NAME. (Name-last parsing avoids
temporal effects which is why forth uses it :)

-----

\ Uses both MPE and 'new notation'

\ dummy for testing
: BUILDLV ( a u +n mode )
CR 2SWAP TYPE SPACE SWAP . . ;

\ Note: BL WORD COUNT will not work
: TOKEN ( -- a u ) PARSE-NAME ;

: LTERM? ( a u -- f )
2DUP S" --" COMPARE >R
S" }" COMPARE R> AND 0= ;

: LSEP? ( a u -- f )
2DUP S" |" COMPARE >R
S" \" COMPARE R> AND 0= ;

: LBSIZE ( -- +n )
POSTPONE [ [CHAR] ] PARSE EVALUATE ] ;

: LB? ( a u -- f )
+ 1 CHARS - C@ [CHAR] [ = ;

: {
1 >R
BEGIN
TOKEN 2DUP LTERM? 0=
WHILE
2DUP LSEP? IF
2DROP R> DROP 0 >R
ELSE
R@ IF
1 CELLS 1
ELSE
2DUP S" [" COMPARE 0= IF
2DROP LBSIZE TOKEN ROT 3
ELSE
2DUP LB? IF
1- LBSIZE 3
ELSE
1 CELLS 2
THEN
THEN
THEN
BUILDLV
THEN
REPEAT
BEGIN
S" }" COMPARE
WHILE
TOKEN
REPEAT
0 0 0 0 BUILDLV
R> DROP ; IMMEDIATE

: TEST1 { a | b c[ 66] [ 77] d e -- f }
CR ." Hello1 " CR ;

TEST1

CR .( swapping c and d ) CR

: TEST2 { a | b [ 77] d c[ 66] e -- f }
CR ." Hello2 " CR ;

TEST2

-----

Anton Ertl

unread,
Jul 27, 2007, 4:55:37 AM7/27/07
to
=?iso-8859-1?B?UGV0ZXIgRuRsdGg=?= <peter...@tin.it> writes:
>On Jul 26, 12:21 pm, an...@mips.complang.tuwien.ac.at (Anton Ertl)
>wrote:
>> Concerning local buffers, yes, this has little to do with stack
>> effects syntax, so one might just as well do them outside { } as
>> inside. But OTOH, there exists an implementation already that does it
>> inside, so unless there is a significant disadvantage of doing it that
>> way, we should standardize on it. If you want to do it outside
>> instead, demonstrate the advantage!
>>
>In my forth I have the following syntax for local buffers
>
> n lbuffer: name
>where n is the number of bytes to reserve.

One significant difference between that and Stephen Pelc's proposal
(apart from th syntax) is that the buffer size is determined at
run-time, which is both an advantage and a disadvantage:

+ The advantage is that one can use that for dynamically sized arrays,
which is occasionally useful.

+ The disadvantage is that the implementation is more complicated, and
without optimization the buffer access even for fixed-size buffers is
slower than if the implementation only had to deal with fixed-size
buffers.

Peter Fälth

unread,
Jul 27, 2007, 5:51:33 AM7/27/07
to
On Jul 27, 10:55 am, an...@mips.complang.tuwien.ac.at (Anton Ertl)
wrote:

> =?iso-8859-1?B?UGV0ZXIgRuRsdGg=?= <peter.fa...@tin.it> writes:
> >On Jul 26, 12:21 pm, an...@mips.complang.tuwien.ac.at (Anton Ertl)
> >wrote:
> >> Concerning local buffers, yes, this has little to do with stack
> >> effects syntax, so one might just as well do them outside { } as
> >> inside. But OTOH, there exists an implementation already that does it
> >> inside, so unless there is a significant disadvantage of doing it that
> >> way, we should standardize on it. If you want to do it outside
> >> instead, demonstrate the advantage!
>
> >In my forth I have the following syntax for local buffers
>
> > n lbuffer: name
> >where n is the number of bytes to reserve.
>
> One significant difference between that and Stephen Pelc's proposal
> (apart from th syntax) is that the buffer size is determined at
> run-time, which is both an advantage and a disadvantage:
>
> + The advantage is that one can use that for dynamically sized arrays,
> which is occasionally useful.
>
> + The disadvantage is that the implementation is more complicated, and
> without optimization the buffer access even for fixed-size buffers is
> slower than if the implementation only had to deal with fixed-size
> buffers.
>
> - anton

My implementation actually requires n to be known at compile time,
either a constant or a number. lbuffer: extracts n from the
previously compiled number, undoes the compilation and allocates
the buffer.

This can be seen from the disassembly

see connect-socket
A48CB0 40783D 92 C80000 5 normal CONNECT-SOCKET

40783D 8D6424F0 lea esp , [esp-10h]
407841 8D0424 lea eax , [esp]
407844 8945FC mov [ebp-4h] , eax
407847 B800000000 mov eax , # 0h
40784C B910000000 mov ecx , # 10h
407851 8B7DFC mov edi , [ebp-4h]
407854 F2 repnz
407855 AA stosb
407856 8D0424 lea eax , [esp]
407859 8B4D00 mov ecx , [ebp]
40785C 66 d16:
40785D 8908 mov [eax] , cx
40785F 8B4504 mov eax , [ebp+4h]
407862 86E0 xchg ah , al
407864 8D0C24 lea ecx , [esp]
407867 83C102 add ecx , # 2h
40786A 66 d16:
40786B 8901 mov [ecx] , ax
40786D 8D0424 lea eax , [esp]
407870 0504000000 add eax , # 4h
407875 8B4D08 mov ecx , [ebp+8h]
407878 8908 mov [eax] , ecx
40787A 8D0424 lea eax , [esp]
40787D 894504 mov [ebp+4h] , eax
407880 C7450810000000 mov dword [ebp+8h] , # 10h
407887 B844177400 mov eax , # 741744h
40788C 8D6D04 lea ebp , [ebp+4h]
40788F E8C7E0FFFF call "0040595B"
407894 8D642410 lea esp , [esp+10h]
407898 C3 ret near
ok

The first instruction allocates the buffer.
doing this dynamically would require some more work as you pointed out

Peter

Stephen Pelc

unread,
Jul 27, 2007, 6:36:08 AM7/27/07
to
On Thu, 26 Jul 2007 10:19:51 -0700, Alex McDonald <bl...@rivadpm.com>
wrote:

>How do you handle interpretation state after buff[ , as interpretation


>state between buff[ ] will have the ] throw you back into compilation
>state, something you presumably don't want to happen?

Since we say nothing about state during execution of { the evaluation
of the text between foo[ ... ] is up to you! See LBSIZE in the
reference implementation.

Stephen


--
Stephen Pelc, steph...@mpeforth.com


MicroProcessor Engineering Ltd - More Real, Less Time
133 Hill Lane, Southampton SO15 5AF, England
tel: +44 (0)23 8063 1441, fax: +44 (0)23 8033 9691

Stephen Pelc

unread,
Jul 27, 2007, 6:47:04 AM7/27/07
to
On Fri, 27 Jul 2007 13:39:47 +1000, "Ed" <nos...@invalid.com> wrote:

>BTW the two notations aren't mutually exclusive, so MPE
>could employ both. See below.

Seriously neat! Taken for the next proposal.

Ed

unread,
Jul 30, 2007, 10:46:22 PM7/30/07
to

"Peter Knaggs" <pkn...@bournemouth.ac.uk> wrote in message news:46950B6A...@bournemouth.ac.uk...
> Stephen Pelc - 7 June 2007
>
> 20070607 Wordsmithing. Corrected reference implementation.
> 20060822 Added explanatory text.
> Corrected reference implementation.
> Updated ambiguous conditions.
>
> ...
> Ambiguous conditions:
> a) The { ... } text extends over more than one line.

Given the max number of local names, buffer expression length,
comment field, variation in source formatting styles - having it
fit on one line is not always practical.

{ ... } should work the same way as does ( ... ) i.e. REFILL
the buffer until } is found. This would also ease inputting
a locals definition from keyboard.

Suggest replace a) with:

a) The buffer expression text extends over more than one line.


0 new messages