6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Thu Nov 21, 2024 11:52 am

All times are UTC




Post new topic Reply to topic  [ 3 posts ] 
Author Message
 Post subject: Exploring 64Forth
PostPosted: Sun Jan 07, 2024 8:12 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 895

64Forth, a FIG Forth written by Tom Zimmer for the Commodore 64, was the first Forth I used. It is the only FIG Forth I've used. From time to time I may post more insights into the working of 64Forth as it may be of use to those using FIG Forth. If anyone else has useful insights into this implementation of FIG Forth, please share your thoughts.
This is what I've been able to uncover about 64Forth's handling of the text stream.
64Forth has sixteen buffers, twelve in the RAM underneath the kernel ROM at $E000 - $FFFF and the I/O section at $D000 - $DFFF and four in the ram at $C000 - $CFFF.
64Forth uses a single communications buffer to act as an interface to these buffers. All access is with the communications buffer. There is a zero stored in the two bytes just past the communications buffer.

64Forth has a version of SEE named SOURCE which was used to decompile EXPECT .
Code:
 : EXPECT    OVER   +   OVER   (DO)   EFLAG   @   0BRANCH 8    KEY
  BRANCH 4    CHRIN   DUP   CLIT 14    =   0BRANCH 2A    DROP   CLIT 9D 
  DUP   EMIT   SPACE   OVER   I   =   DUP   R>   2   -   +   >R   CLIT 93 
  *   -   BRANCH 2C    DUP   CLIT D    =   0BRANCH E    LEAVE   DROP
  BL   0   BRANCH 9    DUP   CLIT 7F    AND   I   C!   0   I   1+
  !   EFLAG   @   0BRANCH 8    EMIT   BRANCH 4    DROP   (LOOP) -7F 
  DROP   ;S

and here is the probable source.
Code:
: EXPECT
   OVER + OVER
   DO
      EFLAG @
      IF  KEY  ELSE  CHRIN  ENDIF
      DUP #20 =
      IF
         DROP #157 DUP EMIT SPACE
         OVER I = DUP R> 2 - + >R #147 * -
      ELSE
         DUP #13 =
         IF
            LEAVE DROP BL 0
         ELSE
            DUP #127 AND
         ENDIF
         I C! 0 I 1+ !
      ENDIF
      EFLAG @
      IF  EMIT  ELSE  DROP  ENDIF
   LOOP
   DROP ;

Notice this section of the source.
Code:
         I C! 0 I 1+ !

As 64Forth's EXPECT is storing text in memory, it is following that text by two zeros.

64Forth's ENCLOSE takes the address of the remaining text to process and a delimiter. It returns that same address and an offset to the start of the next word, the offset to the delimiter after that word and the offset to add to IN , 64Forth's word for >IN . When ENCLOSE encounters a zero after skipping any leading delimiters, it returns, along with the address passed to it, the offset to the location with zero, the offset to the location after zero and the offset for IN .

The decompilation of 64Forth's WORD
Code:
 : WORD    BLK   @   0BRANCH 12    BLK   @   BLOCK   BRANCH 6    TIB
  @   IN   @   +   SWAP   ENCLOSE   HERE   CLIT 34    BLANKS   IN
  +!   OVER   -   >R   R   HERE   C!   +   HERE   1+   R>   CMOVE
  ;S

and the probable source.
Code:
: WORD  ( DELIMITER -- )
   BLK @
   IF
      BLK @ BLOCK
   ELSE
      TIB @
   ENDIF
   IN @ +  SWAP ENCLOSE
   HERE 34 BLANKS  IN +!
   OVER - >R  R HERE C!
   + HERE 1+ R> CMOVE ;

Notice 64Forth's WORD does not leave an address on the data stack.
64Forth's WORD uses the data from ENCLOSE to update IN and store a counted string at HERE . When the zero byte is the only text left in the buffer, the string at HERE has a count of 1 and zero for the text. There is a word with this name in 64Forth. This word is immediate. In 64Forth the count byte and the byte with the last character of a name have their high bit set. The name field of this mystery word is the following: $C1 $80. This is an immediate word with a length of one and a single null character for the name.
Code:
 :      BLK   @   0BRANCH 4    ?EXEC   R>   DROP   ;S IMMEDIATE


64Forth's INTERPRET is an infinite loop. This word, when found, is used to break out of INTERPRET .

In summary, 64Forth's EXPECT does store a zero after the text and the communications buffer has a zero in the two memory locations following the buffer.
When this zero is encountered, a word is executed which exits INTERPRET .


Top
 Profile  
Reply with quote  
 Post subject: Re: Exploring 64Forth
PostPosted: Mon Jan 08, 2024 8:10 am 
Offline

Joined: Sun Apr 26, 2020 3:08 am
Posts: 357
I am starting to think the zero at the end of the line only refers to Forth's that deal with screens and not text files. Not only does Interpret end when interpreting a word, but screens also end when trying to list a screen if a zero is accidentally stored in the middle of a screen.


Top
 Profile  
Reply with quote  
 Post subject: Re: Exploring 64Forth
PostPosted: Tue Jan 09, 2024 1:25 pm 
Offline

Joined: Wed Aug 21, 2019 6:10 pm
Posts: 217
JimBoyd wrote:
... Notice 64Forth's WORD does not leave an address on the data stack.


Yes, that's a big difference between fig Forth and Forth-79/Forth-83 Forth's.

From https://dwheeler.com/6502/fig-forth-glossary.txt:

Code:
ENCLOSE addr1 c -- addr1 n1 n2 n3
        The text scanning primitive used by WORD. From the text address
        addr1 and an ascii delimiting character c, is determined the byte
        offset to the first non-delimiter character n1, the offset to the
        first delimiter after the text n2, and the offset to the first
        character not included.
        This procedure will not process past an ascii 'null', treating it
        as an unconditional delimiter.

IN            ---  addr                        L0
        A user variable containing the byte offset within the current input
        text buffer (terminal or disc) from which the next text will be
        accepted. WORD uses and moves the value of IN.

WORD          c  ---                            L0
        Read the next text characters from the input stream being
        interpreted, until a delimiter c is found, storing the packed
        character string beginning at the dictionary buffer HERE. WORD
        leaves the character count in the first byte, the characters, and
        ends with two or more blanks. Leading occurrences of c are ignored.
        If BLK is zero text is taken from the terminal input buffer,
        otherwise from the disc block stored in BLK.
        See BLK, IN.


IamRob wrote:
I am starting to think the zero at the end of the line only refers to Forth's that deal with screens and not text files. Not only does Interpret end when interpreting a word, but screens also end when trying to list a screen if a zero is accidentally stored in the middle of a screen.


It's part of the fig-Forth model, and fig-Forth's did their file access with Blocks ... but Forth79 allowed using NUL as a delimiter to mark exhaustion of the input stream. In Forth-79, the delimiter is stored at the end of the word, so "DUP COUNT + C@" would get the delimiter or NIL back if you wanted to find out whether there was more text in the stream.

Code:
 WORD           char -- addr                  181
     Receive  characters  from the input stream until the  non-zero
     delimiting  character  is encountered or the input  stream  is
     exhausted,  ignoring leading delimiters.   The characters  are
     stored  as  a  packed string with the character count  in  the
     first  character position.   The actual delimiter  encountered
     (char  or  null)  is stored at the end of  the  text  but  not
     included  in the count.   If the input stream was exhausted as
     WORD is called,  then a zero length will result.   The address
     of the beginning of this packed string is left on the stack.


Using "NUL or delimiter" as the end of parsing was a useful approach when a single word was used for both parsing for a word like "(" with ")" as the delimiter and a blank-delimited word.

In the 80's and 90's, when the approach of a separate word with white space that is anything from space down to NUL became more common, using a less than $21 comparison rather than an equality to $20 comparison, at the same time, it became more common to use text files and INCLUDE because the PC-DOS systems that Forth was running on had more capable text file editing systems.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 3 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 12 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: