The Scope of Variables
Variable names must be unique in their scope. Variable names are local to the program module in which they are declared.
The scope of a variable opens at its declaration. Generally, its scope remains open until the end of the program module. For example, an EQUEL variable declared in a main program will be visible to all subsequent EQUEL statements until a BASIC end, sub, or function statement is processed by EQUEL. (Remember that the preprocessor will process these statements only if they are preceded by the EQUEL ## mark.) Similarly, an EQUEL variable declared in a sub or function subprogram or a formal parameter to that subprogram will be visible until the end sub or end function statement is processed by EQUEL. Processing of another sub or function statement would also close the scope of the subprogram.
Note that scoping rules for def functions differ somewhat for EQUEL and BASIC. The scope of the formal parameters to an EQUEL def function remains open until the end def statement is processed. The same is true of variables declared in the def function. In other words, EQUEL treats such variables as local variables. However, while BASIC also regards parameters as local to the def function, it allows variables declared in the def function to have a global scope. If you wish an EQUEL variable to have a scope that is global to the program module as a whole, you must declare it in the program module, not in a def function definition.
In order to ensure that EQUEL follows the same scoping conventions as those followed by BASIC, you should observe these rules:
• Always use the EQUEL ## mark on sub and function statements, even if the parameters are not EQUEL variables. These statements cause EQUEL to open a new scope, closing off all previous scopes.
• Be aware that the ## declare ingres statement closes off previously opened scopes and opens a new scope. Therefore, if you do issue this statement, you should include it before any EQUEL declarations in your main program.
• If you declare a def function statement to EQUEL, you must also issue the end def statement to EQUEL, so that it may close the local scope of def variables and parameters.
• Issue the end, end sub and end function statements to EQUEL in order that the preprocessor may be fully aware of the scoping of EQUEL variables. These statements must each appear on a line by themselves, with no comments separating the keywords.
The following example illustrates the scope of variables in an EQUEL/BASIC program.
10 ## declare ingres
## common (glob) integer a, real b
declare single c, double d
declare double function xyz(single)
! Visible to EQUEL: a, b
! Visible to BASIC: a, b, c, d, xyz
...
## def double xyz(single e)
## declare byte f
declare string g
! Visible to EQUEL: a, b, e, f
! Visible to BASIC: a, b, c, d, e, f, g, xyz
...
## end def
! Visible to EQUEL: a, b
! Visible to BASIC: a, b, c, d, f, g, xyz
d = xyz(c)
...
call uvw(d)
## end
! Visible to EQUEL: no variables
! Visible to BASIC: no variables
20 ## sub uvw(double p)
! No DECLARE Ingres statement needed in subprogram
## common (glob) integer a, real b
## declare byte q
! Visible to EQUEL: p, a, b, q
! Visible to BASIC: p, a, b, q
...
## end sub
! Visible to EQUEL: no variables
! Visible to BASIC: no variables
Take special care when using variables in a declare cursor statement. The variables used in such a statement must also be valid in the scope of the open statement for that same cursor. The preprocessor actually generates the code for the declare at the point that the open is issued, and, at that time, evaluates any associated variables. For example, in the following program fragment, even though the variable "number" is valid to the preprocessor at the point of the declare cursor statement, it is not an explicitly declared variable name for the BASIC compiler at the point that the open is issued, possibly resulting in a runtime error. Because BASIC allows implicit variable declarations (although EQUEL does not), the compiler itself will not, however, generate an error message.
1 ## sub Init_Csr ! Example contains an error
## declare integer number
! Cursor declaration includes reference to "number"
## declare cursor c1 for
## retrieve (employee.name, employee.age)
## where employee.num = number
...
## end sub
2 ## sub Process_Csr
## declare string ename
## declare integer eage
! Opening the cursor evaluates invalid "number"
## open cursor c1
## retrieve cursor c1 (ename, eage)
...
## end sub