news:074e4320-111b-4352...@z4g2000pbz.googlegroups.com...
> On Jun 14, 8:31 pm, "Rod Pemberton" <do_not_h...@notemailntt.cmm>
> wrote:
...
> > [snip]
> >
> I can't see why you'd want a fixed length header, [...]
>
Originally, it was a result of the C backend. It's also needed to provide
fixed offsets to access the header's fields in Forth. I.e., CFA is always a
fixed offset from the start of the header, ... for high-level Forth words.
DOES> (CREATE) RECURSE >BODY :NONAME WORDS all use
CFA's offset, etc.
Simplified slightly, I declare a fixed element struct for the header
(pointer to typedef'd struct). The offsets to the struct's elements are
passed to the Forth side as initial values of Forth constants (pre-compiled
dictionary entries) or LITs in other Forth words (ditto ...). The header
struct could be rewritten as variable length. Then, I'd need some data
which is sometimes present, sometimes not. Perhaps, I could move DSL
there...
> > AIR, placing something in the PFA was causing data to shift
> > or be in unexpected locations.
>
> Which PFA? The PFA of the created word, or the sub-PFA
> following DOES>
Either...
I thought you said "sub-PFA following DOES>" was the word with
the EXIT and address afterwards. But, that's the same as the earlier
problem, or so I thought. So, I took it to mean "PFA of the created
word" instead. I think that too leads to the same result, but just in a
different word...
> If from your header, you can *infer* the PFA of the created
> word from information available when the CREATEd word
> is executed [...] which you should have in your interpreter
> process, then the DOES> runtime can use that to place the
> PFA address on the stack when it executes. That eliminates
> the need to store the PFA of the created word.
Either you've lost me, or I've lost you.
The PFA of the created word *is* placed onto the stack. That's
the DOVAR like portion of DODOES routine.
My DSL field is the address needed by the interpreter for the
"sub-PFA following DOES>". DSL is the replacement for W
needed by the ENTER like portion of the DODOES routine.
Can we go to "pictures"?
: XXX CREATE 2 , DOES> @ ;
I've ignored the BIT field which has the MSB and IMMEDIATE
bit, a.k.a. precedence bit, set for both XXX and ZZZ below.
XXX is:
\ header
<LFA= address of last dictionary header >
<NFA= XXX >
<PTR= address of CFA of XXX >
\ body
<DSL= unused >
<CFA= ENTER -> pointer to C function >
<PFA 1= address of CREATE >
<PFA 2= address of LIT >
<PFA 3= value 2 >
<PFA 4= address of , (comma) >
<PFA 5= address of DOES> >
<PFA 6= address of @ >
<PFA 7= address of EXIT >
XXX ZZZ
ZZZ is:
\ header
<LFA= address of last dict. header, i.e., XXX >
<NFA= ZZZ >
<PTR= address of CFA of ZZZ >
\ body
<DSL= address of DOES> code in XXX >
<CFA= DODOES -> pointer to C function >
<PFA 1= value 2 >
<PFA 2= not allocated or used yet >
When ZZZ is executed, the ZZZ's CFA field is retrieved by the ITC inner
interpreter. It has the pointer to the C function DODOES. DODOES, places
the address for the start of the PFA of ZZZ onto the stack, i.e., address of
PFA 1 in the pictogram, then retrieves the address in DSL which is the
address for the DOES> code in XXX, i.e., @, and transfers interpreter
"execution" to the DOES> code in XXX.
FYI, DOES> is high-level Forth, but DODOES is low-level, i.e., C code.
You're saying the DSL can be removed. In which case, DSL can be removed
from either XXX (defining) or ZZZ (CREATEd).
A) If I remove DSL in ZZZ (CREATEd), how do I find the (your words) "sub-PFA
following DOES>" or (my words) "address of DOES> code" in XXX? I can't put
ZZZ's DSL into the ZZZ's CFA since it's not a pointer to a C function (more
below). ZZZ's DSL value is an interpretable address, i.e., needs ENTER.
Except via ZZZ's DSL, ZZZ doesn't "know" where XXX is (or any part thereof).
If ZZZ's DSL can't be stored into ZZZ's CFA and ZZZ's DSL is removed, then
the address that was in ZZZ's DSL must be stored elsewhere within ZZZ, yes?
I.e., there is no other way to find it. E.g., an attempt can be made to
store it afterwards, but number of consumed fields in the body is unknown.
That depends on what is between CREATE ... DOES> in the defining word.
How do you find the end of the CREATEd definition?
The problem here is that my CFA fields must contain a pointer to a C
function, declared a certain way. The DSL value is an interpretable
address. An interpretable address needs an ENTER or >R and ; (semis) to
begin interpretation. I don't know how to get ENTER to be executed if the
CFA was an interpretable address, except by making all CFAs interpretable
addresses. I.e., mixing types of CFAs (two different) causes an issue. If
there are executable CFAs and interpretable CFAs, how do I determine which
needs an ENTER and which doesn't?
B) If I remove DSL in XXX (defining), that saves a field. But, that has at
least two issues:
1) The relationship between the header and body isn't fixed for high-level
Forth words. For high-level Forth words, the header and body are
contiguous, with header first. (Pre-compiled Forth in C is reversed: body
first.) So, if XXX's DSL is removed, the constants for the field offsets
for CFA, PFA, DSL, etc for high-level Forth words aren't fixed. These
offsets are passed from C to Forth via Forth constants. E.g.,
CREATE >BODY etc use those offsets. I.e., the words using the constants
would work for high-level Forth words without DSL or vice-versa,
but not both, unless I had "intelligent" "adapting" constants ...
2) If the "sub-PFA following DOES>" address is stored in ZZZ at PFA 2 and a
Forth sequence stores to PFA 3, PFA 4, etc... after ZZZ is created, then
there'll be confusion when coding the "sub-PFA following DOES>" about where
to expect that data. I.e., the code for the "sub-PFA following DOES>" might
expect the data to start at PFA 2, but it'll start at PFA 3 if the address
for the "sub-PFA following DOES>" is stored at PFA 2. As mentioned
previously, I was thinking about strings or tables being stored after
a word was CREATEd.
Reiterating, currently, my DOES> and DODOES do just a couple of things:
DOES>
1) writes DODOES into the CFA (overwriting DOVAR)
2) writes the DOES> address into DSL
DODOES
1) pushes PFA onto the data stack, i.e., DOVAR
2) saves the current IP on the return stack, begins interpreting at the
DOES> address, i.e., a modified ENTER (which normally transfers to W)
E.g., DOES> is the following, but parts of the sequence are
customized to my Forth:
: DOES>
LIT DODOES ( address of CFA of CREATEd word ) !
R> ( address of DSL of CREATEd word ) !
;
R> points to the DOES> code when the defining word with the
CREATE ... DOES> sequence is executed, i.e., "sub-PFA following DOES>".
DODOES could be written in high-level Forth, if IP and W are Forth
variables:
: DODOES
\ this is DOVAR
W
\ this is ENTER modified for DSL instead of W
IP >R
( address of DSL of current word ) @ IP !
;
That assumes the independence from other intracacies, e.g., off-by-one,
ability to set the correct IP within an interpreting word (delayed until
EXIT ... ?), etc.
Rod Pemberton