Now and then I happen to write code where a simple GOTO would be
just too convenient. The same situation happens now and then with
loops: BREAK to leave them, CONTINUE to jump back to loop start,
would come in oh so handy.
Guessing that I am not alone in this, how do you manage? Any magic tricks
up the sleeve to (ab)use standard Forth's control flow words? I don't
expect that someone parses Forth definitions twice just to resolve
backward jumps to preceding labels, or do we..?
PS I don't want to revive that old structured programming yawner:
"don't GOTO, it is evil"
On 2023-03-10 17:34, minf...@arcor.de wrote:
Now and then I happen to write code where a simple GOTO would be
just too convenient. The same situation happens now and then with
loops: BREAK to leave them, CONTINUE to jump back to loop start,
would come in oh so handy.
Guessing that I am not alone in this, how do you manage? Any magic tricks up the sleeve to (ab)use standard Forth's control flow words? I don't expect that someone parses Forth definitions twice just to resolve backward jumps to preceding labels, or do we..?
PS I don't want to revive that old structured programming yawner:It can look as:
"don't GOTO, it is evil"
: foo
[label a ]
...
if goto( b ) then
...
if goto( a ) then
...
[label b ]
;
This problem can be solved easier if:
1. we are limited by the cases when the Forth system uses the data stack
as the control-flow stack (so, it's an environmental dependency),
2. we don't cross DO ... LOOP and the definition boundaries.
Thus, a backward goto can be implemented using begin...again,
and a forward goto can be implemented using ahead...then.
We need to properly save names of goto/label and orig/dest into a list,
and properly resolve them. Also we need to nest this list on a new definition (or use special wrapper like with-goto{ ... }with-goto to
nest this list).
If we don't rely on the data stack, we have to redefine all control-flow words to know the controls depth in every point. After that we can use CS-ROLL to deepen orig/dest and CS-PICK to get it for resolving.
Now and then I happen to write code where a simple GOTO would be
just too convenient.
The same situation happens now and then with
loops: BREAK to leave them, CONTINUE to jump back to loop start,
would come in oh so handy.
Guessing that I am not alone in this, how do you manage?
"minf...@arcor.de" <minf...@arcor.de> writes:
Now and then I happen to write code where a simple GOTO would beWhen I implemented IIRC the unification of the Prolog implementation
just too convenient.
Aristo (in 1990), I at first used a very local view of the cases (and
the respective control flow), so I used gotos, and I thought that this
was necessary. My superior was not happy, and tasked me to eliminate
the gotos, so I drew a control-flow graph and found how to rearrange
the code to use whiles and ifs instead. And the result was nice, and reflected the structure of the data.
Since then, I have not found any need for a direct goto, maybe with
the very rare exception of leaving a nested search loop (and there a
lack of GOTO in Forth is usually worked around by using EXIT).
That leaves us with indirect branches, which are of course heavily
used for threaded code, and I also used it once for implementing a
finite state machine for a lexical scanner; but I think you don't mean indirect gotos, right.
Ruvim schrieb am Samstag, 11. März 2023 um 01:37:58 UTC+1:
On 2023-03-10 17:34, minf...@arcor.de wrote:
Now and then I happen to write code where a simple GOTO would beIt can look as:
just too convenient. The same situation happens now and then with
loops: BREAK to leave them, CONTINUE to jump back to loop start,
would come in oh so handy.
Guessing that I am not alone in this, how do you manage? Any magic tricks >>> up the sleeve to (ab)use standard Forth's control flow words? I don't
expect that someone parses Forth definitions twice just to resolve
backward jumps to preceding labels, or do we..?
PS I don't want to revive that old structured programming yawner:
"don't GOTO, it is evil"
: foo
[label a ]
...
if goto( b ) then
...
if goto( a ) then
...
[label b ]
;
This problem can be solved easier if:
1. we are limited by the cases when the Forth system uses the data stack
as the control-flow stack (so, it's an environmental dependency),
2. we don't cross DO ... LOOP and the definition boundaries.
Thus, a backward goto can be implemented using begin...again,
and a forward goto can be implemented using ahead...then.
We need to properly save names of goto/label and orig/dest into a list,
and properly resolve them. Also we need to nest this list on a new
definition (or use special wrapper like with-goto{ ... }with-goto to
nest this list).
If we don't rely on the data stack, we have to redefine all control-flow
words to know the controls depth in every point. After that we can use
CS-ROLL to deepen orig/dest and CS-PICK to get it for resolving.
Thanks for your ideas. I had been thinking that
- to jump out of a DO..LOOP one could put an UNLOOP before goto(
- labels targeted by more than one gotos would need some control flow
stack cleaning like LEAVE, but
- it would be difficult to not mess with other items on the cfs because
usually Forth does not mark those items in order to being able to allow
"extended" structures like BEGIN..WHILE..WHILE..REPEAT..THEN
With backward jumps like in
.. LABEL A ..
.. LABEL B ..
IF .. GOTO A ..
ELSE .. GOTO B ..
THEN ..
labels are "passive" i.e. they only put their address on the cfs, and
gotos are "active" i.e. they have to resolve the back jumps.
Whereas with forward jumps like in
.. IF .. GOTO A ..
ELSE .. GOTO B ..
THEN
.. LABEL A ..
.. LABEL B ..
gotos are "passive" i.e. they only put their address on the cfs, and
labels are "active" i.e. they have to resolve the forward jumps.
Now and then I happen to write code where a simple GOTO would be
just too convenient. The same situation happens now and then with
loops: BREAK to leave them, CONTINUE to jump back to loop start,
would come in oh so handy.
gotos are "passive" i.e. they only put their address on the cfs, and
labels are "active" i.e. they have to resolve the forward jumps.
On Saturday, March 11, 2023 at 8:25:54 AM UTC+1, minf...@arcor.de wrote:
gotos are "passive" i.e. they only put their address on the cfs, and labels are "active" i.e. they have to resolve the forward jumps.Yes - there is a distinction between jumping to an already defined label and one that has to be resolved later. Not only that - there may be multiple GOTOs
to be resolved.
I use a dedicated control stack that also holds the references - aka a "label"
that signifies the kind of control structure. It helps to trap certain errors and
trap them early IMHO.
Now - GOTO is a horrible match with that structure. E.g. if you jump out of a
BEGIN..REPEAT it will find an unresolved GOTO reference in the midst of WHILE and BEGIN references - probably even embedded in an IF.
That IF reference is also a problem with BREAK and CONTINUE. Again, I can't resolve the IF reference when there is still a BREAK (or CONTINUE) reference.
In case of BREAK I can't even resolve that, because I have no idea where REPEAT
or UNTIL is going to be. Of course, you can break the LIFO consistency of the
control stack - but that's called "dirty" in my book.
WHILE is not much of a problem, since all other constructs are resolved before
the next WHILE comes in (in 4tH anyway). And: WHILE is a "branch if zero" instruction - i.e. it has its conditional component built in, whereas BREAK and
CONTINUE are unconditional branches, always depending on an "IF".
I don't see the use of BREAK - it's perfectly serviced by WHILE. CONTINUE - may be,
but often an IF solves that problem. I got some C code lying around for some time,
but I never felt the need to apply it to the current branch.
The same for GOTO. It's neat, but more trouble than it's worth IMHO. If I really want
to jump back somewhere I just throw an exception. Works fine.
I find Antons CONTOF intriguing, though. Gotta contemplate that one a bit.
...
Good summary of the problems to expect when overloading the standard control structures
like Wil Baden did. Particularly DO..LOOPs can become nasty then. BEGIN.. loops can be
handled.
I believe it would be more straightforward to work on the CS control flow stack directly,
although I haven't tested the idea yet. CS-PICK and CS-ROLL would not be sufficient
as primitives, >CS and CS> would have to be introduced to complement them.
But then it would not be portable. Different Forth systems might not even use a CS
or might put address references (perhaps with flags) on the CS in a peculiar way.
CS elements like orig are even implementation dependent data types of unknown size or
unknown physical meaning, f.ex. like Ruvim's cons+lists concept.
On 13/03/2023 10:45 pm, minf...@arcor.de wrote:
...
Good summary of the problems to expect when overloading the standard control structures
like Wil Baden did. Particularly DO..LOOPs can become nasty then. BEGIN.. loops can be
handled.
I believe it would be more straightforward to work on the CS control flow stack directly,
although I haven't tested the idea yet. CS-PICK and CS-ROLL would not be sufficient
as primitives, >CS and CS> would have to be introduced to complement them.
But then it would not be portable. Different Forth systems might not even use a CSWil Baden was responsible for the CS words in ANS. My understanding is he didn't
or might put address references (perhaps with flags) on the CS in a peculiar way.
CS elements like orig are even implementation dependent data types of unknown size or
unknown physical meaning, f.ex. like Ruvim's cons+lists concept.
do it because forth was lacking control structures; but rather for completeness.
He wanted to be able to express control flow used in classical languages in forth.
He wasn't promoting GOTO et al. If I can find where he explained his position,
I'll post it. Closest to it I've found is this:
https://groups.google.com/g/comp.lang.forth/c/ZXGrOtI1gtM/m/6ZC_JUPyHy8J
And we should not allow to goto inside DO...LOOP
from outside (an error should be raised).
On Monday, March 13, 2023 at 2:26:01 AM UTC+1, Ruvim wrote:
[..]
And we should not allow to goto inside DO...LOOP
from outside (an error should be raised).
For symmetry reasons I have to ask: why not?
In TAOCP Knuth uses GOTO all the time, if not exclusively.
And we should not allow to goto inside DO...LOOP ...In TAOCP Knuth uses GOTO all the time, if not exclusively.
But if we jump inside DO-LOOP, it's impossible to correctly set the loop limit and loop index.
Marcel Hendrix <m...@iae.nl> writes:[..]
In TAOCP Knuth uses GOTO all the time, if not exclusively.The code in TAOCP is in assembly language, and his informal algorithm descriptions are unstructured (no DO loops), so he can't do much else.
Now and then I happen to write code where a simple GOTO would be
just too convenient. The same situation happens now and then with
loops: BREAK to leave them, CONTINUE to jump back to loop start,
would come in oh so handy.
Guessing that I am not alone in this, how do you manage? Any magic tricks
up the sleeve to (ab)use standard Forth's control flow words? I don't
expect that someone parses Forth definitions twice just to resolve
backward jumps to preceding labels, or do we..?
PS I don't want to revive that old structured programming yawner:
"don't GOTO, it is evil"
On Friday, March 10, 2023 at 12:34:57 PM UTC-5, minf...@arcor.de wrote:example of this. I find the goto code to be much more complex or maybe the right word is "messy".
Now and then I happen to write code where a simple GOTO would be
just too convenient. The same situation happens now and then with
loops: BREAK to leave them, CONTINUE to jump back to loop start,
would come in oh so handy.
Guessing that I am not alone in this, how do you manage? Any magic tricks up the sleeve to (ab)use standard Forth's control flow words? I don't expect that someone parses Forth definitions twice just to resolve backward jumps to preceding labels, or do we..?
PS I don't want to revive that old structured programming yawner:I didn't read all the replies, but... I won't say GOTO is evil. That's a strong word. I just never need it. It does make some things complicated, in terms of understanding what is going on in the code. I find the example Ruvim gave, to be a good
"don't GOTO, it is evil"
Maybe you can give a concrete example where a GOTO is a better solution than the standard control flow structures?
dxforth schrieb am Montag, 13. März 2023 um 14:03:11 UTC+1:
On 13/03/2023 10:45 pm, minf...@arcor.de wrote:
...Wil Baden was responsible for the CS words in ANS. My understanding is he didn't
Good summary of the problems to expect when overloading the standard control structures
like Wil Baden did. Particularly DO..LOOPs can become nasty then. BEGIN.. loops can be
handled.
I believe it would be more straightforward to work on the CS control flow stack directly,
although I haven't tested the idea yet. CS-PICK and CS-ROLL would not be sufficient
as primitives, >CS and CS> would have to be introduced to complement them. >>>
But then it would not be portable. Different Forth systems might not even use a CS
or might put address references (perhaps with flags) on the CS in a peculiar way.
CS elements like orig are even implementation dependent data types of unknown size or
unknown physical meaning, f.ex. like Ruvim's cons+lists concept.
do it because forth was lacking control structures; but rather for completeness.
He wanted to be able to express control flow used in classical languages in forth.
He wasn't promoting GOTO et al. If I can find where he explained his position,
I'll post it. Closest to it I've found is this:
https://groups.google.com/g/comp.lang.forth/c/ZXGrOtI1gtM/m/6ZC_JUPyHy8J
Should one really rummage in Wil Baden's past "responsibleness" and past position papers?
He may have changed his mind over time..
Be it. Having a GOTO is very handy sometimes. In my observation it is about 3/4 jumping forward
from one or more code positions to one single target, the rest is jumping backward to one
single target. More would mean spaghetti code; to be avoided.
This can be handled by only 4 simple words
GOTO> >LABEL to jump forward, several gotos allowed
LABEL< <GOTO to jump backward, several gotos allowed
Restriction: only one of each label type allowed per word definition.
Advantage: no namespace cluttering with label names, no interference with the CS because
this simple scheme can be realized with 2 separate small arrays/stacks for holding GOTO
jump locations.
On Monday, March 13, 2023 at 9:07:48 PM UTC+1, Ruvim wrote:
[..]
But if we jump inside DO-LOOP, it's impossible to correctly set the loop
limit and loop index.
Assume an optimizing compiler: the limit and index will be in registers.
Maybe you can give a concrete example where a GOTO is a better solution than the standard control flow structures?
Lorem Ipsum schrieb am Montag, 13. März 2023 um 22:33:17 UTC+1:example of this. I find the goto code to be much more complex or maybe the right word is "messy".
On Friday, March 10, 2023 at 12:34:57 PM UTC-5, minf...@arcor.de wrote:
Now and then I happen to write code where a simple GOTO would be
just too convenient. The same situation happens now and then with
loops: BREAK to leave them, CONTINUE to jump back to loop start,
would come in oh so handy.
Guessing that I am not alone in this, how do you manage? Any magic tricks
up the sleeve to (ab)use standard Forth's control flow words? I don't expect that someone parses Forth definitions twice just to resolve backward jumps to preceding labels, or do we..?
PS I don't want to revive that old structured programming yawner:I didn't read all the replies, but... I won't say GOTO is evil. That's a strong word. I just never need it. It does make some things complicated, in terms of understanding what is going on in the code. I find the example Ruvim gave, to be a good
"don't GOTO, it is evil"
Maybe you can give a concrete example where a GOTO is a better solution than the standard control flow structures?I use some non-standard idioms in my work that would be too distracting here.
But good overview with examples here:
https://en.wikipedia.org/wiki/Goto
Lorem Ipsum schrieb am Dienstag, 14. März 2023 um 05:21:55 UTC+1:example of this. I find the goto code to be much more complex or maybe the right word is "messy".
On Monday, March 13, 2023 at 6:14:40 PM UTC-4, minf...@arcor.de wrote:
Lorem Ipsum schrieb am Montag, 13. März 2023 um 22:33:17 UTC+1:
On Friday, March 10, 2023 at 12:34:57 PM UTC-5, minf...@arcor.de wrote:
Now and then I happen to write code where a simple GOTO would be just too convenient. The same situation happens now and then with loops: BREAK to leave them, CONTINUE to jump back to loop start, would come in oh so handy.
Guessing that I am not alone in this, how do you manage? Any magic tricks
up the sleeve to (ab)use standard Forth's control flow words? I don't
expect that someone parses Forth definitions twice just to resolve backward jumps to preceding labels, or do we..?
PS I don't want to revive that old structured programming yawner: "don't GOTO, it is evil"I didn't read all the replies, but... I won't say GOTO is evil. That's a strong word. I just never need it. It does make some things complicated, in terms of understanding what is going on in the code. I find the example Ruvim gave, to be a good
Maybe you can give a concrete example where a GOTO is a better solution than the standard control flow structures?I use some non-standard idioms in my work that would be too distracting here.
But good overview with examples here:Ok, so you don't have any useful examples. I get it. Thanks
https://en.wikipedia.org/wiki/Goto
I asked, because I've never run across an example that was not a good match for structured programming. But this is Forth we are talking about, where people do all sorts of weird things.Indeed are they not useful to you. What could you do with FOR> .. i" goto m1;" .. NEXT ...
while finding pivot or vector elements?
On Monday, March 13, 2023 at 6:14:40 PM UTC-4, minf...@arcor.de wrote:example of this. I find the goto code to be much more complex or maybe the right word is "messy".
Lorem Ipsum schrieb am Montag, 13. März 2023 um 22:33:17 UTC+1:
On Friday, March 10, 2023 at 12:34:57 PM UTC-5, minf...@arcor.de wrote:
Now and then I happen to write code where a simple GOTO would be
just too convenient. The same situation happens now and then with loops: BREAK to leave them, CONTINUE to jump back to loop start,
would come in oh so handy.
Guessing that I am not alone in this, how do you manage? Any magic tricks
up the sleeve to (ab)use standard Forth's control flow words? I don't expect that someone parses Forth definitions twice just to resolve backward jumps to preceding labels, or do we..?
PS I don't want to revive that old structured programming yawner: "don't GOTO, it is evil"I didn't read all the replies, but... I won't say GOTO is evil. That's a strong word. I just never need it. It does make some things complicated, in terms of understanding what is going on in the code. I find the example Ruvim gave, to be a good
Maybe you can give a concrete example where a GOTO is a better solution than the standard control flow structures?I use some non-standard idioms in my work that would be too distracting here.
But good overview with examples here:Ok, so you don't have any useful examples. I get it. Thanks
https://en.wikipedia.org/wiki/Goto
I asked, because I've never run across an example that was not a good match for structured programming. But this is Forth we are talking about, where people do all sorts of weird things.
I asked, because I've never run across an example that was not a good
match for structured programming. But this is Forth we are talking
about, where people do all sorts of weird things.
Forth's control flow words are usually implemented with lower level primitives like 0BRANCH, which is a conditional goto.
Lorem Ipsum <gnuarm.del...@gmail.com> writes:
I asked, because I've never run across an example that was not a good match for structured programming. But this is Forth we are talkingForth's control flow words are usually implemented with lower level primitives like 0BRANCH, which is a conditional goto.
about, where people do all sorts of weird things.
In C programming I've sometimes used goto to break out of multiple
levels of loops. That's an occasional thing though, and some other
languages make it easier to break from a named block instead of using
goto.
GCC also supports using labels as values, so you can goto an address.
Gforth uses that feature in its inner interpreter to get faster code
than you would get with a switch statement.
: @digit ( "num" -- adr ) bl word c@ $0F and cells tbl + ;
On Tuesday, March 14, 2023 at 8:31:37 AM UTC+1, Paul Rubin wrote:
[..]
In C programming I've sometimes used goto to break out of multiple[..]
levels of loops. That's an occasional thing though, and some other languages make it easier to break from a named block instead of using
goto.
I used it once.
Now and then I happen to write code where a simple GOTO would be
just too convenient. The same situation happens now and then with
loops: BREAK to leave them, CONTINUE to jump back to loop start,
would come in oh so handy.
Guessing that I am not alone in this, how do you manage? Any magic tricks
up the sleeve to (ab)use standard Forth's control flow words? I don't
expect that someone parses Forth definitions twice just to resolve
backward jumps to preceding labels, or do we..?
PS I don't want to revive that old structured programming yawner:
"don't GOTO, it is evil"
In C programming I've sometimes used goto to break out of multiple[..]
levels of loops. That's an occasional thing though, and some other
languages make it easier to break from a named block instead of using
goto.
On 14/03/2023 9:05 pm, dxforth wrote:
: @digit ( "num" -- adr ) bl word c@ $0F and cells tbl + ;bugfix
: @digit ( "num" -- adr ) bl word 1+ c@ $0F and cells tbl + ;
Add syntax sugar...
\ DX-Forth
create tbl 10 cells allot \ labels 0...9
: @digit ( "num" -- adr ) bl word c@ $0F and cells tbl + ;
: LABEL: ( "num" ) postpone BEGIN -1 bal +! @digit ! ; immediate
: GOTO ( "num" ) @digit @ postpone AGAIN 1 bal +! ; immediate
: bar label: 1 ." foobar" ;
: foo goto 1 ;
foo foobar ok
Your example above, is literally replacing BEGIN and AGAIN with other names.
How would you create GOTO> without using a second pass?
A one pass compile would need a list of GOTO>s for every label.
When you encounter the LABEL>: you would need to patch up every GOTO> in that list.
On 2023-03-14 17:27, Lorem Ipsum wrote:
[...]
Your example above, is literally replacing BEGIN and AGAIN with other names.
How would you create GOTO> without using a second pass?Imagine, you have "ahead2" and "then2" which use their own separate control-flow stack.
A one pass compile would need a list of GOTO>s for every label.
When you encounter the LABEL>: you would need to patch up every GOTO> in that list.
Then, a code like:
goto(x) ... goto(x) ... goto(x) ... label(x)
is equivalent to:
ahead2 ... ahead2 ... ahead2 ... then2 then2 then2
Obviously, you don't need two passes for that.
Also, you don't need both "GOTO>" and "<GOTO"
If a given label name already defined above, "goto" behaves like
"<goto", otherwise it behaves like "goto>".
Similar for "label": if the given name already defined in some "goto"
above, it resolves them (like "then2"), and removes the markers from the stack. After that it define new label for possible "goto" on this name bellow.
I asked, because I've never run across an example that was not a good
match for structured programming. But this is Forth we are talking
about, where people do all sorts of weird things.
On Tuesday, March 14, 2023 at 1:54:02 PM UTC-4, Ruvim wrote:
On 2023-03-14 17:27, Lorem Ipsum wrote:
[...]
Your example above, is literally replacing BEGIN and AGAIN with other names.Imagine, you have "ahead2" and "then2" which use their own separate
How would you create GOTO> without using a second pass?
A one pass compile would need a list of GOTO>s for every label.
When you encounter the LABEL>: you would need to patch up every GOTO> in that list.
control-flow stack.
Then, a code like:
goto(x) ... goto(x) ... goto(x) ... label(x)
is equivalent to:
ahead2 ... ahead2 ... ahead2 ... then2 then2 then2
Obviously, you don't need two passes for that.
How do you make label(x) work like multiple then2?
Also, you don't need both "GOTO>" and "<GOTO"
If a given label name already defined above, "goto" behaves like
"<goto", otherwise it behaves like "goto>".
Similar for "label": if the given name already defined in some "goto"
above, it resolves them (like "then2"), and removes the markers from the
stack. After that it define new label for possible "goto" on this name
bellow.
So you would need to add two labels for the same location, if it is being jumped to
from two different locations, one forward, and one back, no?
In a college class I wrote an assembler for the IBM360. There were lots
of tables for jumping and it was a PITA. Forth does it more simply,
in part, by using defined control flow structures that work using
a control flow stack. I can't think of a reason to toss that out.
I don't know why I am discussing this. I think GOTOs are not a useful construct and will not use them.
Lorem Ipsum <gnuarm.del...@gmail.com> writes:
I asked, because I've never run across an example that was not a good match for structured programming. But this is Forth we are talkingAlmost always--in my experience--goto shows up for exceptional code paths. Errors, or extraordiinary scenarios.
about, where people do all sorts of weird things.
Very often in Forth that ends up as throw/catch. Which, while not goto, is still an unstructured control flow change.
Andy Valencia
Home page: https://www.vsta.org/andy/
To contact me: https://www.vsta.org/contact/andy.html
On 2023-03-14 18:26, Lorem Ipsum wrote:
On Tuesday, March 14, 2023 at 1:54:02 PM UTC-4, Ruvim wrote:
On 2023-03-14 17:27, Lorem Ipsum wrote:
[...]
Your example above, is literally replacing BEGIN and AGAIN with other names.Imagine, you have "ahead2" and "then2" which use their own separate
How would you create GOTO> without using a second pass?
A one pass compile would need a list of GOTO>s for every label.
When you encounter the LABEL>: you would need to patch up every GOTO> in that list.
control-flow stack.
Then, a code like:
goto(x) ... goto(x) ... goto(x) ... label(x)
is equivalent to:
ahead2 ... ahead2 ... ahead2 ... then2 then2 then2
Obviously, you don't need two passes for that.
How do you make label(x) work like multiple then2?It can just pop all forward markers for name "x", and perform "then2"
for each of them.
After that it pushes a marker for name "x" for possible backward
references (like "begin2" does).
Also, you don't need both "GOTO>" and "<GOTO"
If a given label name already defined above, "goto" behaves like
"<goto", otherwise it behaves like "goto>".
Similar for "label": if the given name already defined in some "goto"
above, it resolves them (like "then2"), and removes the markers from the >> stack. After that it define new label for possible "goto" on this name
bellow.
So you would need to add two labels for the same location, if it is being jumped toNo. Note that "then2" does not add any label, it only resolves a forward reference.
from two different locations, one forward, and one back, no?
Let's consider another example:
goto(x) ... goto(x) ...
label(x) ...
goto(x) ... goto(x)
...
It's equivalent to:
ahead2 ... ahead2 ...
then2 then2 begin2 ...
[ cs2-dup ] again2 ... [ cs2-dup ] again2
...
[ cs2-drop ] \ at the end
As you can see, label(x) resolves all "ahead2", and adds only *one*
label (marker) for possible backward references (like "begin2" does).
Later we don't consume this marker from the stack, but make a copy and consumes this copy. We drop the original marker when we only sure that
no more backward references are possible (i.e., at the end of the definition).
Real labels behave like if you have a separate stack for each label
name, and per each marker type (orig and dest).
In my implementation [1], I have two stacks (actually lists) and copy or
pop a marker from the stack by a label name. So the result is the same
as you have a separate stack per each name. Don't sure what is simpler.
My implementation works in *any* reach enough standard Forth system that implements the control-flow stack using the data stack. The full package
in ZIP is also available [2].
[1] https://github.com/ruv/puzzle-in-forth/blob/main/extension/goto.fth
[2] https://github.com/ruv/puzzle-in-forth/archive/refs/heads/main.zip
In a college class I wrote an assembler for the IBM360. There were lotsImplementation of GOTO is more difficult than usual control-flow means
of tables for jumping and it was a PITA. Forth does it more simply,
in part, by using defined control flow structures that work using
a control flow stack. I can't think of a reason to toss that out.
in Forth. One simple stack is not enough for that. I employed an
uncertain number of stacks of two types ;-))
I don't know why I am discussing this. I think GOTOs are not a useful construct and will not use them.
I also don't use GOTO. To me, it's just an interesting puzzle.
Now and then I happen to write code where a simple GOTO would be
just too convenient.
On Tuesday, March 14, 2023 at 6:05:25 AM UTC-4, dxforth wrote:
Add syntax sugar...
\ DX-Forth
create tbl 10 cells allot \ labels 0...9
: @digit ( "num" -- adr ) bl word c@ $0F and cells tbl + ;
: LABEL: ( "num" ) postpone BEGIN -1 bal +! @digit ! ; immediate
: GOTO ( "num" ) @digit @ postpone AGAIN 1 bal +! ; immediate
: bar label: 1 ." foobar" ;
: foo goto 1 ;
foo foobar ok
So this works for jumping backwards, in a way that duplicates standard control flow features. How do you jump
forward? You would need a forward LABEL: and :GOTO. I guess :LABEL and GOTO: would suffice. I can see
situations where you want to jump forward and back to the same label, so you'd need,
GOTO> here
blah blah blah
<LABEL: here
LABEL>: here_too
blah blah blah
<GOTO here_too
Yes, there are reasons why gotos are seldom used in Forth... if ever. I realize my example above is absurd. But
then I'm not the one who says there is much use for GOTOs. Your example above, is literally replacing BEGIN and
AGAIN with other names. How would you create GOTO> without using a second pass? A one pass compile would need a
list of GOTO>s for every label. When you encounter the LABEL>: you would need to patch up every GOTO> in that
list.
Mostly, the problem is this code would likely be large for a single definition, with all the concomitant issues.
Rick C.--
minf...@arcor.de schrieb am Freitag, 10. März 2023 um 18:34:57 UTC+1:
Now and then I happen to write code where a simple GOTO would beHere's a very small but comprehensive solution for gforth 0.7.3
just too convenient.
including error checks and test suite (requires tester.fr).
\ ###### GOTO for gforth 0.7.3 ######
10 CONSTANT _#LBL \ max no. of labels/gotos, 0 <= id < #lbl
CREATE _LABELS _#LBL CELLS ALLOT \ struct array {targetadr}
CREATE _GOTOS _#LBL 2* CELLS ALLOT \ struct array {patchadr,id}
: _LABEL() ( id -- adr ) cells _labels + ;
: _GOTO() ( id -- adr ) 2* cells _gotos + ;
: _LASTGOTO ( -- adr ) _#lbl 1- _goto() ;
: _PARSE-ID ( "n" -- n id )
0. parse-name >number abort" no number" 2drop here ;
: _ADD-GOTO ( id adr -- )
over _#lbl u< 0= abort" bad goto id"
_lastgoto @ invert abort" gotos exhausted"
0 _goto() dup 1 _goto() _#lbl 1- 2* cells move 2! ;
\ system specific!
: GOTO ( "n" -- ) \ 0 <= n < #lbl
postpone branch _parse-id _add-goto here cell+ , ; IMMEDIATE
: _ADD-LABEL ( id adr -- )
over _#lbl u< 0= abort" bad label id"
swap _label() dup @ abort" duplicated label" ! ;
: L: ( "n" -- ) \ 0 <= n < #lbl
_parse-id _add-label ; IMMEDIATE
: _CLEAR-LABELS ( -- )
_labels _#lbl cells erase _gotos _#lbl 2* cells -1 fill ; IMMEDIATE
: _RESOLVE-GOTOS ( -- )
_#lbl 0 DO i _label() @ IF
_#lbl 0 DO i _goto() cell+ @ j = IF
j _label() @ i _goto() @ ! \ system specific!
THEN LOOP
THEN LOOP ; IMMEDIATE
\ system integration:
warnings @ 0 warnings !
: : postpone _clear-labels : ;
: ; postpone _resolve-gotos postpone ; ; IMMEDIATE
warnings !
0 [IF] \ ---------- TESTS ----------
REQUIRE tester.fr \ from standard test suite
T{ : GT1 \ forward
1 goto 5 2 L: 5 3 ; --> }T
T{ GT1 --> 1 3 }T
T{ : GT2 \ backward
1 goto 5 2 L: 6 3 exit 4 L: 5 goto 6 7 ; --> }T
T{ GT2 --> 1 3 }T
T{ : GT3 \ multiple labels ignored
L: 3 1 L: 4 2 L: 5 ; --> }T
T{ GT3 --> 1 2 }T
T{ : GT4 \ cross-over
1 goto 0 3 L: 1 4 exit 6 L: 0 2 goto 1 5 ; --> }T
T{ GT4 --> 1 2 4 }T
T{ : GT5 \ with IF..THEN..ELSE
IF goto 8 1 ELSE goto 9 2 THEN 3
L: 8 8 exit 4 L: 9 9 ; --> }T
T{ 1 GT5 --> 8 }T
T{ 0 GT5 --> 9 }T
T{ : GT6 \ with BEGIN..WHILE..REPEAT
5 BEGIN dup WHILE dup 3 = IF goto 9 THEN 1- REPEAT exit
L: 9 9 ; --> }T
T{ GT6 --> 3 9 }T
T{ : GT7 \ with DO..LOOP and CASE..ENDCASE
5 0 DO i CASE
1 OF 11 goto 0 ENDOF
3 OF 13 ENDOF
ENDCASE
L: 1
LOOP exit
L: 0 12 goto 1 ; --> }T
T{ GT7 --> 11 12 13 }T
T{ : GT8 \ multiple gotos forward
5 0 DO i CASE
1 OF 11 goto 0 ENDOF
3 OF 13 goto 0 ENDOF
ENDCASE
L: 1
LOOP exit
L: 0 12 goto 1 ; --> }T
T{ GT8 --> 11 12 13 12 }T
T{ : GT9 \ multiple gotos backward
5 0 DO i CASE
1 OF 11 goto 0 ENDOF
3 OF 13 goto 1 ENDOF
ENDCASE
L: 2
LOOP exit
L: 0 12 goto 2
L: 1 14 goto 2 ; --> }T
T{ GT9 --> 11 12 13 14 }T
sp0 @ sp! \ clean stack
[THEN]
\ ###### END ######
Adaptation to other Forths should be straightforward with using some carnal knowledge about how the other Forth implements unconditional branches
less control flow stack.
Only words affected would be GOTO and _RESOLVE-GOTOS where indicated.
In article <2c73807c-b1c9-4a37...@googlegroups.com>,
Lorem Ipsum <gnuarm.del...@gmail.com> wrote:
On Tuesday, March 14, 2023 at 6:05:25 AM UTC-4, dxforth wrote:
Add syntax sugar...
\ DX-Forth
create tbl 10 cells allot \ labels 0...9
: @digit ( "num" -- adr ) bl word c@ $0F and cells tbl + ;
: LABEL: ( "num" ) postpone BEGIN -1 bal +! @digit ! ; immediate
: GOTO ( "num" ) @digit @ postpone AGAIN 1 bal +! ; immediate
: bar label: 1 ." foobar" ;
: foo goto 1 ;
foo foobar ok
So this works for jumping backwards, in a way that duplicates standard control flow features. How do you jump
forward? You would need a forward LABEL: and :GOTO. I guess :LABEL and GOTO: would suffice. I can see
situations where you want to jump forward and back to the same label, so you'd need,
GOTO> here
blah blah blah
<LABEL: here
LABEL>: here_too
blah blah blah
<GOTO here_too
Yes, there are reasons why gotos are seldom used in Forth... if ever. I realize my example above is absurd. But
then I'm not the one who says there is much use for GOTOs. Your example above, is literally replacing BEGIN and
AGAIN with other names. How would you create GOTO> without using a second pass? A one pass compile would need a
list of GOTO>s for every label. When you encounter the LABEL>: you would need to patch up every GOTO> in that
list.
Mostly, the problem is this code would likely be large for a single definition, with all the concomitant issues.SEE IF
: IF '0BRANCH , (FORWARD ; IMMEDIATE OK
SEE THEN
: THEN FORWARD) ; IMMEDIATE OK
(FORWARD and (BACK serves with any control structure.
But they work *equally well* in assembly source code,
on the premise that the control structure of the code
is not unstructured.
Adding IF, UNTIL, .. is unnecessary, especially if
for an occasional code word.
On Tuesday, March 14, 2023 at 6:05:25 AM UTC-4, dxforth wrote:forward and back to the same label, so you'd need,
Add syntax sugar...So this works for jumping backwards, in a way that duplicates standard control flow features. How do you jump forward? You would need a forward LABEL: and :GOTO. I guess :LABEL and GOTO: would suffice. I can see situations where you want to jump
[...]
GOTO> hereHow would you create GOTO> without using a second pass? A one pass compile would need a list of GOTO>s for every label. When you encounter the LABEL>: you would need to patch up every GOTO> in that list.
blah blah blah
<LABEL: here
LABEL>: here_too
blah blah blah
<GOTO here_too
Yes, there are reasons why gotos are seldom used in Forth... if ever. I realize my example above is absurd. But then I'm not the one who says there is much use for GOTOs. Your example above, is literally replacing BEGIN and AGAIN with other names.
Mostly, the problem is this code would likely be large for a single definition, with all the concomitant issues.
Adaptation to other Forths should be straightforward with using some carnal knowledge about how the other Forth implements unconditional branches
less control flow stack.
\ system integration:
warnings @ 0 warnings !
: : postpone _clear-labels : ;
: ; postpone _resolve-gotos postpone ; ; IMMEDIATE
warnings !
Anton's CASE extensions
Since it's been mentioned,
labels for assembler are likely to cost more than structured. OTOH one can >do more with them which has saved me code.
On Wednesday, March 15, 2023 at 5:45:21 AM UTC-4, none albert wrote:
In article <2c73807c-b1c9-4a37...@googlegroups.com>,standard control flow features. How do you jump
Lorem Ipsum <gnuarm.del...@gmail.com> wrote:
On Tuesday, March 14, 2023 at 6:05:25 AM UTC-4, dxforth wrote:
Add syntax sugar...
\ DX-Forth
create tbl 10 cells allot \ labels 0...9
: @digit ( "num" -- adr ) bl word c@ $0F and cells tbl + ;
: LABEL: ( "num" ) postpone BEGIN -1 bal +! @digit ! ; immediate
: GOTO ( "num" ) @digit @ postpone AGAIN 1 bal +! ; immediate
: bar label: 1 ." foobar" ;
: foo goto 1 ;
foo foobar ok
So this works for jumping backwards, in a way that duplicates
and GOTO: would suffice. I can seeforward? You would need a forward LABEL: and :GOTO. I guess :LABEL
label, so you'd need,situations where you want to jump forward and back to the same
ever. I realize my example above is absurd. But
GOTO> here
blah blah blah
<LABEL: here
LABEL>: here_too
blah blah blah
<GOTO here_too
Yes, there are reasons why gotos are seldom used in Forth... if
example above, is literally replacing BEGIN andthen I'm not the one who says there is much use for GOTOs. Your
second pass? A one pass compile would need aAGAIN with other names. How would you create GOTO> without using a
would need to patch up every GOTO> in thatlist of GOTO>s for every label. When you encounter the LABEL>: you
list.SEE IF
Mostly, the problem is this code would likely be large for a single >definition, with all the concomitant issues.
: IF '0BRANCH , (FORWARD ; IMMEDIATE OK
SEE THEN
: THEN FORWARD) ; IMMEDIATE OK
(FORWARD and (BACK serves with any control structure.
But they work *equally well* in assembly source code,
on the premise that the control structure of the code
is not unstructured.
Adding IF, UNTIL, .. is unnecessary, especially if
for an occasional code word.
Sorry, I have no idea what point you are trying to make. What does
assembly language have to do with the issue?
Rick C.
dxforth <dxforth@gmail.com> writes:
...
Since it's been mentioned,
labels for assembler are likely to cost more than structured. OTOH one can >> do more with them which has saved me code.
It seems to me that the condition code in architectures like AMD64 and
ARM are the reason why we are not so happy with the standard Forth
control flow words in assembly language: combining several conditions complicates the control structure. Wil Baden has suggested using
ANDIF and ORIF, maybe they could make label-less control flow
comfortable enough. RISC-V (like its ancestors MIPS and Alpha) has no condition codes and the standard Forth control structures may work
better for RISC-V.
In article <58c70431-d1d4-4d50...@googlegroups.com>,
Lorem Ipsum <gnuarm.del...@gmail.com> wrote:
On Wednesday, March 15, 2023 at 5:45:21 AM UTC-4, none albert wrote:
In article <2c73807c-b1c9-4a37...@googlegroups.com>,standard control flow features. How do you jump
Lorem Ipsum <gnuarm.del...@gmail.com> wrote:
On Tuesday, March 14, 2023 at 6:05:25 AM UTC-4, dxforth wrote:
Add syntax sugar...
\ DX-Forth
create tbl 10 cells allot \ labels 0...9
: @digit ( "num" -- adr ) bl word c@ $0F and cells tbl + ;
: LABEL: ( "num" ) postpone BEGIN -1 bal +! @digit ! ; immediate
: GOTO ( "num" ) @digit @ postpone AGAIN 1 bal +! ; immediate
: bar label: 1 ." foobar" ;
: foo goto 1 ;
foo foobar ok
So this works for jumping backwards, in a way that duplicates
and GOTO: would suffice. I can seeforward? You would need a forward LABEL: and :GOTO. I guess :LABEL
label, so you'd need,situations where you want to jump forward and back to the same
ever. I realize my example above is absurd. But
GOTO> here
blah blah blah
<LABEL: here
LABEL>: here_too
blah blah blah
<GOTO here_too
Yes, there are reasons why gotos are seldom used in Forth... if
example above, is literally replacing BEGIN andthen I'm not the one who says there is much use for GOTOs. Your
AGAIN with other names. How would you create GOTO> without using a >second pass? A one pass compile would need aSEE IF
list of GOTO>s for every label. When you encounter the LABEL>: you >would need to patch up every GOTO> in that
list.
Mostly, the problem is this code would likely be large for a single >definition, with all the concomitant issues.
: IF '0BRANCH , (FORWARD ; IMMEDIATE OK
SEE THEN
: THEN FORWARD) ; IMMEDIATE OK
(FORWARD and (BACK serves with any control structure.
But they work *equally well* in assembly source code,
on the premise that the control structure of the code
is not unstructured.
Adding IF, UNTIL, .. is unnecessary, especially if
for an occasional code word.
Sorry, I have no idea what point you are trying to make. What does >assembly language have to do with the issue?The issue of calculating offsets for relative branches is the
same in Forth itself.
If restricting yourself to emulating controled programming in
Forth by branches and conditional branches, you have the same
situation in assembly programming. In other words all
information about a control flow stack can be mad to bear on it.
On 15/03/2023 4:27 am, Lorem Ipsum wrote:forward and back to the same label, so you'd need,
On Tuesday, March 14, 2023 at 6:05:25 AM UTC-4, dxforth wrote:
Add syntax sugar...So this works for jumping backwards, in a way that duplicates standard control flow features. How do you jump forward? You would need a forward LABEL: and :GOTO. I guess :LABEL and GOTO: would suffice. I can see situations where you want to jump
[...]
How would you create GOTO> without using a second pass? A one pass compile would need a list of GOTO>s for every label. When you encounter the LABEL>: you would need to patch up every GOTO> in that list.GOTO> here
blah blah blah
<LABEL: here
LABEL>: here_too
blah blah blah
<GOTO here_too
Yes, there are reasons why gotos are seldom used in Forth... if ever. I realize my example above is absurd. But then I'm not the one who says there is much use for GOTOs. Your example above, is literally replacing BEGIN and AGAIN with other names.
Mostly, the problem is this code would likely be large for a single definition, with all the concomitant issues.
Minforth has shown cost isn't overwhelming so it's worth comparing against other proposed schemes such as Anton's CASE extensions - which is better value for money. Folks are free to say they have no use for any of them, which would be the most cost effective of all. Since it's been mentioned, labels for assembler are likely to cost more than structured. OTOH one can do more with them which has saved me code. Whether one can make as good a case for labels in HLL *is* the question.
Do you have a simple way of handling the arbitrary nature of GOTOs and
labels without multiple passes or multiple tables? Sounds complex to
me.
Rick C.
On Wednesday, March 15, 2023 at 8:19:13 PM UTC-4, dxforth wrote:
...Minforth has shown cost isn't overwhelming so it's worth comparing against >> other proposed schemes such as Anton's CASE extensions - which is better
value for money. Folks are free to say they have no use for any of them,
which would be the most cost effective of all. Since it's been mentioned,
labels for assembler are likely to cost more than structured. OTOH one can >> do more with them which has saved me code. Whether one can make as good a
case for labels in HLL *is* the question.
I'm not clear. Is Forth a HLL to you?
On 17/03/2023 2:50 am, Lorem Ipsum wrote:
On Wednesday, March 15, 2023 at 8:19:13 PM UTC-4, dxforth wrote:
...Minforth has shown cost isn't overwhelming so it's worth comparing against
other proposed schemes such as Anton's CASE extensions - which is better >> value for money. Folks are free to say they have no use for any of them, >> which would be the most cost effective of all. Since it's been mentioned, >> labels for assembler are likely to cost more than structured. OTOH one can
do more with them which has saved me code. Whether one can make as good a >> case for labels in HLL *is* the question.
I'm not clear. Is Forth a HLL to you?In Forth one programs at a higher-level than machine code. What else can it be?
In article <346f83f6-e15d-43ac...@googlegroups.com>,
Lorem Ipsum <gnuarm.del...@gmail.com> wrote:
<SNIP>
Do you have a simple way of handling the arbitrary nature of GOTOs and >labels without multiple passes or multiple tables? Sounds complex toIt is quite simple. You mimic the control stack of Forth in assembler.
me.
You are likewise restricted to similar control structures as in Forth.
I have no intention to handle arbitrary GOTOs.
Often, when programmers try to use goofy control flow, it's a sign of poor modularization.
Using the fine scale modularization that is often used in Forth, gets around much of the issues that make people want to use GOTOs.
Sorry, you aren't making much sense to me. Assembly language that I've seen, has no structured flow control.
On Thursday, March 16, 2023 at 10:29:14 PM UTC-4, Lorem Ipsum wrote:
Sorry, you aren't making much sense to me. Assembly language that I've seen, has no structured flow control.Maybe you have never tried Forth Assembler?
All Forth Assemblers that I have seen have structured branching and looping extensions
and usually Labels as well for those sticky moments when it's faster to just jump.
Here is -TRAILING for example in my systems Forth Assembler.
HEX
CODE -TRAILING ( addr len -- addr len')
*SP TOS ADD,
TOS DEC,
R1 2000 LI,
BEGIN,
*TOS R1 CMPB,
EQ WHILE,
TOS DEC,
REPEAT,
*SP TOS SUB,
TOS INC,
NEXT,
ENDCODE
On Thursday, March 16, 2023 at 10:29:14 PM UTC-4, Lorem Ipsum wrote:
Sorry, you aren't making much sense to me. Assembly language that I've seen, has no structured flow control.Maybe you have never tried Forth Assembler?
All Forth Assemblers that I have seen have structured branching and looping extensions
and usually Labels as well for those sticky moments when it's faster to just jump.
Here is -TRAILING for example in my systems Forth Assembler.
HEX
CODE -TRAILING ( addr len -- addr len')
*SP TOS ADD,
TOS DEC,
R1 2000 LI,
BEGIN,
*TOS R1 CMPB,
EQ WHILE,
TOS DEC,
REPEAT,
*SP TOS SUB,
TOS INC,
NEXT,
ENDCODE
On Thursday, March 16, 2023 at 10:29:14 PM UTC-4, Lorem Ipsum wrote:
Sorry, you aren't making much sense to me. Assembly language that I've seen, has no structured flow control.
Maybe you have never tried Forth Assembler?
All Forth Assemblers that I have seen have structured branching and looping extensions
and usually Labels as well for those sticky moments when it's faster to just jump.
Here is -TRAILING for example in my systems Forth Assembler.
HEX
CODE -TRAILING ( addr len -- addr len')
*SP TOS ADD,
TOS DEC,
R1 2000 LI,
BEGIN,
*TOS R1 CMPB,
EQ WHILE,
TOS DEC,
REPEAT,
*SP TOS SUB,
TOS INC,
NEXT,
ENDCODE
F.ex. newer gforths push not 1 but 3 cells on the st=
ack
while compiling BEGIN ( C: -- dest ).
On Thursday, March 16, 2023 at 4:00:47 PM UTC-4, none albert wrote:
In article <346f83f6-e15d-43ac...@googlegroups.com>,
Lorem Ipsum <gnuarm.del...@gmail.com> wrote:
<SNIP>
It is quite simple. You mimic the control stack of Forth in assembler.
Do you have a simple way of handling the arbitrary nature of GOTOs and
labels without multiple passes or multiple tables? Sounds complex to
me.
You are likewise restricted to similar control structures as in Forth.
I have no intention to handle arbitrary GOTOs.
The Forth control stack does not deal with arbitrary GOTOs, both
forward and backward without some distinction, or a lot more complexity
than just the control stack. There are no control flow words in Forth
that can jump in either direction, that I'm aware of.
Of course, you can hack a way. But it's a big, clumsy oaf of a coding >solution.
This discussion seems to have gone haywire. Sure, anything is
possible. But GOTOs are just crap in Forth, just like any other
language.
Rick C.
P.S. unresolved GOTOs are ignored silently, to add checking, exchange
: _RESOLVE-GOTOS ( -- )
_#lbl 0 DO i _label() @ IF
_#lbl 0 DO i _goto() cell+ @ j = IF
j _label() @ i _goto() @ ! \ system specific!
-1 i _goto() !
THEN LOOP
THEN LOOP
_#lbl 0 DO i _goto() @ invert abort" unresolved goto" LOOP ;
On Friday, March 17, 2023 at 1:18:57 AM UTC-4, Brian Fox wrote:Don't laugh to hard. TMS9900.
On Thursday, March 16, 2023 at 10:29:14 PM UTC-4, Lorem Ipsum wrote:
Sorry, you aren't making much sense to me. Assembly language that I've seen, has no structured flow control.Maybe you have never tried Forth Assembler?
All Forth Assemblers that I have seen have structured branching and looping extensions
and usually Labels as well for those sticky moments when it's faster to just jump.
Here is -TRAILING for example in my systems Forth Assembler.
HEXAssembly code for what processor?
CODE -TRAILING ( addr len -- addr len')
*SP TOS ADD,
TOS DEC,
R1 2000 LI,
BEGIN,
*TOS R1 CMPB,
EQ WHILE,
TOS DEC,
REPEAT,
*SP TOS SUB,
TOS INC,
NEXT,
ENDCODE
--
Rick C.
+++ Get 1,000 miles of free Supercharging
+++ Tesla referral code - https://ts.la/richard11209
On 15/03/2023 9:41 pm, minforth wrote:
P.S. unresolved GOTOs are ignored silently, to add checking, exchange
: _RESOLVE-GOTOS ( -- )
_#lbl 0 DO i _label() @ IF
_#lbl 0 DO i _goto() cell+ @ j = IF
j _label() @ i _goto() @ ! \ system specific!
-1 i _goto() !
THEN LOOP
THEN LOOP
_#lbl 0 DO i _goto() @ invert abort" unresolved goto" LOOP ;
One loop should suffice. Scan GOTO array performing 2@. That gives label# and patch addr. If value is -1 exit loop; otherwise SWAP and use label# to index LABEL array then @. If value is zero then label was undefined; otherwise
patch addr.
dxforth schrieb am Freitag, 17. März 2023 um 12:03:35 UTC+1:
On 15/03/2023 9:41 pm, minforth wrote:
P.S. unresolved GOTOs are ignored silently, to add checking, exchange
: _RESOLVE-GOTOS ( -- )
_#lbl 0 DO i _label() @ IF
_#lbl 0 DO i _goto() cell+ @ j = IF
j _label() @ i _goto() @ ! \ system specific!
-1 i _goto() !
THEN LOOP
THEN LOOP
_#lbl 0 DO i _goto() @ invert abort" unresolved goto" LOOP ;
One loop should suffice. Scan GOTO array performing 2@. That gives label#
and patch addr. If value is -1 exit loop; otherwise SWAP and use label# to >> index LABEL array then @. If value is zero then label was undefined; otherwise
patch addr.
Thanks for optimizing some nanoseconds of compile time away,
be it even by reducing code clarity. ;-)
In article <3e537e06-c87e-453f...@googlegroups.com>,
Lorem Ipsum <gnuarm.del...@gmail.com> wrote:
On Thursday, March 16, 2023 at 4:00:47 PM UTC-4, none albert wrote:
In article <346f83f6-e15d-43ac...@googlegroups.com>,
Lorem Ipsum <gnuarm.del...@gmail.com> wrote:
<SNIP>
It is quite simple. You mimic the control stack of Forth in assembler.
Do you have a simple way of handling the arbitrary nature of GOTOs and >> >labels without multiple passes or multiple tables? Sounds complex to
me.
You are likewise restricted to similar control structures as in Forth.
I have no intention to handle arbitrary GOTOs.
The Forth control stack does not deal with arbitrary GOTOs, both
forward and backward without some distinction, or a lot more complexity >than just the control stack. There are no control flow words in Forth
that can jump in either direction, that I'm aware of.
Of course, you can hack a way. But it's a big, clumsy oaf of a coding >solution.
This discussion seems to have gone haywire. Sure, anything isFor your information. There is a habit in the Dutch Forth, e.g.
possible. But GOTOs are just crap in Forth, just like any other
language.
Willem Ouwerkerk, Marcel Hendrix, and others to *not* implement
jumps in assembler. Everything is done via structured assembler.
This is some of the target assembler code for noforth:
inside: code KEY?) ( -- f )
tos sp -) mov #1 UARTctrl0 & bit
#0 tos mov <>? if, #-1 tos mov then, NEXT end-code
inside: code KEY) ( -- c )
begin, #1 UARTctrl0 & .b bit <>? until,
tos sp -) mov uart-in & tos .b mov NEXT end-code
inside: code EMIT) ( c -- )
begin, #2 UARTctrl0 & .b bit <>? until,
tos uart-out & .b mov sp )+ tos mov NEXT end-code
This is handled by code like this
multi constant
2000 =? 2400 <>? 2800 cs? 2C00 cc?
and this
: if, ( cond -- ifloc ifcond ) dup ?cond if,id or here swap 2 allot ;
Why would structured programming work in Forth and not in assembler?
On Friday, March 17, 2023 at 1:49:15 AM UTC-4, Lorem Ipsum wrote:
On Friday, March 17, 2023 at 1:18:57 AM UTC-4, Brian Fox wrote:
On Thursday, March 16, 2023 at 10:29:14 PM UTC-4, Lorem Ipsum wrote:
Sorry, you aren't making much sense to me. Assembly language that I've seen, has no structured flow control.Maybe you have never tried Forth Assembler?
All Forth Assemblers that I have seen have structured branching and looping extensions
and usually Labels as well for those sticky moments when it's faster to just jump.
Here is -TRAILING for example in my systems Forth Assembler.
HEXAssembly code for what processor?
CODE -TRAILING ( addr len -- addr len')
*SP TOS ADD,
TOS DEC,
R1 2000 LI,
BEGIN,
*TOS R1 CMPB,
EQ WHILE,
TOS DEC,
REPEAT,
*SP TOS SUB,
TOS INC,
NEXT,
ENDCODE
--
Rick C.
+++ Get 1,000 miles of free SuperchargingDon't laugh to hard. TMS9900.
+++ Tesla referral code - https://ts.la/richard11209
But I have used structured Assemblers for Intel machines as well.
Just for useless puzzle playing ... :o)
Below is a GOTO mechanism for VfxForth. IMO the test code is the more interesting thing because it covers quite a number of possible cases. Standard test code from file TESTER.FR is attached
\ ###### GOTO for VfxForth using control flow items ######
I don't know CPU design, but I wonder if a Forth style processor, would benefit from a
"workspace" register for fast context switching within the memory blocks used for the
stacks. I suppose each workspace would need to hold the IP,SP,RP register values.
If those registers were actually running in the fast stack RAM it should allow a fast,
one register context switch.
supposed to be a performance advantage from fast register context switches.Don't laugh to hard. TMS9900.I used to have a couple of TMS99x processors. I bought a large PCB, 0.1" thick with the TMS9900 and I think 2708 EPROMs, a pair of course. I made a mod to work with 2716 EPROMs and planned for large parts.
I also rolled a board with the TMS9995 and a single EPROM with some I/O to control a Selectric typewriter. But it turned out, these typewriters wear and become a bit erratic in operation. So that never panned out.
When I started working with FPGAs, I realized the main "feature" of the TMS99x architecture, the registers in memory, was not destined for stardom. The inherent speed difference that had developed meant there was a huge performance penalty, when it was
Even when implemented in on-chip main storage RAM, the RAM interface presented a performance bottleneck. The speed of dedicated registers is not in the raw speed of access, but in being able to access registers in parallel with memory accesses.and the data stack, with one hard register for the top of stack and the block RAM read ports being second on stack. This gives great performance, with address calculations done directly on the register stack.
Much better is a stack oriented architecture which can have very fast access times, and have separate interfaces for as many operands as you'd like to pull off the stack at any one time. I typically split a block RAM for use as the return address stack
On Friday, March 17, 2023 at 5:23:10 PM UTC-4, Lorem Ipsum wrote:was supposed to be a performance advantage from fast register context switches.
Don't laugh to hard. TMS9900.I used to have a couple of TMS99x processors. I bought a large PCB, 0.1" thick with the TMS9900 and I think 2708 EPROMs, a pair of course. I made a mod to work with 2716 EPROMs and planned for large parts.
I also rolled a board with the TMS9995 and a single EPROM with some I/O to control a Selectric typewriter. But it turned out, these typewriters wear and become a bit erratic in operation. So that never panned out.
When I started working with FPGAs, I realized the main "feature" of the TMS99x architecture, the registers in memory, was not destined for stardom. The inherent speed difference that had developed meant there was a huge performance penalty, when it
stack and the data stack, with one hard register for the top of stack and the block RAM read ports being second on stack. This gives great performance, with address calculations done directly on the register stack.Even when implemented in on-chip main storage RAM, the RAM interface presented a performance bottleneck. The speed of dedicated registers is not in the raw speed of access, but in being able to access registers in parallel with memory accesses.
Much better is a stack oriented architecture which can have very fast access times, and have separate interfaces for as many operands as you'd like to pull off the stack at any one time. I typically split a block RAM for use as the return address
That's a pretty clever design for I/O intensive applications. Neat.
For clarity, the 2nd on stack doubles as the stack item or it can read I/O? Is there a bit switch somewhere to change its function to read to stack?
Cool that you know the 9900. Yes the "workspace" concept was intriguing 50 years ago but
in retrospect it was not the solution to the problem of sub-routine nesting. Stacks win that one.
But it is amazing for context switching.
I don't know CPU design, but I wonder if a Forth style processor, would benefit from a
"workspace" register for fast context switching within the memory blocks used for the
stacks. I suppose each workspace would need to hold the IP,SP,RP register values.
If those registers were actually running in the fast stack RAM it should allow a fast,
one register context switch.
Would using stack RAM for the primary registers be to much performance hit?
Of course it might be better to just make more small cores. :-)
On Saturday, March 18, 2023 at 3:49:04 PM UTC+1, Brian Fox wrote:Ok. Thanks for that insight. Nice to know that some of my thoughts have merit. :-)
[..]
I don't know CPU design, but I wonder if a Forth style processor, would benefit from aThat is how INMOS's transputer worked. We wrote tForth for it, and it was, for
"workspace" register for fast context switching within the memory blocks used for the
stacks. I suppose each workspace would need to hold the IP,SP,RP register values.
If those registers were actually running in the fast stack RAM it should allow a fast,
one register context switch.
a (very small) timewindow, quite hot. I lost interest when the T9000 did not materialize. I guess the transputer's ideas (1. CSP, 2. I/O should scale with
computing horsepower) will resurface.
-marcel
[...]The smallest FPGA RAM blocks are ~256 x 16b, and using a RAM block for each stack is likely, so a 2-4b task register could support 4-16 tasks/contexts.
I don't know CPU design, but I wonder if a Forth style processor, would benefit from a
"workspace" register for fast context switching within the memory blocks used for the
stacks. I suppose each workspace would need to hold the IP,SP,RP register values.
If those registers were actually running in the fast stack RAM it should allow a fast,
one register context switch.
Would using stack RAM for the primary registers be to much performance hit?The primary registers would then most likely need to be pushed sequentially
Of course it might be better to just make more small cores. :-)Probably not in FPGA, because of the size of the on-chip RAM blocks.
On Saturday, March 18, 2023 at 3:49:04 PM UTC+1, Brian Fox wrote:
[..]
I don't know CPU design, but I wonder if a Forth style processor, would benefit from aThat is how INMOS's transputer worked. We wrote tForth for it, and it was, for
"workspace" register for fast context switching within the memory blocks used for the
stacks. I suppose each workspace would need to hold the IP,SP,RP register values.
If those registers were actually running in the fast stack RAM it should allow a fast,
one register context switch.
a (very small) timewindow, quite hot. I lost interest when the T9000 did not materialize. I guess the transputer's ideas (1. CSP, 2. I/O should scale with
computing horsepower) will resurface.
On Friday, March 17, 2023 at 5:23:10 PM UTC-4, Lorem Ipsum wrote:was supposed to be a performance advantage from fast register context switches.
Don't laugh to hard. TMS9900.I used to have a couple of TMS99x processors. I bought a large PCB, 0.1" thick with the TMS9900 and I think 2708 EPROMs, a pair of course. I made a mod to work with 2716 EPROMs and planned for large parts.
I also rolled a board with the TMS9995 and a single EPROM with some I/O to control a Selectric typewriter. But it turned out, these typewriters wear and become a bit erratic in operation. So that never panned out.
When I started working with FPGAs, I realized the main "feature" of the TMS99x architecture, the registers in memory, was not destined for stardom. The inherent speed difference that had developed meant there was a huge performance penalty, when it
stack and the data stack, with one hard register for the top of stack and the block RAM read ports being second on stack. This gives great performance, with address calculations done directly on the register stack.Even when implemented in on-chip main storage RAM, the RAM interface presented a performance bottleneck. The speed of dedicated registers is not in the raw speed of access, but in being able to access registers in parallel with memory accesses.
Much better is a stack oriented architecture which can have very fast access times, and have separate interfaces for as many operands as you'd like to pull off the stack at any one time. I typically split a block RAM for use as the return address
That's a pretty clever design for I/O intensive applications. Neat.
For clarity, the 2nd on stack doubles as the stack item or it can read I/O? Is there a bit switch somewhere to change its function to read to stack?
Cool that you know the 9900. Yes the "workspace" concept was intriguing 50 years ago but
in retrospect it was not the solution to the problem of sub-routine nesting. Stacks win that one.
But it is amazing for context switching.
I don't know CPU design, but I wonder if a Forth style processor, would benefit from a
"workspace" register for fast context switching within the memory blocks used for the
stacks. I suppose each workspace would need to hold the IP,SP,RP register values.
If those registers were actually running in the fast stack RAM it should allow a fast,
one register context switch.
Would using stack RAM for the primary registers be to much performance hit?
Of course it might be better to just make more small cores. :-)
On Saturday, March 18, 2023 at 11:11:40 AM UTC-4, Marcel Hendrix wrote:with dozens of processors. I believe it was delivered, but it was to a community where you never hear about it again. I don't think Transputers were used again. At least I didn't hear about them. Without continuing advancements in the devices, there is
On Saturday, March 18, 2023 at 3:49:04 PM UTC+1, Brian Fox wrote:Don't bet on it. If there were value to these ideas, they would have come back long ago.
[..]
I don't know CPU design, but I wonder if a Forth style processor, would benefit from aThat is how INMOS's transputer worked. We wrote tForth for it, and it was, for
"workspace" register for fast context switching within the memory blocks used for the
stacks. I suppose each workspace would need to hold the IP,SP,RP register values.
If those registers were actually running in the fast stack RAM it should allow a fast,
one register context switch.
a (very small) timewindow, quite hot. I lost interest when the T9000 did not
materialize. I guess the transputer's ideas (1. CSP, 2. I/O should scale with
computing horsepower) will resurface.
Many years ago (maybe 25?) I worked on a government project for a DSP application that used Transputers. At first they were going to use COTS computer boards with conventional software. Someone convinced them to use Transputers. It was a large system
Hmmm... I still have one or two of those, somewhere. I remember they came with a fractal program which I didn't understand. Someone in a Google Group explained the colors represent the number of calculation cycles it takes to arrive at a stable valueor running off to infinity giving black.
I expect there's a game of Life out there somewhere. Isn't Life on every CPU ever made?
<snip>Would using stack RAM for the primary registers be to much performance hit?snip>
I'm talking about a stack processor which has no registers other than the stacks,
the program counter, the instruction register and the individual bits that make up
the processor status word. There's no real performance hit from this in an FPGA.
The first on stack *is* a register, and the block RAM is pretty fast for writing and
not slow for reading if it is clocked on the output.
On Saturday, March 18, 2023 at 12:34:04 PM UTC-4, Lorem Ipsum wrote:
<snip>Would using stack RAM for the primary registers be to much performance hit?snip>
I'm talking about a stack processor which has no registers other than the stacks,
the program counter, the instruction register and the individual bits that make up
the processor status word. There's no real performance hit from this in an FPGA.
The first on stack *is* a register, and the block RAM is pretty fast for writing and
not slow for reading if it is clocked on the output.
Thanks for the clarification on the rest.
So we have top of the DATA stack in a register. Got that part.
But how does the machine know what is the "next on stack" location in the block RAM?
My little brain thinks it needs a register somewhere to hold an index value or
a circular counter or something like that.
Same question for the return stack.
I find Antons CONTOF intriguing, though. Gotta contemplate that one a bit.
On 18/03/2023 3:23 am, minforth wrote:
Just for useless puzzle playing ... :o)
Below is a GOTO mechanism for VfxForth. IMO the test code is the more interesting thing because it covers quite a number of possible cases. Standard test code from file TESTER.FR is attached
\ ###### GOTO for VfxForth using control flow items ######Resolving GOTOs on the fly results in less table usage at the expense
of more code. I preferred the original strategy (though not the GOTO resolution which was pointlessly backwards). As there are usually more
GOTO than labels I changed the proportions. Got mine down to 352 bytes
(6 labels, 10 GOTO) ... about what it's worth. It will now go into a
file with other miscellaneous routines along with the ANS CS words.
Itch scratched.
On Saturday, March 18, 2023 at 11:11:40 AM UTC-4, Marcel Hendrix wrote:
On Saturday, March 18, 2023 at 3:49:04 PM UTC+1, Brian Fox wrote:would benefit from a
[..]
I don't know CPU design, but I wonder if a Forth style processor,
blocks used for the"workspace" register for fast context switching within the memory
register values.stacks. I suppose each workspace would need to hold the IP,SP,RP
should allow a fast,If those registers were actually running in the fast stack RAM it
was, forone register context switch.That is how INMOS's transputer worked. We wrote tForth for it, and it
a (very small) timewindow, quite hot. I lost interest when the T9000 did not >> materialize. I guess the transputer's ideas (1. CSP, 2. I/O shouldscale with
computing horsepower) will resurface.
Don't bet on it. If there were value to these ideas, they would have
come back long ago.
Many years ago (maybe 25?) I worked on a government project for a DSP >application that used Transputers. At first they were going to use
COTS computer boards with conventional software. Someone convinced
them to use Transputers. It was a large system with dozens of
processors. I believe it was delivered, but it was to a community
where you never hear about it again. I don't think Transputers were
used again. At least I didn't hear about them. Without continuing >advancements in the devices, there is never a future in alternative >architectures. I think they ran at 25 MHz. How long was that a
cutting edge clock rate? I suppose you could emulate a few dozen of
them in an FPGA for less than the chips cost back then.
Rick C.
In article <694431bd-9ae2-4ed9...@googlegroups.com>,
Lorem Ipsum <gnuarm.del...@gmail.com> wrote:
On Saturday, March 18, 2023 at 11:11:40 AM UTC-4, Marcel Hendrix wrote: >> On Saturday, March 18, 2023 at 3:49:04 PM UTC+1, Brian Fox wrote:
[..]scale with
I don't know CPU design, but I wonder if a Forth style processor, >would benefit from aThat is how INMOS's transputer worked. We wrote tForth for it, and it >was, for
"workspace" register for fast context switching within the memory >blocks used for the
stacks. I suppose each workspace would need to hold the IP,SP,RP >register values.
If those registers were actually running in the fast stack RAM it >should allow a fast,
one register context switch.
a (very small) timewindow, quite hot. I lost interest when the T9000 did not
materialize. I guess the transputer's ideas (1. CSP, 2. I/O should
computing horsepower) will resurface.
Don't bet on it. If there were value to these ideas, they would haveThere are important counter examples for this. The USA should have
come back long ago.
50 year head start in Thorium reactors, now they are 10 years
behind China. The wave around 3D printing started 20 years late,
because the patent holders were holding back.
Remember white leds? These were following blue leds. An obstinate
Japanese inventor took the job on. Now white leds are everywhere.
We are stuck with USA fighter jets in Europe. The fighter jets
designed by Europeans were much better, but politics got in the way.
I agree with Marcel Hendrix that a 1Ghz transputer is an opportunity
that a venture capitalist should jump at. With a considerable
chance of succes.
Remember there are no real processors going substantially
going beyond 1 Ghz.
Supercomputers are parallel, AMD/INTEL or now ARM.
So transputers with an inherent superior connectivity, and a
corresponding software development could win the day.
It boggles the
mind what could have been 30 years of improvement to the t900.
Many years ago (maybe 25?) I worked on a government project for a DSP >application that used Transputers. At first they were going to useIn 1990 I was at Shell, geological modelling. The functionality
COTS computer boards with conventional software. Someone convinced
them to use Transputers. It was a large system with dozens of
processors. I believe it was delivered, but it was to a community
where you never hear about it again. I don't think Transputers were
used again. At least I didn't hear about them. Without continuing >advancements in the devices, there is never a future in alternative >architectures. I think they ran at 25 MHz. How long was that a
cutting edge clock rate? I suppose you could emulate a few dozen of
them in an FPGA for less than the chips cost back then.
presented by transputers was comparable with the CRAY.
(they had one there in Rijswijk). The transputers were at a cost
in order of magnitude lower.
dxforth schrieb am Samstag, 18. März 2023 um 00:30:32 UTC+1:
On 18/03/2023 3:23 am, minforth wrote:
Just for useless puzzle playing ... :o)Resolving GOTOs on the fly results in less table usage at the expense
Below is a GOTO mechanism for VfxForth. IMO the test code is the more
interesting thing because it covers quite a number of possible cases.
Standard test code from file TESTER.FR is attached
\ ###### GOTO for VfxForth using control flow items ######
of more code. I preferred the original strategy (though not the GOTO
resolution which was pointlessly backwards). As there are usually more
GOTO than labels I changed the proportions. Got mine down to 352 bytes
(6 labels, 10 GOTO) ... about what it's worth. It will now go into a
file with other miscellaneous routines along with the ANS CS words.
Itch scratched.
Got an overdose of itching powder? :o)
There's a bit more scratching in the background of the GOTO/LABEL mechanism. It lays the groundwork to simply add nested functions or closures to Forth without changing the internal compiler. Just imagine GOTO not compiling
a branch but a colon plus upvalues, and LABEL a semis and some cleanup.
In the late 80s the state of the art CPU was the Intel 486. I worked at a facility that made supercomputers, in Herndon, VA., 100 MFLOPS. We sold many
machines to the geophysical modeling industry, mostly to support oil exploration. Transputers were not relevant to that industry. There was zero software
to support using Transputers as supercomputers. It was some years later when I worked on the multiprocessor Transputer design that had to write all the
software from the ground up.
Rick C.
In article <0ea8ed03-4da5-4a42...@googlegroups.com>,
Lorem Ipsum <gnuarm.del...@gmail.com> wrote:
In the late 80s the state of the art CPU was the Intel 486. I worked at a facility that made supercomputers, in Herndon, VA., 100 MFLOPS. We sold manyI worked at Rijswijk the most important research centre of Shell worldwide, at geological modelling with transputers in 1990.
machines to the geophysical modeling industry, mostly to support oil exploration. Transputers were not relevant to that industry. There was zero software
to support using Transputers as supercomputers. It was some years later when I worked on the multiprocessor Transputer design that had to write all the
software from the ground up.
I can testify that transputers were relevant. Of course it was bleeding edge and it was developed there and then. The models were certainly more
advanced than what you're working at, but at I'm not at liberty to
disclose details. The oil fields in the North Sea are stratified in a complicated way, more so that e.g. Nigeria.
Color was essential, but not readily available on the VAX at this time.
The project was important enough that Shell put extreme pressure on DEC
for cooperation, cancelling orders.
I guess the transputer's ideas (1. CSP, 2. I/O should scale w=
ith
computing horsepower) will resurface.
On 13/03/2023 9:30 pm, Hans Bezemer wrote:
I find Antons CONTOF intriguing, though. Gotta contemplate that one a bit.
It's syntax sugar for:
BEGIN BEGIN BEGIN ( BEGIN)
WHILE ... REPEAT
WHILE ... REPEAT
WHILE ... REPEAT
...
( AGAIN)
In article <694431bd-9ae2-4ed9-b336-e513f09f5078n@googlegroups.com>,
Lorem Ipsum <gnuarm.deletethisbit@gmail.com> wrote:
On Saturday, March 18, 2023 at 11:11:40 AM UTC-4, Marcel Hendrix wrote:
That is how INMOS's transputer worked. We wrote tForth for it, and it >>was, forscale with
a (very small) timewindow, quite hot. I lost interest when the T9000 did not
materialize. I guess the transputer's ideas (1. CSP, 2. I/O should
computing horsepower) will resurface.
Don't bet on it. If there were value to these ideas, they would have
come back long ago.
There are important counter examples for this. The USA should have
50 year head start in Thorium reactors, now they are 10 years
behind China.
albert@cherry.(none) (albert) writes:
In article <694431bd-9ae2-4ed9-b336-e513f09f5078n@googlegroups.com>,
Lorem Ipsum <gnuarm.deletethisbit@gmail.com> wrote:
On Saturday, March 18, 2023 at 11:11:40 AM UTC-4, Marcel Hendrix wrote: >>>> That is how INMOS's transputer worked. We wrote tForth for it, and it >>>was, for
a (very small) timewindow, quite hot. I lost interest when the T9000 did not
materialize. I guess the transputer's ideas (1. CSP, 2. I/O should >>>scale with
computing horsepower) will resurface.
Don't bet on it. If there were value to these ideas, they would have >>>come back long ago.
There are important counter examples for this. The USA should have
50 year head start in Thorium reactors, now they are 10 years
behind China.
Oh boy, justifying one wishful-thinking technology with another one.
One can point to eventually successful technologies that had their ups
and downs in earlier times (there is even the ><https://en.wikipedia.org/wiki/Gartner_hype_cycle> that describes
this), but there are also lots of failed technologies, some of which
still have a loyal fan base.
Thorium is a case in point. It's not fissile, but you have to breed
it into fissile U233 to make any use of it. We live at a time when
fissile U235 is so plentyful that the USA deems it even too costly to
use fissile Pu239 in their nuclear power stations, and wants to fulfil
their disarmament obligations by blending the Pu239 from their
dismantled bombs with nuclear waste and depositing that. Thorium is
not going to become important until U235 becomes rare, and probably
not even then: There is lots of depleted Uranium already in pure form
which can serve the same purpose, why would one mine Thorium?
--
- anton
Marcel Hendrix <m...@iae.nl> writes:[..]
I guess the transputer's ideas (1. CSP, 2. I/O should scale with
computing horsepower) will resurface.
A big downside of the transputer approach is that it has distributed
memory (each CPU has its own memory and cannot access other CPU's
memory).
dxforth <dxforth@gmail.com> writes:
On 13/03/2023 9:30 pm, Hans Bezemer wrote:
It's syntax sugar for:
I find Antons CONTOF intriguing, though. Gotta contemplate that one a bit. >>
BEGIN BEGIN BEGIN ( BEGIN)
WHILE ... REPEAT
WHILE ... REPEAT
WHILE ... REPEAT
...
( AGAIN)
Only if you don't use ENDOF nor ENDCASE. But yes, you can transform
Eaker's CASE into IF ELSE THEN, and Eaker's CASE extended with ?OF,
CONTOF, and NEXT-CASE into standard Forth code. I find the extended
Eaker's CASE easier to write and read, however.
albert@cherry.(none) (albert) writes:
In article <694431bd-9ae2-4ed9-b336-e513f09f5078n@googlegroups.com>,
Lorem Ipsum <gnuarm.deletethisbit@gmail.com> wrote:
On Saturday, March 18, 2023 at 11:11:40 AM UTC-4, Marcel Hendrix wrote: >>>> That is how INMOS's transputer worked. We wrote tForth for it, and it
was, for
a (very small) timewindow, quite hot. I lost interest when the T9000 did notscale with
materialize. I guess the transputer's ideas (1. CSP, 2. I/O should
computing horsepower) will resurface.
Don't bet on it. If there were value to these ideas, they would have
come back long ago.
There are important counter examples for this. The USA should have
50 year head start in Thorium reactors, now they are 10 years
behind China.
Oh boy, justifying one wishful-thinking technology with another one.
One can point to eventually successful technologies that had their ups
and downs in earlier times (there is even the <https://en.wikipedia.org/wiki/Gartner_hype_cycle> that describes
this), but there are also lots of failed technologies, some of which
still have a loyal fan base.
In article <2023Apr2.194217@mips.complang.tuwien.ac.at>,
Anton Ertl <anton@mips.complang.tuwien.ac.at> wrote:
One can point to eventually successful technologies that had their ups
and downs in earlier times (there is even the >><https://en.wikipedia.org/wiki/Gartner_hype_cycle> that describes
this), but there are also lots of failed technologies, some of which
still have a loyal fan base.
Thorium was not a failed technology per se. At the time nobody was
really interested in nuclear energy, only nuclear bombs.
As far as I can tell, the Chinese are past the point of research and >deploying them commercially.
On Sunday, April 2, 2023 at 7:42:09=E2=80=AFPM UTC+2, Anton Ertl wrote:
Marcel Hendrix <m...@iae.nl> writes:[..]
I guess the transputer's ideas (1. CSP, 2. I/O should scale with
computing horsepower) will resurface.
A big downside of the transputer approach is that it has distributed
memory (each CPU has its own memory and cannot access other CPU's
memory).
The T9000 has shared memory ('The T9000 transputer hardware
reference manual', p26, Chapt.5.2.1). Shared areas can be set to >non-cacheable.
My issue with GOTO and LABEL in Forth is their compatiblity with local variables. E.g. my Forth, zeptoforth, has support for local variables such that they would be highly incompatible with GOTO and LABEL. In particular
the issue is that it has block-scoped local variables, where local variables can be limited to a particular block scope. Consider what would happen with this:
: foo ( -- )
goto bar
begin
1 { my-local }
label bar
my-local .
true until
;
This is further complicated by the storing of local variables on the return stack, where they are pushed by { ... } and dropped when they leave the current scope. The above example would not simply output garbage but
in many cases would simply crash afterwards due to dropping the return address from the return stack because my-local would have never been
pushed onto the return stack in the first place.
Another problem is when you try to combine them with do-loops. Consider
the following:
: baz ( -- )
goto quux
10 0 ?do
label quux
i .
loop
;
See the problem here?
My issue with GOTO and LABEL in Forth is their compatiblity with local variables. E.g. my Forth, zeptoforth, has support for local variables such that they would be highly incompatible with GOTO and LABEL. In particular the issue is that it has block-scoped local variables, where local variables can be limited to a particular block scope. Consider what would happen with this:
: foo ( -- )
goto bar
begin
1 { my-local }
label bar
my-local .
true until
;
This is further complicated by the storing of local variables on the return stack, where they are pushed by { ... } and dropped when they leave the current scope. The above example would not simply output garbage but
in many cases would simply crash afterwards due to dropping the return address from the return stack because my-local would have never been
pushed onto the return stack in the first place.
Another problem is when you try to combine them with do-loops. Consider
the following:
: baz ( -- )
goto quux
10 0 ?do
label quux
i .
loop
;
See the problem here?
Travis
On Monday, April 3, 2023 at 3:29:35 PM UTC-5, minforth wrote:
Travis Bemann schrieb am Montag, 3. April 2023 um 21:53:08 UTC+2:
My issue with GOTO and LABEL in Forth is their compatiblity with local variables. E.g. my Forth, zeptoforth, has support for local variables such
that they would be highly incompatible with GOTO and LABEL. In particular
the issue is that it has block-scoped local variables, where local variables
can be limited to a particular block scope. Consider what would happen with
this:
: foo ( -- )
goto bar
begin
1 { my-local }
label bar
my-local .
true until
;
This is further complicated by the storing of local variables on the return
stack, where they are pushed by { ... } and dropped when they leave the current scope. The above example would not simply output garbage but
in many cases would simply crash afterwards due to dropping the return address from the return stack because my-local would have never been pushed onto the return stack in the first place.
Another problem is when you try to combine them with do-loops. Consider the following:
: baz ( -- )
goto quux
10 0 ?do
label quux
i .
loop
;
See the problem here?
Sure. My advice: don't do it. It would be akin to exiting do-loops without UNLOOP.I actually made it so that it is safe to exit DO-LOOPs without UNLOOP because
I made EXIT an immediate word that is smart enough to check the compile-time local variable stack, on which the DO-LOOP control variables are recorded, and drop
everything pushed onto it from the return stack prior to compiling a POP {PC}
instruction. I kept UNLOOP for the sake of compatibility with existing code but it
is now an no-op. (Note that all of this is not true when zeptoforth is first being
built, where it uses more traditional DO-LOOP words, but it replaces those words
at the same time as when it sets up the local variable stack.)
Travis Bemann schrieb am Montag, 3. April 2023 um 21:53:08 UTC+2:
My issue with GOTO and LABEL in Forth is their compatiblity with local variables. E.g. my Forth, zeptoforth, has support for local variables such that they would be highly incompatible with GOTO and LABEL. In particular the issue is that it has block-scoped local variables, where local variables
can be limited to a particular block scope. Consider what would happen with
this:
: foo ( -- )
goto bar
begin
1 { my-local }
label bar
my-local .
true until
;
This is further complicated by the storing of local variables on the return
stack, where they are pushed by { ... } and dropped when they leave the current scope. The above example would not simply output garbage but
in many cases would simply crash afterwards due to dropping the return address from the return stack because my-local would have never been pushed onto the return stack in the first place.
Another problem is when you try to combine them with do-loops. Consider the following:
: baz ( -- )
goto quux
10 0 ?do
label quux
i .
loop
;
See the problem here?
Sure. My advice: don't do it. It would be akin to exiting do-loops without UNLOOP.
I actually made it so that it is safe to exit DO-LOOPs without UNLOOP because I made EXIT an immediate word that is smart enough to check the compile-time local variable stack, on which the DO-LOOP control variables are recorded, and drop
everything pushed onto it from the return stack prior to compiling a POP {PC} instruction. I kept UNLOOP for the sake of compatibility with existing code but it
is now an no-op. (Note that all of this is not true when zeptoforth is first being
built, where it uses more traditional DO-LOOP words, but it replaces those words
at the same time as when it sets up the local variable stack.)
On 4/04/2023 6:46 am, Travis Bemann wrote:
I actually made it so that it is safe to exit DO-LOOPs without UNLOOP becauseYou don't consider all this stuff under the hood is taking Forth in the opposite
I made EXIT an immediate word that is smart enough to check the compile-time
local variable stack, on which the DO-LOOP control variables are recorded, and drop
everything pushed onto it from the return stack prior to compiling a POP {PC}
instruction. I kept UNLOOP for the sake of compatibility with existing code but it
is now an no-op. (Note that all of this is not true when zeptoforth is first being
built, where it uses more traditional DO-LOOP words, but it replaces those words
at the same time as when it sets up the local variable stack.)
direction? The precedent appears to have been Forth-83 and the immediate LEAVE,
whereby if one can hide complexity from the user then it is justified. When Forth
users find out how much has been hidden from them, won't they question it, arguing
other languages have already done that, and better?
albert@cherry.(none) (albert) writes:
As far as I can tell, the Chinese are past the point of research and >>deploying them commercially.
- anton--
On Monday, April 3, 2023 at 7:35:35 PM UTC-5, dxforth wrote:
On 4/04/2023 6:46 am, Travis Bemann wrote:
You don't consider all this stuff under the hood is taking Forth in the opposite
I actually made it so that it is safe to exit DO-LOOPs without UNLOOP because
I made EXIT an immediate word that is smart enough to check the compile-time
local variable stack, on which the DO-LOOP control variables are recorded, and drop
everything pushed onto it from the return stack prior to compiling a POP {PC}
instruction. I kept UNLOOP for the sake of compatibility with existing code but it
is now an no-op. (Note that all of this is not true when zeptoforth is first being
built, where it uses more traditional DO-LOOP words, but it replaces those words
at the same time as when it sets up the local variable stack.)
direction? The precedent appears to have been Forth-83 and the immediate LEAVE,
whereby if one can hide complexity from the user then it is justified. When Forth
users find out how much has been hidden from them, won't they question it, arguing
other languages have already done that, and better?
I for the longest time resisted adding local variables to zeptoforth because they were
"un-traditional". I finally gave in and implemented them when I tried to implement
a word for blitting from one rectangle on one bitmap to another rectangle on another
bitmap. I was having to juggle about nine values on the data stack, the code was
completely unreadable, the code almost certainly had bugs due to the likelihood of
my making mistakes in the juggling, and it almost certainly would have gotten poor
performance due to all the stack juggling. Also, I could not factor away much of the
complexity; while I did factor away the physical blitting of strips of at most eight bits
high to separate assembly-language routines, there was much that simply could not
ahve been factored.
Faced with this, I scrapped my existing code aside from the assembly-language routines and implemented local variables. After I re-implemented the blitting routine
using local variables, they were far more readable, were bug-free, and were probably
far faster than my original routine would have been had I stuck with it (because local
variables can be accessed as simple offsets into the return stack, with fetches being
three instructions, two to evict the TOS register to the data stack (due to the lack of an
atomic decrement-and-store instruction for stacks other than SP in ARMv6-M), and
just one to read the local variable from an offset from SP into the TOS, and stores
being two instructions, one to store the TOS in an offset from SP, and another to
read the top of the data stack into the TOS (thanks to the ARMv6-M LDM instruction)).
This convinced me that local variables were a big win, and I have found since then that
they make my code far more readable and manageable. Yes, they might be "un-traditional", but they have served me very well and my only regret is that I had not
implemented them earlier, as I have plenty of barely-readable code that would almost
certainly be far more readable to me now ─ and faster too ─ had I implemented them
with local variables.
On Monday, April 3, 2023 at 7:35:35 PM UTC-5, dxforth wrote:Forth made me value variable locals. You can run a code "10x" faster and "10x" smaller but at the cost of taking "10x" and making "10x" more errors.
On 4/04/2023 6:46 am, Travis Bemann wrote:
I for the longest time resisted adding local variables to zeptoforth because they wereI actually made it so that it is safe to exit DO-LOOPs without UNLOOP becauseYou don't consider all this stuff under the hood is taking Forth in the opposite
I made EXIT an immediate word that is smart enough to check the compile-time
local variable stack, on which the DO-LOOP control variables are recorded, and drop
everything pushed onto it from the return stack prior to compiling a POP {PC}
instruction. I kept UNLOOP for the sake of compatibility with existing code but it
is now an no-op. (Note that all of this is not true when zeptoforth is first being
built, where it uses more traditional DO-LOOP words, but it replaces those words
at the same time as when it sets up the local variable stack.)
direction? The precedent appears to have been Forth-83 and the immediate LEAVE,
whereby if one can hide complexity from the user then it is justified. When Forth
users find out how much has been hidden from them, won't they question it, arguing
other languages have already done that, and better?
"un-traditional". I finally gave in and implemented them when I tried to implement
a word for blitting from one rectangle on one bitmap to another rectangle on another
bitmap. I was having to juggle about nine values on the data stack, the code was
completely unreadable, the code almost certainly had bugs due to the likelihood of
my making mistakes in the juggling, and it almost certainly would have gotten poor
performance due to all the stack juggling. Also, I could not factor away much of the
complexity; while I did factor away the physical blitting of strips of at most eight bits
high to separate assembly-language routines, there was much that simply could not
ahve been factored.
Faced with this, I scrapped my existing code aside from the assembly-language
routines and implemented local variables. After I re-implemented the blitting routine
using local variables, they were far more readable, were bug-free, and were probably
far faster than my original routine would have been had I stuck with it (because local
variables can be accessed as simple offsets into the return stack, with fetches being
three instructions, two to evict the TOS register to the data stack (due to the lack of an
atomic decrement-and-store instruction for stacks other than SP in ARMv6-M), and
just one to read the local variable from an offset from SP into the TOS, and stores
being two instructions, one to store the TOS in an offset from SP, and another to
read the top of the data stack into the TOS (thanks to the ARMv6-M LDM instruction)).
This convinced me that local variables were a big win, and I have found since then that
they make my code far more readable and manageable. Yes, they might be "un-traditional", but they have served me very well and my only regret is that I had not
implemented them earlier, as I have plenty of barely-readable code that would almost
certainly be far more readable to me now ─ and faster too ─ had I implemented them
with local variables.
In article <2023Apr3.182858@mips.complang.tuwien.ac.at>,
Anton Ertl <anton@mips.complang.tuwien.ac.at> wrote:
albert@cherry.(none) (albert) writes:
As far as I can tell, the Chinese are past the point of research and >>>deploying them commercially.
I got this from a more recent youtube video.
At least the Chinese are serious about research, investing the equivalent
of 500 million us$.
A pilot plant is underway, 3 MWatt to serve "1000 dwellings".
As it goes according to plan, the next step is a 373 MWatt plant.
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 300 |
Nodes: | 16 (2 / 14) |
Uptime: | 40:35:46 |
Calls: | 6,708 |
Calls today: | 1 |
Files: | 12,243 |
Messages: | 5,353,727 |