Martin,
I will attempt to explain why I consider the threading technique
independent of NEXT.
Couple of caveats first:
- My definitions of NEXT, NEST, and UNNEST were *generic* - i.e., it
had *nothing* to do with Forth but -rather- to do with threaded languages
in general;
- My definitions of NEST and UNNEST were *independent* of NEXT - i.e.,
NEXT was a subset of UNNEST;
- My definition of threading techniques was also *generic* - i.e., the
emphasis was on procedural invocation, NOT on leaving the pfa address on
TOS, etc. a la Forth.
OK, given those caveats, I'll "invent" a virtual machine language.
I'll assume that the virtual machine addresses storage in increments
of the address size. That is if "ADDRESS" is the address of a word which
is a pointer (i.e., a machine address), then "ADDRESS+1" contains the
address of the next address.
- "IP" denotes a variable which is an address which contains the
address of the cfa.
- "[" and "]" will denote the value of an address.
- the operators "PUSH" and "POP" do what you expect they should do.
- a "label" is any string of characters followed by ":".
- the virtual machine unconditional jump operator is "JMP
",
where my be a label, a register, a variable, or the
value/address of an address.
- the "$" operator my be used as part of an expression which denotes
self reference and any "offset" from $ is in terms of instructions.
Thus the expression "$+2" denotes the address of the second
instruction from the current instruction.
- the "<-" operator will denote replacement.
- "REG" will denote a general-purpose machine register.
- the "MACRO " operator will define a macro whose code is
defined by all of the subsequent virtual machine instructions up to,
but not including, the END-MACRO operator. Upon subsequently
referring to the previously defined code will be substituted
for .
- the "RES " operator will reserve and initialize a word
of storage to .
- Finally, a back slash "\" will introduce a comment field (to end of
line).
Here we go:
--------------------------------------------------------------------------
INDIRECT THREADED CODE (ITC):
The basic idea behind ITC is compactness (at the expense of speed).
Here's a possible ITC implementation:
NEST: \ ALL COLON DEFINITION CFA'S POINT HERE
PUSH IP \ SAVE OLD/NEXT IP
REG <- IP - 1 \ GET CURRENT IP
REG <- [IP] \ GET CFA ADDRESS
IP <- [IP + 1] \ LOAD NEW IP
\ NOTE: IP+1 CONTAINS PFA
\ FALL-THRU TO NEXT
NEXT: \ INCREMENT IP AND JUMP TO IP
REG <- [IP] \ GET CURRENT CFA ADDRESS
IP <- IP + 1 \ INCREMENT IP FOR NEXT CFA
JMP [REG] \ INDIRECT JUMP TO CFA
UNNEST:
POP IP \ RESTORE OLD IP
\ NEXT: -- UNNEST INCLUDES NEXT AS A SUBSET
REG <- [IP] \ GET CURRENT CFA ADDRESS
IP <- IP + 1 \ INCREMENT IP FOR NEXT CFA
JMP [REG] \ INDIRECT JUMP TO CFA
\ NOTE: COULD ALSO DO A:
\ JMP NEXT
\ INSTEAD OF THE PREVIOUS THREE INSTRUCTIONS
\ BUT IT HARDLY SEEMS WORTH THE EFFORT
Code word definitions would all be of the form:
CODE-WORD:
RES MACHINE-CODE \ ADDRESS OF MACHINE CODE
MACHINE-CODE:
\ ANY ASSEMBLER CODE YOU LIKE HERE
JMP NEXT
Colon definitions would all be of the form:
COLON-DEFINITION:
RES NEST \ ADDRESS OF NEST
RES PFA \ ADDRESS OF PFA
PFA:
RES WORD1 \ ADDRESS OF ANY FORTH WORD
RES WORD2 \ CAN BE CODE WORD OR COLON DEFINITION
...
RES UNNEST \ ADDRESS OF UNNEST
--------------------------------------------------------------------------
DIRECT THREADED CODE (DTC):
The basic idea behind DTC is more speed at the expense of compactness
(i.e., one level of indirection has been removed from ITC).
Here's a possible DTC implementation:
NEST: \ ALL COLON DEFINITIONS JUMP HERE
PUSH IP \ SAVE OLD/NEXT IP
REG <- IP - 1 \ GET CURRENT IP
REG <- [IP] \ GET CFA ADDRESS
IP <- [IP + 1] \ LOAD NEW IP
\ NOTE: IP+1 CONTAINS PFA
\ THIS ASSUMES "JMP NEST" TAKES ONE
\ WORD OF STORAGE
\ FALL-THRU TO NEXT
NEXT: \ INCREMENT IP AND JUMP TO IP
REG <- [IP] \ GET CURRENT CFA ADDRESS
IP <- IP + 1 \ INCREMENT IP FOR NEXT CFA
JMP REG \ DIRECT *NOT INDIRECT* JUMP TO CFA
UNNEST:
POP IP \ RESTORE OLD IP
\ NEXT: -- UNNEST INCLUDES NEXT AS A SUBSET
REG <- [IP] \ GET CURRENT CFA ADDRESS
IP <- IP + 1 \ INCREMENT IP FOR NEXT CFA
JMP REG \ DIRECT *NOT INDIRECT* JUMP TO CFA
Code word definitions would all be of the form:
CODE-WORD:
\ ANY ASSEMBLER CODE YOU LIKE HERE
JMP NEXT
Colon definitions would all be of the form:
COLON-DEFINITION:
JMP NEST \ NOTE: ALL CFA'S CONTAIN CODE!
RES PFA \ ADDRESS OF PFA
PFA:
RES WORD1 \ ADDRESS OF ANY FORTH WORD
RES WORD2 \ CAN BE CODE WORD OR COLON DEFINITION
...
RES UNNEST \ ADDRESS OF UNNEST
--------------------------------------------------------------------------
SUBROUTINE THREADED CODE (STC):
The basic idea behind STC is all-out speed at the expense of compactness
(i.e., all levels of indirection have been removed).
Here's a possible STC implementation:
MACRO NEXT \ INCREMENT IP AND JUMP TO IP
\ NOTE: MACROS ONLY DEFINE CODE TO BE LATER GENERATED/ADDED
REG <- [IP] \ GET CURRENT CFA ADDRESS
IP <- IP + 1 \ INCREMENT IP FOR NEXT CFA
JMP REG \ DIRECT JUMP TO CFA
END-MACRO
MACRO NEST
PUSH IP \ SAVE OLD/NEXT IP
IP <- $+4 \ PFA 4 INSTRUCTIONS DOWN
\ I.E., PAST NEXT MACRO
\ NOTE: YOU COULD ALSO BE SNEAKY HERE AND
\ LOAD IP WITH THE *SECOND* PFA ADDRESS,
\ LOAD REG WITH THE *FIRST* PFA ADDRESS,
\ AND JMP REG
NEXT \ MACROS CAN BE NESTED
END-MACRO
MACRO UNNEST
RES UP \ ADDRESS OF "REAL" UNNEST
END-MACRO
UP: \ THIS IS THE "REAL" UNNEST!
POP IP \ RESTORE OLD IP
NEXT \ MACROS CAN BE NESTED
Code word definitions would all be of the form:
CODE-WORD:
\ ANY ASSEMBLER CODE YOU LIKE HERE
NEXT \ INVOKE NEXT MACRO
\ GENERATES IN-LINE CODE
Colon definitions would all be of the form:
COLON-DEFINITION:
NEST \ INVOKE NEST MACRO
\ GENERATES IN-LINE CODE
RES WORD1 \ ADDRESS OF ANY FORTH WORD
RES WORD2 \ CAN BE CODE WORD OR COLON DEFINITION
...
UNNEST \ ADDRESS OF UNNEST/UP
--------------------------------------------------------------------------
Assuming that I haven't screwed something up here (which is *highly*
unlikely!) - this stuff should work when translated to a real machine
architecture and modified for the particular requirements of the Forth
threaded machine environment.
At any rate, it should give an idea of what I meant when I previously
used the terms NEXT, NEST, UNNEST, ITC, DTC, and STC.
Hope this helps to explain where I'm coming from. If it don't - then
sorry - but this is getting to be more work than I'd bargained for!
( George)