forthwith

Friday, July 07, 2017

CASE-Based Control Structures

Eaker's CASE structure is at heart a set of  IF ... ELSE clauses that are resolved at a common point. That's a generally useful thing to have, but it is too specialised. ENDCASE not only does the resolving, but drops an item from the stack, and OF may not (in Standard code) be paired with ELSE/THEN nor IF with ENDOF/ENDCASE. Some FORTHS have ?OF to perform the function of IF in that context.

But it's fairly easy to remove those restrictions for a particular Forth.

The simplest example assumes that the control stack is the data stack and that THEN does some stack-checking to ensure it is paired correctly:

 0 CONSTANT CASE IMMEDIATE 
: OF   POSTPONE OVER POSTPONE = POSTPONE IF POSTPONE DROP ;        IMMEDIATE
    : ENDOF  POSTPONE ELSE ; IMMEDIATE

    : END  BEGIN ?DUP WHILE POSTPONE THEN REPEAT DROP ; IMMEDIATE 
          
    : ENDCASE   POSTPONE DROP POSTPONE END ; IMMEDIATE



That is perfectly Standard, but also allows you to avoid writing multiple adjacent THENs


        Nested conditions:    CASE ... IF   ... IF  ... IF  do-this END
     
        and alternatives:       CASE   ... IF do-this ELSE
                         ... IF do-that ELSE
                                do-other END
        are much clearer.

It also allows this technique for combining multiple tests in one flag while ensuring that none are executed needlessly:

     CASE 
         ... TRUE OF
         ... FALSE OF
         ... END IF

TRUE OF  is an and-if' -  if the test is false the rest of the block need not be tested, 
                     and a FALSE flag is returned

FALSE OF  is an or-if' -  if the test is true the rest of the block need not be tested, 
                     and a TRUE flag is returned.

That's not a bad result for the addition of one new word. 

Next time: Integrating Iteration.

                                     

         

Thursday, December 20, 2007

Low-Cost Multi-point Interactive Whiteboards Using the Wiimote

This is a really neat bit of inverted thinking.

A Nintendo Wii Remote can be used with an ordinary PC. It tracks its position in space relative to fixed infra-red light sources. It can work just as well if the sensor is static and the light sources move. Johnny Chung Lee demonstrates how a fixed Wiimote can track up to four points simultaneously, adding multitouch or head-tracking capabilities cheaply to any PC display.

Wednesday, December 19, 2007

Six Days of Creation

Some rough approximations:

Six days from the Big Bang, each hour lasting approx 100 million years.

Earth appears in the last hour of the fourth day.

Oceans form by the start of the fifth day.
The ancestor of all living cells appears around the middle of the day, and by the start of the sixth day its descendants have filled the atmosphere with oxygen, and chloroplasts develop.

In the middle of the sixth day the first dry land appears. Two or three hours later, fungi appear, and plants an hour or so later.
With five or six hours to go to the end of the day, fish and insects.
Three hours to go - amphibians.
Three minutes later seed-bearing plants colonise the land and reptiles follow them 12 minutes later.
Two and a half hours to go - the Permian extinction, after which the dinosaurs develop.
By the start of the last hour there are flowering plants, and the first birds and mammals.
Forty minutes to go - the first grass appears, and shortly afterwards the big dinosaurs are gone.

Four minutes, last common ancestor of humans and chimps.
100 seconds, genus Homo.
One minute, controlled use of fire.
8 seconds, Homo sapiens

Recorded history, 1/5 of a second.

Friday, November 18, 2005

The Future of FIG UK

The FIG UK web site and the accompanying magazine Forthwrite has been dormant for some time now for lack of volunteers.

I've established a forum and it is possible, given enough interest, that Forthwrite will return in a new form. That interests you, and there is some way in which you can help, please get in touch.
.
2017:  The forum is now defunct. The website address above is still valid  (for now) but please link instead to the mirror at the Forth Foundation Library

Wednesday, September 21, 2005

Mixing and Matching Control Structures

Forth uses IMMEDIATE words to build control structures at compile time. The various opening and closing words communicate with each other by passing items on a control stack to ensure proper nesting.

What goes on the control stack



  • BEGIN leaves dest to be consumed by UNTIL or AGAIN

  • AHEAD and IF leave orig to be consumed by THEN

  • (AHEAD compiles an unconditional forward jump)

  • DO and ?DO leave do-sys to be consumed by LOOP or +LOOP

  • CASE leaves case-sys to be consumed by ENDCASE

  • OF leaves of-sys to be consumed by ENDOF

Sometimes, however, strict nesting is not what is needed, and the Standard provides the words CS-PICK and CS-ROLL to change the
order of items on the stack. (0 CS-ROLL is a no-op, 1 CS-ROLL is a swap; 0 CS-PICK is a dup, 1 CS-PICK is an over, and so on...). The details of the control stack and the size and format of items is implementation-dependant, but by far the most common choice is to use the data stack, with either one or two items for each item.

In the examples below I shall use CS-PICK and CS-ROLL explicitly, but they are intended to be used for the definition of new control structure words, as in the examples of ELSE and WHILE below:

: ELSE \ orig1 -- orig2
POSTPONE AHEAD \ orig1 orig2
1 CS-ROLL POSTPONE THEN ; \ consumes orig1
IMMEDIATE

: WHILE \ dest -- orig dest
POSTPONE IF 1 CS-ROLL ; IMMEDIATE

Using WHILE
BEGIN ... WHILE is normally resolved by REPEAT, which is another way of saying AGAIN THEN - but could also be closed with

... UNTIL do this on normal exit only THEN ...

and you can use multiple WHILEs within the loop, each resolved by its own THEN outside

BEGIN ... WHILE ... WHILE ... UNTIL ... THEN ... THEN

But you’ll notice that WHILE does not modify the dest on the top of the control stack. In fact, unless your Forth is overly pedantic, any other item will do as well. For example, in:

IF ... WHILE ... THEN ... THEN

(I don't recommend this - each time I look at it I have to work out again what it actually does).

Generally it is best to strictly nest both forward branches and loops, but it is sometimes useful to branch out of a loop (as in the examples above) or into the middle of a loop:

IF BEGIN maybe ignore first time [ 1 CS-ROLL ] THEN the rest of the loop UNTIL

WHILE may equally well be used to exit a DO ... LOOP, but here you need to use UNLOOP to get rid of the redundant loop index.

DO ... WHILE ... LOOP normal exit ELSE early exit UNLOOP THEN

is very messy, even more so with multiple WHILEs. It would be better to place the ELSE clauses within the loop, changing the sense of the test:

DO ... IF early exit UNLOOP ELSE [ 1 CS-ROLL ] ... LOOP normal exit THEN ...

Of course. if the definition ends at THEN, you can simply do an early return

DO ... IF early exit UNLOOP EXIT THEN ... LOOP normal exit

Or if you just want to exit the loop and perform whatever code follows in all cases:

DO ... IF early exit LEAVE THEN ... LOOP all exits

Branching to a Common Start


This can be done using CS-PICK. The simplest example mimics the Java’s continue keyword:

BEGIN ... WHILE ... [ 0 CS-PICK ] REPEAT ... UNTIL

DO ... WHILE ...[ 0 CS-PICK ] REPEAT ... LOOP

may possibly compile too, but is not guaranteed to work, since do-sys may not be identical to dest. In this case, since the loop counter is decremented by LOOP rather than DO, each time the program hits REPEAT it effectively repeats the same iteration.

The same trick can be used within a CASE statement. Suppose you want the same action for a range of values, with one exception:

CASE
exception OF do-exception ENDOF
DUP range WITHIN IF DROP do-range ELSE [ 1 CS-ROLL ]
...
ENDCASE
THEN

On some (perhaps most) Forths this is unnecessary, since OF is the strict equivalent of OVER IF DROP and so can be paired with THEN, or IF paired with ENDOF.

Of course, if you find this uselful, it's better to define and document your own control words:

   : DONE  \ branch out of the current loop (resolved by implicit or explicit THEN

        POSTPONE ELSE 1 CS-ROLL ;  IMMEDIATE

   :  REPRISE  \  return control to nearest BEGIN
 
        0 CS-PICK  POSTPONE REPEAT ;  IMMEDIATE

Thursday, September 15, 2005

All the Standard Words

Somehow this puts me in mind of C K Ogden and his 850 words of Basic English...

Neal Bridges has produced a four-sheet reference for Standard Forth -- all 371 words with their respective Standard stack diagrams. It's in PDF format, and if printed '4-up' makes a pretty handy single-sheet reference (if a bit hard on the eyes).

I haven't seen this anywhere else in so compact a form. It's very useful for reminding yourself what words are in the Standard and how they are spelt.

Friday, August 06, 2004

Win32Forth discussion group

Win32Forth is probably the oldest-established Windows-based Forth for hobbyists. It has recently received a lot of development. A discussion group has been set up at http://groups.yahoo.com/group/win32forth/ and now has over 170 subscribers.

Forth Wikis

The original and biggest Wiki http://c2.com deals with "Extreme Programming" and Software Patterns. The Extreme Programming methodology has a lot in common with good Forth practice, so it is no surprise to find http://c2.com/cgi/wiki?ForthLanguage Any Forth content added to this wiki should be relevant to the main themes in order to aviod forming a "Walled Garden" - a sub-wiki with no links out to the main body.

What is different about Forth?

I like this summation in a comp.lang.forth Usenet post by Joe Knapka, and particularly the reply from Jeff Fox, one of great names of Forth


Joe Knapka's post
Date: Wed, 07 Apr 2004

Subject: Re: ANN : Forth Versus C - some Infrequently Asked Questions


Agreed. I'm trying to like Forth, but a lot of the Forth evangelism
really reads as if it's directed toward cult members: "People who use
other languages often think X, Y, or Z. Those people are misguided;
you can tell because it takes them three times as long to write their
code. They don't care about making high-quality products; only *we*
care about making high-quality products. Drink the Kool-Aid now..."
It's really quite a turn-off. I've produced what I consider to be
high-quality products in perhaps a dozen different languages; I don't
really like being told that's impossible.

It usually works better to simply say, "Welcome to Language X, which
is based on the W principle: everything is a Widget. This Widget-
centric approach addresses the following specific perceived
shortcomings of the object-oriented, functional, and thingamajig-based
paradigms: .... Language X also provides the following specific
unique features that are not available in any other language: ..."
People who are intrigued by the introduction will then dive in
and write some code, and decide for themselves whether they like
it.

Let's see.

"Welcome to Forth, a mid-level, interactive, stack-based
language. Forth's interactive and stack-based nature addresses the
following specific perceived shortcomings of other mainstream
languages:

  • Unlike many popular languages, Forth is fully-interactive; no
    edit/compile/test cycle is required. Instead, you can edit and run
    code directly from the Forth command line. This means that
    exploratory programming is very easy in Forth. (However, the fact
    that control structures usually can't be used outside procedure
    definitions somewhat limits one's ability to run ad-hoc code at
    the command prompt. [Does any Forth permit loops etc in
    interpreted code?])
  • Unlike many popular scripting languages, Forth can compile
    directly to native code, which means you can have native-code
    performance in a fully-interactive environment.
  • Unlike many popular languages, Forth does not impose any
    particular structure to your code (no "everything is an X"); you
    are free to use procedural, structured, object-oriented, and
    limited functional techniques as circumstances warrant. (However,
    you may need to build your own toolbox.)
  • Unlike virtually all popular languages, a complete Forth
    development environment can run in a surprisingly small memory
    footprint (a few 10's of K for a really large, highly-functional
    implementation), and without an underlying general-purpose
    operating system. Furthermore, the Forth compiler typically
    produces very compact object code. This makes Forth ideal for
    exploratory programming in embedded and resource-constrained
    environments.
  • Unlike most popular languages, Forth makes it possible and natural
    to directly manipulate the hardware on which the Forth system
    runs. Such direct manipulation can be done from the Forth command
    line -- another advantage when doing exploratory development in
    embedded environments.
  • Unlike most popular languages, Forth is extensible - it allows the
    programmer to add to the language facilities (such as control
    structures) that are completely indistinguishable from the
    built-in facilities. Forth takes you beyond the ability to design
    libraries, and makes you a partner in the design of the language
    itself; building a high-level language atop the Forth environment
    is therefore fairly simple. Further, any such high-level language
    can be made immediately available to the user as well as the
    programmer. (Note: do not use this power in the service of evil!)
  • Unlike nearly all popular languages, the internal structure of a
    Forth development environment is extremely simple and easy to
    understand, even for folks with little programming experience.
    While to an experienced C programmer, for example, Forth may seem
    to be full of strange inconsistencies and edge cases, a full
    understanding of the nature of Forth makes it clear that all of
    its features are natural consequences of its simple and elegant
    implementation; and such a full understanding is easy to achieve.
Jeff's reply:
Date: 11 Apr 2004

I would have probably said something similar to describe Forth
in my first twenty years of working with the language. I have
come to think of it as the most common misconception about Forth
among Forth programmers.

Forth is based on the word. Words are like subroutines but
shorter. To facilitate Forth style factoring of code into
words a parameter passing stack is used.

Words also are names. To allow to programmer to focus on the
things that are important enough to be given names there is a
parameter stack where items do not have names.

These aspects of Forth address shortcomings of languages with
rigid syntax and unchangable keywords. The use of short word
definitions increased code re-use and eliminates much of the
work required in other languages to duplicate sections of
their own code. Short word definitions are easier to write,
debug, and maintain.

Forth only requires single pass compilation which in combination
with the use of highly factored code facilitates very fast
compilation times and supports a very fast interactive edit-
compile-test cycle. Forth uses a dictionary to contain and
access words by their name. The dictionary is similar to
the ubiquitous file directories that most programmers use
except that they are early bound and under explicit control
of the programmer while file directories add runtime overhead
by being late bound and remove control from the programmer to
give it to a file system.

In short, Forth uses two stacks as a mechanism to support
a language based on space delimited words. I think it helps
to realize that Forth is word based, not stack based.

If a programmer focuses on stacks as the basis of the language
it is likely that a programmer will not be as focused on factoring
into words, will write stack juggling routines, or may even start
giving stack items names.

I know for the first twenty years that I did Forth while thinking
of it as a stack based language I wrote more code than I needed to
write and made it less readable, less maintainable, and generally
speaking experienced less productivity than when I approached
Forth as a word based language. Of course I am sure that there
were other factors as well that contributed to my learning to
use the language more effectively.

In the light of Jeff's reminder that "Forth is based on the word," it might be a good idea to have a look at one of the classic references for writing clear English: William Strunk's Elements of Style

Compare:
The use of short word definitions increased code re-use and eliminates much of the work required in other languages to duplicate sections of their own code. Short word definitions are easier to write, debug, and maintain.

to:

Vigorous writing is concise. A sentence should contain no unnecessary words, a paragraph no unnecessary sentences, for the same reason that a drawing should have no unnecessary lines and a machine no unnecessary parts. This requires not that the writer make all his sentences short, or that he avoid all detail and treat his subjects only in outline, but that every word tell.