Parameter Passing (In)

Modified September 2014; see History

Any variables in the formal parameter list (var1,...,varN) will be assigned automatically from the calling parameters, converting as necessary. For parameters without explicit "as <typsiz>" clauses, such as flags and width in the Fn'Dec2Hex$ example (see User-Defined Function Examples), their types will be determined by the normal rules for unmapped variables. Otherwise the types will be as declared. (Here the rule regarding string parameters having to end in $ does not apply.) In all cases, the types of the calling parameters will be converted as best they can to the types of the formal parameters. If the call does not specify all the parameters, any leftover are set to 0 or null. Any parameters passed which go beyond those defined in the formal parameter list will not be automatically converted to anything, but they will remain accessible on the stack (along with all the other parameters) where they can be retrieved with explicit XGETARG statements (just as you would in an SBX). (This kind of flexibility might be useful in a function that handles different argument types, depending on the number of parameters passed.) The number of parameters passed will be available in the system dot variable .ARGCNT, and their types and sizes will be available via the dot functions .ARGTYP(argno) and .ARGSIZ(argno).

The parameter list may be empty, in which case you use an empty pair of parentheses ().

Also see the discussion on Parameter Type and Size.

To pass a structure or array as a parameter, you can use the following technique. Let's say we want to pass the following array of structures to a function:

map1 shifts(40)

   map2 empid,s,10

   map2 in,b,4

   map2 out,b,4

 

Since BASIC does not have a syntax by which we can refer to the entire array shifts(), we can use the overlay feature instead, i.e.:

map1 shiftx

   map2 shifts(40)

      map3 empid,s,10

      map3 in,b,4

      map3 out,b,4

 

Now we can pass the entire structure as a single variable, shiftx, i.e.:

total'hours = fn'add'shifts(shiftx)

The function can then receive the structure as a single x720 entity and break it back out into the original array of structures using the same kind of overlay, e.g.

Function fn'add'shifts(shiftx as x720) as f6

   map1 shiftx2,@shiftx     ! overlay shiftx2 on passed structure

      map2 shifts(40)      ! so we can access it via this array

         map3 empid,s,10

         map3 in,b,4

         map3 out,b,4

 

Starting with version 5.1, a considerably more elegant technique for passing complex parameters, such as structures and arrays, is via Defined Structures. To illustrate, in the example above, we could have defined a structure to contain the shifts() array:

define MAX_SHIFTS = 40

defstruct ST_SHIFT_ARRAY

   map2 shifts(MAX_SHIFTS)

      map3 empid,s,10

      map3 in,b,4

      map3 out,b,4

endstruct

 

map1 shiftx,ST_SHIFT_ARRAY

 

Function fn'add'shifts(shiftx as ST_SHIFT_ARRAY) as f6

   map1 hours,b,4

   map1 h,f

   for h = 1 to MAX_SHIFTS

      hours = shiftx.out(h) - shiftx.in(h)

   next h

...

 

Besides offering a simpler, more intuitive syntax, a big advantage of using a defined structure is that it eliminates the need to manually match up the size of the unformatted variable (e.g. shiftx as x720 vs. shiftx as ST_SHIFT_ARRAY). Thus, if you change the definition of the structure, a recompile is all that would be required to synchronize it to the existing functions.

As of A-Shell 6.1.1389, arrays—including arrays of structures and collections—declared with DIMX may be passed by reference; see Passing DIMX Arrays.

A related issue occurs with passing string arguments to functions, in that you often don't know how large to make them. For example, consider the following function which formats a name from its individual parts:

Function Fn'Format'Name$(first$ as s20, mid$ as s20, last$ as s30) as s50

 

The problem is, how do we decide on the appropriate sizes for the parameters and returned string? The best way to handle this is to use common defined symbols through the application, so that they are always consistent:

define MAX_FIRST = 20

define MAX_MID = 20

define MAX_LAST = 30

define MAX_NAME = 50

 

map1 EMP

    map2 E'FIRST,S,MAX_FIRST

    map2 E'MID,S,MAX_MID

    map2 E'LAST,S,MAX_LAST

 

map1 NAME$,S,MAX_NAME

....

    NAME$ = Fn'Format'Name$(E'FIRST, E'MID, E'LAST) 

....

 

    Function Fn'Format'Name$(first as s MAX_FIRST, mid$ as s MAX_MID, last$ as s MAX_LAST) as s MAX_NAME

 

Note that when using defined symbols in place of literal numeric values, you need a space between "s" (for string) and the symbol.

See Also

• References to the :INPUTONLY and :OUTPUTONLY clauses on the User-Defined Functions page.

• Sample programs in [908,61] of the EXLIB demonstrate array passing by reference.

Dynamic Arrays (DIMX)

 

History

2014 September, A-Shell 6.1.1389:  A-Shell now supports Passing DIMX Arrays to functions/procedures by reference.