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

POSTPONE - something I don't understand

303 views
Skip to first unread message

Zbiggy

unread,
May 3, 2012, 9:36:35 AM5/3/12
to
In "Starting Forth" (chapter 11) there is a statement:

#v+
Be sure to note the "intelligence" built into POSTPONE. POSTPONE parses
the next word in the input stream, decides if it is immediate or not, and
proceeds accordingly. If the word was not immediate, POSTPONE compiles the
address of the word into a compilee definition; think of it as deferred
compilation. If the word is immediate, POSTPONE compiles the address of
this word into the definition currently being defined; this is ordinary
compilation, but of an immediate word which otherwise would have been
executed.
#v-

Functionality of POSTPONE in case of "immediate words" is obvious: it makes
them "non-immediate for this time". But I don't understand the second case
mentioned - therefore I made an experiment using Gforth:

: test1 ." Hi " ;
: test2 test1 ." there " ;
: test3 postpone test2 ." - and again " ;
: test4 test3 ." (and this is test4 in action)" ;

Now let's try it:

#v+
test1 Hi ok
test2 Hi there ok
test3 - and again ok
test4 - and again (and this is test4 in action) ok
.s <0> ok
#v-

Neither test3 nor test4 executed test2 - then what about that "deferred
compilation"? Just for reason checked, that no address was left on stack.
--
Forth is a preserver of health (Hippocrates)

Mark Wills

unread,
May 3, 2012, 9:12:29 AM5/3/12
to
None of your examples were immediate. What were you expecting to see.

What happens with this:

: hello ." SURPRISE!" ; immediate

: test hello ;
: test2 postpone hello ;

Zbiggy

unread,
May 3, 2012, 10:17:15 AM5/3/12
to
In comp.lang.forth, Mark Wills wrote:

> None of your examples were immediate.

...because I was curious about that "second case": using POSTPONE with
non-immediate word!

Didn't you read the quoted paragraph?

Mark Wills

unread,
May 3, 2012, 9:25:05 AM5/3/12
to
On May 3, 3:17 pm, Zbiggy <zbigniew2011REM...@gmail.REMOVE.com> wrote:
My apologies.

Just tried it and I see what you mean. That puzzled me, too.

I don't really understand this sentence: "If the word was not
immediate, POSTPONE compiles the address of the word into a compilee
definition; think of it as deferred compilation."

?

Mark Wills

unread,
May 3, 2012, 9:44:36 AM5/3/12
to
On May 3, 2:36 pm, Zbiggy <zbigniew2011REM...@gmail.REMOVE.com> wrote:
See this thread, which goes into more detail.

http://groups.google.com/group/comp.lang.forth/browse_thread/thread/6386aceecbd0d2b0#

Zbiggy

unread,
May 3, 2012, 11:29:14 AM5/3/12
to
In comp.lang.forth, Mark Wills wrote:

#v+
POSTPONE itself is also compile-only. If name is compile-only, its
compilation action is added to the current definition. If name is
immediate, code equivalent to ' name COMPILE, will be executed at
compile-time.

If name is a normal word, will be code equivalent to ' name COMPILE,
will be executed at run-time. In any case, code compiled by POSTPONE
should itself never be invoked while interpreting. The only possible
exception [..]
#v-

My guess is, that " ' name COMPILE" mentioned above means "['] name" of
ANS Forths.

If I'm correct, we're talking about situation: "If name is compile-only, its
compilation action is added to the current definition". Then what actually
means: "its compilation action is added to the current definition"? What is
the consequence?

And what is "normal word", actually? Were my test(1|2|3|4) "normal"?

Zbiggy

unread,
May 3, 2012, 11:38:29 AM5/3/12
to
OK, there has been distinction made:
- immediate words
- normal words
- compile-only words

My test* words are "normal" then - and the doc explained: "If name is a
normal word, will be code equivalent to ' name COMPILE, will be executed
at run-time."

But it doesn't seem to work that way - and that's why I asked my question.

BruceMcF

unread,
May 3, 2012, 11:12:15 AM5/3/12
to
On May 3, 11:38 am, Zbiggy <zbigniew2011REM...@gmail.REMOVE.com>
wrote:
> OK, there has been distinction made:
> - immediate words
> - normal words
> - compile-only words

> My test* words are "normal" then - and the doc explained: "If name is a
> normal word, will be code equivalent to ' name COMPILE, will be executed
> at run-time."

> But it doesn't seem to work that way - and that's why I asked my question.

Yes it does.

: test1 ." Hi " ;
: test2 test1 ." there " ;
: test3 postpone test2 ." - and again " ;
: test4 test3 ." (and this is test4 in action)" ;

test3 EXECUTES when test4 EXECUTES. And when test3 EXECUTES, it
COMPILES test2, it does not EXECUTE test2. So you expect to either
get:

#v+
test1 Hi ok
test2 Hi there ok
test3 - and again ok
test4 - and again (and this is test4 in action) ok
.s <0> ok
#v-

... or to get:

test1 Hi ok
test2 Hi there ok
test3 Error: no definition being compiled
test4 Error: no definition being compiled

... an interesting thing to do would be:

: test5 ( addr1 addr2 -- )
." Compiled " - IF ." something." ELSE ." nothing." THEN ;

HERE CR test1 CR test2 CR test3 CR test4 CR HERE test5

Zbiggy

unread,
May 3, 2012, 1:01:45 PM5/3/12
to
In comp.lang.forth, BruceMcF wrote:

> test3 EXECUTES when test4 EXECUTES. And when test3 EXECUTES, it
> COMPILES test2, it does not EXECUTE test2.

1. But, actually, how the word, that has been compiled already, can be
compiled still again and again? Is it possible to compile "object code"?
How can such compilation be called "deferred", when test2 actually existed
already (and have been compiled) before "POSTPONE test2" has been executed
(while running test3)?

2. As I see, indeed HERE moves forward and forward each time, when I execute
test3. What can be an example of practical use of such (somewhat strange)
technique? Is this just a novelty with no practical meaning - just the
information "it'll work like this" (maybe with "beware" at the beginning) -
or I can do something useful such way?

Bernd Paysan

unread,
May 3, 2012, 12:31:02 PM5/3/12
to
Zbiggy wrote:

> In comp.lang.forth, Mark Wills wrote:
>
>> None of your examples were immediate.
>
> ...because I was curious about that "second case": using POSTPONE with
> non-immediate word!

Yes, but you should at least make the word that postpones a non-
immediate word immediate. Example:

: test1 ." Surprise!" ;
: test2 postpone test1 ; immediate
: test3 test2 ." Or not?" ;

test3 Surprise! Or not? ok

--
Bernd Paysan
"If you want it done right, you have to do it yourself"
http://bernd-paysan.de/

Anton Ertl

unread,
May 3, 2012, 12:19:19 PM5/3/12
to
Zbiggy <zbigniew2...@gmail.REMOVE.com> writes:
>In "Starting Forth" (chapter 11) there is a statement:
>
>#v+
> Be sure to note the "intelligence" built into POSTPONE. POSTPONE parses
> the next word in the input stream, decides if it is immediate or not, and
> proceeds accordingly. If the word was not immediate, POSTPONE compiles the
> address of the word into a compilee definition; think of it as deferred
> compilation. If the word is immediate, POSTPONE compiles the address of
> this word into the definition currently being defined; this is ordinary
> compilation, but of an immediate word which otherwise would have been
> executed.
>#v-

This is a confusing explanation. Forget it.

One uses POSTPONE in a word that compiles stuff into another word.
Example:

: =if
POSTPONE = POSTPONE if ; immediate

: foo
5 =if ." five" then ;

4 foo
5 foo
see foo

What happens here is that =IF is executed during the compilation of
FOO (because =IF is immediate), and the POSTPONEs in =IF compile = and
IF into FOO. So, as a result, FOO is equivalent to:

: foo
5 = if ." five" then ;

So, POSTPONE compiles the following word into the word being defined
during the execution of the code containing the POSTPONE. Whether the
following word is immediate or not is an implementation detail, and
you usually don't need to think about it.

- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.forth200x.org/forth200x.html
EuroForth 2011: http://www.euroforth.org/ef11/

BruceMcF

unread,
May 3, 2012, 1:10:28 PM5/3/12
to
On May 3, 1:01 pm, Zbiggy <zbigniew2011REM...@gmail.REMOVE.com> wrote:
> In comp.lang.forth, BruceMcF wrote:
> > test3 EXECUTES when test4 EXECUTES. And when test3 EXECUTES, it
> > COMPILES test2, it does not EXECUTE test2.
>
> 1. But, actually, how the word, that has been compiled already, can be
> compiled still again and again?
If test2 is not immediate, "POSTPONE test2" compiles something that
causes test2 to be compiled when test3 executes.

For instance,

( flag ) ANDIF ... ( -- flag | executed on TRUE ) THEN

: ANDIF POSTPONE DUP POSTPONE IF POSTPONE DROP ; IMMEDIATE

Every time that ANDIF is executed while compiling a definition, it
compiled a DUP into that definition, then does whatever IF does when
compiling, then compiles a DROP into that definition.

Which is how DUP gets "compiled again and again and again" ~ that's
the POINT of the word, to compile something everytime that ANDIF is
called.

> Is it possible to compile "object code"?
Its not the users concern how an implementation accomplishes it: it
will depend on how the implementation compiles things. A simple
indirect threaded compiler may do it one way, an optimizing compiler
quite a different way.

> How can such compilation be called "deferred",

Because, in the ANDIF example, rather than compiling DUP when ANDIF is
defined, DUP is compiled when ANDIF executes. How the implementation
causes that to happen isn't something that the source code author has
to worry about.

Elizabeth D. Rather

unread,
May 3, 2012, 2:00:00 PM5/3/12
to
On 5/3/12 7:01 AM, Zbiggy wrote:
> In comp.lang.forth, BruceMcF wrote:
>
>> test3 EXECUTES when test4 EXECUTES. And when test3 EXECUTES, it
>> COMPILES test2, it does not EXECUTE test2.
>
> 1. But, actually, how the word, that has been compiled already, can be
> compiled still again and again? Is it possible to compile "object code"?
> How can such compilation be called "deferred", when test2 actually existed
> already (and have been compiled) before "POSTPONE test2" has been executed
> (while running test3)?

test3 compiles a *reference* to test2, "in the current definition". In
your example, it is being used erroneously in interpretation state when
there is no "current definition"; some systems will give an error
message, while others will simply compile a useless reference to test2
which can never be executed.

A word with POSTPONE in it is only useful if it is IMMEDIATE and used
within a colon definition. It is useless otherwise.

> 2. As I see, indeed HERE moves forward and forward each time, when I execute
> test3. What can be an example of practical use of such (somewhat strange)
> technique? Is this just a novelty with no practical meaning - just the
> information "it'll work like this" (maybe with "beware" at the beginning) -
> or I can do something useful such way?

POSTPONE is intended for writing compiler directives, words that will be
used inside colon definitions to compile some sequence of words (whether
those words are immediate or not). In order to be useful, a compiler
directive must be IMMEDIATE. Standards do not require this explicitly;
they depend on programmers understanding the intent of POSTPONE, which I
think is described clearly enough.

Cheers,
Elizabeth

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

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

Zbiggy

unread,
May 3, 2012, 3:46:16 PM5/3/12
to
In comp.lang.forth, Anton Ertl wrote:

> So, POSTPONE compiles the following word into the word being defined
> during the execution of the code containing the POSTPONE. Whether the
> following word is immediate or not is an implementation detail, and
> you usually don't need to think about it.

Then what I've done, by using POSTPONE without any "correspoding" IMMEDIATE,
has no practical sense?

Zbiggy

unread,
May 3, 2012, 3:54:39 PM5/3/12
to
In comp.lang.forth, Elizabeth D. Rather wrote:

> test3 compiles a *reference* to test2, "in the current definition". In
> your example, it is being used erroneously in interpretation state when
> there is no "current definition"; some systems will give an error
> message, while others will simply compile a useless reference to test2
> which can never be executed.

I'm afraid, I don't understand: why in my examples there isn't any "current
definition"? How is "current definition" defined then?

> A word with POSTPONE in it is only useful if it is IMMEDIATE and used
> within a colon definition. It is useless otherwise.

Still I'm wondering, what did I do actually (even, if it has no practical
meaning), in my examples? HERE is moving during each invocation of test3
and test4. What goes on there?

Zbiggy

unread,
May 3, 2012, 4:02:06 PM5/3/12
to
In comp.lang.forth, BruceMcF wrote:

> If test2 is not immediate, "POSTPONE test2" compiles something that
> causes test2 to be compiled when test3 executes.

Do you mean: "test2" gets recompiled, and added - as new word - to the
beginning of "words-chain" (new test2 became the first in current search
order), or something else happened?

I'm curious about HERE incrementing.

Elizabeth D. Rather

unread,
May 3, 2012, 3:09:38 PM5/3/12
to
On 5/3/12 10:02 AM, Zbiggy wrote:
> In comp.lang.forth, BruceMcF wrote:
>
>> If test2 is not immediate, "POSTPONE test2" compiles something that
>> causes test2 to be compiled when test3 executes.
>
> Do you mean: "test2" gets recompiled, and added - as new word - to the
> beginning of "words-chain" (new test2 became the first in current search
> order), or something else happened?
>
> I'm curious about HERE incrementing.

Something else happened.

A *reference* to test2 was compiled at HERE (probably its xt, depending
on how your implementation works). This might be useful had test3 been
IMMEDIATE and executed during the compilation of a new word, but as you
did not mark it as IMMEDIATE and executed it in interpret state, its
action is quite useless.

Elizabeth D. Rather

unread,
May 3, 2012, 3:12:09 PM5/3/12
to
On 5/3/12 9:54 AM, Zbiggy wrote:
> In comp.lang.forth, Elizabeth D. Rather wrote:
>
>> test3 compiles a *reference* to test2, "in the current definition". In
>> your example, it is being used erroneously in interpretation state when
>> there is no "current definition"; some systems will give an error
>> message, while others will simply compile a useless reference to test2
>> which can never be executed.
>
> I'm afraid, I don't understand: why in my examples there isn't any "current
> definition"? How is "current definition" defined then?

A "current definition" is one begun with : <name> ... and not yet ended
with a ; .

>> A word with POSTPONE in it is only useful if it is IMMEDIATE and used
>> within a colon definition. It is useless otherwise.
>
> Still I'm wondering, what did I do actually (even, if it has no practical
> meaning), in my examples? HERE is moving during each invocation of test3
> and test4. What goes on there?

You are compiling a useless reference to test2 at HERE. It is useless
because it isn't in a definition and you can never execute it.

Elizabeth D. Rather

unread,
May 3, 2012, 3:12:33 PM5/3/12
to
On 5/3/12 9:46 AM, Zbiggy wrote:
> In comp.lang.forth, Anton Ertl wrote:
>
>> So, POSTPONE compiles the following word into the word being defined
>> during the execution of the code containing the POSTPONE. Whether the
>> following word is immediate or not is an implementation detail, and
>> you usually don't need to think about it.
>
> Then what I've done, by using POSTPONE without any "correspoding" IMMEDIATE,
> has no practical sense?

Right.

BruceMcF

unread,
May 3, 2012, 3:42:59 PM5/3/12
to
On May 3, 3:54 pm, Zbiggy <zbigniew2011REM...@gmail.REMOVE.com> wrote:
> In comp.lang.forth, Elizabeth D. Rather wrote:
>
> > test3 compiles a *reference* to test2, "in the current definition". In
> > your example, it is being used erroneously in interpretation state when
> > there is no "current definition"; some systems will give an error
> > message, while others will simply compile a useless reference to test2
> > which can never be executed.

> I'm afraid, I don't understand: why in my examples there isn't any "current
> definition"? How is "current definition" defined then?

Yes, there are "current definitions" all over the place. When you are
defining test1, its the current definition, until ";". Then when you
are defining test2, then when defining test3, then when defining
test4.

There isn't a "current definition" when you EXECUTE test3, because you
made a mistake and did not make it IMMEDIATE so that rather than test3
*executing* when test4 is compiled (so test4 would be "the current
definition"), test3 is compiled into test4, and test3 executes when
test4 executes.

So you are telling a word that *COMPILES* test2 to do so, at a time
when you don't have any definition in progress. Since that
implementation does not report an error, its is likely to be doing
whatever it would do if you erroneously entered:
' DUP COMPILE,

... in interpret state.

BruceMcF

unread,
May 3, 2012, 3:47:33 PM5/3/12
to
On May 3, 3:46 pm, Zbiggy <zbigniew2011REM...@gmail.REMOVE.com> wrote:

> Then what I've done, by using POSTPONE without any "correspoding" IMMEDIATE,
> has no practical sense?

The only time you would use POSTPONE without an IMMEDIATE on that word
would be if it was a factor you were going to use in some *other*
IMMEDIATE words.

But I'd avoid doing that, its something that if "source author me" did
today, it would be likely to trip up "maintainer me" sometime in the
future. I'd go ahead and make the factor an immediate compiler
operator, and then POSTPONE it when its used in the other compiler
operator.

Zbiggy

unread,
May 3, 2012, 5:34:00 PM5/3/12
to
In comp.lang.forth, BruceMcF wrote:

> So you are telling a word that *COMPILES* test2 to do so, at a time
> when you don't have any definition in progress.

Got it.

Thanks to all of you!

Rod Pemberton

unread,
May 4, 2012, 2:36:39 AM5/4/12
to
"Zbiggy" <zbigniew2...@gmail.REMOVE.com> wrote in message
news:slrnjq5628.8f8.z...@Tichy.myhome.org...
> In "Starting Forth" (chapter 11) there is a statement:
>
> #v+
> Be sure to note the "intelligence" built into POSTPONE. POSTPONE
> parses the next word in the input stream, decides if it is immediate or
> not, and proceeds accordingly. If the word was not immediate, POSTPONE
> compiles the address of the word into a compilee definition; think of it
> as deferred compilation. If the word is immediate, POSTPONE compiles the
> address of this word into the definition currently being defined; this
> is ordinary compilation, but of an immediate word which otherwise would
> have been executed.
> #v-
>
> Functionality of POSTPONE in case of "immediate words" is obvious: it
> makes them "non-immediate for this time". But I don't understand the
> second case mentioned - therefore I made an experiment using Gforth:
> [snip]

Are you familiar with COMPILE and [COMPILE] ?

COMPILE and [COMPILE] were defined for fig-Forth, Forth-79, Forth-83.
POSTPONE acts as COMPILE for non-immediate words and [COMPILE]
for immediate words.

Do you have the word SEE or the ability to dump a definition? I.e., can you
SEE or see what is compiled in each case?

If so, in one case, you should see the word compiled into a definition. In
the other case, you should see the word compiled into the definition
preceded by a COMPILE or POSTPONE typically. If it's just the word compiled
into a definition, it'll execute when that definition executes. If COMPILE
or POSTPONE is also present, then the word won't execute but will be
compiled into a new definition.

A basic definition for POSTPONE has been reposted here a few times recently.
They usually look like the following:

(all from old c.l.f. posts)

: POSTPONE BL WORD FIND DUP 0= IF <not found code> THEN 0<
IF COMPILE COMPILE THEN , ; IMMEDIATE

: POSTPONE ( "name" -- ) BL WORD FIND DUP 0= ABORT" -?" -1 =
IF COMPILE COMPILE THEN COMPILE, ; IMMEDIATE

: POSTPONE BL WORD FIND DUP 0= ABORT" ?" 0<
IF COMPILE COMPILE THEN , ; IMMEDIATE

Sometimes they are *far* more complicated. And, other times they have been
converted to use COMPILE, instead of , (comma) or even POSTPONE in terms of
POSTPONE POSTPONE i.e., the initial POSTPONE acts like COMPILE etc.

E.g., some typical posts:
http://groups.google.com/group/comp.lang.forth/msg/a58db7a9be07bd01
http://groups.google.com/group/comp.lang.forth/msg/50cb7b5ae28cf655

HTH,


Rod Pemberton


Hugh Aguilar

unread,
May 4, 2012, 3:13:57 AM5/4/12
to
On May 4, 12:36 am, "Rod Pemberton" <do_not_h...@notemailnot.cmm>
wrote:
> Are you familiar with COMPILE and [COMPILE] ?
>
> COMPILE and [COMPILE] were defined for fig-Forth, Forth-79, Forth-83.
> POSTPONE acts as COMPILE for non-immediate words and [COMPILE]
> for immediate words.
> ...
> A basic definition for POSTPONE has been reposted here a few times recently.
> They usually look like the following:
>
> (all from old c.l.f. posts)
>
> : POSTPONE  BL WORD FIND DUP 0= IF <not found code> THEN 0<
> IF COMPILE COMPILE  THEN , ; IMMEDIATE
>
> : POSTPONE ( "name" -- ) BL WORD FIND DUP 0= ABORT" -?" -1 =
> IF COMPILE COMPILE THEN COMPILE, ; IMMEDIATE
>
> : POSTPONE BL WORD FIND DUP 0= ABORT" ?" 0<
> IF COMPILE COMPILE THEN  ,  ; IMMEDIATE
>
> Sometimes they are *far* more complicated.  And, other times they have been
> converted to use COMPILE, instead of , (comma) or even POSTPONE in terms of
> POSTPONE POSTPONE i.e., the initial POSTPONE acts like COMPILE etc.

Don't use comma --- use COMPILE, --- you don't want to assume a
threaded system.

I never understood why ANS-Forth standardized POSTPONE and not COMPILE
considering that POSTPONE can be written in terms of COMPILE. It makes
sense to me to standardize the low-level words, rather than the high-
level words. This was the same point that I was making in that :NAME
should be standardized, as colon can easily be written in terms of it.
My Straight Forth will have COMPILE and [COMPILE] --- but will only
provide POSTPONE as a recommendation. I standardize the low-level
stuff that typically has to be written in assembly-language and
requires carnal knowledge, but I provide the high-level stuff as
recommendations (I provide source-code in standard Forth and recommend
that this be used rather than some similar definition).

ANS-Forth did standardize [COMPILE] --- but SwiftForth failed to
provide it --- so SwiftForth isn't really ANS-Forth compliant.

Anyway, if Zbiggy wants examples of POSTPONE, my novice package has
abundant examples. I use :NAME rather than CREATE DOES> so *all* of my
defining words use POSTPONE and EVALUATE. This is why I have all of
those xxx, words available.

Anton Ertl

unread,
May 4, 2012, 5:19:44 AM5/4/12
to
Zbiggy <zbigniew2...@gmail.REMOVE.com> writes:
>In comp.lang.forth, Anton Ertl wrote:
>
>> So, POSTPONE compiles the following word into the word being defined
>> during the execution of the code containing the POSTPONE. Whether the
>> following word is immediate or not is an implementation detail, and
>> you usually don't need to think about it.
>
>Then what I've done, by using POSTPONE without any "correspoding" IMMEDIATE,
>has no practical sense?

You mean, a word like

: comp-foo postpone foo ;

where COMP-FOO is not immediate. That's not usually done, because if
you want to use COMP-FOO directly to compile something into another
word, you have to switch to interpretation to get COMP-FOO to execute:

: bar [ comp-foo ] ;

You can use words like COMP-FOO for defining other compiling words,
though:

: flip comp-foo ; immediate
: flop flip ;

BruceMcF

unread,
May 4, 2012, 9:49:51 AM5/4/12
to
On May 4, 3:13 am, Hugh Aguilar <hughaguila...@yahoo.com> wrote:
> ANS-Forth did standardize [COMPILE] --- but SwiftForth failed to
> provide it --- so SwiftForth isn't really ANS-Forth compliant.

LOL

For casual browsers who might be misled by this piece of
misinformation, Forth94 standardizes what [COMPILE] is if it is
provided, but since its CORE EXT, a system is not required to provide
it in order to be ANS-Forth compliant.

0 new messages