From 861f800b7fde50ea43ed7115b82842ccc8e24d48 Mon Sep 17 00:00:00 2001 From: rajames Date: Sat, 3 Oct 2026 20:53:56 -0400 Subject: [PATCH] feat(v4.0.0): KEY and ?TERMINAL on the console registers ?TERMINAL reads CONSOLE-STATUS; KEY polls it until a character is pending and then takes it from CONSOLE-RX. Executed on the golden model at both cell widths, including a transcript of the v3 binary, and KEY shown still waiting after 5000 instruction words with no input. v3's KEY returned -1 at the end of its input; here KEY waits. Co-Authored-By: Claude Opus 5.5 --- docs/v4.0.0/DECOMPOSITION.md | 8 ++- v4/tests/test_terminal.c | 127 ++++++++++++++++++++++++++++++++++- 2 files changed, 129 insertions(+), 6 deletions(-) diff --git a/docs/v4.0.0/DECOMPOSITION.md b/docs/v4.0.0/DECOMPOSITION.md index 38f5e6c0..70739894 100644 --- a/docs/v4.0.0/DECOMPOSITION.md +++ b/docs/v4.0.0/DECOMPOSITION.md @@ -148,7 +148,7 @@ times, as on the F18. `FOR ... UNEXT` is the same but the body must fit in one i **Register conventions.** `A` and `B` are caller-saved. A word that uses them says so. Words in this document that clobber `A`: `@ ! +! -! 2@ 2! C@ C! D2/ M* FILL ERASE MOVE COUNT CMOVE CMOVE> BLANK -TRAILING COMPARE SEARCH SCAN SKIP DECIMAL HEX OCTAL UM* * UM/MOD Q.FROM-INT Q.TO-INT Q.* Q./ Q.EXP Q.SQRT Q.LOG Q.SIN Q.COS +LOOP J HOLD SIGN # #S . .R U. U.R D. D.R ? DUMP Q.PRINT TYPE SEND RECV`. Words that clobber `B`: -`COMPARE SEARCH Q./ Q.EXP Q.SQRT Q.LOG Q.SIN Q.COS <# HOLD SIGN # #S #> . .R U. U.R D. D.R ? DUMP Q.PRINT EMIT CR SPACE SPACES TYPE SEND RECV`. +`COMPARE SEARCH Q./ Q.EXP Q.SQRT Q.LOG Q.SIN Q.COS <# HOLD SIGN # #S #> . .R U. U.R D. D.R ? DUMP Q.PRINT EMIT CR SPACE SPACES TYPE KEY ?TERMINAL SEND RECV`. **Return-stack words** (`>R R> R@ 2>R 2R> 2R@ I J UNLOOP` and the loop runtimes) are always IN. @@ -644,8 +644,8 @@ width and print a flood of spaces. | Word | Fate | Notes | | --- | --- | --- | | `EMIT` | DEV | Console service: one-character message. Until the mesh exists it is a store to the `CONSOLE-TX` register (§7): `CONSOLE-TX b! !b`. As in v3, the low byte of the cell is the character. Executed on the golden model (2026-10-03). Clobbers `B`. | -| `KEY` | DEV | Console service: blocking receive. | -| `?TERMINAL` | DEV | Console service: non-blocking status. | +| `KEY` | DEV | Console service: blocking receive. Until the mesh exists it reads the `CONSOLE-STATUS` and `CONSOLE-RX` registers (§7): `L: CONSOLE-STATUS b! @b if WAIT drop CONSOLE-RX b! @b ; WAIT: drop jump L` — it asks whether a character is pending until one is, then takes it. The character is 0–255. v3's `KEY` returned −1 at the end of its input; here there is no end of input, and `KEY` waits. Executed on the golden model (2026-10-03), including a transcript of the v3 binary, and shown still waiting after 5000 instruction words with nothing pending. Leaves its caller 9 data cells and 8 return entries. Clobbers `B`. | +| `?TERMINAL` | DEV | Console service: non-blocking status. Until the mesh exists: `CONSOLE-STATUS b! @b` — −1 when a character is pending, 0 when not, as v3; it takes nothing. Executed on the golden model (2026-10-03). Clobbers `B`. | | `TYPE` | CAP | `( baddr u -- )`. Loop of `C@ EMIT`, or one string message to the console node: `-if OK drop drop NODE-ERROR b! -1 !b ; OK: if DONE over C@ EMIT push 1 + pop -1 + jump OK DONE: drop drop ;` — nothing for `u = 0`; for `u < 0` nothing is printed and `NODE-ERROR` is set, where v3 printed nothing and raised its error flag. The address range is not checked (out-of-range addressing is still open, `node.h`). Executed on the golden model (2026-10-03). Leaves its caller 6 data cells and 6 return entries. Clobbers `A` and `B`. | | `CR` | CAP | `10 EMIT`, as `10 jump EMIT` — executed on the golden model (2026-10-03). Character 10, as v3; the console turns it into a new line. | | `SPACE` | CAP | `BL EMIT`, as `32 jump EMIT` — executed on the golden model (2026-10-03). | @@ -959,3 +959,5 @@ Addresses are assigned in the node memory map (D-4). Names only here. | `PORT-STATUS` | R | Per-port ready flags, for non-blocking polls. | | `NODE-ERROR` | R/W | Arithmetic error flag: set to −1 by `Q./` on division by zero (D-11), by `Q.SQRT` / `Q.LOG` outside their domain (D-12) and by `HOLD` on a bad character or a full buffer (D-13), cleared by writing 0. `VM-ERROR?` reads it. | | `CONSOLE-TX` | W | Console transmit: a store sends the low 8 bits of the value as one character. This is what `EMIT` writes to. On the single-node golden model it is a capture register: the character is appended to a buffer on the node and memory is not written (`v4_node_console_attach`, `v4/include/v4/node.h`), so printing words can be run and their output compared with v3's. With the mesh (step 2) it becomes the port to the console node. | +| `CONSOLE-RX` | R | Console receive: a fetch gives the next pending character, 0–255, and takes it; with none pending it gives −1 and takes nothing. This is what `KEY` reads. On the single-node golden model the characters come from a queue the test feeds (`v4_node_console_input_attach`, `v4_node_console_feed`, `v4/include/v4/node.h`). Only the data fetches `@`, `@+` and `@b` see the register; instruction words and literals at the same address are read as memory. With the mesh (step 2) it becomes the port from the console node, and a read with nothing pending will block instead. | +| `CONSOLE-STATUS` | R | Console receive status: a fetch gives −1 when a character is pending and 0 when not, and changes nothing. `?TERMINAL` reads it, and `KEY` polls it. On the mesh it is the console port's bit of `PORT-STATUS`. | diff --git a/v4/tests/test_terminal.c b/v4/tests/test_terminal.c index fafbf3f1..1984526e 100644 --- a/v4/tests/test_terminal.c +++ b/v4/tests/test_terminal.c @@ -1,4 +1,4 @@ -/* test_terminal.c -- EMIT, CR, SPACE and TYPE, executed. +/* test_terminal.c -- EMIT, CR, SPACE, TYPE, KEY and ?TERMINAL, executed. * * DECOMPOSITION.md 5.10. EMIT is a device service; on the single-node model * it is a store to the CONSOLE-TX capture register (node.h), so what these @@ -9,7 +9,14 @@ * bytes, nothing for u = 0, and for u < 0 prints nothing and raises its error * flag. v4 sets NODE-ERROR in that last case, as D-13 does for HOLD. * - * Two transcripts of the real v3 binary are recorded below as expected + * KEY ( -- c ) and ?TERMINAL ( -- flag ) are device services too; on the + * single-node model they read the CONSOLE-RX and CONSOLE-STATUS registers + * (node.h), which hand out characters the test feeds. v3: KEY is the next + * character of input, waiting for one; ?TERMINAL is -1 when one is ready and + * 0 when not. At the end of its input v3's KEY returns -1; here there is no + * end of input, and KEY waits. + * + * Three transcripts of the real v3 binary are recorded below as expected * output. They were taken on 2026-10-03 from * printf '