- capsule/numout.v4: <# # #S HOLD SIGN #>, . .R U. U.R D. D.R, ?, SPACES,
DECIMAL HEX OCTAL -- the definitions DECOMPOSITION.md 5.8 gives and the
mesh-node tests execute, now words of the host node's vocabulary.
- .S, which D-16 makes possible again: as v3, the depth, then every value
from the deepest, then a new line. It needs six cells of the stack
free.
- tests/test_host_quit.c: printed from the prompt, with 14 more sessions
that are transcripts of the v3 binary, and the ends of the number range
at each cell width.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With the stacks counted and guarded (D-16) their size is a parameter of
the node. The host node, which runs the interpreter and the compiler
under the user's programme, gets 32 values and 32 return entries; a mesh
node keeps the F18's 10 and 9. Nothing else about the mechanism or any
word's definition changes.
- stack.h: V4_DATA_RING and V4_RET_RING are build parameters; the
Makefile sets them for the host-node tests.
- tests/test_host_quit.c no longer assumes a size: it fills the stacks to
whatever they are, and takes every exit with the return stack full.
- Measured on the host node now: 28 values on a line, 29 waiting between
lines, words 31 deep from the prompt.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ruled 2026-10-04, revising D-2: stack overflow and underflow are errors
that are shown and return to the prompt, not silent wrap-around.
- Each stack counts what it holds. Before every opcode the executor
checks that the stacks hold what it takes and have room for what it
leaves; otherwise the opcode does nothing and the node faults, as for a
bad address, to that kind's handler. Every fault empties both stacks.
- The fault handler is now a table of five jumps: address, data overflow,
data underflow, return overflow, return underflow. The host node says
"Stack overflow", "Stack underflow", "Return stack overflow",
"Return stack underflow", then ERROR and the prompt.
- Two registers, DSTACK-DEPTH and RSTACK-DEPTH: a fetch reads the depth,
a store empties the stack. QUIT, ABORT and the error exits empty the
return stack before they call anything; ABORT empties the data stack.
- capsule/forth.v4: DEPTH, PICK and ROLL, to FORTH-79 (counting from
one). PICK and ROLL set the values above the one wanted aside in
memory, and work with the stack full.
- Division by zero now takes its operands off the stack, as v3 does.
- A colon with no room for its entry abandons the line.
- tests: every opcode at every depth of both stacks; the faults, the
registers and the three words from the prompt.
The sizes are unchanged: ten values, nine return entries.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ruled 2026-10-04: guarded, an error shown, back to the prompt.
- capsule/forth.v4: / MOD /MOD */ */MOD M/MOD, M* and S>D join the
vocabulary. Each dividing word tests its divisor first; zero prints
v3's message ("/: Division by zero"), ends an open definition, prints
ERROR and returns to the prompt from however deep.
- SM/REM here has UM/MOD written into it and keeps its signs in memory,
and */MOD has M* written in, so that division can be used inside words
that other words call: / from four words deep, */MOD from three.
- forth.v4 now loads after quit.v4, which the guard leaves through.
- tests: v3 transcripts for each message; /MOD, /, MOD and */MOD against
C on every pair of edge values.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Layer 5 of the compiler capsule. The host node is now started at QUIT and
left running: it prompts, reads a line from its console with QUERY,
interprets it, says " ok" or " ERROR", and goes round again.
- capsule/quit.v4: QUIT and ABORT (FORTH-79), ABORT" and (ABORT") as v3 has
them, ." and (.") (FORTH-79). Text is compiled as a counted string after
the call; the run-time word returns to the cell after it.
- INTERPRET prints v3's messages before abandoning a line:
UNKNOWN WORD: 'xxx' and xxx: compile-only.
- core.v4: CR SPACE COUNT TYPE, as DECOMPOSITION.md gives them.
- input.v4: WORD split so that (PARSE) can take text without skipping
leading delimiters (." " is an empty string); EXPECT keeps its place in
memory, so six values may wait on the stack while a line is typed.
- tests/test_host_quit.c: the node is fed characters and its output read;
16 sessions are transcripts of the v3 binary.
QUIT stops the line from inside any word and says nothing; v3's goes on
with the line and cannot be compiled. v3's compiled ABORT" crashes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Measured, compiling a DO loop left one return entry spare under
INTERPRET and a defining word called from inside another word
overflowed the nine-entry return stack (D-2); the prompt loop will take
one more.
C@ and C! shift without a loop. The code generator shifts each opcode
into the word being built, so nothing is placed by a counted shift, and
the address masks come from a table. The dictionary search, the
in-liner, the end of a loop and the making of a data word are each one
word reached by a jump.
Every kind of line now leaves at least three return entries spare while
it compiles; a word run from the interpreter has six; and CREATE ...
DOES> works from the prompt, from a word, and from a word that calls
that.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
WORD, the dictionary words and the code generator run underneath
whatever the user has on the stacks, which are ten and nine deep (D-2).
Measured, they used five to seven data cells of their own, leaving a
line about three. Each now keeps what it works on in its file's
scratch cells and has at most three cells on the data stack; , calls
nothing; and the longest chains of calls are shorter.
The public words of core.v4, input.v4 and dict.v4 get dictionary
headers. NUMBER is split so the interpreter can have a flag instead of
NODE-ERROR. The host-node tests share one memory map, host_map.h.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>