CASE construct by George Beckett.
A new implementation of a CASE construct for the ACE. Original based from the version in Personal Computing World March 1984.
Its a new working version many thanks to George Beckett.
The code below is fully commented and is worth reading for a full understanding of how the FORTH code works on the Jupiter ACE.
A TAP/TZX file can be found here (CRC-32 57AB8211).
( CASE CONSTRUCT FOR JUPITER ACE / MINSTREL 4TH )
( )
( ORIGINALLY PRINTED IN PERSONAL COMPUTER )
( WORLD, MARCH 1985. IMPLEMENTATION TWEEKED BY )
( GEORGE BECKETT, SEPT 2020, TO REMOVE )
( POTENTIAL BUG. )
( )
( SYNTAX: )
( CASE )
( xx OF ... ENDOF )
( xx OF ... ENDOF )
( OTHERWISE ... )
( ENDCASE )
( )
( NOTES: )
( - CAN BE LISTED, EDITED, AND REDEFINED. )
( - MUST HAVE 'OTHERWISE' CLAUSE. )
( - ERROR 5, IF SYNTAX ERROR. )
( - CASE STATEMENTS MAY BE NESTED, SUBJECT TO )
( RESPECTING SYNTAX )
( CHECK SYNTAX GUIDES MATCH )
: ?PAIRS ( M N -- )
= 0= ( ARE THEY NOT EQUAL? )
IF
." ERROR 5" CR ABORT ( ABORT COMPILATION, IF NOT EQUAL )
THEN
;
0 COMPILER CASE
0 ( MARKER ON STACK, USED BY ENDCASE TO CHECK DONE )
9 ( SYNTAX GUIDE, MUST MATCH WITH 'OF' )
RUNS>
DROP ( NOTHING TO DO EXCEPT DROP ADDR OF PARAMETER FIELD )
;
2 COMPILER OF
9 ?PAIRS ( CHECK PRECEDED BY CASE OR ENDOF )
HERE ( SAVE CURRENT DICTIONARY LOCATION FOR ENDOF )
0 , ( RESERVE TWO BYTES AT THAT LOCATION )
7 ( SYNTAX GUIDE, MUST MATCH WITH 'ENDOF' )
RUNS>
>R ( SAVE PARAMETER-FIELD ADDR )
OVER = ( CHECK FOR MATCH WITH CASE VALUE, PRESERVING COPY OF INPUT )
R> ( RECOVER PARAMETER-FIELD ADDR )
SWAP ( BRING MATCH RESULT BACK TO TOP OF STACK )
IF ( INDICATES MATCH )
DROP DROP ( DROP PARAMETER-FIELD ADDR AND INPUT, AS DONE )
ELSE
@ ( RETRIEVE OFFSET TO NEXT 'OF' FROM PARAMETER FIELD )
R> + >R ( ADVANCE TO NEXT 'OF' STATEMENT )
THEN
;
( IF SYNTAX IS CORRECT, TOS = 7 AND 2OS = PARAM FIELD OF 'OF'
2 COMPILER ENDOF
7 ?PAIRS ( CHECK PRECEDED BY 'OF' )
HERE ( PUT CURRENT DICTIONARY LOCATION ON STACK )
SWAP ( SWAP WITH ADDRESS OF PARAM FIELD FOR 'OF' )
0 , ( RESERVE TWO BYTES IN DICTIONARY )
OVER OVER - ( WORK OUT OFFSET FROM 'OF' TO 'HERE' )
SWAP ! ( STORE IN PARAMETER FIELD OF 'OF' )
9 ( SYNTAX GUIDE, MUST MATCH TO 'OF' OR 'OTHERWISE' )
RUNS>
@ ( RETRIEVE OFFSET TO JUST AFTER 'ENDCASE' FROM PARAMETER FIELD )
R> + 4 - >R ( APPLY TO RETURN ADDRESS, NEED TO BACKTRACK BY 4 )
;
0 COMPILER OTHERWISE
9 ?PAIRS ( CHECK PRECEDED BY 'CASE' OR 'ENDOF' )
8 ( SYNTAX GUIDE, MUST MATCH WITH 'ENDCASE' )
RUNS>
DROP DROP ( DROP PARAMETER-FIELD ADDR AND INPUT, AS DONE )
;
0 COMPILER ENDCASE
8 ?PAIRS ( CHECK PRECEDED BY 'OTHERWISE' )
BEGIN
?DUP ( IF PARAMETER-FIELD ADDRESS NON-ZERO, DUPLICATE )
WHILE ( OTHERWISE, ALL DONE )
HERE OVER - ( WORK OUT OFFSET )
SWAP ! ( STORE IN PARAMETER FIELD OF 'ENDOF' )
REPEAT ( DO FOR EACH 'ENDOF' )
RUNS>
DROP ( DROP PARAMETER FIELD, AS DONE )
;
: SILLY ( EXAMPLE USE OF CASE )
CASE
1 OF CR ." NUMBER ONE!" CR ENDOF
6 OF CR ." NUMBER SIX!" CR ENDOF
40 OF CR ." NUMBER FORTY!" CR ENDOF
OTHERWISE CR ." NOT 1, NOT 6, NOT 40!" CR
ENDCASE
." The end of a pointless word."
CR
;