forth: remove CMPDST

We now always do ","-style writes in (HERE), even in IMMEDIATE mode. Simplifies
things and paves the way for compiling words in Forth.
This commit is contained in:
Virgil Dupras 2020-03-12 13:08:11 -04:00
parent ff281f69a8
commit 3819dbc083
2 changed files with 36 additions and 22 deletions

View File

@ -332,12 +332,12 @@ IMMEDIATE:
.db 1 ; IMMEDIATE .db 1 ; IMMEDIATE
LITERAL: LITERAL:
.dw nativeWord .dw nativeWord
ld hl, (CMPDST) ld hl, (HERE)
ld de, NUMBER ld de, NUMBER
call DEinHL call DEinHL
pop de ; number from stack pop de ; number from stack
call DEinHL call DEinHL
ld (CMPDST), hl ld (HERE), hl
jp exit jp exit
; ( -- c ) ; ( -- c )
@ -641,12 +641,12 @@ IF:
; Spit a conditional branching atom, followed by an empty 1b cell. Then, ; Spit a conditional branching atom, followed by an empty 1b cell. Then,
; push the address of that cell on the PS. ELSE or THEN will pick ; push the address of that cell on the PS. ELSE or THEN will pick
; them up and set the offset. ; them up and set the offset.
ld hl, (CMPDST) ld hl, (HERE)
ld de, CBRANCH ld de, CBRANCH
call DEinHL call DEinHL
push hl ; address of cell to fill push hl ; address of cell to fill
inc hl ; empty 1b cell inc hl ; empty 1b cell
ld (CMPDST), hl ld (HERE), hl
jp exit jp exit
.db "ELSE" .db "ELSE"
@ -657,7 +657,7 @@ ELSE:
.dw nativeWord .dw nativeWord
; First, let's set IF's branching cell. ; First, let's set IF's branching cell.
pop de ; cell's address pop de ; cell's address
ld hl, (CMPDST) ld hl, (HERE)
; also skip ELSE word. ; also skip ELSE word.
inc hl \ inc hl \ inc hl inc hl \ inc hl \ inc hl
or a ; clear carry or a ; clear carry
@ -667,12 +667,12 @@ ELSE:
; Set IF's branching cell to current atom address and spit our own ; Set IF's branching cell to current atom address and spit our own
; uncondition branching cell, which will then be picked up by THEN. ; uncondition branching cell, which will then be picked up by THEN.
; First, let's spit our 4 bytes ; First, let's spit our 4 bytes
ld hl, (CMPDST) ld hl, (HERE)
ld de, BRANCH ld de, BRANCH
call DEinHL call DEinHL
push hl ; address of cell to fill push hl ; address of cell to fill
inc hl ; empty 1b cell inc hl ; empty 1b cell
ld (CMPDST), hl ld (HERE), hl
jp exit jp exit
.db "THEN" .db "THEN"
@ -683,7 +683,7 @@ THEN:
.dw nativeWord .dw nativeWord
; See comments in IF and ELSE ; See comments in IF and ELSE
pop de ; cell's address pop de ; cell's address
ld hl, (CMPDST) ld hl, (HERE)
; There is nothing to skip because THEN leaves nothing. ; There is nothing to skip because THEN leaves nothing.
or a ; clear carry or a ; clear carry
sbc hl, de ; HL now has relative offset sbc hl, de ; HL now has relative offset

View File

@ -21,9 +21,6 @@
.equ HERE @+2 .equ HERE @+2
; Pointer to where we currently are in the interpretation of the current line. ; Pointer to where we currently are in the interpretation of the current line.
.equ INPUTPOS @+2 .equ INPUTPOS @+2
; Pointer to where compiling words should output. During interpret, it's a
; moving target in (COMPBUF). During DEFINE, it's (HERE).
.equ CMPDST @+2
; Buffer where we compile the current input line. Same size as STDIO_BUFSIZE. ; Buffer where we compile the current input line. Same size as STDIO_BUFSIZE.
.equ COMPBUF @+2 .equ COMPBUF @+2
.equ FORTH_RAMEND @+0x40 .equ FORTH_RAMEND @+0x40
@ -38,19 +35,29 @@
; ;
; 1. read single word from line ; 1. read single word from line
; 2. compile word to atom ; 2. compile word to atom
; 3. execute atom ; 3. if immediate, execute atom
; 4. goto 1 ; 4. goto 1 until we exhaust words
; 5. Execute compiled atom list as if it was a regular compiledWord.
; ;
; During step 3, it's possible that atom read from input, so INPUTPOS might ; Because the Parameter Stack uses SP, we can't just go around calling routines:
; have moved between 3 and 4.
;
; Because the Parameter Stack uses PS, we can't just go around calling routines:
; This messes with the PS. This is why we almost always jump (unless our call ; This messes with the PS. This is why we almost always jump (unless our call
; doesn't involve Forth words in any way). ; doesn't involve Forth words in any way).
; ;
; This presents a challenge for our interpret loop because step 4, "goto 1" ; This presents a challenge for our interpret loop because step 4, "goto 1"
; isn't obvious. To be able to do that, we must push a "return routine" to the ; isn't obvious. To be able to do that, we must push a "return routine" to the
; Return Stack before step 3. ; Return Stack before step 3.
;
; HERE and IMMEDIATE: When compiling in step 2, we spit compiled atoms in
; (HERE) to simplify "," semantic in Forth (spitting, in all cases, is done in
; (HERE)). However, suring input line compilation, it isn't like during ":", we
; aren't creating a new entry.
;
; Compiling and executing from (HERE) would be dangerous because an
; entry-creation word, during runtime, could end up overwriting the atom list
; we're executing. This is why we have this list in COMPBUF.
;
; During IMMEDIATE mode, (HERE) is temporarily set to COMPBUF, and when we're
; done, we restore (HERE) for runtime. This way, everyone is happy.
; *** Code *** ; *** Code ***
forthMain: forthMain:
@ -78,8 +85,12 @@ forthRdLine:
call stdioReadLine call stdioReadLine
ld ix, RS_ADDR-2 ; -2 because we inc-before-push ld ix, RS_ADDR-2 ; -2 because we inc-before-push
ld (INPUTPOS), hl ld (INPUTPOS), hl
; We're about to compile the line and possibly execute IMMEDIATE words.
; Let's save current (HERE) and temporarily set it to COMPBUF.
ld hl, (HERE)
push hl ; Saving HERE
ld hl, COMPBUF ld hl, COMPBUF
ld (CMPDST), hl ld (HERE), hl
forthInterpret: forthInterpret:
call readword call readword
jr nz, .execute jr nz, .execute
@ -111,9 +122,9 @@ forthInterpret:
; called, triggering an abort. ; called, triggering an abort.
ld de, LIT ld de, LIT
call .writeDE call .writeDE
ld de, (CMPDST) ld de, (HERE)
call strcpyM call strcpyM
ld (CMPDST), de ld (HERE), de
jr forthInterpret jr forthInterpret
.immed: .immed:
push hl ; --> lvl 1 push hl ; --> lvl 1
@ -124,16 +135,19 @@ forthInterpret:
.execute: .execute:
ld de, QUIT ld de, QUIT
call .writeDE call .writeDE
; Compilation done, let's restore (HERE) and execute!
pop hl ; Restore old (HERE)
ld (HERE), hl
ld iy, COMPBUF ld iy, COMPBUF
jp compiledWord jp compiledWord
.writeDE: .writeDE:
push hl push hl
ld hl, (CMPDST) ld hl, (HERE)
ld (hl), e ld (hl), e
inc hl inc hl
ld (hl), d ld (hl), d
inc hl inc hl
ld (CMPDST), hl ld (HERE), hl
pop hl pop hl
ret ret