feat(v4.0.0): a node is handed a line -- ENGINE.md step 1

A v4 node no longer reads its own command line or prints a prompt.  Its
host puts a line of text in the node's input buffer and starts it at
(LINE); the node interprets it and stops at (IDLE), leaving in
(LINE-STATUS) how it ended: completed, an error, or QUIT.  The host says
" ok" or " ERROR" and prompts, as the kernel's REPL does for a v3 VM.  A
line may be 1024 characters, a block, as v3's.  Ruled 2026-10-05
(V3-PARITY.md 1b); design ENGINE.md 3.1.

- quit.v4: (REPL), the node's prompt loop, is gone; (LINE) (IDLE) (DONE)
- image.h/.c: v4_line_begin, v4_line_done, v4_line_status; the node is
  idle at switch-on
- boot.c: v4_boot_line, the one loop the hosted binary, the kernel and the
  capsule loader hand a line with; the code that took " ok" and the prompt
  back out of the node's output is gone
- hosted.c, sk_v4.c: the prompt and the line editing are the host's
- test_host_quit.c: the tests are the node's host; two tests of the old
  80-character prompt line now test a whole line, 1024 and 1025 characters

Verified: make -C v4 test passes at both widths; hosted-check passes on
three ISAs; clean qemu with STARFORTH_V4=1 on amd64, aarch64 and riscv64
passes POST (550 of 550) with the same hashes as hosted, and three lines
typed at each bare-metal prompt through the serial port are answered
correctly (logs/20261005-180922, -181152, -181541).

Still the lone node: kernel_main.c starts it before the fleet tables.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-05 18:17:37 -04:00
co-authored by Claude Opus 5.5
parent ab7a9bf06f
commit 01c447f9ab
17 changed files with 771 additions and 253 deletions
+33 -9
View File
@@ -29,9 +29,17 @@ typedef struct {
/* what the image was built for */
unsigned cell_bits, node_words, data_ring, ret_ring;
/* where to start, and where a fault goes */
v4_cell entry; /* QUIT */
v4_cell fault_table; /* (FAULTS) */
/* 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 */
v4_cell fault_table; /* (FAULTS): where a fault goes */
/* KEY's code: a node whose P is in key_start .. key_end - 1 with no
* character pending is waiting for one */
@@ -53,17 +61,33 @@ typedef struct {
/* The image built from v4/capsule (the generated file defines it). */
extern const v4_image v4_capsule_image;
/* 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" */
/* Reset `n`, load the image into it, attach its registers -- with `disk`,
* `blocks` blocks of 1024 bytes, as its block storage, or none if `disk` is
* 0 -- and leave it about to execute its first instruction. Returns 1, or 0
* if the image is not for this build of the engine (nothing is then done).
*
* After it, the caller 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) and giving it what is typed with v4_node_console_feed. */
* 0 -- and leave it idle, waiting to be handed a line. Returns 1, or 0 if
* the image is not for this build of the engine (nothing is then done). */
int v4_image_boot(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);