A parameter shares storage with its argument. As such, the storage class is ultimately determined by that of the associated argument. Technically, the parameter variable itself is an AUTOMATIC variable containing the address of the corresponding argument. For convenience, a parameter may be considered to have a distinct "parameter" storage class. For example:
DECLARE X FLOAT; CALL P (X); . . . P: PROCEDURE (Y); DECLARE Y FLOAT;
In this example, X is an argument and Y is a parameter variable. A parameter variable is declared within a procedure declaration and receives a value when that procedure is invoked. Simple Open PL/I variable arguments are passed by reference.
A parameter has a data type, perhaps a data type with extents, and in the simplest case, an argument passed to the parameter will have the same data type and extents as the parameter. If this is not the case, Open PL/I will, whenever possible, convert the argument to a value with the same data type and extents as the parameter and pass that value to the parameter.
In the absence of specifications to the contrary, when a variable is passed as an argument to a parameter with matching data type and extents, the argument is passed "by reference." This means that it is the address of the actual variable itself that is passed as the argument, and the parameter is sharing storage with this variable. Hence, any assignment to the parameter is actually changing the argument variable itself.
In other cases — that is, when the argument is a variable whose data type and extents do not match the parameter, or when the argument is an expression, a constant, a function reference, or a simple variable enclosed in parentheses — the argument is passed "by value." This means that the value of the argument is converted as described above and stored in a temporary location. It is the address of this temporary location that is passed as the argument. Hence, any assignment to the parameter can have no effect on any variable in the calling procedure.
The precision of arithmetic data is part of its data type. This means that a Float Decimal(7) variable cannot be passed by reference to anything except a Float Decimal(7) parameter. The VARYING and ALIGNED attributes, as well as the declared string length, are part of a string variable's data type and must match those of the corresponding parameter for the parameter to share storage with the actual argument (true pass-by-reference). A picture variable can be passed by reference only if the corresponding parameter has an identical picture. The ALIGNED and UNALIGNED attributes of non-string arguments and parameters must match.
The BYVALUE attribute is an argument-passing attribute that indicates that the value and not the address of the parameter has been passed to the procedure.
An array parameter with constant extents can be passed only those array arguments that have identical constant extents and an identical data type. A parameter structure can be passed only a structure or substructure of identical size, shape, and component data types. Array or structure arguments cannot be passed by value.
The ANY attribute is an argument-passing attribute that specifies, for a parameter, that the corresponding argument can be of any data type.
A procedure that has a character or bit-string parameter with a constant length may be called with string arguments of variable length or differing constant length. Since all such arguments are passed by value, they are effectively converted to the length of the parameter. For example:
CALL P(A,(B));
In this example, A is passed by reference if it matches its corresponding parameter and is passed by value if it does not. B is always passed by value.
If the argument is an expression, function reference, built-in function reference, constant, parenthetical variable reference, or a reference to a variable whose data type does not match that of the parameter, the argument is copied to a temporary block of storage in the caller's stack frame and is said to be passed by value. The value of the variable in the caller will not be modified if it is passed by value. Actually, the address of the temporary storage is passed, and the parameter shares the storage allocated to the temporary storage.
The extents of a parameter can be either integer constants or asterisks (*). If the parameter's extents are integer constants, any argument to be passed by reference must have identical constant extents. If the parameter's extents are asterisks, its corresponding argument may have extents of any value. In the latter case, the extents of the parameter are those of its corresponding argument. For example:
DECLARE A(10) FLOAT; DECLARE B(25) FLOAT; . . . CALL P(A); . . . CALL P(B); . . . P: PROCEDURE(X); DECLARE X(*) FLOAT;
During the first call in this example, the extents of X are (1:10). During the second call, they are (1:25).