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:
co-authored by
Claude Opus 5.5
parent
6e1ac157c6
commit
9efe8aad3a
+46
-4
@@ -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.
|
||||
|
||||
+68
-8
@@ -78,7 +78,8 @@ macro R-CLEAR RSTACK-DEPTH b! a !b endmacro
|
||||
\ line was, and (FINISH) reports how it ended. A message for another node
|
||||
\ is passed on, (PASS-ON).
|
||||
: (IDLE)
|
||||
L: (MQ#) a! @ if WAIT drop jump HAVE
|
||||
L: (PAY) \ a refusal owed is sent first (core.v4)
|
||||
(MQ#) a! @ if WAIT drop jump HAVE
|
||||
WAIT: 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:
|
||||
@@ -96,7 +97,12 @@ macro R-CLEAR RSTACK-DEPTH b! a !b endmacro
|
||||
(MSG)+6 a! @ SPAN a! !
|
||||
(MSG) a! @ (ME) a! @ xor if MINE drop jump (PASS-ON)
|
||||
MINE: drop
|
||||
(MSG)+2 a! @ -1 + if TEXT drop jump (IDLE) \ for this node and not text: let go
|
||||
(MSG)+2 a! @ -1 + if TEXT \ for this node, and
|
||||
-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 (REPLY) a! @ (ROUTE-DEFAULT) a! @ xor if CENTRE \ a node is gone, if its centre says so:
|
||||
drop jump (IDLE)
|
||||
CENTRE: drop TIB 2/ 2/ a! @ NO-ROUTE jump (IDLE) \ the way to it is forgotten
|
||||
TEXT: drop
|
||||
(MSG)+1 a! @ (PORT-FOR) if D0 jump D1 \ the way back to whoever sent it:
|
||||
D0: drop (REPLY) a! @ \ the port it came on, if no other is known
|
||||
@@ -119,7 +125,10 @@ macro R-CLEAR RSTACK-DEPTH b! a !b endmacro
|
||||
-1 + TIB 2/ 2/ a! FOR @+ !b UNEXT \ and its text
|
||||
jump (IDLE)
|
||||
SENT: drop jump (IDLE)
|
||||
NOWAY: drop (LOST) a! @ 1 + ! jump (IDLE)
|
||||
NOWAY: drop (LOST) a! @ 1 + !
|
||||
(MSG)+2 a! @ -4 + -if NOT-OWED \ its sender is told, unless it is a NACK or a GONE
|
||||
drop (MSG)+1 a! @ (MSG) a! @ (OWE) jump (IDLE)
|
||||
NOT-OWED: drop jump (IDLE)
|
||||
|
||||
\ ( -- ) 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
|
||||
@@ -160,6 +169,35 @@ header NEIGHBOUR
|
||||
header DEFAULT-ROUTE
|
||||
: DEFAULT-ROUTE (PORT) + (ROUTE-DEFAULT) a! ! ;
|
||||
|
||||
\ ( node -- ) forget the way to that node, if one is known: what is for it
|
||||
\ then goes by the way for every node not told of, if there is one. The
|
||||
\ last way in the table takes its place.
|
||||
header NO-ROUTE
|
||||
: NO-ROUTE
|
||||
(ROUTE#) a! @ if NONE -1 + (ROUTES) a!
|
||||
FOR dup @+ xor if HIT drop @+ drop NEXT
|
||||
drop ;
|
||||
NONE: drop drop ;
|
||||
HIT: drop drop pop drop
|
||||
a -1 + push \ where its entry is
|
||||
(ROUTE#) a! @ -1 + dup ! \ one way fewer
|
||||
2* (ROUTES) + a! @+ @ \ the last entry: node port
|
||||
pop a! SWAP !+ ! ;
|
||||
|
||||
\ ( about node type -- ) send the node a message of one word, `about`:
|
||||
\ a NACK is type 4, a GONE type 5 (MESH.md 7b). With no way to the node
|
||||
\ it is error 12.
|
||||
: (SEND1)
|
||||
push dup (PORT-FOR) if NOWAY
|
||||
(GATE) !b 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
|
||||
\ if this node is its centre: it forgets the way to n, and if it is waiting
|
||||
\ for n's answer the wait ends.
|
||||
header GONE
|
||||
: GONE 5 jump (SEND1)
|
||||
|
||||
\ ( -- ) forget every way: for when the wiring has changed
|
||||
header NO-ROUTES
|
||||
: NO-ROUTES 0 (ROUTE#) a! ! 0 (ROUTE-DEFAULT) a! ! ;
|
||||
@@ -197,17 +235,34 @@ header SEND-ON
|
||||
\ ( node -- how ) WAIT FOR THE NODE'S WORD OF HOW TEXT ENDED: 0 QUIT,
|
||||
\ 1 completed, 2 an error. This node is blocked reading its ports until a
|
||||
\ message of type 3 comes for it from that node; every other message that
|
||||
\ comes meanwhile is kept with the messages waiting. It waits for ever
|
||||
\ for a node that never answers.
|
||||
\ comes meanwhile is kept with the messages waiting. (AWAIT-FROM) holds the
|
||||
\ node while it waits, and 0 otherwise.
|
||||
\ THE WAIT ALSO ENDS, in an error, when the answer is not going to come
|
||||
\ (MESH.md section 7b): a NACK about that node, error 19, Message refused;
|
||||
\ or a GONE about it from this node's centre, error 20, Node gone. A NACK
|
||||
\ about another node is counted, and a GONE about another has its way
|
||||
\ forgotten, as they would be if this node were not waiting.
|
||||
header AWAIT
|
||||
: AWAIT
|
||||
(AWAIT-FROM) a! !
|
||||
L: (PORT)+8 b! @b (PORT)+9 b! @b (PORT) + dup b! SWAP (TAKE-HDR)
|
||||
(MQ-HDR) a! @ (ME) a! @ xor if A1 drop jump KEEP
|
||||
A1: drop (MQ-HDR)+2 a! @ -3 + if A2 drop jump KEEP
|
||||
A2: drop (MQ-HDR)+1 a! @ (AWAIT-FROM) a! @ xor if A3 drop jump KEEP
|
||||
A1: drop (MQ-HDR)+2 a! @ \ for this node: its type
|
||||
-3 + if ANSWER -1 + if NACK -1 + if GONE drop jump KEEP
|
||||
ANSWER: drop (MQ-HDR)+1 a! @ (AWAIT-FROM) a! @ xor if A3 drop jump KEEP
|
||||
A3: drop (MQ-HDR)+6 a! @ -4 + if A4 drop jump KEEP
|
||||
A4: drop @b ; \ its one word
|
||||
A4: drop 0 (AWAIT-FROM) a! ! @b ; \ its one word
|
||||
NACK: drop (MQ-HDR)+6 a! @ -4 + if N4 drop jump KEEP
|
||||
N4: drop @b (AWAIT-FROM) a! @ xor if REFUSED \ about the node waited for?
|
||||
drop (REFUSED) a! @ 1 + ! jump L \ another: counted
|
||||
REFUSED: drop 0 (AWAIT-FROM) a! ! NODE-ERROR b! 19 !b ;
|
||||
GONE: drop (MQ-HDR)+6 a! @ -4 + if G4 drop jump KEEP
|
||||
G4: drop @b \ the node that is gone
|
||||
(MQ-HDR)+7 a! @ (ROUTE-DEFAULT) a! @ xor if CENTRE \ only its centre is believed
|
||||
drop drop jump L
|
||||
CENTRE: drop dup NO-ROUTE
|
||||
(AWAIT-FROM) a! @ xor if LEFT drop jump L
|
||||
LEFT: drop 0 (AWAIT-FROM) a! ! NODE-ERROR b! 20 !b ;
|
||||
KEEP: (TAKE-KEEP) jump L
|
||||
|
||||
\ ( w port -- ) write a cell to the port, by its number. It waits until
|
||||
@@ -239,6 +294,7 @@ header NODE-ERROR inline : NODE-ERROR' NODE-ERROR ;
|
||||
header (ME) inline : (ME)' (ME) ;
|
||||
header (CONSOLE) inline : (CONSOLE)' (CONSOLE) ;
|
||||
header (LOST) inline : (LOST)' (LOST) ;
|
||||
header (REFUSED) inline : (REFUSED)' (REFUSED) ;
|
||||
header (WORD-DEFINED) inline : (WORD-DEFINED)' (WORD-DEFINED) ;
|
||||
header (WORD-FORGOTTEN) inline : (WORD-FORGOTTEN)' (WORD-FORGOTTEN) ;
|
||||
|
||||
@@ -285,6 +341,7 @@ header ABORT
|
||||
-1 + if M5 -1 + if M6 -1 + if M7 -1 + if M8 -1 + if M9
|
||||
-1 + if M10 -1 + if M11 -1 + if M12 -1 + if M13 -1 + if M14
|
||||
-1 + if M15 -1 + if M16 -1 + if M17 -1 + if M18
|
||||
-1 + if M19 -1 + if M20 -1 + if M21
|
||||
drop 2 jump (DONE)
|
||||
M1: drop $6167654E (EMIT4) $65766974 (EMIT4) $756F6320 (EMIT4) $746E (EMIT4) CR 2 jump (DONE)
|
||||
M2: drop $20746F4E (EMIT4) $756E2061 (EMIT4) $7265626D (EMIT4) CR 2 jump (DONE)
|
||||
@@ -304,6 +361,9 @@ header ABORT
|
||||
M16: drop $20746F4E (EMIT4) $6F772061 (EMIT4) $6472 (EMIT4) CR 2 jump (DONE)
|
||||
M17: drop $726F7453 (EMIT4) $20656761 (EMIT4) $75666572 (EMIT4) $646573 (EMIT4) CR 2 jump (DONE)
|
||||
M18: drop $6F206F4E (EMIT4) $6F20656E (EMIT4) $6874206E (EMIT4) $70207461 (EMIT4) $74726F (EMIT4) CR 2 jump (DONE)
|
||||
M19: drop $7373654D (EMIT4) $20656761 (EMIT4) $75666572 (EMIT4) $646573 (EMIT4) CR 2 jump (DONE)
|
||||
M20: drop $65646F4E (EMIT4) $6E6F6720 (EMIT4) $65 (EMIT4) CR 2 jump (DONE)
|
||||
M21: drop $65746E49 (EMIT4) $70757272 (EMIT4) $646574 (EMIT4) CR 2 jump (DONE)
|
||||
|
||||
\ The table the loader gives the node: six words, one for each kind of
|
||||
\ fault in the node's order, each a jump. A jump fills its word, so they
|
||||
|
||||
Reference in New Issue
Block a user