This document discusses those object types which can be invoked as routines; that is, as subordinate programs.
Helproutines and maps, although they are also invoked from other objects, are strictly speaking not routines as such, and are therefore discussed in separate documents; see Helproutine and Map.
Basically, programs, subprograms and subroutines differ from one another in the way data can be passed between them and in their possibilities of sharing each other's data areas. Therefore, the decision which object type to use for which purpose depends very much on the data structure of your application.
This document covers the following topics:
Typically, a Natural application does not consist of a single huge program, but is split into several object modules. Each of these objects is a functional unit of manageable size, and each object is connected to the other objects of the application in a clearly defined way. This provides for a well-structured application, which makes its development and subsequent maintenance a lot easier and faster.
During the execution of a main program, other programs, subprograms, subroutines, helproutines and maps can be invoked. These objects can in turn invoke other objects (for example, a subroutine can itself invoke another subroutine). Thus, the object-oriented structure of an application can become quite complex and extend over several levels.
Each invoked object is one level below the level of the object from which it was invoked; that is, each time a subordinate object is invoked, the level number is incremented by 1.
Any program that is directly executed is at Level 1; any subprogram, subroutine, map or helproutine directly invoked by the main program is at Level 2; when such a subroutine in turn invokes another subroutine, the latter is at Level 3.
A program invoked with a FETCH statement from within
                  			 another object is classified as a main program, operating from Level 1. A
                  			 program that is invoked with FETCH RETURN, however, is classified
                  			 as a subordinate program and is assigned a level one below that of the invoking
                  			 object.
               
The following illustration is an example of multiple levels of invoked objects and also shows how these levels are counted:

If you wish to ascertain the level number of the object that is
                  			 currently being executed, you can use the system variable
                  			 *LEVEL
                  			 (which is described in the System Variables
                  			 documentation).
               
When the CALLNAT,
                  			 PERFORM or
                  			 FETCH RETURN
                  			 statement or the function call that invokes a subordinate routine - a
                  			 subprogram, an external subroutine, a program or a function respectively - is
                  			 executed, the execution of the invoking object is suspended and the execution
                  			 of the subordinate routine begins.
               
The execution of the subordinate routine continues until either its
                  			 END statement is reached
                  			 or processing of the subordinate routine is stopped by an
                  			 ESCAPE
                        			 ROUTINE or ESCAPE
                        			 MODULE statement being executed.
               
In either case, processing of the invoking object will then continue
                  			 with the statement following the CALLNAT, PERFORM or
                  			 FETCH RETURN statement used to invoke the subordinate routine.
                  			 
               
In the case of a function call, processing of the invoking object will then continue with the statement that contains the function call.

A program can be executed - and thus tested - by itself.
To catalog (compile) and execute a source program, you use the
                        					 system command RUN.
                     
To execute a program that already exists as a cataloged
                        					 object, you use the system command
                        					 EXECUTE.
                     
A program can also be invoked from another object with a
                  			 FETCH or
                  			 FETCH RETURN
                  			 statement. The invoking object can be another program, a
                  			 subroutine,
                  			 subprogram,
                  			 function, a
                  			 helproutine or a processing
                  			 rule in a map.
               
When a program is invoked with FETCH RETURN, the
                        				  execution of the invoking object will be suspended - not terminated - and the
                        				  fetched program will be activated as a subordinate program. When the
                        				  execution of the FETCHed program is terminated, the invoking
                        				  object will be re-activated and its execution continued with the statement
                        				  following the FETCH RETURN statement.
                     
When a program is invoked with FETCH, the execution
                        				  of the invoking object will be terminated and the FETCHed program
                        				  will be activated as a main program. The invoking object will not be
                        				  re-activated upon termination of the fetched program.
                     
The following topics are covered below:

A program invoked with FETCH RETURN can access
                  				the global data area (GDA)
                  				used by the invoking object.
               
In addition, every program can have its own local data area (LDA) which defines the fields that are to be used within the program only. Furthermore, a program can access application-independent variables (AIVs); see Defining Application-Independent Variables in the Statements documentation for details.
However, a program invoked with FETCH RETURN cannot
                  				have its own global data area (GDA).
               

A program invoked with FETCH as a main program
                  				usually establishes its own global data area (as shown in the illustration
                  				above). However, it could also use the same global data area as established by
                  				the invoking object.
               
Note:
 A source program can also be invoked with a RUN
                     				statement; see the RUN
                     				statement in the Statements documentation.
                  
Typically, a subroutine implements functionality that is used by different objects in an application.
The statements that make up a subroutine must be defined within a
                  			 DEFINE SUBROUTINE
                  			 ... END-SUBROUTINE statement block.
               
A subroutine is invoked with a PERFORM statement.
               
A subroutine may be an inline subroutine or an external subroutine:
Inline Subroutine
An inline subroutine is defined within the object which contains
                        				  the PERFORM statement that invokes it.
                     
External Subroutine
An external subroutine is defined in a separate object - of type
                        				  subroutine - outside the object which invokes it.
                     
If you have a block of code which is to be executed several times
                  			 within the same object, it is useful to use an inline subroutine. You then only
                  			 have to code this block once within a DEFINE SUBROUTINE statement
                  			 block and invoke it with several PERFORM statements.
               
The following topics are covered below:

An inline subroutine can be contained within an object of type program, function, subprogram, subroutine or helproutine.
An inline subroutine has access to all data fields within the object in which it is contained.

An external subroutine - that is, an object of type subroutine - cannot be executed by itself. It must be invoked from another object. The invoking object can be a program, function, subprogram, subroutine, helproutine or a processing rule in a map.
An external subroutine can access the global data area (GDA) used by the invoking object.
Moreover, parameters can be passed with the
                  				PERFORM statement
                  				from the invoking object to the external subroutine. These parameters must be
                  				defined either in the DEFINE DATA
                        				PARAMETER statement of the subroutine, or in a
                  				parameter data area (PDA)
                  				used by the subroutine.
               
In addition, an external subroutine can have its local data area (LDA) in which the fields that are to be used only within the subroutine are defined. However, an external subroutine cannot have its own global data area (GDA).
An external subroutine can also access application-independent variables (AIVs); see Defining Application-Independent Variables in the Statements documentation for details.
Typically, a subprogram implements functionality that is used by different objects in an application.
A subprogram cannot be executed by itself. It must be invoked from another object. The invoking object can be a program, function, subprogram, subroutine or helproutine.
A subprogram is invoked with a CALLNAT statement.
               
When the CALLNAT statement is executed, the execution
                  			 of the invoking object will be suspended and the subprogram executed. After the
                  			 subprogram has been executed, the execution of the invoking object will be
                  			 continued with the statement following the CALLNAT statement.
               
With the CALLNAT statement, parameters
                  				can be passed from the invoking object to the subprogram. These parameters are
                  				the only data available to the subprogram from the invoking object. They must
                  				be defined either in the DEFINE DATA
                        				PARAMETER statement of the subprogram, or in a
                  				parameter data area (PDA)
                  				used by the subprogram. 
               

In addition, a subprogram can have its own local data area (LDA) in which the fields to be used within the subprogram are defined.
If a subprogram in turn invokes a subroutine or helproutine, it can also establish its own global data area (GDA) to be shared with the subroutine/helproutine.
Furthermore, a subprogram can access application-independent variables (AIVs); see Defining Application-Independent Variables in the Statements documentation for details.
Typically, a function implements functionality that is used by different objects in an application.
A function provides user-defined functionality as opposed to the standard system functions (see the relevant documentation) supplied by Natural.
A function returns a result value that is used by the invoking object. The result value is computed from the data available to the function.
A function object contains a single function defined with a
                  			 DEFINE FUNCTION and
                  			 an END statement.
               
A function itself is invoked by a function call.
With the function call, parameters can be passed from the invoking
                  				object to the function. These parameters are the only data available to the
                  				function from the invoking object. They must be defined in the
                  				DEFINE FUNCTION
                  				statement.
               
In addition, a function can have its own local data area (LDA) in which the fields to be used within the function are defined. However, a function cannot have its own global data area (GDA).
A function can also access application-independent variables (AIVs); see Defining Application-Independent Variables in the Statements documentation for details.
If required, you can define the result and parameter layouts for
                  				the object calling a function by using the DEFINE PROTOTYPE
                  				statement.
               

For further information, see the section Function Call.
This section is a summarized feature comparison between external subroutines, subprograms and functions.
This is the same for all of them:
The programming code forming the routine logic is coded in a separate object which is stored in a Natural library.
Parameters are defined in the object using a DEFINE DATA
                           				  PARAMETER statement. 
                     
The differences between an external subroutine, a subprogram and a function are indicated in the following table:
| Subject | External Subroutine | Subprogram | Function | 
|---|---|---|---|
| Maximum length of name | 32 characters | 8 characters | 32 characters | 
| Use of global data area (GDA) | Shares a GDA with its caller | Creates an instance of a GDA | A GDA is not allowed. | 
| Check of format/length of passed parameters against definition in called object at compile time | Only checked if the compiler option PCHECKis
                           						set toON | Only checked if the compiler option PCHECKis
                           						set toON | Only checked if a cataloged function object exists at compile time | 
| Invoked by | Invoked by the PERFORMstatement | Invoked by the CALLNATstatement | Invoked by a
                           						function call A function call can be used in statements instead of read-only operands; a function call can also be used as a statement. | 
| Determination of the object to be called at compile/execution time | Determined at compile time | Determined at compile or execution time
                           						depending on the operand used for the CALLNATstatement | Determined at compile or execution time depending on the operand used for the function call | 
| Use of result value in a statement | A result value must be assigned to a parameter to be used as an operand in a statement. | A result value must be assigned to a parameter to be used as an operand in a statement. | The result of a function call is used as an operand in the statement that contains the function call. | 
The following examples compare a function call with a subprogram call:
The following example shows a program calling a function, and the
                  				function definition created with a DEFINE FUNCTION statement.
               
** Example 'FUNCAX01': Calling a function  (Program)                    
************************************************************************
*                                                                       
WRITE 'Function call' F#ADD(< 2,3 >)  /* Function call.                   
                                      /* No temporary variables needed. 
*                                                                       
END 
 
               			 ** Example 'FUNCAX02': Calling a function  (Function)                   
************************************************************************
DEFINE FUNCTION F#ADD                                                    
  RETURNS #RESULT (I4)                                                  
  DEFINE DATA PARAMETER                                                 
    1 #SUMMAND1 (I4) BY VALUE                                                    
    1 #SUMMAND2 (I4) BY VALUE                                                     
  END-DEFINE                                                            
  /*                                                                    
  #RESULT := #SUMMAND1 + #SUMMAND2                                      
  /*                                                                    
END-FUNCTION                                                            
*                                                                       
END  
               		   
               		  
               To implement the same functionality as shown in the example of a function call by using a subprogram call instead, you need to specify temporary variables.
The following example shows a program calling a subprogram, involving the use of a temporary variable.
** Example 'FUNCAX03': Calling a subprogram  (Program)                  
************************************************************************
DEFINE DATA LOCAL                                                       
  1 #RESULT (I4) INIT <0>                                               
END-DEFINE                                                              
*                                                                       
CALLNAT 'FUNCAX04' #RESULT 2 3    /* Result is stored in #RESULT.     
*                                                                       
WRITE '=' #RESULT                 /* Print out the result of the        
                                  /* subprogram.                        
*                                                                       
END 
 
               			 ** Example 'FUNCAX04': Calling a subprogram (Subprogram) ************************************************************************ DEFINE DATA PARAMETER 1 #RESULT (I4) BY VALUE RESULT 1 #SUMMAND1 (I4) BY VALUE 1 #SUMMAND2 (I4) BY VALUE END-DEFINE * #RESULT := #SUMMAND1 + #SUMMAND2 * END