A WFL job can include any number of subroutines, and each subroutine can contain further subroutine declarations within itself. In addition, a subroutine can contain statements invoking itself, or other subroutines in the WFL job. (The rules concerning which subroutines can be invoked from a given subroutine are discussed under Scope of Declarations.
WFL enables an identifier to be associated with a statement or group of statements. This can be accomplished by using the subroutine declaration. Once a subroutine has been declared, it can be invoked in the WFL job by using the identifier associated with it. The subroutine is a convenient shorthand for referring to a piece of code that the WFL job is going to invoke repeatedly.
Examples
The WFL subroutines can be invoked with parameters that pass values to the subroutines. Consider the following example:
?BEGIN JOB WFLCHART(REAL VALUE1, REAL VALUE2, REAL VALUE3); SUBROUTINE RUNCHART(REAL RVAL VALUE); % Beginning of subroutine BEGIN % declaration RUN (PORT)CHART/COL/NAV(RVAL); END RUNCHART; % End of subroutine % declaration % WFL job statements follow DISPLAY "RUNNING WITH FIRST VALUE SUPPLIED"; RUNCHART(VALUE1); DISPLAY "RUNNING WITH SECOND VALUE SUPPLIED"; RUNCHART(VALUE2); DISPLAY "RUNNING WITH THIRD VALUE SUPPLIED"; RUNCHART(VALUE3); ?END JOB.
This job is initiated with a START statement that has three real numbers specified as parameters. The job then calls on the subroutine RUNCHART three times, each time supplying a different parameter value to the subroutine. This method saves code repetition when a lengthy subroutine is called.
The following example is a subroutine that invokes itself:
?BEGIN JOB WFLINV(INTEGER VALUE1, INTEGER VALUE2); SUBROUTINE DISPLAYONE; DISPLAY "IT WORKED ALL RIGHT"; SUBROUTINE RUNINV(INTEGER IVAL1); BEGIN RUN (PARTS)OBJECT/OLD/INV(IVAL1); STATION=MYSELF(SOURCESTATION); DISPLAYONE; IVAL1 := IVAL1 + 1; IF IVAL1 LEQ VALUE2 THEN RUNINV(IVAL1); END; RUNINV(VALUE1); DISPLAYONE; ?END JOB.
This job accepts two integer values as parameters. The job uses the first job parameter as a parameter in the RUN statement for the program OBJECT/OLD/INV. This program is run several times, with an increase in the value of the parameter each time, until the parameter equals the value of the second parameter that was supplied to the job.
This example shows several kinds of subroutine invocations that are available. The outer block of the WFL job calls on the subroutines RUNINV and DISPLAYONE. The subroutine RUNINV also calls on the subroutine DISPLAYONE, which was previously defined. Further, the subroutine RUNINV calls on itself, so that it will continue repeating as long as the expression in the IF statement evaluates to TRUE.The following example illustrates the use of the RETURN statement as a means of exiting a subroutine early:
?BEGIN JOB WFLTEST(INTEGER VALUE1); TASK T; SUBROUTINE RUNTEST(INTEGER IVAL1); BEGIN RUN (WALLY)OBJECT/TEST(IVAL1) [T]; IF T ISNT COMPLETEDOK THEN RETURN; IVAL1 := IVAL1 + 1; IF IVAL1 LEQ 7 THEN RUNTEST(IVAL1); END; RUNTEST(VALUE1); ?END JOB.
This example runs the program (WALLY)OBJECT/TEST repeatedly. However, if the task variable T indicates the program did not run successfully, the RETURN statement is invoked to cause the subroutine to be exited. The remaining statements in the subroutine will then be bypassed, and control will pass back to the parent of the subroutine (in this case, the outer block of the WFL job).