2020-03-08 04:13:15 +11:00
|
|
|
; *** Const ***
|
|
|
|
; Base of the Return Stack
|
|
|
|
.equ RS_ADDR 0xf000
|
|
|
|
; Number of bytes we keep as a padding between HERE and the scratchpad
|
|
|
|
.equ PADDING 0x20
|
2020-03-08 09:09:45 +11:00
|
|
|
; Max length of dict entry names
|
|
|
|
.equ NAMELEN 8
|
2020-03-08 04:13:15 +11:00
|
|
|
; Offset of the code link relative to the beginning of the word
|
|
|
|
.equ CODELINK_OFFSET 10
|
2020-03-08 09:09:45 +11:00
|
|
|
; When set, the interpreter should abort parsing of current line and return to
|
|
|
|
; prompt.
|
|
|
|
.equ FLAG_QUITTING 0
|
|
|
|
; When set, the interpreter should quit
|
2020-03-08 05:15:19 +11:00
|
|
|
.equ FLAG_ENDPGM 1
|
2020-03-08 04:13:15 +11:00
|
|
|
|
|
|
|
; *** Variables ***
|
|
|
|
.equ INITIAL_SP FORTH_RAMSTART
|
|
|
|
.equ CURRENT @+2
|
|
|
|
.equ HERE @+2
|
|
|
|
.equ INPUTPOS @+2
|
2020-03-08 05:15:19 +11:00
|
|
|
.equ FLAGS @+2
|
2020-03-08 09:09:45 +11:00
|
|
|
; Buffer where we compile the current input line. Same size as STDIO_BUFSIZE.
|
|
|
|
.equ COMPBUF @+1
|
|
|
|
.equ FORTH_RAMEND @+0x40
|
2020-03-08 04:13:15 +11:00
|
|
|
|
|
|
|
; *** Code ***
|
|
|
|
MAIN:
|
|
|
|
.dw compiledWord
|
|
|
|
.dw INTERPRET+CODELINK_OFFSET
|
2020-03-08 05:15:19 +11:00
|
|
|
.dw CHKEND
|
2020-03-08 04:13:15 +11:00
|
|
|
|
2020-03-08 05:15:19 +11:00
|
|
|
; If FLAG_ENDPGM is set, stop the program, else, tweak the RS so that we loop.
|
|
|
|
CHKEND:
|
2020-03-08 04:13:15 +11:00
|
|
|
.dw nativeWord
|
2020-03-08 05:15:19 +11:00
|
|
|
ld hl, FLAGS
|
|
|
|
bit FLAG_ENDPGM, (hl)
|
|
|
|
jr nz, .endpgm
|
2020-03-08 09:09:45 +11:00
|
|
|
; not quitting program, are we supposed to continue parsing line?
|
|
|
|
ld hl, FLAGS
|
|
|
|
bit FLAG_QUITTING, (hl)
|
|
|
|
jr nz, forthRdLine
|
|
|
|
; Not quitting line either.
|
|
|
|
jr forthInterpret
|
2020-03-08 05:15:19 +11:00
|
|
|
.endpgm:
|
2020-03-08 04:13:15 +11:00
|
|
|
ld sp, (INITIAL_SP)
|
2020-03-08 12:20:11 +11:00
|
|
|
; restore stack
|
|
|
|
pop af \ pop af \ pop af
|
2020-03-08 04:13:15 +11:00
|
|
|
xor a
|
|
|
|
ret
|
|
|
|
|
|
|
|
forthMain:
|
2020-03-08 12:20:11 +11:00
|
|
|
; STACK OVERFLOW PROTECTION:
|
|
|
|
; To avoid having to check for stack underflow after each pop operation
|
|
|
|
; (which can end up being prohibitive in terms of costs), we give
|
|
|
|
; ourselves a nice 6 bytes buffer. 6 bytes because we seldom have words
|
|
|
|
; requiring more than 3 items from the stack. Then, at each "exit" call
|
|
|
|
; we check for stack underflow.
|
|
|
|
push af \ push af \ push af
|
2020-03-08 04:13:15 +11:00
|
|
|
ld (INITIAL_SP), sp
|
2020-03-08 13:12:30 +11:00
|
|
|
ld hl, ALLOT ; last entry in hardcoded dict
|
2020-03-08 04:13:15 +11:00
|
|
|
ld (CURRENT), hl
|
|
|
|
ld hl, FORTH_RAMEND
|
|
|
|
ld (HERE), hl
|
2020-03-08 09:09:45 +11:00
|
|
|
forthRdLine:
|
|
|
|
xor a
|
|
|
|
ld (FLAGS), a
|
|
|
|
ld hl, msgOk
|
|
|
|
call printstr
|
|
|
|
call printcrlf
|
|
|
|
call stdioReadLine
|
|
|
|
ld (INPUTPOS), hl
|
|
|
|
forthInterpret:
|
2020-03-08 04:13:15 +11:00
|
|
|
ld ix, RS_ADDR
|
|
|
|
ld iy, MAIN
|
|
|
|
jp executeCodeLink
|
2020-03-08 09:09:45 +11:00
|
|
|
msgOk:
|
|
|
|
.db " ok", 0
|