diff options
| author | kitty <nepeta@canaglie.net> | 2026-03-23 00:42:21 +1100 |
|---|---|---|
| committer | kitty <nepeta@canaglie.net> | 2026-03-23 00:42:21 +1100 |
| commit | ccc5e9514111ecec8c045a9b78cb2052da090c95 (patch) | |
| tree | 6769e4902049b6e978703994a5ce277ed3be3721 | |
| parent | 8f76c163e577393bda45d9c98745bb4670f27f10 (diff) | |
boilerplate for create does>
| -rw-r--r-- | readme.md | 48 | ||||
| -rw-r--r-- | sanctuary.fs | 16 | ||||
| -rw-r--r-- | sanctuary.s | 16 |
3 files changed, 78 insertions, 2 deletions
@@ -24,6 +24,14 @@ store the 64 bit value u into the memory address a. ### `#tib ( -- a )` variable containing the amount of characters in the input buffer. +### `' ( "word" -- xt )` +read a word from the input buffer, +push to the stack its execution token. + +### `'h ( "word" -- ht )` +read a word from the input buffer, +push to the stack its header token. + ### `( ( -- ) IMMEDIATE` start a comment which lasts until the next closed bracket. if the unclosed bracket in the description above bothers you, @@ -32,6 +40,19 @@ have a closing bracket: ). ### `(0handler) ( -- )` the very early error handler, which simply quits the program. +### `(create) ( -- )` +the default behaviour of a word made by `create`, +which simply pushes the address following the definition to the stack. +this messes with the return stack and is not meant to be called +outside of its specific context. + +### `(does>) ( -- )` +run non-default behaviour of a `create`d word. +pushes the data location onto the stack and calls the word +immediately following the `(does>)` call. +this messes with the return stack and is not meant to be called +outside of its specific context. + ### `(header) ( a u -- ht )` create a dictionary header for a word named the provided string. this word does not set the code field. @@ -42,7 +63,7 @@ multiply u1 and u2. ### `*/mod ( n1 n2 n3 -- n4 n5 )` multiply n1 and n2, divide the result by n3. -remainder is in n3, result is in n4 +remainder is in n4, result is in n5. ### `+ ( u1 u2 -- u )` add u2 to u1. @@ -69,6 +90,13 @@ divide u1 by u2. result is in u4, remainder is in u3. ### `[ ( -- ) IMMEDIATE` set the system to interpret mode. +### `['] ( "word" -- ) IMMEDIATE COMPILE-ONLY` +read a word from the input buffer, +compile into the current definition a stack push of the xt of the word. + +### `[compile] ( "word" -- ) IMMEDIATE COMPILE-ONLY` +compile into the current definition a call to a normally immediate word. + ### `] ( -- ) IMMEDIATE` set the system to compiling mode. @@ -129,6 +157,15 @@ compile into user memory an incomplete conditional branch. if the value on the stack is zero the branch is taken. a 32 bit branch offset must be written immediately after. +### `?dup ( n -- 0 | n n )` +if n is not zero, perform `dup`. + +### `?find ( a u -- ht )` +look in the dictionary for the word a (of u characters). +if a word was found, +its link field address is returned along with the true flag. +if no word was found or the string is of length zero, abort. + ### `0= ( n -- ? )` return true if n is equal to zero. @@ -213,6 +250,9 @@ bytes are copied in low memory to high memory order. copy u bytes of memory from a1 to a2. bytes are copied in high memory to low memory order. +### `compile, ( xt -- )` +compile a call to xt into user memory. + ### `d, ( n -- )` write a 32 bit value to user memory and increment the user memory pointer. @@ -317,6 +357,12 @@ and return as a string. tabs (ascii 0x09), newlines (ascii 0x10), and spaces (ascii 0x20) are considered whitespace. +### `postpone ( "name" -- ) IMMEDIATE COMPILE-ONLY` +compile the execution behaviour of a word into the current definition. +if the word is immediate, that will execute the word at runtime +(like `[compile]`). +if the word is not immediate, this will compile code that compiles that word. + ### `r> ( -- u ) ( R: u -- )` move a value from the return stack to the working stack. diff --git a/sanctuary.fs b/sanctuary.fs index 4fe9f8c..b0867d1 100644 --- a/sanctuary.fs +++ b/sanctuary.fs @@ -14,11 +14,25 @@ : begin <mark ; immediate : again branch <resolve ; immediate : until ?branch <resolve ; immediate -: if ?branch >mark ; immediate ( I: -- a ) +: if ?branch >mark ; immediate : else branch >mark swap >resolve ; immediate : then >resolve ; immediate : while ?branch >mark ; immediate : repeat branch swap <resolve >resolve ; immediate +: ?dup dup 0<> if dup then ; + : allot here swap dp +! ; + +: ?find ?dup if find 0= if 2drop abort then else abort then ; +: 'h parse-name ?find ; +: ' 'h >body ; +: [compile] ' ( word ) compile, ; immediate +: ['] ' ( word ) [compile] literal ; immediate +: postpone 'h ( word ) dup immediate? if >body compile, + else >body [compile] literal ['] compile, compile, then ; immediate + +\ my plan is that (CREATE) is followed by a dummy zero cell +\ which (DOES>) uses. waste of 8 bytes but it's simpler +: create parse-name (header) latest ! ['] (create) compile, 0 , ; bye diff --git a/sanctuary.s b/sanctuary.s index 7c47326..8fe545d 100644 --- a/sanctuary.s +++ b/sanctuary.s @@ -1006,6 +1006,22 @@ defcode "abort", abort, 0 ret ; }}} +; these words are called from `create`d words, +; (create) expects a dummy value (used by (does>)) to skip past. +defcode "(create)", docreate, 0 + pop r11 + add r11, 8 ; skip dummy value unused by (create) + pspush r11 + ret + +defcode "(does>)", dodoes, 0 + pop r11 + mov r12, [r11] + add r11, 8 + pspush r11 + jmp r12 + ; no RET + ; TEMPORARY WONKY DEBUGGING FUNCTIONS {{{ ; .s {{{ defcode ".s", dots, 0 |
