Digest #65 2019-07-13
As for now the following code is standard (it may be part of a standard program):
: E POSTPONE EXIT ; E
But some Forth systems can throw an exception on the second line since this code tries to append something to the current definition in the absent of current definition. And such Forth systems are not standard for that.
To allow a standard Forth system to throw an exception in such situation, this situation should be an ambiguous condition. And in that case the code above will not be standard.
Add into the section 4.1.2 Ambiguous conditions, after the item "interpreting a word with undefined interpretation semantics;" the following item:
appending any semantics to the current definition if there is no current definition;
As far as I can see, the standard clearly specifies that [UNLESS] does not work as intended in the not-taken branch of an [IF], so this case may be worth a discussion in the rationale, but its not something where implementations would diverge. I just tried the following code on Gforth, SwiftForth, VFX, and iForth:
: [unless] 0= postpone [if] ; immediate 0 [if] 0 [unless] [else] .( t) [then]
and they all had the same behaviour (output "t"). It's unclear to me why the ambiguous condition exists.
[UNLESS] construction will break an outer
[IF]. But it nothing to do with the possible ambiguity of
POSTPONE [IF]. For example, the following definition is equivalent, has the same issue, but without any ambiguous condition:
: [UNLESS] ( flag -- ) IF POSTPONE [ELSE] THEN ; IMMEDIATE
As a contrived example, we can just redefine
[IF] to count its top-level occurrences:
VARIABLE cnt cnt 0! VARIABLE lvl lvl 0! : [IF] ( flag -- ) lvl @ 0= IF cnt 1+! THEN lvl 1+! POSTPONE [IF] lvl 1-! ; IMMEDIATE
This code works always correctly. Perhaps it is just a mistake that
POSTPONE [IF] was specified as an ambiguous condition.
Well, the example counts not only the top-level __[IF]__s. But it is beyond the discussed problem.