[comp.lang.forth] interactive control structures

tsaari@tukki.jyu.fi (Antero Taivalsaari) (01/03/90)

In message <6581@tekgvs.LABS.TEK.COM> toma@tekgvs.LABS.TEK.COM (Tom Almy)
writes:

>One of the problems with Forth for naive users is that control structures
>can only be used in colon definitions. Since users of my CAD program often
>want iterative control structures but seldom need to write their own
>functions, this was quite a problem.  Some Forth variations (STOIC comes
>first to mind) compile everything typed in and don't have this problem. I
>solved the problem by having control structures force compilation if they
>are executed outside of a colon definition. The result greatly enhances the
>consistancy of Forth while causing no execution time penalty.

We were discussing this problem with Mike Perry at FORML'89, and I
agree with Tom Almy in that one of Forth's nasty features is the
inhomogeneousness of the control structures. There are plenty of
applications in which the interactive control structures would 
make things a lot easier for the user (think about a database query 
language in Forth, for example). 

In 1987 I built a Forth (for VAX/VMS) which now seems to be based 
on similar ideas that are used in that STOIC system you mention, 
although I'm completely unfamiliar with STOIC. 

My system, which I (at that time unaware of the other dozen systems 
with equivalent name) named Fifth (Fully Interactive ForTH),
has many similarities to the code presented by Mitch Bradley
in his reply message <8912301510.AA00667@jade.berkeley.edu>;
each time a control structure word is encountered, a special
counter variable is either incremented or decremented. The execution
(except for the immediate words) can not take place, unless the 
counter variable is zero. In case of 'abort', the counter variable 
is set back to zero.

The major difference from traditional Forth is, however, that my 
Fifth system never executes a word immediately (unless it is
an immediate word), but it always keeps on compiling, until a 
special compilation ending word ('|' which I, as in Unix, call 
'pipe') is encountered. Normally pressing the return key has the 
effect of the pipe word, too. The system has two compilation areas, 
one for immediate compilation and one for 'traditional' compilation. 
The words 'allot' and ',' are state-smart, so that the compiled 
code goes into either of these areas, according to the variable 
'state'. When the pipe word is encountered, 'next' (return from 
subroutine) is compiled into the end of the immediate compilation 
area, and then the code in that area is executed. After execution, 
or in case of 'abort', the immediate compilation area pointers 
will be reset.

The Fifth system works just fine, and it has the advantage of all
the immediate words (not just control structures) being able to
work equally both in the compile and execution state. Since two
separate compilation areas are provided, there are no problems 
in error situations or in switching between execution and compilation. 

...Yes, I know it isn't standard Forth anymore, but it has encouraged 
me to believe that there is no reason why I shouldn't be able to use
DO-LOOPs and IFs interactively in normal Forth systems, too. I 
certainly hope that Mitch Bradley's proposals to ANSI Forth team 
about including interactive control structure facilities into Forth 
and removing the "compilation only" restriction will be seriously 
considered.

Finally, as I am quite unaware of other approaches in making
Forth more interactive, I would appreciate if someone mailed 
comp.lang.forth a reference list of articles in which this 
subject is discussed.
 

Antero Taivalsaari
University of Jyvaskyla
FINLAND
tsaari@jyu.fi

toma@tekgvs.LABS.TEK.COM (Tom Almy) (01/04/90)

In article <2620@tukki.jyu.fi> tsaari@tukki.jyu.fi (Antero Taivalsaari) writes:
>In 1987 I built a Forth (for VAX/VMS) which now seems to be based 
>on similar ideas that are used in that STOIC system you mention, 
>although I'm completely unfamiliar with STOIC. 

>My system, which I (at that time unaware of the other dozen systems 
>with equivalent name) named Fifth (Fully Interactive ForTH),
>has many similarities to the code presented by Mitch Bradley
[Description of operation deleted]

Your system sounds quite like STOIC, but STOIC only compiled into
one location (The "compiler buffer").  When carriage return was hit
and the nesting level was zero, then the code in the compiler buffer
would be executed and then tossed. The current nesting level was part
of the prompt.

The Colon word in STOIC copies the following contents of the compiler
buffer, up to the "semicolon" marker into the dictionary. Clever!

One additional user-friendly feature was that the tokenizer (equivalent
to Forth WORD) tokenized string literals. Thus strings would be pushed
on the stack and used just like numeric literals. STOIC was completely
postfix -- words taking string arguments got them off of the stack
instead of reading from the input stream (another confusing factor to
the novice).

>...Yes, I know it isn't standard Forth anymore, but it has encouraged 
>me to believe that there is no reason why I shouldn't be able to use
>DO-LOOPs and IFs interactively in normal Forth systems, too.

But it doesn't break any existing Forth code. It is a perfect extension
to the language.

One last novice-confusing factor. The use of the decimal point to indicate
a double precision integer *AND* the fact it doesn't matter where the decimal
point is! My PRIDE CAD system redefines the numeric input routines so that
the suffix "D" is used to indicate double integers, and a decimal point 
indicates a floating point literal, like people are used to.

Tom Almy
toma@tekgvs.labs.tek.com
Standard Disclaimers Apply

wmb@SUN.COM (01/05/90)

Antero Taivalsaari writes:
> my Fifth system never executes a word immediately (unless it is
> an immediate word), but it always keeps on compiling, until a
> special compilation ending word ... is encountered. Normally pressing
> the return key has the effect of the pipe word, too.

I experimented with this kind of a scheme several years ago, and it
had some nice properties and also some interesting side effects.

For instance, you end up needing to make HEX and DECIMAL immediate,
otherwise you couldn't write, for instance:

    HEX 1234

Instead you would have to use:

    HEX
    1234

Or:

    HEX | 1234


Of course, Forth really ought to have some way of explicitly declaring
the radix of an individual number.  At the last ANSI meeting, I proposed
that number syntax should allow the prefixes H# , D# , O# , and B# for
entering explicit hex, decimal, octal, and binary numbers, without
permanently altering the value of BASE .  Thus you could write
H#12a4 or D#5478 and get what you wanted regardless of the current BASE .
There was general agreement that this facility was worthwhile, but
there was some objection to making this a syntactic.  The consensus
was that I should amend the proposal to instead define Forth words
H# and D# , which would be followed by a space and the number.
We'll see how this amended proposal fares.

But, back to the discussion of the temporal aspects of interpretation
and compilation:  I see three possibilites:

1) The traditional Forth model:  A line of input is collected, then
   the words on that line are executed one-at-a-time

2) The "compile-a-line-model": A line of input is collected, compiled
   as a unit, and then executed.  (As in Antero Taivalsaari's system)

3) The LaForth model: The system reads a word from the input device,
   executes it, reads the next word, executes it, etc.

   (LaForth was a Forth variant written by LaFarr Stewart at about the
   same time as FIG Forth.  It has a number of interesting features.)

Analysis:

(3) appeals to me from an intellectual standpoint; the basic execution
unit of Forth is a word, so why should the unit of input be a line?

LaForth handled typos very nicely; since the system "wakes up" on every
space, if you mistype a word, the system doesn't abort; it just erases
the word (or part of it) and beeps at you; then you type it right.

On the other hand, this scheme takes a bit of getting used to;
"line-at-a-time" typing habits are pretty ingrained.  I discovered this
when I wrote the schematic editor macro language that I alluded to in
a previous message.  It used the LaForth "word-at-a-time" model, and
using it comfortably required unlearning some old habits.  It just felt
wierd to have things happen as soon as I typed a space.  The feedback
just seems a little too frequent.

bouma@cs.purdue.EDU (William J. Bouma) (01/06/90)

In article <9001050440.AA25729@jade.berkeley.edu> Forth Interest Group International List <FIGI-L%SCFVM.bitnet@jade.berkeley.edu> writes:
>But, back to the discussion of the temporal aspects of interpretation
>and compilation:  I see three possibilites:
>
>1) The traditional Forth model:  A line of input is collected, then
>   the words on that line are executed one-at-a-time
>
>2) The "compile-a-line-model": A line of input is collected, compiled
>   as a unit, and then executed.  (As in Antero Taivalsaari's system)
>
>3) The LaForth model: The system reads a word from the input device,
>   executes it, reads the next word, executes it, etc.
>
>Analysis:
>
>(3) appeals to me from an intellectual standpoint; the basic execution
>unit of Forth is a word, so why should the unit of input be a line?
>

   The reason I like (1) is because I like command line history/editing.
   Although the unit of execution is one word, often a unit of meaning is
   a group of words. I prefer to type in a line of junk I want done, decide
   that that is indeed what I want, then signal the computer to do that by
   hitting <return>.

   It appeals to me to have this happen:

ok, 1 . 2 . 3 .<cr>
1 2 3
ok,

   Rather than this:

ok, 1 . 1 2 . 2 3 .<cr>
3
ok,


   The difference between (1) and (2) is very slight. I don't see a big
   deal here. If you want to compile the input when it contains a control
   structure, go ahead. All it does is saves the user a few keystrokes of
   defining a word and executing it.
-- 
Bill <bouma@cs.purdue.edu>  ||  ...!purdue!bouma 

DAVID@PENNDRLS.BITNET (01/07/90)

Bill writes that he prefers traditional forth input handling or
compile-by-line input handling because he likes to type in a line, think
about it, and *then* tell the computer to go ahead and do it.
With this I heartily agree.  In fact, I sometimes have the same
problem with non-command oriented systems.  (Not well designed ones,
but, as we all know, 90% of everything is crap.)

I had been thinking about the compile-a-line approach before the
topic came up here, and it seems to me that the second biggest
advantage of the approach is that it eliminates the need for
state-smart words.  In fact, from a system design standpoint that
may be the bigger of the advantages (interactive control structures
being the other under discussion).

It seems to me you need two compile buffers in addition to the end of
the dictionary you are compiling into: one for the line you are
compiling, and a temp buffer for doing things like

  : Offset ( n -- a ) [ 4 CellSize * ] Literal * Buffer + ;

How does (e.g.) Stoic handle this?

-- R. David Murray    (DAVID@PENNDRLS.BITNET, DAVID@PENNDRLS.UPENN.EDU)

stever@tree.uucp (Steve Rudek) (01/07/90)

In article <9167@medusa.cs.purdue.edu>, bouma@cs.purdue.EDU (William J. Bouma) writes:
> In article <9001050440.AA25729@jade.berkeley.edu> Forth Interest Group International List <FIGI-L%SCFVM.bitnet@jade.berkeley.edu> writes:
> >But, back to the discussion of the temporal aspects of interpretation
> >and compilation:  I see three possibilites:
> >
> >1) The traditional Forth model:  A line of input is collected, then
> >   the words on that line are executed one-at-a-time
> >
> >2) The "compile-a-line-model": A line of input is collected, compiled
> >   as a unit, and then executed.  (As in Antero Taivalsaari's system)
> >
> >3) The LaForth model: The system reads a word from the input device,
> >   executes it, reads the next word, executes it, etc.
> >
> >(3) appeals to me from an intellectual standpoint; the basic execution
> >
>    The reason I like (1) is because I like command line history/editing.

I've been thinking for a while that it would be nice to have the option
of single character input to the interpreter so you could write single character
"words".  For instance, in F83 I keep typing "N L<return>" or "A L<return>"
(display the next or the shadow screen).  It would be neat to be able to
switch the interpreter into single character interpretation mode and
have words "N" and "A" which took these actions.  Even better would
be a "word completion" routine which monitored the input,
one character at a time, and when it had sufficient characters to uniquely
identify the word, typed the rest of the word to the screen
and then passed the word to the interpreter for execution.  That's how
this system's bbs front end works and it is nice -- this scheme would allow you
to use the convenience of single character input yet have more than 256
such "words".
 
Why not let everyone have their cake and eat it too ... and let them
choose WHEN they want to eat!  Define a variable along the lines of
"BASE" which would control the preferred input mode, 1 through 4.  (It
would be frosting if the <ESC> key could be "hot wired"
to pop you into single character mode--possibly switching to a vocabulary
of single character words at the same time).

One of the things which has always dumbfounded me about Forth and Forth
programmers is how come there can be all these HOT programmers, working
with source code to this HOT interpreter...and the interpreter interface 
remains so dismal and archaic.  Yeah, I've seen F-PC now.  It's a step in the
right direction but it's not the end-all...and WHY did it have to wait 
until AFTER turbo pascal, quick basic, etc?.  I've heard the standard
disclaimer about how the vendors just don't want to preempt the Forth
programmer's God-given right to 'roll his own' interface.  But I don't
buy that.  What's the explanation for why the Forth interpreter interface
is commonly sadly anachronistic?  Surely it isn't as simple as a collective
lack of imagination?  I'm not talking about just "bells and whistles",
either.  Things like history stacks, full screen editors, interpret mode
control structures, single character input "words" (as I'm propounding),
hypertext facilities, visual run-time displays of the stacks in a separate
window, tree editors, etc. are all relatively obvious ideas which would
produce definite and substantial paybacks in programmer productivity.  These
ideas could have been and SHOULD have been appearing in Forth implementations
way back at the beginning of the 80's.  But it's the 90's...and these types of
improvements (or comparable improvements, in the case of non-interpreted
languages) are old hat in other languages and "cutting edge" in Forth
implementations??
 
I'm admittedly not half the programmer many of you are.  But WAY back
in 1982 I got frustrated with the fact that Microsoft BASIC on my Osborne
01 CP/M machine didn't have a full screen editor.  So I did the sensible
thing.  I disassembled the interpreter, discovered where its tokenizing,
DOS, and main interpreter code were located.  Then I PATCHED the
interpreter so it would jump to an editor (which I'd written and previously
loaded into high memory) anytime I pressed <ESC>.  The editor code would
hotpatch BASIC to snag use of its tokenizing and detokenizing routines.  It
would let me edit my program and, when I pressed <ESC> again, it would
retokenize, remove the hotpatches in BASIC and jump back down to the
interpreter.  It worked quite well, thank you.  And I didn't even have
source to Microsoft BASIC (which was a tangled mess, by the way).

What's YOUR excuse?  Maybe Forth should resolve to LEAD the way in this
new decade??

P.S. I've resolved to be "a kinder, gentler" critic in this new year. :-)
--
-- 
{pacbell!sactoh0! OR ucdavis!csusac!}tree!stever

wmb@SUN.COM (Mitch Bradley) (01/09/90)

> ... discussion about various fancy input mechanisms ...
> ... These ideas could have been and SHOULD have been appearing in Forth
> implementations ...
>
> What's YOUR excuse?

No excuse needed.  Such things HAVE appeared and do appear in Forth
implementations.

It seems to me that you are basing much of your opinion on a very small
sample of Forth implementations, and almost zero exposure to the Forth
literature.  I think it would be a good idea to read some back issues
of JFAR, Forth Dimensions, FORML conference proceedings, and Rochester
Conference Proceedings.  No sense in reinventing the wheel.

Mitch