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 *v3:* `vm_dict_hash_fn`, a hook the birth protocol calls. *v4:* the same
hook, answered from the node's dictionary. 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) ## 3a. Many VMs at once (Captain Bob, 2026-10-05)
> Do not forget that this is multiuser, multitasking, and a hybrid of > 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`, **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 `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 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 ## 4. What was built on the detour
| Built 2026-10-05 | What becomes of it | | 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. | | `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 4, when v3's birth protocol loads the capsules and prints v3's parity lines. | | `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. | | 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. | | `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. | | `(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 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 ## 5. Steps
@@ -214,14 +275,18 @@ its logs.
3. **A word is being executed (3.5).** The hook at `call`; the ACL's 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`. countdown and recheck; the word's count; `stadium_word_dispatch`.
In-line words become calls. The per-call-target count goes. In-line words become calls. The per-call-target count goes.
4. **In place.** Under `STARFORTH_V4` the kernel's own boot brings the 4. **The node as v3's interpreter, hosted.** The third interpreter file
node up where it brings a v3 VM up, after the fleet tables; the (3c). v3's hosted program built with it: `vm_interpret` hands the node
kernel's REPL drives it; blocks come from the block subsystem. the line; `register_word` makes a kernel word and its record; the
`sk_v4_run()` and `boot.c` go. node's own words get records. It reaches v3's prompt. v3's POST runs
5. **Hera as v3 has her.** `init.4th` runs on the node; v3's whole POST; through it and its failures are the list of what is not yet there.
v3's parity lines. 5. **The same, in the kernel.** Under `STARFORTH_V4` the kernel's boot
6. **The fleet.** Hestia and Artemis; message delivery; the switcher. brings the node up where it brings a v3 VM up. `sk_v4_run()`,
7. **Identity and the prompt.** Zuse; `[zuse@Hera] ok>`. `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 Moving words from the assembled nucleus to `forth79.4th` goes on beside
these, a group at a time, with POST after each. 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 | | 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 | | `EXECUTE`, which enters a word by a return | Step 3 |
| `>R R> R@ I J LEAVE`, which cannot be called | 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 | | 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 6 | | The node's safe moment for message delivery and switching | Step 7 |
| `PAD 42 OVER !`, a byte address given to `!` (D-1) | Step 5 | | `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 | | Which word patrons' accounts the hosted product keeps, having no Stadium | Step 3 |