Parameter Passing¶
Approach¶
INPUT Parameters¶
INPUT-OUTPUT and OUTPUT Parameters¶
Function or procedure parameters can be modified in the called code. If the parameter has INPUT-OUTPUT
or OUTPUT
type, any modifications will be visible by the calling code.
Primitives cannot be directly used since in Java there is no such thing as a reference to a primitive. That means that the modifications of primitives passed as parameters cannot be seen by the calling code.
Java object wrappers cannot be used directly since they are immutable. This means that the content of the object passed by reference to a Java object wrapper (e.g. Integer
) cannot be modified in the called code. The called code can assign the reference to another object, but as that reference is passed by value in Java, this does not affect the reference in the calling code.
The solution is to create mutable FWD wrapper classes for each data type.
ASSIGN Database Trigger Parameter¶
A database trigger that is invoked when the associated field is assigned, passing the old field's value as a named parameter. Specified as a TRIGGER PROCEDURE
or in an ON
statement.
TBD
Constructor Parameter¶
Object-oriented 4GL extensions allow class definitions. Class definitions may contain a CONSTRUCTOR
statement (a special method called to create a new instance of the object). Parameters to the constructor are local variables that are scoped to that method.
DEFINE PARAMETER¶
This statement specifies a parameter for an external procedure or internal procedure. This statement determines the data type, mode and ordinal position in the procedure's signature. In particular, the ordinal position is determined by the order of the DEFINE PARAMETER
statements, where the 1st DEFINE PARAMETER
statement in the procedure is the 1st parameter and so forth. To invoke the procedure, the corresponding parameter(s) must be specified in the RUN statement (with the same type, mode and order as defined in the procedure itself).
At a high level, Progress 4GL has 7 main forms of this statement. The following summarizes FWD support for these forms:
Form | Description | Supported | Notes |
---|---|---|---|
DEFINE <mode> PARAMETER <parm_name> { AS | LIKE } <primitive_type> [variable_options]. |
Defines a parameter in which the caller will pass a reference to a variable (INPUT-OUTPUT or OUTPUT mode) or a value of an expression (@INPUT* mode). |
Yes | The following are NOT supported: • DLL and UNIX shared library access ( RETURN mode, data types)• data types which are not yet supported by FWD (see the Variables section of this chapter) • EXTENT (array) parameters• ActiveX control event procedures |
DEFINE <mode> PARAMETER <parm_name> AS [CLASS] <class_name> [EXTENT <num_elements>]. |
Defines a parameter that is an instance of the specified class. | No | |
DEFINE PARAMETER BUFFER <buffername> FOR [TEMP-TABLE] <table> [PRESELECT]. |
Defines a parameter in which the caller will pass a reference to a buffer (always INPUT-OUTPUT mode) that accesses a temp-table or database table. |
Yes | See Part 5 of this book for details. |
DEFINE <mode> PARAMETER TABLE FOR <temp_table_name> [table_options]. |
Defines a parameter in which the caller will pass a temp-table by reference or by value. | Yes | See Part 5 of this book for details. |
DEFINE <mode> PARAMETER TABLE-HANDLE <temp_table_handle> [table_options]. |
Defines a parameter in which the caller will pass a handle to a temp-table. | No | See Part 5 of this book for details. |
DEFINE <mode> PARAMETER DATASET FOR <dataset_name> [table_options]. |
Defines a parameter in which the caller will pass a Pro-Dataset by reference or by value. | No | See Part 5 of this book for details. |
DEFINE <mode> PARAMETER DATASET-HANDLE <dataset_handle> [table_options]. |
Defines a parameter in which the caller will pass a handle to a Pro-Dataset. | No | See Part 5 of this book for details. |
This section of the book will only describe how the common or "variable" form of this statement is converted. When the CLASS
form is supported, this section will also describe that support. All other forms are database-related and thus are described in Part 5 of this book.
The supported modes are INPUT
, INPUT-OUTPUT
and OUTPUT
. RETURN
is not supported (in Progress 4GL it is only used for DLL access and FWD does not provide DLL access yet). All data types which are supported in FWD as variables can be used as parameter types. The use of both AS and LIKE are supported.
The following is a simple 4GL example showing parameters of each supported mode type and the core options:
define input parameter txt1 as character. define input-output parameter num2 as integer. define output parameter dat3 as date. define input parameter txt4 as character case-sensitive. define input-output parameter dec5 as decimal decimals 2 no-undo. define output parameter log6 as logical initial true.
If this code is in an external procedure, the resulting Java code will look like this (the comments have been added by hand to make it easier to understand):
public void execute(final character _txt1, final integer num2, final date dat3, final character _txt4, final decimal dec5, final logical log6) { externalProcedure(new Block() { // these member variables are copies of input parameters that were passed in, any edits // will not be "visible" in the calling code character txt1 = new character(_txt1); character txt4 = new character(_txt4); public void init() { // all parameters are UNDO by default; each undoable variable must be registered here // and all NO-UNDO variables must be excluded TransactionManager.register(txt1, num2, dat3, txt4, log6); // output parameters must be initialized to their default value or to the value given // in an initializer option (for date variables the default is the unknown value) dat3.assign(date.instantiateUnknownDate()); log6.assign(new logical(true)); // options other than initializers txt4.setCaseSensitive(true); dec5.setPrecision(2); // any INPUT-OUTPUT or OUTPUT parameters that are NO-UNDO will be configured here TransactionManager.deregister(new Undoable[] { dec5 }); } public void body() { // all parameters can be accessed here by name as needed } }); }
Parameters are emitted the same way for both internal procedures and external procedures. The above example is of an external procedure, but for an internal procedure, only the method name would be different (instead of execute()
it would be named a valid Java name based on the 4GL internal procedure name) and the externalProcedure()
call would be changed to an internalProcedure()
call.
All parameters are final
. Since the replacement for 4GL assignment in FWD calls a method (usually BaseDataType.assign()
), there are no conditions in which a named parameter reference must be assigned a different reference using the Java assignment operator (=
). This means that final
can be used for all parameters. The primary requirement for doing this is to allow all inner classes to be able to directly refer to these parameters. Since all the 4GL block behavior is implemented using anonymous inner classes, this simplifies the resulting code.
Each data type will be directly mapped from the 4GL type to the FWD replacement type.
The FWD conversion uses its 4GL to Java name conversion routines to create a unique Java variable name for each parameter, based on the original 4GL parameter name. All references to that parameter will likewise use that same converted name. For details on how parameter names convert, please see the Naming section of the Other Customization chapter of the FWD Conversion Handbook. Parameter naming works the same as variable naming.
INPUT-OUTPUT
and OUTPUT
parameters must by nature be shared references with the calling code. This means that the converted code will directly use the reference passed in as a parameter. These parameter references will use the same Java name as is named in the method signature for the internal or external procedure.
INPUT
parameters must by nature be a one-way transfer of data from the caller to the called code. This means that the called code cannot directly refer to the same reference as is given in the method signature. Just as in Java, in the 4GL it is valid to modify an INPUT
parameter. This means that the called code must have its own local copy of the parameter so that changes are not visible in any reference provided by the caller. To achieve this, the parameter name in the method signature will be the converted Java name prefixed by an underscore (_
) character. In the above example, the 4GL INPUT
parameter txt1
is named _txt1
in the method signature. Then inside the anonymous inner class (see new Block() { … }
above), there will be a "properly" named member variable of the same type. This is the local copy of the INPUT
parameter which can be directly referenced by the converted code. Each local copy is initialized from the matching parameter passed in. So in this example, txt1
is initialized from the _txt1
passed in reference. Since the local copy is a member of the anonymous inner class, it effectively has the same scope as the rest of the parameters.
All other options and initialization code will emit inside the Block.init()
method. This is a method that is only called once, it is never executed again (even during the equivalent of a 4GL "retry") and it is called before the Block.body()
is executed. This makes it perfect for initialization code.
All procedure parameters are enabled for UNDO
by default (in FWD terms they are "undoable"). All undoable parameters will be listed in a TransactionManager.register()
method call (it takes a variable argument list) and any NO-UNDO
parameters will be excluded from that call.
INPUT-OUTPUT
and OUTPUT
parameters can optionally be specified as NO-UNDO
. The NO-UNDO
parameters will be passed in an Undoable[]
to TransactionManager.deregister()
. The reason this is necessary is that by definition, INPUT-OUTPUT
and OUTPUT
parameters already exist in a block somewhere in the calling code. This means that they may already be registered for UNDO
support in the calling code. To properly implement NO-UNDO
, it is necessary to de-register those instances from the UNDO
lists for the called code, while leaving the UNDO
lists for the calling code unchanged. This is why it is not enough to just avoid the register() method call.
Any initialization for parameters (using the INITIAL
option) will be emitted in the init()
method. These initializers will emit as assign()
method calls using the literals specified in the INITIAL
option. Since OUTPUT
parameters must also have a default value assigned, if there is no explicit INITIAL
option, any OUTPUT
parameter will be initialized to its default value. For all variable types (except date
), the default value is implemented by the default constructor for the wrapper class. For date
, the default constructor creates an instance with today's date (the same as the TODAY
built-in function). But since the 4GL date
instance will default to unknown value, to properly initialize it, the date.instantiateUnknownDate()
static method is used. INPUT
and INPUT-OUTPUT
parameters are not initialized unless there is an explicit INITIAL
option.
User-interface specific options are removed from the replacement business logic but their settings will be honored in any frames or user-interface processing that reference that parameter.
Other options that are supported are CASE-SENSITIVE
, NOT CASE-SENSITIVE
and DECIMALS
. These options are set into the parameter instances in the init()
method, just as described in the section below entitled Data Type Options.
Options summary:
Option | Description | Supported | Notes |
---|---|---|---|
CASE-SENSITIVE |
The character parameter will be compared and sorted on a case-sensitive basis. | Yes | See Data Type Options below. |
COLUMN-LABEL |
When this parameter is used as a widget in a frame, this defines the descriptive text column label for the widget. | Yes | See Part 6 of this book. |
DECIMALS |
Sets the number of digits to the right of the decimal point for this decimal parameter. | Yes | See Data Type Options below. |
EXTENT |
Defines an array parameter with a specific number of elements. | No | See Data Type Options below. |
FORMAT |
Specifies the pattern used to format the output of this parameter when used as a widget in a frame. | Yes | See Part 6 of this book. |
INITIAL |
Defines an explicit initial value for the parameter. | Yes | See Data Type Options below. |
LABEL |
When this parameter is used as a widget in a frame, this defines the descriptive text label for the widget. | Yes | See Part 6 of this book. |
NO-UNDO |
UNDO support is disabled for the parameter. | Yes | See UNDO below. |
NOT CASE-SENSITIVE |
The character parameter will be compared and sorted on a case-insensitive basis. | Yes | See Data Type Options below. |
Function Parameter¶
This statement specifies a parameter for a user-defined function. This statement determines the data type, mode and ordinal position in the function's signature. In particular, the ordinal position is determined by the order of the parameters listed in the FUNCTION
statement. To invoke the function, the corresponding parameter(s) must be specified in the function call (with the same type, mode and order as defined in the FUNCTION
statement itself).
At a high level, Progress 4GL has 7 main forms of this statement. The following summarizes FWD support for these forms:
Form | Description | Supported | Notes |
---|---|---|---|
<mode> <parm_name> AS <primitive_type> [EXTENT <num_elements>] |
Defines a parameter in which the caller will pass a reference to a variable (INPUT-OUTPUT or OUTPUT mode) or a value of an expression (INPUT mode). |
Yes | The following are NOT supported: • data types which are not yet supported by FWD (see the Variables section of this chapter) • EXTENT (array) parameters |
<mode> <parm_name> AS [CLASS] <class_name> [EXTENT <num_elements>] |
Defines a parameter that is an instance of the specified class. | No | |
BUFFER <buffername> FOR <table> [PRESELECT] |
Defines a parameter in which the caller will pass a reference to a buffer (always INPUT-OUTPUT mode) that accesses a temp-table or database table. |
Yes | See Part 5 of this book for details. |
<mode> TABLE <temp_table_name> [table_options] |
Defines a parameter in which the caller will pass a temp-table by reference or by value. | Yes | See Part 5 of this book for details. |
<mode> TABLE-HANDLE <temp_table_handle> [table_options] |
Defines a parameter in which the caller will pass a handle to a temp-table. | No | See Part 5 of this book for details. |
<mode> DATASET <dataset_name> [table_options] |
Defines a parameter in which the caller will pass a Pro-Dataset by reference or by value. | No | See Part 5 of this book for details. |
<mode> DATASET-HANDLE <dataset_handle> [table_options] |
Defines a parameter in which the caller will pass a handle to a Pro-Dataset. | No | See Part 5 of this book for details. |
This section of the book will describe how the common or "variable" form of this statement is converted. When the CLASS
form is supported, this section will also describe that conversion. All other forms are database-related and thus are described in Part 5 of this book.
The supported modes are INPUT
, INPUT-OUTPUT
and OUTPUT
. All data types which are supported in FWD as variables can be used as parameter types. The 4GL syntax and the Java converted code are very similar to that in the DEFINE PARAMETER
statement. The following is a list of the key differences (all of these match up with differences in how the 4GL works):
- All function parameters are always
NO-UNDO
. This means that function parameters are never added to theTransactionManager.register()
method call. More importantly,INPUT-OUTPUT
andOUTPUT
mode function parameters are always added to aTransactionManager.deregister()
method call to ensure that any preexistingUNDO
reference to those variables in the calling procedure is temporarily removed for the scope of the function. - There are never any options that can be specified for a function parameter.
EXTENT
is possible in later 4GL versions but is not supported yet in FWD. - Since there is no
INITIAL
option (and no alternative 4GL syntax for an explicit initializer), there is no way to set the initial value of a function parameter.OUTPUT
mode parameters do get initialized, but as in the 4GL, they are always initialized to the unknown value. - In some cases, the mode can be left unspecified in the 4GL code. Any unspecified mode is the same as an INPUT mode parameter.
The following is a 4GL example:
function example returns integer (input txt1 as character, input-output num2 as integer, output dat3 as date): return 0. end.
This is the resulting Java code:
public integer example(final character _txt1, final integer num2, final date dat3) { return integerFunction(new Block() { character txt1 = new character(_txt1); public void init() { TransactionManager.deregister(new Undoable[] { num2, dat3 }); dat3.assign(date.instantiateUnknownDate()); } public void body() { returnNormal(0); } }); }
Please see the DEFINE PARAMETER
section above for more details on why the Java code emits in this manner.
Method Parameter¶
This is part of the class support in v10 4GL. User-defined methods can be created as part of a class and each method can have a custom parameter list.
Property Setter Parameter¶
This is an optional method that can encode logic that is executed when a property is assigned (see DEFINE PROPERTY
above). There cannot be more than one parameter for this special setter method.
© 2004-2022 Golden Code Development Corporation. ALL RIGHTS RESERVED.