names and scope. scope suppose that a name is used many times for different entities in text of the...

24
Names and Scope

Upload: lee-white

Post on 31-Dec-2015

214 views

Category:

Documents


0 download

TRANSCRIPT

Names and Scope

Scope

Suppose that a name is used many times for different entities in text of the program, or in the course of execution. When the name is used, to which of these entities does it refer?

Types of names

• Variables • Constants• Statement labels• Functions/procedures• Types• Macros• Exceptions• Modules (packages, files, etc.)

Postponing

• Names of modules and references between modules (to lecture on modules)

• Variables used in functions passed as parameters and returned as values (to lecture on functional programming)

• Exceptions (to lecture on exceptions).

Easy cases

• Types and macros are (as far as I know) global to a module.

• Statements labels are scoped within the function, and are visible in that functions and in lexically contained functions.

Function names

In non-hierarchical languages (e.g. C), function names are global to the module.

Some languages require that a function be declared lexically before it is used; others do not.

If you impose this rule for mutually recursive functions, then there must be declarations that are separate from definition.

Function names: Hierarchical languages

Closest nested scope:

Suppose that function C is lexically inside B which is lexically inside A, and C calls function F.

In order look for a declaration of F immediately inside first C, then B, then A, then global. Otherwise, the reference is invalid.

Example (Pascal)function A() function F() begin … end // Body of F1 function B() function F() begin … end // Body of F2

function C() begin … F() … end // Body of C. Call to F2

begin … F() … end // Body of B. Call to F2

function D() begin … F() … end // Body of D. Call to F1

begin … F() … end // Body of A. Call to F1

Scope of Function Name

Nothing particularly interesting has to be done in terms of the compiled code. The compiler uses the scope rule to assign the reference, but the calling and returning protocols are unaffected.

Scope of Variables

• Static scope (also called “lexical scope”). As with functions, use the nearest containing scope that declares the variable. Note: The reference can be determined at compile time.

• Dynamic scope. Use the most recent declaration in the calling sequence

Static and dynamic scoping: Example

int N;void main() {N=1; A(); printf(“main: %1d”,N);}

void A()int N;{ N = 2; B(); printf(“A: %1d . ”, N); }

void B() { N = 3; }

Static scoping: Prints “A: 2 . main: 3” (I in B is global)Dynamic scoping: Prints “A: 3 . main: 1” (I in B is I in A)

Implementing static scoping: no function imbedding

Trivial: Variables are either local (in current activation record) or global (fixed address).

Implementing static scoping:function imbedding

• Each activation record on the stack has a static link to the activation record of the most recent call to the routine that lexically contains it.

• To resolve a reference to a variable in a routine K levels out from the current routine, follow the chain of static links K steps to the proper activation record, and then go the appropriate offset.

• Number of links and offset are known at compile time.

function A() { int I;

function B() { int J;

function C() { int K;

K=I+J; B(); }

C(); } // body of B.

B(); } // body of A.

A calls B calls C calls

B calls C.

Setting static links in calling protocol

• If F calls G and G is immediately lexically contained in H, then (by the scoping rules for functions) either – F=H, in which case the static link from G points to the

static link in F’s activation record– or F is lexically contained in H (not necessarily

immediately), in which case the link to H is a known number of steps down the static chain from F.

• In either case, the compiler can determine how F should set the static link for G.

Implementing dynamic scoping:symbol table

Symbol table: For each variable name X, keep a pointer to the most recent version of X.

If function F declares X, then F must store a pointer to the previous version of X.

On entering routine F, push a pointer to previous location of X onto stack,

On exiting F, restore previous value of X to symbol table.

Example

function A() {

int I,J; B(); }

function B() {

int J,K; C(); }

function C() {

int I,K B(); }

A calls B calls C calls B.

Declarations and definitions

• Is declaration separate from definition?

• If a name is declared, is the scope the entire context, or only after it is declared?

• Can a name be used before it is declared?

Particularly important for mutually recursive types and function definitions.

In weird cases, it can be important for constant definitions.

Mutually recursive functions: Pascal

forward procedure B(I: integer) // declaration

procedure A(I: integer) // declaration and

begin B(I-1) end // definition

procedure B(I: integer) // definition

begin A(I-1) end

Mutually recursive functions: C

void B(int I); // declaration

void A(int I) { B(I-1); } // declaration and // definition

void B(int I) { A(I-1); } // definition

Ada is similar.

Recursive types: Pascal

In defining a pointer type P, you can refer to another type T before T has been declared (because nothing about P, such as the size, actually depends on T).

type PRED = ^RED;PBLACK = ^BLACK;RED = record V,D: Integer; L,R: PBLACK end;BLACK = record V,D: Integer; L,R: PRED end;

Recursive types: C

Separate declaration from definition, like functions.

struct RED;

struct BLACK { int V, P; struct RED *L, *R; }

struct RED { int V,P; struct BLACK *L, *R; }

Constant anomaly in Pascal (and some other languages)

• Scope of a declaration is the entire block.• Declarations must precede use.const N=10;procedure f;const M=N; N=20;In “M=N”, N refers to the declaration in f;

hence it is used before it is declared.