To make this question more concrete, let's assume we have
: [foo] ... ; immediate
: [bar]
...
... \ compile [foo] here
... ; immediate
: bla ... [bar] ... ; \ use [bar] in definition
... [bar] ... \ interpret [bar]
Please answer the following questions:
1) Give a code fragment for compiling [foo] in the definition of [bar].
2) Do you think that the code above with your code fragment inserted
is an ANS Forth program? (assuming "..." is ANS Forth code).
Please reply to me directly in the next three days, then I'll
summarize the replies (mentioning your name unless you explicitly
don't want it); the followups are set to "poster" (so most newsreaders
will mail followups to me). I would like to see the discussion
delayed until I post the summary (to avoid influencing the replies).
- anton
--
M. Anton Ertl Some things have to be seen to be believed
an...@mips.complang.tuwien.ac.at Most things have to be believed to be seen
http://www.complang.tuwien.ac.at/anton/home.html
Three days have passed, so here's the summary; thanks to all who
replied. Below you will find just the answers. Several people have
also written interesting comments. I think you should post them
yourself in the discussion (I can mail you your entry if you no longer
have it), but I can do it for you upon request.
Answer A
1) POSTPONE [foo]
2)
Several people gave an unconditional yes:
Lars Krueger <lars.k...@dbag.ulm.daimlerbenz.com>
"Tom Zegub" <tze...@dhc.net>
Neal Crook <ne...@pinga.free-online.co.uk>
Some said yes, but [bar] must not compile, execute IF, etc. for the
interpreted part:
Wil Baden <wilb...@netcom.com> (probably)
jeth...@ix.netcom.com
"Marcel Hendrix" <M.A.M....@nl.cis.philips.com>
No answer:
"Julian V. Noble" <j...@unix.mail.virginia.edu>
Answer B
1) ['] [foo] execute
2) no answer
"Julian V. Noble" <j...@unix.mail.virginia.edu>
Answer C
1) S" [Foo]" COMPILE-WORD
This appears to be a factorization of Answer A, though.
2) No.
"Samuel A. Falvo II" <kc5...@dolphin.openprojects.net>
The winner by far is:
> Answer A
>
> 1) POSTPONE [foo]
2) yes ([bar] does not compile (append semantics)).
I believe that the answer to 2) is "no" after the TC Reply to Q99-027
in <7eluqb$hb0$1...@oak.prod.itd.earthlink.net>:
Philip Preston wrote:
> 1. It is an ambiguous condition for a program to perform compilation
>semantics in the interpretation state.
...
>: (S POSTPONE ( ; IMMEDIATE
>Execution of (S involves performing the compilation semantics of ( but does
>not involve appending semantics to the current definition.
Note that this is the same situation as with the definition of [bar]
using "POSTPONE [foo]" above. It is independent of whether [bar]
compiles something.
The TC answered:
>The answer to question (1.) is Yes.
So, I think the interpretive use of [bar] defined using "POSTPONE
[foo]" is now non-standard.
> Answer B
>
> 1) ['] [foo] execute
With this answer the example above is completely legal IMO. ['] gives
the execution semantics, not the compilation semantics.
Another standard way (for the same reason) is this:
[ ' [foo] ] [compile,]
where [compile,] is defined in this way:
: [compile,] compile, ; immediate
[..]
> So, I think the interpretive use of [bar] defined using "POSTPONE
> [foo]" is now non-standard.
<kamikaze>
I'm really, really, fed up with this. Why can't we get on writing good,
useful, code instead of quibbling over these stupid basic things again
and again?
Let's outlaw POSTPONE . It dawns on me that it is just an ugly cosmetic
patch, designed to allow (keep on allowing) the fact that some words
have context dependent behavior (how many states are there by now?
2? 3? 4?)
Besides, POSTPONE 18 doesn't work ( POSTPONE 0 however ... ). We might
be better off ripping up every word which mixes behaviors, and/or go
back to COMPILE and [COMPILE] (they work with iForth, are there current
Forths that have problems?)
</kamikaze>
[..]
-marcel
> Let's outlaw POSTPONE . It dawns on me that it is just an ugly cosmetic
> patch
> Besides, POSTPONE 18 doesn't work ( POSTPONE 0 however ... ).
Good point. Extremely good point.
> We might
> be better off ripping up every word which mixes behaviors, and/or go
> back to COMPILE and [COMPILE] (they work with iForth, are there current
> Forths that have problems?)
I'm still having trouble with "POSTPONE". Whenever I see code that uses
it, I try imagine which, COMPILE or [COMPILE] , to replace it with, and
only *then* I can start and understand what the code is doing.
Conservatism? Maybe. But I do think that it's the opposite step of the
ideal of the "dumb words" as defended so vigourously in "Thinking
FORTH". LEAVE is the only word I know that benefits from it. That is not
enough.
Just me two cents.
Bart.
As usual, there's confusion over aims here. There are at least two aims:
1. The ANS aim, which is to reconcile the unreconcilable.
2. The "advancing the state of the art" aim.
Once again we have this problem because in other languages point 2 is
"modifying the language" which you only do if you're a compiler writer (in
Forth, we're all compiler writers).
FWIW, I think POSTPONE does a good job of papering over the cracks. If you
think in semantics terms, it's right on, even though in most Forth
compilers (including mine) it's obviously a hacked together munge of
COMPILE and [COMPILE].
As to point 2, Anton's assertion that "STATE is evil" is eminently
sensible to me, because it's just a special case of the general
observation that global state is bad. Compilation seems to me to be one of
two areas that would benefit most from an OOP implementation (where a word
has a compilation and an interpretation method). The other is I/O.
I came to these conclusions while writing my Forth compiler. Indeed in
the end I *couldn't* implement S" without doing this, because S"'s
semantics, as extended in the FILE word set, give it an interpretation and
a compilation behaviour. AFAIK (correct me if I'm wrong) you can't
implement S" with STATE, because then POSTPONE doesn't work correctly on
it. The other word that has this problem is TO, but TO is specifically
covered by the standard (POSTPONEing it is an ambiguous condition).
I'd be interested to know how others have implemented S" when they've
implemented the FILE wordset; the only other ways I could think of were
horrible hacks like having a special bit in the word's header to say
"treat this word specially when POSTPONEing it".
Ditto many I/O words, that in a classical implementation are a switch on
SOURCE-ID, when the code for each I/O stream type should be separate.
While this *could* be achieved with classical methods, e.g. vectoring,
it's surely much better to write the I/O code in an OOP fashion, wrapping
up each device type (console, file, block) as a different class.
<trailer>I've been thinking for years about, as it were, my take on
Machine Forth, i.e. how I would radically simplify and reimplement Forth.
All the recent discussion (and my work) on Machine Forth have made this
come out into the open again, and I *may* (thesis permitting) have some
code implementing my thoughts for people to play with soon. My main thrust
is linguistic rather than VM-ish, and I've been influenced heavily by
DSSP.</trailer>
--
http://www.cl.cam.ac.uk/users/rrt1001/ | maxim, n. wisdom for fools
>> Let's outlaw POSTPONE . It dawns on me that it is just an ugly cosmetic
>> patch, designed to allow (keep on allowing) the fact that some words
>> have context dependent behavior (how many states are there by now?
>> 2? 3? 4?)
>As usual, there's confusion over aims here. There are at least two aims:
>1. The ANS aim, which is to reconcile the unreconcilable.
>2. The "advancing the state of the art" aim.
>Once again we have this problem because in other languages point 2 is
>"modifying the language" which you only do if you're a compiler writer (in
>Forth, we're all compiler writers).
<snip excellent summary>
It looks to me like the committee had a cluster of goals and succeeded
at most of them.
First, they mostly didn't specify which words are immediate. So if
you're an implementor and you figure out a good way to make a word that
usually has a compile-time behavior run as a simple compiled word or
vice versa, you can do it your way provided standard programs can't
tell the difference.
Similarly if you're anapplication programmer and you want to replace a
normal word with a state-smart immediate one, you can do that provided
a standard program can't tell the difference.
If the standard specified exactly which words are immediate I think
we'd have even more complaints with that than we do with POSTPONE .
However, Anton found some bugs. He reported them after the approach
had survived several drafts with nobody else catching them, and after
the final standard was published.
Here is one bug: Some words are compile-only, like IF . What happens
if you do
: MY-IF POSTPONE IF ; IMMEDIATE
and then do MY-IF while interpreting? My interpretation was that you
shouldn't do that. Any word that POSTPONEs a compile-only word should
be treated like it's compile-only too. If it's acceptable to write a
Forth where IF is state-smart and does something almost exactly like
[IF] for its interpret behavior (which people said is acceptable) then
you can't depend on a POSTPONEd IF to do the compilation behavior.
Similarly if you do POSTPONE ROT your word must execute only while
compiling a definition, the standard doesn't say what happens
otherwise. But Anton pointed out that the precise wording of the
standard does fit his interpretation and doesn't fit mine. That
wording will be changed.
Here is another bug: If you have a state-smart word THE-WORD that
emulates a normal word, when you do ' THE-WORD you get an xt, and
when you execute the xt you get the state-smart behavior. Now,
the compilation behavior has to be to compile something (and maybe
do other things that a standard program won't notice). And the
interpretation behavior has to be whatever the word does, which
won't include compiling anything (but maybe it does other things
that a standard program won't notice). When the compiler finds
THE-WORD it will let THE-WORD do something that will include
compiling a word that has the right action. What it compiles
can't be THE-WORD itself because it has the wrong behavior while
compiling. But ['] THE-WORD COMPILE, does compile THE-WORD itself
which leads to a lot of problems. I noticed some of that when I
first looked at the standard and I asked a couple of senior members
of the committee about it. They said it worked and I got convinced.
When Anton showed me the problem I thought it meant that when you do
['] THE-WORD EXECUTE you must be careful to do that only while
interpreting. A nice symmetry, ' ['] for interpret and POSTPONE for
compile. The standard didn't anywhere mention this restriction any
more than it mentioned the one about postponing compile-only words,
but it was clear to me that unless you followed that rule your code
wouldn't be portable to systems that made a different set of words
immediate. But Anton interpreted it the other way around, that
systems were required to provide only the interpret behavior or the
compile behavior, and he argued that state-smart words couldn't do
that. Committee members argued successfully that the compile behavior
and the interpret behavior of a state-smart word are both to execute
the definition. But that left state-smart words with different
behaviors than Anton's double-xt words. Anton's words were clearly
standard. If state-smart versions of words that the standard doesn't
say are state-smart can be standard, then we have a programming
restriction -- if you ever depend on the compilation behavior of what
you get from ' or ['] , or if you ever depend on interpreting a word
that contains POSTPONE , you have a dependency on whatever behavior
you expect from that.
Anton argues reasonably that if we completely eliminate all
state-smart words, various problems go away and the benefits that
also go away are easy to get some other way. I like the idea but
I don't see that the standard should mandate it any time soon.
A different form of state, something that says whether there's a
definition in progress, might be more useful. But it's one more
system state.
If we were to make STATE obsolescent, as a warning that it might
someday go away....
> I came to these conclusions while writing my Forth compiler. Indeed in
> the end I *couldn't* implement S" without doing this, because S"'s
> semantics, as extended in the FILE word set, give it an interpretation and
> a compilation behaviour. AFAIK (correct me if I'm wrong) you can't
> implement S" with STATE, because then POSTPONE doesn't work correctly on
> it. The other word that has this problem is TO, but TO is specifically
> covered by the standard (POSTPONEing it is an ambiguous condition).
> I'd be interested to know how others have implemented S" when they've
> implemented the FILE wordset; the only other ways I could think of were
> horrible hacks like having a special bit in the word's header to say
> "treat this word specially when POSTPONEing it".
Aha! Great. Since POSTPONE parses, this could be specialised to having
POSTPONE check to see if it is S" it is postponing, otherwise do its
general thing.
I don't know whether or not STATE is evil, but S" is clearly a flawed
concept.
Virtually,
Bruce R. McFarling, Newcastle, NSW
ec...@cc.newcastle.edu.au
You may use '18 POSTPONE LITERAL'.
'POSTPONE 0' works when the system have this: '0 CONSTANT 0'
The issue becomes whether POSTPONE solves more problems than it
creates. The problem that POSTPONE should solve is to make it
unnecessary to know whether a word is IMMEDIATE or not, and to
insulate the application programmer from kernel implementation
issues. This is very desirable, and it has permitted portable code
over a wider range of implementation techniques.
POSTPONE and state-smart words don't go together. State-smart
words are very useful for application programmers, and I and
others would be reluctant to see them go as an entitlement.
Perhaps it is time to redefine POSTPONE or to define a new
version of POSTPONE now that we have several years practical
experience with it. The present approach of trying to add
more and more ambiguous conditions to the standard seems
to be leading a condition in which the application programmer
using POSTPONE needs to know about the kernel implementation
again, which rather defeats the initial objective of
POSTPONE.
--
Stephen Pelc, MicroProcessor Engineering - More real, less time
133 Hill Lane, Shirley, Southampton SO15 5AF, England
tel: +44 1703 631441, fax: +44 1703 339691, net: s...@mpeltd.demon.co.uk
web: http://www.mpeltd.demon.co.uk
>POSTPONE and state-smart words don't go together. State-smart
>words are very useful for application programmers, and I and
>others would be reluctant to see them go as an entitlement.
>Perhaps it is time to redefine POSTPONE or to define a new
>version of POSTPONE now that we have several years practical
>experience with it.
What about defining a new syntax for state-smart words?
Or something that isn't exactly state-smart but something else
that's kind of similar but not as bug-provoking. Anton has
made some suggestions about that. The following was at least
inspired by him, and if it matches what he said I'd be glad to
give him full credit for it -- Make the smartness not in whether
STATE is on or off when the word executes. Instead make the
smartness whether there is an unfinished definition in progress
when the word is found in the input stream. POSTPONE should
give the compile behavior, and the word that includes POSTPONE
becomes compile-only. ' should give the compiled behavior.
>The present approach of trying to add
>more and more ambiguous conditions to the standard seems
>to be leading a condition in which the application programmer
>using POSTPONE needs to know about the kernel implementation
>again, which rather defeats the initial objective of
>POSTPONE.
Yes. We should get ambiguous conditions when the differences
among compilers can't be eliminated or papered over, and it
doesn't make sense to declare one or another compiler flavor
to be nonstandard.
Anton has argued convincingly that traditional state-smart words
are bad. STATE isn't the right state to test, and the resulting
behavior can be too surprising. If we were to do better, we'd
have to balance the troubles for implementors to add the new
feature and the problems of back-compatibility against the value
of the new structure.
[snip]
> POSTPONE and state-smart words don't go together. State-smart
> words are very useful for application programmers, and I and
> others would be reluctant to see them go as an entitlement.
> Perhaps it is time to redefine POSTPONE or to define a new
> version of POSTPONE now that we have several years practical
> experience with it. The present approach of trying to add
> more and more ambiguous conditions to the standard seems
> to be leading a condition in which the application programmer
> using POSTPONE needs to know about the kernel implementation
> again, which rather defeats the initial objective of
> POSTPONE.
It seems to me its the other way around. State-smart words are causing the
problems, POSTPONE is rather benign.
Cheers,
Mark W. Humphries
-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own
Bad example. If you haven't found any problems with CATCH/THROW you
haven't tried hard enough :)
>The issue becomes whether POSTPONE solves more problems than it
>creates. The problem that POSTPONE should solve is to make it
>unnecessary to know whether a word is IMMEDIATE or not, and to
>insulate the application programmer from kernel implementation
>issues. This is very desirable, and it has permitted portable code
>over a wider range of implementation techniques.
So what are the problems that POSTPONE creates?
Certainly there was a problem in that the text of the Standard did not
appear to correspond to the informally stated opinions of influential TC
members concerning the execution of compilation semantics in the
interpretation state, but
a) This has now been resolved by the recent RFI response
b) It was not a problem created by POSTPONE; Anton's example which
caused Marcel to get so fed up would be no different if [COMPILE] were
used instead of POSTPONE.
>POSTPONE and state-smart words don't go together.
Eh?
> State-smart
>words are very useful for application programmers, and I and
>others would be reluctant to see them go as an entitlement.
Agreed.
>Perhaps it is time to redefine POSTPONE or to define a new
>version of POSTPONE now that we have several years practical
>experience with it.
How should this new version differ from the present one?
What are its proposed semantics?
> The present approach of trying to add
>more and more ambiguous conditions to the standard seems
>to be leading a condition in which the application programmer
>using POSTPONE needs to know about the kernel implementation
>again,
I don't see this at all. Can you give an example?
> which rather defeats the initial objective of
>POSTPONE.
Philip Preston.
I doubt it. With SwiftForth:
: xx 18 POSTPONE LITERAL ; ok
53 xx . 53 ok
: yy 53 xx ; ok
yy . 53 ok
Or should I somehow use LITERAL outside a definition?
For reference:
see xx
456FB3 4 # EBP SUB 83ED04
456FB6 EBX 0 [EBP] MOV 895D00
456FB9 12 # EBX MOV BB12000000
456FBE 4092DB ( LITERAL ) CALL E81823FBFF
456FC3 RET C3 ok
Jerry
--
Engineering is the art | Let's talk about what
of making what you want | you need; you may see
from things you can get. | how to do without it.
---------------------------------------------------------
The TC Reply to Q99-027 "fixed" that. It simply outlawed those usages
of POSTPONE where a STATE-smart S" would have problems. They used a
shotgun crossfire approach that hit a lot of innocent bystanders like
POSTPONE ( and POSTPONE foo in words to be used interpretively.
However, if it's legal to tick S" and TO, these words still cannot be
implemented as STATE-smart words.
GForth 0.4.0, Copyright (C) 1998 Free Software Foundation, Inc.
GForth comes with ABSOLUTELY NO WARRANTY; for details type `license'
Type `bye' to exit
: foo POSTPONE 0 ;
:1
: foo POSTPONE 0 ;
^
Error: Undefined word
> We might
> be better off ripping up every word which mixes behaviors,
Good idea.
> and/or go
> back to COMPILE and [COMPILE]
That does not help. Defining [bar] using "[COMPILE] [foo]" was
outlawed with the same RFI that outlawed using "POSTPONE [foo]" there.
> (they work with iForth, are there current
> Forths that have problems?)
"[COMPILE] foo" does not work correctly in Gforth, if foo has default
compilation semantics, but was defined with INTERPET/COMPILE:. This
problem is probably also present in other Forth systems that support
combined words (I remember a message by Andras Zsoter on this topic).
It does not buy much. Let's look at the issue:
] DUP [
This appends the execution semantics of DUP to the current definition.
But we don't have a current definition.
1) We might argue that this is non-standard anyway ("append to the
current definition" has no meaning if there is no current definition),
and the system can do what it wants.
2) Let's assume it is standard: There is no way to do anything with
the code; the system might just as well do nothing if it notices this.
If the TC decides to outlaw this explicitly, I doubt any system will
change. The system could do in this case whatever it likes, including
compiling DUP as before. Few, if any, systems will maintain a
current-definition flag and report an error when you try to do the
above.
Hmm, it might protect against the practice of creating XT tables in
this way:
create tab ] foo bar boing [
tab cell+ @ execute
But I don't think many implementors will make the effort.
[..]
RT> Compilation seems to me to be
RT> one of two areas that would benefit most from an OOP implementation
RT> (where a word has a compilation and an interpretation method). The
RT> other is I/O.
What do you think a double-'o' would help? There is a 'now' (for
compilation) and there is a 'later' (when compiled stuff is run) - this
simple fact applies to other kinds of embedding as well. Only the taste
changes.
"P> POSTPONE and state-smart words don't go together. State-smart words
"P> are very useful for application programmers, and I and others would
"P> be reluctant to see them go as an entitlement.
"P> Perhaps it is time to redefine POSTPONE or to define a new
"P> version of POSTPONE now that we have several years practical
"P> experience with it. The present approach of trying to add
"P> more and more ambiguous conditions to the standard seems
"P> to be leading a condition in which the application programmer using
"P> POSTPONE needs to know about the kernel implementation again, which
"P> rather defeats the initial objective of
"P> POSTPONE.
Let me try to enumerate (with the remark at the beginning that this is
only for the more intricate fields of Forth) -
for implementations:
- have STATE and IMMEDIATE only (distinction at run-time);
- have search-order manipulation and distinct definitions;
for applications writing (once more the same):
- have STATE and IMMEDIATE only (distinction at run-time);
- have search-order manipulation and distinct definitions.
Since there is 'distinct behaviour for implementations' hidden via
POSTPONE, it will be hard now to get rid of POSTPONE, I'm afraid.
As I see it, ANS-Forth protects state-smart definitions in
implementations and leaves only state-smartness for applications. This
makes for the biggest pool of implementations which may conform, with
some minor trade-offs (measured against the win and the small percentage
where the trade-offs show-up). And it leaves a dilemma, since the
wording is about distinct behaviours - at least the dilemma comes up, as
soon as those distinct behaviours are to be referenced by an xt or by a
name.
Make xx an IMMEDIATE word and it should work for you.
--
Neal Bridges
<http://www.interlog.com/~nbridges/> Home of the Quartus Forth compiler!
: xx 18 postpone literal ; immediate ok
xx . 10747444 Stack underflow
: yy xx ; ok
yy . 18 ok
So xx is now an immediate word which only works when compiled.
What good is it?
>> > > Marcel Hendrix wrote:
>> > > [skip]
>> > > : Besides, POSTPONE 18 doesn't work ( POSTPONE 0 however ... ). We might
>> > > : be better off ripping up every word which mixes behaviors, and/or go
>> > > : back to COMPILE and [COMPILE] (they work with iForth, are there current
>> > > : Forths that have problems?)
>> > > You may use '18 POSTPONE LITERAL'.
>> > ...
>> > I doubt it. With SwiftForth:
>> > : xx 18 POSTPONE LITERAL ; ok
>> > 53 xx . 53 ok
>> > : yy 53 xx ; ok
>> > yy . 53 ok
>> > Or should I somehow use LITERAL outside a definition?
>> Make xx an IMMEDIATE word and it should work for you.
>: xx 18 postpone literal ; immediate ok
>xx . 10747444 Stack underflow
>: yy xx ; ok
>yy . 18 ok
>So xx is now an immediate word which only works when compiled.
>What good is it?
Well, we've demonstrated how confusing all this is.
What good is : yy POSTPONE IF ; IMMEDIATE ? It's about as good
as xx .
The original question was how to POSTPONE a number. This works.
18 POSTPONE LITERAL will do it.
You wind up with an immediate word which only works while compiling
into a definition. That's true of most words that use POSTPONE .
If the word compiles something, or if it's compiled, then when you
POSTPONE it you get a word whose execution behavior is to compile
something.
The exceptions are things like ( and \ which have an immediate effect
but which don't compile anything themselves. When you POSTPONE them
you get a word that will execute them along with whatever else it
does when it executes. If the word does the same thing interpreting
and compiling then you can POSTPONE it and still interpret the word
you postpone it into. Otherwise the new word is for all practical
purposes compile-only. IMMEDIATE gives it a useless capability
(execution while interpreting) along with the useful one (executing
while compiling). I think the reason this hasn't been changed is
mostly inertia.
For Standard programs it's true of all words that use POSTPONE except
for state-smart words which ensure that the piece of code which contains
POSTPONE does not get executed in the interpretation state.
>If the word compiles something, or if it's compiled, then when you
>POSTPONE it you get a word whose execution behavior is to compile
>something.
>
>The exceptions are things like ( and \ which have an immediate effect
>but which don't compile anything themselves.
These are not exceptions as far as the Standard is concerned. I
deliberately used the example of POSTPONE ( in the RFI in order to get
this clarified. Actually It was you who convinced me (about 6 months
ago) that for Open Firmware to be ANS compliant the execution of
compilation semantics in the interpretation state needed to be an
ambiguous condition whether or not those compilation semantics compiled
anything.
> When you POSTPONE them
>you get a word that will execute them along with whatever else it
>does when it executes. If the word does the same thing interpreting
>and compiling then you can POSTPONE it and still interpret the word
>you postpone it into.
On many systems you can get away with this but it is not safe to rely on
it in a Standard program. Because it involves the execution of
compilation semantics a Standard system could legitimately trap this in
the interpretation state and throw an exception. If XXX does the same
thing interpreting and compiling then use ['] XXX EXECUTE rather than
POSTPONE XXX to guarantee proper execution in the interpretation state.
> Otherwise the new word is for all practical
>purposes compile-only.
Yes, if you are writing Standard programs, but otherwise not
necessarily.
Now it is clear that the execution of compilation semantics in the
interpretation state is an ambiguous condition, implementors are free to
make LITERAL and the run-time of POSTPONE state-smart (both no-ops in
the interpretation state). On such a system definitions can be written
which are automatically state-smart without an explicit test of STATE,
eg:
: IS ' >BODY POSTPONE LITERAL POSTPONE ! ; IMMEDIATE
Philip Preston.
>[snip]
>>You wind up with an immediate word which only works while compiling
>>into a definition. That's true of most words that use POSTPONE .
>For Standard programs it's true of all words that use POSTPONE except
>for state-smart words which ensure that the piece of code which contains
>POSTPONE does not get executed in the interpretation state.
Ouch. You're right.
>>If the word does the same thing interpreting
>>and compiling then you can POSTPONE it and still interpret the word
>>you postpone it into.
>On many systems you can get away with this but it is not safe to rely on
>it in a Standard program. Because it involves the execution of
>compilation semantics a Standard system could legitimately trap this in
>the interpretation state and throw an exception.
Ouch. You're right again.
>> Otherwise the new word is for all practical
>>purposes compile-only.
>Yes, if you are writing Standard programs, but otherwise not
>necessarily.
The standard is about the interface between standard systems and
standard programs.
>Now it is clear that the execution of compilation semantics in the
>interpretation state is an ambiguous condition, implementors are free to
>make LITERAL and the run-time of POSTPONE state-smart (both no-ops in
>the interpretation state). On such a system definitions can be written
>which are automatically state-smart without an explicit test of STATE,
>eg:
>: IS ' >BODY POSTPONE LITERAL POSTPONE ! ; IMMEDIATE
That's neat. But programs that use it will have an environmental
dependency on it.
: LITERAL
STATE @ IF POSTPONE LITERAL THEN ; IMMEDIATE
: 2LITERAL
STATE @ IF POSTPONE 2LITERAL THEN ; IMMEDIATE
: FLITERAL
STATE @ IF POSTPONE FLITERAL THEN ; IMMEDIATE
: POSTPONE
STATE @ IF POSTPONE POSTPONE THEN ; IMMEDIATE
That looks simple enough. I wonder what weird results it will give
in the peculiar worst cases Anton is so good at finding.
It deserves an ENVIRONMENT? string so you can test whether it's
there and load it if not. I don't have a good name for the string.
Maybe SMART-POSTPONE ?
And it would be good to have a way to add environment strings to
existing systems.
JA> I doubt it. With SwiftForth:
JA> : xx 18 POSTPONE LITERAL ; ok
JA> 53 xx . 53 ok
JA> : yy 53 xx ; ok
JA> yy . 53 ok
JA> Or should I somehow use LITERAL outside a definition?
It does not belong there since it appends to a definition.
Consider the following:
: xx01 postpone literal ; immediate
: xx02 [ 18 ] xx1 ;
: xx03 [ 18 ] literal ;
: number-in 0. bl word count >number drop ;
: xx11 state @ if postpone literal then ; immediate
: xx12 number-in postpone xx11 ; immediate
18 xx11 .
xx12 18 .
: xx21 [ 18 ] xx11 ;
: xx22 xx12 18 ;
xx21 .
xx22 .
(Maybe some-ones might want to flame me here, but state-smart
definitions have both compilation and interpretation semantics, so one
shoud be able to make use of both, if one takes care of what happens.)
[snip]
> The exceptions are things like ( and \ which have an immediate effect
> but which don't compile anything themselves. When you POSTPONE them
> you get a word that will execute them along with whatever else it
> does when it executes. If the word does the same thing interpreting
> and compiling then you can POSTPONE it and still interpret the word
> you postpone it into. Otherwise the new word is for all practical
> purposes compile-only. IMMEDIATE gives it a useless capability
> (execution while interpreting) along with the useful one (executing
> while compiling). I think the reason this hasn't been changed is
> mostly inertia.
IMMEDIATE is not enough, we also need COMPILE-ONLY, and
: COMPILING ( -- ) IMMEDIATE COMPILE-ONLY ;
Cheers,
Mark W. Humphries
For this technique to work it's the run-time behaviour of POSTPONE that
needs to be state-smart. I think this has to be system dependant. On a
system where the run-time word is a FORTH-83 style COMPILE such as
: COMPILE R> DUP @ , CELL+ >R ;
this could be changed to
: COMPILE STATE @ IF R> DUP @ , CELL+ >R THEN ;
before being incorporated into POSTPONE
: POSTPONE BL WORD FIND DUP 0= ABORT" ?"
0< IF COMPILE COMPILE THEN , ; IMMEDIATE
POSTPONE itself could be made state-smart for the sake of completeness
but it's not essential.
>That looks simple enough. I wonder what weird results it will give
>in the peculiar worst cases Anton is so good at finding.
You need to be careful when dealing with more than one single cell
parameter. The following work ok in the compilation state but leave the
cells in the wrong order in the interpretation state:
: 2LITERAL SWAP POSTPONE LITERAL POSTPONE LITERAL ; IMMEDIATE
: 3LITERAL ROT POSTPONE LITERAL POSTPONE 2LITERAL ; IMMEDIATE
: 4LITERAL 2SWAP POSTPONE 2LITERAL POSTPONE 2LITERAL ; IMMEDIATE
etc.
Instead you need:
: 2LITERAL >R POSTPONE LITERAL R> POSTPONE LITERAL ; IMMEDIATE
: 3LITERAL 2>R POSTPONE LITERAL 2R> POSTPONE 2LITERAL ; IMMEDIATE
: 4LITERAL 2>R POSTPONE 2LITERAL 2R> POSTPONE 2LITERAL ; IMMEDIATE
etc.
But once you have these words available you can avoid the problem in
other definitions by using only one nLITERAL word each time where n is
the appropriate size to compile all your parameters in one fell swoop.
I haven't used this for quite a few years so there may be other gotchas
I've forgotten about.
Philip Preston.
>The issue becomes whether POSTPONE solves more problems than it
>creates. The problem that POSTPONE should solve is to make it
>unnecessary to know whether a word is IMMEDIATE or not, and to
>insulate the application programmer from kernel implementation
>issues. This is very desirable, and it has permitted portable code
>over a wider range of implementation techniques.
>
Good intent but flawed logic. A programmer must know if a word is
IMMEDIATE or not. POSTPONE Foo will only work right if Foo has the
immediacy that the programmer expected. POSTPONE fails in freeing the
programmer from the necessity of knowing such things. The only
thing that POSTPONE freed the programmer from was knowing which word
COMPILE or [COMPILE] he should use given that he knows what the
following word is. This is no great relief. On the contrary, at least
COMPILE and [COMPILE] tells the analyst what the programmer thought
the following word would be.
Experimentation is nice, but to prevent over-engineering changes to
the language should come very conservatively especially as the language
in its past form has served well for a long number of years.
Where is the driving need for change? If it aint broke, don't fix it!
"The problem that POSTPONE should solve is"
(1) "to make it unnecessary to know whether a word is IMMEDIATE or
not"
Big whoop, even if it succeeded which it didn't.
(2) "and to insulate the application programmer from kernel implementation
issues"
Good intent but POSTPONE by itself doesn't do it.
POSTPONE should be relegated to experimental until the larger
issue of immediacy is resolved. And then changes made only after they
can be shown to have clear and substantial benefit and that they work.
--
Tom Zegub
WasteLand http://www.dhc.net/~tzegub
tze...@dhc.net
>[snip]
>>: POSTPONE
>> STATE @ IF POSTPONE POSTPONE THEN ; IMMEDIATE
>For this technique to work it's the run-time behaviour of POSTPONE that
>needs to be state-smart. I think this has to be system dependant. On a
>system where the run-time word is a FORTH-83 style COMPILE such as
Yes! I saw that this version worked right with LITERAL but it doesn't
work right with anything else. The run-time behavior is much harder.
We want to put code into an immediate word, and when the immediate word
executes we want to execute the code if we're interpreting and POSTPONE
it if we aren't. The trouble is that we've already stretched across too
many implementations and there's too much incompatibility under the hood.
The simplest approach would be to EVALUATE the code. Very simple.
: POSTPONE
BL WORD COUNT POSTPONE SLITERAL POSTPONE EVALUATE ; IMMEDIATE
The trouble with this is that it binds too late, if a postponed word
gets rewritten we'll pick up the new version instead of the old one.
: MAYBE-POSTPONED ( xt -- j* )
STATE @ IF EXECUTE ELSE COMPILE, THEN ;
: POSTPONE
BL WORD FIND DUP IF
POSTPONE LITERAL 1 = IF
POSTPONE EXECUTE ELSE
POSTPONE MAYBE-POSTPONED THEN
ELSE
." bad POSTPONE" ABORT
THEN ; IMMEDIATE
This fails with compile-only words that aren't immediate. As I
understand it, BL WORD IF FIND isn't guaranteed to work at all, IF
might simply not be found. The only thing that's guaranteed to work
portably on IF is POSTPONE and there's no way to early-bind that and
still get a late result.
We want it to partly fail with compile-only words. We certainly don't
want to execute them in interpret state. The trouble is that on some
systems we can't even POSTPONE them this way. On those systems we
could do the following:
: POSTPONE
BL WORD FIND DUP IF
1 = IF
POSTPONE LITERAL POSTPONE EXECUTE
ELSE
POSTPONE LITERAL POSTPONE STATE POSTPONE @ POSTPONE IF
POSTPONE COMPILE, POSTPONE ELSE POSTPONE EXECUTE POSTPONE THEN
ELSE
DROP COUNT POSTPONE SLITERAL POSTPONE EVALUATE
THEN ; IMMEDIATE
Then if you do POSTPONE IF it will work. If you redefine IF to
something nonstandard you'll have some extra problems but your
system is nonstandard anyway. If you do POSTPONE IG as a typo you
won't find out until run-time, which is a disadvantage.
The only good thing about having a portable method is that it lets
you port code easier. You don't have to know enough about the new
compiler to subtly change it to what you want, you can just run the
(overcomplex) portable version and keep going, and make it more
efficient later. You don't have to declare an environmental
dependency on the POSTPONE you need.
This code isn't tested but something similar should work.
Upon pondering all the replies to Anton's survey (some of which I
anticipated some years ago in a posting re: POSTPONE and dpANS94's
explication thereof) it seems to me that the problem is neither
state-smartness, nor IMMEDIACY, but COMPILE-ONLYness, for want of
a better term. That is, in the above example
: xx 18 POSTPONE LITERAL ;
needs to be IMMEDIATE in order to work as intended. For ex.,
: test xx . ;
test 18 ok
But a word like xx is surely intended to be COMPILE-ONLY, since what
could it possibly do interpretively (unless made state-smart, which
Anton argues is a bad idea--although I sometimes do it anyway to
make my life simpler)?
This leads to a suggestion for augmenting the CORE (or CORE EXT)
wordset. We already have IMMEDIATE; what we also need is a way to
mark a COMPILE-ONLY word as COMPILE-ONLY. At present the writers
of Forths often include a test of STATE so if a word like IF is
used interpretively a message can be generated. This is obviously
good as far as it goes, but wouldn't it be easier to mark the word
itself--as IMMEDIATE does--so a word like POSTPONE can do the intell-
igent thing with it? Just a thought, which doubtless occurred to the
old X3J14 Committee, and which was doubtless rejected for some good
reason. But maybe it's time to reconsider?
--
Julian V. Noble
j...@virginia.edu
"Elegance is for tailors!" -- Ludwig Boltzmann
>As to point 2, Anton's assertion that "STATE is evil" is eminently
>sensible to me, because it's just a special case of the general
>observation that global state is bad.
That's an interesting point of view.
>Compilation seems to me to be one of
>two areas that would benefit most from an OOP implementation (where a word
>has a compilation and an interpretation method).
I can see that working. Of course, it gets a little complicated.
>The other is I/O.
How?
><trailer>I've been thinking for years about, as it were, my take on
>Machine Forth, i.e. how I would radically simplify and reimplement Forth.
>All the recent discussion (and my work) on Machine Forth have made this
>come out into the open again, and I *may* (thesis permitting) have some
>code implementing my thoughts for people to play with soon. My main thrust
>is linguistic rather than VM-ish, and I've been influenced heavily by
>DSSP.</trailer>
I look forward to hearing about it. I've always been facinated by
linguistics. For example, back a few years ago I was toying with the
thought of making a totally unambiguous, pronouncable, *thinkable*
vocabulary for Forth. I stopped when I realized that I was implying the
creation of an entire spoken language.
I'm shocked to see that my dream is alive -- Lojban (a derivative of
Loglan) not only does that, but it does it in a way which would be usable
for Forth. It has absolutely no inflection, so dictionary lookup works.
It uses a positional sentance structure, complete with SWAP operators (and
local variables).
Of course, it's not really applicable to Forth right out of the box --
it's based on predicate logic -- but I bet a Forth subset would work.
>http://www.cl.cam.ac.uk/users/rrt1001/ | maxim, n. wisdom for fools
--
-William "Billy" Tanksley
"But you shall not escape my iambics."
-- Gaius Valerius Catullus
>Upon pondering all the replies to Anton's survey (some of which I
>anticipated some years ago in a posting re: POSTPONE and dpANS94's
>explication thereof) it seems to me that the problem is neither
>state-smartness, nor IMMEDIACY, but COMPILE-ONLYness, for want of
>a better term. That is, in the above example
>
> : xx 18 POSTPONE LITERAL ;
>
>needs to be IMMEDIATE in order to work as intended. For ex.,
>
> : test xx . ;
> test 18 ok
>
>But a word like xx is surely intended to be COMPILE-ONLY, since what
>could it possibly do interpretively (unless made state-smart, which
>Anton argues is a bad idea--although I sometimes do it anyway to
>make my life simpler)?
>
>This leads to a suggestion for augmenting the CORE (or CORE EXT)
>wordset. We already have IMMEDIATE; what we also need is a way to
>mark a COMPILE-ONLY word as COMPILE-ONLY. At present the writers
>of Forths often include a test of STATE so if a word like IF is
>used interpretively a message can be generated. This is obviously
>good as far as it goes, but wouldn't it be easier to mark the word
>itself--as IMMEDIATE does--so a word like POSTPONE can do the intell-
>igent thing with it? Just a thought, which doubtless occurred to the
>old X3J14 Committee, and which was doubtless rejected for some good
>reason. But maybe it's time to reconsider?
The TC intended the phrase: "Interpretation semantics for this word are
undefined." to mean "this word is compile-only." Despite all the
discussion,
I personally don't see how you can read it any other way! We have further
attempted to clarify this by the recent RFI response. I understand some
members are working on a complete re-phrasing of all the stuff about
semantics. Meanwhile, please look at your standard, and note that _none_
of the words marked as having _no_ interpretation semantics may be
executed interpretively in a standard program, no matter how you re-package
them.
Cheers,
Elizabeth
>The TC intended the phrase: "Interpretation semantics for this word are
>undefined." to mean "this word is compile-only." Despite all the
>discussion, I personally don't see how you can read it any other way!
I agree! If you interpret a word with undefined interpretation semantics,
you have an environmental dependency on whatever you're depending the word
to do.
>Meanwhile, please look at your standard, and note that _none_
>of the words marked as having _no_ interpretation semantics may be
>executed interpretively in a standard program, no matter how you re-package
>them.
A picky point -- I thought it was legal to repackage them.
: BOMB
CR ." Hi! I am a thirty-second bomb! I am a thirty-second bomb!"
1 30 DO
CR I . [CHAR] ! EMIT 1000 MS
-1 LOOP
ABORT ;
: IF
STATE @ IF
POSTPONE IF
ELSE
BOMB
THEN ; IMMEDIATE
Interpretation semantics for IF were undefined before, but *now* they're
defined.
Here are some things missing for compile-only words that we can get by
without but that might be useful to have.
1. Users can't make new compile-only words. They just have to know not
to use certain immediate words while interpreting. We can live with that,
if you aren't sure what a word does then you shouldn't interpret it, but
it would be nice if there was a way to make such words compile-only for
real instead of just expect people not to interpret them.
2. Users have no way to tell which words are compile-only. Immediate
words might be compile-only. On some systems words that FIND says are
not immediate might be compile-only, I believe the wording of the
standard doesn't say that FIND should return 1 for compile-only words.
Maybe FIND won't even find compile-only words? So long as the only
compile-only words are the ones defined in the standard to have no
interpretation semantics, users can "just know" which are which from
the standard. It would be nice if there was some test you could use
to tell whether a word is compile-only.
[snip]
> 2. Users have no way to tell which words are compile-only. Immediate
> words might be compile-only. On some systems words that FIND says are
> not immediate might be compile-only, I believe the wording of the
> standard doesn't say that FIND should return 1 for compile-only words.
> Maybe FIND won't even find compile-only words? So long as the only
> compile-only words are the ones defined in the standard to have no
> interpretation semantics, users can "just know" which are which from
> the standard. It would be nice if there was some test you could use
> to tell whether a word is compile-only.
I'd rather do it the other way around. Instead of searching for a name in the
dictionary and being told if its normal or compile-only;
I use the word LOOKUP, which searches for a name/semantics combination.
In other words I can say 'lookup the interpreter xt of "abcd"', or 'lookup the
compiler xt of "abcd"' (which may or may not be the same xt BTW).
If I'm explicit about which semantics I'm searching for in the dictionary I
never need to check state, e.g. no STATE or state-smart words.
Here's one distinctly non-Standard idea: use #FIND, a variant of FIND
that treats literals as IMMEDIATE words.
So for example, if #FIND recognises a single-cell number, it returns:
n ' LITERAL -1
When interpreting, you don't want to know about IMMEDIATE words (i.e.
you don't want to execute DO and the like) so you drop the flag and the
xt, leaving in this case the number on the stack. When compiling, you
execute LITERAL, or whatever literal-handling word that number type has
left.
: POSTPONE \ ++ ; postpone following word
BL WORD FIND DUP 1 = IF
DROP LITERAL ['] COMPILE, COMPILE, ELSE
-1 = IF COMPILE, ELSE
#FIND IF
DUP >R EXECUTE \ compile as a literal
R> COMPILE, \ compile the code to do it again later
ELSE
what-is-this? THEN THEN ; IMMEDIATE
I think it was Bernd Paysan who first suggested this.
> It deserves an ENVIRONMENT? string so you can test whether it's
> there and load it if not. I don't have a good name for the string.
> Maybe SMART-POSTPONE ?
>
> And it would be good to have a way to add environment strings to
> existing systems.
I would suggest:
ENVIRONMENT! \ hide the latest definition and make it available
\ as an environment string
Usage: TRUE CONSTANT SMART-POSTPONE ENVIRONMENT!
Can you give an exmple that demonstrates this?
Philip Preston.
I don't think it's important for this technique to be portable.
Definitions that exploit it will always be portable for use in the the
compilation state (unless they use other non-standard features as well)
and if you need to use one in the interpretation state in a program
script it is trivial to provide an explicitly state-smart version of it.
What matters to me is that it is posible for a system to provide this
feature and still be a Standard system. Before the response to my RFI I
had thought this was not so.
Phili[p Preston.
Why? What are the problems with POSTPONE determining the compiler-xt and the
immediatness of a word and acting accordingly?
The following code is from my very non-standard system but I think you'll get
the idea.
- "DEFINED" looks-up the next token and raises an exception if not found
- "~{" is equivalent to NOT IF
- "}" is equivalent THEN
: POSTPONE ( -- )
COMPILER-BIT DEFINED DUP IMMEDIATE?
~{ COMPILE COMPILE } CFA , ; COMPILING
Without entering deeper waters, why try to POSTPONE magic numbers?
18 CONSTANT Marcel's
: xx POSTPONE Marcel's ; IMMEDIATE
: test xx . ;
Not tested.
Leo Wong
he...@albany.net
http://www.albany.net/~hello/
>> A different form of state, something that says whether there's a
>> definition in progress, might be more useful. But it's one more
>> system state.
>It does not buy much. Let's look at the issue:
>] DUP [
>This appends the execution semantics of DUP to the current definition.
>But we don't have a current definition.
>1) We might argue that this is non-standard anyway ("append to the
>current definition" has no meaning if there is no current definition),
>and the system can do what it wants.
I'd argue that.
>If the TC decides to outlaw this explicitly, I doubt any system will
>change.
I believe this is explicitly outlawed though I haven't looked it up.
Here's what I was thinking -- this is what we really wanted to outlaw
when we made compile-only words. State-smart words make trouble,
words that checked this other state might make less trouble. I'm not
clear about it yet.
I have a hunch that it mostly doesn't make sense for words to check
the state of the system to decide what to do. They can never check
enough states to keep out of trouble in complex cases. It's probably
better for each word to just do one thing and you use it when you
want that thing. Still, you've pointed out that STATE doesn't really
track what we want to track. You've challenged us to find a system
where POSTPONE DUP fails when STATE = 0 and the closest I've found
is Pygmy and cmForth, neither of which attempt to be standard. If
we'd had this other state all along we wouldn't have been trapped
into deciding we can't compile while STATE = 0 .
Here's another flag that would probably be useful, if only we could
implement it easily and consistently --
EXECUTING? ( -- flag )
false if the word that contains EXECUTING? is being interpreted from
the current input buffer or is POSTPONEd, true if it is simply being
executed as part of another definition.
I remember a long time ago I thought this was sometimes the condition
I wanted to base state-smartness on instead of STATE but I don't now
remember why I thought that. It will probably come back to me if I
keep thinking about it.
>The TC intended the phrase: "Interpretation semantics for this word are
>undefined." to mean "this word is compile-only." Despite all the
>discussion, I personally don't see how you can read it any other way!
You can. Easily. Read it another way, I mean.
"XXX semantics for this word are undefined" may well mean "You can make
it do whatever you feel like.".
I'm pretty sure it was actually intended as "if you use something that
is "undefined" in the standard, it should generate an error, or at least
(compare to arithmetic overflow), you should treat it as if it had
generated an error."
Bart.
I meant to add that I was converted to this opinion by programming in ML
during my degree. ML, being a functional language (pure functional if you
don't use references, which, unlike not using pointers in C, comes quite
naturally), makes it hard to add global state to your programs. I found
that, owing to a combination of the wonderful type system, the delightful
pattern matching declarative style of programming, and the fact that all
the state in a function consisted of its arguments, my programs tended to
do what I wanted *if they compiled*. Once I'd got the program past the
compiler, it was usually correct.
>>Compilation seems to me to be one of
>>two areas that would benefit most from an OOP implementation (where a word
>>has a compilation and an interpretation method).
>
>I can see that working. Of course, it gets a little complicated.
On the contrary, I think it's likely to be much simpler than the current
mess with immediacy, at least with regards to the ANS standard.
Effectively you give each word a compile, interpret and (while we're at
it) execute method. Then performing the compilation, execution or
interpretation semantics is just a question of calling that method.
>>The other is I/O.
>
>How?
As in other OOP languages: have a class "stream" with various methods:
read, write, read-line, write-line, reposition &c. Of course for some
streams some methods will do nothing or raise an exception (repositioning
the console, for example).
--
>>The TC intended the phrase: "Interpretation semantics for this word are
>>undefined." to mean "this word is compile-only." Despite all the
>>discussion, I personally don't see how you can read it any other way!
>You can. Easily. Read it another way, I mean.
>"XXX semantics for this word are undefined" may well mean "You can make
>it do whatever you feel like.".
We're looking at the interface between systems and programs. It means
"You (the implementor) can make it do whatever you feel like.". That
implies "You (the programmer) can't portably depend on it to do anything
in particular.".
>I'm pretty sure it was actually intended as "if you use something that
>is "undefined" in the standard, it should generate an error, or at least
>(compare to arithmetic overflow), you should treat it as if it had
>generated an error."
No, there's absolutely no requirement that a system generate an error
for something that's undefined. The system implementor can make his
system do absolutely whatever he wants to in that situation and his
system can still be standard.
A standard program has the following choices given that:
1. Don't do anything to generate an ambiguous condition, don't use
any word in circumstances where its action is undefined. Your program
will have some limitations but it will be maximally portable.
2. Do it the way you want to, that works on your system, and document
your environmental dependency. Your standard program will only port
unchanged to systems that meet your requirements.
>(Maybe some-ones might want to flame me here, but state-smart
>definitions have both compilation and interpretation semantics, so one
>shoud be able to make use of both, if one takes care of what happens.)
>
No flame from me on this one. State-smart words have never
caused me a problem. The potential problems seem to be too rare to
warrant all the clamor that's raised over it. Perhaps I don't frequent
the paths where it would be problemsome. But doing things in a
non-state-smart manner has been irritable. I don't like needing two
words to do the job that one state-smart word can do. Invariably, I
will be writing a script file using CHAR and then slip into a
definition and forget to change to [CHAR].
Two possible solutions:
1. Make CHAR state-smart and let others worry about changing it
to [CHAR] to run on their systems
2. Use state-smart ASCII composed of CHAR and [CHAR] and include
it as part of the application wordset.
The second solution appears to appease all parties. Define standard
words as non-state-smart but retain STATE to handle state-smart
application words. However, if all systems can handle a state-smart
application word ASCII then there is no reason why CHAR cannot be
built state-smart and used in definitions. [CHAR] is then just an
optional alternative for use in definitions when someone is afraid
that state-smartness will affect his application. I would never use
[CHAR] but have it in case I come across it in imported code.
Reviewing the ANS specifications I don't see anything preventing
CHAR from being state-smart and used in definitions. However, leaving
state-smartness out of CORE words seems reasonable in regard to keeping
CORE words as simple as possible. I lean to option 2.
> No flame from me on this one. State-smart words have never
>caused me a problem. The potential problems seem to be too rare to
>warrant all the clamor that's raised over it. Perhaps I don't frequent
>the paths where it would be problemsome. But doing things in a
>non-state-smart manner has been irritable. I don't like needing two
>words to do the job that one state-smart word can do. Invariably, I
>will be writing a script file using CHAR and then slip into a
>definition and forget to change to [CHAR].
This argument recurs so predictably that we probably ought to summarise
the main viewpoints and put them in the FAQ.
I'll restate my POV: Forth has a simple obvious approach. When you
interpret you execute words and when you compile you compile them.
But then we got exceptions, words that you execute while compiling.
And we needed exceptions to the exceptions, sometimes you need to
[COMPILE] immediate words and sometimes you want to [ word ] execute
nonimmediate words. Since some words are one way and some another
it isn't always clear what you'll get when you ['] word EXECUTE them.
Not to mention that some words have flipflopped in succeeding standards
(partly reflecting changing practice) so you can't be sure on foreign
systems whether they'll be exceptions or not.
The simple obvious *right* way to do it is to get rid of all the
exceptions. When you're compiling you compile, when you're
interpreting you interpret. If you want to do IF you write [ IF ] .
It's always completely clear whether you're doing it now or doing it
later. But it's surely too late for that, everybody is firmly set in
our habits and it would break all of everybody's code.
Sometimes while I'm compiling I want to do CHAR right then. Sometimes
I want to compile CHAR to do later. Sometimes I might even want a word
that will compile CHAR into another word later. It's even possible
that in some special case I might want a word that will tell its
daughter words to compile CHAR into their daughter words. These are
complex concepts and I might be better off not to think them. But
they're even more complex when I have regular words and exceptional
words and I need two different methods to handle both kinds. And it's
*out of hand* when I can't be sure ahead of time whether a word is
an exception or not.
Chuck was having an off day when he invented IMMEDIATE . It fit his
immediate needs and he never updated it to something better. Or
maybe now he's at last improved it, maybe with Color Forth he has a
color to say "do this now" versus "compile this" and all the words
that used to be immediate get the new color when they need it.
Since the tools are flawed the obvious solution is to never do
anything so complicated that the flaws create a failure. Some simple
rules that help with that are:
1. Keep a list of all your state-smart words and be cautious with them.
2. Never execute a state-smart word inside anything else. Remember that
any word that executes a state-smart word is state-smart itself.
3. Never ever POSTPONE a state-smart word.
Indeed "undefined" means it can do whatever. But the real point is that
from the perspective of a "standard program" if that program cannot depend
on a defined behavior there is no way it can use it! If System A does
something potentially useful in the interpretation semantics, System B
issues an error message, System C crashes, and System D treats it as a
no-op, (all of which are legal responses)how can you use this feature in a
standard program? Answer is, you should avoid such things.
Cheers,
Elizabeth
CHAR already has (default) interpretation and compilation semantics
specified by the Standard. If you use it in a definition its execution
semantics are appended to the current definition. If this were changed
it would break existing Standard programs. On the other hand [CHAR] has
undefined interpretation semantics so it could be made state-smart
without causing such problems.
Philip Preston.
> Stephen Pelc wrote in message <01be8be3$8543c240$0200a8c0@stephen>...
> >Marcel Hendrix <m...@iaehv.iae.nl> wrote in article
> ><7fii5f$7bl$1...@news.IAEhv.nl>...
>> <kamikaze>
[..]
I'd like to clarify my banzai posting. Due to the enormous volume of
postings lately, I'm forced to do that here.
> b) It was not a problem created by POSTPONE; Anton's example which
> caused Marcel to get so fed up would be no different if [COMPILE] were
> used instead of POSTPONE.
POSTPONE is not bad, but it papers over the real problem: having to know
which words are immediate (better, what words do exactly in any of
a number of "states"). My itch is that 99.9% of these problems are only
important to 0.1% of the users, and only at the time when they're reading
clf (I'm fond of hyperbolae).
In the past I've found many times that the only way to get good code
is to rip up and retry, not to patch over (doesn't work for raising
children, though). It always pays to reduce complexity, because (overly)
complex things tend *not to be used at all*, or are repatched endlessly.
The key word is "overly". Is anybody still comfortable with using
POSTPONE , STATE and EVALUATE in published code? Please be honest :-)
[..]
-marcel
>POSTPONE is not bad, but it papers over the real problem: having to know
>which words are immediate (better, what words do exactly in any of
>a number of "states").
Yes!
But if you accept a couple of limitations you can avoid most of that
problem. Try these rules:
1. If a definition includes POSTPONE then don't ever execute that word
except while compiling another definition.
2. Never POSTPONE a state-smart word.
How many problems are left after this?
>Is anybody still comfortable with using
>POSTPONE , STATE and EVALUATE in published code? Please be honest :-)
I feel comfortable doing it when I'm sure I don't break my rules.
Though I try to avoid using STATE .
"Z> I don't like needing two
"Z> words to do the job that one state-smart word can do. Invariably, I
"Z> will be writing a script file using CHAR and then slip into a
"Z> definition and forget to change to [CHAR].
"Z> Two possible solutions:
"Z> 1. Make CHAR state-smart and let others worry about changing it
"Z> to [CHAR] to run on their systems
"Z> 2. Use state-smart ASCII composed of CHAR and [CHAR] and include
"Z> it as part of the application wordset.
I keep with the other side here - glad to have the distinction of [CHAR]
and CHAR. Encountered too many errors when formerly writing with ASCII.
"Z> The second solution appears to appease all parties. Define
standard
"Z> words as non-state-smart but retain STATE to handle state-smart
"Z> application words.
This for sure is an option, and implementations may avoid state-smart
definitions - but ANS-Forth protects implementations which build at
least those words with distinct compile-only behaviour with state-smart
words (TO and S"). In an implementation which has distinct definitions,
[CHAR] may simply be unknown when not in compilation state. And CHAR
just behaves as you expect it from each other 'normal' word (similar as
for ['] and ')').
For applications, there is only state-smart definitions left in ANS for
to build distinct compile-only things. For sure, from time to time there
arise situations, which necessitate it to POSTPONE one of those.
"Z> However,
"Z> leaving state-smartness out of CORE words seems reasonable in
"Z> regard to keeping CORE words as simple as possible. I lean to
option
"Z> 2.
I cannot talk for the TC, but as I see it, the point is, that this is
merely an option. Compile-only words may be state-smart or but hidden
during interpretation. On the other hand, Forth gives enough power to
applications programming to do funny things, and it would render the
standard for sure inacceptable if all this were prevented. As:
: 'IF ( * migration) POSTPONE IF ; IMMEDIATE
'IF
I'd vote not to try to prevent this at the compilation level (at the
interpretation level it provides us an ambiguos situation), but maybe to
try to achieve as acceptable again what is 'outlawed' for the moment:
: \ ( * mirroring) POSTPONE \ ; IMMEDIATE
because for the moment it looks like it has to read (more in consequence
of the wording used for description, instead of technical reason)
something like:
: \ STATE @ IF POSTPONE \ ELSE ['] \ EXECUTE THEN ; IMMEDIATE
As the standard protects both kinds of implementations (behaviour is
late bound by being state-smart, or early bound by search-order
manipulation), so maybe we're left with the latter alternative.
>[switching to compilation somewhere in the desert]
>JT> I believe this is explicitly outlawed though I haven't looked it
>up.
>It is not.
>20
>:noname
> locals| ab |
> ahead [
>create rr1 0 ,
> does> ab over ! @
> locals| cd |
> ahead [
This is explicitly forbidden.
"A program shall not attempt to nest compilation of definitions."
>POSTPONE is not bad, but it papers over the real problem: having to know
>which words are immediate (better, what words do exactly in any of
>a number of "states"). My itch is that 99.9% of these problems are only
>important to 0.1% of the users, and only at the time when they're reading
>clf (I'm fond of hyperbolae).
I still do not understand what the objection to POSTPONE is in concrete
terms. Can you give a specific example of a problem that arises from
using POSTPONE which would not arise if COMPILE / [COMPILE] were used
instead?
Philip Preston.
> 2. Users have no way to tell which words are compile-only. Immediate
> words might be compile-only. On some systems words that FIND says are
> not immediate might be compile-only, I believe the wording of the
> standard doesn't say that FIND should return 1 for compile-only words.
> Maybe FIND won't even find compile-only words? So long as the only
> compile-only words are the ones defined in the standard to have no
> interpretation semantics, users can "just know" which are which from
> the standard. It would be nice if there was some test you could use
> to tell whether a word is compile-only.
Amen!
Jerry
--
Engineering is the art | Let's talk about what
of making what you want | you need; you may see
from things you can get. | how to do without it.
---------------------------------------------------------
[snip]
> This argument recurs so predictably that we probably ought to summarise
> the main viewpoints and put them in the FAQ.
>
> I'll restate my POV: Forth has a simple obvious approach. When you
> interpret you execute words and when you compile you compile them.
> But then we got exceptions, words that you execute while compiling.
> And we needed exceptions to the exceptions, sometimes you need to
> [COMPILE] immediate words and sometimes you want to [ word ] execute
> nonimmediate words. Since some words are one way and some another
> it isn't always clear what you'll get when you ['] word EXECUTE them.
> Not to mention that some words have flipflopped in succeeding standards
> (partly reflecting changing practice) so you can't be sure on foreign
> systems whether they'll be exceptions or not.
>
> The simple obvious *right* way to do it is to get rid of all the
> exceptions. When you're compiling you compile, when you're
> interpreting you interpret. If you want to do IF you write [ IF ] .
Yuk! Control-flow words are naturaly immediate.
[snip]
> Chuck was having an off day when he invented IMMEDIATE . It fit his
> immediate needs and he never updated it to something better.
I disagree the concept of immediacy is quite natural in a language that
supports both interpretation and compilation.
> Or maybe now he's at last improved it, maybe with Color Forth he has a
> color to say "do this now" versus "compile this" and all the words
> that used to be immediate get the new color when they need it.
Same difference, just syntactic sugar.
> Since the tools are flawed the obvious solution is to never do
> anything so complicated that the flaws create a failure. Some simple
> rules that help with that are:
1. Don't use STATE or state-smart words
2. Use COMPILE-ONLY for words which have no interpretation semantics
3. Use IMMEDIATE as usual (IMMEDIATE can be combined with COMPILE-ONLY e.g.
COMPILING)
3. Allow the possibility (though not the nececity) of a word having different
compiler and interpreter xts.
4. ' always returns the interpreter-xt of a word, use C' to retrieve the
compiler-xt (which may or may not be the same xt)
5. During compilation lookup compiler-xts ignoring interpreter-xts, during
interpretation lookup interpreter-xts ignoring compiler-xts
> 1. Keep a list of all your state-smart words and be cautious with them.
> 2. Never execute a state-smart word inside anything else. Remember that
> any word that executes a state-smart word is state-smart itself.
> 3. Never ever POSTPONE a state-smart word.
Cheers,
Mark W. Humphries
[switching to compilation somewhere in the desert]
JT> I believe this is explicitly outlawed though I haven't looked it
up.
It is not.
20
:noname
locals| ab |
ahead [
create rr1 0 ,
does> ab over ! @
locals| cd |
ahead [
create rr2 0 ,
does> cd over ! @
locals| ef |
ef ;
] then rr2 ;
] then rr1
if ab 1-
dup .
recurse
then ;
cr tuck execute cr
\ 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
To make the distinction of 'interpretation behaviour' and 'temporary
interpretation behaviour' (by limiting ']' to occur in pairs _after_ '['
only - which is _not_ the case now), gives as well a point to start with
nested compilation... The above should be a minimal test suite for that
case (assuming as well there is an interpreting DOES>) ;)
> ahead [
JT> This is explicitly forbidden.
Maybe you've overseen that smiley at the end?
So this what not a question about conformance but one about
consequences.
MH> The key word is "overly". Is anybody still comfortable with using
MH> POSTPONE , STATE and EVALUATE in published code? Please be honest
MH> :-)
For sure it is in a negligible range, but it is not nil. Let me give one
rare example of an application which I'd not like to change as well
after a debate like this.
Consider an application, which uses different behaviours for created
words in interpretation and in compilation state (those words made by
CREATE-BUILD, which associates as well a new wordlist). Therefore, those
are immediate and have a method:
: TBL-BUILD
create-build immediate
DOES>
do-exe ;
DO-EXE is state-smart then. It postpones access to the data of a created
word when compiling, so at run-time an environment can be set. As well
it switches the search-order at compile-time (inserting the associated
wordlist). During interpretation, the search-order needs to be switched
as well - so interpretation behaviour is significant.
This is about databases, with those created words being names of files,
and those additional wordlists contain the names of the fields for the
records in the files. Interpretation plays a role here, since
configuration files and a database (fields-) definition file are fed to
the interpreter.
Here it is quite natural, to use all the time the same words for
switching the scope by using the name of a file (or database table)
(whatever the interpreter or the compiler do by this). In consequence,
this makes relational database handling straight forward (where names of
fields maybe aren't unique for the application, as they are dictated
from user-level and not from programmer's view).
On 1999-04-23 jeth...@ix.netcom.com said:
:2. Never POSTPONE a state-smart word.
How can you tell?
--
Communa (lis...@zetnet.co.uk) -- you know soft spoken changes nothing
> :2. Never POSTPONE a state-smart word.
>How can you tell?
If you wrote it, then you just know.
If you have source code, you can check.
If you bought it without source code and it doesn't
work right, you can at least complain to tech support.
Catch-22
Agreed. This is one place where inconsistency is a virtue.
>
> [snip]
> > Chuck was having an off day when he invented IMMEDIATE . It fit his
> > immediate needs and he never updated it to something better.
>
> I disagree the concept of immediacy is quite natural in a language that
> supports both interpretation and compilation.
Yes. Things get too hairy otherwise. but there are other ways, like a
(immediate) word that causes the next word in the input stream to become
temporarily immediate. I know, I know: [ ] .
>
> > Or maybe now he's at last improved it, maybe with Color Forth he has a
> > color to say "do this now" versus "compile this" and all the words
> > that used to be immediate get the new color when they need it.
>
> Same difference, just syntactic sugar.
Not nececarilly. If the color appears in the WORDS list, that would be a
big step forward.
>
[snip]
>
> Cheers,
> Mark W. Humphries
All true, but id becomes a documentation nightmare. Some scheme for self
documentation is needed. It isn't hard for immediacy, but compile-only
requires a source trace, and state smartness is even harder.
>> Good intent but flawed logic. A programmer must know if a word is
>>IMMEDIATE or not. POSTPONE Foo will only work right if Foo has the
>>immediacy that the programmer expected.
>
>Can you give an exmple that demonstrates this?
>
(Ok, but it is self-evident that POSTPONE Foo gives one of two results
depending if Foo is IMMEDIATE or not. Hence, a programmer wanting one
result or the other needs to know the nature of Foo.)
Example 1: POSTPONE fails to free programmer from knowing the
immediacy of a word.
--SCR 10
TEST MARKER TEST
: FOO ." broke" CR ;
BAD [IF] IMMEDIATE [THEN]
: A CR POSTPONE FOO ; IMMEDIATE
: X ." A isn't " A ;
X
--END SCR 10
DEFER BAD
MARKER TEST
\ case 1: FOO not immediate
' FALSE IS BAD \ make BAD false
10 LOAD \ load script
A isn't broke Ok \ result
\ case 2: FOO is immediate
' TRUE IS BAD \ make BAD true
10 LOAD \ load script
broke \ result
A isn't Ok \ result
The programmer needed to know the immediacy of FOO in order for
A to work as intended.
Example 2: POSTPONE fails to hide kernel implementation differences
On system X : Foo ." hello world" ; IMMEDIATE
On system Y : Foo ." hello world" ;
On both systems : A postpone Foo ;
On system X A hello world ok \ what was intended
On system Y A ok \ !@# broke
On the programmer's system X where Foo is immediate, A worked. But when
his code was compiled on system Y that had Foo but it wasn't immediate,
then A broke.
Example 3: POSTPONE subtracts from analysis intelligence that was
available with COMPILE and [COMPILE]
Analyst looking at ": A [COMPILE] Foo ;" sees that A expected
Foo be immediate. When a quick check of Foo (See Foo) shows it not to
be, the problem is obvious.
Analyst looking at ": A POSTPONE Foo ;" has question of intent. Maybe
A is to be used elsewhere to defer compile Foo.
Granted the added intelligence is minuscule, but any little help is
often appreciated.
Summary:
In that POSTPONE neither achieves it's stated goals nor shows
substantial advantage over words it would replace,it should be
assigned to experimental status.
>Example 1: POSTPONE fails to free programmer from knowing the
> immediacy of a word.
>--SCR 10
> TEST MARKER TEST
> : FOO ." broke" CR ;
> BAD [IF] IMMEDIATE [THEN]
> : A CR POSTPONE FOO ; IMMEDIATE
> : X ." A isn't " A ;
> X
>--END SCR 10
> DEFER BAD
> MARKER TEST
>\ case 1: FOO not immediate
> ' FALSE IS BAD \ make BAD false
> 10 LOAD \ load script
> A isn't broke Ok \ result
>\ case 2: FOO is immediate
> ' TRUE IS BAD \ make BAD true
> 10 LOAD \ load script
> broke \ result
> A isn't Ok \ result
> The programmer needed to know the immediacy of FOO in order for
>A to work as intended.
You're comparing apples and oranges, you have two words with two
different behaviors. Try it this way:
: FOO ." broke" CR ;
: A POSTPONE FOO ; IMMEDIATE
: X ." A isn't " A ;
X
: A ." broke" CR ;
: X ." A isn't " A ;
X
Given two words with the same compiled behavior, one of them immediate
and one not, you don't have to know whether they're immediate.
Does that not seem like a fair comparison? OK, let's take it one step
further.
: FOO-EXE ." broke" CR ;
: FOO POSTPONE FOO-EXE ; IMMEDIATE
: A POSTPONE FOO ; IMMEDIATE
: X ." A isn't " A ;
X
: FOO ." broke" CR ;
: A POSTPONE FOO ; IMMEDIATE
: X ." A isn't " A ;
We don't have to know whether FOO is immediate for POSTPONE to work,
we only have to know the result of encountering FOO in the input stream
during compilation.
>Example 2: POSTPONE fails to hide kernel implementation differences
> On system X : Foo ." hello world" ; IMMEDIATE
> On system Y : Foo ." hello world" ;
> On both systems : A postpone Foo ;
> On system X A hello world ok \ what was intended
> On system Y A ok \ !@# broke
> On the programmer's system X where Foo is immediate, A worked. But when
>his code was compiled on system Y that had Foo but it wasn't immediate,
>then A broke.
A includes POSTPONE and you have no business executing A while
interpreting. Would this have worked correctly if you'd done
: A [COMPILE] Foo :
?
>Summary:
> In that POSTPONE neither achieves it's stated goals nor shows
>substantial advantage over words it would replace,it should be
>assigned to experimental status.
Apart from whether POSTPONE should be experimental, it would be
interesting to have words with experimental status. I should
have posted my experimental words to one or more of the websites
that promote such things, and I haven't.
On 1999-04-24 m...@intranetsys.com said:
:Jonah Thomas <jeth...@ix.netcom.com> wrote:
:> The simple obvious *right* way to do it is to get rid of all the
:> exceptions. When you're compiling you compile, when you're
:> interpreting you interpret. If you want to do IF you write [ IF
:> ] .
Jonah - [ is an exception. How are you going to implement [ without
IMMEDIATE?
:Yuk! Control-flow words are naturaly immediate.
They are necessarily immediate, but I wouldn't say they were naturally
so. We write IF and THEN inside definitions, but then run into problems
when we try to do something with them outside.
:> Chuck was having an off day when he invented IMMEDIATE . It fit
:>his immediate needs and he never updated it to something better.
:I disagree the concept of immediacy is quite natural in a language
:that supports both interpretation and compilation.
I see your point; LISP has the same idea (they call them macros). And
the Forth method of doing it is more transparent than the LISP one.
However, I'm not convinced that IMMEDIATE is the right way to do
immediacy.
:> Or maybe now he's at last improved it, maybe with Color Forth he
:>has a color to say "do this now" versus "compile this" and all
:>the words that used to be immediate get the new color when they
:>need it.
:Same difference, just syntactic sugar.
No, it's not! Color Forth has eight words, effectively, and they each
have one character and live between the textual tokens. Rather than
saying that a word is IMMEDIATE henceforth, you say "interpret this
word" or "compile this word". But instead of having to say:
: Forth ', this ', is '> IF ', a ', definition '> THEN '> ;
you can replace : and ', and '> with red spaces, green spaces and black
spaces. That's not syntactic sugar, it's quite a radical restructuring
of Forth. And of course it makes it quite a lot simpler, and completely
disposes of special cases. And it is the ultimate simplification of the
dictionary structure; word <=> address.
(Of course, what I would say to Chuck is "why is it the space at the
*beginning* of the word that says what to do with it?" But then I'm
strange...)
> :> The simple obvious *right* way to do it is to get rid of all the
> :> exceptions. When you're compiling you compile, when you're
> :> interpreting you interpret. If you want to do IF you write [ IF
> :> ] .
>Jonah - [ is an exception. How are you going to implement [ without
>IMMEDIATE?
If you only have one exception you can put it into the compiler. When
the compiler's compiling and it sees the "[" token it switches to the
interpreter. That's simpler than checking each word to see whether
it's immediate.
> :> Or maybe now he's at last improved it, maybe with Color Forth he
> :>has a color to say "do this now" versus "compile this" and all
> :>the words that used to be immediate get the new color when they
> :>need it.
> :Same difference, just syntactic sugar.
>No, it's not! Color Forth has eight words, effectively, and they each
>have one character and live between the textual tokens. Rather than
>saying that a word is IMMEDIATE henceforth, you say "interpret this
>word" or "compile this word". But instead of having to say:
>: Forth ', this ', is '> IF ', a ', definition '> THEN '> ;
>you can replace : and ', and '> with red spaces, green spaces and black
>spaces. That's not syntactic sugar, it's quite a radical restructuring
>of Forth. And of course it makes it quite a lot simpler, and completely
>disposes of special cases. And it is the ultimate simplification of the
>dictionary structure; word <=> address.
Yes!
For regular Forth that would translate to a word that executes the next
word only, as opposed to [ which switches and doesn't switch back.
OK, we could have two tokens for the compiler to recognise, [ and ` .
` IF says interpret the following string. It would seem completely
natural if we hadn't gotten used to the other way.
[snip]
> :> Or maybe now he's at last improved it, maybe with Color Forth he
> :>has a color to say "do this now" versus "compile this" and all
> :>the words that used to be immediate get the new color when they
> :>need it.
>
> :Same difference, just syntactic sugar.
>
> No, it's not! Color Forth has eight words, effectively, and they each
> have one character and live between the textual tokens. Rather than
> saying that a word is IMMEDIATE henceforth, you say "interpret this
> word" or "compile this word". But instead of having to say:
>
> : Forth ', this ', is '> IF ', a ', definition '> THEN '> ;
>
> you can replace : and ', and '> with red spaces, green spaces and black
> spaces. That's not syntactic sugar, it's quite a radical restructuring
> of Forth. And of course it makes it quite a lot simpler, and completely
> disposes of special cases. And it is the ultimate simplification of the
> dictionary structure; word <=> address.
>
> (Of course, what I would say to Chuck is "why is it the space at the
> *beginning* of the word that says what to do with it?" But then I'm
> strange...)
I see. Does the color-change-token (cct) only affect the next token, or is it
more like a mode change until the next cct comes along?
If the former interesting but cumborsome (3 different types of spaces to deal
with). If the latter then we're back to explicit mode changes, although color
replaces the clutter words.
Quite fascinating. In many ways this is a predictable next step in Chuck's
underlying trend of being explicit with what you want rather then leaving the
general case to an underlying mechanism, and needing other mechanisms to
handle the exceptions.
Quite the contrary of OOP when you think about it. ;>
> Summary:
> In that POSTPONE neither achieves it's stated goals nor shows
> substantial advantage over words it would replace,it should be
> assigned to experimental status.
You have a point there, when I added POSPONE to my Forth, I got rid of
[COMPILE]. One or the other is useful, but both is redundant.
The point is that POSTPONE doesn't do any better than COMPILE and
[COMPILE] in handling IMMEDIATE words in a portable way. POSTPONE
didn't solve anything. The fact that POSTPONE can test a word and do
the appropriate COMPILE or [COMPILE] action in itself is not sufficient
to solve the problem. However, that aspect has been flaunted to garner
support for justifying its use but it has little value and only
sidetracks the unwary from the unresolved issue.
For sure I don't want to make [CHAR] state-smart. The whole purpose
is to be rid of that excess word not just to be state-smart.
You're right, making CHAR state-smart would break existing code
(not just because of state-smartness) because it would have added
compiling word behavior resulting in a different sequence than it
would have now when used in a definition. Just looking at the words
definition its not easy to see where these things are specified.
<ANS spec fragment>
6.1.0895 <CHAR>
<char> CORE
( <"<spaces>name"> -- char )
Skip leading space delimiters. Parse name delimited by a space. Put the
value of its first character onto the stack.
</ANS spec fragment>
I assume the rule is that if two behaviors are not indicated in the
stack effects then the word shall not have them.
(note: Comments within the referenced text are more for
paraphrasing than for discussion. Discussion is at the end.)
>I'll restate my POV: Forth has a simple obvious approach. When you
>interpret you execute words and when you compile you compile them.
>But then we got exceptions, words that you execute while compiling.
Exceptions being "compiling words", words that do a job when the
word containing them is being compiled. In other languages words that
do this are "macros".
>And we needed exceptions to the exceptions, sometimes you need to
>[COMPILE] immediate words and sometimes you want to [ word ] execute
>nonimmediate words.
[COMPILE] is used to force compile a "compiling word" (immediate word),
viewed simply as a switch that disables the immediacy of the following
word.
[ and ] are used to drop out and then back into the compiling state.
Alternatives aren't nice?
>Since some words are one way and some another
>it isn't always clear what you'll get when you ['] word EXECUTE them.
For a given system having words of different type, IMMEDIATE,
state-smart, or not doesn't confound what is returned by [']. Finding
consistency among varying systems may be a different story.
>Not to mention that some words have flipflopped in succeeding standards
>(partly reflecting changing practice) so you can't be sure on foreign
>systems whether they'll be exceptions or not.
>
Portability of compiling words is an unresolved issue. But for local
words it's trivial to tell if a word is immediate or not. Most systems
show it with a word like SEE . But using a word that unknowingly uses
a compiling word is the usual example of the problem.
>The simple obvious *right* way to do it is to get rid of all the
>exceptions. When you're compiling you compile, when you're
>interpreting you interpret. If you want to do IF you write [ IF ] .
>It's always completely clear whether you're doing it now or doing it
>later. But it's surely too late for that, everybody is firmly set in
>our habits and it would break all of everybody's code.
>
Exceptions or alternatives, depends on what spin one wants.
Ok, you want to keep [ and ] to start and stop compilation state and
get rid of all compiling words along with [COMPILE] . No more Forth
macros (not talking about Wil Baden's type) but only stop and start
compiler as needed. Is there anything a compiler word can do that
can't be done by stopping the compiler, execute a word and restart the
compiler? Is [ FOO ] equivalent to an immediate FOO ?
>Sometimes while I'm compiling I want to do CHAR right then. Sometimes
>I want to compile CHAR to do later. Sometimes I might even want a word
>that will compile CHAR into another word later. It's even possible
>that in some special case I might want a word that will tell its
>daughter words to compile CHAR into their daughter words. These are
>complex concepts and I might be better off not to think them. But
>they're even more complex when I have regular words and exceptional
>words and I need two different methods to handle both kinds. And it's
>*out of hand* when I can't be sure ahead of time whether a word is
>an exception or not.
>
Deferred compilation, COMPILE , is complex. Having to contend with
compiling words and knowing when to use [COMPILE] is more trouble.
Word needing [COMPILE] is not an exception. It's a whole different
intent.
>Chuck was having an off day when he invented IMMEDIATE . It fit his
>immediate needs and he never updated it to something better. Or
>maybe now he's at last improved it, maybe with Color Forth he has a
>color to say "do this now" versus "compile this" and all the words
>that used to be immediate get the new color when they need it.
>
IMMEDIATE saves having to place [ and ] around compiling words. Maybe
he didn't see clarity as a problem or he thought with discipline it
could be managed.
>Since the tools are flawed the obvious solution is to never do
>anything so complicated that the flaws create a failure. Some simple
>rules that help with that are:
>
>1. Keep a list of all your state-smart words and be cautious with them.
>2. Never execute a state-smart word inside anything else. Remember that
> any word that executes a state-smart word is state-smart itself.
>3. Never ever POSTPONE a state-smart word.
>
Well, it seemed that most of the discussion had to do with compiling
words and now we're specific to subcategory state-smart. Did I miss a
turn in the road or is state-smart being used to include all compiling
words and not just those with mixed semantics.
Number 2 is the gotcha.
Discussion starts here.
From the above I ascertained the following items:
1) Portability of compiling words is unresolved.
This is just a recognition of the current status in this area.
2) Proposal to do away with category of compiling words to clarify
when a word is executing and when it is being compiled.
The example looked simple enough. Let's try it for real.
I'll replace [CHAR] in a word with CHAR.
: FOO [CHAR] A . ; \ this get replaced by
: FOO [ CHAR A ] LITERAL . ; \ this
I'm not going to like this when working with longer definitions in
a block file. I'll be paying the price for clarity every day.
Most likely you had something better in mind.
3) Allegation that state-smart and compiling words confound prediction
of what will occur after bracket-tick and execute of word.
For a given system compiling words do not confound what is returned
by bracket-tick. There may be disagreement among systems as to
what should be returned but that just something the people who
build different systems need to resolve.
Predicting the final outcome of a tick and execute may however
be more complex when compiling words are involved, but is it to a
degree worth all the fuss? Is a word containing [ FOO ] more
predictable than a word containing an immediate FOO ?
4) Deferred compiling is complex; the addition of compiling words make
it intolrable.
I used Forth a long time without ever bothering to look much under
the hood. When the time came that I did, I found it required a good
long look at compiling words, compiler control words, tick and
sequence timing. When on the low end of the learning curve, it
was very confusing when to use COMPILE and when to use [COMPILE]
but now there is little mystery. I still may need to be more
attentive when doing deferred compilation but if [COMPILE] is taken
out of the mix I wouldn't feel much gain.
5) Judicial use of state-smart words.
I won't go so far as to say never but for sure the creation of
compiling words should be done in a judicial manner. They serve
more as an extension to the compiler than for application. How
much extension does the compiler need? Very little.
I can see compiling words being potentialy troublesome but I'm far
from feeling that they are "the root of all evil". And what you view as
pestering exceptions, I welcome as fexible alternatives. I don't aim to
sway anyone's viewpoint; just want to stand and be counted. If I find
the count is 1 then I will re-evaluate.
>
>I keep with the other side here - glad to have the distinction of [CHAR]
>and CHAR. Encountered too many errors when formerly writing with ASCII.
>
With normal use or when getting creative?
>>I'll restate my POV: Forth has a simple obvious approach. When you
>>interpret you execute words and when you compile you compile them.
>>But then we got exceptions, words that you execute while compiling.
>Exceptions being "compiling words", words that do a job when the
>word containing them is being compiled. In other languages words that
>do this are "macros".
Yes. In Forth you can't tell them from other words, and when they
need special treatment you have to just know to provide it.
We have a potential hierarchy of compiling words. There are
Regular words.
Words that compile.
Words that compile words that compile.
Words that compile words that compile words that compile.
Etc.
Then we have words that compile sometimes and don't compile
other times, eg depending on STATE .
What we want to do _can become_ inherently complicated. It
makes sense to keep it simple, to write more code instead of
doing clever compiling tricks. If we do complicated things
it makes sense to do them in ways that show what you're doing
instead of hiding the subtle peculiar behaviors inside words
that give no indication what's going on. Unless you can make
the subtle behavior bombproof.
One suggestion I've tried out is to name all the new
compile-only words with [] Like [DO-THIS] . It's a reminder
that they're only for compiling. But most of the standard
compile-only words don't do it, and [IF] [ELSE] [THEN] do it
and break that rule. A word that compiles compile-only words
gets named [[DO-THIS]] . Etc. I haven't thought of a good
notation to warn me about state-smart words.
Conceptually it's a mess and it would be simpler to throw out
the whole thing and do it right this time. But we won't.
>>Since some words are one way and some another
>>it isn't always clear what you'll get when you ['] word EXECUTE them.
>For a given system having words of different type, IMMEDIATE,
>state-smart, or not doesn't confound what is returned by [']. Finding
>consistency among varying systems may be a different story.
You know it will be executed, assuming ['] finds the word and you'll
get an abort or a throw if it doesn't. If it's a compile-only word
that you execute the word that executes it is implicitly compile-only.
If it's a state-smart word you execute the word that executes it will
be implicitly state-smart.
>Well, it seemed that most of the discussion had to do with compiling
>words and now we're specific to subcategory state-smart. Did I miss a
>turn in the road or is state-smart being used to include all compiling
>words and not just those with mixed semantics.
State-smart is the worst of it. All of it works. All of it can be
made to do things you wouldn't expect. We can work with poor tools
so long as we keep it simple, so it could be argued that having bad
tools is a strong encouragement to us to maintain simplicity.
>Discussion starts here.
> From the above I ascertained the following items:
>1) Portability of compiling words is unresolved.
> This is just a recognition of the current status in this area.
Lots of things are resolved about it, there are just some issues
left. The recent standards committee decision collapse the waveform
some. If you want your code to be widely portable to standard systems,
1. Words that POSTPONE should be treated as compile-only.
2. Words that execute compile-only words should be treated as compile-only.
3. You can't reliably ' or ['] a compile-only word.
4. On some systems ' and ['] provide only the interpret behavior, so
standard state-smart words won't be state-smart if 'ed.
5. Words that execute state-smart words are state-smart.
6. Words that compile state-smart words have state-smart daughters.
7. On some systems POSTPONE provides only the compile behavior, so
standard state-smart words won't be state-smart if POSTPONEd.
There are probably some other things to keep in mind that I don't think
of right now. There are lots of things you can do portably and there
are some things you can't.
> The example looked simple enough. Let's try it for real.
> I'll replace [CHAR] in a word with CHAR.
> : FOO [CHAR] A . ; \ this get replaced by
> : FOO [ CHAR A ] LITERAL . ; \ this
: FOO [ CHAR A LITERAL ] . ;
> I'm not going to like this when working with longer definitions in
> a block file. I'll be paying the price for clarity every day.
> Most likely you had something better in mind.
Rename LITERAL as something shorter. For that matter you could have
new names.
: CHAR,, CHAR LITERAL ;
I used a second , since LITERAL is so different from , but maybe some
better short name would suggest itself. [CHAR] would look funny.
Two actions, two names. With state-smart you can get rid of a name
at the expense of needing to jump through hoops when you want the
other behavior at what's usually the inappropriate time, and you
have to keep track. CHAR,, compiles. Something that compiled CHAR,,
would only execute properly while making compiling words. The
complex behaviors are still there, and it would still be possible to
get confused about them. But at least you always know whether right
now you're compiling or executing.
> Predicting the final outcome of a tick and execute may however
> be more complex when compiling words are involved, but is it to a
> degree worth all the fuss? Is a word containing [ FOO ] more
> predictable than a word containing an immediate FOO ?
It's certainly easier to predict -- you don't have to know whether
it's immediate or not. [ FOO ] executes and FOO is compiled. It
probably isn't worth the fuss. If we were starting from scratch it
might be. We understand how it works now, and one more thing to
enforce KISS on us doesn't matter when we're intent on maintaining
KISS anyway.
> I can see compiling words being potentialy troublesome but I'm far
>from feeling that they are "the root of all evil". And what you view as
>pestering exceptions, I welcome as fexible alternatives. I don't aim to
>sway anyone's viewpoint; just want to stand and be counted. If I find
>the count is 1 then I will re-evaluate.
I tend to agree with you. It would be nice to have a cleaner way.
Anton made a cleaner way but it wasn't compatible enough with the
old way and the standards committee wasn't willing to throw out the
old way and only allow his way.
On 1999-04-24 jeth...@ix.netcom.com said:
:If you only have one exception you can put it into the compiler.
:When the compiler's compiling and it sees the "[" token it switches
:to the interpreter. That's simpler than checking each word to see
:whether it's immediate.
Actually, I suspect it would be of the same complexity, given that you
can't test for immediacy until you've found the word, which is always
the hard bit. And with some dictionary structures, you don't even have
to check for immediacy, either; you just jump to either the interpretive
or the compiled version, depending on modes.
So you have two concepts of equivalent complexity, but one is completely
general and one is quite limited. I think even Chuck would choose the
more general variant in this case. :> I think he did.
[ColorForth]
:For regular Forth that would translate to a word that executes the
:next word only, as opposed to [ which switches and doesn't switch
:back. OK, we could have two tokens for the compiler to recognise, [
:and ` . ` IF says interpret the following string. It would seem
:completely natural if we hadn't gotten used to the other way.
Yes, except that if your tokens are space-delimited you have to
the equivalent of WORD twice, whilst if they are space-equivalent they
look ugly and make soure unreadable. This is why using colour-change
tokens is a comparative win; you see the effect but you don't have to
see the token, leaving you free to focus on what the words mean. The
drawback is that you have to use several kinds of space.
On 1999-04-25 m...@intranetsys.com said:
:I see. Does the color-change-token (cct) only affect the next token,
:or is it more like a mode change until the next cct comes along?
I have no idea, but if I were coding it I would have made it the former,
and that is how I conceptually understand ColorForth.
:If the former interesting but cumborsome (3 different types of
:spaces to deal with). If the latter then we're back to explicit
:mode changes, although color replaces the clutter words.
True. But I suspect that the 3 different kinds of space (more when you
add in numbers and tick) is more manageable than the different mode
changes; for one thing, you can have a "default space" and change its
colour using control keys. It may be cumbersome, but most of the time it
will do what you want, and then you get the benefit of not having to
figure out keystrokes for 8 spaces but the interpreter will still see it
as being 8 different key strokes.
:Quite fascinating. In many ways this is a predictable next step in
:Chuck's underlying trend of being explicit with what you want
:rather then leaving the general case to an underlying mechanism,
:and needing other mechanisms to handle the exceptions.
I suppose it is, though as yet I'm not convinced it's the simplest
approach. I think the best approach to this is the concept of having a
"compiling CFA" like Zsoter's OOF, which is probably even more general
than the IMMEDIATE concept, and a good deal faster, even though it costs
an extra pointer in header space. For example, in something I'm knocking
up at the moment, I have this header structure:
<name field> <compiling CFA> <interpreting CFA>
(All fields are 4 bytes, and WORD turns the next token into a base 63
number - about the last 16/3 characters.) When a word is found, its
interpreting CFA is stored in a special variable. In interpreting mode
the interpreting CFA gets called, but in compile mode the compiling CFA
gets called and compiles a call to the (saved) interpreting CFA. All the
compiler loop has to do is select one of two words, which corresponds to
values of 0 and 4 in a STATE variable somewhere, and execute it.
(Actually I keep the system in compile mode all the time, but throw away
code that is compiled outside a definition - after executing it of
course.)
:Quite the contrary of OOP when you think about it. ;>
Tee hee. :> I'm not quite convinced by OOP yet. If you need it, it's
perfect, but I'm not sure it's a sensible way to write programs in
general. I think it's more use at OS level than in core code, when you
will actually need the kind of loose interface it enables.
>Actually, I suspect it would be of the same complexity, given that you
>can't test for immediacy until you've found the word, which is always
>the hard bit. And with some dictionary structures, you don't even have
>to check for immediacy, either; you just jump to either the interpretive
>or the compiled version, depending on modes.
>So you have two concepts of equivalent complexity, but one is completely
>general and one is quite limited. I think even Chuck would choose the
>more general variant in this case. :> I think he did.
I'll try it.
Old way:
DEFER HANDLE-WORD
: COMPILE-WORD ( i* xt 1|-1 | i* ca 0 -- j*)
DUP IF
1+ IF
EXECUTE ELSE
COMPILE,
THEN
ELSE
NUMBER POSTPONE LITERAL
THEN ;
: INTERPRET-WORD ( i* xt 1|-1 | i* ca 0 -- j* )
IF
EXECUTE ELSE
NUMBER
THEN ;
: [ ['] INTERPRET-WORD [IS] HANDLE-WORD ; IMMEDIATE
: ] ['] COMPILE-WORD [IS] HANDLE-WORD ;
: INTERPRET ( i* ca len -- j* )
THE-SOURCE 2! 0 >IN !
BEGIN
SOURCE >IN @ > WHILE
BL WORD FIND HANDLE-WORD
REPEAT ;
This is probably enough, and I can't give a definition
for FIND portably since it depends on subtleties of the
headers.
I'll write the other version as if it was written in the
code that it runs.
: COMPILE-WORD ( i* xt true | i* ca false -- j* )
IF
DUP [ ' [ LITERAL ] = IF
] ELSE
COMPILE, THEN
ELSE
NUMBER LITERAL
THEN ;
About the same. I needed an extra LITERAL but no POSTPONE .
: INTERPRET-WORD
The same exactly.
: ] [ ' COMPILE-WORD LITERAL ' HANDLE-WORD LITERAL ] IS' ;
This is the same but the wordset we use now would need to
be changed around for convenience. Something like
: ]IS[ LITERAL ' LITERAL IS ;
: ] [ ' COMPILE-WORD ]IS[ HANDLE-WORD ] ;
It looks a little funny and it's slightly longer.
: [ [ ' INTERPRET-WORD ]IS[ HANDLE-WORD ] ;
Basically the same.
: INTERPRET
The same exactly.
Nothing is more complex so far except a little of the
syntax. What really gets simpler is FIND which becomes
: FIND ( ca -- ca false | xt true )
Every word is simpler, there's no need to tell whether
it's immediate or not. At a minimum you get an extra
bit in each header to use however you like.
It's simpler but it's also less powerful. You always
know whether the current word is executed or compiled.
If you tell it to execute it executes and if you tell
it to compile then it compiles. You can make state-smart
words but you probably don't want to -- most words will
be executed in interpret state, and a state-smart word
won't execute while compiling if it's found in the input
stream, it will only do its state-smart behavior after
it's been compiled into another word that internally
switches to compile-state. The useful behavior is gone
and the buggy behavior remains in limited form.
It looks to me conceptually simpler but it might not be
simpler to use. Information that a normal Forth compiler
hides from you would be visible at a glance, but you'd
have to write it in to make it visible at a glance which
is more work. (Although you could design a text editor
that would do that with a single keystroke.) Current
Forth users would have to change their habits to use it
and there's no reason to expect that any will. And of
course it breaks all existing code and it's completely
nonstandard.
Section 3.4.3.2 Interpretation semantics
Unless otherwise specified in an "Interpretation:" section of the glossary
entry, the interpretation semantics of a Forth definition are its execution
semantics.
...
Section 3.4.3.3 Compilation semantics
Unless otherwise specified in a "Compilation:" section ot the glossay entry,
the compilation semantics of a Forth definition shall be to append its
execution semantics to the execution semantics of the current definition.
Philip Preston.
A number of techniques for native code compilation and optimisation involve
making "normal" words immediate. Problem: these techniques could not be used
to implement FORTH-83 systems because that standard had to specify which
words were immediate and which were not so that programmers would know when
to use [COMPILE] and when to use COMPILE . ANS does not need to specify the
immediacy or non-immediacy of most words because POSTPONE will produce the
right result in either case. So these techniques can be used to implement
ANS systems.
That, as I understand it, is the problem that POSTPONE was intended to solve
and AFIK has solved successfully.
> The fact that POSTPONE can test a word and do
>the appropriate COMPILE or [COMPILE] action in itself is not sufficient
>to solve the problem.
Is this the same problem that I described above? If so, in what respect has
it not been solved? If not, what problem are you referring to?
> However, that aspect has been flaunted to garner
>support for justifying its use but it has little value and only
>sidetracks the unwary from the unresolved issue.
What is the unresolved issue?
Philip Preston.
[snip]
> :Quite fascinating. In many ways this is a predictable next step in
> :Chuck's underlying trend of being explicit with what you want
> :rather then leaving the general case to an underlying mechanism,
> :and needing other mechanisms to handle the exceptions.
>
> I suppose it is, though as yet I'm not convinced it's the simplest
> approach.
Neither am I, I haven't grasped all the consequences of such a model change.
> I think the best approach to this is the concept of having a
> "compiling CFA" like Zsoter's OOF, which is probably even more general
> than the IMMEDIATE concept, and a good deal faster, even though it costs
> an extra pointer in header space. For example, in something I'm knocking
> up at the moment, I have this header structure:
>
> <name field> <compiling CFA> <interpreting CFA>
>
> (All fields are 4 bytes, and WORD turns the next token into a base 63
> number - about the last 16/3 characters.) When a word is found, its
> interpreting CFA is stored in a special variable. In interpreting mode
> the interpreting CFA gets called, but in compile mode the compiling CFA
> gets called and compiles a call to the (saved) interpreting CFA. All the
> compiler loop has to do is select one of two words, which corresponds to
> values of 0 and 4 in a STATE variable somewhere, and execute it.
>
> (Actually I keep the system in compile mode all the time, but throw away
> code that is compiled outside a definition - after executing it of
> course.)
I rewrote my Forth to have 3 flags with each word (interpreter, compiler,
immediate) and only one cfa in the header. The compiler only sees words which
have the compiler bit set, the interpreter only sees words which have the
interpreter bit set (state-smartness is kept where it belongs, e.g. in the
outer interpreter). No STATE. When I need a word which has an unusual
combination of interpretation and compilation behaviors (which is rare, but
happens), I create one definition for each behavior. I have 2 sets of tick
words ' and ['] for the interpreter cfa, C' and [C'] for the compiler cfa
(which may or may not be the same cfa).
No more state-smart problem, no more "what does ' return" problem, supports
words which are compile-only and words which are compiling (compile-only and
immediate) and so-called combined behavior words (which used be state-smart).
When the i. and c. behaviors differ, which is a minority case, they're
factored into separate definitions. I'm not saying this is the ultimate
solution, but for me its been a step in the right direction compared to ANS's
muddled model.
> :Quite the contrary of OOP when you think about it. ;>
>
> Tee hee. :> I'm not quite convinced by OOP yet. If you need it, it's
> perfect, but I'm not sure it's a sensible way to write programs in
> general. I think it's more use at OS level than in core code, when you
> will actually need the kind of loose interface it enables.
[ Flame-proof garments in place]
Agreed, I view most OO programming as "programing by exception", e.g. "what I
need is just like this class, except I need to override these methods with
these others..." ad nauseum. I'd rather explicitly code based on what I want,
rather than coding exceptions to what I don't want. This is a major cause of
bloat in oop IMHO.
With oop you want the banana, you get the gorilla :)
[ Evasive Maneuvers on - Running and ducking like heck =:-o ]
Cheers,
Mark W. Humphries
> Communa (lis...@zetnet.co.uk) -- you know soft spoken changes nothing
-----------== Posted via Deja News, The Discussion Network ==----------
> I haven't thought of a good notation to warn me about state-smart words.
Don't waste a good notation on state-smart words. Use a stupid one
instead, say ?[]word-name (that is, ``I'm going to ask if we are in [
or in ] state).
(
----------
Virtually,
Bruce McFarling, Newcastle,
ec...@cc.newcastle.edu.au
)
>I rewrote my Forth to have 3 flags with each word (interpreter, compiler,
>immediate) and only one cfa in the header. The compiler only sees words which
>have the compiler bit set, the interpreter only sees words which have the
>interpreter bit set (state-smartness is kept where it belongs, e.g. in the
>outer interpreter). No STATE.
I guess this idea has been discussed in clf before. It sure looks
familiar. And I (kinda) like it.
A quick question: if you POSTPONE such a word, what do you postpone? The
compiler version? the interpreter version? The decision which one to
use? This last case is in fact a new shape of state-smartness, if you
ask me.
Bart.
What two words? The only thing different in the two runs was that FOO
was made immediate in the second run and broke X. The point being that
the result of POSTPONE FOO is dependent on FOO's immediacy. Using
POSTPONE doesn't free the programmer from having to know the nature of
FOO.
>Try it this way:
>
>: FOO ." broke" CR ;
>: A POSTPONE FOO ; IMMEDIATE
>: X ." A isn't " A ;
>
>X
>
>: A ." broke" CR ;
>: X ." A isn't " A ;
>
>X
>
>Given two words with the same compiled behavior, one of them immediate
>and one not, you don't have to know whether they're immediate.
>
>Does that not seem like a fair comparison?
>
Its a fair comparison but it doesn't appear relative to my point. It
does, however, suggest an aspect that may be potentially useful to
exploit in some situations.
>OK, let's take it one step
>further.
>
>: FOO-EXE ." broke" CR ;
>: FOO POSTPONE FOO-EXE ; IMMEDIATE
>: A POSTPONE FOO ; IMMEDIATE
>: X ." A isn't " A ;
>X
>
>: FOO ." broke" CR ;
>: A POSTPONE FOO ; IMMEDIATE
>: X ." A isn't " A ;
>
This is worse. Change FOO-EXE to immediate and X is broke by A's
grandson.
>We don't have to know whether FOO is immediate for POSTPONE to work,
>we only have to know the result of encountering FOO in the input stream
>during compilation.
>
There is no claim that POSTPONE FOO can't be set up in a manner where FOO
results in the same behavior whether immediate or not. The claim being
challanged was that POSTPONE FOO frees the programmer from having to know
about immediacy, but the programmer had to consider it even in this case
so as to arrange it in such a manner to be a non-issue. It doesn't come
automatic by virtue of using POSTPONE.
>>Example 2: POSTPONE fails to hide kernel implementation differences
>
>> On system X : Foo ." hello world" ; IMMEDIATE
>> On system Y : Foo ." hello world" ;
>
>> On both systems : A postpone Foo ;
>
>> On system X A hello world ok \ what was intended
>> On system Y A ok \ !@# broke
>
>> On the programmer's system X where Foo is immediate, A worked. But when
>>his code was compiled on system Y that had Foo but it wasn't immediate,
>>then A broke.
>
>A includes POSTPONE and you have no business executing A while
>interpreting.
>
rule: Never interpret a word that includes POSTPONE
(should POSTPONE include a compiling state check, ?COMP)
My example did confirmed your rule, but that's beside the point.
If you like, I will use your example.
If FOO-EXE is immediate on system Y, then X breaks on system Y.
>Would this have worked correctly if you'd done
>
>: A [COMPILE] Foo :
>
>?
No, but [COMPILE] was not claimed to hide kernel implementaion details.
The claim was that POSTPONE did and this was to show that it doesn't.
>
>
>>Summary:
>> In that POSTPONE neither achieves it's stated goals nor shows
>>substantial advantage over words it would replace,it should be
>>assigned to experimental status.
>
>Apart from whether POSTPONE should be experimental, it would be
>interesting to have words with experimental status. I should
>have posted my experimental words to one or more of the websites
>that promote such things, and I haven't.
>
>
--
[snip]
> A quick question: if you POSTPONE such a word, what do you postpone? The
> compiler version? the interpreter version? The decision which one to
> use? This last case is in fact a new shape of state-smartness, if you
> ask me.
The compiler-xt seems to me the logical one to postpone during compilation.
: POSTPONE ( -- )
COMPILER-WORD DEFINED DUP IMMEDIATE? ~{ COMPILE COMPILE } CFA , ; COMPILING
- COMPILER-WORD is just a bit-mask
- DEFINED gets token from input stream, looks requested version up, returns a
header address if found (lfa), rejects token if not found
- IMMEDIATE? ( lfa - flag )
- ~{ aka NOT IF
- } aka THEN
- CFA ( lfa -- cfa )
Cheers,
Mark W. Humphries
>
> Bart.
The result of POSTPONE FOO is dependant on FOO's behaviour. There is nothing
remarkable about the fact that it only takes the inclusion or exclusion of a
single word to change this significantly and nothing special about IMMEDIATE
in this respect.
> Using
>POSTPONE doesn't free the programmer from having to know the nature of
>FOO.
Programmers need to know the behaviour of FOO. They need to know its stack
effects, its execution semantics, its compilation semantics and so on. If
the behaviour of FOO is adequately documented they don't need to know the
details of its implementation. The immediacy of FOO is an implementation
detail.
Of course, if the behaviour is not documented, as in your example,
programmers do need to look at the implementation (the source code) and
deduce the behaviour from that. To correctly deduce the behaviour from the
implementation immediacy must be taken into account but it does not need to
be documented as part of that behaviour. If programmers know a word's
behaviour they don't need to know whether or not IMMEDIATE was used in its
implementation.
Philip Preston.
I think it really is time for a reality check, before people go off suggesting
multiple execution tokens, multiple lists, objects or whatever to solve a
problem that only exists if you you want to do this sort of nonsense.
Anton Ertl wrote:
> In article <7f6u5e$5vt$1...@news.tuwien.ac.at>,
> an...@mips.complang.tuwien.ac.at (Anton Ertl) writes:
> > In some situations we want to compile an immediate word into another
> > definition, instead of executing it when it occurs in another
> > definition. The purpose of this poll is to find out what is the
> > common usage for doing this.
<snip>
>A couple of big question have to be asked. Why do you want to postpone an
>immediate word and interpret it? A useful example would be nice. Why do you
>want to make your code so difficult to understand?
>I think it really is time for a reality check, before people go off suggesting
>multiple execution tokens, multiple lists, objects or whatever to solve a
>problem that only exists if you you want to do this sort of nonsense.
This sort of thing gives a lot of power. For me those special words are
mostly parsing words. The whole point of immediate words is to change the
compiler, to get the compiler to do things at compile-time that it wasn't
doing before. You can change the language to fit your needs, get new
elegance and power. You can extend the language to get new syntax that
fits your specific needs. Power.
I always think the special compiling words will be easy to use -- otherwise
I wouldn't consider them. It might be a little hard to understand how they
work but it should be completely obvious what to do with them.
The big problems come when you start extending the special extended compiling
words. Things that worked perfectly when you just used them the way you
intended start doing weird things when you use them inside other words in
ways you didn't intend before. I'd give examples but I've mercifully
forgotten them.
It would be possible to revise the methods so that all the weird special
cases smooth out and the whole thing is logically consistent. It would
still be complicated to use the special cases. People aren't too
interested because most of them have tools that work as well as they need.
>Tom Zegub wrote in message
><572CD3C7F2B80F21.3420312E...@library-proxy.airnews.ne
>t>...
>> The point is that POSTPONE doesn't do any better than COMPILE and
>>[COMPILE] in handling IMMEDIATE words in a portable way. POSTPONE
>>didn't solve anything.
>
>A number of techniques for native code compilation and optimisation involve
>making "normal" words immediate. Problem: these techniques could not be used
>to implement FORTH-83 systems because that standard had to specify which
>words were immediate and which were not so that programmers would know when
>to use [COMPILE] and when to use COMPILE . ANS does not need to specify the
>immediacy or non-immediacy of most words because POSTPONE will produce the
>right result in either case. So these techniques can be used to implement
>ANS systems.
>
>That, as I understand it, is the problem that POSTPONE was intended to solve
>and AFIK has solved successfully.
>
To POSTPONE most "normal" words without regard to immediacy should give
the right result 50 per-cent of the time. However, I assume there is
more to the story which makes it work.
But assume POSTPONE was the answer for some situation. POSTPONE does no
more than give either [COMPILE] or COMPILE behavior based on immediacy test.
The two standard words were sufficient for whatever use POSTPONE has.
There was no need to chunk them. Use them in combination on occasion when
needed. For the general case where the programmer has control of the code
the use of [COMPILE] or COMPILE alone is appropriate and adds clarity as
to intent.
>> The fact that POSTPONE can test a word and do
>>the appropriate COMPILE or [COMPILE] action in itself is not sufficient
>>to solve the problem.
>
>Is this the same problem that I described above? If so, in what respect has
>it not been solved? If not, what problem are you referring to?
>
The claim that POSTPONE makes immediacy a don't care for the programmer.
For that to be the case POSTPONE would have to give the same behavior for
a word whether it was immediate or not. What words do this?
>> However, that aspect has been flaunted to garner
>>support for justifying its use but it has little value and only
>>sidetracks the unwary from the unresolved issue.
>
>What is the unresolved issue?
>
Portability in general with respect to immediacy. ANS does not govern
a words behavior with respect to immediacy. POSTPONE in itself does not
provide immunity to immediacy differences among systems.
From your posts leading up to this one, you're question has been, "what
do you think is broke with POSTPONE?" Well, nothing. The flak is not that
POSTPONE is broke but that it seems to get more credit than it deserves.
Claims look far-fetched such as:
"ANS does not need to specify the immediacy or non-immediacy of most words
because POSTPONE will produce the right result in either case."
POSTPONE will produce a result in either case but if the result is right
depends on if its the one the programmer expected.
> The big problems come when you start extending the special extended compiling
> words. Things that worked perfectly when you just used them the way you
> intended start doing weird things when you use them inside other words in
> ways you didn't intend before. I'd give examples but I've mercifully
> forgotten them.
I think that if you have the visibility flags (interpret &
compile), there should be conditions in which the visibility is inherited
when that word gets compiled into another word.
Perhaps when postponing a word that is invisible to the
interpreter, the word being defined should be made invisible. Then rather
than having to catch or correct the problem of words without interpretor
behaviour being indirectly executed by the interpreter, the problem may be
prevented by making the word carrying that behaviour invisible to the
interpreter.
I am not yet confident that this is something which can be done
automatically, but it seems to be a straightforward way of implementing
someone's (Jonah's?) injunctions for avoiding trouble with POSTPONE.
Virtually,
Bruce R. McFarling, Newcastle, NSW
ec...@cc.newcastle.edu.au
[snip]
> I think that if you have the visibility flags (interpret &
> compile), there should be conditions in which the visibility is inherited
> when that word gets compiled into another word.
> Perhaps when postponing a word that is invisible to the
> interpreter, the word being defined should be made invisible. Then rather
> than having to catch or correct the problem of words without interpretor
> behaviour being indirectly executed by the interpreter, the problem may be
> prevented by making the word carrying that behaviour invisible to the
> interpreter.
> I am not yet confident that this is something which can be done
> automatically, but it seems to be a straightforward way of implementing
> someone's (Jonah's?) injunctions for avoiding trouble with POSTPONE.
That's a possibility. I just set the new word's compiler flag explicitly. I
don't like too many things happening implicitly under the hood. Eventualy you
run into a special case and have to write a work around to such automatic
behavior. End result: code bloat.
: NEW-WORD .... ; COMPILE-ONLY
or
: NEW-WORD ... ; COMPILING
: COMPILING ( -- ) IMMEDIATE COMPILE-ONLY ;
Cheers,
Mark W. Humphries
>The claim that POSTPONE makes immediacy a don't care for the programmer.
>For that to be the case POSTPONE would have to give the same behavior for
>a word whether it was immediate or not. What words do this?
If you know what the behavior is, POSTPONE will give the same behavior
regardless whether the word is immediate or not. Whether the compile
behavior is to be compiled and execute later, or the compile behavior
is to compile something that will execute later, either way POSTPONE
will give you that result.
But if you don't know what the word does you can't depend on what it
will do when it's POSTPONEd. With POSTPONE you don't care whether
the word is immediate or not. You don't care *how* it gets the effect
it does, but you have to know what the effect is.
>>What is the unresolved issue?
>Portability in general with respect to immediacy. ANS does not govern
>a words behavior with respect to immediacy. POSTPONE in itself does not
>provide immunity to immediacy differences among systems.
The words that POSTPONE doesn't help with are things like LEAVE where
Forth-79 specified one thing and Forth-83 specified another. Two
different behaviors are required by different systems and POSTPONE
can't and shouldn't automatically turn one into the other. But if
you POSTPONE a standard word the standard tells you what the result
should be, and if your system gives a different result then you don't
have a standard system. The standard does not tell you whether the
word is immediate, though -- it only says what result you should get
if it's immediate, and the same result if it isn't.
>From your posts leading up to this one, you're question has been, "what
>do you think is broke with POSTPONE?" Well, nothing. The flak is not that
>POSTPONE is broke but that it seems to get more credit than it deserves.
>Claims look far-fetched such as:
> "ANS does not need to specify the immediacy or non-immediacy of most words
> because POSTPONE will produce the right result in either case."
>POSTPONE will produce a result in either case but if the result is right
>depends on if its the one the programmer expected.
If it's a standard word or if it's written using standard words, the
result the programmer should expect is the result the standard specifies.
If it's your own word then it should give the result you specify, or else
you coded it wrong.
> Perhaps when postponing a word that is invisible to the
>interpreter, the word being defined should be made invisible. Then rather
>than having to catch or correct the problem of words without interpretor
>behaviour being indirectly executed by the interpreter, the problem may be
>prevented by making the word carrying that behaviour invisible to the
>interpreter.
That ought to be perfectly workable on a lot of systems. We can't code it
using only standard code because we don't have a good way to make words
invisible using only standard code. The only way I can see is to use
wordlists, and if compilation changes the search order then some code that
uses GET-ORDER and SET-ORDER will probably break.
(You could probably do it, and then redefine GET-ORDER and SET-ORDER to
hide those details from a user and automatically rearrange things so they
work right. It looks tricky but probably feasible.)
> I am not yet confident that this is something which can be done
>automatically, but it seems to be a straightforward way of implementing
>someone's (Jonah's?) injunctions for avoiding trouble with POSTPONE.
It should work fine on some particular systems, but it isn't something
we can demand of every system -- for one thing some systems are set up
intentionally to use state-smart words in ways that this would interfere
with, and the standard doesn't forbid standard systems to do that, it
only forbids standard programs to use those capabilities without
documenting the portability problem that results.
Jonah Thomas wrote:
> Charles Esson <char...@cvs.com.au> wrote:
>
> >A couple of big question have to be asked. Why do you want to postpone an
> >immediate word and interpret it? A useful example would be nice. Why do you
> >want to make your code so difficult to understand?
>
> >I think it really is time for a reality check, before people go off suggesting
> >multiple execution tokens, multiple lists, objects or whatever to solve a
> >problem that only exists if you you want to do this sort of nonsense.
>
> This sort of thing gives a lot of power. For me those special words are
> mostly parsing words. The whole point of immediate words is to change the
> compiler, to get the compiler to do things at compile-time that it wasn't
> doing before.
A very good reason to postpone an immediate word and use it to compile code, but
not to postpone it and interpret it.
> You can change the language to fit your needs, get new
> elegance and power. You can extend the language to get new syntax that
> fits your specific needs. Power.
I'm not arguing against immediate words, nor for that matter am I argue against
state. Both have their application. What I really find upsetting is people
complaining that a immediate word postponed and and then interpreted doesn't behave
according to their interpretation of the standard. Or an immediate word ticked and
then used in a situation where the compilation or interpretation semantics are
required can cause problems.
>
> I always think the special compiling words will be easy to use -- otherwise
> I wouldn't consider them. It might be a little hard to understand how they
> work but it should be completely obvious what to do with them.
What do believe tick should do? If it doesn't return a token that carries both
both the compile semantics and the interpret semantics then you can't postpone and
expect to extract the desired semantics. This is the fundamental problem with tick,
you lose the immediacy information. It matters very little if the word was in a
different list or used flags to provide the immediacy information in the first
place.
I have implemented the different list option, and these are the problems I saw
before abandoning that option
1) The system is bigger because you have two entries for most word.
2) Just which version do you have ' return.
3) You can still make up strange code that will fall over just as you can with a
flag based implementation.
I am also at a loss to see how a version of forth that retains immediacy
information through the ' is more standard than one that does not. As I see it both
systems will be standard, and as both will behave in different ways when you ' and
then try and extract the compilation or interpretation semantics the result is
ambiguous.
> The big problems come when you start extending the special extended compiling
> words. Things that worked perfectly when you just used them the way you
> intended start doing weird things when you use them inside other words in
> ways you didn't intend before. I'd give examples but I've mercifully
> forgotten them.
And I wish a few more people would forget about them. So much written around such
obscure code.
>
>
> It would be possible to revise the methods so that all the weird special
> cases smooth out and the whole thing is logically consistent.
I am yet to see an example that provides a simple solution to the perceived
problems. If you ' a word it losses it's immediacy. The standard says it provides
an execution token, it says no more. If you then take that execution token and use
it in situation where you need the compiling semantics or the execution semantics,
stiff. I can't find one place in the standard that says that should be possible.
> It would
> still be complicated to use the special cases. People aren't too
> interested because most of them have tools that work as well as they need.
Perhaps people aren't interested because code written in such a way is impossible
to understand. And also perhaps those pushing for a particular interpretation of
the standard are pushing for an interpretation that is not universally shared.
Regards Charles
>> You can change the language to fit your needs, get new
>> elegance and power. You can extend the language to get new syntax that
>> fits your specific needs. Power.
>I'm not arguing against immediate words, nor for that matter am I argue against
>state. Both have their application. What I really find upsetting is people
>complaining that a immediate word postponed and and then interpreted doesn't behave
>according to their interpretation of the standard. Or an immediate word ticked and
>then used in a situation where the compilation or interpretation semantics are
>required can cause problems.
Of course we each want the standard to fit the way we code.
>> I always think the special compiling words will be easy to use -- otherwise
>> I wouldn't consider them. It might be a little hard to understand how they
>> work but it should be completely obvious what to do with them.
>What do believe tick should do? If it doesn't return a token that carries both
>both the compile semantics and the interpret semantics then you can't postpone and
>expect to extract the desired semantics. This is the fundamental problem with tick,
>you lose the immediacy information. It matters very little if the word was in a
>different list or used flags to provide the immediacy information in the first
>place.
If you ' a word, and if you then EXECUTE it while in interpret state, it should
do what the word itself would do in interpret state. If you ' a compile-only
word you might possibly get an xt and in that case the standard doesn't say
what it will do. Or you might not get one. If you ' a word and execute it
in compile state then all bets are off, it will do whatever the system
implementor wants it to.
>I have implemented the different list option, and these are the problems I saw
>before abandoning that option
>1) The system is bigger because you have two entries for most word.
Yes, that's a disadvantage for very small systems. But if you want a tiny
target system you can keep that information on the host where the size
doesn't matter (hehe it's funny to talk that way in Forth) and otherwise it
will only be a small increase -- one cell per word, if your average word has
4 cells of header and 16 cells of body that's less than a 5% increase. The
less you factor the less difference one more cell per word will make.
>2) Just which version do you have ' return.
The interpret version, and POSTPONE can return the compile version.
>3) You can still make up strange code that will fall over just as you can with a
>flag based implementation.
Yes. In either case the strange code will do the right thing, the only
problem is that the right thing isn't intuitive and it can cause trouble
for people who haven't thought it out. It's a style problem, a question
of what you like. If you understand all of Forth all the time then it
won't matter except for the 2nd-rate people who have to maintain your
code. If you're very good and programming for other people who're very
good then you'll want to keep it simple and clear on all levels. If
you're very good and you're making systems for people who aren't very
good it will make sense to make the easy stuff as easy as possible and
you can figure they won't bother with the hard stuff. I think that last
is the Open Firmware position.
>I am also at a loss to see how a version of forth that retains immediacy
>information through the ' is more standard than one that does not. As I see it both
>systems will be standard, and as both will behave in different ways when you ' and
>then try and extract the compilation or interpretation semantics the result is
>ambiguous.
That's what the committee decided. The wording of the document unfortunately
suggested to some people that only one way should be allowed.
>> It would be possible to revise the methods so that all the weird special
>> cases smooth out and the whole thing is logically consistent.
>I am yet to see an example that provides a simple solution to the perceived
>problems. If you ' a word it losses it's immediacy. The standard says it provides
>an execution token, it says no more. If you then take that execution token and use
>it in situation where you need the compiling semantics or the execution semantics,
>stiff. I can't find one place in the standard that says that should be possible.
Yes. We could change the standard to clear all this up, but it would break
everybody's code. It isn't worth it when what we get is to improve the style
for things that we don't do very much and probably still wouldn't do very much.
>> People aren't too
>> interested because most of them have tools that work as well as they need.
>Perhaps people aren't interested because code written in such a way is impossible
>to understand. And also perhaps those pushing for a particular interpretation of
>the standard are pushing for an interpretation that is not universally shared.
Different people find different things easy to understand. And if one
interpretation was universally shared nobody would feel the need to push
for it.
>The result of POSTPONE FOO is dependant on FOO's behaviour. There is nothing
>remarkable about the fact that it only takes the inclusion or exclusion of a
>single word to change this significantly and nothing special about IMMEDIATE
>in this respect.
>
>> Using
>>POSTPONE doesn't free the programmer from having to know the nature of
>>FOO.
>
>Programmers need to know the behaviour of FOO. They need to know its stack
>effects, its execution semantics, its compilation semantics and so on. If
>the behaviour of FOO is adequately documented they don't need to know the
>details of its implementation. The immediacy of FOO is an implementation
>detail.
>
>Of course, if the behaviour is not documented, as in your example,
>programmers do need to look at the implementation (the source code) and
>deduce the behaviour from that. To correctly deduce the behaviour from the
>implementation immediacy must be taken into account but it does not need to
>be documented as part of that behaviour. If programmers know a word's
>behaviour they don't need to know whether or not IMMEDIATE was used in its
>implementation.
>
So the burden that the progrmmer was freed from was only a shift from
knowing immediacy to knowing behavior. Maybe not any less burdensome
to the application programmer but to the system programmer it was
a clear gain alowing him the fexibilty in doing immediacy either way,
just adjust the behavior sequence as needed.
Ok. It's all clear now what going on.
I kind of got the idea from Jonah that the FOO's were being arranged
to give a common result but that wasn't jiving with saving the
programmer anything. I was looking at the wrong programmer.
Thank-you and also Jonah,
#Example: Behavior of Foo Adjusted to Compensate for Immediacy
--SCR 10--
TEST MARKER TEST
FLAG [IF] ' FALSE [ELSE] ' TRUE [THEN] IS FLAG
FLAG [IF] CR .( Immediate FOO: )
: FOO-EXE ." Hello World" ;
: FOO STATE @ IF POSTPONE FOO-EXE ELSE FOO-EXE THEN ;
IMMEDIATE
[ELSE] CR .( Normal FOO: )
: FOO ." Hello World" ;
[THEN]
CR .( Behavior of FOO: ) FOO \ FOO INTERPRETED
: BAR FOO ;
CR .( Behavior of COMPILED FOO: ) BAR \ FOO COMPILED
: A POSTPONE FOO ; IMMEDIATE
: X CR ." Behavior of POSTPONE FOO: " A ;
X \ FOO POSTPONED
----------
DEFER FLAG ' TRUE IS FLAG
MARKER TEST
10 LOAD
Immediate FOO:
Behavior of FOO: Hello World
Behavior of compiled FOO: Hello World
Behavior of postponed FOO: Hello World
Ok
10 LOAD
Normal FOO:
Behavior of FOO: Hello World
Behavior of compiled FOO: Hello World
Behavior of postponed FOO: Hello World
Ok
[snip]
> Now you developing away and you want to get your hands on the compile version
> (remember one of the advantages of forth is the interactive development, how
> do you do that). My thought was to make ' state smart, but then the user had
> to know to set state to true if he wanted to play with the compile version.
Have ' and ['] always return the interpreter-xt
Have C' and [C'] always return the compiler-xt
Jonah Thomas wrote:
Agree.
>
>
> >I have implemented the different list option, and these are the problems I saw
> >before abandoning that option
>
> >1) The system is bigger because you have two entries for most word.
>
> Yes, that's a disadvantage for very small systems. But if you want a tiny
> target system you can keep that information on the host where the size
> doesn't matter (hehe it's funny to talk that way in Forth) and otherwise it
> will only be a small increase -- one cell per word, if your average word has
> 4 cells of header and 16 cells of body that's less than a 5% increase. The
> less you factor the less difference one more cell per word will make.
>
> >2) Just which version do you have ' return.
>
> The interpret version, and POSTPONE can return the compile version.
Now you developing away and you want to get your hands on the compile version ( remember
one of the advantages of forth is the interactive development, how do you do that). My
thought was to make ' state smart, but then the user had to know to set state to true if
he wanted to play with the compile version. It was then I stopped with the thought, this
is nonsense. Mind you the proposed change, to make it only possible to add to the
dictionary when in compile mode ( that is when state is true) makes that a very valid
option.
But the standard was designed to allow duel list systems, not to make them mandatory.
>
>
> >3) You can still make up strange code that will fall over just as you can with a
> >flag based implementation.
>
> Yes. In either case the strange code will do the right thing, the only
> problem is that the right thing isn't intuitive and it can cause trouble
> for people who haven't thought it out.
Agree 100%.
> It's a style problem, a question
> of what you like.
Agree 100%
> If you understand all of Forth all the time then it
> won't matter except for the 2nd-rate people who have to maintain your
> code.
And this is where I have problems, a good program will program for the inexperienced and
the 2nd-rate, these are likely to be the ones maintaining your code. A smart person will
write code that can be passed on to others to maintain. A large program is an animal
that has to be fed. The more people that can feed it the better.
> If you're very good and programming for other people who're very
> good then you'll want to keep it simple and clear on all levels.
Well I need not of written the above paragraph. We agree.
> If
> you're very good and you're making systems for people who aren't very
> good it will make sense to make the easy stuff as easy as possible and
> you can figure they won't bother with the hard stuff. I think that last
> is the Open Firmware position.
>
> >I am also at a loss to see how a version of forth that retains immediacy
> >information through the ' is more standard than one that does not. As I see it both
> >systems will be standard, and as both will behave in different ways when you ' and
> >then try and extract the compilation or interpretation semantics the result is
> >ambiguous.
>
> That's what the committee decided. The wording of the document unfortunately
> suggested to some people that only one way should be allowed.
Yes perhaps from the words written in the standard, but a little knowledge on how FORTH
system have been traditionally implemented would of led you to the conclusion that the
words in the standard need improvement. After all it has always been clearly stated the
standard was not designed to force any particular implementation. It was designed to
find common ground across implementations. I think that's what annoys me most, the
suggestion that the committee has taken away a god given right when clearly it is not
something that can be given with a traditional forth system.
>
>
> >> It would be possible to revise the methods so that all the weird special
> >> cases smooth out and the whole thing is logically consistent.
>
> >I am yet to see an example that provides a simple solution to the perceived
> >problems. If you ' a word it losses it's immediacy. The standard says it provides
> >an execution token, it says no more. If you then take that execution token and use
> >it in situation where you need the compiling semantics or the execution semantics,
> >stiff. I can't find one place in the standard that says that should be possible.
>
> Yes. We could change the standard to clear all this up, but it would break
> everybody's code. It isn't worth it when what we get is to improve the style
> for things that we don't do very much and probably still wouldn't do very much.
>
Agree 100%
>
> >> People aren't too
> >> interested because most of them have tools that work as well as they need.
>
> >Perhaps people aren't interested because code written in such a way is impossible
> >to understand. And also perhaps those pushing for a particular interpretation of
> >the standard are pushing for an interpretation that is not universally shared.
>
> Different people find different things easy to understand. And if one
> interpretation was universally shared nobody would feel the need to push
> for it.
True.
>m...@intranetsys.com wrote:
>
>>I rewrote my Forth to have 3 flags with each word (interpreter, compiler,
>>immediate) and only one cfa in the header. The compiler only sees words which
>>have the compiler bit set, the interpreter only sees words which have the
>>interpreter bit set (state-smartness is kept where it belongs, e.g. in the
>>outer interpreter). No STATE.
>
>I guess this idea has been discussed in clf before. It sure looks
>familiar. And I (kinda) like it.
>
>A quick question: if you POSTPONE such a word, what do you postpone? The
>compiler version? the interpreter version? The decision which one to
>use? This last case is in fact a new shape of state-smartness, if you
>ask me.
From the rules posted previously, it seems like you should
copy the flags of whichever one you postponed to the new words, so
that if you have postponed a word that is compile only, the
interpreter can only find it when compiling.
m...@intranetsys.com wrote:
> In article <3725F4C3...@cvs.com.au>,
> Charles Esson <char...@cvs.com.au> wrote:
>
> [snip]
> > Now you developing away and you want to get your hands on the compile version
> > (remember one of the advantages of forth is the interactive development, how
> > do you do that). My thought was to make ' state smart, but then the user had
> > to know to set state to true if he wanted to play with the compile version.
>
> Have ' and ['] always return the interpreter-xt
> Have C' and [C'] always return the compiler-xt
Very logical but hardly standard.
>> Have ' and ['] always return the interpreter-xt
>> Have C' and [C'] always return the compiler-xt
>
>Very logical but hardly standard.
Personally I don't consider the Standard to be the final word on FORTH.
You would be killing evolution, and therefore, any improvements, that
way.
If the Standard doesn't work, change the Standard.
Bart.