Files
WAFER/docs/wafer-anki.txt
T

390 lines
103 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#separator:tab
#html:true
#tags column:3
#deck:Forth 2012 + WAFER
<code>DUP</code> <b>( x -- x x )</b><br>Copy top of stack. The workhorse of Forth — sets up operand reuse.<br><code>5 DUP * . \ 25 — classic square idiom</code><br><code>DUP 0&lt; IF NEGATE THEN \ ABS pattern</code><br><i>WAFER: IR [Dup]. Peephole: OVER OVER → 2DUP. Eligible for stack-to-local promotion.</i><br>See: ?DUP 2DUP OVER core stack ir-primitive
<code>DROP</code> <b>( x -- )</b><br>Discard TOS. Used to consume unwanted results.<br><code>/MOD DROP \ keep only remainder = MOD</code><br><code>/MOD NIP \ keep only quotient = /</code><br><i>WAFER: IR [Drop]. Peephole: DROP DROP → 2DROP.</i><br>See: NIP 2DROP core stack ir-primitive
<code>SWAP</code> <b>( x1 x2 -- x2 x1 )</b><br>Exchange top two items. Reorders operands for non-commutative ops.<br><code>3 5 SWAP - . \ 2 (5-3)</code><br><i>WAFER: IR [Swap]. Common peephole target: SWAP DROP → NIP.</i><br>See: ROT 2SWAP core stack ir-primitive
<code>OVER</code> <b>( x1 x2 -- x1 x2 x1 )</b><br>Copy second item to top. Lets you access NOS without destroying stack order.<br><code>: MAX 2DUP &lt; IF SWAP THEN DROP ;</code><br><i>WAFER: IR [Over]. Peephole: OVER OVER → 2DUP.</i><br>See: PICK TUCK DUP core stack ir-primitive
<code>ROT</code> <b>( x1 x2 x3 -- x2 x3 x1 )</b><br>Rotate third item to top. Brings buried item up; rarely elegant — consider refactoring if used heavily.<br><code>: -ROT ROT ROT ; \ reverse rotate idiom</code><br><i>WAFER: IR [Rot].</i><br>See: 2ROT -ROT core stack ir-primitive
<code>?DUP</code> <b>( x -- 0 | x x )</b><br>Duplicate only if nonzero. Eliminates a common DUP IF … DROP THEN pattern.<br><code>: SAFE/ ?DUP IF / ELSE DROP 0 THEN ;</code><br><i>WAFER: IR [QDup]. Single opcode, not a macro.</i><br>See: DUP IF core stack ir-primitive
<code>PICK</code> <b>( x<sub>u</sub>…x<sub>1</sub> x<sub>0</sub> u -- x<sub>u</sub>…x<sub>1</sub> x<sub>0</sub> x<sub>u</sub> )</b><br>Copy u-th item (0-indexed). <code>0 PICK</code> = DUP, <code>1 PICK</code> = OVER. Deep picks signal stack abuse — refactor with locals or return stack.<br><code>2 PICK \ copies third item to top</code><br><i>WAFER: Host function. Runtime bounds check.</i><br>See: DUP OVER core stack host-function
<code>DEPTH</code> <b>( -- +n )</b><br>Number of single-cell values on the data stack before DEPTH executed.<br><code>1 2 3 DEPTH . \ 3</code><br><i>WAFER: Host function. Computes (STACK_TOP - DSP) / 4.</i><br>See: FDEPTH .S core stack host-function
<code>2DUP</code> <b>( x1 x2 -- x1 x2 x1 x2 )</b><br>Duplicate top cell pair. Essential before consuming comparisons.<br><code>: MAX 2DUP &lt; IF SWAP THEN DROP ;</code><br><i>WAFER: IR [TwoDup]. Peephole target: OVER OVER optimized to 2DUP.</i><br>See: DUP 2OVER 2DROP core stack ir-primitive
<code>2DROP</code> <b>( x1 x2 -- )</b><br>Drop top cell pair. Cleans up after double-cell operations.<br><code>S" hello" 2DROP \ discard c-addr u</code><br><i>WAFER: IR [TwoDrop]. Peephole: DROP DROP → 2DROP.</i><br>See: DROP 2DUP core stack ir-primitive
<code>2SWAP</code> <b>( x1 x2 x3 x4 -- x3 x4 x1 x2 )</b><br>Exchange top two cell pairs. Used with double-cell numbers or string descriptors (c-addr u).<br><code>1 2 3 4 2SWAP \ leaves 3 4 1 2</code><br><i>WAFER: Host function.</i><br>See: SWAP 2OVER 2ROT core stack host-function
<code>2OVER</code> <b>( x1 x2 x3 x4 -- x1 x2 x3 x4 x1 x2 )</b><br>Copy second cell pair over top pair. Mirror of OVER for double-width values.<br><i>WAFER: Host function.</i><br>See: OVER 2DUP 2SWAP core stack host-function
<code>+</code> <b>( n1|u1 n2|u2 -- n3|u3 )</b><br>Add. Works identically for signed and unsigned (two's complement).<br><code>3 4 + . \ 7</code><br><i>WAFER: IR [Add]. Peephole: LIT(1) + → 1+. Strength reduction: LIT(2) * → 2*.</i><br>See: - 1+ D+ M+ core arithmetic ir-primitive
<code>-</code> <b>( n1|u1 n2|u2 -- n3|u3 )</b><br>Subtract (n1 minus n2).<br><code>10 3 - . \ 7</code><br><i>WAFER: IR [Sub]. Peephole: LIT(1) - → 1-.</i><br>See: + NEGATE D- core arithmetic ir-primitive
<code>*</code> <b>( n1|u1 n2|u2 -- n3|u3 )</b><br>Multiply. Result is the low-order cell of the double-cell product; use M* for full double result.<br><code>6 7 * . \ 42</code><br><i>WAFER: IR [Mul]. Strength reduction: LIT(2) * → LSHIFT(1), LIT(4) * → LSHIFT(2), etc.</i><br>See: M* UM* */ 2* core arithmetic ir-primitive
<code>/</code> <b>( n1 n2 -- n3 )</b><br>Signed division. Implementation-defined rounding (symmetric in most systems). WAFER uses symmetric (truncate toward zero).<br><code>7 2 / . \ 3</code><br><code>-7 2 / . \ -3 (symmetric)</code><br><i>WAFER: IR [DivMod, Nip] — /MOD then keep quotient.</i><br>See: MOD /MOD FM/MOD SM/REM core arithmetic ir-primitive
<code>MOD</code> <b>( n1 n2 -- n3 )</b><br>Signed remainder. Sign follows division semantics (symmetric in WAFER).<br><code>7 3 MOD . \ 1</code><br><code>-7 3 MOD . \ -1 (symmetric)</code><br><i>WAFER: IR [DivMod, Drop] — /MOD then keep remainder.</i><br>See: / /MOD FM/MOD core arithmetic ir-primitive
<code>/MOD</code> <b>( n1 n2 -- n-rem n-quot )</b><br>Signed division with remainder. Remainder on top of quotient. Division semantics are implementation-defined.<br><code>7 3 /MOD . . \ 2 1 (quot=2, rem=1)</code><br><i>WAFER: IR [DivMod]. Maps to WASM i32.div_s + i32.rem_s. Core building block for / and MOD.</i><br>See: / MOD FM/MOD SM/REM UM/MOD core arithmetic ir-primitive
<code>*/</code> <b>( n1 n2 n3 -- n4 )</b><br>Multiply then divide: (n1*n2)/n3. Intermediate result is double-cell, avoiding overflow. Essential for scaling and fixed-point.<br><code>355 113 */ \ approximates pi ratio</code><br><i>WAFER: Host function. Uses i64 intermediate.</i><br>See: */MOD M* core arithmetic host-function
<code>*/MOD</code> <b>( n1 n2 n3 -- n-rem n-quot )</b><br>Multiply then divmod: n1*n2 divided by n3, double-cell intermediate.<br><code>7 3 2 */MOD . . \ quot=10, rem=1</code><br><i>WAFER: Host function. Uses i64 intermediate.</i><br>See: */ /MOD core arithmetic host-function
<code>NEGATE</code> <b>( n -- -n )</b><br>Two's complement negation. Note: NEGATE of the most negative number overflows silently.<br><code>5 NEGATE . \ -5</code><br><code>-1 NEGATE . \ 1</code><br><i>WAFER: IR [Negate]. Implemented as 0 SWAP SUB in WASM.</i><br>See: ABS DNEGATE FNEGATE core arithmetic ir-primitive
<code>ABS</code> <b>( n -- u )</b><br>Absolute value. ABS of MIN-INT (most negative) returns MIN-INT (overflow).<br><code>-42 ABS . \ 42</code><br><i>WAFER: IR [Abs].</i><br>See: NEGATE DABS FABS core arithmetic ir-primitive
<code>MIN</code> <b>( n1 n2 -- n3 )</b><br>Signed minimum. For unsigned minimum, use custom logic with U&lt;.<br><code>3 7 MIN . \ 3</code><br><i>WAFER: Host function.</i><br>See: MAX FMIN DMIN core arithmetic host-function
<code>MAX</code> <b>( n1 n2 -- n3 )</b><br>Signed maximum.<br><code>3 7 MAX . \ 7</code><br><i>WAFER: Host function.</i><br>See: MIN FMAX DMAX core arithmetic host-function
<code>1+</code> <b>( n -- n+1 )</b><br>Increment by one. Faster than <code>1 +</code>; common in address arithmetic and counters.<br><code>VARIABLE CTR : BUMP CTR @ 1+ CTR ! ;</code><br><i>WAFER: IR [PushI32(1), Add]. Peephole target: LIT(1) + → 1+.</i><br>See: 1- CELL+ CHAR+ core arithmetic ir-primitive
<code>1-</code> <b>( n -- n-1 )</b><br>Decrement by one.<br><code>10 BEGIN DUP . 1- DUP 0= UNTIL DROP</code><br><i>WAFER: IR [PushI32(1), Sub]. Peephole target: LIT(1) - → 1-.</i><br>See: 1+ core arithmetic ir-primitive
<code>2*</code> <b>( x -- x*2 )</b><br>Arithmetic left shift by 1. Equivalent to <code>1 LSHIFT</code>. Works on both signed and unsigned.<br><i>WAFER: IR [PushI32(1), Lshift]. Strength reduction target: LIT(2) * → 2*.</i><br>See: 2/ LSHIFT D2* core arithmetic ir-primitive
<code>2/</code> <b>( x -- x/2 )</b><br>Arithmetic right shift by 1 (sign-extending). NOT equivalent to <code>1 RSHIFT</code> for negative numbers — RSHIFT is logical (zero-fill), 2/ preserves sign.<br><code>-7 2/ . \ -4 (rounds toward negative infinity)</code><br><i>WAFER: IR [ArithRshift]. Uses WASM i32.shr_s.</i><br>See: 2* RSHIFT D2/ core arithmetic ir-primitive
<code>M*</code> <b>( n1 n2 -- d )</b><br>Signed multiply producing double-cell result. No overflow possible. Foundation for */ and */MOD.<br><code>100000 100000 M* D. \ 10000000000</code><br><i>WAFER: Host function. Uses Rust i64 multiply, splits into lo/hi i32.</i><br>See: UM* * D+ M*/ core arithmetic host-function
<code>UM*</code> <b>( u1 u2 -- ud )</b><br>Unsigned multiply producing unsigned double-cell result.<br><i>WAFER: Host function. Uses Rust u64 multiply.</i><br>See: M* * core arithmetic host-function
<code>UM/MOD</code> <b>( ud u1 -- u-rem u-quot )</b><br>Unsigned double-cell by single-cell division. Foundation for pictured numeric output (#).<br><code>0 10 3 UM/MOD . . \ 3 1</code><br><i>WAFER: Host function.</i><br>See: FM/MOD SM/REM /MOD core arithmetic host-function
<code>FM/MOD</code> <b>( d n1 -- n-rem n-quot )</b><br>Floored division: quotient rounded toward negative infinity. Remainder has same sign as divisor. Preferred for modular arithmetic.<br><code>-7. 2 FM/MOD . . \ -4 1 (not -3 -1)</code><br><i>WAFER: Host function. Adjusts SM/REM result when signs differ.</i><br>See: SM/REM /MOD UM/MOD core arithmetic host-function
<code>SM/REM</code> <b>( d n1 -- n-rem n-quot )</b><br>Symmetric division: quotient truncated toward zero. Remainder has same sign as dividend. C-like semantics.<br><code>-7. 2 SM/REM . . \ -3 -1</code><br><i>WAFER: Host function. Direct WASM i32 div/rem.</i><br>See: FM/MOD /MOD UM/MOD core arithmetic host-function
<code>S&gt;D</code> <b>( n -- d )</b><br>Sign-extend single to double. Pushes sign word (0 or -1) above n.<br><code>-1 S&gt;D D. \ -1</code><br><code>5 S&gt;D D. \ 5</code><br><i>WAFER: IR [StoD]. Uses WASM i32.shr_s by 31 for sign extension.</i><br>See: D&gt;S D&gt;F core conversion ir-primitive
<code>=</code> <b>( x1 x2 -- flag )</b><br>True if equal. Returns well-formed flag (-1 or 0).<br><code>3 3 = . \ -1</code><br><code>3 4 = . \ 0</code><br><i>WAFER: IR [Eq]. Compiles to WASM i32.eq.</i><br>See: &lt;&gt; D= F= core comparison ir-primitive
<code>&lt;</code> <b>( n1 n2 -- flag )</b><br>Signed less-than. Treats values as signed 32-bit integers.<br><code>3 5 &lt; . \ -1</code><br><code>-1 0 &lt; . \ -1</code><br><i>WAFER: IR [Lt]. Compiles to WASM i32.lt_s.</i><br>See: &gt; U&lt; 0&lt; D&lt; core comparison ir-primitive
<code>&gt;</code> <b>( n1 n2 -- flag )</b><br>Signed greater-than.<br><code>5 3 &gt; . \ -1</code><br><i>WAFER: IR [Gt]. Compiles to WASM i32.gt_s.</i><br>See: &lt; U&gt; 0&gt; core comparison ir-primitive
<code>U&lt;</code> <b>( u1 u2 -- flag )</b><br>Unsigned less-than. Treats values as unsigned. Critical: -1 (0xFFFFFFFF) is the largest unsigned value.<br><code>-1 0 U&lt; . \ 0 (unsigned: -1 is max)</code><br><i>WAFER: IR [LtUnsigned]. Compiles to WASM i32.lt_u.</i><br>See: &lt; U&gt; DU&lt; core comparison ir-primitive
<code>0=</code> <b>( x -- flag )</b><br>True if zero. Also serves as logical NOT for well-formed flags.<br><code>0 0= . \ -1</code><br><code>FALSE 0= . \ -1 (logical NOT)</code><br><i>WAFER: IR [ZeroEq]. Compiles to WASM i32.eqz.</i><br>See: 0&lt; 0&lt;&gt; 0&gt; core comparison ir-primitive
<code>0&lt;</code> <b>( n -- flag )</b><br>True if negative (sign bit set).<br><code>-5 0&lt; . \ -1</code><br><code>0 0&lt; . \ 0</code><br><i>WAFER: IR [ZeroLt]. Tests sign bit.</i><br>See: 0= 0&gt; 0&lt;&gt; core comparison ir-primitive
<code>WITHIN</code> <b>( n lo hi -- flag )</b><br>True if lo ≤ n &lt; hi (unsigned comparison after subtracting lo). Works correctly even when range wraps around.<br><code>5 3 10 WITHIN . \ -1</code><br><code>3 3 10 WITHIN . \ -1 (inclusive low)</code><br><code>10 3 10 WITHIN . \ 0 (exclusive high)</code><br><i>WAFER: Host function.</i><br>See: &lt; &gt; U&lt; core-ext comparison host-function
<code>AND</code> <b>( x1 x2 -- x3 )</b><br>Bitwise AND. For logical AND with flags, this works because -1 AND -1 = -1. Also used for masking bits.<br><code>0xFF 0x0F AND . \ 15</code><br><code>TRUE TRUE AND . \ -1</code><br><i>WAFER: IR [And]. Compiles to WASM i32.and.</i><br>See: OR XOR INVERT core logic ir-primitive
<code>OR</code> <b>( x1 x2 -- x3 )</b><br>Bitwise OR. Combines flag values and bit masks.<br><code>0xF0 0x0F OR . \ 255</code><br><i>WAFER: IR [Or]. Compiles to WASM i32.or.</i><br>See: AND XOR INVERT core logic ir-primitive
<code>XOR</code> <b>( x1 x2 -- x3 )</b><br>Bitwise exclusive OR. <code>x x XOR</code> yields 0. Useful for toggling bits.<br><code>0xFF 0x0F XOR . \ 240</code><br><i>WAFER: IR [Xor]. Compiles to WASM i32.xor.</i><br>See: AND OR INVERT core logic ir-primitive
<code>INVERT</code> <b>( x -- x' )</b><br>Bitwise NOT (one's complement). For flags: inverts all bits, so <code>TRUE INVERT</code> = FALSE and vice versa. NOT equivalent to logical NOT — use <code>0=</code> for that.<br><code>0 INVERT . \ -1</code><br><i>WAFER: IR [Invert].</i><br>See: NEGATE 0= core logic ir-primitive
<code>LSHIFT</code> <b>( x1 u -- x2 )</b><br>Logical left shift by u bits. Undefined for u ≥ cell-width (32).<br><code>1 8 LSHIFT . \ 256</code><br><i>WAFER: IR [Lshift]. Compiles to WASM i32.shl.</i><br>See: RSHIFT 2* D2* core logic ir-primitive
<code>RSHIFT</code> <b>( x1 u -- x2 )</b><br>Logical right shift (zero-fill). NOT arithmetic shift — does not preserve sign. Use 2/ for signed division by 2.<br><code>256 8 RSHIFT . \ 1</code><br><code>-1 1 RSHIFT . \ 2147483647 (not -1!)</code><br><i>WAFER: IR [Rshift]. Compiles to WASM i32.shr_u.</i><br>See: LSHIFT 2/ core logic ir-primitive
<code>@</code> <b>( a-addr -- x )</b><br>Fetch cell from aligned address. Address must be cell-aligned (4-byte in WAFER). Unaligned access is undefined.<br><code>VARIABLE X 42 X ! X @ . \ 42</code><br><i>WAFER: IR [Fetch]. Compiles to WASM i32.load. Address is byte offset into linear memory.</i><br>See: ! C@ 2@ F@ core memory-ops ir-primitive
<code>!</code> <b>( x a-addr -- )</b><br>Store cell to aligned address.<br><code>99 X !</code><br><i>WAFER: IR [Store]. Compiles to WASM i32.store.</i><br>See: @ C! 2! +! F! core memory-ops ir-primitive
<code>C@</code> <b>( c-addr -- char )</b><br>Fetch single byte (zero-extended to cell).<br><code>S" ABC" DROP C@ . \ 65 (ASCII 'A')</code><br><i>WAFER: IR [CFetch]. Compiles to WASM i32.load8_u.</i><br>See: C! @ COUNT core memory-ops ir-primitive
<code>C!</code> <b>( char c-addr -- )</b><br>Store single byte (low 8 bits of char).<br><code>65 PAD C! PAD C@ . \ 65</code><br><i>WAFER: IR [CStore]. Compiles to WASM i32.store8.</i><br>See: C@ ! core memory-ops ir-primitive
<code>+!</code> <b>( n a-addr -- )</b><br>Add n to the cell at a-addr. Atomic read-modify-write idiom.<br><code>VARIABLE CTR 0 CTR ! 5 CTR +! CTR @ . \ 5</code><br><i>WAFER: IR [PlusStore]. Compiles to load + add + store sequence.</i><br>See: @ ! 1+ core memory-ops ir-primitive
<code>2@</code> <b>( a-addr -- x1 x2 )</b><br>Fetch cell pair. x2 is from a-addr, x1 from a-addr+cell. Note: high cell is at lower address (big-endian pair order).<br><i>WAFER: Host function.</i><br>See: 2! @ 2DUP core memory-ops host-function
<code>2!</code> <b>( x1 x2 a-addr -- )</b><br>Store cell pair. x2 stored at a-addr, x1 at a-addr+cell.<br><i>WAFER: Host function.</i><br>See: 2@ ! 2DROP core memory-ops host-function
<code>HERE</code> <b>( -- addr )</b><br>Address of next available dictionary space. Moves as you ALLOT or comma.<br><code>HERE . \ shows current dictionary pointer</code><br><i>WAFER: Host function. Reads system variable at address 0x0C.</i><br>See: ALLOT , C, UNUSED core memory-ops host-function
<code>ALLOT</code> <b>( n -- )</b><br>Reserve n address units (bytes) at HERE. Negative values reclaim space.<br><code>CREATE BUFFER 100 ALLOT \ allocate 100 bytes</code><br><i>WAFER: Host function. Advances HERE pointer.</i><br>See: HERE CREATE , core memory-ops host-function
<code>,</code> (comma) <b>( x -- )</b><br>Compile cell value at HERE and advance HERE by one cell. Used to build data structures.<br><code>CREATE TABLE 1 , 2 , 3 ,</code><br><i>WAFER: Host function.</i><br>See: C, HERE ALLOT core memory-ops host-function
<code>C,</code> <b>( char -- )</b><br>Compile byte at HERE and advance HERE by one byte.<br><i>WAFER: Host function.</i><br>See: , HERE core memory-ops host-function
<code>CELLS</code> <b>( n -- n*cell )</b><br>Convert cell count to address units. Cell = 4 bytes in WAFER (32-bit).<br><code>10 CELLS . \ 40</code><br><i>WAFER: IR [PushI32(4), Mul]. Strength-reduced to 2 LSHIFT.</i><br>See: CELL+ CHARS FLOATS core memory-ops ir-primitive
<code>CELL+</code> <b>( a-addr -- a-addr' )</b><br>Add one cell size. Steps to next cell in memory.<br><i>WAFER: IR [PushI32(4), Add].</i><br>See: CELLS CHAR+ core memory-ops ir-primitive
<code>CHARS</code> <b>( n -- n*char )</b><br>Convert character count to address units. In WAFER (byte-addressed), this is a no-op (1 char = 1 byte).<br><i>WAFER: IR [] (identity). CHARS is zero IR ops.</i><br>See: CHAR+ CELLS core memory-ops ir-primitive
<code>CHAR+</code> <b>( c-addr -- c-addr' )</b><br>Add one character size (1 byte).<br><i>WAFER: IR [PushI32(1), Add].</i><br>See: CHARS CELL+ core memory-ops ir-primitive
<code>ALIGNED</code> <b>( addr -- a-addr )</b><br>Round up to next cell-aligned address. <code>(addr + 3) AND NOT 3</code>.<br><code>5 ALIGNED . \ 8</code><br><i>WAFER: IR [PushI32(3), Add, PushI32(3), Invert, And].</i><br>See: ALIGN FALIGNED core memory-ops ir-primitive
<code>ALIGN</code> <b>( -- )</b><br>Align HERE to cell boundary. Always call after storing non-cell data with C,.<br><i>WAFER: Host function. Sets HERE = ALIGNED(HERE).</i><br>See: ALIGNED FALIGN core memory-ops host-function
<code>MOVE</code> <b>( addr1 addr2 u -- )</b><br>Copy u bytes from addr1 to addr2. Handles overlapping regions correctly (like C memmove).<br><i>WAFER: Host function. Rust memcpy with overlap detection.</i><br>See: CMOVE CMOVE&gt; FILL core memory-ops host-function
<code>FILL</code> <b>( c-addr u char -- )</b><br>Fill u bytes starting at c-addr with char.<br><code>PAD 10 42 FILL \ fill PAD with '*'</code><br><i>WAFER: Host function.</i><br>See: ERASE BLANK MOVE core memory-ops host-function
<code>&gt;R</code> <b>( x -- ) ( R: -- x )</b><br>Push to return stack. Must be balanced with R&gt; within same definition. Cannot cross control-flow boundaries (IF/THEN, DO/LOOP).<br><code>: 3RD &gt;R &gt;R DUP R&gt; R&gt; ROT ; \ copy third item</code><br><i>WAFER: IR [ToR]. Return stack at 0x1540-0x2540.</i><br>See: R&gt; R@ 2&gt;R core return-stack ir-primitive
<code>R&gt;</code> <b>( -- x ) ( R: x -- )</b><br>Pop from return stack to data stack. Every &gt;R must have a matching R&gt;.<br><i>WAFER: IR [FromR].</i><br>See: &gt;R R@ core return-stack ir-primitive
<code>R@</code> <b>( -- x ) ( R: x -- x )</b><br>Copy top of return stack without consuming. Same as I inside a DO loop.<br><i>WAFER: IR [RFetch].</i><br>See: &gt;R R&gt; I core return-stack ir-primitive
<code>IF</code> <b>Compilation: ( -- orig )<br>Runtime: ( x -- )</b><br>Conditional branch. Consumes flag; branches to ELSE or THEN if zero. Non-zero = true (any bits set).<br><code>: SIGN DUP 0&lt; IF ." negative" ELSE ." non-negative" THEN ;</code><br><i>WAFER: Special token. Compiles to IR If{then,else} block. Nests arbitrarily.</i><br>See: ELSE THEN ?DUP core control-flow special-token
<code>ELSE</code> <b>Compilation: ( orig1 -- orig2 )</b><br>Optional false branch of IF. Execution continues at THEN.<br><i>WAFER: Special token. Part of If{then,else} IR structure.</i><br>See: IF THEN core control-flow special-token
<code>THEN</code> <b>Compilation: ( orig -- )</b><br>Resolve forward reference from IF or ELSE. Every IF needs exactly one THEN.<br><i>WAFER: Special token.</i><br>See: IF ELSE core control-flow special-token
<code>DO</code> <b>Runtime: ( n1|u1 n2|u2 -- ) ( R: -- loop-sys )</b><br>Begin counted loop. n2 is initial index, n1 is limit. Executes body at least once even if limit=index (use ?DO to skip).<br><code>10 0 DO I . LOOP \ prints 0 1 2 ... 9</code><br><i>WAFER: Special token. Compiles to IR DoLoop{body, is_plus:false}. Loop params on return stack.</i><br>See: LOOP +LOOP I J ?DO LEAVE UNLOOP core control-flow special-token
<code>LOOP</code> <b>Runtime: ( -- ) ( R: loop-sys -- )</b><br>Increment index by 1. If index crosses the limit boundary, exit loop; otherwise branch to DO.<br><i>WAFER: Special token. End of DoLoop IR block.</i><br>See: DO +LOOP core control-flow special-token
<code>+LOOP</code> <b>Runtime: ( n -- ) ( R: loop-sys -- )</b><br>Add n to index. Exits when index crosses limit boundary. Works with negative increments for counting down.<br><code>100 0 DO I . 10 +LOOP \ 0 10 20 ... 90</code><br><code>0 10 DO I . -1 +LOOP \ 10 9 8 ... 0</code><br><i>WAFER: Special token. Compiles DoLoop{is_plus:true}.</i><br>See: DO LOOP core control-flow special-token
<code>I</code> <b>( -- n ) ( R: loop-sys -- loop-sys )</b><br>Current loop index. Same as R@ inside DO…LOOP. Zero overhead — reads return stack directly.<br><code>5 0 DO I . LOOP \ 0 1 2 3 4</code><br><i>WAFER: IR [RFetch] (alias of R@).</i><br>See: J R@ LEAVE core control-flow ir-primitive
<code>J</code> <b>( -- n ) ( R: loop-sys1 loop-sys2 -- loop-sys1 loop-sys2 )</b><br>Outer loop index in nested DO loops. Accesses third item on return stack.<br><code>3 0 DO 3 0 DO I J * . LOOP LOOP</code><br><i>WAFER: Host function. Peeks 3 cells deep into return stack.</i><br>See: I core control-flow host-function
<code>UNLOOP</code> <b>( -- ) ( R: loop-sys -- )</b><br>Discard loop parameters from return stack. Required before EXIT inside a DO loop, otherwise return stack is corrupted.<br><code>: FIND-FIRST 10 0 DO I 5 = IF I UNLOOP EXIT THEN LOOP -1 ;</code><br><i>WAFER: IR [UnloopOp]. Drops 3 return stack cells (index, limit, leave-addr).</i><br>See: LEAVE EXIT core control-flow ir-primitive
<code>LEAVE</code> <b>( -- ) ( R: loop-sys -- )</b><br>Exit DO loop immediately. Execution continues after LOOP/+LOOP.<br><code>100 0 DO I 50 &gt; IF LEAVE THEN LOOP</code><br><i>WAFER: Host function. Sets index = limit to force loop exit.</i><br>See: UNLOOP EXIT core control-flow host-function
<code>BEGIN</code> <b>Compilation: ( -- dest )</b><br>Mark loop beginning. Used with UNTIL, WHILE/REPEAT, or AGAIN.<br><i>WAFER: Special token. Marks start of IR loop block.</i><br>See: UNTIL WHILE REPEAT AGAIN core control-flow special-token
<code>UNTIL</code> <b>Runtime: ( x -- )</b><br>Loop back to BEGIN if false. Exit when true. Post-test loop (body executes at least once).<br><code>BEGIN DUP . 1- DUP 0= UNTIL DROP</code><br><i>WAFER: Special token. Compiles to IR BeginUntil{body}.</i><br>See: BEGIN WHILE REPEAT core control-flow special-token
<code>WHILE</code> <b>Runtime: ( x -- )</b><br>Test condition mid-loop. If false, exit to after REPEAT. Pre-test when placed at start of loop body.<br><code>BEGIN DUP WHILE DUP . 1- REPEAT DROP</code><br><i>WAFER: Special token. Part of IR BeginWhileRepeat{test, body}.</i><br>See: BEGIN REPEAT UNTIL core control-flow special-token
<code>REPEAT</code> <b>Compilation: ( -- )</b><br>Unconditional branch back to BEGIN. Loop continues at the WHILE test.<br><i>WAFER: Special token.</i><br>See: BEGIN WHILE core control-flow special-token
<code>RECURSE</code> <b>Compilation: ( -- )</b><br>Compile a call to the currently-being-defined word. Because the word is HIDDEN during compilation, you can't use its name.<br><code>: FACTORIAL DUP 1 &gt; IF DUP 1- RECURSE * ELSE DROP 1 THEN ;</code><br><i>WAFER: Special token. Emits IR Call(current_word_id). Eligible for tail-call optimization when last operation.</i><br>See: EXIT core control-flow special-token
<code>EXIT</code> <b>( -- )</b><br>Return from current word immediately. Inside DO loops, UNLOOP first! After EXIT, remaining code in the word is dead.<br><i>WAFER: Special token. Compiles IR Exit. DCE removes code after unconditional EXIT.</i><br>See: RECURSE UNLOOP ; LEAVE core control-flow special-token
<code>:</code> (colon) <b>( C: "&lt;spaces&gt;name" -- colon-sys )</b><br>Begin new word definition. Enters compile mode. The word is HIDDEN until <code>;</code> reveals it.<br><code>: SQUARE DUP * ;</code><br><i>WAFER: Special token. Creates dictionary entry (HIDDEN), switches to compile mode, allocates new WordId.</i><br>See: ; :NONAME IMMEDIATE core defining special-token
<code>;</code> (semicolon) <b>Compilation: ( colon-sys -- )</b><br>End word definition. Compiles EXIT, optimizes IR, generates WASM module, reveals word, returns to interpret mode.<br><i>WAFER: Special token. Triggers full pipeline: IR → optimize → codegen → wasmtime instantiate → reveal.</i><br>See: : EXIT core defining special-token
<code>VARIABLE</code> <b>( "&lt;spaces&gt;name" -- )</b><br>Create word that pushes address of a cell. Initialized to 0 in WAFER. Usage: <code>VARIABLE X 42 X ! X @ .</code><br><i>WAFER: Special token. Allocates 4 bytes in user data space (starts at 0x10000). Word pushes the address.</i><br>See: CONSTANT VALUE CREATE 2VARIABLE core defining special-token
<code>CONSTANT</code> <b>( x "&lt;spaces&gt;name" -- )</b><br>Create word that pushes x. Immutable after creation — use VALUE if you need mutability.<br><code>42 CONSTANT ANSWER ANSWER . \ 42</code><br><i>WAFER: Special token. Compiled as IR PushI32(x). Inlined by optimizer.</i><br>See: VARIABLE VALUE 2CONSTANT FCONSTANT core defining special-token
<code>CREATE</code> <b>( "&lt;spaces&gt;name" -- )</b><br>Create a word that pushes the address of its data field. Foundation for all defining words. Use with DOES&gt; for custom defining words.<br><code>CREATE TABLE 10 , 20 , 30 ,</code><br><code>TABLE 2 CELLS + @ . \ 30</code><br><i>WAFER: Special token. Allocates dictionary header, word pushes parameter field address.</i><br>See: DOES&gt; ALLOT , VARIABLE core defining special-token
<code>DOES&gt;</code> <b>( -- a-addr )</b><br>Define runtime behavior for words created by the enclosing defining word. Code after DOES&gt; runs when a CREATE'd word executes, with the data address on stack.<br><code>: ARRAY CREATE CELLS ALLOT DOES&gt; SWAP CELLS + ;</code><br><code>5 ARRAY X 42 3 X ! 3 X @ . \ 42</code><br><i>WAFER: Special token + host function (_DOES_PATCH_). Patches the child word's code field to run the DOES&gt; body. Supports double-DOES&gt;.</i><br>See: CREATE core defining special-token
<code>IMMEDIATE</code> <b>( -- )</b><br>Mark most recently defined word as immediate. Immediate words execute during compilation instead of being compiled. Used for compile-time computation and syntax extensions.<br><code>: [MOD] MOD ; IMMEDIATE</code><br><i>WAFER: Host function. Sets IMMEDIATE flag (0x80) in dictionary entry.</i><br>See: POSTPONE [ ] core defining host-function
<code>.</code> (dot) <b>( n -- )</b><br>Print signed integer followed by a space. Uses current BASE.<br><code>42 . \ prints "42 "</code><br><code>HEX 255 . \ prints "FF "</code><br><i>WAFER: Host function. Formats via Rust, appends to output buffer.</i><br>See: U. .R D. F. core io host-function
<code>U.</code> <b>( u -- )</b><br>Print unsigned integer followed by a space. Critical difference from <code>.</code> for values &gt; MAX-INT.<br><code>-1 U. \ prints "4294967295 " (on 32-bit)</code><br><i>WAFER: Host function.</i><br>See: . U.R core io host-function
<code>EMIT</code> <b>( x -- )</b><br>Output character with code x. Low 8 bits used.<br><code>65 EMIT \ prints 'A'</code><br><code>: STARS 0 DO 42 EMIT LOOP ;</code><br><i>WAFER: IR [Emit]. Compiles to host call for output.</i><br>See: TYPE CR KEY core io ir-primitive
<code>CR</code> <b>( -- )</b><br>Output newline character.<br><i>WAFER: IR [Cr].</i><br>See: EMIT SPACE core io ir-primitive
<code>SPACE</code> <b>( -- )</b><br>Output single space (BL EMIT).<br><i>WAFER: IR [PushI32(32), Emit].</i><br>See: SPACES BL CR core io ir-primitive
<code>SPACES</code> <b>( n -- )</b><br>Output n spaces. If n ≤ 0, does nothing.<br><i>WAFER: Host function. Loop of EMIT(32).</i><br>See: SPACE core io host-function
<code>TYPE</code> <b>( c-addr u -- )</b><br>Output u characters starting at c-addr.<br><code>S" Hello" TYPE \ prints Hello</code><br><i>WAFER: IR [Type] / Host function.</i><br>See: EMIT ." S" core io host-function
<code>."</code> (dot-quote) <b>Compilation: ( "ccc&lt;quote&gt;" -- )<br>Runtime: ( -- )</b><br>Compile and display string literal. In interpret mode, displays immediately.<br><code>: GREET ." Hello, World!" CR ;</code><br><i>WAFER: Special token. In compile mode, stores string in data space and compiles Type IR. In interpret mode, outputs immediately.</i><br>See: S" TYPE core io special-token
<code>S"</code> (s-quote) <b>Compilation: ( "ccc&lt;quote&gt;" -- )<br>Runtime: ( -- c-addr u )</b><br>String literal. Pushes address and length. In interpret mode, string is transient (valid until next S" or buffer reuse).<br><code>S" Hello" TYPE</code><br><i>WAFER: Special token. Compile mode: stores in data space, compiles PushI32 pair. Interpret mode: stores at HERE temporarily.</i><br>See: ." S\" C" SLITERAL core io special-token
<code>ACCEPT</code> <b>( c-addr +n1 -- +n2 )</b><br>Read up to n1 characters into buffer at c-addr. Returns actual count n2. Implementation-defined line editing.<br><i>WAFER: Host function. Reads from input source.</i><br>See: KEY REFILL SOURCE core io host-function
<code>KEY</code> <b>( -- char )</b><br>Receive one character. Blocks until available. No echo.<br><i>WAFER: Host function.</i><br>See: KEY? ACCEPT EMIT core io host-function
<code>.R</code> <b>( n1 n2 -- )</b><br>Print n1 right-justified in field of n2 characters. Uses current BASE.<br><code>42 10 .R \ prints " 42"</code><br><i>WAFER: Host function.</i><br>See: . U.R D.R core-ext io host-function
<code>CHAR</code> <b>( "&lt;spaces&gt;name" -- char )</b><br>Parse word and push ASCII value of first character. Interpretation-time only.<br><code>CHAR A . \ 65</code><br><i>WAFER: Special token (interpret mode).</i><br>See: [CHAR] BL core parsing special-token
<code>[CHAR]</code> <b>Compilation: ( "&lt;spaces&gt;name" -- )</b><br>Compile character literal. Immediate word — executes during compilation to push ASCII code.<br><code>: EMIT-A [CHAR] A EMIT ;</code><br><i>WAFER: Special token. Compiles IR PushI32(char_code).</i><br>See: CHAR LITERAL core parsing special-token
<code>WORD</code> <b>( char "&lt;chars&gt;ccc&lt;char&gt;" -- c-addr )</b><br>Parse using delimiter char. Returns counted string at HERE. Obsolescent — prefer PARSE-NAME.<br><code>CHAR | WORD COUNT TYPE \ parses until |</code><br><i>WAFER: Host function. Stores counted string at HERE.</i><br>See: PARSE PARSE-NAME FIND core parsing host-function
<code>FIND</code> <b>( c-addr -- c-addr 0 | xt 1 | xt -1 )</b><br>Search dictionary for counted string. Returns xt and 1 (immediate) or -1 (normal), or original addr and 0 if not found.<br><i>WAFER: Host function. Uses hash index for O(1) lookup.</i><br>See: ' WORD SEARCH-WORDLIST core parsing host-function
<code>COUNT</code> <b>( c-addr -- c-addr+1 u )</b><br>Convert counted string to addr-length pair. First byte is length.<br><i>WAFER: Host function.</i><br>See: WORD S" core parsing host-function
<code>&gt;NUMBER</code> <b>( ud1 c-addr1 u1 -- ud2 c-addr2 u2 )</b><br>Accumulate digits from string into double ud. Stops at first non-digit. u2=0 means entire string consumed.<br><code>0. S" 123" &gt;NUMBER 2DROP D. \ 123</code><br><i>WAFER: Host function. Respects current BASE.</i><br>See: BASE core parsing host-function
<code>EXECUTE</code> <b>( i*x xt -- j*x )</b><br>Execute the word identified by execution token xt. Foundation for callbacks, dispatch tables, and deferred execution.<br><code>' DUP EXECUTE \ same as DUP</code><br><i>WAFER: IR [Execute]. Compiles to WASM call_indirect. The function table index is the xt.</i><br>See: ' ['] DEFER COMPILE, core compilation ir-primitive
<code>'</code> (tick) <b>( "&lt;spaces&gt;name" -- xt )</b><br>Parse word name and return its execution token. Interpretation-time only — use ['] in compile mode. Throws -13 if word not found.<br><code>' DUP EXECUTE \ executes DUP</code><br><i>WAFER: Host function. xt = function table index (WordId).</i><br>See: ['] EXECUTE &gt;BODY FIND core compilation host-function
<code>[']</code> (bracket-tick) <b>Compilation: ( "&lt;spaces&gt;name" -- )</b><br>Compile xt of next word as a literal. Immediate. Use inside definitions where ' would execute at compile time.<br><code>: DO-DUP ['] DUP EXECUTE ;</code><br><i>WAFER: Special token. Compiles IR PushI32(xt).</i><br>See: ' LITERAL POSTPONE core compilation special-token
<code>&gt;BODY</code> <b>( xt -- a-addr )</b><br>Convert execution token to data-field address. Only valid for CREATE'd words. Result undefined for : definitions.<br><code>CREATE X 42 , ' X &gt;BODY @ . \ 42</code><br><i>WAFER: Host function. Reads parameter field address from dictionary entry.</i><br>See: CREATE ' EXECUTE core compilation host-function
<code>LITERAL</code> <b>Compilation: ( x -- )<br>Runtime: ( -- x )</b><br>Compile TOS as a literal. Immediate. Used in macros and [ ] sequences.<br><code>: CACHE-SIZE [ 64 1024 * ] LITERAL ;</code><br><i>WAFER: Special token. Compiles IR PushI32(x). Constant folding may further optimize.</i><br>See: 2LITERAL FLITERAL SLITERAL ['] core compilation special-token
<code>POSTPONE</code> <b>Compilation: ( "&lt;spaces&gt;name" -- )</b><br>Defer compilation of next word. For immediate words: compiles their code. For non-immediate: compiles code that will compile them. The key mechanism for writing compile-time words.<br><code>: MY-IF POSTPONE IF ; IMMEDIATE</code><br><code>: [+] POSTPONE + ; IMMEDIATE</code><br><i>WAFER: Special token. Emits IR for immediate words directly; for non-immediate, emits LITERAL(xt) + COMPILE, sequence.</i><br>See: IMMEDIATE COMPILE, [COMPILE] core compilation special-token
<code>[</code> (left-bracket) <b>( -- )</b><br>Switch to interpret mode during compilation. Lets you compute values at compile time.<br><code>: X [ 6 7 * ] LITERAL ; X . \ 42</code><br><i>WAFER: Special token. Sets STATE to 0. Immediate.</i><br>See: ] LITERAL STATE core compilation special-token
<code>]</code> (right-bracket) <b>( -- )</b><br>Switch to compile mode.<br><i>WAFER: Special token. Sets STATE to -1.</i><br>See: [ STATE core compilation special-token
<code>EVALUATE</code> <b>( i*x c-addr u -- j*x )</b><br>Interpret/compile the string as Forth source. Saves and restores input source specification. Powerful but dangerous — runtime code generation.<br><code>S" 2 3 +" EVALUATE . \ 5</code><br><i>WAFER: Host function. Recursively calls outer interpreter on the string.</i><br>See: SOURCE &gt;IN core compilation host-function
<code>ABORT</code> <b>( i*x -- ) ( R: j*x -- )</b><br>Clear stacks and return to outer interpreter. Equivalent to <code>-1 THROW</code>.<br><i>WAFER: Host function.</i><br>See: ABORT" THROW QUIT core compilation host-function
<code>ABORT"</code> <b>Compilation: ( "ccc&lt;quote&gt;" -- )<br>Runtime: ( i*x x -- | i*x )</b><br>If x is non-zero, display string and abort. Conditional abort with message.<br><code>: CHECK DUP 0&lt; ABORT" negative!" ;</code><br><i>WAFER: Special token. Compiles as IF + string + ABORT sequence.</i><br>See: ABORT THROW core compilation special-token
<code>QUIT</code> <b>( -- )</b><br>Clear return stack, set interpret mode, enter outer interpreter loop. Does not clear data stack (unlike ABORT).<br><i>WAFER: Host function.</i><br>See: ABORT BYE core compilation host-function
<code>STATE</code> <b>( -- a-addr )</b><br>Address of compilation state flag. 0 = interpreting, non-zero = compiling. Do NOT use STATE to write mode-dependent words — use POSTPONE instead.<br><i>WAFER: IR primitive. Returns address of system variable at offset 0x00.</i><br>See: [ ] POSTPONE core compilation ir-primitive
<code>BASE</code> <b>( -- a-addr )</b><br>Address of current number base. Default 10 (decimal). Valid range 2-36.<br><code>HEX BASE @ . \ 10 (printed in hex = 16)</code><br><i>WAFER: IR primitive. System variable at offset 0x04.</i><br>See: DECIMAL HEX core compilation ir-primitive
<code>&gt;IN</code> <b>( -- a-addr )</b><br>Address of input parse position. Offset into current input buffer. Manipulating &gt;IN allows re-parsing (e.g., for POSTPONE).<br><i>WAFER: IR primitive. System variable at offset 0x08.</i><br>See: SOURCE WORD PARSE core compilation ir-primitive
<code>SOURCE</code> <b>( -- c-addr u )</b><br>Current input source buffer and length.<br><i>WAFER: Host function. Returns input buffer address and length.</i><br>See: &gt;IN EVALUATE REFILL core compilation host-function
<code>DECIMAL</code> <b>( -- )</b><br>Set BASE to 10.<br><i>WAFER: Host function. Stores 10 to BASE variable.</i><br>See: HEX BASE core compilation host-function
<code>BL</code> <b>( -- char )</b><br>Push space character (32).<br><code>BL EMIT \ same as SPACE</code><br><i>WAFER: IR [PushI32(32)].</i><br>See: SPACE CHAR core compilation ir-primitive
<code>TRUE</code> <b>( -- true )</b><br>Well-formed true flag: -1 (all bits set). Any non-zero is logically true, but only -1 is canonical TRUE.<br><i>WAFER: IR [PushI32(-1)].</i><br>See: FALSE 0= AND OR core compilation ir-primitive
<code>FALSE</code> <b>( -- false )</b><br>Canonical false flag: 0.<br><i>WAFER: IR [PushI32(0)].</i><br>See: TRUE 0= core compilation ir-primitive
<code>ENVIRONMENT?</code> <b>( c-addr u -- false | i*x true )</b><br>Query implementation environment. Returns info about system capabilities.<br><code>S" MAX-N" ENVIRONMENT? IF . THEN</code><br><i>WAFER: Host function. Supports queries like MAX-N, MAX-U, ADDRESS-UNIT-BITS, STACK-CELLS, RETURN-STACK-CELLS.</i> core compilation host-function
<code>&lt;#</code> <b>( -- )</b><br>Begin pictured numeric output. Initializes the output buffer (grows right to left from PAD end).<br><code>: U. 0 &lt;# #S #&gt; TYPE SPACE ;</code><br><i>WAFER: Host function. Sets HLD pointer to end of PAD area.</i><br>See: # #S #&gt; HOLD SIGN core pictured-numeric host-function
<code>#</code> (number-sign) <b>( ud1 -- ud2 )</b><br>Convert one digit of ud, prepend to pictured output. Divides ud by BASE, converts remainder to ASCII digit.<br><code>0 42 &lt;# # # #&gt; TYPE \ "42"</code><br><i>WAFER: Host function. Uses UM/MOD internally.</i><br>See: #S &lt;# #&gt; core pictured-numeric host-function
<code>#S</code> <b>( ud -- 0 0 )</b><br>Convert all remaining digits. Calls # repeatedly until ud is zero. Always generates at least one digit.<br><code>0 0 &lt;# #S #&gt; TYPE \ "0"</code><br><i>WAFER: Host function.</i><br>See: # &lt;# #&gt; core pictured-numeric host-function
<code>#&gt;</code> <b>( xd -- c-addr u )</b><br>End pictured output. Drops the double number, returns buffer address and length. Buffer is transient.<br><i>WAFER: Host function.</i><br>See: &lt;# # #S TYPE core pictured-numeric host-function
<code>HOLD</code> <b>( char -- )</b><br>Prepend character to pictured output. Used between &lt;# and #&gt; for custom formatting (decimal points, separators).<br><code>: D. TUCK DABS &lt;# #S ROT SIGN #&gt; TYPE SPACE ;</code><br><i>WAFER: Host function.</i><br>See: HOLDS SIGN &lt;# core pictured-numeric host-function
<code>SIGN</code> <b>( n -- )</b><br>If n is negative, prepend '-' to pictured output. Must be called after #S (since output builds right to left, sign goes last).<br><i>WAFER: Host function.</i><br>See: HOLD &lt;# #S core pictured-numeric host-function
<code>NIP</code> <b>( x1 x2 -- x2 )</b><br>Remove second item. Equivalent to SWAP DROP. Cleans up after you've extracted what you need from NOS.<br><code>/MOD NIP \ keep only quotient</code><br><i>WAFER: IR [Nip]. Peephole target: SWAP DROP → NIP.</i><br>See: DROP TUCK core-ext stack ir-primitive
<code>TUCK</code> <b>( x1 x2 -- x2 x1 x2 )</b><br>Copy TOS below second item. Equivalent to SWAP OVER. Useful when you need to save TOS before a consuming operation.<br><code>: !+ TUCK ! CELL+ ; \ store and advance</code><br><i>WAFER: IR [Tuck]. Peephole target: SWAP OVER → TUCK.</i><br>See: NIP OVER core-ext stack ir-primitive
<code>0&lt;&gt;</code> <b>( x -- flag )</b><br>True if not zero. Logical identity for non-canonical flags: normalizes any non-zero to TRUE.<br><code>42 0&lt;&gt; . \ -1</code><br><i>WAFER: IR [ZeroEq, ZeroEq] (double negate). Normalizes to well-formed flag.</i><br>See: 0= &lt;&gt; core-ext comparison ir-primitive
<code>0&gt;</code> <b>( n -- flag )</b><br>True if strictly positive (greater than zero).<br><code>1 0&gt; . \ -1</code><br><code>0 0&gt; . \ 0</code><br><i>WAFER: IR [PushI32(0), Gt].</i><br>See: 0&lt; 0= 0&lt;&gt; core-ext comparison ir-primitive
<code>&lt;&gt;</code> <b>( x1 x2 -- flag )</b><br>True if not equal. Complement of =.<br><i>WAFER: IR [NotEq].</i><br>See: = 0&lt;&gt; core-ext comparison ir-primitive
<code>U&gt;</code> <b>( u1 u2 -- flag )</b><br>Unsigned greater-than.<br><i>WAFER: IR [LtUnsigned with swapped operands] or host function.</i><br>See: U&lt; &gt; core-ext comparison
<code>2&gt;R</code> <b>( x1 x2 -- ) ( R: -- x1 x2 )</b><br>Push cell pair to return stack. Useful for saving double-cell values.<br><i>WAFER: IR [TwoToR].</i><br>See: 2R&gt; 2R@ &gt;R core-ext return-stack ir-primitive
<code>2R&gt;</code> <b>( -- x1 x2 ) ( R: x1 x2 -- )</b><br>Pop cell pair from return stack.<br><i>WAFER: IR [TwoFromR].</i><br>See: 2&gt;R 2R@ R&gt; core-ext return-stack ir-primitive
<code>2R@</code> <b>( -- x1 x2 ) ( R: x1 x2 -- x1 x2 )</b><br>Copy cell pair from return stack.<br><i>WAFER: IR [TwoRFetch].</i><br>See: 2&gt;R 2R&gt; R@ core-ext return-stack ir-primitive
<code>VALUE</code> <b>( x "&lt;spaces&gt;name" -- )</b><br>Create word that pushes x. Unlike CONSTANT, can be changed with TO. Cleaner than VARIABLE for simple storage.<br><code>42 VALUE ANSWER ANSWER . \ 42</code><br><code>99 TO ANSWER ANSWER . \ 99</code><br><i>WAFER: Special token. Stores in data space; TO modifies the stored value.</i><br>See: TO CONSTANT VARIABLE 2VALUE FVALUE core-ext defining special-token
<code>TO</code> <b>Interpretation: ( x "&lt;spaces&gt;name" -- )<br>Compilation: ( "&lt;spaces&gt;name" -- )</b><br>Change a VALUE. Works at both interpret and compile time.<br><code>99 TO MY-VALUE</code><br><i>WAFER: Special token. Compiles store to VALUE's data address.</i><br>See: VALUE 2VALUE FVALUE core-ext defining special-token
<code>DEFER</code> <b>( "&lt;spaces&gt;name" -- )</b><br>Create word with deferred execution. Initially calls ABORT. Set with DEFER! or IS. Enables late binding and forward references.<br><code>DEFER GREET : SAY-HI ." Hi!" ; ' SAY-HI IS GREET</code><br><i>WAFER: Special token. Word calls through a stored xt.</i><br>See: DEFER! DEFER@ IS ACTION-OF core-ext defining special-token
<code>DEFER!</code> <b>( xt2 xt1 -- )</b><br>Store xt2 as the behavior of deferred word xt1.<br><code>' NEW-BEHAVIOR ' MY-DEFER DEFER!</code><br><i>WAFER: Host function.</i><br>See: DEFER DEFER@ IS core-ext defining host-function
<code>DEFER@</code> <b>( xt1 -- xt2 )</b><br>Fetch the current xt stored in deferred word xt1.<br><i>WAFER: Host function.</i><br>See: DEFER DEFER! ACTION-OF core-ext defining host-function
<code>IS</code> <b>Interpretation: ( xt "&lt;spaces&gt;name" -- )<br>Compilation: ( "&lt;spaces&gt;name" -- )</b><br>Set DEFER'd word or VALUE. Syntactic sugar for DEFER! with name lookup.<br><code>' NEW-IMPL IS MY-DEFER</code><br><i>WAFER: Special token. Resolves name, calls DEFER!.</i><br>See: DEFER TO ACTION-OF core-ext defining special-token
<code>ACTION-OF</code> <b>Interpretation: ( "&lt;spaces&gt;name" -- xt )<br>Compilation: ( "&lt;spaces&gt;name" -- )</b><br>Get the xt currently assigned to a DEFER'd word. Compile-time: compiles code to push it at runtime.<br><i>WAFER: Special token.</i><br>See: DEFER@ IS core-ext defining special-token
<code>?DO</code> <b>Runtime: ( n1|u1 n2|u2 -- ) ( R: -- loop-sys )</b><br>Like DO but skips body if limit=index. Compiles as IF check + DO. Always prefer ?DO unless you know limit ≠ index.<br><code>: STARS 0 ?DO [CHAR] * EMIT LOOP ; \ 0 STARS does nothing</code><br><i>WAFER: Special token. Compiles as 2DUP = IF 2DROP ELSE DO ... LOOP THEN.</i><br>See: DO LOOP +LOOP core-ext control-flow special-token
<code>AGAIN</code> <b>Compilation: ( -- )</b><br>Unconditional loop back to BEGIN. Infinite loop — exit with LEAVE, EXIT, or THROW.<br><code>: FOREVER BEGIN ." loop " AGAIN ; \ never returns</code><br><i>WAFER: Special token. Compiles to IR BeginAgain{body}.</i><br>See: BEGIN UNTIL WHILE core-ext control-flow special-token
<code>CASE</code> <b>Compilation: ( -- case-sys )</b><br>Begin CASE structure. Multi-way conditional — Forth's switch statement.<br><code>: CHECK CASE</code><br><code> 1 OF ." one" ENDOF</code><br><code> 2 OF ." two" ENDOF</code><br><code> ." other"</code><br><code>ENDCASE ;</code><br><i>WAFER: Special token. Compiles to nested IF/ELSE/THEN.</i><br>See: OF ENDOF ENDCASE core-ext control-flow special-token
<code>OF</code> <b>Runtime: ( x1 x2 -- | x1 )</b><br>Compare TOS to case value. If equal, drop both and execute clause. If not, keep x1 and skip to ENDOF.<br><i>WAFER: Special token.</i><br>See: CASE ENDOF ENDCASE core-ext control-flow special-token
<code>ENDOF</code> <b>Compilation: ( case-sys -- case-sys )</b><br>End an OF clause. Branches to after ENDCASE.<br><i>WAFER: Special token.</i><br>See: OF CASE ENDCASE core-ext control-flow special-token
<code>ENDCASE</code> <b>Runtime: ( x -- )</b><br>End CASE structure. Drops the selector value.<br><i>WAFER: Special token.</i><br>See: CASE OF ENDOF core-ext control-flow special-token
<code>PAD</code> <b>( -- c-addr )</b><br>Address of transient scratch buffer (256 bytes in WAFER). Separate from dictionary and stacks. Used for string formatting.<br><i>WAFER: IR [PushI32(0x0440)]. Address is a compile-time constant.</i><br>See: HERE &lt;# S" core-ext memory-ops ir-primitive
<code>ERASE</code> <b>( addr u -- )</b><br>Fill u bytes with zero. Equivalent to <code>0 FILL</code>.<br><i>WAFER: Host function.</i><br>See: FILL BLANK core-ext memory-ops host-function
<code>MARKER</code> <b>( "&lt;spaces&gt;name" -- )</b><br>Create a snapshot. Executing the marker word restores dictionary to the state before the marker was created. Useful for development: redefine everything by calling the marker first.<br><code>MARKER CLEAN : FOO ." test" ; CLEAN \ FOO is forgotten</code><br><i>WAFER: Host function. Saves HERE and LATEST, restores on execution.</i><br>See: ALLOT HERE core-ext defining host-function
<code>BUFFER:</code> <b>( u "&lt;spaces&gt;name" -- )</b><br>Create word that pushes address of u-byte buffer. Like <code>CREATE n ALLOT</code> but more portable.<br><code>256 BUFFER: LINE-BUF</code><br><i>WAFER: Special token.</i><br>See: CREATE ALLOT VARIABLE core-ext defining special-token
<code>:NONAME</code> <b>( -- xt )</b><br>Begin anonymous word definition. Returns execution token. No dictionary entry created.<br><code>:NONAME DUP * ; CONSTANT SQUARE-XT</code><br><code>5 SQUARE-XT EXECUTE . \ 25</code><br><i>WAFER: Special token. Allocates WordId but no dictionary header.</i><br>See: : DEFER EXECUTE core-ext defining special-token
<code>COMPILE,</code> <b>( xt -- )</b><br>Append call to xt to current definition. Runtime compilation. Used by POSTPONE for non-immediate words.<br><i>WAFER: Host function. Appends IR Call(word_id) to compiling_ir.</i><br>See: POSTPONE LITERAL EXECUTE core-ext compilation host-function
<code>C"</code> <b>Compilation: ( "ccc&lt;quote&gt;" -- )<br>Runtime: ( -- c-addr )</b><br>Counted string literal. First byte is length, followed by characters. Max 255 chars.<br><i>WAFER: Special token.</i><br>See: S" COUNT core-ext io special-token
<code>S\"</code> (s-backslash-quote) <b>Compilation: ( "ccc&lt;quote&gt;" -- )<br>Runtime: ( -- c-addr u )</b><br>String literal with escape sequences: \n (newline), \t (tab), \\ (backslash), \" (quote), \0 (null), \x41 (hex byte).<br><code>S\" Hello\nWorld" TYPE</code><br><i>WAFER: Special token. Parses escape sequences at compile time.</i><br>See: S" core-ext io special-token
<code>.(</code> (dot-paren) <b>( "ccc&lt;paren&gt;" -- )</b><br>Display string immediately (delimited by closing paren). Immediate — works in both modes. Useful for compile-time messages.<br><code>.( Compiling... )</code><br><i>WAFER: Special token.</i><br>See: ." TYPE core-ext io special-token
<code>\</code> (backslash) <b>( -- )</b><br>Line comment — skip rest of input line. Immediate.<br><code>: FOO DUP * ; \ this is a comment</code><br><i>WAFER: Special token. Sets &gt;IN to end of input buffer.</i><br>See: ( core-ext parsing special-token
<code>(</code> (paren) <b>( "ccc&lt;paren&gt;" -- )</b><br>Block comment — skip until closing paren. Immediate. Can span multiple lines (if input provides them). Convention: stack comments in parentheses.<br><code>: FOO ( n -- n*n ) DUP * ;</code><br><i>WAFER: Special token.</i><br>See: \ core parsing special-token
<code>PARSE</code> <b>( char "ccc&lt;char&gt;" -- c-addr u )</b><br>Parse input delimited by char. Does not skip leading delimiters (unlike WORD). Returns pointer into input buffer.<br><i>WAFER: Host function.</i><br>See: PARSE-NAME WORD core-ext parsing host-function
<code>PARSE-NAME</code> <b>( "&lt;spaces&gt;name" -- c-addr u )</b><br>Parse whitespace-delimited name. Skips leading whitespace. Preferred over WORD for modern Forth.<br><i>WAFER: Host function.</i><br>See: PARSE WORD core-ext parsing host-function
<code>REFILL</code> <b>( -- flag )</b><br>Attempt to refill the input buffer. Returns TRUE if successful. Returns FALSE for string input (EVALUATE).<br><i>WAFER: Host function.</i><br>See: SOURCE EVALUATE core-ext parsing host-function
<code>HOLDS</code> <b>( c-addr u -- )</b><br>Prepend string to pictured numeric output. Like HOLD but for multiple characters at once.<br><i>WAFER: Host function.</i><br>See: HOLD &lt;# #&gt; core-ext pictured-numeric host-function
<code>HEX</code> <b>( -- )</b><br>Set BASE to 16.<br><code>HEX FF . \ 255 (in hex output: FF)</code><br><i>WAFER: Host function.</i><br>See: DECIMAL BASE core-ext compilation host-function
<code>UNUSED</code> <b>( -- u )</b><br>Number of address units remaining in data space.<br><i>WAFER: Host function.</i><br>See: HERE ALLOT core-ext memory-ops host-function
<code>SOURCE-ID</code> <b>( -- 0 | -1 )</b><br>Input source identifier: 0 for user input, -1 for EVALUATE string.<br><i>WAFER: Host function.</i><br>See: SOURCE EVALUATE core-ext compilation host-function
<code>[COMPILE]</code> <b>Compilation: ( "&lt;spaces&gt;name" -- )</b><br>Obsolescent. Compile the immediately-following word even if it's immediate. Replaced by POSTPONE in modern Forth.<br><i>Not recommended. Use POSTPONE instead.</i><br>See: POSTPONE core-ext compilation
<code>2CONSTANT</code> <b>( x1 x2 "&lt;spaces&gt;name" -- )</b><br>Create word that pushes double-cell constant.<br><code>1000000. 2CONSTANT BIG</code><br><i>WAFER: Special token.</i><br>See: CONSTANT 2VARIABLE DCONSTANT core-ext defining special-token
<code>2VARIABLE</code> <b>( "&lt;spaces&gt;name" -- )</b><br>Create word that pushes address of double-cell variable.<br><i>WAFER: Special token. Allocates 8 bytes.</i><br>See: VARIABLE 2CONSTANT core-ext defining special-token
<code>2VALUE</code> <b>( x1 x2 "&lt;spaces&gt;name" -- )</b><br>Create word that pushes double-cell value. Change with <code>TO</code>.<br><i>WAFER: Special token.</i><br>See: VALUE 2CONSTANT TO double-ext defining special-token
<code>2LITERAL</code> <b>Compilation: ( x1 x2 -- )<br>Runtime: ( -- x1 x2 )</b><br>Compile double-cell literal. Immediate.<br><i>WAFER: Special token. Compiles two IR PushI32 ops.</i><br>See: LITERAL FLITERAL double compilation special-token
<code>D+</code> <b>( d1 d2 -- d3 )</b><br>Double-cell addition. Handles carry between low and high cells.<br><code>1. 2. D+ D. \ 3</code><br><i>WAFER: Host function. Uses Rust i64 arithmetic.</i><br>See: D- + M+ double arithmetic host-function
<code>D-</code> <b>( d1 d2 -- d3 )</b><br>Double-cell subtraction.<br><i>WAFER: Host function.</i><br>See: D+ - DNEGATE double arithmetic host-function
<code>D.</code> <b>( d -- )</b><br>Print signed double-cell number followed by space.<br><code>-1. D. \ -1</code><br><i>WAFER: Host function.</i><br>See: D.R . U. double io host-function
<code>D.R</code> <b>( d n -- )</b><br>Print double-cell number right-justified in n-character field.<br><i>WAFER: Host function.</i><br>See: D. .R double io host-function
<code>D0=</code> <b>( d -- flag )</b><br>True if double is zero. Both cells must be zero.<br><i>WAFER: Host function.</i><br>See: D0&lt; 0= D= double comparison host-function
<code>D0&lt;</code> <b>( d -- flag )</b><br>True if double is negative. Tests sign bit of high cell.<br><i>WAFER: Host function.</i><br>See: D0= 0&lt; double comparison host-function
<code>D=</code> <b>( d1 d2 -- flag )</b><br>True if two doubles are equal.<br><i>WAFER: Host function.</i><br>See: D&lt; = D0= double comparison host-function
<code>D&lt;</code> <b>( d1 d2 -- flag )</b><br>Signed double less-than.<br><i>WAFER: Host function.</i><br>See: D= DU&lt; &lt; double comparison host-function
<code>DU&lt;</code> <b>( ud1 ud2 -- flag )</b><br>Unsigned double less-than.<br><i>WAFER: Host function.</i><br>See: D&lt; U&lt; double comparison host-function
<code>DNEGATE</code> <b>( d -- -d )</b><br>Negate double-cell number. Two's complement across both cells.<br><i>WAFER: Host function.</i><br>See: NEGATE DABS double arithmetic host-function
<code>DABS</code> <b>( d -- ud )</b><br>Double-cell absolute value.<br><i>WAFER: Host function.</i><br>See: DNEGATE ABS double arithmetic host-function
<code>D2*</code> <b>( d -- d*2 )</b><br>Double-cell left shift by 1. Shifts carry between cells.<br><i>WAFER: Host function.</i><br>See: D2/ 2* double arithmetic host-function
<code>D2/</code> <b>( d -- d/2 )</b><br>Double-cell arithmetic right shift by 1. Preserves sign.<br><i>WAFER: Host function.</i><br>See: D2* 2/ double arithmetic host-function
<code>DMAX</code> <b>( d1 d2 -- d3 )</b><br>Signed double-cell maximum.<br><i>WAFER: Host function.</i><br>See: DMIN MAX double arithmetic host-function
<code>DMIN</code> <b>( d1 d2 -- d3 )</b><br>Signed double-cell minimum.<br><i>WAFER: Host function.</i><br>See: DMAX MIN double arithmetic host-function
<code>D&gt;S</code> <b>( d -- n )</b><br>Convert double to single by dropping high cell. Result is undefined if d doesn't fit in a single cell.<br><i>WAFER: IR primitive. Just drops the high cell.</i><br>See: S&gt;D double-ext conversion ir-primitive
<code>M+</code> <b>( d n -- d' )</b><br>Add single-cell to double-cell.<br><i>WAFER: Host function. Sign-extends n, then D+.</i><br>See: D+ + double arithmetic host-function
<code>M*/</code> <b>( d1 n1 +n2 -- d2 )</b><br>Multiply double d1 by n1, divide by +n2. Triple-cell intermediate avoids overflow. n2 must be positive.<br><i>WAFER: Host function. Uses Rust i128 intermediate.</i><br>See: */ M* double arithmetic host-function
<code>2ROT</code> <b>( x1 x2 x3 x4 x5 x6 -- x3 x4 x5 x6 x1 x2 )</b><br>Rotate third cell pair to top. The double-width version of ROT.<br><i>WAFER: Host function.</i><br>See: ROT 2SWAP 2OVER double stack host-function
<code>CATCH</code> <b>( i*x xt -- j*x 0 | i*x n )</b><br>Execute xt, catching any THROW. Returns 0 if no exception, or the throw code n. Saves and restores stacks on exception.<br><code>: SAFE ['] RISKY CATCH IF ." error!" THEN ;</code><br><i>WAFER: Host function. Saves DSP/RSP/FSP. Nested CATCH supported.</i><br>See: THROW ABORT exception control-flow host-function
<code>THROW</code> <b>( k*x n -- k*x | i*x n )</b><br>Throw exception n. If n=0, does nothing. If no matching CATCH, behaves as ABORT. Standard codes: -1 ABORT, -2 ABORT", -4 stack underflow, -13 undefined word.<br><code>: CHECK DUP 0&lt; IF -24 THROW THEN ;</code><br><i>WAFER: Host function. Unwinds to nearest CATCH, restoring stacks.</i><br>See: CATCH ABORT ABORT" exception control-flow host-function
<code>COMPARE</code> <b>( c-addr1 u1 c-addr2 u2 -- n )</b><br>Compare two strings. Returns 0 if equal, -1 if first is less, +1 if first is greater. Lexicographic, case-sensitive.<br><code>S" ABC" S" ABD" COMPARE . \ -1</code><br><i>WAFER: Host function.</i><br>See: SEARCH S= string comparison host-function
<code>SEARCH</code> <b>( c-addr1 u1 c-addr2 u2 -- c-addr3 u3 flag )</b><br>Search string1 for string2. If found: c-addr3 points to match, flag=true. If not: original string1, flag=false.<br><code>S" Hello World" S" World" SEARCH . TYPE \ -1 World</code><br><i>WAFER: Host function.</i><br>See: COMPARE /STRING string parsing host-function
<code>/STRING</code> <b>( c-addr u n -- c-addr' u' )</b><br>Advance string by n characters. Adds n to c-addr, subtracts n from u.<br><code>S" Hello" 2 /STRING TYPE \ llo</code><br><i>WAFER: Host function.</i><br>See: SEARCH -TRAILING string memory-ops host-function
<code>BLANK</code> <b>( c-addr u -- )</b><br>Fill u bytes with spaces (BL). Equivalent to <code>BL FILL</code>.<br><i>WAFER: Host function.</i><br>See: FILL ERASE string memory-ops host-function
<code>-TRAILING</code> <b>( c-addr u1 -- c-addr u2 )</b><br>Remove trailing spaces. Adjusts length; address unchanged.<br><code>S" hello " -TRAILING TYPE . \ "hello" 5</code><br><i>WAFER: Host function.</i><br>See: /STRING BLANK string parsing host-function
<code>CMOVE</code> <b>( c-addr1 c-addr2 u -- )</b><br>Copy u bytes from addr1 to addr2, low address to high. Use when destination is lower than source (or non-overlapping).<br><i>WAFER: Host function.</i><br>See: CMOVE&gt; MOVE string memory-ops host-function
<code>CMOVE&gt;</code> <b>( c-addr1 c-addr2 u -- )</b><br>Copy u bytes from addr1 to addr2, high address to low. Use when destination is higher than source (overlapping).<br><i>WAFER: Host function.</i><br>See: CMOVE MOVE string memory-ops host-function
<code>SLITERAL</code> <b>Compilation: ( c-addr u -- )<br>Runtime: ( -- c-addr u )</b><br>Compile string literal from stack. Immediate. Used in macros that produce strings at compile time.<br><i>WAFER: Special token.</i><br>See: S" LITERAL 2LITERAL string compilation special-token
<code>FDROP</code> <b>( F: r -- )</b><br>Drop top of float stack.<br><i>WAFER: Host function. Decrements FSP.</i><br>See: FDUP FSWAP DROP float stack host-function
<code>FDUP</code> <b>( F: r -- r r )</b><br>Duplicate top of float stack.<br><code>3.14e FDUP F* F. \ 9.8596 (pi squared approx)</code><br><i>WAFER: Host function.</i><br>See: FDROP FOVER DUP float stack host-function
<code>FSWAP</code> <b>( F: r1 r2 -- r2 r1 )</b><br>Exchange top two float stack items.<br><i>WAFER: Host function.</i><br>See: FROT FOVER SWAP float stack host-function
<code>FOVER</code> <b>( F: r1 r2 -- r1 r2 r1 )</b><br>Copy second float to top.<br><i>WAFER: Host function.</i><br>See: FDUP FSWAP OVER float stack host-function
<code>FROT</code> <b>( F: r1 r2 r3 -- r2 r3 r1 )</b><br>Rotate third float to top.<br><i>WAFER: Host function.</i><br>See: FSWAP ROT float stack host-function
<code>FNIP</code> <b>( F: r1 r2 -- r2 )</b><br>Remove second float.<br><i>WAFER: Host function.</i><br>See: FDROP NIP float stack host-function
<code>FTUCK</code> <b>( F: r1 r2 -- r2 r1 r2 )</b><br>Tuck top float below second.<br><i>WAFER: Host function.</i><br>See: FSWAP TUCK float stack host-function
<code>FDEPTH</code> <b>( -- +n )</b><br>Number of values on the float stack.<br><i>WAFER: Host function.</i><br>See: DEPTH float stack host-function
<code>F+</code> <b>( F: r1 r2 -- r3 )</b><br>Float addition.<br><code>1.5e 2.5e F+ F. \ 4.0</code><br><i>WAFER: Host function. Uses f64 add.</i><br>See: F- F* D+ float arithmetic host-function
<code>F-</code> <b>( F: r1 r2 -- r3 )</b><br>Float subtraction (r1 minus r2).<br><i>WAFER: Host function.</i><br>See: F+ FNEGATE float arithmetic host-function
<code>F*</code> <b>( F: r1 r2 -- r3 )</b><br>Float multiplication.<br><code>3.0e 4.0e F* F. \ 12.0</code><br><i>WAFER: Host function.</i><br>See: F/ F** float arithmetic host-function
<code>F/</code> <b>( F: r1 r2 -- r3 )</b><br>Float division. Division by zero produces ±Infinity per IEEE 754.<br><code>22.0e 7.0e F/ F. \ 3.142857</code><br><i>WAFER: Host function.</i><br>See: F* / float arithmetic host-function
<code>FNEGATE</code> <b>( F: r -- -r )</b><br>Negate float. Flips sign bit; works on ±0, ±Inf, NaN.<br><i>WAFER: Host function.</i><br>See: FABS NEGATE float arithmetic host-function
<code>FABS</code> <b>( F: r -- |r| )</b><br>Float absolute value.<br><i>WAFER: Host function.</i><br>See: FNEGATE ABS float arithmetic host-function
<code>FMAX</code> <b>( F: r1 r2 -- r3 )</b><br>Float maximum. NaN propagation is implementation-defined.<br><i>WAFER: Host function. Uses Rust f64::max.</i><br>See: FMIN MAX float arithmetic host-function
<code>FMIN</code> <b>( F: r1 r2 -- r3 )</b><br>Float minimum.<br><i>WAFER: Host function.</i><br>See: FMAX MIN float arithmetic host-function
<code>FSQRT</code> <b>( F: r -- r' )</b><br>Square root. Negative input produces NaN.<br><code>2.0e FSQRT F. \ 1.41421356...</code><br><i>WAFER: Host function. Uses Rust f64::sqrt.</i><br>See: F** FABS float-ext arithmetic host-function
<code>FLOOR</code> <b>( F: r -- r' )</b><br>Round toward negative infinity. Returns float, not integer.<br><code>3.7e FLOOR F. \ 3.0</code><br><code>-3.2e FLOOR F. \ -4.0</code><br><i>WAFER: Host function.</i><br>See: FROUND F&gt;S float arithmetic host-function
<code>FROUND</code> <b>( F: r -- r' )</b><br>Round to nearest (banker's rounding: ties to even). Returns float.<br><code>2.5e FROUND F. \ 2.0 (ties to even)</code><br><code>3.5e FROUND F. \ 4.0</code><br><i>WAFER: Host function.</i><br>See: FLOOR F&gt;S float arithmetic host-function
<code>F**</code> <b>( F: r1 r2 -- r3 )</b><br>Float exponentiation: r1 raised to r2.<br><code>2.0e 10.0e F** F. \ 1024.0</code><br><i>WAFER: Host function. Uses Rust f64::powf.</i><br>See: FSQRT FEXP float-ext arithmetic host-function
<code>F0=</code> <b>( F: r -- ) ( -- flag )</b><br>True if float is zero (positive or negative zero).<br><i>WAFER: Host function.</i><br>See: F0&lt; F= 0= float comparison host-function
<code>F0&lt;</code> <b>( F: r -- ) ( -- flag )</b><br>True if float is negative. Negative zero returns false.<br><i>WAFER: Host function.</i><br>See: F0= 0&lt; float comparison host-function
<code>F=</code> <b>( F: r1 r2 -- ) ( -- flag )</b><br>True if floats are exactly equal. Beware: floating-point comparison with == is usually wrong. Prefer F~ for approximate comparison.<br><i>WAFER: Host function.</i><br>See: F~ F&lt; = float comparison host-function
<code>F&lt;</code> <b>( F: r1 r2 -- ) ( -- flag )</b><br>True if r1 &lt; r2. NaN comparisons return false.<br><i>WAFER: Host function.</i><br>See: F= &lt; float comparison host-function
<code>F~</code> <b>( F: r1 r2 r3 -- ) ( -- flag )</b><br>Approximate float comparison. Three modes: r3&gt;0: |r1-r2| &lt; r3 (absolute). r3=0: exact bitwise equality. r3&lt;0: |r1-r2| &lt; |r3|*(|r1|+|r2|) (relative).<br><code>1.0e 3.0e F/ 3.0e F* 1.0e 1e-15 F~ . \ -1 (close enough)</code><br><i>WAFER: Host function.</i><br>See: F= F0= float-ext comparison host-function
<code>F@</code> <b>( f-addr -- ) ( F: -- r )</b><br>Fetch 64-bit float from memory to float stack.<br><code>FVARIABLE X 3.14e X F! X F@ F.</code><br><i>WAFER: Host function. Reads 8 bytes as f64.</i><br>See: F! @ SF@ DF@ float memory-ops host-function
<code>F!</code> <b>( f-addr -- ) ( F: r -- )</b><br>Store 64-bit float from float stack to memory.<br><i>WAFER: Host function. Writes 8 bytes.</i><br>See: F@ ! SF! DF! float memory-ops host-function
<code>SF@</code> <b>( sf-addr -- ) ( F: -- r )</b><br>Fetch 32-bit single-precision float, widen to f64.<br><i>WAFER: Host function.</i><br>See: SF! F@ DF@ float-ext memory-ops host-function
<code>SF!</code> <b>( sf-addr -- ) ( F: r -- )</b><br>Store float as 32-bit single-precision (truncating).<br><i>WAFER: Host function.</i><br>See: SF@ F! DF! float-ext memory-ops host-function
<code>DF@</code> <b>( df-addr -- ) ( F: -- r )</b><br>Fetch 64-bit double-precision float. Same as F@ in WAFER (native float = f64).<br><i>WAFER: Host function. Identical to F@ since WAFER floats are f64.</i><br>See: DF! F@ SF@ float-ext memory-ops host-function
<code>DF!</code> <b>( df-addr -- ) ( F: r -- )</b><br>Store 64-bit double-precision float. Same as F! in WAFER.<br><i>WAFER: Host function.</i><br>See: DF@ F! SF! float-ext memory-ops host-function
<code>FALIGNED</code> <b>( addr -- f-addr )</b><br>Align address to float boundary (8 bytes).<br><i>WAFER: Host function.</i><br>See: FALIGN ALIGNED SFALIGNED DFALIGNED float memory-ops host-function
<code>FALIGN</code> <b>( -- )</b><br>Align HERE to float boundary.<br><i>WAFER: Host function.</i><br>See: FALIGNED ALIGN float memory-ops host-function
<code>FLOAT+</code> <b>( f-addr -- f-addr' )</b><br>Add one float size (8 bytes) to address.<br><i>WAFER: Host function.</i><br>See: FLOATS CELL+ SFLOAT+ DFLOAT+ float memory-ops host-function
<code>FLOATS</code> <b>( n -- n*float )</b><br>Convert float count to address units. Multiplies by 8.<br><i>WAFER: Host function.</i><br>See: FLOAT+ CELLS float memory-ops host-function
<code>SFALIGNED</code> <b>( addr -- sf-addr )</b><br>Align to single-float boundary (4 bytes).<br><i>WAFER: Host function.</i><br>See: SFALIGN FALIGNED float-ext memory-ops host-function
<code>SFALIGN</code> <b>( -- )</b><br>Align HERE to single-float boundary.<br><i>WAFER: Host function.</i><br>See: SFALIGNED FALIGN float-ext memory-ops host-function
<code>SFLOAT+</code> <b>( sf-addr -- sf-addr' )</b><br>Add single-float size (4 bytes).<br><i>WAFER: Host function.</i><br>See: SFLOATS FLOAT+ float-ext memory-ops host-function
<code>SFLOATS</code> <b>( n -- n*sfloat )</b><br>Convert single-float count to address units (×4).<br><i>WAFER: Host function.</i><br>See: SFLOAT+ FLOATS float-ext memory-ops host-function
<code>DFALIGNED</code> <b>( addr -- df-addr )</b><br>Align to double-float boundary (8 bytes).<br><i>WAFER: Host function.</i><br>See: DFALIGN FALIGNED float-ext memory-ops host-function
<code>DFALIGN</code> <b>( -- )</b><br>Align HERE to double-float boundary.<br><i>WAFER: Host function.</i><br>See: DFALIGNED FALIGN float-ext memory-ops host-function
<code>DFLOAT+</code> <b>( df-addr -- df-addr' )</b><br>Add double-float size (8 bytes).<br><i>WAFER: Host function.</i><br>See: DFLOATS FLOAT+ float-ext memory-ops host-function
<code>DFLOATS</code> <b>( n -- n*dfloat )</b><br>Convert double-float count to address units (×8).<br><i>WAFER: Host function.</i><br>See: DFLOAT+ FLOATS float-ext memory-ops host-function
<code>D&gt;F</code> <b>( d -- ) ( F: -- r )</b><br>Convert double-cell integer to float.<br><code>1000000. D&gt;F F. \ 1000000.0</code><br><i>WAFER: Host function. Combines two i32 cells → i64 → f64.</i><br>See: F&gt;D S&gt;F float-ext conversion host-function
<code>F&gt;D</code> <b>( F: r -- ) ( -- d )</b><br>Convert float to double-cell integer (truncate toward zero).<br><code>3.99e F&gt;D D. \ 3</code><br><i>WAFER: Host function.</i><br>See: D&gt;F F&gt;S float-ext conversion host-function
<code>S&gt;F</code> <b>( n -- ) ( F: -- r )</b><br>Convert single-cell signed integer to float.<br><code>42 S&gt;F F. \ 42.0</code><br><i>WAFER: Host function.</i><br>See: F&gt;S D&gt;F S&gt;D float-ext conversion host-function
<code>F&gt;S</code> <b>( F: r -- ) ( -- n )</b><br>Convert float to single-cell integer (truncate toward zero). Undefined if out of range.<br><code>3.7e F&gt;S . \ 3</code><br><i>WAFER: Host function.</i><br>See: S&gt;F F&gt;D FLOOR float-ext conversion host-function
<code>&gt;FLOAT</code> <b>( c-addr u -- flag ) ( F: -- r | )</b><br>Parse string as float. If successful, push float and return true. Otherwise just return false. Accepts E notation.<br><code>S" 3.14" &gt;FLOAT . F. \ -1 3.14</code><br><i>WAFER: Host function. Uses Rust f64 parser.</i><br>See: &gt;NUMBER S&gt;F float conversion host-function
<code>FSIN</code> <b>( F: r -- r' )</b><br>Sine (radians).<br><code>3.14159265e 2.0e F/ FSIN F. \ ≈1.0</code><br><i>WAFER: Host function. Uses Rust f64::sin.</i><br>See: FCOS FTAN FASIN FSINCOS float-ext trig host-function
<code>FCOS</code> <b>( F: r -- r' )</b><br>Cosine (radians).<br><code>0.0e FCOS F. \ 1.0</code><br><i>WAFER: Host function.</i><br>See: FSIN FTAN FACOS float-ext trig host-function
<code>FTAN</code> <b>( F: r -- r' )</b><br>Tangent (radians).<br><i>WAFER: Host function.</i><br>See: FSIN FCOS FATAN float-ext trig host-function
<code>FASIN</code> <b>( F: r -- r' )</b><br>Arc sine. Input range [-1, 1], output [-π/2, π/2].<br><i>WAFER: Host function.</i><br>See: FSIN FACOS FATAN float-ext trig host-function
<code>FACOS</code> <b>( F: r -- r' )</b><br>Arc cosine. Input [-1, 1], output [0, π].<br><i>WAFER: Host function.</i><br>See: FCOS FASIN float-ext trig host-function
<code>FATAN</code> <b>( F: r -- r' )</b><br>Arc tangent. Output (-π/2, π/2).<br><i>WAFER: Host function.</i><br>See: FATAN2 FTAN float-ext trig host-function
<code>FATAN2</code> <b>( F: r1 r2 -- r3 )</b><br>Two-argument arc tangent: atan2(r1, r2). Returns angle in (-π, π]. Handles all quadrants correctly. r1 is y, r2 is x.<br><code>1.0e 0.0e FATAN2 F. \ ≈1.5708 (π/2)</code><br><i>WAFER: Host function.</i><br>See: FATAN FSIN FCOS float-ext trig host-function
<code>FSINCOS</code> <b>( F: r -- r-sin r-cos )</b><br>Compute both sine and cosine. More efficient than calling FSIN and FCOS separately.<br><i>WAFER: Host function.</i><br>See: FSIN FCOS float-ext trig host-function
<code>FEXP</code> <b>( F: r -- r' )</b><br>Natural exponential e^r.<br><code>1.0e FEXP F. \ ≈2.71828</code><br><i>WAFER: Host function.</i><br>See: FLN FEXPM1 FALOG float-ext arithmetic host-function
<code>FEXPM1</code> <b>( F: r -- r' )</b><br>e^r - 1. More accurate than FEXP 1.0 F- for small r (avoids catastrophic cancellation).<br><code>1e-15 FEXPM1 F. \ ≈1e-15 (not 0.0)</code><br><i>WAFER: Host function.</i><br>See: FEXP FLNP1 float-ext arithmetic host-function
<code>FLN</code> <b>( F: r -- r' )</b><br>Natural logarithm. Domain: r &gt; 0.<br><code>2.71828e FLN F. \ ≈1.0</code><br><i>WAFER: Host function.</i><br>See: FEXP FLOG FLNP1 float-ext arithmetic host-function
<code>FLNP1</code> <b>( F: r -- r' )</b><br>ln(1+r). More accurate than <code>1.0 F+ FLN</code> for small r.<br><i>WAFER: Host function.</i><br>See: FLN FEXPM1 float-ext arithmetic host-function
<code>FLOG</code> <b>( F: r -- r' )</b><br>Base-10 logarithm.<br><code>100.0e FLOG F. \ 2.0</code><br><i>WAFER: Host function.</i><br>See: FALOG FLN float-ext arithmetic host-function
<code>FALOG</code> <b>( F: r -- r' )</b><br>Base-10 antilogarithm: 10^r.<br><code>3.0e FALOG F. \ 1000.0</code><br><i>WAFER: Host function.</i><br>See: FLOG FEXP float-ext arithmetic host-function
<code>FSINH</code> <b>( F: r -- r' )</b><br>Hyperbolic sine.<br><i>WAFER: Host function. Uses Rust f64::sinh.</i><br>See: FCOSH FTANH FASINH float-ext trig host-function
<code>FCOSH</code> <b>( F: r -- r' )</b><br>Hyperbolic cosine. Always ≥ 1.<br><i>WAFER: Host function.</i><br>See: FSINH FTANH FACOSH float-ext trig host-function
<code>FTANH</code> <b>( F: r -- r' )</b><br>Hyperbolic tangent. Output range (-1, 1).<br><i>WAFER: Host function.</i><br>See: FSINH FCOSH FATANH float-ext trig host-function
<code>FASINH</code> <b>( F: r -- r' )</b><br>Inverse hyperbolic sine.<br><i>WAFER: Host function.</i><br>See: FSINH float-ext trig host-function
<code>FACOSH</code> <b>( F: r -- r' )</b><br>Inverse hyperbolic cosine. Domain: r ≥ 1.<br><i>WAFER: Host function.</i><br>See: FCOSH float-ext trig host-function
<code>FATANH</code> <b>( F: r -- r' )</b><br>Inverse hyperbolic tangent. Domain: |r| &lt; 1.<br><i>WAFER: Host function.</i><br>See: FTANH float-ext trig host-function
<code>F.</code> (f-dot) <b>( F: r -- )</b><br>Print float in free-format with trailing space. Precision controlled by SET-PRECISION (default 6).<br><code>3.14159e F. \ 3.14159</code><br><i>WAFER: Host function. Uses Rust formatting.</i><br>See: FE. FS. PRECISION float-ext io host-function
<code>FE.</code> <b>( F: r -- )</b><br>Print float in engineering notation (exponent is multiple of 3).<br><code>12345.0e FE. \ 12.345E3</code><br><i>WAFER: Host function.</i><br>See: F. FS. float-ext io host-function
<code>FS.</code> <b>( F: r -- )</b><br>Print float in scientific notation (one digit before decimal).<br><code>12345.0e FS. \ 1.2345E4</code><br><i>WAFER: Host function.</i><br>See: F. FE. float-ext io host-function
<code>PRECISION</code> <b>( -- u )</b><br>Current number of significant digits for F. FE. FS. output.<br><i>WAFER: Host function. Default 6.</i><br>See: SET-PRECISION float-ext io host-function
<code>SET-PRECISION</code> <b>( u -- )</b><br>Set number of significant digits for float output.<br><code>15 SET-PRECISION 3.14159265358979e F.</code><br><i>WAFER: Host function.</i><br>See: PRECISION float-ext io host-function
<code>REPRESENT</code> <b>( c-addr u -- n flag1 flag2 ) ( F: r -- )</b><br>Convert float to digit string. Low-level building block for custom float formatting. n = decimal exponent, flag1 = valid, flag2 = negative.<br><i>WAFER: Host function.</i><br>See: F. &lt;# float io host-function
<code>FVARIABLE</code> <b>( "&lt;spaces&gt;name" -- )</b><br>Create float variable (8 bytes). Access with F@ and F!.<br><code>FVARIABLE PI 3.14159265e PI F!</code><br><i>WAFER: Special token. Allocates 8 bytes in data space.</i><br>See: FCONSTANT FVALUE VARIABLE float defining special-token
<code>FCONSTANT</code> <b>( F: r -- ) ( "&lt;spaces&gt;name" -- )</b><br>Create float constant.<br><code>3.14159265358979e FCONSTANT PI</code><br><i>WAFER: Special token.</i><br>See: FVARIABLE FVALUE CONSTANT float defining special-token
<code>FVALUE</code> <b>( F: r -- ) ( "&lt;spaces&gt;name" -- )</b><br>Create float value. Change with <code>TO</code>.<br><code>0.0e FVALUE RESULT 3.14e TO RESULT</code><br><i>WAFER: Special token.</i><br>See: FCONSTANT FVARIABLE VALUE TO float-ext defining special-token
<code>FLITERAL</code> <b>Compilation: ( F: r -- )<br>Runtime: ( F: -- r )</b><br>Compile float literal. Immediate. Used for compile-time float computation.<br><code>: PI [ 355e 113e F/ ] FLITERAL ;</code><br><i>WAFER: Special token. Compiles IR PushF64(r).</i><br>See: LITERAL 2LITERAL float compilation special-token
<code>AT-XY</code> <b>( u1 u2 -- )</b><br>Set cursor position. u1 = column, u2 = row (0-indexed). Sends ANSI escape sequence.<br><code>0 0 AT-XY ." top-left"</code><br><i>WAFER: Host function (if implemented). Facility word set.</i> facility io host-function
<code>KEY?</code> <b>( -- flag )</b><br>True if a character is available from the input device (non-blocking check).<br><i>WAFER: Host function. Facility word set.</i><br>See: KEY EKEY? facility io host-function
<code>PAGE</code> <b>( -- )</b><br>Clear screen and move cursor to top-left. Implementation-specific escape sequence.<br><i>WAFER: Host function. Facility word set.</i><br>See: AT-XY CR facility io host-function
<code>EKEY</code> <b>( -- u )</b><br>Receive keyboard event (may include function keys, arrows). Extended key — wider than CHAR range.<br><i>WAFER: Host function. Facility EXT.</i><br>See: KEY EKEY? EKEY&gt;CHAR facility-ext io host-function
<code>EKEY&gt;CHAR</code> <b>( u -- u false | char true )</b><br>Convert extended key to character. Returns false if key has no character representation (function key).<br><i>WAFER: Host function. Facility EXT.</i><br>See: EKEY facility-ext io host-function
<code>EKEY?</code> <b>( -- flag )</b><br>Non-blocking check for extended key availability.<br><i>WAFER: Host function. Facility EXT.</i><br>See: KEY? EKEY facility-ext io host-function
<code>EMIT?</code> <b>( -- flag )</b><br>True if the output device is ready to accept a character.<br><i>WAFER: Host function. Facility EXT.</i><br>See: EMIT KEY? facility-ext io host-function
<code>MS</code> <b>( u -- )</b><br>Wait at least u milliseconds.<br><code>1000 MS \ pause 1 second</code><br><i>Facility EXT.</i> facility-ext io
<code>BEGIN-STRUCTURE</code> <b>( "&lt;spaces&gt;name" -- addr 0 )</b><br>Begin defining a structure type. Pushes initial offset 0.<br><code>BEGIN-STRUCTURE POINT FIELD: X FIELD: Y END-STRUCTURE</code><br><i>Facility EXT. Enables type-safe struct-like memory layouts.</i><br>See: END-STRUCTURE FIELD: +FIELD facility-ext defining
<code>END-STRUCTURE</code> <b>( addr n -- )</b><br>Complete structure definition. Stores total size as a constant.<br><code>POINT . \ prints structure size (8 for two cells)</code><br><i>Facility EXT.</i><br>See: BEGIN-STRUCTURE FIELD: facility-ext defining
<code>FIELD:</code> <b>( n1 "&lt;spaces&gt;name" -- n2 )</b><br>Create cell-width field. Adds CELL to offset. Created word: <code>( addr -- addr' )</code>.<br><code>BEGIN-STRUCTURE COLOR FIELD: R FIELD: G FIELD: B END-STRUCTURE</code><br><i>Facility EXT.</i><br>See: +FIELD CFIELD: facility-ext defining
<code>+FIELD</code> <b>( n1 n2 "&lt;spaces&gt;name" -- n3 )</b><br>Create field of arbitrary size n2 bytes. Most general field creator.<br><code>BEGIN-STRUCTURE FOO 8 +FIELD F1 END-STRUCTURE</code><br><i>Facility EXT.</i><br>See: FIELD: CFIELD: facility-ext defining
<code>CFIELD:</code> <b>( n1 "&lt;spaces&gt;name" -- n2 )</b><br>Create single-byte field. Like FIELD: but only 1 byte wide.<br><i>Facility EXT.</i><br>See: FIELD: +FIELD facility-ext defining
<code>{:</code> (open-brace-colon) <b>( -- )</b><br>Begin local variable declaration. Forth 2012 locals syntax. Items before | are initialized from stack; items after | are uninitialized.<br><code>: QUAD {: a b c x -- res :} a x * x * b x * + c + ;</code><br><i>WAFER: Special token. Locals word set. Names become local variables.</i><br>See: (LOCAL) locals defining special-token
<code>(LOCAL)</code> <b>( c-addr u -- )</b><br>Low-level local variable creation. Used by {: implementation. Rarely used directly.<br><i>Locals EXT. Implementation primitive for the locals subsystem.</i><br>See: {: locals-ext defining
<code>ALLOCATE</code> <b>( u -- a-addr ior )</b><br>Allocate u bytes of memory. Returns address and I/O result (0 = success). Memory is not in dictionary space.<br><code>100 ALLOCATE THROW \ a-addr on success</code><br><i>WAFER: Host function. Memory-Allocation word set. Uses Rust allocator.</i><br>See: FREE RESIZE memory memory-ops host-function
<code>FREE</code> <b>( a-addr -- ior )</b><br>Free previously allocated memory. ior 0 = success.<br><code>100 ALLOCATE THROW DUP ... FREE THROW</code><br><i>WAFER: Host function.</i><br>See: ALLOCATE RESIZE memory memory-ops host-function
<code>RESIZE</code> <b>( a-addr u -- a-addr' ior )</b><br>Resize allocated memory block. May move the block. Like C realloc.<br><i>WAFER: Host function.</i><br>See: ALLOCATE FREE memory memory-ops host-function
<code>.S</code> <b>( -- )</b><br>Non-destructive stack display. Shows all items on data stack without consuming them. Format: &lt;n&gt; x1 x2 ...<br><code>1 2 3 .S \ &lt;3&gt; 1 2 3</code><br><i>WAFER: Host function. Programming-Tools word set.</i><br>See: DEPTH . tools io host-function
<code>?</code> (question) <b>( a-addr -- )</b><br>Display contents of address. Short for <code>@ .</code><br><code>VARIABLE X 42 X ! X ? \ 42</code><br><i>Programming-Tools word set.</i><br>See: @ . tools io
<code>DUMP</code> <b>( addr u -- )</b><br>Display u bytes of memory starting at addr in hex dump format.<br><code>HERE 64 DUMP</code><br><i>Programming-Tools word set.</i><br>See: .S ? tools io
<code>SEE</code> <b>( "&lt;spaces&gt;name" -- )</b><br>Decompile/disassemble word. Shows source-level or implementation-level representation.<br><code>SEE DUP</code><br><i>Programming-Tools EXT.</i><br>See: WORDS ' tools-ext io
<code>WORDS</code> <b>( -- )</b><br>List all words in current search order. Implementation-defined format.<br><i>WAFER: Host function. Programming-Tools EXT.</i><br>See: SEE ORDER tools-ext io host-function
<code>BYE</code> <b>( -- )</b><br>Exit Forth system. Returns to operating system.<br><i>WAFER: Handled in CLI REPL. Programming-Tools EXT.</i><br>See: QUIT ABORT tools-ext compilation
<code>[IF]</code> <b>Compilation: ( flag -- )</b><br>Conditional compilation. If flag is false, skip to [ELSE] or [THEN]. Works at compile AND interpret time. Not nestable (unlike #ifdef).<br><code>TRUE [IF] : FOO ." yes" ; [THEN]</code><br><i>Programming-Tools EXT. Immediate.</i><br>See: [ELSE] [THEN] [DEFINED] tools-ext compilation
<code>[ELSE]</code> <b>Compilation: ( -- )</b><br>Alternative branch for [IF].<br><i>Programming-Tools EXT. Immediate.</i><br>See: [IF] [THEN] tools-ext compilation
<code>[THEN]</code> <b>Compilation: ( -- )</b><br>End conditional compilation block.<br><i>Programming-Tools EXT. Immediate.</i><br>See: [IF] [ELSE] tools-ext compilation
<code>[DEFINED]</code> <b>( "&lt;spaces&gt;name" -- flag )</b><br>True if word is defined. Used with [IF] for conditional compilation.<br><code>[DEFINED] FSIN [IF] .( Float math available ) [THEN]</code><br><i>Programming-Tools EXT. Immediate.</i><br>See: [UNDEFINED] [IF] tools-ext compilation
<code>[UNDEFINED]</code> <b>( "&lt;spaces&gt;name" -- flag )</b><br>True if word is NOT defined. Complement of [DEFINED].<br><code>[UNDEFINED] MY-WORD [IF] : MY-WORD ." default" ; [THEN]</code><br><i>Programming-Tools EXT. Immediate.</i><br>See: [DEFINED] [IF] tools-ext compilation
<code>AHEAD</code> <b>Compilation: ( -- orig )</b><br>Unconditional forward branch. Resolved by THEN. Used in complex control structures.<br><i>Programming-Tools EXT.</i><br>See: IF THEN tools-ext control-flow
<code>N&gt;R</code> <b>( i*n +n -- ) ( R: -- i*n +n )</b><br>Move n items plus count to return stack. Useful for saving/restoring variable-depth stack segments.<br><i>Programming-Tools EXT.</i><br>See: NR&gt; &gt;R tools-ext return-stack
<code>NR&gt;</code> <b>( -- i*n +n ) ( R: i*n +n -- )</b><br>Restore items from return stack (reverse of N&gt;R).<br><i>Programming-Tools EXT.</i><br>See: N&gt;R R&gt; tools-ext return-stack
<code>SYNONYM</code> <b>( "&lt;spaces&gt;newname" "&lt;spaces&gt;oldname" -- )</b><br>Create newname as an alias for oldname.<br><code>SYNONYM THIRD 2 PICK</code><br><i>Programming-Tools EXT.</i><br>See: DEFER tools-ext defining
<code>FORTH-WORDLIST</code> <b>( -- wid )</b><br>Return the wordlist ID of the FORTH vocabulary.<br><i>WAFER: Host function. Search-Order word set.</i><br>See: WORDLIST GET-ORDER search-order compilation host-function
<code>WORDLIST</code> <b>( -- wid )</b><br>Create a new empty wordlist. Returns its identifier.<br><i>WAFER: Host function. Search-Order word set.</i><br>See: FORTH-WORDLIST SET-ORDER search-order defining host-function
<code>GET-ORDER</code> <b>( -- wid<sub>n</sub>...wid<sub>1</sub> n )</b><br>Get the current search order as a stack of wordlist IDs and count.<br><i>WAFER: Host function.</i><br>See: SET-ORDER ORDER search-order compilation host-function
<code>SET-ORDER</code> <b>( wid<sub>n</sub>...wid<sub>1</sub> n -- )</b><br>Set the search order. n = -1 sets default (FORTH-WORDLIST only).<br><i>WAFER: Host function.</i><br>See: GET-ORDER ALSO ONLY search-order compilation host-function
<code>GET-CURRENT</code> <b>( -- wid )</b><br>Get the compilation wordlist (where new definitions go).<br><i>WAFER: Host function.</i><br>See: SET-CURRENT DEFINITIONS search-order compilation host-function
<code>SET-CURRENT</code> <b>( wid -- )</b><br>Set the compilation wordlist.<br><i>WAFER: Host function.</i><br>See: GET-CURRENT DEFINITIONS search-order compilation host-function
<code>SEARCH-WORDLIST</code> <b>( c-addr u wid -- 0 | xt 1 | xt -1 )</b><br>Search specific wordlist. Returns same as FIND but takes wordlist ID.<br><i>WAFER: Host function.</i><br>See: FIND FORTH-WORDLIST search-order parsing host-function
<code>DEFINITIONS</code> <b>( -- )</b><br>Set compilation wordlist to first in search order. Common after ALSO to direct definitions into a specific vocabulary.<br><i>WAFER: Host function.</i><br>See: SET-CURRENT GET-ORDER search-order compilation host-function
<code>ALSO</code> <b>( -- )</b><br>Duplicate first wordlist in search order. Typically followed by a vocabulary name to add it to search order.<br><code>ALSO MY-VOCAB</code><br><i>WAFER: Host function. Search-Order EXT.</i><br>See: ONLY PREVIOUS FORTH search-order-ext compilation host-function
<code>ONLY</code> <b>( -- )</b><br>Set search order to minimum (implementation-defined default). Usually just FORTH-WORDLIST.<br><i>WAFER: Host function. Search-Order EXT.</i><br>See: ALSO FORTH search-order-ext compilation host-function
<code>FORTH</code> <b>( -- )</b><br>Replace first wordlist in search order with FORTH-WORDLIST.<br><i>WAFER: Host function. Search-Order EXT.</i><br>See: ONLY ALSO search-order-ext compilation host-function
<code>PREVIOUS</code> <b>( -- )</b><br>Remove first wordlist from search order (reverse of ALSO).<br><i>WAFER: Host function. Search-Order EXT.</i><br>See: ALSO search-order-ext compilation host-function
<code>ORDER</code> <b>( -- )</b><br>Display current search order and compilation wordlist.<br><i>WAFER: Host function. Search-Order EXT.</i><br>See: GET-ORDER .S search-order-ext io host-function
<code>BIN</code> <b>( fam -- fam' )</b><br>Modify file access method for binary (no line-ending translation).<br><code>S" data.bin" R/O BIN OPEN-FILE THROW</code><br><i>File-Access word set. WAFER: Not implemented (requires WASI).</i><br>See: R/O R/W W/O file io not-implemented
<code>R/O</code> <b>( -- fam )</b><br>Read-only file access method.<br><i>File-Access. WAFER: Not implemented.</i><br>See: R/W W/O BIN file io not-implemented
<code>R/W</code> <b>( -- fam )</b><br>Read-write file access method.<br><i>File-Access. WAFER: Not implemented.</i><br>See: R/O W/O file io not-implemented
<code>W/O</code> <b>( -- fam )</b><br>Write-only file access method.<br><i>File-Access. WAFER: Not implemented.</i><br>See: R/O R/W file io not-implemented
<code>OPEN-FILE</code> <b>( c-addr u fam -- fileid ior )</b><br>Open existing file. Returns file ID and I/O result.<br><code>S" input.txt" R/O OPEN-FILE THROW</code><br><i>File-Access. WAFER: Not implemented.</i><br>See: CREATE-FILE CLOSE-FILE file io not-implemented
<code>CREATE-FILE</code> <b>( c-addr u fam -- fileid ior )</b><br>Create file (or truncate existing). Returns file ID.<br><i>File-Access. WAFER: Not implemented.</i><br>See: OPEN-FILE DELETE-FILE file io not-implemented
<code>CLOSE-FILE</code> <b>( fileid -- ior )</b><br>Close file.<br><i>File-Access. WAFER: Not implemented.</i><br>See: OPEN-FILE file io not-implemented
<code>READ-FILE</code> <b>( c-addr u1 fileid -- u2 ior )</b><br>Read up to u1 characters into buffer. u2 = actual chars read.<br><i>File-Access. WAFER: Not implemented.</i><br>See: WRITE-FILE READ-LINE file io not-implemented
<code>READ-LINE</code> <b>( c-addr u1 fileid -- u2 flag ior )</b><br>Read one line. flag = true if line read successfully (false at EOF).<br><i>File-Access. WAFER: Not implemented.</i><br>See: READ-FILE WRITE-LINE file io not-implemented
<code>WRITE-FILE</code> <b>( c-addr u fileid -- ior )</b><br>Write u characters to file.<br><i>File-Access. WAFER: Not implemented.</i><br>See: READ-FILE WRITE-LINE file io not-implemented
<code>WRITE-LINE</code> <b>( c-addr u fileid -- ior )</b><br>Write characters followed by line terminator.<br><i>File-Access. WAFER: Not implemented.</i><br>See: WRITE-FILE READ-LINE file io not-implemented
<code>DELETE-FILE</code> <b>( c-addr u -- ior )</b><br>Delete named file.<br><i>File-Access. WAFER: Not implemented.</i><br>See: CREATE-FILE file io not-implemented
<code>FILE-POSITION</code> <b>( fileid -- ud ior )</b><br>Get current file position as double-cell unsigned.<br><i>File-Access. WAFER: Not implemented.</i><br>See: REPOSITION-FILE FILE-SIZE file io not-implemented
<code>FILE-SIZE</code> <b>( fileid -- ud ior )</b><br>Get file size as double-cell unsigned.<br><i>File-Access. WAFER: Not implemented.</i><br>See: FILE-POSITION file io not-implemented
<code>REPOSITION-FILE</code> <b>( ud fileid -- ior )</b><br>Set file position (seek).<br><i>File-Access. WAFER: Not implemented.</i><br>See: FILE-POSITION file io not-implemented
<code>RESIZE-FILE</code> <b>( ud fileid -- ior )</b><br>Change file size. Truncates or extends.<br><i>File-Access. WAFER: Not implemented.</i><br>See: FILE-SIZE file io not-implemented
<code>FLUSH-FILE</code> <b>( fileid -- ior )</b><br>Flush file buffers to storage.<br><i>File-Access EXT. WAFER: Not implemented.</i><br>See: CLOSE-FILE file io not-implemented
<code>INCLUDE-FILE</code> <b>( i*x fileid -- j*x )</b><br>Interpret Forth source from file. Nests: included file can include others.<br><i>File-Access. WAFER: Not implemented.</i><br>See: INCLUDED REQUIRE file compilation not-implemented
<code>INCLUDED</code> <b>( i*x c-addr u -- j*x )</b><br>Open and interpret named file. Combines OPEN-FILE and INCLUDE-FILE.<br><code>S" library.fth" INCLUDED</code><br><i>File-Access. WAFER: Not implemented.</i><br>See: INCLUDE-FILE REQUIRE file compilation not-implemented
<code>REQUIRE</code> <b>( i*x "name" -- j*x )</b><br>Include file only if not already included. Prevents double-loading.<br><code>REQUIRE utils.fth</code><br><i>File-Access EXT. WAFER: Not implemented.</i><br>See: INCLUDED REQUIRED file-ext compilation not-implemented
<code>REQUIRED</code> <b>( i*x c-addr u -- j*x )</b><br>Stack-based version of REQUIRE.<br><i>File-Access EXT. WAFER: Not implemented.</i><br>See: REQUIRE INCLUDED file-ext compilation not-implemented
What is WAFER's compilation pipeline? <b>Forth source → Outer interpreter → Vec&lt;IrOp&gt; → Optimizer (6 passes) → WASM codegen (wasm-encoder) → wasmtime instantiation</b><br>Each colon definition becomes its own WASM module. The module is instantiated immediately, and its function is added to the shared function table.<br><code>: SQUARE DUP * ; \ creates entire WASM module</code><br><i>Key insight: no bytecode interpreter. Every word runs as native machine code via Cranelift JIT.</i> wafer architecture
What are WAFER's two kinds of primitives? <b>IR primitives</b> (~80 words): Defined as <code>Vec&lt;IrOp&gt;</code>, compiled to WASM like user words. Subject to all optimizations.<br><b>Host primitives</b> (~120+ words): Rust closures with direct memory access via wasmtime <code>Func::new</code>. Used for I/O, complex logic, float ops.<br><code>register_primitive("DUP", false, vec![IrOp::Dup])?; // IR</code><br><code>register_host_primitive(".", false, func)?; // Host</code><br><i>IR primitives are faster (inlined, optimized). Host functions are more flexible (full Rust power).</i> wafer architecture
What is WAFER's memory layout? <b>1 MiB initial (16 pages), 16 MiB max (256 pages)</b><br><code>0x0000 System vars (64B): STATE, BASE, &gt;IN, HERE, LATEST, HLD</code><br><code>0x0040 Input buffer (1024B)</code><br><code>0x0440 PAD (256B)</code><br><code>0x0540 Data stack (4096B) — grows ↓ from 0x1540</code><br><code>0x1540 Return stack (4096B) — grows ↓ from 0x2540</code><br><code>0x2540 Float stack (2048B) — grows ↓ from 0x2D40</code><br><code>0x2D40 Dictionary (variable) — grows ↑</code><br><code>0x10000 User data space — grows ↑</code><br><i>All stacks grow downward. Cell = 4 bytes. Float = 8 bytes (f64).</i> wafer architecture
How does WAFER implement word calling? <b>Subroutine threading via WASM function table + call_indirect.</b><br>Every word has a unique WordId = index into the shared function table. Calling a word compiles to:<br><code>(i32.const &lt;word_id&gt;) (call_indirect (type ...))</code><br>All modules share: linear memory, globals (DSP, RSP, FSP), and the function table.<br><i>No interpreter loop. No token threading. Direct WASM function dispatch.</i> wafer architecture
What is WAFER's dictionary structure? <b>Linked list in linear memory (Vec&lt;u8&gt; in Rust).</b><br><code>+0: Link (4B) — address of previous entry (0 = end)</code><br><code>+4: Flags (1B) — IMMEDIATE(0x80) | HIDDEN(0x40) | len(0x1F)</code><br><code>+5: Name (N bytes, uppercase)</code><br><code>+5+N: Padding to 4-byte alignment</code><br><code> : Code field (4B) — function table index (WordId)</code><br><code> : Parameter field — data for VARIABLE/CONSTANT/DOES&gt;</code><br><i>O(1) lookup via Rust HashMap index alongside the linked list.</i> wafer architecture
What are WAFER's 6 IR optimization passes? <b>1. Peephole</b> — pattern matching: OVER OVER → 2DUP, SWAP DROP → NIP, LIT(1) + → 1+<br><b>2. Constant folding</b> — evaluate pure operations at compile time: LIT(3) LIT(4) + → LIT(7)<br><b>3. Strength reduction</b> — replace expensive ops: LIT(2) * → LSHIFT(1), LIT(8) * → LSHIFT(3)<br><b>4. Dead code elimination</b> — remove code after unconditional EXIT<br><b>5. Tail call detection</b> — convert final Call before Exit to TailCall (reuses stack frame)<br><b>6. Inlining</b> — inline small words (≤8 IR ops) at call site<br><i>All passes configurable via WaferConfig. Default: all enabled.</i> wafer optimization
What is stack-to-local promotion? <b>WAFER codegen optimization that maps Forth's memory stack to WASM locals for straight-line code (no control flow).</b><br>Instead of DSP load/store for every stack operation, values live in WASM locals that Cranelift maps to registers.<br>Effect: <code>DUP *</code> goes from ~30 WASM instructions to ~4.<br><b>7x speedup</b> for arithmetic-heavy words.<br><i>Only applies to words without IF/DO/BEGIN. Phase 1 limitation.</i><br>Controlled by: <code>WaferConfig::codegen.stack_to_local_promotion</code> wafer optimization
What is WAFER's consolidation mode? <b>Recompile all user-defined words into a single WASM module.</b><br><code>wafer --consolidate program.fth</code><br><code>wafer --consolidate -o output.wasm program.fth</code><br>Benefits:<br>• Direct <code>call</code> instead of <code>call_indirect</code> (no table lookup)<br>• Cranelift can inline across word boundaries<br>• Single module = single compilation unit<br><i>Use after interactive development for deployment. Not for REPL.</i> wafer optimization
What is DSP caching in WAFER? <b>Cache the <code>dsp</code> global variable in a WASM local at function entry. Write back only before calls and at exit.</b><br>Without caching: every stack operation reads/writes the global DSP, which is slow.<br>With caching: a local variable tracks DSP, only syncing when needed.<br><b>~30-40% fewer global access instructions.</b><br><i>Enabled by default. Pairs well with stack-to-local promotion.</i> wafer optimization
What is batch compilation in WAFER? <b>At startup, all ~80 IR primitives are compiled into a single WASM module instead of individual modules.</b><br>Without batching: 80 separate wasmtime compilations (~7ms boot).<br>With batching: 1 compilation (~0.6ms boot).<br><b>12x faster startup.</b><br><i>Implementation: batch_mode flag during register_primitives(), flush with batch_compile_deferred().</i> wafer optimization
How does WAFER handle the IrOp enum? <b>~50 opcodes representing the intermediate representation between Forth and WASM.</b><br>Categories:<br>• Literals: <code>PushI32(i32)</code>, <code>PushI64(i64)</code>, <code>PushF64(f64)</code><br>• Stack: <code>Dup</code>, <code>Drop</code>, <code>Swap</code>, <code>Over</code>, <code>Rot</code>, <code>Nip</code>, <code>Tuck</code><br>• Arithmetic: <code>Add</code>, <code>Sub</code>, <code>Mul</code>, <code>DivMod</code>, <code>Negate</code>, <code>Abs</code><br>• Control: <code>If{then,else}</code>, <code>DoLoop{body,is_plus}</code>, <code>BeginUntil{body}</code><br>• Calls: <code>Call(WordId)</code>, <code>TailCall(WordId)</code>, <code>Execute</code>, <code>Exit</code><br><i>Nested control flow uses recursive Vec&lt;IrOp&gt; (tree structure, not flat).</i> wafer architecture
How does WAFER handle DOES&gt;? <b>Two-phase mechanism:</b><br>1. At define-time: <code>DOES&gt;</code> compiles the runtime body and saves its xt.<br>2. <code>_DOES_PATCH_</code> (host function) patches the most recently CREATE'd word's code to call the DOES&gt; body with the data address on stack.<br><code>: ARRAY CREATE CELLS ALLOT DOES&gt; SWAP CELLS + ;</code><br><i>WAFER supports double-DOES&gt; (redefining runtime behavior). The patched word pushes its parameter field address, then calls the DOES&gt; code.</i> wafer architecture
How are float literals compiled in WAFER? <b>Float literals (e.g., <code>3.14e</code>) compile to <code>IrOp::PushF64(f64)</code>.</b><br>In interpret mode: the float is pushed directly to the float stack.<br>In compile mode: FLITERAL is automatically applied.<br>Syntax: any number containing <code>.</code> or <code>E</code>/<code>e</code> with no base prefix is parsed as float when BASE=10.<br><code>1.5e \ 1.5</code><br><code>1.5e2 \ 150.0</code><br><code>-3.14e0 \ -3.14</code><br><i>Note: Floats only parsed when BASE is DECIMAL. In HEX, "1.5e2" would be parsed as an integer.</i> wafer architecture
What is WAFER's WaferConfig? <b>Unified configuration for all optimization passes and codegen options.</b><br><code>WaferConfig {</code><br><code> opt: OptConfig { peephole, constant_fold, tail_call, strength_reduce, dce, inline }</code><br><code> codegen: CodegenOpts { stack_to_local_promotion }</code><br><code>}</code><br>Presets: <code>WaferConfig::all()</code> (all on, default), <code>WaferConfig::none()</code> (all off, for debugging).<br><code>let vm = ForthVM::new_with_config(WaferConfig::none())?;</code> wafer architecture
How does WAFER handle CATCH/THROW? <b>Nested exception frames with stack snapshot/restore.</b><br>CATCH: saves DSP, RSP, FSP. If the xt THROWs, stacks are restored to saved state, throw code is pushed.<br>THROW: if code ≠ 0, unwinds to nearest CATCH frame. If no CATCH, behaves like ABORT.<br>Standard codes: -1 (ABORT), -2 (ABORT"), -4 (stack underflow), -13 (undefined word), -14 (compile-only).<br><code>['] RISKY CATCH ?DUP IF ." Error: " . THEN</code><br><i>WAFER uses Rust-side exception handling — the throw code is returned through the host function boundary.</i> wafer architecture
What is the CONSOLIDATE word? <b>WAFER-specific word (not in Forth 2012).</b> Recompiles all compiled definitions into a single WASM module with direct function calls. Equivalent to <code>--consolidate</code> CLI flag but callable from Forth code.<br><code>: FOO ... ; : BAR FOO FOO ; CONSOLIDATE</code><br><i>After CONSOLIDATE, all existing words use direct calls. New words still use call_indirect until next CONSOLIDATE.</i> wafer architecture wafer-specific
What Forth 2012 word sets does WAFER implement? <b>12 of 14 at 100% compliance:</b><br>Core, Core-Ext, Double-Number, Exception, Facility, Floating-Point (+ Ext), Locals, Memory-Allocation, Programming-Tools, Search-Order, String<br><b>Not implemented (2):</b><br>File-Access (requires WASI), Extended-Character (Unicode)<br><i>392 tests: 380 unit + 1 benchmark + 11 compliance test modules.</i><br><code>cargo test -p wafer-core --test compliance</code> wafer architecture
What is the difference between FM/MOD and SM/REM? <b>FM/MOD</b>: Floored division. Quotient rounds toward −∞. Remainder has same sign as <i>divisor</i>.<br><b>SM/REM</b>: Symmetric division. Quotient truncates toward 0. Remainder has same sign as <i>dividend</i>. (C-like)<br><code>-7. 2 FM/MOD . . \ -4 1</code><br><code>-7. 2 SM/REM . . \ -3 -1</code><br><i>FM/MOD is preferred for modular arithmetic (always non-negative remainder with positive divisor). Forth 2012 leaves / and MOD implementation-defined. WAFER uses symmetric (SM/REM).</i> patterns arithmetic
CREATE DOES&gt; pattern <b>The fundamental pattern for user-defined defining words in Forth.</b><br>CREATE allocates data. DOES&gt; specifies runtime behavior. The child word pushes its data address, then executes the DOES&gt; body.<br><code>: ARRAY ( n -- ) CREATE CELLS ALLOT DOES&gt; ( n -- addr ) SWAP CELLS + ;</code><br><code>10 ARRAY DATA 42 3 DATA ! 3 DATA @ . \ 42</code><br>Other examples: tables, structs, state machines, OOP vtables.<br><i>Mastering CREATE DOES&gt; is the bridge from Forth user to Forth metaprogrammer.</i> patterns defining
Pictured numeric output pattern <b>&lt;# ... #&gt; — right-to-left digit conversion.</b><br>Build output from least-significant digit. Use # for each digit, #S for remaining, HOLD for custom chars, SIGN for negative.<br><code>: DOLLARS ( n -- c-addr u )</code><br><code> S&gt;D TUCK DABS &lt;# # # [CHAR] . HOLD #S ROT SIGN [CHAR] $ HOLD #&gt; ;</code><br><code>-1234 DOLLARS TYPE \ $-12.34</code><br><i>Always start with &lt;#, end with #&gt;. The double number is consumed by # and #S.</i> patterns pictured-numeric
POSTPONE idiom for compile-time words <b>POSTPONE defers compilation of a word to when the defining word's code runs.</b><br>For building syntax extensions and compile-time macros.<br><code>: MY-IF POSTPONE IF ; IMMEDIATE</code><br><code>: [+] POSTPONE + ; IMMEDIATE \ compiles + wherever [+] appears</code><br>For immediate words: POSTPONE compiles their behavior.<br>For non-immediate: POSTPONE compiles code that <i>will compile</i> them.<br><i>Replaces obsolescent [COMPILE] and COMPILE. The single tool for all compile-time word building.</i> patterns compilation
VALUE/TO vs VARIABLE/@/! <b>VALUE</b>: cleaner syntax for simple storage. Access by name, update with TO.<br><b>VARIABLE</b>: gives address, needed for +!, pointer passing, arrays.<br><code>42 VALUE X X . 99 TO X \ clean, reads like English</code><br><code>VARIABLE Y 42 Y ! Y @ . 5 Y +! \ address-based, more flexible</code><br><i>Rule of thumb: use VALUE unless you need the address. Use VARIABLE for data structures, pointer math, or +!.</i> patterns defining
DEFER/IS pattern for late binding <b>DEFER creates a word with swappable behavior. IS changes what it does.</b><br><code>DEFER GREET</code><br><code>: HELLO ." Hello!" ; ' HELLO IS GREET</code><br><code>: HI ." Hi!" ; ' HI IS GREET</code><br>Use cases: forward references, pluggable behavior, mock/stub in tests, state machines.<br><i>ACTION-OF retrieves current xt. DEFER@ and DEFER! are the low-level equivalents.</i> patterns defining
Double-number literal syntax <b>A trailing dot makes a number double-cell.</b><br><code>42. \ pushes double-cell (42 0) — note: this is NOT a float!</code><br><code>-1. \ pushes (-1 -1) — sign-extended</code><br><code>1000000. D. \ prints 1000000</code><br><i>Common confusion: <code>3.14</code> is NOT a float literal in standard Forth without the E. It's <code>314</code> as a double (the dot is inside the number). Use <code>3.14e</code> or <code>3.14E0</code> for floats.</i> patterns conversion
CATCH/THROW error handling pattern <b>Structured exception handling. CATCH wraps an xt; THROW unwinds to it.</b><br><code>: SAFE ['] RISKY CATCH</code><br><code> CASE</code><br><code> 0 OF ." ok" ENDOF</code><br><code> -1 OF ." aborted" ENDOF</code><br><code> ." error: " DUP .</code><br><code> ENDCASE ;</code><br><i>THROW 0 is a no-op. Negative codes are standard (-1 ABORT, -2 ABORT", etc.). Positive codes are application-defined.</i> patterns control-flow
:NONAME for anonymous execution <b>Create unnamed word, get its xt. Perfect for callbacks and dispatch tables.</b><br><code>:NONAME DUP * ; CONSTANT SQUARE-XT</code><br><code>5 SQUARE-XT EXECUTE . \ 25</code><br><code>\ Dispatch table:</code><br><code>CREATE OPS :NONAME + ; , :NONAME - ; , :NONAME * ; ,</code><br><code>: DISPATCH CELLS OPS + @ EXECUTE ;</code><br><i>No dictionary entry is created. The xt is only accessible through the value on the stack at definition time.</i> patterns defining
MARKER for interactive development <b>Create a restore point. Execute the marker to forget everything defined after it.</b><br><code>MARKER CLEAN</code><br><code>: FOO ." v1" ; : BAR FOO ;</code><br><code>CLEAN \ FOO and BAR are forgotten</code><br><code>: FOO ." v2" ; \ redefine from scratch</code><br><i>Essential for REPL-driven development: mark, experiment, restore, repeat. Like an undo point for the dictionary.</i> patterns defining
Loop idiom: 0 DO ... LOOP <b>Standard counted loop. Index available via I (or J for outer loop).</b><br><code>: STARS 0 ?DO [CHAR] * EMIT LOOP ;</code><br><code>: TABLE 4 0 DO 4 0 DO I J * 4 .R LOOP CR LOOP ;</code><br><i>Use ?DO (not DO) when count might be 0. DO executes at least once even if limit=start. UNLOOP before EXIT in a loop. LEAVE exits immediately.</i> patterns control-flow
EVALUATE for dynamic compilation <b>Interpret a string as Forth source at runtime. Extremely powerful; use with care.</b><br><code>: RUN S" 2 3 + ." EVALUATE ; \ prints 5</code><br><code>\ Dynamic word creation:</code><br><code>: MAKE-CONST ( n "name" -- )</code><br><code> &gt;R S" CONSTANT " R&gt; ... ; \ simplified</code><br><i>SOURCE-ID returns -1 during EVALUATE. &gt;IN and SOURCE reflect the evaluated string. Nesting is allowed.</i> patterns compilation