Discussion:
Operator overloading?
(too old to reply)
minforth
2024-07-25 14:38:11 UTC
Permalink
Thanks. But it seems this is only the old 16-bit DOS version.
Looking at the Vierte Dimension 2/2024, which arrived this week, I
find another article about the new, 32-bit strongForth, and also the
link
https://www.stephan-becher.de/strongforth3/
Wow!! Thanks for the link. And kudos to Stephan Becher!!

First I'll have to digest this a bit more...
minforth
2024-07-25 14:49:55 UTC
Permalink
DO you mean something like the below? The code stays the
same but it is possible to choose a different type of
variable (from BYTE to arbitrary precision).
Thank you! Yes, something like that.

If I understand correctly, the intelligence is within LET
which decides which operator matches the type of the operands.

I have also dynamic vector and array types. And 24-bit floats..
The other discussion in the automatic differentiation thread
introduces dual fp-numbers, etc. Overall, working with many
different types would explode the number of type-dependent
operators. So it becomes a natural idea to smarten up the
compiler in this respect.
minforth
2024-07-26 08:33:41 UTC
Permalink
Post by minforth
DO you mean something like the below? The code stays the
same but it is possible to choose a different type of
variable (from BYTE to arbitrary precision).
...
0-VALUE GLOCAL t0
LET SQRT(1/3): GLOCAL ti1
LET SQRT(1/3): GLOCAL ti2
...
I gather the (integer) 6 is autoconverted. Why not I as well?
Post by minforth
Thank you! Yes, something like that.
If I understand correctly, the intelligence is within LET
which decides which operator matches the type of the operands.
Can you use global VALUEs (or even VARIABLEs) within LET?
Or does it only work with local types?
mhx
2024-07-26 11:25:35 UTC
Permalink
[..]
Post by minforth
I gather the (integer) 6 is autoconverted. Why not I as well?
The problem is that I must be understood as an integer, not a
float, as it would be by default. It probably works fine without
double[] here. Functions with mixed types are a nuisance.

The '6' will become a float by default and that is just what is
needed.

[..]
Post by minforth
Post by minforth
If I understand correctly, the intelligence is within LET
which decides which operator matches the type of the operands.
LET is the XOPG entry word and converts standard formulas
to Forth with the asked for floating or integer numeric precision.
Post by minforth
Can you use global VALUEs (or even VARIABLEs) within LET?
Or does it only work with local types?
It works with variables, values, and locals of any type. Arrays
of standard & iForth types are also supported.
That it can work with locals is actually the unique feature
here :--)

LET is not written in standard Forth. It is based on
Wil Baden's OPG (Operator Precedence Grammar), but there are
additions so that XOPG can be used as a SPICE expression
evaluator/compiler.

-marcel
minforth
2024-07-26 15:32:37 UTC
Permalink
Post by mhx
LET is not written in standard Forth. It is based on
Wil Baden's OPG (Operator Precedence Grammar), but there are
additions so that XOPG can be used as a SPICE expression
evaluator/compiler.
Okay, thanks! I found OPG here
http://www.wilbaden.com/neil_bawd/opg.txt

Interesting concept. I knew only of Julian Noble's ftran.
Jan Coombs
2024-07-26 11:31:41 UTC
Permalink
On Thu, 25 Jul 2024 07:30:58 +0000
Or has anyone found another way to bundle/overload Forth operators?
Would an (in-development) hardware solution be of any interest?

Jan Coombs
--
Michael Raitza
2024-07-25 08:02:22 UTC
Permalink
I just googled it and it lives here, now:
https://www.stephan-becher.de/strongforth/
Anton Ertl
2024-07-25 12:08:58 UTC
Permalink
Thanks. But it seems this is only the old 16-bit DOS version.
Looking at the Vierte Dimension 2/2024, which arrived this week, I
find another article about the new, 32-bit strongForth, and also the
link

https://www.stephan-becher.de/strongforth3/
I have been looking for the ANS-compatible layer file
mentioned in the discussion.
IMHO and without belittling strongforth's merits, I think
that it went too far and proposed another Forth dialect.
Whether it's too far or not is up to the recipient to decide. But
yes, if you have a single and a double on the stack, say "1 2.", then
in standard Forth you have to use ROT to switch them around, while in
StrongForth you use SWAP.
I am thinking on a much smaller scale i.e. unification of
operators for xVALUEs and xLOCALs. ANS Forth already has
overloaded TO but stops there.
+TO is a common extension.

- 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: https://forth-standard.org/
EuroForth 2024: https://euro.theforth.net
minforth
2024-07-27 12:10:28 UTC
Permalink
Post by Anton Ertl
I am thinking on a much smaller scale i.e. unification of
operators for xVALUEs and xLOCALs. ANS Forth already has
overloaded TO but stops there.
+TO is a common extension.
Certainly. I have some array operations in mind, but they
are not relevant here. The principle is like

: INIT { a }
[[: a ;]] \ read counter
[[: 1 +to a ;]] ; \ increment counter
DEFER count IS count
DEFER read IS read
5 INIT
COUNT COUNT READ -> should give 7

[[: ;]] define closures, but unlike gforth's more flexible
flat closures, they capture simply all upvalues (here local a).

The code compiles unmodified for different types of a.
Incidentally, it compiles now with +TO, but realistically you
can't declare new 'op'TOs for too many different 'op' operators.
Anton Ertl
2024-07-27 15:35:55 UTC
Permalink
Post by minforth
Post by Anton Ertl
I am thinking on a much smaller scale i.e. unification of
operators for xVALUEs and xLOCALs. ANS Forth already has
overloaded TO but stops there.
+TO is a common extension.
Certainly. I have some array operations in mind, but they
are not relevant here. The principle is like
: INIT { a }
[[: a ;]] \ read counter
[[: 1 +to a ;]] ; \ increment counter
DEFER count IS count
DEFER read IS read
5 INIT
COUNT COUNT READ -> should give 7
My guess is that three lines here should be

DEFER count
DEFER read
5 INIT IS count IS read
Post by minforth
[[: ;]] define closures, but unlike gforth's more flexible
flat closures, they capture simply all upvalues (here local a).
Gforth's flag closures can be considered lower-level (they come out of
implementation ideas in the Scheme community) and are easier to
implement, but emulating closures that capture outer locals is more
cumbersome. One other aspect is that in Gforth's closures the
programmer decides whether closures are allocated in the dictionary,
on the locals stack, on the heap, or elsewhere. In the present case
the dictionary seems to be a good place, and one can write this
example as:

: init ( a -- )
align here >r , \ allocate a on the heap
r@ [n:d @ ;] \ read counter
r> [n:d 1 swap +! ;] \ increment counter
;
DEFER count
DEFER read
5 INIT IS count IS read
count count read . \ prints "7 "

INIT uses pure-stack closures [n:d consumes a value (in this exampl,
the address of the cell containing A) from the stack at closure
creation time and pushes it on the stack at closure run-time. Look,
Ma, no locals:-).

However, this does not use value-flavoured stuff, because we have to
pass the address of A around, and then it's easier to use the
variable-flavoured words. However, if you prefer the value-flavoured
words, value-flavoured fields were recently added to Gforth and can be
used to do that:

begin-structure counter
value: counter-val
end-structure
: init ( a -- )
align here >r counter allot
r@ to counter-val
r@ [n:d counter-val ;]
r> [n:d 1 swap +to counter-val ;]
;
DEFER count
DEFER read
5 INIT IS count IS read
count count read . \ prints "7 "

However, you still have to deal with the address explicitly, which
becomes especially obvious in the counter closure.

This raises the question of why you want to use closures for this
task. Why not use one of the object-oriented Forth packages, some of
which support value-flavoured fields (Mini-OOF2 among them AFAIK).
Post by minforth
The code compiles unmodified for different types of a.
Incidentally, it compiles now with +TO, but realistically you
can't declare new 'op'TOs for too many different 'op' operators.
This statement can be read in two different ways. I think there can
be too many, but Stephen Pelc may think otherwise:-).

In any case, if the reason you want value-flavoured stuff is that you
want to be able to change the types, then yes, value-flavoured fields
(in objects or plain structures) are the way to go.

One caveat that we have here is that TO (and, AFAIK in existing
implementations, +TO) have different stack effects for VALUEs,
2VALUEs, and FVALUEs, which means that you usually cannot change the
types between the types that deal with one cell on the stack (VALUE:
CVALUE: WVALUE: LVALUE: etc.) and those that take two cells or a float
value.

- 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: https://forth-standard.org/
EuroForth 2024: https://euro.theforth.net
minforth
2024-07-27 18:16:20 UTC
Permalink
Post by Anton Ertl
Post by minforth
[[: ;]] define closures, but unlike gforth's more flexible
flat closures, they capture simply all upvalues (here local a).
Gforth's flag closures can be considered lower-level (they come out of
implementation ideas in the Scheme community) and are easier to
implement, but emulating closures that capture outer locals is more
cumbersome.
In MF36 quotations already have read/write access to the locals of the
parent function. So closures became a simple by-product through
capturing
the parent's locals stack and injecting it at startup during closure
runtime. When the closure finishes, the captured stack is simply
updated.

I don't know if this would be good enough for a Lisp/Scheme programmer,
but it works for my needs. And look Ma, no garbage collection. :-)
Post by Anton Ertl
One other aspect is that in Gforth's closures the
programmer decides whether closures are allocated in the dictionary,
on the locals stack, on the heap, or elsewhere.
In MF36 it is only the locals stack. AFAIU in other programming
languagues there are closures where the parent function can be seen as
constructor. IOW call the parent function twice and you get different
xts/addresses. From this perspective MF36 closures would perhaps only
qualify as 'half-closures'.
Post by Anton Ertl
This raises the question of why you want to use closures for this
task. Why not use one of the object-oriented Forth packages, some of
which support value-flavoured fields (Mini-OOF2 among them AFAIK).
MF36 VALUEs and LOCALs are already built with method VTs. TO et al
just call the method in the correct method slot. You don't need to
program type-specific TO +TO *TO. For example

4 XTBUFFER: _VZMETHODS Z@ Z! Z+ Z* \ methods table for complex values
: ZVALUE \ ( r: r1 r2 <name> -- ) complex value
_vzmethods _(value) f, f, ;

Similarly for xVALUEs of all other data types, including strings and
matrices.
Ruvim
2024-07-30 19:32:05 UTC
Permalink
Post by minforth
Post by Anton Ertl
Post by minforth
[[: ;]] define closures, but unlike gforth's more flexible
flat closures, they capture simply all upvalues (here local a).
Gforth's flag closures can be considered lower-level (they come out of
implementation ideas in the Scheme community) and are easier to
implement, but emulating closures that capture outer locals is more
cumbersome.
In MF36 quotations already have read/write access to the locals of the
parent function.
I think, the standard quotation (that is defined via "[: ... ;]") shall
return the same xt in different runs in run-time.

For example, the following word "foo":

: foo ( -- xt ) [: bar ;] ;

is a constant, as it always returns the same xt.

Therefore, it's better to throw an exception if an external local
variable is referenced in a standard quotation.


If a local variable can be referenced in a nested definition (and the
funarg problem is solved), it's better to call that definition a
"closure" rather than a "quotation".
Post by minforth
So closures became a simple by-product through capturing
the parent's locals stack and injecting it at startup during closure
runtime. When the closure finishes, the captured stack is simply
updated.
I don't know if this would be good enough for a Lisp/Scheme programmer,
but it works for my needs. And look Ma, no garbage collection. :-)
Post by Anton Ertl
One other aspect is that in Gforth's closures the
programmer decides whether closures are allocated in the dictionary,
on the locals stack, on the heap, or elsewhere.
In MF36 it is only the locals stack. AFAIU in other programming
languagues there are closures where the parent function can be seen as
constructor. IOW call the parent function twice and you get different
xts/addresses. From this perspective MF36 closures would perhaps only
qualify as 'half-closures'.
A related problem is known as the funarg problem [1].

I can guess, the upwards funarg problem is not solved in MF36.

Concerning the downwards funarg problem — is it solved for the cases
when the enclosing function is called recursively (directly or indirectly)?


A dumb testcase:

: t1 ( u xt -- u )
{: k xt :}
k 0= if 0 exit then
k 1- [[: k ;]] dup >r recurse r> execute +
xt if xt execute + then
;
t{ 0 0 t1 -> 0 }t
t{ 1 0 t1 -> 1 }t
t{ 2 0 t1 -> 5 }t
t{ 3 0 t1 -> 11 }t


[1] https://en.wikipedia.org/wiki/Funarg_problem



--
Ruvim
Anton Ertl
2024-08-01 13:35:54 UTC
Permalink
Post by minforth
Post by Anton Ertl
Post by minforth
[[: ;]] define closures, but unlike gforth's more flexible
flat closures, they capture simply all upvalues (here local a).
Gforth's flag closures can be considered lower-level (they come out of
implementation ideas in the Scheme community) and are easier to
implement, but emulating closures that capture outer locals is more
cumbersome.
In MF36 quotations already have read/write access to the locals of the
parent function. So closures became a simple by-product through
capturing
the parent's locals stack and injecting it at startup during closure
runtime. When the closure finishes, the captured stack is simply
updated.
I don't know if this would be good enough for a Lisp/Scheme programmer,
but it works for my needs. And look Ma, no garbage collection. :-)
But then, with

| : INIT { a }
| [[: a ;]] \ read counter
| [[: 1 +to a ;]] ; \ increment counter
| DEFER count IS count
| DEFER read IS read
| 5 INIT
| COUNT COUNT READ -> should give 7

is A not gone after INIT is finished, and COUNT and READ will do ...
interesting things?
Post by minforth
Post by Anton Ertl
One other aspect is that in Gforth's closures the
programmer decides whether closures are allocated in the dictionary,
on the locals stack, on the heap, or elsewhere.
In MF36 it is only the locals stack. AFAIU in other programming
languagues there are closures where the parent function can be seen as
constructor. IOW call the parent function twice and you get different
xts/addresses. From this perspective MF36 closures would perhaps only
qualify as 'half-closures'.
Your description sounds like MF36 can do downwards funargs (like
Pascal), but not upward funargs.
Post by minforth
Post by Anton Ertl
This raises the question of why you want to use closures for this
task. Why not use one of the object-oriented Forth packages, some of
which support value-flavoured fields (Mini-OOF2 among them AFAIK).
MF36 VALUEs and LOCALs are already built with method VTs. TO et al
just call the method in the correct method slot.
Sure, but the point here is how to define an INIT that initializes
some data, and then you can call COUNT and READ on it, possibly with
different INITs for different types. And you don't want to give names
to all the things that are produced by INIT. That sounds like a job
for an object-oriented package.

- 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: https://forth-standard.org/
EuroForth 2024: https://euro.theforth.net
minforth
2024-08-01 16:35:26 UTC
Permalink
Post by Anton Ertl
Post by minforth
I don't know if this would be good enough for a Lisp/Scheme programmer,
but it works for my needs. And look Ma, no garbage collection. :-)
But then, with
| : INIT { a }
| [[: a ;]] \ read counter
| [[: 1 +to a ;]] ; \ increment counter
| DEFER count IS count
| DEFER read IS read
| 5 INIT
| COUNT COUNT READ -> should give 7
is A not gone after INIT is finished, and COUNT and READ will do ...
interesting things?
Of course not. When the compiler encounters the first [[: it lays
down code to capture the contents INIT's locals stack (environment)
when INIT is executed. All subsequent [[: "closures" are just
quotations which inject the captured stack segment into their own
locals stack, and update the captured environment when finished and
before their own locals stack is discarded.

In this way these "closure-flavoured quotations" see an updated A
i.e. shared upvalue, whenever one of them is called again. Execute
INIT a second time and the previously captured environment will be
overwritten.

The code is only a few lines long. I don't know if Pascal does
similar things, or if funarg problems are a show-stopper. And of
course this simple scheme is not OOP, but when it comes quasi for
free and is handy enough for small applications..
a***@spenarnc.xs4all.nl
2024-07-27 20:55:48 UTC
Permalink
Post by Anton Ertl
Post by minforth
Post by Anton Ertl
I am thinking on a much smaller scale i.e. unification of
operators for xVALUEs and xLOCALs. ANS Forth already has
overloaded TO but stops there.
+TO is a common extension.
Certainly. I have some array operations in mind, but they
are not relevant here. The principle is like
: INIT { a }
[[: a ;]] \ read counter
[[: 1 +to a ;]] ; \ increment counter
DEFER count IS count
DEFER read IS read
5 INIT
COUNT COUNT READ -> should give 7
My guess is that three lines here should be
DEFER count
DEFER read
5 INIT IS count IS read
Post by minforth
[[: ;]] define closures, but unlike gforth's more flexible
flat closures, they capture simply all upvalues (here local a).
Gforth's flag closures can be considered lower-level (they come out of
implementation ideas in the Scheme community) and are easier to
implement, but emulating closures that capture outer locals is more
cumbersome. One other aspect is that in Gforth's closures the
programmer decides whether closures are allocated in the dictionary,
on the locals stack, on the heap, or elsewhere. In the present case
the dictionary seems to be a good place, and one can write this
: init ( a -- )
align here >r , \ allocate a on the heap
r> [n:d 1 swap +! ;] \ increment counter
;
DEFER count
DEFER read
5 INIT IS count IS read
count count read . \ prints "7 "
INIT uses pure-stack closures [n:d consumes a value (in this exampl,
the address of the cell containing A) from the stack at closure
creation time and pushes it on the stack at closure run-time. Look,
Ma, no locals:-).
However, this does not use value-flavoured stuff, because we have to
pass the address of A around, and then it's easier to use the
variable-flavoured words. However, if you prefer the value-flavoured
words, value-flavoured fields were recently added to Gforth and can be
begin-structure counter
value: counter-val
end-structure
: init ( a -- )
align here >r counter allot
r> [n:d 1 swap +to counter-val ;]
;
DEFER count
DEFER read
5 INIT IS count IS read
count count read . \ prints "7 "
However, you still have to deal with the address explicitly, which
becomes especially obvious in the counter closure.
This raises the question of why you want to use closures for this
task. Why not use one of the object-oriented Forth packages, some of
which support value-flavoured fields (Mini-OOF2 among them AFAIK).
Post by minforth
The code compiles unmodified for different types of a.
Incidentally, it compiles now with +TO, but realistically you
can't declare new 'op'TOs for too many different 'op' operators.
This statement can be read in two different ways. I think there can
be too many, but Stephen Pelc may think otherwise:-).
Also Marcel Hendrix thinks that. I count a dozen opTO's in tforth
and iforth.
Personnaly I hate TO and +TO, but if you decide to use them, you
could as well go all the way.
Post by Anton Ertl
- anton
Groetjes Albert
--
Don't praise the day before the evening. One swallow doesn't make spring.
You must not say "hey" before you have crossed the bridge. Don't sell the
hide of the bear until you shot it. Better one bird in the hand than ten in
the air. First gain is a cat purring. - the Wise from Antrim -
minforth
2024-07-29 07:22:18 UTC
Permalink
Post by a***@spenarnc.xs4all.nl
Personnaly I hate TO and +TO, but if you decide to use them, you
could as well go all the way.
I know what you mean. For global values I follow you.

For locals it becomes annoying IMO to readjust operators in the
code body to changed data types. Contrived dumb example

\ for single item
: TT { f: dat -- res } <- local type: f:
pi dat f* ; <- suitable operator: f*
\ for vector/matrix
: TT { m: dat -- res } <- local type: m:
pi dat m.* ; <- suitable operator: m.*

With TO
: TT { <type>: dat -- res } <- replace <type> with suitable type id
pi *to dat dat ; <- no adjustment required, no errors

While this example may look dumb, things look different when you
have many non-trivial words.
minforth
2024-07-25 08:21:12 UTC
Permalink
Thanks. But it seems this is only the old 16-bit DOS version.
I have been looking for the ANS-compatible layer file
mentioned in the discussion.

IMHO and without belittling strongforth's merits, I think
that it went too far and proposed another Forth dialect.

I am thinking on a much smaller scale i.e. unification of
operators for xVALUEs and xLOCALs. ANS Forth already has
overloaded TO but stops there.
mhx
2024-07-25 09:06:03 UTC
Permalink
DO you mean something like the below? The code stays the
same but it is possible to choose a different type of
variable (from BYTE to arbitrary precision).

-marcel

(*
* LANGUAGE : ANS Forth with extensions
* PROJECT : Forth Environments
* DESCRIPTION : Hairy floating-point issues
* CATEGORY : Demonstration, using of OPG (see also archimedes.frt)
* AUTHOR : Marcel Hendrix
* LAST CHANGE : August 4, 2012, Marcel Hendrix
* LAST CHANGE : Saturday, December 22, 2012, 22:46, Marcel Hendrix
*)


NEEDS -xopg

REVISION -archimedes "--- Archimedes' PI Version 2.01 ---"

PRIVATES

DOC
(*
Round-off error can affect the convergence and accuracy of iterative
numerical procedures. As an example, Archimedes approximated PI by
calculating the perimeters of polygons inscribing and circumscribing
a circle, starting with hexagons, and successively doubling the number
of sides. As noted above, computations may be rearranged in a way that
is mathematically equivalent but less prone to error (numerical
analysis).
Two forms of the recurrence formula for the circumscribed polygon are:

t0 = 1 / sqrt(3)

sqrt(ti^2+1) - 1
first form: ti+1 = ----------------
ti

ti
second form: ti+1 = ----------------
sqrt(ti^2+1) + 1

*)
ENDDOC

\ .xfloat.p
.arbitrary.p

: #SHOW ( -- )
0-VALUE GLOCAL t0
PI-VALUE GLOCAL pi
LET SQRT(1/3): GLOCAL ti1
LET SQRT(1/3): GLOCAL ti2

#129 0 DO
I #15 AND
0= IF
CR I 3 .R SPACE
LET t0=6*ti1*2^DOUBLE[I]:
LET (t0-PI,t0): .PRINT ." (err=" .PRINT ." )"
CR 4 SPACES
LET t0=6*ti2*2^DOUBLE[I]:
LET (t0-PI,t0): .PRINT ." (err=" .PRINT ." )"
ENDIF
LET ti1 = (SQRT(ti1*ti1+1)-1)/ti1:
LET ti2 = ti2/(SQRT(ti2*ti2+1)+1):
LOOP ;

:ABOUT CR ." Try: #SHOW -- approximates PI using two different
algorithms."
CR ." PI = " PI-VALUE .PRINT ;

.ABOUT -archimedes CR
DEPRIVE

(* End of Source *)
dxf
2024-07-25 07:42:00 UTC
Permalink
Unfortunately, the website for downloading strongforth.f
is no longer available.
https://www.stephan-becher.de/strongforth/
Ruvim
2024-07-30 10:30:52 UTC
Permalink
Post by minforth
Thanks. But it seems this is only the old 16-bit DOS version.
Looking at the Vierte Dimension 2/2024, which arrived this week, I
find another article about the new, 32-bit strongForth, and also the
link
https://www.stephan-becher.de/strongforth3/
Wow!! Thanks for the link. And kudos to Stephan Becher!!
First I'll have to digest this a bit more...
An older StrongForth.f version 1.2 (originally released on 2009-02-03)
is also available at
https://www.arestlessmind.org/2013/08/17/
https://www.arestlessmind.org/2009/02/03/strongforth.f-1.2.tar.bz2


--
Ruvim
Stephen Pelc
2024-07-30 15:16:28 UTC
Permalink
Forth has a lot of ‘redundant’ operators for e.g. arithmetic or
stack operations, depending on the data type.
There was once an interesting approach for a type-bound layer
https://comp.lang.forth.narkive.com/rexLEBd0/strongforth-implemented-in-ans-forth
Unfortunately, the website for downloading strongforth.f
is no longer available.
Or has anyone found another way to bundle/overload Forth operators?
The standard suggests/specifies that operators such as TO behave as if
they parse. Ignore that for the moment and define

variable operator

: to 1 operator ! ; immediate

A child of VALUE is probably an immediate word that inspects OPERATOR
and compiles the fetch action if 0 or the store action if 1. This scheme can
be extended to support a wide range of operators, such as +TO INCR DECR
and so on. MPE has used this scheme for several decades with no tech
support issues. If you really want to to be fussy and avoid the use of the
"as if" rule for parsing, you can do something like (untested) the below
for TO. But why bother?

: to
1 operator ! ' execute
; immediate

Stephen
--
Stephen Pelc, ***@vfxforth.com
MicroProcessor Engineering, Ltd. - More Real, Less Time
133 Hill Lane, Southampton SO15 5AF, England
tel: +44 (0)78 0390 3612, +34 649 662 974
http://www.mpeforth.com
MPE website
http://www.vfxforth.com/downloads/VfxCommunity/
downloads
minforth
2024-07-30 18:55:55 UTC
Permalink
Post by Stephen Pelc
The standard suggests/specifies that operators such as TO behave as if
they parse. Ignore that for the moment and define
variable operator
: to 1 operator ! ; immediate
A child of VALUE is probably an immediate word that inspects OPERATOR
and compiles the fetch action if 0 or the store action if 1. This scheme can
be extended to support a wide range of operators, such as +TO INCR DECR
and so on. MPE has used this scheme for several decades with no tech
support issues. If you really want to to be fussy and avoid the use of the
"as if" rule for parsing, you can do something like (untested) the below
for TO. But why bother?
: to
1 operator ! ' execute
; immediate
Thank you. So instead of wasting time on parsing during compilation- or
interpretation time, the runtime action of an xVALUE (even when
compiled)
involves to walk a type-specific operator chain (a large CASE construct
in VFX). This makes them slower when compiled, but why not.
Stephen Pelc
2024-07-30 19:44:40 UTC
Permalink
Post by minforth
Post by Stephen Pelc
The standard suggests/specifies that operators such as TO behave as if
they parse. Ignore that for the moment and define
variable operator
: to 1 operator ! ; immediate
A child of VALUE is probably an immediate word that inspects OPERATOR
and compiles the fetch action if 0 or the store action if 1. This scheme can
be extended to support a wide range of operators, such as +TO INCR DECR
and so on. MPE has used this scheme for several decades with no tech
support issues. If you really want to to be fussy and avoid the use of the
"as if" rule for parsing, you can do something like (untested) the below
for TO. But why bother?
: to
1 operator ! ' execute
; immediate
Thank you. So instead of wasting time on parsing during compilation- or
interpretation time, the runtime action of an xVALUE (even when
compiled)
involves to walk a type-specific operator chain (a large CASE construct
in VFX). This makes them slower when compiled, but why not.
The CASE statements are walked at compile time and so can produce
fully optimised code. Just download a VFX Forth, read the source code,
and disassemble the results.

Stephen
--
Stephen Pelc, ***@vfxforth.com
MicroProcessor Engineering, Ltd. - More Real, Less Time
133 Hill Lane, Southampton SO15 5AF, England
tel: +44 (0)78 0390 3612, +34 649 662 974
http://www.mpeforth.com
MPE website
http://www.vfxforth.com/downloads/VfxCommunity/
downloads
Anton Ertl
2024-08-01 12:35:32 UTC
Permalink
Post by minforth
the runtime action of an xVALUE (even when
compiled)
involves to walk a type-specific operator chain (a large CASE construct
in VFX).
Instead of a CASE, an alternative is to have a table that is indexted
by the number of the operator. This is used in Gforth. And AFAICS,
we managed to get rid of the OPERATOR variable. Instead, the operator
passes the index on the stack to "(to)" or "(to),", which does the
table lookup and then runs ("(to)") or compiles ("(to),") the
appropriate method.

Gforth uses a parsing approach, which allows passing the index on the
stack instead of through a variable and provides better error
checking. E.g., for TO the implementation is:

: int-to ( "name" x -- ) \ gforth-internal
\g Interpretation semantics of \code{to}.
record-name 0 (') (to) ;

: comp-to ( compilation "name" -- ; run-time x -- ) \ gforth-internal
\g Compilation semantics of \code{to}.
record-name 0 (') (to), ; immediate restrict

' int-to ' comp-to interpret/compile: TO ( value "name" -- ) \ core-ext
\g changes the value of @var{name} to @var{value}

Here 0 is the index into the table. RECORD-NAME just records
meta-information for Gforth's development environment. For (TO) the
help text is:

'(to)' ( val operation xt -- ) gforth-1.0 "paren-to"
xt is of a value like word name. Stores val 'to' name. operation
selects between 'to' (0), '+to' (1), 'addr' (2), 'action-of' (3) and
'is' (4).

(TO) is a method of the word specified by xt, so different words have
different implementations, but they are basically to look up the
appropriate table entry end execute it. E.g., for a word defined with
VALUE, the table entry with index 0 (i.e., TO) of the word is the xt
of "!", and (TO) performs

( val xt ) >body !

The thing about "(TO)," means that when compiling this stuff, the
whole table lookup is performed at compile time, and what is compiled
is equivalent to

( val ) [ xt >body ] literal !

- 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: https://forth-standard.org/
EuroForth 2024: https://euro.theforth.net
a***@spenarnc.xs4all.nl
2024-07-31 07:47:52 UTC
Permalink
Forth has a lot of ‘redundant’ operators for e.g. arithmetic or
stack operations, depending on the data type.
There was once an interesting approach for a type-bound layer
https://comp.lang.forth.narkive.com/rexLEBd0/strongforth-implemented-in-ans-forth
Unfortunately, the website for downloading strongforth.f
is no longer available.
Or has anyone found another way to bundle/overload Forth operators?
The standard suggests/specifies that operators such as TO behave as if
they parse. Ignore that for the moment and define
There was a discussion about that before. The stipulaton is null and void.
It was established that there was no way a compliant program could
decide either way. It could be as well eliminated.

<SNIP>
Stephen
Groetjes Albert
--
Don't praise the day before the evening. One swallow doesn't make spring.
You must not say "hey" before you have crossed the bridge. Don't sell the
hide of the bear until you shot it. Better one bird in the hand than ten in
the air. First gain is a cat purring. - the Wise from Antrim -
Gerry Jackson
2024-07-31 09:08:43 UTC
Permalink
Post by a***@spenarnc.xs4all.nl
Forth has a lot of ‘redundant’ operators for e.g. arithmetic or
stack operations, depending on the data type.
There was once an interesting approach for a type-bound layer
https://comp.lang.forth.narkive.com/rexLEBd0/strongforth-implemented-in-ans-forth
Unfortunately, the website for downloading strongforth.f
is no longer available.
Or has anyone found another way to bundle/overload Forth operators?
The standard suggests/specifies that operators such as TO behave as if
they parse. Ignore that for the moment and define
There was a discussion about that before. The stipulaton is null and void.
It was established that there was no way a compliant program could
decide either way. It could be as well eliminated.
Here's a program that demonstrates a non-parsing TO:

VFX Forth 64 for Windows x64
© MicroProcessor Engineering Ltd, 1998-2023

Version: 5.43 [build 4238]
Build date: 9 November 2023

Free dictionary = 6731782 bytes [6574kb]

111 value x x . 111 ok
222 to cr .( Does TO parse? ) x x 222 = [if] .( No it doesn't!) [then]
Does TO parse? No it doesn't! ok

Using a flag means that x could be on another line or even in another file.

You could argue that it's not a standard program because it contains a
deliberate ambiguous condition so a parsing TO would fail in some way
but it does demonstrate non-compliant behaviour.

Whether it matters is another matter.
--
Gerry
mhx
2024-07-31 09:41:23 UTC
Permalink
On Wed, 31 Jul 2024 9:08:43 +0000, Gerry Jackson wrote:
[..]
Post by Gerry Jackson
111 value x x . 111 ok
222 to cr .( Does TO parse? ) x x 222 = [if] .( No it doesn't!) [then]
Does TO parse? No it doesn't! ok
[..]

As does iForth.
Post by Gerry Jackson
You could argue that it's not a standard program because it contains a
deliberate ambiguous condition so a parsing TO would fail in some way
but it does demonstrate non-compliant behaviour.
222 TO cr

should (I hope!) produce an exception (unless CR is redefined),
so this *definitely* fails and doesn't even finish the test.

I'm not sure that you can use a buggy program to test for an ambiguous
condition (looks like a top job for an eager lawyer). It would be
much better if the anomaly can be shown with a valid program. What's
the damage when a intentionally erroneous piece of code fails?
Also note that this program's output is correct on Vfx and fails with
an exception on compliant Forths :--)

-marcel
minforth
2024-07-31 10:31:29 UTC
Permalink
1 value fv
222 to cr
fv

looks weird but probably works with a non-parsing TO i.e.
store 222 in fv.

TO stores an id as a message in a global variable which is
queried and reset by the next value.

It's a bit like in the old message-object vs object-message
discussion. Both have pros and cons.
mhx
2024-07-31 13:15:55 UTC
Permalink
Post by minforth
1 value fv
222 to cr
fv
looks weird but probably works with a non-parsing TO i.e.
store 222 in fv.
TO stores an id as a message in a global variable which is
queried and reset by the next value.
It's a bit like in the old message-object vs object-message
discussion. Both have pros and cons.
The behavior makes some code a bit more "readable", e.g.,
when using TO-arrays ( stockprice here):

55e TO (( 5 )) stockprice

However, it could be that the index calculation uses
VALUEs too (very visibly here),

5 value ix
55 (( ix )) stockprice

and then it quickly becomes far less pretty. In FysForth
they let (( and )) stack/unstack the VALUE selector message.

In iForth I have never used (( )) or value arrays and never
missed them.

-marcel
mhx
2024-07-31 13:18:41 UTC
Permalink
On Wed, 31 Jul 2024 13:15:55 +0000, mhx wrote:

Too many errors :-(
Post by mhx
5 value ix
55 (( ix )) stockprice
should be

5 value ix
55e TO (( ix )) stockprice

-marcel
Ruvim
2024-07-31 16:14:51 UTC
Permalink
Post by mhx
[..]
111 value x x . 111  ok
222 to cr .( Does TO parse? ) x x 222 = [if] .( No it doesn't!) [then]
Does TO parse? No it doesn't! ok
[..]
As does iForth.
You could argue that it's not a standard program because it contains a
deliberate ambiguous condition so a parsing TO would fail in some way
but it does demonstrate non-compliant behaviour.
 222 TO cr
should (I hope!) produce an exception (unless CR is redefined),
so this *definitely* fails and doesn't even finish the test.
I'm not sure that you can use a buggy program to test for an ambiguous
condition (looks like a top job for an eager lawyer). It would be
much better if the anomaly can be shown with a valid program.
When we want to apply a parsing word to a calculated string, we can use
"execute-parsing" (that can be defined in a standard way [1]). For a not
parsing "to", this standard-compliant method will fail.


A testcase:

: apply-compiling(to) ( sd.name -- )
[: postpone to ;] execute-parsing
;

t{ 0 value x -> }t
t{ : t1 1 [ s" x" apply-compiling(to) ] ; -> }t
t{ x t1 x -> 0 1 }t



NB: "postpone" can be defined in a standard way via "find-name" so that
is apples to "to" [2].

[1] <https://theforth.net/package/compat/current-view/execute-parsing.fs>
[2]
<https://github.com/ForthHub/discussion/discussions/103#user-content-solution>


--
Ruvim
Anton Ertl
2024-07-31 17:33:44 UTC
Permalink
Post by Ruvim
: apply-compiling(to) ( sd.name -- )
[: postpone to ;] execute-parsing
;
The standard says (in 6.2.2295):

|An ambiguous condition exists if any of POSTPONE, [COMPILE], ' or [']
|are applied to TO.
Post by Ruvim
NB: "postpone" can be defined in a standard way via "find-name" so that
is apples to "to" [2].
But FIND-NAME is not in Forth-2012. Maybe those who like this kind of
TO implementation will make a proposal that means that you cannot
POSTPONE TO with a user-defined POSTPONE. Note that FIND and
SEARCH-WORDLIST are alreading in Forth-94, and TRAVERSE-WORDLIST is in
Forth-2012.

- 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: https://forth-standard.org/
EuroForth 2024: https://euro.theforth.net
Ruvim
2024-08-01 00:21:30 UTC
Permalink
Post by Anton Ertl
Post by Ruvim
: apply-compiling(to) ( sd.name -- )
[: postpone to ;] execute-parsing
;
|An ambiguous condition exists if any of POSTPONE, [COMPILE], ' or [']
|are applied to TO.
Yes, that is why I added the note below.
Post by Anton Ertl
Post by Ruvim
NB: "postpone" can be defined in a standard way via "find-name" so that
is apples to "to" [2].
But FIND-NAME is not in Forth-2012.
Yes. But "find-name" has already been accepted, and, anyway, it can be
implemented via "get-order" and "traverse-wordlist".
Post by Anton Ertl
Maybe those who like this kind of
TO implementation will make a proposal that means that you cannot
POSTPONE TO with a user-defined POSTPONE.
How? Disallow obtaining the name token for "to"? That's a very weak
approach.


It seems, it is possible to test whether "to" is parsing, and if not,
redefine it to provide a parsing "to" in a standard system.

I came up with the following test:

0 value _v1 immediate
0 value _v2

: test(to)
1 1
[ 1 ] to _v1 _v2 [ ( 1 | 1 0 ) ?dup 2drop ]
( 1 | 1 0 ) ?dup 2drop
;
test(to) _v2 [if]
.( ["to" is not a parsing word] )
[else]
.( ["to" is a parsing word] )
[then]


Suddenly, compilation of "test(to)" failed in VfxForth, version
VFX Forth 64 5.43 [build 0199] 2023-11-09 for Linux x64

So, either this "test(to)" or VfxForth is not standard compliant.



I changed "test(to)" to make it compilable in VfxForth:

: ndrop ( i*x u.i -- ) 0 ?do drop loop ;

2 value _v1 immediate
0 value _v2

: test(to) ( -- )
depth >r 1
[ 0 1 ] to _v1 _v2 [ ( 0 | 0 1 | 0 1 2 ) ndrop ]
( | 1 | 1 0 ) depth r> - ndrop
;

\ in this point _v1 and _v2 shall be unchanged,
\ but _v1 is changed in VfxForth
_v1 2 <> [if]
.( [error, _v1 is changed during compilation] )
[then]
_v2 0 <> [if]
.( [error, _v2 is changed during compilation] )
[then]


\ Check what variable is changed by "test(to)"
0 to _v1
0 to _v2
test(to)

_v1 [if]
.( ["to" is a parsing word] )
[else]
_v2 [if]
.( ["to" is not a parsing word] )
[else] \ neither _v1 nor _v2 is changed
.( ["to" is implemented incorrectly] )
[then] [then]


In this test, VfxForth falls into third case, ["to" is implemented
incorrectly].


I redefined "to" in VfxForth as following:

: to ( "ccc<name>" -- ) ( run-time: x -- )
' ['] to ( xt.argument xt.to )
state @ if compile, compile, else execute execute then
; immediate


And it did not change anything in the above tests!

It looks like "compile," in VfxForth still violates the standard, having
unspecified detectable side effects.
Post by Anton Ertl
Note that FIND and SEARCH-WORDLIST are alreading in Forth-94,
and TRAVERSE-WORDLIST is in Forth-2012.
As well as "name>compile" (to define "postpone").


Regarding "find" — it's possible to use "find" to implement "postpone"
only if "find" is implemented in such a way that the interpreter loop
from a single-xt+immediacy-flag system correctly works.

For example, the following "interpret":

: tt-xt ( i*x xt -- j*x )
state @ if compile, else execute then
;
: tt-word ( i*x xt flag.special -- j*x )
if execute exit then tt-xt
;
: interpret ( i*x -- j*x )
begin
bl word find dup if 1 =
tt-word
else drop count dup if \ try to recognize a number
\ ...
-13 throw
else 2drop exit then then
again
;



--
Ruvim
Anton Ertl
2024-08-01 10:07:30 UTC
Permalink
Post by Ruvim
Post by Anton Ertl
Maybe those who like this kind of
TO implementation will make a proposal that means that you cannot
POSTPONE TO with a user-defined POSTPONE.
How?
That's up to those to work out who would benefit from such a
restriction. The alternative (which may require less work) is to
implement TO in a way that makes such a restriction unnecessary (i.e.,
such that POSTPONE TO works even with a user-defined and maybe also
the system-defined POSTPONE).
Post by Ruvim
Disallow obtaining the name token for "to"? That's a very weak
approach.
That appears to be overly blunt to me and would be unlikely to gain my
support.
Post by Ruvim
It seems, it is possible to test whether "to" is parsing, and if not,
redefine it to provide a parsing "to" in a standard system.
0 value _v1 immediate
0 value _v2
: test(to)
1 1
[ 1 ] to _v1 _v2 [ ( 1 | 1 0 ) ?dup 2drop ]
( 1 | 1 0 ) ?dup 2drop
;
test(to) _v2 [if]
.( ["to" is not a parsing word] )
[else]
.( ["to" is a parsing word] )
[then]
This is clever. Given that your test uses only Forth-94 features,
already Forth-94 can see the difference between parsing and
non-parsing TO.
Post by Ruvim
Suddenly, compilation of "test(to)" failed in VfxForth, version
VFX Forth 64 5.43 [build 0199] 2023-11-09 for Linux x64
So, either this "test(to)" or VfxForth is not standard compliant.
I see nothing here that makes TEST(TO) non-standard. One can condense
the case where VFX fails into:

0 value _v1 immediate
: test-to 1 to _v1 ;

VFX Forth 64 5.43 [build 0199] reacts with:

Err# -4 ERR: Data stack underflow.
-> : test-to 1 to _v1 ;
^

Let's see how your test works for the original flag-setting TO
(without optimizations):

variable to-state false to-state !
: to true to-state ! ;
: value
create ,
does>
to-state @ if
! false to-state !
else
@
then ;

Your test indeed outputs "["to" is not a parsing word]".

- 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: https://forth-standard.org/
EuroForth 2024: https://euro.theforth.net
Ruvim
2024-08-02 13:32:35 UTC
Permalink
Post by Anton Ertl
Post by Ruvim
Post by Anton Ertl
Maybe those who like this kind of
TO implementation will make a proposal that means that you cannot
POSTPONE TO with a user-defined POSTPONE.
How?
That's up to those to work out who would benefit from such a
restriction.
The alternative (which may require less work) is to
implement TO in a way that makes such a restriction unnecessary (i.e.,
such that POSTPONE TO works even with a user-defined and maybe also
the system-defined POSTPONE).
It is better to implement "to" as a parsing word.

Because another disadvantage of a not parsing "to" (beside the problem
with "execute-parsing") is that such "to" cannot be used to implement
the Forth text interpreter loop itself. Otherwise, "to" will not work
when it's encountered by this text interpreter in interpretation state
(in some implementations for "to", at least).

A plausible implementation, for example:

0 0 2value current-lexeme

: ?found ( 0 -- _ | x -- x )
dup if exit then
-13 throw" unrecognized: {current-lexeme}"
\ NB: string interpolation is employed
;
: translate-lexeme ( i*x sd -- j*x )
2dup to current-lexeme
perceive ?found ( ut xt.tt ) execute
;
: interpret
begin parse-lexeme dup while translate-lexeme repeat 2drop
;

interpret 0 value x 1 to x x .

\ if "to" is not a parsing word and implemented
\ in the approach (2) below,
\ this line prints 0, but it shall print 1
Post by Anton Ertl
Post by Ruvim
Disallow obtaining the name token for "to"? That's a very weak
approach.
That appears to be overly blunt to me and would be unlikely to gain my
support.
Post by Ruvim
It seems, it is possible to test whether "to" is parsing, and if not,
redefine it to provide a parsing "to" in a standard system.
0 value _v1 immediate
0 value _v2
: test(to)
1 1
[ 1 ] to _v1 _v2 [ ( 1 | 1 0 ) ?dup 2drop ]
( 1 | 1 0 ) ?dup 2drop
;
test(to) _v2 [if]
.( ["to" is not a parsing word] )
[else]
.( ["to" is a parsing word] )
[then]
This is clever. Given that your test uses only Forth-94 features,
already Forth-94 can see the difference between parsing and
non-parsing TO.
Then, can we conclude, that "to" *shall* be implemented as a parsing word?

The standard normatively specifies that "to" does parsing.

The rationale says that "Some implementations of TO do not parse", but
this is not a normative part. In the normative part an ambiguous
condition is declared:
| An ambiguous condition exists if any of
| POSTPONE, [COMPILE], ' or ['] are applied to TO.
*** (1)

The intent of this ambiguous condition in Forth-94 was probably to
ensure that a standard program will not be able to detect whether "to"
does parsing (and thus to allow different implementations).

Now it is obvious that this ambiguous condition does not prevent a
standard program to detect whether "to" does parsing. This clearly means
that implementations of "to" that do not parse *are not allowed*.

Moreover, in Forth-2012, a standard program can define an equivalent of
"postpone" and Tick (both "'" and "[']") and apply them to "to".

Therefore, the ambiguous condition (1) can be removed without any
consequences for standard programs and systems.
Post by Anton Ertl
Post by Ruvim
Suddenly, compilation of "test(to)" failed in VfxForth, version
VFX Forth 64 5.43 [build 0199] 2023-11-09 for Linux x64
So, either this "test(to)" or VfxForth is not standard compliant.
I see nothing here that makes TEST(TO) non-standard. One can condense
0 value _v1 immediate
: test-to 1 to _v1 ;
Err# -4 ERR: Data stack underflow.
-> : test-to 1 to _v1 ;
^
Let's see how your test works for the original flag-setting TO
*** (2)
Post by Anton Ertl
variable to-state false to-state !
: to true to-state ! ;
: value
create ,
does>
! false to-state !
else
@
then ;
Your test indeed outputs "["to" is not a parsing word]".
--
Ruvim
minforth
2024-08-03 09:55:18 UTC
Permalink
TO is not part of the CORE wordset, and the standard has no
normative parts - only compliance requirements, which do not
include TO. See standard section 5.

So language lawyering seems rather insubstantial here.

Don't nail your own foot to the floor...
Ruvim
2024-08-03 14:28:46 UTC
Permalink
Post by minforth
TO is not part of the CORE wordset,
Yes, and what does it change?

A standard Forth system shall either provide standard-compliant "TO" or
not provide one at all.
Post by minforth
and the standard has no normative parts
- only compliance requirements,
Changing the wording/terminology does not change my point: statements
from the "Rationale" section are neither requirements nor permissions.
Post by minforth
which do not include TO. See standard section 5.
Yes, a standard system is not required to provide words from the Core
extensions word set or any optional word set. But if the system provides
such a word, it must provide a standard-compliant implementation of that
word.

Moreover, a standard system cannot provide a word (in FORTH-WORDLIST)
that has the name of some standard word and behaves differently from
that standard word (as far as specified by the standard).

Do not agree?



--
Ruvim
minforth
2024-08-03 19:50:28 UTC
Permalink
Post by Ruvim
Do not agree?
I don't, because rejecting Stephen's (and other's) TO-implementation
method just because of some old and unclear wording is against
innovation and optimisation.

From a higher perspective: Forth has not really innovated over the
last 50 years. Forth-94 achieved streamlining Forth-79 and Forth-83.
Since then: only minor fixes. IIRC Charles Moore did not like the
standard because it fossilised history and stifled creativity.
Factor and 8th went their own ways, incorporation modern programming
language features.

Of course, a standard is no place for innovation or new features.
But dogmatic paper lawyering is like digging Forth's grave a little
deeper.
Ruvim
2024-08-03 23:25:58 UTC
Permalink
Post by minforth
Post by Ruvim
Do not agree?
I don't, because rejecting Stephen's (and other's) TO-implementation
method just because of some old and unclear wording is against
innovation and optimisation.
What particular is unclear? The wording in the glossary entry for "TO"
is quite clear to me: <https://forth-standard.org/standard/core/TO>


Whether "TO" is parsing or non-parsing is nothing to do with optimization.

Moreover, it's easy to implement a parsing "TO" via a non-parsing "TO":

synonym np-to to \ it's a non-parsing to

: to ( interp: x "name" -- ) ( comp: "name" -- )
' >r state @ if postpone to r> compile, exit then
['] to execute r> execute
; immediate

\ This does not work in VfxForth because "postpone" and/or "compile,"
\ are broken for some arguments in VfxForth.


NB: we cannot appeal to the corresponding ambiguous condition in
Forth-2012, because "postpone to" can be replaced with:
[ s" to" forth-wordlist find-name-in name>compile swap lit, compile, ]

and "['] to" can be replaced with:
[ s" to" forth-wordlist find-name-in name>interpret lit, ]

where

: lit, ( x -- ) postpone literal ;

: find-name-in ( sd.name wid -- nt|0 )
Post by minforth
r 0 [: ( sd.name 0 nt -- sd.name 0 nt | sd.name nt 0 )
2over 2 pick name>string compare 0= if swap then
;] r> traverse-wordlist nip nip
;




If you want to allow a non-parsing "TO" in a standard Forth system, you
might want to make a proposal. But it's complicated, and it does not
make much sense, because a non-parsing "TO" has *no* advantage over a
parsing "TO".

However, as I showed earlier, a parsing "TO" has several advantages over
a non-parsing "TO".
Post by minforth
From a higher perspective: Forth has not really innovated over the
last 50 years. Forth-94 achieved streamlining Forth-79 and Forth-83.
Since then: only minor fixes.
Who needs innovations in Forth?
Post by minforth
IIRC Charles Moore did not like the standard because it fossilised
history and stifled creativity.
Charles Moore was consistent — he did not care whether the standard
rejects any implementation or behavior variation.

If one cares — they should convince other why this variation matters.
Post by minforth
Factor and 8th went their own ways, incorporation modern programming
language features.
Of course, a standard is no place for innovation or new features.
A non-parsing "TO" is not an innovation.
Post by minforth
But dogmatic paper lawyering is like digging Forth's grave a little
deeper.
My position concerning "TO" is not dogmatical, but practical :)


--
Ruvim
mhx
2024-08-04 07:17:41 UTC
Permalink
Post by Ruvim
However, as I showed earlier, a parsing "TO" has several advantages over
a non-parsing "TO".
Am I the only one that thinks parsing words are an incredible nuisance?

-marcel
Paul Rubin
2024-08-04 08:05:03 UTC
Permalink
Post by mhx
Am I the only one that thinks parsing words are an incredible nuisance?
I haven't followed this whole thing and didn't realize a sane
non-parsing TO was even possible. I've sometimes thought of a version
of VALUE that makes two separate words, for reading and writing the
value:

17 XVALUE foo

creates two words, "?foo" and "!foo". ?foo pushes the value from foo
(initially 17) onto the stack. !foo moves TOS to foo.
mhx
2024-08-04 09:38:00 UTC
Permalink
[..] I've sometimes thought of a version
of VALUE that makes two separate words, for reading and writing the
17 XVALUE foo
creates two words, "?foo" and "!foo". ?foo pushes the value from foo
(initially 17) onto the stack. !foo moves TOS to foo.
That would work too, but apart from messing up Forth's unspoken
formatting guidelines, the scheme becomes impractical when you want to
propel additional messages like +TO, -TO, 'OF (returns address of),
0TO or CLEAR, SIZEOF and /OF . In practice, the latter two are used
very infrequently.

-marcel
Ruvim
2024-08-04 10:09:42 UTC
Permalink
Post by mhx
[..] I've sometimes thought of a version
of VALUE that makes two separate words, for reading and writing the
17 XVALUE foo
creates two words, "?foo" and "!foo".  ?foo pushes the value from foo
(initially 17) onto the stack.  !foo moves TOS to foo.
That would work too, but apart from messing up Forth's unspoken
formatting guidelines, the scheme becomes impractical when you want to
propel additional messages like +TO, -TO, 'OF (returns address of),
0TO or CLEAR, SIZEOF and /OF . In practice, the latter two are used
very infrequently.
One problem of this OOP-like approach with many messages is that it
works for a named object only, and does not work for an anonymous object
on the stack.

In OOP, you can pass an object as parameter, and send messages to this
object (or call its methods). But you cannot pass a value-flavored
object as a parameter and then call its methods.


By the way, unlike value-flavored objects, a defer-flavored object can
be passed as xt, and the methods `defer!`, `defer@`, and `execute` can
be applied to this object.


In value-flavored structures approach the objects are anonymous and only
passed as a stack parameter. But using "TO" is very confusing, because
the immediate argument of "TO" is not an object name, but a class
variable name (conceptually), and with object on the stack.



--
Ruvim
Ruvim
2024-08-04 12:19:28 UTC
Permalink
Post by Paul Rubin
Post by mhx
Am I the only one that thinks parsing words are an incredible nuisance?
I haven't followed this whole thing and didn't realize a sane
non-parsing TO was even possible. I've sometimes thought of a version
of VALUE that makes two separate words, for reading and writing the
17 XVALUE foo
creates two words, "?foo" and "!foo". ?foo pushes the value from foo
(initially 17) onto the stack. !foo moves TOS to foo.
I use this approach, but with "foo" instead of "?foo".

A standard-compliant implementation:
<https://gist.github.com/ruv/438d57d0af6a38e616efb59b43795e1b#file-slot-fth>


--
Ruvim
Anton Ertl
2024-08-04 09:36:51 UTC
Permalink
Post by mhx
Am I the only one that thinks parsing words are an incredible nuisance?
No. They are one of the reasons for the STATE-smartness idiocy and
they don't work with ]]...[[. In case of TO Gforth (development)
implements a to-recognizer:

5 value foo
7 ->foo
foo . \ 7
: bar ->foo ;
9 bar
foo . \ 9
: bla ]] ->foo [[ ; immediate
: blub bla ;
3 blub
foo . \ 3

The to-recognizer makes TO unnecessary (both parsing or non-parsing).
And instead of +TO FOO one writes +>FOO:

6 +>foo
foo . 9

- 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: https://forth-standard.org/
EuroForth 2024: https://euro.theforth.net
a***@spenarnc.xs4all.nl
2024-08-04 11:11:03 UTC
Permalink
Post by mhx
Post by Ruvim
However, as I showed earlier, a parsing "TO" has several advantages over
a non-parsing "TO".
Am I the only one that thinks parsing words are an incredible nuisance?
Numbers (denotations) must be parsed. Otherwise I do think parsing
words is a nuisance.
I might tolerate an exception with
"FILENAME" INCLUDED
"FILESNAME" NEEDED
"WORDNAME" WANTED
to be supplemented with
INCLUDE FILENAME
NEED FILESNAME
WANT WORDNAME
Merely for convenience to not type double quotes that are
far from the hand position, and even have different position
on the keyboard. And only in interactive sessions.

Particularly I hate ' / ['] .
My solution that ' has to elevated to a denotation.
Meaning 'someword leave the address/dea/handle/nametoken
of `` someword '' that is the same in interpret and compile mode.
If you want separate behaviours in some mode, they must be arrived
at via the dea.
Post by mhx
-marcel
Groetjes Albert
--
Don't praise the day before the evening. One swallow doesn't make spring.
You must not say "hey" before you have crossed the bridge. Don't sell the
hide of the bear until you shot it. Better one bird in the hand than ten in
the air. First gain is a cat purring. - the Wise from Antrim -
Ruvim
2024-08-04 12:14:25 UTC
Permalink
Post by a***@spenarnc.xs4all.nl
Post by mhx
Post by Ruvim
However, as I showed earlier, a parsing "TO" has several advantages over
a non-parsing "TO".
Am I the only one that thinks parsing words are an incredible nuisance?
Numbers (denotations) must be parsed. Otherwise I do think parsing
words is a nuisance.
I might tolerate an exception with
"FILENAME" INCLUDED
"FILESNAME" NEEDED
"WORDNAME" WANTED
to be supplemented with
INCLUDE FILENAME
NEED FILESNAME
WANT WORDNAME
Merely for convenience to not type double quotes that are
far from the hand position, and even have different position
on the keyboard. And only in interactive sessions.
Particularly I hate ' / ['] .
My solution that ' has to elevated to a denotation.
Meaning 'someword leave the address/dea/handle/nametoken
of `` someword '' that is the same in interpret and compile mode.
I also often use `'someword` instead of `['] someword` and `' someword`,
because I hate different forms for the conceptually same thing in
interpretation and compilation, and because the form `'someword` is shorter.

Another thing I hate is when it's not obvious that a word is a parsing
word, or what its delimiter. So I prefer when parsing delimiters are
visible.

For example, I would prefer:
want( word1 word2 word3 )
rather than:
want word1 want word2 want word3



But if you hate parsing words in principle (just because they do
parsing), why not hate such long parsing words like `[if]`, `\`, the
construct "]]...[[", etc? What is an alternative for them?
Post by a***@spenarnc.xs4all.nl
If you want separate behaviours in some mode, they must be arrived
at via the dea.
Agreed.

But simplicity of the dual-nt approach (like in cmForth) is sometimes
preferable. Because compilation semantics for a word are defined as an
ordinary word.


--
Ruvim
a***@spenarnc.xs4all.nl
2024-08-05 10:04:31 UTC
Permalink
Post by Ruvim
Post by a***@spenarnc.xs4all.nl
Particularly I hate ' / ['] .
My solution that ' has to elevated to a denotation.
Meaning 'someword leave the address/dea/handle/nametoken
of `` someword '' that is the same in interpret and compile mode.
I also often use `'someword` instead of `['] someword` and `' someword`,
because I hate different forms for the conceptually same thing in
interpretation and compilation, and because the form `'someword` is shorter.
Another thing I hate is when it's not obvious that a word is a parsing
word, or what its delimiter. So I prefer when parsing delimiters are
visible.
want( word1 word2 word3 )
want word1 want word2 want word3
I have changed WANT to accept several words on the same line
want word1 word2 word3
This is one of the few "improvements" I'm not sure about.
By itself WANT is a concession because it is actually
"word1" WANTED "word2" WANTED "word3" WANTED
Your proposal makes sense, having several WANT(ED) on the same line
is ugly and impractical, but parsing to the end of line is dubious.
Post by Ruvim
But if you hate parsing words in principle (just because they do
parsing), why not hate such long parsing words like `[if]`, `\`, the
construct "]]...[[", etc? What is an alternative for them?
WANT is used recursively in blocks. If you wanted to accomplish the
same thing with [IF], it would be a horrid mess.
The same blockfile is valid for MSDOS WINDOWS DPMI en DLL en LINUX
and 32 64 bit forths.
For example ALIAS is used all over the place, but it is not in the kernel.
"ALIAS" WANTED can be added and that is it.
WANTED and the conditional rejection of blocks is all that is needed.
This is the header of a block that is only valid for 32 bits.
( CRC-MORE CRC ) CF: ?32 \ AvdH C2feb27
Note that it is orthogonal to any windows/linux distinction.

I actually like \ because it is absolutely obvious where the comment ends.
I hate DOC / ENDDOC pairs and the worst is that you define such pair
<------- / -----> for a meta forth compilation, as I have seen.

]] .. [[ confuses me.
I have introduced
:I inl aa bb cc ;
The :I means that the definition is supposed to be inlined.
That allows bb for instance be >R .
Post by Ruvim
Post by a***@spenarnc.xs4all.nl
If you want separate behaviours in some mode, they must be arrived
at via the dea.
Agreed.
But simplicity of the dual-nt approach (like in cmForth) is sometimes
preferable. Because compilation semantics for a word are defined as an
ordinary word.
I do not object replacing >CFA (executable address) with >CFA1
and >CFA2 as long as the starting point is the dea.
Post by Ruvim
--
Ruvim
Groetjes Albert
--
Don't praise the day before the evening. One swallow doesn't make spring.
You must not say "hey" before you have crossed the bridge. Don't sell the
hide of the bear until you shot it. Better one bird in the hand than ten in
the air. First gain is a cat purring. - the Wise from Antrim -
Ruvim
2024-08-05 14:28:14 UTC
Permalink
Post by a***@spenarnc.xs4all.nl
Post by Ruvim
Post by a***@spenarnc.xs4all.nl
Particularly I hate ' / ['] .
My solution that ' has to elevated to a denotation.
Meaning 'someword leave the address/dea/handle/nametoken
of `` someword '' that is the same in interpret and compile mode.
I also often use `'someword` instead of `['] someword` and `' someword`,
because I hate different forms for the conceptually same thing in
interpretation and compilation, and because the form `'someword` is shorter.
Another thing I hate is when it's not obvious that a word is a parsing
word, or what its delimiter. So I prefer when parsing delimiters are
visible.
want( word1 word2 word3 )
want word1 want word2 want word3
I have changed WANT to accept several words on the same line
want word1 word2 word3
This is one of the few "improvements" I'm not sure about.
By itself WANT is a concession because it is actually
"word1" WANTED "word2" WANTED "word3" WANTED
Your proposal makes sense, having several WANT(ED) on the same line
is ugly and impractical, but parsing to the end of line is dubious.
Post by Ruvim
But if you hate parsing words in principle (just because they do
parsing), why not hate such long parsing words like `[if]`, `\`, the
construct "]]...[[", etc? What is an alternative for them?
WANT is used recursively in blocks. If you wanted to accomplish the
same thing with [IF], it would be a horrid mess.
I meant the word `[IF]` by itself, without connection with `WANT`.

The word `[IF]` is a parsing word. If you hate parsing words in general,
what alternative to `[IF]` could you suggest?


The word `]]` is also a parsing word (in a standard-compliant
implementation). It parses the input stream till the lexeme "[[".

How to implement such functionality without active parsing the input stream?


But if such long parsing words like `[IF]` and `]]` are acceptable, why
the words that parses a single lexeme are not acceptable? (apart from
naming and terminator visibility problems)?



--
Ruvim
Anton Ertl
2024-08-05 14:33:10 UTC
Permalink
Post by Ruvim
Post by Ruvim
But if you hate parsing words in principle (just because they do
parsing), why not hate such long parsing words like `[if]`, `\`, the
construct "]]...[[", etc? What is an alternative for them?
...
Post by Ruvim
I meant the word `[IF]` by itself, without connection with `WANT`.
Not necessarily a parsing word. Could also be treated as something
like another state (i.e., the text interpreter does the parsing, but
does something different with the words than interpretation state or
compile state. In every case, the interaction with other features is
problematic; e.g., consider:

0 [IF]
...
\ ....
\ [ELSE]
\ ....
cr .( you should see this according to the standard)
[THEN]

(and the systems I tested actually comply with the standard requirements)

This behaviour might surprise users, especially in connection with
nested [IF]s. However, there have been few complaints, so it
obviously is only a minor issue.

\ parses, but apart from interactions like above it looks fine to me.
Post by Ruvim
The word `]]` is also a parsing word (in a standard-compliant
implementation).
You mean that implementing ]] as a standard program requires parsing.
That's true, but the usual implementation in systems is as another
state-like thing. And you also get interesting interactions if you
combine it with [if], or parsing words like \ or (. The sequences
inside ]]...[[ are short enough that this is rarely necessary, and if
it is, you can do, e.g.

]] bla [[ ( x y ) ]] blub [[

instead of

]] bla ( x y ) blub [[

Not great, but has not been a significant issue yet.
Post by Ruvim
How to implement such functionality without active parsing the input stream?
How does :NONAME or ] implement its functionality? Do you also
consider it a parsing word? Note that in some Forth, Inc. Forth
systems ] parses on its own rather than using a state of the ordinary
text interpreter.
Post by Ruvim
But if such long parsing words like `[IF]` and `]]` are acceptable, why
the words that parses a single lexeme are not acceptable? (apart from
naming and terminator visibility problems)?
A problem with parsing words like ' and ['] is that code using them
usually cannot be copied and pasted between interpreted and compiled
code. A problem with parsing words like S" is that implementing them
properly requires mechanisms beyond what has been traditionally
available.

- 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: https://forth-standard.org/
EuroForth 2024: https://euro.theforth.net
Ruvim
2024-08-06 10:12:00 UTC
Permalink
Post by Anton Ertl
Post by Ruvim
I meant the word `[IF]` by itself, without connection with `WANT`.
Not necessarily a parsing word. Could also be treated as something
like another state (i.e., the text interpreter does the parsing, but
does something different with the words than interpretation state or
compile state.
In every case, the interaction with other features is
0 [IF]
...
\ ....
\ [ELSE]
\ ....
cr .( you should see this according to the standard)
[THEN]
(and the systems I tested actually comply with the standard requirements)
This behaviour might surprise users, especially in connection with
nested [IF]s. However, there have been few complaints, so it
obviously is only a minor issue.
This problem is not endemic to Forth. It takes place in many other
programming languages too.

For example, in "C++":

/*

// /* comment */ puts("you should see this");
// the above command takes effect despite the line comment

/* other comment */


A rule of thumb: the one who gains control first wins.


--
Ruvim
mhx
2024-08-06 10:43:39 UTC
Permalink
On Tue, 6 Aug 2024 10:12:00 +0000, Ruvim wrote:
[..]
Post by Ruvim
/*
// /* comment */ puts("you should see this");
// the above command takes effect despite the line comment
/* other comment */
A rule of thumb: the one who gains control first wins.
One of the rare occasions where a colorizing text editor is
helpful.

-marcel
a***@spenarnc.xs4all.nl
2024-08-07 10:29:13 UTC
Permalink
Post by Ruvim
Post by Anton Ertl
Post by Ruvim
I meant the word `[IF]` by itself, without connection with `WANT`.
Not necessarily a parsing word. Could also be treated as something
like another state (i.e., the text interpreter does the parsing, but
does something different with the words than interpretation state or
compile state.
In every case, the interaction with other features is
0 [IF]
...
\ ....
\ [ELSE]
\ ....
cr .( you should see this according to the standard)
[THEN]
(and the systems I tested actually comply with the standard requirements)
This behaviour might surprise users, especially in connection with
nested [IF]s. However, there have been few complaints, so it
obviously is only a minor issue.
This problem is not endemic to Forth. It takes place in many other
programming languages too.
/*
// /* comment */ puts("you should see this");
// the above command takes effect despite the line comment
/* other comment */
A rule of thumb: the one who gains control first wins.
So you cannot read it unless you start parsing from the
very beginning.
The problem is that it becomes unreadable. Most people
who want to comment out sections that contains comment
are messy in other respects too. In my coding standards
there is the rule, that no nested comments are to be
saved in a source control system.
All commented out code is questionable. It shows that you
don't use your source control system properly.

In a language like Forth where everything can mean anything
it is good to have a comment sign \ that goes until the end
of the line.
If your editor can't do
123,456s/^/\\/
or some such, it is simply not powerful enough to serve
as a program editor.
(I have never used a folding editor, but probably it could
be used too.)
Post by Ruvim
Ruvim
Groetjes Albert
--
Don't praise the day before the evening. One swallow doesn't make spring.
You must not say "hey" before you have crossed the bridge. Don't sell the
hide of the bear until you shot it. Better one bird in the hand than ten in
the air. First gain is a cat purring. - the Wise from Antrim -
Ruvim
2024-08-06 12:19:29 UTC
Permalink
Post by Anton Ertl
Post by Ruvim
Post by Ruvim
But if you hate parsing words in principle (just because they do
parsing), why not hate such long parsing words like `[if]`, `\`, the
construct "]]...[[", etc? What is an alternative for them?
...
Post by Ruvim
I meant the word `[IF]` by itself, without connection with `WANT`.
Not necessarily a parsing word. Could also be treated as something
like another state (i.e., the text interpreter does the parsing, but
does something different with the words than interpretation state or
compile state.
[...]
Post by Anton Ertl
\ parses, but apart from interactions like above it looks fine to me.
Post by Ruvim
The word `]]` is also a parsing word (in a standard-compliant
implementation).
You mean that implementing ]] as a standard program requires parsing.
That's true, but the usual implementation in systems is as another
state-like thing. And you also get interesting interactions if you
combine it with [if], or parsing words like \ or (. The sequences
inside ]]...[[ are short enough that this is rarely necessary, and if
it is, you can do, e.g.
]] bla [[ ( x y ) ]] blub [[
instead of
]] bla ( x y ) blub [[
Not great, but has not been a significant issue yet.
Post by Ruvim
How to implement such functionality without active parsing the input stream?
How does :NONAME or ] implement its functionality? Do you also
consider it a parsing word? Note that in some Forth, Inc. Forth
systems ] parses on its own rather than using a state of the ordinary
text interpreter.
Yes, I mean that in a standard program the only approach available to
implement such functionality is the active parsing approach (at the moment).


The Recognizer API allows to replace short parsing words with
syntactically recognized forms (limited by one lexeme). Actually, it is
a generalization of numeric literals.


But to implement string literals or string templates (for string
interpolation), we still need active parsing. And we need it even if we
implement the beginning of such a literal as a recognizable form.

An illustration of this two approaches:

- a parsing word `s"`:
s" lorem ipsum dolor"

- a recognizable form, a lexeme that starts with `"`:
"lorem ipsum dolor"

If a recognizer has no side effects and returns a token translator on
success, then, for a string literal, the returned translator *parses*
the input buffer (or the input stream) till `"` [1,2].

So, in general, parsing is *inevitable*. Whether it is a parsing word
or a parsing translator — it does not matter.
Post by Anton Ertl
Post by Ruvim
But if such long parsing words like `[IF]` and `]]` are acceptable, why
the words that parses a single lexeme are not acceptable? (apart from
naming and terminator visibility problems)?
A problem with parsing words like ' and ['] is that code using them
usually cannot be copied and pasted between interpreted and compiled
code.
I would define interpretation semantics for `[']` to be the same as for
`'`, as follows:

: compilation ( -- flag ) state @ 0<> ;
: tt-lit ( x -- x | ) compilation if lit, then ; immediate
: ['] ( "name" -- xt | ) ' tt-lit ; immediate


So, this problem can be easily solved.
Post by Anton Ertl
A problem with parsing words like S" is that implementing them
properly requires mechanisms beyond what has been traditionally
available.
It does not require mechanisms beyond the Forth-2012.

If you say that `postpone` behaves incorrectly for such words, you now
my answer — it is a problem of a particular implementation of
`postpone`, and this problem can be easily fixed [3].




[1] String literals via Recognizer API
<https://gist.github.com/ruv/67134d5eb0493969520f77d3f89f85d5#file-file-01-string-literal-via-recognizer-v5-fth>
[2] A recognizer for multi-line string literal
<https://gist.github.com/ruv/60450afc33a7ad0f614bedefe4841ddb>
[3] A polyfill for `postpone`
<https://github.com/ForthHub/discussion/discussions/103#user-content-solution>


--
Ruvim
Ruvim
2024-08-09 13:37:20 UTC
Permalink
Post by Ruvim
Post by Ruvim
Post by Ruvim
But if you hate parsing words in principle (just because they do
parsing), why not hate such long parsing words like `[if]`, `\`, the
construct "]]...[[", etc? What is an alternative for them?
...
Post by Ruvim
I meant the word `[IF]` by itself, without connection with `WANT`.
Not necessarily a parsing word.  Could also be treated as something
like another state (i.e., the text interpreter does the parsing, but
does something different with the words than interpretation state or
compile state.
[...]
\ parses, but apart from interactions like above it looks fine to me.
Post by Ruvim
The word `]]` is also a parsing word (in a standard-compliant
implementation).
You mean that implementing ]] as a standard program requires parsing.
That's true, but the usual implementation in systems is as another
state-like thing.
[...]
Post by Ruvim
Post by Ruvim
How to implement such functionality without active parsing the input stream?
How does :NONAME or ] implement its functionality?  Do you also
consider it a parsing word?  Note that in some Forth, Inc. Forth
systems ] parses on its own rather than using a state of the ordinary
text interpreter.
Yes, I mean that in a standard program the only approach available to
implement such functionality is the active parsing approach (at the moment).
The Recognizer API allows to replace short parsing words with
syntactically recognized forms (limited by one lexeme). Actually, it is
a generalization of numeric literals.
But to implement string literals or string templates (for string
interpolation), we still need active parsing. And we need it even if we
implement the beginning of such a literal as a recognizable form.
  s" lorem ipsum dolor"
  "lorem ipsum dolor"
If a recognizer has no side effects and returns a token translator on
success, then, for a string literal, the returned translator *parses*
the input buffer (or the input stream) till `"` [1,2].
So, in general, parsing is *inevitable*.  Whether it is a parsing word
or a parsing translator — it does not matter.
One difference between parsing words and a recognizable syntactic forms
is visual — the latter does not require a space before the enclosed
content (this makes sense when whitespaces matter, like in string literals).

Another difference is related to API: `[']` and `postpone` are not
applicable to the latter (but are applicable to the former).

NB: applying `postpone` to `s"` is not the same as applying `postpone`
to a particular string literal.

So, a parsing word can be used by itself to reuse its functionality. But
to reuse functionality of some recognizable syntactic form, additional
words should be provided. It's notable that the Recognizers API
encourages (or even forces) us to provide such additional words.


One of features that Recognizer API provides is the *ability* to reuse
the system's Forth text interpreter loop without nesting.


An example:

\ Common data types that are related to the Recognizer API:
\ DataType: recognizer ⇒ xt
\ DataType: tt ⇒ xt
\ DataType: token ⇒ ( S: i*x F: j*k )
\ DataType: qt ⇒ ( token tt | 0 )
\ Functional data types qualifications:
\ DataType: recognizer = ( sd.lexeme -- qt )
\ DataType: tt = ( i*x token -- j*x )


wordlist constant foo-wid
here constant foo-magic

\ DataType: foo-sys ⇒ ( recognizer.prev x.foo-magic )

: end-foo ( foo-sys -- )
foo-magic <> -22 and throw \ "control structure mismatch"
set-perceptor \ restore the perceptor state
;
: recognize-foo ( sd.lexeme -- tt | 0 )
2dup "}foo" equals if 2drop ['] end-foo exit then
foo-wid search-wordlist if exit then 0
;
: begin-foo ( -- foo-sys )
\ save the perceptor state
perceptor foo-magic ( recognizer.prev x.foo-magic ) ( foo-sys )
\ set the system to use our recognizer
['] recognize-foo set-perceptor
;
: foo{ ( -- foo-sys )
begin-foo
; immediate
\ NB: "}foo" is not a word, but just a terminator.

\ create some test words
get-current foo-wid set-current
: test ." (test passed)" ;
: n1 1 ; : n2 2 ; : + + ; : . . ;
set-current

\ run some tests
foo{ test }foo \ should print "(test passed)"
foo{ n1 n2 + . }foo \ should print "3"
t{ foo{ n1 n2 + }foo -> 3 }t

Voilà! The third test fails with error -22. Because of foo-sys, we
cannot freely consume or produce stack parameters from/to outside of the
foo{ }foo structure.

NB: this example is not intended to show how to implement this dummy
functionality, but to show how the Recognizer API is used.


This functionality can be also implemented as a parsing word, using the
same Recognizer API, as follows:

: recognize-foo ( sd.lexeme -- tt | 0 )
foo-wid search-wordlist if exit then 0
;
: foo{
[: ( sd.lexeme -- qt )
2dup "}foo" equals 0= if recognize-foo exit then
2drop ['] unnest-translation
;] translate-input-with
; immediate


Where the following common factors are used:

: extract-lexeme ( -- sd.lexeme | 0 0 )
begin parse-name dup if exit then 2drop refill 0= until 0 0
;
: unnest-translation ( -- ⊥ )
true abort" unnest-translation is not handled"
;
: translate-input-till-unnest ( i*x -- j*x )
begin extract-lexeme
dup 0= -39 and throw \ "unexpected end of file"
perceive dup 0= -13 and throw \ "unrecognized"
dup ['] unnest-translation <> while execute
repeat drop
;
: translate-input-with ( i*x recognizer -- j*x )
perceptor >r set-perceptor
['] translate-input-till-unnest catch
r> set-perceptor throw
;



This implementation for "foo{" does not leave foo-sys on the stack, so
the following works as expected:

t{ foo{ n1 n2 + }foo -> 3 }t

Also, in this implementation the perceptor state is restored on error.





Thus, with Recognizer API, in some cases we have the choice of using the
non-parsing approach or the parsing approach.


The advantages of the parsing approach are:
- no additional items on the data stack;
- restoring the system's state on error;
- the API for reuse the implemented functionality does not impose a
particular terminator (and the provided recognizer is not polluted by a
particular terminator);


Now the question is: why should one prefer the non-parsing approach to
implement some functionality?


--
Ruvim

a***@spenarnc.xs4all.nl
2024-08-08 09:34:36 UTC
Permalink
Post by Anton Ertl
Post by Ruvim
Post by Ruvim
But if you hate parsing words in principle (just because they do
parsing), why not hate such long parsing words like `[if]`, `\`, the
construct "]]...[[", etc? What is an alternative for them?
...
Post by Ruvim
I meant the word `[IF]` by itself, without connection with `WANT`.
Not necessarily a parsing word. Could also be treated as something
like another state (i.e., the text interpreter does the parsing, but
does something different with the words than interpretation state or
compile state. In every case, the interaction with other features is
If PREFIX-es are present, this can be handled by a wordlist that
contains [IF] [THEN] [ELSE] and a PREFIX with an empty name.
The empty prefix matches everything, and is defined as a noop.
(Also handy in lisp to generate symbols that prior didn't exist)
Manipulating this wordlist in the proper way, all parsing is
handled in INTERPRET.
Post by Anton Ertl
- anton
--
Don't praise the day before the evening. One swallow doesn't make spring.
You must not say "hey" before you have crossed the bridge. Don't sell the
hide of the bear until you shot it. Better one bird in the hand than ten in
the air. First gain is a cat purring. - the Wise from Antrim -
a***@spenarnc.xs4all.nl
2024-08-06 08:46:29 UTC
Permalink
Post by Ruvim
Post by a***@spenarnc.xs4all.nl
Post by Ruvim
Post by a***@spenarnc.xs4all.nl
Particularly I hate ' / ['] .
My solution that ' has to elevated to a denotation.
Meaning 'someword leave the address/dea/handle/nametoken
of `` someword '' that is the same in interpret and compile mode.
I also often use `'someword` instead of `['] someword` and `' someword`,
because I hate different forms for the conceptually same thing in
interpretation and compilation, and because the form `'someword` is shorter.
Another thing I hate is when it's not obvious that a word is a parsing
word, or what its delimiter. So I prefer when parsing delimiters are
visible.
want( word1 word2 word3 )
want word1 want word2 want word3
I have changed WANT to accept several words on the same line
want word1 word2 word3
This is one of the few "improvements" I'm not sure about.
By itself WANT is a concession because it is actually
"word1" WANTED "word2" WANTED "word3" WANTED
Your proposal makes sense, having several WANT(ED) on the same line
is ugly and impractical, but parsing to the end of line is dubious.
Post by Ruvim
But if you hate parsing words in principle (just because they do
parsing), why not hate such long parsing words like `[if]`, `\`, the
construct "]]...[[", etc? What is an alternative for them?
WANT is used recursively in blocks. If you wanted to accomplish the
same thing with [IF], it would be a horrid mess.
I meant the word `[IF]` by itself, without connection with `WANT`.
The word `[IF]` is a parsing word. If you hate parsing words in general,
what alternative to `[IF]` could you suggest?
The word `]]` is also a parsing word (in a standard-compliant
implementation). It parses the input stream till the lexeme "[[".
How to implement such functionality without active parsing the input stream?
But if such long parsing words like `[IF]` and `]]` are acceptable, why
the words that parses a single lexeme are not acceptable? (apart from
naming and terminator visibility problems)?
Long story short:
I'm practical. I don't care for [IF] and I just copied from the
ANSI manual. I'm not dogmatic about it.
[IF] can be implemented by wordlists, relying on regular parsing
INTERPRET. I don't care for [IF] to implement that more elegant
method, and take on the burden of testing.
In my lisp efforts I have found that using INTERPRET recursively
can be very effective as long as you can switch the inputstream
easily. That makes EXECUTE-PARSING all but superfluous.

E.g. manx is an elaborate program running from windows32 to linux64.
There is only one [IF] to do tracing output, not used in a long time.
My reverse engineering assembler/disassembler is equally portable and
contains not a single [IF].
This is possible by using a library mechanism described above
WANTED.
Post by Ruvim
Ruvim
Groetjes Albert
--
Don't praise the day before the evening. One swallow doesn't make spring.
You must not say "hey" before you have crossed the bridge. Don't sell the
hide of the bear until you shot it. Better one bird in the hand than ten in
the air. First gain is a cat purring. - the Wise from Antrim -
Stephen Pelc
2024-08-05 09:28:14 UTC
Permalink
Post by mhx
Post by Ruvim
However, as I showed earlier, a parsing "TO" has several advantages over
a non-parsing "TO".
Am I the only one that thinks parsing words are an incredible nuisance?
No.

Stephen
--
Stephen Pelc, ***@vfxforth.com
MicroProcessor Engineering, Ltd. - More Real, Less Time
133 Hill Lane, Southampton SO15 5AF, England
tel: +44 (0)78 0390 3612, +34 649 662 974
http://www.mpeforth.com
MPE website
http://www.vfxforth.com/downloads/VfxCommunity/
downloads
dxf
2024-08-05 12:26:26 UTC
Permalink
Post by mhx
Post by Ruvim
However, as I showed earlier, a parsing "TO" has several advantages over
a non-parsing "TO".
Am I the only one that thinks parsing words are an incredible nuisance?
Don't know but to this day Mitch Bradley (ANS, Open Firmware) still uses
parsing words to interpret hex, double, float numbers. He also uses
state-smart words.
mhx
2024-08-05 12:38:09 UTC
Permalink
Post by dxf
Post by mhx
Post by Ruvim
However, as I showed earlier, a parsing "TO" has several advantages over
a non-parsing "TO".
Am I the only one that thinks parsing words are an incredible nuisance?
Don't know but to this day Mitch Bradley (ANS, Open Firmware) still uses
parsing words to interpret hex, double, float numbers.
"de gustibus non disputandum est."
Post by dxf
He also uses state-smart words.
Show me a Forther *without* strong opinions *and* unfathomable
inconsistencies.

-marcel
dxf
2024-08-05 15:07:39 UTC
Permalink
Post by mhx
Post by dxf
Post by mhx
Post by Ruvim
However, as I showed earlier, a parsing "TO" has several advantages over
a non-parsing "TO".
Am I the only one that thinks parsing words are an incredible nuisance?
Don't know but to this day Mitch Bradley (ANS, Open Firmware) still uses
parsing words to interpret hex, double, float numbers.
"de gustibus non disputandum est."
Post by dxf
He also uses state-smart words.
Show me a Forther *without* strong opinions *and* unfathomable
inconsistencies.
I'm more interested in knowing how parsing words can be a nuisance? Do they
possess a life of their own? We've been told state-smart words are evil.
Ruvim
2024-08-05 16:08:58 UTC
Permalink
Post by dxf
Post by mhx
Post by dxf
Post by mhx
Post by Ruvim
However, as I showed earlier, a parsing "TO" has several advantages over
a non-parsing "TO".
Am I the only one that thinks parsing words are an incredible nuisance?
Don't know but to this day Mitch Bradley (ANS, Open Firmware) still uses
parsing words to interpret hex, double, float numbers.
"de gustibus non disputandum est."
Post by dxf
He also uses state-smart words.
Show me a Forther *without* strong opinions *and* unfathomable
inconsistencies.
I'm more interested in knowing how parsing words can be a nuisance? Do they
possess a life of their own?
We've been told state-smart words are evil.
The only reason for that evil is that `POSTPONE` in a classic
implementation behaves incorrectly for them.

See "About POSTPONE semantics in edge cases"
<https://github.com/ForthHub/discussion/discussions/103>

Nobody have pointed out any logical error in my reasoning.


--
Ruvim
dxf
2024-08-06 04:27:15 UTC
Permalink
...
Post by dxf
We've been told state-smart words are evil.
The only reason for that evil is that `POSTPONE` in a classic implementation behaves incorrectly for them.
See "About POSTPONE semantics in edge cases" <https://github.com/ForthHub/discussion/discussions/103>
Nobody have pointed out any logical error in my reasoning.
ISTR dual-xt solutions also have problems with 'edge cases'. Pursuit of
perfection is for folks with much time on their hands.
dxf
2024-08-07 03:08:49 UTC
Permalink
Post by dxf
...
ISTR dual-xt solutions also have problems with 'edge cases'.
Works for state-smart but not dual-xt:

: ," postpone s" dup c, here over allot swap cmove ;

," Hello world"

Perhaps it's time to consider all 'smart' words 'evil'.
Anton Ertl
2024-08-07 06:11:03 UTC
Permalink
Post by dxf
Post by dxf
...
ISTR dual-xt solutions also have problems with 'edge cases'.
: ," postpone s" dup c, here over allot swap cmove ;
," Hello world"
I did not understand at first what this code was supposed to do, in
particular why you would want to perform the compilation semantics of
S" outside a colon definition.

After some thinking I found that this code actually relies on a buggy
implementation of S" which does not implement the compilation
semantics of the standard S" in this usage. It's better to write code
that does not rely on such bugs:

: ," ['] s" execute dup c, here over allot swap cmove ;

," Hello world"

or just

: ," '"' parse dup c, here over allot swap cmove ;

," Hello world"

As for the argument that this is supposed to be a problem of correct
implementations of S": Yes, one can write code that relies on a bug,
for every bug. That does not justify the bug.

- 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: https://forth-standard.org/
EuroForth 2024: https://euro.theforth.net
dxf
2024-08-07 07:23:26 UTC
Permalink
Post by Anton Ertl
Post by dxf
Post by dxf
...
ISTR dual-xt solutions also have problems with 'edge cases'.
: ," postpone s" dup c, here over allot swap cmove ;
," Hello world"
I did not understand at first what this code was supposed to do, in
particular why you would want to perform the compilation semantics of
S" outside a colon definition.
Not understand? Didn't you write a paper on state-smart words?
Post by Anton Ertl
After some thinking I found that this code actually relies on a buggy
implementation of S" which does not implement the compilation
semantics of the standard S" in this usage.
Is the 200x TC prepared to attest to that with a vote of members? Because
if they don't, then common practice prevails.
Post by Anton Ertl
It's better to write code
: ," ['] s" execute dup c, here over allot swap cmove ;
," Hello world"
So dual-xt words don't replace state-smart. Rather it's about what you want
these words to do. Good to know.
Ruvim
2024-08-07 10:12:38 UTC
Permalink
Post by Anton Ertl
Post by dxf
Post by dxf
...
ISTR dual-xt solutions also have problems with 'edge cases'.
: ," postpone s" dup c, here over allot swap cmove ;
," Hello world"
I did not understand at first what this code was supposed to do, in
particular why you would want to perform the compilation semantics of
S" outside a colon definition.
After some thinking I found that this code actually relies on a buggy
implementation of S" which does not implement the compilation
semantics of the standard S" in this usage.
I would say, this code actually relies on a buggy implementation of
`postpone` ;-)
Post by Anton Ertl
: ," ['] s" execute dup c, here over allot swap cmove ;
," Hello world"
A portable implementation that behaves the same on almost any Forth
system regardless of the current STATE:

: ," ['] s" execute-interpreting
dup c, here over allot swap cmove ;


where

: compilation ( -- flag ) state @ 0<> ;
: enter-compilation ( -- ) ] ;
: leave-compilation ( -- ) postpone [ ;

: execute-interpreting ( i*x xt --j*x )
compilation 0= if execute exit then
leave-compilation execute enter-compilation
;


This approach also works for any immediate word when you want to perform
the interpretation semantics of this word — the behavior observed when
the Forth text interpreter encounters the word in interpretation state.





Regarding terminology.

If by "interpretation semantics" we mean such behavior that, for the
case of an immediate word, is always equal to the execution semantics of
this word (meaning 2), then we will need *another* term to refer the
very behavior observed when the Forth text interpreter encounters the
word in interpretation state (meaning 1).

But there is no particular point in introducing another term, since the
term for the meaning 2 is not needed at all! Neither in formalization,
no in practice. But the meaning 1 is required.

Therefore, by "interpretation semantics" we should always imply the
meaning 1, and never imply the meaning 2.


Note. It's easy to define such a word `foo` that its execution
semantics, identified by the phrase:
['] foo

are *not* equal to the execution semantics identified by the phrase:
[: ['] foo execute-interpreting ;]

Normatively, the interpretation semantics for the word `foo` is equal to
the execution semantics identified by the latter phrase.


--
Ruvim
a***@spenarnc.xs4all.nl
2024-08-07 10:09:04 UTC
Permalink
Post by dxf
Post by dxf
...
ISTR dual-xt solutions also have problems with 'edge cases'.
: ," postpone s" dup c, here over allot swap cmove ;
," Hello world"
Perhaps it's time to consider all 'smart' words 'evil'.
Numbers (also denotations, such as strings) must be smart.
There is no harm because they are constant.
As far as I'm concerned all others can be banned.
Most state-smart words in my Forth are relics from old standards.
I routinely replace
."
by
"..." TYPE

Groetjes Albert
--
Don't praise the day before the evening. One swallow doesn't make spring.
You must not say "hey" before you have crossed the bridge. Don't sell the
hide of the bear until you shot it. Better one bird in the hand than ten in
the air. First gain is a cat purring. - the Wise from Antrim -
Paul Rubin
2024-08-07 19:35:28 UTC
Permalink
Post by a***@spenarnc.xs4all.nl
Numbers (also denotations, such as strings) must be smart.
I've thought of having non-smart numbers in a small Forth. Instead of
123 you would say # 123 or something similar, where # is a parsing word
that emits LIT and the number. I remember that the eForth metacompiler
does something like that, to handle the case where the host and target
processors have differing number representations (e.g. word sizes).
a***@spenarnc.xs4all.nl
2024-08-08 09:25:51 UTC
Permalink
Post by Paul Rubin
Post by a***@spenarnc.xs4all.nl
Numbers (also denotations, such as strings) must be smart.
I've thought of having non-smart numbers in a small Forth. Instead of
123 you would say # 123 or something similar, where # is a parsing word
that emits LIT and the number. I remember that the eForth metacompiler
does something like that, to handle the case where the host and target
processors have differing number representations (e.g. word sizes).
I don't think that would count as non-smart numbers.
A long time ago I demonstrated handling denotations (numbers)
in INTERPRET . Reminder denotations are constant and the same
in either mode.
It requires that there is a separate compilation stack.

As soon as INTERPRET detects that a word (obviously immediate)
leaves something on the stack, and it is in compilation state,
it compiles one or more literals.
That is in the context of PREFIXes. 0x is a prefix immediate.
0x1234 gets control and generates hex 1234 . INTERPRET takes
cares of the rest.
Bottom line, that is the single location in the whole Forth
where STATE is inspected.

In ciforth I don't go that far, but all denotations ends in a
call to LITERAL/DLITERAL which comes close.

Groetjes Albert
--
Don't praise the day before the evening. One swallow doesn't make spring.
You must not say "hey" before you have crossed the bridge. Don't sell the
hide of the bear until you shot it. Better one bird in the hand than ten in
the air. First gain is a cat purring. - the Wise from Antrim -
Anton Ertl
2024-08-05 15:18:00 UTC
Permalink
Post by mhx
Post by dxf
Don't know but to this day Mitch Bradley (ANS, Open Firmware) still uses
parsing words to interpret hex, double, float numbers.
"de gustibus non disputandum est."
Post by dxf
He also uses state-smart words.
Show me a Forther *without* strong opinions *and* unfathomable
inconsistencies.
In this case it's actually consistent: Mitch Bradley finds the
pitfalls of STATE-smart words acceptable, so he uses such words to
deal with various literals.

I, OTOH, don't consider them to be acceptable, so I prefer
recognizers, like the standard already has for words, single and
double integer numbers, and FP numbers.

- 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: https://forth-standard.org/
EuroForth 2024: https://euro.theforth.net
a***@spenarnc.xs4all.nl
2024-08-06 08:58:54 UTC
Permalink
Post by Anton Ertl
Post by mhx
Post by dxf
Don't know but to this day Mitch Bradley (ANS, Open Firmware) still uses
parsing words to interpret hex, double, float numbers.
"de gustibus non disputandum est."
Post by dxf
He also uses state-smart words.
Show me a Forther *without* strong opinions *and* unfathomable
inconsistencies.
In this case it's actually consistent: Mitch Bradley finds the
pitfalls of STATE-smart words acceptable, so he uses such words to
deal with various literals.
I, OTOH, don't consider them to be acceptable, so I prefer
recognizers, like the standard already has for words, single and
double integer numbers, and FP numbers.
Actually there is not much difference between
DX ABCD
and
0x ABCD
and
0xABCD
or
$ABCD

As long as you make 0x/$ a PREFIX and recognize that
it is inevitable that numbers are state-smart.
Making the expression into a single word solves much.
The whole recognizer thing becomes superfluous at the expense
of 5 words in INTERPRET.
Post by Anton Ertl
- anton
Groetjes Albert
--
Don't praise the day before the evening. One swallow doesn't make spring.
You must not say "hey" before you have crossed the bridge. Don't sell the
hide of the bear until you shot it. Better one bird in the hand than ten in
the air. First gain is a cat purring. - the Wise from Antrim -
Anton Ertl
2024-08-03 14:19:34 UTC
Permalink
Post by minforth
TO is not part of the CORE wordset, and the standard has no
normative parts
What makes you think so? Everything is normative that is not marked
as informative (the appendices).
Post by minforth
- only compliance requirements, which do not
include TO. See standard section 5.
Sure, you can implement a Forth-94 or Forth-2012 system that
implements only the core wordset. But if you implement TO and claim
that your system is a standard system, your implementation of TO must
behave as specified in the standard. See chapter 3:

|No standard word provided by a system shall alter the system state in
|a way that changes the effect of execution of any other standard word
|except as provided in this standard.
Post by minforth
Don't nail your own foot to the floor...
Of course, you are free to implement a non-standard system.

- 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: https://forth-standard.org/
EuroForth 2024: https://euro.theforth.net
mhx
2024-08-03 10:49:48 UTC
Permalink
FORTH> 0 value _v1 immediate ok
FORTH> : test-to 1 to _v1 ; ok
FORTH> see test-to
Flags: TOKENIZE, ANSI
: test-to 1 TO _v1 ; ok
FORTH> : tt test-to _v1 . ; ok
FORTH> see tt
Flags: ANSI
$01341640 : tt
$0134164A mov $01341190 qword-offset, 1 d#
$01341655 push $01341190 qword-offset
$0134165B jmp .+10 ( $0124A102 ) offset NEAR
FORTH> tt 1 ok
FORTH>

FWIW.

-marcel
Ruvim
2024-08-04 09:39:25 UTC
Permalink
FORTH> 0 value _v1 immediate  ok
FORTH> : test-to 1 to _v1 ;  ok
FORTH> see test-to
Flags: TOKENIZE, ANSI
: test-to  1 TO _v1 ;  ok
FORTH> : tt test-to _v1 . ;  ok
FORTH> see tt
Flags: ANSI
$01341640  : tt
$0134164A  mov           $01341190 qword-offset, 1 d#
$01341655  push          $01341190 qword-offset
$0134165B  jmp           .+10 ( $0124A102 ) offset NEAR
FORTH> tt 1  ok
FORTH>
FWIW.
This shows how a non-parsing "TO" in iForth passes Anton's test, doesn't it?

I can guess, "TO" in iForth changes how the Forth text interpreter
translates the next lexeme.

Conceptually, something like this:

defer translate-lexeme
' translate-lexeme-default is translate-lexeme

: interpret
begin parse-name dup if translate-lexeme repeat 2drop
;

: to
[: ( sd.name -- | x sd.name -- )
['] translate-lexeme-default is translate-lexeme
find-name ?found ( nt | x nt )
name>action(to) ( xt | x xt )
state @ if compile, else execute then
;]
is translate-lexeme
; immediate


A parsing "to" can be defined via this variant as follows:

: to ( "name" -- | x "name" -- )
['] to execute parse-name evaluate
; immediate



My "test(to)" fails to detect this implementation variant for "to" as
non-parsing. A special test should be used to detect namely this variant.

Obviously, this non-parsing variant of "TO" fails when used with
"execute-parsing".

A similar bug win non-parsing "[if]" and "[else]" was fixed in Gforth in
2018, see <https://github.com/forthy42/gforth/issues/16>


--
Ruvim
a***@spenarnc.xs4all.nl
2024-08-01 12:01:06 UTC
Permalink
Post by Ruvim
Post by mhx
[..]
111 value x x . 111  ok
222 to cr .( Does TO parse? ) x x 222 = [if] .( No it doesn't!) [then]
Does TO parse? No it doesn't! ok
[..]
As does iForth.
You could argue that it's not a standard program because it contains a
deliberate ambiguous condition so a parsing TO would fail in some way
but it does demonstrate non-compliant behaviour.
 222 TO cr
should (I hope!) produce an exception (unless CR is redefined),
so this *definitely* fails and doesn't even finish the test.
I'm not sure that you can use a buggy program to test for an ambiguous
condition (looks like a top job for an eager lawyer). It would be
much better if the anomaly can be shown with a valid program.
When we want to apply a parsing word to a calculated string, we can use
"execute-parsing" (that can be defined in a standard way [1]). For a not
parsing "to", this standard-compliant method will fail.
: apply-compiling(to) ( sd.name -- )
[: postpone to ;] execute-parsing
;
This is foreseen. The standard stipulates that is not allowed
to POSTPONE TO

<SNIP>

If I redefine a CONSTANT SIZE , I rather use the standard
1,000,000,000 'SIZE >DFA !
instead of using a VALUE.
Post by Ruvim
--
Ruvim
--
Don't praise the day before the evening. One swallow doesn't make spring.
You must not say "hey" before you have crossed the bridge. Don't sell the
hide of the bear until you shot it. Better one bird in the hand than ten in
the air. First gain is a cat purring. - the Wise from Antrim -
minforth
2024-08-01 12:16:41 UTC
Permalink
Post by a***@spenarnc.xs4all.nl
If I redefine a CONSTANT SIZE , I rather use the standard
1,000,000,000 'SIZE >DFA !
instead of using a VALUE.
Variable constants should be in everyone's toolbox. :o)
a***@spenarnc.xs4all.nl
2024-08-02 09:40:19 UTC
Permalink
Post by minforth
Post by a***@spenarnc.xs4all.nl
If I redefine a CONSTANT SIZE , I rather use the standard
1,000,000,000 'SIZE >DFA !
instead of using a VALUE.
Variable constants should be in everyone's toolbox. :o)
That must be of course "non-standard".
Thanks.

Groetjes Albert
--
Don't praise the day before the evening. One swallow doesn't make spring.
You must not say "hey" before you have crossed the bridge. Don't sell the
hide of the bear until you shot it. Better one bird in the hand than ten in
the air. First gain is a cat purring. - the Wise from Antrim -
Ruvim
2024-08-01 18:37:35 UTC
Permalink
Post by a***@spenarnc.xs4all.nl
Post by Ruvim
Post by mhx
I'm not sure that you can use a buggy program to test for an ambiguous
condition (looks like a top job for an eager lawyer). It would be
much better if the anomaly can be shown with a valid program.
When we want to apply a parsing word to a calculated string, we can use
"execute-parsing" (that can be defined in a standard way [1]). For a not
parsing "to", this standard-compliant method will fail.
: apply-compiling(to) ( sd.name -- )
[: postpone to ;] execute-parsing
;
This is foreseen. The standard stipulates that is not allowed
to POSTPONE TO
Yes, I know. That is why I pointed to a standard-compliant
implementation for "postpone" [2].

In Forth-2012, you can define a new "postpone" using "get-order",
"traverse-wordlist", "name>compile", "compile," and "literal". And
nothing in the standard prohibits applying this word to "to".

[2]
<https://github.com/ForthHub/discussion/discussions/103#user-content-solution>


--
Ruvim
Gerry Jackson
2024-07-31 18:36:10 UTC
Permalink
Post by mhx
[..]
111 value x x . 111  ok
222 to cr .( Does TO parse? ) x x 222 = [if] .( No it doesn't!) [then]
Does TO parse? No it doesn't! ok
[..]
As does iForth.
Another silly thing that can be done in a flag setting Forth is

0 value x
2 to to to to x
--
Gerry
Anton Ertl
2024-07-31 16:14:53 UTC
Permalink
Post by Gerry Jackson
VFX Forth 64 for Windows x64
© MicroProcessor Engineering Ltd, 1998-2023
Version: 5.43 [build 4238]
Build date: 9 November 2023
Free dictionary = 6731782 bytes [6574kb]
111 value x x . 111 ok
222 to cr .( Does TO parse? ) x x 222 = [if] .( No it doesn't!) [then]
Does TO parse? No it doesn't! ok
Using a flag means that x could be on another line or even in another file.
You could argue that it's not a standard program because it contains a
deliberate ambiguous condition
Exactly, it's not a standard program, and no particular behaviour is
specified in the standard for this program.
Post by Gerry Jackson
so a parsing TO would fail in some way
but it does demonstrate non-compliant behaviour.
Given that it's not a standard program and no particular behaviour is
prescribed, the behaviour of VFX is compliant for this program.

There may be some way to construct a compliant program using FIND,
SEARCH-WORDLIST, TRAVERSE-WORDLIST, or FIND-NAME, where VFX does not
behave compliantly, though.

- 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: https://forth-standard.org/
EuroForth 2024: https://euro.theforth.net
Loading...