Discussion:
portable or not? Volatile strings
Add Reply
a***@spenarnc.xs4all.nl
2024-08-11 13:35:38 UTC
Reply
Permalink
I come across a tetris game, and there were bricks defined in
this way:

: DEF-BRICK CREATE 4 0 DO
' EXECUTE 0 DO DUP I CHARS + C@ C, LOOP DROP
REFILL DROP
LOOP
DOES> ROT 4 * ROT + 2* CHARS + ;

DEF-BRICK BRICK1 S" "
S" ###### "
S" ## "
S" "

Apparently the data field of bricks are filled in some mysterious
way by DEF-BRICK but that is not the subject.
It does some parsing from the input stream, which is kind of
tricky. As REFILL is not present in lina's core, you must
do "-traditional- WANTED" , but that still is not the issue.

I made S" " such that it ALLOT's the string at HERE, to
prevent problems with going out of scope, even in interpret mode.
(Only 256,000,000,000 -10 bytes left).

This doesn't sit well with the definition of BRICK1 ,
that sees its data area grabbed.
You are probably not surprised that tetris doesn't work.

The question is, is it legal to store these temporary strings
in the dictionary in this way?

[ It was sufficient to replace S" with S"' in order to make it run:
: S"' &" PARSE ;
]

Groetjes Albert
--
Don't praise the day before the evening. One swallow doesn't make spring.
You must not say "hey" before you have crossed the bridge. Don't sell the
hide of the bear until you shot it. Better one bird in the hand than ten in
the air. First gain is a cat purring. - the Wise from Antrim -
Ruvim
2024-08-12 08:05:59 UTC
Reply
Permalink
Post by a***@spenarnc.xs4all.nl
I come across a tetris game, and there were bricks defined in
: DEF-BRICK CREATE 4 0 DO
REFILL DROP
LOOP
DOES> ROT 4 * ROT + 2* CHARS + ;
DEF-BRICK BRICK1 S" "
S" ###### "
S" ## "
S" "
Apparently the data field of bricks are filled in some mysterious
way by DEF-BRICK but that is not the subject.
It does some parsing from the input stream, which is kind of
tricky. As REFILL is not present in lina's core, you must
do "-traditional- WANTED" , but that still is not the issue.
I made S" " such that it ALLOT's the string at HERE, to
prevent problems with going out of scope, even in interpret mode.
(Only 256,000,000,000 -10 bytes left).
This doesn't sit well with the definition of BRICK1 ,
that sees its data area grabbed.
You are probably not surprised that tetris doesn't work.
The question is, is it legal to store these temporary strings
in the dictionary in this way?
Strings that are stored relatively to the HERE address may become
invalid after:
- a definition is created via a defining word;
- definitions are compiled with : or :NONAME;
- data space is allocated using ALLOT, `,` (comma),
`C,` (c-comma), or ALIGN.
— as "3.3.3.6 Other transient regions"
<https://forth-standard.org/standard/usage#usage:transient> says.

All affected transition regions shall be listed. If a region is not
listed as affected, than it is not affected by allocating data space memory.


The section "11.3.4 Other transient regions"
<https://forth-standard.org/standard/file#file:buffers> says:

| The system provides transient buffers for S" and S\" strings.
| These buffers shall be no less than 80 characters in length,
| and there shall be at least two buffers. The system should be
| able to store two strings defined by sequential use of
| S" or S\". RAM-limited systems may have environmental
| restrictions on the number of buffers and their lifetimes.


Since this doesn't say that the buffer my become invalid after some
memory allocation, the buffer shall not become invalid after any memory
allocation (by default).

In the same time, a Forth system is allowed to limit the buffer lifetime
(for example, till the next memory allocation), and document it as an
environmental restriction.
Post by a***@spenarnc.xs4all.nl
: S"' &" PARSE ;
]
Groetjes Albert
--
Ruvim
a***@spenarnc.xs4all.nl
2024-08-12 09:01:48 UTC
Reply
Permalink
Post by Ruvim
Post by a***@spenarnc.xs4all.nl
I come across a tetris game, and there were bricks defined in
: DEF-BRICK CREATE 4 0 DO
REFILL DROP
LOOP
DOES> ROT 4 * ROT + 2* CHARS + ;
DEF-BRICK BRICK1 S" "
S" ###### "
S" ## "
S" "
Apparently the data field of bricks are filled in some mysterious
way by DEF-BRICK but that is not the subject.
It does some parsing from the input stream, which is kind of
tricky. As REFILL is not present in lina's core, you must
do "-traditional- WANTED" , but that still is not the issue.
I made S" " such that it ALLOT's the string at HERE, to
prevent problems with going out of scope, even in interpret mode.
(Only 256,000,000,000 -10 bytes left).
This doesn't sit well with the definition of BRICK1 ,
that sees its data area grabbed.
You are probably not surprised that tetris doesn't work.
The question is, is it legal to store these temporary strings
in the dictionary in this way?
Strings that are stored relatively to the HERE address may become
- a definition is created via a defining word;
- definitions are compiled with : or :NONAME;
- data space is allocated using ALLOT, `,` (comma),
`C,` (c-comma), or ALIGN.
— as "3.3.3.6 Other transient regions"
Not relevant. My "transient" region is permanent. That I have
permission to invalidate doesn't affect me.
Post by Ruvim
<https://forth-standard.org/standard/usage#usage:transient> says.
All affected transition regions shall be listed. If a region is not
listed as affected, than it is not affected by allocating data space memory.
My regions are not affected. So again this is not relevant.
Post by Ruvim
The section "11.3.4 Other transient regions"
| The system provides transient buffers for S" and S\" strings.
| These buffers shall be no less than 80 characters in length,
| and there shall be at least two buffers. The system should be
| able to store two strings defined by sequential use of
| S" or S\". RAM-limited systems may have environmental
| restrictions on the number of buffers and their lifetimes.
A permanent buffer can count as transient.
Post by Ruvim
Since this doesn't say that the buffer my become invalid after some
memory allocation, the buffer shall not become invalid after any memory
allocation (by default).
That is putting restriction to my buffer.
Post by Ruvim
In the same time, a Forth system is allowed to limit the buffer lifetime
(for example, till the next memory allocation), and document it as an
environmental restriction.
Lots of talk of whether the buffers become invalid.
My buffers never become invalid. That is not the point.
The standard talks about transient region. My regions are permanent
and there are other ways to handle S" , say by using ALLOCATE.
To call a region transient and then restrict how transient they are,
make a region not really temporary. So in this respect I am in the clear.
Note that as S" is in a definition, the string is bound to be permanent.

So I think the program is not portable, because what I do is perfectly
legal.
I can't make out what you think.
Post by Ruvim
Post by a***@spenarnc.xs4all.nl
: S"' &" PARSE ;
]
Okay let's say it out loud. Classic Forth is not fit for handling strings.
A denotation that generates a constant string "blablabla" that has
a status as a number is long overdue.
The mindset of formulating standards is so 70's.
Post by Ruvim
Post by a***@spenarnc.xs4all.nl
Groetjes Albert
--
Ruvim
Groetjes Albert
--
Don't praise the day before the evening. One swallow doesn't make spring.
You must not say "hey" before you have crossed the bridge. Don't sell the
hide of the bear until you shot it. Better one bird in the hand than ten in
the air. First gain is a cat purring. - the Wise from Antrim -
Ruvim
2024-08-12 11:00:53 UTC
Reply
Permalink
[...]
Post by a***@spenarnc.xs4all.nl
Post by Ruvim
Post by a***@spenarnc.xs4all.nl
I made S" " such that it ALLOT's the string at HERE, to
prevent problems with going out of scope, even in interpret mode.
(Only 256,000,000,000 -10 bytes left).
This doesn't sit well with the definition of BRICK1 ,
that sees its data area grabbed.
You are probably not surprised that tetris doesn't work.
The question is, is it legal to store these temporary strings
in the dictionary in this way?
Strings that are stored relatively to the HERE address may become
- a definition is created via a defining word;
- definitions are compiled with : or :NONAME;
- data space is allocated using ALLOT, `,` (comma),
`C,` (c-comma), or ALIGN.
— as "3.3.3.6 Other transient regions"
Not relevant. My "transient" region is permanent. That I have
permission to invalidate doesn't affect me.
Yes, this is not relevant to your case, but this is correct by itself.

Then I realized irrelevance and made another post.
Post by a***@spenarnc.xs4all.nl
Post by Ruvim
<https://forth-standard.org/standard/usage#usage:transient> says.
All affected transition regions shall be listed. If a region is not
listed as affected, than it is not affected by allocating data space memory.
My regions are not affected. So again this is not relevant.
There is no need to repeat this.

[...]
Post by a***@spenarnc.xs4all.nl
Post by Ruvim
In the same time, a Forth system is allowed to limit the buffer
lifetime (for example, till the next memory allocation), and
document it as an environmental restriction.
[...]
Post by a***@spenarnc.xs4all.nl
I can't make out what you think.
A possible implementation for the interpretation semantics for `S"` is
to keep data somewhere in the memory region that returns by "here
unused", and declare the lifetime restriction for the returned string.

For example:

128 constant _sbufsize
0 value _sn
4 value _snlimit

: _sbuf-next ( -- c-addr u )
here aligned 4096 + _sbufsize _sn * + _sbufsize
( c-addr.buf u.buf-len )
2dup + here unused + u> if -8 throw then \ "dictionary overflow"
_sn 1+ _snlimit mod to _sn
;
: _memorize-string ( c-addr1 u -- c-addr2 u )
if -18 throw then \ "parsed string overflow"
r@ over >r chars move r> r>
;

: s" ( -- c-addr u | )
'"' parse compilation if slit, exit then _memorize-string
; immediate


At first I thought you were asking about this approach.

This approach implies an environmental restriction.
Post by a***@spenarnc.xs4all.nl
Post by Ruvim
Post by a***@spenarnc.xs4all.nl
: S"' &" PARSE ;
]
Okay let's say it out loud. Classic Forth is not fit for handling strings.
A denotation that generates a constant string "blablabla" that has
a status as a number is long overdue.
The mindset of formulating standards is so 70's.
Why not prepare a proposal?


--
Ruvim
Gerry Jackson
2024-08-12 11:36:18 UTC
Reply
Permalink
is way?
Post by a***@spenarnc.xs4all.nl
Post by Ruvim
Strings that are stored relatively to the HERE address may become
- a definition is created via a defining word;
- definitions are compiled with : or :NONAME;
- data space is allocated using ALLOT, `,` (comma),
`C,` (c-comma), or ALIGN.
— as "3.3.3.6 Other transient regions"
Not relevant. My "transient" region is permanent. That I have
permission to invalidate doesn't affect me.
Post by Ruvim
<https://forth-standard.org/standard/usage#usage:transient> says.
All affected transition regions shall be listed. If a region is not
listed as affected, than it is not affected by allocating data space memory.
My regions are not affected. So again this is not relevant.
Post by Ruvim
The section "11.3.4 Other transient regions"
| The system provides transient buffers for S" and S\" strings.
| These buffers shall be no less than 80 characters in length,
| and there shall be at least two buffers. The system should be
| able to store two strings defined by sequential use of
| S" or S\". RAM-limited systems may have environmental
| restrictions on the number of buffers and their lifetimes.
A permanent buffer can count as transient.
Post by Ruvim
Since this doesn't say that the buffer my become invalid after some
memory allocation, the buffer shall not become invalid after any memory
allocation (by default).
That is putting restriction to my buffer.
Post by Ruvim
In the same time, a Forth system is allowed to limit the buffer lifetime
(for example, till the next memory allocation), and document it as an
environmental restriction.
Lots of talk of whether the buffers become invalid.
My buffers never become invalid. That is not the point.
The standard talks about transient region. My regions are permanent
and there are other ways to handle S" , say by using ALLOCATE.
To call a region transient and then restrict how transient they are,
make a region not really temporary. So in this respect I am in the clear.
Note that as S" is in a definition, the string is bound to be permanent.
So I think the program is not portable, because what I do is perfectly
legal.
I can't make out what you think.
Post by Ruvim
Post by a***@spenarnc.xs4all.nl
: S"' &" PARSE ;
]
Okay let's say it out loud. Classic Forth is not fit for handling strings.
A denotation that generates a constant string "blablabla" that has
a status as a number is long overdue.
The mindset of formulating standards is so 70's.
Yes, transient regions are another Forth anachronism from the early days
of Forth when memory was scarce and expensive. In my system all
transient regions are permanent so I don't worry about them getting
corrupted. The standard ought to be updated to make them permanent or
make provision for the user to allot or allocate them.
--
Gerry
mhx
2024-08-13 18:44:49 UTC
Reply
Permalink
Post by a***@spenarnc.xs4all.nl
Okay let's say it out loud. Classic Forth is not fit for handling strings.
I don't agree. Classic Forth is perfectly fit for handling strings.
It just needs some user-defined words added. The longer such words
are not standardized, the better the final result will probably be.
Post by a***@spenarnc.xs4all.nl
A denotation that generates a constant string "blablabla" that has
a status as a number is long overdue.
Which illustrates my point. Having a built-in string type denoted
by quotes might be a good thing. It is hard to find a argument
against that when numbers are already a comparable exception that
nobody has found a way to get rid of. And maybe we can then even
tick strings and numbers like everything else?

-marcel
dxf
2024-08-14 02:09:12 UTC
Reply
Permalink
Post by mhx
Post by a***@spenarnc.xs4all.nl
Okay let's say it out loud. Classic Forth is not fit for handling strings.
I don't agree. Classic Forth is perfectly fit for handling strings.
It just needs some user-defined words added. The longer such words
are not standardized, the better the final result will probably be.
Post by a***@spenarnc.xs4all.nl
A denotation that generates a constant string "blablabla" that has
a status as a number is long overdue.
Which illustrates my point. Having a built-in string type denoted
by quotes might be a good thing. It is hard to find a argument
against that when numbers are already a comparable exception that
nobody has found a way to get rid of. And maybe we can then even
tick strings and numbers like everything else?
'might be a good thing' - these would have to be the most used words
in Forth :)
mhx
2024-08-14 07:41:07 UTC
Reply
Permalink
[..]
Post by dxf
Post by mhx
Which illustrates my point. Having a built-in string type denoted
by quotes might be a good thing.
[..]
Post by dxf
'might be a good thing' - these would have to be the most used words
in Forth :)
Here I genuinely meant that I don't know if it is really a good
thing, but *my* mind is open to it.

-marcel
Anton Ertl
2024-08-14 07:03:52 UTC
Reply
Permalink
Post by mhx
Having a built-in string type denoted
by quotes might be a good thing. It is hard to find a argument
against that when numbers are already a comparable exception that
nobody has found a way to get rid of.
Mitch Bradley introduced parsing words for numbers, which would allow
to get rid of the number recognizers.

But yes, the mainstream is in the opposite direction: Introduce
recognizers not just for numbers, but also for strings, and a
mechanism for user-defined recognizers.
Post by mhx
And maybe we can then even
tick strings and numbers like everything else?
I explored this idea in a EuroForth 2016 paper, in particular in
Section 4.1.

@InProceedings{ertl-recognizers16,
author = {M. Anton Ertl},
title = {Recognizers: Arguments and Design Decisions},
crossref = {euroforth16},
pages = {58--63},
url = {https://www.complang.tuwien.ac.at/papers/ertl-recognizers16.pdf},
video = {https://wiki.forth-ev.de/lib/exe/fetch.php/events:recognizers.mp4},
OPTnote = {not refereed},
abstract = {The Forth text interpreter processes words and
numbers. Currently the set of words can be extended
by programmers, but not the recognized numbers.
User-defined recognizers allow to extend the
number-recognizer part, too. This paper shows the
benefits of recognizers and discusses
counterarguments. It also discusses several design
decisions: Whether to define temporary words, or a
set of interpretation, compilation, and postponing
actions; and whether to hook the recognizers inside
\code{find} or in the text interpreter.}
}

@Proceedings{euroforth16,
title = {32nd EuroForth Conference},
booktitle = {32nd EuroForth Conference},
year = {2016},
key = {EuroForth'16},
url = {https://www.complang.tuwien.ac.at/anton/euroforth/ef16/papers/proceedings.pdf}
}

The discussion has moved on since then, and getting the xt of a
recognized thing is not something that anyone (including me) found
worth the cost, so AFAIK nobody has implemented the temporary-word
approach.

However, if we adopt Gerry Jackson's attitude and make every transient
region permanent, creating a new permanent word (in a separate
section) for every parsed number, string, etc. is fine, and ticking
that word is fine, too. For most programs, the space taken by the
recognized words is proportional to the size of the source code, which
is acceptable on desktops with GBs of RAM. However, programs that use
EVALUATE a lot will need more recognized-word storage. A contrived
example is:

: foo 1000000000 0 ?do s" 123" evaluate drop loop ; foo

You might imagine optimizing this by using only one definition for all
these occurences of "123", so here's another example where that
optimization would not work:

: bar 1000000000 0 ?do i 0 <# #s #> evaluate drop loop ; bar

Of course, if you make all transient regions permanent, already the <#
#s #> consumes a lot of memory in BAR, and the recognized words just
increase this by a constant factor.

While I have some sympathies for the idea of permanent "transient"
data (e.g., in Gforth S"'s intepretation semantics produce a string
that lives until the end of the session, I don't think that this would
find consensus in the standards committee.

And if you really want an execution token for a string or number,
writing

[: s" foo" ;] [: 123 ;]

inside a colon definition (or the same with :NONAME ... ; outside a
colon definition) seems easy enough.

- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: https://forth-standard.org/
EuroForth 2024: https://euro.theforth.net
Gerry Jackson
2024-08-14 10:16:30 UTC
Reply
Permalink
Post by Anton Ertl
However, if we adopt Gerry Jackson's attitude and make every transient
region permanent, creating a new permanent word (in a separate
section) for every parsed number, string, etc. is fine, and ticking
that word is fine, too. For most programs, the space taken by the
recognized words is proportional to the size of the source code, which
is acceptable on desktops with GBs of RAM. However, programs that use
EVALUATE a lot will need more recognized-word storage. A contrived
: foo 1000000000 0 ?do s" 123" evaluate drop loop ; foo
I wasn't clear enough when I suggested making transient areas
'permanent'. Currently transient areas are overwritten either by the
user or the system when it decides to re-use the transient region for
something else. If we take the <# buffer as an example, I meant that the
user would declare the memory to be used for that buffer once and that
would be used thereafter. It's permanent in the sense that the
allocation is permanent, not the contents - the system would not be
allowed to corrupt it. THe user would be free to re-use it or to make
the contents permanent by declaring another bit of memory to be used for
the buffer. If the user ALLOCATEd the memory it could later be FREEd by
the user. The user manages it not the system.
--
Gerry
a***@spenarnc.xs4all.nl
2024-08-14 10:38:55 UTC
Reply
Permalink
Post by Gerry Jackson
Post by Anton Ertl
However, if we adopt Gerry Jackson's attitude and make every transient
region permanent, creating a new permanent word (in a separate
section) for every parsed number, string, etc. is fine, and ticking
that word is fine, too. For most programs, the space taken by the
recognized words is proportional to the size of the source code, which
is acceptable on desktops with GBs of RAM. However, programs that use
EVALUATE a lot will need more recognized-word storage. A contrived
: foo 1000000000 0 ?do s" 123" evaluate drop loop ; foo
I wasn't clear enough when I suggested making transient areas
'permanent'. Currently transient areas are overwritten either by the
user or the system when it decides to re-use the transient region for
something else. If we take the <# buffer as an example, I meant that the
user would declare the memory to be used for that buffer once and that
would be used thereafter. It's permanent in the sense that the
allocation is permanent, not the contents - the system would not be
allowed to corrupt it. THe user would be free to re-use it or to make
the contents permanent by declaring another bit of memory to be used for
the buffer. If the user ALLOCATEd the memory it could later be FREEd by
the user. The user manages it not the system.
Constant strings should not be stored in a "transient area".
Then trigger endless discussion for how long transient means.

You are near my idea's of : $! $@ $+! $C+ $/
Have low level abstractions of strings, but do not mix the
storage requirements of this strings into these low level abstraction.

Example
CREATE $VAR1 100 ALLOT
"AAP" \ is permanent. (somehow )
2DUP $VAR1 $! \ You take responsibilty that `$VAR is large enough
\ The constant string is still on the stack and can be reused.
Post by Gerry Jackson
--
Gerry
Groetjes Albert
--
Don't praise the day before the evening. One swallow doesn't make spring.
You must not say "hey" before you have crossed the bridge. Don't sell the
hide of the bear until you shot it. Better one bird in the hand than ten in
the air. First gain is a cat purring. - the Wise from Antrim -
mhx
2024-08-14 14:06:25 UTC
Reply
Permalink
On Wed, 14 Aug 2024 10:38:55 +0000, ***@spenarnc.xs4all.nl wrote:

[..]
Post by a***@spenarnc.xs4all.nl
Example
CREATE $VAR1 100 ALLOT
"AAP" \ is permanent. (somehow )
2DUP $VAR1 $! \ You take responsibilty that `$VAR is large enough
\ The constant string is still on the stack and can be reused.
Oh, now you point to an unwanted, or complicating, effect.
The phrase ' "aap" must create the string before its descriptor
can be returned. Unless, of course, "aap" exists already. A ticked
number has the same problem.

Just make that exception?

-marcel
a***@spenarnc.xs4all.nl
2024-08-14 18:49:45 UTC
Reply
Permalink
Post by mhx
[..]
Post by a***@spenarnc.xs4all.nl
Example
CREATE $VAR1 100 ALLOT
"AAP" \ is permanent. (somehow )
2DUP $VAR1 $! \ You take responsibilty that `$VAR is large enough
\ The constant string is still on the stack and can be reused.
Oh, now you point to an unwanted, or complicating, effect.
The phrase ' "aap" must create the string before its descriptor
can be returned. Unless, of course, "aap" exists already. A ticked
number has the same problem.
Just make that exception?
What?

Ticking a constant or constant string makes no sense.
At most it is the same constant again.

AMDX86 ciforth 5.5.1
"AAP"
OK
2DUP TYPE
AAP OK
2DUP TYPE
AAP OK
.S

S[ 4250664 3 ] OK
' "AAP"
' "AAP" ? ciforth ERROR # 11 : WORD IS NOT FOUND
' 12
' 12 ? ciforth ERROR # 11 : WORD IS NOT FOUND
Post by mhx
-marcel
Groetjes Albert
--
Don't praise the day before the evening. One swallow doesn't make spring.
You must not say "hey" before you have crossed the bridge. Don't sell the
hide of the bear until you shot it. Better one bird in the hand than ten in
the air. First gain is a cat purring. - the Wise from Antrim -
minforth
2024-08-14 19:46:48 UTC
Reply
Permalink
Post by a***@spenarnc.xs4all.nl
Ticking a constant or constant string makes no sense.
Try

' +INF

It takes forever.
dxf
2024-08-15 01:57:17 UTC
Reply
Permalink
Post by minforth
Post by a***@spenarnc.xs4all.nl
Ticking a constant or constant string makes no sense.
Try
' +INF
It takes forever.
Some folks think this works :)

' God
a***@spenarnc.xs4all.nl
2024-08-15 09:04:41 UTC
Reply
Permalink
Post by dxf
Post by minforth
Post by a***@spenarnc.xs4all.nl
Ticking a constant or constant string makes no sense.
Try
' +INF
It takes forever.
Some folks think this works :)
' God
Some Forth try to speed up by predefining constants:

' 0
OK
.S

S[ 4206176 ] OK
SEE 0

0000,0000,0000,0000 CONSTANT 0

What has to do with anything?

Groetjes Albert
--
Don't praise the day before the evening. One swallow doesn't make spring.
You must not say "hey" before you have crossed the bridge. Don't sell the
hide of the bear until you shot it. Better one bird in the hand than ten in
the air. First gain is a cat purring. - the Wise from Antrim -
dxf
2024-08-16 04:23:32 UTC
Reply
Permalink
Post by a***@spenarnc.xs4all.nl
Post by dxf
Post by minforth
Post by a***@spenarnc.xs4all.nl
Ticking a constant or constant string makes no sense.
Try
' +INF
It takes forever.
Some folks think this works :)
' God
' 0
OK
.S
S[ 4206176 ] OK
SEE 0
0000,0000,0000,0000 CONSTANT 0
What has to do with anything?
It has to do with the assertion ticking constants and strings 'might a good thing'.
a***@spenarnc.xs4all.nl
2024-08-14 10:25:16 UTC
Reply
Permalink
Post by Anton Ertl
Post by mhx
Having a built-in string type denoted
by quotes might be a good thing. It is hard to find a argument
against that when numbers are already a comparable exception that
nobody has found a way to get rid of.
Mitch Bradley introduced parsing words for numbers, which would allow
to get rid of the number recognizers.
But yes, the mainstream is in the opposite direction: Introduce
recognizers not just for numbers, but also for strings, and a
mechanism for user-defined recognizers.
You need a magnifying glass to see the difference:
Bradly: 0x DEADBEEF
We: 0xDEAFBEAF

I think recognizing 0xDEADBEAF as a number (pun intended),
one can proceed without adjusting the notion of what a number is.

Having a mechanism that recognizing the Intel DEADBEEFH is a bridge too far.

<SNIP>
Post by Anton Ertl
- anton
--
Don't praise the day before the evening. One swallow doesn't make spring.
You must not say "hey" before you have crossed the bridge. Don't sell the
hide of the bear until you shot it. Better one bird in the hand than ten in
the air. First gain is a cat purring. - the Wise from Antrim -
Ruvim
2024-08-12 08:28:27 UTC
Reply
Permalink
Post by a***@spenarnc.xs4all.nl
I come across a tetris game, and there were bricks defined in
: DEF-BRICK CREATE 4 0 DO
REFILL DROP
LOOP
DOES> ROT 4 * ROT + 2* CHARS + ;
DEF-BRICK BRICK1 S" "
S" ###### "
S" ## "
S" "
Apparently the data field of bricks are filled in some mysterious
way by DEF-BRICK but that is not the subject.
It does some parsing from the input stream, which is kind of
tricky. As REFILL is not present in lina's core, you must
do "-traditional- WANTED" , but that still is not the issue.
I made S" " such that it ALLOT's the string at HERE,
This is not allowed, without any options.

The alloted data space regions shall be contiguous unless "definitions
are added to or removed from the dictionary between allocations"
(3.3.3.2), or the function of `INCLUDED` is performed (11.6.1.1718,
11.6.2.1714). No other conditions are mentioned anywhere.
Post by a***@spenarnc.xs4all.nl
to prevent problems with going out of scope, even in interpret mode.
(Only 256,000,000,000 -10 bytes left).
This doesn't sit well with the definition of BRICK1 ,
that sees its data area grabbed.
You are probably not surprised that tetris doesn't work.
The question is, is it legal to store these temporary strings
in the dictionary in this way?
: S"' &" PARSE ;
]
--
Ruvim
a***@spenarnc.xs4all.nl
2024-08-12 09:31:17 UTC
Reply
Permalink
Post by Ruvim
Post by a***@spenarnc.xs4all.nl
I come across a tetris game, and there were bricks defined in
: DEF-BRICK CREATE 4 0 DO
REFILL DROP
LOOP
DOES> ROT 4 * ROT + 2* CHARS + ;
DEF-BRICK BRICK1 S" "
S" ###### "
S" ## "
S" "
Apparently the data field of bricks are filled in some mysterious
way by DEF-BRICK but that is not the subject.
It does some parsing from the input stream, which is kind of
tricky. As REFILL is not present in lina's core, you must
do "-traditional- WANTED" , but that still is not the issue.
I made S" " such that it ALLOT's the string at HERE,
This is not allowed, without any options.
The alloted data space regions shall be contiguous unless "definitions
are added to or removed from the dictionary between allocations"
(3.3.3.2), or the function of `INCLUDED` is performed (11.6.1.1718,
11.6.2.1714). No other conditions are mentioned anywhere.
That settles it. Note that it applies to interpret mode only,
during a definition being permanent is not an issue because it is in a
definition.
This is a defect ("bug") in S" in ciforth.

The only solution is to make S" state smart:
: S" STATE @ IF POSTPONE " ELSE &" PARSE ; IMMEDIATE

[ Before it was an alias for the "-as-a-prefix without the
prefix flag.
: S" POSTPONE " ; IMMEDIATE
It sticks to the design rule for ciforth that only denotations,
generalisation of numbers, are allowed to be state smart. ]
Post by Ruvim
Post by a***@spenarnc.xs4all.nl
to prevent problems with going out of scope, even in interpret mode.
(Only 256,000,000,000 -10 bytes left).
This doesn't sit well with the definition of BRICK1 ,
that sees its data area grabbed.
You are probably not surprised that tetris doesn't work.
The question is, is it legal to store these temporary strings
in the dictionary in this way?
: S"' &" PARSE ;
]
--
Ruvim
--
Don't praise the day before the evening. One swallow doesn't make spring.
You must not say "hey" before you have crossed the bridge. Don't sell the
hide of the bear until you shot it. Better one bird in the hand than ten in
the air. First gain is a cat purring. - the Wise from Antrim -
Ruvim
2024-08-12 11:27:54 UTC
Reply
Permalink
[...]
Post by a***@spenarnc.xs4all.nl
Post by Ruvim
Post by a***@spenarnc.xs4all.nl
I made S" " such that it ALLOT's the string at HERE,
This is not allowed, without any options.
The alloted data space regions shall be contiguous unless "definitions
are added to or removed from the dictionary between allocations"
(3.3.3.2), or the function of `INCLUDED` is performed (11.6.1.1718,
11.6.2.1714). No other conditions are mentioned anywhere.
That settles it. Note that it applies to interpret mode only,
during a definition being permanent is not an issue because it is in a
definition.
This is a defect ("bug") in S" in ciforth.
This implementation implies an environmental restriction: the string
returned by the interpretation semantics of `S"` is valid until a
subsequent invocation of `REFILL`, because the returned string is
located in the input buffer.
Post by a***@spenarnc.xs4all.nl
[ Before it was an alias for the "-as-a-prefix without the
prefix flag.
: S" POSTPONE " ; IMMEDIATE
In this implementation the interpretation semantics are incorrect, right?
Post by a***@spenarnc.xs4all.nl
It sticks to the design rule for ciforth that only denotations,
generalisation of numbers, are allowed to be state smart. ]
--
Ruvim
a***@spenarnc.xs4all.nl
2024-08-12 19:34:31 UTC
Reply
Permalink
Post by Ruvim
[...]
Post by a***@spenarnc.xs4all.nl
Post by Ruvim
Post by a***@spenarnc.xs4all.nl
I made S" " such that it ALLOT's the string at HERE,
This is not allowed, without any options.
The alloted data space regions shall be contiguous unless "definitions
are added to or removed from the dictionary between allocations"
(3.3.3.2), or the function of `INCLUDED` is performed (11.6.1.1718,
11.6.2.1714). No other conditions are mentioned anywhere.
That settles it. Note that it applies to interpret mode only,
during a definition being permanent is not an issue because it is in a
definition.
This is a defect ("bug") in S" in ciforth.
This implementation implies an environmental restriction: the string
returned by the interpretation semantics of `S"` is valid until a
subsequent invocation of `REFILL`, because the returned string is
located in the input buffer.
Remember ciforth is not only "computer intelligence Forth"
it is also "close to iso forth", cutting corners for simplicity.
There is no REFILL in ciforth, all files are slurped.

In my lisp , manx , ciasdis I never needed REFILL.
In the above tetris example, this S" works with REFILL.

I implemented REFILL in the library. Dutch Forth Users wanted
that.
For each nested include you need a separate buffer for each file.
Fortunately the block/screen buffers can serve because they have a
lock/unlock state.
Still it was a pain, and you have to carefully load all facilities
belonging to a -traditional- expansion at the same time,
because you probably need WORD FIND .
7 blocks have to be loaded,

In the presence of REFILL I have to load the ALLOCATE wordset
and follow $" PARSE with $MAKE-PERMANENT or some such.

But ... the code becomes better without REFILL.

In my book the code should be

" "
"###### "
" ## "
" "
DEF-BRICK BRICK1

Instead of

DEF-BRICK BRICK1 S" "
S" ###### "
S" ## "
S" "

The code (untested) could be
: DEF-BRICK CREATE
2>R 2>R 2>R 2>R
2R> ,, 2R> ,, 2R> ,, 2R> ,,
DOES> ... ;

More Forth like. First data then creation of a structure with it.
More readable code. No brain twisting REFILL where the first word
is looked up in the dictionary via ' .

At the expense of storing the strings two times in the dictionary.
(I know most Forthers really get sick by the idea alone.)
Post by Ruvim
Post by a***@spenarnc.xs4all.nl
[ Before it was an alias for the "-as-a-prefix without the
prefix flag.
: S" POSTPONE " ; IMMEDIATE
In this implementation the interpretation semantics are incorrect, right?
Right. S" aap" does the same as "aap" storing the string at HERE.
The former finds `` S" '' in the dictionary, the latter `` " ''
found as a prefix. S"aap" is not found, because S" is not marked
PREFIX.
Post by Ruvim
Post by a***@spenarnc.xs4all.nl
It sticks to the design rule for ciforth that only denotations,
generalisation of numbers, are allowed to be state smart. ]
--
Ruvim
NOTE:
: ,, HERE SWAP DUP ALLOT MOVE ;
--
Don't praise the day before the evening. One swallow doesn't make spring.
You must not say "hey" before you have crossed the bridge. Don't sell the
hide of the bear until you shot it. Better one bird in the hand than ten in
the air. First gain is a cat purring. - the Wise from Antrim -
dxf
2024-08-13 04:07:51 UTC
Reply
Permalink
Post by a***@spenarnc.xs4all.nl
...
In my book the code should be
" "
"###### "
" ## "
" "
DEF-BRICK BRICK1
Instead of
DEF-BRICK BRICK1 S" "
S" ###### "
S" ## "
S" "
The code (untested) could be
: DEF-BRICK CREATE
2>R 2>R 2>R 2>R
2R> ,, 2R> ,, 2R> ,, 2R> ,,
DOES> ... ;
OTOH it's no less difficult to write...

: M" [CHAR] " PARSE HERE OVER ALLOT SWAP MOVE ;

: DEF-BRICK CREATE DOES> ROT 4 * ROT + 2* CHARS + ;

DEF-BRICK BRICK1 M" "
M" ###### "
M" ## "
M" "
a***@spenarnc.xs4all.nl
2024-08-13 08:39:25 UTC
Reply
Permalink
Post by dxf
Post by a***@spenarnc.xs4all.nl
...
In my book the code should be
" "
"###### "
" ## "
" "
DEF-BRICK BRICK1
Instead of
DEF-BRICK BRICK1 S" "
S" ###### "
S" ## "
S" "
The code (untested) could be
: DEF-BRICK CREATE
2>R 2>R 2>R 2>R
2R> ,, 2R> ,, 2R> ,, 2R> ,,
DOES> ... ;
OTOH it's no less difficult to write...
: M" [CHAR] " PARSE HERE OVER ALLOT SWAP MOVE ;
: DEF-BRICK CREATE DOES> ROT 4 * ROT + 2* CHARS + ;
DEF-BRICK BRICK1 M" "
M" ###### "
M" ## "
M" "
There you are!
My solution is even more extreme, because it avoids
parsing words altogether, apart from
denotations^H^H^H^H^H^H numbers.

Groetjes Albert
--
Don't praise the day before the evening. One swallow doesn't make spring.
You must not say "hey" before you have crossed the bridge. Don't sell the
hide of the bear until you shot it. Better one bird in the hand than ten in
the air. First gain is a cat purring. - the Wise from Antrim -
Hans Bezemer
2024-08-21 17:12:36 UTC
Reply
Permalink
Post by dxf
Post by a***@spenarnc.xs4all.nl
...
In my book the code should be
" "
"###### "
" ## "
" "
DEF-BRICK BRICK1
Instead of
DEF-BRICK BRICK1 S" "
S" ###### "
S" ## "
S" "
The code (untested) could be
: DEF-BRICK CREATE
2>R 2>R 2>R 2>R
2R> ,, 2R> ,, 2R> ,, 2R> ,,
DOES> ... ;
OTOH it's no less difficult to write...
: M" [CHAR] " PARSE HERE OVER ALLOT SWAP MOVE ;
: DEF-BRICK CREATE DOES> ROT 4 * ROT + 2* CHARS + ;
DEF-BRICK BRICK1 M" "
M" ###### "
M" ## "
M" "
In 4tH, the easiest solution would be:

: BRICK@ ROT + @C SWAP 2* CHARS + ;

CREATE BRICK1
," "
," ###### "
," ## "
," "
DOES> BRICK@ ;

I could throw a bit of preprocessor magic in the mix, so it would
resemble your solution even closer, but I guess you can do without ;-)

Hans Bezemer
a***@spenarnc.xs4all.nl
2024-08-22 10:59:15 UTC
Reply
Permalink
Post by Hans Bezemer
Post by dxf
Post by a***@spenarnc.xs4all.nl
...
In my book the code should be
" "
"###### "
" ## "
" "
DEF-BRICK BRICK1
Instead of
DEF-BRICK BRICK1 S" "
S" ###### "
S" ## "
S" "
The code (untested) could be
: DEF-BRICK CREATE
2>R 2>R 2>R 2>R
2R> ,, 2R> ,, 2R> ,, 2R> ,,
DOES> ... ;
OTOH it's no less difficult to write...
: M" [CHAR] " PARSE HERE OVER ALLOT SWAP MOVE ;
: DEF-BRICK CREATE DOES> ROT 4 * ROT + 2* CHARS + ;
DEF-BRICK BRICK1 M" "
M" ###### "
M" ## "
M" "
CREATE BRICK1
," "
," ###### "
," ## "
," "
I dislike the use of parsing here by ," . It happens to work
because ," doesn't destroy the concatenation of HERE.
So you couldn't check the solution without digging into the 4TH
documentation.

In these case parsing is more or less advantageous because it allows
easier represent the bricks. The introduction of an auxiliary word M"
that is easily understood and checked is far superior using ," .

I changed my version to use the proposed M" now and it works fine.
Post by Hans Bezemer
I could throw a bit of preprocessor magic in the mix, so it would
resemble your solution even closer, but I guess you can do without ;-)
Hans Bezemer
--
Temu exploits Christians: (Disclaimer, only 10 apostles)
Last Supper Acrylic Suncatcher - 15Cm Round Stained Glass- Style Wall
Art For Home, Office And Garden Decor - Perfect For Windows, Bars,
And Gifts For Friends Family And Colleagues.
dxf
2024-08-24 02:58:26 UTC
Reply
Permalink
Post by a***@spenarnc.xs4all.nl
Post by Hans Bezemer
Post by dxf
Post by a***@spenarnc.xs4all.nl
...
In my book the code should be
" "
"###### "
" ## "
" "
DEF-BRICK BRICK1
Instead of
DEF-BRICK BRICK1 S" "
S" ###### "
S" ## "
S" "
The code (untested) could be
: DEF-BRICK CREATE
2>R 2>R 2>R 2>R
2R> ,, 2R> ,, 2R> ,, 2R> ,,
DOES> ... ;
OTOH it's no less difficult to write...
: M" [CHAR] " PARSE HERE OVER ALLOT SWAP MOVE ;
: DEF-BRICK CREATE DOES> ROT 4 * ROT + 2* CHARS + ;
DEF-BRICK BRICK1 M" "
M" ###### "
M" ## "
M" "
CREATE BRICK1
," "
," ###### "
," ## "
," "
I dislike the use of parsing here by ," . It happens to work
because ," doesn't destroy the concatenation of HERE.
So you couldn't check the solution without digging into the 4TH
documentation.
In these case parsing is more or less advantageous because it allows
easier represent the bricks. The introduction of an auxiliary word M"
that is easily understood and checked is far superior using ," .
...
For the general case that's true. OTOH 4tH is free to exploit what it has.
The original ANS-Forth version tried using S" but it got complicated due
to the dual-action word. If standard compliance is the goal then options
are limited. OTOH a Gforth user not caring about compliance could exploit
what he had and define things more succinctly:

: M" \"-parse mem, ;

(assuming he knew these words existed)
a***@spenarnc.xs4all.nl
2024-08-24 10:10:57 UTC
Reply
Permalink
Post by dxf
Post by a***@spenarnc.xs4all.nl
Post by Hans Bezemer
Post by dxf
Post by a***@spenarnc.xs4all.nl
...
In my book the code should be
" "
"###### "
" ## "
" "
DEF-BRICK BRICK1
Instead of
DEF-BRICK BRICK1 S" "
S" ###### "
S" ## "
S" "
The code (untested) could be
: DEF-BRICK CREATE
2>R 2>R 2>R 2>R
2R> ,, 2R> ,, 2R> ,, 2R> ,,
DOES> ... ;
OTOH it's no less difficult to write...
: M" [CHAR] " PARSE HERE OVER ALLOT SWAP MOVE ;
: DEF-BRICK CREATE DOES> ROT 4 * ROT + 2* CHARS + ;
DEF-BRICK BRICK1 M" "
M" ###### "
M" ## "
M" "
CREATE BRICK1
," "
," ###### "
," ## "
," "
I dislike the use of parsing here by ," . It happens to work
because ," doesn't destroy the concatenation of HERE.
So you couldn't check the solution without digging into the 4TH
documentation.
In these case parsing is more or less advantageous because it allows
easier represent the bricks. The introduction of an auxiliary word M"
that is easily understood and checked is far superior using ," .
...
For the general case that's true. OTOH 4tH is free to exploit what it has.
The original ANS-Forth version tried using S" but it got complicated due
to the dual-action word. If standard compliance is the goal then options
are limited. OTOH a Gforth user not caring about compliance could exploit
: M" \"-parse mem, ;
(assuming he knew these words existed)
I accept the use of non standard words if there is an advantage for it.
In this case a small change keeps the program totally standard,
at the same time allowing to escape confusion over allocation
situations and having it run on a ciforth 10% of the complexity of
gforth.

I occasionally promote ciforth techniques, if they are substantially
simpler and standard programs look akward in comparison.

Probably mem, is the same as my
: ,, HERE SWAP DUP ALLOT MOVE ;

Groetjes Albert
--
Temu exploits Christians: (Disclaimer, only 10 apostles)
Last Supper Acrylic Suncatcher - 15Cm Round Stained Glass- Style Wall
Art For Home, Office And Garden Decor - Perfect For Windows, Bars,
And Gifts For Friends Family And Colleagues.
Hans Bezemer
2024-08-24 11:23:29 UTC
Reply
Permalink
Post by dxf
For the general case that's true. OTOH 4tH is free to exploit what it has.
The original ANS-Forth version tried using S" but it got complicated due
to the dual-action word. If standard compliance is the goal then options
are limited. OTOH a Gforth user not caring about compliance could exploit
: M" \"-parse mem, ;
(assuming he knew these words existed)
You're completely right (I assume because you've had some exposure to
4tH). There is no "ALLOT" in 4tH, because it has no dictionary. It has
segments for bytes, cells, words and constant strings.

Now *ONLY* 4tH "builtins" have access to the latter - and the segment
where the code resides is "read-only". What ," does is compile an "NOOP"
word with the address of the "string constant".

The "@C" word gets that address, copies the constant string to the
"bytes" segment and returns that address - which is accessible to the
programmer.

There is another way, which is to define words like:

OFFSET BRICK1
C" "
C" ###### "
C" ## "
C" "

Now "BRICK1" will hold the starting address in the "constant string"
segment. The "BRICK1" word will take any integer as an offset relative
to BRICK1, so "5 BRICK1" will return the ASCII value of the sixth
character after BRICK1.

Note C" has nothing to do with ANS-Forth C" and *only* allows for
printable characters to be inserted that way (sorry, no UTF-8). It does
*NOT* compile a terminator or count.

The thing is, however, you cannot add a "DOES>" definition to an "OFFSET".

Therefore the 4tH "CREATE" solution is the closest approximation you can
get in 4tH.

Hans Bezemer

Loading...