fix(v4.0.0): shorter chains of calls in the compiler capsule
Measured, compiling a DO loop left one return entry spare under INTERPRET and a defining word called from inside another word overflowed the nine-entry return stack (D-2); the prompt loop will take one more. C@ and C! shift without a loop. The code generator shifts each opcode into the word being built, so nothing is placed by a counted shift, and the address masks come from a table. The dictionary search, the in-liner, the end of a loop and the making of a data word are each one word reached by a jump. Every kind of line now leaves at least three return entries spare while it compiles; a word run from the interpreter has six; and CREATE ... DOES> works from the prompt, from a word, and from a word that calls that. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
dac7ffac92
commit
806f876ee0
+21
-23
@@ -118,12 +118,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)+4 (CLIP)'s string
|
||||
|
||||
\ ( baddr -- baddr ) cut the counted string to 31 characters, in place
|
||||
: (CLIP)
|
||||
dup (D)+4 a! ! C@ -32 + -if LONG drop (D)+4 a! @ ;
|
||||
LONG: drop 31 (D)+4 a! @ C! (D)+4 a! @ ;
|
||||
\ (D)+3 a count
|
||||
|
||||
\ ( -- bytes ) what an entry for a name of (D)+3 characters takes: its name
|
||||
\ cells and three more
|
||||
@@ -157,27 +152,30 @@ header HIDDEN
|
||||
|
||||
\ ---- looking a name up -----------------------------------------------------
|
||||
|
||||
\ ( -- flag ) the name of the entry in (D)+2 is the counted string in (D)+1
|
||||
: (NAME=)
|
||||
(D)+2 a! @ >NAME (D) a! !
|
||||
(D)+1 a! @ C@ 1 + (D)+3 a! ! \ the count byte and the characters
|
||||
L: (D)+3 a! @ if SAME -1 + dup ! \ k
|
||||
dup (D) a! @ + C@ \ k c1
|
||||
SWAP (D)+1 a! @ + C@ \ c1 c2
|
||||
xor if EQ drop 0 ;
|
||||
EQ: drop jump L
|
||||
SAME: drop -1 ;
|
||||
|
||||
\ ( baddr -- xt | 0 ) the newest visible entry named by the counted string
|
||||
\ ( baddr -- xt | 0 ) the newest visible entry named by the counted string.
|
||||
\ Written out in one piece -- the string cut to 31, each entry's flags and
|
||||
\ name fetched, the two names compared byte by byte -- so that the only call
|
||||
\ it makes is C@: it is called from the interpreter for every word of every
|
||||
\ line, with the user's return stack beneath it.
|
||||
: (LOOKUP)
|
||||
(CLIP) (D)+1 a! !
|
||||
dup (D)+1 a! ! \ cut the string to 31 characters
|
||||
C@ -32 + -if LONG drop jump CUT
|
||||
LONG: drop 31 (D)+1 a! @ C!
|
||||
CUT:
|
||||
LATEST
|
||||
L: if END
|
||||
(D)+2 a! !
|
||||
(D)+2 a! @ (FLAGS) a! @ 2 and if VISIBLE drop jump OLDER
|
||||
VISIBLE: drop (NAME=) if DIFF drop (D)+2 a! @ ;
|
||||
DIFF: drop
|
||||
OLDER: (D)+2 a! @ >LINK a! @ jump L
|
||||
(D)+2 a! @ -3 + a! @ 2 and if VISIBLE drop jump OLDER
|
||||
VISIBLE: drop
|
||||
(D)+2 a! @ -2 + a! @ 4* (D) a! ! \ its name
|
||||
(D)+1 a! @ C@ 1 + (D)+3 a! ! \ the count byte and the characters
|
||||
C: (D)+3 a! @ if SAME -1 + dup ! \ k
|
||||
dup (D) a! @ + C@ \ k c1
|
||||
SWAP (D)+1 a! @ + C@ \ c1 c2
|
||||
xor if EQ drop jump OLDER
|
||||
EQ: drop jump C
|
||||
SAME: drop (D)+2 a! @ ;
|
||||
OLDER: (D)+2 a! @ -1 + a! @ jump L
|
||||
END: ;
|
||||
|
||||
\ ( -- xt | 0 ) FORTH-79: the compilation address of the next word in the
|
||||
|
||||
Reference in New Issue
Block a user