How to save memory in AMPLE

Kevin Doyle
Users of the Studio 5000 software on a BBC Model B may find themselves coming up against the dreaded '!No room' error message. In most cases some simple changes to the program can free enough space to allow programming to continue.
To work out how best to tackle memory saving, it helps to understand the way in which an AMPLE program is stored.
As with BASIC on the BBC micro, AMPLE is stored in a tokenised form - each AMPLE Nucleus word being stored as a single byte. This means that the actual length of the AMPLE words is unrelated to the memory usage; the AMPLE Nucleus words C, !, #OUT, EVERY, and SIMPLEACT all take up one byte of memory.
User words and module words take up two bytes of memory.
All this means that memory saving depends on reducing the number of words used rather than on the length of the displayed definition. For example, replacing all occurrences of the AMPLE Nucleus word #OUT with a single letter word, say,
"x" [#OUT]
may reduce the length of the displayed words in Notepad but would actually take up more memory.
To reduce the number of words in AMPLE definitions you have three options:
1) Remove redundant words;
2) Replace recurring word groups;
3) Change to more efficient syntax.
These options are arranged in a rough order of difficulty and I will now discuss each option giving examples.

1) Remove redundant words

The most obvious way to reduce redundant words is to eliminate any which are no longer in use. In more complex programs, words may have been created which are no longer used. There is no easy way to discover these except by knowing how the program was built. To get rid of a redundant word use:
"word" DELETE
If the word is still part of another word's definition the message "!In use" will be returned.
If no words are completely redundant then you must look for redundancy within the word definitions themselves.
The easiest things to remove are comments and spaces. Any words following the comment word '%' on the same line can be removed without affecting the operation of the program. The only exception to this is where the '%' is the first word on the line and it follows a DISPLAY or MENUDISP word earlier in the definition.
Each single space in an AMPLE program takes up one byte of memory. Multiple spaces only take up two bytes regardless of the number. For clarity most people will write AMPLE with spaces between each word. When memory is short, however, clarity may have to be sacrificed to save memory. Removing spaces between words can have a significant effect on memory usage and many spaces can normally be removed from a program without sacrificing readability altogether.
Care must be taken, however, where ambiguities could occur. For example, words such as CHAN and VOICE can be changed inadvertently to CHANS and VOICES if the next word starts with an 'S'. Similarly, a hex value can be confused by a following word starting with the letters A-F. So &FFF4CODE will generate an error as it will be interpreted as &FFF4C ODE by AMPLE.

2) Replace recurring word groups

As mentioned earlier, any reference to a user word in a word definition takes up two bytes. Therefore any phrase you wish to replace with a user word must contain more than two bytes to save memory. Although it was stated earlier that AMPLE Nucleus words take up one byte, this is a slight simplification. There are some AMPLE Nucleus words which use more than one byte of memory.
Numbers, strings and comments are stored with preceding bytes to indicate which type of data follows. So, one byte numbers (0-255) take up two bytes and two byte numbers take up three bytes.
Strings and comments take two bytes more than the length of the string (ignore surrounding inverted commas or the '%' sign).
AMPLE structures such as IF(...)IF, REP(...)REP and FOR(...)FOR take extra bytes to provide control information. Each IF(...)IF or REP(...)REP structure takes up a total of 4 bytes with an additional 3 if an )ELSE( or an )UNTIL( is used. Each FOR(...)FOR loop takes up 8 bytes (not including the preceding number). The ACT(...)ACT control structure takes up 5 bytes.
To search for repeating word groups amongst, rather than within, word definitions, try printing out your program. Seeing the program as a whole should make the spotting of repeating phrases easier.
Any new word takes up a minimum of 8 bytes of memory plus the number of characters in the word name. So, even an empty word such as
"test" []
will take up 12 bytes.
Because the actual word name is only stored once (in the definition) and all references to it are tokenised (as two bytes) there is often little point, in memory terms, in choosing very short words (such as 'x' or 'z') to replace repeating phases.
Shortening the word name only saves on memory once and may make the program a lot less readable.

3) Change to more efficient syntax

Some AMPLE expressions can be rephrased in a more memory-efficient way without altering their effect. For example, I mentioned earlier that single byte numbers are stored as two bytes. If you have a program containing lots of zeros then it is more efficient to replace these with the AMPLE word OFF which takes only one byte.
Displaying a string with only one character (such as "x"$OUT) takes up 4 bytes. Replacing this with the ASCII number for the character and the word #OUT takes only three bytes.
Strings containing more than 13 consecutive repeating characters could be more effectively replaced by a FOR(n#OUT)FOR construction (where n is the ASCII code for the character).
Because each FOR(...)FOR construction takes 10 bytes (including a single byte loop number) it may be more memory efficient to repeat the contents of such a structure if it being repeated a small number of times. For example,
4FOR(riff1)FOR
(taking 12 bytes) where riff1 is a another user word, would be more memory efficient as
riff1riff1riff1riff1
which takes only 8 bytes.
There is a special AMPLE word which represents three consecutive rests thereby reducing memory usage with multiple rests. Therefore, grouping rests into threes is a way of saving of a few bytes of memory.
Each end of line in an AMPLE program is indicated by a one-byte token, so the fewer the number of lines the less the memory required for the program.
As you can see, there are only limited savings to be made by rephrasing AMPLE expressions and more intimate knowledge of AMPLE is needed to find the opportunities. For all but the most desperate situation the first two techniques should be all that is necessary.

Published in AMPLINEX 004, March 1988