feat(v4.0.0): a node asks its kernel by a blocking write to its port
ENGINE.md step 2, the carrier. Ruled 2026-10-05 (V3-PARITY.md 1i), on DECOMPOSITION.md section 6: a write to a port blocks until the neighbour reads. - node: v4_node_port_attach, v4_node_port_served; a store to the port keeps the value as the request and blocks the node - exec: a blocked node executes nothing; served, it goes on from the opcode after the store, in the same instruction word; a fault meanwhile abandons the rest of the word - compile.v4: n KERNEL-WORD name makes a word whose body writes n to the port; its arguments and results are on the data stack - boot: the kernel's words are made by handing the node text, and requests are served between the node's opcodes; one no one serves is error 12 - BYE, the first kernel word: hosted it leaves the program, as hosted v3; on the lone node it is v3's cold restart - ENGINE.md 3a: multiuser, multitasking, preemptive and cooperative, and what that asks of the engine Verified: make -C v4 test passes at both widths, with tests/test_port.c; hosted-check passes on three ISAs; clean qemu with STARFORTH_V4=1 on amd64, aarch64 and riscv64 passes POST with the same hashes as hosted, and a kernel word no one serves and BYE typed at each prompt are answered (logs/20261005-185506, -185734, -190101; -185234 is an amd64 run in which those two lines were not typed). Not done: v3's own C functions serving a node. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
5f1f60fc84
commit
8df6c16766
@@ -152,6 +152,18 @@ int v4_boot_line(const v4_boot *b, const char *text, unsigned len)
|
||||
n->console_len = 0;
|
||||
}
|
||||
if (n->stopped) return V4_BOOT_LINE_STOPPED;
|
||||
if (n->asking) { /* blocked at its port: the kernel's turn */
|
||||
if (b->serve && n->request >= 1 && n->request <= (v4_cell)b->word_count) {
|
||||
b->serve(n, (unsigned)n->request);
|
||||
v4_node_port_served(n);
|
||||
} else {
|
||||
/* a request no one serves is an error, as any other (D-18):
|
||||
* 12, Argument out of range */
|
||||
v4_node_port_served(n);
|
||||
v4_node_store(n, n->error_reg, 12); /* a store to NODE-ERROR raises it */
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (v4_line_done(n, b->im)) return v4_line_status(n, b->im);
|
||||
if (v4_image_waiting(n, b->im)) { /* the line is reading the keyboard */
|
||||
int c = b->key ? b->key() : V4_BOOT_KEY_END;
|
||||
@@ -261,6 +273,20 @@ int v4_boot_run(const v4_boot *b, unsigned char *disk, unsigned blocks)
|
||||
say(b, " image_hash="); say_hex(b, image_hash(b->im));
|
||||
say(b, "\n");
|
||||
|
||||
/* the kernel's words, before any capsule that might use one */
|
||||
for (i = 0; i < b->word_count; i++) {
|
||||
char text[64];
|
||||
unsigned at = 0, k, num = i + 1, div = 1;
|
||||
while (num / div >= 10) div *= 10;
|
||||
for (; div; div /= 10) text[at++] = (char)('0' + num / div % 10);
|
||||
for (k = 0; " KERNEL-WORD "[k]; k++) text[at++] = " KERNEL-WORD "[k];
|
||||
for (k = 0; b->words[i][k] && at < sizeof text; k++) text[at++] = b->words[i][k];
|
||||
if (b->words[i][k] || v4_boot_line(b, text, at) != V4_LINE_COMPLETED) {
|
||||
say(b, "V4: kernel word "); say(b, b->words[i]); say(b, " could not be made\nPARITY:FAIL\nPOST: FAILED\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < sizeof boot_capsules / sizeof boot_capsules[0]; i++)
|
||||
if (!load_capsule(b, boot_capsules[i])) { say(b, "PARITY:FAIL\nPOST: FAILED\n"); return 0; }
|
||||
#if V4_POST_AT_BOOT
|
||||
|
||||
Reference in New Issue
Block a user