feat(v4): the system hands no GONE on; (GONE-HOOK) goes (MESH step 7, increment 2)

Ruling 7 as amended: the kernel tells a node's going, so the system's
hand-on is not used.  (GONE-HOOK), (DOWN) and (RUN) go from quit.f18, and
COLD's hook-clearing from system.f18; the cell is free again.  The tests of
the hand-on go with it (mesh: the hand-on checks and the fourth disturbed
exchange; depth sweep: path 10, as before 529ba0fc).  A believed GONE going
no further is still checked.  test_host_unit.c's message for GONE down the
graph now says the kernel tells.  MESH.md: 9a.6 items 5 and 7, and step 7's
record of both increments.

Suite EXIT 0; depth sweep 230 runs, 0 failures; mkcapsule lint 0
violations.  Hosted and bare metal, all three ISAs: word_count=317
dict_hash=0xfec8c47cfc6f437f.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-20 13:05:45 -04:00
co-authored by Claude Opus 5.5
parent 9138ebd8bb
commit 6cb8f1285f
9 changed files with 51 additions and 82 deletions
-1
View File
@@ -83,7 +83,6 @@ constant (MSG) 14664
constant (OUT) 14312 constant (OUT) 14312
constant (WORD-DEFINED) 14701 constant (WORD-DEFINED) 14701
constant (WORD-FORGOTTEN) 14700 constant (WORD-FORGOTTEN) 14700
constant (GONE-HOOK) 14691
constant BLOCK# -1 constant BLOCK# -1
constant BUFFER# -2 constant BUFFER# -2
constant UPDATE# -3 constant UPDATE# -3
-1
View File
@@ -83,7 +83,6 @@ constant (MSG) 14664
constant (OUT) 14312 constant (OUT) 14312
constant (WORD-DEFINED) 14701 constant (WORD-DEFINED) 14701
constant (WORD-FORGOTTEN) 14700 constant (WORD-FORGOTTEN) 14700
constant (GONE-HOOK) 14691
constant BLOCK# -1 constant BLOCK# -1
constant BUFFER# -2 constant BUFFER# -2
constant UPDATE# -3 constant UPDATE# -3
+3 -24
View File
@@ -80,39 +80,19 @@ macro R-CLEAR RSTACK-DEPTH b! a !b endmacro
OK: drop 1 jump (FINISH) OK: drop 1 jump (FINISH)
GO: drop 0 jump (FINISH) GO: drop 0 jump (FINISH)
\ ( -- ) a GONE has been believed: the word whose xt is in (GONE-HOOK), if
\ there is one, is given the number of the node that is gone, in (ONE), so
\ that the GONE goes on down the birth graph (MESH.md 9a.2, ruling 7;
\ capsules/v4/centre.4th, GONE-DOWN). 0 there, as at switch-on: nothing.
\ The word is called, not jumped to, and (ONE) is put back when it
\ returns: what called this -- AWAIT, with the node it waits on -- reads
\ (ONE) after, and a GONE the word sends writes it. (Found by the depth
\ sweep of MESH.md 9a.6: a word that handed on a GONE about another node
\ left AWAIT waiting for ever.)
\ ( n xt -- ) the word whose xt it is, given n. It returns to whoever
\ called this, as (DEFINED) does (dict.f18).
: (RUN) push ;
: (DOWN)
(GONE-HOOK) b! @b if NONE
drop (ONE) a! @ dup push (GONE-HOOK) b! @b (RUN)
pop (ONE) a! ! ;
NONE: drop ;
\ ( -- flag ) A GONE has been taken: its seven words are in (IN), the \ ( -- flag ) A GONE has been taken: its seven words are in (IN), the
\ node it is about in (ONE), and (S-WIRE) is the wire it came by. It is \ node it is about in (ONE), and (S-WIRE) is the wire it came by. It is
\ believed only if it came by the port that leads to this node's centre \ believed only if it came by the port that leads to this node's centre
\ and says it is from the centre (MESH.md 7b.4): the way to the node is \ and says it is from the centre (MESH.md 7b.4): the way to the node is
\ then forgotten, and the flag is -1. Otherwise nothing is done, and 0. \ then forgotten, and the flag is -1. Otherwise nothing is done, and 0.
\ (As first built only what it said it was from was looked at, and one \ (As first built only what it said it was from was looked at, and one
\ that came by another port was believed.) Believed, it is handed on: \ that came by another port was believed.) A node does not hand a GONE
\ (DOWN). \ on: the kernel tells each node a node's going (MESH.md 9a.2, ruling 7).
: (GONE?) : (GONE?)
(CENTRE) if NOT (IN)+1 a! @ xor if FROM drop 0 ; (CENTRE) if NOT (IN)+1 a! @ xor if FROM drop 0 ;
NOT: ; NOT: ;
FROM: drop (ROUTE-DEFAULT) a! @ (PORT) - (S-WIRE) a! @ xor if YES drop 0 ; FROM: drop (ROUTE-DEFAULT) a! @ (PORT) - (S-WIRE) a! @ xor if YES drop 0 ;
YES: drop (ONE) a! @ NO-ROUTE (DOWN) -1 ; YES: drop (ONE) a! @ NO-ROUTE -1 ;
\ ( -- ) WAITING (MESH.md 7d.4). A node with nothing to do passes on \ ( -- ) WAITING (MESH.md 7d.4). A node with nothing to do passes on
\ what has come for other nodes, (SERVE), and then goes through what has \ what has come for other nodes, (SERVE), and then goes through what has
@@ -440,7 +420,6 @@ set HDR-NFA here ", (LOST) #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here :
set HDR-NFA here ", (REFUSED) #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : (REFUSED)' (REFUSED) ; set HDR-NFA here ", (REFUSED) #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : (REFUSED)' (REFUSED) ;
set HDR-NFA here ", (WORD-DEFINED) #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : (WORD-DEFINED)' (WORD-DEFINED) ; set HDR-NFA here ", (WORD-DEFINED) #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : (WORD-DEFINED)' (WORD-DEFINED) ;
set HDR-NFA here ", (WORD-FORGOTTEN) #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : (WORD-FORGOTTEN)' (WORD-FORGOTTEN) ; set HDR-NFA here ", (WORD-FORGOTTEN) #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : (WORD-FORGOTTEN)' (WORD-FORGOTTEN) ;
set HDR-NFA here ", (GONE-HOOK) #, 8 #, HDR-NFA #, HDR-LINK set HDR-LINK here : (GONE-HOOK)' (GONE-HOOK) ;
set HDR-NFA here ", QUIT #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here set HDR-NFA here ", QUIT #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: QUIT R-CLEAR (RESET) CR 0 jump (DONE) : QUIT R-CLEAR (RESET) CR 0 jump (DONE)
+1 -6
View File
@@ -135,8 +135,7 @@ set HDR-NFA here ", WARM #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
\ ( -- ) the system as it was when the capsule had just been loaded: \ ( -- ) the system as it was when the capsule had just been loaded:
\ everything defined since is gone, there is one vocabulary, numbers are \ everything defined since is gone, there is one vocabulary, numbers are
\ decimal, the block buffers are empty. A word in (GONE-HOOK) that COLD \ decimal, the block buffers are empty. Then as WARM.
\ forgets is taken out of it (quit.f18, (DOWN)). Then as WARM.
set HDR-NFA here ", COLD #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here set HDR-NFA here ", COLD #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
: COLD : COLD
(BOOT) a! @ DP a! ! (BOOT) a! @ DP a! !
@@ -145,10 +144,6 @@ set HDR-NFA here ", COLD #, 0 #, HDR-NFA #, HDR-LINK set HDR-LINK here
(LATEST) CONTEXT a! ! (LATEST) CURRENT a! ! 0 VOC-LINK a! ! (LATEST) CONTEXT a! ! (LATEST) CURRENT a! ! 0 VOC-LINK a! !
10 BASE a! ! 0 SCR a! ! 2 (LOG-LEVEL) a! ! 0 (ACL-HOOK) a! ! EMPTY-BUFFERS 10 BASE a! ! 0 SCR a! ! 2 (LOG-LEVEL) a! ! 0 (ACL-HOOK) a! ! EMPTY-BUFFERS
(BOOT) a! @ 2/ 2/ (FORGOTTEN) \ the kernel's records of what has gone go too (dict.f18) (BOOT) a! @ 2/ 2/ (FORGOTTEN) \ the kernel's records of what has gone go too (dict.f18)
(GONE-HOOK) a! @ (BOOT) b! @b 2/ 2/ inv 1 + + \ the hook's xt less the sealed HERE, in cells
-if CLEAR drop jump KEPT \ below the sealed system: it stays (0 is below)
CLEAR: drop 0 (GONE-HOOK) a! ! \ at or above it: forgotten with what COLD forgets
KEPT:
$54524F46 (EMIT4) $39372D48 (EMIT4) $6C6F4320 (EMIT4) $74532064 (EMIT4) $747261 (EMIT4) CR $54524F46 (EMIT4) $39372D48 (EMIT4) $6C6F4320 (EMIT4) $74532064 (EMIT4) $747261 (EMIT4) CR
$74737953 (EMIT4) $69206D65 (EMIT4) $6974696E (EMIT4) $7A696C61 (EMIT4) $2E6465 (EMIT4) CR $74737953 (EMIT4) $69206D65 (EMIT4) $6974696E (EMIT4) $7A696C61 (EMIT4) $2E6465 (EMIT4) CR
jump ABORT jump ABORT
+35 -5
View File
@@ -1524,18 +1524,23 @@ Each test is written to fail first.
4. **GONE down the graph.** A node of unit 2 waiting on a node of unit 1 4. **GONE down the graph.** A node of unit 2 waiting on a node of unit 1
ends "Node gone" when Hera kills that node. A GONE from any node but a ends "Node gone" when Hera kills that node. A GONE from any node but a
node's own centre is still not believed. node's own centre is still not believed.
5. **The new message path** (a centre passing a GONE on to the nodes it 5. ~~**The new message path** (a centre passing a GONE on to the nodes it
birthed): every depth of both stacks (`v4/tests/test_host_depth.c`); birthed): every depth of both stacks (`v4/tests/test_host_depth.c`);
and the passing on disturbed at every engine step -- the centre and the passing on disturbed at every engine step -- the centre
removed, a child removed, the wire cut -- with every node left coming removed, a child removed, the wire cut -- with every node left coming
to rest and answering (`v4/tests/test_host_mesh.c`'s way). to rest and answering (`v4/tests/test_host_mesh.c`'s way).~~
**Withdrawn with ruling 7 (2026-10-16):** no node passes a GONE on, so
there is no new message path on a node. The kernel's telling is tested
in C at both widths (`v4/tests/test_manage.c`) and in the fabric
(`v4/tests/test_host_unit.c`, item 4).
6. **The kernel's side.** The registry and who may ask, tested in C at 6. **The kernel's side.** The registry and who may ask, tested in C at
both cell widths. both cell widths.
7. **Nothing else changes.** `make -C v4 test test-32 sanitize 7. **Nothing else changes.** `make -C v4 test test-32 sanitize
hosted-check`; `mkcapsule --lint capsules/`; the three QEMU boots and hosted-check`; `mkcapsule --lint capsules/`; the three QEMU boots and
`make -C v4 test-32`, as `.claude/CLAUDE.md` says. The system changes `make -C v4 test-32`, as `.claude/CLAUDE.md` says. The system changes,
(`(GONE-HOOK)`), so the products' `dict_hash` changes; it must be the so the products' `dict_hash` changes; it must be the same on all three
same on all three ISAs (ruled 2026-10-16, planning). ISAs (ruled 2026-10-16, planning). (The change was first `(GONE-HOOK)`;
with ruling 7 it is that word's going.)
**A limit kept, not widened:** `test_host_unit.c` is not run at 32 bits; **A limit kept, not widened:** `test_host_unit.c` is not run at 32 bits;
POST's expected results are 64-bit (step 5). POST's expected results are 64-bit (step 5).
@@ -2114,6 +2119,31 @@ Each is tested, committed and pushed before the next.
(riscv64): POST 538 of 538, `word_count=318`, (riscv64): POST 538 of 538, `word_count=318`,
`dict_hash=0x248b4edc47f4357e` on all six systems (the system changed, `dict_hash=0x248b4edc47f4357e` on all six systems (the system changed,
so the hash did); `make -C v4 test-32`, 0 failures. so the hash did); `make -C v4 test-32`, 0 failures.
- **Amended 2026-10-20, ruling 7 (the kernel tells a node's going).**
Two increments, each accepted on its own.
*Increment 1* (5707b07a): `manage.c`'s `KILL` puts a GONE about the
node on the wire of every live node from its parent, as if its parent
had sent it; `centre.4th` loses `GONE-DOWN` and its table of the
nodes it birthed; `hera.4th`'s `KILL` is the kernel's kill and
`NO-ROUTE`. Accepted in 9138ebd8: `logs/20261020-084230` (amd64),
`-084520` (aarch64), `-084933` (riscv64), POST 538 of 538,
`dict_hash=0x248b4edc47f4357e` on all three.
*Increment 2*: the system's hand-on goes -- `(GONE-HOOK)`, `(DOWN)`
and `(RUN)` from `quit.f18`, `COLD`'s hook-clearing from
`system.f18`; the cell is free again (`v4/tests/host_map.h`). The
tests of the hand-on go with it: the mesh test's hand-on checks and
its fourth disturbed exchange, and the depth sweep's path "AWAIT
ended by a GONE that is handed on", which is again as before
529ba0fc. What stays: a GONE believed from a node's centre goes no
further (`v4/tests/test_host_mesh.c`, 244 checks); GONE down the graph
ends a wait in the second unit (`v4/tests/test_host_unit.c`, 126
checks); the kernel's side (`v4/tests/test_manage.c`, 52 checks, both
widths). Verified: `make -C v4 test test-32 sanitize hosted-check`
(depth sweep 230 runs, 0 failures); `mkcapsule --lint capsules/`, 0
violations; three bare-metal boots, `logs/20261020-125114` (amd64),
`-125411` (aarch64), `-125820` (riscv64): POST 538 of 538, `PARITY:OK`,
`word_count=317`, `dict_hash=0xfec8c47cfc6f437f` on all six systems;
`make -C v4 test-32`, 0 failures.
8. **The hosted product is the five nodes**, on three ISAs: acceptance 1 8. **The hosted product is the five nodes**, on three ISAs: acceptance 1
to 5. to 5.
9. **The same on bare metal:** acceptance 6. 9. **The same on bare metal:** acceptance 6.
+1 -3
View File
@@ -119,7 +119,7 @@
/* THE IMAGE RECORD: where the system's source says, with `store`, the addresses a host needs (v4/image.h): where the /* THE IMAGE RECORD: where the system's source says, with `store`, the addresses a host needs (v4/image.h): where the
* node waits for a message, its fault table, and KEY's code. */ * node waits for a message, its fault table, and KEY's code. */
#define ROM_IMG (BUF0_W - 119) /* idle, fault table, KEY, the word after KEY: 4 cells */ #define ROM_IMG (BUF0_W - 119) /* idle, fault table, KEY, the word after KEY: 4 cells */
/* FREE, plain memory: BUF0_W - 22; - 115 .. - 113; BUF0_W - 144 .. - 141 (what a flush makes zero after /* FREE, plain memory: BUF0_W - 22 .. - 21; - 115 .. - 113; BUF0_W - 144 .. - 141 (what a flush makes zero after
* a full output buffer); and OUT_W - 144 .. OUT_W - 65. They and * a full output buffer); and OUT_W - 144 .. OUT_W - 65. They and
* the cells above held the messages waiting, the refusals owed and what went with them (MESH.md 7a, 7b), which a * the cells above held the messages waiting, the refusals owed and what went with them (MESH.md 7a, 7b), which a
* node no longer keeps. */ * node no longer keeps. */
@@ -205,7 +205,6 @@ enum { V4_ROM_ERRORS(ROM_ERR_ENUM_) ROM_ERR_END_ };
#define ROM_ADDR_TOP ((v4_cell)(V4_NODE_WORDS + V4_ROM_WORDS - 1u)) /* the top of the address space */ #define ROM_ADDR_TOP ((v4_cell)(V4_NODE_WORDS + V4_ROM_WORDS - 1u)) /* the top of the address space */
#define WORD_DEFINED (BUF0_W - 11) /* the xt of the word that is told of each new entry, or 0 */ #define WORD_DEFINED (BUF0_W - 11) /* the xt of the word that is told of each new entry, or 0 */
#define WORD_FORGOTTEN (BUF0_W - 12) /* the xt of the word that is told when entries go, or 0 */ #define WORD_FORGOTTEN (BUF0_W - 12) /* the xt of the word that is told when entries go, or 0 */
#define GONE_HOOK (BUF0_W - 21) /* the xt of the word a believed GONE is handed to, or 0 (MESH.md 9a.2, ruling 7) */
#define LOG_LEVEL (BUF0_W - 5) /* the level at or below which a message is printed */ #define LOG_LEVEL (BUF0_W - 5) /* the level at or below which a message is printed */
#define BOOT_CELLS (BVARS + 14) /* (BOOT): DP and LATEST as the loader left them, 2 cells */ #define BOOT_CELLS (BVARS + 14) /* (BOOT): DP and LATEST as the loader left them, 2 cells */
#define BUF0_W (BVARS - (v4_cell)(V4_BLOCK_SLOTS * V4_BLOCK_CELLS)) /* the block window: the kernel's slots, 256 cells each (v4/blocks.h) */ #define BUF0_W (BVARS - (v4_cell)(V4_BLOCK_SLOTS * V4_BLOCK_CELLS)) /* the block window: the kernel's slots, 256 cells each (v4/blocks.h) */
@@ -331,7 +330,6 @@ static unsigned host_branch_slots(void)
X("(OUT)", OUT_W) \ X("(OUT)", OUT_W) \
X("(WORD-DEFINED)", WORD_DEFINED) \ X("(WORD-DEFINED)", WORD_DEFINED) \
X("(WORD-FORGOTTEN)", WORD_FORGOTTEN) \ X("(WORD-FORGOTTEN)", WORD_FORGOTTEN) \
X("(GONE-HOOK)", GONE_HOOK) \
X("BLOCK#", V4_REQ_BLOCK) /* the kernel's block requests (v4/blocks.h) */ \ X("BLOCK#", V4_REQ_BLOCK) /* the kernel's block requests (v4/blocks.h) */ \
X("BUFFER#", V4_REQ_BUFFER) \ X("BUFFER#", V4_REQ_BUFFER) \
X("UPDATE#", V4_REQ_UPDATE) \ X("UPDATE#", V4_REQ_UPDATE) \
+4 -25
View File
@@ -218,10 +218,10 @@ static void fill(char *text, size_t cap, unsigned count)
for (bit = 8; bit; bit >>= 1) if (count >= bit) { at += (size_t)snprintf(text + at, cap - at, "P%u ", bit); count -= bit; } for (bit = 8; bit; bit >>= 1) if (count >= bit) { at += (size_t)snprintf(text + at, cap - at, "P%u ", bit); count -= bit; }
} }
#define PATHS 11u #define PATHS 10u
static const char *const path_name[PATHS] = { "a text that prints", "SEND", "SEND with no way", "AWAIT answered", "AWAIT ended by a GONE", "passing on while its text waits for room", static const char *const path_name[PATHS] = { "a text that prints", "SEND", "SEND with no way", "AWAIT answered", "AWAIT ended by a GONE", "passing on while its text waits for room",
"AWAIT broken by a line from the console", "a refusal while its text waits for room", "GONE", "AWAIT broken by a line from the console", "a refusal while its text waits for room", "GONE",
"a spent message refused while its text waits", "AWAIT ended by a GONE that is handed on" }; "a spent message refused while its text waits" };
static char numbers[8192]; /* what 1200 0 DO I . LOOP prints */ static char numbers[8192]; /* what 1200 0 DO I . LOOP prints */
/* A row made afresh for one path; node 11 is given the word ACT that takes it, and the words that fill the /* A row made afresh for one path; node 11 is given the word ACT that takes it, and the words that fill the
@@ -239,7 +239,6 @@ static int made(unsigned path)
": ACT 1200 0 DO I . LOOP ;", ": ACT 1200 0 DO I . LOOP ;",
": ACT 44 12 GONE ;", ": ACT 44 12 GONE ;",
": ACT 1200 0 DO I . LOOP ;", ": ACT 1200 0 DO I . LOOP ;",
": ACT 77 AWAIT DROP ;",
}; };
char line[64]; char line[64];
unsigned k; unsigned k;
@@ -251,11 +250,6 @@ static int made(unsigned path)
} }
if (path == 2 && !told(11, "NO-ROUTES 1 2 ROUTE 10 2 ROUTE 12 3 ROUTE")) return 0; /* no way for any node it has not been told of */ if (path == 2 && !told(11, "NO-ROUTES 1 2 ROUTE 10 2 ROUTE 12 3 ROUTE")) return 0; /* no way for any node it has not been told of */
if (path == 4 && !told(12, ": LL 400000 0 DO LOOP ;")) return 0; if (path == 4 && !told(12, ": LL 400000 0 DO LOOP ;")) return 0;
/* path 10: node 11 waits on a node 77 that never answers; its centre says 77 is gone, and node 11 hands the
* believed GONE on (MESH.md 9a.2, ruling 7) -- a GONE about 44 to node 12, which knows a way to 44. (Not
* about 12: believing a GONE about 12 makes node 11 forget its way to 12, and a GONE-DOWN never tells a node
* of its own going.) */
if (path == 10 && !told(11, "VARIABLE FWD : DOWN DROP 44 12 GONE 1 FWD +! ; ' DOWN (GONE-HOOK) !")) return 0;
if (path == 5 && !told(10, ": SLOW 500000 0 DO LOOP ; : BUSY SLOW S\" 1 DROP\" 12 SEND SLOW ;")) return 0; if (path == 5 && !told(10, ": SLOW 500000 0 DO LOOP ; : BUSY SLOW S\" 1 DROP\" 12 SEND SLOW ;")) return 0;
if (path == 9 && !told(10, ": SLOW 500000 0 DO LOOP ; : BUSY SLOW SLOW ;")) return 0; if (path == 9 && !told(10, ": SLOW 500000 0 DO LOOP ; : BUSY SLOW SLOW ;")) return 0;
/* 320 characters: more than fits beside what node 11 itself is waiting to print */ /* 320 characters: more than fits beside what node 11 itself is waiting to print */
@@ -286,16 +280,12 @@ static int one(unsigned path, const char *what, unsigned depth, const char *text
runs++; runs++;
step_cap = 60000000; step_cap = 60000000;
if (path == 8 && !told(12, "44 2 ROUTE")) why = "node 12 did not take a way"; if (path == 8 && !told(12, "44 2 ROUTE")) why = "node 12 did not take a way";
if (path == 10 && !(told(11, "0 FWD !") && told(12, "44 NO-ROUTE 44 2 ROUTE"))) why = "node 11 did not clear FWD, or node 12 did not take a way to 44";
ways12 = pool[far].n.mem[ROUTE_COUNT]; ways12 = pool[far].n.mem[ROUTE_COUNT];
forget(); forget();
saw_room_wait = 0; saw_passed = 0; saw_room_wait = 0; saw_passed = 0;
clock12 = pool[far].es.anticlock; clock12 = pool[far].es.anticlock;
if (why) { } if (why) { }
else if (path == 10) { /* node 11 waits on 77; its centre says 77 is gone */ else if (path == 4) { /* node 12 is busy for a long while and sends no answer; node 11 waits; its centre says 12 is gone */
if (!put_text(11, text) || !run()) why = "it did not come to wait";
else if (!put_text(10, "77 11 GONE") || !run()) why = "the nodes did not come to rest";
} else if (path == 4) { /* node 12 is busy for a long while and sends no answer; node 11 waits; its centre says 12 is gone */
stuck = 1u << far; stuck = 1u << far;
if (!put_text(12, "LL") || !put_text(11, text) || !run()) why = "it did not come to wait"; if (!put_text(12, "LL") || !put_text(11, text) || !run()) why = "it did not come to wait";
else if (!put_text(10, "12 11 GONE") || !run()) why = "the GONE was not done"; else if (!put_text(10, "12 11 GONE") || !run()) why = "the GONE was not done";
@@ -350,17 +340,6 @@ static int one(unsigned path, const char *what, unsigned depth, const char *text
clean_error = over && is_cut_short(printed, numbers, over) && pool[far].n.mem[REFUSED] == refused12 + 1; break; /* whoever refused it, node 12 was told */ clean_error = over && is_cut_short(printed, numbers, over) && pool[far].n.mem[REFUSED] == refused12 + 1; break; /* whoever refused it, node 12 was told */
case 8: works = how11 == V4_TEXT_COMPLETED && printed_len == 0 && left == values && pool[far].n.mem[ROUTE_COUNT] == ways12 - 1; case 8: works = how11 == V4_TEXT_COMPLETED && printed_len == 0 && left == values && pool[far].n.mem[ROUTE_COUNT] == ways12 - 1;
clean_error = over && strcmp(printed, over) == 0; break; clean_error = over && strcmp(printed, over) == 0; break;
case 10: {
int down = pool[far].n.mem[ROUTE_COUNT] == ways12 - 1; /* node 12 believed the GONE node 11 handed on */
works = how11 == V4_TEXT_ERROR && strcmp(printed, "Node gone\n") == 0 && left == values && down;
clean_error = over && strcmp(printed, over) == 0;
if (works) works = strcmp(tell(11, "FWD @ ."), "1 ") == 0;
else if (clean_error) {
int fwd1 = strcmp(tell(11, "FWD @ ."), "1 ") == 0, fwd0 = strcmp(printed, "0 ") == 0;
clean_error = down ? (fwd1 || fwd0) : fwd0;
}
break;
}
case 9: works = how11 == V4_TEXT_COMPLETED && strcmp(printed, numbers) == 0 && left == values && saw_room_wait > 0 case 9: works = how11 == V4_TEXT_COMPLETED && strcmp(printed, numbers) == 0 && left == values && saw_room_wait > 0
&& pool[mid].n.mem[LOST] == lost11 + 1 && pool[far].n.mem[REFUSED] == refused12 + 1; && pool[mid].n.mem[LOST] == lost11 + 1 && pool[far].n.mem[REFUSED] == refused12 + 1;
clean_error = over && is_cut_short(printed, numbers, over) && pool[mid].n.mem[LOST] == lost11 + 1 && pool[far].n.mem[REFUSED] == refused12 + 1; break; /* it was dropped: its sender was told */ clean_error = over && is_cut_short(printed, numbers, over) && pool[mid].n.mem[LOST] == lost11 + 1 && pool[far].n.mem[REFUSED] == refused12 + 1; break; /* it was dropped: its sender was told */
@@ -441,7 +420,7 @@ int main(void)
first_error = 0; first_error = 0;
for (k = V4_RET_DEPTH - 18u; k <= V4_RET_DEPTH + 1u; k++) { for (k = V4_RET_DEPTH - 18u; k <= V4_RET_DEPTH + 1u; k++) {
snprintf(text, sizeof text, "N%u", k); snprintf(text, sizeof text, "N%u", k);
r = one(path, "calls deep", k, text, 0, k + ((path == 5 || path == 7 || path == 9) ? 16u : path == 10 ? 14u : 11u) <= V4_RET_DEPTH); r = one(path, "calls deep", k, text, 0, k + ((path == 5 || path == 7 || path == 9) ? 16u : 11u) <= V4_RET_DEPTH);
if (r == 0 && !first_error) first_error = k; if (r == 0 && !first_error) first_error = k;
} }
printf(" calls: works to %u deep; %u worked, %u clean errors, %u failures\n", first_error ? first_error - 1u : (unsigned)(V4_RET_DEPTH + 1u), worked - w0, refused_clean - e0, bad - before); printf(" calls: works to %u deep; %u worked, %u clean errors, %u failures\n", first_error ? first_error - 1u : (unsigned)(V4_RET_DEPTH + 1u), worked - w0, refused_clean - e0, bad - before);
+6 -16
View File
@@ -1096,23 +1096,14 @@ int main(void)
CHECK(undone == 0 && wrong == 0, "whenever the room came, both texts were done, the first first: %u not done, %u in the wrong order, the first when it came at step %u", undone, wrong, first_wrong); CHECK(undone == 0 && wrong == 0, "whenever the room came, both texts were done, the first first: %u not done, %u in the wrong order, the first when it came at step %u", undone, wrong, first_wrong);
} }
/* ---- A BELIEVED GONE IS HANDED ON (MESH.md 9a.2, ruling 7; 9a.3) ---- /* ---- A BELIEVED GONE GOES NO FURTHER (MESH.md 9a.2, ruling 7) ----
* The word in (GONE-HOOK) is given the number of the node that is gone, each time a GONE is believed: * The kernel tells each node a node's going; a node does not hand a GONE on. Node 11 believes one from its
* centre.4th puts GONE-DOWN there, which tells the nodes the node birthed. Here node 11 has a word that * centre and forgets its way to 44, and node 12, which also knows a way to 44, is told nothing. */
* tells node 12; node 12 believes it, since node 11 is its centre, and forgets its way to 44. */
CHECK(row() && told(12, "44 2 ROUTE") && told(11, "44 3 ROUTE"), "a row; nodes 11 and 12 each know a way to 44"); CHECK(row() && told(12, "44 2 ROUTE") && told(11, "44 3 ROUTE"), "a row; nodes 11 and 12 each know a way to 44");
{ {
v4_cell ways11 = pool[mid].n.mem[ROUTE_COUNT], ways12 = pool[far].n.mem[ROUTE_COUNT]; v4_cell ways11 = pool[mid].n.mem[ROUTE_COUNT], ways12 = pool[far].n.mem[ROUTE_COUNT];
CHECK(told(10, "44 11 GONE") && pool[mid].n.mem[ROUTE_COUNT] == ways11 - 1 && pool[far].n.mem[ROUTE_COUNT] == ways12 && asleep(far), CHECK(told(10, "44 11 GONE") && pool[mid].n.mem[ROUTE_COUNT] == ways11 - 1 && pool[far].n.mem[ROUTE_COUNT] == ways12 && asleep(far),
"with nothing in (GONE-HOOK) node 11 believes a GONE from its centre and tells no one"); "node 11 believes a GONE from its centre and tells no one");
CHECK(told(11, "44 3 ROUTE : DOWN 12 GONE ; ' DOWN (GONE-HOOK) !"), "node 11 is given a word to hand a GONE on with");
CHECK(told(10, "44 11 GONE") && pool[mid].n.mem[ROUTE_COUNT] == ways11 - 1 && pool[far].n.mem[ROUTE_COUNT] == ways12 - 1 && asleep(far) && asleep(mid),
"now node 11 believes it and hands it on: node 12 believes it from its centre and forgets 44 too");
CHECK(told(12, "44 2 ROUTE") && told(11, "44 3 ROUTE") && told(12, "44 12 GONE") && pool[mid].n.mem[ROUTE_COUNT] == ways11,
"a GONE that is not believed -- node 12 is not node 11's centre -- is not handed on");
CHECK(v4_fabric_wire_kernel(&f, mid, 0, &kernel_dev), "a kernel on node 11's port 0, for COLD's EMPTY-BUFFERS");
CHECK(strstr(tell(11, "COLD"), "Cold Start") != NULL && strcmp(tell(11, "(GONE-HOOK) @ ."), "0 ") == 0,
"COLD forgets DOWN, so (GONE-HOOK) no longer points at it: \"%s\"", printed);
CHECK(strcmp(tell(10, "1 2 + ."), "3 ") == 0 && strcmp(tell(11, "1 2 + ."), "3 ") == 0 && strcmp(tell(12, "1 2 + ."), "3 ") == 0, "and every node answers"); CHECK(strcmp(tell(10, "1 2 + ."), "3 ") == 0 && strcmp(tell(11, "1 2 + ."), "3 ") == 0 && strcmp(tell(12, "1 2 + ."), "3 ") == 0, "and every node answers");
} }
@@ -1128,16 +1119,15 @@ int main(void)
* (Hera's KILL does: test_host_unit.c). Its wait is ended by the line it is then typed, "Interrupted", * (Hera's KILL does: test_host_unit.c). Its wait is ended by the line it is then typed, "Interrupted",
* and it answers. */ * and it answers. */
{ {
static const struct { const char *what, *set10, *set11, *set12; v4_cell node; const char *text; } ex[4] = { static const struct { const char *what, *set10, *set11, *set12; v4_cell node; const char *text; } ex[3] = {
{ "text from the console for node 12, what it prints and how it ended", "1 DROP", "1 DROP", ": A 7 8 * . ;", 12, "A" }, { "text from the console for node 12, what it prints and how it ended", "1 DROP", "1 DROP", ": A 7 8 * . ;", 12, "A" },
{ "node 11 SENDs node 12 text and waits for its answer", "1 DROP", ": T S\" Q\" 12 SEND 12 AWAIT . ;", "1 DROP", 11, "T" }, { "node 11 SENDs node 12 text and waits for its answer", "1 DROP", ": T S\" Q\" 12 SEND 12 AWAIT . ;", "1 DROP", 11, "T" },
{ "a GONE node 10 sends node 11, which node 11 hands on to node 12", ": G 44 11 GONE ;", ": DOWN 12 GONE ; ' DOWN (GONE-HOOK) ! 44 3 ROUTE", "44 2 ROUTE", 10, "G" },
{ "a message node 12 has no way for, and its NACK to node 10", "55 2 ROUTE : N S\" 1 DROP\" 55 SEND ;", "55 3 ROUTE", "NO-ROUTES 1 2 ROUTE 10 2 ROUTE 11 2 ROUTE", 10, "N" } { "a message node 12 has no way for, and its NACK to node 10", "55 2 ROUTE : N S\" 1 DROP\" 55 SEND ;", "55 3 ROUTE", "NO-ROUTES 1 2 ROUTE 10 2 ROUTE 11 2 ROUTE", 10, "N" }
}; };
static const char *const how_name[4] = { "", "node 11 removed", "node 12 removed", "the wire between nodes 11 and 12 cut and made again" }; static const char *const how_name[4] = { "", "node 11 removed", "node 12 removed", "the wire between nodes 11 and 12 cut and made again" };
unsigned e, g, whole, tried, wrong, first, all = 0; unsigned e, g, whole, tried, wrong, first, all = 0;
step_cap = 2000000; step_cap = 2000000;
for (e = 0; e < 4; e++) { for (e = 0; e < 3; e++) {
CHECK(row() && told(10, ex[e].set10) && told(11, ex[e].set11) && told(12, ex[e].set12) && told(10, ASK) && told(11, ASK) && told(12, ASK), "a row made afresh for: %s", ex[e].what); CHECK(row() && told(10, ex[e].set10) && told(11, ex[e].set11) && told(12, ex[e].set12) && told(10, ASK) && told(11, ASK) && told(12, ASK), "a row made afresh for: %s", ex[e].what);
step_cap = 2000000; step_cap = 2000000;
keep(); keep();
+1 -1
View File
@@ -696,7 +696,7 @@ int main(void)
CHECK(ended == 0 && node_numbered(21)->mem[AWAIT_FROM] == 12 && waiting(21), "node 21 of the second unit waits on node 12 of the first"); CHECK(ended == 0 && node_numbered(21)->mem[AWAIT_FROM] == 12 && waiting(21), "node 21 of the second unit waits on node 12 of the first");
(void)tell(10, "12 KILL"); (void)tell(10, "12 KILL");
CHECK(node_numbered(12) == NULL && strstr(printed, "Node gone") != NULL && node_numbered(21)->mem[AWAIT_FROM] == 0, CHECK(node_numbered(12) == NULL && strstr(printed, "Node gone") != NULL && node_numbered(21)->mem[AWAIT_FROM] == 0,
"Hera kills node 12: her GONE goes to node 20, which tells its own, and node 21's wait ends: \"%s\"", printed); "Hera kills node 12: the kernel tells each node it is gone, and node 21's wait ends: \"%s\"", printed);
{ {
v4_cell ways = node_numbered(22)->mem[ROUTE_COUNT]; v4_cell ways = node_numbered(22)->mem[ROUTE_COUNT];
CHECK(told(22, "88 3 ROUTE") && told(21, "88 22 GONE") && node_numbered(22)->mem[ROUTE_COUNT] == ways + 1, CHECK(told(22, "88 3 ROUTE") && told(21, "88 22 GONE") && node_numbered(22)->mem[ROUTE_COUNT] == ways + 1,