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:
rajames
2026-10-06 11:19:46 -04:00
co-authored by Claude Opus 5.5
parent 42610e844f
commit a041b401ea
24 changed files with 844 additions and 178 deletions
+2 -2
View File
@@ -67,9 +67,9 @@ int main(void)
len = strlen(line);
if (len && line[len - 1] == '\n') len--;
how = v4_boot_line(&boot, line, (unsigned)len);
if (how == V4_LINE_COMPLETED) fputs(" ok\n", stdout);
if (how == V4_TEXT_COMPLETED) fputs(" ok\n", stdout);
if (leaving) { fflush(stdout); return 0; }
else if (how == V4_LINE_ERROR) fputs(" ERROR\n", stdout);
else if (how == V4_TEXT_ERROR) fputs(" ERROR\n", stdout);
else if (how == V4_BOOT_LINE_TOO_LONG) fputs("Line too long\n ERROR\n", stdout);
else if (how == V4_BOOT_LINE_NO_INPUT) { putchar('\n'); return 0; }
else if (how == V4_BOOT_LINE_STOPPED) { fflush(stdout); fprintf(stderr, "starforth4: the node stopped on a fault\n"); return 1; }
+4 -5
View File
@@ -52,7 +52,7 @@ int main(int argc, char **argv)
static const char *const files[] = { "core.v4", "input.v4", "dict.v4", "codegen.v4", "compile.v4", "quit.v4", "forth.v4",
"numout.v4", "words.v4", "system.v4", "qmath.v4", "blocks.v4", "log.v4", "acl.v4" };
FILE *out;
v4_cell k, line, idle, faults, voc;
v4_cell k, idle, faults, voc;
unsigned count = 0;
if (argc != 3) die("usage: mkimage DESCRIPTION.c CAPSULE.f18", NULL);
@@ -60,7 +60,6 @@ int main(int argc, char **argv)
if (!host_load(&tx, &n, files, (unsigned)(sizeof files / sizeof files[0]))) die("the capsule does not assemble", NULL);
if (!v4_text_finish(&tx)) die("not everything is defined", v4_text_error(&tx));
if (v4_text_here(&tx) >= DICT_W) die("the capsule's code runs into the dictionary space", NULL);
line = v4_text_word(&tx, "(LINE)");
idle = v4_text_word(&tx, "(IDLE)");
faults = v4_text_word(&tx, "(FAULTS)");
w_key = v4_text_word(&tx, "KEY");
@@ -99,7 +98,8 @@ int main(int argc, char **argv)
for (voc = n.mem[VOC_LINK]; voc != 0; voc = n.mem[voc + 1]) clear_acl(n.mem[voc]);
if (!v4_node_guards_intact(&n)) die("the node's guards are damaged", NULL);
n.mem[LINE_STATUS] = V4_LINE_COMPLETED; /* idle, with nothing to report */
n.mem[LINE_STATUS] = 1; /* nothing has ended badly */
n.mem[OUT_PTR] = OUT_W; /* nothing has been printed */
/* the nucleus as a capsule of F18 code: the words a neighbour writes to
* an empty node's port, each in V4_CELL_BITS / 8 bytes, low byte first */
@@ -113,8 +113,7 @@ int main(int argc, char **argv)
fprintf(out, "/* Generated by v4/tools/mkimage.c from v4/capsule -- do not edit. */\n#include \"v4/image.h\"\n\n");
fprintf(out, "const v4_image v4_capsule_image = {\n %uu, %uu, %uu, %uu,\n",
(unsigned)V4_CELL_BITS, (unsigned)V4_NODE_WORDS, (unsigned)V4_DATA_RING, (unsigned)V4_RET_RING);
fprintf(out, " %ld, %ld, %ld,\n %ld, %uu, %ld,\n %ld, %ld,\n %ld, %ld,\n", (long)line, (long)idle, (long)LINE_STATUS,
(long)TIB, 1025u, (long)SPAN, (long)faults, (long)PORT, (long)w_key, (long)w_key_end);
fprintf(out, " %ld,\n %ld, %ld,\n %ld, %ld,\n", (long)idle, (long)faults, (long)PORT, (long)w_key, (long)w_key_end);
fprintf(out, " %ld, %ld, %ld,\n %ld, %ld,\n %ld,\n %ld,\n %ld, %ld,\n %ld, %ld\n};\n", (long)CONSOLE_TX, (long)CONSOLE_RX, (long)CONSOLE_ST,
(long)DSTACK_REG, (long)RSTACK_REG, (long)NODE_ERROR, (long)STORAGE_REG, (long)DP, (long)LATEST,
(long)BOOT_CELLS, (long)FENCE);