Dynamic Arrays (DIMX)

Rewritten December 2011

{qualifier} DIMX arrayname(expr1,...,exprn),type{,sizeexpr {,AUTO_EXTEND}}

{qualifier} DIMX arrayname(expr1,...,exprn),structname {,AUTO_EXTEND}

DIMX declares an array whose element size and extent may be determined at run time. The size of the array can be changed explicitly after the initial DIMX using REDIMX or, with the AUTO_EXTEND keyword, it can be extended automatically.

Arguments

qualifier

An optional keyword to qualify the scope and longevity of the array.  Valid qualifiers are STATIC, PRIVATE and PUBLIC. (See MAP Statement Extensions)

expr1,...,exprn

One or more expressions (literal values, variables or arithmetic expressions) evaluated when the statement is encountered at runtime.  The number of expressions given determines the number of dimensions of the resulting array.

type

standard variable types (F, B, X, S, I)

sizeexpr

Arithmetic expression (evaluated at runtime) for the size of each element in the array

structname

Name of a structure previously defined with DEFSTRUCT. See Defined Structures and Dynamic arrays of structures.

AUTO_EXTEND

This keyword (case insensitive) causes the array to be automatically extended as required by direct assignment statements.  See notes below for more details.

 

Examples

IMX FDATA(COUNT),F

STATIC DIMX SDATA(COUNT1,A*B,C),S,len(S2$)

PRIVATE DIMX CUSARY(0),ST_CUS,AUTO_EXTEND

The first DIMX statement above represents a simple example of allocating a single-dimensioned array of COUNT (evaluated at runtime) items, each of them a floating point value (using the default floating point size). This is similar to the original DIM statement.

The second statement declares a three-dimension array of string elements whose size matches the logical length of the string S2$ (evaluated at the time the DIMX statement is encountered). The STATIC qualifier would make sense only within the context of a function or procedure; see MAP Statement Extensions for further notes.

The third statement declares an auto-extending array of ST_CUS DEFSTRUCT. The initial size of this array is 0 elements, but will grow automatically as assignments are made to it; see comments about AUTO_EXTEND in the notes below. The PRIVATE keyword would limit access to the array to routines within the same ++INCLUDE file. In order for that to make any sense, the statement would have to appear at the top of the ++INCLUDE file, above any functions and procedures. Furthermore, the ++INCLUDE file would need to be positioned at the top of the main program, or otherwise in arranged so that the run time flow of execution encountered the DIMX statement before it encountered any other references to it.

 

Notes

   DIMX allocations are automatically freed (and memory recovered) when the RUN or SBX in which they are created exits. DIMX allocations that occur within functions and procedures are automatically freed on return from the routine, unless the STATIC qualifier is used.

   To reset (i.e. delete / free) a DIMX allocation explicitly, use REDIMX to set the subscript extents to zero.

   The contents of a DIMX array (including any extensions to it due to the AUTO_EXTEND feature) are always pre-cleared to nulls.

   The maximum size of an individual DIMX array is determined by the MALLOCLIMIT (default 8MB) option in miame.ini. The limit is tested whenever a DIMX or REDIMX operation takes place, including implicit REDIMX operations triggered by AUTO_EXTEND.

   When an array is automatically extended by the AUTO_EXTEND it will be extended somewhat beyond the amount actually needed for the assignment (on the theory that subsequent expansions are likely to follow). The exact amount of extra expansion is based on a heuristic that is subject to change, but as of build 1191, it consists of the smallest of 110% of the minimum amount required, and 150% of the previous array size. But in no case will the excess expansion (beyond what is immediately needed) be more than 128K. Also see the .EXTENT dot function.

   The MALLOC trace option will trace DIMX and REDIMX memory allocations (along with most other memory allocations/de-allocations), making it a useful debugging tool.

   Because there is no support for it under AMOS, DIMX is not normally supported by the /RC compiler switch. However, you can override that (i.e. cause DIMX to be allowed when compiling in /RC mode) by adding the statement "OPTIONS=RC_DIMX" (without quotes) to miame.ini. Just be careful to make sure that you don't actually try to execute that statement when running your program under AMOS.

   Global DIMX arrays can be made visible to functions and procedures either via the ++EXTERN mechanism documented in Referencing DIMX Variables or via Dynamic Overlays. Only the latter will work for SBXs. DIMX arrays declared within functions and procedures are normally only visible within that routine; the PRIVATE or PUBLIC qualifiers may be used to extend visibility to the ++INCLUDE file containing the routine or to the entire program, respectively.

   Like MAP statements, DIMX statements must occur physically prior to any statements referencing the array, so that the compiler can define the variable. Also, as with MAP statements, the array gets initialized (or in this case, allocated) when it is encountered at run time. This generally requires some care in properly positioning the statement to suit the requirements of both the compiler and the run time system; often coupled with some conditional logic to prevent it from being executed more than one time by the run time interpreter.

 

See Also

•   Passing DIMX Arrays

•   REDIMX

•   DIMX vs DIM

•   Dynamic Array of Structures

•   MAP Statement Extensions

•   Referencing DIMX Variables

•   .EXTENT

 

History

2013 January, A-Shell 6.0.1264:  Refinement of DIMX / SBX refinement: Use of DIMX within a function or procedure, within an SBX, no longer clears the SBX cache flag. Previously, the cache flag was being cleared so as to force a reload from disk on the next XCALL to the SBX, because DIMX modifies the memory map of the RUN module, thus making it non-reusable.

There are two significant consequences to this rather obscure refinement. The first is that re-executing an SBX that is already cached in memory is much faster than loading it from disk. So for SBXs that are called frequently, and which contain DIMX statements within functions, this can be a significant speed-up.

The second is that it permits the SBX to XCALL itself, either directly or indirectly. Previously, clearing the cache flag caused the SBX to be flushed from memory on the next subroutine. But if the SBX was still executing (in a higher stack frame), clearing it from memory would have rather disastrous ramifications (although typically resulting in an illegal syntax error when returning to the higher level instance of the SBX).

Warning:  using DIMX inside an SBX but outside a function/procedure remains incompatible with SBX recursion, although there is currently no way for the runtime system to detect and warn you about it.

2012 March, A-Shell 6.0.1245:  DIMX refinement: On the initial allocation for a DIMX statement, the array extent is now adjusted upward to take advantage of the memory chunk actually allocated. In some cases, A-Shell will reuse a convenient chunk of memory that is somewhat larger than the amount requested.

AUTO_EXTEND refinement: when reallocating memory for a larger array, the minimum new size is 105% of the old. Previously there was a limit of 128K of expansion, which may have resulted in increments of as small as a single unit when the base element size was very large.

2011 September, A-Shell 5.1.1235:  Add direct support for structures. See Dynamic Array of Structures.

2011 March, A-Shell 5.1.1209:  The value of the first subscript in the DIMX statement can now be zero; previously the minimum was one and zero caused a subscript out of range error.

2010 November, A-Shell 5.1.1193:  Local non-static DIMX statements are now fully cleaned up on exit from the function or procedure. Previously, the variable descriptor was removed (along with all of the other local stack variables), but the memory handle and allocation remained in effect. With this enhancement, it is no longer necessary to use REDIMX(0...) to "undimx" any DIMX'd arrays at the end of the function. (But it doesn't hurt to perform that step redundantly.) Note that this is purely a compiler adjustment (compiler edit 469, which was included in A-Shell edit 1193), and not a runtime fix.

2010 September, A-Shell 5.1.1192:  Added EXTENT dot function and Referencing DIMX Variables capabilities.

2010 August, A-Shell 5.1.1191:  Minor refinement in the expansion heuristics used by DIMX with AUTO_EXTEND. When the array needs to be expanded, it is now expanded by a minimum of 150% of the previous array size, or 110% of the size required for the assignment triggering the expansion. But, this is then limited to no more than 128K beyond what would be required for the current assignment. Also, a 128K grace or overage is now added to the MALLOCLIMIT value, to prevent the possibility of the expansion failing because of these heuristics.

2010 August, A-Shell 5.1.1190:  Improvements were added in 1190 and 1191 to support its use within recursive SBXs, to add the AUTO_EXTEND feature, and to support removal via REDIMX.

2005 May, A-Shell 4.9.931:  DIMX added to A-Shell.