However, I didn't know the how dual execution and compilation nature of
immediate words was implemented in FORTH. Wait a minute... Does an
immediate word have a dual execution and compilation nature? Or, does it
only have a single immediate nature? By that, I'm asking does an immediate
word do the same thing all the time? Or, does an immediate word do one
thing all the time and also an additional something when being compiled?
Anyway, since I didn't understand what was supposed to happen with immediate
words, I implemented the immediate words I needed as "primitives" coded in
C. Basically, the problem I have is that I can represent compiled words and
primitive words in C, but not immediate words. I'd like to be able to
implement immediate words as immediate words and/or as compiled words, and
not as primitives since that requires more C code.
Apparently, there were a few extra bits in the historical "name field" of a
dictionary header. One of these was the "precedence bit" which determined
if the word would be compiled or executed immediately. I have a "link
field", "code field", "parameter field(s)", and "name field" as the header,
but I don't have the "precedence bit" (or "smudge bit"... ?).
So, how is a FORTH word marked as an immediate word in today's FORTHs? Is
there still a "precedence bit" in a word's dictionary header? Is it still
part of the "name field"? What bit(s) are used to indicate immediate, where
is this bit stored, and what words are used to modify and check the bit's
value? From some older c.l.f posts, I see mention of precedence,
compile-only, and immediate-only bits.
Now, to implement the interpreter, I simplified/modified some FORTH
(probably fig-FORTH ...?) words. So, the following INTERPRET word will
probably look slightly odd, e.g., no integers:
: INTERPRET (--)
MODE
FIND
IF
IF EXECUTE ELSE STORE THEN
ELSE
IF BYE ELSE COMPILE THEN
THEN
EXIT
;
In my comments, I have:
EXECUTE listed as "found and interpret", interprets word
STORE listed as "found and not interpret", stores CFA's
BYE (probably "not found and interpret"...?)
COMPILE listed as "not found and not interpret", starts new word
So, I would think that EXECUTE is implementing the immediate
functionality... Yes? However, while COLON and (essentially) SEMICOL are
toggling the interpretive state, I have nothing on the words themselves to
indicate whether to select between EXECUTE or STORE.
This post seems to indicate that instead of toggling the interpreter state
via COLON and SEMICOL, I need a variable called STATE:
http://groups.google.com/group/comp.lang.forth/msg/c15f99be974e6687?hl=en
...which I must assume checks the precedence bit... ?
Thanks.
Rod Pemberton
> However, I didn't know the how dual execution and compilation nature
> of immediate words was implemented in FORTH. Wait a minute... Does
> an immediate word have a dual execution and compilation nature?
No.
> Or, does it only have a single immediate nature?
Yes.
> By that, I'm asking does an immediate word do the same thing all the
> time? Or, does an immediate word do one thing all the time and also
> an additional something when being compiled?
No. An immediate word does one thing all the time.
> Anyway, since I didn't understand what was supposed to happen with
> immediate words, I implemented the immediate words I needed as
> "primitives" coded in C. Basically, the problem I have is that I
> can represent compiled words and primitive words in C, but not
> immediate words. I'd like to be able to implement immediate words
> as immediate words and/or as compiled words, and not as primitives
> since that requires more C code.
> Apparently, there were a few extra bits in the historical "name
> field" of a dictionary header. One of these was the "precedence
> bit" which determined if the word would be compiled or executed
> immediately. I have a "link field", "code field", "parameter
> field(s)", and "name field" as the header, but I don't have the
> "precedence bit" (or "smudge bit"... ?).
A precedence (aka IMMEDIATE) bit is agood way to do it.
> So, how is a FORTH word marked as an immediate word in today's
> FORTHs? Is there still a "precedence bit" in a word's dictionary
> header? Is it still part of the "name field"? What bit(s) are used
> to indicate immediate, where is this bit stored, and what words are
> used to modify and check the bit's value?
It's up to you: there are no rules in this area. However, allocating
a single bit somewhere in the header shouldn't be difficult.
> From some older c.l.f posts, I see mention of precedence,
> compile-only, and immediate-only bits.
This is not necessary for standard Forth.
> Now, to implement the interpreter, I simplified/modified some FORTH
> (probably fig-FORTH ...?) words. So, the following INTERPRET word will
> probably look slightly odd, e.g., no integers:
> : INTERPRET (--)
> MODE
> FIND
> IF
> IF EXECUTE ELSE STORE THEN
> ELSE
> IF BYE ELSE COMPILE THEN
> THEN
> EXIT
> ;
> In my comments, I have:
> EXECUTE listed as "found and interpret", interprets word
> STORE listed as "found and not interpret", stores CFA's
> BYE (probably "not found and interpret"...?)
> COMPILE listed as "not found and not interpret", starts new word
> So, I would think that EXECUTE is implementing the immediate
> functionality... Yes?
Yes.
> However, while COLON and (essentially) SEMICOL are toggling the
> interpretive state, I have nothing on the words themselves to
> indicate whether to select between EXECUTE or STORE.
> This post seems to indicate that instead of toggling the interpreter state
> via COLON and SEMICOL, I need a variable called STATE:
> http://groups.google.com/group/comp.lang.forth/msg/c15f99be974e6687?hl=en
> ...which I must assume checks the precedence bit... ?
No. It goes like this:
: interpret
begin
state @ if compiler else interpreter then
again;
: interpreter
find if execute else >number then ;
: compiler
find if immemdiate? if execute else compile, then
else >number ,literal then ;
(This glosses over a lot of detail, but it's more or less right.)
Andrew.
Mostly immediate words do only one thing. Words that can do more than
one thing are called 'state-smart' meaning they check STATE to see
what
to do. There are different opinions about such words because they
break some things that some people do.
FIG-FORTH and many implementations used a header bit for immediate
status to the compiler and another bit for compile-only status and
another bit for SMUDGE.
In cmForth and colorforth Chuck did not use a header bit but used
two wordlists; Forth and macro. Macro is searched first when
compiling
so one marks a word before it is defined by saying macro. In FIG-
FORTH
one declares IMMEDIATE after a word is defined.
> Apparently, there were a few extra bits in the historical "name field" of a
> dictionary header. One of these was the "precedence bit" which determined
> if the word would be compiled or executed immediately. I have a "link
> field", "code field", "parameter field(s)", and "name field" as the header,
> but I don't have the "precedence bit" (or "smudge bit"... ?).
People used a bit to show IMMEDIATE use to the compiler. If you don't
want
to do that you could use some other mechanism to mark them or put them
into an IMMEDIATE wordlist and manipulate search order.
SMUDGE is used to hide a definition while it is being compiled so that
you can use the name of the word inside of the word and have it refer
to the the last definition of that word not the current word. Unless
you
smudge and unsmudge while defining or hide a definition in some other
way you can't redefine a word and use the old definition name in the
new
definition with the same name easily.
> BYE (probably "not found and interpret"...?)
People usually ABORT back to the command line or
ABORT" with a message rather than quit with BYE.
> So, I would think that EXECUTE is implementing the immediate
> functionality... Yes? However, while COLON and (essentially) SEMICOL are
> toggling the interpretive state, I have nothing on the words themselves to
> indicate whether to select between EXECUTE or STORE.
You need something.
> This post seems to indicate that instead of toggling the interpreter state
> via COLON and SEMICOL, I need a variable called STATE
> :http://groups.google.com/group/comp.lang.forth/msg/c15f99be974e6687?h...
> ...which I must assume checks the precedence bit... ?
STATE is not traditionally used to mark IMMEDIATE words.
STATE traditionally represents interpret state vs compile state.
The STATE variable and the smudge bit in the header get toggled
by COLON and SEMICOLON. STATE is also toggled by [ and ]
A state-smart word checks STATE to see what it is suppose to do for
the appropriate state when it executes. I will let others address
their concern about the use of state-smart words if you are
concerned.
Best Wishes
In terms of ANS Forth, the interpretation and compilation semantics of
immediate words are the same.
>By that, I'm asking does an immediate
>word do the same thing all the time?
At least when being interpreted or compiled.
>Apparently, there were a few extra bits in the historical "name field" of a
>dictionary header. One of these was the "precedence bit" which determined
>if the word would be compiled or executed immediately. I have a "link
>field", "code field", "parameter field(s)", and "name field" as the header,
>but I don't have the "precedence bit" (or "smudge bit"... ?).
In a classical system (e.g., Fig-Forth) precedence bit indicates
immediacy. The precedence and smudge bits are in bits 5 and 6 of the
count byte of the name field in Fig-Forth (and the top bit (bit 7) is
always set).
>So, how is a FORTH word marked as an immediate word in today's FORTHs? Is
>there still a "precedence bit" in a word's dictionary header? Is it still
>part of the "name field"? What bit(s) are used to indicate immediate, where
>is this bit stored, and what words are used to modify and check the bit's
>value? From some older c.l.f posts, I see mention of precedence,
>compile-only, and immediate-only bits.
Gforth has an immediate (precedence) bit, a compile-only bit, no
smudge bit, and an alias bit, and it has a count cell, not a count
byte. It also has a hackish implementation of combined words (with an
arbitrary combination of interpretation and compilation semantics).
If you want some ideas for a cleaner implementation, read
<http://www.complang.tuwien.ac.at/forth/header-ideas.html>
- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.forth200x.org/forth200x.html
EuroForth 2009: http://www.euroforth.org/ef09/
In Retro, the dictionary is a linked list containing pointers to the
previous
entry, word address, class handler, and then the actual namee of the
word. The
key bit in the interpreter is the class handler, which is responsible
for dealing
with the execution or compilation of the word.
Immediate words share a class handler that always executes the word. I
have other
classes for words with different behaviors.
-- crc
Thanks. Yes, that needs to be corrected. IIRC, it was needed to get it to
exit for it's prior use when there was no more input. As Andrew showed, I
think that's where one of the unimplemented number words goes.
Rod Pemberton
Ok, my "store" compiles an existing word, so if I ignore the "immediate?"
check for now, it corresponds to "compile" in ":compiler". My "compile"
compiles a new word whereas my "colon" just toggles the variable for "mode".
So, I'm thinking that "store" should be renamed "compile", "mode" renamed
"state", and the functionality in my "compile", which compiles a new word,
probably should've actually been part of "colon", I'm guessing... I'll
probably rework it the way you have it.
Thanks.
Rod Pemberton
I call the smudge bit the "INVISIBILITY" bit. It makes a word
unfindable. I find this generally useful, apart from handling
RECURSE.
An example from my optimiser experiment:
---------------------------
' ALIGN-NOOPS ALIAS | \ Convenience alias
: ]L POSTPONE ] POSTPONE LITERAL ; IMMEDIATE \ Convenience alias
: (MATCH-TABLE) |
\ `` MATCH-TABLE'' points here :
'P EXECUTE | P | \ Execute optimisation
'P + 'P + | 'P 'P + + | \ Associativity optimisation
...
[ 0 ]L AND | DROP 0 |
[ 0 ]L XOR | NOOP |
[ 1 ]L M* DROP | NOOP |
[ 1 ]L / | NOOP |
[ -1 ]L M* DROP | NEGATE |
...
'P 0BRANCH [ 'P , ] | NOOP | \ Non-zero, zero is matched by previous
< 0= | > |
> 0= | < |
;
\ Optimalisation of this table is thoroughly forbidden!
FMASK-HOB ' (MATCH-TABLE) >FFA OR!
\ Get rid of those auxiliary words.
' | HIDDEN ' ]L HIDDEN
---------
The word HIDDEN manipulates the INVISIBILITY bit.
With a c-ish long "mnemonic" definition of ]L and | the table
becomes unreadable. Those words mustn't persist, however.
In tForth the word PRIVATE makes words invisible outside of a
certain scope, similar to the word static in C.
It was (is) also present in iforth.
>- anton
>--
>M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
Groetjes Albert
--
--
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- like all pyramid schemes -- ultimately falters.
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst
A normal word has interpretation=1 compilation=1 precedence=0
A normal immediate word has i=1 c=1 p=0
A compile-only non-immediate word has i=0 c=1 p=0
A directive (i.e. compile-only immediate) word has i=0 c=1 p=1
An interpret-only word has i=1 c=0 p=0
No smudge bit, or state.
Correction to my last post:
A normal immediate word has i=1 c=1 p=1
Cheers,
Mark
> ... So, how is a FORTH word marked as an immediate word in today's FORTHs? Is
> there still a "precedence bit" in a word's dictionary header? Is it still
> part of the "name field"? What bit(s) are used to indicate immediate, where
> is this bit stored, and what words are used to modify and check the bit's
> value? From some older c.l.f posts, I see mention of precedence,
> compile-only, and immediate-only bits.
>
kForth uses two bits to define precedence of a word in compile and interpret
states. This method is non-standard, but provides flexibility in executing
what would otherwise be compile-only code, e.g. DO loops, IF ... THEN and
so on. For more information on how this works, and on compatibility issues,
see
http://www.ccreweb.org/software/kforth/kforth5.html#Special%20Features
Krishna
I like this technique, but I found your explanation a bit difficult to
follow the first time I saw it. To me, "nondeferred" doesn't really
match the concept of "execute and discard the deferred opcodes". Also,
it would be easier to follow if you used descriptive names in the table
instead of E0 E1 E2.
So I'd suggest something like the following:
>>Unlike a conventional Forth interpreter which executes each token as it
>>is interpreted, kForth caches them as a sequence of byte codes, until a
>>keyword or end of line in the input stream necessitates execution.
>>Deferred execution in interpreter mode is implemented by extending the
>>normal concept of precedence in Forth. Instead of a single prncedence
>>bit associated with each word, kForth uses a precedence byte having two
>>significant bits to describe the behavior of each word in both compiled
>>and interpreted modes. Thus, a word may have one of four possible
>>precedence values:
>>
>> 0 - -
>> 1 IMMEDIATE -
>> 2 - SYNCHRONIZE
>> 3 IMMEDIATE SYNCHRONIZE
>>
>>To understand the execution behavior of a word in each of these states,
>>it is helpful to view a table of execution modes for each precedence
>>value and for the two compilation states: interpret and compile. We
>>define the following execution modes:
>>
>> * compile -- compile word into the opcode vector.
>> * synch -- compile word, then execute and discard the opcode vector.
>> * execute -- execute word instead of adding it to the opcode vector.
>>
>>Precedence Interpret Compile
>>------------------------------
>> 0 compile compile
>> 1 execute execute
>> 2 synch compile
>> 3 synch execute
That's my two cents, anyway.
--Josh
Thanks for the feedback. I like the idea of using descriptive names
instead of labels, E0, ..., for the execution modes, although I'm not
sure whether "synch" is the most appropriate label for non-deferred
execution. Also, I think that the first table listing the four precedence
values needs to be more explicit.
Krishna
How about "flush"? I think of this model as being like a cache;
accumulating semantics for batch execution (instead of executing each
word immediately as Forth usually does). I did some searching through a
thesaurus, and "synchronize" and "flush" were the only two words that I
felt fit that concept well. But maybe you think of it differently?
The thing that confused me about "nondeferred" was that my brain wanted
it to mean the same thing as "immediate".
--Josh
There seems to be some other meaning for the word "nondeferred" in a
Forth 200x proposal, which I have yet to look at closely. The word
"flush" is closer to the functionality than "synchronize" --- it may be
appropriate, if a bit crude. Thanks for the suggestion. I plan to rework
the description for this feature of kForth, although it's further down
on my stack of things to do for the present.
Krishna
"Flush" has the strong historical connotation of something you do to
disk block buffers. And I'm not sure what "nondeferred" means in ths
context.
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."
==================================================