collapseos/apps/forth/dict.asm

251 lines
4.0 KiB
NASM
Raw Normal View History

2020-03-07 12:13:15 -05:00
; A dictionary entry has this structure:
; - 8b name (zero-padded)
; - 2b prev pointer
; - 2b code pointer
; - Parameter field (PF)
2020-03-07 12:13:15 -05:00
;
; The code pointer point to "word routines". These routines expect to be called
; with IY pointing to the PF. They themselves are expected to end by jumping
2020-03-07 12:13:15 -05:00
; to the address at the top of the Return Stack. They will usually do so with
; "jp exit".
; Execute a word containing native code at its PF address (PFA)
2020-03-07 12:13:15 -05:00
nativeWord:
jp (iy)
; Execute a compiled word containing a list of references to other words,
; usually ended by a reference to EXIT.
; A reference to a word in a compiledWord section is *not* a direct reference,
; but a word+CODELINK_OFFSET reference. Therefore, for a code link "link",
; (link) is the routine to call.
compiledWord:
push iy \ pop hl
inc hl
inc hl
; HL points to next Interpreter pointer.
call pushRS
ld l, (iy)
ld h, (iy+1)
push hl \ pop iy
; IY points to code link
jp executeCodeLink
; Pushes the PFA directly
cellWord:
push iy
jp exit
; Pushes the address in the first word of the PF
sysvarWord:
ld l, (iy)
ld h, (iy+1)
push hl
jp exit
2020-03-07 19:25:55 -05:00
; This is not a word, but a number literal. This works a bit differently than
; others: PF means nothing and the actual number is placed next to the
; numberWord reference in the compiled word list. What we need to do to fetch
; that number is to play with the Return stack: We pop it, read the number, push
; it to the Parameter stack and then push an increase Interpreter Pointer back
; to RS.
numberWord:
call popRS
ld e, (hl)
inc hl
ld d, (hl)
inc hl
call pushRS
push de
jp exit
NUMBER:
.dw numberWord
2020-03-07 12:13:15 -05:00
; ( R:I -- )
EXIT:
.db "EXIT", 0, 0, 0, 0
.dw 0
.dw nativeWord
; When we call the EXIT word, we have to do a "double exit" because our current
; Interpreter pointer is pointing to the word *next* to our EXIT reference when,
; in fact, we want to continue processing the one above it.
call popRS
exit:
call popRS
; We have a pointer to a word
push hl \ pop iy
jp compiledWord
; ( R:I -- )
QUIT:
.db "QUIT", 0, 0, 0, 0
.dw EXIT
.dw nativeWord
quit:
ld hl, FLAGS
set FLAG_QUITTING, (hl)
jp exit
BYE:
.db "BYE"
.fill 5
.dw QUIT
.dw nativeWord
ld hl, FLAGS
set FLAG_ENDPGM, (hl)
jp exit
2020-03-07 12:13:15 -05:00
; ( c -- )
EMIT:
.db "EMIT", 0, 0, 0, 0
.dw BYE
2020-03-07 12:13:15 -05:00
.dw nativeWord
pop hl
ld a, l
call stdioPutC
jp exit
; ( addr -- )
EXECUTE:
.db "EXECUTE", 0
.dw EMIT
.dw nativeWord
pop iy ; Points to word_offset
ld de, CODELINK_OFFSET
add iy, de
executeCodeLink:
ld l, (iy)
ld h, (iy+1)
; HL points to code pointer
inc iy
inc iy
; IY points to PFA
jp (hl) ; go!
2020-03-07 18:53:20 -05:00
DEFINE:
.db ":"
.fill 7
.dw EXECUTE
.dw nativeWord
call entryhead
jp nz, quit
ld de, compiledWord
ld (hl), e
inc hl
ld (hl), d
inc hl
push hl \ pop iy
.loop:
call readword
jr nz, .end
call .issemicol
jr z, .end
call compile
jr nz, quit
jr .loop
.end:
; end chain with EXIT
ld hl, EXIT+CODELINK_OFFSET
2020-03-07 19:25:55 -05:00
call wrCompHL
2020-03-07 18:53:20 -05:00
ld (HERE), iy
jp exit
.issemicol:
ld a, (hl)
cp ';'
ret nz
inc hl
ld a, (hl)
dec hl
or a
ret
2020-03-07 12:13:15 -05:00
; ( -- c )
KEY:
.db "KEY"
.fill 5
2020-03-07 18:53:20 -05:00
.dw DEFINE
2020-03-07 12:13:15 -05:00
.dw nativeWord
call stdioGetC
ld h, 0
ld l, a
push hl
jp exit
INTERPRET:
.db "INTERPRE"
.dw KEY
.dw nativeWord
interpret:
2020-03-07 12:13:15 -05:00
call readword
jp nz, quit
ld iy, COMPBUF
2020-03-07 12:13:15 -05:00
call compile
jp nz, .notfound
ld hl, EXIT+CODELINK_OFFSET
ld (iy), l
ld (iy+1), h
ld iy, COMPBUF
2020-03-07 12:13:15 -05:00
jp compiledWord
.notfound:
ld hl, .msg
call printstr
jp quit
2020-03-07 12:13:15 -05:00
.msg:
.db "not found", 0
2020-03-07 12:50:54 -05:00
CREATE:
.db "CREATE", 0, 0
.dw INTERPRET
.dw nativeWord
2020-03-07 18:53:20 -05:00
call entryhead
jp nz, quit
ld de, cellWord
ld (hl), e
inc hl
ld (hl), d
inc hl
ld (HERE), hl
jp exit
HERE_: ; Caution: conflicts with actual variable name
.db "HERE"
.fill 4
.dw CREATE
.dw sysvarWord
.dw HERE
2020-03-07 12:50:54 -05:00
; ( n -- )
DOT:
.db "."
.fill 7
.dw HERE_
2020-03-07 12:50:54 -05:00
.dw nativeWord
pop de
call pad
call fmtDecimalS
call printstr
jp exit
; ( n a -- )
STORE:
.db "!"
.fill 7
.dw DOT
.dw nativeWord
pop iy
pop hl
ld (iy), l
ld (iy+1), h
jp exit
; ( a -- n )
FETCH:
.db "@"
.fill 7
.dw STORE
.dw nativeWord
pop hl
call intoHL
push hl
jp exit