summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--readme.md77
-rw-r--r--sanctuary.fs16
-rw-r--r--sanctuary.s51
3 files changed, 105 insertions, 39 deletions
diff --git a/readme.md b/readme.md
index 4613d21..b3eefce 100644
--- a/readme.md
+++ b/readme.md
@@ -10,6 +10,7 @@ sanctuary is a 64-bit subroutine threaded forth for amd64 linux systems.
- `u`: unsigned integer
- `?`: boolean flag
- `xt`: execution token
+- `ht`: header token
- `""`: string in input buffer
- `|`: 'or'
@@ -31,15 +32,12 @@ have a closing bracket: ).
### `(0handler) ( -- )`
the very early error handler, which simply quits the program.
-### `(execute) ( a -- )`
-call the function at the address.
-
-### `(header) ( a u -- xt )`
+### `(header) ( a u -- ht )`
create a dictionary header for a word named the provided string.
this word does not set the code field.
-this word returns an incompleted xt and does not update latest.
+this word does not update latest.
-### `* ( u1 u2 -- u)`
+### `* ( u1 u2 -- u )`
multiply u1 and u2.
### `*/mod ( n1 n2 n3 -- n4 n5 )`
@@ -98,22 +96,34 @@ return true if n1 is less than or equal to n2.
### `<> ( n1 n2 -- ? )`
return true if n1 and n2 are not equal.
+### `<mark ( -- a )`
+mark the destination of a backward branch.
+
+### `<resolve ( a -- )`
+mark the source of a backward branch.
+
### `> ( n1 n2 -- ? )`
return true if n1 is greater than n2.
### `>= ( n1 n2 -- ? )`
return true if n1 is greater than or equal to n2.
-### `>body ( xt -- a )`
-yield the code field of xt.
+### `>body ( ht -- xt )`
+yield the code field of header token.
### `>in ( -- a )`
variable containing the index of the first unparsed character
in the input buffer.
+### `>mark ( -- a )`
+mark the source of a forward branch.
+
### `>r ( u -- ) ( R: -- u )`
move a value from the working stack to the return stack.
+### `>resolve ( a -- )`
+mark the destination of a forward branch.
+
### `?branch ( -- )`
compile into user memory an incomplete conditional branch.
if the value on the stack is zero the branch is taken.
@@ -153,6 +163,12 @@ duplicate the two topmost values on the stack.
call the error handler
(the address of which is in the variable `handler`)
+### `again ( -- ) IMMEDIATE`
+complete an infinite loop began by the word `begin`.
+
+### `allot ( u -- )`
+reserve u bytes of user memory.
+
### `and ( u1 u2 -- u )`
perform bitwise AND on u1 and u2.
@@ -160,6 +176,10 @@ perform bitwise AND on u1 and u2.
a variable containing the current numeric input/output base.
by default this is 10.
+### `begin ( -- ) IMMEDIATE`
+mark the beginning of a begin-again, begin-until,
+or begin-while-repeat loop.
+
### `binary ( -- )`
set current base to binary.
@@ -196,6 +216,9 @@ bytes are copied in high memory to low memory order.
### `d, ( n -- )`
write a 32 bit value to user memory and increment the user memory pointer.
+### `d! ( u a -- )`
+store the 32 bit value u into the memory address a.
+
### `decimal ( -- )`
set current base to decimal.
@@ -214,6 +237,11 @@ remove the value at the top of the stack.
### `dup ( u -- u u )`
duplicate the value at the top of the stack.
+### `else ( -- ) IMMEDIATE`
+update the current if statement to branch here
+when the flag is false,
+and skip to `then` if the corresponding `if` was true.
+
### `executable ( a u -- )`
marks the u bytes starting at address a as executable.
this is used primarily to mark the program break,
@@ -222,11 +250,11 @@ which is used as the user memory space.
### `execute ( xt -- )`
call the word xt.
-### `find ( a u -- a u 0 | xt -1 )`
+### `find ( a u -- a u 0 | a -1 )`
look in the dictionary for the word a (of u characters).
a zero is returned along with the original given string
if no word was found. if a word was found,
-its xt is returned along with the true flag.
+its link field address is returned along with the true flag.
### `grow ( u -- )`
grows, and marks as executable, the user memory space by u bytes.
@@ -240,11 +268,15 @@ yields the address of the first available byte in user memory.
### `hex ( -- )`
set current base to hexadecimal.
+### `if ( ? -- ) IMMEDIATE`
+if the flag is true, execute the following if statement,
+terminated by `else` or `then`.
+
### `immediate ( -- )`
mark the most recently defined word as immediate.
-### `immediate? ( xt -- ? )`
-true if xt is marked immediate, false otherwise.
+### `immediate? ( ht -- ? )`
+true if ht is marked immediate, false otherwise.
### `interpret ( -- )`
interprets the contents of the terminal input buffer
@@ -265,9 +297,15 @@ convert given string into a number along with a flag.
if parsing a number fails then 0 (false) is returned
and no number is provided.
+### `octal ( -- )`
+set current base to octal.
+
### `or ( u1 u2 -- u )`
perform bitwise OR on u1 and u2.
+### `over ( u1 u2 -- u1 u2 u1 )`
+copy the second-highest value on the stack and move it to the top of the stack.
+
### `parse ( "name<c>" c -- a u )`
parse one word from the input buffer,
separated by a newline or the character c,
@@ -285,6 +323,9 @@ move a value from the return stack to the working stack.
### `rdrop ( R: u -- )`
remove the value at the top of the return stack.
+### `repeat ( -- ) IMMEDIATE`
+in a begin-while-repeat loop, loop back to the condition.
+
### `rot ( u1 u2 u3 -- u2 u3 u1 )`
rotate the top three values on the stack so that the third highest value is moved to the top.
@@ -318,17 +359,21 @@ perform the syscall with the id in `rax`,
taking three parameters placed in `rdi`, `rsi` and `rdx`,
and push the value of the `rax` register to the stack.
+### `then ( -- ) IMMEDIATE`
+conclude an if statement.
+
### `tib ( -- a )`
a variable containing the address of the current input buffer.
### `type ( a u -- )`
write u characters at a to output.
-### `octal ( -- )`
-set current base to octal.
+### `until ( ? -- ) IMMEDIATE`
+if the given flag is true, loop back to `begin`.
-### `over ( u1 u2 -- u1 u2 u1 )`
-copy the second-highest value on the stack and move it to the top of the stack.
+### `while ( ? -- ) IMMEDIATE`
+if given flag is true, continue the current begin-while-repeat loop,
+otherwise branch to after.
### `xor ( u1 u2 -- u )`
perform bitwise XOR on u1 and u2.
diff --git a/sanctuary.fs b/sanctuary.fs
index 9ed0e61..4fe9f8c 100644
--- a/sanctuary.fs
+++ b/sanctuary.fs
@@ -5,4 +5,20 @@
: octal 8 base ! ;
: decimal 10 base ! ;
: hex 16 base ! ;
+
+: <mark here ;
+: <resolve here 4 + - d, ;
+: >mark here 0 d, ;
+: >resolve dup here swap - 4 - swap d! ;
+
+: begin <mark ; immediate
+: again branch <resolve ; immediate
+: until ?branch <resolve ; immediate
+: if ?branch >mark ; immediate ( I: -- a )
+: else branch >mark swap >resolve ; immediate
+: then >resolve ; immediate
+: while ?branch >mark ; immediate
+: repeat branch swap <resolve >resolve ; immediate
+
+: allot here swap dp +! ;
bye
diff --git a/sanctuary.s b/sanctuary.s
index 53749cc..7c47326 100644
--- a/sanctuary.s
+++ b/sanctuary.s
@@ -513,16 +513,11 @@ defcode "char", char, 0
pspush r11
ret
-defcode "(execute)", do_execute, 0
+defcode "execute", execute, 0
pspop r11
call r11
ret
-defcode "execute", execute, 0
- call to_body
- call do_execute
- ret
-
; number {{{
defcode "number", number, 0 ; ( c-addr u -- ?n flag )
pspop r11 ; u
@@ -720,6 +715,12 @@ defcode "!", store, 0
mov qword [r11], r12
ret
+defcode "d!", dstore, 0
+ pspop r11
+ pspop r12
+ mov dword [r11], r12d
+ ret
+
defcode "c!", cstore, 0
pspop r11
pspop r12
@@ -740,26 +741,26 @@ defcode "-!", minusstore, 0
defcode ",", comma, 0
pspop r11
- mov r12, [here]
+ mov r12, [dp]
mov qword [r12], r11
add r12, 8
- mov qword [here], r12
+ mov qword [dp], r12
ret
defcode "d,", d_comma, 0
pspop r11
- mov r12, [here]
+ mov r12, [dp]
mov dword [r12], r11d
- inc r12
- mov qword [here], r12
+ add r12, 4
+ mov qword [dp], r12
ret
defcode "c,", c_comma, 0
pspop r11
- mov r12, [here]
+ mov r12, [dp]
mov byte [r12], r11b
inc r12
- mov qword [here], r12
+ mov qword [dp], r12
ret
defcode "cmove", _cmove, 0
@@ -825,21 +826,21 @@ defcode "/mod", divmod, 0
defcode "and", _and, 0
pspop r11
- and [r14], r11
+ and [r15], r11
ret
defcode "or", _or, 0
pspop r11
- or [r14], r11
+ or [r15], r11
ret
defcode "xor", _xor, 0
pspop r11
- xor [r14], r11
+ xor [r15], r11
ret
defcode "invert", invert, 0
- not qword [r14]
+ not qword [r15]
ret
defcode "*/mod", starslashmod, 0
@@ -970,20 +971,24 @@ defcode "0>=", zero_greatereq, 0
; }}}
defcode "branch", branch, 0
- mov r12, [here]
+ mov r12, [dp]
mov byte [r12], 0xe9
inc r12
- mov qword [here], r12
+ mov qword [dp], r12
ret
+; 4d 8b 1f mov r11, qword [r15]
+; 4d 8d 7f 08 lea r15, [r15+8]
+; 4d 85 db test r11, r11
+; 0f 84 [REL] je [REL]
defcode "?branch", q_branch, 0
- mov r12, [here]
- mov r11, 0x4d08768d4d1e8b4d ; pspop r11, first bit of test r11, r11
+ mov r12, [dp]
+ mov r11, 0x4d087f8d4d1f8b4d
mov qword [r12], r11
add r12, 8
- mov dword [r12], 0x840fdb85 ; rest of ^, je
+ mov dword [r12], 0x840fdb85
add r12, 4
- mov qword [here], r12
+ mov qword [dp], r12
ret
; error handling {{{