Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

:NONAME

151 views
Skip to first unread message

Mark Wills

unread,
Apr 12, 2012, 4:48:19 PM4/12/12
to
I think I read the other day, :NONAME pushes an xt on the stack
allowing the compiled word to be executed with EXECUTE.

I take it that LATEST and HERE are *not* changed when a :NONAME
definition is built? I.e the word is fleeting - it exists for as long
as you have the XT, and is overwritten by the next compiling activity,
such as , CREATE : etc

Would that be accurate?

Mark

Zbiggy

unread,
Apr 12, 2012, 6:08:32 PM4/12/12
to
In comp.lang.forth, Mark Wills wrote:

> I think I read the other day, :NONAME pushes an xt on the stack
> allowing the compiled word to be executed with EXECUTE.
>
> I take it that LATEST and HERE are *not* changed when a :NONAME
> definition is built?

Why? IMHO HERE _has_ to be changed, when new definition has been added.
New xt is a proof, that you've got another tool at your disposal. It's
definition could be overwritten, if HERE would stay at its earlier address.
--
Forth is a preserver of health (Hippocrates)

Andrew Haley

unread,
Apr 12, 2012, 5:53:23 PM4/12/12
to
Mark Wills <markrob...@yahoo.co.uk> wrote:
> I think I read the other day, :NONAME pushes an xt on the stack
> allowing the compiled word to be executed with EXECUTE.
>
> I take it that LATEST and HERE are *not* changed when a :NONAME
> definition is built?

LATEST must be: you need RECURSE to work; RECURSE calls LATEST. HERE
has to change too, because that's probably where the code goes.

Andrew.

BruceMcF

unread,
Apr 12, 2012, 5:54:22 PM4/12/12
to
Nope, its completely backwards.

(1) If any data space has been allocated ~ including the common
situation where code space is in data space and so every single word
compiled allocates data space ~ HERE *must* change.

(2) Whatever DOES> uses to work out what to modify when it executed,
then :NONAME *must* update that.

The word is not fleeting, otherwise you couldn't put the XT in a
constant or a vector table for later execution.

Elizabeth D. Rather

unread,
Apr 12, 2012, 7:54:48 PM4/12/12
to
No.

As others have pointed out, the code very definitely goes in the
dictionary and is there permanently (unless discarded by, e.g., MARKER).
HERE will be modified if the implementation combines code and data
space. LATEST will definitely change. In other words, this is a
definition like any other colon definition except that it does not have
a FINDable name; access is only through its xt.

Cheers,
Elizabeth

--
==================================================
Elizabeth D. Rather (US & Canada) 800-55-FORTH
FORTH Inc. +1 310.999.6784
5959 West Century Blvd. Suite 700
Los Angeles, CA 90045
http://www.forth.com

"Forth-based products and Services for real-time
applications since 1973."
==================================================

The Beez

unread,
Apr 13, 2012, 2:50:14 AM4/13/12
to
On Apr 12, 11:53 pm, Andrew Haley <andre...@littlepinkcloud.invalid>
wrote:
> LATEST must be: you need RECURSE to work; RECURSE calls LATEST.  HERE
> has to change too, because that's probably where the code goes.
True, otherwise anonymous recursion won't work. I have some experience
there myself.

Hans Bezemer

Mark Wills

unread,
Apr 13, 2012, 2:58:54 AM4/13/12
to
On Apr 12, 10:54 pm, BruceMcF <agil...@netscape.net> wrote:
>
> The word is not fleeting, otherwise you couldn't put the XT in a
> constant or a vector table for later execution.

There doesn't seem to be much point in it then, quite frankly. I mean,
it gets compiled, and leaves it's xt. Wowee. You mean like:

: thing ... ;
' thing

Am I missing something here?

Elizabeth D. Rather

unread,
Apr 13, 2012, 3:11:30 AM4/13/12
to
Not really.

The theory is that you can do something like:

DEFER FOO
:noname <default action> ; IS FOO
:noname <option1> ; CONSTANT OPTION1
:noname <option2> ; CONSTANT OPTION2

OPTION1 IS FOO

...and this vector to your favorite option.

I'm with you on this one. I don't see much point, but there are those
who love it.

Ian Osgood

unread,
Apr 13, 2012, 7:31:23 AM4/13/12
to
Sometimes you only want to refer to a word by index rather than by
name. :NONAME gives you a mechanism to create an array of functions
without filling the dictionary with meaningless function names.

http://rosettacode.org/wiki/Roman_numerals/Encode#Forth

Also, :NONAME/DEFER gives you a mechanism for forward declaration
which is otherwise absent, for implementing things like vectored
execution and mutual recursion.

Ian

BruceMcF

unread,
Apr 13, 2012, 8:15:27 AM4/13/12
to
All you're missing with :NONAME is the "thing" name. It can be useful
as a factor in some situations, since if what you want is an xt to
work with rather than a name, you don't have to come up with a dummy
name. Look up mini-oof and its examples to see a common scenario where
some people like to use it.

One assumes that the name comes from the following pattern to get the
same effect by hand in a fairly self-documenting way ~ if MyVector is
an XT vector that has been previously allocated, and is filled up one
at a time by "AppendXT", then ...

: NONAME ( ... ) ... ;
' NONAME MyVecter AppendXT

BruceMcF

unread,
Apr 13, 2012, 8:34:12 AM4/13/12
to
On Apr 12, 5:53 pm, Andrew Haley <andre...@littlepinkcloud.invalid>
wrote:
RECURSE has to somehow work out what the current definition is. If it
does that by calling LATEST, then either LATEST must change, or else
RECURSE written to call something else.

Andrew Haley

unread,
Apr 13, 2012, 9:00:59 AM4/13/12
to
Mark Wills <markrob...@yahoo.co.uk> wrote:
Not really. It's just a small useful factor. There are many cases
where you need to define a word but don't need to give it a name.

defer factor

...

:noname ... ; is factor

is by far the nicest way to do it. And, IMO, it provides a perfectly
decent way to do recursion without RECURSE , but I may be in a
minority of one with that opinion!

Andrew.

Andrew Haley

unread,
Apr 13, 2012, 9:02:18 AM4/13/12
to
BruceMcF <agi...@netscape.net> wrote:
> On Apr 12, 5:53?pm, Andrew Haley <andre...@littlepinkcloud.invalid>
> wrote:
>> Mark Wills <markrobertwi...@yahoo.co.uk> wrote:
>> > I think I read the other day, :NONAME pushes an xt on the stack
>> > allowing the compiled word to be executed with EXECUTE.
>
>> > I take it that LATEST and HERE are *not* changed when a :NONAME
>> > definition is built?
>
>> LATEST must be: you need RECURSE to work; RECURSE calls LATEST. ?HERE
>> has to change too, because that's probably where the code goes.
>
> RECURSE has to somehow work out what the current definition is. If it
> does that by calling LATEST, then either LATEST must change, or else
> RECURSE written to call something else.

But LATEST is defined simply as the word with this functionality: it
points to the latest definition. It doesn't have to be called LATEST,
obviously.

Andrew.

Mark Wills

unread,
Apr 13, 2012, 9:19:58 AM4/13/12
to
On Apr 13, 2:00 pm, Andrew Haley <andre...@littlepinkcloud.invalid>
wrote:
> :noname ... ; is factor

But hang on... if you needed to assign the anonymous definition to a
defferred word, then it *did* need a name, didn't it?!

:-)

BruceMcF

unread,
Apr 13, 2012, 10:26:45 AM4/13/12
to
On Apr 13, 9:02 am, Andrew Haley <andre...@littlepinkcloud.invalid>
wrote:
The question is how the functionality is provided ~ in a system with
no headerless definitions, pointing to the most recently created
dictionary entry works to get to the most recently created definition.
But if its sometimes used to get the most recent definition, and
sometimes used to get the most recently created dictionary entry, then
those two uses have to be split up if support for headerless
definition is added.

BruceMcF

unread,
Apr 13, 2012, 10:33:37 AM4/13/12
to
Yes, in that use :noname avoids having to define two names for the
same thing when the second name is only used once, to tick it:

: factor-defn ... ;
' factor-defn is factor

Rod Pemberton

unread,
Apr 13, 2012, 11:54:36 AM4/13/12
to
"Elizabeth D. Rather" <era...@forth.com> wrote in message
news:LOOdnQg-lPDU9hrS...@supernews.com...
> On 4/12/12 10:48 AM, Mark Wills wrote:
> > [asked about :NONAME]
>
> As others have pointed out, the code very definitely goes in the
> dictionary and is there permanently (unless discarded by, e.g., MARKER).
> HERE will be modified if the implementation combines code and data
> space. LATEST will definitely change. In other words, this is a
> definition like any other colon definition except that it does not have
> a FINDable name; access is only through its xt.
>

"... except that it does not have a FINDable name ..."

Interesting...

You stated that somewhat differently than the other replies and that brings
up an interesting question. I.e., I took some of the other replies to
indicate that :NONAME creates a headerless word. However, your reply
indicates it only needs to be unFINDable. I see no requirement in ANS that
:NONAME words be headerless. So, if a name field is empty for a normal
: (colon) definition, then the word is not findable even though the name
field itself is still present. (yes?) So, is it possible to define :NONAME
using : (colon) and then clear out the name field afterwards? E.g., after
: (colon) definition has called CREATE it should be possible to use LATEST
and >NAME and FILL to wipe the name. Alternately, maybe :NONAME
should be defined using CREATE ... E.g., I'd probably attempt to start with
a rough definition somewhat like so, just guessing:

: :NONAME : LATEST >NAME COUNT FILL ;

In fact, with one remaining error, this works for my Forth (with LAST
instead of LATEST):

: :NONAME : LAST @ LINK> DUP >NAME DUP BL SWAP C! CHAR+ 0 SWAP C! ;

"LAST @ LINK>" gets the CFA, i.e., "xt", and DUP leaves a copy for "xt" on
the stack, as required. >NAME gets the NFA. The rest clears the name. I'm
using C style null-terminated strings, not counted strings like nearly ever
Forth. So, it writes a space and zero to clear the name string. You'd have
to write a count of one and a space, and remove the zero char code if
modifying it for a normal Forth.

The remaining error, which I think is fixable, is that it still needs a
name.

I.e., instead of:
:NONAME 1 . ;

It needs, using XX for the name:
:NONAME XX 1 . ;

Now, I just need to figure out how to automatically fill the name in with
something ... unless it needs to be headerless too ...


Rod Pemberton


Mark Wills

unread,
Apr 13, 2012, 1:23:45 PM4/13/12
to
On Apr 13, 4:54 pm, "Rod Pemberton" <do_not_h...@notemailnot.cmm>
wrote:
> "Elizabeth D. Rather" <erat...@forth.com> wrote in messagenews:LOOdnQg-lPDU9hrS...@supernews.com...
Well, like you say, it doesn't have to be headless so you might as
well negate the length or something so that the word is never found.
Nice and simple!

Albert van der Horst

unread,
Apr 13, 2012, 3:40:30 PM4/13/12
to
In article <ba539ad0-31f9-4f97...@v7g2000pbs.googlegroups.com>,
Ian Osgood <ia...@quirkster.com> wrote:
>On Apr 12, 11:58=A0pm, Mark Wills <markrobertwi...@yahoo.co.uk> wrote:
>> On Apr 12, 10:54=A0pm, BruceMcF <agil...@netscape.net> wrote:
>>
>>
>>
>> > The word is not fleeting, otherwise you couldn't put the XT in a
>> > constant or a vector table for later execution.
>>
>> There doesn't seem to be much point in it then, quite frankly. I mean,
>> it gets compiled, and leaves it's xt. Wowee. You mean like:
>>
>> : thing ... ;
>> ' thing
>>
>> Am I missing something here?
>
>Sometimes you only want to refer to a word by index rather than by
>name. :NONAME gives you a mechanism to create an array of functions
>without filling the dictionary with meaningless function names.
>
> http://rosettacode.org/wiki/Roman_numerals/Encode#Forth
>
>Also, :NONAME/DEFER gives you a mechanism for forward declaration
>which is otherwise absent, for implementing things like vectored
>execution and mutual recursion.

I just coded mutula recursion for an Euler problem.

VARIABLE G'
: HH ... G' @ EXECUTE ... ;
: G .... ;
' G G' !

The reason: I find it hard to remember how to use DEFER.
It also doesn't make it any more concise.

A similar thing with class methods:

class DISASSEMBLE-ITEM
...
M: DISASSEMBLE @ EXECUTE M;
M: DEFINE-DISASSEMBLER ! M; 0 ,
...

endclass

DEFINE-DISASSEMBLER is used to fill in a virtual method.
No need for a special syntax for "inheritance".

N.B. In my class system, M: is like DOES>
Both methods get the address from where the 0 is stored.

>
>Ian

Groetjes Albert

--
--
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

BruceMcF

unread,
Apr 13, 2012, 4:02:10 PM4/13/12
to
On Apr 13, 11:54 am, "Rod Pemberton" <do_not_h...@notemailnot.cmm>
wrote:

> You stated that somewhat differently than the other replies and that brings
> up an interesting question.  I.e., I took some of the other replies to
> indicate that :NONAME creates a headerless word.

:NONAME *permits* a system to create a headerless word. It doesn't
*require* a system to create a headerless word. For instance, if your
FIND traps up front for zero length words, you could just create a
header with a 0-length name. You have a redundant dictionary entry
link, but don't have to modify a compiler model that assumes that all
definitions have a dictionary entry.

Mark Wills

unread,
Apr 13, 2012, 4:06:52 PM4/13/12
to

>   :NONAME XX 1 . ;
>
> Now, I just need to figure out how to automatically fill the name in with
> something ... unless it needs to be headerless too ...
>
> Rod Pemberton

Hopefully you have a word such as HEADER, which takes a string length/
address pair and creates a linked entry in the dictionary. It's a
useful factor for : CREATE CONSTANT VARIABLE et al.

My earlier suggestion of negating the length won't work - it'll break
FIND. Might as well create a word with two spaces as its name... Find
won't find it

BruceMcF

unread,
Apr 13, 2012, 6:57:33 PM4/13/12
to
Wrapping a FIND (or equivalent) that does not trap zero-length strings
to fail immediately on a zero-length string is straightforward:

: FIND ( c-addr -- c-addr 0 | xt 1 | xt -1 )
DUP C@ IF FIND EXIT THEN 0 ;

Then as long as HEADER when presented with a nul string stores the
length but does not attempt to fetch any text ...
0 0 HEADER

... when :NONAME is being defined.

Albert van der Horst

unread,
Apr 13, 2012, 9:05:38 PM4/13/12
to
In article <cbc60ea8-0362-4436...@w5g2000vbp.googlegroups.com>,
Mark Wills <markrob...@yahoo.co.uk> wrote:
>
>> =A0 :NONAME XX 1 . ;
The non-tricky thing to do it is to just call it `` NONAME ''.
Then do `` LATEST HIDDEN '' such that the entry is ignored because
of a flag in the header. (Or you may have SMUDGE )

Rod Pemberton

unread,
Apr 14, 2012, 5:23:28 PM4/14/12
to
"Mark Wills" <markrob...@yahoo.co.uk> wrote in message
news:cbc60ea8-0362-4436...@w5g2000vbp.googlegroups.com...
> RP wrote:
...

> > Now, I just need to figure out how to automatically fill the name in
> > with something ... unless it needs to be headerless too ...
>
> Hopefully you have a word such as HEADER, which takes a string
> length/ address pair and creates a linked entry in the dictionary. It's a
> useful factor for : CREATE CONSTANT VARIABLE et al.

CREATE and : (colon) use (CREATE) . fig-Forth uses CREATE directly in :
(colon) . For some reason, mine uses (CREATE) and either ENTER compiled for
: (colon) or DOVAR compiled for CREATE ... It may be because of the
definitions I chose to use for VARIABLE and CONSTANT . I've been meaning to
look into why exactly and also figure out why fig-Forth is different here.
It's like (CREATE) really should be CREATE ...

CONSTANT VARIABLE VALUE 2CONSTANT 2VARIABLE SET use CREATE
directly. DEFER will too, if I decide it's definition is useful.

> My earlier suggestion of negating the length won't work - it'll break
> FIND. Might as well create a word with two spaces as its name... Find
> won't find it

:-)

As Albert van der Horst pointed out, we could've used SMUDGE. Sigh ...
I guess I'll have to keep it in mind to find out which is trivially quicker.


Rod Pemberton


BruceMcF

unread,
Apr 14, 2012, 7:22:10 PM4/14/12
to
On Apr 14, 5:23 pm, "Rod Pemberton" <do_not_h...@notemailnot.cmm>
wrote:

> CREATE and : (colon) use (CREATE)

I don't see (CREATE) in either the z80 or 6502 fig-forth assembly
listing ~ what is its stack picture?

>> My earlier suggestion of negating the length won't work - it'll break
>> FIND. Might as well create a word with two spaces as its name... Find
>> won't find it

Why two spaces?

CREATE SPACE$ 1 C, 32 C,
: noname ( -- ca u ) SPACE$ COUNT ;

... there's a noname for :NONAME that would only use one.

Rod Pemberton

unread,
Apr 15, 2012, 12:50:45 PM4/15/12
to
"BruceMcF" <agi...@netscape.net> wrote in message
news:0a0b2095-bab4-41c4...@9g2000yqp.googlegroups.com...
> On Apr 14, 5:23 pm, "Rod Pemberton" <do_not_h...@notemailnot.cmm>
> wrote:
...

> > CREATE and : (colon) use (CREATE)
>
> I don't see (CREATE) in either the z80 or 6502 fig-forth
> assembly listing ~ what is its stack picture?

Ok, I wasn't clear enough ...

fig-Forth only uses CREATE . My CREATE and my : (colon) call (CREATE) with
a compiled DOVAR or ENTER , respectively. I was trying to figure out why my
CREATE is "split". I.e., fig-Forth must be compiling only a DOVAR or only a
ENTER/DOCOL, but not both. I'm selectively compiling one or the other.
Why?

> >> My earlier suggestion of negating the length won't work
> >> - it'll break FIND. Might as well create a word with two
> >> spaces as its name... Find won't find it
>
> Why two spaces?
>

I don't know. That was Mark Wills who said that. I'd suspect that either
1) he has a minimum name length issue or 2) he is using a 16-bit Forth and
must write at least 16-bits at a time.


Rod Pemberton




Elizabeth D. Rather

unread,
Apr 15, 2012, 2:12:43 PM4/15/12
to
On 4/15/12 6:50 AM, Rod Pemberton wrote:
> "BruceMcF"<agi...@netscape.net> wrote in message
> news:0a0b2095-bab4-41c4...@9g2000yqp.googlegroups.com...
>> On Apr 14, 5:23 pm, "Rod Pemberton"<do_not_h...@notemailnot.cmm>
>> wrote:
> ...
>
>>> CREATE and : (colon) use (CREATE)
>>
>> I don't see (CREATE) in either the z80 or 6502 fig-forth
>> assembly listing ~ what is its stack picture?
>
> Ok, I wasn't clear enough ...
>
> fig-Forth only uses CREATE . My CREATE and my : (colon) call (CREATE) with
> a compiled DOVAR or ENTER , respectively. I was trying to figure out why my
> CREATE is "split". I.e., fig-Forth must be compiling only a DOVAR or only a
> ENTER/DOCOL, but not both. I'm selectively compiling one or the other.
> Why?

If I'm not mistaken (I'm no expert on figForth) it's because they had
<BUILDS ... DOES> for making defining words, which was a different (and
far less efficient factoring). When CREATE ... DOES> was adopted, the
figForth CREATE had to be factored differently, hence (CREATE) for the
sharable factor that constructs the basic dictionary entry.

BruceMcF

unread,
Apr 15, 2012, 2:17:24 PM4/15/12
to
On Apr 15, 12:50 pm, "Rod Pemberton" <do_not_h...@notemailnot.cmm>
wrote:
> fig-Forth only uses CREATE .  My CREATE and my : (colon) call (CREATE) with
> a compiled DOVAR or ENTER , respectively.  I was trying to figure out why
> my CREATE is "split".  I.e., fig-Forth must be compiling only a DOVAR or
> only a ENTER/DOCOL, but not both.  I'm selectively compiling one or the
> other.
> Why?

Part of updating fig Forth to support CREATE DOES> maybe?

Hugh Aguilar

unread,
Apr 17, 2012, 7:21:41 PM4/17/12
to
On Apr 13, 2:06 pm, Mark Wills <markrobertwi...@yahoo.co.uk> wrote:
> Hopefully you have a word such as HEADER, which takes a string length/
> address pair and creates a linked entry in the dictionary. It's a
> useful factor for : CREATE CONSTANT VARIABLE et al.

That is what my :NAME does --- the Forth-200x committee hated it and
refused to standardize any such thing.

I agree that it makes sense to standardize low-level words such
as :NAME, and to then define the high-level words (colon, etc.) in
terms of the low-level words. As it stands however, colon is defined,
but :NAME is not defined --- in my novice package I have to
define :NAME in terms of colon by constructing a string and then
giving that string to EVALUATE --- this turns the concept of factoring
completely upside-down!

Anton Ertl said that :NAME was trivial to implement in ANS-Forth
(using string construction and EVALUATE) and hence was something that
application programmers could do themselves --- but that there would
be no standard way to do it, so it would be different for everybody
that implemented it --- he's hoping that, given a mish-mash of
incompatible implementations, the casual Forth community will be
discouraged from adopting *any* implementation. Anton Ertl's plan is
to defeat the general Forth community through balkanization, but to
promote Forth Inc. by standardizing everything in SwiftForth
(including trivialities such as BUFFER:) so that SwiftForth
effectively becomes the standard.

Note that when you call it HEADER, and you require an adr/cnt pair,
you are not compatible with my :NAME --- this is the balkanization
that Anton Ertl was hoping for. I don't really care if it is called
HEADER or :NAME (I actually used HEADER originally), or about other
details --- but I do think that it would be a good idea for everybody
to be compatible rather than to differ in trivial details such as the
name of the word.

This is my :NAME word:

: :name ( str wid -- )
get-current >r set-current
<cstr
c" : " +cstr +cstr c" " +cstr
cstr> count evaluate
r> set-current ;

This depends upon <CSTR for string construction. All of this is in the
novice package:
http://www.forth.org/novice.html
Note that "wid" is the ANS-Forth term for "word-list identifier" ---
basically a vocabulary number.

Hugh Aguilar

unread,
Apr 23, 2012, 2:13:40 AM4/23/12
to
On Apr 13, 1:11 am, "Elizabeth D. Rather" <erat...@forth.com> wrote:
> On 4/12/12 8:58 PM, Mark Wills wrote:
>
> > On Apr 12, 10:54 pm, BruceMcF<agil...@netscape.net>  wrote:
>
> >> The word is not fleeting, otherwise you couldn't put the XT in a
> >> constant or a vector table for later execution.
>
> > There doesn't seem to be much point in it then, quite frankly. I mean,
> > it gets compiled, and leaves it's xt. Wowee. You mean like:
>
> > : thing ... ;
> > ' thing
>
> > Am I missing something here?
>
> Not really.
>
> The theory is that you can do something like:
>
> DEFER FOO
> :noname <default action> ;  IS FOO
> :noname <option1> ; CONSTANT OPTION1
> :noname <option2> ; CONSTANT OPTION2
>
> OPTION1 IS FOO
>
> ...and this vector to your favorite option.
>
> I'm with you on this one. I don't see much point, but there are those
> who love it.
>
> Cheers,
> Elizabeth

See this thread for an example of :NONAME being used:
https://groups.google.com/group/comp.lang.forth/browse_thread/thread/dd8e30fcc7589749

Rod Pemberton

unread,
Jun 1, 2012, 8:13:17 PM6/1/12
to
"Rod Pemberton" <do_no...@notemailnot.cmm> wrote in message
news:jm9i7n$u44$1...@speranza.aioe.org...
> ever[y] Forth. So, it writes a space and zero to clear the name string.
> You'd have to write a count of one and a space, and remove the zero char
> code if modifying it for a normal Forth.
>
> The remaining error, which I think is fixable, is that it still needs a
> name.
>
> I.e., instead of:
> :NONAME 1 . ;
>
> It needs, using XX for the name:
> :NONAME XX 1 . ;
>
> Now, I just need to figure out how to automatically fill the name in with
> something ... unless it needs to be headerless too ...
>

Apparently, the solution is to not create the header in the first place ...
I.e., headerless.

It seems that that's done by using the definition for : (colon) but
replacing CREATE or (CREATE) with HERE.


In my case, : (colon) is (written in high-level Forth):

: : (CREATE) COMPILE ENTER ] SMUDGE ;

So, :NONAME becomes:

: :NONAME HERE COMPILE ENTER ] SMUDGE ;

Or, if replacing COMPILE with LIT <word> , (comma) sequence:

: :NONAME HERE LIT ENTER , ] SMUDGE ;


Rod Pemberton



Rod Pemberton

unread,
Jun 1, 2012, 9:09:50 PM6/1/12
to
"Rod Pemberton" <do_no...@notemailntt.cmm> wrote in message
news:jqblpa$au0$1...@speranza.aioe.org...
Well, it's got no header any longer, so it shouldn't need SMUDGE anymore...

Fortunately, the way I wrote SMUDGE it doesn't corrupt the body of the prior
word in the dictionary. It will SMUDGE the last valid definition with a
header via LAST, though. So, that's not good, but not serious, and quickly
fixable...


Rod Pemberton


Rod Pemberton

unread,
Jun 1, 2012, 9:41:18 PM6/1/12
to
"Rod Pemberton" <do_no...@notemailnot.cmm> wrote in message
news:jqbp3b$hrq$1...@speranza.aioe.org...
Unfortunately, ; (semicol) will still SMUDGE. SMUDGE needs to be paired,
but SMUDGE is no longer paired with the SMUDGE in ; (semicol) if :NONAME has
no SMUDGE. Let's see what happens.

a) : (colon) and ; (semicol)
: (colon) will SMUDGE the current definition.
; (semicol) will SMUDGE the current definition.
SMUDGE is paired.
For this situation, it doesn't matter if SMUDGE sets or toggles.

b) :NONAME with SMUDGE and ; (semicol)
:NONAME with SMUDGE will SMUDGE the last definition with a header.
; (semicol) will SMUDGE the last definition with a header.
SMUDGE is paired.
For this situation, it doesn't matter if SMUDGE sets or toggles.

c) :NONAME without SMUDGE and ; (semicol)
:NONAME without SMUDGE won't SMUDGE.
; (semicol) will SMUDGE the last definition with a header.
SMUDGE is not paired. It's only in ; (semicol).
A SMUDGE which sets won't corrupt the state of SMUDGE.
A SMUDGE which toggles will corrupt the state of SMUDGE.

I recently asked about SMUDGE setting or toggling. Apparently, the
introduction of :NONAME created a situation where setting may be preferred
to toggling. Alternately, keeping SMUDGE in :NONAME should work too.


Rod Pemberton



Coos Haak

unread,
Jun 2, 2012, 9:06:56 AM6/2/12
to
Op Fri, 1 Jun 2012 21:41:18 -0400 schreef Rod Pemberton:
Can't you use a word that HIDE a definition and REVEAL it when needed. They
may be implemented by resetting of setting a flag in the header (or
breaking and making a link, as I do) respectively.

Get rid of that antique and hopelessly disturbing word SMUDGE that may set
or reset a bit but also can toggle a bit. There is not a recent standard in
sight that defines SMUDGE.

My :NONAME does not make a header, it only generates an xt (or cfa as
want).

--
Coos

CHForth, 16 bit DOS applications
http://home.hccnet.nl/j.j.haak/forth.html

Rod Pemberton

unread,
Jun 11, 2012, 5:42:25 AM6/11/12
to
"Coos Haak" <chf...@hccnet.nl> wrote in message
news:1aemzp8elrrl1.h...@40tude.net...
> Op Fri, 1 Jun 2012 21:41:18 -0400 schreef Rod Pemberton:
...

> > [snip]
>
> My :NONAME does not make a header, it only generates an xt
> (or cfa as want).

Does your :NONAME work with RECURSE?


Rod Pemberton



Rod Pemberton

unread,
Jun 11, 2012, 5:46:18 AM6/11/12
to
"Rod Pemberton" <do_no...@notemailntt.cmm> wrote in message
news:jqblpa$au0$1...@speranza.aioe.org...
> "Rod Pemberton" <do_no...@notemailnot.cmm> wrote in message
> news:jm9i7n$u44$1...@speranza.aioe.org...

[snip]

> > I.e., I took some of the other replies to indicate that :NONAME
> > creates a headerless word. However, [ER's] reply indicates it only
> > needs to be unFINDable. I see no requirement in ANS
> > that :NONAME words be headerless.
> >
> > [RP solution]
> >
>
> Apparently, the solution is to not create the header in the first place
> ... I.e., headerless.
>

Well, *that* doesn't work...

If LAST is used to provide the xt for RECURSE, then LAST needs to work for
both : (colon) and :NONAME words, not just : (colon) words. That means
:NONAME words need to have LAST set to them too. If LAST is also used in
locating dictionary fields and initiating searches, then :NONAME words need
a correctly linked header too. A header also ensures SMUDGE on :NONAME
words, if LAST can point to :NONAME words, doesn't corrupt prior dictionary
data.

So, in order to make :NONAME work for my interpreter, *all* of the following
things must work together:

1) :NONAME
2) RECURSE
3) LAST
4) SMUDGE(s)

To do that, a fake or "dummy" header must be constructed for :NONAME words.
If RECURSE in :NONAME words is unnecessary, then no header is needed, i.e.,
truly headerless instead of faked headerless via a blank name or SMUDGE bit.


Rod Pemberton





Alex McDonald

unread,
Jun 11, 2012, 6:46:28 AM6/11/12
to
On Jun 11, 5:46 am, "Rod Pemberton" <do_not_h...@notemailntt.cmm>
wrote:
> "Rod Pemberton" <do_not_h...@notemailntt.cmm> wrote in message
>
> news:jqblpa$au0$1...@speranza.aioe.org...
>
> > "Rod Pemberton" <do_not_h...@notemailnot.cmm> wrote in message
One solution is to have LAST-NAMED-XT and LATEST-XT (or whatever you
wish to call them).

All words that generate a named XT (such as CREATE : and so on) set
both LATEST-XT and LAST-NAMED-XT; then IMMEDIATE and those words that
only work on words with headers utilise LAST-NAMED-XT.

:NONAME only sets LATEST-XT. Words that work with either named or
headerless words such as RECURSE use LATEST-XT. This is the approach
taken by Win32Forth where :NONAMEs are headerless.

: X ... recurse ( uses LATEST-XT ) ;
:noname ... recurse ( uses LATEST-XT ) ; immediate ( uses LAST-NAMED-
XT and acts on X )

Josh Grams

unread,
Jun 11, 2012, 8:17:52 AM6/11/12
to
Rod Pemberton wrote: <jr4enb$rug$1...@speranza.aioe.org>
> In order to make :NONAME work for my interpreter, *all* of the following
> things must work together:
>
> 1) :NONAME
> 2) RECURSE
> 3) LAST
> 4) SMUDGE(s)
>
> To do that, a fake or "dummy" header must be constructed for :NONAME words.
> If RECURSE in :NONAME words is unnecessary, then no header is needed, i.e.,
> truly headerless instead of faked headerless via a blank name or SMUDGE bit.

RECURSE just needs the address of the code, so if you separate that from
LAST then you can get away without a dummy header.

--Josh

Coos Haak

unread,
Jun 11, 2012, 1:08:29 PM6/11/12
to
Op Mon, 11 Jun 2012 05:42:25 -0400 schreef Rod Pemberton:
Of course, Alex McDonald and Josh Grams give the reason why.

Albert van der Horst

unread,
Jun 11, 2012, 9:09:48 PM6/11/12
to
In article <4fd5e1f0$0$6615$882e...@usenet-news.net>,
This is not generally true. For indirect threaded code the code address
is docol (the inner interpreter) and there needs to be some pointer to
the threaded code too.
The best solution for Rod is just make dummy headers for his indirect
threaded Forth. I'm very content with my 100% percent consistent headers
and the careful names such that the most essential fields come first
alphabetically:

CFA
DFA
FFA
LFA
NFA
SFA
XFA

Yes they cost 56 bytes plus the name itself.

>
>--Josh

Rod Pemberton

unread,
Jun 11, 2012, 9:39:08 PM6/11/12
to
"Albert van der Horst" <alb...@spenarnc.xs4all.nl> wrote in message
news:m5hck...@spenarnc.xs4all.nl...
...

> For indirect threaded code the code address
> is docol (the inner interpreter) and there needs
> to be some pointer to the threaded code too.
>
> The best solution for Rod is just make dummy headers for
> his indirect threaded Forth.

The dual variable method they suggested should work, but I'd rather not
create another system variable ...

System variables have some C dependence, whereas the dictionary header
doesn't. Not needing a header will save space in the dictionary, but
otherwise it doesn't seem that much is gained by not having a header. Any
code that updates both last xt variables, e.g., the code for : (colon) or
CREATE, also becomes longer, slower. I don't like wasting space for an
unneeded header or even DOES> link, but I've got plenty of space available
and my header is compact...

Just how many times is :NONAME going to be used in a typical program
anyway? My guess is not very many times. Who bothers to use it instead of
: (colon)? E.g., seems to be special case usage to me...

Also, making sure SMUDGE and IMMEDIATE don't accidentally or even
temporarily corrupt another definition seems like a good thing to me. Since
my SMUDGE is XOR based, I considered letting it corrupt and uncorrupt data
in the prior definition. However, that word was IMMEDIATE and used in the
current definition... boom!

> I'm very content with my 100% percent consistent headers
> and the careful names such that the most essential fields come first
> alphabetically:
>
> CFA
> DFA
> FFA
> LFA
> NFA
> SFA
> XFA
>
> Yes they cost 56 bytes plus the name itself.
>

Originally, I had the NFA and bits first, then switched to LFA first, then
had to switch back temporarily due to implementation issues.

Currently, I'm using 48 bytes for the header, including the name (fixed
size). However, I've placed a few fields into the body:

\ header
LFA (link field pointer)
BIT (name field bits)
NFA (name field)
PTR (address of CFA)

\ body
DSL (for DOES>)
CFA (Forth action - C function)
PFA (variable size, Forth address list)

The header and body are mostly adjacent, but can be located separately. PTR
points to or holds the address of the CFA, not the body. This allows the C
compiler to control the organization of internal, pre-compiled Forth words
coded in C. E.g., the C compiler can place the body above the header.
Primitives, or low-level words, use a different format for the body, just a
CFA field, but they could be setup to use the same...

Having the link field also be the starting address of the dictionary header
simplifies locating the other fields, IMO. No searching for set bits on
name and just offsets. Of course, if you only have the CFA you can't easily
find the header via Forth code, e.g., to get the name. You have to search
the entire list via LFA checking that PTR matches CFA. I decided a second
link from body to header wasn't really needed for this, i.e., low-use...


Rod Pemberton







Alex McDonald

unread,
Jun 12, 2012, 5:08:41 AM6/12/12
to
On Jun 12, 2:39 am, "Rod Pemberton" <do_not_h...@notemailntt.cmm>
wrote:
> "Albert van der Horst" <alb...@spenarnc.xs4all.nl> wrote in messagenews:m5hck...@spenarnc.xs4all.nl...
> ...
>
> > For indirect threaded code the code address
> > is docol (the inner interpreter) and there needs
> > to be some pointer to the threaded code too.
>
> > The best solution for Rod is just make dummy headers for
> > his indirect threaded Forth.
>
> The dual variable method they suggested should work, but I'd rather not
> create another system variable ...

Then make it a 2variable.

>
> System variables have some C dependence, whereas the dictionary header
> doesn't.  Not needing a header will save space in the dictionary, but
> otherwise it doesn't seem that much is gained by not having a header.  Any
> code that updates both last xt variables, e.g., the code for : (colon) or
> CREATE, also becomes longer, slower.  I don't like wasting space for an
> unneeded header or even DOES> link, but I've got plenty of space available
> and my header is compact...

I don't think you'll be able to measure it; how much compile time vs
run time do you expect? Will having headers for :NONAME be more
expensive in terms of space that an extra variable?

>
> Just how many times is :NONAME going to be used in a typical program
> anyway? My guess is not very many times.  Who bothers to use it instead of
> : (colon)?  E.g., seems to be special case usage to me...
>
> Also, making sure SMUDGE and IMMEDIATE don't accidentally or even
> temporarily corrupt another definition seems like a good thing to me.  Since
> my SMUDGE is XOR based, I considered letting it corrupt and uncorrupt data
> in the prior definition.  However, that word was IMMEDIATE and used in the
> current definition... boom!

That sounds like an implementation error or weakness in the internal
structure of the compiler.

>
> > I'm very content with my 100% percent consistent headers
> > and the careful names such that the most essential fields come first
> > alphabetically:
>
> >  CFA
> >  DFA
> >  FFA
> >  LFA
> >  NFA
> >  SFA
> >  XFA
>
> > Yes they cost 56 bytes plus the name itself.
>
> Originally, I had the NFA and bits first, then switched to LFA first, then
> had to switch back temporarily due to implementation issues.
>
> Currently, I'm using 48 bytes for the header, including the name (fixed
> size).  However, I've placed a few fields into the body:
>
> \ header
> LFA  (link field pointer)
> BIT    (name field bits)

What does this contain?

> NFA  (name field)
> PTR  (address of CFA)
>
> \ body
> DSL  (for DOES>)

What is this for?

> CFA  (Forth action - C function)
> PFA  (variable size, Forth address list)

What does this point to?

>
> The header and body are mostly adjacent, but can be located separately.  PTR
> points to or holds the address of the CFA, not the body.  This allows the C
> compiler to control the organization of internal, pre-compiled Forth words
> coded in C.   E.g., the C compiler can place the body above the header.
> Primitives, or low-level words, use a different format for the body, just a
> CFA field, but they could be setup to use the same...
>
> Having the link field also be the starting address of the dictionary header
> simplifies locating the other fields, IMO.  No searching for set bits on
> name and just offsets.  Of course, if you only have the CFA you can't easily
> find the header via Forth code, e.g., to get the name.  You have to search
> the entire list via LFA checking that PTR matches CFA.  I decided a second
> link from body to header wasn't really needed for this, i.e., low-use...
>

Headers are all different, but both of these seem to be in the
heavyweight category. My Forth header is 23 bytes plus name, and that
is with a link, a dual XT to support smart COMPILE, sufficient space
to record stack effects, and the line and file that the word came
from.

> Rod Pemberton

BruceMcF

unread,
Jun 12, 2012, 7:00:45 PM6/12/12
to
On Jun 11, 9:09 pm, Albert van der Horst <alb...@spenarnc.xs4all.nl>
wrote:
> In article <4fd5e1f0$0$6615$882e7...@usenet-news.net>,
> Josh Grams  <j...@qualdan.com> wrote:

>> RECURSE just needs the address of the code, so if you separate that from
>> LAST then you can get away without a dummy header.

> This is not generally true. For indirect threaded code the code address
> is docol (the inner interpreter) and there needs to be some pointer to
> the threaded code too.

this is reading "address of the code" overly literally ~ you need the
address of the Forth code, whether that is pointing to machine
language code, to a "code field" followed by the linked list, or etc.
is obviously implementation dependent, but the general point stands.
If you have HEAD and LASTXT then RECURSE can use LASTXT. CREATE or a
factor of CREATE (eg HEADER) fills HEAD while a common factor of :
and :NONAME (eg DEFINE,) fills LASTXT.

Indeed, :NONAME can then be, if DEFINE, is ( ct: -- x=colon-sys ):

: :NONAME ( ct: -- xt colon-sys ) DEFINE, LASTXT @ SWAP POSTPONE [ ;

Rod Pemberton

unread,
Jun 12, 2012, 11:20:01 PM6/12/12
to
"Alex McDonald" <bl...@rivadpm.com> wrote in message
news:fc93f094-74d9-42f0...@l32g2000yqc.googlegroups.com...
> On Jun 12, 2:39 am, "Rod Pemberton" <do_not_h...@notemailntt.cmm>
> wrote:
> > "Albert van der Horst" <alb...@spenarnc.xs4all.nl> wrote in
> > messagenews:m5hck...@spenarnc.xs4all.nl...

> > > [snip]
> >
> > Just how many times is :NONAME going to be used in a typical program
> > anyway? My guess is not very many times. Who bothers to use it instead
> > of : (colon)? E.g., seems to be special case usage to me...
> >
> > Also, making sure SMUDGE and IMMEDIATE don't accidentally or even
> > temporarily corrupt another definition seems like a good thing to me.
> > Since my SMUDGE is XOR based, I considered letting it corrupt and
> > uncorrupt data in the prior definition. However, that word was IMMEDIATE
> > and used in the current definition... boom!
>
> That sounds like an implementation error or weakness in the internal
> structure of the compiler.

It's fixed now. I created a mostly blank header for :NONAME words.

But, that was in the context that I have a single LAST, which you replied
about a "LATEST-XT" and "LAST-NAMED-XT". I thought you replied
appropriately, but stated again:

If LAST works like "LAST-NAMED-XT" (which it did) and :NONAME doesn't have a
header, then SMUDGE corrupting data is not an issue. SMUDGE works on a
valid header. But, then my RECURSE which used LAST didn't work on the
correct word.

If LAST works like "LATEST-XT" (which it does now) and :NONAME doesn't have
a header, then SMUDGE corrupting data is an issue. SMUDGE is offset based
and works where the header would be if present, but :NONAME doesn't have
header. So, it corrupts data, although if XOR based it undoes it, i.e.,
temporary.

If LAST works like "LATEST-XT" (which it does now) and :NONAME does have a
header, then SMUDGE corrupting data is not an issue and RECURSE using LAST
works too.

> > Currently, I'm using 48 bytes for the header, including the name (fixed

> > size). However, I've placed a few fields into the body:
> >
> > \ header
> > LFA (link field pointer)
> > BIT (name field bits)
>
> What does this contain?

You're not interested in Albert's header? :-) I can guess at some of his
abbreviations, but I don't know what they're for.

It's classic fig-Forth usage... I just didn't know what to name it.

BIT contains 8-bits of which 3 are currently used. Bit7 (the MSB) is set
but not used anywhere, currently. Bit6 is the precedence bit used by
IMMEDIATE. Bit 5 is the SMUDGE bit.

Bit7 was originally used to find the start of a dictionary entry name field.
I use the LFA instead. I plan on using the classic fig-Forth interpreter
loop, or something closer to it than what I've got now. fig-Forth used the
Bit7 for a comparison. So, it maybe used eventually.

The other bits might be used for compile-only or no-execute or created-word.
I think I've eliminated the need for marking created words for >BODY. I.e.,
layouts the same whethere CREATEd or not.

> > NFA (name field)
> > PTR (address of CFA)
> >
> > \ body
> > DSL (for DOES>)
>
> What is this for?

This is a field for the address of where the DOES> code is located for
a word created by CREATE ... DOES> .

BruceMcF (Bruce McFarland) discussed this with me in "dot-quote
implementation question" thread.

FYI, I had already implemented the separation of the header and body before
inserting that field...

> > CFA (Forth action - C function)
> > PFA (variable size, Forth address list)
>
> What does this point to?

Nothing.

Technically, I guess it's the "PF area" and not PFA, or perhaps a bunch of
PFAs... Ms. ER mentions that too. It's just the area of compiled addresses
for a compiled high-level word. I'm assuming one of Albert's is an "area"
too.

> > > Yes the [header] cost [is] 56 bytes plus the name itself.
> > >
> > Currently, I'm using 48 bytes for the header [...]

Sorry, that's 48 bytes for header and the DSL and CFA... They are both
non-body data, but not part of my header, officially. So, without them,
it's 40 bytes, or 8 bytes without the name and bit-fields.

> Headers are all different, but both of these seem to
> be in the heavyweight category.

Well, neither of us stated the size of integers or pointers. Mine are 4
bytes (32-bits).

Perhaps, it's better to state the fields size independently. So, my header
is two pointers, a name field, and a byte for control bits. If I include
the CFA and DSL fields, that's four pointers, a name field, and a byte, for
all the non-body data.

> My Forth header is 23 bytes plus name, and that
> is with a link, a dual XT to support smart COMPILE,
> sufficient space to record stack effects, and the line
> and file that the word came from.

Just to be clear, is "plus" inclusive or exclusive? By "plus", you mean to
"add" the name length, not "plus" as in already "includes" the name length,
yes? That goes for Albert too...


Rod Pemberton



Alex McDonald

unread,
Jun 13, 2012, 3:32:30 AM6/13/12
to
On Jun 13, 4:20 am, "Rod Pemberton" <do_not_h...@notemailntt.cmm>
wrote:
> "Alex McDonald" <b...@rivadpm.com> wrote in message
Does this work in your Forth?

: doubledoes create , does> @ 1+ . does> @ 1- . ; ok
20 doubledoes x ok
x 21 ok
x 19 ok
x 19 ok
23 bytes exclusive of the name with a 32bit ptrs.

begin-structure head%
6 cells - 1+ \ most words return head.nfa
lfield: head.link \ [ link field ] lfa
lfield: head.comp \ [ ' xt-call, ] comp token;
normally xt-call,
lfield: head.ct \ [ ' (compile) ] ct: compile
token action
lfield: head.xtptr \ +---- [ xt ptr field ] xt-ptr
wfield: head.vfa \ | [ view field ] vfa (line#)
wfield: head.ofa \ | [ optimize field ] ofa (length
of code for inline)
wfield: head.ste \ | [ stack effects ] ste
cfield: head.tfa \ | [ type flag ] tfa
cfield: head.nfa \ | [ the name letters ]
6 cells + 1- \ |
end-structure \ |
\ |
\ | [ ct-off ] rel offset to
head.ct
\ +---> [ xt field ] code (the xt)


>
> Rod Pemberton

Albert van der Horst

unread,
Jun 13, 2012, 4:49:14 AM6/13/12
to
In article <97b9afa0-0873-4b69...@p27g2000vbl.googlegroups.com>,
BruceMcF <agi...@netscape.net> wrote:
>On Jun 11, 9:09=A0pm, Albert van der Horst <alb...@spenarnc.xs4all.nl>
>wrote:
>> In article <4fd5e1f0$0$6615$882e7...@usenet-news.net>,
>> Josh Grams =A0<j...@qualdan.com> wrote:
>
>>> RECURSE just needs the address of the code, so if you separate that from
>>> LAST then you can get away without a dummy header.
>
>> This is not generally true. For indirect threaded code the code address
>> is docol (the inner interpreter) and there needs to be some pointer to
>> the threaded code too.
>
>this is reading "address of the code" overly literally ~ you need the
>address of the Forth code, whether that is pointing to machine
>language code, to a "code field" followed by the linked list, or etc.
>is obviously implementation dependent, but the general point stands.
>If you have HEAD and LASTXT then RECURSE can use LASTXT. CREATE or a
>factor of CREATE (eg HEADER) fills HEAD while a common factor of :
>and :NONAME (eg DEFINE,) fills LASTXT.
>
>Indeed, :NONAME can then be, if DEFINE, is ( ct: -- x=3Dcolon-sys ):
>
>: :NONAME ( ct: -- xt colon-sys ) DEFINE, LASTXT @ SWAP POSTPONE [ ;

You're right of course. :NONAME centres on the abstraction of
execution token. If you have an xt, that is the only thing you
ever need to EXECUTE. An xt represents the "address of code".

BruceMcF

unread,
Jun 13, 2012, 1:25:16 PM6/13/12
to
On Jun 12, 11:20 pm, "Rod Pemberton" <do_not_h...@notemailntt.cmm>
wrote:
> "Alex McDonald" <b...@rivadpm.com> wrote in message

> If LAST works like "LAST-NAMED-XT" (which it did) and :NONAME doesn't have a
> header, then SMUDGE corrupting data is not an issue.  SMUDGE works on a
> valid header.  But, then my RECURSE which used LAST didn't work on the
> correct word.

Quite. A factor that makes the bare header ... aka HEADER ... and a
factor that starts a definition ... aka DEFINE, ... would
independently fill HEAD and LASTXT with CREATE calling HEADER and so
filling HEAD while : calls both HEADER and DEFINE, and so fills HEAD
and LASTXT both and :NONAME calls DEFINE, and so fills LASTXT.

RECURSE would use LASTXT and ignore HEAD. DOES> and IMMEDIATE would
use HEAD and ignore LASTXT.

> > > Currently, I'm using 48 bytes for the header, including the name (fixed
> > > size). However, I've placed a few fields into the body:

> > > \ header
> > > LFA (link field pointer)
> > > BIT (name field bits)

> > > NFA (name field)
> > > PTR (address of CFA)

> > > \ body
> > > DSL (for DOES>)
>
> > What is this for?
>
> This is a field for the address of where the DOES> code is located for
> a word created by CREATE ... DOES> .
>
> BruceMcF (Bruce McFarling) discussed this with me in "dot-quote
> implementation question" thread.

Though with PTR it seems that DSL could be omitted, since the c-
function pointer for {DOES} could be portably embedded in the word
containing DOES>, following the EXIT, and the location of the DOES>-
sub-parameter-field inferred as the cell following the one pointed to
by PTR.

Coos Haak

unread,
Jun 14, 2012, 1:24:41 PM6/14/12
to
Op Wed, 13 Jun 2012 10:25:16 -0700 (PDT) schreef BruceMcF:

> On Jun 12, 11:20 pm, "Rod Pemberton" <do_not_h...@notemailntt.cmm>
> wrote:
>> "Alex McDonald" <b...@rivadpm.com> wrote in message
>
>> If LAST works like "LAST-NAMED-XT" (which it did) and :NONAME doesn't have a
>> header, then SMUDGE corrupting data is not an issue.  SMUDGE works on a
>> valid header.  But, then my RECURSE which used LAST didn't work on the
>> correct word.
>
> Quite. A factor that makes the bare header ... aka HEADER ... and a
> factor that starts a definition ... aka DEFINE, ... would
> independently fill HEAD and LASTXT with CREATE calling HEADER and so
> filling HEAD while : calls both HEADER and DEFINE, and so fills HEAD
> and LASTXT both and :NONAME calls DEFINE, and so fills LASTXT.
>
> RECURSE would use LASTXT and ignore HEAD. DOES> and IMMEDIATE would
> use HEAD and ignore LASTXT.
>

Yes, IMMEDIATE needs to know what part of the header is to modified and can
not reliably use LASTXT for that.
Yes, RECURSE uses LASTXT.
No, DOES> (or the runtime of it) can modify the code pointed to by LASTXT
without needing to know about a present or missing header.

Rod Pemberton

unread,
Jun 14, 2012, 8:31:39 PM6/14/12
to
"BruceMcF" <agi...@netscape.net> wrote in message
news:460e8200-c21f-4e2f...@k5g2000vbf.googlegroups.com...

> A factor that makes the bare header ... aka HEADER ... and a
> factor that starts a definition ... aka DEFINE, ... would [...]
> CREATE calling HEADER [...]

Yes, I considered a HEADER word, maybe not by that name. Someone else here
(Andrew?) mentioned it a few times, and I saw it in a Unix forth. But, I
have (CREATE) and it ALLOTs or , (comma) as the header is filled. So, it's
much like HEADER. I didn't see the point of just a blank header word, e.g.,
ALLOT would do. So, much of :NONAME ends up being a modified (CREATE),
i.e., without the extra stuff, and no nice factoring like you did... :-)

I currently consider :NONAME to be low use, so am not too concerned. I can
factor it later for size ... or leave it for speed.

> BruceMcF (Bruce McFarling)

Um, is that Bruce McFarland ... ? I saw him in the c.l.f. archives. Excuse
me, if I asked that previously...

> Though with PTR it seems that DSL could be omitted, since the c-
> function pointer for {DOES} could be portably embedded in the word
> containing DOES>, following the EXIT, and the location of the DOES>-
> sub-parameter-field inferred as the cell following the one pointed to
> by PTR.

By {DOES} do you mean DODOES or (DOES) or (DOES>) ? Or, do you
mean the address of the DOES> code?

Won't doing what you've just suggested lead to the same issue I was having
problems with in the "dot-quote implementation question" thread? I think it
will.

AIR, placing something in the PFA was causing data to shift or be in
unexpected locations. I.e., I see omitting DSL working most of the time,
but not all the time. Since CREATE ... DOES> is always high-level code
(now) in my Forth, the header and body will always be together. So, I can
locate PTR from CFA or PFA, in that situation.

AISI, this should work with your suggestion:

: ZZZ CREATE <prep> DOES> <action> ;

ZZZ XYZ \ nothing else stored into XYZ

AISI, this might not work with your suggestion:

: ZZZ CREATE <prep> DOES> <action which needs data> ;

ZZZ XYZ <data> , <data> , <data> , \ data stored afterwards

In the second case, the DSL valued will be stored in the PFA. So, the coded
<action> may expect the data in a certain location, but it'll be in a
different location.

I haven't had a chance to check, but was thinking that the 2nd case might
affect usage of string words or creating tables etc ...

If I omit the DSL, the CFA is still DODOES. DODOES is the C-function, or
XT. It must fetch the address of the DOES> code in the CREATE ... DOES>
sequence, and transfer interpretation to there. The address of the DOES>
code should be at a fixed location relative to the start of the header.
That's an interpretable address. It needs and ENTER or R> and ; (semis) to
transfer interpretation there. I'm not sure where or how I'd insert that
into my code. Most PTR fields will be valid XTs and then a few will be
non-XTs, the DOES> code address. I.e., I'm also not sure how to detect
that.

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)

I.e., it looks like your earlier suggestion, or the way I implemented, works
for all situations, but does consume a cell. So, I'm not sure why the
suggestion to change back to what I was doing previously or something
similar.


Rod Pemberton



BruceMcF

unread,
Jun 15, 2012, 10:03:57 AM6/15/12
to
On Jun 14, 8:31 pm, "Rod Pemberton" <do_not_h...@notemailntt.cmm>
wrote:
> "BruceMcF" <agil...@netscape.net> wrote:

> Yes, I considered a HEADER word, maybe not by that name.  Someone else here
> (Andrew?) mentioned it a few times, and I saw it in a Unix forth.  But, I
> have (CREATE) and it ALLOTs or , (comma) as the header is filled.  So, it's
> much like HEADER.

It sounds very much like it *is* HEADER

> I didn't see the point of just a blank header word

I don't either. If you were going a null header approach because of
not factoring out HEAD and LASTXT, you'd just create a null header by
passing it a nul-length string. HEAD (by whatever name) wouldn't be
standardizable, as some would pass an STR string, some a cell counted
string, some a counted string, some in a fixed buffer, and some would
parse the string in the place where the name would end up.

I can't see why you'd want a fixed length header, but if you do, all
the more reason to factor out the HEAD and LASTXT functionality.

>> BruceMcF (Bruce McFarling)

> Um, is that Bruce McFarland ... ?  I saw him in the c.l.f. archives.
That would likely be Bruce McFarling then. I've been chatting on and
on on clf since I was teaching in Newcastle, Australia.

> By {DOES} do you mean DODOES or (DOES) or (DOES>) ?

... or doDOES> or _DOES> etc.

> Won't doing what you've just suggested lead to the same issue I was having
> problems with in the "dot-quote implementation question" thread?
> I think it will.

> 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>

If from your header, you can *infer* the PFA of the created word from
information available when the CREATEd word is executed (and after
all, this only has to work for headers built by CREATE not for any
generic header) 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.

That depends on how the Forth VM is defined. Sometimes that can be
inferred, and sometimes it cannot. Brad Rodriguez goes in more detail
in his DOES> article in his Moving Forth series.

> : ZZZ  CREATE  <prep>  DOES>  <action which needs data> ;

> ZZZ XYZ <data> , <data> , <data> , \ data stored afterwards

> In the second case, the DSL valued will be stored in the PFA.

No, it works when {DOES} can avoid requiring a stored CREATE-PFA at
all, because the address of the PTR through which the {DOES} runtime
was called can still be recovered. This may of course require a static
declaration in C.

BruceMcF

unread,
Jun 15, 2012, 10:05:53 AM6/15/12
to
On Jun 14, 1:24 pm, Coos Haak <chfo...@hccnet.nl> wrote:
> No, DOES> (or the runtime of it) can modify the code pointed to by LASTXT
> without needing to know about a present or missing header.

The DOES> compile time has no need of the xt of the word in which it
is contained, and no need to worry about a missing header, since it
applies to the last CREATEd word.


Coos Haak

unread,
Jun 15, 2012, 2:40:19 PM6/15/12
to
Op Fri, 15 Jun 2012 07:05:53 -0700 (PDT) schreef BruceMcF:
But the word compiled by DOES>, call it (DOES>) or (;CODE) must calculate
the position of the xt from the header address. LASTXT has it right away.
This is how Gforth and my current implementation do it.

Coos Haak

unread,
Jun 15, 2012, 2:45:21 PM6/15/12
to
Op Thu, 14 Jun 2012 20:31:39 -0400 schreef Rod Pemberton:

<snip>
>
> By {DOES} do you mean DODOES or (DOES) or (DOES>) ? Or, do you
> mean the address of the DOES> code?
>
> Won't doing what you've just suggested lead to the same issue I was having
> problems with in the "dot-quote implementation question" thread? I think it
> will.
>
> AIR, placing something in the PFA was causing data to shift or be in
> unexpected locations. I.e., I see omitting DSL working most of the time,
> but not all the time. Since CREATE ... DOES> is always high-level code
> (now) in my Forth, the header and body will always be together. So, I can
> locate PTR from CFA or PFA, in that situation.
>
> AISI, this should work with your suggestion:
>
>: ZZZ CREATE <prep> DOES> <action> ;
>
> ZZZ XYZ \ nothing else stored into XYZ
>
> AISI, this might not work with your suggestion:
>
>: ZZZ CREATE <prep> DOES> <action which needs data> ;
>
> ZZZ XYZ <data> , <data> , <data> , \ data stored afterwards
>
> In the second case, the DSL valued will be stored in the PFA. So, the coded
> <action> may expect the data in a certain location, but it'll be in a
> different location.

: CONST1 CREATE , DOES> @ ;
10 CONST1 TEN TEN . will print 10
: CONST2 CREATE DOES> @ ;
CONST2 TWENTY 20 , TWENTY . will print 20

You see, the parameter field may be filled while createing (CONST1) or
after creating (CONST2). Both parameter fields start at the same location,
taking in account the different defining words.

BruceMcF

unread,
Jun 15, 2012, 2:56:05 PM6/15/12
to
On Jun 15, 2:40 pm, Coos Haak <chfo...@hccnet.nl> wrote:

> But the word compiled by DOES>, call it (DOES>) or (;CODE) must calculate
> the position of the xt from the header address. LASTXT has it right away.

It may, depending on implementation. It might not. If it does,
skipping:
... nt>code-address ....

... would indeed save an entire word in the definition. If it doesn't,
its:
... xt>code-address ...

... anyway, whatever that process is (in a direct threaded
implementation, xt>code-address may be 1+ or 2+ or CELL+).

Coos Haak

unread,
Jun 15, 2012, 3:15:12 PM6/15/12
to
Op Fri, 15 Jun 2012 11:56:05 -0700 (PDT) schreef BruceMcF:
O, I was talking the address that must be patched during the execution of
the word that contains DOES>. Never mind.

BruceMcF

unread,
Jun 15, 2012, 3:43:36 PM6/15/12
to
On Jun 15, 3:15 pm, Coos Haak <chfo...@hccnet.nl> wrote:
> O, I was talking the address that must be patched during the execution of
> the word that contains DOES>. Never mind.

LASTXT wouldn't serve for that, if CREATE does not set it. And so long
as that address can be inferred from the name token in HEAD there is
no pressing need to re-arrange CREATE to have it fill LASTXT

Rod Pemberton

unread,
Jun 19, 2012, 9:10:45 PM6/19/12
to
"BruceMcF" <agi...@netscape.net> wrote in message
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





0 new messages