Dr Jefyll wrote:
BTW, I'll quickly inject a comment of my own. Ragsdale's assembler (and yours, I think) check to see that conditionals are properly paired, which means (for example) that BEGIN leaves both an address and an error-check code on stack and UNTIL removes these two items. Usually that's fine, but in certain situations the error-check code becomes a nuisance, leading to extra SWAPs ROTs etc.
I'd like to add that the compiler security isn't meant to be restrictive. It is modeled on high level forth control flow structures where the security is there to make sure that
>MARK is resolved by
>RESOLVE and
<MARK is resolved by
<RESOLVE . There is no assembler version of the mark and resolve words, but in the assembler, any word that needs a forward branch or jump resolved can be paired with any word that resolves a forward branch or jump. Any word that leaves an address for a backward branch or jump can be paired with any word that uses that address for a backward branch or jump. For example,
ELSE, ,
ELIF, , and
WHILE, are defined like this:
Code:
: ELSE, ( ADR1 CS -- ADR2 CS )
[COMPILE] AHEAD, 2SWAP
[COMPILE] THEN, ; IMMEDIATE
: ELIF, ( ADDR1 CS1 -- ADDR2 CS2 )
[COMPILE] IF, 2SWAP
[COMPILE] THEN, ; IMMEDIATE
: WHILE, ( A1 C1 -- A2 C2 A1 C1 )
[COMPILE] IF, 2SWAP ; IMMEDIATE
Which means that, oddly, any number of
ELSE, or
ELIF, clauses can be between an
IF, and a
THEN,. But then, no restrictions, just making sure that forward and backward references are properly resolved.