<subroutine invocation statement>
──<subroutine identifier>─┬──────────────────────────────────────┬─────┤ │ ┌◄─────────── , ───────────┐ │ └─ ( ─┴─┬─<real expression>────┬─┴─ ) ─┘ ├─<integer expression>─┤ ├─<Boolean expression>─┤ ├─<string expression>──┤ ├─<task identifier>────┤ └─<file identifier>────┘
Explanation
The subroutine invocation statement initiates execution of a subroutine. The subroutine identifier must be the name of a subroutine that was declared earlier in the job.
The subroutine is normally executed synchronously with the rest of the job. However, the subroutine can be made to execute as an asynchronous task by placing the subroutine invocation in a PROCESS statement. Then a task variable and a task equation list can be specified. Refer to Task Initiation for more information.
The name of a subroutine task initiated by a PROCESS statement is set by WFL when the subroutine is invoked. Prior settings of the NAME task attribute are overridden, and the default name of the subroutine task is the same as the name of the subroutine. The name of the subroutine task can be changed by specifying a different value for the NAME task attribute when the subroutine is invoked.
The order and number of the parameters in the subroutine invocation statement must be the same as the order and number of the parameters in the matching subroutine declaration.
If a parameter was specified in the subroutine declaration as VALUE, then the parameter in the subroutine invocation statement is passed by value. Otherwise, the parameter in the subroutine invocation statement is passed by reference. For a definition of call‑by‑reference and call-by-value parameters, refer to Subroutines.
Subroutine invocation statements can be included in subroutines. The rules defining which subroutines can be invoked from a particular subroutine are defined under Declaration Syntax.
Note: | A subroutine invocation statement can cause the job to enter an infinite loop if the subroutine invokes itself or a subroutine that is nested within a subroutine. In these cases, a test should normally be included to cause one of the subroutines involved in the loop to be exited if some specified condition is met. |
When a task is initiated in a subroutine, that subroutine becomes the critical block for the task. Whether the task variable associated with the task is declared locally or globally does not affect which block is the critical block for the task.
A subroutine is not exited until all asynchronous tasks initiated within that subroutine have gone to end of task. An explicit WAIT is not necessary; the subroutine automatically waits.
A subroutine invocation statement accepts string expressions of up to 1800 characters as parameters.
Examples
The following is an example of a subroutine:
SUBROUTINE COMPANDGO(FILE FNAME, STRING PARAM1, INTEGER PARAM2); BEGIN COMPILE XYZ WITH ALGOL LIBRARY; COMPILER FILE CARD (TITLE=#FNAME(TITLE),KIND=DISK); RUN XYZ (PARAM1,PARAM2); REMOVE XYZ; PARAM2 := PARAM2+1; END COMPANDGO; INTEGER I; FILE F1(TITLE=TEST1); FILE F2(TITLE=FLOP2); I:=1; COMPANDGO(F1, "TEST" & STRING(I,2), I); COMPANDGO(F2, "FLOP" & STRING(I,2), I);
This example illustrates that a subroutine waits for its asynchronous tasks to complete before returning. The subroutine SUB waits for the completion of OBJECT/PROG before returning to the outer block.
?BEGIN JOB PROCESS/TEST; TASK TSK; SUBROUTINE SUB; BEGIN PROCESS RUN OBJECT/PROG [TSK]; DISPLAY "SUB is waiting for OBJECT/PROG"; END SUB; SUB; ?END JOB.
This example runs the subroutine SUB1 and the program OBJECT/TEST2 asynchronously and waits for the subroutine SUB1 to finish before continuing.
SUBROUTINE SUB1; BEGIN COPY MONTHLY/SUMMARY AS CURRENT/SUMMARY FROM USERS(DISK); RUN OBJECT/ALGOL/1; END SUB1; PROCESS SUB1 [TSK]; RUN OBJECT/TEST2; WAIT (TSK IS COMPLETED);
In this example, the prior value of TESTSUB for the NAME task attribute (set with the task variable T) is overridden when the subroutine SUB1 is invoked by a PROCESS statement. The name of the subroutine task is changed from its default value of SUB1 to the value of TEST1.
SUBROUTINE SUB1; BEGIN RUN TEST/1; END; T(NAME=TESTSUB); PROCESS SUB1[T]; NAME=TEST1;