Kevin Doyle
This article uses material
from the AMPLE Nucleus Programmer's Guide published by Hybrid Technology, with
their kind permission.
There are several new words available in AMPLE Nucleus to
give the advanced AMPLE programmer enhanced data storage facilities and better
access to the contents of the number stack.
The new words are DIM and ARRAY for data storage and FVAR,
FRAME?, FRAME!, FRAME and FCOPY for stack control.
Data storage words
DIM – reserve memory
sizenumber DIM => address
DIM reserves a specified amount of memory for the program to
use for data storage, and leaves the address of the first location. It is
usually used with ARRAY to define an array, in which case the number before DIM
is the maximum array element number. See ARRAY for more information.
DIM can also be used without ARRAY, leaving you to access
memory directly. The DIM is included in a simple definition which serves to
give the memory block a name, like a GVAR variable, and lets you include
address calculations to make access easier, like ARRAY. This allows you to
create custom storage words, for single byte arrays, faster access store, specially-indexed
arrays, string variables, operating system interface control blocks and many
more. DIM reserves (sizenumber+1)*2 bytes.
Without the checking of ARRAY, it is up to you to make sure
not to use memory outside the DIM block.
READY clears all DIM memory.
Related words: ARRAY #! #? #+!
#B! #B?
Some examples:
"list" [ 10 DIM ARRAY ]
% array with elements 0 to 10
% array with elements 0 to 10
"chars" [ 4 DIM #+ ]
% array with one-byte elements 0-10
% so,
% array with one-byte elements 0-10
% so,
255 0 chars #B!
% stores 255 in element 0
% stores 255 in element 0
A general purpose string store and fetch definition:
"$!" [ %
does string address $!
LEN #212 #B! % store length
LEN FOR( 1 #+ % next location
1 $- ASC #212 #B! % store character
)FOR $2 % discard empty
#2 % string and extra
] % number from loop
LEN #212 #B! % store length
LEN FOR( 1 #+ % next location
1 $- ASC #212 #B! % store character
)FOR $2 % discard empty
#2 % string and extra
] % number from loop
"$?" [ % does address $? => string
#11 #B? FOR( 1 #+ % next character
#11 #B! $CHR $+ % fetch character
)FOR #2 % discard extra no.
$REV ] % reverse string
#11 #B? FOR( 1 #+ % next character
#11 #B! $CHR $+ % fetch character
)FOR #2 % discard extra no.
$REV ] % reverse string
Using the words defined above:
"$var" [ 63DIM ]
% define string
% variable
% variable
$IN $var $! % get string and
% store (for use
% inside [])
% store (for use
% inside [])
$var $? $OUT %
fetch string from
% store (for use
% inside [])
% store (for use
% inside [])
Further information:
The first use of each DIM instruction finds and reserves the
memory, and subsequent uses ignore the size number. If the size is less than
zero, a value of zero is used. The size (in words) is stored as a two-byte number
at the number at the address minus 2. The maximum size theoretically possible
is 16383, though in practice there will never be enough memory for this amount!
The structure of the DIM memory block, relative to the
address returned by DIM, is as follows:
Information
Location
–––––––––––––––––––––––– –––––––––––
No. of elements in array address – 2
element 1 address
element 2 address + 2
...
–––––––––––––––––––––––– –––––––––––
No. of elements in array address – 2
element 1 address
element 2 address + 2
...
DIM takes memory from the program area. The consumption is
shown by MEM. DIM memory is cleared by any command that moves or removes user
words. From the keyboard, only the first execution of DIM reserves memory.
Where DIM memory is required only temporarily, for example
for a control block, you can use the DIM instruction in-line with no name. For
example, a word to open files using OSFIND:
"fopen" [
% filename opno fopen => channelnumber
10 DIM #11 % filename buffer
LEN FOR( % loop to transfer
1 $- ASC % characters into #
212 #B! % filename buffer
1 #+)FOR $2 % incrementing address
13 #12 #B! % store CR character
#12 % leaves: address opno
&FFCE CODE % OS call YX CA => PA
#12 #2 &FF AND % leave channel number
]
10 DIM #11 % filename buffer
LEN FOR( % loop to transfer
1 $- ASC % characters into #
212 #B! % filename buffer
1 #+)FOR $2 % incrementing address
13 #12 #B! % store CR character
#12 % leaves: address opno
&FFCE CODE % OS call YX CA => PA
#12 #2 &FF AND % leave channel number
]
Using the word defined above:
"input" &40 fopen % => channelnumber
"output" &80 fopen % => channelnumber
"update" &C0 fopen % => channelnumber
(see BBC Micro User
Guide for details of use of OSFIND)
ARRAY – access array element
elementnumber ARRAY => address
ARRAY is used in the definition of arrays. It is usually
used after DIM, which reserves storage from program memory, in a word
definition which serves to give a name to the array.
For example:
"totals" [ 10 DIM ARRAY ]
| |
array name maximum element number
(11 elements in array)
| |
array name maximum element number
(11 elements in array)
The array elements are numbered from 0 to the maximum
specified, though you will often leave 0 unused. Array elements are stored to
(set) by #! and fetched from (read) by #?. The array element number goes
immediately before the array name.
The array definition can include instructions that process
the element number for special applications, for example two-dimensional
arrays.
Related words: DIM #! #? #+!
#B! #B?
Some examples:
"values" [ 20 DIM ARRAY ]
0 1 values #! %
store 0 in element 1
3 values #? NOUT % display element 3
3 values #? NOUT % display element 3
"matrix" [ % 10 x 10 array
1 #- 10 #* #+ % col row matrix
100 DIM ARRAY ] % => address
1 #- 10 #* #+ % col row matrix
100 DIM ARRAY ] % => address
"dispmatrix" [ % display matrix
10 FOR( COUNT
10 FOR(
#11 COUNT matrix #? NOUT SP
)FOR #2 NL
)FOR ]
10 FOR( COUNT
10 FOR(
#11 COUNT matrix #? NOUT SP
)FOR #2 NL
)FOR ]
"plvar" [ %
player-local variable
PNUM 8 % - each player has a
DIM ARRAY] % private location!
PNUM 8 % - each player has a
DIM ARRAY] % private location!
Further information:
ARRAY performs the following:
1) Converts the element number into the location address
2) Checks that the address is in range
2) Checks that the address is in range
ARRAY is sometimes worth using in addition to a simple DIM
merely for its range checking function.
Any arrays created by a program remain in existence after it
finishes, but they are discarded by those commands that stop any program that
is executing, that is, COMPACT, SAVE, LOAD, NEW etc.
Stack control words
FRAME – set frame pointer to top
of stack
FRAME marks the current top of the number stack frame which
can then be accessed like an array, using FVAR. The top item becomes the first element.
The pointer to the previous stack frame can be saved and restored with FRAME?
and FRAME!. Music events use a stack frame to hold action variables, and
therefore FRAME is undefined over music events, so you should save and restore
FRAME if necessary.
For examples see FVAR.
Related words: FVAR FRAME?
FRAME!
FRAME! – write frame pointer
pointernumber FRAME!
FRAME! sets the stack frame pointer to the value supplied.
It is used to restore the pointer to the value read with FRAME?.
Related words: FVAR FRAME
FRAME?
For examples see FVAR.
FRAME? – read frame pointer
FRAME? => pointernumber
FRAME? reads the value of the stack frame pointer. It is
used to save the pointer value on the stack for later restoration by FRAME!.
Related words: FVAR FRAME
FRAME!
For examples see FVAR.
FVAR – access stack frame item
elementnumber FVAR => address
FVAR is used to access the items in the stack frame marked
by FRAME as elements of an array. It is used for convenient access to temporary
values on the stack, and to access temporary variable storage on the stack.
It takes the element number and returns the address of it, for
use by #?, #!, #+!, #B? and #B!. The position of the top of the stack when
FRAME was used is element number 1.
Related words: FRAME FRAME!
FRAME?
Some examples:
FRAME 4 FVAR #? %
copy the fourth item
% to the top, so,
% 4321 => 43214
% to the top, so,
% 4321 => 43214
"top3out" [ % set frame pointer
FRAME % and then display top
3 FOR( COUNT % three items on the
FVAR #? % stack leaving them
NOUT SP )FOR ] % unchanged
FRAME % and then display top
3 FOR( COUNT % three items on the
FVAR #? % stack leaving them
NOUT SP )FOR ] % unchanged
"#pick" [ % does n #pick => number
% copy nth number down to the top
FRAME? % save frame pointer
FRAME % set frame pointer
#12 2 #+ % get n, adjust it
FVAR #? % read value and
#12 FRAME! % restore frame
] % pointer
% copy nth number down to the top
FRAME? % save frame pointer
FRAME % set frame pointer
#12 2 #+ % get n, adjust it
FVAR #? % read value and
#12 FRAME! % restore frame
] % pointer
FCOPY – copy n items below stack
frame to top of stack
FCOPY copies a group of adjacent items in the stack frame
marked by FRAME to the top of the stack. It is used for duplication of groups
of values within the stack (cf. #11, #212 and #2121 which copy 1 or 2 items
from the top of the stack) and for access to groups of items on the stack.
For example:
FRAME 3 FCOPY %
copy the 3 items below
% FRAME to the top, so,
% 4321 => 4321321
% FRAME to the top, so,
% 4321 => 4321321
Related words: FVAR FRAME
FRAME!
Published in AMPLINEX 001, September 1987