Arrays and Function Parameter Lists
When a formal parameter to a function is an array, instead of specifying the extent of each dimension, a list of variables is used to both implicitly specify the number of dimensions and to hold the extent of each dimension. These variables are read-only and cannot be modified within the function.
Adopt a convention for assigning names to placeholders. One such convention is to use the name of the array with a numerical suffix. For example,
function f(a(a1,a2,a3) as integer) as integer
where a1, a2, and a3 are the variables that get the extents of the array, a.
The function f above would be called as follows:
dim x_array(3,4,5) as integer
dim y_array(1,2,10) as integer
print f(x_array()) + f(y_array())
In both invocations of f, the function correctly determines the extent of each dimension of the passed array.
Remember that when passing an array to a function, the type of the array must match EXACTLY with the type expected by the function. Unlike scalar arguments (implicitly coerced from float to int or int to float), arrays are NOT coerced. An attempt to pass an integer array to a function that expects a float array results in a compile-time error.
Optimizations
As mentioned in an earlier section, constant definitions are completely ‘folded’ at the point of definition. This is efficient code. Constant expressions inside AKD BASIC statements are also folded under certain conditions. For example, in the statement:
const PI = 3.1415926535
Main Print PI^2 End Main
The value of PI^2 is not computed at run-time. It is detected as a constant value and pre-computed by the compiler as a single literal constant to be printed.
Similarly, the literal constant 3*4*PI in
x = 3 * 4 * PI * x
is folded at compile-time, leaving only one multiplication to be performed at run-time.
However, certain constant expressions are not folded. For example:
x = 3 * PI * x * 4
is computed at run-time, involving 3 multiplications because the analysis of constant expressions does not attempt to exploit algebraic commutativity laws. Since the basic arithmetic operators are ‘left associative’, you can ensure the best performance by grouping constant factors together towards the left (or using a new constant definition).
If a function is not referenced (transitively from MAIN, plus any interrupt handlers), the compiler does not generate code for it. So, you can freely $include libraries with unused code (e.g., a comprehensive library containing functions supporting several possible axis configurations). Although the compiler parses and type-checks all the included source, it does not generate code into the downloaded program.
If select-case cases are all constants, more efficient code is generated. If a case is a variable, the generated code is equivalent to a string of if-then-else statements for all cases.
If any of the cases is an open-ended range (e.g., is 10), or covers a large range (e.g., 1 to 1000), a fast table-lookup is generated.
If all of the cases are constant, and can be grouped into locally dense subsets, the fastest possible code is generated — a binary search of dispatch tables, followed by an indirect jump through the table. If speed is a consideration, keep your cases constant and close together. (values form a reasonably dense set.)
The compiler performs limited dead-code elimination based on simple constant analysis. For example:
const DEBUGGING = FALSE Main
dim i, sum as integer
for i = 1 to 10 sum = sum + i if DEBUGGING then
print “partial sum is ”;sum next i End Main
Since the value of DEBUGGING is FALSE, the compiler recognizes that the printing of the partial sum never happens and does not generate the print statement. This allows you to place debugging code in strategic locations in your programs and effectively disable it when shipping a production version (shrinks the size of the generated code).
This dead-code elimination also applies to functions whose only point of reference lies in eliminated code. The functions themselves become dead-code and no code is generated for their definitions.
The compiler does not eliminate the print statement from the following program:
dim DEBUGGING as integer
Main
dim i, sum as integer DEBUGGING = FALSE for i = 1 to 10 sum = sum + i if DEBUGGING
print“partial sum is ”;sum next i End Main
In this case, the print statement never executes, but the code to implement is generated because the value of the integer DEBUGGING could be changed by the AKD’s Integrated Development Environment Debugger at runtime, causing the print statement to be executed!