feat(v4.0.0): vocabularies, to FORTH-79
- VOCABULARY DEFINITIONS CONTEXT CURRENT FORTH, and v3's ORDER. A name is looked up in the CONTEXT vocabulary and then in FORTH; a new entry goes into the CURRENT vocabulary; : makes the CURRENT vocabulary CONTEXT; FORTH is immediate. - WORDS lists the CONTEXT vocabulary. FORGET takes what was defined later out of every vocabulary, and a vocabulary that goes gives way to FORTH. - v3's vocabularies separate nothing: a word defined in one is found from every other, and one redefined in a vocabulary replaces FORTH's for good. - tests/test_host_quit.c: isolation, chaining to FORTH, two vocabularies with the same names, FORGET across them; and DUMP is now checked to put BASE back. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
ab272cc2ad
commit
0fbe1432b7
@@ -186,10 +186,12 @@ header [LITERAL] immediate
|
||||
|
||||
\ ---- colon definitions -----------------------------------------------------------
|
||||
|
||||
\ FORTH-79: start a definition; it cannot be found until ; ends it.
|
||||
\ FORTH-79: start a definition; it cannot be found until ; ends it. The
|
||||
\ CONTEXT vocabulary is set to the CURRENT one.
|
||||
\ (C)+2 holds LATEST while the entry is made, to tell whether one was.
|
||||
header :
|
||||
: COLON
|
||||
CURRENT a! @ CONTEXT a! !
|
||||
LATEST (C)+2 a! !
|
||||
32 WORD (HEADER)
|
||||
LATEST (C)+2 a! @ xor if NONE drop
|
||||
|
||||
+19
-6
@@ -26,7 +26,15 @@
|
||||
\
|
||||
\ Constants the loader supplies:
|
||||
\ DP word address of the variable: the next free byte
|
||||
\ (LATEST) word address of the variable: the xt of the newest entry, or 0
|
||||
\ (LATEST) word address of the variable: the xt of the newest entry of the
|
||||
\ FORTH vocabulary, or 0
|
||||
\ CONTEXT CURRENT word addresses of the variables: each holds the address
|
||||
\ of a vocabulary's head cell -- the cell that holds the xt of
|
||||
\ that vocabulary's newest entry. FORTH's head cell is (LATEST).
|
||||
\
|
||||
\ VOCABULARIES (FORTH-79). A name is looked up in the CONTEXT vocabulary and
|
||||
\ then, if that is not FORTH, in FORTH. A new entry goes into the CURRENT
|
||||
\ vocabulary: it is linked to that vocabulary's newest entry and becomes it.
|
||||
\ DBASE DLIMIT byte addresses of the start and end of dictionary space
|
||||
\ PAD byte address of the scratch area for strings, 84 bytes or more
|
||||
\ (D) word address of five cells of scratch for this file
|
||||
@@ -78,7 +86,7 @@ header 2,
|
||||
: 2, ( lo hi -- ) SWAP , , ; \ the low cell first, as v3
|
||||
|
||||
header LATEST
|
||||
: LATEST ( -- xt ) (LATEST) a! @ ;
|
||||
: LATEST ( -- xt ) CURRENT a! @ a! @ ; \ the newest entry of the CURRENT vocabulary
|
||||
|
||||
\ ---- the fields of an entry (5.13) -----------------------------------------
|
||||
|
||||
@@ -118,7 +126,7 @@ header HIDDEN
|
||||
\ ---- making an entry -------------------------------------------------------
|
||||
\ (D)+0 where the name starts (D)+1 the name being looked up
|
||||
\ (D)+2 the name being copied, or the entry being looked at
|
||||
\ (D)+3 a count
|
||||
\ (D)+3 a count (D)+4 whether a lookup has gone on to FORTH
|
||||
|
||||
\ ( -- bytes ) what an entry for a name of (D)+3 characters takes: its name
|
||||
\ cells and three more
|
||||
@@ -146,7 +154,7 @@ header HIDDEN
|
||||
P: DP b! @b 3 and if ALIGNED drop 0 C, jump P
|
||||
ALIGNED: drop
|
||||
0 , (D) a! @ , LATEST ,
|
||||
HERE (LATEST) a! ! ;
|
||||
HERE CURRENT a! @ a! ! ;
|
||||
FULL: drop ; \ (DP+) has set NODE-ERROR
|
||||
EMPTY: drop NODE-ERROR b! 6 !b ; \ name missing
|
||||
|
||||
@@ -162,7 +170,8 @@ header HIDDEN
|
||||
C@ -32 + -if LONG drop jump CUT
|
||||
LONG: drop 31 (D)+1 a! @ C!
|
||||
CUT:
|
||||
LATEST
|
||||
0 (D)+4 a! ! \ not yet on to FORTH
|
||||
CONTEXT a! @ a! @
|
||||
L: if END
|
||||
(D)+2 a! !
|
||||
(D)+2 a! @ -3 + a! @ 2 and if VISIBLE drop jump OLDER
|
||||
@@ -176,7 +185,11 @@ header HIDDEN
|
||||
EQ: drop jump C
|
||||
SAME: drop (D)+2 a! @ ;
|
||||
OLDER: (D)+2 a! @ -1 + a! @ jump L
|
||||
END: ;
|
||||
END: (D)+4 a! @ if FIRST drop ; \ FORTH has been searched: not found
|
||||
FIRST: drop -1 (D)+4 a! !
|
||||
CONTEXT a! @ (LATEST) xor if ISFORTH \ CONTEXT is FORTH: that was it
|
||||
drop drop (LATEST) a! @ jump L
|
||||
ISFORTH: drop ;
|
||||
|
||||
\ ( -- xt | 0 ) FORTH-79: the compilation address of the next word in the
|
||||
\ input stream, or 0 if it is not in the dictionary.
|
||||
|
||||
+71
-10
@@ -6,16 +6,57 @@
|
||||
\ Constants the loader supplies:
|
||||
\ FENCE word address of the variable: FORGET will not remove an entry
|
||||
\ that starts below the address it holds
|
||||
\ VOC-LINK word address of the variable: the newest vocabulary, or 0
|
||||
|
||||
header FENCE inline : FENCE' FENCE ;
|
||||
|
||||
\ ( -- ) the names in the dictionary, the newest first, a blank after
|
||||
\ ---- vocabularies (FORTH-79) ----------------------------------------------------
|
||||
\ A vocabulary is two cells: its head -- the xt of its newest entry, or 0 --
|
||||
\ and the address of the vocabulary defined before it, or 0. VOC-LINK holds
|
||||
\ the newest one's address. FORTH's head is (LATEST) and it is in no chain.
|
||||
header CONTEXT inline : CONTEXT' CONTEXT ;
|
||||
header CURRENT inline : CURRENT' CURRENT ;
|
||||
|
||||
\ FORTH-79: the primary vocabulary; it becomes the CONTEXT vocabulary.
|
||||
header FORTH immediate
|
||||
: FORTH (LATEST) CONTEXT a! ! ;
|
||||
\ FORTH-79: new definitions go into the CONTEXT vocabulary from now on.
|
||||
header DEFINITIONS
|
||||
: DEFINITIONS CONTEXT a! @ CURRENT a! ! ;
|
||||
|
||||
\ VOCABULARY xxx FORTH-79: xxx is a new, empty list of words; executing
|
||||
\ xxx makes it the CONTEXT vocabulary. When a search of it finds nothing,
|
||||
\ FORTH is searched.
|
||||
: (DOVOC) pop CONTEXT a! ! ;
|
||||
header VOCABULARY
|
||||
: VOCABULARY
|
||||
&(DOVOC) (C)+3 a! ! (DATA) (C)+8 a! @ if NONE drop
|
||||
0 , VOC-LINK a! @ , HERE -2 + VOC-LINK a! ! ;
|
||||
NONE: drop ;
|
||||
|
||||
\ ( cell -- ) print the name of the vocabulary whose head cell this is
|
||||
: (.VOC)
|
||||
dup (LATEST) xor if F drop -1 + -2 + a! @ 4* COUNT 31 and jump TYPE
|
||||
F: drop drop $54524F46 (EMIT4) $48 (EMIT4) ;
|
||||
|
||||
\ ( -- ) as v3's, but true: where names are looked for, and where new ones go
|
||||
header ORDER
|
||||
: ORDER
|
||||
$72616553 (EMIT4) $6F206863 (EMIT4) $72656472 (EMIT4) $203A (EMIT4)
|
||||
CONTEXT a! @ dup (.VOC) SPACE
|
||||
(LATEST) xor if ONLY drop (LATEST) (.VOC) jump TWO
|
||||
ONLY: drop
|
||||
TWO: CR
|
||||
$72727543 (EMIT4) $3A746E65 (EMIT4) $20 (EMIT4)
|
||||
CURRENT a! @ (.VOC) jump CR
|
||||
|
||||
\ ( -- ) the names in the CONTEXT vocabulary, the newest first, a blank after
|
||||
\ each, a new line whenever one has passed column 64. Hidden entries -- a
|
||||
\ definition under way -- are not shown. (Q)+0 is the column.
|
||||
header WORDS
|
||||
: WORDS
|
||||
0 (Q) a! !
|
||||
LATEST
|
||||
CONTEXT a! @ a! @
|
||||
L: if DONE
|
||||
dup -3 + a! @ 2 and if SHOW drop jump NXT
|
||||
SHOW: drop
|
||||
@@ -29,17 +70,37 @@ header WORDS
|
||||
header VLIST
|
||||
: VLIST jump WORDS
|
||||
|
||||
\ FORGET xxx FORTH-79: remove xxx and every word defined after it. The
|
||||
\ space they took is free again. A word that is not there is an error, and
|
||||
\ so is one below FENCE, which is where the capsule's own words are (code
|
||||
\ 10, "Protected word").
|
||||
\ ( cell -- ) take off a vocabulary's list every entry at or above the
|
||||
\ address in (Q)+0. The newest are first, so it stops at the first one below.
|
||||
: (PRUNE)
|
||||
(Q)+1 a! !
|
||||
L: (Q)+1 a! @ a! @ if DONE
|
||||
dup (Q) a! @ inv + 1 + -if CUT drop drop ;
|
||||
CUT: drop -1 + a! @ (Q)+1 a! @ a! ! jump L
|
||||
DONE: drop ;
|
||||
|
||||
\ FORGET xxx FORTH-79: remove xxx and every word defined after it, in
|
||||
\ whatever vocabulary; the space they took is free again. A vocabulary that
|
||||
\ goes is no longer CONTEXT or CURRENT: FORTH is. A word that is not there
|
||||
\ is an error, and so is one below FENCE, which is where the capsule's own
|
||||
\ words are (code 10, "Protected word").
|
||||
header FORGET
|
||||
: FORGET
|
||||
32 WORD (LOOKUP) if MISSING
|
||||
dup -2 + a! @ \ xt name
|
||||
-2 + a! @ \ where its name starts
|
||||
dup FENCE a! @ inv + 1 + -if OK \ name - fence
|
||||
drop drop drop NODE-ERROR b! 10 !b ;
|
||||
drop drop NODE-ERROR b! 10 !b ;
|
||||
OK: drop
|
||||
4* DP a! ! \ the space from its name on
|
||||
-1 + a! @ (LATEST) a! ! ; \ and the entry before it is the newest
|
||||
dup (Q) a! ! 4* DP a! ! \ the space from its name on
|
||||
(LATEST) (PRUNE)
|
||||
V: VOC-LINK a! @ if PRUNED \ vocabularies that go
|
||||
dup (Q) a! @ inv + 1 + -if GONE drop jump KEPT
|
||||
GONE: drop 1 + a! @ VOC-LINK a! ! jump V
|
||||
KEPT: P: if PRUNED \ the lists of those that stay
|
||||
dup (PRUNE) 1 + a! @ jump P
|
||||
PRUNED: drop
|
||||
CONTEXT a! @ (Q) a! @ inv + 1 + -if C1 drop jump C2
|
||||
C1: drop (LATEST) CONTEXT a! !
|
||||
C2: CURRENT a! @ (Q) a! @ inv + 1 + -if C3 drop ;
|
||||
C3: drop (LATEST) CURRENT a! ! ;
|
||||
MISSING: drop (UNKNOWN) drop ;
|
||||
|
||||
Reference in New Issue
Block a user