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.
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:
[ 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 ] } } |
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 the following table.
Invocation type | Default mode |
---|---|
Procedure | INPUT |
User-defined function | Uses the mode defined for the corresponding parameter in the function prototype. For more information on defining prototypes for user-defined functions, see the FUNCTION statement reference entry. |
Method of a class or class constructor | Uses the mode defined for the corresponding
parameter in the method or constructor prototype, depending on overloading
requirements. For more information on defining prototypes for class-based
methods and constructors, see the METHOD statement and CONSTRUCTOR statement reference
entries. 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. |
Publish( ) event method | Uses the mode defined for the corresponding parameter in the class event definition. For more information on defining class events, see the DEFINE EVENT statement reference entry. |
When identifying the parameter mode for a .NET method or constructor, each .NET language uses its own keyword syntax to identify it. The following table 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.
ABL parameter mode | Corresponding C# syntax |
---|---|
INPUT parm | parm |
OUTPUT parm | out parm |
INPUT-OUTPUT 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.
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 the following table, where the arrow ( —>) indicates the direction that a value can be passed for the parameter.
Narrower —> Wider | ||
---|---|---|
CHARACTER | – | LONGCHAR |
INTEGER | INT64 | DECIMAL |
DATE | DATETIME | DATETIME-TZ |
Thus, ABL supports the widening of data types in the direction that the parameter is defined, according to its mode:
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. The following table shows the possible combinations.
The following parameter data type . . . | In this routine type . . . | Can take these arguments (parm) . . . |
---|---|---|
.NET mapped data type1 | .NET routine2 | The same .NET data type (for example, a .NET property), any corresponding ABL primitive type (as shown in Table 43), and on OUTPUT only, a System.Object4 |
.NET mapped data type5 | ABL method that overrides or implements a .NET method | Any compatible ABL primitive type or any compatible .NET mapped data type (for example, a .NET property) as shown in Table 43,6 |
.NET array | .NET routine | A compatible .NET or ABL array type7, 8, and on OUTPUT only, a System.Array, System.Object, or Progress.Lang.Object |
.NET array | ABL routine9, 10 | A compatible .NET array type8,, 11and on OUTPUT only, a System.Array, System.Object, or Progress.Lang.Object, |
System.Array | .NET routine | 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 |
System.Array | ABL routine9, 10 | On INPUT, any .NET array object type11, and on OUTPUT only, a System.Array, System.Object, or Progress.Lang.Object |
System.Object | .NET routine | 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 |
System.Object | ABL routine9, 10 | On INPUT, any .NET object type11, and on OUTPUT only, a System.Object or Progress.Lang.Object |
Any .NET object type (except those in the previous rows) | .NET routine | Any compatible .NET object type, and on OUTPUT only, a System.Object or a Progress.Lang.Object |
Any .NET object type (except those in the previous rows) | ABL routine9, 10 | Any compatible .NET object type, and on OUTPUT only, a System.Object or a Progress.Lang.Object |
ABL primitive type5 | ABL routine (always)9 | Any compatible ABL primitive type or any compatible .NET mapped data type (for example, a .NET property) as shown in Table 43,6 |
ABL array | ABL routine (always)9 | A compatible ABL array type6 |
Progress.Lang.Object | ABL routine (always)9 | On INPUT only, any ABL object and any supported .NET object type except a .NET mapped data type4 |
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 5 in the Data types reference entry.
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.
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.
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.
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.
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.
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.
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.
The following table 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 4 for a more complete description of these limitations.)
.NET parameter object type | C# parameter primitive type | ABL implicit mapping data type | ABL INPUT widening data type |
---|---|---|---|
System.DateTime | N/A | DATETIME | DATE |
System.Decimal | decimal | DECIMAL | INTEGER, INT64 |
System.UInt32 | uint | INT64 | INTEGER13 |
System.Int64 | long | INT64 | INTEGER |
System.UInt64 | ulong | DECIMAL | INTEGER13, INT6413 |
System.Double | double | DECIMAL | INTEGER, INT64 |
System.Single | float | DECIMAL | INTEGER14, INT6414 |
The following table 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 4 for a more complete description of these limitations.)
.NET parameter object type | C# parameter primitive type | ABL implicit mapping data type | ABL OUTPUT widening data type |
---|---|---|---|
System.Byte | byte | INTEGER | INT64, DECIMAL |
System.SByte | sbyte | INTEGER | INT64, DECIMAL |
System.Char | char | CHARACTER | LONGCHAR |
System.DateTime | N/A | DATETIME | DATETIME-TZ |
System.Int16 | short | INTEGER | INT64, DECIMAL |
System.UInt16 | ushort | INTEGER | INT64, DECIMAL |
System.Int32 | int | INTEGER | INT64, DECIMAL |
System.UInt32 | uint | INT64 | DECIMAL |
System.Int64 | long | INT64 | DECIMAL |
For more information on passing class-based objects as parameters between an OpenEdge application server and an ABL client, see the Progress Application Server for OpenEdge: Application Migration and Development Guide or OpenEdge Application Server: Developing AppServer Applications.
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.