Blocks, locality, and scope

Blocks

A block is made up of declarations, which are written and combined in any order, and statements. Each block is part of a procedure declaration, a function declaration, a method declaration, or a program or unit. All identifiers and labels declared in the declaration part are local to the block.

The overall syntax of any block follows this format:

block

declaration part

Labels that mark statements in the corresponding statement part are declared in the

label declaration part. Each label must mark only one statement.

Blocks, locality, and scope - 图1label declaration part

A label must be an identifier or a digit sequence in the range 0 to 9999.

The constant declaration part consists of constant declarations local to the block.

constant declaration part

The type declaration part includes all type declarations local to the block.

type declaration part

The variable declaration part is composed of variable declarations local to the block.

variable declaration part

The procedure and function declarations local to the block make up the procedure and function declaration part.

procedure/function declaration part

The exports clause lists all procedures and functions that are exported by the current program or dynamic-link library. An exports clause is allowed only in the outermost declaration part of a program or dynamic-link library—it isn’t allowed in the declaration part of a procedure, function, or unit. See “The exports clause” on page 135.

The statement part defines the statements or algorithmic actions to be executed by the block.

statement part

Rules of scope

The presence of an identifier or label in a declaration defines the identifier or label. Each time the identifier or label occurs again, it must be within the scope of this declaration.

Block scope

The scope of an identifier or label declared in a label, constant, type, variable, procedure, or function declaration stretches from the point of declaration to the end of the current block, and includes all blocks enclosed by the current block.

An identifier or label declared in an outer block can be redeclared in an inner block enclosed by the outer block. Before the point of declaration in the inner block, and

after the end of the inner block, the identifier or label represents the entity declared in the outer block.

program Outer; { Start of outer scope }

type

I = Integer; { define I as type Integer }

var

T: I; { define T as an Integer variable }

procedure Inner; { Start of inner scope }

type

T = I; { redefine T as type Integer }

var

I: T; { redefine I as an Integer variable }

begin

I := 1;

end; { End of inner scope }

begin

T := 1;

end. { End of outer scope }

Record scope

The scope of a field identifier declared in a record-type definition extends from the point of declaration to the end of the record-type definition. Also, the scope of field identifiers includes field designators and with statements that operate on variable references of the given record type. See “Record types” on page 19.

Class scope

The scope of a component identifier declared in a class type extends from the point of declaration to the end of the class-type definition, and extends over all descendants of the class type and the blocks of all method declarations of the class type. Also, the scope of component identifiers includes field, method, and property designators, and with statements that operate on variables of the given class type. For more information on classes, see Chapter 9, Class Types.

Unit scope

The scope of identifiers declared in the interface section of a unit follows the rules of block scope and extends over all clients of the unit. In other words, programs or units containing uses clauses have access to the identifiers belonging to the interface parts of the units in those uses clauses.

Each unit in a uses clause imposes a new scope that encloses the remaining units used and the program or unit containing the uses clause. The first unit in a uses clause represents the outermost scope, and the last unit represents the innermost scope. This implies that if two or more units declare the same identifier, an unqualified reference to the identifier selects the instance declared by the last unit in

the uses clause. If you use a qualified identifier (a unit identifier, followed by a period, followed by the identifier), every instance of the identifier can be selected.

The identifiers of Object Pascal’s predefined constants, types, variables, procedures, and functions act as if they were declared in a block enclosing all used units and the entire program. In fact, these standard objects are defined in a unit called System, which is used by any program or unit before the units named in the uses clause.

This means that any unit or program can redeclare the standard identifiers, but a specific reference can still be made through a qualified identifier, for example, System.Integer or System.Writeln.

C h a p t e r