A SUB-PROCEDURE is a piece of code that can be called and executed from other parts of the script. SUB-PROCEDURE subsections must be declared within the PROCEDURE section of the code using a
SUB-PROCEDURE <name> statement and end with an
END SUB-PROCEDURE statement. Bear in mind that you can't define a SUB-PROCEDURE within a SUB-PROCEDURE. Also bear in mind that you can CALL a SUB-PROCEDURE before it has been declared, but the compilation process will fail if the compiler doesn't find the SUB-PROCEDURE once it has parsed all the files in your program.
The full syntax for declaring sub-procedures is this one:
SUB-PROCEDURE procedureNamePARAMETERS:< parameters go here >LOCAL DATA:< local variable declarations go here >PROCEDURE:< code goes here >END SUB-PROCEDURE
LOCAL DATA: sub-sections are optional (more on these later). If you decide to not include both the
LOCAL DATA: sub-sections, you can skip the
PROCEDURE: tag and just go ahead writing your code like this:
SUB mySub# Your code goes here! For exampleDISPLAY "I love sub-procedures!" crlfEND SUB
As shown in the example above, the statements
END SUB can be used instead of
END SUB-PROCEDURE, if you prefer.
In context, the full declaration of a SUB-PROCEDURE looks like this:
DATA:# ...PROCEDURE:# ...SUB-PROCEDURE mySubprocedurePARAMETERS:# Parameters declarationLOCAL DATA:# Local variables declarationPROCEDURE:# Sub procedure code# goes here.END SUB-PROCEDURE
Of course, you cannot have two SUB-PROCEDUREs with the same name. SUB-PROCEDURE names follow the same naming guidelines variable names follow.
SUB-PROCEDUREs have three sub-sections:
LOCAL DATA: and
PROCEDURE:. Again, the first two sub-sections are optional and only
PROCEDURE: is mandatory, but you can skip the
PROCEDURE: label if you only use this section, like this:
DATA:# ...PROCEDURE:# ...SUB-PROCEDURE mySubprocedure# Sub procedure code# goes here.END SUB-PROCEDURE
PROCEDURE: sub-section, you write the code of the SUB-PROCEDURE using statements like in the main
PROCEDURE: section, with the addition of the RETURN statement.
LOCAL DATA: you can only use variable declaration statements, just like in the DATA section. The variables defined here can only be used inside the
PROCEDURE: sub-section of the SUB-PROCEDURE where they are declared; you can declare variables with names declared in other SUB-PROCEDURE or in the main
DATA: section, but bear in mind that if you use these variables in your SUB-PROCEDURE code, they will always refer to the ones you declared within the SUB-PROCEDURE. For example:
DATA:i IS numberPROCEDURE:SUB-PROCEDURE mySubprocedureLOCAL DATA:i IS textPROCEDURE:STORE "I'm a variable from mySubprocedure! " IN iDISPLAY iEND SUB-PROCEDURESTORE 42 IN iCALL mySubprocedureDISPLAY i# The output of this program is "I'm a variable from mySubprocedure! 42"
At the start of the SUB-PROCEDURE execution, all the variables declared in
LOCAL DATA: will be initialized with its default value, and each invocation of the SUB-PROCEDURE will have its own copy of the local variables. This is important if you want to implement a recursive SUB-PROCEDURE, for example:
DATA:executions IS numberPROCEDURE:SUB-PROCEDURE myRecursiveSubprocedureLOCAL DATA:myLocalVar IS numberPROCEDURE:INCR executionsIF executions IS EQUAL TO 3 THENRETURN # We don't want this to run forever!END IFDISPLAY "[myLocalVar starts at " myLocalVar "!"STORE executions IN myLocalVarCALL myRecursiveSubprocedureDISPLAY "I'm execution Nº " myLocalVar "!]"END SUB-PROCEDURECALL myRecursiveSubprocedure# The output of this program is# "[myLocalVar starts at 0![myLocalVar starts at 0!I'm execution Nº 2!]I'm execution Nº 1!]"
Variables declared in
PARAMETERS: are quite different, they will start with the value passed from the CALL using the
WITH keyword. Variables are passed by reference. This means that if you modify a parameter in a SUB-PROCEDURE, the variable passed in the
CALL will also be modified. Be careful with this, and make sure to copy a parameter in a local variable if you need it. Passing variables by reference lets you return results from your SUB-PROCEDURE, for example:
DATA:i IS numberPROCEDURE:SUB-PROCEDURE duplicatePARAMETERS:input IS numberresult IS numberPROCEDURE:IN result solve input + inputEND SUB-PROCEDURECALL duplicate WITH 2 iDISPLAY i# The output of this program is "4"