summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkitty <nepeta@canaglie.net>2026-03-23 00:42:21 +1100
committerkitty <nepeta@canaglie.net>2026-03-23 00:42:21 +1100
commitccc5e9514111ecec8c045a9b78cb2052da090c95 (patch)
tree6769e4902049b6e978703994a5ce277ed3be3721
parent8f76c163e577393bda45d9c98745bb4670f27f10 (diff)
boilerplate for create does>
-rw-r--r--readme.md48
-rw-r--r--sanctuary.fs16
-rw-r--r--sanctuary.s16
3 files changed, 78 insertions, 2 deletions
diff --git a/readme.md b/readme.md
index b3eefce..c9e5323 100644
--- a/readme.md
+++ b/readme.md
@@ -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