Add Forth 2012 + WAFER Anki flashcard deck

This commit is contained in:
2026-04-02 14:11:26 +02:00
parent 22373d89af
commit 321903831d
+389
View File
@@ -0,0 +1,389 @@
#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