Page 1 of 1
Testing CREATE DOES>
Posted: Thu Dec 13, 2018 9:49 pm
by JimBoyd
I noticed on the Forth standard website when testing
DOES>, there were no tests of nested
CREATE DOES>. Something similar might be useful in an object oriented package for Forth. Here is a test I came up with for nested
CREATE DOES>.
Code: Select all
SCR# 3
// TEST CREATE DOES>
HEX
: LEVEL0 ( N -- )
CREATE , DOES> ( N2 -- )
CREATE @ , , DOES> ( N3 -- )
CREATE 2@ , , , DOES> ( N4 -- )
CREATE DUP 2+ 2@ ROT @ , , , ,
DOES> ( -- )
DUP 4 + 2@ ROT 2@ 4 0
DO U. LOOP ;
2 LEVEL0 LEVEL1
3 LEVEL1 LEVEL2
5 LEVEL2 LEVEL3
7 LEVEL3 LEVEL4
LEVEL4
And here is the result
And an examination of the parameter fields.
Code: Select all
' LEVEL1 >BODY 10 DUMP
5A11 2 0 6 5A 86 4C 45 56 45 4C B2 BD 59 2 0 3 ...Z.LEVEL..Y...
OK
' LEVEL2 >BODY 10 DUMP
5A1E 2 0 3 0 13 5A 86 4C 45 56 45 4C B3 CC 59 2 .....Z.LEVEL..Y.
OK
' LEVEL3 >BODY 10 DUMP
5A2D 2 0 3 0 5 0 22 5A 86 4C 45 56 45 4C B4 E5 ......"Z.LEVEL..
OK
' LEVEL4 >BODY 10 DUMP
5A3E 2 0 3 0 5 0 7 0 4 44 55 4D 50 20 20 20 .........DUMP
OK
I'd like to hear about difficulties implementing
CREATE DOES> , what situation caused it to fail, so those of us writing our own Forths can more thoroughly test our implementations of
CREATE DOES>.
Cheers,
Jim
Re: Testing CREATE DOES>
Posted: Sat Dec 15, 2018 8:10 am
by scotws
I'm glad somebody is trying to get this test, the whole concept makes my brain explode. I know that
https://forth-standard.org/ allows comments and discussions, have you considered posting it there for feedback?
Re: Testing CREATE DOES>
Posted: Sat Dec 15, 2018 9:41 am
by GARTHWILSON
I had to go through that when I did my '816 Forth, but it has been many years so I'll have to review it when I get time. The way I originally did it turned out to have a problem, so I had to put some more brain power into it. I believe the 2nd time was a charm, but I don't remember much about it. There's also ;code, and does (a runtime routine).
Re: Testing CREATE DOES>
Posted: Sun Dec 16, 2018 7:47 pm
by JimBoyd
There's also ;code, and does (a runtime routine).
I like it. My runtime routine for
DOES> and
;CODE is named
(;CODE) but I like
DOES , it's a smaller name, and I may just rename mine.
Re: Testing CREATE DOES>
Posted: Sun Dec 16, 2018 7:54 pm
by GARTHWILSON
There's also ;code, and does (a runtime routine).
I like it. My runtime routine for
DOES> and
;CODE is named
(;CODE) but I like
DOES , it's a smaller name, and I may just rename mine.
The 6502 Forth I got started on used lower-case for the internals, and I have stuck with that. So for example,
DO compiles
do,
LOOP compiles
loop,
IF compiles
0branch, etc.. It's shorter than
(do),
(loop), etc.. which I think fig-Forth does, and if you want to put it in a comment marked out by parentheses, you can, without ending the comment prematurely.
Re: Testing CREATE DOES>
Posted: Sun Dec 30, 2018 10:17 pm
by JimBoyd
I'm glad somebody is trying to get this test, the whole concept makes my brain explode.
It really makes you appreciate what Charles Moore accomplished.
Re: Testing CREATE DOES>
Posted: Sun Dec 30, 2018 10:36 pm
by JimBoyd
The 6502 Forth I got started on used lower-case for the internals, and I have stuck with that. So for example, DO compiles do, LOOP compiles loop, IF compiles 0branch, etc.. It's shorter than (do), (loop), etc.. which I think fig-Forth does, and if you want to put it in a comment marked out by parentheses, you can, without ending the comment prematurely.
Sadly, the Commodore 64 uses PETSCII and it doesn't have a caps lock key, it has a shift lock key.
Re: Testing CREATE DOES>
Posted: Thu Jan 03, 2019 11:31 pm
by JimBoyd
Regrettably, I cannot relate any difficulties I had because the first time I wrote a Forth for the C64, the only Forth I've written, was in the mid 1990's and I have no records ( notes or source code ) from that time.
Re: Testing CREATE DOES>
Posted: Mon Jan 07, 2019 9:46 pm
by JimBoyd
The following should also work under Forth-83 and ANSForth. Edited so the computer's responses are in curly braces.
Code: Select all
: DOES1 DOES> @ . ; { OK }
: DOES2 DOES> @ 2* . ; { OK }
CREATE PI 314 , { OK }
DOES1 PI { 314 OK }
PI { 314 OK }
DOES2 PI { 628 OK }
PI { 628 OK }
DOES1 PI { 314 OK }
PI { 314 OK }
Re: Testing CREATE DOES>
Posted: Fri Oct 14, 2022 10:42 pm
by JimBoyd
The following example is for an ITC Forth. It's not so much a test to determine if CREATE DOES> is properly implemented, more like a test of what's possible. This example is a number generator which may also work with other Forth threading techniques.
Code: Select all
: GEN ( -- )
CREATE
NOOP
DOES>
DUP 2@ SWAP ROT +! ;
Now to alter GEN to change it into a number generator. Each time it is called it will return a number.
Set GEN to return an initial value of zero and increment by one each time it is executed.
Code: Select all
' GEN >BODY OFF
1 ' GEN >BODY 2+ !
Now set the new initial value to 1000 and the increment to 5.
Code: Select all
1000 ' GEN >BODY !
5 ' GEN >BODY 2+ !
In this example NOOP is just a place holder. DOES> compiles DOES , which will change the code field of the latest word in the current vocabulary. Since GEN is used to change its own code field, these two words are only executed once and can be safely overwritten after GEN modifies itself.
Re: Testing CREATE DOES>
Posted: Thu Apr 20, 2023 2:09 am
by JimBoyd
Should CREATE ;CODE be nestable if after ;CODE there is a shift to high level Forth?
Here is a test of nesting CREATE ;CODE and placing a CREATE DOES> in the mix. The JSR to the subroutine DO.VAR places the PFA on the data stack.
Code: Select all
SCR# 1
// DO.VAR
SUBR DO.VAR ( -- ADR )
CLC
W LDA 2 # ADC
W 1+ LDY CS IF INY THEN
DEX DEX
0 ,X STA 1 ,X STY
RTS
END-CODE
SCR# 2
// TEST CREATE ;CODE
DECIMAL
: LEVEL0 ( N -- )
CREATE , ;CODE ( N2 -- )
DO.VAR JSR >FORTH
CREATE @ , , ;CODE ( N3 -- )
DO.VAR JSR >FORTH
CREATE 2@ , , , ;CODE ( N4 -- )
DO.VAR JSR >FORTH
CREATE DUP 2+ 2@ ROT @ , , , ,
DOES> ( -- )
DUP 4 + 2@ ROT 2@ 4 0
DO U. LOOP ;
SCR# 3
// THE TEST RUN
2 LEVEL0 LEVEL1
3 LEVEL1 LEVEL2
5 LEVEL2 LEVEL3
7 LEVEL3 LEVEL4
LEVEL4
And the result.
Code: Select all
1 RAM 3 RAM THRU 4001 4002 4003 2 3 5 7 OK
The contents of the parameter fields of LEVEL1 , LEVEL2 , LEVEL3 and LEVEL4 .
Code: Select all
' LEVEL1 >BODY 2 DUMP
7A0C 2 0 3 40 1 7A 86 4C 45 56 45 4C B2 B0 79 2 B@C@A..LEVEL...B
OK
' LEVEL2 >BODY 4 DUMP
7A1B 2 0 3 0 3 40 10 7A 86 4C 45 56 45 4C B3 C2 B@C@C@P..LEVEL..
OK
' LEVEL3 >BODY 6 DUMP
7A2C 2 0 3 0 5 0 3 40 21 7A 86 4C 45 56 45 4C B@C@E@C@!..LEVEL
OK
' LEVEL4 >BODY 8 DUMP
7A3F 2 0 3 0 5 0 7 0 4 44 55 4D 50 20 20 20 B@C@E@G@DDUMP
OK
These are the same results as with my test of nested CREATE DOES> .
Re: Testing CREATE DOES>
Posted: Thu Nov 16, 2023 10:09 pm
by JimBoyd
I made an error in the following and I'm surprised nobody noticed. At least, nobody commented on it.
The following example is for an ITC Forth. It's not so much a test to determine if CREATE DOES> is properly implemented, more like a test of what's possible. This example is a number generator which may also work with other Forth threading techniques.
Code: Select all
: GEN ( -- )
CREATE
NOOP
DOES>
DUP 2@ SWAP ROT +! ;
Now to alter GEN to change it into a number generator. Each time it is called it will return a number.
Set GEN to return an initial value of zero and increment by one each time it is executed.
Code: Select all
' GEN >BODY OFF
1 ' GEN >BODY 2+ !
Now set the new initial value to 1000 and the increment to 5.
Code: Select all
1000 ' GEN >BODY !
5 ' GEN >BODY 2+ !
In this example NOOP is just a place holder. DOES> compiles DOES , which will change the code field of the latest word in the current vocabulary. Since GEN is used to change its own code field, these two words are only executed once and can be safely overwritten after GEN modifies itself.
When GEN is run without a name, CREATE will abort with an error message.
CREATE should not be in the definition of GEN if it is to modify itself. The presence of NOOP and DOES (compiled by DOES> ) reserves room for two cells.
Code: Select all
: GEN
NOOP
DOES>
DUP 2@ SWAP ROT +! ;
GEN
1000 ' GEN >BODY !
5 ' GEN >BODY 2+ !
A short test.
And the results.
Code: Select all
TEST 1000 1005 1010 1015 1020 OK
TEST 1025 1030 1035 1040 1045 OK
TEST 1050 1055 1060 1065 1070 OK
Re: Testing CREATE DOES>
Posted: Tue Nov 21, 2023 4:10 pm
by BruceRMcF
The 6502 Forth I got started on used lower-case for the internals, and I have stuck with that. So for example, DO compiles do, LOOP compiles loop, IF compiles 0branch, etc.. It's shorter than (do), (loop), etc.. which I think fig-Forth does, and if you want to put it in a comment marked out by parentheses, you can, without ending the comment prematurely.
Sadly, the Commodore 64 uses PETSCII and it doesn't have a caps lock key, it has a shift lock key.
For my (still unfinished) xForth for the X16, which supports both ASCII and PETSCII, I use upper case ASCII for the Forth words, which is still upper case in PETSCII graphics and is lower case in PETSCII upper/lower case. In that context, lower case for the internals would drive me around the bend, since it would be EXTERNALNAME internalname in ASCII mode and externalname INTERNALNAME in PETSCII upper/lower case and EXTERNALNAME <petsciigraphicstring> in PETSCII graphics mode.
At one time I must have come across a Forth that uses DO<name> for internals, since that I what I mostly have ... DOLOOP DOLIT etc. ... but one of the conventions I might use to save a scattered byte here or there is to use the leading underscore for the internals ... _LOOP _LIT etc.
In PETSCII, that underscore character is a right pointing arrow, which kind of works.
Re: Testing CREATE DOES>
Posted: Thu Dec 21, 2023 12:01 am
by JimBoyd
The internals for the DO LOOPs and a few others now have the same name as the compiling words in my Forth.
The internal for DO is DO and the internal for LOOP is LOOP to name just two. This is because an internal does not normally need found once its compiling word is defined.