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

Code: Select all

3 LOAD 2 3 5 7  OK
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
GARTHWILSON wrote:
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
JimBoyd wrote:
GARTHWILSON wrote:
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
scotws wrote:
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
GARTHWILSON wrote:
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.

Code: Select all

GEN

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.
JimBoyd wrote:

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.

Code: Select all

GEN

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.

Code: Select all

GEN 
GEN
   
NAME?!

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.

Code: Select all

: TEST 
   5 0 
   DO 
       GEN . 
   LOOP ; 

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
JimBoyd wrote:
GARTHWILSON wrote:
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.