Please enable JavaScript to view this site.

A-Shell Reference

Revised June 2026

Parameters in function and procedure definitions have an optional "as <typsiz>{:<mod>)" clause to declare the type, size, and modifiers for the parameter. This also applies to the return type of the Function. If no clause is specified, the default type and size follows the normal rules for ASB. The fact that you probably aren't 100% certain what those rules are should reinforce the importance of always defining the type and size explicitly. The following examples will help clarify the syntax:

Example 1

FUNCTION Fn'Test(p1 as S10, p2 as f6, p3 as B2, p4 As x256) AS i2

This illustrates the fact that although the <typsiz> clause uses the same fundamental data types as in MAP statements, here there is no comma between the type and size (e.g. "var2 as f6" instead of "map2 var2,f,6"). It also illustrates the case insensitivity of the native type codes (F, S, B, X, I) and the AS keyword.

Example 2

Function fn'display'name$(cus as ST_CUS_REC, bold as BOOLEAN) as s MAX_NAME

This shows the possibilities for using symbolic types and sizes rather than just the fundamental types and hard-coded sizes. One possibility is to use a DEFSTRUCT (i.e. "as ST_CUS_REC"). Another is to use a symbol defined via a DEFTYPE statement(i.e. "bold as BOOLEAN"). Syntactically, it's impossible to tell the difference between a defined structure name and DEFTYPE name, but the assumption here is that BOOLEAN was defined via DEFTYPE BOOLEAN = I,2.

A third possibility is to replace just the size with a symbol, e.g. "as s MAX_NAME"). In this case, a single space is required between the native variable type ("s") and the symbol name (MAX_NAME). Using a symbol rather than a hard-coded number is useful for avoiding a common bug that may happen when passing string arguments to functions, where you decide to increase the size of the string field elsewhere in the application but forget about the function, resulting in the value being truncated within the function. But the technique has largely been superseded by the DEFTYPE method, which eliminates such discrepancies both in the parameter size and its type.

For string and X parameters, another way to avoid the truncation bug just described is to use Dynamically Sized Variables within the function.

Example 3

function fn'test(p1 as s20:inputonly, p2 as ST_PHONE:outputonly)

This illustrates the use of the optional :<mod> clause to specify a modifier affecting the way the parameter is to be used. The available modifiers are inputonly and outputonly.

The inputonly modifiier serves primarily as an aid to self-documenting code, but will also cause the compiler to generate an error if you explicitly reference the parameter in an XPUTARG statement. Note, however, that there is no run-time aspect of this feature, so you won't be stopped from outputting to the parameter using a variable to specify the parameter number in the XPUTARG statement.

The outputonly modifier also aids in self-documenting your code, but in addition it skips the input parameter binding operation (which, for very large parameters could save a lot of CPU cycles).

In the absence of an inputonly or outputonly modifier, the parameter is consider input/output. Note however, that since parameter passing is, in almost all cases, by value (as opposed to by reference), there is no automatic updating of the variables passed by the caller, unless you use explicit XPUTARG statements.

Example 4

function Fn'Get'Date'Time$(dt=-1 as b4:outputonly, tm=-1 as b4:outputonly) as s40

This illustrates the use of default values (=-1) and outputonly clauses.  Without the default value, any parameter not explicitly passed by the caller,  and all outputonly parameters, would be initialized to zero or null, just like mapped variables.  Specifying a default value also has the less obvious effect of allowing the caller to ignore (i.e.not specify) particular parameters, and/or vary the parameter order, e.g.

call Fn'Get'Date'Time$(tm=TIME'NOW)

Without the default value for the dt parameter in the function declaration, the compiler would complain about the above statement missing the mandatory dt parameter. See the Named Parameters and Parameter Passing (In) topics for more about that.

Warning: the treatment of the outputonly modifier has changed over time; see the History notes below for details.

History

March 2025, A-Shell 7.0.1770.2, compiler edit 1065:  The .ARG_PASSED(@parm) status is now inherited even for outputonly parameters.  (Technically, while the caller may specify an outputonly parameter,  they aren't passed.  The intent of the .ARG_PASSED() function, despite its name,  was to allow the function to decide whether it was necessary to go to any extra effort to pass the parameter back.)

January 2025, A-Shell 7.0.1767.0, compiler edit 1054:  Introduce ++PRAGMA OVERRIDE_OUTPUTONLY (causing outputonly to revert to the behavior prior to compiler edit 1047)

November 2024, A-Shell 7.0.1756.6, compiler edit 1047:  Prior to this update, specifying a default value causing the outputonly modifier to be ignored, which also meant that the value of the parameter passed by the caller would override the default value clause.  The outputonly clause was also interfering with the ability to reference the parameter in a DYNFUNC() call.