From f862d6303b99c1342b0b7b1091589e84fc724780 Mon Sep 17 00:00:00 2001 From: Patrick Kloepfer Date: Tue, 23 Mar 2021 16:19:27 -0400 Subject: [PATCH] added forth testing files --- .Floppies/A2OSX.MAKE.po | Bin 33553920 -> 33553920 bytes .Floppies/STABLE.32MB.po | Bin 33553920 -> 33553920 bytes FORTH/blocktest.f | 675 +++++++++++++++++++++++++ FORTH/core.f | 1014 ++++++++++++++++++++++++++++++++++++++ FORTH/coreexttest.f | 770 +++++++++++++++++++++++++++++ FORTH/coreplustest.f | 305 ++++++++++++ 6 files changed, 2764 insertions(+) create mode 100644 FORTH/blocktest.f create mode 100644 FORTH/core.f create mode 100644 FORTH/coreexttest.f create mode 100644 FORTH/coreplustest.f diff --git a/.Floppies/A2OSX.MAKE.po b/.Floppies/A2OSX.MAKE.po index fdd09223f92dc9ae04cb68fd329884eef6f73f06..c0bd3fd49be4f2d54668956a551245a77b466968 100644 GIT binary patch delta 62024 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 delta 58319 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 delta 6778 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 H@$mlu7W_KF diff --git a/FORTH/blocktest.f b/FORTH/blocktest.f new file mode 100644 index 00000000..fcc0ca33 --- /dev/null +++ b/FORTH/blocktest.f @@ -0,0 +1,675 @@ +\ To test the ANS Forth Block word set and extension words + +\ This program was written by Steve Palmer in 2015, 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.1 23 October 2015 First Version +\ Version 0.2 15 November 2015 Updated after feedback from Gerry Jackson + +\ ------------------------------------------------------------------------------ +\ The tests are based on John Hayes test program for the core word set +\ +\ Words tested in this file are: +\ BLK BLOCK BUFFER EVALUATE FLUSH LOAD SAVE-BUFFERS UPDATE +\ EMPTY-BUFFERS LIST SCR THRU REFILL SAVE-INPUT RESTORE-INPUT \ +\ +\ ------------------------------------------------------------------------------ +\ Assumptions and dependencies: +\ - tester.fr or ttester.fs has been loaded prior to this file +\ - errorreport.fth has been loaded prior to this file +\ - utilities.fth has been loaded prioir to this file +\ ------------------------------------------------------------------------------ +TESTING Block word set + +DECIMAL + +\ Define these constants from the system documentation provided. +\ WARNING: The contents of the test blocks will be destroyed by this test. +\ The blocks tested will be in the range +\ FIRST-TEST-BLOCK <= u < LIMIT-TEST-BLOCK +\ The tests need at least 2 test blocks in the range to complete. +20 CONSTANT FIRST-TEST-BLOCK +30 CONSTANT LIMIT-TEST-BLOCK \ one beyond the last + +FIRST-TEST-BLOCK LIMIT-TEST-BLOCK U< 0= [?IF] +\? .( Error: Test Block range not identified ) CR ABORT +[?THEN] + +LIMIT-TEST-BLOCK FIRST-TEST-BLOCK - CONSTANT TEST-BLOCK-COUNT +TEST-BLOCK-COUNT 2 U< [?IF] +\? .( Error: At least 2 Test Blocks are required to run the tests ) CR ABORT +[?THEN] + +\ ------------------------------------------------------------------------------ +TESTING Random Number Utilities + +\ The block tests make extensive use of random numbers to select blocks to test +\ and to set the contents of the block. It also makes use of a Hash code to +\ ensure the integrity of the blocks against unexpected changes. + +\ == Memory Walk tools == + +: @++ ( a-addr -- a-addr+4 a-addr@ ) + DUP CELL+ SWAP @ ; + +: !++ ( x a-addr -- a-addr+4 ) + TUCK ! CELL+ ; + +: C@++ ( c-addr -- c-addr;char+ c-addr@ ) + DUP CHAR+ SWAP C@ ; + +: C!++ ( char c-addr -- c-addr+1 ) + TUCK ! CHAR+ ; + +\ == Random Numbers == +\ Based on "Xorshift" PRNG wikipedia page +\ reporting on results by George Marsaglia +\ https://en.wikipedia.org/wiki/Xorshift +\ Note: THIS IS NOT CRYPTOGRAPHIC QUALITY + +: PRNG + CREATE ( "name" -- ) + 4 CELLS ALLOT + DOES> ( -- prng ) +; + +: PRNG-ERROR-CODE ( prng -- errcode | 0 ) + 0 4 0 DO \ prng acc + >R @++ R> OR \ prng acc' + LOOP \ prng xORyORzORw + NIP 0= ; \ xORyORzORw=0 + +: PRNG-COPY ( src-prng dst-prng -- ) + 4 CELLS MOVE ; + +: PRNG-SET-SEED ( prng w z y x -- ) + 4 PICK \ prng w z y x prng + 4 0 DO !++ LOOP DROP \ prng + DUP PRNG-ERROR-CODE IF \ prng + 1 OVER +! \ prng + THEN \ prng + DROP ; \ + +BITS/CELL 64 = [?IF] +\? : PRNG-RND ( prng -- rnd ) +\? DUP @ +\? DUP 21 LSHIFT XOR +\? DUP 35 RSHIFT XOR +\? DUP 4 LSHIFT XOR +\? TUCK SWAP ! ; +[?THEN] + +BITS/CELL 32 = [?IF] +\? : PRNG-RND ( prng -- rnd ) +\? DUP @ \ prng x +\? DUP 11 LSHIFT XOR \ prng t=x^(x<<11) +\? DUP 8 RSHIFT XOR \ prng t'=t^(t>>8) +\? OVER DUP CELL+ SWAP 3 CELLS MOVE \ prng t' +\? OVER 3 CELLS + @ \ prng t' w +\? DUP 19 RSHIFT XOR \ prng t' w'=w^(w>>19) +\? XOR \ prng rnd=w'^t' +\? TUCK SWAP 3 CELLS + ! ; \ rnd +[?THEN] + +BITS/CELL 16 = [?IF] +\? .( === NOT TESTED === ) +\? \ From http://b2d-f9r.blogspot.co.uk/2010/08/16-bit-xorshift-rng-now-with-more.html +\? : PRNG-RND ( prng -- rnd ) +\? DUP @ \ prng x +\? DUP 5 LSHIFT XOR \ prng t=x^(x<<5) +\? DUP 3 RSHIFT XOR \ prng t'=t^(t>>3) +\? OVER DUP CELL+ @ TUCK SWAP ! \ prng t' y +\? DUP 1 RSHIFT XOR \ prng t' y'=y^(y>>1) +\? XOR \ prng rnd=y'^t' +\? TUCK SWAP CELL+ ! ; \ rnd +[?THEN] + +[?DEF] PRNG-RND +\? .( You need to add a Psuedo Random Number Generator for your cell size: ) +\? BITS/CELL U. CR +\? ABORT +[?THEN] + +: PRNG-RANDOM ( lower upper prng -- rnd ) + >R OVER - R> PRNG-RND UM* NIP + ; +\ PostCondition: T{ lower upper 2DUP 2>R prng PRNG-RANDOM 2R> WITHIN -> TRUE }T + +PRNG BLOCK-PRNG +\ Generated by Random.org +BLOCK-PRNG -1865266521 188896058 -2021545234 -1456609962 PRNG-SET-SEED +: BLOCK-RND ( -- rnd ) BLOCK-PRNG PRNG-RND ; +: BLOCK-RANDOM ( lower upper -- rnd ) BLOCK-PRNG PRNG-RANDOM ; + +: RND-TEST-BLOCK ( -- blk ) + FIRST-TEST-BLOCK LIMIT-TEST-BLOCK BLOCK-RANDOM ; +\ PostCondition: T{ RND-TEST-BLOCK FIRST-TEST-BLOCK LIMIT-TEST-BLOCK WITHIN -> TRUE }T + +\ Two distinct random test blocks +: 2RND-TEST-BLOCKS ( -- blk1 blk2 ) + RND-TEST-BLOCK BEGIN \ blk1 + RND-TEST-BLOCK \ blk1 blk2 + 2DUP = \ blk1 blk2 blk1==blk2 + WHILE \ blk1 blk1 + DROP \ blk1 + REPEAT ; \ blk1 blk2 +\ PostCondition: T{ 2RND-TEST-BLOCKS = -> FALSE }T + +\ first random test block in a sequence of length u +: RND-TEST-BLOCK-SEQ ( u -- blks ) + FIRST-TEST-BLOCK LIMIT-TEST-BLOCK ROT 1- - BLOCK-RANDOM ; + +\ I'm not sure if this algorithm is correct if " 1 CHARS 1 <> ". +: ELF-HASH-ACCUMULATE ( hash c-addr u -- hash ) + >R SWAP R> 0 DO \ c-addr h + 4 LSHIFT \ c-addr h<<=4 + SWAP C@++ ROT + \ c-addr' h+=*s + DUP [ HEX ] F0000000 [ DECIMAL ] AND \ c-addr' h high=h&0xF0000000 + DUP IF \ c-addr' h high + DUP >R 24 RSHIFT XOR R> \ c-addr' h^=high>>24 high + THEN \ c-addr' h high + INVERT AND \ c-addr' h&=~high + LOOP NIP ; + +: ELF-HASH ( c-addr u -- hash ) + 0 ROT ROT ELF-HASH-ACCUMULATE ; + +\ ------------------------------------------------------------------------------ +TESTING BLOCK ( read-only mode ) + +\ BLOCK signature +T{ RND-TEST-BLOCK BLOCK DUP ALIGNED = -> TRUE }T + +\ BLOCK accepts all blocks in the test range +: BLOCK-ALL ( blk2 blk1 -- ) + DO + I BLOCK DROP + LOOP ; +T{ LIMIT-TEST-BLOCK FIRST-TEST-BLOCK BLOCK-ALL -> }T + +\ BLOCK twice on same block returns the same value +T{ RND-TEST-BLOCK DUP BLOCK SWAP BLOCK = -> TRUE }T + +\ BLOCK twice on distinct block numbers +\ may or may not return the same value! +\ Nothing to test + +\ ------------------------------------------------------------------------------ +TESTING BUFFER ( read-only mode ) + +\ Although it is not in the spirit of the specification, +\ a compliant definition of BUFFER would be +\ : BUFFER BLOCK ; +\ So we can only repeat the tests for BLOCK ... + +\ BUFFER signature +T{ RND-TEST-BLOCK BUFFER DUP ALIGNED = -> TRUE }T + +\ BUFFER accepts all blocks in the test range +: BUFFER-ALL ( blk2 blk1 -- ) + DO + I BUFFER DROP + LOOP ; +T{ LIMIT-TEST-BLOCK FIRST-TEST-BLOCK BUFFER-ALL -> }T + +\ BUFFER twice on the same block returns the same value +T{ RND-TEST-BLOCK DUP BUFFER SWAP BUFFER = -> TRUE }T + +\ BUFFER twice on distinct block numbers +\ may or may not return the same value! +\ Nothing to test + +\ Combinations with BUFFER +T{ RND-TEST-BLOCK DUP BLOCK SWAP BUFFER = -> TRUE }T +T{ RND-TEST-BLOCK DUP BUFFER SWAP BLOCK = -> TRUE }T + +\ ------------------------------------------------------------------------------ +TESTING Read and Write access with UPDATE and FLUSH + +\ Ideally, we'd like to be able to test the persistence across power cycles +\ of the writes, but we can't do that in a simple test. +\ The tests below could be fooled by a large buffers store and a tricky FLUSH +\ but what else are you going to do? + +\ Signatures +T{ RND-TEST-BLOCK BLOCK DROP UPDATE -> }T +T{ FLUSH -> }T + +: BLANK-BUFFER ( blk -- blk-addr ) + BUFFER DUP 1024 BL FILL ; + +\ Test R/W of a Simple Blank Random Block +T{ RND-TEST-BLOCK \ blk + DUP BLANK-BUFFER \ blk blk-addr1 + 1024 ELF-HASH \ blk hash + UPDATE FLUSH \ blk hash + SWAP BLOCK \ hash blk-addr2 + 1024 ELF-HASH = -> TRUE }T + +\ Boundary Test: Modify first character +T{ RND-TEST-BLOCK \ blk + DUP BLANK-BUFFER \ blk blk-addr1 + CHAR \ OVER C! \ blk blk-addr1 + 1024 ELF-HASH \ blk hash + UPDATE FLUSH \ blk hash + SWAP BLOCK \ hash blk-addr2 + 1024 ELF-HASH = -> TRUE }T + +\ Boundary Test: Modify last character +T{ RND-TEST-BLOCK \ blk + DUP BLANK-BUFFER \ blk blk-addr1 + CHAR \ OVER 1023 CHARS + C! \ blk blk-addr1 + 1024 ELF-HASH \ blk hash + UPDATE FLUSH \ blk hash + SWAP BLOCK \ hash blk-addr2 + 1024 ELF-HASH = -> TRUE }T + +\ Boundary Test: First and Last (and all other) blocks in the test range +1024 8 * BITS/CELL / CONSTANT CELLS/BLOCK + +: PREPARE-RND-BLOCK ( hash blk -- hash' ) + BUFFER DUP \ hash blk-addr blk-addr + CELLS/BLOCK 0 DO \ hash blk-addr blk-addr[i] + BLOCK-RND OVER ! CELL+ \ hash blk-addr blk-addr[i+1] + LOOP DROP \ hash blk-addr + 1024 ELF-HASH-ACCUMULATE ; \ hash' + +: WRITE-RND-BLOCKS-WITH-HASH ( blk2 blk1 -- hash ) + 0 ROT ROT DO \ hash + I PREPARE-RND-BLOCK UPDATE \ hash' + LOOP ; \ hash' + +: READ-BLOCKS-AND-HASH ( blk2 blk1 -- hash ) + 0 ROT ROT DO \ hash(i) + I BLOCK 1024 ELF-HASH-ACCUMULATE \ hash(i+1) + LOOP ; \ hash + +T{ LIMIT-TEST-BLOCK FIRST-TEST-BLOCK WRITE-RND-BLOCKS-WITH-HASH FLUSH + LIMIT-TEST-BLOCK FIRST-TEST-BLOCK READ-BLOCKS-AND-HASH = -> TRUE }T + +: TUF1 ( xt blk -- hash ) + DUP BLANK-BUFFER \ xt blk blk-addr1 + 1024 ELF-HASH \ xt blk hash + ROT EXECUTE \ blk hash + SWAP BLOCK \ hash blk-addr2 + 1024 ELF-HASH = ; \ TRUE + +\ Double UPDATE make no difference +: TUF1-1 ( -- ) UPDATE UPDATE FLUSH ; +T{ ' TUF1-1 RND-TEST-BLOCK TUF1 -> TRUE }T + +\ Double FLUSH make no difference +: TUF1-2 ( -- ) UPDATE FLUSH FLUSH ; +T{ ' TUF1-2 RND-TEST-BLOCK TUF1 -> TRUE }T + +\ FLUSH only saves UPDATEd buffers +T{ RND-TEST-BLOCK \ blk + 0 OVER PREPARE-RND-BLOCK \ blk hash + UPDATE FLUSH \ blk hash + OVER 0 SWAP PREPARE-RND-BLOCK DROP \ blk hash + FLUSH ( with no preliminary UPDATE) \ blk hash + SWAP BLOCK 1024 ELF-HASH = -> TRUE }T + +\ UPDATE only marks the current block buffer +\ This test needs at least 2 distinct buffers, though this is not a +\ requirement of the language specification. If 2 distinct buffers +\ are not returned, then the tests quits with a trivial Pass +: TUF2 ( xt blk1 blk2 -- hash1'' hash2'' hash1' hash2' hash1 hash2 ) + OVER BUFFER OVER BUFFER = IF \ test needs 2 distinct buffers + 2DROP DROP 0 0 0 0 0 0 \ Dummy result + ELSE + OVER 0 SWAP PREPARE-RND-BLOCK UPDATE \ xt blk1 blk2 hash1 + OVER 0 SWAP PREPARE-RND-BLOCK UPDATE \ xt blk1 blk2 hash1 hash2 + 2>R \ xt blk1 blk2 + FLUSH \ xt blk1 blk2 + OVER 0 SWAP PREPARE-RND-BLOCK \ xt blk1 blk2 hash1' + OVER 0 SWAP PREPARE-RND-BLOCK \ xt blk1 blk2 hash1' hash2' + 2>R \ xt blk1 blk2 + ROT EXECUTE \ blk1 blk2 + FLUSH \ blk1 blk2 + SWAP BLOCK 1024 ELF-HASH \ blk2 hash1'' + SWAP BLOCK 1024 ELF-HASH \ hash1'' hash2'' + 2R> 2R> \ hash1'' hash2'' hash1' hash2' hash1 hash2 + THEN ; + +: 2= ( x1 x2 x3 x4 -- flag ) + ROT = ROT ROT = AND ; + +: TUF2-0 ( blk1 blk2 -- blk1 blk2 ) ; \ no updates +T{ ' TUF2-0 2RND-TEST-BLOCKS TUF2 \ run test procedure + 2SWAP 2DROP 2= -> TRUE }T \ compare expected and actual + +: TUF2-1 ( blk1 blk2 -- blk1 blk2 ) \ update blk1 only + OVER BLOCK DROP UPDATE ; +T{ ' TUF2-1 2RND-TEST-BLOCKS TUF2 \ run test procedure + SWAP DROP SWAP DROP 2= -> TRUE }T + +: TUF2-2 ( blk1 blk2 -- blk1 blk2 ) \ update blk2 only + DUP BUFFER DROP UPDATE ; +T{ ' TUF2-2 2RND-TEST-BLOCKS TUF2 \ run test procedure + DROP ROT DROP SWAP 2= -> TRUE }T + +: TUF2-3 ( blk1 blk2 -- blk1 blk2 ) \ update blk1 and blk2 + TUF2-1 TUF2-2 ; +T{ ' TUF2-3 2RND-TEST-BLOCKS TUF2 \ run test procedure + 2DROP 2= -> TRUE }T + +\ FLUSH and then UPDATE is ambiguous and untestable + +\ ------------------------------------------------------------------------------ +TESTING SAVE-BUFFERS + +\ In principle, all the tests above can be repeated with SAVE-BUFFERS instead of +\ FLUSH. However, only the full random test is repeated... + +T{ LIMIT-TEST-BLOCK FIRST-TEST-BLOCK WRITE-RND-BLOCKS-WITH-HASH SAVE-BUFFERS + LIMIT-TEST-BLOCK FIRST-TEST-BLOCK READ-BLOCKS-AND-HASH = -> TRUE }T + +\ FLUSH and then SAVE-BUFFERS is harmless but undetectable +\ SAVE-BUFFERS and then FLUSH is undetectable + +\ Unlike FLUSH, SAVE-BUFFERS then BUFFER/BLOCK +\ returns the original buffer address +T{ RND-TEST-BLOCK DUP BLANK-BUFFER + SAVE-BUFFERS SWAP BUFFER = -> TRUE }T +T{ RND-TEST-BLOCK DUP BLANK-BUFFER + UPDATE SAVE-BUFFERS SWAP BUFFER = -> TRUE }T +T{ RND-TEST-BLOCK DUP BLANK-BUFFER + SAVE-BUFFERS SWAP BLOCK = -> TRUE }T +T{ RND-TEST-BLOCK DUP BLANK-BUFFER + UPDATE SAVE-BUFFERS SWAP BLOCK = -> TRUE }T + +\ ------------------------------------------------------------------------------ +TESTING BLK + +\ Signature +T{ BLK DUP ALIGNED = -> TRUE }T + +\ None of the words considered so far effect BLK +T{ BLK @ RND-TEST-BLOCK BUFFER DROP BLK @ = -> TRUE }T +T{ BLK @ RND-TEST-BLOCK BLOCK DROP BLK @ = -> TRUE }T +T{ BLK @ UPDATE BLK @ = -> TRUE }T + +T{ BLK @ FLUSH BLK @ = -> TRUE }T +T{ BLK @ SAVE-BUFFERS BLK @ = -> TRUE }T + +\ ------------------------------------------------------------------------------ +TESTING LOAD and EVALUATE + +\ Signature: n LOAD --> blank screen +T{ RND-TEST-BLOCK DUP BLANK-BUFFER DROP UPDATE FLUSH LOAD -> }T + +T{ BLK @ RND-TEST-BLOCK DUP BLANK-BUFFER DROP UPDATE FLUSH LOAD BLK @ = -> TRUE }T + +: WRITE-BLOCK ( blk c-addr u -- ) + ROT BLANK-BUFFER SWAP CHARS MOVE UPDATE FLUSH ; + +\ blk: u; blk LOAD +: TL1 ( u blk -- ) + SWAP 0 <# #S #> WRITE-BLOCK ; +T{ BLOCK-RND RND-TEST-BLOCK 2DUP TL1 LOAD = -> TRUE }T + +\ Boundary Test: FIRST-TEST-BLOCK +T{ BLOCK-RND FIRST-TEST-BLOCK 2DUP TL1 LOAD = -> TRUE }T + +\ Boundary Test: LIMIT-TEST-BLOCK-1 +T{ BLOCK-RND LIMIT-TEST-BLOCK 1- 2DUP TL1 LOAD = -> TRUE }T + +: WRITE-AT-END-OF-BLOCK ( blk c-addr u -- ) + ROT BLANK-BUFFER + OVER 1024 SWAP - CHARS + + SWAP CHARS MOVE UPDATE FLUSH ; + +\ Boundary Test: End of Buffer +: TL2 ( u blk -- ) + SWAP 0 <# #S #> WRITE-AT-END-OF-BLOCK ; +T{ BLOCK-RND RND-TEST-BLOCK 2DUP TL2 LOAD = -> TRUE }T + +\ LOAD updates BLK +\ u: "BLK @"; u LOAD +: TL3 ( blk -- ) + S" BLK @" WRITE-BLOCK ; +T{ RND-TEST-BLOCK DUP TL3 DUP LOAD = -> TRUE }T + +\ EVALUATE resets BLK +\ u: "EVALUATE-BLK@"; u LOAD +: EVALUATE-BLK@ ( -- BLK@ ) + S" BLK @" EVALUATE ; +: TL4 ( blk -- ) + S" EVALUATE-BLK@" WRITE-BLOCK ; +T{ RND-TEST-BLOCK DUP TL4 LOAD -> 0 }T + +\ EVALUTE can nest with LOAD +\ u: "BLK @"; S" u LOAD" EVALUATE +: TL5 ( blk -- c-addr u ) + 0 <# \ blk 0 + [CHAR] D HOLD + [CHAR] A HOLD + [CHAR] O HOLD + [CHAR] L HOLD + BL HOLD + #S #> ; \ c-addr u +T{ RND-TEST-BLOCK DUP TL3 DUP TL5 EVALUATE = -> TRUE }T + +\ Nested LOADs +\ u2: "BLK @"; u1: "LOAD u2"; u1 LOAD +: TL6 ( blk1 blk2 -- ) + DUP TL3 \ blk1 blk2 + TL5 WRITE-BLOCK ; +T{ 2RND-TEST-BLOCKS 2DUP TL6 SWAP LOAD = -> TRUE }T + +\ LOAD changes the currect block that is effected by UPDATE +\ This test needs at least 2 distinct buffers, though this is not a +\ requirement of the language specification. If 2 distinct buffers +\ are not returned, then the tests quits with a trivial Pass +: TL7 ( blk1 blk2 -- u1 u2 rnd2 blk2-addr rnd1' rnd1 ) + OVER BUFFER OVER BUFFER = IF \ test needs 2 distinct buffers + 2DROP 0 0 0 0 0 0 \ Dummy result + ELSE + OVER BLOCK-RND DUP ROT TL1 >R \ blk1 blk2 + DUP S" SOURCE DROP" WRITE-BLOCK \ blk1 blk2 + \ change blk1 to a new rnd, but don't UPDATE + OVER BLANK-BUFFER \ blk1 blk2 blk1-addr + BLOCK-RND DUP >R \ blk1 blk2 blk1-addr rnd1' + 0 <# #S #> \ blk1 blk2 blk1-addr c-addr u + ROT SWAP CHARS MOVE \ blk1 blk2 + \ Now LOAD blk2 + DUP LOAD DUP >R \ blk1 blk2 blk2-addr + \ Write a new blk2 + DUP 1024 BL FILL \ blk1 blk2 blk2-addr + BLOCK-RND DUP >R \ blk1 blk2 blk2-addr rnd2 + 0 <# #S #> \ blk1 blk2 blk2-addr c-addr u + ROT SWAP CHARS MOVE \ blk1 blk2 + \ The following UPDATE should refer to the LOADed blk2, not blk1 + UPDATE FLUSH \ blk1 blk2 + \ Finally, load both blocks then collect all results + LOAD SWAP LOAD \ u2 u1 + R> R> R> R> \ u2 u1 rnd2 blk2-addr rnd1' rnd1 + THEN ; +T{ 2RND-TEST-BLOCKS TL7 \ run test procedure + SWAP DROP SWAP DROP \ u2 u1 rnd2 rnd1 + 2= -> TRUE }T + +\ I would expect LOAD to work on the contents of the buffer cache +\ and not the block device, but the specification doesn't say. +\ Similarly, I would not expect LOAD to FLUSH the buffer cache, +\ but the specification doesn't say so. + +\ ------------------------------------------------------------------------------ +TESTING LIST and SCR + +\ Signatures +T{ SCR DUP ALIGNED = -> TRUE }T +\ LIST signature is test implicitly in the following tests... + +: TLS1 ( blk -- ) + S" Should show a (mostly) blank screen" WRITE-BLOCK ; +T{ RND-TEST-BLOCK DUP TLS1 DUP LIST SCR @ = -> TRUE }T + +\ Boundary Test: FIRST-TEST-BLOCK +: TLS2 ( blk -- ) + S" List of the First test block" WRITE-BLOCK ; +T{ FIRST-TEST-BLOCK DUP TLS2 LIST -> }T + +\ Boundary Test: LIMIT-TEST-BLOCK +: TLS3 ( blk -- ) + S" List of the Last test block" WRITE-BLOCK ; +T{ LIMIT-TEST-BLOCK 1- DUP TLS3 LIST -> }T + +\ Boundary Test: End of Screen +: TLS4 ( blk -- ) + S" End of Screen" WRITE-AT-END-OF-BLOCK ; +T{ RND-TEST-BLOCK DUP TLS4 LIST -> }T + +\ BLOCK, BUFFER, UPDATE et al don't change SCR +: TLS5 ( blk -- ) + S" Should show another (mostly) blank screen" WRITE-BLOCK ; +\ the first test below sets the scenario for the subsequent tests +\ BLK is unchanged by LIST +T{ BLK @ RND-TEST-BLOCK DUP TLS5 LIST BLK @ = -> TRUE }T +\ SCR is unchanged by Earlier words +T{ SCR @ FLUSH SCR @ = -> TRUE }T +T{ SCR @ FLUSH DUP 1+ BUFFER DROP SCR @ = -> TRUE }T +T{ SCR @ FLUSH DUP 1+ BLOCK DROP SCR @ = -> TRUE }T +T{ SCR @ FLUSH DUP 1+ BLOCK DROP UPDATE SCR @ = -> TRUE }T +T{ SCR @ FLUSH DUP 1+ BLOCK DROP UPDATE SAVE-BUFFERS SCR @ = -> TRUE }T +: TLS6 ( blk -- ) + S" SCR @" WRITE-BLOCK ; +T{ SCR @ RND-TEST-BLOCK DUP TLS6 LOAD SCR @ OVER 2= -> TRUE }T + +\ ------------------------------------------------------------------------------ +TESTING EMPTY-BUFFERS + +T{ EMPTY-BUFFERS -> }T +T{ BLK @ EMPTY-BUFFERS BLK @ = -> TRUE }T +T{ SCR @ EMPTY-BUFFERS SCR @ = -> TRUE }T + +\ Test R/W, but discarded changes with EMPTY-BUFFERS +T{ RND-TEST-BLOCK \ blk + DUP BLANK-BUFFER \ blk blk-addr1 + 1024 ELF-HASH \ blk hash + UPDATE FLUSH \ blk hash + OVER BLOCK CHAR \ SWAP C! \ blk hash + UPDATE EMPTY-BUFFERS FLUSH \ blk hash + SWAP BLOCK \ hash blk-addr2 + 1024 ELF-HASH = -> TRUE }T + +\ EMPTY-BUFFERS discards all buffers +: TUF2-EB ( blk1 blk2 -- blk1 blk2 ) + TUF2-1 TUF2-2 EMPTY-BUFFERS ; \ c.f. TUF2-3 +T{ ' TUF2-EB 2RND-TEST-BLOCKS TUF2 + 2SWAP 2DROP 2= -> TRUE }T + +\ FLUSH and then EMPTY-BUFFERS is acceptable but untestable +\ EMPTY-BUFFERS and then UPDATE is ambiguous and untestable + +\ ------------------------------------------------------------------------------ +TESTING >IN manipulation from a block source + +: TIN ( blk -- ) + S" 1 8 >IN +! 2 3" WRITE-BLOCK ; +T{ RND-TEST-BLOCK DUP TIN LOAD -> 1 3 }T + +\ ------------------------------------------------------------------------------ +TESTING \, SAVE-INPUT, RESTORE-INPUT and REFILL from a block source + +\ Try to determine the number of charaters per line +\ Assumes an even number of characters per line +: | ( u -- u-2 ) 2 - ; +: C/L-CALC ( blk -- c/l ) + DUP BLANK-BUFFER \ blk blk-addr + [CHAR] \ OVER C! \ blk blk-addr blk:"\" + 511 0 DO \ blk c-addr[i] + CHAR+ CHAR+ [CHAR] | OVER C! \ blk c-addr[i+1] + LOOP DROP \ blk blk:"\ | | | | ... |" + UPDATE SAVE-BUFFERS FLUSH \ blk + 1024 SWAP LOAD ; \ c/l +[?DEF] C/L +[?ELSE] +\? .( Given Characters per Line: ) C/L U. CR +[?ELSE] +\? RND-TEST-BLOCK C/L-CALC CONSTANT C/L +\? C/L 1024 U< [?IF] +\? .( Calculated Characters per Line: ) C/L U. CR +[?THEN] + +: WRITE-BLOCK-LINE ( lin-addr[i] c-addr u -- lin-addr[i+1] ) + 2>R DUP C/L CHARS + SWAP 2R> ROT SWAP MOVE ; + +\ Discards to the end of the line +: TCSIRIR1 ( blk -- ) + BLANK-BUFFER + C/L 1024 U< IF + S" 2222 \ 3333" WRITE-BLOCK-LINE + S" 4444" WRITE-BLOCK-LINE + THEN + DROP UPDATE SAVE-BUFFERS ; +T{ RND-TEST-BLOCK DUP TCSIRIR1 LOAD -> 2222 4444 }T + +VARIABLE T-CNT 0 T-CNT ! + +: MARK ( "" -- ) \ Use between <# and #> + CHAR HOLD ; IMMEDIATE + +: ?EXECUTE ( xt f -- ) + IF EXECUTE ELSE DROP THEN ; + +\ SAVE-INPUT and RESTORE-INPUT within a single block +: TCSIRIR2-EXPECTED S" EDCBCBA" ; \ Remember that the string comes out backwards +: TCSIRIR2 ( blk -- ) + C/L 1024 U< IF + BLANK-BUFFER + S" 0 T-CNT !" WRITE-BLOCK-LINE + S" <# MARK A SAVE-INPUT MARK B" WRITE-BLOCK-LINE +S" 1 T-CNT +! MARK C ' RESTORE-INPUT T-CNT @ 2 < ?EXECUTE MARK D" WRITE-BLOCK-LINE + S" MARK E 0 0 #>" WRITE-BLOCK-LINE + UPDATE SAVE-BUFFERS DROP + ELSE + S" 0 TCSIRIR2-EXPECTED" WRITE-BLOCK + THEN ; +T{ RND-TEST-BLOCK DUP TCSIRIR2 LOAD TCSIRIR2-EXPECTED S= -> 0 TRUE }T + +\ REFILL across 2 blocks +: TCSIRIR3 ( blks -- ) + DUP S" 1 2 3 REFILL 4 5 6" WRITE-BLOCK + 1+ S" 10 11 12" WRITE-BLOCK ; +T{ 2 RND-TEST-BLOCK-SEQ DUP TCSIRIR3 LOAD -> 1 2 3 -1 10 11 12 }T + +\ SAVE-INPUT and RESTORE-INPUT across 2 blocks +: TCSIRIR4-EXPECTED S" HGF1ECBF1ECBA" ; \ Remember that the string comes out backwards +: TCSIRIR4 ( blks -- ) + C/L 1024 U< IF + DUP BLANK-BUFFER + S" 0 T-CNT !" WRITE-BLOCK-LINE + S" <# MARK A SAVE-INPUT MARK B" WRITE-BLOCK-LINE + S" MARK C REFILL MARK D" WRITE-BLOCK-LINE + DROP UPDATE 1+ BLANK-BUFFER + S" MARK E ABS CHAR 0 + HOLD" WRITE-BLOCK-LINE +S" 1 T-CNT +! MARK F ' RESTORE-INPUT T-CNT @ 2 < ?EXECUTE MARK G" WRITE-BLOCK-LINE + S" MARK H 0 0 #>" WRITE-BLOCK-LINE + DROP UPDATE SAVE-BUFFERS + ELSE + S" 0 TCSIRIR4-EXPECTED" WRITE-BLOCK + THEN ; +T{ 2 RND-TEST-BLOCK-SEQ DUP TCSIRIR4 LOAD TCSIRIR4-EXPECTED S= -> 0 TRUE }T + +\ ------------------------------------------------------------------------------ +TESTING THRU + +: TT1 ( blks -- ) + DUP S" BLK" WRITE-BLOCK + 1+ S" @" WRITE-BLOCK ; +T{ 2 RND-TEST-BLOCK-SEQ DUP TT1 DUP DUP 1+ THRU 1- = -> TRUE }T + +\ ------------------------------------------------------------------------------ + +BLOCK-ERRORS SET-ERROR-COUNT + +CR .( End of Block word tests) CR diff --git a/FORTH/core.f b/FORTH/core.f new file mode 100644 index 00000000..31014819 --- /dev/null +++ b/FORTH/core.f @@ -0,0 +1,1014 @@ +NEW + PREFIX +AUTO 4,1 +#!/bin/forth +\ From: John Hayes S1I +\ Subject: core.f +\ Date: Mon, 27 Nov 95 13:10 + +\ (C) 1995 JOHNS HOPKINS UNIVERSITY / APPLIED PHYSICS LABORATORY +\ MAY BE DISTRIBUTED FREELY AS LONG AS THIS COPYRIGHT NOTICE REMAINS. +\ VERSION 1.2 +\ THIS PROGRAM TESTS THE CORE WORDS OF AN ANS FORTH SYSTEM. +\ THE PROGRAM ASSUMES A TWO'S COMPLEMENT IMPLEMENTATION WHERE +\ THE RANGE OF SIGNED NUMBERS IS -2^(N-1) ... 2^(N-1)-1 AND +\ THE RANGE OF UNSIGNED NUMBERS IS 0 ... 2^(N)-1. +\ I HAVEN'T FIGURED OUT HOW TO TEST KEY, QUIT, ABORT, OR ABORT"... +\ I ALSO HAVEN'T THOUGHT OF A WAY TO TEST ENVIRONMENT?... + +CR +TESTING CORE WORDS +HEX + +\ ------------------------------------------------------------------------ +TESTING BASIC ASSUMPTIONS + +T{ -> }T \ START WITH CLEAN SLATE +( TEST IF ANY BITS ARE SET; ANSWER IN BASE 1 ) +T{ : BITSSET? IF 0 0 ELSE 0 THEN ; -> }T +T{ 0 BITSSET? -> 0 }T ( ZERO IS ALL BITS CLEAR ) +T{ 1 BITSSET? -> 0 0 }T ( OTHER NUMBER HAVE AT LEAST ONE BIT ) +T{ -1 BITSSET? -> 0 0 }T + +\ ------------------------------------------------------------------------ +TESTING BOOLEANS: INVERT AND OR XOR + +T{ 0 0 AND -> 0 }T +T{ 0 1 AND -> 0 }T +T{ 1 0 AND -> 0 }T +T{ 1 1 AND -> 1 }T + +T{ 0 INVERT 1 AND -> 1 }T +T{ 1 INVERT 1 AND -> 0 }T + +0 CONSTANT 0S +0 INVERT CONSTANT 1S + +T{ 0S INVERT -> 1S }T +T{ 1S INVERT -> 0S }T + +T{ 0S 0S AND -> 0S }T +T{ 0S 1S AND -> 0S }T +T{ 1S 0S AND -> 0S }T +T{ 1S 1S AND -> 1S }T + +T{ 0S 0S OR -> 0S }T +T{ 0S 1S OR -> 1S }T +T{ 1S 0S OR -> 1S }T +T{ 1S 1S OR -> 1S }T + +T{ 0S 0S XOR -> 0S }T +T{ 0S 1S XOR -> 1S }T +T{ 1S 0S XOR -> 1S }T +T{ 1S 1S XOR -> 0S }T + +\ ------------------------------------------------------------------------ +TESTING 2* 2/ LSHIFT RSHIFT + +( WE TRUST 1S, INVERT, AND BITSSET?; WE WILL CONFIRM RSHIFT LATER ) +1S 1 RSHIFT INVERT CONSTANT MSB +T{ MSB BITSSET? -> 0 0 }T + +T{ 0S 2* -> 0S }T +T{ 1 2* -> 2 }T +T{ 4000 2* -> 8000 }T +T{ 1S 2* 1 XOR -> 1S }T +T{ MSB 2* -> 0S }T + +T{ 0S 2/ -> 0S }T +T{ 1 2/ -> 0 }T +T{ 4000 2/ -> 2000 }T +T{ 1S 2/ -> 1S }T \ MSB PROPOGATED +T{ 1S 1 XOR 2/ -> 1S }T +T{ MSB 2/ MSB AND -> MSB }T + +T{ 1 0 LSHIFT -> 1 }T +T{ 1 1 LSHIFT -> 2 }T +T{ 1 2 LSHIFT -> 4 }T +T{ 1 F LSHIFT -> 8000 }T \ BIGGEST GUARANTEED SHIFT +T{ 1S 1 LSHIFT 1 XOR -> 1S }T +T{ MSB 1 LSHIFT -> 0 }T + +T{ 1 0 RSHIFT -> 1 }T +T{ 1 1 RSHIFT -> 0 }T +T{ 2 1 RSHIFT -> 1 }T +T{ 4 2 RSHIFT -> 1 }T +T{ 8000 F RSHIFT -> 1 }T \ BIGGEST +T{ MSB 1 RSHIFT MSB AND -> 0 }T \ RSHIFT ZERO FILLS MSBS +T{ MSB 1 RSHIFT 2* -> MSB }T + +\ ------------------------------------------------------------------------ +TESTING COMPARISONS: 0= = 0< < > U< MIN MAX +0 INVERT CONSTANT MAX-UINT +0 INVERT 1 RSHIFT CONSTANT MAX-INT +0 INVERT 1 RSHIFT INVERT CONSTANT MIN-INT +0 INVERT 1 RSHIFT CONSTANT MID-UINT +0 INVERT 1 RSHIFT INVERT CONSTANT MID-UINT+1 + +0S CONSTANT +1S CONSTANT + +T{ 0 0= -> }T +T{ 1 0= -> }T +T{ 2 0= -> }T +T{ -1 0= -> }T +T{ MAX-UINT 0= -> }T +T{ MIN-INT 0= -> }T +T{ MAX-INT 0= -> }T + +T{ 0 0 = -> }T +T{ 1 1 = -> }T +T{ -1 -1 = -> }T +T{ 1 0 = -> }T +T{ -1 0 = -> }T +T{ 0 1 = -> }T +T{ 0 -1 = -> }T + +T{ 0 0< -> }T +T{ -1 0< -> }T +T{ MIN-INT 0< -> }T +T{ 1 0< -> }T +T{ MAX-INT 0< -> }T + +T{ 0 1 < -> }T +T{ 1 2 < -> }T +T{ -1 0 < -> }T +T{ -1 1 < -> }T +T{ MIN-INT 0 < -> }T +T{ MIN-INT MAX-INT < -> }T +T{ 0 MAX-INT < -> }T +T{ 0 0 < -> }T +T{ 1 1 < -> }T +T{ 1 0 < -> }T +T{ 2 1 < -> }T +T{ 0 -1 < -> }T +T{ 1 -1 < -> }T +T{ 0 MIN-INT < -> }T +T{ MAX-INT MIN-INT < -> }T +T{ MAX-INT 0 < -> }T + +T{ 0 1 > -> }T +T{ 1 2 > -> }T +T{ -1 0 > -> }T +T{ -1 1 > -> }T +T{ MIN-INT 0 > -> }T +T{ MIN-INT MAX-INT > -> }T +T{ 0 MAX-INT > -> }T +T{ 0 0 > -> }T +T{ 1 1 > -> }T +T{ 1 0 > -> }T +T{ 2 1 > -> }T +T{ 0 -1 > -> }T +T{ 1 -1 > -> }T +T{ 0 MIN-INT > -> }T +T{ MAX-INT MIN-INT > -> }T +T{ MAX-INT 0 > -> }T + +T{ 0 1 U< -> }T +T{ 1 2 U< -> }T +T{ 0 MID-UINT U< -> }T +T{ 0 MAX-UINT U< -> }T +T{ MID-UINT MAX-UINT U< -> }T +T{ 0 0 U< -> }T +T{ 1 1 U< -> }T +T{ 1 0 U< -> }T +T{ 2 1 U< -> }T +T{ MID-UINT 0 U< -> }T +T{ MAX-UINT 0 U< -> }T +T{ MAX-UINT MID-UINT U< -> }T + +T{ 0 1 MIN -> 0 }T +T{ 1 2 MIN -> 1 }T +T{ -1 0 MIN -> -1 }T +T{ -1 1 MIN -> -1 }T +T{ MIN-INT 0 MIN -> MIN-INT }T +T{ MIN-INT MAX-INT MIN -> MIN-INT }T +T{ 0 MAX-INT MIN -> 0 }T +T{ 0 0 MIN -> 0 }T +T{ 1 1 MIN -> 1 }T +T{ 1 0 MIN -> 0 }T +T{ 2 1 MIN -> 1 }T +T{ 0 -1 MIN -> -1 }T +T{ 1 -1 MIN -> -1 }T +T{ 0 MIN-INT MIN -> MIN-INT }T +T{ MAX-INT MIN-INT MIN -> MIN-INT }T +T{ MAX-INT 0 MIN -> 0 }T + +T{ 0 1 MAX -> 1 }T +T{ 1 2 MAX -> 2 }T +T{ -1 0 MAX -> 0 }T +T{ -1 1 MAX -> 1 }T +T{ MIN-INT 0 MAX -> 0 }T +T{ MIN-INT MAX-INT MAX -> MAX-INT }T +T{ 0 MAX-INT MAX -> MAX-INT }T +T{ 0 0 MAX -> 0 }T +T{ 1 1 MAX -> 1 }T +T{ 1 0 MAX -> 1 }T +T{ 2 1 MAX -> 2 }T +T{ 0 -1 MAX -> 0 }T +T{ 1 -1 MAX -> 1 }T +T{ 0 MIN-INT MAX -> 0 }T +T{ MAX-INT MIN-INT MAX -> MAX-INT }T +T{ MAX-INT 0 MAX -> MAX-INT }T + +\ ------------------------------------------------------------------------ +TESTING STACK OPS: 2DROP 2DUP 2OVER 2SWAP ?DUP DEPTH DROP DUP OVER ROT SWAP + +T{ 1 2 2DROP -> }T +T{ 1 2 2DUP -> 1 2 1 2 }T +T{ 1 2 3 4 2OVER -> 1 2 3 4 1 2 }T +T{ 1 2 3 4 2SWAP -> 3 4 1 2 }T +T{ 0 ?DUP -> 0 }T +T{ 1 ?DUP -> 1 1 }T +T{ -1 ?DUP -> -1 -1 }T +T{ DEPTH -> 0 }T +T{ 0 DEPTH -> 0 1 }T +T{ 0 1 DEPTH -> 0 1 2 }T +T{ 0 DROP -> }T +T{ 1 2 DROP -> 1 }T +T{ 1 DUP -> 1 1 }T +T{ 1 2 OVER -> 1 2 1 }T +T{ 1 2 3 ROT -> 2 3 1 }T +T{ 1 2 SWAP -> 2 1 }T + +\ ------------------------------------------------------------------------ +TESTING >R R> R@ + +T{ : GR1 >R R> ; -> }T +T{ : GR2 >R R@ R> DROP ; -> }T +T{ 123 GR1 -> 123 }T +T{ 123 GR2 -> 123 }T +T{ 1S GR1 -> 1S }T ( RETURN STACK HOLDS CELLS ) + +\ ------------------------------------------------------------------------ +TESTING ADD/SUBTRACT: + - 1+ 1- ABS NEGATE + +T{ 0 5 + -> 5 }T +T{ 5 0 + -> 5 }T +T{ 0 -5 + -> -5 }T +T{ -5 0 + -> -5 }T +T{ 1 2 + -> 3 }T +T{ 1 -2 + -> -1 }T +T{ -1 2 + -> 1 }T +T{ -1 -2 + -> -3 }T +T{ -1 1 + -> 0 }T +T{ MID-UINT 1 + -> MID-UINT+1 }T + +T{ 0 5 - -> -5 }T +T{ 5 0 - -> 5 }T +T{ 0 -5 - -> 5 }T +T{ -5 0 - -> -5 }T +T{ 1 2 - -> -1 }T +T{ 1 -2 - -> 3 }T +T{ -1 2 - -> -3 }T +T{ -1 -2 - -> 1 }T +T{ 0 1 - -> -1 }T +T{ MID-UINT+1 1 - -> MID-UINT }T + +T{ 0 1+ -> 1 }T +T{ -1 1+ -> 0 }T +T{ 1 1+ -> 2 }T +T{ MID-UINT 1+ -> MID-UINT+1 }T + +T{ 2 1- -> 1 }T +T{ 1 1- -> 0 }T +T{ 0 1- -> -1 }T +T{ MID-UINT+1 1- -> MID-UINT }T + +T{ 0 NEGATE -> 0 }T +T{ 1 NEGATE -> -1 }T +T{ -1 NEGATE -> 1 }T +T{ 2 NEGATE -> -2 }T +T{ -2 NEGATE -> 2 }T + +T{ 0 ABS -> 0 }T +T{ 1 ABS -> 1 }T +T{ -1 ABS -> 1 }T +T{ MIN-INT ABS -> MID-UINT+1 }T + +\ ------------------------------------------------------------------------ +TESTING MULTIPLY: S>D * M* UM* + +T{ 0 S>D -> 0 0 }T +T{ 1 S>D -> 1 0 }T +T{ 2 S>D -> 2 0 }T +T{ -1 S>D -> -1 -1 }T +T{ -2 S>D -> -2 -1 }T +T{ MIN-INT S>D -> MIN-INT -1 }T +T{ MAX-INT S>D -> MAX-INT 0 }T + +T{ 0 0 M* -> 0 S>D }T +T{ 0 1 M* -> 0 S>D }T +T{ 1 0 M* -> 0 S>D }T +T{ 1 2 M* -> 2 S>D }T +T{ 2 1 M* -> 2 S>D }T +T{ 3 3 M* -> 9 S>D }T +T{ -3 3 M* -> -9 S>D }T +T{ 3 -3 M* -> -9 S>D }T +T{ -3 -3 M* -> 9 S>D }T +T{ 0 MIN-INT M* -> 0 S>D }T +T{ 1 MIN-INT M* -> MIN-INT S>D }T +T{ 2 MIN-INT M* -> 0 1S }T +T{ 0 MAX-INT M* -> 0 S>D }T +T{ 1 MAX-INT M* -> MAX-INT S>D }T +T{ 2 MAX-INT M* -> MAX-INT 1 LSHIFT 0 }T +T{ MIN-INT MIN-INT M* -> 0 MSB 1 RSHIFT }T +T{ MAX-INT MIN-INT M* -> MSB MSB 2/ }T +T{ MAX-INT MAX-INT M* -> 1 MSB 2/ INVERT }T + +T{ 0 0 * -> 0 }T \ TEST IDENTITIES +T{ 0 1 * -> 0 }T +T{ 1 0 * -> 0 }T +T{ 1 2 * -> 2 }T +T{ 2 1 * -> 2 }T +T{ 3 3 * -> 9 }T +T{ -3 3 * -> -9 }T +T{ 3 -3 * -> -9 }T +T{ -3 -3 * -> 9 }T + +T{ MID-UINT+1 1 RSHIFT 2 * -> MID-UINT+1 }T +T{ MID-UINT+1 2 RSHIFT 4 * -> MID-UINT+1 }T +T{ MID-UINT+1 1 RSHIFT MID-UINT+1 OR 2 * -> MID-UINT+1 }T + +T{ 0 0 UM* -> 0 0 }T +T{ 0 1 UM* -> 0 0 }T +T{ 1 0 UM* -> 0 0 }T +T{ 1 2 UM* -> 2 0 }T +T{ 2 1 UM* -> 2 0 }T +T{ 3 3 UM* -> 9 0 }T + +T{ MID-UINT+1 1 RSHIFT 2 UM* -> MID-UINT+1 0 }T +T{ MID-UINT+1 2 UM* -> 0 1 }T +T{ MID-UINT+1 4 UM* -> 0 2 }T +T{ 1S 2 UM* -> 1S 1 LSHIFT 1 }T +T{ MAX-UINT MAX-UINT UM* -> 1 1 INVERT }T + +\ ------------------------------------------------------------------------ +TESTING DIVIDE: FM/MOD SM/REM UM/MOD */ */MOD / /MOD MOD + +T{ 0 S>D 1 FM/MOD -> 0 0 }T +T{ 1 S>D 1 FM/MOD -> 0 1 }T +T{ 2 S>D 1 FM/MOD -> 0 2 }T +T{ -1 S>D 1 FM/MOD -> 0 -1 }T +T{ -2 S>D 1 FM/MOD -> 0 -2 }T +T{ 0 S>D -1 FM/MOD -> 0 0 }T +T{ 1 S>D -1 FM/MOD -> 0 -1 }T +T{ 2 S>D -1 FM/MOD -> 0 -2 }T +T{ -1 S>D -1 FM/MOD -> 0 1 }T +T{ -2 S>D -1 FM/MOD -> 0 2 }T +T{ 2 S>D 2 FM/MOD -> 0 1 }T +T{ -1 S>D -1 FM/MOD -> 0 1 }T +T{ -2 S>D -2 FM/MOD -> 0 1 }T +T{ 7 S>D 3 FM/MOD -> 1 2 }T +T{ 7 S>D -3 FM/MOD -> -2 -3 }T +T{ -7 S>D 3 FM/MOD -> 2 -3 }T +T{ -7 S>D -3 FM/MOD -> -1 2 }T +T{ MAX-INT S>D 1 FM/MOD -> 0 MAX-INT }T +T{ MIN-INT S>D 1 FM/MOD -> 0 MIN-INT }T +T{ MAX-INT S>D MAX-INT FM/MOD -> 0 1 }T +T{ MIN-INT S>D MIN-INT FM/MOD -> 0 1 }T +T{ 1S 1 4 FM/MOD -> 3 MAX-INT }T +T{ 1 MIN-INT M* 1 FM/MOD -> 0 MIN-INT }T +T{ 1 MIN-INT M* MIN-INT FM/MOD -> 0 1 }T +T{ 2 MIN-INT M* 2 FM/MOD -> 0 MIN-INT }T +T{ 2 MIN-INT M* MIN-INT FM/MOD -> 0 2 }T +T{ 1 MAX-INT M* 1 FM/MOD -> 0 MAX-INT }T +T{ 1 MAX-INT M* MAX-INT FM/MOD -> 0 1 }T +T{ 2 MAX-INT M* 2 FM/MOD -> 0 MAX-INT }T +T{ 2 MAX-INT M* MAX-INT FM/MOD -> 0 2 }T +T{ MIN-INT MIN-INT M* MIN-INT FM/MOD -> 0 MIN-INT }T +T{ MIN-INT MAX-INT M* MIN-INT FM/MOD -> 0 MAX-INT }T +T{ MIN-INT MAX-INT M* MAX-INT FM/MOD -> 0 MIN-INT }T +T{ MAX-INT MAX-INT M* MAX-INT FM/MOD -> 0 MAX-INT }T + +T{ 0 S>D 1 SM/REM -> 0 0 }T +T{ 1 S>D 1 SM/REM -> 0 1 }T +T{ 2 S>D 1 SM/REM -> 0 2 }T +T{ -1 S>D 1 SM/REM -> 0 -1 }T +T{ -2 S>D 1 SM/REM -> 0 -2 }T +T{ 0 S>D -1 SM/REM -> 0 0 }T +T{ 1 S>D -1 SM/REM -> 0 -1 }T +T{ 2 S>D -1 SM/REM -> 0 -2 }T +T{ -1 S>D -1 SM/REM -> 0 1 }T +T{ -2 S>D -1 SM/REM -> 0 2 }T +T{ 2 S>D 2 SM/REM -> 0 1 }T +T{ -1 S>D -1 SM/REM -> 0 1 }T +T{ -2 S>D -2 SM/REM -> 0 1 }T +T{ 7 S>D 3 SM/REM -> 1 2 }T +T{ 7 S>D -3 SM/REM -> 1 -2 }T +T{ -7 S>D 3 SM/REM -> -1 -2 }T +T{ -7 S>D -3 SM/REM -> -1 2 }T +T{ MAX-INT S>D 1 SM/REM -> 0 MAX-INT }T +T{ MIN-INT S>D 1 SM/REM -> 0 MIN-INT }T +T{ MAX-INT S>D MAX-INT SM/REM -> 0 1 }T +T{ MIN-INT S>D MIN-INT SM/REM -> 0 1 }T +T{ 1S 1 4 SM/REM -> 3 MAX-INT }T +T{ 2 MIN-INT M* 2 SM/REM -> 0 MIN-INT }T +T{ 2 MIN-INT M* MIN-INT SM/REM -> 0 2 }T +T{ 2 MAX-INT M* 2 SM/REM -> 0 MAX-INT }T +T{ 2 MAX-INT M* MAX-INT SM/REM -> 0 2 }T +T{ MIN-INT MIN-INT M* MIN-INT SM/REM -> 0 MIN-INT }T +T{ MIN-INT MAX-INT M* MIN-INT SM/REM -> 0 MAX-INT }T +T{ MIN-INT MAX-INT M* MAX-INT SM/REM -> 0 MIN-INT }T +T{ MAX-INT MAX-INT M* MAX-INT SM/REM -> 0 MAX-INT }T + +T{ 0 0 1 UM/MOD -> 0 0 }T +T{ 1 0 1 UM/MOD -> 0 1 }T +T{ 1 0 2 UM/MOD -> 1 0 }T +T{ 3 0 2 UM/MOD -> 1 1 }T +T{ MAX-UINT 2 UM* 2 UM/MOD -> 0 MAX-UINT }T +T{ MAX-UINT 2 UM* MAX-UINT UM/MOD -> 0 2 }T +T{ MAX-UINT MAX-UINT UM* MAX-UINT UM/MOD -> 0 MAX-UINT }T + +: IFFLOORED + [ -3 2 / -2 = INVERT ] LITERAL IF POSTPONE \ THEN ; + +: IFSYM + [ -3 2 / -1 = INVERT ] LITERAL IF POSTPONE \ THEN ; + +\ THE SYSTEM MIGHT DO EITHER FLOORED OR SYMMETRIC DIVISION. +\ SINCE WE HAVE ALREADY TESTED M*, FM/MOD, AND SM/REM WE CAN USE THEM IN TEST. + +IFFLOORED : T/MOD >R S>D R> FM/MOD ; +IFFLOORED : T/ T/MOD SWAP DROP ; +IFFLOORED : TMOD T/MOD DROP ; +IFFLOORED : T*/MOD >R M* R> FM/MOD ; +IFFLOORED : T*/ T*/MOD SWAP DROP ; +IFSYM : T/MOD >R S>D R> SM/REM ; +IFSYM : T/ T/MOD SWAP DROP ; +IFSYM : TMOD T/MOD DROP ; +IFSYM : T*/MOD >R M* R> SM/REM ; +IFSYM : T*/ T*/MOD SWAP DROP ; + +T{ 0 1 /MOD -> 0 1 T/MOD }T +T{ 1 1 /MOD -> 1 1 T/MOD }T +T{ 2 1 /MOD -> 2 1 T/MOD }T +T{ -1 1 /MOD -> -1 1 T/MOD }T +T{ -2 1 /MOD -> -2 1 T/MOD }T +T{ 0 -1 /MOD -> 0 -1 T/MOD }T +T{ 1 -1 /MOD -> 1 -1 T/MOD }T +T{ 2 -1 /MOD -> 2 -1 T/MOD }T +T{ -1 -1 /MOD -> -1 -1 T/MOD }T +T{ -2 -1 /MOD -> -2 -1 T/MOD }T +T{ 2 2 /MOD -> 2 2 T/MOD }T +T{ -1 -1 /MOD -> -1 -1 T/MOD }T +T{ -2 -2 /MOD -> -2 -2 T/MOD }T +T{ 7 3 /MOD -> 7 3 T/MOD }T +T{ 7 -3 /MOD -> 7 -3 T/MOD }T +T{ -7 3 /MOD -> -7 3 T/MOD }T +T{ -7 -3 /MOD -> -7 -3 T/MOD }T +T{ MAX-INT 1 /MOD -> MAX-INT 1 T/MOD }T +T{ MIN-INT 1 /MOD -> MIN-INT 1 T/MOD }T +T{ MAX-INT MAX-INT /MOD -> MAX-INT MAX-INT T/MOD }T +T{ MIN-INT MIN-INT /MOD -> MIN-INT MIN-INT T/MOD }T + +T{ 0 1 / -> 0 1 T/ }T +T{ 1 1 / -> 1 1 T/ }T +T{ 2 1 / -> 2 1 T/ }T +T{ -1 1 / -> -1 1 T/ }T +T{ -2 1 / -> -2 1 T/ }T +T{ 0 -1 / -> 0 -1 T/ }T +T{ 1 -1 / -> 1 -1 T/ }T +T{ 2 -1 / -> 2 -1 T/ }T +T{ -1 -1 / -> -1 -1 T/ }T +T{ -2 -1 / -> -2 -1 T/ }T +T{ 2 2 / -> 2 2 T/ }T +T{ -1 -1 / -> -1 -1 T/ }T +T{ -2 -2 / -> -2 -2 T/ }T +T{ 7 3 / -> 7 3 T/ }T +T{ 7 -3 / -> 7 -3 T/ }T +T{ -7 3 / -> -7 3 T/ }T +T{ -7 -3 / -> -7 -3 T/ }T +T{ MAX-INT 1 / -> MAX-INT 1 T/ }T +T{ MIN-INT 1 / -> MIN-INT 1 T/ }T +T{ MAX-INT MAX-INT / -> MAX-INT MAX-INT T/ }T +T{ MIN-INT MIN-INT / -> MIN-INT MIN-INT T/ }T + +T{ 0 1 MOD -> 0 1 TMOD }T +T{ 1 1 MOD -> 1 1 TMOD }T +T{ 2 1 MOD -> 2 1 TMOD }T +T{ -1 1 MOD -> -1 1 TMOD }T +T{ -2 1 MOD -> -2 1 TMOD }T +T{ 0 -1 MOD -> 0 -1 TMOD }T +T{ 1 -1 MOD -> 1 -1 TMOD }T +T{ 2 -1 MOD -> 2 -1 TMOD }T +T{ -1 -1 MOD -> -1 -1 TMOD }T +T{ -2 -1 MOD -> -2 -1 TMOD }T +T{ 2 2 MOD -> 2 2 TMOD }T +T{ -1 -1 MOD -> -1 -1 TMOD }T +T{ -2 -2 MOD -> -2 -2 TMOD }T +T{ 7 3 MOD -> 7 3 TMOD }T +T{ 7 -3 MOD -> 7 -3 TMOD }T +T{ -7 3 MOD -> -7 3 TMOD }T +T{ -7 -3 MOD -> -7 -3 TMOD }T +T{ MAX-INT 1 MOD -> MAX-INT 1 TMOD }T +T{ MIN-INT 1 MOD -> MIN-INT 1 TMOD }T +T{ MAX-INT MAX-INT MOD -> MAX-INT MAX-INT TMOD }T +T{ MIN-INT MIN-INT MOD -> MIN-INT MIN-INT TMOD }T + +T{ 0 2 1 */ -> 0 2 1 T*/ }T +T{ 1 2 1 */ -> 1 2 1 T*/ }T +T{ 2 2 1 */ -> 2 2 1 T*/ }T +T{ -1 2 1 */ -> -1 2 1 T*/ }T +T{ -2 2 1 */ -> -2 2 1 T*/ }T +T{ 0 2 -1 */ -> 0 2 -1 T*/ }T +T{ 1 2 -1 */ -> 1 2 -1 T*/ }T +T{ 2 2 -1 */ -> 2 2 -1 T*/ }T +T{ -1 2 -1 */ -> -1 2 -1 T*/ }T +T{ -2 2 -1 */ -> -2 2 -1 T*/ }T +T{ 2 2 2 */ -> 2 2 2 T*/ }T +T{ -1 2 -1 */ -> -1 2 -1 T*/ }T +T{ -2 2 -2 */ -> -2 2 -2 T*/ }T +T{ 7 2 3 */ -> 7 2 3 T*/ }T +T{ 7 2 -3 */ -> 7 2 -3 T*/ }T +T{ -7 2 3 */ -> -7 2 3 T*/ }T +T{ -7 2 -3 */ -> -7 2 -3 T*/ }T +T{ MAX-INT 2 MAX-INT */ -> MAX-INT 2 MAX-INT T*/ }T +T{ MIN-INT 2 MIN-INT */ -> MIN-INT 2 MIN-INT T*/ }T + +T{ 0 2 1 */MOD -> 0 2 1 T*/MOD }T +T{ 1 2 1 */MOD -> 1 2 1 T*/MOD }T +T{ 2 2 1 */MOD -> 2 2 1 T*/MOD }T +T{ -1 2 1 */MOD -> -1 2 1 T*/MOD }T +T{ -2 2 1 */MOD -> -2 2 1 T*/MOD }T +T{ 0 2 -1 */MOD -> 0 2 -1 T*/MOD }T +T{ 1 2 -1 */MOD -> 1 2 -1 T*/MOD }T +T{ 2 2 -1 */MOD -> 2 2 -1 T*/MOD }T +T{ -1 2 -1 */MOD -> -1 2 -1 T*/MOD }T +T{ -2 2 -1 */MOD -> -2 2 -1 T*/MOD }T +T{ 2 2 2 */MOD -> 2 2 2 T*/MOD }T +T{ -1 2 -1 */MOD -> -1 2 -1 T*/MOD }T +T{ -2 2 -2 */MOD -> -2 2 -2 T*/MOD }T +T{ 7 2 3 */MOD -> 7 2 3 T*/MOD }T +T{ 7 2 -3 */MOD -> 7 2 -3 T*/MOD }T +T{ -7 2 3 */MOD -> -7 2 3 T*/MOD }T +T{ -7 2 -3 */MOD -> -7 2 -3 T*/MOD }T +T{ MAX-INT 2 MAX-INT */MOD -> MAX-INT 2 MAX-INT T*/MOD }T +T{ MIN-INT 2 MIN-INT */MOD -> MIN-INT 2 MIN-INT T*/MOD }T + +\ ------------------------------------------------------------------------ +TESTING HERE , @ ! CELL+ CELLS C, C@ C! CHARS 2@ 2! ALIGN ALIGNED +! ALLOT + +HERE 1 ALLOT +HERE +CONSTANT 2NDA +CONSTANT 1STA +T{ 1STA 2NDA U< -> }T \ HERE MUST GROW WITH ALLOT +T{ 1STA 1+ -> 2NDA }T \ ... BY ONE ADDRESS UNIT +( MISSING TEST: NEGATIVE ALLOT ) + +\ Added by GWJ so that ALIGN can be used before , (comma) is tested +1 ALIGNED CONSTANT ALMNT \ -- 1|2|4|8 for 8|16|32|64 bit alignment +ALIGN +T{ HERE 1 ALLOT ALIGN HERE SWAP - ALMNT = -> }T +\ End of extra test + +HERE 1 , +HERE 2 , +CONSTANT 2ND +CONSTANT 1ST +T{ 1ST 2ND U< -> }T \ HERE MUST GROW WITH ALLOT +T{ 1ST CELL+ -> 2ND }T \ ... BY ONE CELL +T{ 1ST 1 CELLS + -> 2ND }T +T{ 1ST @ 2ND @ -> 1 2 }T +T{ 5 1ST ! -> }T +T{ 1ST @ 2ND @ -> 5 2 }T +T{ 6 2ND ! -> }T +T{ 1ST @ 2ND @ -> 5 6 }T +T{ 1ST 2@ -> 6 5 }T +T{ 2 1 1ST 2! -> }T +T{ 1ST 2@ -> 2 1 }T +T{ 1S 1ST ! 1ST @ -> 1S }T \ CAN STORE CELL-WIDE VALUE + +HERE 1 C, +HERE 2 C, +CONSTANT 2NDC +CONSTANT 1STC +T{ 1STC 2NDC U< -> }T \ HERE MUST GROW WITH ALLOT +T{ 1STC CHAR+ -> 2NDC }T \ ... BY ONE CHAR +T{ 1STC 1 CHARS + -> 2NDC }T +T{ 1STC C@ 2NDC C@ -> 1 2 }T +T{ 3 1STC C! -> }T +T{ 1STC C@ 2NDC C@ -> 3 2 }T +T{ 4 2NDC C! -> }T +T{ 1STC C@ 2NDC C@ -> 3 4 }T + +ALIGN 1 ALLOT HERE ALIGN HERE 3 CELLS ALLOT +CONSTANT A-ADDR CONSTANT UA-ADDR +T{ UA-ADDR ALIGNED -> A-ADDR }T +T{ 1 A-ADDR C! A-ADDR C@ -> 1 }T +T{ 1234 A-ADDR ! A-ADDR @ -> 1234 }T +T{ 123 456 A-ADDR 2! A-ADDR 2@ -> 123 456 }T +T{ 2 A-ADDR CHAR+ C! A-ADDR CHAR+ C@ -> 2 }T +T{ 3 A-ADDR CELL+ C! A-ADDR CELL+ C@ -> 3 }T +T{ 1234 A-ADDR CELL+ ! A-ADDR CELL+ @ -> 1234 }T +T{ 123 456 A-ADDR CELL+ 2! A-ADDR CELL+ 2@ -> 123 456 }T + +: BITS ( X -- U ) + 0 SWAP BEGIN DUP WHILE DUP MSB AND IF >R 1+ R> THEN 2* REPEAT DROP ; +( CHARACTERS >= 1 AU, <= SIZE OF CELL, >= 8 BITS ) +T{ 1 CHARS 1 < -> }T +T{ 1 CHARS 1 CELLS > -> }T +( TBD: HOW TO FIND NUMBER OF BITS? ) + +( CELLS >= 1 AU, INTEGRAL MULTIPLE OF CHAR SIZE, >= 16 BITS ) +T{ 1 CELLS 1 < -> }T +T{ 1 CELLS 1 CHARS MOD -> 0 }T +T{ 1S BITS 10 < -> }T + +T{ 0 1ST ! -> }T +T{ 1 1ST +! -> }T +T{ 1ST @ -> 1 }T +T{ -1 1ST +! 1ST @ -> 0 }T + +\ ------------------------------------------------------------------------ +TESTING CHAR [CHAR] [ ] BL S" + +T{ BL -> 20 }T +T{ CHAR X -> 58 }T +T{ CHAR HELLO -> 48 }T +T{ : GC1 [CHAR] X ; -> }T +T{ : GC2 [CHAR] HELLO ; -> }T +T{ GC1 -> 58 }T +T{ GC2 -> 48 }T +T{ : GC3 [ GC1 ] LITERAL ; -> }T +T{ GC3 -> 58 }T +T{ : GC4 S" XY" ; -> }T +T{ GC4 SWAP DROP -> 2 }T +T{ GC4 DROP DUP C@ SWAP CHAR+ C@ -> 58 59 }T + +\ ------------------------------------------------------------------------ +TESTING ' ['] FIND EXECUTE IMMEDIATE COUNT LITERAL POSTPONE STATE + +T{ : GT1 123 ; -> }T +T{ ' GT1 EXECUTE -> 123 }T +T{ : GT2 ['] GT1 ; IMMEDIATE -> }T +T{ GT2 EXECUTE -> 123 }T +HERE 3 C, CHAR G C, CHAR T C, CHAR 1 C, CONSTANT GT1STRING +HERE 3 C, CHAR G C, CHAR T C, CHAR 2 C, CONSTANT GT2STRING +T{ GT1STRING FIND -> ' GT1 -1 }T +T{ GT2STRING FIND -> ' GT2 1 }T +( HOW TO SEARCH FOR NON-EXISTENT WORD? ) +T{ : GT3 GT2 LITERAL ; -> }T +T{ GT3 -> ' GT1 }T +T{ GT1STRING COUNT -> GT1STRING CHAR+ 3 }T + +T{ : GT4 POSTPONE GT1 ; IMMEDIATE -> }T +T{ : GT5 GT4 ; -> }T +T{ GT5 -> 123 }T +T{ : GT6 345 ; IMMEDIATE -> }T +T{ : GT7 POSTPONE GT6 ; -> }T +T{ GT7 -> 345 }T + +T{ : GT8 STATE @ ; IMMEDIATE -> }T +T{ GT8 -> 0 }T +T{ : GT9 GT8 LITERAL ; -> }T +T{ GT9 0= -> }T + +\ ------------------------------------------------------------------------ +TESTING IF ELSE THEN BEGIN WHILE REPEAT UNTIL RECURSE + +T{ : GI1 IF 123 THEN ; -> }T +T{ : GI2 IF 123 ELSE 234 THEN ; -> }T +T{ 0 GI1 -> }T +T{ 1 GI1 -> 123 }T +T{ -1 GI1 -> 123 }T +T{ 0 GI2 -> 234 }T +T{ 1 GI2 -> 123 }T +T{ -1 GI1 -> 123 }T + +T{ : GI3 BEGIN DUP 5 < WHILE DUP 1+ REPEAT ; -> }T +T{ 0 GI3 -> 0 1 2 3 4 5 }T +T{ 4 GI3 -> 4 5 }T +T{ 5 GI3 -> 5 }T +T{ 6 GI3 -> 6 }T + +T{ : GI4 BEGIN DUP 1+ DUP 5 > UNTIL ; -> }T +T{ 3 GI4 -> 3 4 5 6 }T +T{ 5 GI4 -> 5 6 }T +T{ 6 GI4 -> 6 7 }T + +T{ : GI5 BEGIN DUP 2 > + WHILE DUP 5 < WHILE DUP 1+ REPEAT 123 ELSE 345 THEN ; -> }T +T{ 1 GI5 -> 1 345 }T +T{ 2 GI5 -> 2 345 }T +T{ 3 GI5 -> 3 4 5 123 }T +T{ 4 GI5 -> 4 5 123 }T +T{ 5 GI5 -> 5 123 }T + +T{ : GI6 ( N -- 0,1,..N ) DUP IF DUP >R 1- RECURSE R> THEN ; -> }T +T{ 0 GI6 -> 0 }T +T{ 1 GI6 -> 0 1 }T +T{ 2 GI6 -> 0 1 2 }T +T{ 3 GI6 -> 0 1 2 3 }T +T{ 4 GI6 -> 0 1 2 3 4 }T + +\ ------------------------------------------------------------------------ +TESTING DO LOOP +LOOP I J UNLOOP LEAVE EXIT + +T{ : GD1 DO I LOOP ; -> }T +T{ 4 1 GD1 -> 1 2 3 }T +T{ 2 -1 GD1 -> -1 0 1 }T +T{ MID-UINT+1 MID-UINT GD1 -> MID-UINT }T + +T{ : GD2 DO I -1 +LOOP ; -> }T +T{ 1 4 GD2 -> 4 3 2 1 }T +T{ -1 2 GD2 -> 2 1 0 -1 }T +T{ MID-UINT MID-UINT+1 GD2 -> MID-UINT+1 MID-UINT }T + +T{ : GD3 DO 1 0 DO J LOOP LOOP ; -> }T +T{ 4 1 GD3 -> 1 2 3 }T +T{ 2 -1 GD3 -> -1 0 1 }T +T{ MID-UINT+1 MID-UINT GD3 -> MID-UINT }T + +T{ : GD4 DO 1 0 DO J LOOP -1 +LOOP ; -> }T +T{ 1 4 GD4 -> 4 3 2 1 }T +T{ -1 2 GD4 -> 2 1 0 -1 }T +T{ MID-UINT MID-UINT+1 GD4 -> MID-UINT+1 MID-UINT }T + +T{ : GD5 123 SWAP 0 DO I 4 > IF DROP 234 LEAVE THEN LOOP ; -> }T +T{ 1 GD5 -> 123 }T +T{ 5 GD5 -> 123 }T +T{ 6 GD5 -> 234 }T + +T{ : GD6 ( PAT: T{0 0},{0 0}{1 0}{1 1},{0 0}{1 0}{1 1}{2 0}{2 1}{2 2} ) + 0 SWAP 0 DO + I 1+ 0 DO I J + 3 = IF I UNLOOP I UNLOOP EXIT THEN 1+ LOOP + LOOP ; -> }T +T{ 1 GD6 -> 1 }T +T{ 2 GD6 -> 3 }T +T{ 3 GD6 -> 4 1 2 }T + +\ ------------------------------------------------------------------------ +TESTING DEFINING WORDS: : ; CONSTANT VARIABLE CREATE DOES> >BODY + +T{ 123 CONSTANT X123 -> }T +T{ X123 -> 123 }T +T{ : EQU CONSTANT ; -> }T +T{ X123 EQU Y123 -> }T +T{ Y123 -> 123 }T + +T{ VARIABLE V1 -> }T +T{ 123 V1 ! -> }T +T{ V1 @ -> 123 }T + +T{ : NOP : POSTPONE ; ; -> }T +T{ NOP NOP1 NOP NOP2 -> }T +T{ NOP1 -> }T +T{ NOP2 -> }T + +T{ : DOES1 DOES> @ 1 + ; -> }T +T{ : DOES2 DOES> @ 2 + ; -> }T +T{ CREATE CR1 -> }T +T{ CR1 -> HERE }T +T{ ' CR1 >BODY -> HERE }T +T{ 1 , -> }T +T{ CR1 @ -> 1 }T +T{ DOES1 -> }T +T{ CR1 -> 2 }T +T{ DOES2 -> }T +T{ CR1 -> 3 }T + +T{ : WEIRD: CREATE DOES> 1 + DOES> 2 + ; -> }T +T{ WEIRD: W1 -> }T +T{ ' W1 >BODY -> HERE }T +T{ W1 -> HERE 1 + }T +T{ W1 -> HERE 2 + }T + +\ ------------------------------------------------------------------------ +TESTING EVALUATE + +: GE1 S" 123" ; IMMEDIATE +: GE2 S" 123 1+" ; IMMEDIATE +: GE3 S" : GE4 345 ;" ; +: GE5 EVALUATE ; IMMEDIATE + +T{ GE1 EVALUATE -> 123 }T ( TEST EVALUATE IN INTERP. STATE ) +T{ GE2 EVALUATE -> 124 }T +T{ GE3 EVALUATE -> }T +T{ GE4 -> 345 }T + +T{ : GE6 GE1 GE5 ; -> }T ( TEST EVALUATE IN COMPILE STATE ) +T{ GE6 -> 123 }T +T{ : GE7 GE2 GE5 ; -> }T +T{ GE7 -> 124 }T + +\ ------------------------------------------------------------------------ +TESTING SOURCE >IN WORD + +: GS1 S" SOURCE" 2DUP EVALUATE + >R SWAP >R = R> R> = ; +T{ GS1 -> }T + +VARIABLE SCANS +: RESCAN? -1 SCANS +! SCANS @ IF 0 >IN ! THEN ; + +T{ 2 SCANS ! +345 RESCAN? +-> 345 345 }T + +: GS2 5 SCANS ! S" 123 RESCAN?" EVALUATE ; +T{ GS2 -> 123 123 123 123 123 }T + +: GS3 WORD COUNT SWAP C@ ; +T{ BL GS3 HELLO -> 5 CHAR H }T +T{ CHAR " GS3 GOODBYE" -> 7 CHAR G }T +T{ BL GS3 +DROP -> 0 }T \ BLANK LINE RETURN ZERO-LENGTH STRING + +: GS4 SOURCE >IN ! DROP ; +T{ GS4 123 456 +-> }T + +\ ------------------------------------------------------------------------ +TESTING <# # #S #> HOLD SIGN BASE >NUMBER HEX DECIMAL + +: S= \ ( ADDR1 C1 ADDR2 C2 -- T/F ) COMPARE TWO STRINGS. + >R SWAP R@ = IF \ MAKE SURE STRINGS HAVE SAME LENGTH + R> ?DUP IF \ IF NON-EMPTY STRINGS + 0 DO + OVER C@ OVER C@ - IF 2DROP UNLOOP EXIT THEN + SWAP CHAR+ SWAP CHAR+ + LOOP + THEN + 2DROP \ IF WE GET HERE, STRINGS MATCH + ELSE + R> DROP 2DROP \ LENGTHS MISMATCH + THEN ; + +: GP1 <# 41 HOLD 42 HOLD 0 0 #> S" BA" S= ; +T{ GP1 -> }T + +: GP2 <# -1 SIGN 0 SIGN -1 SIGN 0 0 #> S" --" S= ; +T{ GP2 -> }T + +: GP3 <# 1 0 # # #> S" 01" S= ; +T{ GP3 -> }T + +: GP4 <# 1 0 #S #> S" 1" S= ; +T{ GP4 -> }T + +24 CONSTANT MAX-BASE \ BASE 2 .. 36 +: COUNT-BITS + 0 0 INVERT BEGIN DUP WHILE >R 1+ R> 2* REPEAT DROP ; +COUNT-BITS 2* CONSTANT #BITS-UD \ NUMBER OF BITS IN UD + +: GP5 + BASE @ + MAX-BASE 1+ 2 DO \ FOR EACH POSSIBLE BASE + I BASE ! \ TBD: ASSUMES BASE WORKS + I 0 <# #S #> S" 10" S= AND + LOOP + SWAP BASE ! ; +T{ GP5 -> }T + +: GP6 + BASE @ >R 2 BASE ! + MAX-UINT MAX-UINT <# #S #> \ MAXIMUM UD TO BINARY + R> BASE ! \ S: C-ADDR U + DUP #BITS-UD = SWAP + 0 DO \ S: C-ADDR FLAG + OVER C@ [CHAR] 1 = AND \ ALL ONES + >R CHAR+ R> + LOOP SWAP DROP ; +T{ GP6 -> }T + +: GP7 + BASE @ >R MAX-BASE BASE ! + + A 0 DO + I 0 <# #S #> + 1 = SWAP C@ I 30 + = AND AND + LOOP + MAX-BASE A DO + I 0 <# #S #> + 1 = SWAP C@ 41 I A - + = AND AND + LOOP + R> BASE ! ; + +T{ GP7 -> }T + +\ >NUMBER TESTS +CREATE GN-BUF 0 C, +: GN-STRING GN-BUF 1 ; +: GN-CONSUMED GN-BUF CHAR+ 0 ; +: GN' [CHAR] ' WORD CHAR+ C@ GN-BUF C! GN-STRING ; + +T{ 0 0 GN' 0' >NUMBER -> 0 0 GN-CONSUMED }T +T{ 0 0 GN' 1' >NUMBER -> 1 0 GN-CONSUMED }T +T{ 1 0 GN' 1' >NUMBER -> BASE @ 1+ 0 GN-CONSUMED }T +T{ 0 0 GN' -' >NUMBER -> 0 0 GN-STRING }T \ SHOULD FAIL TO CONVERT THESE +T{ 0 0 GN' +' >NUMBER -> 0 0 GN-STRING }T +T{ 0 0 GN' .' >NUMBER -> 0 0 GN-STRING }T + +: >NUMBER-BASED + BASE @ >R BASE ! >NUMBER R> BASE ! ; + +T{ 0 0 GN' 2' 10 >NUMBER-BASED -> 2 0 GN-CONSUMED }T +T{ 0 0 GN' 2' 2 >NUMBER-BASED -> 0 0 GN-STRING }T +T{ 0 0 GN' F' 10 >NUMBER-BASED -> F 0 GN-CONSUMED }T +T{ 0 0 GN' G' 10 >NUMBER-BASED -> 0 0 GN-STRING }T +T{ 0 0 GN' G' MAX-BASE >NUMBER-BASED -> 10 0 GN-CONSUMED }T +T{ 0 0 GN' Z' MAX-BASE >NUMBER-BASED -> 23 0 GN-CONSUMED }T + +: GN1 \ ( UD BASE -- UD' LEN ) UD SHOULD EQUAL UD' AND LEN SHOULD BE ZERO. + BASE @ >R BASE ! + <# #S #> + 0 0 2SWAP >NUMBER SWAP DROP \ RETURN LENGTH ONLY + R> BASE ! ; +T{ 0 0 2 GN1 -> 0 0 0 }T +T{ MAX-UINT 0 2 GN1 -> MAX-UINT 0 0 }T +T{ MAX-UINT DUP 2 GN1 -> MAX-UINT DUP 0 }T +T{ 0 0 MAX-BASE GN1 -> 0 0 0 }T +T{ MAX-UINT 0 MAX-BASE GN1 -> MAX-UINT 0 0 }T +T{ MAX-UINT DUP MAX-BASE GN1 -> MAX-UINT DUP 0 }T + +: GN2 \ ( -- 16 10 ) + BASE @ >R HEX BASE @ DECIMAL BASE @ R> BASE ! ; +T{ GN2 -> 10 A }T + +\ ------------------------------------------------------------------------ +TESTING FILL MOVE + +CREATE FBUF 00 C, 00 C, 00 C, +CREATE SBUF 12 C, 34 C, 56 C, +: SEEBUF FBUF C@ FBUF CHAR+ C@ FBUF CHAR+ CHAR+ C@ ; + +T{ FBUF 0 20 FILL -> }T +T{ SEEBUF -> 00 00 00 }T + +T{ FBUF 1 20 FILL -> }T +T{ SEEBUF -> 20 00 00 }T + +T{ FBUF 3 20 FILL -> }T +T{ SEEBUF -> 20 20 20 }T + +T{ FBUF FBUF 3 CHARS MOVE -> }T \ BIZARRE SPECIAL CASE +T{ SEEBUF -> 20 20 20 }T + +T{ SBUF FBUF 0 CHARS MOVE -> }T +T{ SEEBUF -> 20 20 20 }T + +T{ SBUF FBUF 1 CHARS MOVE -> }T +T{ SEEBUF -> 12 20 20 }T + +T{ SBUF FBUF 3 CHARS MOVE -> }T +T{ SEEBUF -> 12 34 56 }T + +T{ FBUF FBUF CHAR+ 2 CHARS MOVE -> }T +T{ SEEBUF -> 12 12 34 }T + +T{ FBUF CHAR+ FBUF 2 CHARS MOVE -> }T +T{ SEEBUF -> 12 34 34 }T + +\ ------------------------------------------------------------------------ +TESTING OUTPUT: . ." CR EMIT SPACE SPACES TYPE U. + +: OUTPUT-TEST + ." YOU SHOULD SEE THE STANDARD GRAPHIC CHARACTERS:" CR + 41 BL DO I EMIT LOOP CR + 61 41 DO I EMIT LOOP CR + 7F 61 DO I EMIT LOOP CR + ." YOU SHOULD SEE 0-9 SEPARATED BY A SPACE:" CR + 9 1+ 0 DO I . LOOP CR + ." YOU SHOULD SEE 0-9 (WITH NO SPACES):" CR + [CHAR] 9 1+ [CHAR] 0 DO I 0 SPACES EMIT LOOP CR + ." YOU SHOULD SEE A-G SEPARATED BY A SPACE:" CR + [CHAR] G 1+ [CHAR] A DO I EMIT SPACE LOOP CR + ." YOU SHOULD SEE 0-5 SEPARATED BY TWO SPACES:" CR + 5 1+ 0 DO I [CHAR] 0 + EMIT 2 SPACES LOOP CR + ." YOU SHOULD SEE TWO SEPARATE LINES:" CR + S" LINE 1" TYPE CR S" LINE 2" TYPE CR + ." YOU SHOULD SEE THE NUMBER RANGES OF SIGNED AND UNSIGNED NUMBERS:" CR + ." SIGNED: " MIN-INT . MAX-INT . CR + ." UNSIGNED: " 0 U. MAX-UINT U. CR +; + +T{ OUTPUT-TEST -> }T + + +\ ------------------------------------------------------------------------ +TESTING INPUT: ACCEPT + +CREATE ABUF 50 CHARS ALLOT + +: ACCEPT-TEST + CR ." PLEASE TYPE UP TO 80 CHARACTERS:" CR + ABUF 50 ACCEPT + CR ." RECEIVED: " [CHAR] " EMIT + ABUF SWAP TYPE [CHAR] " EMIT CR +; + +T{ ACCEPT-TEST -> }T + +\ ------------------------------------------------------------------------ +TESTING DICTIONARY SEARCH RULES + +T{ : GDX 123 ; : GDX GDX 234 ; -> }T + +T{ GDX -> 123 234 }T + +CR .( End of Core word set tests) CR + +MAN +TEXT /MAKE/USR/SHARE/forth/core.f diff --git a/FORTH/coreexttest.f b/FORTH/coreexttest.f new file mode 100644 index 00000000..51fe62ef --- /dev/null +++ b/FORTH/coreexttest.f @@ -0,0 +1,770 @@ +\ To test the ANS Forth Core Extension word set + +\ 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.13 28 October 2015 +\ Replace and with FALSE and TRUE to avoid +\ dependence on Core tests +\ Moved SAVE-INPUT and RESTORE-INPUT tests in a file to filetest.fth +\ Use of 2VARIABLE (from optional wordset) replaced with CREATE. +\ Minor lower to upper case conversions. +\ Calls to COMPARE replaced by S= (in utilities.fth) to avoid use +\ of a word from an optional word set. +\ UNUSED tests revised as UNUSED UNUSED = may return FALSE when an +\ implementation has the data stack sharing unused dataspace. +\ Double number input dependency removed from the HOLDS tests. +\ Minor case sensitivities removed in definition names. +\ 0.11 25 April 2015 +\ Added tests for PARSE-NAME HOLDS BUFFER: +\ S\" tests added +\ DEFER IS ACTION-OF DEFER! DEFER@ tests added +\ Empty CASE statement test added +\ [COMPILE] tests removed because it is obsolescent in Forth 2012 +\ 0.10 1 August 2014 +\ Added tests contributed by James Bowman for: +\ <> U> 0<> 0> NIP TUCK ROLL PICK 2>R 2R@ 2R> +\ HEX WITHIN UNUSED AGAIN MARKER +\ Added tests for: +\ .R U.R ERASE PAD REFILL SOURCE-ID +\ Removed ABORT from NeverExecuted to enable Win32 +\ to continue after failure of RESTORE-INPUT. +\ Removed max-intx which is no longer used. +\ 0.7 6 June 2012 Extra CASE test added +\ 0.6 1 April 2012 Tests placed in the public domain. +\ SAVE-INPUT & RESTORE-INPUT tests, position +\ of T{ moved so that tests work with ttester.fs +\ CONVERT test deleted - obsolete word removed from Forth 200X +\ IMMEDIATE VALUEs tested +\ RECURSE with :NONAME tested +\ PARSE and .( tested +\ Parsing behaviour of C" added +\ 0.5 14 September 2011 Removed the double [ELSE] from the +\ initial SAVE-INPUT & RESTORE-INPUT test +\ 0.4 30 November 2009 max-int replaced with max-intx to +\ avoid redefinition warnings. +\ 0.3 6 March 2009 { and } replaced with T{ and }T +\ CONVERT test now independent of cell size +\ 0.2 20 April 2007 ANS Forth words changed to upper case +\ Tests qd3 to qd6 by Reinhold Straub +\ 0.1 Oct 2006 First version released +\ ----------------------------------------------------------------------------- +\ The tests are based on John Hayes test program for the core word set + +\ Words tested in this file are: +\ .( .R 0<> 0> 2>R 2R> 2R@ :NONAME <> ?DO AGAIN C" CASE COMPILE, ENDCASE +\ ENDOF ERASE FALSE HEX MARKER NIP OF PAD PARSE PICK REFILL +\ RESTORE-INPUT ROLL SAVE-INPUT SOURCE-ID TO TRUE TUCK U.R U> UNUSED +\ VALUE WITHIN [COMPILE] + +\ Words not tested or partially tested: +\ \ because it has been extensively used already and is, hence, unnecessary +\ REFILL and SOURCE-ID from the user input device which are not possible +\ when testing from a file such as this one +\ UNUSED (partially tested) as the value returned is system dependent +\ Obsolescent words #TIB CONVERT EXPECT QUERY SPAN TIB as they have been +\ removed from the Forth 2012 standard + +\ Results from words that output to the user output device have to visually +\ checked for correctness. These are .R U.R .( + +\ ----------------------------------------------------------------------------- +\ Assumptions & dependencies: +\ - tester.fr (or ttester.fs), errorreport.fth and utilities.fth have been +\ included prior to this file +\ - the Core word set available +\ ----------------------------------------------------------------------------- +TESTING Core Extension words + +DECIMAL + +TESTING TRUE FALSE + +T{ TRUE -> 0 INVERT }T +T{ FALSE -> 0 }T + +\ ----------------------------------------------------------------------------- +TESTING <> U> (contributed by James Bowman) + +T{ 0 0 <> -> FALSE }T +T{ 1 1 <> -> FALSE }T +T{ -1 -1 <> -> FALSE }T +T{ 1 0 <> -> TRUE }T +T{ -1 0 <> -> TRUE }T +T{ 0 1 <> -> TRUE }T +T{ 0 -1 <> -> TRUE }T + +T{ 0 1 U> -> FALSE }T +T{ 1 2 U> -> FALSE }T +T{ 0 MID-UINT U> -> FALSE }T +T{ 0 MAX-UINT U> -> FALSE }T +T{ MID-UINT MAX-UINT U> -> FALSE }T +T{ 0 0 U> -> FALSE }T +T{ 1 1 U> -> FALSE }T +T{ 1 0 U> -> TRUE }T +T{ 2 1 U> -> TRUE }T +T{ MID-UINT 0 U> -> TRUE }T +T{ MAX-UINT 0 U> -> TRUE }T +T{ MAX-UINT MID-UINT U> -> TRUE }T + +\ ----------------------------------------------------------------------------- +TESTING 0<> 0> (contributed by James Bowman) + +T{ 0 0<> -> FALSE }T +T{ 1 0<> -> TRUE }T +T{ 2 0<> -> TRUE }T +T{ -1 0<> -> TRUE }T +T{ MAX-UINT 0<> -> TRUE }T +T{ MIN-INT 0<> -> TRUE }T +T{ MAX-INT 0<> -> TRUE }T + +T{ 0 0> -> FALSE }T +T{ -1 0> -> FALSE }T +T{ MIN-INT 0> -> FALSE }T +T{ 1 0> -> TRUE }T +T{ MAX-INT 0> -> TRUE }T + +\ ----------------------------------------------------------------------------- +TESTING NIP TUCK ROLL PICK (contributed by James Bowman) + +T{ 1 2 NIP -> 2 }T +T{ 1 2 3 NIP -> 1 3 }T + +T{ 1 2 TUCK -> 2 1 2 }T +T{ 1 2 3 TUCK -> 1 3 2 3 }T + +T{ : RO5 100 200 300 400 500 ; -> }T +T{ RO5 3 ROLL -> 100 300 400 500 200 }T +T{ RO5 2 ROLL -> RO5 ROT }T +T{ RO5 1 ROLL -> RO5 SWAP }T +T{ RO5 0 ROLL -> RO5 }T + +T{ RO5 2 PICK -> 100 200 300 400 500 300 }T +T{ RO5 1 PICK -> RO5 OVER }T +T{ RO5 0 PICK -> RO5 DUP }T + +\ ----------------------------------------------------------------------------- +TESTING 2>R 2R@ 2R> (contributed by James Bowman) + +T{ : RR0 2>R 100 R> R> ; -> }T +T{ 300 400 RR0 -> 100 400 300 }T +T{ 200 300 400 RR0 -> 200 100 400 300 }T + +T{ : RR1 2>R 100 2R@ R> R> ; -> }T +T{ 300 400 RR1 -> 100 300 400 400 300 }T +T{ 200 300 400 RR1 -> 200 100 300 400 400 300 }T + +T{ : RR2 2>R 100 2R> ; -> }T +T{ 300 400 RR2 -> 100 300 400 }T +T{ 200 300 400 RR2 -> 200 100 300 400 }T + +\ ----------------------------------------------------------------------------- +TESTING HEX (contributed by James Bowman) + +T{ BASE @ HEX BASE @ DECIMAL BASE @ - SWAP BASE ! -> 6 }T + +\ ----------------------------------------------------------------------------- +TESTING WITHIN (contributed by James Bowman) + +T{ 0 0 0 WITHIN -> FALSE }T +T{ 0 0 MID-UINT WITHIN -> TRUE }T +T{ 0 0 MID-UINT+1 WITHIN -> TRUE }T +T{ 0 0 MAX-UINT WITHIN -> TRUE }T +T{ 0 MID-UINT 0 WITHIN -> FALSE }T +T{ 0 MID-UINT MID-UINT WITHIN -> FALSE }T +T{ 0 MID-UINT MID-UINT+1 WITHIN -> FALSE }T +T{ 0 MID-UINT MAX-UINT WITHIN -> FALSE }T +T{ 0 MID-UINT+1 0 WITHIN -> FALSE }T +T{ 0 MID-UINT+1 MID-UINT WITHIN -> TRUE }T +T{ 0 MID-UINT+1 MID-UINT+1 WITHIN -> FALSE }T +T{ 0 MID-UINT+1 MAX-UINT WITHIN -> FALSE }T +T{ 0 MAX-UINT 0 WITHIN -> FALSE }T +T{ 0 MAX-UINT MID-UINT WITHIN -> TRUE }T +T{ 0 MAX-UINT MID-UINT+1 WITHIN -> TRUE }T +T{ 0 MAX-UINT MAX-UINT WITHIN -> FALSE }T +T{ MID-UINT 0 0 WITHIN -> FALSE }T +T{ MID-UINT 0 MID-UINT WITHIN -> FALSE }T +T{ MID-UINT 0 MID-UINT+1 WITHIN -> TRUE }T +T{ MID-UINT 0 MAX-UINT WITHIN -> TRUE }T +T{ MID-UINT MID-UINT 0 WITHIN -> TRUE }T +T{ MID-UINT MID-UINT MID-UINT WITHIN -> FALSE }T +T{ MID-UINT MID-UINT MID-UINT+1 WITHIN -> TRUE }T +T{ MID-UINT MID-UINT MAX-UINT WITHIN -> TRUE }T +T{ MID-UINT MID-UINT+1 0 WITHIN -> FALSE }T +T{ MID-UINT MID-UINT+1 MID-UINT WITHIN -> FALSE }T +T{ MID-UINT MID-UINT+1 MID-UINT+1 WITHIN -> FALSE }T +T{ MID-UINT MID-UINT+1 MAX-UINT WITHIN -> FALSE }T +T{ MID-UINT MAX-UINT 0 WITHIN -> FALSE }T +T{ MID-UINT MAX-UINT MID-UINT WITHIN -> FALSE }T +T{ MID-UINT MAX-UINT MID-UINT+1 WITHIN -> TRUE }T +T{ MID-UINT MAX-UINT MAX-UINT WITHIN -> FALSE }T +T{ MID-UINT+1 0 0 WITHIN -> FALSE }T +T{ MID-UINT+1 0 MID-UINT WITHIN -> FALSE }T +T{ MID-UINT+1 0 MID-UINT+1 WITHIN -> FALSE }T +T{ MID-UINT+1 0 MAX-UINT WITHIN -> TRUE }T +T{ MID-UINT+1 MID-UINT 0 WITHIN -> TRUE }T +T{ MID-UINT+1 MID-UINT MID-UINT WITHIN -> FALSE }T +T{ MID-UINT+1 MID-UINT MID-UINT+1 WITHIN -> FALSE }T +T{ MID-UINT+1 MID-UINT MAX-UINT WITHIN -> TRUE }T +T{ MID-UINT+1 MID-UINT+1 0 WITHIN -> TRUE }T +T{ MID-UINT+1 MID-UINT+1 MID-UINT WITHIN -> TRUE }T +T{ MID-UINT+1 MID-UINT+1 MID-UINT+1 WITHIN -> FALSE }T +T{ MID-UINT+1 MID-UINT+1 MAX-UINT WITHIN -> TRUE }T +T{ MID-UINT+1 MAX-UINT 0 WITHIN -> FALSE }T +T{ MID-UINT+1 MAX-UINT MID-UINT WITHIN -> FALSE }T +T{ MID-UINT+1 MAX-UINT MID-UINT+1 WITHIN -> FALSE }T +T{ MID-UINT+1 MAX-UINT MAX-UINT WITHIN -> FALSE }T +T{ MAX-UINT 0 0 WITHIN -> FALSE }T +T{ MAX-UINT 0 MID-UINT WITHIN -> FALSE }T +T{ MAX-UINT 0 MID-UINT+1 WITHIN -> FALSE }T +T{ MAX-UINT 0 MAX-UINT WITHIN -> FALSE }T +T{ MAX-UINT MID-UINT 0 WITHIN -> TRUE }T +T{ MAX-UINT MID-UINT MID-UINT WITHIN -> FALSE }T +T{ MAX-UINT MID-UINT MID-UINT+1 WITHIN -> FALSE }T +T{ MAX-UINT MID-UINT MAX-UINT WITHIN -> FALSE }T +T{ MAX-UINT MID-UINT+1 0 WITHIN -> TRUE }T +T{ MAX-UINT MID-UINT+1 MID-UINT WITHIN -> TRUE }T +T{ MAX-UINT MID-UINT+1 MID-UINT+1 WITHIN -> FALSE }T +T{ MAX-UINT MID-UINT+1 MAX-UINT WITHIN -> FALSE }T +T{ MAX-UINT MAX-UINT 0 WITHIN -> TRUE }T +T{ MAX-UINT MAX-UINT MID-UINT WITHIN -> TRUE }T +T{ MAX-UINT MAX-UINT MID-UINT+1 WITHIN -> TRUE }T +T{ MAX-UINT MAX-UINT MAX-UINT WITHIN -> FALSE }T + +T{ MIN-INT MIN-INT MIN-INT WITHIN -> FALSE }T +T{ MIN-INT MIN-INT 0 WITHIN -> TRUE }T +T{ MIN-INT MIN-INT 1 WITHIN -> TRUE }T +T{ MIN-INT MIN-INT MAX-INT WITHIN -> TRUE }T +T{ MIN-INT 0 MIN-INT WITHIN -> FALSE }T +T{ MIN-INT 0 0 WITHIN -> FALSE }T +T{ MIN-INT 0 1 WITHIN -> FALSE }T +T{ MIN-INT 0 MAX-INT WITHIN -> FALSE }T +T{ MIN-INT 1 MIN-INT WITHIN -> FALSE }T +T{ MIN-INT 1 0 WITHIN -> TRUE }T +T{ MIN-INT 1 1 WITHIN -> FALSE }T +T{ MIN-INT 1 MAX-INT WITHIN -> FALSE }T +T{ MIN-INT MAX-INT MIN-INT WITHIN -> FALSE }T +T{ MIN-INT MAX-INT 0 WITHIN -> TRUE }T +T{ MIN-INT MAX-INT 1 WITHIN -> TRUE }T +T{ MIN-INT MAX-INT MAX-INT WITHIN -> FALSE }T +T{ 0 MIN-INT MIN-INT WITHIN -> FALSE }T +T{ 0 MIN-INT 0 WITHIN -> FALSE }T +T{ 0 MIN-INT 1 WITHIN -> TRUE }T +T{ 0 MIN-INT MAX-INT WITHIN -> TRUE }T +T{ 0 0 MIN-INT WITHIN -> TRUE }T +T{ 0 0 0 WITHIN -> FALSE }T +T{ 0 0 1 WITHIN -> TRUE }T +T{ 0 0 MAX-INT WITHIN -> TRUE }T +T{ 0 1 MIN-INT WITHIN -> FALSE }T +T{ 0 1 0 WITHIN -> FALSE }T +T{ 0 1 1 WITHIN -> FALSE }T +T{ 0 1 MAX-INT WITHIN -> FALSE }T +T{ 0 MAX-INT MIN-INT WITHIN -> FALSE }T +T{ 0 MAX-INT 0 WITHIN -> FALSE }T +T{ 0 MAX-INT 1 WITHIN -> TRUE }T +T{ 0 MAX-INT MAX-INT WITHIN -> FALSE }T +T{ 1 MIN-INT MIN-INT WITHIN -> FALSE }T +T{ 1 MIN-INT 0 WITHIN -> FALSE }T +T{ 1 MIN-INT 1 WITHIN -> FALSE }T +T{ 1 MIN-INT MAX-INT WITHIN -> TRUE }T +T{ 1 0 MIN-INT WITHIN -> TRUE }T +T{ 1 0 0 WITHIN -> FALSE }T +T{ 1 0 1 WITHIN -> FALSE }T +T{ 1 0 MAX-INT WITHIN -> TRUE }T +T{ 1 1 MIN-INT WITHIN -> TRUE }T +T{ 1 1 0 WITHIN -> TRUE }T +T{ 1 1 1 WITHIN -> FALSE }T +T{ 1 1 MAX-INT WITHIN -> TRUE }T +T{ 1 MAX-INT MIN-INT WITHIN -> FALSE }T +T{ 1 MAX-INT 0 WITHIN -> FALSE }T +T{ 1 MAX-INT 1 WITHIN -> FALSE }T +T{ 1 MAX-INT MAX-INT WITHIN -> FALSE }T +T{ MAX-INT MIN-INT MIN-INT WITHIN -> FALSE }T +T{ MAX-INT MIN-INT 0 WITHIN -> FALSE }T +T{ MAX-INT MIN-INT 1 WITHIN -> FALSE }T +T{ MAX-INT MIN-INT MAX-INT WITHIN -> FALSE }T +T{ MAX-INT 0 MIN-INT WITHIN -> TRUE }T +T{ MAX-INT 0 0 WITHIN -> FALSE }T +T{ MAX-INT 0 1 WITHIN -> FALSE }T +T{ MAX-INT 0 MAX-INT WITHIN -> FALSE }T +T{ MAX-INT 1 MIN-INT WITHIN -> TRUE }T +T{ MAX-INT 1 0 WITHIN -> TRUE }T +T{ MAX-INT 1 1 WITHIN -> FALSE }T +T{ MAX-INT 1 MAX-INT WITHIN -> FALSE }T +T{ MAX-INT MAX-INT MIN-INT WITHIN -> TRUE }T +T{ MAX-INT MAX-INT 0 WITHIN -> TRUE }T +T{ MAX-INT MAX-INT 1 WITHIN -> TRUE }T +T{ MAX-INT MAX-INT MAX-INT WITHIN -> FALSE }T + +\ ----------------------------------------------------------------------------- +TESTING UNUSED (contributed by James Bowman & Peter Knaggs) + +VARIABLE UNUSED0 +T{ UNUSED DROP -> }T +T{ ALIGN UNUSED UNUSED0 ! 0 , UNUSED CELL+ UNUSED0 @ = -> TRUE }T +T{ UNUSED UNUSED0 ! 0 C, UNUSED CHAR+ UNUSED0 @ = + -> TRUE }T \ aligned -> unaligned +T{ UNUSED UNUSED0 ! 0 C, UNUSED CHAR+ UNUSED0 @ = -> TRUE }T \ unaligned -> ? + +\ ----------------------------------------------------------------------------- +TESTING AGAIN (contributed by James Bowman) + +T{ : AG0 701 BEGIN DUP 7 MOD 0= IF EXIT THEN 1+ AGAIN ; -> }T +T{ AG0 -> 707 }T + +\ ----------------------------------------------------------------------------- +TESTING MARKER (contributed by James Bowman) + +T{ : MA? BL WORD FIND NIP 0<> ; -> }T +T{ MARKER MA0 -> }T +T{ : MA1 111 ; -> }T +T{ MARKER MA2 -> }T +T{ : MA1 222 ; -> }T +T{ MA? MA0 MA? MA1 MA? MA2 -> TRUE TRUE TRUE }T +T{ MA1 MA2 MA1 -> 222 111 }T +T{ MA? MA0 MA? MA1 MA? MA2 -> TRUE TRUE FALSE }T +T{ MA0 -> }T +T{ MA? MA0 MA? MA1 MA? MA2 -> FALSE FALSE FALSE }T + +\ ----------------------------------------------------------------------------- +TESTING ?DO + +: QD ?DO I LOOP ; +T{ 789 789 QD -> }T +T{ -9876 -9876 QD -> }T +T{ 5 0 QD -> 0 1 2 3 4 }T + +: QD1 ?DO I 10 +LOOP ; +T{ 50 1 QD1 -> 1 11 21 31 41 }T +T{ 50 0 QD1 -> 0 10 20 30 40 }T + +: QD2 ?DO I 3 > IF LEAVE ELSE I THEN LOOP ; +T{ 5 -1 QD2 -> -1 0 1 2 3 }T + +: QD3 ?DO I 1 +LOOP ; +T{ 4 4 QD3 -> }T +T{ 4 1 QD3 -> 1 2 3 }T +T{ 2 -1 QD3 -> -1 0 1 }T + +: QD4 ?DO I -1 +LOOP ; +T{ 4 4 QD4 -> }T +T{ 1 4 QD4 -> 4 3 2 1 }T +T{ -1 2 QD4 -> 2 1 0 -1 }T + +: QD5 ?DO I -10 +LOOP ; +T{ 1 50 QD5 -> 50 40 30 20 10 }T +T{ 0 50 QD5 -> 50 40 30 20 10 0 }T +T{ -25 10 QD5 -> 10 0 -10 -20 }T + +VARIABLE ITERS +VARIABLE INCRMNT + +: QD6 ( limit start increment -- ) + INCRMNT ! + 0 ITERS ! + ?DO + 1 ITERS +! + I + ITERS @ 6 = IF LEAVE THEN + INCRMNT @ + +LOOP ITERS @ +; + +T{ 4 4 -1 QD6 -> 0 }T +T{ 1 4 -1 QD6 -> 4 3 2 1 4 }T +T{ 4 1 -1 QD6 -> 1 0 -1 -2 -3 -4 6 }T +T{ 4 1 0 QD6 -> 1 1 1 1 1 1 6 }T +T{ 0 0 0 QD6 -> 0 }T +T{ 1 4 0 QD6 -> 4 4 4 4 4 4 6 }T +T{ 1 4 1 QD6 -> 4 5 6 7 8 9 6 }T +T{ 4 1 1 QD6 -> 1 2 3 3 }T +T{ 4 4 1 QD6 -> 0 }T +T{ 2 -1 -1 QD6 -> -1 -2 -3 -4 -5 -6 6 }T +T{ -1 2 -1 QD6 -> 2 1 0 -1 4 }T +T{ 2 -1 0 QD6 -> -1 -1 -1 -1 -1 -1 6 }T +T{ -1 2 0 QD6 -> 2 2 2 2 2 2 6 }T +T{ -1 2 1 QD6 -> 2 3 4 5 6 7 6 }T +T{ 2 -1 1 QD6 -> -1 0 1 3 }T + +\ ----------------------------------------------------------------------------- +TESTING BUFFER: + +T{ 8 BUFFER: BUF:TEST -> }T +T{ BUF:TEST DUP ALIGNED = -> TRUE }T +T{ 111 BUF:TEST ! 222 BUF:TEST CELL+ ! -> }T +T{ BUF:TEST @ BUF:TEST CELL+ @ -> 111 222 }T + +\ ----------------------------------------------------------------------------- +TESTING VALUE TO + +T{ 111 VALUE VAL1 -999 VALUE VAL2 -> }T +T{ VAL1 -> 111 }T +T{ VAL2 -> -999 }T +T{ 222 TO VAL1 -> }T +T{ VAL1 -> 222 }T +T{ : VD1 VAL1 ; -> }T +T{ VD1 -> 222 }T +T{ : VD2 TO VAL2 ; -> }T +T{ VAL2 -> -999 }T +T{ -333 VD2 -> }T +T{ VAL2 -> -333 }T +T{ VAL1 -> 222 }T +T{ 123 VALUE VAL3 IMMEDIATE VAL3 -> 123 }T +T{ : VD3 VAL3 LITERAL ; VD3 -> 123 }T + +\ ----------------------------------------------------------------------------- +TESTING CASE OF ENDOF ENDCASE + +: CS1 CASE 1 OF 111 ENDOF + 2 OF 222 ENDOF + 3 OF 333 ENDOF + >R 999 R> + ENDCASE +; + +T{ 1 CS1 -> 111 }T +T{ 2 CS1 -> 222 }T +T{ 3 CS1 -> 333 }T +T{ 4 CS1 -> 999 }T + +\ Nested CASE's + +: CS2 >R CASE -1 OF CASE R@ 1 OF 100 ENDOF + 2 OF 200 ENDOF + >R -300 R> + ENDCASE + ENDOF + -2 OF CASE R@ 1 OF -99 ENDOF + >R -199 R> + ENDCASE + ENDOF + >R 299 R> + ENDCASE R> DROP +; + +T{ -1 1 CS2 -> 100 }T +T{ -1 2 CS2 -> 200 }T +T{ -1 3 CS2 -> -300 }T +T{ -2 1 CS2 -> -99 }T +T{ -2 2 CS2 -> -199 }T +T{ 0 2 CS2 -> 299 }T + +\ Boolean short circuiting using CASE + +: CS3 ( N1 -- N2 ) + CASE 1- FALSE OF 11 ENDOF + 1- FALSE OF 22 ENDOF + 1- FALSE OF 33 ENDOF + 44 SWAP + ENDCASE +; + +T{ 1 CS3 -> 11 }T +T{ 2 CS3 -> 22 }T +T{ 3 CS3 -> 33 }T +T{ 9 CS3 -> 44 }T + +\ Empty CASE statements with/without default + +T{ : CS4 CASE ENDCASE ; 1 CS4 -> }T +T{ : CS5 CASE 2 SWAP ENDCASE ; 1 CS5 -> 2 }T +T{ : CS6 CASE 1 OF ENDOF 2 ENDCASE ; 1 CS6 -> }T +T{ : CS7 CASE 3 OF ENDOF 2 ENDCASE ; 1 CS7 -> 1 }T + +\ ----------------------------------------------------------------------------- +TESTING :NONAME RECURSE + +VARIABLE NN1 +VARIABLE NN2 +:NONAME 1234 ; NN1 ! +:NONAME 9876 ; NN2 ! +T{ NN1 @ EXECUTE -> 1234 }T +T{ NN2 @ EXECUTE -> 9876 }T + +T{ :NONAME ( n -- 0,1,..n ) DUP IF DUP >R 1- RECURSE R> THEN ; + CONSTANT RN1 -> }T +T{ 0 RN1 EXECUTE -> 0 }T +T{ 4 RN1 EXECUTE -> 0 1 2 3 4 }T + +:NONAME ( n -- n1 ) \ Multiple RECURSEs in one definition + 1- DUP + CASE 0 OF EXIT ENDOF + 1 OF 11 SWAP RECURSE ENDOF + 2 OF 22 SWAP RECURSE ENDOF + 3 OF 33 SWAP RECURSE ENDOF + DROP ABS RECURSE EXIT + ENDCASE +; CONSTANT RN2 + +T{ 1 RN2 EXECUTE -> 0 }T +T{ 2 RN2 EXECUTE -> 11 0 }T +T{ 4 RN2 EXECUTE -> 33 22 11 0 }T +T{ 25 RN2 EXECUTE -> 33 22 11 0 }T + +\ ----------------------------------------------------------------------------- +TESTING C" + +T{ : CQ1 C" 123" ; -> }T +T{ CQ1 COUNT EVALUATE -> 123 }T +T{ : CQ2 C" " ; -> }T +T{ CQ2 COUNT EVALUATE -> }T +T{ : CQ3 C" 2345"COUNT EVALUATE ; CQ3 -> 2345 }T + +\ ----------------------------------------------------------------------------- +TESTING COMPILE, + +:NONAME DUP + ; CONSTANT DUP+ +T{ : Q DUP+ COMPILE, ; -> }T +T{ : AS1 [ Q ] ; -> }T +T{ 123 AS1 -> 246 }T + +\ ----------------------------------------------------------------------------- +\ Cannot automatically test SAVE-INPUT and RESTORE-INPUT from a console source + +TESTING SAVE-INPUT and RESTORE-INPUT with a string source + +VARIABLE SI_INC 0 SI_INC ! + +: SI1 + SI_INC @ >IN +! + 15 SI_INC ! +; + +: S$ S" SAVE-INPUT SI1 RESTORE-INPUT 12345" ; + +T{ S$ EVALUATE SI_INC @ -> 0 2345 15 }T + +\ ----------------------------------------------------------------------------- +TESTING .( + +CR CR .( Output from .() +T{ CR .( You should see -9876: ) -9876 . -> }T +T{ CR .( and again: ).( -9876)CR -> }T + +CR CR .( On the next 2 lines you should see First then Second messages:) +T{ : DOTP CR ." Second message via ." [CHAR] " EMIT \ Check .( is immediate + [ CR ] .( First message via .( ) ; DOTP -> }T +CR CR +T{ : IMM? BL WORD FIND NIP ; IMM? .( -> 1 }T + +\ ----------------------------------------------------------------------------- +TESTING .R and U.R - has to handle different cell sizes + +\ Create some large integers just below/above MAX and Min INTs +MAX-INT 73 79 */ CONSTANT LI1 +MIN-INT 71 73 */ CONSTANT LI2 + +LI1 0 <# #S #> NIP CONSTANT LENLI1 + +: (.R&U.R) ( u1 u2 -- ) \ u1 <= string length, u2 is required indentation + TUCK + >R + LI1 OVER SPACES . CR R@ LI1 SWAP .R CR + LI2 OVER SPACES . CR R@ 1+ LI2 SWAP .R CR + LI1 OVER SPACES U. CR R@ LI1 SWAP U.R CR + LI2 SWAP SPACES U. CR R> LI2 SWAP U.R CR +; + +: .R&U.R ( -- ) + CR ." You should see lines duplicated:" CR + ." indented by 0 spaces" CR 0 0 (.R&U.R) CR + ." indented by 0 spaces" CR LENLI1 0 (.R&U.R) CR \ Just fits required width + ." indented by 5 spaces" CR LENLI1 5 (.R&U.R) CR +; + +CR CR .( Output from .R and U.R) +T{ .R&U.R -> }T + +\ ----------------------------------------------------------------------------- +TESTING PAD ERASE +\ Must handle different size characters i.e. 1 CHARS >= 1 + +84 CONSTANT CHARS/PAD \ Minimum size of PAD in chars +CHARS/PAD CHARS CONSTANT AUS/PAD +: CHECKPAD ( caddr u ch -- f ) \ f = TRUE if u chars = ch + SWAP 0 + ?DO + OVER I CHARS + C@ OVER <> + IF 2DROP UNLOOP FALSE EXIT THEN + LOOP + 2DROP TRUE +; + +T{ PAD DROP -> }T +T{ 0 INVERT PAD C! -> }T +T{ PAD C@ CONSTANT MAXCHAR -> }T +T{ PAD CHARS/PAD 2DUP MAXCHAR FILL MAXCHAR CHECKPAD -> TRUE }T +T{ PAD CHARS/PAD 2DUP CHARS ERASE 0 CHECKPAD -> TRUE }T +T{ PAD CHARS/PAD 2DUP MAXCHAR FILL PAD 0 ERASE MAXCHAR CHECKPAD -> TRUE }T +T{ PAD 43 CHARS + 9 CHARS ERASE -> }T +T{ PAD 43 MAXCHAR CHECKPAD -> TRUE }T +T{ PAD 43 CHARS + 9 0 CHECKPAD -> TRUE }T +T{ PAD 52 CHARS + CHARS/PAD 52 - MAXCHAR CHECKPAD -> TRUE }T + +\ Check that use of WORD and pictured numeric output do not corrupt PAD +\ Minimum size of buffers for these are 33 chars and (2*n)+2 chars respectively +\ where n is number of bits per cell + +PAD CHARS/PAD ERASE +2 BASE ! +MAX-UINT MAX-UINT <# #S CHAR 1 DUP HOLD HOLD #> 2DROP +DECIMAL +BL WORD 12345678123456781234567812345678 DROP +T{ PAD CHARS/PAD 0 CHECKPAD -> TRUE }T + +\ ----------------------------------------------------------------------------- +TESTING PARSE + +T{ CHAR | PARSE 1234| DUP ROT ROT EVALUATE -> 4 1234 }T +T{ CHAR ^ PARSE 23 45 ^ DUP ROT ROT EVALUATE -> 7 23 45 }T +: PA1 [CHAR] $ PARSE DUP >R PAD SWAP CHARS MOVE PAD R> ; +T{ PA1 3456 + DUP ROT ROT EVALUATE -> 4 3456 }T +T{ CHAR A PARSE A SWAP DROP -> 0 }T +T{ CHAR Z PARSE + SWAP DROP -> 0 }T +T{ CHAR " PARSE 4567 "DUP ROT ROT EVALUATE -> 5 4567 }T + +\ ----------------------------------------------------------------------------- +TESTING PARSE-NAME (Forth 2012) +\ Adapted from the PARSE-NAME RfD tests + +T{ PARSE-NAME abcd STR1 S= -> TRUE }T \ No leading spaces +T{ PARSE-NAME abcde STR2 S= -> TRUE }T \ Leading spaces + +\ Test empty parse area, new lines are necessary +T{ PARSE-NAME + NIP -> 0 }T +\ Empty parse area with spaces after PARSE-NAME +T{ PARSE-NAME + NIP -> 0 }T + +T{ : PARSE-NAME-TEST ( "name1" "name2" -- n ) + PARSE-NAME PARSE-NAME S= ; -> }T +T{ PARSE-NAME-TEST abcd abcd -> TRUE }T +T{ PARSE-NAME-TEST abcd abcd -> TRUE }T \ Leading spaces +T{ PARSE-NAME-TEST abcde abcdf -> FALSE }T +T{ PARSE-NAME-TEST abcdf abcde -> FALSE }T +T{ PARSE-NAME-TEST abcde abcde + -> TRUE }T \ Parse to end of line +T{ PARSE-NAME-TEST abcde abcde + -> TRUE }T \ Leading and trailing spaces + +\ ----------------------------------------------------------------------------- +TESTING DEFER DEFER@ DEFER! IS ACTION-OF (Forth 2012) +\ Adapted from the Forth 200X RfD tests + +T{ DEFER DEFER1 -> }T +T{ : MY-DEFER DEFER ; -> }T +T{ : IS-DEFER1 IS DEFER1 ; -> }T +T{ : ACTION-DEFER1 ACTION-OF DEFER1 ; -> }T +T{ : DEF! DEFER! ; -> }T +T{ : DEF@ DEFER@ ; -> }T + +T{ ' * ' DEFER1 DEFER! -> }T +T{ 2 3 DEFER1 -> 6 }T +T{ ' DEFER1 DEFER@ -> ' * }T +T{ ' DEFER1 DEF@ -> ' * }T +T{ ACTION-OF DEFER1 -> ' * }T +T{ ACTION-DEFER1 -> ' * }T +T{ ' + IS DEFER1 -> }T +T{ 1 2 DEFER1 -> 3 }T +T{ ' DEFER1 DEFER@ -> ' + }T +T{ ' DEFER1 DEF@ -> ' + }T +T{ ACTION-OF DEFER1 -> ' + }T +T{ ACTION-DEFER1 -> ' + }T +T{ ' - IS-DEFER1 -> }T +T{ 1 2 DEFER1 -> -1 }T +T{ ' DEFER1 DEFER@ -> ' - }T +T{ ' DEFER1 DEF@ -> ' - }T +T{ ACTION-OF DEFER1 -> ' - }T +T{ ACTION-DEFER1 -> ' - }T + +T{ MY-DEFER DEFER2 -> }T +T{ ' DUP IS DEFER2 -> }T +T{ 1 DEFER2 -> 1 1 }T + +\ ----------------------------------------------------------------------------- +TESTING HOLDS (Forth 2012) + +: HTEST S" Testing HOLDS" ; +: HTEST2 S" works" ; +: HTEST3 S" Testing HOLDS works 123" ; +T{ 0 0 <# HTEST HOLDS #> HTEST S= -> TRUE }T +T{ 123 0 <# #S BL HOLD HTEST2 HOLDS BL HOLD HTEST HOLDS #> + HTEST3 S= -> TRUE }T +T{ : HLD HOLDS ; -> }T +T{ 0 0 <# HTEST HLD #> HTEST S= -> TRUE }T + +\ ----------------------------------------------------------------------------- +TESTING REFILL SOURCE-ID +\ REFILL and SOURCE-ID from the user input device can't be tested from a file, +\ can only be tested from a string via EVALUATE + +T{ : RF1 S" REFILL" EVALUATE ; RF1 -> FALSE }T +T{ : SID1 S" SOURCE-ID" EVALUATE ; SID1 -> -1 }T + +\ ------------------------------------------------------------------------------ +TESTING S\" (Forth 2012 compilation mode) +\ Extended the Forth 200X RfD tests +\ Note this tests the Core Ext definition of S\" which has unedfined +\ interpretation semantics. S\" in interpretation mode is tested in the tests on +\ the File-Access word set + +T{ : SSQ1 S\" abc" S" abc" S= ; -> }T \ No escapes +T{ SSQ1 -> TRUE }T +T{ : SSQ2 S\" " ; SSQ2 SWAP DROP -> 0 }T \ Empty string + +T{ : SSQ3 S\" \a\b\e\f\l\m\q\r\t\v\x0F0\x1Fa\xaBx\z\"\\" ; -> }T +T{ SSQ3 SWAP DROP -> 20 }T \ String length +T{ SSQ3 DROP C@ -> 7 }T \ \a BEL Bell +T{ SSQ3 DROP 1 CHARS + C@ -> 8 }T \ \b BS Backspace +T{ SSQ3 DROP 2 CHARS + C@ -> 27 }T \ \e ESC Escape +T{ SSQ3 DROP 3 CHARS + C@ -> 12 }T \ \f FF Form feed +T{ SSQ3 DROP 4 CHARS + C@ -> 10 }T \ \l LF Line feed +T{ SSQ3 DROP 5 CHARS + C@ -> 13 }T \ \m CR of CR/LF pair +T{ SSQ3 DROP 6 CHARS + C@ -> 10 }T \ LF of CR/LF pair +T{ SSQ3 DROP 7 CHARS + C@ -> 34 }T \ \q " Double Quote +T{ SSQ3 DROP 8 CHARS + C@ -> 13 }T \ \r CR Carriage Return +T{ SSQ3 DROP 9 CHARS + C@ -> 9 }T \ \t TAB Horizontal Tab +T{ SSQ3 DROP 10 CHARS + C@ -> 11 }T \ \v VT Vertical Tab +T{ SSQ3 DROP 11 CHARS + C@ -> 15 }T \ \x0F Given Char +T{ SSQ3 DROP 12 CHARS + C@ -> 48 }T \ 0 0 Digit follow on +T{ SSQ3 DROP 13 CHARS + C@ -> 31 }T \ \x1F Given Char +T{ SSQ3 DROP 14 CHARS + C@ -> 97 }T \ a a Hex follow on +T{ SSQ3 DROP 15 CHARS + C@ -> 171 }T \ \xaB Insensitive Given Char +T{ SSQ3 DROP 16 CHARS + C@ -> 120 }T \ x x Non hex follow on +T{ SSQ3 DROP 17 CHARS + C@ -> 0 }T \ \z NUL No Character +T{ SSQ3 DROP 18 CHARS + C@ -> 34 }T \ \" " Double Quote +T{ SSQ3 DROP 19 CHARS + C@ -> 92 }T \ \\ \ Back Slash + +\ The above does not test \n as this is a system dependent value. +\ Check it displays a new line +CR .( The next test should display:) +CR .( One line...) +CR .( another line) +T{ : SSQ4 S\" \nOne line...\nanotherLine\n" TYPE ; SSQ4 -> }T + +\ Test bare escapable characters appear as themselves +T{ : SSQ5 S\" abeflmnqrtvxz" S" abeflmnqrtvxz" S= ; SSQ5 -> TRUE }T + +T{ : SSQ6 S\" a\""2DROP 1111 ; SSQ6 -> 1111 }T \ Parsing behaviour + +T{ : SSQ7 S\" 111 : SSQ8 S\\\" 222\" EVALUATE ; SSQ8 333" EVALUATE ; -> }T +T{ SSQ7 -> 111 222 333 }T +T{ : SSQ9 S\" 11 : SSQ10 S\\\" \\x32\\x32\" EVALUATE ; SSQ10 33" EVALUATE ; -> }T +T{ SSQ9 -> 11 22 33 }T + +\ ----------------------------------------------------------------------------- +CORE-EXT-ERRORS SET-ERROR-COUNT + +CR .( End of Core Extension word tests) CR + + diff --git a/FORTH/coreplustest.f b/FORTH/coreplustest.f new file mode 100644 index 00000000..1d128c56 --- /dev/null +++ b/FORTH/coreplustest.f @@ -0,0 +1,305 @@ +\ Additional tests on the the ANS Forth Core word set + +\ This program was written by Gerry Jackson in 2007, 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 + +\ ------------------------------------------------------------------------------ +\ The tests are based on John Hayes test program for the core word set +\ +\ This file provides some more tests on Core words where the original Hayes +\ tests are thought to be incomplete +\ +\ Words tested in this file are: +\ DO I +LOOP RECURSE ELSE >IN IMMEDIATE FIND IF...BEGIN...REPEAT ALLOT DOES> +\ and +\ Parsing behaviour +\ Number prefixes # $ % and 'A' character input +\ Definition names +\ ------------------------------------------------------------------------------ +\ Assumptions and dependencies: +\ - tester.fr or ttester.fs has been loaded prior to this file +\ - core.fr has been loaded so that constants MAX-INT, MIN-INT and +\ MAX-UINT are defined +\ ------------------------------------------------------------------------------ + +DECIMAL + +TESTING DO +LOOP with run-time increment, negative increment, infinite loop +\ Contributed by Reinhold Straub + +VARIABLE ITERATIONS +VARIABLE INCREMENT +: GD7 ( LIMIT START INCREMENT -- ) + INCREMENT ! + 0 ITERATIONS ! + DO + 1 ITERATIONS +! + I + ITERATIONS @ 6 = IF LEAVE THEN + INCREMENT @ + +LOOP ITERATIONS @ +; + +T{ 4 4 -1 GD7 -> 4 1 }T +T{ 1 4 -1 GD7 -> 4 3 2 1 4 }T +T{ 4 1 -1 GD7 -> 1 0 -1 -2 -3 -4 6 }T +T{ 4 1 0 GD7 -> 1 1 1 1 1 1 6 }T +T{ 0 0 0 GD7 -> 0 0 0 0 0 0 6 }T +T{ 1 4 0 GD7 -> 4 4 4 4 4 4 6 }T +T{ 1 4 1 GD7 -> 4 5 6 7 8 9 6 }T +T{ 4 1 1 GD7 -> 1 2 3 3 }T +T{ 4 4 1 GD7 -> 4 5 6 7 8 9 6 }T +T{ 2 -1 -1 GD7 -> -1 -2 -3 -4 -5 -6 6 }T +T{ -1 2 -1 GD7 -> 2 1 0 -1 4 }T +T{ 2 -1 0 GD7 -> -1 -1 -1 -1 -1 -1 6 }T +T{ -1 2 0 GD7 -> 2 2 2 2 2 2 6 }T +T{ -1 2 1 GD7 -> 2 3 4 5 6 7 6 }T +T{ 2 -1 1 GD7 -> -1 0 1 3 }T +T{ -20 30 -10 GD7 -> 30 20 10 0 -10 -20 6 }T +T{ -20 31 -10 GD7 -> 31 21 11 1 -9 -19 6 }T +T{ -20 29 -10 GD7 -> 29 19 9 -1 -11 5 }T + +\ ------------------------------------------------------------------------------ +TESTING DO +LOOP with large and small increments + +\ Contributed by Andrew Haley + +MAX-UINT 8 RSHIFT 1+ CONSTANT USTEP +USTEP NEGATE CONSTANT -USTEP +MAX-INT 7 RSHIFT 1+ CONSTANT STEP +STEP NEGATE CONSTANT -STEP + +VARIABLE BUMP + +T{ : GD8 BUMP ! DO 1+ BUMP @ +LOOP ; -> }T + +T{ 0 MAX-UINT 0 USTEP GD8 -> 256 }T +T{ 0 0 MAX-UINT -USTEP GD8 -> 256 }T + +T{ 0 MAX-INT MIN-INT STEP GD8 -> 256 }T +T{ 0 MIN-INT MAX-INT -STEP GD8 -> 256 }T + +\ Two's complement arithmetic, wraps around modulo wordsize +\ Only tested if the Forth system does wrap around, use of conditional +\ compilation deliberately avoided + +MAX-INT 1+ MIN-INT = CONSTANT +WRAP? +MIN-INT 1- MAX-INT = CONSTANT -WRAP? +MAX-UINT 1+ 0= CONSTANT +UWRAP? +0 1- MAX-UINT = CONSTANT -UWRAP? + +: GD9 ( n limit start step f result -- ) + >R IF GD8 ELSE 2DROP 2DROP R@ THEN -> R> }T +; + +T{ 0 0 0 USTEP +UWRAP? 256 GD9 +T{ 0 0 0 -USTEP -UWRAP? 1 GD9 +T{ 0 MIN-INT MAX-INT STEP +WRAP? 1 GD9 +T{ 0 MAX-INT MIN-INT -STEP -WRAP? 1 GD9 + +\ ------------------------------------------------------------------------------ +TESTING DO +LOOP with maximum and minimum increments + +: (-MI) MAX-INT DUP NEGATE + 0= IF MAX-INT NEGATE ELSE -32767 THEN ; +(-MI) CONSTANT -MAX-INT + +T{ 0 1 0 MAX-INT GD8 -> 1 }T +T{ 0 -MAX-INT NEGATE -MAX-INT OVER GD8 -> 2 }T + +T{ 0 MAX-INT 0 MAX-INT GD8 -> 1 }T +T{ 0 MAX-INT 1 MAX-INT GD8 -> 1 }T +T{ 0 MAX-INT -1 MAX-INT GD8 -> 2 }T +T{ 0 MAX-INT DUP 1- MAX-INT GD8 -> 1 }T + +T{ 0 MIN-INT 1+ 0 MIN-INT GD8 -> 1 }T +T{ 0 MIN-INT 1+ -1 MIN-INT GD8 -> 1 }T +T{ 0 MIN-INT 1+ 1 MIN-INT GD8 -> 2 }T +T{ 0 MIN-INT 1+ DUP MIN-INT GD8 -> 1 }T + +\ ------------------------------------------------------------------------------ +\ TESTING +LOOP setting I to an arbitrary value + +\ The specification for +LOOP permits the loop index I to be set to any value +\ including a value outside the range given to the corresponding DO. + +\ SET-I is a helper to set I in a DO ... +LOOP to a given value +\ n2 is the value of I in a DO ... +LOOP +\ n3 is a test value +\ If n2=n3 then return n1-n2 else return 1 +: SET-I ( n1 n2 n3 -- n1-n2 | 1 ) + OVER = IF - ELSE 2DROP 1 THEN +; + +: -SET-I ( n1 n2 n3 -- n1-n2 | -1 ) + SET-I DUP 1 = IF NEGATE THEN +; + +: PL1 20 1 DO I 18 I 3 SET-I +LOOP ; +T{ PL1 -> 1 2 3 18 19 }T +: PL2 20 1 DO I 20 I 2 SET-I +LOOP ; +T{ PL2 -> 1 2 }T +: PL3 20 5 DO I 19 I 2 SET-I DUP 1 = IF DROP 0 I 6 SET-I THEN +LOOP ; +T{ PL3 -> 5 6 0 1 2 19 }T +: PL4 20 1 DO I MAX-INT I 4 SET-I +LOOP ; +T{ PL4 -> 1 2 3 4 }T +: PL5 -20 -1 DO I -19 I -3 -SET-I +LOOP ; +T{ PL5 -> -1 -2 -3 -19 -20 }T +: PL6 -20 -1 DO I -21 I -4 -SET-I +LOOP ; +T{ PL6 -> -1 -2 -3 -4 }T +: PL7 -20 -1 DO I MIN-INT I -5 -SET-I +LOOP ; +T{ PL7 -> -1 -2 -3 -4 -5 }T +: PL8 -20 -5 DO I -20 I -2 -SET-I DUP -1 = IF DROP 0 I -6 -SET-I THEN +LOOP ; +T{ PL8 -> -5 -6 0 -1 -2 -20 }T + +\ ------------------------------------------------------------------------------ +TESTING multiple RECURSEs in one colon definition + +: ACK ( m n -- u ) \ Ackermann function, from Rosetta Code + OVER 0= IF NIP 1+ EXIT THEN \ ack(0, n) = n+1 + SWAP 1- SWAP ( -- m-1 n ) + DUP 0= IF 1+ RECURSE EXIT THEN \ ack(m, 0) = ack(m-1, 1) + 1- OVER 1+ SWAP RECURSE RECURSE \ ack(m, n) = ack(m-1, ack(m,n-1)) +; + +T{ 0 0 ACK -> 1 }T +T{ 3 0 ACK -> 5 }T +T{ 2 4 ACK -> 11 }T + +\ ------------------------------------------------------------------------------ +TESTING multiple ELSE's in an IF statement +\ Discussed on comp.lang.forth and accepted as valid ANS Forth + +: MELSE IF 1 ELSE 2 ELSE 3 ELSE 4 ELSE 5 THEN ; +T{ 0 MELSE -> 2 4 }T +T{ -1 MELSE -> 1 3 5 }T + +\ ------------------------------------------------------------------------------ +TESTING manipulation of >IN in interpreter mode + +T{ 12345 DEPTH OVER 9 < 34 AND + 3 + >IN ! -> 12345 2345 345 45 5 }T +T{ 14145 8115 ?DUP 0= 34 AND >IN +! TUCK MOD 14 >IN ! GCD CALCULATION -> 15 }T + +\ ------------------------------------------------------------------------------ +TESTING IMMEDIATE with CONSTANT VARIABLE and CREATE [ ... DOES> ] + +T{ 123 CONSTANT IW1 IMMEDIATE IW1 -> 123 }T +T{ : IW2 IW1 LITERAL ; IW2 -> 123 }T +T{ VARIABLE IW3 IMMEDIATE 234 IW3 ! IW3 @ -> 234 }T +T{ : IW4 IW3 [ @ ] LITERAL ; IW4 -> 234 }T +T{ :NONAME [ 345 ] IW3 [ ! ] ; DROP IW3 @ -> 345 }T +T{ CREATE IW5 456 , IMMEDIATE -> }T +T{ :NONAME IW5 [ @ IW3 ! ] ; DROP IW3 @ -> 456 }T +T{ : IW6 CREATE , IMMEDIATE DOES> @ 1+ ; -> }T +T{ 111 IW6 IW7 IW7 -> 112 }T +T{ : IW8 IW7 LITERAL 1+ ; IW8 -> 113 }T +T{ : IW9 CREATE , DOES> @ 2 + IMMEDIATE ; -> }T +: FIND-IW BL WORD FIND NIP ; ( -- 0 | 1 | -1 ) +T{ 222 IW9 IW10 FIND-IW IW10 -> -1 }T \ IW10 is not immediate +T{ IW10 FIND-IW IW10 -> 224 1 }T \ IW10 becomes immediate + +\ ------------------------------------------------------------------------------ +TESTING that IMMEDIATE doesn't toggle a flag + +VARIABLE IT1 0 IT1 ! +: IT2 1234 IT1 ! ; IMMEDIATE IMMEDIATE +T{ : IT3 IT2 ; IT1 @ -> 1234 }T + +\ ------------------------------------------------------------------------------ +TESTING parsing behaviour of S" ." and ( +\ which should parse to just beyond the terminating character no space needed + +T{ : GC5 S" A string"2DROP ; GC5 -> }T +T{ ( A comment)1234 -> 1234 }T +T{ : PB1 CR ." You should see 2345: "." 2345"( A comment) CR ; PB1 -> }T + +\ ------------------------------------------------------------------------------ +TESTING number prefixes # $ % and 'c' character input +\ Adapted from the Forth 200X Draft 14.5 document + +VARIABLE OLD-BASE +DECIMAL BASE @ OLD-BASE ! +T{ #1289 -> 1289 }T +T{ #-1289 -> -1289 }T +T{ $12eF -> 4847 }T +T{ $-12eF -> -4847 }T +T{ %10010110 -> 150 }T +T{ %-10010110 -> -150 }T +T{ 'z' -> 122 }T +T{ 'Z' -> 90 }T +\ Check BASE is unchanged +T{ BASE @ OLD-BASE @ = -> }T + +\ Repeat in Hex mode +16 OLD-BASE ! 16 BASE ! +T{ #1289 -> 509 }T +T{ #-1289 -> -509 }T +T{ $12eF -> 12EF }T +T{ $-12eF -> -12EF }T +T{ %10010110 -> 96 }T +T{ %-10010110 -> -96 }T +T{ 'z' -> 7a }T +T{ 'Z' -> 5a }T +\ Check BASE is unchanged +T{ BASE @ OLD-BASE @ = -> }T \ 2 + +DECIMAL +\ Check number prefixes in compile mode +T{ : nmp #8327 $-2cbe %011010111 ''' ; nmp -> 8327 -11454 215 39 }T + +\ ------------------------------------------------------------------------------ +TESTING definition names +\ should support {1..31} graphical characters +: !"#$%&'()*+,-./0123456789:;<=>? 1 ; +T{ !"#$%&'()*+,-./0123456789:;<=>? -> 1 }T +: @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^ 2 ; +T{ @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^ -> 2 }T +: _`abcdefghijklmnopqrstuvwxyz{|} 3 ; +T{ _`abcdefghijklmnopqrstuvwxyz{|} -> 3 }T +: _`abcdefghijklmnopqrstuvwxyz{|~ 4 ; \ Last character different +T{ _`abcdefghijklmnopqrstuvwxyz{|~ -> 4 }T +T{ _`abcdefghijklmnopqrstuvwxyz{|} -> 3 }T + +\ ------------------------------------------------------------------------------ +TESTING FIND with a zero length string and a non-existent word + +CREATE EMPTYSTRING 0 C, +: EMPTYSTRING-FIND-CHECK ( c-addr 0 | xt 1 | xt -1 -- t|f ) + DUP IF ." FIND returns a TRUE value for an empty string!" CR THEN + 0= SWAP EMPTYSTRING = = ; +T{ EMPTYSTRING FIND EMPTYSTRING-FIND-CHECK -> }T + +CREATE NON-EXISTENT-WORD \ Same as in exceptiontest.fth + 15 C, CHAR $ C, CHAR $ C, CHAR Q C, CHAR W C, CHAR E C, CHAR Q C, + CHAR W C, CHAR E C, CHAR Q C, CHAR W C, CHAR E C, CHAR R C, CHAR T C, + CHAR $ C, CHAR $ C, +T{ NON-EXISTENT-WORD FIND -> NON-EXISTENT-WORD 0 }T + +\ ------------------------------------------------------------------------------ +TESTING IF ... BEGIN ... REPEAT (unstructured) + +T{ : UNS1 DUP 0 > IF 9 SWAP BEGIN 1+ DUP 3 > IF EXIT THEN REPEAT ; -> }T +T{ -6 UNS1 -> -6 }T +T{ 1 UNS1 -> 9 4 }T + +\ ------------------------------------------------------------------------------ +TESTING DOES> doesn't cause a problem with a CREATEd address + +: MAKE-2CONST DOES> 2@ ; +T{ CREATE 2K 3 , 2K , MAKE-2CONST 2K -> ' 2K >BODY 3 }T + +\ ------------------------------------------------------------------------------ +TESTING ALLOT ( n -- ) where n <= 0 + +T{ HERE 5 ALLOT -5 ALLOT HERE = -> }T +T{ HERE 0 ALLOT HERE = -> }T + +\ ------------------------------------------------------------------------------ + +CR .( End of additional Core tests) CR