/anstests/toolstest.fth
https://github.com/jamesbowman/swapforth · Forth · 319 lines · 255 code · 64 blank · 0 comment · 8 complexity · b85772f9c0630b92cf5bbfd4b244f662 MD5 · raw file
- \ To test some of the ANS Forth Programming Tools and extension wordset
-
- \ This program was written by Gerry Jackson in 2006, with contributions from
- \ others where indicated, and is in the public domain - it can be distributed
- \ and/or modified in any way but please retain this notice.
-
- \ This program is distributed in the hope that it will be useful,
- \ but WITHOUT ANY WARRANTY; without even the implied warranty of
- \ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-
- \ The tests are not claimed to be comprehensive or correct
-
- \ ------------------------------------------------------------------------------
- \ Version 0.11 25 April Added tests for N>R NR> SYNONYM TRAVERSE-WORDLIST
- \ NAME>COMPILE NAME>INTERPRET NAME>STRING
- \ 0.6 1 April 2012 Tests placed in the public domain.
- \ Further tests on [IF] [ELSE] [THEN]
- \ 0.5 30 November 2009 <true> and <false> replaced with TRUE and FALSE
- \ 0.4 6 March 2009 ENDIF changed to THEN. {...} changed to T{...}T
- \ 0.3 20 April 2007 ANS Forth words changed to upper case
- \ 0.2 30 Oct 2006 updated following GForth test to avoid
- \ changing stack depth during a colon definition
- \ 0.1 Oct 2006 First version released
-
- \ ------------------------------------------------------------------------------
- \ The tests are based on John Hayes test program
-
- \ Words tested in this file are:
- \ AHEAD [IF] [ELSE] [THEN] CS-PICK CS-ROLL [DEFINED] [UNDEFINED]
- \ N>R NR> SYNONYM TRAVERSE-WORDLIST NAME>COMPILE NAME>INTERPRET
- \ NAME>STRING
- \
-
- \ Words not tested:
- \ .S ? DUMP SEE WORDS
- \ ;CODE ASSEMBLER BYE CODE EDITOR FORGET STATE
- \ ------------------------------------------------------------------------------
- \ Assumptions and dependencies:
- \ - tester.fr or ttester.fs has been loaded prior to this file
- \ - testing TRAVERSE-WORDLIST uses WORDLIST SEARCH-WORDLIST GET-CURRENT
- \ SET-CURRENT and FORTH-WORDLIST from the Search-order word set
- \ ------------------------------------------------------------------------------
-
- DECIMAL
-
- \ ------------------------------------------------------------------------------
- TESTING AHEAD
-
- T{ : PT1 AHEAD 1111 2222 THEN 3333 ; -> }T
- T{ PT1 -> 3333 }T
-
- \ ------------------------------------------------------------------------------
- TESTING [IF] [ELSE] [THEN]
-
- T{ TRUE [IF] 111 [ELSE] 222 [THEN] -> 111 }T
- T{ FALSE [IF] 111 [ELSE] 222 [THEN] -> 222 }T
-
- T{ TRUE [IF] 1 \ Code spread over more than 1 line
- 2
- [ELSE]
- 3
- 4
- [THEN] -> 1 2 }T
- T{ FALSE [IF]
- 1 2
- [ELSE]
- 3 4
- [THEN] -> 3 4 }T
-
- T{ TRUE [IF] 1 TRUE [IF] 2 [ELSE] 3 [THEN] [ELSE] 4 [THEN] -> 1 2 }T
- T{ FALSE [IF] 1 TRUE [IF] 2 [ELSE] 3 [THEN] [ELSE] 4 [THEN] -> 4 }T
- T{ TRUE [IF] 1 FALSE [IF] 2 [ELSE] 3 [THEN] [ELSE] 4 [THEN] -> 1 3 }T
- T{ FALSE [IF] 1 FALSE [IF] 2 [ELSE] 3 [THEN] [ELSE] 4 [THEN] -> 4 }T
-
- \ ------------------------------------------------------------------------------
- TESTING immediacy of [IF] [ELSE] [THEN]
-
- T{ : PT2 [ 0 ] [IF] 1111 [ELSE] 2222 [THEN] ; PT2 -> 2222 }T
- T{ : PT3 [ -1 ] [IF] 3333 [ELSE] 4444 [THEN] ; PT3 -> 3333 }T
- : PT9 BL WORD FIND ;
- T{ PT9 [IF] NIP -> 1 }T
- T{ PT9 [ELSE] NIP -> 1 }T
- T{ PT9 [THEN] NIP -> 1 }T
-
- \ -----------------------------------------------------------------------------
- TESTING [IF] and [ELSE] carry out a text scan by parsing and discarding words
- \ so that an [ELSE] or [THEN] in a comment or string is recognised
-
- : PT10 REFILL DROP REFILL DROP ;
-
- T{ 0 [IF] \ WORDS IGNORED UP TO [ELSE] 2
- [THEN] -> 2 }T
- T{ -1 [IF] 2 [ELSE] 3 S" [THEN] 4 PT10 IGNORED TO END OF LINE"
- [THEN] \ PRECAUTION IN CASE [THEN] IN STRING ISN'T RECOGNISED
- -> 2 4 }T
-
- \ ------------------------------------------------------------------------------
- TESTING CS-PICK and CS-ROLL
-
- \ Test pt5 based on example in ANS document p 176.
-
- : ?REPEAT
- 0 CS-PICK POSTPONE UNTIL
- ; IMMEDIATE
-
- VARIABLE PT4
-
- T{ : PT5 ( N1 -- )
- PT4 !
- BEGIN
- -1 PT4 +!
- PT4 @ 4 > 0= ?REPEAT \ BACK TO BEGIN IF FALSE
- 111
- PT4 @ 3 > 0= ?REPEAT
- 222
- PT4 @ 2 > 0= ?REPEAT
- 333
- PT4 @ 1 =
- UNTIL
- ; -> }T
-
- T{ 6 PT5 -> 111 111 222 111 222 333 111 222 333 }T
-
-
- T{ : ?DONE POSTPONE IF 1 CS-ROLL ; IMMEDIATE -> }T \ Same as WHILE
- T{ : PT6
- >R
- BEGIN
- R@
- ?DONE
- R@
- R> 1- >R
- REPEAT
- R> DROP
- ; -> }T
-
- T{ 5 PT6 -> 5 4 3 2 1 }T
-
- : MIX_UP 2 CS-ROLL ; IMMEDIATE \ CS-ROT
-
- : PT7 ( f3 f2 f1 -- ? )
- IF 1111 ROT ROT ( -- 1111 f3 f2 ) ( cs: -- orig1 )
- IF 2222 SWAP ( -- 1111 2222 f3 ) ( cs: -- orig1 orig2 )
- IF ( cs: -- orig1 orig2 orig3 )
- 3333 MIX_UP ( -- 1111 2222 3333 ) ( cs: -- orig2 orig3 orig1 )
- THEN ( cs: -- orig2 orig3 )
- 4444 \ Hence failure of first IF comes here and falls through
- THEN ( cs: -- orig2 )
- 5555 \ Failure of 3rd IF comes here
- THEN ( cs: -- )
- 6666 \ Failure of 2nd IF comes here
- ;
-
- T{ -1 -1 -1 PT7 -> 1111 2222 3333 4444 5555 6666 }T
- T{ 0 -1 -1 PT7 -> 1111 2222 5555 6666 }T
- T{ 0 0 -1 PT7 -> 1111 0 6666 }T
- T{ 0 0 0 PT7 -> 0 0 4444 5555 6666 }T
-
- : [1CS-ROLL] 1 CS-ROLL ; IMMEDIATE
-
- T{ : PT8
- >R
- AHEAD 111
- BEGIN 222
- [1CS-ROLL]
- THEN
- 333
- R> 1- >R
- R@ 0<
- UNTIL
- R> DROP
- ; -> }T
-
- T{ 1 PT8 -> 333 222 333 }T
-
- \ ------------------------------------------------------------------------------
- TESTING [DEFINED] [UNDEFINED]
-
- CREATE DEF1
-
- T{ [DEFINED] DEF1 -> TRUE }T
- T{ [UNDEFINED] DEF1 -> FALSE }T
- T{ [DEFINED] 12345678901234567890 -> FALSE }T
- T{ [UNDEFINED] 12345678901234567890 -> TRUE }T
- T{ : DEF2 [DEFINED] DEF1 [IF] 1 [ELSE] 2 [THEN] ; -> }T
- T{ : DEF3 [UNDEFINED] DEF1 [IF] 3 [ELSE] 4 [THEN] ; -> }T
- T{ DEF2 -> 1 }T
- T{ DEF3 -> 4 }T
-
- 0 [IF] \ { xxx not yet in swapforth
- \ ------------------------------------------------------------------------------
- TESTING N>R NR>
-
- T{ : NTR N>R -1 NR> ; -> }T
- T{ 1 2 3 4 5 6 7 4 NTR -> 1 2 3 -1 4 5 6 7 4 }T
- T{ 1 0 NTR -> 1 -1 0 }T
- T{ : NTR2 N>R N>R -1 NR> -2 NR> ;
- T{ 1 2 2 3 4 5 3 NTR2 -> -1 1 2 2 -2 3 4 5 3 }T
- T{ 1 0 0 NTR2 -> 1 -1 0 -2 0 }T
-
- \ ------------------------------------------------------------------------------
- TESTING SYNONYM
-
- : SYN1 1234 ;
- T{ SYNONYM NEW-SYN1 SYN1 -> }T
- T{ NEW-SYN1 -> 1234 }T
- : SYN2 2345 ; IMMEDIATE
- T{ SYNONYM NEW-SYN2 SYN2 -> }T
- T{ NEW-SYN2 -> 2345 }T
- T{ : SYN3 SYN2 LITERAL ; SYN3 -> 2345 }T
-
- \ ------------------------------------------------------------------------------
- TESTING TRAVERSE-WORDLIST NAME>COMPILE NAME>INTERPRET NAME>STRING
-
- GET-CURRENT CONSTANT CURR-WL
- WORDLIST CONSTANT TRAV-WL
- : WDCT ( n nt -- n+1 f ) DROP 1+ TRUE ;
- T{ 0 ' WDCT TRAV-WL TRAVERSE-WORDLIST -> 0 }T
-
- TRAV-WL SET-CURRENT
- : TRAV1 1 ;
- T{ 0 ' WDCT TRAV-WL TRAVERSE-WORDLIST -> 1 }T
- : TRAV2 2 ; : TRAV3 3 ; : TRAV4 4 ; : TRAV5 5 ; : TRAV6 6 ; IMMEDIATE
- CURR-WL SET-CURRENT
- T{ 0 ' WDCT TRAV-WL TRAVERSE-WORDLIST -> 6 }T \ Traverse whole wordlist
-
- \ Terminate TRAVERSE-WORDLIST after n words & check it compiles
- : (PART-OF-WL) ( ct n nt -- ct+1 n-1 ) DROP DUP IF SWAP 1+ SWAP 1- THEN DUP ;
- : PART-OF-WL ( n -- ct 0 | ct+1 n-1)
- 0 SWAP ['] (PART-OF-WL) TRAV-WL TRAVERSE-WORDLIST DROP
- ;
- T{ 0 PART-OF-WL -> 0 }T
- T{ 1 PART-OF-WL -> 1 }T
- T{ 4 PART-OF-WL -> 4 }T
- T{ 9 PART-OF-WL -> 6 }T \ Traverse whole wordlist
-
- \ Testing NAME>.. words require a name token. It will be easier to test them
- \ if there is a way of obtaining the name token of a given word. To get this we
- \ need a definition to compare a given name with the result of NAME>STRING.
- \ The output from NAME>STRING has to be copied into a buffer and converted to a
- \ known case as a given Forth system may store names as lower, upper or mixed case.
-
- CREATE UCBUF 32 CHARS ALLOT \ The buffer
-
- \ Convert string to upper case and save in the buffer.
-
- : >UPPERCASE ( caddr u -- caddr2 u2 )
- 32 MIN DUP >R UCBUF ROT ROT
- OVER + SWAP
- DO
- I C@ DUP [CHAR] a [CHAR] z 1+ WITHIN IF 32 INVERT AND THEN
- OVER C! CHAR+
- LOOP DROP
- UCBUF R>
- ;
-
- \ Compare string (caddr u) with name associated with nt, f=0 if the same
- : NAME? ( caddr u nt -- caddr u f ) \ f = true for name = (caddr u) string
- NAME>STRING >UPPERCASE 2OVER COMPARE 0=
- ;
-
- \ The word to be executed by TRAVERSE-WORDLIST
- : GET-NT ( caddr u 0 nt -- caddr u nt false | caddr u 0 nt ) \ nt <> 0
- 2>R R@ NAME? IF R> R> ELSE 2R> THEN
- ;
-
- \ Get name token of (caddr u) in wordlist wid, return 0 if not present
- : GET-NAME-TOKEN ( caddr u wid -- nt | 0 )
- 0 ['] GET-NT ROT TRAVERSE-WORDLIST >R 2DROP R>
- ;
-
- \ Test NAME>STRING via TRAVERSE-WORDLIST
- T{ S" ABCDE" TRAV-WL GET-NAME-TOKEN 0= -> TRUE }T \ Not in wordlist
- T{ S" TRAV4" TRAV-WL GET-NAME-TOKEN 0= -> FALSE }T
-
- \ Test NAME>INTERPRET on a word with interpretation semantics
- T{ S" TRAV3" TRAV-WL GET-NAME-TOKEN NAME>INTERPRET EXECUTE -> 3 }T
-
- \ Test NAME>INTERPRET on a word without interpretation semantics. It is
- \ difficult to choose a suitable word because:
- \ - a user cannot define one in a standard system
- \ - a Forth system may choose to define interpretation semantics for a word
- \ despite the standard stating they are undefined.
- \ Standard words that are not likely to have interpretation semantics defined
- \ could be: ; EXIT ['] [CHAR] RECURSE
- \ ['] will be used since it has an equivalent in interpretation mode, if that
- \ doesn't work in a given system choose another word for that system.
- \ FORTH-WORDLIST is needed
-
- T{ S" [']" FORTH-WORDLIST GET-NAME-TOKEN NAME>INTERPRET -> 0 }T
-
- \ Test NAME>COMPILE
- : N>C ( caddr u -- ) TRAV-WL GET-NAME-TOKEN NAME>COMPILE EXECUTE ; IMMEDIATE
- T{ : N>C1 ( -- n ) [ S" TRAV2" ] N>C ; N>C1 -> 2 }T \ Not immediate
- T{ : N>C2 ( -- n ) [ S" TRAV6" ] N>C LITERAL ; N>C2 -> 6 }T \ Immediate word
- T{ S" TRAV6" TRAV-WL GET-NAME-TOKEN NAME>COMPILE EXECUTE -> 6 }T
-
- \ Test the order of finding words with the same name
- TRAV-WL SET-CURRENT
- : TRAV3 33 ; : TRAV3 333 ; : TRAV7 7 ; : TRAV3 3333 ;
- CURR-WL SET-CURRENT
-
- : GET-ALL ( caddr u nt -- [n] caddr u true )
- DUP >R NAME? IF R@ NAME>INTERPRET EXECUTE ROT ROT THEN
- R> DROP TRUE
- ;
-
- : GET-ALL ( caddr u -- i*x )
- ['] GET-ALL TRAV-WL TRAVERSE-WORDLIST 2DROP
- ;
-
- T{ S" TRAV3" GET-ALL -> 3333 333 33 3 }T
-
- \ ------------------------------------------------------------------------------
- [THEN] \ }
-
- TOOLS-ERRORS SET-ERROR-COUNT
-
- CR .( End of Programming Tools word tests) CR