Previous Next

Parameter passing syntax
Specifies one or more parameters to pass during invocation of an ABL procedure, a user-defined function, a method of a class (ABL or .NET), a class constructor (ABL or .NET), or the built-in Publish( ) event method or PUBLISH statement to publish class or named events, respectively.
Syntax 
 
( parameter [ , parameter ] ... )
The parameters specified by parameter must match in number and order, according to mode and data type, as required by the given procedure, user-defined function, method, or constructor definition. Use the following syntax to specify each parameter:
 
Syntax 
[ INPUT | OUTPUT | INPUT-OUTPUT ]
{   parm [ AS data-type ]
  | { {   TABLE temp-table-name 
         | TABLE-HANDLE temp-table-handle 
         | DATASET dataset-name 
         | DATASET-HANDLE dataset-handle 
        } [ APPEND ] [ BY-VALUE | BY-REFERENCE | BIND ] 
     }
}
 
BUFFER buffer 
[ INPUT | OUTPUT | INPUT-OUTPUT ]
Specifies the parameter mode. For more information on parameter modes, see the reference entries for the DEFINE PARAMETER statement (for procedures) and the Parameter definition syntax (for user-defined functions, methods, and class events).
Note that for methods and constructors, the parameter mode is optional except for certain overloading conditions. Thus, the default mode depends on the type of invocation, as described in Table 50.
 
If the method is overloaded by a given parameter only by mode, you must specify the mode for this parameter in the method call. If you do not do so, ABL raises a compile-time ambiguity error. For example, if a method is overloaded twice by an INTEGER parameter, and the parameter for one method definition has the INPUT mode while the parameter for the other method definition has the OUTPUT mode, you must specify the INPUT keyword if you intend to use the method defined with the INPUT parameter.
When identifying the parameter mode for a .NET method or constructor, each .NET language uses its own keyword syntax to identify it. Table 51 shows the C# parameter syntax that corresponds to an ABL parameter specified with a given mode. Note that in C#, the default (no keyword) corresponds to the ABL INPUT mode.
 
INPUT parm
OUTPUT parm
out parm
ref parm
Also note, as with ABL class-based methods, the default parameter passing modes for calling .NET methods and constructors are based on the parameter passing modes defined for the method or constructor prototypes, depending on overloading. Thus, you must specify the parameter passing mode for each affected parameter if the method is overloaded only by a given parameter’s mode.
parm
Specifies the argument passed to the parameter. This can be either an ABL data element or Expression, or a .NET data element, depending on the parameter mode. For an INPUT parameter, parm can be an Expression. For an OUTPUT or INPUT-OUTPUT parameter, parm can be any of the elements defined for the left side of an Assignment (=) statement. For an INPUT-OUTPUT parameter, any property argument must be both writable and readable.
Note:
For procedures, the data type of parm must be compatible with the data type defined for the parameter. Procedures allow the matching of a wide variety of different data types between the passed parameter and the parameter definition. When it can, the AVM converts the passed value from the source data type to an appropriate value in the destination data type, depending on the direction (parameter mode) of the passed value. For procedures, the AVM checks data type matching and appropriate overflow conditions at run time.
For user-defined functions, methods of a class, class constructors, and the Publish( ) event method, the data types of the passed parameter and the parameter definition are validated by the AVM at compile time and must match exactly, unless they have a widening relationship.
The AVM implicitly converts passed parameter values of certain data types from a narrow data type in the source to a widened data type in the destination, depending on the parameter mode. A widened data type is one that can hold all the values of a narrower data type without loss of data. Widening is supported for three related sets of data types, as shown in Table 52, where the arrow () indicates the direction that a value can be passed for the parameter.
 
Narrower Wider
Thus, ABL supports the widening of data types in the direction that the parameter is defined, according to its mode:
*
INPUT parameters — The data type of the passed parameter can be narrower than the defined parameter.
*
OUTPUT parameters — The data type of the passed parameter can be wider than the defined parameter.
*
INPUT-OUTPUT parameters — Widening is not supported. Because values are passed in both directions, the data type of the passed parameter must exactly match the data type of the defined parameter.
For .NET method parameters, ABL also supports widening relationships between ABL and some .NET data types. For more information, see the notes of this reference entry.
For a parm that involves .NET data types, either as the parameter definition or as the argument, the requirements for parameter passing depend on the parameter and argument data types and the type of routine that defines the parameter. Table 53 shows the possible combinations.
Note:
Table 53 refers to .NET value types, .NET mapped data types, .NET arrays of mapped types, boxing, and unboxing. Boxing and unboxing refer to a .NET mechanism for converting between .NET value types and .NET object types. ABL supports a similar mechanism for converting between ABL primitive or array types and a .NET System.Object or compatible array object type. For more information on .NET data types, concepts, and compatibility, see the Data types reference entry.
 
.NET mapped data type1
.NET routine2
.NET mapped data type5
A compatible .NET or ABL array type7,8, and on OUTPUT only, a System.Array, System.Object, or Progress.Lang.Object
ABL routine9,10
A compatible .NET array type8,11, and on OUTPUT only, a System.Array, System.Object, or Progress.Lang.Object
On INPUT, any .NET array object type or compatible ABL array type12, and on OUTPUT only, a System.Array, System.Object, or Progress.Lang.Object
On INPUT, any .NET array object type11, and on OUTPUT only, a System.Array, System.Object, or Progress.Lang.Object
On INPUT, any .NET object type, an ABL primitive type, or compatible ABL array type12, and on OUTPUT only, a System.Object or Progress.Lang.Object
On INPUT, any .NET object type11, and on OUTPUT only, a System.Object or Progress.Lang.Object
Any compatible .NET object type, and on OUTPUT only, a System.Object or a Progress.Lang.Object
Any compatible .NET object type, and on OUTPUT only, a System.Object or a Progress.Lang.Object

1
A .NET mapped data type is any .NET primitive or object type that ABL maps implicitly to an ABL primitive type. For more information, see the Data types reference entry and Table 24.

2
A .NET routine can be a .NET method or constructor.

3
For an ABL or .NET method, the parameter and argument data types must match exactly or map according to the widening rules of the target (on INPUT or OUTPUT) described in this entry. Also note that you cannot pass a System.Object on INPUT to a primitive parameter, because it is a typical narrowing case.

4
You cannot pass parameters where a Progress.Lang.Object is exchanged with a .NET mapped data type, because ABL does not do intermediate boxing or unboxing to a System.Object in order to exchange the value with a Progress.Lang.Object. However, you can pass parameters, exchanging a Progress.Lang.Object with a System.Object (with casting, as appropriate).

5
For an ABL routine, you cannot define parameters (or any data elements) directly as a .NET mapped data type (such as, System.Int32). To define parameters that take a .NET mapped type as an argument, you must use the matching ABL primitive type, as shown in Table 24 (such as, INTEGER). However, if an ABL method overrides a .NET method or implements a method of a .NET interface, you must define any .NET parameter that is a .NET mapped type using an ABL keyword (AS data type) that explicitly indicates this .NET type. Also note that this parameter functions at run time as its matching ABL primitive type, not the mapped type as defined by .NET. For more information, see the Parameter definition syntax reference entry.

6
ABL does not automatically box or unbox the value of a .NET System.Object or array object argument passed to a compatible ABL primitive or array parameter of an ABL routine. Also note that you cannot provide a Progress.Lang.Object argument to this parameter on OUTPUT, because an ABL primitive or array, even one with object type elements, is not an object itself and ABL does no boxing to a Progress.Lang.Object.

7
For an INPUT .NET array parameter of mapped type elements, because ABL does not have a unique primitive type to match each .NET mapped data type, ABL allows you to box any ABL array whose element type implicitly maps to the elements of the target .NET array, as shown in Table 24. For example, if the parameter is defined as a .NET "System.Int16[]" array object type, you can pass another "System.Int16[]" or an ABL INTEGER array to box, but you cannot pass an ABL INT64 array to box. On INPUT, you also cannot pass an ABL primitive array to a "System.Object[]" parameter, because ABL does not do automatic boxing at the element level of an array object.

8
If the parameter is defined as a .NET value type array (such as, "System.Drawing.Size[]"), the argument must be an identical .NET or ABL array type (such as "System.Drawing.Size[]" or System.Drawing.Size EXTENT). Also, while an INPUT System.Array parameter can take any appropriate .NET or ABL array argument, an INPUT "System.Object[]" parameter cannot take any ABL array (for .NET methods) or .NET array argument whose element type is an ABL primitive or .NET value type.

9
An ABL routine can be an ABL method, constructor, procedure, or user-defined function.

10
This includes any ABL method that overrides a .NET method or implements a method of a .NET interface.

11
ABL does not automatically box or unbox a compatible ABL primitive or array data type passed to a corresponding .NET System.Object or array object parameter of an ABL routine. On INPUT, you can pass an ABL BOX function call taking a compatible ABL primitive or array type as input. On OUTPUT, you can provide a System.Object or compatible .NET array object argument and then convert it to an ABL primitive or array type by assigning or using the UNBOX function.

12
For a .NET method with an ABL primitive type argument: on INPUT, the AVM boxes the argument value into the default matching .NET object type. With a compatible ABL array argument: on INPUT, the AVM boxes the argument as the corresponding .NET array type.

AS data-type
Indicates an explicit mapping between an argument with an ABL primitive type and the parameter of a .NET method or constructor. Assuming that the .NET data type defined for the parameter is compatible with the data type of the ABL argument, data-type represents an ABL keyword (AS data type) that indicates an alternative .NET data type mapping to identify with the .NET parameter. This option is necessary in the following cases:
*
Note:
*
The parameter is defined as a System.Object, and you want the .NET value of the passed ABL primitive type to be stored as a .NET mapped data type that is not the default match. For example, you might want the System.Object parameter to store an ABL INTEGER value as a System.Int16 instead of as a System.Int32 (the default match).
For the a list of available keywords that you can specify for data-type, as well as the default matches for ABL primitive types with multiple .NET data type mappings, see Table 25 in the Data types reference entry.
Note:
The AS data types in Table 25 represent some different data types than you can specify using the AS option to pass a COM method parameter. For more information on passing COM method parameters, see the “Syntax for accessing COM object properties and methods” section.
TABLE temp-table-name
Specifies the name of a static temp-table.
This parameter type can match at compile time with any TABLE parameter with the same schema, or any TABLE-HANDLE parameter. If the matching type is TABLE-HANDLE, a run-time check occurs if the TABLE-HANDLE is not the Unknown value (?) in order to ensure that the run-time schemas match. A parameter of a user-defined function or method of a class is verified at compile time, while a parameter of a procedure is verified at run time.
TABLE-HANDLE temp-table-handle
Specifies a handle to a temp-table. Use a temp-table handle as a parameter for a dynamic temp-table. The full schema definition behind the handle and the contents of the temp-table are passed unless the temp-table SCHEMA-MARSHAL attribute is set to minimize or prevent schema marshalling.
This parameter type can match at compile time with any TABLE or TABLE-HANDLE parameter. If the matching type is TABLE-HANDLE, a run-time check occurs if the TABLE-HANDLE is not the Unknown value (?) in order to ensure that the run-time schemas match. A parameter of a user-defined function or method of a class is verified at compile time, while a parameter of a procedure is verified at run time.
DATASET dataset-name
Specifies the name of a static ProDataSet.
This parameter type can match at compile time with any DATASET parameter with the same schema, or any DATASET-HANDLE parameter. If the matching type is DATASET-HANDLE, a run-time check occurs if the DATASET-HANDLE is not the Unknown value (?) in order to ensure that the run-time schemas match. A parameter of a user-defined function or method of a class is verified at compile time, while a parameter of a procedure is verified at run time.
DATASET-HANDLE dataset-handle
Specifies a handle to a ProDataSet. Use a ProDataSet object handle as a parameter for a dynamic ProDataSet. The full schema definition behind the handle and the contents of the ProDataSet object are passed unless the SCHEMA-MARSHAL attribute for one or more of its temp-tables are set to minimize or prevent schema marshalling.
This parameter type can match at compile time with any DATASET or DATASET-HANDLE parameter. If the matching type is DATASET-HANDLE, a run-time check occurs if the DATASET-HANDLE is not the Unknown value (?) in order to ensure that the run-time schemas match. A parameter of a user-defined function or method of a class is verified at compile time, while a parameter of a procedure is verified at run time.
BUFFER buffer
Specifies the name of a buffer.
APPEND
Specifies whether or not to append the source temp-table data to the destination temp-table data. To append OUTPUT parameter data, specify the APPEND option for the parameter in the routine call. To append INPUT parameter data, specify the APPEND option for the parameter in the routine definition.
BY-VALUE | BY-REFERENCE | BIND
Specifies whether to pass a TABLE, TABLE-HANDLE, DATASET, or DATASET-HANDLE parameter by value, by reference, or by binding. The default is BY-VALUE.
You can pass TABLE, TABLE-HANDLE, DATASET, and DATASET-HANDLE parameters to both local and remote procedures. These parameter types are normally passed by value, by default. That is, the calling routine and the called routine each have their own instance of the object, and the parameter is deep-copied from the calling routine’s instance to the called routine’s instance.
When passing one of these parameters to a local routine, you can override the default in the calling routine by specifying the BY-REFERENCE or BIND option.
Passing one of these parameters to a local routine using the BY-REFERENCE option allows the calling routine and the called routine to access the same object instance. That is, both routines access the calling routine’s instance and ignore the called routine’s instance. Since the called routine’s object instance is ignored, you should define the static object as reference-only by specifying the REFERENCE-ONLY option in the DEFINE statement for the object.
Passing one of these parameters to a local routine using the BIND option allows the calling routine and the called routine to access the same object instance. You can do this by:
*
*
In the static case, you must define a reference-only object in either the calling routine or the called routine by specifying the REFERENCE-ONLY option in the DEFINE statement for the object. You must also define the parameter by specifying the BIND option in the parameter definition.
When you define a reference-only object in the calling routine and pass it to the called routine using the BIND option, the AVM binds the definition of the object in the calling routine to the object instance in the called routine. When you define a reference-only object in the called routine and receive the object from the calling routine, the AVM binds the definition of the object in the called routine to the object instance in the calling routine. In either case, the reference-only object definition remains bound to the object instance until the routine containing the reference-only object definition is deleted or terminates.
Caution:
You can bind multiple reference-only object definitions to the same object instance. You can also bind a single reference-only object definition to the same object instance multiple times without generating an error. However, you cannot bind a single reference-only object definition to multiple object instances.
When passing one of these parameters to a remote procedure, the AVM ignores the BY-REFERENCE and BIND options and deep-copies the parameter based on the specified parameter mode.
Examples 
The following two code fragments show how the AS data type works when calling an overloaded .NET method, in this case the System.Math:Max( ) method. This static .NET method compares two values of the same data type and returns the largest of the two. The first fragment compiles and runs. It compares the value 50, passed as a System.Byte (specified by the AS data type, UNSIGNED-BYTE), with the maximum value of a System.Byte, returned by the System.Byte:MaxValue data member. The result returned by the Max( ) method is 255, the maximum System.Byte value:
 
DEFINE VARIABLE iVal1   AS INTEGER NO-UNDO INITIAL 50.
DEFINE VARIABLE iVal2   AS INTEGER NO-UNDO.
DEFINE VARIABLE iReturn AS INTEGER NO-UNDO.
 
iVal2 = System.Byte:MaxValue.
iReturn = System.Math:Max( INPUT iVal1 AS UNSIGNED-BYTE, 
                           INPUT iVal2 AS UNSIGNED-BYTE ).
The second fragment compiles, but returns a run-time error. Again, it passes the same two values to the System.Math:Max( ) method, but this time passes them as a System.SByte (specified by the AS data type, BYTE). A signed byte parameter cannot hold positive values as large as an unsigned byte. So, passing the maximum value of a System.Byte (unsigned byte) as a System.SByte (signed byte) causes the Max( ) method to raise a run-time overflow error:
 
DEFINE VARIABLE iVal1   AS INTEGER NO-UNDO INITIAL 50.
DEFINE VARIABLE iVal2   AS INTEGER NO-UNDO.
DEFINE VARIABLE iReturn AS INTEGER NO-UNDO.
 
iVal2 = System.Byte:MaxValue.
iReturn = System.Math:Max( INPUT iVal1 AS BYTE, 
                           INPUT iVal2 AS BYTE ). /* Run-time error */
The following code fragment shows an example of ABL data type widening when passing parameters to a .NET method. This example shows INPUT widening, in this case, passing different ABL data types (INTEGER and INT64) that are acceptable as arguments to a System.Double input parameter:
 
DEFINE VARIABLE i4Val  AS INTEGER NO-UNDO.
DEFINE VARIABLE i8Val  AS INT64   NO-UNDO.
DEFINE VARIABLE iRoot1 AS DECIMAL NO-UNDO.
DEFINE VARIABLE iRoot2 AS DECIMAL NO-UNDO.
 
ASSIGN
  i4Val  = System.Int32:MaxValue
  i8Val  = System.Int64:MaxValue
  iRoot1 = System.Math:Sqrt( INPUT i4Val )
  iRoot2 = System.Math:Sqrt( INPUT i8Val ).
For more information on data type widening, see the Notes section later in this reference entry.
Notes 
*
*
*
When you call the Publish( ) event method to publish a class event, or when you execute the PUBLISH statement to publish a named event, any parameters are passed to every event handler that is subscribed to the event. However, any parameter values returned from the Publish( ) method or PUBLISH statement reflect the settings of the last event handler to execute. Therefore, when you publish a class or named event, the value returned for an OUTPUT or INPUT-OUTPUT parameter, or for a member of any object (class or handle-based) referenced in an INPUT parameter, depends on the execution order of the event handlers subscribed to the event, which is not guaranteed. In addition, for INPUT-OUTPUT parameters or for members of objects referenced by INPUT parameters, the values returned from each event handler are used as input to the next event handler that executes.
Caution:
*
*
When you instantiate a class dynamically, using the DYNAMIC-NEW statement, ABL distinguishes overloaded constructors only by the number of parameters.
*
*
*
Table 54 lists the .NET parameter data types for which ABL supports the widening of ABL data types passed as INPUT arguments. For each .NET parameter data type, the listed ABL implicit mapping data type represents the closest matching ABL data type that you can pass to a .NET input parameter defined with the matching .NET data type. The corresponding listed ABL INPUT widening data types can hold smaller values that might also be acceptable to the .NET input parameter. However, they might also adhere to similar limitations as defined for passing values as the listed ABL implicit mapping data type. (Again, see Table 24 for a more complete description of these limitations.)
 
System.DateTime
System.Decimal
decimal
System.UInt32
uint
INTEGER1
System.Int64
long
System.UInt64
ulong
INTEGER1, INT641
System.Double
double
System.Single
float
INTEGER2, INT642

1
If you pass a negative ABL data type to an unsigned data type, the ABL virtual machine (AVM) raises a run-time error.

2
You can lose precision if you pass an ABL INTEGER or INT64 to a System.Single parameter.

*
Table 55 lists the .NET parameter data types for which ABL supports the widening of ABL data types passed as OUTPUT arguments. For each .NET parameter data type, the listed ABL implicit mapping data type represents the closest matching ABL data type that can hold a .NET value passed to the OUTPUT parameter defined with the matching .NET data type. The corresponding listed ABL OUTPUT widening data types might hold even larger values than the listed ABL implicit mapping data type. However, but they might also adhere to similar limitations as defined for the listed ABL implicit mapping data type (Again, see Table 24 for a more complete description of these limitations.)
 
System.Byte
byte
System.SByte
sbyte
System.Char
char
System.DateTime
System.Int16
short
System.UInt16
ushort
System.Int32
int
System.UInt32
uint
System.Int64
long
*
*
*
*
*
*
*
*
If you call a remote procedure asynchronously and pass a parameter as OUTPUT TABLE-HANDLE temp-table-handle APPEND, the event procedure must specify a corresponding DEFINE INPUT PARAMETER TABLE-HANDLE FOR temp-table-handle APPEND statement, and temp-table-handle must be global to both the calling procedure and the event procedure.
*
If you pass a TABLE parameter to a similarly overloaded method or constructor, the AVM executes the method or constructor with a matching TABLE parameter definition. If the AVM cannot identify a method or constructor with a matching TABLE parameter definition, it executes the method or constructor with the corresponding TABLE-HANDLE parameter definition.
If the AVM cannot locate a method or constructor whose temp-table parameter definitions match the corresponding TABLE-HANDLE or TABLE parameter, the AVM raises a run-time error identifying the ambiguity.
*
If you pass a DATASET parameter to a similarly overloaded method or constructor, the AVM executes the method or constructor with a matching DATASET parameter definition. If the AVM cannot identify a method or constructor with a matching DATASET parameter definition, it executes the method or constructor with the corresponding DATASET-HANDLE parameter definition.
If the AVM cannot locate a method or constructor whose ProDataSet parameter definitions match the corresponding DATASET-HANDLE or DATASET parameter, the AVM raises a run-time error identifying the ambiguity.
*
*
*
If you pass the Unknown value (?) to a parameter of an overloaded method or constructor, the AVM only selects the correct method or constructor to execute when passing the Unknown value (?) causes no ambiguity among them. Otherwise, the AVM generates a compile-time error for ambiguity.
*
*
You can avoid compile-time ambiguity errors when passing the Unknown value (?) or an expression of an unknown data type in one of two ways:
*
Convert the Unknown value (?) or expression to a specific data type using the appropriate ABL data type conversion function to pass the value.
*
Assign the Unknown value (?) or expression to a variable of a specific data type to pass the value.
*
If you pass a method of a class as a parameter to another method, constructor, procedure, or user-defined function that you invoke, and the method parameter executes the RETURN statement with the ERROR option, the method, constructor, procedure, or user-defined function that you invoke does not run. The AVM then raises ERROR on the invoked method, constructor, or procedure. The AVM does not raise ERROR on an invoked user-defined function.
See also 
Assignment (=) statement, Expression, FUNCTION statement, NEW function (classes), Publish( ) event method, PUBLISH statement, RUN statement, RUN SUPER statement, SUPER statement, SUPER system reference, THIS-OBJECT statement

Previous Next
© 2013 Progress Software Corporation and/or its subsidiaries or affiliates.