implementationforth

do, ?do and loop implementation


The DO ... LOOP execute always at least one time. If I want to skip execution when limit = index, I can put the loop inside a if ... then :

2DUP <> IF DO ... LOOP THEN 

The recommended alternative is

?DO ... LOOP

In this last case, where does THEN goes? As I see it, the ?DO word contains an IF that doesn't get closed.


Solution

  • The word ?do can be defined via do as follows.

    : noop ( -- ) ;
    : then, ( orig -- ) postpone then ;
    
    : ?do ( -- do-sys )
      postpone 2dup  postpone =
      postpone if    postpone 2drop
      postpone else
      postpone do  ['] then,
    ; immediate
    
    : do ( -- do-sys )
      postpone do  ['] noop
    ; immediate
    
    : loop ( do-sys -- )
      >r postpone loop  r> execute
    ; immediate
    
    : +loop ( do-sys -- )
      >r postpone +loop r> execute
    ; immediate
    
    

    With this ?do, a definition:

    : foo  ?do bar baz loop ;
    

    is compiled as:

    : foo  2dup = if 2drop else do  bar baz loop  then ;
    

    In some Forth implementations, if you perform see ?do, it will show you that ?do contains if and else, as well as see then, will show that then, (sic comma) contains then. This means that then, performs the compilation semantics of then, and ?do performs the compilation semantics of if and else.