docs(v4.0.0): ENGINE -- a word's two halves; what exactly is swapped in v3

Ruling A recorded as design.  Measured: each build has one interpreter file
(v3/src/vm.c hosted, kernel/src/vm/vm_core.c in the kernel) and the swap is
a third, answering the same functions with a node.  So the hosted v4
product is v3's hosted program with the node as its interpreter, not a
separate program.  Steps re-cut; two things in v3's C words that do not
carry over as they are (vm_ptr into packed bytes, direct stack fields).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
rajames
2026-10-05 19:13:55 -04:00
co-authored by Claude Opus 5.5
parent d4b1b4ff91
commit 085d0881de
+80 -15
View File
@@ -133,6 +133,67 @@ engine's.
*v3:* `vm_dict_hash_fn`, a hook the birth protocol calls. *v4:* the same
hook, answered from the node's dictionary.
## 3b. A word's two halves (ruled 2026-10-05: "A is good")
`V3-PARITY.md` section 1j. A word on a node is its name and its code, in
the node's memory, with its word ID in its header. Its accounts are v3's
own `DictEntry` record, kept by the kernel: `execution_heat`, `physics`,
the four ACL fields, the transition metrics, the word ID. The two are
joined by the word ID.
- The node tells the kernel when a word is defined and when words are
forgotten, by a request through its port. The kernel makes or drops the
record.
- At each `call` the kernel does on the record what v3's inner loop does
(3.5).
- v3's physics, heartbeat, ACL words, Stadium word layer and parity run on
the records, unchanged. The ACL fields v4 keeps in an entry's flags cell
(`v4/capsule/acl.v4`) go: v3's C ACL words serve a node as they are.
## 3c. What exactly is swapped, in v3's own files
Measured 2026-10-05. Each build already has one file that is the
interpreter, and the rest of v3 calls into it:
| Build | The interpreter file | The stacks |
|---|---|---|
| Hosted | `v3/src/vm.c` | `v3/src/stack_management.c` |
| Kernel | `kernel/src/vm/vm_core.c` (the kernel build leaves `v3/src/vm.c` out) | the same |
The functions in it that execute FORTH, and so are the node's to answer:
`vm_interpret`, `vm_interpret_word`, `execute_colon_word`, `acl_recheck`,
`vm_parse_word`, `vm_parse_number`, `vm_enter_compile_mode`,
`vm_exit_compile_mode`, `vm_compile_word`, `vm_compile_literal`,
`vm_compile_call`, `vm_compile_exit`, `vm_make_immediate`; the memory
accessors `vm_addr_ok`, `vm_ptr`, `vm_load_u8`, `vm_store_u8`,
`vm_load_cell`, `vm_store_cell`; and the stacks, `vm_push`, `vm_pop`,
`vm_rpush`, `vm_rpop`. The rest of those files — host services, the time
base, `vm_cleanup` — is not the engine and stays.
So the swap is a third interpreter file, for both builds: the same
functions, answered by a node. Everything else of v3 is compiled as it is.
**This changes what the hosted v4 product is.** It is not a separate
program (`v4/tools/hosted.c`, `v4/system/boot.c`). It is v3's hosted
program — its `main`, its REPL, its physics, its POST — built with the
node as its interpreter, exactly as the kernel product is v3's kernel
built the same way. `hosted.c` and `boot.c` are the lone node's and go
when that build reaches its prompt.
**Two things in v3's C words do not carry over as they are**, and must be
dealt with word by word:
- A C word that takes an address from the stack and reads memory through
`vm_ptr` gets a pointer into v3's flat bytes. A node's bytes are four to
a cell (D-1), so they are not a flat run of C bytes. Such a word needs
the text copied out of the node. `mama_forth_words.c` has 40 such uses.
- A C word that reaches into `vm->data_stack` or `vm->dsp` directly must
go through `vm_push`, `vm_pop` or a depth accessor. `mama_forth_words.c`
has 45.
Both are changes to files v3 also builds, so each must leave v3 as it is
and be accepted by v3's own three-ISA boot.
## 3a. Many VMs at once (Captain Bob, 2026-10-05)
> Do not forget that this is multiuser, multitasking, and a hybrid of
@@ -166,19 +227,19 @@ It is step 6's, and section 6 lists it as open.
**The loop that runs one node until its line ends** (`v4_boot_line`,
`v4/system/boot.c`) is the lone node's and the hosted program's, where
there is one node and nothing to share the processor with. It is not how
the kernel will run a fleet, and goes with the lone node at step 4.
the kernel will run a fleet, and goes with the lone node at step 5.
## 4. What was built on the detour
| Built 2026-10-05 | What becomes of it |
|---|---|
| `kernel_main.c` calling `sk_v4_run()` before the fleet tables | Goes at step 4. Until then it is how the bare-metal build is kept booting while the interface is built. |
| `v4/system/boot.c`: its own capsule loader and `PARITY:V4_*` lines | Goes at step 4, when v3's birth protocol loads the capsules and prints v3's parity lines. |
| `kernel_main.c` calling `sk_v4_run()` before the fleet tables | Goes at step 5. Until then it is how the bare-metal build is kept booting while the interface is built. |
| `v4/system/boot.c`: its own capsule loader and `PARITY:V4_*` lines | Goes at step 5, when v3's birth protocol loads the capsules and prints v3's parity lines. |
| The node's prompt loop, and the code that strips ` ok` from its output | Goes at step 1. |
| `capsules/v4/forth79.4th`, `post79.4th`, `mkpost.py`, the rules | Stay. POST is the gate for every word moved out of the nucleus. |
| `(CATCH)`, `(EMIT-HOOK)`, `NODE-ERROR` by name | Stay; POST uses them. |
| The per-call-target count (`v4/src/heat.c`, `call[]`) | Goes at step 3, when the node does at `call` what v3 does. |
| The hosted Linux product | Stays, on the same interface. Hosted v3 has no fleet and neither has hosted v4. |
| The hosted Linux product, as `v4/tools/hosted.c` | Goes at step 4: the hosted product is v3's hosted program with the node as its interpreter (3c). |
## 5. Steps
@@ -214,14 +275,18 @@ its logs.
3. **A word is being executed (3.5).** The hook at `call`; the ACL's
countdown and recheck; the word's count; `stadium_word_dispatch`.
In-line words become calls. The per-call-target count goes.
4. **In place.** Under `STARFORTH_V4` the kernel's own boot brings the
node up where it brings a v3 VM up, after the fleet tables; the
kernel's REPL drives it; blocks come from the block subsystem.
`sk_v4_run()` and `boot.c` go.
5. **Hera as v3 has her.** `init.4th` runs on the node; v3's whole POST;
v3's parity lines.
6. **The fleet.** Hestia and Artemis; message delivery; the switcher.
7. **Identity and the prompt.** Zuse; `[zuse@Hera] ok>`.
4. **The node as v3's interpreter, hosted.** The third interpreter file
(3c). v3's hosted program built with it: `vm_interpret` hands the node
the line; `register_word` makes a kernel word and its record; the
node's own words get records. It reaches v3's prompt. v3's POST runs
through it and its failures are the list of what is not yet there.
5. **The same, in the kernel.** Under `STARFORTH_V4` the kernel's boot
brings the node up where it brings a v3 VM up. `sk_v4_run()`,
`boot.c` and `hosted.c` go.
6. **Hera as v3 has her.** `init.4th` runs on the node; v3's whole POST
passes; v3's parity lines.
7. **The fleet.** Hestia and Artemis; message delivery; who runs next.
8. **Identity and the prompt.** Zuse; `[zuse@Hera] ok>`.
Moving words from the assembled nucleus to `forth79.4th` goes on beside
these, a group at a time, with POST after each.
@@ -233,7 +298,7 @@ these, a group at a time, with POST after each.
| How the node tells a dictionary entry from a bare address at `call` | Step 3 |
| `EXECUTE`, which enters a word by a return | Step 3 |
| `>R R> R@ I J LEAVE`, which cannot be called | Step 3 |
| Who decides which node runs next, and when: Hera, by compudynamics; preemptive and cooperative | Step 6 |
| The node's safe moment for message delivery and switching | Step 6 |
| `PAD 42 OVER !`, a byte address given to `!` (D-1) | Step 5 |
| Who decides which node runs next, and when: Hera, by compudynamics; preemptive and cooperative | Step 7 |
| The node's safe moment for message delivery and switching | Step 7 |
| `PAD 42 OVER !`, a byte address given to `!` (D-1) | Step 6 |
| Which word patrons' accounts the hosted product keeps, having no Stadium | Step 3 |