Please enable JavaScript to view this site.

A-Shell Consolidated Reference

Once a dynamic structure variable has been declared and bound to a structure definition it is ready to be referenced or used. The general idea and syntax are similar to that for regular fixed structure members, with the main difference being that the members are unknown to the compiler, and instead have to be resolved at runtime.

Assignment to Dynstruct as a Whole

If the destination dynstruct has not been bound, then the only allowable assignment to it is from another bound dynstruct, in which case the operation starts by auto-binding the destination dynstruct to match the source, followed by the assignment as described below. Note that this logic also applies when the source is a function that returns a bound dynstruct, and also when the assignment is to a function parameter via an XPUTARG statement.

If the destination dynstruct has been bound, then an assignment to it is a raw copy, essentially equivalent to an n assignment to an instance of a defstruct or any other fixed length unformatted (X) variable. There is no attempt to determine whether the source and destination layouts are compatible, and the number of bytes copied will be determined by the smaller of the source and destination.  The only difference with the dynstruct destination is that if the source is smaller than the destination, the remaining bytes in the destination are set to nulls. Unlike the defstruct or fixed length X variable assignment, where extra bytes in the destination are untouched.

Any other assignment to an un-bound dynstruct results in an error #70 (invalid dynstruct reference).  See History below for evolution of this behavior.

Assignment from a Dynstruct as a Whole

A bound dynstruct acts the same as an instance of a defstruct or a fixed length X variable when used as the source in an assignment statement. The one exception is where the destination is also a dynstruct as described previously.

An attempt to use an unbound dynstruct as the source of an assignment statement will generate ASB error #70, invalid dynstruct reference.

Simple Indirect

The syntax here is identical to that for a traditional structure, e.g.

ds.id = "Dynamo"! member name is "id"
ds.amount = 12.34! member name is "amount"

 

Although the above syntax is the same as for traditional structures, the semantics are different. Instead of using the compiled definition of the member, the run-time interpreter looks up the member by its textual name —e.g. "id" or "amount"—in the dynstruct definition bound to the dynstruct variable (ds in this example) to get the member’s data type and offset within the structure.

This scheme is probably most useful for repurposing code originally written to work on traditional structures and conforms to the "duck typing" paradigm.

Indirect Deferred

In this variation, the specified member name is a string variable whose contents contain the actual member name, which is then treated as in the Simple Indirect scheme described above. The syntax uses a dot followed by the "at" sign, i.e. ".@",hopefully reinforcing the idea that the target member requires two steps to resolve.

ds.@id = "Dynamo"! member name is value of id var
ds.@amount = 12.34! member name is value of amount var

 

The indirect deferred method is more flexible than the simple indirect in that it doesn’t require you to have code written in advance with any knowledge of the structure members. But most likely you would want to use a string array to hold the field names, rather than individual scalar variables. For example:

map1 ds,dynstruct

dimx fnames$(0),s,64,auto_extend  ! array of potential member names

<load fnames$() array from some external source>

<define the dynamic structure and bind it to the variable ds>

for i = 1 to .extent(fnames$())   ! now cycle thru the members

    ds.@fnames$(i) = <value>

next i

 

Array Dynstruct Members

Array dynstruct members present a potential syntactic ambiguity in that it isn’t obvious from the source code whether ds.@fname$(i) refers to a scalar member whose name is the value of fname$(i), or an array member whose name is the value of fname$, in which case the subscript (i) applies to the dynstruct array member.

To avoid this ambiguity, the compiler will treat fname$(i) as a normal array variable (as we would expect), i.e. as the container holding the name of the scalar dynstruct member. The only way to access an array member using the indirect deferred syntax is to use an array variable to hold the member name, which will result in two sets of subscripts, one for the array holding the member name, and one for the target dynstruct member array. For example, consider the structure:

Defstruct ST_FOO

    map2 sku,s,10

    map2 price(3),f

Endstruct

 

If the structure is defined and bound to a dynstruct variable ds, and fname$(1) = "sku" and fname$(2) = "price(", then:

? ds.@fname$(1)    ! refers to sku member

? ds.@fname$(2)(1) ! refers to ds.price(1) 

? ds.@fname$(2)(2) ! refers to ds.price(2) 

? ds.@fname$(2)(3) ! refers to ds.price(3) 

 

ASB  has no variable syntax with adjacent pairs of parenthesized terms, so there is no ambiguity for the compiler in recognizing that fname$(2)(3) can be compiled as two separate components: fname$(2), resolved at runtime as "price(", and (3), resolved separately at runtime and then combined with "price(" to get the member name "price(3)".

Note that when referring to the name of a dynstruct array member, it must contain at least the open parenthesis, i.e. "price(" rather than simply "price".

History

2023 June, A-Shell 6.5.1733:  assignments from an initialized (bound) DYNSTRUCT to an uninitialized (un-bound) DYNSTRUCT now allowed. Previously, this condition generated an ASB error #70, invalid dynstruct reference. Conversely, assignment from an uninitialized DYNSTRUCT now generates ASB error #70; it previously acted like an uninitialized X,0 variable.

2022 December, A-Shell 6.5.1724: assignments to an uninitialized DYNSTRUCT now generate ASB error #67 (invalid reference to structure).  Previously they acted as an assignment to X,0 variable.

2022 December, A-Shell 6.5.1723:  assignments to a bound DYNSTRUCT now act as if to a fixed sized structure.  Previously they acted as if the DYNSTRUCT variable was like an X,0 variable, expanding or contracting to match the size of the source.