Commit Graph
831 Commits
Author SHA1 Message Date
rajamesandClaude Opus 5.5 b128a4d6db docs(v4.0.0): console -- the kernel hands a v4 node a line, as it does a v3 VM
Records v3's console as built (fabric, Hestia, proxies, the kernel's REPL
owning input and the prompt) and the ruling of 2026-10-05: for now a v4
node is handed a whole line and gives characters back; its own prompt loop
plays no part at that level.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 16:58:55 -04:00
rajamesandClaude Opus 5.5 79db64c4e2 docs(v4.0.0): correct V3-PARITY -- the pieces are not missing, v4 is beside them
The table called rows 1 and 6-12 missing in v4.  They are all in this
kernel and run today.  kernel_main.c calls sk_v4_run() before the fleet
tables, VM bootstrap, devices, Mama birth, heartbeat and fleet birth, and it
never returns, so the v4 node comes up beside the system and skips it.
Records how v3's boot fits together around the VM interface, and that the
open question is how the F18 engine takes the VM's place behind it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 16:49:52 -04:00
rajamesandClaude Opus 5.5 e88032b7e8 docs(v4.0.0): ruling -- the unit of heat in v4 is the opcode, not the word
Captain Bob, 2026-10-05: v4 = v3 functionally; heat accumulates on the 32
opcodes; the opcode replaces the word as the smallest unit.  Answers D-6 and
the three conflicts of V3-PARITY.md 2.4.  Records what follows (the
per-call-target array goes; pipelining and the hot-words cache are not
retired; decomposition no longer waits) and what is still open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 16:44:57 -04:00
rajamesandClaude Opus 5.5 2abaf51aee docs(v4.0.0): v4 against v3 up to the first prompt; row 3, physics and heat
Measures v4 against the ruling of 2026-10-05: v4 is exactly like v3 in
functional requirements up to the first FORTH prompt.  Twelve things v3 does
before its prompt, and what v4 does of each.  Row 3 in full: what v3 does
for every executed word and on every heartbeat tick, what a v4 node has,
what the v4 design documents say instead, the three places they conflict
with the ruling, and what each answer would take.  Lists the stand-ins
found in v4.  Proposes; decides nothing; nothing in it has been built.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 16:40:41 -04:00
rajamesandClaude Opus 5.5 2930349bbf feat(v4.0.0): POST passes and is part of the boot; U* and U/MOD
The boot is now nucleus, forth79.4th, POST, prompt, on both products.

- forth79.4th: U* and U/MOD, the capsule's first colon definitions.  They
  are in the FORTH-79 Required Word Set and neither v3 nor v4 had them.
- post79.4th: 550 cases, 126 of the 130 required words.  443 are v3's with
  v3's result.  The rest follow three rulings (2026-10-05): address-
  dependent cases are checked for count, not value; where v3 departs from
  FORTH-79 the standard's result is expected; words v3 has no case for get
  cases written by hand.  v4/tools/post79_rules.py holds each exception
  with its reason and docs/v4.0.0/POST79.md lists them all.
- every case starts from an empty stack, DECIMAL and FORTH DEFINITIONS
- the boot requires POST's tally line with fail=0

Verified: tests=550 pass=550 fail=0 and identical PARITY lines on hosted
amd64, aarch64 and riscv64 (make -C v4 hosted-check) and on bare metal,
clean qemu with STARFORTH_V4=1, on the same three (logs/20261005-1619xx,
-1621xx, -1625xx).  A U/MOD broken on purpose fails five cases and stops
the boot.  make -C v4 test passes.

Not shown: all words but those two are still assembled, so POST has so far
tested the assembled words.  Nothing was typed at a bare-metal prompt.
Open: PAD 42 OVER ! faults on v4 (D-1).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 16:28:01 -04:00
rajamesandClaude Opus 5.5 5d6043e37e feat(v4.0.0): POST for FORTH-79, from v3's cases; not passing yet
capsules/v4/post79.4th: 537 of v3's POST cases for the FORTH-79 Required
Word Set, each carrying what the hosted v3 binary did with the same line
(error or not, the stack, the length and checksum of what it printed).
Written by v4/tools/mkpost.py.  The harness is FORTH-79 plus the two
nucleus hooks.  docs/v4.0.0/NUCLEUS.md section 6.

- NODE-ERROR has a FORTH name: how a definition in FORTH raises an error
- the boot passes POST only on seeing its tally line with fail=0
- POST is not in the boot yet (V4_POST_AT_BOOT=0); make -C v4 post runs it

Result: tests=537 pass=439 fail=98.  The 98 are not yet sorted into v4
defects and differences needing a ruling; v4/README.md has a first reading.

Verified: make -C v4 test passes; hosted-check passes on three ISAs; clean
qemu with STARFORTH_V4=1 on amd64, aarch64 and riscv64 reaches ok> with the
same hashes as hosted (logs/20261005-1601xx..1604xx).  Nothing was typed at
a bare-metal prompt.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 16:04:48 -04:00
rajamesandClaude Opus 5.5 ed6b11ad88 feat(v4.0.0): (CATCH) and (EMIT-HOOK), the two nucleus hooks POST needs
(CATCH): while it is not zero, a line that ends in an error sets it to -1
and ends " ok" instead of " ERROR".  (EMIT-HOOK): the xt of a word that is
given each character EMIT would send to the console.  The prompt loop sets
(EMIT-HOOK) to 0 at the end of every line.  docs/v4.0.0/NUCLEUS.md 6.3,
amended: it said one nucleus word would do.

Verified: make -C v4 test passes at both widths; by hand at the hosted
prompt, an unknown word and a division by zero are caught, the output hook
receives every character, and an uncaught error still says ERROR.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 15:49:43 -04:00
rajamesandClaude Opus 5.5 506b645726 test(v4.0.0): v4 boots on bare metal and loads its capsule, three ISAs
clean qemu with STARFORTH_V4=1 on amd64, aarch64 and riscv64, one at a
time.  Each prints the same PARITY:V4_NUCLEUS and PARITY:V4_CAPSULE lines as
the three hosted binaries (image_hash 0x60b74e4f87adb0ac, dict_hash
0x0baed67626b4fac4), then PARITY:OK and ok>.

Each run was ended once the prompt was in the log.  Nothing was typed at a
bare-metal prompt.  The capsules were unsigned: no signing key on this
machine.  The v3 boot (STARFORTH_V4=0) was not re-run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 15:42:40 -04:00
rajamesandClaude Opus 5.5 294e69463a feat(v4.0.0): the system boots from a nucleus and loads its capsules
One boot, v4/system/boot.c, for both products: it starts the nucleus image,
finds each capsule in the baked capsule directory, recomputes its hash,
checks its signature, gives its blocks to the node a line at a time, and
prints PARITY:V4_NUCLEUS, PARITY:V4_CAPSULE and PARITY:OK before the prompt.
A line the node does not accept ends the boot with the capsule, block and
line named.  docs/v4.0.0/NUCLEUS.md.

- hosted Linux product for amd64, aarch64 and riscv64 (make -C v4 hosted);
  make -C v4 hosted-check boots all three and requires identical output
- the kernel's v4 entry (STARFORTH_V4=1) calls the same boot
- capsules/v4/forth79.4th, block 6000: no definitions yet
- mkimage builds the nucleus only; no FORTH source is compiled at build time
- capsule_blocks.c: the Block-header parse, free of any VM, for every loader

Verified: make -C v4 test passes; hosted-check passes on the three ISAs with
the same hashes; the kernel compiles with STARFORTH_V4=1 on the three.
Not verified: no bare-metal boot of v4 has been run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 15:28:30 -04:00
rajamesandClaude Opus 5.5 903321e548 feat(mkcapsule): no upper bound on capsule block numbers
Blocks 0..2047, the VM's fast RAM, are the only ones a capsule may not
claim (docs/v4.0.0/NUCLEUS.md 5.2).  The ceiling of 5120 matched no device.
All 36 capsule files still lint clean.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 15:18:30 -04:00
rajamesandClaude Opus 5.5 d4bd6e9601 docs(v4.0.0): nucleus, FORTH-79 capsule and POST design
The assembled vocabulary shrinks to a nucleus; the FORTH-79 Required Word
Set is loaded at boot from a capsule as colon definitions, POST (v3's cases,
ported, comparing results) runs on it, and the node reaches ok> -- hosted
and bare metal, on amd64, aarch64 and riscv64.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 15:16:00 -04:00
rajamesandClaude Opus 5.5 c1bbcaaba4 feat(v4.0.0): word-level access control at the prompt, as v3
- Each entry's flags cell also holds v3's four fields: denied, pinned,
  mode and a 16-bit TTL.
- compile.v4: INTERPRET checks every word it is about to execute or
  compile -- recheck at TTL 0, else count down; a denied word is refused
  with v3's line, the stack emptied and the line ended.
- capsule/acl.v4: ACL-MODE@ ACL-MODE! ACL-TTL@ ACL-TTL! ACL-ALLOW@
  ACL-ALLOW! ACL-PINNED? ACL-PIN ACL-INHERIT ACL-INIT-PRIMITIVES ACL-HEAT@
  ACL-WORD-ID, and ACL-HOOK.
- capsule/ACL.fth: v3's ACL.4th as FORTH source the node compiles; loading
  it switches access control on.
- v3 checks every execution, inside definitions too.  v4's code is native,
  so it checks a word when it is compiled as well as when interpreted; a
  call compiled while the word was allowed is not checked again.
  DECOMPOSITION.md 5.20 says so.
- ACL-HEAT@ is 0 until heat is readable (D-6).
- tests/test_host_quit.c: seven transcripts of the v3 binary; the policy
  file loaded and exercised; COLD.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 11:58:43 -04:00
rajamesandClaude Opus 5.5 384a6c1cd2 feat(v4.0.0): logging, as v3
- capsule/log.v4: the level constants LOG-ERROR .. LOG-DEBUG, LOG-LEVEL!
  and LOG-LEVEL@, LOG-ERROR" .. LOG-DEBUG" and LOG-ERROR-STR ..
  LOG-DEBUG-STR.  A message is printed if its level is at or below
  LOG-LEVEL, as v3's line -- colour, level, text -- without the time of
  day, which a node has not got.
- LOG-xxx" compiles like ." : the level, a call to (LOG"), the text.  SEE
  shows it as text.  COLD puts LOG-LEVEL back to LOG-INFO.
- tests/test_host_quit.c: ten transcripts of the v3 binary, every level
  at every setting.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 11:31:32 -04:00
rajamesandClaude Opus 5.5 8c540b0305 feat(v4.0.0): SEE, a disassembler written in FORTH
- capsule/tools.fth: SEE as FORTH source the node compiles itself.  v4
  code is native, so it shows each instruction word of a definition: the
  opcodes by name, literals' values, the names of the words called or
  jumped to, and text compiled by ." S" and ABORT" as text.  A data word
  shows what it holds; an immediate word says so.
- quit.v4: the three string run-time words get names, compile-only, so
  that SEE can tell text from code.
- tests/test_host_quit.c: definitions with literals, text, IF and loops;
  the capsule's own words; SEE shown by SEE.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 10:53:22 -04:00
rajamesandClaude Opus 5.5 a1afb44598 feat(v4.0.0): the editor, redone in FORTH; COLD WARM PAGE VERSION DEFER
- capsule/editor.fth: the block editor as FORTH source, which the node
  compiles itself.  It is a vocabulary, EDITOR, used at the ordinary
  prompt: n EDIT, then L N B T P E D S H R I WIPE DONE.  v3's EDIT, a
  shell of its own, is not carried over (ruled 2026-10-05); v3's L S and
  SHOW are kept in FORTH as they were, with COPY.
- system.v4: COLD (the system as the loader left it), WARM, PAGE,
  VERSION, 79-STANDARD (FORTH-79: silent), and DEFER IS DEFER@ as v3.
- input.v4: where words are split at blanks a zero byte reads as a blank,
  so a block never written, or filled a line at a time, loads cleanly.
- tests/test_host_quit.c: the editor's source fed to the prompt line by
  line, every command on empty and full screens, what reaches storage;
  the system words; deferred words.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 10:25:20 -04:00
rajamesandClaude Opus 5.5 c8dc14897c feat(v4.0.0): block storage, LOAD and LIST (D-19)
- The golden model's host node gets a block storage device: four
  memory-mapped registers (number, address, command, status), 1024-byte
  blocks as 256 cells.  tests/test_node.c.
- capsule/blocks.v4: BLOCK BUFFER UPDATE SAVE-BUFFERS EMPTY-BUFFERS LIST
  LOAD SCR BLK (FORTH-79) and v3's FLUSH THRU and -->, over two buffers.
- The text being interpreted is at the address in (SRC), which QUERY makes
  the terminal's buffer and LOAD a block's; LOAD saves and restores it, so
  blocks nest and the rest of LOAD's line runs afterwards.  WORD makes
  sure a loading block is still in a buffer before it reads.
- In a block, \ skips to the next 64-character line.
- A block number that does not exist, and --> at the terminal, are errors
  with messages (D-18).
- tests/test_host_quit.c: ten transcripts of the v3 binary; nesting three
  deep on two buffers; what reaches the device and when.

v3's LOAD drops the rest of its line, and v3 has no BLK.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 08:32:04 -04:00
rajamesandClaude Opus 5.5 0fbe1432b7 feat(v4.0.0): vocabularies, to FORTH-79
- VOCABULARY DEFINITIONS CONTEXT CURRENT FORTH, and v3's ORDER.  A name is
  looked up in the CONTEXT vocabulary and then in FORTH; a new entry goes
  into the CURRENT vocabulary; : makes the CURRENT vocabulary CONTEXT;
  FORTH is immediate.
- WORDS lists the CONTEXT vocabulary.  FORGET takes what was defined later
  out of every vocabulary, and a vocabulary that goes gives way to FORTH.
- v3's vocabularies separate nothing: a word defined in one is found from
  every other, and one redefined in a vocabulary replaces FORTH's for good.
- tests/test_host_quit.c: isolation, chaining to FORTH, two vocabularies
  with the same names, FORGET across them; and DUMP is now checked to put
  BASE back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 07:18:28 -04:00
rajamesandClaude Opus 5.5 ab272cc2ad feat(v4.0.0): the Q48.16 words and DUMP at the prompt
- capsule/qmath.v4: Q.FROM-INT Q.TO-INT Q.1 Q.0 Q.SCALE Q.+ Q.- Q.* Q./
  Q.ABS Q.NEG Q.= Q.< Q.> Q.0= Q.MAX Q.MIN Q.EXP Q.SQRT Q.LOG Q.SIN Q.COS
  Q.PRINT -- the definitions test_foundation.c executes on the mesh node,
  now in the host node's vocabulary.
- numout.v4: DUMP.
- Q./ by zero, and Q.SQRT and Q.LOG outside their domain, leave the
  result D-11 and D-12 give and then raise an error (D-18): "Division by
  zero", "Argument out of range".  v3 returns 0 silently.
- tests/test_host_quit.c: 122 results printed by Q.PRINT are transcripts
  of the v3 binary, the same at both cell widths; signed values, the
  errors and DUMP's layout besides.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 07:00:27 -04:00
rajamesandClaude Opus 5.5 e7d686c7a2 feat(v4.0.0): CASE, ['], S", WORDS, FORGET and FENCE
- compile.v4: CASE OF ENDOF ENDCASE, as v3 (they nest; a word out of
  place is a control structure mismatch); ['] and [LITERAL].
- quit.v4: S" and its run-time word; at the prompt the text is copied to
  PAD.
- capsule/system.v4: WORDS and VLIST; FORGET (FORTH-79), which gives the
  space back and will not remove a word below FENCE -- the capsule's own
  words -- where v3's FORGET DUP succeeds.
- tests/test_host_quit.c: ten more transcripts of the v3 binary, and
  nesting, the fence and the listing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 20:49:53 -04:00
rajamesandClaude Opus 5.5 c02505db69 feat(v4.0.0): 48 more words at the prompt (words.v4)
capsule/words.v4: the stack, comparison, shift, double, mixed and string
words whose definitions DECOMPOSITION.md already gives and the mesh-node
tests execute, now in the host node's vocabulary:

  2SWAP 2OVER 2ROT 2>R 2R> 2R@ 2@ 2! -! 0<> 0> <> <= >= U< U> ABS MAX MIN
  WITHIN LSHIFT RSHIFT D- DABS D0= D0< D= D2* D2/ D< DMAX DMIN M+ M-
  CMOVE> MOVE FILL ERASE BLANK -TRAILING COMPARE SEARCH SCAN SKIP
  ?TERMINAL TRUE FALSE INVERT NOP

- A shift count that is negative or as large as the cell is an error, as
  in v3 (code 9, "Shift count out of range").
- tests/test_host_quit.c: 36 sessions from the prompt that are
  transcripts of the v3 binary, and the cases where v4 keeps the standard
  (MOVE in cells; M+ and M- with the double low cell first).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 20:34:13 -04:00
rajamesandClaude Opus 5.5 dc7e37ba5c feat(v4.0.0): every error is raised and ends the line (D-18)
Ruled 2026-10-04: guard all errors.  The errors that set NODE-ERROR and
let the line run on now stop it at once, with a message.

- A store of a non-zero code to NODE-ERROR is a trap, a sixth kind of
  fault: nothing after it executes, the return stack is emptied, and the
  data stack is left as the word left it.  Not attached, NODE-ERROR is
  plain memory, as the tests below the prompt use it.
- The capsule's words store a code where they stored -1, and the prompt's
  (RAISED) prints its message: Negative count, Not a number, Number too
  long, Not a character, Dictionary full, Name missing, Control structure
  mismatch, Control structures too deep.
- ' and COMPILE and [COMPILE] of a word that is not there say
  UNKNOWN WORD: 'xxx', as the interpreter does.
- tests: the trap in test_exec.c; every message from the prompt, with the
  rest of the line not run and the stack kept, in test_host_quit.c.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 20:13:23 -04:00
rajamesandClaude Opus 5.5 644bfc0a25 feat(v4.0.0): number output in the capsule, and .S
- 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>
2026-10-04 18:50:12 -04:00
rajamesandClaude Opus 5.5 ebffa6082d feat(v4.0.0): the host node's stacks are 32 deep (D-17)
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>
2026-10-04 18:29:10 -04:00
rajamesandClaude Opus 5.5 0da7e32a0b feat(v4.0.0): the stacks are guarded (D-16); DEPTH, PICK and ROLL
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>
2026-10-04 17:31:18 -04:00
rajamesandClaude Opus 5.5 361dcd1148 feat(v4.0.0): division by zero is guarded (D-15); division words in the capsule
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>
2026-10-04 12:23:30 -04:00
rajamesandClaude Opus 5.5 b3d2d56d11 feat(v4.0.0): address faults -- an address outside memory is guarded (D-14)
Ruled 2026-10-04: guarded, an error shown, back to the prompt.

- The executor checks every address a programme uses (P, A, B) before
  using it.  Outside memory the opcode does nothing, the rest of its word
  is not executed, and P becomes the node's fault handler; a node with no
  handler stops.  v4_node_load/store never index outside memory.
- capsule/quit.v4: (FAULT), the host node's handler, prints
  "Address out of range", ends an open definition, prints ERROR and
  returns to the prompt.
- tests: every memory opcode and P in test_exec.c; from the prompt, from
  inside nested words and loops, in test_host_quit.c.

This closes the hole node.h described: a wild address used to index the
model's own memory gigabytes out of bounds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 12:04:59 -04:00
rajamesandClaude Opus 5.5 b5d644d498 feat(v4.0.0): the prompt -- QUIT, ABORT, ABORT" and ."
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>
2026-10-04 11:49:44 -04:00
rajamesandClaude Opus 5.5 806f876ee0 fix(v4.0.0): shorter chains of calls in the compiler capsule
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>
2026-10-04 11:17:58 -04:00
rajamesandClaude Opus 5.5 dac7ffac92 feat(v4.0.0): the defining and compiling words
The fourth layer of the compiler capsule.  compile.v4: INTERPRET's
loop, STATE [ ] : ; EXIT IMMEDIATE LITERAL COMPILE [COMPILE] ' EXECUTE,
CREATE VARIABLE CONSTANT DOES>, and IF ELSE THEN BEGIN UNTIL AGAIN
WHILE REPEAT DO ?DO LOOP +LOOP on a control-flow stack in memory.
forth.v4: the first words of the vocabulary, the in-line ones.

FORTH source now goes in and running code comes out.  49 programmes
were run through the v3 binary and through this; every result agrees,
bar COMPILE, which v3 cannot run.  The code laid down for each control
structure is word for word the expansion DECOMPOSITION.md gives.

A line may have six values on the stack while it is interpreted, and
words called from the interpreter may nest eight deep.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 10:42:23 -04:00
rajamesandClaude Opus 5.5 bbd1b4047f refactor(v4.0.0): the capsule's inner words keep their state in memory
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>
2026-10-04 10:41:50 -04:00
rajamesandClaude Opus 5.5 44ffd261bb feat(v4.0.0): the text assembler takes &NAME and CONST+N
&NAME is the address of a word as a literal; CONST+N is a loader
constant plus an offset as one literal, so that a capsule file can
address the cells of its scratch area without adding at run time.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 10:41:50 -04:00
rajamesandClaude Opus 5.5 26a6a16537 feat(v4.0.0): the text assembler lays down dictionary headers
'header NAME [flags]' in front of a word gives it a dictionary entry in
the layout capsule/dict.v4 uses, linked to the header before it, so the
words of a capsule are in the dictionary as soon as it is assembled.
The name is taken as it stands (it may be ( or + or ;) and the
assembler's own name for the code may differ.

Tested in the assembler's own test, and by FIND and the field words
running over assembler-made entries beside ones (HEADER) made.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 09:58:26 -04:00
rajamesandClaude Opus 5.5 880560fc00 feat(v4.0.0): the code generator
The third layer of the compiler capsule, v4/capsule/codegen.v4: opcodes,
literals and branches packed into instruction words at HERE, by the
rules of sections 1.2 and 2.  (OP,) (LIT,) (LABEL) (BRANCH,) (JUMP,)
(CALL,) (BRANCH>) (RESOLVE) (FLUSH) (CG-RESET).

Tested by laying the same programmes down with the text assembler on
one node and with the code generator, running, on another, and
comparing memory word for word: every opcode, literals and branches in
every slot position, and 600 random programmes.  What it lays down is
then run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 09:19:57 -04:00
rajamesandClaude Opus 5.5 c10d3a9cca feat(v4.0.0): the dictionary: its space, its entries, and FIND
The second layer of the compiler capsule, v4/capsule/dict.v4: HERE ALIGN
ALLOT , C, 2, PAD LATEST; an entry layout reached entirely from the xt,
with >LINK LFA LINK> >NAME NFA NAME> CFA PFA >BODY TRAVERSE SMUDGE
HIDDEN on it; and FIND and ' .

FIND is FORTH-79's and v3's.  ' is FORTH-79's: the parameter field
address, which for a code word is what FIND gives.  ALLOT counts cells
(D-1).  31 characters of a name are significant.

Executed at both cell widths against a list of 300 entries kept in C.
WORD no longer holds its length on the return stack.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 08:59:06 -04:00
rajamesandClaude Opus 5.5 01b5bbb23f fix(v4.0.0): .R U.R and D.R print no trailing space
FORTH-79's reference .R right-justifies the number in its field and
prints nothing after it; v3 printed a space.  . U. and D. still print
their one space.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 08:47:29 -04:00
rajamesandClaude Opus 5.5 b137678691 fix(v4.0.0): MOVE follows FORTH-79
MOVE moves n cells, the cell at addr1 first, and nothing for n <= 0.
v3's moved bytes like memmove; CMOVE and CMOVE> do that.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 08:47:29 -04:00
rajamesandClaude Opus 5.5 e178a76c36 fix(v4.0.0): LEAVE follows FORTH-79
LEAVE sets the limit equal to the index: the rest of the body runs with
the index unchanged and the loop ends at the next LOOP or +LOOP.  v3's
left the loop at once, which is FORTH-83's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 08:47:29 -04:00
rajamesandClaude Opus 5.5 7b42a9b6c1 fix(v4.0.0): EXPECT, QUERY and WORD follow FORTH-79
Ruled 2026-10-04: standard words follow the standard where v3 did not.

EXPECT takes up to n characters (v3 took n-1) and does nothing for
n <= 0.  QUERY takes up to 80 (v3: 1024).  WORD stores the delimiter it
met, or a zero at the end of the text, after the word, and leaves >IN
just past that one delimiter (v3 skipped them all and stored a zero);
the word may be up to 255 characters (v3: 62).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 08:37:44 -04:00
rajamesandClaude Opus 5.5 443439c3d2 feat(v4.0.0): reading a line and splitting it into words and numbers
The first layer of the compiler capsule, on the host node: TIB >IN SPAN
SOURCE BL EXPECT QUERY WORD ENCLOSE CONVERT NUMBER and the comment
words.  The definitions are text, v4/capsule/core.v4 (the core words
they rest on) and v4/capsule/input.v4, assembled by the text assembler,
which can now read a file.

EXPECT, QUERY, WORD and ENCLOSE behave as v3's.  CONVERT and NUMBER are
FORTH-79 (ruled 2026-10-04): any BASE, a double in the standard order,
and NUMBER returns a signed double or sets NODE-ERROR.

Executed at both cell widths against C and against values recorded from
the v3 binary.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 08:30:32 -04:00
rajamesandClaude Opus 5.5 31fcdcd0a3 feat(v4.0.0): a 16384-word host node for the compiler tests
Node memory is a build parameter.  Tests named test_host_*.c are now
built with V4_NODE_WORDS=16384, the host node that will hold the
compiler, the dictionary and the text being compiled; every other test
keeps the 1024-word mesh node.

The first such test checks the node at that size and the text
assembler's branch placement, which only matters there: a branch slot
that cannot reach the whole node is not used.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 21:18:38 -04:00
rajamesandClaude Opus 5.5 7b710aa322 feat(v4.0.0): assemble definitions written as text
Test support, beside the slot packer: reads definitions in the notation
DECOMPOSITION.md uses -- words, opcodes, literals, constants, labels,
branches, FOR NEXT and FOR UNEXT, in-line macros, comments -- and lays
them down through the slot packer, so they no longer have to be retyped
opcode by opcode in C.

Tested by assembling SWAP, UM/MOD, C@ and C! both ways on two nodes and
comparing memory word for word, by running what is assembled, and on
every error it reports, each with its line number.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 21:13:32 -04:00
rajamesandClaude Opus 5.5 861f800b7f 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 <noreply@anthropic.com>
2026-10-03 20:53:56 -04:00
rajamesandClaude Opus 5.5 2c16183788 feat(v4.0.0): CONSOLE-RX and CONSOLE-STATUS on the single-node model
The console's receive side, standing in for the console node until the
mesh exists, as CONSOLE-TX does for output.  A data fetch (@, @+, @b)
from CONSOLE-STATUS gives -1 when a character is pending and 0 when
not; from CONSOLE-RX it gives the next character and takes it, or -1
with none pending.  The characters come from a queue the test feeds.

Instruction words and literals are still fetched with v4_node_load, so
code at a register's address is never taken for the register.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 20:53:56 -04:00
rajamesandClaude Opus 5.5 03d8d991ef feat(v4.0.0): the DO loop runtimes
(DO) (?DO) (LOOP) (+LOOP) (LEAVE) I J UNLOOP and (0BRANCH), laid down
in line by hand as the compiler will, executed on the golden model at
both cell widths against C on every pair of 14 loop ends and 11 steps,
and against sequences recorded from the v3 binary.

(LOOP) goes round again while index < limit, signed, as v3 does; the
document's equality test differed whenever start >= limit.  (+LOOP) is
now specified.  J keeps the outer index in A and needs no extra return
entry.

LEAVE discards the limit and index.  v3 left them on its return stack,
which made a LEAVE in an inner loop stop the outer one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 20:13:24 -04:00
rajamesandClaude Opus 5.5 481d484e93 feat(v4.0.0): the mixed and double leftovers
M- M* M/MOD MOD */ */MOD, D0< D2* D2/ 2ROT, 2DROP and 2>R 2R@ 2R>,
beside UM* and SM/REM in test_foundation.c.  Executed on the golden
model at both cell widths against C and results recorded from the v3
binary.

M- widens n before negating it, so the most negative n is right.
*/MOD goes through a full double product.  D2/ is one +* step.
M- and M/MOD take the double in the standard order ( lo hi ), as M+
does; v3 took its low cell on top.

The foundation test's node is now full: 958 of the 960 words below its
variables.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 18:37:53 -04:00
rajamesandClaude Opus 5.5 84c7711763 feat(v4.0.0): the small single-cell words
NIP SWAP ROT -ROT ?DUP 2DUP, >R R@ R>, @ ! +! -! 2@ 2! CELLS,
- NEGATE 1+ 1- 2+ 2- MIN MAX, OR NOT 0= 0< 0<> 0> = <> < > <= >= U<
WITHIN TRUE FALSE in a new test, and * and / beside UM* and /MOD in
test_foundation.c.  Executed on the golden model at both cell widths
against C on every combination of the edge values and against recorded
transcripts of the v3 binary.

WITHIN is low <= n < high with signed comparisons, which is what v3
computes; the document's circular form differed for low > high.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 17:49:30 -04:00
rajamesandClaude Opus 5.5 cb66db1107 feat(v4.0.0): the byte-string words
FILL ERASE MOVE, COUNT CMOVE CMOVE> BLANK -TRAILING COMPARE SEARCH SCAN
SKIP, as loops over the call-free C@ and C!, executed on the golden
model at both cell widths against C and five recorded transcripts of
the v3 binary.

A negative count reads as 0 where v3 read it so, and elsewhere writes
nothing and sets NODE-ERROR.  v3's counted-string auto-detection is not
kept in any of them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 17:25:27 -04:00
rajamesandClaude Opus 5.5 7c5be22799 feat(v4.0.0): C@ is call-free
One case per byte position, like C!: the cell is shifted down with a
2/ loop and masked.  It replaces the version built on LSHIFT, RSHIFT
and SWAP calls.  C@ now leaves its caller 7 return entries (was 4), and
the words above it gain with it: TYPE 6 (was 3), DUMP 4, Q.PRINT, U.
and U.R 3 (were 2).  The signed number words stay at 2: their sign
waits on the return stack.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 17:15:57 -04:00
rajamesandClaude Opus 5.5 e50cc1f73a feat(v4.0.0): BASE, DECIMAL, HEX, OCTAL and HLD
BASE and HLD leave their variable's word address; DECIMAL, HEX and
OCTAL store 10, 16 and 8.  Executed on the golden model at both cell
widths, including a recorded transcript of the v3 binary.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 16:46:38 -04:00
rajamesandClaude Opus 5.5 030ca63639 feat(v4.0.0): ?, Q.PRINT and DUMP
Built on the number-output words and executed on the golden model at
both cell widths against a C reference and recorded transcripts of the
v3 binary (DUMP byte for byte at 64-bit cells).

Q.PRINT is signed (D-8) and always decimal; DUMP is always hex; both
put BASE back.  Each keeps its working state in a variable, (QP) and
(DP), so each leaves its caller 4 data cells and 2 return entries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 16:33:19 -04:00