Files
LithosAnanake/docs/v4.0.0/POST79.md
T
rajamesandClaude Opus 5.5 f9c034cadd feat(v4.0.0): a node looks before it writes; two neighbours no longer stop each other
MESH.md step 4, the fault found there, as ruled (section 7a): a node
writes only to a neighbour that is reading, keeps what it takes in
meanwhile, and loses and counts what it has no room for.

Engine: two more addresses after a node's ports -- which ports have a
neighbour waiting to write to it, which to read from it. Nucleus: (GATE)
before every message; the messages waiting, a ring of 400 cells, dealt
with when the node is idle. Of two neighbours the lower number may wait
to write (ruled after it was built); NEIGHBOUR tells a node who is on
each port.

test_host_mesh.c, 44 checks: the case that stopped the nodes passes; six
messages from each node to each at once all arrive; 800 at once, the
nodes come to rest and every message arrived or was counted (287 arrived,
714 of all kinds let go). test_fabric.c: the two looks. Both widths,
ASan+UBSan.

POST: twelve cases handed HERE, a cell address on v4, to words that take
a byte address, and so wrote into or read from the nucleus's code at cell
HERE/4. Ruled: left out, marked OPEN, until HERE and the byte words are
made to agree as its own step. POST is 538 cases.

hosted-check on three ISAs, 538/538. Bare metal: logs/20261006-134817
(amd64), -135044 (aarch64), -135440 (riscv64).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 13:56:57 -04:00

206 lines
22 KiB
Markdown

# POST for the FORTH-79 Required Word Set: where it departs from v3
Written by `v4/tools/mkpost.py` from `v4/tools/post79_rules.py`; do not edit.
Design: `NUCLEUS.md` section 6. The capsule is `capsules/v4/post79.4th`.
POST runs 538 cases. 431 are v3's, with what the hosted v3 binary did as the
expected result. This file lists every other case, and why.
## 1. Rewritten for FORTH-79 (59)
v3 departs from the standard, or the case is written for v3's machine. v4
follows the standard (standing ruling), so the expected result is the
standard's and not v3's.
| Case | v3's line | What v3 did | As POST runs it | Must do | Why |
|---|---|---|---|---|---|
| `PICK.pick_0` | `1 2 3 0 PICK . CR` | stack `1 2 3`, printed `3 \n` | unchanged | an error | FORTH-79: PICK and ROLL count from 1; v3 counts from 0; 0 PICK is an error |
| `PICK.pick_1` | `1 2 3 1 PICK . CR` | stack `1 2 3`, printed `2 \n` | unchanged | stack `1 2 3`, prints `3 \n` | FORTH-79: PICK and ROLL count from 1; v3 counts from 0 |
| `PICK.pick_2` | `1 2 3 2 PICK . CR` | stack `1 2 3`, printed `1 \n` | unchanged | stack `1 2 3`, prints `2 \n` | FORTH-79: PICK and ROLL count from 1; v3 counts from 0 |
| `ROLL.roll_1` | `1 2 3 1 ROLL . . . CR` | stack `empty`, printed `1 3 2 \n` | unchanged | stack `empty`, prints `3 2 1 \n` | FORTH-79: PICK and ROLL count from 1; v3 counts from 0 |
| `>R.basic` | `42 >R R@ . R> . CR` | stack `empty`, printed `42 42 \n` | `: RS1 42 >R R@ . R> . CR ; RS1` | stack `empty`, prints `42 42 \n` | FORTH-79: >R R> R@ are for use inside a definition; v4 refuses them at the prompt |
| `>R.zero` | `0 >R R@ . R> . CR` | stack `empty`, printed `0 0 \n` | `: RS2 0 >R R@ . R> . CR ; RS2` | stack `empty`, prints `0 0 \n` | FORTH-79: >R R> R@ are for use inside a definition; v4 refuses them at the prompt |
| `>R.negative` | `-123 >R R@ . R> . CR` | stack `empty`, printed `-123 -123 \n` | `: RS3 -123 >R R@ . R> . CR ; RS3` | stack `empty`, prints `-123 -123 \n` | FORTH-79: >R R> R@ are for use inside a definition; v4 refuses them at the prompt |
| `>R.multiple` | `1 2 >R >R R@ . R> . R@ . R> . CR` | stack `empty`, printed `1 1 2 2 \n` | `: RS4 1 2 >R >R R@ . R> . R@ . R> . CR ; RS4` | stack `empty`, prints `1 1 2 2 \n` | FORTH-79: >R R> R@ are for use inside a definition; v4 refuses them at the prompt |
| `R>.basic` | `42 >R R> . CR` | stack `empty`, printed `42 \n` | `: RS5 42 >R R> . CR ; RS5` | stack `empty`, prints `42 \n` | FORTH-79: >R R> R@ are for use inside a definition; v4 refuses them at the prompt |
| `R>.lifo_order` | `1 2 >R >R R> . R> . CR` | stack `empty`, printed `1 2 \n` | `: RS6 1 2 >R >R R> . R> . CR ; RS6` | stack `empty`, prints `1 2 \n` | FORTH-79: >R R> R@ are for use inside a definition; v4 refuses them at the prompt |
| `R@.basic` | `42 >R R@ . R> DROP CR` | stack `empty`, printed `42 \n` | `: RS7 42 >R R@ . R> DROP CR ; RS7` | stack `empty`, prints `42 \n` | FORTH-79: >R R> R@ are for use inside a definition; v4 refuses them at the prompt |
| `R@.non_destructive` | `99 >R R@ R@ = . R> DROP CR` | stack `empty`, printed `-1 \n` | `: RS8 99 >R R@ R@ = . R> DROP CR ; RS8` | stack `empty`, prints `-1 \n` | FORTH-79: >R R> R@ are for use inside a definition; v4 refuses them at the prompt |
| `,.basic` | `42 , HERE 8 - @ . CR` | stack `empty`, printed `42 \n` | `42 , HERE 1 - @ . CR` | stack `empty`, prints `42 \n` | v3's address unit is a byte; a v4 address unit is a cell (D-1) |
| `,.negative` | `-999 , HERE 8 - @ . CR` | stack `empty`, printed `-999 \n` | `-999 , HERE 1 - @ . CR` | stack `empty`, prints `-999 \n` | v3's address unit is a byte; a v4 address unit is a cell (D-1) |
| `+!.basic` | `10 HERE ! 5 HERE +! HERE @ . CR` | error | unchanged | stack `empty`, prints `15 \n` | v3 raises an error FORTH-79 does not ask for: a store to HERE |
| `+!.by_zero` | `42 HERE ! 0 HERE +! HERE @ . CR` | error | unchanged | stack `empty`, prints `42 \n` | v3 raises an error FORTH-79 does not ask for: a store to HERE |
| `+!.negative` | `10 HERE ! -3 HERE +! HERE @ . CR` | error | unchanged | stack `empty`, prints `7 \n` | v3 raises an error FORTH-79 does not ask for: a store to HERE |
| `+!.accumulate` | `0 HERE ! 1 HERE +! 2 HERE +! 3 HERE +! HERE @ . CR` | error | unchanged | stack `empty`, prints `6 \n` | v3 raises an error FORTH-79 does not ask for: a store to HERE |
| `HERE.after_comma~2` | `HERE 42 , HERE SWAP - 1 CELLS = 0 SWAP /` | error | unchanged | stack `0`, prints nothing | the case divides by zero unless HERE moved by one cell; on v3 it had moved by 8 |
| `MOVE.basic` | `HERE 65 OVER C! HERE 1+ 66 OVER C! HERE HERE 16 + 2 MOVE HERE 16 + C@ . HERE 17 + C@ . CR` | stack `302 303`, printed `65 66 \n` | `65 HERE ! 66 HERE 1+ ! HERE HERE 16 + 2 MOVE HERE 16 + @ . HERE 17 + @ . CR` | stack `empty`, prints `65 66 \n` | FORTH-79: MOVE moves cells; and v3's address unit is a byte; a v4 address unit is a cell (D-1) |
| `BASE.base_store` | `16 BASE ! 255 . CR` | stack `empty`, printed `597 \n` | unchanged | stack `empty`, prints `255 \n` | 255 read in base 16 and printed in base 16 is 255; v3 printed 467 |
| `<#.basic` | `DECIMAL 42 S>D <# #S #> TYPE CR` | stack `empty`, printed `774763251095801167872\n` | unchanged | stack `empty`, prints `42\n` | v3 prints 774763251095801167872 for 42 S>D <# #S #> |
| `<#.empty` | `0 <# #> TYPE CR` | stack `0`, printed `\n` | `0 0 <# #> TYPE CR` | stack `empty`, prints `\n` | FORTH-79: <# # #S #> work on a double number; v3 takes a single |
| `<#.negative` | `-42 <# #S #> TYPE CR` | stack `empty`, printed `42\n` | `-42 DUP ABS 0 <# #S ROT SIGN #> TYPE CR` | stack `empty`, prints `-42\n` | FORTH-79: <# # #S #> work on a double number; v3 takes a single |
| `#.single_digit` | `15 <# # #> TYPE CR` | stack `empty`, printed `5\n` | `15 0 <# # #> TYPE CR` | stack `empty`, prints `5\n` | FORTH-79: <# # #S #> work on a double number; v3 takes a single |
| `#.multiple` | `15 <# # # #> TYPE CR` | stack `empty`, printed `15\n` | `15 0 <# # # #> TYPE CR` | stack `empty`, prints `15\n` | FORTH-79: <# # #S #> work on a double number; v3 takes a single |
| `#.zero_pad` | `5 <# # 0 # #> TYPE CR` | stack `0`, printed `05\n` | `5 0 <# # # #> TYPE CR` | stack `empty`, prints `05\n` | FORTH-79: <# # #S #> work on a double number; v3 takes a single |
| `#S.basic` | `42 <# #S #> TYPE CR` | stack `empty`, printed `42\n` | `42 0 <# #S #> TYPE CR` | stack `empty`, prints `42\n` | FORTH-79: <# # #S #> work on a double number; v3 takes a single |
| `#S.zero` | `0 <# #S #> TYPE CR` | stack `empty`, printed `0\n` | `0 0 <# #S #> TYPE CR` | stack `empty`, prints `0\n` | FORTH-79: <# # #S #> work on a double number; v3 takes a single |
| `#S.large` | `1234567890 <# #S #> TYPE CR` | stack `empty`, printed `1234567890\n` | `1234567890 0 <# #S #> TYPE CR` | stack `empty`, prints `1234567890\n` | FORTH-79: <# # #S #> work on a double number; v3 takes a single |
| `SIGN.negative` | `-42 ABS <# #S SIGN #> TYPE CR` | stack `0`, printed `42\n` | `-42 DUP ABS 0 <# #S ROT SIGN #> TYPE CR` | stack `empty`, prints `-42\n` | FORTH-79: <# # #S #> work on a double number; v3 takes a single |
| `SIGN.positive` | `42 <# #S SIGN #> TYPE CR` | stack `0`, printed `42\n` | `42 DUP ABS 0 <# #S ROT SIGN #> TYPE CR` | stack `empty`, prints `42\n` | FORTH-79: <# # #S #> work on a double number; v3 takes a single |
| `SIGN.zero` | `0 <# #S SIGN #> TYPE CR` | stack `0`, printed `0\n` | `0 DUP ABS 0 <# #S ROT SIGN #> TYPE CR` | stack `empty`, prints `0\n` | FORTH-79: <# # #S #> work on a double number; v3 takes a single |
| `#>.normal` | `42 <# #S #> TYPE CR` | stack `empty`, printed `42\n` | `42 0 <# #S #> TYPE CR` | stack `empty`, prints `42\n` | FORTH-79: <# # #S #> work on a double number; v3 takes a single |
| `#>.empty` | `0 <# #> TYPE CR` | stack `0`, printed `\n` | `0 0 <# #> TYPE CR` | stack `empty`, prints `\n` | FORTH-79: <# # #S #> work on a double number; v3 takes a single |
| `#>.stack_effect` | `42 <# #S #> SWAP . . CR` | stack `empty`, printed `24 2 \n` | `42 0 <# #S #> SWAP DROP . CR` | stack `empty`, prints `2 \n` | FORTH-79: <# # #S #> work on a double number; v3 takes a single |
| `HOLD.basic` | `42 <# 46 HOLD #S #> TYPE CR` | stack `empty`, printed `42.\n` | `42 0 <# 46 HOLD #S #> TYPE CR` | stack `empty`, prints `42.\n` | FORTH-79: <# # #S #> work on a double number; v3 takes a single |
| `COUNT.basic` | `HERE S" Test" DROP COUNT . . CR` | stack `302`, printed `84 303 \n` | `4 PAD C! PAD COUNT . PAD - . CR` | stack `empty`, prints `4 1 \n` | v3's address unit is a byte; a v4 address unit is a cell (D-1); and S" is not FORTH-79 |
| `COUNT.empty` | `HERE 0 OVER C! COUNT . . CR` | stack `empty`, printed `0 308 \n` | `0 PAD C! PAD COUNT . PAD - . CR` | stack `empty`, prints `0 1 \n` | v3's address unit is a byte; a v4 address unit is a cell (D-1) |
| `COUNT.max_length` | `HERE 255 OVER C! COUNT . . CR` | stack `empty`, printed `255 308 \n` | `255 PAD C! PAD COUNT . PAD - . CR` | stack `empty`, prints `255 1 \n` | v3's address unit is a byte; a v4 address unit is a cell (D-1) |
| `COUNT.basic~2` | `HERE S" Test" DROP C@ HERE 1+ SWAP COUNT . . CR` | stack `412 418`, printed `0 85 \n` | `4 PAD C! PAD COUNT . PAD - . CR` | stack `empty`, prints `4 1 \n` | v3's address unit is a byte; a v4 address unit is a cell (D-1) |
| `COUNT.empty~2` | `HERE 0 OVER C! COUNT . . CR` | stack `empty`, printed `0 418 \n` | `0 PAD C! PAD COUNT . PAD - . CR` | stack `empty`, prints `0 1 \n` | v3's address unit is a byte; a v4 address unit is a cell (D-1) |
| `COUNT.max_length~2` | `HERE 255 OVER C! COUNT . . CR` | stack `empty`, printed `255 418 \n` | `255 PAD C! PAD COUNT . PAD - . CR` | stack `empty`, prints `255 1 \n` | v3's address unit is a byte; a v4 address unit is a cell (D-1) |
| `CMOVE.basic` | `HERE S" Test" DUP >R HERE 10 + SWAP CMOVE CR` | stack `325`, printed `\n` | `65 PAD C! 66 PAD 1+ C! PAD PAD 10 + 2 CMOVE PAD 10 + C@ . PAD 11 + C@ . CR` | stack `empty`, prints `65 66 \n` | v3's address unit is a byte; a v4 address unit is a cell (D-1); and the v3 case leaves a value on the return stack |
| `TYPE.basic_string` | `HERE S" Hello" DUP >R HERE SWAP CMOVE HERE R> TYPE CR` | stack `400`, printed `Hello\n` | `72 PAD C! 105 PAD 1+ C! PAD 2 TYPE CR` | stack `empty`, prints `Hi\n` | v3's address unit is a byte; a v4 address unit is a cell (D-1); and FORTH-79: >R R> R@ are for use inside a definition; v4 refuses them at the prompt |
| `TYPE.numbers` | `HERE S" 12345" DUP >R HERE SWAP CMOVE HERE R> TYPE CR` | stack `406`, printed `12345\n` | `49 PAD C! 50 PAD 1+ C! PAD 2 TYPE CR` | stack `empty`, prints `12\n` | v3's address unit is a byte; a v4 address unit is a cell (D-1); and FORTH-79: >R R> R@ are for use inside a definition; v4 refuses them at the prompt |
| `>IN.initial` | `>IN @ . CR` | stack `empty`, printed `1009040112 \n` | unchanged | stack `empty`, prints `9 \n` | FORTH-79: >IN is the offset into the input, 9 here; v3 prints an address |
| `UPDATE.no_block` | `0 SCR ! UPDATE` | error | unchanged | stack `empty`, prints nothing | v3 raises an error FORTH-79 does not ask for |
| `SCR.after_load` | `1 LOAD SCR @ . CR` | stack `empty`, printed `` | unchanged | stack `empty`, prints `1 \n` | v3 prints nothing after 1 LOAD; SCR is still 1 from the LIST before |
| `FIND.existing` | `FIND DUP . CR` | stack `empty`, printed `1009039472 \n` | unchanged | 0 value(s) left; output not compared | FORTH-79: FIND takes the next word, DUP here, and leaves its address, which is printed |
| `FIND.user_word` | `: test5 44 ; FIND test5 . CR` | stack `empty`, printed `1009366512 \n` | unchanged | 0 value(s) left; output not compared | the address FIND leaves is printed |
| `FIND.empty` | `FIND` | error | unchanged | stack `0`, prints nothing | FORTH-79: FIND leaves 0 when there is no word; v3 raises an error |
| `VOCABULARY.cross_vocab_access` | `VOCABULARY V1 V1 DEFINITIONS : V1WORD 11 ; FORTH V1WORD . CR` | stack `empty`, printed `11 \n` | unchanged | an error | FORTH-79: a word defined in another vocabulary is not found from FORTH; v3 finds it |
| `VOCABULARY.duplicate` | `VOCABULARY TESTVOC VOCABULARY TESTVOC` | error | unchanged | stack `empty`, prints nothing | v3 raises an error FORTH-79 does not ask for: defining a name again |
| `IF.true` | `: TEST1 IF 42 ELSE 24 THEN ; -1 TEST1 . CR` | stack `empty`, printed `42 \n` | unchanged | stack `empty`, prints `42 \n` | v3 runs an older TEST1 from another vocabulary and leaves the flag |
| `IF.false` | `: TEST2 IF 42 ELSE 24 THEN ; 0 TEST2 . CR` | stack `empty`, printed `24 \n` | unchanged | stack `empty`, prints `24 \n` | v3 runs an older TEST2 from another vocabulary and leaves the flag |
| `LEAVE.basic` | `: TLV 0 5 0 DO I 3 = IF LEAVE THEN 1+ LOOP ; TLV . CR` | stack `empty`, printed `3 \n` | unchanged | stack `empty`, prints `4 \n` | FORTH-79: LEAVE ends the loop at the next LOOP; v3 jumps out at once |
| `LEAVE.at_start` | `: TLV2 0 5 0 DO LEAVE 1+ LOOP ; TLV2 . CR` | stack `empty`, printed `0 \n` | unchanged | stack `empty`, prints `1 \n` | FORTH-79: LEAVE ends the loop at the next LOOP; v3 jumps out at once |
| `LEAVE.qdloop` | `: TLV3 0 5 0 ?DO I 2 = IF LEAVE THEN 1+ LOOP ; TLV3 . CR` | stack `empty`, printed `2 \n` | unchanged | stack `empty`, prints `3 \n` | FORTH-79: LEAVE ends the loop at the next LOOP; v3 jumps out at once |
## 2. Address-dependent (20)
The case leaves or prints a memory address, which is a different number on
the two machines. The number of values left is checked, and what is
printed unless an address is printed; the values are not.
| Case | Line | Checked |
|---|---|---|
| `-TRAILING.basic` | `HERE S" Test " -TRAILING TYPE CR` | values left, and output |
| `-TRAILING.all_spaces` | `HERE S" " -TRAILING TYPE CR` | values left, and output |
| `-TRAILING.no_spaces` | `HERE S" Test" -TRAILING TYPE CR` | values left, and output |
| `HERE.stability` | `HERE DUP HERE = . CR` | values left, and output |
| `PAD.stability` | `PAD DUP PAD = . CR` | values left, and output |
| `UPDATE.basic` | `1 BLOCK UPDATE` | values left, and output |
| `UPDATE.multiple` | `1 BLOCK UPDATE UPDATE` | values left, and output |
| `SAVE-BUFFERS.dirty_blocks` | `1 BLOCK UPDATE SAVE-BUFFERS` | values left, and output |
| `EMPTY-BUFFERS.after_use` | `1 BLOCK EMPTY-BUFFERS` | values left, and output |
| `EMPTY-BUFFERS.dirty_blocks` | `1 BLOCK UPDATE EMPTY-BUFFERS` | values left, and output |
| `BUFFER.flush_dirty` | `2 BLOCK 1+ 2 BUFFER` | values left, and output |
| `BLOCK.basic` | `1 BLOCK DUP . CR` | values left only |
| `BUFFER.basic` | `1 BUFFER DUP . CR` | values left only |
| `VOCABULARY.create_and_switch` | `VOCABULARY MYVOC MYVOC DEFINITIONS CONTEXT @ . CR` | values left only |
| `CONTEXT.basic` | `CONTEXT @ . CR` | values left only |
| `CONTEXT.initial` | `FORTH CONTEXT @ . CR` | values left only |
| `CURRENT.basic` | `CURRENT @ . CR` | values left only |
| `CURRENT.after_def` | `VOCABULARY TEST-VOC8 TEST-VOC8 DEFINITIONS CURRENT @ . CR` | values left only |
| `LIST.basic` | `1 LIST` | values left only |
| `SCR.after_list` | `1 LIST SCR @ . CR` | values left only |
## 3. Written by hand (28)
For required words v3 has no case for. The expected results are the
standard's; no v3 run stands behind them.
| Case | Line | Must do |
|---|---|---|
| `U*.small` | `3 4 U* . . CR` | stack `empty`, prints `0 12 \n` |
| `U*.zero` | `0 5 U* . . CR` | stack `empty`, prints `0 0 \n` |
| `U*.full` | `-1 -1 U* 2+ . 1 = . CR` | stack `empty`, prints `0 -1 \n` |
| `U/MOD.small` | `7 0 2 U/MOD . . CR` | stack `empty`, prints `3 1 \n` |
| `U/MOD.exact` | `12 0 4 U/MOD . . CR` | stack `empty`, prints `3 0 \n` |
| `U/MOD.double` | `0 1 2 U/MOD 2* . . CR` | stack `empty`, prints `0 0 \n` |
| `U/MOD.inverse` | `-1 -1 U* -1 U/MOD 1+ . . CR` | stack `empty`, prints `0 0 \n` |
| `U/MOD.carry` | `-1 -2 -1 U/MOD 1+ . 2+ . CR` | stack `empty`, prints `0 0 \n` |
| `U/MOD.by_zero` | `1 0 0 U/MOD` | an error |
| `?.basic` | `VARIABLE Q1 42 Q1 ! Q1 ? CR` | stack `empty`, prints `42 \n` |
| `EXECUTE.found` | `: E1 7 ; FIND E1 EXECUTE . CR` | stack `empty`, prints `7 \n` |
| `U..small` | `42 U. CR` | stack `empty`, prints `42 \n` |
| `U..unsigned` | `-1 U. CR` | stack `empty`, prints `18446744073709551615 \n` |
| `CONVERT.digits` | `: C1 0 0 BL WORD CONVERT DROP ; C1 123 . . CR` | stack `empty`, prints `0 123 \n` |
| `'.found` | `' DUP 0= . CR` | stack `empty`, prints `0 \n` |
| `.".in_definition` | `: Q3 ." hi there" ; Q3 CR` | stack `empty`, prints `hi there\n` |
| `LITERAL.basic` | `: Q4 [ 5 ] LITERAL ; Q4 . CR` | stack `empty`, prints `5 \n` |
| `STATE.interpreting` | `STATE @ . CR` | stack `empty`, prints `0 \n` |
| `STATE.compiling` | `: Q5 STATE @ 0= . ; IMMEDIATE : Q6 Q5 ; CR` | stack `empty`, prints `0 \n` |
| `COMPILE.basic` | `: Q7 COMPILE DUP ; IMMEDIATE : Q8 Q7 ; 3 Q8 . . CR` | stack `empty`, prints `3 3 \n` |
| `[COMPILE].basic` | `: Q9 [COMPILE] IF ; IMMEDIATE : Q10 Q9 1 ELSE 2 THEN ; 0 Q10 . -1 Q10 . CR` | stack `empty`, prints `2 1 \n` |
| `(.comment` | `1 ( 2 ) 3 . . CR` | stack `empty`, prints `3 1 \n` |
| `BLK.terminal` | `BLK @ . CR` | stack `empty`, prints `0 \n` |
| `79-STANDARD.present` | `79-STANDARD` | stack `empty`, prints nothing |
| `WORD.next_word` | `: W1 BL WORD COUNT TYPE ; W1 HELLO` | stack `empty`, prints `HELLO` |
| `WORD.delimiter` | `: W2 44 WORD COUNT TYPE ; W2 A B,` | stack `empty`, prints `A B` |
| `WORD.count` | `: W3 BL WORD C@ . ; W3 ABC` | stack `empty`, prints `3 ` |
| `WORD.skips_leading` | `: W4 BL WORD COUNT TYPE ; W4 X` | stack `empty`, prints `X` |
## 4. v3 cases left out (39)
| Case | Why |
|---|---|
| `EXPECT.zero_length` | reads the keyboard |
| `EXPECT.one_item` | reads the keyboard |
| `EXPECT.empty_stack` | reads the keyboard |
| `FORGET.nonexistent` | forgets a word of the system |
| `FORGET.protected` | forgets a word of the system |
| `CONTEXT.modify` | damages the system on purpose |
| `CURRENT.protect` | damages the system on purpose |
| `QUIT.in_definition` | v3 did not get through it in one session |
| `:.nested` | v3 did not get through it in one session |
| `].basic` | v3 did not get through it in one session |
| `ELSE.double` | v3 did not get through it in one session |
| `THEN.extra` | v3 did not get through it in one session |
| `C!.basic` | OPEN: HERE is a cell address on v4 and this word takes a byte address (D-1): the case wrote to or read from the nucleus's code at cell HERE/4 |
| `C!.zero` | OPEN: HERE is a cell address on v4 and this word takes a byte address (D-1): the case wrote to or read from the nucleus's code at cell HERE/4 |
| `C!.high_byte` | OPEN: HERE is a cell address on v4 and this word takes a byte address (D-1): the case wrote to or read from the nucleus's code at cell HERE/4 |
| `C!.truncation` | OPEN: HERE is a cell address on v4 and this word takes a byte address (D-1): the case wrote to or read from the nucleus's code at cell HERE/4 |
| `C@.after_cstore` | OPEN: HERE is a cell address on v4 and this word takes a byte address (D-1): the case wrote to or read from the nucleus's code at cell HERE/4 |
| `C@.zero_byte` | OPEN: HERE is a cell address on v4 and this word takes a byte address (D-1): the case wrote to or read from the nucleus's code at cell HERE/4 |
| `FILL.basic` | OPEN: HERE is a cell address on v4 and this word takes a byte address (D-1): the case wrote to or read from the nucleus's code at cell HERE/4 |
| `FILL.zero_byte` | OPEN: HERE is a cell address on v4 and this word takes a byte address (D-1): the case wrote to or read from the nucleus's code at cell HERE/4 |
| `COUNT.string_bounds` | OPEN: HERE is a cell address on v4 and this word takes a byte address (D-1): the case wrote to or read from the nucleus's code at cell HERE/4 |
| `CMOVE.overlap` | OPEN: HERE is a cell address on v4 and this word takes a byte address (D-1): the case wrote to or read from the nucleus's code at cell HERE/4 |
| `CMOVE.bounds` | moves 1000 bytes over the system; v3 refuses by a bounds rule FORTH-79 has not got |
| `TYPE.single_char` | OPEN: HERE is a cell address on v4 and this word takes a byte address (D-1): the case wrote to or read from the nucleus's code at cell HERE/4 |
| `COUNT.zero_addr_plus_one` | OPEN: HERE is a cell address on v4 and this word takes a byte address (D-1): the case wrote to or read from the nucleus's code at cell HERE/4 |
| `WORD.empty_input` | v3's WORD does not take the next word from the input, as FORTH-79's does; see the WORD cases written by hand |
| `WORD.space_delim` | v3's WORD does not take the next word from the input, as FORTH-79's does; see the WORD cases written by hand |
| `WORD.newline_delim` | v3's WORD does not take the next word from the input, as FORTH-79's does; see the WORD cases written by hand |
| `WORD.tab_delim` | v3's WORD does not take the next word from the input, as FORTH-79's does; see the WORD cases written by hand |
| `WORD.comma_delim` | v3's WORD does not take the next word from the input, as FORTH-79's does; see the WORD cases written by hand |
| `WORD.skip_leading` | v3's WORD does not take the next word from the input, as FORTH-79's does; see the WORD cases written by hand |
| `WORD.single_char` | v3's WORD does not take the next word from the input, as FORTH-79's does; see the WORD cases written by hand |
| `WORD.long_word` | v3's WORD does not take the next word from the input, as FORTH-79's does; see the WORD cases written by hand |
| `WORD.zero_delim` | v3's WORD does not take the next word from the input, as FORTH-79's does; see the WORD cases written by hand |
| `WORD.high_ascii` | v3's WORD does not take the next word from the input, as FORTH-79's does; see the WORD cases written by hand |
| `WORD.count_format` | v3's WORD does not take the next word from the input, as FORTH-79's does; see the WORD cases written by hand |
| `WORD.count_value` | v3's WORD does not take the next word from the input, as FORTH-79's does; see the WORD cases written by hand |
| `WORD.multi_delim` | v3's WORD does not take the next word from the input, as FORTH-79's does; see the WORD cases written by hand |
| `PAD.usable` | OPEN: PAD 42 OVER ! faults on v4 -- PAD is a byte address and ! takes a cell address (D-1) |
## 5. Required words POST does not test
`KEY` `EXPECT` `QUERY` `QUIT`.
`KEY`, `EXPECT` and `QUERY` wait for the keyboard, which a boot cannot type
at. `QUIT` returns to the terminal without `ok`, which the capsule loader
takes for a refused line.
## 6. Where v3 did not do what its own table expects (6)
POST expects what v3 did, unless section 1 says otherwise.
| Case | |
|---|---|
| `+!.basic` | v3's table says no error, v3 raised one |
| `+!.by_zero` | v3's table says no error, v3 raised one |
| `+!.negative` | v3's table says no error, v3 raised one |
| `+!.accumulate` | v3's table says no error, v3 raised one |
| `HERE.after_comma~2` | v3's table says no error, v3 raised one |
| `CREATE.long_name` | v3's table says error, v3 raised none |