                            BASICOMP
                   by Dr. Dimitri P. Bertsekas
                        225 School Street
                  Belmont, Massachusetts  02178

        This program is a more powerful version of the BASIC
compiler for Models I and III that I presented in the October,
1982 issue of 80 Micro.  Major improvements include four times
faster compilation through the use of machine language
routines, and essentially full compatibility of the compiler
and the BASIC interpreter.  Other improvements include
expansion of the list of commands supported by the compiler,
support of rectangular two dimensional array computations, and
the option to call machine language routines from within the
compiled code through the USR command.  However the program now
requires at least 32K of memory and Disk BASIC.
        The compiler can translate into pure machine code an
ordinary BASIC program containing virtually any type of single
precision computations, a fair amount of integer computations
and graphics, plus a limited amount of string handling.  The
machine code will run much faster than its BASIC equivalent
(usually between 3 and 20 times faster depending on the nature
of the program).  Thus you can speed up your BASIC programs a
great deal without rewriting them in assembly language.
        The machine code generated by the compiler is, I
believe, very efficient.  It is generally comparable in speed
to the one generated by Microsoft's Fortran compiler available
from Radio Shack.  However matrix computations are compiled
more efficiently by this compiler.  For example a matrix
calculation program (published in my 80 Micro article) when
compiled by this compiler runs roughly 11 times faster than in
interpreted BASIC but runs only 7 times faster when compiled in
Fortran.  This is due to a special scheme used for storing two
dimensional array addresses.  Also the size of the compiled
code produced is quite modest.  This is due to the extensive
use of ROM routines and absence of a separate subroutine
library.  For example the matrix program mentioned above
compiled in 391 bytes but its Fortran equivalent is more than
10000 bytes long.
        One of the most powerful features of this compiler is
its capability to interface harmoniously with the BASIC
interpreter through unlimited exchange of variables.  It is
possible to compile into machine code only a portion of a BASIC
program (presumably the most computation intensive).  The
remaining uncompiled portion can be merged with the machine
code into a single BASIC program and run as usual.  Values of
any variable computed by the BASIC code can be used by the
machine code and vice versa.  In this way you get the best of
all possible worlds; the convenience and broad command
repertoire of the BASIC interpreter together with the speed of
pure machine language code.

                       USING THE COMPILER

        Load BASICOMP and if you have 32K of memory change the
statement MR=0 in lines 1000 and 6650 to MR=1.  As an
illustration we will compile the program:

10 CLS:FOR I%=15360 TO 16383:POKE I%,191:NEXT
20 A$="PRESS BREAK TO EXIT":PRINT A$;
30 A%=PEEK(14400):IF A%<>4GOTO30:' test for break key
500 END

Enter these lines and RUN.  Line 10 will execute in interpreted
BASIC as usual and will first clear and then white the screen.
Execution will stop when you press BREAK and the END statement
in line 500 is encountered.
        Now type RUN 1000 and press <C>.  After a short while
the compiler will start translating line 10 into machine code
and poke the code in memory starting at location -2000 (or
-18384 if you have 32K of memory).  It will then translate
lines 20, 30, and the END statement in line 500 and stop
compiling.  The start and end of the compiled code will be
displayed on your screen.  You then have the option of
executing the code directly by pressing ENTER.  If you do so
the screen will clear and turn white almost instantly.  What
happened is that statement 10 executed in machine code 63 times
faster than in the usual interpreted BASIC mode.  Press BREAK,
type X=USR(0) and press ENTER.  The compiled code will execute
again exactly as the first time.  You can now save the compiled
program on disk using the Dump command and the start and end
addresses displayed earlier.
        The preceding example illustrates some of the basic
rules for using the compiler.  These are:
        a) The BASIC program to be compiled should be entered
or merged together with the compiler in lines ranging from 0 to
500.  The command to compile it is RUN 1000.  The compiler will
successively translate into machine code all BASIC lines with
numbers from 0 to 500 and store the machine code somewhere near
the top of your memory.
        b) An END statement is required at each point where you
wish the compiled code to stop execution and return you to the
BASIC interpreter.  You can run the compiled code as many times
as you wish, once it is stored in memory at the place where it
was originally compiled, by executing the BASIC command
X=USR(0) (the USR address is the start of the compiled code and
should be first defined by a DEFUSR statement - for example if
-2000 is the start of the compiled code you must first execute
DEFUSR=-2000, see lines 1300 and 1340).
        c) The program should contain only statements from
Table 2.  (See the end of the documentation.  Table 1 lists the
abbreviations used in the descriptions of Table 2).  If your
program includes some statement that is either not contained in
Table 2 or is incorrectly coded the compiler will not recognize
it and will warn you with an error message.
        d) Multiple statements, remarks and blanks are allowed
in each program line but blanks should not appear within a
variable name and on either side of an = sign.
        e) Only integer, single precision, and string variables
are allowed in the program to be compiled.  Furthermore their
names are restricted as follows.  Integer names allowed are A%
to Z%.  String names allowed are A$ to Z$.  Single precision
simple variable names allowed are A-Z, A0-Z0, ..., A9-Z9.
Single precision one and two dimensional array names allowed
are A-Z.  No integer and string arrays are accepted by this
compiler.  Some additional restrictions on the use of variable
names dictated by memory management considerations will be
explained shortly.
        There are a few more rules that you must observe before
you can use the compiler to its full potential.  These have to
do with effective memory management, and interfacing
harmoniously compiled code with ordinary BASIC code.  We will
take these up in sequence.

               VARIABLE USE AND MEMORY MANAGEMENT

         When the machine code generated by the compiler runs
it uses variables similarly as usual BASIC programs and
therefore it must store these variables somewhere in memory.
In our case it stores the compiled code near the top of memory
and stores variables right below the compiled code.  Referring
to lines 6690 and 6700, integers are stored starting at
location VT, single precision simple variables are stored right
after integers starting at location VF, then one dimensional
arrays starting at VA, two dimensional arrays starting at VD,
and finally string variables starting at VN.
         Most existing compilers will allocate storage space
only for the actual compiled code and only for those variables
that you actually use in your program.  This compiler differs
in that it allocates storage space for compiled code and for
some variables whether you use them or not.  To avoid a serious
potential memory waste it requires you to provide information
as to how much space for compiled code and how many variables
you need for your program.  This is done by modifying the
storage parameters CC and SS in line 6650 and
IS,DO,DT,DC,SL,NO,NT,NS in line 6660.
         More specifically CC is the number of bytes allocated
for storage of compiled code.  Set this to a close overestimate
of the size of the compiled program.  If you make a mistake and
allocate too little space you will soon find out when the
compiler tries to store machine code beyond the limits of your
memory.  If you allocate too much space your program will be
compiled correctly, you will see its actual size, and you will
have the chance to adjust the parameter CC and recompile the
program should you wish to economize in memory space.  The
parameter SS sets the start of storage of variables and should
always be greater or equal to CC.  Ordinarily it should equal
CC unless you wish to leave some space between compiled code
and variable storage in which to put something else - for
example a machine language routine or a second compiled program
that shares the same variables with the first.
         Returning to the use of variables the compiler will
always allocate space for the integer variables A%-Z% and the
single precision simple variables A-Z whether you use them or
not (a total of 156 bytes).  If you set all the parameters in
line 6660 to zero you will not be allowed to use any additional
variables and the total amount of storage used other than for
the code itself will be the minimum possible 156 for variables,
and another 26 bytes for internal use of the compiled program -
a total of 182 bytes.
         You can tell the compiler that you need to use more
variables than the minimum allowed by setting some of the
parameters in line 6660 to nonzero values.  The parameter IS
specifies the number of single precision variables per letter
in addition to the letter itself that you can use.  If you set
for example IS to one then only the variables A-Z, A0-Z0, are
allowed, while if you set IS to ten all the variables A-Z,
A0-Z0, ..., A9-Z9 are allowed.
         The parameters NO and DO specify the number and
dimension of one dimensional arrays that you can use.  For
example if you set NO=26 and DO=10 all the arrays A(.) through
Z(.) can be used and their indexes must take values between 0
and 9.  If NO=2 and DO=501 only the arrays A(.) and B(.) can be
used and their indexes must take values between 0 and 500.
         The parameters NT, DT, and DC specify the number of
two dimensional arrays that can be used, and their row and
column dimension.  For example if NT=3, DT=15, and DC=10 only
the matrices A(.,.), B(.,.), and C(.,.) can be used and their
first and second indexes must take values from 0 to 14, and 0
to 9 respectively.
         In both one and two dimensional arrays the indexes
should either be an integer within the dimension range of the
array (this is checked by the compiler), or one of the integer
variables A%-Z%.
         For example if NS=5 and SL=40 then only the string
variables A$-E$ can be used and each must have length no
greater than 40 characters including blanks.
         Simple single precision variables and elements of
arrays take up 4 bytes of storage each so you can easily go
beyond the limits of your memory if you don't control carefully
their number.  The compiler displays the storage parameters, so
you have the chance to change them before starting to compile.
         Finally when compiling programs you must protect the
memory area where the compiled code and the assembly language
routines used by the compiler are stored (see the DATA
statements in lines 7380-7620).  The rule is that the number of
protected bytes should be at least 750 plus the allocated size
for compiled code (the value of CC in line 6650).  The number
of protected bytes is set by adjusting the parameter PC in line
1000.  You also have the chance to change this number on line
when running the compiler.  It is also possible to operate the
compiler without memory protection (PC=0 in line 1000) as long
as the the compiled code does not extend to the top 300 bytes
or so of memory.
         When executing the compiled code in conjunction with a
BASIC program (see the next section), you must set memory size
which is sufficient to protect both the compiled code and the
area where it stores its variables.  The compiler displays the
required memory size at the end of compilation.  Note that it
is possible to set memory size from within a BASIC program.
Line 6620 shows how this is done.  The desired memory size is
poked into locations 16561 and 16562 and this is followed by a
CLEAR statement (any number of string bytes CLEARed will do).
         If the preceding discussion seems confusing at first
use the original parameters of BASICOMP for variable and code
storage.  This allows you 2000 bytes of compiled code, the
integer variables A%-Z%, the simple single precision variables
A-Z, the one dimensional arrays A(.)-C(.) with 20 elements
each, and the string variables A$-D$ with maximum length 30
characters.  The total size of a compiled program including
variables with this parameter setting is 2551 bytes.

         COMBINING COMPILED PROGRAMS WITH BASIC PROGRAMS

         Because many normal functions of the BASIC interpreter
cannot be compiled (disk I/O or PRINT USING for example), it is
essential to be able to interface the compiled code
harmoniously with ordinary BASIC code.  As discussed earlier
you can execute the compiled code from BASIC as many times as
you want via the USR command.  Similarly, by introducing END
statements at the points where you wish the compiled code to
return to BASIC, you can carry out the reverse process.
However this switching back and forth from BASIC to compiled
code would be of limited use if you didn't have the means of
passing variable values in either direction.  For this purpose
the two special statements X=0+Y and X=1*Y have been provided.
Here X is an integer or single precision variable of the
compiled code and Y is an integer or single precision variable
of the BASIC code.  Note that X and Y must be both variables of
the same type (both integer or both single precision).
         As an illustration consider the statement A%=0+AB%.
When compiled and executed it finds the location where the
BASIC interpreter stores the variable AB% and transfers the
current value of AB% into the location where the compiled code
stores the variable A%.  The statement A%=1*AB% performs the
reverse process.  It transfers the current value of the
compiled code variable A% into the BASIC variable AB% (from
where it can be picked up for disk I/O or further calculation
for example).  If the BASIC variable AB% has not yet been
established the compiled code creates it automatically.  As an
example consider the following two lines:

10 FOR I%=0 TO 10:I%=1*I%:A(I%)=0+VECTOR(I%):NEXT
20 FOR I%=0 TO 10:I%=1*I1%:FOR J%=0 TO 10:J%=1*J1%:
A(I%,J%)=1*MATRIX(I1%,J1%):NEXT:NEXT

When compiled and executed, line 10 transfers the elements 0-10
of the BASIC one dimensional array VECTOR into the
corresponding elements of the compiled code array A.  Line 20
transfers the specified elements of the compiled code array A
into the corresponding elements of the BASIC array MATRIX.  If
MATRIX or the integer variables I1% and J1% have not yet been
defined they will be created.
         If the names of X and Y are identical, the statements
X=0+Y and X=1*Y when executed in BASIC while you are debugging
will not interfere with the program's operation.
         Let's discuss now the process of writing a combined
BASIC and compiled code program.  First, write your program in
BASIC, test it and debug it as usual.  During this stage try to
use statements and variables that the compiler will accept, and
structure the program so it requires few modifications later.
Then decide which part of your program you are going to
compile.  Isolate that part and introduce interfaces for
exchanging variables with the remaining parts using the
statements X=0+Y and X=1*Y described earlier.  Duplicate any
subroutines used by both parts since the compiled code cannot
call BASIC subroutines.
         Renumber the part to be compiled so its line numbers
are in the range 0-500 while the remaining part has numbers
10000 or higher.  Test the program again by introducing GOTO
statements to make sure it works after renumbering.  Introduce
a USR command at each point where you want the BASIC program to
switch to the compiled code, and an END statement at each point
where you wish the compiled code to switch to BASIC.  At this
point you should have a program such as the one in the Sample
Listing (see the end of the documentation).  This is a program
that randomly generates N% numbers (lines 10020-10030), and
calls the compiled code (line 10050) to compute their average.
The compiled code first obtains from BASIC the value of N%
(line 10), then obtains successively from BASIC all the numbers
and gradually builds up their average A (lines 20-70).  The
value of A is passed to BASIC (line 80) and the compiled code
returns to BASIC (line 500).  BASIC now prints the average
(line 70) and goes back to line 10020 to start again.  Line
10010 sets memory size to protect the compiled code, and sets
up the USR call.
         Once you have written a combined program such as the
one in the Sample Listing you should save it in ASCII on disk
and load BASICOMP.  Then merge the combined program with the
compiler, adjust the storage parameters in lines 6650 and 6660
if necessary and RUN 1000.  After compilation is completed you
should dump the compiled code on disk and BREAK (or BREAK first
and then Dump the code on disk if you don't use NEWDOS80).
Then set memory size and set up the USR call (compare with line
10010), delete all lines up to 10000 if you wish, and your
combined program can be executed via RUN 10000.
         Once you have the combined program in its final form
you may wish to translate the compiled code into DATA
statements and merge it with the BASIC code in a single
program.  80 Micro has published an excellent program for this
purpose (Datagen, August 1981).  Otherwise you must load the
compiled code in memory via the DOS LOAD command before you can
run the combined program.

                         TROUBLESHOOTING

         The compiler checks for most syntax errors during
compilation.  However some errors can remain undetected until
you find out the hard way during execution time.
         If the compiled program runs but gives different
results than its equivalent BASIC program the most likely
problem is that some compiled code variable appears in the
right hand side of an assignment statement without being
initialized first (remember the BASIC interpreter automatically
initializes all variables to zero but the compiler doesn't).
Also the compiler does not check whether the result of an
integer LET expression lies within the legal range (-32767 to
32767), another source of errors or program crashes depending
on how the results are used later.
         If the compiled program crashes check the For...Next
loops; make sure they are set up properly (each For is matched
by a Next) and that there is no jump out of the range of a
For...Next loop.
         Finally there are three more compiler parameters that
you will rarely if ever need to adjust.  These are the
dimensions of the arrays L1, L2, and A in line 6630.  The
dimension of L1 and L2 is the maximum number of lines that can
be compiled, and the dimension of A is the maximum numbers of
jumps (GOTOs and GOSUBs) that can be compiled.  Listing 1
allows 100 program lines and 50 jump statements.  If you try to
compile a program that is too long or has too many jumps,
compilation will stop with a "subscript out of range" error.
In that case you must increase appropriately the dimensions of
L1 and L2 or A.

                          MODIFICATIONS

         The compiler takes a lot of memory space which you may
need if you want to compile a long program.  One way to save
memory is to delete all remarks.  In fact this is essential if
you have less than 48K of memory.  If you don't need to see the
current parameter settings before compiling delete lines
6710-6720.  If you don't need all of the compiler's
capabilities you can delete the corresponding lines and save
space.  For example if you don't need OUT delete line 1185 and
lines 5500-5550.  If you don't need SET, RESET, and POINT
delete lines 2030, 6000-6110.  If you don't need FIX, CINT, SGN
and RND delete lines 2021-2024 etc.  Another memory saving
device is to write the DATA statements in lines 7380-7620 in a
disk file and read instead the DATA in line 7200 from that
file.
         The option to Dump the compiled code to disk directly
from the compiler (see line 1335) works for the NEWDOS
operating system for both Models I and III.  If you have TRSDOS
you will have to forego this option and use the Dump command as
described in your TRSDOS manual.  You may, if you wish, then
delete line 1335 and the portion "ANDA%<>68" in line 1330, and
modify the Print statements in line 1320.  If you have a
different operating system that allows you to execute the Dump
command directly from BASIC you should modify appropriately
line 1335.
         As an aid in understanding the program note that the
functions of the four machine language routines used by the
compiler are as follows:

USR0: Pokes P into memory location M and increments M.
USR1: Sets B to the next nonspace byte of the BASIC program.
USR2: Corrects the addresses of the compiled code jumps.
USR3: Sets E1 and D1 to the least and most significant bytes of
the variable C respectively.

                END OF DOCUMENTATION TEXT
============================================================
TABLE 1: Definitions and abbreviations
             --------------------------------------

Integer Variable (IV): One of the variables A%-Z%

Single Precision Variable (SPV): A simple variable A-Z, A0-Z0,
A9-Z9 or a one or two-dimensional array element

String Variable (SV): One of the variables A$-Z$

Constant (C): Any integer or decimal number

Possible Integer (PI): Any integer in the range -32767 to
32767

One Byte Integer (OBI): Any integer in the range 0-255

Sting (S): Any sequence of blanks or printable characters
enclosed in quotation marks (the right quotation mark is
optional if the string lies at the end of the line)

Integer Expression (IE): A sequence of the form X1sX2sX3...
where X1, X2, X3,... is a positive integer less than or equal
to 32767 or an integer variable, and s is plus or minus. The
sequence may begin with a minus sign but not with a plus sign
or a zero followed by a plus sign. Parentheses are not allowed
(and not needed). The compiler evaluates integer expressions in
the same way as the interpreter but if the result is outside
the range -32767 to 32767 the compiled code will not indicate
an error

Single Precision Expression (SPE): An arbitrarily parenthesized
legal Basic expression involving constants, single precision or
integer variables, the operators +, -, *, /, [, and the
functions RND(0), SQR, ABS, LOG, EXP, COS, SIN, TAN, ATN. Here
are some examples of SPE's:
a) -(1+SQR(1.2*A% + SIN(A(I%,J%)*2.5)))
b) LOG(EXP(B0+C)/2.3+.1)*B%
c) (-1.2+3.4)
d) (I%)

                      END OF TABLE 1
============================================================
TABLE 2: Program statements that can be compiled
      -------------------------------------------------
           (Expressions in brackets are optional)
           --------------------------------------

LET: There are several types of LET (assignment)
     statements. In each case the LET keyword is optional
     1) X=Y (Integer LET)
     X:IV
     Y:IE
     2)X=Y (Single Precision LET)
     X:SPV
     Y:SPE
     3)X=Y (String LET)
     X:SV
     Y:S or CHR$(Z1)[+ CHR$(Z2)[+CHR$(Z3)[+ ... where Z1,
Z2, ... are IVs or OBIs

PRINT: There are several types of PRINT statements:
     1) PRINT (line feed and carriage return)
     2) PRINT X1[;X2[;X3[;...
     X1,X2,X3,...: SPEs or SVs or Ss
     3) PRINT @ X,Y1[;Y2[;Y3[;...
     X:PI in the range 0-1023 or IV
     Y1,Y2,Y3,...: SPEs or IVs or Ss

LPRINT: Same format as PRINT statements 1) and 2) above.

IF...THEN...ELSE: The format of this statement is:
     IF X rel Y THEN (line #)[:][ELSE...]
     where
     rel is any of =,<,>,<=,=<,>=,=>,<>,><
     X is an IV or a SPE that does not begin with an IV
     Y is a SPE, but if X is an IV then Y must be an IV or
a PI
     THEN can be replaced by GOTO or by THEN GOTO
     ELSE can be followed by any other legal statements
including another IF...THEN statement
     Note: If X is an integer variable and Y is a SPE which
     is not an IV or a PI the compiler will give an error.
     If you compare an IV with a SPE other than the above
     type, code the statement as in (I%)relSPE or SPErelI%.
     Note that an IF...THEN statement involving integers
     will execute much faster than one involving SPEs.

GOTO (line #):

GOSUB (line #):

INPUT X:
     X:IV or SPV. The constant keyed in should have no more
     than six digits. If X is an IV, it is not necessary 
     that the constant keyed in is an integer. The code
     automatically truncates it to an integer. If the
     absolute value of the constant is larger than 32767
     and X is an IV a fatal error will occur.

POKE X,Y:
     X:IV or PI
     Y:IV or OBI

SET(X,Y);RESET(X,Y):
     X,Y:IV or OBI in the legal range of the SET and RESET
     commands.

CLS:

REM (or '):
     The compiler skips over statements that begin with REM
     or '.

END:
     It is mandarory to have an END statement at each point
     where you wish the USR to return to BASIC. This 
     statement is translated as a Return to the point where
     the USR was called.

FOR X=Y1 TO Y2:
     X:IV
     Y1,Y2:IV or PI
     Note: Y1 must have a value less than or equal to that
     of Y2 and the STEP option is not supported. If Y1 has
     a larger value than Y2, the program will get caught in
     an infinite loop, give incorrect results, or hang up.
     The compiler does not check for this error.

NEXT [X]:
     X: IV
     Notes: An unlimited number of FOR...NEXT loops is
allowed but the loops must be matched (each FOR is
matched by a NEXT). It is not legal to jump to a line
outside the range of a FOR...NEXT loop from a line
inside the loop. Code that violates this rule will be
compiled with no indication of error but very likely
crash upon execution.

X=FN(Y):
     X: IV
     Y: SPE
     FN: Any of INT, SGN, FIX, CINT

X=RND(Y):
     X: IV
     Y: Integer between 1 and 32767

X=PEEK(Y):
     X: IV
     Y: PI or IV

X=POINT(Z1,Z2):
     X: IV
     Z1, Z2: IV or OBI

X=USR(Y):
     X: IV
     Y: IV or PI
     Notes: This statement calls a machine language routine
     with entry point Y. The integer variable X is dummy 
     and its value is not affected by execution of this
     statement. This function works differently in Basic
     (see the Level II manual).

X=VARPTR(Y):
     X: IV
     Y: Name of a Basic integer, single precision, double
     precision, or string variable.

X=ASC(Y):
     X: IV
     Y: S
     Note: When this function is executed X equals the 
     ASCII value of the first character of the string Y. If
     Y="" then X will equal zero. By contrast in ordinary
     Basic ASC("") gives an error.

X=INKEY$:
     X=: S
     Notes: The string X will equal the character of the
     key pressed while the statement was executed. If no
     key was pressed then X="". By contrast Basic returns
     the character of the key latest pressed (see the Level
     II manual). This function together with the ASC
     function is useful in a program line such as:
     10 A$=INKEY$:A%=ASC(A$):IF A%=0 THEN 10
     The statement above will loop until a key is pressed.
     At that time A% will equal the ASCII value of the key.

OUT X,Y:
     X: IV or OBI
     Y: IV or OBI

                     END OF TABLE 2
============================================================
SAMPLE LISTING
                     --------------

5 ' LINES 10-500 ARE A SAMPLE PROGRAM READY TO BE COMPILED AND
RUN IN CONJUCTION WITH THE BASIC PROGRAM STARTING AT LINE
10000
10 N%=0+N%' GET VALUE OF N% FROM BASIC
20 S=0:P%=N%-1
30 FOR I%=0 TO P%
40 I%=1*I%:N=0+ARRAY(I%)
50 S=S+N
60 NEXT
70 A=S/N% ' COMPUTE THE AVERAGE
80 A=1*AV:' PASS AVERAGE TO BASIC
500 END:' RETURN TO BASIC
10000 ' SAMPLE COMBINED PROGRAM THAT COMPUTES THE AVERAGE OF A
SET OF RANDOMLY GENERATED NUMBERS
10010 MR=0:HS=-2551-MR*16384+65535:POKE 16562,HS/256:POKE
16561,HS-INT(HS/256)*256:CLEAR 100:MR=0:DEFUSR=-2000-MR*16384:'
SET MR=1 FOR A 32K SYSTEM; THIS LINE SETS MEMORY SIZE AND SETS
UP THE USR CALL
10020 DIM ARRAY(19)
10030 INPUT "HOW MANY NUMBERS (1 TO 20)";N%:FOR I=0 TO
N%-1:ARRAY(I)=RND(0):NEXT:S=0:FOR I=0 TO
N%-1:S=S+ARRAY(I):NEXT:PRINT "AVERAGE =";S/N%
10040 PRINT "PRESS <ENTER> TO RUN THE COMPILED CODE":GOSUB
11000
10050 X=USR(0)
10060 PRINT "AVERAGE COMPUTED BY THE COMPILED CODE =";AV
10070 PRINT STRING$(64,176):GOTO 10030
11000 A$=INKEY$
11010 A$=INKEY$:IF A$="" GOTO 11010 ELSE RETURN

                  END OF SAMPLE LISTING
============================================================
                                                          
 