feat(v4.0.0): a node is sent text as a message and sends back what it prints
MESH.md step 3. The ports are the transport; the message is what is transported: to, from, type, heat and TTL, ACL tag, sequence, length, then text four characters to a word. - quit.v4: a node with nothing to do is blocked reading "any port"; text for it is interpreted; (FINISH) sends what it printed and then how the text ended, and it waits again - core.v4: EMIT keeps what is printed, (FLUSH-OUT) and (HDR) send it to the sender on the port the message came on. EMIT still needs one free data cell and no more; it works on the return stack and in A and B - message.h/.c: the same format for whatever is on a port and is not a node - boot.c: the boot is the node's console on port 1 and its kernel on port 0 - the prompt tests are a console that speaks messages - gone: v4_line_begin, v4_line_done, v4_line_status; writing a node's input buffer and setting its P from outside; any use of CONSOLE-TX Verified: make -C v4 test (test_host_quit.c 1283 checks, the full-stack figures unchanged) and make -C v4 sanitize pass; hosted-check passes on three ISAs with POST 550 of 550; clean qemu with STARFORTH_V4=1 passes POST and answers lines typed at each prompt on amd64, aarch64 and riscv64 (logs/20261006-110551, -111621, -111341). -110837 is an aarch64 run ended by the test wrapper's limit while still in UEFI firmware; it shows nothing about v4. Not done: KEY, EXPECT and QUERY still read the console's input registers; a message not for this node is let go (step 4). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
42610e844f
commit
a041b401ea
@@ -33,6 +33,7 @@
|
||||
#define V4_BOOT_H
|
||||
|
||||
#include "v4/image.h"
|
||||
#include "v4/message.h"
|
||||
|
||||
typedef struct {
|
||||
v4_node *n;
|
||||
@@ -66,8 +67,9 @@ typedef struct {
|
||||
int v4_boot_run(const v4_boot *b, unsigned char *disk, unsigned blocks);
|
||||
|
||||
/* Hand the node a line and run it to its end, sending what it prints to
|
||||
* `out`. Returns how it ended -- V4_LINE_QUIT, V4_LINE_COMPLETED or
|
||||
* V4_LINE_ERROR (image.h) -- or one of these: */
|
||||
* `out`. The line is sent to the node as a message and what it prints
|
||||
* comes back as messages (message.h). Returns how it ended -- V4_TEXT_QUIT,
|
||||
* V4_TEXT_COMPLETED or V4_TEXT_ERROR -- or one of these: */
|
||||
#define V4_BOOT_LINE_TOO_LONG (-1) /* more than the node's input buffer holds; nothing was run */
|
||||
#define V4_BOOT_LINE_STOPPED (-2) /* the node stopped on a fault, or never finished */
|
||||
#define V4_BOOT_LINE_NO_INPUT (-3) /* the line read the keyboard and there is no more input */
|
||||
|
||||
+8
-30
@@ -10,6 +10,10 @@
|
||||
* (capsules/v4/nucleus-<width>.f18). docs/v4.0.0/MESH.md section 5.
|
||||
* - this description of it, a C file: the addresses a host needs.
|
||||
*
|
||||
* A node that has taken the nucleus in is sent text as messages and sends
|
||||
* back what it prints (v4/include/v4/message.h); nothing here hands it a
|
||||
* line.
|
||||
*
|
||||
* A description is for one cell width, one node size and one pair of stack
|
||||
* sizes; v4_image_born refuses one the engine was not built for.
|
||||
*/
|
||||
@@ -22,16 +26,10 @@ typedef struct {
|
||||
/* what the image was built for */
|
||||
unsigned cell_bits, node_words, data_ring, ret_ring;
|
||||
|
||||
/* The node is handed a line (docs/v4.0.0/ENGINE.md 3.1). Its host puts
|
||||
* text in the input buffer and starts it at `line`; it stops at `idle`,
|
||||
* with how the line ended in the cell `line_status`. At switch-on it
|
||||
* is at `idle`. */
|
||||
v4_cell line; /* (LINE) */
|
||||
v4_cell idle; /* (IDLE) */
|
||||
v4_cell line_status; /* word address of the variable (LINE-STATUS) */
|
||||
v4_cell tib; /* byte address of the input buffer */
|
||||
unsigned tib_bytes; /* its size: a line may be one less */
|
||||
v4_cell span; /* word address of the variable SPAN */
|
||||
/* Where the nucleus waits for a message (v4/capsule/quit.v4, (IDLE)):
|
||||
* the node's P is there, blocked reading its ports, when it has nothing
|
||||
* to do. */
|
||||
v4_cell idle;
|
||||
v4_cell fault_table; /* (FAULTS): where a fault goes */
|
||||
v4_cell port; /* word address of the node's port (node.h) */
|
||||
|
||||
@@ -67,11 +65,6 @@ extern const v4_image v4_capsule_image;
|
||||
* back to, and FORGET will not go below it. */
|
||||
void v4_image_seal(v4_node *n, const v4_image *im);
|
||||
|
||||
/* How a line ended. */
|
||||
#define V4_LINE_QUIT 0 /* QUIT: nothing is to be said */
|
||||
#define V4_LINE_COMPLETED 1 /* the host says " ok" */
|
||||
#define V4_LINE_ERROR 2 /* the message is printed; the host says " ERROR" */
|
||||
|
||||
/* A node newly born (node.h), with the registers the nucleus expects of the
|
||||
* node it runs on -- and `disk`, `blocks` blocks of 1024 bytes, as its block
|
||||
* storage, or none if `disk` is 0. Its memory is empty and it is blocked
|
||||
@@ -81,21 +74,6 @@ void v4_image_seal(v4_node *n, const v4_image *im);
|
||||
int v4_image_born(v4_node *n, v4_exec_state *es, v4_heat *h, const v4_image *im,
|
||||
unsigned char *disk, unsigned blocks);
|
||||
|
||||
/* Hand the node `len` characters of text to interpret. Returns 1, or 0 if
|
||||
* the text is longer than the node's input buffer holds (nothing is then
|
||||
* done). After it the host runs the node -- v4_exec_step_word again and
|
||||
* again, taking what the node prints from n->console and setting
|
||||
* n->console_len back to 0 -- until v4_line_done; if v4_image_waiting comes
|
||||
* first, the line is reading the keyboard, and the host gives it characters
|
||||
* with v4_node_console_feed. */
|
||||
int v4_line_begin(v4_node *n, const v4_image *im, const char *text, unsigned len);
|
||||
|
||||
/* 1 when the node has finished the line it was handed and is idle again. */
|
||||
int v4_line_done(const v4_node *n, const v4_image *im);
|
||||
|
||||
/* How the line just finished ended: V4_LINE_QUIT, _COMPLETED or _ERROR. */
|
||||
int v4_line_status(const v4_node *n, const v4_image *im);
|
||||
|
||||
/* 1 if the node is waiting for a character: it is inside KEY and none is
|
||||
* pending. */
|
||||
int v4_image_waiting(const v4_node *n, const v4_image *im);
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/* message.h -- a message, as it is written to a port and read from one.
|
||||
* docs/v4.0.0/MESH.md section 6.
|
||||
*
|
||||
* The ports are the transport; the message is what is transported. It is
|
||||
* v3's Hermes message with what it carries, a word at a time:
|
||||
*
|
||||
* word 0 to: the node it is for
|
||||
* word 1 from: the node that sent it
|
||||
* word 2 type
|
||||
* word 3 heat and TTL
|
||||
* word 4 ACL tag: the sender's identity fingerprint
|
||||
* word 5 sequence
|
||||
* word 6 how many characters of text follow, 0 to 1024
|
||||
* word 7.. the text, four characters to a word, the first lowest
|
||||
*
|
||||
* Words 3, 4 and 5 are carried and not yet used: checking them is the
|
||||
* router's, and awaits rulings (MESH.md section 3).
|
||||
*
|
||||
* This is for whatever is on the other end of a node's port and is not a
|
||||
* node -- a console, a host -- to speak what the nodes speak (v4/capsule/
|
||||
* core.v4 and quit.v4 are the same thing in the node). Nothing here uses
|
||||
* the C library.
|
||||
*/
|
||||
#ifndef V4_MESSAGE_H
|
||||
#define V4_MESSAGE_H
|
||||
|
||||
#include "v4/cell.h"
|
||||
|
||||
#define V4_MSG_HEADER 7u
|
||||
#define V4_MSG_MAX_CHARS 1024u /* a block */
|
||||
#define V4_MSG_MAX_WORDS (V4_MSG_HEADER + V4_MSG_MAX_CHARS / 4u)
|
||||
|
||||
#define V4_MSG_TEXT 1 /* text to be interpreted */
|
||||
#define V4_MSG_OUTPUT 2 /* what a node printed */
|
||||
#define V4_MSG_DONE 3 /* how the text ended: one word, V4_TEXT_* */
|
||||
|
||||
/* how text ended */
|
||||
#define V4_TEXT_QUIT 0 /* QUIT: nothing is to be said */
|
||||
#define V4_TEXT_COMPLETED 1 /* a console says " ok" */
|
||||
#define V4_TEXT_ERROR 2 /* the message is printed; a console says " ERROR" */
|
||||
|
||||
typedef struct {
|
||||
v4_cell word[V4_MSG_MAX_WORDS];
|
||||
unsigned count; /* words in it */
|
||||
} v4_message;
|
||||
|
||||
/* A message of `len` characters, at most V4_MSG_MAX_CHARS. Returns how many
|
||||
* words it is, or 0 if `len` is too many. */
|
||||
unsigned v4_message_text(v4_message *m, v4_cell to, v4_cell from, v4_cell type, const char *chars, unsigned len);
|
||||
|
||||
/* A message arriving a word at a time. Start with m->count = 0 and give
|
||||
* each word as it comes: returns 1 when the message is whole, 0 if there is
|
||||
* more to come. A length that is not 0 to V4_MSG_MAX_CHARS is taken as 0. */
|
||||
int v4_message_word(v4_message *m, v4_cell word);
|
||||
|
||||
/* Its parts. */
|
||||
#define v4_message_to(m) ((m)->word[0])
|
||||
#define v4_message_from(m) ((m)->word[1])
|
||||
#define v4_message_type(m) ((m)->word[2])
|
||||
unsigned v4_message_length(const v4_message *m); /* characters of text */
|
||||
char v4_message_char(const v4_message *m, unsigned i); /* the i-th of them */
|
||||
|
||||
#endif /* V4_MESSAGE_H */
|
||||
Reference in New Issue
Block a user