Jump to content
IGNORED

Camel99 Forth Information goes here


TheBF

Recommended Posts

 ?Burnt Neurons?

 

Well it took me long enough but after reviewing the Forth Standard web site and a couple of other implementations I finally have  a pretty good version of WORDLISTs and VOCABULARY for Camel99 Forth.

Pointers to pointers can make me crazy and I had to make some internal changes to the Camel Forth kernel which was not built for this business.

 

FIND is now a vectored word in the kernel so I can replace its functionality with FIND12 in this file.

I also needed a CURRENT variable and CONTEXT array of 9 cells and the word HEADER which creates names in the dictionary needed a tweek as well.

 

WORDLIST and VOCABULARY and this lexicon address the issue of NAMESPACE control in a Forth system.  The nice thing about these new ideas is that you can make the search order of the namespaces anything you want, in this case limited to 8 different name spaces. Or you can just make an abstract WORDLIST and use these operations on them more manually.

 

Here is the code. It could use some improvements for SET-ORDER and GET-ORDER which are right off the Forth- Standard.org. The 2012 standard assumes you have a pretty big machine, so it's kind of bulky.

But after two weeks of playing with this I am going to leave it working for now. :)

 

I need to explore the 4 way hashed dictionary concept from F83 Forth too because I really need to burn more brain cells with even more pointers... ?

But more seriously speeding up compilation by a factor of 3X would make Camel99 compile at 30 lines/second!

 

I will do a demonstration video at some point of how these wordlists are used.

If anyone wants a version of the newest kernel & libs let me know. Otherwise I will hang on until I get this fast compiling working.

 

It doesn't look like much but I had never delved into this area before so it was stretching me.

 

Edit: replaced with final code.  Now ONLY puts two copies of the ROOT-WORDLIST in the context array so there is always one copy available to the system. ROOT vocabulary is now not needed.

 

Spoiler

\ wordlist.fth   for CAMEL99 FORTH    Oct 2020 Brian Fox
\ Code adapted from Web: https://forth-standard.org/standard/search

\ 'wid' is a word-list ID.
\ Holds the address of the last Forth word in the list
\ In Camel Forth terms, wid is a pointer to a Name field address (NFA)

\ This implementation uses a pre-defined CONTEXT array to hold the
\ ROOT wordlist plus 8 user defined wordlists

\ NEEDS .S     FROM DSK1.TOOLS
HERE
DECIMAL
9 CONSTANT #WIDS        \ max no. of wordlists
  VARIABLE #ORDER       \ No. of active wordlists
  1 #ORDER !            \ init the #order to 1
  VARIABLE WID-LINK     \ Pointer to the most recently defined wordlist.

: (WORDLIST) ( addr -- wid)
   0 ,                      \ "LATEST" for this word list
   WID-LINK @ , WID-LINK !  \ link to previous wordlist (none)
   LATEST @ ,               \ compile NFA of latest word created
;
\ non-standard: named wordlist
: WORDLIST  ( <name> -- wid) CREATE  HERE (WORDLIST) ;

 WORDLIST FORTH-WORDLIST
 WORDLIST ROOT-WORDLIST

HEX ( make ASM version)
: ]CONTEXT ( n -- addr) CELLS CONTEXT + ;  \ CONTEXT array

\ E.16.6.1.1647 GET-ORDER
: GET-ORDER ( -- widn ... wid1 n ) \ *Notice reversed order on stack
   #ORDER @ 0
   ?DO
     #ORDER @ I - 1- ]CONTEXT @
   LOOP
  #ORDER @
;

\ E.16.6.1.2197 SET-ORDER
\ This is the complement of E.16.6.1.1647 GET-ORDER.
DECIMAL
: SET-ORDER ( wid1x ... wid1 n -- )  \ n cannot be 0
   DUP TRUE =
   IF
     DROP                 \ drop flag, push default wordlists
     ROOT-WORDLIST DUP 2  \ 2 copies of ROOT so it's always there
   THEN
   DUP 9 1 WITHIN ABORT" #ORDER range[1..8]"
   DUP #ORDER !
   0 ?DO  I ]CONTEXT !  LOOP
;

\ E.16.6.2.0715 ALSO
: ALSO ( -- ) GET-ORDER OVER SWAP 1+ SET-ORDER ;

\ E.16.6.2.1965  ONLY
: ONLY ( -- ) TRUE SET-ORDER ;  \ sets default search order

\ E.16.6.2.2037 PREVIOUS
: PREVIOUS    ( -- ) GET-ORDER NIP 1- SET-ORDER ;

: SET-CURRENT ( wid --) CURRENT ! ;
: SET-CONTEXT ( wid -- ) \  place 'wid' at beginning of search order
       >R
       GET-ORDER NIP       \ remove 1st 'wid'
       R>                  \ put this 'wid in the order
       SWAP SET-ORDER  ;   \ make it so

: DEFINITIONS ( -- ) CONTEXT @ SET-CURRENT ;

\ non-standard but nice to have
: VOCABULARY  ( wid -- )   \ create a named vocabulary
    CREATE
      HERE 2+ ,            \ pointer to the wid
      HERE (WORDLIST)      \ create the wordlist structure
    DOES> @ SET-CONTEXT ;

HEX
: .WID  ( wid -- ) [ 2 CELLS ] LITERAL + @ COUNT 1F AND TYPE ;
: ORDER ( -- )  \ display search order by wordlist name
   CR ." Order: "
   GET-ORDER 0 DO   .WID  SPACE   LOOP
   CR ." Current: " CURRENT @ .WID CR ;

\ 6.1.1550 Extend FIND to search all active wordlists
\ Find the definition named in the counted string at c-addr.
: FIND12 ( c-addr -- c-addr 0 | xt 1 | xt -1 )
      FALSE             \ default flag
      CONTEXT #ORDER @ CELLS
      BOUNDS  \ compute end-address,start-address
      ?DO     \ I is the address for faster searches
          OVER I @ @ (FIND)
          ?DUP
           IF
              2SWAP 2DROP
              UNLOOP EXIT
           THEN
           DROP
       2 +LOOP ;

\ : ROOT   ( -- ) ROOT-WORDLIST  SET-CONTEXT ;
: FORTH  ( -- ) FORTH-WORDLIST SET-CONTEXT ;
LATEST @  FORTH-WORDLIST !  \ patch FORTH-WORDLIST to this point

 FORTH-WORDLIST SET-CONTEXT
 ROOT-WORDLIST SET-CURRENT  \ compile into ROOT-WORDLIST

\ " minimum search order shall include the words FORTH-WORDLIST & SET-ORDER"
: FORTH-WORDLIST  FORTH-WORDLIST ;
: SET-ORDER       SET-ORDER ;

: FORTH  FORTH ;
\ : ROOT   ROOT  ;
: ONLY   ONLY  ;
: ALSO   ALSO  ;
: ORDER  ORDER ;
: DEFINITIONS  DEFINITIONS ;

ONLY FORTH DEFINITIONS

\ patch FIND to become FIND12
 ' FIND12 'FIND !
HERE SWAP - DECIMAL SPACE . .( bytes) CR
HEX

 

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

1 hour ago, TheBF said:

Well it took me long enough but after reviewing the Forth Standard web site and a couple of other implementations I finally have  a pretty good version of WORDLISTs and VOCABULARY for Camel99 Forth.  . . .

 

I have only scanned it, so certainly have not assimilated it, but I am confused by a couple of things (doesn’t take much!):

  • I don’t understand the second to last definition. Is it mistyped—( ' FIND12 ' FIND ! )?
  • It is not fair to ask this question without reading what you have read, but what is the ROOT word list for and why would one need re-definitions to place words there?

Yeah, my head hurts a little, too—and I have not dug as deep as you have.

 

...lee

Link to comment
Share on other sites

8 hours ago, Lee Stewart said:

 

I have only scanned it, so certainly have not assimilated it, but I am confused by a couple of things (doesn’t take much!):

  • I don’t understand the second to last definition. Is it mistyped—( ' FIND12 ' FIND ! )?
  • It is not fair to ask this question without reading what you have read, but what is the ROOT word list for and why would one need re-definitions to place words there?

Yeah, my head hurts a little, too—and I have not dug as deep as you have.

 

...lee

 

If you look closely you see the second ' is part of find.

' FIND12  'FIND !

'FIND is a variable. :)   I used the tick to remind me that it is the "address of something".  I have seen this mnemonic usage from others. 

 

And FIND is  defined as

: FIND   'FIND PERFORM ;

PERFORM is a new word that is like "@ EXECUTE"  in ALC so it's a bit faster.

 

So whatever execution token  (CFA) I stuff into 'FIND  gets executed when you run FIND.

It's a manual way to do a DEFER word thing without adding all the overhead to my tiny kernel.

 

I do the same thing for INTERPRET because I needed a forward reference to INTERPRET in the cross-compiling process but that's another story.

Suffice to say I had the mechanism so I am using it to patch the FIND word to allow search order control after the kernel has been built.

A lot of Forth kernels used DEFER words for multiple parts of the system so that you can change their operation as needed for special cases.

 

ROOT

 

So this is part of the Forth 83 and forward ideas on VOCABULARIES.  If the programmer is free to change the search order what happens if they remove FORTH from the search order?  :)

The word ONLY is there to revert back to some default set of words that will let you get back home to FORTH.  :)

 

This is actually a bug in my current code.  I need to LOCK the ROOT vocabulary in  [0]CONTEXT of the CONTEXT array and never move it and allow the programmer to only change 1 .. 8.

That's on my list for today.

 

 

  • Like 2
Link to comment
Share on other sites

44 minutes ago, TheBF said:

This is actually a bug in my current code.  I need to LOCK the ROOT vocabulary in  [0]CONTEXT of the CONTEXT array and never move it and allow the programmer to only change 1 .. 8.

That's on my list for today.

Actually simplest thing to do is make ONLY put both the ROOT wordlist and the FORTH-WORDLIST in the search order.

That's as easy as:

 

: SET-ORDER ( wid1x ... wid1 n -- )  \ n cannot be 0
   DUP TRUE =
   IF
     DROP    \ drop the flag, push default wordlist and no. of lists
     ROOT FORTH-WORDLIST 2  \ default to ROOT and FORTH-WORDLIST
   THEN
   DUP 10 1 WITHIN ABORT" #ORDER range[1..9]"
   DUP #ORDER !
   0 ?DO  I ]CONTEXT !  LOOP
;

Which begs the question do I even need a ROOT wordlist?  Just make Forth the default. when ONLY is executed.  Things to consider.

  • Like 1
Link to comment
Share on other sites

So I have played around with this version and it seems pretty stable. It's also pretty big at 806 bytes.

BUT...

 

With the ability to search across 9 wordlists what if I put each wordlist in it's own 8K SAMS space?

FORTH vocabulary would use the pass-through SAMS values.

The would give me 72K of total code space! :) 

And the compiler can search all of it...

 

I think I have the code to make that work pretty quickly.

There goes another week...

 

Edit:  Final version is here

 

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

? Give that CAMEL a Bigger Hump! -> ?

 

So I have been tardy in doing this but it was time I made a way to save the Camel99 Forth system from memory to EA5 files.

This allows a developer to compile their favourite tools and then save the entire image as a custom Forth configuration. Really speeds up getting started versus re-compiling all the tools.

 

I had the beginnings of it in the cross-assembler demo so I just started today to "git 'er done".

Traditional Forth systems use blocks to save the binary data with the command BSAVE and then you can reload the code back to memory from Forth like an overlay with BLOAD.

 

Camel99 doesn't use block files unless they are loaded. I wanted to save in EA5 format and I thought it might get awkward.

It turned out that by taking the Forth approach and making a meta-language to compute the file properties it got simpler.

These words are the key:

\ words to compute Forth system properties
: SYS-SIZE    ( -- n) 'ORG HERE SWAP - ;
: #FILES      ( -- n)  SYS-SIZE 8K /MOD SWAP IF 1+ THEN ;
: CODECHUNK   ( n -- start) 8K * 'ORG + ;
: CHUNKSIZE   ( n -- n ) HERE SWAP CODECHUNK -  8K MIN ;

SYS-SIZE      gives you the number bytes the Forth dictionary is using

#FILES         computes how many 8K files will it take to store the dictionary

CODECHUNK takes an index 0..n and returns where that 8K section is in memory

CHUNKSIZE  takes an index 0..n and returns how many bytes the chunk size is. (the lesser of the CHUNKsize and 8K, for that last CHUNK) 

 

With these it was mostly just looping #FILES times and setting up the header, writing the chunks to VDP RAM and saving as a program file.

 

There are some rules.  

  1. You must create a startup word.  If it's Forth it must start with WARM to init the system and end with ABORT to reset the command line interpreter. In between put whatever you like.
  2. You must pass the "execution token" (XT) of your startup word to SAVESYS on the data stack.  You get that XT with the tick (')  operator.  See the bottom of the spoiler.
  3. You must use the LOCK command at the point where you want the system to remember the dictionary. Everything after LOCK will not be present when you restart the image.
  4. You must give SAVESYS a valid path to save the files.  

The video shows the spoiler being pasted into Classic99 creating a system binary called BIGCAMEL. Then we bounce out and load BIGCAMEL from the main menu.

Only took me 4 years to get here. :)

 

Edit: Removed line of code from older thinking...

Spoiler

\ SAVESYS.FTH  save Forth dictionary as EA5 program   B Fox Oct 2020
\ creates a binary program E/A 5 format.
\ Makes as many files as needed to save the system

\ put your include options here
INCLUDE DSK1.TOOLS
INCLUDE DSK1.WORDLISTS
INCLUDE DSK1.ASM9900
INCLUDE DSK1.LOADSAVE

\ Make your BOOT routine. it must start with WARM and end with ABORT
: NEW-START
     WARM
     CR ." Includes TOOLS,WORDLISTS and ASSEMBLER"
     ABORT ; \ the simplest start-up routine

LOCK   \ everything compiled before this will restore when
       \ this saved system is reloaded.
       \ The SAVESYS code will not be in the dictionary on restart
       \ UNLESS you put LOCK at the end of this file.

MARKER /SAVESYS

HEX
A000 CONSTANT 'ORG     \ start of Camel99 Forth program in CPU RAM
1000 CONSTANT VDPBUFF  \ Programs write to file from VDP Ram
2000 CONSTANT 8K
0013 CONSTANT <PROGRAM> \ file type

\ define the file header fields *THESE ARE VDP ADDRESSES*
VDPBUFF           CONSTANT MULTIFLAG
VDPBUFF 1 CELLS + CONSTANT PROGSIZE
VDPBUFF 2 CELLS + CONSTANT LOADADDRESS

VDPBUFF 3 CELLS + CONSTANT CODEORG \ COPY 8K program chunks to here

\ words to compute Forth system properties
: SYS-SIZE    ( -- n) 'ORG HERE SWAP - ;
: #FILES      ( -- n)  SYS-SIZE 8K /MOD SWAP IF 1+ THEN ;
: CODECHUNK   ( n -- start) 8K * 'ORG + ;
: CHUNKSIZE   ( n -- n ) HERE SWAP CODECHUNK -  8K MIN ;
: LASTCHAR++  ( addr len) 1- +  1 SWAP C+! ;

CREATE FBUFF ( -- addr) 20 ALLOT
: FILE$      ( -- addr len)   FBUFF COUNT ;

HEX
: SAVESYS ( XT -- <textpath> )
        BOOT !
        BL PARSE-WORD  ?PATH  FBUFF PLACE
        #FILES 0
        ?DO
          CR ." Writing file " 0 . ." of " #FILES .
          CR ." Init header " I .
          CR
           I 1+ #FILES <> DUP .  MULTIFLAG V!
           I CHUNKSIZE    DUP .  PROGSIZE V!
           I CODECHUNK    DUP .  LOADADDRESS V!

          CR ." Erase CODE buffer"
             CODEORG  8K 0 VFILL
          CR ." Copy CODE chunk to VDP"
           I CODECHUNK CODEORG  PROGSIZE V@  VWRITE
          CR ." Write to disk ..."
            FILE$  VDPBUFF PROGSIZE V@  <PROGRAM> SAVE-FILE
           CR ." Update file name"
           FILE$ LASTCHAR++
           CR
        LOOP
        CR ." System Save complete"
        CR ." In " #FILES .  ." EA5 files"
;

' NEW-START SAVESYS DSK1.BIGCAMEL

 

 

  • Like 1
Link to comment
Share on other sites

SAVESYS Update

 

Well... it works mostly.  It does not play nicely with my recent WORDLIST code. Something else needs initializing.

I quickly realized I needed to patch in the multiple-wordlist search routine but there something more to connect. Pointers pointers everywhere.

I am done for the night.

 

:) 

  • Like 1
Link to comment
Share on other sites

On 10/16/2020 at 10:45 AM, GDMike said:

"used the tick to remind me that it is the "address of something".  "

Ooooh, I like that!!! Very interesting 

This is an interesting area in Forth.  Since a Forth word can me made of any ascii characters there have been some naming "conventions" that evolved over time.

 

So ' mentioned is used to indicate addresses or execution tokens (which are just addresses in threaded Forth)

Here are a few more with examples:

  • Leading question mark:  means this word will do something conditionally based on the input parameter (?ABORT  ?PATH)
  • Trailing question mark: This word returns a flag  ( KEY?   READY?  CTS? )
  • Leading Dot character: This word prints something ( .NAME .ADDRESS .CITY)
  • @ character:  These words fetch something from memory  or an I/O channel ( RECORD@  FREQUENCY@ )
  • ! character:  Store something.  ( RECORD!  FREQUENCY!)
  • '/' character:  Used like 'per' in English.  ("characters per line"  C/L   BYTES/RECORD ) 
  • Bracketed words: Internal words for the system. Not normally used directly.  (TYPE)  (EMIT)  (KEY)
  • Square bracketed words: These word execute immediately even when the compiler is on. [CHAR] [COMPILE] 
  • : and ;   These words compile new things and end the compilation.  ( ASM:  ;ASM)
  • #  trailing usually means  this  word returns a number.  ( PHONE#  REC# )

This one I have only seen in Open-Firmware code by Mitch Bradley but I use it

  • Leading bracket: These words require an index.  ( ]MYARRAY  ]PHONE# )

    This one is frowned upon by Forth purists but I find it handy.
  • Trailing $: the word is a string.   ( A$ B$ C$ ) :) 
  • Leading $: This word is a string function ( $RIGHT $POS )
  • Like 1
Link to comment
Share on other sites

7 minutes ago, GDMike said:

Do most FORTHs use "/" as a comment on First line or "(" as a remark,? Ended with ")"?

Or is that something that can be defined?

 

'\'  is the single line comment.

 

(  your comment goes here )  is the inside some code comment.

 

But it you want your own comment do this:


: \\    BL WORD DROP ;  ( C++ )
: --   BL WORD DROP  ;  ( ADA )
: REM   BL WORD DROP ;  ( YOU KNOW...)

:) 

 

Oops I think C++ is //   

Link to comment
Share on other sites

11 minutes ago, TheBF said:
  • This one is frowned upon by Forth purists but I find it handy.
  • Trailing $: the word is a string.   ( A$ B$ C$ )

Haha, I wonder why it matters because you can't beat one character if production is what your looking for?

I find"." Period odd too, bit that's me. For displaying an output stream or whatever you call it, DOS uses a pipe I think, maybe not it's been awhile.

Link to comment
Share on other sites

1 minute ago, GDMike said:

Hmm I'll have to see what"word" doos

Remember it these characters don't "do" anything.  They are just names in the dictionary.

"word"  could also be the name of the text for a string that spells "word" :)

 

I do things like this too:

CHAR A CONSTANT 'A'
CHAR Q CONSTANT 'Q'

It can make the code more readable but it does not affect what happens.  After these definitions 'A' will just put the ascii value 65 on the stack. :)  You could have just typed 65.

 

  • Like 1
Link to comment
Share on other sites

Create an Executable Program in Camel99 Forth

 

I of course discovered some bugs in my SAVESYS command that involved compensating for the 6 byte header at the top of an EA5 program file. :)

It was subtle.  It meant that everything in the saved Forth system worked normally except for that one routine that crossed the gap between the 1st file chunk and the 2nd file chunk.

Fortunately with the excellent tools provided by TI99DIR I could clearly see what was missing and add the 6 byte offsets (positive and negative) where they were needed.

The spoiler has the finished working code.  It worked so well I made a video for my channel.  

 

 

 

 

Spoiler

\ SAVESYS.FTH  save Forth dictionary as EA5 program   B Fox Oct 2020
\ creates a binary program E/A 5 format.
\ Makes as many files as needed to save the system

\ typically load your include options first
\ INCLUDE DSK1.TOOLS
\ INCLUDE DSK1.SHELL

MARKER /SAVESYS
INCLUDE DSK1.LOADSAVE  \ we use SAVE-FILE from this library

HEX
A000 CONSTANT 'ORG     \ start of Camel99 Forth program in CPU RAM
1000 CONSTANT VDPBUFF  \ Programs write to file from VDP Ram
2000 CONSTANT 8K
  13 CONSTANT PROG     \ file mode for Program files

\ define the file header fields *THESE ARE VDP ADDRESSES*
VDPBUFF            CONSTANT MULTIFLAG
VDPBUFF  1 CELLS + CONSTANT PROGSIZE
VDPBUFF  2 CELLS + CONSTANT LOADADDR
VDPBUFF  3 CELLS + CONSTANT CODEORG     \ COPY 8K program chunks to here

\ words to compute Forth system properties
: SYS-SIZE    ( -- n) 'ORG HERE SWAP - ;
: #FILES      ( -- n)  SYS-SIZE 8K /MOD SWAP IF 1+ THEN ;
: CODECHUNK   ( n -- addr)
              DUP 8K * ( -- n addr)
              SWAP IF          \ if n <> 0 ie: 2nd, 3rd, chunks
                  3 CELLS  -  \ subtract header space
              THEN 'ORG + ;

: CHUNKSIZE   ( n -- n )
              HERE SWAP CODECHUNK -    \ compute size
              3 CELLS +                \ add 6 bytes for header
              8K MIN  ;                \ take lesser of size or 8K

: LASTCHAR++  ( Caddr --) COUNT 1- +  1 SWAP C+! ;

HEX
: SAVESYS ( XT -- <textpath> )
       CR
        BOOT !
        BL PARSE-WORD  ?PATH  PAD PLACE
        #FILES 0
        ?DO
          CR ." Writing file " I . ." of " #FILES .
          CR ." Init file header " I . ." : "
           I 1+ #FILES <> DUP .  MULTIFLAG V!
           I CHUNKSIZE    DUP .  PROGSIZE V!
           I CODECHUNK    DUP .  LOADADDR V!

          CR ." Copy CODE chunk to VDP"
           CODEORG  8K 0 VFILL
           LOADADDR V@  CODEORG  PROGSIZE V@  VWRITE

          CR ." Write to disk ..."
            PAD COUNT  VDPBUFF PROGSIZE V@  PROG SAVE-FILE
           CR ." Update file name"
           PAD LASTCHAR++
           CR
        LOOP
        CR ." System size=" DECIMAL SYS-SIZE U. ." bytes"
        CR ." Saved in " #FILES .  ." EA5 files"
        CR
;

\ Make your BOOT routine. it must start with WARM and end with ABORT
\ -OR- the word that starts your application.
HEX
: COLD   \ A simple start-up routine
     WARM       ( this also sets 40 col. TEXT mode)
     17 7 VWTR  ( set screen color)
     CR ." Includes TOOLS,SHELL,SAVESYS"
     ABORT ;

LOCK   \ everything compiled before this will restore when
       \ this saved system is reloaded.
       \ The SAVESYS code will not be in the dictionary on restart
       \ UNLESS you put LOCK at the end of this file.


' COLD SAVESYS DSK1.FXFORTH

 

 

 

  • Like 1
Link to comment
Share on other sites

On 10/19/2020 at 8:03 PM, GDMike said:

Or dec 65..I don't think ti Forth knows dec as decimal, but I'd create it.

Like gotoxy I've shortened to GXY

On our favourite little computer you have to be careful redefining lots of stuff. Each Name you add to the dictionary takes space for the text and the header that makes it into a linked list, plus the EXIT (2 bytes) that is compiled by the ';'  

It can add up quickly.   Just doing this in FbForth, Turbo Forth or Camel99 Forth uses 12 extra bytes.

: TEST ;

 

  • Thanks 1
Link to comment
Share on other sites

4 hours ago, TheBF said:

On our favourite little computer you have to be careful redefining lots of stuff. Each Name you add to the dictionary takes space for the text and the header that makes it into a linked list, plus the EXIT (2 bytes) that is compiled by the ';'  

It can add up quickly.   Just doing this in FbForth, Turbo Forth or Camel99 Forth uses 12 extra bytes.


: TEST ;

And I thought memory was free..

Good to know.thx

Edited by GDMike
Link to comment
Share on other sites

On 10/19/2020 at 7:48 PM, GDMike said:

Hmm I'll have to see what"word" doos

Just realized I didn't respond to this one. If you didn't already look it up WORD is the primary text parser in Forth83,Forth79 and Fig Forth (Like TI-Forth and FbForth are Fig descendants)

It is used by the compiler and interpreter to get each word from the string we feed to them, one word at a time.

 

Here is the "official definition" for Forth 2012.

WORD

( char "<chars>ccc<char>" -- c-addr )

Skip leading delimiters. Parse characters ccc delimited by char. An ambiguous condition exists if the length of the parsed string is greater than the implementation-defined length of a counted string.

c-addr is the address of a transient region containing the parsed word as a counted string.

If the parse area was empty or contained no characters other than the delimiter, the resulting string has a zero length. A program may replace characters within the string.

 

So if that doesn't help you... :)  (amazing)

 

Here is what they are trying to tell us:

  • Take a character delimiter parameter from the data stack.
  • Read the text after the word WORD until you encounter that delimiter character. 
  • While reading the text, skip any leading spaces (blanks).
  • Typically WORD stores the string at the address called HERE and appends a space to the end of the string it read.
  • It leaves behind a *byte counted string on the data stack with the delimited text.

    ( *string where the 1st byte is the length)

    It is not like INPUT in BASIC. It is really best used if you want to make your own compiler extensions. 
    If you are careful you can use WORD to make commands like the Assembler DATA and BYTE directives for example.

 

 

  • Like 1
Link to comment
Share on other sites

1 hour ago, TheBF said:

WORD

( char "<chars>ccc<char>" -- c-addr )

I do not believe the counted string is left on the stack, but, rather, its address. figForth (and its descendants TI ForthfbForth, et al.) always stashes the parsed char-delimited token as a counted string at HERE and des not leave the address because it is already known. Pretty much the only useful place for WORD in figForth is in a definition because the very next token in the input stream is processed by INTERPRET , which uses WORD to parse it and store it at HERE , overwriting the token you were interested in before you can use it.

 

A word that is more like Basic’s INPUT is EXPECT , which requires the storage address and maximum character count on the stack. Only the entered string is stored.

 

...lee

  • Like 2
Link to comment
Share on other sites

1 hour ago, Lee Stewart said:

I do not believe the counted string is left on the stack, but, rather, its address. figForth (and its descendants TI ForthfbForth, et al.) always stashes the parsed char-delimited token as a counted string at HERE and des not leave the address because it is already known. Pretty much the only useful place for WORD in figForth is in a definition because the very next token in the input stream is processed by INTERPRET , which uses WORD to parse it and store it at HERE , overwriting the token you were interested in before you can use it.

 

A word that is more like Basic’s INPUT is EXPECT , which requires the storage address and maximum character count on the stack. Only the entered string is stored.

 

...lee

Yes I misspoke. It is the address of course. Since that is how Forth uses strings I tend to forget that detail in common parlance.   

I also forgot about that FigForth WORD doesn't leave the address on the stack. There are a lot of small differences between the old systems and Forth83 and forward.

Small wonder it makes folks skittish.

  • Like 2
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...