RISC OS BASIC

Mike Williams describes some of the new features to be found in Basic V under RISC OS.

In this article I shall deal with the additions to Basic itself, but note that there are also a number of changes to the Basic assembler which we hope to deal with in a separate article.

DYNAMIC LIBRARIES

One of the useful features introduced into the original version of Basic V was the facility to access libraries of functions and procedures from within Basic. A set of such routines could be loaded into memory from a file by using the INSTALL or LIBRARY commands (see RISC User Volume 1 Issue 2). However, the management of this facility was not as flexible as it might have been.

If more than one library is needed, then each will take up additional memory as it is loaded, resulting in the allocation of quite excessive amounts of memory in some instances.

There is a well established way of overcoming this, and that is in the use of overlays. In the past a program would be divided up into a main program and several additional modules, only one of which needed to be in memory at any one time. Provided sufficient memory for the largest module was allocated from the outset as an overlay area, any module could be loaded dynamically as and when required.

That is basically the idea now implemented in Basic V. It allows any one of a series of named libraries to be loaded dynamically as required into a single overlay area, and it works as follows.

The new OVERLAY statement specifies a string array, which must already have been dimensioned, containing the names of the library files that may need to be loaded. It allocates an area of memory large enough for the biggest library, though none is loaded at this stage. Then, when a function or procedure is called, Basic V proceeds as follows.

It first searches the current program, it then searches any LIBRARYs, then any INSTALLed libraries, and finally the overlay area. If the routine can still not be found it searches through each library file named in the OVERLAY array. Provided the routine is found in one of the OVERLAY files, that library will then be loaded into the overlay area and the routine executed. For example, we could write:
DIM overlay$(10)
overlay$(1)="$.Library.Maths1"
overlay$(2)="$.Library.Maths2"
overlay$(3)="$.Library.Input"
overlay$(4)="$.Library.Output"
OVERLAY overlay$()

to specify the four overlays given above. Any of the four named overlays will be loaded into the overlay area if it contains a function or procedure which cannot otherwise be found.

Unlike the use of LIBRARY and INSTALL, an overlay routine cannot reference a function or procedure in another overlay for obvious reasons, as all overlays dynamically share the same area of memory. Any overlays no longer required may have their name replaced by a null string in the overlay array, (""), which will speed up any subsequent searching.

Also, new overlay file names may be added to an existing overlay array (provided none is larger than any originally specified, but the names stored there should not otherwise be changed. A new OVERLAY statement will effectively re-initialise the whole overlay facility, including a new allocation of memory for the overlay area.

ARRAY HANDLING ENHANCEMENTS

Although Basic V already allows for all the elements of an array to be initialised to the same value (string or number as appropriate), there has until now been no simple way to set different values, other than by multiple assignment statements. This has now been changed, and the values may be listed after an equals sign ("=") separated by commas, thus:
DIM code(5)
code()=129,132,135,131,133,134

Remember that the first element of any array is element zero, and there are therefore six values for the dimensioned array in the example above. For multi-dimensional arrays, the order is that where the right-most subscript changes the quickest.

Two additional functions have now been provided. SUMLEN returns the sum of the lengths of all the strings stored in a string array (and is to some extent the string equivalent of the numerical SUM function), while MOD returns the modulus of the elements of a numeric array, that is the square root of the sum of the squares of the elements, for example:
modA=MOD(A())
or just:
modA=MOD A()

SAVE AND RESTORE DATA POINTER

Just as the error status can be saved to and retrieved from the stack (using LOCAL ERROR and RESTORE ERROR), the DATA pointer can now be similarly saved and recovered. LOCAL DATA saves the current DATA pointer to the stack, and RESTORE DATA retrieves it again. This is most useful where DATA statements are included in function and procedure libraries, where RESTORE+0 (usually - but see below) is used to set the DATA pointer to the first item of data in the library routine. On exit from a procedure or function, the DATA pointer is automatically reset from the stack (similar to what happens with the error status), and RESTORE DATA is not explicitly needed in these circumstances. LOCAL DATA must be the last item to be declared LOCAL in a function or procedure definition (apart from LOCAL ERROR).

Note, that in general, the statement:
RESTORE +n
will move the data pointer 'n' numbered lines of Basic from the current line number. The form RESTORE +0 serves the purpose of setting the data pointer in a library procedure or function (if included near the start) to a point in the routine before any DATA statements.

MISCELLANEOUS ENHANCEMENTS

As a further aid to error trapping, a statement of the form:
ERROR EXT <number>,<string>
will cause the current error handler to be invoked with the error number and message specified (as is the case when ERROR alone is used in the same way), but will now cause an exit from Basic to the supervisor. This can be useful if a Basic program effectively implements a star command so that when an error occurs an exit can be made back to the star prompt.

If Basic is invoked with the command *BASIC, this can optionally be followed by a qualifier and filename. Thus:
*BASIC Myprog
will run the Basic program Myprog, and:
*BASIC -chain Myprog
has exactly the same effect, while
*BASIC -load Myprog
will load but not run the program, and:
*BASIC -quit Myprog
will run the Basic program Myprog, and quit to RISC OS on termination. The pseudo-variable QUIT may now be used in a Basic program to determine if the qualifier -quit was used (TRUE) or not (FALSE).

A further change is that the pseudo-variable END may now be assigned a value (in a multi-tasking program). In this environment the task manager will allocate an initial amount of memory, but by assigning a suitable value to END (during the course of the program), a multi-tasking program can release unwanted memory for use by other tasks (or grab more). Remember that Basic starts at &8000 and will usually require a minimum of about 10K, thus:
END=&A000
is about the minimum setting for END in a multi-tasking context. If a Basic program is not multi-tasking, then this feature should be ignored.

Finally, there are a number of additional or changed error messages:
0Incorrect in-core file description
2Assembler limit reached
6Type mismatch: numeric array needed
6Type mismatch: string array needed
10No room to do matrix multiply
11No room for this DIM [was error 10]
11No room for this dimension [also 10]
27Missing (
37No room for function/procedure call
42DATA pointer not found on stack
44Too many nested structures
52Can't install library
52Bad program used as procedure/function
library
52No room for library