- ABORT
- ABORT"
- ABS
- ACCEPT
- ACTION-OF
- AGAIN
- ALIGN
- ALIGNED
- ALLOT
- AND
- BASE
- BEGIN
- BL
- BUFFER:
- [
- [CHAR]
- [COMPILE]
- [']
- CASE
- C,
- CELL+
- CELLS
- C@
- CHAR
- CHAR+
- CHARS
- COMPILE,
- CONSTANT
- COUNT
- CR
- CREATE
- C!
- :
- :NONAME
- ,
- C"
- DECIMAL
- DEFER
- DEFER@
- DEFER!
- DEPTH
- DO
- DOES>
- DROP
- DUP
- /
- /MOD
- .R
- .(
- ."
- ELSE
- EMIT
- ENDCASE
- ENDOF
- ENVIRONMENT?
- ERASE
- EVALUATE
- EXECUTE
- EXIT
- =
- FALSE
- FILL
- FIND
- FM/MOD
- @
- HERE
- HEX
- HOLD
- HOLDS
- I
- IF
- IMMEDIATE
- INVERT
- IS
- J
- KEY
- LEAVE
- LITERAL
- LOOP
- LSHIFT
- MARKER
- MAX
- MIN
- MOD
- MOVE
- M*
- -
- NEGATE
- NIP
- OF
- OR
- OVER
- 1-
- 1+
- PAD
- PARSE-NAME
- PARSE
- PICK
- POSTPONE
- +
- +LOOP
- +!
- QUIT
- RECURSE
- REFILL
- REPEAT
- RESTORE-INPUT
- R@
- ROLL
- ROT
- RSHIFT
- R>
- SAVE-INPUT
- SIGN
- SM/REM
- SOURCE-ID
- SOURCE
- SPACE
- SPACES
- STATE
- SWAP
- ;
- S\"
- S"
- S>D
- !
- THEN
- TO
- TRUE
- TUCK
- TYPE
- '
- *
- */
- */MOD
- 2DROP
- 2DUP
- 2/
- 2@
- 2OVER
- 2R@
- 2R>
- 2SWAP
- 2!
- 2*
- 2>R
- U.R
- UM/MOD
- UM*
- UNLOOP
- UNTIL
- UNUSED
- U.
- U<
- U>
- VALUE
- VARIABLE
- WHILE
- WITHIN
- WORD
- XOR
- 0=
- 0<
- 0>
- 0<>
- \
- .
- <
- >
- <>
- #>
- <#
- #
- #S
- (
- ?DO
- ?DUP
- >BODY
- >IN
- >NUMBER
- >R
6.2.1950 OF CORE EXT
Interpretation:
Compilation:
Put of-sys onto the control flow stack. Append the run-time semantics given below to the current definition. The semantics are incomplete until resolved by a consumer of of-sys such as ENDOF.
Run-time:
If the two values on the stack are not equal, discard the top value and continue execution at the location specified by the consumer of of-sys, e.g., following the next ENDOF. Otherwise, discard both values and continue execution in line.
See:
Rationale:
Testing:
ContributeContributions
EricBlake
[392] May OF modify the enclosing case-sys on the control stack?Request for clarification2025-08-01 21:33:04
The stack diagram for OF compilation, ( C: -- of-sys )
, implies that it can only add an of-sys, even though presumably the intent is that OF should never be called outside of a CASE/ENDCASE structure and thus there should always be a case-sys somewhere higher on the control stack (whether or not that is also part of the data stack). On the other hand, ENDOF is clear that the case-sys must be adjacent to the of-sys (at least in terms of the control stack), and that it can be modified, since it specifies ( C: case-sys1 of-sys -- case-sys2 )
.
And yet, the standard also includes a sample implementation of OF that does modify the enclosing case-sys: https://forth-standard.org/standard/rationale#paragraph.A.3.2.3.2, when it gives : OF ( #of -- orig #of+1 / x -- )
. Viewing the reference in context, it is clear that it implements case-sys as a variable length structure consisting of 0 or more orig and one u (and in fact, where the representation may be split across the data stack for u and the control stack for the array of orig). If OF is permitted to modify the case-sys, then one could view that implementation as having an of-sys that occupies zero cells. And the entire reason that the reference implementation modifies case-sys in OF is because it is careful to use >R and R> to move #of out of the was so before doing any work that manipulates the control stack, in case the POSTPONE ELSE of ENDOF is using 1 CS_ROLL, and regardless of whether the control stack shares the data stack.
See also the enlightening discussion on whether LEAVE may modify its enclosing do-sys; https://forth-standard.org/standard/core/LEAVE#contribution-185; to which the committee replied that it is not compliant for LEAVE to modify the control stack (because there, the standard mandated ( -- )
rather than permitting ( C: do-sys1 i*x -- do-sys2 i*x )
, even though such an implementation would be unlikely to trip up any production program.
I'm left scratching my head as to how to portably implement an OF that only appends an of-sys, and then ENDOF that merges the of-sys into the adjacent case-sys, without requiring carnal knowledge of whether the control stack shares the data stack. Trying to use of CS_PICK and CS_ROLL, even with the addition of CS_DROP https://forth-standard.org/proposals/cs-drop-revised-2019-08-22-#reply-1370, doesn't help; those are specified to operate on dest and orig without any correlation to how they might fare on case-sys or of-sys in the mix. That said, on a simple a system where orig and dest are one cell each, and where the control stack resides on the data stack, a solution with the same variable-length case-sys (namely, orig*n n) is trivial: Just move the +1 out of OF and into ENDOF; and at that point you might as well rely on SWAP instead of >R and R>:
: OF ( C: -- of-sys ) ( runtime: x1 x2 -- | x1 )
POSTPONE OVER POSTPONE = ( runtime: x1 flag )
POSTPONE IF ( C: of-sys ) ( runtime: x1 ) \ where of-sys and orig are identical
POSTPONE DROP ( runtime: -- )
; IMMEDIATE
: ENDOF ( C: case-sys1 of-sys -- case-sys2 )
POSTPONE ELSE ( C: orig*n n orig1 -- orig*n n orig2 ) \ convert of-sys to orig2, where case-sys is a variable-length orig*n n
SWAP ( C: orig*n orig2 n ) \ abuse carnal knowledge of relation between n and orig2
1+ ( C: orig*[n+1] n+1 ) \ case-sys2 is now one cell larger than case-sys1
; IMMEDIATE