Discussion:
How robust is INCLUDE
Add Reply
mhx
2024-12-19 15:22:39 UTC
Reply
Permalink
I wonder if the following code is (partially) ANS compatible, and
if it is easy to understand what it does, especially the word MAIN3.
Can it be written in a completely standard way?

What I need is a word that is passed parameters that define an index
into an array that is not allotted yet. So neither the index nor the
base address
can be pre-computed. When the word executes (after much more code which
finally sets up the data), it should access the array to fetch a byte at
the indexed position.
The way I've set it up, the user of the program edits a file to allocate
the data and define a function that does the fetching.

If your Forth lacks >S S> S , leave them away or replace with >R R> R@

FORTH> MAIN3
one, two, three = 1 2 3 \ 1 2 3
result = 123
MAIN3 compiled a noname $013454C0 ok
FORTH> $013454C0 idis
$013454C0 : [trashed]
$013454CA movzx rbx, $01345086 byte-offset
$013454D1 push rbx
$013454D2 ;
FORTH> $01345086 c@ . 123 ok

-marcel
---
\ in THIS file
CREATE myinsert
," ] CR DUP . R@ . S . one . two . three . one two * three * DUP TO
result ["
: MAIN0 ( -- )
1 2 3 0 LOCALS| result three two one |
4 >S 5 >R 6
[ myinsert COUNT EVALUATE ] ( compile time, locals accessible )
CR ." myinsert compiled `one two * three * DUP TO result` "
CR ." stack = " . ." \ 6"
CR ." R> = " R> . ." \ 5"
CR ." S> = " S> . ." \ 4"
CR ." one, two, three = " one . two . three . ." \ 1 2 3"
CR ." MAIN0 does `one two * three *` = " 0DEC.R
." , result = " result . ;

\ in file inside1.frt
\ ] CR DUP . R@ . S . one . two . three . one two * three * DUP TO
result [
: MAIN1 ( -- )
1 2 3 0 LOCALS| result three two one |
4 >S 5 >R 6
[ S" inside1.frt" INCLUDED ] ( at compile time, locals accessible )
CR ." inside1.frt compiled `one two * three * DUP TO result` "
CR ." stack = " . ." \ 6"
CR ." R> = " R> . ." \ 5"
CR ." S> = " S> . ." \ 4"
CR ." one, two, three = " one . two . three . ." \ 1 2 3"
CR ." MAIN1 does `one two * three *` = " 0DEC.R
." , result = " result . ;

\ in file inside2.frt
\ CR .( I see ) DUP . .( on the stack, ) S .
\ .( on the S-stack, locals one/two/three = ) OVER . 2 PICK . 3 PICK
Anton Ertl
2024-12-20 09:59:38 UTC
Reply
Permalink
Post by mhx
I wonder if the following code is (partially) ANS compatible, and
if it is easy to understand what it does, especially the word MAIN3.
There is no definition of MAIN3 in what you posted, only a use, so no.
Post by mhx
What I need is a word that is passed parameters that define an index
into an array that is not allotted yet. So neither the index nor the
base address
can be pre-computed.
When the word executes (after much more code which
finally sets up the data), it should access the array to fetch a byte at
the indexed position.
From this description, what's wrong with

: array-c@ ( c-addr uindex -- c ) + c@ ;

? But I expect that I missed something about your requirements.

In general, if you want a program to be easily understandable, avoid
iForthisms (especially where standard alternatives are
straightforwardly available. Avoiding LOCALS| is also a good idea.
It's unintuitive and therefore harder-to-understand order of locals
was the reason why {: was standardized.

- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: https://forth-standard.org/
EuroForth 2024: https://euro.theforth.net
minforth
2024-12-20 10:12:13 UTC
Reply
Permalink
I don't think I quite understand what you're trying to achieve.
But what happens if there are errors in the process?
Leftover garbage on the s-stack?

At least in my system(s), INCLUDED is implemented with an
internal CATCH/THROW mechanism, which clears all important
stacks (and some internal stuff) on error.

As for ANS compatibility: who cares, as long as your code
is well documented.
mhx
2024-12-20 11:23:43 UTC
Reply
Permalink
Post by minforth
I don't think I quite understand what you're trying to achieve.
But what happens if there are errors in the process?
Leftover garbage on the s-stack?
In iForth the S-stack is a first class citizen. It might also work
to make this stack cyclical.
Post by minforth
At least in my system(s), INCLUDED is implemented with an
internal CATCH/THROW mechanism, which clears all important
stacks (and some internal stuff) on error.
I would sure hope so :-)
Post by minforth
As for ANS compatibility: who cares, as long as your code
is well documented.
I was more interested in WHY it would not be compatible.
In (old) SwiftForth the problem is that >R and R> don't work while
INCLUDEing. In (very old) gForth the problem is compiler
security. The [ >S ] is supposed to move the expected address
left by :NONAME away to expose the arguments on the data
stack. In gForth the data stack is polluted with security stuff.

Was there a problem in minforth?

-marcel
Ruvim
2025-01-28 23:00:04 UTC
Reply
Permalink
Post by mhx
I wonder if the following code is (partially) ANS compatible,
[...]
Post by mhx
\ in file inside1.frt
result [
: MAIN1 ( -- )
     1 2 3 0 LOCALS| result three two one |
     4 >S 5 >R 6
     [ S" inside1.frt" INCLUDED ]  ( at compile time, locals accessible )
Such loading of a file has an environmental dependency.

11.6.1.1718:
| INCLUDED may allocate memory in data space
| before it starts interpreting the file.

If it does such allocating, and if code space interlaces with data
space, your loading of a definition fragment will not work.


Another possible problem is accessing locals when you place data on the
return stack. This also introduces an environmental dependency.

13.3.3.2, d:
| After a definition's locals have been declared,
| a program may place data on the return stack. However,
| if this is done, locals shall not be accessed until
| those values have been removed from the return stack;


--
Ruvim

Loading...