Commit Graph
6 Commits
Author SHA1 Message Date
rajamesandClaude Opus 5.5 25fc5fd5e3 feat(v4.0.0): the node tells its kernel of its words; the boot seals the system
ENGINE.md 3b, the node's side of ruling A (a word's code is the node's, its
accounts the kernel's).

- dict.v4, system.v4: (WORD-DEFINED) ( xt -- ) is run when an entry is
  made, (WORD-FORGOTTEN) ( w -- ) when FORGET or COLD removes entries; with
  0 there no one is told, as on the hosted product
- test_host_quit.c: a kernel that keeps the list of words and is checked to
  hold exactly the node's dictionary after definitions, a vocabulary, an
  abandoned definition, FORGET, a refused FORGET and COLD; KERNEL-WORD
  called from the prompt and from a definition

Fixed, found while writing that test: since the capsules moved from build
time to boot time (294e6946), what COLD returns to and FORGET protects was
still the nucleus alone, so COLD lost U*, U/MOD and BYE and FORGET U* was
allowed.  The boot now seals the system when it has loaded it
(v4_image_seal), and hosted-check checks COLD, the capsule word after it,
the refused FORGET and BYE.

Verified: make -C v4 test passes at both widths (1283 checks in
test_host_quit.c); hosted-check passes on three ISAs; clean qemu with
STARFORTH_V4=1 on amd64, aarch64 and riscv64 passes POST, and COLD, U*
after it, FORGET U* (refused), an unserved kernel word and BYE typed at
each prompt are answered correctly (logs/20261005-193045, -193307, -193636).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 19:38:40 -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 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 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 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 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