Caution: This should be considered very much "beta", as the implementation touched many parts of the core variable handling logic and needs more field testing before it can be deemed safe for production.
To declare a dynamic variable, assign it an explicit size of zero, e.g.:
MAP1 STRING,S,0 ! dynamically sized string
MAP1 UNF,X,0 ! dynamically sized unformatted
MAP1 DARY(75),S,0 ! fixed-length array of dynamic strings
MAP1 XARY(24,9),X,0 ! fixed-length array of dynamic unformatted
NOTE 1: Dynamic variables may only be declared at the MAP1 level.
NOTE 2: An array may be made up of dynamic elements, but the range of index values for the array remains fixed. However, you may use DIMX and REDIMX to dynamically allocate and resize such as array, e.g.
DIMX ZARY(A,B,C),S,0
REDIMX ZARY(A*2,B,C)
(Re-imensioning an array doesn't preserve the original contents unless only the first dimension changes, as in the example above.)
Dynamic variables may also be used in function and procedure parameter lists, as well as for the return value of a function, i.e.:
Function Fn'Test$(a$ as s0) as s0
Dynamic variables (and array elements) initially take up 8 bytes of storage memory (used as a descriptor), so it won't make much sense to use them if they aren't going to expand beyond 8 bytes.
When an assignment is made to the variable, either via an assignment (e.g. STRING = "abc"), INPUT statement, or via an XCALL, Function, or Procedure, the variable will be expanded as needed to contain the data. If referenced in an expression before any value is assigned, they act like null strings.
NOTE 3: It is not wise to use INPUT RAW with dynamic X variables, since the amount of data input depends on the current size of the variable, which would be 0 initially, but could be anything later (after some other kind of assignment).
As currently implemented, the internal memory allocated to a variable does not shrink, so first assigning a large amount of data and later assigning a small amount does not free memory. (This may change as the implementation evolves.)
Two pools of dynamic variable memory are maintained - one for global or persistent program variables, and one for automatic (aka local or stack) variables (i.e. within functions and procedures). Both are allowed to grow without any particular limit during the execution of a program, but are cleared (and the memory freed) when the program terminates.
To compile programs with dynamic variables, you must use compiler edit 439+, and the /X:2 switch. Any legally compiled program containing dynamic variables will receive a new RUN header value of 0xF167 or 0xF1E7 (if /av), and will generate a "?RUN file incompatible" error if executed under any A-Shell runtime prior to 5.1.1159. Programs which do not contain dynamic variables should continue to compile and run exactly as before.