STRUCTURED PROGRAMMING (16K ZX-81)
By Andy Wilson
from Popular Computing Weekly, 1-7 December 1983, pages 19-21

Andy Wilson introduces structured programming on the ZX81 in the first of a
three-part series.

The English language contains many words which, if they were to appear upon
the pages of this publication, would send
many a reader into spasms of angry letter writing. English of course is not
unique in this respect. French. German,
Chinese and Serbo-Croatian, they all have their 'taboo' words and phrases.

Most programming languages, however, appear to ignore this unwritten rule.
If a word is there, it is there to be used.

Algol 60 (the original version of the language) is one exception. Although
the Goto statement is supported, its use is
frowned upon by most programmers. It goes against all the principles of that
great cult, Structured Programming.

The home computing press is very fond of the phrase, but hardly ever bothers
to explain exactly what is Structured
Programming. I aim to give the reader a rough idea of the underlying
concepts and, by introducing a few new Basic
commands, show how ZX81 programs can be made much more readable. Although
the programs and machine code routines will
be specific to the humble Sinclair machine, many of the ideas will be useful
to owners of other computers.

As you probably realise, readability is the most important idea behind
Structured Programming. One of the biggest
problems facing commercial programmers is deciphering other people's
programs. In the commercial world, more time is
spent amending and debugging old programs than writing new ones, so
readability is very important.

A well structured program should reflect the thinking behind it. It should,
where possible, be divided into natural
"blocks" where each block contains the code for one process.

The problem with the Goto is that, when we make a decision in the real
world, we usually decide on a complete course of
action. For example, suppose you a sitting in your favourile armchair
reading the latest PCW when you hear a bell.
There are two possibilities, it could be the doorbell or the telephone. What
should you do?

In Basic the problem could be written as follows:

   10 IF DOORBELL THEN GOTO 100
   20 Code for answering phone

   90 GOTO 200
  100 Code for answering door

  200 Rest of program

A slight improvement would be to use Gosubs. This is like having a notebook
containing instructions on how to answer
the door or telephone and, when you have decided which bell is ringing,
choosing the appropriate page number to find
out what to do next. Surely, it would be better if we could write:

   10 IF DOORBELL THEN ANSWERDOOR
   20 IF PHONEBELL THEN ANSWERPHONE

or even better

   10 IF DOORBELL THEN ANSWERDOOR ELSE ANSWERPHONE

This can be done in many languages, including Algol, Pascal and BBC Basic.
It is done using a structute called the
Procedure.

A Procedure is a bit like a Gosub routine, but is called by a name rathar
than a line number. In Algol the procedure
for answering the phone would be defined as follows:

    PROCEDURE ANSWERPHONE;
            BEGIN
   Code for answering phone
              :
             END;

and thereafter any reference to Answerphone would execute the procedure.
Similarly, in BBC Basic we could write:

  100 DEFPROC ANSWERPHONE
                    :
  Code for answering phone
                    :
  200 ENDPROC

and the procedure would be called by the statement Proc Answerphone.

To see the effect this has on readability, find a listing of a program
written for the BBC which avoids the use of
Gotos and Gosubs, and compare it with a program written for another,
unfamiliar micro.

There is another occasion on which the Goto is often used. Suppose you are
still sitting in your chair reading PCW, but
this time you are expecting a telephone call. You want to carry on reading
until the telephone rings. How could this be
modelled in Basic? The usual way would be to write:

   10 Code for reading PCW
                :
   50 IF NOT PHONE THEN GOTO 10

This is like saying, "I will carry on reading but now and then I will check
to see if the telephone is ringing. If it
isn't, I will go back to my reading."

A better model could be written using a structure found in many Basics,
including of course that on the BBC. This is
the Repeat-Until loop. II is usually used as follows:

   10 REPEAT
   20 Code for reading PCW
   50 UNTIL PHONE

It should be immediately obvious how this is a much more accurate model of
the original problem.

Now to get more machine specific. The accompanying machine code routines
allow procedures and Repeat-Until loops to be
used on the 16K ZX81.

The new commands are listed below. Note that commands {ii} and (iii) are
always used together. Procedure names should
be as self-explanatory as possible and should be reserved for this purpose
only.

  i) RAND USR REPAT
          :
 ii) POKE UNTIL,<CONDITION>
iii) RAND USR CHECK
 iv) LET <NAME>=USR DEFPROC
  v) RAND USR ENDPROC
 vi) LET <NAME>=USR CALLPROC

The error messages are more or less self-explanatory, but it shoudl be noted
that the line numbers often refer to the
line that 'finds the error', rather than the actual error.


LIMITATIONS TO USE

As mentoned previously, variables used as procedure names should not be used
for any other purpose within the program.
If other machine code routines are used and given 'names', these 'names'
should not begin with E or D.

Unfortunately, procedures cannot be nested, ie, one procedure cannot be
defined within another. This is because the
nested procedure would remain undefined until the outer procedure was
called.

The condition after Until should be Boolean, ie, it should result in an
answer of 1 or 0.

Both Repeat-Until loops and procedure calls can only be nested up to five
deep, as they rely on special stacks of fixed
size. Scroll should be used with care. If the display file is upset, the
error message routine may cause a system
crash. It is best to follow Scroll with:

    PRINT TAB 31;" "

An example of how to use the procedure routines is given in the HexDumper
program.

Remember, the whole idea is to make the program as readable as possible, so
use meaningful names and try to separate
blocks of program using empty Rem statements. Make liberal use of proper
Rems as headings to explain the program, and
try not to worry too much about memory - if you've got it, use it!
