feat(v4.0.0): every message begins through the wait -- a stuck node holds up no one

(GATE) offers a message's first word and sleeps until it is taken, taking
in whatever is written to the node meanwhile; (PAY) offers every refusal
owed at once, one to a port; a node that owes one sleeps in the wait.
Writing without looking, looking again and again, and the lower-number
rule are gone.  Text from the console for a node whose own text waits to
begin a message ends that text Interrupted.  The lone node's hosts serve
an offer as a write.  MESH.md 7c; plan step 6d task 2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-07 23:38:07 -04:00
co-authored by Claude Opus 5.5
parent 075385ab63
commit 482cc75faf
8 changed files with 188 additions and 113 deletions
+9 -13
View File
@@ -58,7 +58,7 @@ macro R-CLEAR RSTACK-DEPTH b! a !b endmacro
1 (QUIET) a! ! \ from here an error is not this text's: see (RAISED)
(LINE-STATUS) b! dup !b
(FLUSH-OUT)
(DONE-PORT) a! @ (GATE) (MSG)+1 a! @ !b \ to whoever sent the text
(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
jump (IDLE)
@@ -80,12 +80,8 @@ macro R-CLEAR RSTACK-DEPTH b! a !b endmacro
\ is passed on, (PASS-ON).
: (IDLE)
L: 1 (QUIET) a! ! \ nothing here is any text's doing: see (RAISED)
(PAY) \ what refusals can be sent now, are (core.v4)
(MQ#) a! @ if WAIT drop jump HAVE
WAIT: drop (OWED#) a! @ if BLOCK \ with one still owed it does not sleep:
drop (WRITERS) b! @b if L0 \ it takes in whatever is being written to it,
(LOW) (PORT) + dup b! @b (TAKE) jump L
L0: drop jump L \ and tries again
WAIT: drop (PAY) if BLOCK drop jump L \ what it owes is offered, and it sleeps (core.v4)
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:
@@ -131,7 +127,7 @@ macro R-CLEAR RSTACK-DEPTH b! a !b endmacro
COUNT: -1 + if SPENT (MSG)+3 a! !
(MSG) a! @ (PORT-FOR) if NOWAY
dup (THERE) if NOONE drop
(GATE) (MSG) a! 6 FOR @+ !b UNEXT \ its seven words
(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)
@@ -169,8 +165,8 @@ header ROUTE
\ ( node port -- ) the node on the other end of the port, by its number;
\ 0: none, or a device. Whoever wires the node tells it, and tells it again
\ when the wiring changes. It is what lets one of two neighbours, and one
\ only, wait to write to the other (core.v4, (GATE)).
\ when the wiring changes. It is how a node knows who its centre is
\ ((CENTRE)), from whom alone it believes a GONE.
header NEIGHBOUR
: NEIGHBOUR
dup -if POS jump BAD
@@ -201,7 +197,7 @@ header NO-ROUTE
\ it is error 12.
: (SEND1)
push dup (PORT-FOR) if NOWAY
(GATE) !b pop (HDR) 4 !b !b ;
(GATE) pop (HDR) 4 !b !b ;
NOWAY: drop drop drop pop drop NODE-ERROR b! 12 !b ;
\ ( n node -- ) tell the node that node n is gone. It acts on that only
@@ -216,10 +212,10 @@ header NO-ROUTES
\ ( baddr u node port -- ) send the node u characters of text to
\ interpret, by the port given, by its address. It is on its way when this
\ returns. The write waits for the neighbour to read, and is not begun
\ until it may be (core.v4, (GATE)).
\ returns. Its first word is offered until the neighbour takes it
\ (core.v4, (GATE)); the rest is written, each word waiting for it.
: (SEND-ON)
(GATE) !b \ to
(GATE) \ to
1 (HDR)
dup !b \ length
3 + 2/ 2/ if NONE -1 +