Page 2 of 2

Re: Does EXPECT store a zero at the end of the text?

Posted: Thu Jan 11, 2024 11:52 am
by IamRob
Here is Uniforths definintions for compiling if someone wants to see if they can follow them.

The problem I have with all this is, if one enters a long line of up to 80 characters, like QUERY limits one to, then the next input line is shorter, what prevents INTERPRET from re-compiling the words that come after the shorter input as it looks like the previous, longer definitions are still in the TIB?

INTERPRET also doesn't check for SPAN or #TIB for the limit.

ADDENDUM: ok, as I was uploading this, I noticed ?STACK is in INTERPRET. I think the way ?STACK would work is if -FIND left the stack empty as it was searching for words, then it would ABORT.

I put a note in #FIND that it calls NEXT. But if #FIND calls NEXT, then there would be no need for ?STACK.

I still have to disassemble #FIND to see what it sees as an end-of-line marker that it knows to leave the stack empty. Without a zero at the end of the input, it should theoretically keep compiling old word definitions.

Code: Select all

: QUIT 0 BLK ! [  BEGIN RP! CR QUERY INTERPRET STATE @ O= IF ." OK" REPEAT THEN ;

: QUERY TIB @ 80 EXPECT 0 >IN ! ;

: EXPECT ( addr len -- ) OVER + DUP 1 - SPAN ! OVER 
DO KEY DUP 16 +ORIGIN C@ = OVER 17 +ORIGIN C@ = OR 
( 16 + ORIGIN = 8, 17 + ORIGIN = 7F )
IF DROP DUP I = R> 2 - OVER - >R 
  IF 7 
  ELSE 8 DUP EMIT BL EMIT 
  THEN 
ELSE 
DUP 15 = ( ctrl-u) IF DROP R> DROP DUP 1 - R@ - >R 
  5E EMIT 55 EMIT D EMIT A 
  ELSE
DUP D = IF DROP BL EMIT I SPAN ! LEAVE 
    ELSE DUP 
    THEN I C! 
  THEN 
THEN 
EMIT LOOP 
SPAN @ SWAP - SPAN ! ;

: WORD BLK @ IF BLK @ BLOCK ELSE TIB @ THEN >IN @ + SWAP ENCLOSE
  HERE 2+ 22 BLANKS >IN +! OVER - >R R@ HERE 2+ C! + HERE 3 + R>
  CMOVE HERE 2+ ;

: INTERPRET
 BEGIN
   -FIND IF
       STATE @ < IF ,
       ELSE EXECUTE ?STACK
    ELSE 

  HERE 2+ NUMBER DPL @ 1+ IF 
      PRECIS @ 2 = IF FLITERAL
      ELSE DLITERAL
  ELSE SWAP DROP LITERAL

  THEN
  THEN ?STACK
  THEN
  THEN
  REPEAT  ( There is no ;S to end this word )

: -FIND 0 TRUNK @ CONTEXT @ #FIND ;

: TFIND 0 TRUNK @ CONTEXT @ 2DUP = IF DROP THEN CURRENT @ SWAP #FIND ;

: #FIND BL DUP WORD COUNT 2DUP UPPER + C! BEGIN DUP IF HERE 2+ SWAP HASH @ (FIND) ?DUP IF >R BEGIN ROT 0= UNTIL R> ELSE THEN REPEAT THEN THEN ;

: HASH - Inline code ( calls NEXT - why? )

: (FIND) - Inline code


Re: Does EXPECT store a zero at the end of the text?

Posted: Thu Jan 11, 2024 8:47 pm
by BruceRMcF
JimBoyd wrote:
... FIG Forth's INTERPRET does look like an endless loop, but it isn't. When the text stream is exhausted WORD leaves a counted string at HERE . The string has a count of 1 and a single null for the text. There is such a word in the FIG Forth dictionary.

Code: Select all

: X 
   BLK   @
   IF  ?EXEC  ENDIF
   R>   DROP   ; IMMEDIATE
The name is not really X , it is the null name and when found will force INTERPRET to exit. This is how INTERPRET 'knows' when to stop interpreting.
It seems like the key to all of this is the fig Forth text scanning primitive ENCLOSE:
Quote:
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.

Code: Select all

 Uniforth >>>
: WORD ( c -- ca ) \ parse counted string, located at ca
    BLK @ IF BLK @ BLOCK ELSE TIB @ THEN
    \ c addr0 \ the base address of the text source
    >IN @ +
    \ c addr1 \ This is the address start of the unparsed text
    SWAP ENCLOSE
    \ addr1 n1 n2 n3 \ unparsed text address & 3 offsets
    HERE 2+ 22 BLANKS
    \ addr1 n1 n2 n3 \ blank out HERE+2...HERE+23 ... evidently hex
    >IN +! 
    \ addr1 n1 n2 \ update start of unparsed text
    OVER - >R R@
    \ addr1 n1 (n2-n1) R: (n2-n1)
    HERE 2+ C!
    \ addr1 n1 R: (n2-n1) \ count stored at HERE+2
    + HERE 3 + R>
    \ (addr1+n1) (HERE+3) (n2-n1) \ set up copy
    CMOVE
    \ \ counted string at HERE+2
    HERE 2+
    \ HERE+2 \ return WORD counted string address
;
~~~~~~~~~~~~

Code: Select all

fig-Forth >>>
: WORD ( c -- )
    BLK @ IF BLK @ BLOCK ELSE TIB @ THEN IN @ +
    \ c addr1 \
    SWAP ENCLOSE
    \ addr1 n1 n2 n3 \
    HERE 34 BLANKS IN +!
    \ addr1 n1 n2 \ same as Uniforth except word name is at HERE, not HERE+2
    OVER - >R R
    \ addr1 n1 (n2-1)  | R: (n2-n1) \
    HERE C!
    \ addr1 n1 | R: (n2-n1) \ now the count is at HERE
   + HERE 1+ R>
    \ (addr1+n1) (here+1) (n2-n1) \ set up for cmove 
   CMOVE
    \ \
;
Note that UniForth likely has the link at the beginning of the dictionary entry rather than after the name, which is why the WORD buffer is at HERE+2 rather than at HERE, as with fig Forth.

If UniForth WORD does not process past the end of the current buffer, even if there is junk past the end of the current buffer left over from a longer previous line, then perhaps UniForth ENCLOSE is respecting TIB# for text in the TIB and the block length for a screen in a block buffer.

Perhaps the fig Forth ENCLOSE can hacked to have the same effect, acting "as if" there was a 0 at the address past the end of parse-able text. Otherwise, the start of the definition:

Code: Select all

    BLK @ IF BLK @ BLOCK ELSE TIB @ THEN IN @ +
... leaves you with an opening. A word "EOL? ( c ca -- c ca flag )" that tests for the address at ca, skipping any "c" delimiters, being at the end of the TIB or the end of the block buffer would allow:

Code: Select all

 ...
    BLK @ IF BLK @ BLOCK ELSE TIB @ THEN IN @ +
    EOL? IF DROP DROP 1 HERE ! ELSE ...
and then a "THEN" right before the concluding ; in WORD.

I'd reckon EOL? should be implemented as a code word, to avoid bogging down the outer interpreter.