diff --git a/capsules/v4/nucleus-64.f18 b/capsules/v4/nucleus-64.f18 index 2622e492..a1085821 100644 Binary files a/capsules/v4/nucleus-64.f18 and b/capsules/v4/nucleus-64.f18 differ diff --git a/v4/capsule/core.v4 b/v4/capsule/core.v4 index 0ac19c32..e5fcc2d0 100644 --- a/v4/capsule/core.v4 +++ b/v4/capsule/core.v4 @@ -182,7 +182,7 @@ header CMOVE \ messages in so as to be free to write, where it cannot begin a message \ of its own: so it notes what it owes, (OWE), in the eight pairs at \ (OWED) -- whom it is owed to, and the node the message was for -- and -\ sends it when it next has nothing else to do, (PAY). With eight owed +\ sends it when it next has nothing else to do, (PAY-SET). With eight owed \ already, one more is let go and counted. Nothing is owed for a NACK or \ for a GONE, type 5: there is no NACK for a NACK. The last 36 cells of \ the messages waiting are kept for those two types, so that ordinary @@ -303,13 +303,14 @@ header CMOVE 16 !b 0 !b 0 !b ; \ how many nodes may pass it on (the TTL: MESH.md 7b); ACL tag; sequence \ PAYING WHAT IS OWED (MESH.md 7c.3). Every refusal owed is offered at -\ once, each on the port it goes by, one to a port, and the node sleeps in -\ the wait: so one owed to a node that is stuck does not keep back one -\ owed to a node that waits for it, and the node takes in whatever is -\ written to it meanwhile. One there is no way for, or whose way is a +\ once, each on the port it goes by, one to a port, with whatever the node +\ has to pass on (quit.v4, (IDLE)), and the node sleeps in the wait: so +\ one owed to a node that is stuck does not keep back one owed to a node +\ that waits for it, and the node takes in whatever is written to it +\ meanwhile. One there is no way for, or whose way is a \ port with nothing on it, is let go and counted first. (PAY-K) has a \ cell for each port: which refusal is offered there, counted from 1; 0, -\ none. +\ none; -1, a message being passed on. \ ( k -- ) the k-th refusal owed is done with: the last takes its place : (PAID) @@ -327,30 +328,32 @@ header CMOVE \ ( k -- ) offer the k-th refusal owed on its port, if nothing is there yet : (PAY-OFFER) - dup 2* (OWED) + a! @ \ k to - dup (PORT-FOR) (PORT) - \ k to n the port, by its number + dup push 2* (OWED) + a! @ \ to R: k (the stack is kept shallow: this runs between lines) + dup (PORT-FOR) (PORT) - \ to n the port, by its number dup (PAY-K) + a! @ if FREE - drop drop drop drop ; + drop drop drop pop drop ; FREE: drop - dup push (OFFER) + a! ! \ k the message's first word, whom it is to - 1 + pop (PAY-K) + a! ! ; + dup push (OFFER) + a! ! \ the message's first word, whom it is to + pop pop 1 + SWAP (PAY-K) + a! ! ; -\ ( -- flag ) offer every refusal this node owes and wait once: if one -\ is taken its other words are written and it is done with. Zero if -\ nothing is owed, and then nothing was waited for. -: (PAY) +\ ( -- ) let go every refusal owed that cannot be sent; no port has an +\ offer; then offer each that is left on its port +: (PAY-SET) (OWED#) a! @ if NONE -1 + FOR pop dup push (PAY-DROP) NEXT - (OWED#) a! @ if NONE - (PAY-K) a! PORTS-1 FOR 0 !+ NEXT - -1 + FOR pop dup push (PAY-OFFER) NEXT - (OFFERS) if CAME - drop (GATE-PORT) a! @ (PORT) - (PAY-K) + a! @ -1 + \ k: the one that was taken + jump CLEAR + NONE: drop + CLEAR: (PAY-K) a! PORTS-1 FOR 0 !+ NEXT + (OWED#) a! @ if NONE2 + -1 + FOR pop dup push (PAY-OFFER) NEXT ; + NONE2: drop ; + +\ ( k -- ) the offer of the k-th refusal owed was taken, and B is at the +\ port: its other words are written, and it is done with +: (PAY-GO) dup 2* (OWED) + 1 + a! @ \ k about 4 (HDR) 4 !b !b \ from, type 4; four characters; about - (PAID) -1 ; - CAME: drop -1 ; - NONE: drop 0 ; + jump (PAID) \ ( -- ) send what has been printed, to where (PRINT-TO) says, by the port \ (PRINT-PORT): its length, then its characters, four to a word, the first diff --git a/v4/capsule/quit.v4 b/v4/capsule/quit.v4 index 039360f8..80b8abfb 100644 --- a/v4/capsule/quit.v4 +++ b/v4/capsule/quit.v4 @@ -54,12 +54,24 @@ macro R-CLEAR RSTACK-DEPTH b! a !b endmacro \ stops compiling first; it is always jumped to, never called, by \ something that has emptied the return stack (or by a fault, which empties \ it). (LINE-STATUS) keeps how the last text ended. +\ THE MESSAGE SAYING HOW IT ENDED is not written here: whoever sent the +\ text may be stuck, and this node would wait on it. It is put with the +\ messages waiting and passed on from (IDLE), as any message for another +\ node is. : (FINISH) ( s -- ) 1 (QUIET) a! ! \ from here an error is not this text's: see (RAISED) (LINE-STATUS) b! dup !b (FLUSH-OUT) - (MSG)+1 a! @ (DONE-PORT) a! @ (GATE) \ to whoever sent the text - 3 (HDR) 4 !b !b \ a message of type 3, four characters long: how it ended + 1 (MQ#) a! @ + -MQ-ROOM + -if FULL \ how it ended goes with the messages waiting, + drop \ to be passed on as any is: (IDLE) + (MSG)+1 a! @ (MQ!) (ME) a! @ (MQ!) 3 (MQ!) \ to whoever sent the text, from this node, type 3 + 0 (MQ!) 0 (MQ!) 0 (MQ!) 4 (MQ!) \ four characters long + 0 (DONE-PORT) a! @ - (MQ!) \ by the port that leads back, kept below zero: this node's own + (MQ!) \ how it ended + jump (IDLE) + FULL: drop \ no room at all: it is offered here, and the node waits + (MSG)+1 a! @ (DONE-PORT) a! @ (GATE) + 3 (HDR) 4 !b !b jump (IDLE) : (DONE) @@ -68,38 +80,144 @@ macro R-CLEAR RSTACK-DEPTH b! a !b endmacro OK: drop 1 jump (FINISH) GO: drop 0 jump (FINISH) -\ ( -- ) WAITING. A node with nothing to do deals with the oldest of the -\ messages waiting (core.v4). With none waiting it is blocked reading its -\ ports (docs/v4.0.0/MESH.md 4.1): it executes nothing until a neighbour -\ writes, and what arrives is taken in as any message is, its first word -\ from any port and the rest from the port that came on. The message's -\ text goes into TIB, which holds 1024 characters, the most a message -\ carries; one that came with a length no message has is error 12. A -\ message of type 1 for this node is text to interpret: it is done as a -\ line was, and (FINISH) reports how it ended. A message for another node -\ is passed on, (PASS-ON). +\ THE MESSAGES WAITING, GONE THROUGH. Three words below go through them +\ all, as (A-QUEUE) does further down: each in turn is taken from the +\ front, its eight cells into (MQ-HDR), and either used up or put at the +\ back, so that those that stay are in the order they were in. (A-LEFT) +\ is how many cells are still to be looked at, and (A-FOUND) what the pass +\ has found. + +\ ( -- n ) the next of them is in (MQ-HDR); n is how many words of text +\ it has, which are still at the front +: (MQ-NEXT) + (A-HDR) + (MQ-HDR)+6 a! @ -if SIZED drop 0 jump N + SIZED: 3 + 2/ 2/ + N: (A-LEFT) a! @ over 8 + - ! ; + +\ ( -- port | 0 ) the port the message in (MQ-HDR) goes by: for one this +\ node made itself, (FINISH), the port kept with it, below zero; for any +\ other, the way to the node it is for +: (FWD-PORT) + (MQ-HDR)+7 a! @ -if THEIRS 0 SWAP - ; + THEIRS: drop (MQ-HDR) a! @ jump (PORT-FOR) + +\ ( -- flag ) IS THERE ONE FOR THIS NODE? The first that is, is taken +\ out: its seven words into (MSG), the port it came on into (REPLY), its +\ text into TIB. +: (MINE?) + 0 (A-FOUND) a! ! + (MQ#) a! @ (A-LEFT) a! ! + L: (A-LEFT) a! @ if END drop + (MQ-NEXT) + (A-FOUND) a! @ if LOOK drop jump KEEP + LOOK: drop + (MQ-HDR) a! @ (ME) a! @ xor if MINE drop jump KEEP + MINE: drop 1 (A-FOUND) a! ! + (MQ-HDR) a! @ (MSG) a! ! (MQ-HDR)+1 a! @ (MSG)+1 a! ! (MQ-HDR)+2 a! @ (MSG)+2 a! ! + (MQ-HDR)+3 a! @ (MSG)+3 a! ! (MQ-HDR)+4 a! @ (MSG)+4 a! ! (MQ-HDR)+5 a! @ (MSG)+5 a! ! + (MQ-HDR)+6 a! @ (MSG)+6 a! ! (MQ-HDR)+7 a! @ (REPLY) a! ! + TIB 2/ 2/ SWAP if EMPTY + -1 + FOR (MQ@) over a! ! 1 + NEXT + drop jump L + EMPTY: drop drop jump L + KEEP: (A-BACK) (A-TEXT) jump L + END: drop (A-FOUND) a! @ ; + +\ ( -- flag ) WHAT IS TO BE PASSED ON IS OFFERED (MESH.md 7c.3): for each +\ message, the first for its port, its first word is offered there, unless +\ a refusal owed is offered there already; (PAY-K) is set to -1 for that +\ port. It stays with the messages waiting until the offer is taken. +\ One that cannot go at all is let go, counted in (LOST), and whoever +\ waits on it is told (core.v4, (TELL-OF)): one with no way known; one +\ whose way is a port with nothing on it; and one that fifteen nodes have +\ passed on already. The flag is not zero if any was let go. +\ A MESSAGE IS PASSED ON BY AT MOST 16 NODES. Its fourth word says how +\ many more may; 0, as a device sends it, is taken for 16. +: (FWD-SET) + 0 (A-FOUND) a! ! + (MQ#) a! @ (A-LEFT) a! ! + L: (A-LEFT) a! @ if END drop + (MQ-NEXT) (A-WORD) a! ! \ its words of text, kept off the stack: this runs between lines + (MQ-HDR)+3 a! @ if FRESH jump COUNT + FRESH: drop 16 + COUNT: -1 + if REFUSE drop + (FWD-PORT) if REFUSE \ ( port ) + dup (THERE) if REFUSE2 drop + (PORT) - dup (PAY-K) + a! @ if FREE \ ( p slot ) p: the port, by its number + drop drop jump KEEP + FREE: drop dup push (MQ-HDR) a! @ SWAP (OFFER) + a! ! \ whom it is to, offered + -1 pop (PAY-K) + a! ! + KEEP: (A-BACK) (A-WORD) a! @ (A-TEXT) jump L + REFUSE2: drop + REFUSE: drop + (A-WORD) a! @ if NOTEXT -1 + FOR (MQ@) drop NEXT jump TOLD + NOTEXT: drop + TOLD: (LOST) a! @ 1 + ! 1 (A-FOUND) a! ! + (MQ-HDR)+1 a! @ (MQ-HDR) a! @ (MQ-HDR)+2 a! @ (TELL-OF) jump L + END: drop (A-FOUND) a! @ ; + +\ ( -- ) THE OFFER OF ONE WAS TAKEN, on the port (GATE-PORT) holds: the +\ first of the messages waiting that goes by that port is the one. Its +\ other words are written, each waiting for the neighbour, which has its +\ first and reads to the end; and it is done with. +: (FWD-GO) + 0 (A-FOUND) a! ! + (MQ#) a! @ (A-LEFT) a! ! + L: (A-LEFT) a! @ if END drop + (MQ-NEXT) + (A-FOUND) a! @ if LOOK drop jump KEEP + LOOK: drop + (FWD-PORT) (GATE-PORT) a! @ xor if THIS drop jump KEEP + THIS: drop 1 (A-FOUND) a! ! + (GATE-PORT) a! @ b! + (MQ-HDR)+1 a! @ !b (MQ-HDR)+2 a! @ !b + (MQ-HDR)+3 a! @ if FRESH jump COUNT + FRESH: drop 16 + COUNT: -1 + !b \ one fewer may pass it on + (MQ-HDR)+4 a! @ !b (MQ-HDR)+5 a! @ !b (MQ-HDR)+6 a! @ !b + if NOTEXT -1 + FOR (MQ@) !b NEXT jump L + NOTEXT: drop jump L + KEEP: (A-BACK) (A-TEXT) jump L + END: drop ; + +\ ( -- ) WAITING. A node with nothing to do looks through the messages +\ waiting (core.v4). +\ ONE FOR THIS NODE is dealt with, the oldest first: (MINE?). A message +\ of type 1 is text to interpret: it is done as a line was, and (FINISH) +\ reports how it ended; one that came with a length no message has is +\ error 12. A NACK is counted and a GONE from the node's centre believed. +\ WITH NONE FOR IT, what it has for other nodes, and the refusals it owes, +\ are offered, each on the port it goes by, and the node sleeps in the +\ wait (MESH.md 7c): until one is taken, and then the rest of that one is +\ written; or until a word comes for it, and then that message is taken in +\ and it looks again. A node that is stuck never takes what is offered +\ it, and holds up nothing else. +\ WITH NOTHING WAITING AND NOTHING OWED it is blocked reading its ports +\ (docs/v4.0.0/MESH.md 4.1): it executes nothing until a neighbour writes, +\ and what arrives is taken in as any message is. : (IDLE) L: 1 (QUIET) a! ! \ nothing here is any text's doing: see (RAISED) - (MQ#) a! @ if WAIT drop jump HAVE - WAIT: drop (PAY) if BLOCK drop jump L \ what it owes is offered, and it sleeps (core.v4) + (MINE?) if OTHERS drop jump HAVE + OTHERS: drop + (MQ#) a! @ (OWED#) a! @ + if BLOCK drop + (PAY-SET) (FWD-SET) if SET drop jump L \ one was let go: what is owed has changed + SET: drop + (MQ#) a! @ (OWED#) a! @ + if BLOCK drop + (OFFERS) if CAME drop + (GATE-PORT) a! @ (PORT) - (PAY-K) + a! @ \ what was offered on the port it was taken on + -if OWED drop (FWD-GO) jump L + OWED: -1 + (PAY-GO) jump L + CAME: drop jump L BLOCK: drop (PORT)+8 b! @b (PORT)+9 b! @b (PORT) + dup b! \ ( to port ) B: the port it came on SWAP (TAKE) jump L HAVE: - (MQ@) (MSG) a! ! (MQ@) (MSG)+1 a! ! (MQ@) (MSG)+2 a! ! (MQ@) (MSG)+3 a! ! - (MQ@) (MSG)+4 a! ! (MQ@) (MSG)+5 a! ! (MQ@) (MSG)+6 a! ! (MQ@) (REPLY) a! ! (MSG)+6 a! @ -if SIZED drop 0 (MSG)+6 a! ! 0 SPAN a! ! NODE-ERROR b! 12 !b \ no telling what it was SIZED: drop - TIB 2/ 2/ (MSG)+6 a! @ 3 + 2/ 2/ if EMPTY - -1 + FOR (MQ@) over a! ! 1 + NEXT - drop jump READ - EMPTY: drop drop - READ: 0 (MSG)+6 a! @ TIB + C! \ a zero after the text (MSG)+6 a! @ SPAN a! ! - (MSG) a! @ (ME) a! @ xor if MINE drop jump (PASS-ON) - MINE: drop - (MSG)+2 a! @ -1 + if TEXT \ for this node, and + (MSG)+2 a! @ -1 + if TEXT -3 + if NACK -1 + if GONE drop jump (IDLE) \ neither text nor these: let go NACK: drop (REFUSED) a! @ 1 + ! jump (IDLE) \ a message of this node's was refused: counted GONE: drop (MSG)+6 a! @ -4 + if G4 drop jump (IDLE) \ a node is gone, if its centre says so: @@ -118,25 +236,6 @@ macro R-CLEAR RSTACK-DEPTH b! a !b endmacro Q1: (PRINT-PORT) a! ! jump (LINE) -\ ( -- ) A MESSAGE FOR ANOTHER NODE is passed on (MESH.md section 7): all -\ of it, as it came, to the port that leads toward that node. With no way -\ known it is let go, and (LOST) counts it. -: (PASS-ON) - (MSG)+3 a! @ if FRESH jump COUNT \ how many more nodes may pass it on; - FRESH: drop 16 \ from a device, which set none: sixteen - COUNT: -1 + if SPENT (MSG)+3 a! ! - (MSG) a! @ (PORT-FOR) if NOWAY - dup (THERE) if NOONE drop - (MSG) a! @ SWAP (GATE) (MSG)+1 a! 5 FOR @+ !b UNEXT \ its seven words - (MSG)+6 a! @ 3 + 2/ 2/ if SENT - -1 + TIB 2/ 2/ a! FOR @+ !b UNEXT \ and its text - jump (IDLE) - SENT: drop jump (IDLE) - NOONE: drop \ its way is a port with nothing on it - SPENT: \ it has been passed on as often as it may be - NOWAY: drop (LOST) a! @ 1 + ! - (MSG)+1 a! @ (MSG) a! @ (MSG)+2 a! @ (TELL-OF) jump (IDLE) \ whoever waits on it is told (core.v4) - \ ( -- ) THE TEXT, INTERPRETED. It is in TIB with a zero after it and its \ length in SPAN, and the return stack is empty. It is interpreted with one \ return entry under it, this word's call of INTERPRET; whatever is on the diff --git a/v4/tests/test_host_mesh.c b/v4/tests/test_host_mesh.c index 7a86554c..4da5ff66 100644 --- a/v4/tests/test_host_mesh.c +++ b/v4/tests/test_host_mesh.c @@ -398,6 +398,13 @@ int main(void) CHECK(is_empty(tell(10, "66 NO-ROUTE")) && waiting(hera) && waiting(mid) && waiting(far), "the way is forgotten, and all three are at rest"); } + /* ---- what a node passes on keeps its order, however long it must be kept (MESH.md 7c) ---- */ + CHECK(is_empty(tell(11, "12 2 ROUTE")), "node 11 is told the way to node 12 is by node 10"); + CHECK(is_empty(tell(12, ": SLOW 30000 0 DO LOOP ;")), "node 12 is given a word that takes a while"); + CHECK(strcmp(tell(11, ": TRIO S\" SLOW 68 EMIT\" 12 SEND S\" 69 EMIT\" 12 SEND S\" 70 EMIT\" 12 SEND ; TRIO"), "DEF") == 0, + "it sends node 12 three texts, the first slow to do: node 10 keeps the other two until node 12 reads again, and they are done in order: \"%s\"", printed); + CHECK(is_empty(tell(11, "12 3 ROUTE")) && waiting(hera) && waiting(mid) && waiting(far) && pool[0].n.mem[MQ_COUNT] == 0, "the way is told again; all three are at rest, keeping nothing"); + /* ---- a node that is stuck holds up no one (MESH.md 7c) ------------------- */ v4_fabric_gone_error(&f, V4_ERROR_NO_ONE); @@ -406,7 +413,7 @@ int main(void) /* a refusal owed to a stuck node whose number is the lower */ CHECK(is_empty(said(12, "NO-ROUTES 1 3 ROUTE 10 3 ROUTE 11 2 ROUTE")) && is_empty(said(11, "55 3 ROUTE")), "node 12 has no way for 55; node 11 is told the way to 55 is by node 12"); - CHECK(strcmp(tell(11, ": C1 S\" 1 DROP\" 55 SEND BEGIN 0 UNTIL ; C1"), "(still running)") == 0, "node 11 sends 55 a message and is then stuck in a loop"); + CHECK(strcmp(tell(11, ": C1 S\" 1 DROP\" 55 SEND S\" 1 DROP\" 12 SEND BEGIN 0 UNTIL ; C1"), "(still running)") == 0, "node 11 sends 55 a message, and node 12 text, and is then stuck in a loop"); CHECK(pool[2].n.mem[OWED_COUNT] == 1, "node 12 owes node 11 a refusal, and cannot give it: node 11 is not reading"); CHECK(strcmp(said(12, "7 8 * ."), "56 ") == 0 && printed_from == 12, "node 12 goes on doing what it is sent: \"%s\"", printed); { @@ -423,6 +430,18 @@ int main(void) "node 10 sends 77 a message and waits: node 12, which still owes the stuck node, tells node 10 it was refused: \"%s\"", printed); CHECK(is_empty(said(10, "77 NO-ROUTE")), "the way is forgotten"); + /* a message passed on toward the stuck node waits with the node passing it on, which goes on serving */ + { + v4_cell kept = pool[0].n.mem[MQ_COUNT]; + CHECK(is_empty(said(11, "1 DROP")) && ended == 0 && pool[0].n.mem[MQ_COUNT] > kept && v4_node_in_wait(&pool[0].n), + "text from the console for the stuck node comes to node 10, which cannot hand it on: it keeps it, offered, and sleeps"); + CHECK(strcmp(said(10, "1 2 + ."), "3 ") == 0 && strcmp(said(12, "7 8 * ."), "56 ") == 0 && printed_from == 12, + "node 10 goes on doing what it is sent, and passing on what is for others: \"%s\"", printed); + CHECK(pool[0].n.mem[MQ_COUNT] > kept && v4_node_in_wait(&pool[0].n), "still keeping what is for the stuck node"); + } + /* the stuck node's own answer: node 12 did text node 11 sent before it stuck, and cannot give it the answer */ + CHECK(pool[2].n.mem[MQ_COUNT] > 0 && v4_node_in_wait(&pool[2].n), "node 12 keeps the answer it has for node 11, offered, and sleeps"); + /* a line that must begin a message to the stuck node waits, and the node takes in what comes */ CHECK(is_empty(said(10, ": TO11 S\" 1 DROP\" 11 SEND 65 EMIT ; TO11")) && ended == 0 && v4_node_in_wait(&pool[0].n) && !pool[0].n.asking, "node 10 sends the stuck node a message: its line waits in the wait, not blocked writing"); @@ -447,8 +466,8 @@ int main(void) CHECK(strstr(printed, "No one on that port") != NULL && strstr(printed, "A") == NULL && ended == 1, "the line ends in an error that says no one is there: \"%s\"", printed); } step_cap = 20000000; - CHECK(strcmp(said(12, "7 8 * ."), "56 ") == 0 && pool[2].n.mem[OWED_COUNT] == 0 && waiting(far) && !v4_node_in_wait(&pool[2].n) && waiting(hera), - "node 12 goes on, the refusal it owed node 11 let go: it owes nothing and is at rest"); + CHECK(strcmp(said(12, "7 8 * ."), "56 ") == 0 && pool[2].n.mem[OWED_COUNT] == 0 && pool[2].n.mem[MQ_COUNT] == 0 && pool[0].n.mem[MQ_COUNT] == 0 && waiting(far) && !v4_node_in_wait(&pool[2].n) && waiting(hera), + "node 12 goes on; what it owed node 11 and kept for it, and what node 10 kept for it, are let go: they owe and keep nothing, and are at rest"); /* a refusal owed to a stuck node whose number is the higher */ step_cap = 3000000; diff --git a/v4/tests/test_host_quit.c b/v4/tests/test_host_quit.c index b9a5e1a2..e5ff6d8d 100644 --- a/v4/tests/test_host_quit.c +++ b/v4/tests/test_host_quit.c @@ -63,7 +63,7 @@ static v4_heat h; static v4_text tx; static v4_cell w_key, w_key_end, w_fault, capsule_latest; static v4_cell w_idle; /* (IDLE): where the node waits for a message */ -static v4_cell w_idle_end; /* (PASS-ON): the word after it */ +static v4_cell w_idle_end; /* (LINE): the word after it */ static char out[V4_CONSOLE_CAP + 1]; /* STORAGE (MESH.md section 8). The node asks its kernel for its blocks, and @@ -871,7 +871,7 @@ int main(void) printf(" capsule: %ld words\n", (long)v4_text_here(&tx) - 16); if (failures) { printf(" %d checks, %d failures\n", checks, failures); return 1; } w_idle = v4_text_word(&tx, "(IDLE)"); - w_idle_end = v4_text_word(&tx, "(PASS-ON)"); /* the word after (IDLE) in quit.v4 */ + w_idle_end = v4_text_word(&tx, "(LINE)"); /* the word after (IDLE) in quit.v4 */ w_key = v4_text_word(&tx, "KEY"); w_key_end = v4_text_word(&tx, "CR"); /* the word after KEY in core.v4 */ w_fault = v4_text_word(&tx, "(FAULTS)"); diff --git a/v4/tests/test_host_unit.c b/v4/tests/test_host_unit.c index f988783f..ff5e38a1 100644 --- a/v4/tests/test_host_unit.c +++ b/v4/tests/test_host_unit.c @@ -530,7 +530,16 @@ int main(void) CHECK(strcmp(tell(13, ": SPIN BEGIN 0 UNTIL ; SPIN"), "(still running)") == 0, "node 13 is stuck in a loop"); CHECK(strcmp(tell(12, ": W13 13 AWAIT . ; W13"), "(still running)") == 0 && node_numbered(12)->mem[AWAIT_FROM] == 13 && waiting(12), "node 12, which is not wired to it, waits for its answer"); + /* while it is stuck it holds up no one (MESH.md 7c): text for it waits with Hera, who goes on */ + (void)tell(13, "1 DROP"); + CHECK(ended == 0 && v4_node_in_wait(node_numbered(10)) && !node_numbered(10)->asking && node_numbered(10)->mem[MQ_COUNT] > 0, + "text typed for the stuck node waits with Hera, offered: she sleeps in the wait, not blocked writing"); + (void)tell(11, "11 100 * ."); + CHECK(strcmp(printed, "1100 ") == 0 && ended == 1, "text typed for another node is passed on and done meanwhile: \"%s\"", printed); + (void)tell(10, "1 2 + ."); + CHECK(strcmp(printed, "3 ") == 0 && ended == 1, "and so is text for Hera herself: \"%s\"", printed); (void)tell(10, "13 KILL"); + CHECK(node_numbered(10)->mem[MQ_COUNT] == 0, "killing it, she lets go what she kept for it"); CHECK(node_numbered(13) == NULL && strstr(printed, "Node gone") != NULL && node_numbered(12)->mem[AWAIT_FROM] == 0 && waiting(12), "Hera kills node 13: node 12's wait ends, with an error that says the node is gone: \"%s\"", printed); step_limit = 30000000ul;