parsinginputforth

Skip over input stream in ATLAST forth


I'm trying to implement a kind of "conditional :" in ATLAST, the reasoning being I have a file that gets FLOADed multiple times to handle multiple steps of my program flow (I'm essentially abusing Forth as an assembler, step 1 does a first parsing for references, etc. and in step 2 the instruction words actually emit bytes).

So when declaring words for "macros" in that file, it errors out in step 2, because they were already declared in step 1, but I also can't just FORGET them, because that would forget everything that came afterwards, such as the references I just collected in step 1.

So essentially I need a ": that only runs in step 1", my idea being something like this:

VARIABLE STAGE

: ::
  STAGE @ 0 = IF
    [COMPILE] : ( be a word declaration )
  EXIT
  THEN
  BEGIN    ( eat the disabled declaration )
    '      ( get the address of the next word )
    ['] ;  ( get the address of semicolon )
    =      ( loop until they are equal )
  UNTIL
; IMMEDIATE

:: FIVE 5 ; ( declares as expected )

FIVE .      ( prints 5 )

1 STAGE !   ( up to here everything's fine )

:: FIVE 6 ; ( is supposed to do nothing, but errors out )

FIVE .      ( is supposed to print 5 again )

The traced error message (starting from 1 STAGE !):

Trace: !
Trace: ::
Trace: STAGE
Trace: @
Trace: (LIT) 0
Trace: =
Trace: ?BRANCH
Trace: '
Trace: (LIT) 94721509587192
Trace: =
Trace: ?BRANCH
Trace: '
Word not specified when expected.

Trace: ;
Compiler word outside definition.
Walkback:
   ;

KEY ( -- ch ) as common in some other Forths for reading a single character from the input stream ( outside the :: declaration, since it's IMMEDIATE ) doesn't exist in ATLAST, the only related words I could find are:

There aren't any WORD or PARSE either, as in some other Forths.

As you can see, ' is struggling actually getting something from the input stream for some weird reason, and it looks like ['] is failing to capture the ; which then errors out because it's suddenly encountering a ; where it doesn't belong.

I suspect it actually ran ' ['], even though it's supposed to work on the input stream, not the immediate line, and I'm clearly in compile mode there.

I did a similar thing with conditionally declaring variables, there it was rather easy to just [COMPILE] ' DROP to skip a single word (turning RES x into ' x DROP), but here I'm pretty sure I can't actually compile those instructions, because I can't emit a loop outside of a declaration. Unless there is a way to somehow compile similar code that recursively gets rid of everything until the ;.


Solution

  • A problem is that ' cannot find a number. A possible solution is to use a special dummy name for the definition, instead of skip it over:

    : :: 
      STAGE @ 0 = IF : EXIT THEN
      ' DROP \ this xt isn't needed
      " : _dummy" EVALUATE ( -- n ) DROP
    ;
    

    Or maybe use a new name every time:

    : :: 
      STAGE @ 0 = IF : EXIT THEN
      ' >NAME @ \ ( s1 ) \ should be checked
      ": _dummy_" DUP >R S+
      R> EVALUATE ( -- n ) DROP
    ;
    

    But due to non standard words it might not work. Another problem is that non colon-definitions are out of the scope.

    Perhaps, a better solution is a preprocessing by external means.