feat(v4.0.0): a refused message is told to its sender -- NACK and GONE

A node that has no room for a message, or no way to pass it on, lets it
go and counts it as before, and now notes that it owes its sender a NACK
(type 4: the node the message was for).  It sends what it owes when it
next has nothing else to do.  36 cells of the messages waiting are kept
for NACK and GONE, and nothing is owed for either.

A node sent a NACK counts it in (REFUSED); one waiting for an answer from
that node (AWAIT) stops, with error 19, Message refused.  A GONE (type 5)
from a node's centre makes it forget the way to the node named (NO-ROUTE,
new), and ends a wait on it with error 20, Node gone.  From anyone else
it is ignored.  GONE ( n node -- ) sends one.

test_host_mesh.c, three nodes: text for a node nobody has a way to comes
back to the console, and to a node two away, as a NACK; a waiting sender's
line ends Message refused; a node that is waiting keeps what it has room
for, owes eight refusals, counts the rest, and sends them when its wait is
ended by a GONE from its centre.  70 checks, both widths, sanitizers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-07 19:58:27 -04:00
co-authored by Claude Opus 5.5
parent 6e1ac157c6
commit 9efe8aad3a
5 changed files with 184 additions and 14 deletions
+46 -4
View File
@@ -21,6 +21,8 @@
\ 13 Block out of range 14 No block is being loaded
\ 15 Deferred word not set 16 Not a word
\ 17 Storage refused 18 No one on that port
\ 19 Message refused 20 Node gone
\ 21 Interrupted
\ -1 the word has printed its own message
macro SWAP over push push drop pop pop endmacro
@@ -182,6 +184,27 @@ header CMOVE
SET: (MQ-HEAD) a! !
(MQ#) a! @ -1 + ! ;
\ REFUSALS (MESH.md section 7b). A message this node has no room for, or
\ no way to pass on, is let go and counted in (LOST); and its sender is
\ told, by a message of type 4, a NACK, whose one word is the node the
\ refused message was for. A node finds it has no room while it is taking
\ 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
\ 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
\ messages cannot take all the room.
\ ( to about -- ) a refusal is owed to the node `to`, about the node `about`
: (OWE)
(OWED#) a! @ -8 + -if NOROOM
drop (OWED#) a! @ 2* (OWED) + a!
push !+ pop !
(OWED#) a! @ 1 + ! ;
NOROOM: drop drop drop (LOST) a! @ 1 + ! ;
\ ( port to -- ) the seven words of a message being taken in, and the
\ port, go into (MQ-HDR). B is at the port, by its address, and `to` is
\ the message's first word, already read from it.
@@ -199,15 +222,22 @@ header CMOVE
SIZED: dup -1025 + -if LONG drop 3 + 2/ 2/ jump COUNTED
LONG: drop 3 + 2/ 2/ -1 + FOR @b drop UNEXT -1 (MQ-HDR)+6 a! ! 0
COUNTED: \ ( n ) how many words of text follow
dup (MQ#) a! @ + -MQ-ROOM + -if FULL
dup (MQ#) a! @ + \ what it would come to
(MQ-HDR)+2 a! @ -4 + -if KEPT-FOR \ a NACK or a GONE may use the room kept for them
drop -MQ-ORDINARY + jump ROOM
KEPT-FOR: drop -MQ-ROOM +
ROOM: -if FULL
drop push
(MQ-HDR) a! @ (MQ!) (MQ-HDR)+1 a! @ (MQ!) (MQ-HDR)+2 a! @ (MQ!) (MQ-HDR)+3 a! @ (MQ!)
(MQ-HDR)+4 a! @ (MQ!) (MQ-HDR)+5 a! @ (MQ!) (MQ-HDR)+6 a! @ (MQ!) (MQ-HDR)+7 a! @ (MQ!)
pop if NOTEXT -1 + FOR @b (MQ!) NEXT ;
NOTEXT: drop ;
FULL: drop if GONE -1 + FOR @b drop UNEXT jump LOSE
GONE: drop
LOSE: (LOST) a! @ 1 + ! ;
FULL: drop if READ -1 + FOR @b drop UNEXT jump LOSE
READ: drop
LOSE: (LOST) a! @ 1 + !
(MQ-HDR)+2 a! @ -4 + -if NOT-OWED \ nothing is owed for a NACK or a GONE
drop (MQ-HDR)+1 a! @ (MQ-HDR) a! @ jump (OWE) \ to whoever sent it, about whom it was for
NOT-OWED: drop ;
\ ( port to -- ) take in a message and keep it
: (TAKE) (TAKE-HDR) jump (TAKE-KEEP)
@@ -238,6 +268,18 @@ header CMOVE
!b \ type
0 !b 0 !b 0 !b ; \ heat and TTL, ACL tag, sequence
\ ( -- ) send one refusal this node owes, if it owes any: the one noted
\ last. With no way to whom it is owed, it is let go and counted.
: (PAY)
(OWED#) a! @ if NONE
-1 + dup !
2* (OWED) + a! @+ @ \ to about
over (PORT-FOR) if NOWAY
(GATE) over !b \ to
4 (HDR) 4 !b !b drop ; \ from, type 4; four characters; about
NOWAY: drop drop drop (LOST) a! @ 1 + ! ;
NONE: drop ;
\ ( -- ) 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
\ lowest. quit.v4 sets those two when text for this node arrives.