docs: add StarForth primitive word reference
Lists every C-registered StarForth primitive with stack notation and usage notes, grouped by module, plus a section on implementation quirks. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BY9HMwK5Cetz3caBgHGyds
This commit is contained in:
@@ -0,0 +1,787 @@
|
||||
# StarForth Primitive Word Reference
|
||||
|
||||
This reference covers every **C-implemented primitive** word that StarForth registers. It was built from
|
||||
`admin/LithosAnanake` at commit `6302dcb` (2026-09-23). It lists only words registered in C
|
||||
through `register_word()` or `vm_create_word()`. Words defined in FORTH inside capsules (`*.4th`) are out of scope.
|
||||
|
||||
Sources:
|
||||
|
||||
- `src/word_registry.c`: `register_forth79_words()` registers the core set in every VM.
|
||||
- `src/word_source/*.c`: one file per module.
|
||||
- `src/starkernel/capsule/mama_forth_words.c`: kernel-only Hera (Mama) and child-VM words.
|
||||
- `src/starkernel/repl.c` and `src/starkernel/doe_log.c`: kernel-only REPL and DoE words.
|
||||
|
||||
---
|
||||
|
||||
## Conventions
|
||||
|
||||
| Item | Meaning |
|
||||
|---|---|
|
||||
| Cell | `cell_t` is `int64_t`, so every cell is 64 bits and signed. |
|
||||
| Flag | TRUE is `-1` (all bits set) and FALSE is `0`. Words that take a flag treat any non-zero value as true. |
|
||||
| `addr` | A **VM address**: a byte offset into the VM's 5 MB linear memory (`VM_MEMORY_SIZE`), not a host pointer. |
|
||||
| `c-addr u` | A string given as its address and length. |
|
||||
| `d`, `ud` | A double-cell number made of two cells, with the **high cell on top**. |
|
||||
| `xt` | An execution token. In StarForth this is the `DictEntry*` of the word. |
|
||||
| `q` | A Q48.16 fixed-point value in one cell (`1.0` = `65536`). |
|
||||
| `"name"` | The word parses a name from the input stream after it. |
|
||||
| `( R: ... )` | The effect on the return stack. |
|
||||
| **IMM** | The word is IMMEDIATE, so it runs even while compiling. |
|
||||
| **CO** | The word is compile-only and sets `vm->error` if used outside a definition. |
|
||||
| **K** | The word is registered only in the kernel build (`__STARKERNEL__`). |
|
||||
| **H** | The word is registered only in the hosted build (the Linux or macOS binary). |
|
||||
|
||||
Errors: a primitive does not throw. On stack underflow or overflow, a bad address, or division by zero it sets
|
||||
`vm->error = 1` and logs a message.
|
||||
|
||||
Stack limits: the data stack and return stack hold 1024 cells each (`STACK_SIZE`). A word name can be at most 31
|
||||
characters (`WORD_NAME_MAX`).
|
||||
|
||||
Shadowing: when a later module registers a name again, the newer entry wins lookups. For example, `MOD`, `/MOD`,
|
||||
`*/` and `*/MOD` are registered by the arithmetic module and again by the mixed-arithmetic module, so the
|
||||
mixed-arithmetic versions are the active ones.
|
||||
|
||||
---
|
||||
|
||||
## Contents
|
||||
|
||||
1. [Stack](#1-stack)
|
||||
2. [Return stack](#2-return-stack)
|
||||
3. [Memory](#3-memory)
|
||||
4. [Arithmetic](#4-arithmetic)
|
||||
5. [Logic and comparison](#5-logic-and-comparison)
|
||||
6. [Mixed-precision arithmetic](#6-mixed-precision-arithmetic)
|
||||
7. [Double-cell numbers](#7-double-cell-numbers)
|
||||
8. [Number formatting and output](#8-number-formatting-and-output)
|
||||
9. [Strings, parsing, and input](#9-strings-parsing-and-input)
|
||||
10. [Terminal I/O](#10-terminal-io)
|
||||
11. [Blocks and mass storage](#11-blocks-and-mass-storage)
|
||||
12. [Dictionary space](#12-dictionary-space)
|
||||
13. [Dictionary manipulation](#13-dictionary-manipulation)
|
||||
14. [Vocabularies](#14-vocabularies)
|
||||
15. [System](#15-system)
|
||||
16. [Line editor](#16-line-editor)
|
||||
17. [Defining words and the compiler](#17-defining-words-and-the-compiler)
|
||||
18. [Control flow](#18-control-flow)
|
||||
19. [StarForth extensions](#19-starforth-extensions)
|
||||
20. [Word-level ACL](#20-word-level-acl)
|
||||
21. [Physics: benchmark and diagnostics](#21-physics-benchmark-and-diagnostics)
|
||||
22. [Physics: pipelining diagnostics](#22-physics-pipelining-diagnostics)
|
||||
23. [Physics: freeze, heat, and decay](#23-physics-freeze-heat-and-decay)
|
||||
24. [Dictionary heat optimisation](#24-dictionary-heat-optimisation)
|
||||
25. [Logging](#25-logging)
|
||||
26. [Q48.16 fixed-point math](#26-q4816-fixed-point-math)
|
||||
27. [Inference engine (SSM, L8, and Bayes)](#27-inference-engine-ssm-l8-and-bayes)
|
||||
28. [DEFER and IS](#28-defer-and-is)
|
||||
29. [Framebuffer (Hestia only)](#29-framebuffer-hestia-only)
|
||||
30. [Keyboard](#30-keyboard)
|
||||
31. [TrueType text](#31-truetype-text)
|
||||
32. [REPL scrollback](#32-repl-scrollback)
|
||||
33. [Kernel REPL and DoE hooks](#33-kernel-repl-and-doe-hooks)
|
||||
34. [Hera (Mama) and child-VM words](#34-hera-mama-and-child-vm-words)
|
||||
35. [Hosted lifecycle stubs](#35-hosted-lifecycle-stubs)
|
||||
36. [Implementation quirks to know](#36-implementation-quirks-to-know)
|
||||
|
||||
---
|
||||
|
||||
## 1. Stack
|
||||
`src/word_source/stack_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `DROP` | `( x -- )` | Discards the top cell. |
|
||||
| `DUP` | `( x -- x x )` | Copies the top cell. |
|
||||
| `?DUP` | `( x -- x x \| 0 -- 0 )` | Copies the top cell only when it is non-zero. The usual idiom is `?DUP IF ... THEN`. |
|
||||
| `SWAP` | `( x1 x2 -- x2 x1 )` | Swaps the top two cells. |
|
||||
| `OVER` | `( x1 x2 -- x1 x2 x1 )` | Copies the second cell to the top. |
|
||||
| `ROT` | `( x1 x2 x3 -- x2 x3 x1 )` | Moves the third cell to the top. |
|
||||
| `-ROT` | `( x1 x2 x3 -- x3 x1 x2 )` | Moves the top cell down to third place. This is the reverse of `ROT`. |
|
||||
| `DEPTH` | `( -- n )` | Pushes the number of cells that were on the data stack before `DEPTH` ran. |
|
||||
| `PICK` | `( xn … x0 n -- xn … x0 xn )` | Copies the n-th cell to the top. **0-based:** `0 PICK` is `DUP` and `1 PICK` is `OVER`. An error occurs if `n < 0` or `n ≥ depth`. |
|
||||
| `ROLL` | `( … n -- … )` | Moves a cell to the top and closes the gap. **Non-standard:** `n` counts from the *bottom* of the stack (1-based), so `1 ROLL` moves the deepest cell to the top. `0 ROLL` does nothing. See [§36](#36-implementation-quirks-to-know). |
|
||||
|
||||
## 2. Return stack
|
||||
`src/word_source/return_stack_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `>R` | `( x -- ) ( R: -- x )` | Moves a cell from the data stack to the return stack. Inside a definition, balance it with `R>` before `;` or `EXIT`. |
|
||||
| `R>` | `( -- x ) ( R: x -- )` | Moves a cell from the return stack back to the data stack. |
|
||||
| `R@` | `( -- x ) ( R: x -- x )` | Copies the top of the return stack without removing it. |
|
||||
|
||||
## 3. Memory
|
||||
`src/word_source/memory_words.c`. Every address is a VM byte offset and is checked against the VM's memory bounds.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `@` | `( addr -- x )` | Fetches the cell at `addr`. |
|
||||
| `!` | `( x addr -- )` | Stores `x` at `addr`. |
|
||||
| `C@` | `( addr -- c )` | Fetches the byte at `addr`, zero-extended. |
|
||||
| `C!` | `( c addr -- )` | Stores the low 8 bits of `c` at `addr`. |
|
||||
| `+!` | `( n addr -- )` | Adds `n` to the cell at `addr`. |
|
||||
| `-!` | `( n addr -- )` | Subtracts `n` from the cell at `addr`. |
|
||||
| `2@` | `( addr -- x-lo x-hi )` | Fetches two cells: the low cell from `addr` and the high cell from `addr+8`, leaving the high cell on top. |
|
||||
| `2!` | `( x-lo x-hi addr -- )` | Stores two cells: the low cell at `addr` and the high cell at `addr+8`. |
|
||||
| `FILL` | `( addr u c -- )` | Fills `u` bytes starting at `addr` with the byte `c`. |
|
||||
| `MOVE` | `( src dst u -- )` | Copies `u` bytes from `src` to `dst`. It is safe when the ranges overlap because it uses memmove semantics. |
|
||||
| `ERASE` | `( addr u -- )` | Sets `u` bytes to zero. |
|
||||
| `CELLS` | `( n -- n*8 )` | Scales a cell count to a byte count. |
|
||||
|
||||
## 4. Arithmetic
|
||||
`src/word_source/arithmetic_words.c`. All arithmetic is signed 64-bit, and division truncates toward zero as in C.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `+` | `( n1 n2 -- n1+n2 )` | Adds the two cells. |
|
||||
| `-` | `( n1 n2 -- n1-n2 )` | Subtracts `n2` from `n1`. |
|
||||
| `*` | `( n1 n2 -- n1*n2 )` | Multiplies the two cells. The result wraps modulo 2⁶⁴. |
|
||||
| `/` | `( n1 n2 -- n1/n2 )` | Divides, truncating toward zero. Division by zero sets an error. |
|
||||
| `MOD` | `( n1 n2 -- rem )` | Pushes the remainder of `n1 / n2`, which has the sign of `n1`. This name is shadowed by §6. |
|
||||
| `/MOD` | `( n1 n2 -- rem quot )` | Pushes the remainder and the quotient, with the quotient on top. This name is shadowed by §6. |
|
||||
| `*/` | `( n1 n2 n3 -- n1*n2/n3 )` | Multiplies and then divides using a wide intermediate. This name is shadowed by §6. |
|
||||
| `*/MOD` | `( n1 n2 n3 -- rem quot )` | Like `*/`, but also leaves the remainder. This name is shadowed by §6. |
|
||||
| `1+` `1-` | `( n -- n±1 )` | Increments or decrements by 1. |
|
||||
| `2+` `2-` | `( n -- n±2 )` | Adds or subtracts 2. |
|
||||
| `2*` | `( n -- n*2 )` | Shifts left by one bit. |
|
||||
| `2/` | `( n -- n/2 )` | Shifts right by one bit, keeping the sign (arithmetic shift). |
|
||||
| `ABS` | `( n -- \|n\| )` | Pushes the absolute value. |
|
||||
| `NEGATE` | `( n -- -n )` | Pushes the two's-complement negation. |
|
||||
| `MIN` `MAX` | `( n1 n2 -- n3 )` | Pushes the smaller or the larger value, compared as signed numbers. |
|
||||
|
||||
## 5. Logic and comparison
|
||||
`src/word_source/logical_words.c`. Comparison words return a proper flag of `-1` or `0`.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `AND` `OR` `XOR` | `( x1 x2 -- x3 )` | Bitwise AND, OR, and XOR. |
|
||||
| `NOT` | `( x -- flag )` | **FORTH-79 logical NOT:** `0` gives `TRUE` and any other value gives `FALSE`. This is *not* a bitwise complement; use `INVERT` for that. |
|
||||
| `INVERT` | `( x -- ~x )` | Bitwise complement (from FORTH-83). |
|
||||
| `LSHIFT` | `( x u -- x<<u )` | Logical shift left by `u` bits. |
|
||||
| `RSHIFT` | `( x u -- x>>u )` | Logical (unsigned) shift right by `u` bits. |
|
||||
| `0=` | `( n -- flag )` | True if `n` is 0. |
|
||||
| `0<` | `( n -- flag )` | True if `n` is negative. |
|
||||
| `0>` | `( n -- flag )` | True if `n` is positive. |
|
||||
| `0<>` | `( n -- flag )` | True if `n` is not 0. |
|
||||
| `=` `<>` | `( n1 n2 -- flag )` | Tests for equality or inequality. |
|
||||
| `<` `>` `<=` `>=` | `( n1 n2 -- flag )` | Signed comparisons of `n1` against `n2`. |
|
||||
| `U<` `U>` | `( u1 u2 -- flag )` | Unsigned comparisons. |
|
||||
| `WITHIN` | `( n lo hi -- flag )` | True if `lo ≤ n < hi`, using the standard half-open range. |
|
||||
| `TRUE` | `( -- -1 )` | Pushes the canonical true flag. |
|
||||
| `FALSE` | `( -- 0 )` | Pushes the canonical false flag. |
|
||||
|
||||
## 6. Mixed-precision arithmetic
|
||||
`src/word_source/mixed_arithmetic_words.c`. A double here means two full 64-bit cells (128 bits).
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `M+` | `( d n -- d' )` | Adds a signed single to a double and propagates the carry into the high cell. |
|
||||
| `M-` | `( d n -- d' )` | Subtracts a signed single from a double and propagates the borrow. |
|
||||
| `M*` | `( n1 n2 -- d )` | Multiplies 64×64 into a full 128-bit signed product, using `__int128` internally. The result can be printed with `D.`. |
|
||||
| `M/MOD` | `( d n -- rem quot )` | Divides a 128-bit double by a single, leaving the quotient on top. It uses bit-serial long division, so it works in the freestanding kernel without libgcc. |
|
||||
| `MOD` | `( n1 n2 -- rem )` | **Active version.** Computes `n1 % n2`. Division by zero sets an error. |
|
||||
| `/MOD` | `( n1 n2 -- rem quot )` | **Active version.** Leaves the remainder under the quotient. Division by zero sets an error. |
|
||||
| `*/` | `( n1 n2 n3 -- n4 )` | **Active version.** Computes `(n1*n2)/n3` with a wide intermediate, so `n1*n2` does not overflow. Division by zero sets an error. Typical use is scaling, for example `x 355 113 */`. |
|
||||
| `*/MOD` | `( n1 n2 n3 -- rem quot )` | **Active version.** Like `*/`, but also leaves the remainder under the quotient. |
|
||||
|
||||
## 7. Double-cell numbers
|
||||
`src/word_source/double_words.c`. In every stack picture, `d` stands for the pair `( lo hi )` with the high cell on top.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `S>D` | `( n -- d )` | Sign-extends a single to a double. |
|
||||
| `D+` `D-` | `( d1 d2 -- d3 )` | Double add and subtract, with carry or borrow. |
|
||||
| `DNEGATE` | `( d -- -d )` | Negates a double. |
|
||||
| `DABS` | `( d -- \|d\| )` | Pushes the absolute value of a double. |
|
||||
| `DMAX` `DMIN` | `( d1 d2 -- d3 )` | Pushes the larger or smaller double, compared as signed values. |
|
||||
| `D<` | `( d1 d2 -- flag )` | Signed less-than on doubles. |
|
||||
| `D=` | `( d1 d2 -- flag )` | Equality on doubles. |
|
||||
| `D0=` | `( d -- flag )` | True if the double is zero. |
|
||||
| `D0<` | `( d -- flag )` | True if the double is negative. |
|
||||
| `D2*` | `( d -- d*2 )` | Shifts a double left by one bit across both cells. |
|
||||
| `D2/` | `( d -- d/2 )` | Shifts a double right by one bit (arithmetic shift) across both cells. |
|
||||
| `2DROP` | `( x1 x2 -- )` | Drops a cell pair. |
|
||||
| `2DUP` | `( x1 x2 -- x1 x2 x1 x2 )` | Duplicates a cell pair. |
|
||||
| `2SWAP` | `( p1 p2 -- p2 p1 )` | Swaps two cell pairs. |
|
||||
| `2OVER` | `( p1 p2 -- p1 p2 p1 )` | Copies the second pair to the top. |
|
||||
| `2ROT` | `( p1 p2 p3 -- p2 p3 p1 )` | Rotates three cell pairs. |
|
||||
| `2>R` | `( x1 x2 -- ) ( R: -- x1 x2 )` | Moves a pair to the return stack. |
|
||||
| `2R>` | `( -- x1 x2 ) ( R: x1 x2 -- )` | Moves a pair back from the return stack. |
|
||||
| `2R@` | `( -- x1 x2 ) ( R: x1 x2 -- x1 x2 )` | Copies a pair from the return stack. |
|
||||
|
||||
## 8. Number formatting and output
|
||||
`src/word_source/format_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `.` | `( n -- )` | Prints a signed number in the current `BASE`, followed by a space. |
|
||||
| `.R` | `( n width -- )` | Prints a signed number right-aligned in a field `width` characters wide. |
|
||||
| `U.` | `( u -- )` | Prints an unsigned number followed by a space. |
|
||||
| `U.R` | `( u width -- )` | Prints an unsigned number right-aligned. |
|
||||
| `D.` | `( d -- )` | Prints a signed double. |
|
||||
| `D.R` | `( d width -- )` | Prints a signed double right-aligned. |
|
||||
| `.S` | `( -- )` | Prints the data stack without changing it. This is the main debugging aid. |
|
||||
| `?` | `( addr -- )` | Prints the cell at `addr`; it is the same as `@ .`. |
|
||||
| `DUMP` | `( addr u -- )` | Prints a hex and ASCII dump of `u` bytes starting at `addr`. |
|
||||
| `<#` | `( -- )` | Starts pictured numeric output by resetting the conversion buffer. |
|
||||
| `#` | `( ud -- ud' )` | Converts one digit (`ud mod BASE`) into the buffer. It also accepts a single signed cell and converts its magnitude. |
|
||||
| `#S` | `( ud -- 0 0 )` | Converts digits until the value is zero, always producing at least one digit. It accepts a single cell the same way `#` does. |
|
||||
| `HOLD` | `( c -- )` | Inserts the character `c` into the pictured output buffer. |
|
||||
| `SIGN` | `( n -- )` | Inserts `-` if `n` is negative. |
|
||||
| `#>` | `( ud -- c-addr u )` | Ends conversion and leaves the string. It is tolerant: it pops `ud` only if one is present. |
|
||||
| `BASE` | `( -- addr )` | Pushes the address of the number-conversion radix variable. |
|
||||
| `DECIMAL` `HEX` `OCTAL` | `( -- )` | Sets `BASE` to 10, 16, or 8. |
|
||||
|
||||
Example: `: .$ ( n -- ) <# # # 46 HOLD #S #> TYPE ;` prints `1234` as `12.34`.
|
||||
|
||||
## 9. Strings, parsing, and input
|
||||
`src/word_source/string_words.c`. The comparison and search words below also accept a counted string in place of an
|
||||
`addr u` pair; they detect it when the first byte at `addr` equals `u`.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `COUNT` | `( c-addr1 -- c-addr2 u )` | Converts a counted string (length byte followed by characters) into an address and length. |
|
||||
| `EXPECT` | `( addr u -- )` | Reads up to `u` characters from the terminal into `addr` and stores the count read in `SPAN`. |
|
||||
| `SPAN` | `( -- addr )` | Pushes the address of the variable that holds the count from the last `EXPECT`. |
|
||||
| `QUERY` | `( -- )` | Reads a line into `TIB` and resets `>IN`. |
|
||||
| `TIB` | `( -- addr )` | Pushes the address of the terminal input buffer. |
|
||||
| `>IN` | `( -- addr )` | Pushes the address of the offset into the current input source. |
|
||||
| `SOURCE` | `( -- addr u )` | Pushes the current input buffer and its length. |
|
||||
| `WORD` | `( c -- c-addr )` | Skips leading `c` characters, parses up to the next `c`, and returns a counted string. The usual form is `BL WORD`. |
|
||||
| `BL` | `( -- 32 )` | Pushes the ASCII space character. |
|
||||
| `S"` **IMM** | `( "ccc<">" -- c-addr u )` | In interpret mode, stores the string at `HERE` and pushes it. When compiling, it compiles `(s")` followed by the inline text. |
|
||||
| `(s")` | `( -- c-addr u )` | Runtime for a compiled `S"`: reads the inline `[len][chars][pad]` block and skips the IP past it. The compiler inserts it; you do not call it directly. |
|
||||
| `[']` **IMM** | `( "name" -- xt )` | While compiling, compiles the xt of `name` as a literal. In interpret mode it behaves like `'`. |
|
||||
| `LITERAL` `[LITERAL]` | – | Placeholders that do nothing. `LITERAL` is re-registered in §17 (the working version); `[LITERAL]` has no replacement and still does nothing. |
|
||||
| `CONVERT` | `( d1 addr1 -- d2 addr2 )` | Accumulates the digits at `addr1+1…` into `d1` and stops at the first non-digit. This is a simplified version. |
|
||||
| `NUMBER` | `( c-addr -- n flag )` | Converts a counted string to a number. Only base 10 is supported, and `flag` shows whether it succeeded. |
|
||||
| `ENCLOSE` | `( addr c -- addr n1 n2 n3 )` | The classic FIG parser: gives the offsets of the start of the token, the delimiter after it, and the next character. |
|
||||
| `-TRAILING` | `( addr u -- addr u' )` | Removes trailing spaces from the length. |
|
||||
| `CMOVE` | `( src dst u -- )` | Copies bytes upward from low to high addresses. It is safe for overlapping ranges when `dst ≤ src`. |
|
||||
| `CMOVE>` | `( src dst u -- )` | Copies bytes downward from high to low addresses. It is safe for overlapping ranges when `dst > src`. |
|
||||
| `COMPARE` | `( a1 u1 a2 u2 -- n )` | Compares two strings case-sensitively and returns `-1`, `0`, or `1`. |
|
||||
| `SEARCH` | `( a1 u1 a2 u2 -- a3 u3 flag )` | Finds string 2 inside string 1. If found, it returns the tail starting at the match and `-1`. If not, it returns string 1 unchanged and `0`. |
|
||||
| `SCAN` | `( addr u c -- addr' u' )` | Advances to the first occurrence of `c`. If there is none, it returns the end of the string and `0`. |
|
||||
| `SKIP` | `( addr u c -- addr' u' )` | Skips leading occurrences of `c`. |
|
||||
| `BLANK` | `( addr u -- )` | Fills `u` bytes with spaces. |
|
||||
|
||||
## 10. Terminal I/O
|
||||
`src/word_source/io_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `EMIT` | `( c -- )` | Prints one character. |
|
||||
| `CR` | `( -- )` | Prints a newline. |
|
||||
| `KEY` | `( -- c )` | Waits for a character and pushes it. |
|
||||
| `?TERMINAL` | `( -- flag )` | True if a key is waiting. It does not block. |
|
||||
| `TYPE` | `( c-addr u -- )` | Prints `u` characters. |
|
||||
| `SPACE` | `( -- )` | Prints one space. |
|
||||
| `SPACES` | `( n -- )` | Prints `n` spaces. |
|
||||
| `."` **IMM** | `( "ccc<">" -- )` | In interpret mode, prints the string immediately. When compiling, it compiles `(do-string)` and the inline text. |
|
||||
| `(do-string)` | `( -- )` | Runtime for a compiled `."`: prints the inline string and skips the IP past it. The compiler inserts it; you do not call it directly. |
|
||||
|
||||
## 11. Blocks and mass storage
|
||||
`src/word_source/block_words.c`. A block is 1024 bytes, viewed as 16 lines of 64 characters. Block numbers are
|
||||
LBNs (logical block numbers) in one address space that spans every attached device.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `BLOCK` | `( u -- addr )` | Returns the VM address of the buffer holding block `u`, reading it from disk if needed. It does not mark the buffer dirty. |
|
||||
| `BUFFER` | `( u -- addr )` | Assigns a buffer to block `u` *without* reading from disk and marks it dirty. Use it when you will overwrite the whole block. |
|
||||
| `UPDATE` | `( -- )` | Marks the current (`SCR`) block dirty and syncs it to the C block layer. |
|
||||
| `SAVE-BUFFERS` | `( -- )` | Writes every dirty buffer to disk. |
|
||||
| `EMPTY-BUFFERS` | `( -- )` | Discards every buffer **without** writing it and zeroes the user block window. |
|
||||
| `FLUSH` | `( -- )` | Runs `SAVE-BUFFERS` and then invalidates all buffers. |
|
||||
| `LOAD` | `( u -- )` | Sets `SCR` to `u` and interprets the 1024 bytes of block `u` as FORTH source. Block 0 cannot be loaded. |
|
||||
| `THRU` | `( u1 u2 -- )` | Loads blocks `u1` through `u2`, including both ends. |
|
||||
| `-->` | `( -- )` | Inside a block being loaded, continues interpreting at the next block. |
|
||||
| `LIST` | `( u -- )` | Sets `SCR` to `u` and prints the block. |
|
||||
| `SCR` | `( -- addr )` | Pushes the address of the variable holding the block number last listed or loaded. |
|
||||
| `BLK-CONFIRM-FORMAT` | `( lbn -- )` | Commits the container format of the device that owns `lbn`. Until this has run, the block layer **refuses every write** to that device. Only the owner (for example Artemis) should call it, and only after checking the disk contents are safe to touch. |
|
||||
| `RELOCATE-BLOCK` | `( home target -- )` | Moves the contents of `home` to `target` and redirects all later access to `home` through `target`. It is a mechanical primitive: it does not check whether `target` is free or owned by the caller. |
|
||||
| `BLK-ACL-ALLOW@` | `( blk -- allow )` | Reads the cached allow/deny flag of a block's ACL. |
|
||||
| `BLK-ACL-ALLOW!` | `( allow blk -- )` | Sets a block's cached allow/deny flag. |
|
||||
| `BLK-ACL-TTL@` | `( blk -- ttl )` | Reads a block's ACL TTL countdown. |
|
||||
| `BLK-ACL-TTL!` | `( ttl blk -- )` | Sets a block's ACL TTL countdown. |
|
||||
| `BLK-OWNER@` | `( blk -- fp )` | Pushes the 8-byte owner fingerprint as the raw bits of one cell. There is no `BLK-OWNER!`: ownership is set only in C, during MINT or birth. |
|
||||
| `BLK-ATTACH` | `( dev-ptr -- ok? )` | Registers an already-open `blkio_dev_t*`, passed as a raw pointer cell, in the unified LBN space. The pointer is trusted without checks. Artemis's USB-attach handler uses it. |
|
||||
|
||||
## 12. Dictionary space
|
||||
`src/word_source/dictionary_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `HERE` | `( -- addr )` | Pushes the next free byte in the dictionary. |
|
||||
| `ALIGN` | `( -- )` | Rounds `HERE` up to the next 8-byte cell boundary. |
|
||||
| `ALLOT` | `( n -- )` | Reserves `n` bytes at `HERE`. A negative `n` gives space back. |
|
||||
| `,` | `( x -- )` | Compiles one cell at `HERE` and advances `HERE`. |
|
||||
| `C,` | `( c -- )` | Compiles one byte. |
|
||||
| `2,` | `( x-lo x-hi -- )` | Compiles two cells, low cell first. |
|
||||
| `PAD` | `( -- addr )` | Pushes the address of a 512-byte scratch buffer near the top of memory. It is safe for temporary strings. |
|
||||
| `SP@` | `( -- n )` | Pushes the data stack pointer *index* (`dsp`). An empty stack gives `-1` and one item gives `0`. |
|
||||
| `SP!` | `( n -- )` | Restores the stack pointer index. It can only shrink the stack, never grow it. |
|
||||
| `LATEST` | `( -- addr )` | Pushes the address of the most recent definition. |
|
||||
|
||||
## 13. Dictionary manipulation
|
||||
`src/word_source/dictionary_manipulation_words.c`. Header-field words work on raw header addresses. They exist for
|
||||
FIG and FORTH-79 compatibility; take care with them.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `'` | `( "name" -- xt )` | Parses `name` and pushes its xt. It is not IMMEDIATE; inside a definition, use `[']`. |
|
||||
| `FIND` | `( "name" -- xt \| 0 )` | **Parses from the input stream**, not from a counted string on the stack. It pushes the entry, or `0` if the word is not found (a miss is not an error). For a counted string already in memory, use `(FIND)` from §14. |
|
||||
| `SMUDGE` | `( -- )` | **CO.** Toggles the smudge (hidden) bit on the latest word. |
|
||||
| `HIDDEN` | `( -- )` | **CO.** Sets the latest word's hidden bit (unlike `SMUDGE`, it does not toggle). |
|
||||
| `>BODY` | `( xt -- addr )` | Pushes the address of the parameter (data) field. |
|
||||
| `>NAME` | `( xt -- nfa )` | Pushes the name field. |
|
||||
| `NAME>` | `( nfa -- xt )` | Goes from the name field to the xt. |
|
||||
| `>LINK` | `( xt -- lfa )` | Pushes the link field. |
|
||||
| `LINK>` | `( lfa -- xt )` | Follows the link to the next (older) word. |
|
||||
| `CFA` `LFA` `NFA` `PFA` | `( addr -- addr' )` | FIG-style field-address conversions (code, link, name, and parameter fields). |
|
||||
| `TRAVERSE` | `( addr n -- addr' )` | Moves across a name field forward (`n=1`) or backward (`n=-1`). |
|
||||
| `INTERPRET` | `( -- )` | Runs the text interpreter on the rest of the current input. |
|
||||
|
||||
## 14. Vocabularies
|
||||
`src/word_source/vocabulary_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `VOCABULARY` | `( "name" -- )` | Creates a vocabulary. Running `name` later makes it the `CONTEXT` (search) vocabulary. |
|
||||
| `DEFINITIONS` | `( -- )` | Sets `CURRENT` to `CONTEXT`, so new definitions go into the vocabulary being searched. |
|
||||
| `CONTEXT` | `( -- addr )` | Pushes the address of the search-vocabulary pointer. |
|
||||
| `CURRENT` | `( -- addr )` | Pushes the address of the definition-vocabulary pointer. |
|
||||
| `FORTH` | `( -- )` | Makes the root `FORTH` vocabulary the context. |
|
||||
| `ORDER` | `( -- )` | Prints the search order (`CONTEXT`, then `FORTH`) and `CURRENT`. |
|
||||
| `(FIND)` | `( c-addr -- c-addr 0 \| xt 1 \| xt -1 )` | Looks up a counted string in `CONTEXT` and then in `FORTH`. It returns `1` for an IMMEDIATE word, `-1` for a normal word, and `0` if not found. |
|
||||
|
||||
Example: `VOCABULARY GRAPHICS GRAPHICS DEFINITIONS : BOX ... ; FORTH DEFINITIONS`
|
||||
|
||||
## 15. System
|
||||
`src/word_source/system_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `(` **IMM** | `( "ccc<)>" -- )` | Starts a comment that runs to the closing `)`. |
|
||||
| `\` **IMM** | `( "ccc<eol>" -- )` | Starts a comment that runs to the end of the line. |
|
||||
| `EXECUTE` | `( xt -- )` | Runs the word identified by `xt`. |
|
||||
| `NOP` | `( -- )` | Does nothing. |
|
||||
| `QUIT` **IMM** | `( -- ) ( R: … -- )` | Clears the return stack and the error flag and returns to the outer interpreter. The data stack is kept. It is refused (sets an error) inside a definition. |
|
||||
| `ABORT` | `( … -- )` | Clears both stacks and returns to the interpreter. It is **not** reported as an error. |
|
||||
| `ABORT"` **IMM** | `( flag "ccc<">" -- )` | If `flag` is non-zero, prints the message and runs `ABORT`. It works in both interpret and compile mode. |
|
||||
| `(ABORT")` | `( flag addr u -- )` | Runtime for a compiled `ABORT"`. The compiler inserts it; you do not call it directly. |
|
||||
| `COLD` | `( -- )` | Clears both stacks and the error flag, returns to interpret mode, and moves `HERE` back to 1024 if it is higher. Dictionary headers are **not** removed; this is a minimal cold start. |
|
||||
| `WARM` | `( -- )` | Clears both stacks and the error flag and returns to interpret mode. `HERE` and the dictionary are kept. |
|
||||
| `BYE` | `( -- )` | Leaves this VM. In a child VM it halts the VM and returns to the parent's REPL. On Hera, the kernel's `BYE` from §34 takes precedence. |
|
||||
| `REBOOT` | `( c-addr u -- )` | Sets the boot arguments and does a cold reset. Interpret mode only. |
|
||||
| `SAVE-SYSTEM` | `( -- )` | Takes a simple snapshot of the start of VM memory. |
|
||||
| `WORDS` | `( -- )` | Lists the words in the current vocabulary. |
|
||||
| `VLIST` | `( -- )` | Gives a detailed word listing. |
|
||||
| `SEE` | `( "name" -- )` | Decompiles and shows a definition. |
|
||||
| `PAGE` | `( -- )` | Clears the screen. |
|
||||
| `79-STANDARD` | `( -- flag )` | Pushes `-1` when FORTH-79 compliance mode is on. |
|
||||
|
||||
## 16. Line editor
|
||||
`src/word_source/editor_words.c`. The editor works on block `SCR` as 16 lines of 64 characters.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `L` | `( u -- )` | Prints line `u` (0–15) of the current screen. |
|
||||
| `S` | `( c-addr len u -- )` | Replaces line `u` with the string, padding with spaces or truncating to 64 characters. |
|
||||
| `SHOW` | `( -- )` | Prints the whole screen with line numbers. |
|
||||
| `EDIT` | `( u -- )` | Opens a minimal stdin/stdout line-editor shell on block `u`. |
|
||||
|
||||
## 17. Defining words and the compiler
|
||||
`src/word_source/defining_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `:` **IMM** | `( "name" -- )` | Starts a colon definition and switches to compile mode. The new word stays hidden until `;`. |
|
||||
| `;` **IMM** | `( -- )` | Compiles `EXIT`, ends the definition, reveals the word, and returns to interpret mode. |
|
||||
| `CREATE` | `( "name" -- )` | Makes a header whose runtime pushes its data-field address (`HERE` aligned to a cell). It allocates **no** space, so follow it with `ALLOT` or `,`. |
|
||||
| `VARIABLE` | `( "name" -- )` | Makes a word that pushes the address of one newly allocated cell. |
|
||||
| `CONSTANT` | `( x "name" -- )` | Makes a word that pushes `x`. |
|
||||
| `DOES>` **IMM** | `( -- )` | Inside a defining word, ends the create part. Words later made by that defining word run the code after `DOES>` with their body address on the stack. |
|
||||
| `IMMEDIATE` **IMM** | `( -- )` | Marks the latest definition IMMEDIATE. |
|
||||
| `STATE` | `( -- addr )` | Pushes the address of the compile-state cell (0 means interpreting). |
|
||||
| `[` **IMM** | `( -- )` | Switches to interpret mode inside a definition. |
|
||||
| `]` **IMM** | `( -- )` | Switches to compile mode. |
|
||||
| `LITERAL` **IMM** | `( x -- )` | Compiles `x` so that it is pushed at runtime. Typical use: `[ 6 7 * ] LITERAL`. |
|
||||
| `LIT` | `( -- x )` | Runtime for literals: pushes the next inline cell. The compiler inserts it; you do not call it directly. |
|
||||
| `COMPILE` **IMM** | `( "name" -- )` | Legacy form: compiles a call to `name`. |
|
||||
| `[COMPILE]` **IMM** | `( "name" -- )` | Compiles `name` even when it is IMMEDIATE. |
|
||||
| `FORGET` | `( "name" -- )` | Removes `name` and every newer word and moves `HERE` back. Words below `FENCE` cannot be forgotten. |
|
||||
| `FENCE` | `( -- )` | Moves the `FORGET` boundary up to the current top of the dictionary. A capsule calls it after loading to protect its own words. |
|
||||
| `does_rt` | – | Internal `DOES>` helper that switches the new child word to DODOES. It is registered only so the threaded code can refer to it; do not call it. |
|
||||
|
||||
Example: `: ARRAY ( n "name" -- ) CREATE CELLS ALLOT DOES> ( i -- addr ) SWAP CELLS + ;`
|
||||
|
||||
## 18. Control flow
|
||||
`src/word_source/control_words.c`. Every structure word is **IMM** and **CO**. Branch offsets are in bytes. Up to 64
|
||||
structures can be nested at compile time (`CF_STACK_MAX`).
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `IF` | `( flag -- )` | Runs the following code only if `flag` is non-zero. It compiles `(0BRANCH)`. |
|
||||
| `ELSE` | `( -- )` | Starts the code that runs when the `IF` flag was zero. |
|
||||
| `THEN` | `( -- )` | Ends an `IF` or `IF … ELSE` structure. |
|
||||
| `BEGIN` | `( -- )` | Marks the start of a loop. |
|
||||
| `UNTIL` | `( flag -- )` | Loops back to `BEGIN` while `flag` is zero. |
|
||||
| `AGAIN` | `( -- )` | Loops back to `BEGIN` unconditionally. Leave with `EXIT` or `ABORT`. |
|
||||
| `WHILE` | `( flag -- )` | In `BEGIN … WHILE … REPEAT`, leaves the loop when `flag` is zero. |
|
||||
| `REPEAT` | `( -- )` | Jumps back to `BEGIN` and resolves the exit of `WHILE`. |
|
||||
| `DO` | `( limit start -- ) ( R: -- limit index )` | Starts a counted loop that always runs at least once. |
|
||||
| `?DO` | `( limit start -- )` | Like `DO`, but skips the loop body when `start = limit`. |
|
||||
| `LOOP` | `( -- )` | Adds 1 to the index and loops while `index < limit`. |
|
||||
| `+LOOP` | `( n -- )` | Adds `n` to the index. For `n ≥ 0` it continues while `index < limit`; for `n < 0` it continues while `index ≥ limit`. |
|
||||
| `LEAVE` | `( -- )` | Exits the innermost `DO` loop immediately: it sets the index to the limit and jumps past `LOOP`. |
|
||||
| `I` | `( -- index )` | Pushes the index of the innermost loop. It is not IMMEDIATE. |
|
||||
| `J` | `( -- index )` | Pushes the index of the next outer loop. |
|
||||
| `UNLOOP` | `( -- ) ( R: limit index -- )` | Drops the loop parameters. Use it before `EXIT` inside a `DO` loop. |
|
||||
| `EXIT` | `( -- )` | Returns from the current colon definition. Using it in interpret mode is an error. |
|
||||
| `CASE` | `( x -- x )` | Starts a case structure. |
|
||||
| `OF` | `( x v -- \| x )` | If `x = v`, drops both and runs the clause; otherwise keeps `x` and skips to the next `OF`. |
|
||||
| `ENDOF` | `( -- )` | Ends an `OF` clause and jumps to `ENDCASE`. |
|
||||
| `ENDCASE` | `( x -- )` | Drops the selector and resolves every `ENDOF` jump. |
|
||||
| `(BRANCH)` | `( -- )` | Runtime: unconditional relative branch. The compiler inserts it; you do not call it directly. |
|
||||
| `(0BRANCH)` | `( flag -- )` | Runtime: branches when `flag` is 0. The compiler inserts it; you do not call it directly. |
|
||||
| `(DO)` `(?DO)` | `( limit start -- )` | Runtime for loop entry. The compiler inserts them; you do not call them directly. |
|
||||
| `(LOOP)` `(+LOOP)` | `( -- )` / `( n -- )` | Runtime for loop increment and test. The compiler inserts them; you do not call them directly. |
|
||||
| `(LEAVE)` | `( -- )` | Runtime for `LEAVE`: sets index to limit. The compiler inserts it; you do not call it directly. |
|
||||
|
||||
Examples:
|
||||
```forth
|
||||
: COUNTDOWN ( n -- ) BEGIN DUP . 1- DUP 0= UNTIL DROP ;
|
||||
: TABLE ( -- ) 5 0 DO 5 0 DO I J * 4 .R LOOP CR LOOP ;
|
||||
: COLOR ( n -- ) CASE 0 OF ." red" ENDOF 1 OF ." green" ENDOF ." ?" ENDCASE ;
|
||||
```
|
||||
|
||||
## 19. StarForth extensions
|
||||
`src/word_source/starforth_words.c`. These words are registered in both `FORTH` and the `STARFORTH` vocabulary.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `ENTROPY@` | `( xt -- n )` | Pushes the `execution_heat` counter of a word. The name says "entropy", but the value is execution heat. Registered only in the `STARFORTH` vocabulary. |
|
||||
| `ENTROPY!` | `( n xt -- )` | Sets a word's `execution_heat` counter. Registered only in the `STARFORTH` vocabulary. |
|
||||
| `WORD-ENTROPY` | `( -- )` | Prints the execution heat of every word. |
|
||||
| `RESET-ENTROPY` | `( -- )` | Sets every heat counter to zero. |
|
||||
| `TOP-WORDS` | `( n -- )` | Prints the `n` hottest words. |
|
||||
| `(-` | `( "ccc<)>" -- )` | A comment that marks metadata blocks to extract into `init.4th`. It consumes input up to `)`. |
|
||||
| `INIT` | `( -- )` | Reads `./capsules/core/init.4th`, copies its blocks from block 1 onward, and runs them. |
|
||||
| `VERSION` | `( -- )` | Prints `StarForth v<ver> <arch> <variant> <timestamp>`. |
|
||||
| `SEED` | `( n -- )` | Seeds the PRNG so random sequences can be reproduced. |
|
||||
| `RANDOM` | `( lo hi -- n )` | Pushes a pseudo-random number in `[lo, hi]`, including both ends. |
|
||||
| `WAIT` | `( n -- )` | Waits `n` heartbeat ticks by calling `vm_tick()` `n` times. It counts heartbeats, not wall-clock time, so it behaves the same on amd64, aarch64, and riscv64. |
|
||||
| `HEARTBEAT-TICKS@` | `( -- n )` | Pushes the canonical heartbeat tick count (Loop #7). The project uses this as its clock. It is read-only. |
|
||||
| `ZUSE-AUTHENTICATE` | `( -- )` | Sets `zuse_session = 1`. The write happens only in C. |
|
||||
| `ZUSE-SESSION?` | `( -- flag )` | True if `ZUSE-AUTHENTICATE` has run during this boot. It is read-only. |
|
||||
| `ZUSE-PUBKEY@` | `( i -- u )` | Pushes 8-byte little-endian chunk `i` (0–3) of Zuse's Ed25519 **public** key. An out-of-range `i` pushes 0 and sets an error. The private seed is never exposed. |
|
||||
| `ZUSE-CERT-INSTALLED?` | `( -- flag )` | True once the one-time certificate fuse has been blown. |
|
||||
|
||||
## 20. Word-level ACL
|
||||
`src/word_source/acl_words.c`. Every word takes an `xt`, obtained with `'` or `[']`. Writes are silently ignored for
|
||||
a **pinned** word.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `ACL-MODE@` | `( xt -- mode )` | Pushes the enforcement mode: 0 is STRICT (the decision is permanent) and 1 is TTL (the decision is rechecked when the countdown expires). |
|
||||
| `ACL-MODE!` | `( mode xt -- )` | Sets the enforcement mode. |
|
||||
| `ACL-TTL@` | `( xt -- n )` | Pushes the TTL countdown. At 0 in TTL mode, the interpreter calls `acl_recheck()`. |
|
||||
| `ACL-TTL!` | `( n xt -- )` | Sets the TTL, clamped to `[0, UINT32_MAX]`. |
|
||||
| `ACL-ALLOW@` | `( xt -- flag )` | Pushes the cached decision: `-1` means allowed and `0` means denied. |
|
||||
| `ACL-ALLOW!` | `( flag xt -- )` | Sets the cached decision; any non-zero value means allowed. |
|
||||
| `ACL-PINNED?` | `( xt -- flag )` | True if the ACL fields are pinned and therefore immutable. |
|
||||
| `ACL-PIN` | `( xt -- )` | Pins the word. **This is one-way**: no FORTH word can unpin it. |
|
||||
| `ACL-HEAT@` | `( xt -- heat )` | Pushes the execution heat. `ACL.4th` uses it to calibrate TTLs. |
|
||||
| `ACL-WORD-ID` | `( xt -- id )` | Pushes the word's stable `word_id`. It never changes, so it is safe to use as a table index. |
|
||||
| `ACL-INHERIT` | `( src-xt dst-xt -- )` | Copies the mode from `src` to `dst` and resets `dst`: unpinned, TTL 0, allowed. It is written in C because only C may clear a pin. |
|
||||
| `ACL-INIT-PRIMITIVES` | `( -- )` | For every unpinned word, sets TTL to 0, allow to 1, and mode to TTL. `ACL-BOOT` calls it. |
|
||||
|
||||
## 21. Physics: benchmark and diagnostics
|
||||
`src/word_source/physics_benchmark_words.c`. These are interactive diagnostics that print to the console.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `BENCH-DICT-LOOKUP` | `( iterations -- )` | Benchmarks dictionary lookup and records Q48.16 latencies. Use at least 10,000 iterations; 100,000 is the standard run and 1,000,000 is a stress test. |
|
||||
| `PHYSICS-CACHE-STATS` | `( -- )` | Prints hot-words cache statistics. |
|
||||
| `PHYSICS-TOGGLE-CACHE` | `( -- )` | Turns the hot-words cache on or off, for A/B testing. |
|
||||
| `PHYSICS-RESET-STATS` | `( -- )` | Resets the cache statistics. |
|
||||
| `PHYSICS-BUILD-INFO` | `( -- )` | Prints the variant's build configuration. |
|
||||
| `PHYSICS-BAYESIAN-REPORT` | `( addr -- )` | Prints a Bayesian comparison of the current cache statistics against the baseline stored at `addr`. |
|
||||
|
||||
> `physics_diagnostic_words.c` also defines `PHYSICS-WORD-METRICS`, `PHYSICS-CALC-KNOBS`, `PHYSICS-BURN ( n -- )`
|
||||
> and `PHYSICS-SHOW-FEEDBACK`, but nothing calls `register_physics_diagnostic_words()`, so **none of them are in
|
||||
> the dictionary** at this commit.
|
||||
|
||||
## 22. Physics: pipelining diagnostics
|
||||
`src/word_source/physics_pipelining_diagnostic_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `PIPELINING-SHOW-STATS` | `( "name" -- )` | Prints the word-to-word transition metrics of `name`. |
|
||||
| `PIPELINING-SHOW-TOP-TRANSITIONS` | `( "name" n -- )` | Prints the `n` words that most often follow `name`. |
|
||||
| `PIPELINING-ANALYZE-WORD` | `( "name" -- )` | Prints a full analysis of one word's transitions, with hints for reading them. |
|
||||
| `PIPELINING-STATS` | `( -- )` | Prints pipelining statistics aggregated across the whole dictionary. |
|
||||
| `PIPELINING-RESET-ALL` | `( -- )` | Clears all transition metrics. |
|
||||
| `PIPELINING-ENABLE` | `( -- )` | Placeholder. Pipelining is switched on or off at compile time. |
|
||||
|
||||
## 23. Physics: freeze, heat, and decay
|
||||
`src/word_source/physics_freeze_words.c`. Words are named by `c-addr u` strings, for example `S" DUP" HEAT@`. An
|
||||
unknown name is not an error.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `FREEZE-WORD` | `( c-addr u -- )` | Sets `WORD_FROZEN` on the word, so Loop #3 decay stops lowering its heat. |
|
||||
| `UNFREEZE-WORD` | `( c-addr u -- )` | Clears `WORD_FROZEN` and leaves `WORD_PINNED` alone. |
|
||||
| `FROZEN?` | `( c-addr u -- flag )` | True if the word is frozen. An unknown word gives `0`. |
|
||||
| `HEAT!` | `( heat c-addr u -- )` | Writes `execution_heat` directly, bypassing Loops #1 and #3. For testing only. |
|
||||
| `HEAT@` | `( c-addr u -- heat )` | Reads `execution_heat`. An unknown word gives `0`. |
|
||||
| `SHOW-HEAT` | `( c-addr u -- )` | Prints `NAME: HEAT (frozen) (pinned)`. |
|
||||
| `ALL-HEATS` | `( -- )` | Prints up to 1024 words sorted by heat, hottest first. |
|
||||
| `DECAY-RATE@` | `( -- q )` | Pushes the base decay rate per µs (`DECAY_RATE_PER_US_Q16`) in Q48.16. |
|
||||
| `FREEZE-CRITICAL` | `( -- )` | Freezes 21 core words: `DUP DROP SWAP OVER ROT @ ! C@ C! EXECUTE IF THEN ELSE DO LOOP BEGIN UNTIL REPEAT . EMIT CR`. |
|
||||
|
||||
## 24. Dictionary heat optimisation
|
||||
`src/word_source/dictionary_heat_diagnostic_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `HEAT-PERCENTILES` | `( -- p25 p50 p75 )` | Pushes the current heat percentile thresholds, with the 75th on top. |
|
||||
| `LOOKUP-STRATEGY@` | `( -- n )` | Pushes the lookup strategy: 0 is naive (newest-first linear scan) and 1 is heat-aware (hot bucket first). |
|
||||
| `LOOKUP-STRATEGY!` | `( n -- )` | Sets the strategy. Only 0 or 1 is accepted; other values are silently ignored. |
|
||||
| `REORG-BUCKETS` | `( -- )` | Re-sorts the lookup buckets by heat and refreshes the percentiles immediately, without waiting for the heartbeat. |
|
||||
| `SHOW-HEAT-OPTIMIZATION` | `( -- )` | Prints the strategy, the percentiles, and the hot, warm, and cool zones. |
|
||||
| `COMPARE-LOOKUPS` | `( iterations -- )` | Benchmarks naive against heat-aware lookup and prints the speedup. It restores the original strategy afterwards. |
|
||||
|
||||
## 25. Logging
|
||||
`src/word_source/log_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `LOG-ERROR` `LOG-WARN` `LOG-INFO` `LOG-TEST` `LOG-DEBUG` | `( -- level )` | Push the log level constants. |
|
||||
| `LOG-LEVEL!` | `( level -- )` | Sets the active log filter, clamped to `[LOG-ERROR, LOG-DEBUG]`. |
|
||||
| `LOG-LEVEL@` | `( -- level )` | Pushes the current log level. |
|
||||
| `LOG-ERROR"` `LOG-WARN"` `LOG-INFO"` `LOG-TEST"` `LOG-DEBUG"` **IMM** | `( "ccc<">" -- )` | Log a literal string at that level. In interpret mode the string is logged immediately; when compiling, a runtime word and the inline string are compiled. |
|
||||
| `LOG-ERROR-STR` `LOG-WARN-STR` `LOG-INFO-STR` `LOG-TEST-STR` `LOG-DEBUG-STR` | `( c-addr u -- )` | Log a string taken from the stack at that level. |
|
||||
| `(do-log-error)` `(do-log-warn)` `(do-log-info)` `(do-log-test)` `(do-log-debug)` | `( -- )` | Runtimes for the compiled `LOG-*"` words. The compiler inserts them; you do not call them directly. |
|
||||
| `(LOG-APPEND-RAW)` **K** | `( level timestamp c-addr u -- )` | Appends a raw entry to the kernel log ring, attributed to the calling VM (or `HADES`). It reports errors on the console, not through `log_message`, to avoid recursion. |
|
||||
|
||||
Example: `: CHECK ( n -- ) 0< IF LOG-WARN" negative input" THEN ;`
|
||||
|
||||
## 26. Q48.16 fixed-point math
|
||||
`src/word_source/q48_words.c`. A value is `n × 65536`. The underlying type is **unsigned** `uint64_t`; see
|
||||
[§36](#36-implementation-quirks-to-know) for what that means for negative values.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `Q.+` `Q.-` | `( q1 q2 -- q3 )` | Add and subtract. |
|
||||
| `Q.*` | `( q1 q2 -- q3 )` | Multiplies, computing `(a*b) >> 16`. |
|
||||
| `Q./` | `( q1 q2 -- q3 )` | Divides, computing `(a << 16) / b`. **Division by zero returns 0** and sets no error. |
|
||||
| `Q.ABS` | `( q -- \|q\| )` | Absolute value, treating the top bit as a sign bit. |
|
||||
| `Q.NEG` | `( q -- -q )` | Two's-complement negation. |
|
||||
| `Q.LOG` | `( q -- ln q )` | Natural logarithm by Newton-Raphson. Requires `q > 0`. |
|
||||
| `Q.EXP` | `( q -- e^q )` | Exponential by Taylor series. |
|
||||
| `Q.SQRT` | `( q -- √q )` | Square root by Newton-Raphson. |
|
||||
| `Q.SIN` `Q.COS` | `( q -- q' )` | Sine and cosine of an angle in radians. The argument is reduced to [-π, π] and then a Taylor series is applied. |
|
||||
| `Q.FROM-INT` | `( n -- q )` | Converts an integer to Q48.16 as `n << 16`. **A negative `n` becomes 0.** |
|
||||
| `Q.TO-INT` | `( q -- n )` | Converts to an integer as `q >> 16`, truncating. |
|
||||
| `Q.1` | `( -- 65536 )` | Pushes 1.0. |
|
||||
| `Q.0` | `( -- 0 )` | Pushes 0.0. |
|
||||
| `Q.SCALE` | `( -- 65536 )` | Pushes the scale factor; the same value as `Q.1`. |
|
||||
| `Q.=` | `( q1 q2 -- flag )` | Equality. |
|
||||
| `Q.<` `Q.>` | `( q1 q2 -- flag )` | Comparison, done **unsigned**. |
|
||||
| `Q.0=` | `( q -- flag )` | True if the value is zero. |
|
||||
| `Q.MAX` `Q.MIN` | `( q1 q2 -- q3 )` | Maximum and minimum, compared **unsigned**. |
|
||||
| `Q.PRINT` | `( q -- )` | Prints the value as `int.fffff ` with five fractional digits. |
|
||||
|
||||
Example: `3 Q.FROM-INT Q.SQRT Q.PRINT` prints approximately `1.732`.
|
||||
|
||||
## 27. Inference engine (SSM, L8, and Bayes)
|
||||
`src/word_source/inference_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `INFER-RUN` | `( -- )` | Runs the full inference engine on this VM's rolling window and dictionary heat, and caches the results. |
|
||||
| `INFER-WINDOW@` | `( -- u )` | Pushes the last inferred optimal window width. |
|
||||
| `INFER-DECAY@` | `( -- q )` | Pushes the last inferred decay slope. |
|
||||
| `INFER-VARIANCE@` | `( -- q )` | Pushes the last inferred variance. |
|
||||
| `INFER-FIT@` | `( -- q )` | Pushes the last fit quality. |
|
||||
| `INFER-EARLY-EXIT@` | `( -- flag )` | True if the last run exited early. |
|
||||
| `Q.VARIANCE` | `( addr u -- q )` | Pushes the variance of `u` uint64 cells at `addr`. |
|
||||
| `INFER-DECAY-SLOPE` | `( addr u -- q )` | Fits a decay slope to the array by linear regression. |
|
||||
| `INFER-WINDOW-WIDTH` | `( addr u -- n )` | Computes the optimal window width for the array. |
|
||||
| `WINDOW-DIVERSITY` | `( -- u )` | Pushes the number of distinct words in the rolling window. |
|
||||
| `L8-MODE` | `( -- n )` | Pushes the current L8 (legacy 16-mode) Jacquard selection. |
|
||||
| `L8-UPDATE` | `( entropy cv temporal stability -- )` | Feeds four Q48.16 metrics to `ssm_l8_update()`. `stability` is on top of the stack. |
|
||||
| `L8-APPLY` | `( -- )` | Applies the currently selected L8 mode. |
|
||||
| `L8-TABLE-FORCE` | `( idx -- )` | Forces the adaptive 128-config table to `idx & 127` as though the UCB bandit had picked it, and applies it. Unlike `L8-UPDATE` and `L8-APPLY`, this choice is not overwritten at the next heartbeat trial. Use it for DoE campaigns. |
|
||||
| `BAYES-CACHE-MEAN` `BAYES-CACHE-LOWER` `BAYES-CACHE-UPPER` | `( -- q )` | Push the posterior mean latency and the 95 % credible bounds for hot-words cache hits. |
|
||||
| `BAYES-BUCKET-MEAN` `BAYES-BUCKET-LOWER` `BAYES-BUCKET-UPPER` | `( -- q )` | Push the same three values for bucket searches. |
|
||||
|
||||
## 28. DEFER and IS
|
||||
`src/word_source/defer_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `DEFER` | `( "name" -- )` | Creates a vectored word. Running it before an action has been set with `IS` sets `vm->error`. |
|
||||
| `IS` | `( xt "name" -- )` | Sets the action of `name`. It is refused unless `name` was created by `DEFER`. |
|
||||
| `DEFER@` | `( "name" -- xt )` | Pushes the current action of a deferred word. |
|
||||
|
||||
Example: `DEFER GREET : HI ." hi" ; ' HI IS GREET GREET`
|
||||
|
||||
## 29. Framebuffer (Hestia only)
|
||||
`src/word_source/framebuffer_words.c`. These words are registered only in the Hestia VM, by `capsule_birth_baby()`,
|
||||
and not by `register_forth79_words()`.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `PLOT` | `( x y color -- )` | Writes one raw pixel. The origin is top-left and Y increases downward. |
|
||||
| `FB-WIDTH` | `( -- n )` | Pushes the framebuffer width in pixels. |
|
||||
| `FB-HEIGHT` | `( -- n )` | Pushes the framebuffer height in pixels. |
|
||||
|
||||
## 30. Keyboard
|
||||
`src/word_source/keyboard_words.c`. These are diagnostics for the console fabric. On a platform without the device,
|
||||
each word pushes `0`.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `KBD-SCAN` | `( -- sc -1 \| 0 )` | amd64 i8042: pops one raw XT scancode from the queue, if there is one. |
|
||||
| `KBD-DEBUG` | `( -- isr spurious )` | amd64: pushes the i8042 interrupt count and the spurious-interrupt count. |
|
||||
| `VKBD-EVENT` | `( -- code value -1 \| 0 )` | riscv64 and aarch64 virtio-input: pops one Linux-style `EV_KEY` code and value. |
|
||||
| `VKBD-DEBUG` | `( -- isr )` | riscv64 and aarch64: pushes the virtio-input interrupt count. |
|
||||
| `KEY-EVENT` | `( -- keycode pressed -1 \| 0 )` | The unified event on every architecture: pops one keycode with its pressed (1) or released (0) state. |
|
||||
| `ALT+TAB` | `( -- )` | Switches the console between text and graphics, the same as the physical Alt+Tab. |
|
||||
|
||||
## 31. TrueType text
|
||||
`src/word_source/ttf_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `TTF-TEXT` **K** | `( c-addr u x y size color -- )` | Draws the string with the TrueType renderer at pixel `(x, y)` in the given size and color. |
|
||||
|
||||
## 32. REPL scrollback
|
||||
`src/word_source/scroll_words.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `SCROLL-BACK` **K** | `( n -- )` | Scrolls the REPL view back `n` lines. |
|
||||
| `SCROLL-FWD` **K** | `( n -- )` | Scrolls the REPL view forward `n` lines, toward the live output. |
|
||||
|
||||
## 33. Kernel REPL and DoE hooks
|
||||
`src/starkernel/repl.c` and `src/starkernel/doe_log.c`
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `HB-ON` **K** | `( -- )` | Turns on per-tick DoE instrumentation. |
|
||||
| `HB-OFF` **K** | `( -- )` | Turns off per-tick DoE instrumentation. |
|
||||
| `BLK-ATTACH-ACK` **K** | `( dev-ptr ok? -- )` | The acknowledgement Artemis sends to Hera after `BLK-ATTACH`, delivered with `VM-EXEC`. On success, Hera runs the deferred Zuse or WIREBIND attach. |
|
||||
| `KH-BLK-ATTACH-SEND` **K** | `( c-addr u -- ok? )` | Sends a payload to Hera through kernel-Hermes. The sender and receiver are worked out in C, so the caller cannot spoof them. A refused send is logged. |
|
||||
| `KH-ELEVATE-SEND` **K** | `( c-addr u -- ok? )` | The same mechanism for elevation requests. Nothing calls it at present. |
|
||||
|
||||
## 34. Hera (Mama) and child-VM words
|
||||
`src/starkernel/capsule/mama_forth_words.c`. These are **K** only. Hera receives every word in this section, in
|
||||
both `FORTH` and the `MAMA` vocabulary. Child VMs receive only `STOP EXEC USE BIRTH CAPSULE-BIRTH VM-EXEC VM-CALL
|
||||
VM-HEAT VM-ERROR? SWITCH-MARK-WORK` and the `STADIUM-*` words. VM names are matched without regard to case.
|
||||
|
||||
### VM lifecycle
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `BIRTH` | `( c-addr u -- )` | Births a VM from its capsule (`S" Artemis"` loads `artemis:init.4th`). If the VM is already live, nothing happens. `Hera` is rejected. |
|
||||
| `KILL` | `( c-addr u -- )` | Destroys a VM. Hera cannot be killed, and killing a dead VM does nothing. |
|
||||
| `START` | `( c-addr u -- )` | Enters the VM's REPL and blocks until it runs `STOP` or `BYE`. It refuses a VM that is LIVE, DEAD, or STILLBORN. |
|
||||
| `STOP` | `( -- )` | Halts the current VM, so its REPL loop returns. |
|
||||
| `USE` | `( c-addr u -- )` | Redirects console input to the named VM without nesting the C stack, and changes the prompt to `[Name]`. `S" Hera" USE` switches back to Hera. |
|
||||
| `EXEC` | `( c-addr u -- )` | Runs a named capsule inside the current VM. |
|
||||
| `EJECT` | `( -- )` | Cleanly detaches the identity attached through USB home blocks: it flushes the user VM and kills it, or logs Zuse out. |
|
||||
| `CONNECT-HERMES` | `( -- )` | Enters Hermes's REPL, birthing Hermes first if needed. |
|
||||
| `CONNECT-ARTEMIS` | `( -- )` | Enters Artemis's REPL, birthing Artemis first if needed. |
|
||||
| `BYE` | `( -- )` | **On Hera:** reaps every child and then cold-resets the machine. |
|
||||
|
||||
### Cross-VM execution (compudynamics)
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `VM-EXEC` | `( cmd-a cmd-u name-a name-u -- )` | Injects a command into the named VM and runs it immediately without blocking. Example: `S" DOE-WORK" S" Hermes" VM-EXEC`. |
|
||||
| `VM-CALL` | `( cmd-a cmd-u name-a name-u -- n )` | Like `VM-EXEC`, then pops the target's top of stack onto the caller's stack. If the target left nothing, it pushes 0 and sets an error. |
|
||||
| `VM-STEP` | `( c-addr u -- )` | Gives the named VM one REPL turn: one prompt, one line, then it returns. |
|
||||
| `VM-HEAT` | `( c-addr u -- q )` | Pushes the VM's `execution_heat_q48`. An unknown VM gives 0 and prints nothing. |
|
||||
| `VM-ERROR?` | `( c-addr u -- flag )` | True if the VM has `vm->error` set. An unknown VM gives `0`. |
|
||||
| `VM-COUNT` | `( -- n )` | Pushes the number of registered VMs. |
|
||||
| `VM-CONSERVED?` | `( -- flag )` | True if the total fleet heat is within ε of `Q.1`. |
|
||||
| `VM-PHYSICS-STATUS` | `( -- )` | Prints the fleet physics report. |
|
||||
| `SWITCH-MARK-WORK` | `( c-addr u -- )` | Marks a VM as having work, which makes it eligible for a context switch. The message path calls it, and it ignores bad names silently. |
|
||||
| `MAMA-VM-ID` | `( -- 0 0 )` | Pushes Hera's 128-bit VM ID, which is all zeros. |
|
||||
| `NAME>XT` | `( c-addr u -- xt \| 0 )` | Looks up a name held in a data buffer. A miss gives `0`. |
|
||||
|
||||
### Capsules
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `CAPSULE-COUNT` | `( -- n )` | Pushes the number of entries in the capsule directory. |
|
||||
| `CAPSULE@` | `( idx -- desc \| 0 )` | Pushes the descriptor for the capsule at `idx`. |
|
||||
| `CAPSULE-HASH@` | `( desc -- hash )` | Pushes the capsule's content hash. |
|
||||
| `CAPSULE-FLAGS@` | `( desc -- flags )` | Pushes the capsule's flags. |
|
||||
| `CAPSULE-LEN@` | `( desc -- len )` | Pushes the capsule's payload length. |
|
||||
| `CAPSULE-BIRTH` | `( id -- vmid-lo vmid-hi )` | Births an unnamed VM from a production (p) capsule and pushes its 128-bit ID. On failure both cells are all ones. |
|
||||
| `CAPSULE-RUN` | `( id -- )` | Runs an experiment (e) capsule on Hera. |
|
||||
| `CAPSULE-TEST` | `( -- )` | Prints a message confirming the capsule system is running. |
|
||||
| `WORKER-BIRTH` | `( cap-a cap-u name-a name-u -- ok? )` | Births a named, `VM-EXEC`-addressable worker from any p-capsule, with no identity attached. |
|
||||
| `UNATTENDED-BIRTH` | `( cap-a cap-u name-a name-u -- ok? )` | Births a VM and installs the verified identity whose `UNATTENDED-ID-UUID` and `UNATTENDED-ID-CERT` the capsule defined. |
|
||||
| `CONSOLE-ATTACH` | `( name-a name-u -- ok? )` | Pairs a new console VM with the live VM registered as `<name>~user`. |
|
||||
|
||||
### Identity, Zuse, and diagnostics
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `MINT` | `( fn-a fn-u un-a un-u em-a em-u ph-a ph-u restrict? -- ok? )` | Mints an identity onto the attached USB drive. The full name and username are required; pass an empty string for email or phone to leave them out. A non-zero `restrict?` selects the locked-down personality that allows only FORTH-79 and FORTH-83 words. |
|
||||
| `MINT-SCRATCH` | same as `MINT` | Mints onto the scratch device instead, prints the UUID, and pushes 1 or 0. |
|
||||
| `MINT-SCRATCH-EMIT` | `( -- ok? )` | Prints the last scratch mint as FORTH source (`CREATE UNATTENDED-ID-UUID` / `-CERT` byte lists) for copying by hand. It refuses (pushes 0) if no mint has succeeded. |
|
||||
| `ZUSE-ELIGIBILITY-ADD` | `( c-addr -- ok? )` | Adds the 32-byte Ed25519 public key at `c-addr` to Zuse's elevation list. |
|
||||
| `ZUSE-ELIGIBLE?` | `( c-addr -- flag )` | Checks whether a key is on the list. It fails closed. |
|
||||
| `ELEVATE-PUBKEY-UNPACK` | `( pk0 pk1 pk2 pk3 buf -- )` | Rebuilds a 32-byte public key from four cells. It is the inverse of `ZUSE-PUBKEY@`. |
|
||||
| `RUNCAP-TEST` | `( c-addr u -- ok? rc )` | Diagnostic: runs `capsule_runcap_birth()` against the current home-blocks drive. |
|
||||
| `PAIR-TEST` | `( c-addr u -- ok? )` | Diagnostic: births a console VM and a `<name>~user` VM as a pair. |
|
||||
|
||||
### Stadium (heat accounting)
|
||||
Heat values are Q48.16. Each word works only on the calling VM's own quota.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `STADIUM-ADMIT` | `( identity heat behaviour -- cell \| -1 )` | Admits a patron. `behaviour` must be 0–3. |
|
||||
| `STADIUM-EVICT` | `( cell -- flag )` | Reaps the patron in `cell`. It is refused if the cell is out of range, not resident, pinned, or blocked by what it contains. |
|
||||
| `STADIUM-HEAT@` | `( cell -- heat )` | Reads a resident cell's heat. A cell that is not the caller's gives 0. |
|
||||
| `STADIUM-HEAT!` | `( heat cell -- )` | Writes a cell's heat, pulling the difference from the reservoir or pushing it back. An increase the reservoir cannot cover is silently refused. |
|
||||
| `STADIUM-RES@` | `( -- heat )` | Pushes the VM's reservoir balance. |
|
||||
| `STADIUM-RES-PULL` | `( qty -- got )` | Pulls up to `qty` from the reservoir and pushes the amount actually taken. |
|
||||
| `STADIUM-RES-PUSH` | `( heat -- )` | Credits heat back to the reservoir. |
|
||||
| `STADIUM-WORD-HEAT` | `( -- heat )` | Pushes the total heat held by this VM's word-execution residents. |
|
||||
|
||||
## 35. Hosted lifecycle stubs
|
||||
`src/word_source/lifecycle_words_hosted.c`. These are **H** only; `main.c` registers them. Each word only logs
|
||||
`"<WORD> <name> (hosted)"`. They exist so that capsule scripts also parse in hosted builds.
|
||||
|
||||
| Word | Stack | Description |
|
||||
|---|---|---|
|
||||
| `BIRTH` `KILL` `PAUSE` `RESUME` `USE` | `( c-addr u -- )` | No-op stubs that only write a log line. |
|
||||
|
||||
---
|
||||
|
||||
## 36. Implementation quirks to know
|
||||
|
||||
These behaviours differ from what a FORTH-79 or ANS programmer would expect. Each was checked against the C source.
|
||||
|
||||
1. **`ROLL` counts from the bottom of the stack.** With `1 2 3` on the stack, `1 ROLL` gives `2 3 1`; ANS gives
|
||||
`1 3 2`. The test suite (`stack_words_test.c`) asserts the current behaviour, so it looks intended. Portable code
|
||||
should use `SWAP` and `ROT`.
|
||||
2. **`PICK` is 0-based,** as in ANS. FORTH-79's `PICK` was 1-based.
|
||||
3. **`FIND` parses the input stream.** It does not take a counted string. Use `(FIND)` for a counted string or
|
||||
`NAME>XT` (kernel only) for a name in a buffer.
|
||||
4. **The Q48.16 type is unsigned.** `Q.<`, `Q.>`, `Q.MIN`, `Q.MAX` and `Q.PRINT` treat a negative Q value as a huge
|
||||
positive one, and `Q.FROM-INT` turns a negative integer into 0. `Q.ABS` and `Q.NEG` do treat the top bit as a sign.
|
||||
5. **`Q./` by zero returns 0 without setting an error,** while the integer `/`, `MOD`, and `*/` all set `vm->error`.
|
||||
6. **`[LITERAL]` does nothing,** and `LITERAL` works only because §17 registers it again after the placeholder.
|
||||
7. **`MOD`, `/MOD`, `*/`, and `*/MOD` are registered twice.** The mixed-arithmetic versions (§6) are the ones used.
|
||||
8. **Four `PHYSICS-*` diagnostic words are not registered.** `PHYSICS-WORD-METRICS`, `PHYSICS-CALC-KNOBS`,
|
||||
`PHYSICS-BURN` and `PHYSICS-SHOW-FEEDBACK` are defined in C but never added to the dictionary.
|
||||
9. **`does_rt` is a visible dictionary entry.** It is an internal helper; do not call it.
|
||||
10. **The `STARFORTH` vocabulary registers its words twice** (once in `FORTH`, once in `STARFORTH`). Hera does the
|
||||
same with `MAMA`. As a result, those names appear twice in `WORDS` output.
|
||||
Reference in New Issue
Block a user