Chapter 5: References

This chapter describes each type of reference and the rules and basic steps involved in resolving references.

Introduction

A reference is the declared name of a variable or constant, along with any subscript list, pointer qualifier (–>), or structure qualifier necessary to indicate its purpose. References to procedures or built-in functions may also include an argument list.

Examples:
X
Y(5,K)
F(Z*5+B,SQRT(Z))
P->S.A(K)
Q.NEXT->NODE.FIELD1

The first example is a simple reference, and the second is a subscripted reference. The third example is a reference to a procedure. The fourth and fifth examples are pointer qualified references.

A reference is associated with a declaration according to the scope of the declared name. The process of associating a reference with a declaration is called reference resolution, and it occurs during compilation of the program.

Simple and Subscripted References

A simple reference is a name without any subscripts, pointer qualifiers, structure names, or argument lists.

A subscripted reference is a name that has been declared as an array, followed by a parenthetical list of subscript expressions. Each subscript expression must produce an integer fixed-point value that lies within the lower and upper bounds specified for that dimension in the array declaration. The number of subscript expressions must be equal to the number of dimensions.

An asterisk subscript refers to the entire array bounds range for the corresponding dimension. Subscripts containing asterisks do not refer to a single data item. Thus, such references are array expressions, not element expressions.

A cross-section of an array may reference two or more elements that are not stored adjacently in memory. Such storage is referred to as non-connected storage.

DECLARE A(5,5) FLOAT; 
DECLARE B(10) FLOAT;
   .
   .
   .
A(K*2,*) = B(1); 
A(*,*) = 5;

In the preceding example, both A (K*2,*) and B (1) are subscripted references; K is a simple reference. A(*,*) references the entire array and A(K*2,*) references the entire 2Kth row.

Structure Qualified References

Because the names of structure members (with the exception of the major structure name) can be redeclared or reused within the same block, their scopes overlap. If a member's name has been redeclared within the same block, any reference to that member must be qualified by the name of its containing structure. If the containing structure's name has been redeclared within the same block, it must be qualified, in turn, by the name of its containing structure until an unambiguous reference is created.

A structure qualified reference is a sequence of names written left-to-right in order of increasing level-numbers. The names are separated by periods, and blanks may be written around the periods. The sequence need not include all containing structure names, but it must include sufficient names to make the reference unique. For example:

DECLARE       1  S,
     2          A  FIXED,
     2          B,
     3          A  FLOAT,
     3          C  FLOAT;

In this example, a reference to A is ambiguous because the scope of A FLOAT overlaps the scope of A FIXED. A structure qualified reference to S.A refers to A FIXED. A structure qualified reference to B.A refers to A FLOAT, as does S.B.A.

A structure qualified reference that includes the name of each containing structure from the major structure down to the member is a fully qualified reference. If the name of one or more of the containing structures is omitted, the reference is a partially qualified reference. In the previous example, B.A is a partially qualified reference, and S.B.A is a fully qualified reference, as are S.A, S.B, and S.B.C.

Subscripts can be used anywhere within a structure qualified reference, but it is best to write each set of subscripts immediately following the name that has the corresponding bounds declared for it. For example:

DECLARE     1   S(10),
     2        A    FIXED,
     2        B(3)    FLOAT,
     2        C(3),
     3        D   POINTER;

In the previous example, a reference to S(K).A and a reference to S.A(K) are equivalent, but a reference to S(K).A is preferred. Other recommended references are S(K).B(J) and S(K).C(J).

Locator Qualified References

A reference to a based variable may be qualified by a reference to a pointer or offset variable. For example:

DECLARE A(10) FLOAT BASED; 
DECLARE P POINTER;

In this example, P –>A and P –>A(K) are pointer qualified references to the based variable A.

Since a pointer variable may itself be based, multiple qualification is possible. For example:

DECLARE     1 NODE BASED,
            2 NEXT POINTER, 
            2 VALUE FLOAT;
DECLARE HEAD POINTER;

In this example, HEAD –>NODE.NEXT–>NODE.VALUE is a pointer qualified reference to NODE.VALUE. It is qualified by NODE.NEXT, which is, in turn, qualified by HEAD.

Pointer-valued functions and pointer-valued built-in functions may also be used as pointer qualifiers.

DECLARE NEXT_NODE ENTRY RETURNS(POINTER);

In this example, NEXT_NODE() –>NODE.VALUE is a pointer qualified reference to NODE.VALUE whose qualifier is a function reference.

When addressing data allocated in an area, an offset variable can be used as a locator qualifier in the same fashion as the pointer is in the above examples. The offset value will be implicitly converted to a pointer value by adding the address of the area specified in the OFFSET attribute of its declaration. See the section Offset Data.

Procedure References

A procedure reference is any reference followed by an argument list consisting of a parenthetical list of expressions separated by commas or followed by an empty argument list (). A procedure reference that returns a value is called a function reference. A procedure reference that does not return a value is called a subroutine reference.

If an argument list or empty argument list is given, the referenced name must be declared as an entry either by appearing as a label prefix on a PROCEDURE statement or by a DECLARE statement. Unless the reference is part of a CALL statement, the referenced entry must return a value. If the reference is part of a CALL statement, the entry must not return a value; therefore, a procedure that returns a value must always be called as a function, and a procedure that does not return a value must always be called as a subroutine.

A name declared as an entry is called only when it is referenced with an argument list or when it is called by a CALL statement. A function that has no parameters must be referenced with an empty argument list.

Except when it is part of a CALL statement, a reference to an entry written without an argument list is a reference to the entry value, rather than a function reference that calls the entry.

The following example demonstrates a range of procedure references.

DECLARE F ENTRY RETURNS(POINTER);
DECLARE G ENTRY(FIXED) RETURNS(FLOAT); 
DECLARE V ENTRY VARIABLE RETURNS(POINTER); 
DECLARE P POINTER, X FLOAT;
   . 
   . 
   .
P = F(); 
V = F;
X = G(0);

In this example, a reference to F() calls F and produces a pointer value. A reference to F is a reference to the entry value of F and can be assigned to the entry variable V. A reference to G is also a reference to an entry value and does not call G. G is called by references containing an argument list.

An array of entry variables may be referenced with subscripts and with an argument list. In this case, the argument list follows the subscript fist, as shown in the following example:

DECLARE E(5) ENTRY(FIXED) VARIABLE 
      RETURNS(POINTER);

According to E's declaration, E is a reference to the entire array of entry values. E (k) (j) is a pointer valued function reference that calls E (kf, passing it the argument j. E (k) is an entry value that may be passed to an entry parameter or assigned to an entry variable. If E had been declared without parameters, E (k) would have to be invoked using an empty argument list — E(k) () .

Built-In Function References

A reference to a built-in function always produces the value of that function and is never an entry value. Built-in functions cannot be assigned to entry variables or passed as arguments to entry valued parameters.

Built-in functions that take arguments do not have to be declared, but built-in functions that take no arguments, such as NULL and ONCODE, must either be referenced with an empty argument list () or must be declared with the BUILTIN attribute.

Variable References

A reference to a variable may occur in a context that expects a value, or it may occur in a context that assigns a value to the variable. If a value is expected, the variable must have previously been assigned a value or must be a variable declared with the INITIAL attribute. A reference to the value of a variable that has no value produces unpredictable results.

The left side of an assignment operator or the format-list of a GET statement causes assignment to a variable. Using a variable as the argument to a procedure or function call may also cause assignment to the variable if the corresponding parameter is given a value. The ADDR, HBOUND, LBOUND, DIMENSION, and LENGTH built-in functions reference a variable but do not expect a value. (However, LENGTH of a varying string variable does require that the string variable have a value.) A variable passed by reference to a parameter does not need to have a value if the parameter is not expected to have a value upon entry to its procedure. The record I/O statements copy a variable's storage and do not require the variable to have a value.

Reference Resolution

The following is the sequence of steps taken by the Compiler to resolve references:

  1. Determine the initial block in which the search for the declaration begins.
  2. Find the referenced declaration and the block to which it belongs. Find the activation associated with that block.
  3. Evaluate the locator qualifier (if any) to obtain a pointer value.
  4. Evaluate the basis reference (if the reference is to a defined variable) and pointer.
  5. Determine all the extents (if any) of the referenced variables.
  6. Interpret the subscripts (if any).
  7. Invoke the procedure (if any).

Remember the following points when preparing for reference resolution:


Copyright © 2009 Micro Focus (IP) Ltd. All rights reserved.