1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-23 23:48:05 +11:00

forth: Forth-ify RECURSE

This comes with RS-modifying words. Also, this commit separates ";" from "EXIT",
allowing EXIT to be used in definitions (was needed for RECURSE).
This commit is contained in:
Virgil Dupras 2020-03-13 16:40:55 -04:00
parent c3838714d5
commit d60ea4cb30
6 changed files with 115 additions and 36 deletions

View File

@ -14,3 +14,4 @@
: = CMP NOT ; : = CMP NOT ;
: < CMP 0 1 - = ; : < CMP 0 1 - = ;
: > CMP 1 = ; : > CMP 1 = ;
: RECURSE R> R> 2 - >R >R EXIT ;

View File

@ -18,7 +18,7 @@
; IP, but we also take care of increasing it my 2 before jumping ; IP, but we also take care of increasing it my 2 before jumping
next: next:
; Before we continue: are stacks within bounds? ; Before we continue: are stacks within bounds?
call chkPS call chkPSRS
ld de, (IP) ld de, (IP)
ld h, d ld h, d
ld l, e ld l, e
@ -115,9 +115,10 @@ LIT:
; Pop previous IP from Return stack and execute it. ; Pop previous IP from Return stack and execute it.
; ( R:I -- ) ; ( R:I -- )
.db ";" .db "EXIT"
.fill 7 .fill 3
.dw 0 .dw 0
.db 0
EXIT: EXIT:
.dw nativeWord .dw nativeWord
call popRS call popRS
@ -214,9 +215,18 @@ executeCodeLink:
; IY points to PFA ; IY points to PFA
jp (hl) ; go! jp (hl) ; go!
.db ";"
.fill 6
.dw EXECUTE
.db 0
ENDDEF:
.dw nativeWord
jp EXIT+2
.db ":" .db ":"
.fill 6 .fill 6
.dw EXECUTE .dw ENDDEF
.db 0 .db 0
DEFINE: DEFINE:
.dw nativeWord .dw nativeWord
@ -232,7 +242,10 @@ DEFINE:
ld (HERE), de ; update HERE ld (HERE), de ; update HERE
ld hl, (IP) ld hl, (IP)
.loop: .loop:
call HLPointsEXIT push de ; --> lvl 1
ld de, ENDDEF
call HLPointsDE
pop de ; <-- lvl 1
jr z, .loopend jr z, .loopend
call compSkip call compSkip
jr .loop jr .loop
@ -358,9 +371,20 @@ KEY:
push hl push hl
jp next jp next
.db "WORD"
.fill 3
.dw KEY
.db 0
WORD:
.dw nativeWord
call readword
jp nz, abort
push hl
jp next
.db "CREATE" .db "CREATE"
.fill 1 .fill 1
.dw KEY .dw WORD
.db 0 .db 0
CREATE: CREATE:
.dw nativeWord .dw nativeWord
@ -398,7 +422,7 @@ DOT:
pop de pop de
; We check PS explicitly because it doesn't look nice to spew gibberish ; We check PS explicitly because it doesn't look nice to spew gibberish
; before aborting the stack underflow. ; before aborting the stack underflow.
call chkPS call chkPSRS
call pad call pad
call fmtDecimalS call fmtDecimalS
call printstr call printstr
@ -454,7 +478,6 @@ CFETCH:
push hl push hl
jp next jp next
; ( -- a )
.db "LIT@" .db "LIT@"
.fill 3 .fill 3
.dw CFETCH .dw CFETCH
@ -554,10 +577,63 @@ OVER2:
push bc ; B push bc ; B
jp next jp next
.db ">R"
.fill 5
.dw OVER2
.db 0
P2R:
.dw nativeWord
pop hl
call pushRS
jp next
.db "R>"
.fill 5
.dw P2R
.db 0
R2P:
.dw nativeWord
call popRS
push hl
jp next
.db "I"
.fill 6
.dw R2P
.db 0
I:
.dw nativeWord
ld l, (ix)
ld h, (ix+1)
push hl
jp next
.db "I'"
.fill 5
.dw I
.db 0
IPRIME:
.dw nativeWord
ld l, (ix-2)
ld h, (ix-1)
push hl
jp next
.db "J"
.fill 6
.dw IPRIME
.db 0
J:
.dw nativeWord
ld l, (ix-4)
ld h, (ix-3)
push hl
jp next
; ( a b -- c ) A + B ; ( a b -- c ) A + B
.db "+" .db "+"
.fill 6 .fill 6
.dw OVER2 .dw J
.db 0 .db 0
PLUS: PLUS:
.dw nativeWord .dw nativeWord
@ -670,17 +746,6 @@ FBRC:
ld (IP), hl ld (IP), hl
jp next jp next
.db "RECURSE"
.dw FBRC
.db 0
RECURSE:
.dw nativeWord
call popRS
dec hl \ dec hl
ld (IP), hl
push hl \ pop iy
jp compiledWord
LATEST: LATEST:
.dw RECURSE .dw FBRC

View File

@ -60,7 +60,7 @@ QUIT R:drop -- Return to interpreter promp immediately
RECURSE R:I -- R:I-2 Run the current word again. RECURSE R:I -- R:I-2 Run the current word again.
THEN I:a -- *I* Set branching cell at a. THEN I:a -- *I* Set branching cell at a.
*** Stack *** *** Parameter Stack ***
DUP a -- a a DUP a -- a a
OVER a b -- a b a OVER a b -- a b a
SWAP a b -- b a SWAP a b -- b a
@ -68,6 +68,13 @@ SWAP a b -- b a
2OVER a b c d -- a b c d a b 2OVER a b c d -- a b c d a b
2SWAP a b c d -- c d a b 2SWAP a b c d -- c d a b
*** Return Stack ***
>R n -- R:n Pops PS and push to RS
R> R:n -- n Pops RS and push to PS
I -- n Copy RS TOS to PS
I' -- n Copy RS second item to PS
J -- n Copy RS third item to PS
*** Memory *** *** Memory ***
@ a -- n Set n to value at address a @ a -- n Set n to value at address a
! n a -- Store n in address a ! n a -- Store n in address a
@ -75,7 +82,7 @@ SWAP a b -- b a
+! n a -- Increase value of addr a by n +! n a -- Increase value of addr a by n
C@ a -- c Set c to byte at address a C@ a -- c Set c to byte at address a
C! c a -- Store byte c in address a C! c a -- Store byte c in address a
CURRENT -- n Set n to wordref of last added entry. CURRENT -- a Set a to wordref of last added entry.
HERE -- a Push HERE's address HERE -- a Push HERE's address
H -- a HERE @ H -- a HERE @
@ -96,8 +103,8 @@ CMP n1 n2 -- n Compare n1 and n2 and set n to -1, 0, or 1.
NOT f -- f Push the logical opposite of f NOT f -- f Push the logical opposite of f
*** Strings *** *** Strings ***
LIT@ x -- a Read folloing LIT and push its addr to a LIT@ x -- a Read following LIT and push its addr to a
S= a1 a2 -- n Compare strings a1 and a2. See CMP SCMP a1 a2 -- n Compare strings a1 and a2. See CMP
*** I/O *** *** I/O ***
. n -- Print n in its decimal form . n -- Print n in its decimal form
@ -105,4 +112,5 @@ EMIT c -- Spit char c to stdout
KEY -- c Get char c from stdin KEY -- c Get char c from stdin
PC! c a -- Spit c to port a PC! c a -- Spit c to port a
PC@ a -- c Fetch c from port a PC@ a -- c Fetch c from port a
WORD -- a Read one word from stdin and push its addr

View File

@ -17,8 +17,12 @@
; *** Variables *** ; *** Variables ***
.equ INITIAL_SP FORTH_RAMSTART .equ INITIAL_SP FORTH_RAMSTART
; wordref of the last entry of the dict.
.equ CURRENT @+2 .equ CURRENT @+2
; Pointer to the next free byte in dict. During compilation of input text, this
; temporarily points to the next free byte in COMPBUF.
.equ HERE @+2 .equ HERE @+2
; Used to hold HERE while we temporarily point it to COMPBUF
.equ OLDHERE @+2 .equ OLDHERE @+2
; Interpreter pointer. See Execution model comment below. ; Interpreter pointer. See Execution model comment below.
.equ IP @+2 .equ IP @+2

View File

@ -36,8 +36,15 @@ skipRS:
pop hl pop hl
ret ret
; Verifies that SP is within bounds. If it's not, call ABORT ; Verifies that SP and RS are within bounds. If it's not, call ABORT
chkPS: chkPSRS:
push ix \ pop hl
push de ; --> lvl 1
ld de, RS_ADDR
or a ; clear carry
sbc hl, de
pop de ; <-- lvl 1
jr c, .underflow
ld hl, (INITIAL_SP) ld hl, (INITIAL_SP)
; We have the return address for this very call on the stack. Let's ; We have the return address for this very call on the stack. Let's
; compensate ; compensate
@ -45,6 +52,7 @@ chkPS:
or a ; clear carry or a ; clear carry
sbc hl, sp sbc hl, sp
ret nc ; (INITIAL_SP) >= SP? good ret nc ; (INITIAL_SP) >= SP? good
.underflow:
; underflow ; underflow
ld hl, .msg ld hl, .msg
call printstr call printstr

View File

@ -80,13 +80,6 @@ HLPointsBR:
pop de pop de
ret ret
HLPointsEXIT:
push de
ld de, EXIT
call HLPointsDE
pop de
ret
; Skip the compword where HL is currently pointing. If it's a regular word, ; Skip the compword where HL is currently pointing. If it's a regular word,
; it's easy: we inc by 2. If it's a NUMBER, we inc by 4. If it's a LIT, we skip ; it's easy: we inc by 2. If it's a NUMBER, we inc by 4. If it's a LIT, we skip
; to after null-termination. ; to after null-termination.