forth: add words "(fbr)", "(fbr?)", "'", "[']"
This commit is contained in:
parent
fb54fd51af
commit
d5a7d5faf8
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user