I've changed the way WORD is defined in Fleet Forth.
Both versions use 'STREAM to obtain the address of the current position in the text stream and the remaining length. Here is the latest definition of 'STREAM .
Code: Select all
: 'STREAM ( -- ADR N )
BLK @ ?DUP
IF
BLOCK B/BUF
ELSE
TIB #TIB @
THEN
>IN @
OVER UMIN /STRING ;
Both use SKIP to skip leading occurrences of the delimiter and SCAN to scan for the delimiter at the end of the parsed text.
The new version of Fleet Forth's WORD is different in how it adjusts >IN . The old WORD saved the length returned by 'STREAM , the address returned by SKIP , and the address and length returned by SCAN . They were passed to the headerless word ADJUST in this order: address returned by SKIP , length returned by 'STREAM , address returned by SCAN , and length returned by SCAN . ADJUST calculated how far to move >IN without making it point further than one byte past the text stream. Even though ADJUST was headerless, it did have a name in the source used by the metacompiler.
For the old and new versions of WORD , as well as CHAR , when the source is a block, WORD will never leave >IN with a value larger than B/BUF ( 1024), otherwise >IN will never be left with a value larger than that in #TIB . Although >IN can be manually set to a larger value, doing so causes 'STREAM to return a size of zero for the remaining length of the text stream.
The new version of Fleet Forth's WORD does away with the headerless word ADJUST . The length returned by 'STREAM is added to >IN , pushing it just past the text stream. The length remaining returned by SCAN is decremented and the maximum of it and zero is subtracted from >IN .
The change to CHAR also did away with the need for ADJUST . CHAR takes a delimiter and returns an address and length for the parsed text. CHAR does not skip leading delimiters and the text stream can not be exhausted without an error condition since the delimiter must be found. The only place CHAR alters >IN is where the returned length plus one is added to >IN .
Here are the old versions of WORD and CHAR .
Code: Select all
NH
2VARIABLE HISTORY
NH
: ADJUST ( A1 L1 A2 L2 -- A1 CNT )
DUP 0<> + NEGATE ROT + \ adr1 adr2 len3
>IN +! \ adr1 adr2
OVER - ; \ adr1 cnt
: WORD ( C -- ADR )
>R 'STREAM \ adr1 len1
BLK 2@ HISTORY 2! \ save BLK and >IN
TUCK R@ SKIP \ len1 adr2 len2
>R TUCK R> R> SCAN \ adr2 len1 adr3 len3
ADJUST >HERE ; \ adr2 cnt
: CHAR ( C -- ADR CNT )
DUP>R LIT [ HERE >A 0 , ] C!
'STREAM 2DUP R> \ adr1 len1 adr1 len1 c
SCAN DUP 0= \ adr1 len1 adr2 len2 flag
[ HERE 3 + A> ! ]
ABORT" MISSING"
ADJUST ; \ adr1 cnt
Here are the new versions.
Code: Select all
NH
2VARIABLE HISTORY
: WORD ( C -- HERE )
'STREAM \ c adr1 len1
BLK 2@ HISTORY 2! \ save BLK and >IN
DUP >IN +!
2PICK SKIP \ c adr2 len2
ROT 2PICK -ROT SCAN \ adr2 adr3 len3
1- 0 MAX NEGATE >IN +! \ adr2 adr3
OVER - >HERE ; \ here
: CHAR ( C -- ADR CNT )
DUP>R LIT [ HERE >A 0 , ] C!
'STREAM 2DUP R> \ adr1 len1 adr1 len1 c
SCAN 0= \ adr1 len1 adr2 flag
[ HERE 3 + A> ! ]
ABORT" MISSING"
NIP OVER - \ adr2 cnt
DUP 1+ >IN +! ; \ adr2 cnt
The line:
Code: Select all
BLK 2@ HISTORY 2! \ save BLK and >IN
saves the values of BLK and >IN in a headerless double variable HISTORY for use by WHERE , the word which displays where an error occurred.
The extra size of WORD and CHAR exactly offset the memory saved by removing the headerless word ADJUST ; however, there are fewer trips through NEXT with WORD and CHAR so they will be slightly faster.