Background: The heads table is like a cut-down version of the Forth dictionary, that only records the entry point of each word, rather than the entry point, name and backlink. Heads are needed for mapping token numbers in *.seed files to addresses.
As mentioned in the previous PR, I wanted to make it so that heads are not created during seedForthInteractive -- because now that execution tokens are simply addresses, heads are not needed once we have loaded and started the *.seed file.
To do this, I have modified the new and create words so that creation of heads is now a caller responsibility. The revised new and create words simply return the here address as it was before creating the code field of the newly created token.
For reference see, for example, /i386/seedForth-i386.pre where it defines the new and create words. The updated way:
: new ( -- xt )
here lit enter , ;
: create ( -- xt )
0 , \ dummy does> field
here lit dovar , ;
And then see /common/seedForth.pre where it refers to the new word. The updated way:
: fun ( -- )
new h, compiler ;
It's pleasing that we can now do something sensible with the address returned by new, rather than the old new drop.
Inserting a call to h, after create is harder. Consider the seedForth code in /common/seedForthRuntime.seedsource:
Definer Variable ( <name> -- ) create ( x ) drop 0 , ;
Compare with the corresponding textual Forth code in /common/runtime.forth which is used with seedForthInteractive:
: Variable ( <name> )
Create 0 , ;
My analysis is that Definer is a seedForthism, which does not exist in standard Forth, and which behaves like :, but gives the tokenizer a hook so that it can capture the name of the new word being defined, here Variable, create a token for it, and thus keep the token numbering in sync. And we can see that the usage is identical, i.e. the two definitions are the same, except that : is replaced with Definer in the seedForth source. To preserve this equivalence, what I've done is to have the tokenizer insert the sequence here h, in the start of the Definer-body, somewhat as if the user had executed the following definition:
Definer Variable ( <name> -- ) here h, create ( x ) drop 0 , ;
Of course we could make this a user responsibility, in which case the user would have to write this (somewhat more pleasing):
But, I considered it too difficult for the user if they have to deviate too much from standard Forth. What do you think about it?
Update: I have just noticed that the create ( x ) drop sequence is also a seedForthism, as compared with standard Forth where Create doesn't seem to return an execution token (see the /common/runtime.forth snippet I showed above). Because of this we might have some more latitude to change things, such as requiring the user to call create (x) h,. But I'm not sure.
Background: The heads table is like a cut-down version of the Forth dictionary, that only records the entry point of each word, rather than the entry point, name and backlink. Heads are needed for mapping token numbers in
*.seed
files to addresses.As mentioned in the previous PR, I wanted to make it so that heads are not created during seedForthInteractive -- because now that execution tokens are simply addresses, heads are not needed once we have loaded and started the
*.seed
file.To do this, I have modified the
new
andcreate
words so that creation of heads is now a caller responsibility. The revisednew
andcreate
words simply return thehere
address as it was before creating the code field of the newly created token.For reference see, for example,
/i386/seedForth-i386.pre
where it defines thenew
andcreate
words. The updated way:And then see
/common/seedForth.pre
where it refers to thenew
word. The updated way:It's pleasing that we can now do something sensible with the address returned by
new
, rather than the oldnew drop
.Inserting a call to
h,
aftercreate
is harder. Consider the seedForth code in/common/seedForthRuntime.seedsource
:Compare with the corresponding textual Forth code in
/common/runtime.forth
which is used withseedForthInteractive
:My analysis is that
Definer
is a seedForthism, which does not exist in standard Forth, and which behaves like:
, but gives the tokenizer a hook so that it can capture the name of the new word being defined, hereVariable
, create a token for it, and thus keep the token numbering in sync. And we can see that the usage is identical, i.e. the two definitions are the same, except that:
is replaced withDefiner
in the seedForth source. To preserve this equivalence, what I've done is to have the tokenizer insert the sequencehere h,
in the start of the Definer-body, somewhat as if the user had executed the following definition:Of course we could make this a user responsibility, in which case the user would have to write this (somewhat more pleasing):
But, I considered it too difficult for the user if they have to deviate too much from standard Forth. What do you think about it?
Update: I have just noticed that the
create ( x ) drop
sequence is also a seedForthism, as compared with standard Forth whereCreate
doesn't seem to return an execution token (see the/common/runtime.forth
snippet I showed above). Because of this we might have some more latitude to change things, such as requiring the user to callcreate (x) h,
. But I'm not sure.