forth: add words "(fbr)", "(fbr?)", "'", "[']"

This commit is contained in:
Virgil Dupras 2020-03-12 21:16:20 -04:00
parent fb54fd51af
commit d5a7d5faf8
3 changed files with 110 additions and 52 deletions

View File

@ -11,7 +11,7 @@
; "jp exit".
;
; That's for "regular" words (words that are part of the dict chain). There are
; also "special words", for example NUMBER, LIT, BRANCH, that have a slightly
; also "special words", for example NUMBER, LIT, FBR, that have a slightly
; different structure. They're also a pointer to an executable, but as for the
; other fields, the only one they have is the "flags" field.
@ -56,42 +56,6 @@ doesWord:
push hl \ pop iy
jr compiledWord
; This word is followed by 1b *relative* offset (to the cell's addr) to where to
; branch to. For example, The branching cell of "IF THEN" would contain 3. Add
; this value to RS.
branchWord:
push de
ld l, (ix)
ld h, (ix+1)
ld a, (hl)
call addHL
ld (ix), l
ld (ix+1), h
pop de
jp exit
.db 0b10 ; Flags
BRANCH:
.dw branchWord
; Conditional branch, only branch if TOS is zero
cbranchWord:
pop hl
ld a, h
or l
jr z, branchWord
; skip next byte in RS
ld l, (ix)
ld h, (ix+1)
inc hl
ld (ix), l
ld (ix+1), h
jp exit
.db 0b10 ; Flags
CBRANCH:
.dw cbranchWord
; 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
@ -338,10 +302,53 @@ LITERAL:
ld (HERE), hl
jp exit
.db "'"
.fill 6
.dw LITERAL
.db 0
APOS:
.dw nativeWord
call readLITBOS
call find
jr nz, .notfound
push de
jp exit
.notfound:
ld hl, .msg
call printstr
jp abort
.msg:
.db "word not found", 0
.db "[']"
.fill 4
.dw APOS
.db 0b01 ; IMMEDIATE
APOSI:
.dw nativeWord
call readword
call find
jr nz, .notfound
ld hl, (HERE)
push de ; --> lvl 1
ld de, NUMBER
call DEinHL
pop de ; <-- lvl 1
call DEinHL
ld (HERE), hl
jp exit
.notfound:
ld hl, .msg
call printstr
jp abort
.msg:
.db "word not found", 0
; ( -- c )
.db "KEY"
.fill 4
.dw LITERAL
.dw APOSI
.db 0
KEY:
.dw nativeWord
@ -630,9 +637,49 @@ CMP:
push bc
jp exit
; This word's atom is followed by 1b *relative* offset (to the cell's addr) to
; where to branch to. For example, The branching cell of "IF THEN" would
; contain 3. Add this value to RS.
.db "(fbr)"
.fill 2
.dw CMP
.db 0
FBR:
.dw nativeWord
push de
ld l, (ix)
ld h, (ix+1)
ld a, (hl)
call addHL
ld (ix), l
ld (ix+1), h
pop de
jp exit
; Conditional branch, only branch if TOS is zero
.db "(fbr?)"
.fill 1
.dw FBR
.db 0
FBRC:
.dw nativeWord
pop hl
ld a, h
or l
jr z, FBR+2
; skip next byte in RS
ld l, (ix)
ld h, (ix+1)
inc hl
ld (ix), l
ld (ix+1), h
jp exit
; : IF ' (fbr?) , HERE @ 0 C, ; IMMEDIATE
.db "IF"
.fill 5
.dw CMP
.dw FBRC
.db 1 ; IMMEDIATE
IF:
.dw nativeWord
@ -640,7 +687,7 @@ IF:
; push the address of that cell on the PS. ELSE or THEN will pick
; them up and set the offset.
ld hl, (HERE)
ld de, CBRANCH
ld de, FBRC
call DEinHL
push hl ; address of cell to fill
inc hl ; empty 1b cell
@ -666,7 +713,7 @@ ELSE:
; uncondition branching cell, which will then be picked up by THEN.
; First, let's spit our 4 bytes
ld hl, (HERE)
ld de, BRANCH
ld de, FBR
call DEinHL
push hl ; address of cell to fill
inc hl ; empty 1b cell

View File

@ -1,6 +1,7 @@
Stack notation: "<stack before> -- <stack after>". Rightmost is top of stack
(TOS). For example, in "a b -- c d", b is TOS before, d is TOS after. "R:" means
that the Return Stack is modified.
that the Return Stack is modified. "I:" prefix means "IMMEDIATE", that is, that
this stack transformation is made at compile time.
DOES>: Used inside a colon definition that itself uses CREATE, DOES> transforms
that newly created word into a "does cell", that is, a regular cell ( when
@ -25,29 +26,39 @@ Atom: A word of the type compiledWord contains, in its PF, a list of what we
call "atoms". Those atoms are most of the time word references, but they can
also be references to NUMBER and LIT.
Words between "()" are "support words" that aren't really meant to be used
directly, but as part of another word.
"*I*" in description indicates an IMMEDIATE word.
*** Defining words ***
: x ... -- Define a new word
; R:I -- Exit a colon definition
, n -- Write n in HERE and advance it.
' x -- a Push addr of word x to a.
['] x -- *I* Like "'", but spits the addr as a number literal.
ALLOT n -- Move HERE by n bytes
C, b -- Write byte b in HERE and advance it.
CREATE x -- Create cell named x. Doesn't allocate a PF.
CONSTANT x n -- Creates cell x that when called pushes its value
DOES> -- See description at top of file
IMMEDIATE -- Flag the latest defined word as immediate.
LITERAL n -- Inserts number from TOS as a literal
LITERAL n -- *I* Inserts number from TOS as a literal
VARIABLE c -- Creates cell x with 2 bytes allocation.
*** Flow ***
ELSE -- Branch to THEN
(fbr?) f -- Conditionally branches forward by the number
specified in its atom's cell.
(fbr) -- Branches forward by the number specified in its
atom's cell.
ELSE I:a -- *I* Compiles a (fbr) and set branching cell at a.
EXECUTE a -- Execute wordref at addr a
IF n -- Branch to ELSE or THEN if n is zero
IF -- I:a *I* Compiles a (fbr?) and pushes its cell's addr
INTERPRET -- Get a line from stdin, compile it in tmp memory,
then execute the compiled contents.
QUIT R:drop -- Return to interpreter promp immediately
RECURSE R:I -- R:I-2 Run the current word again.
THEN -- Does nothing. Serves as a branching merker for IF
and ELSE.
THEN I:a -- *I* Set branching cell at a.
*** Stack ***
DUP a -- a a

View File

@ -69,12 +69,12 @@ HLPointsLIT:
pop de
ret
HLPointsBRANCH:
HLPointsBR:
push de
ld de, BRANCH
ld de, FBR
call HLPointsDE
jr z, .end
ld de, CBRANCH
ld de, FBRC
call HLPointsDE
.end:
pop de
@ -93,7 +93,7 @@ HLPointsEXIT:
compSkip:
call HLPointsNUMBER
jr z, .isNum
call HLPointsBRANCH
call HLPointsBR
jr z, .isBranch
call HLPointsLIT
jr nz, .isWord
@ -171,7 +171,7 @@ readLIT:
.notLIT:
; Alright, not a literal, but is it a word?
call HLPointsUNWORD
jr nz, .notWord
jr z, .notWord
; Not a number, then it's a word. Copy word to pad and point to it.
push hl ; --> lvl 1. we need it to set DE later
call intoHL