460 likes | 738 Views
Scope Rules. Programming Language Principles Lecture 16. Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida. Definition. Scope: the region of program text in which a binding holds. Static binding is prevalent in most modern PLs. New scope in each function.
E N D
Scope Rules Programming Language Principles Lecture 16 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida
Definition • Scope: the region of program text in which a binding holds. • Static binding is prevalent in most modern PLs. • New scope in each function. • Activate bindings for parameters and locals. • Deactivate bindings of globals obscured by locals. • Deactivate bindings upon function return.
RPAL Is Statically Scoped (CSE Rule 4): CONTROLSTACK __________________________________________________ ec ... <λ,x,i,k> R ... ec ec ... enδk en ...ec __________________________________________________ where en = [R/x] ei. <--- defines lexical scoping !
RPAL Is Statically Scoped (cont’d) • ei is the environment in effect when the lambda closure was created. • Change ei to ec (the current environment at the point of function application), and RPAL becomes dynamically scoped.
Example let Sqr x = x * x in let f a b = Sqr a + b in Print(f 4 3 + (let Sqr x = x+x in f 4 3)) ) • In RPAL, this program prints 19 + 19 = 38. • If RPAL used dynamic scoping, the result would be 19 + 11 = 30.
Suggested Exercise • Run the CSE by hand, and see the environments. • Changing RPAL from lexical to dynamic scoping involves changing ONE letter ! (The power of formal semantic specification ...) • Some dynamically scoped languages: SNOBOL, APL, perl (?) early LISP (later changed by J. McCarthy).
Terminology • Referencing environment: the set of active bindings at a given point in a program's execution. • Deep binding: the reference environment of a fcn/proc is determined when the function is created. • Shallow binding: the reference environment of a fcn/proc is determined when the function is called.
Structure of Referencing Environments • Normally, a stack suffices (C, C++, Java). • If a procedure (not merely a pointer) can be passed as a parameter, the referencing environments are organized as a tree.
Example: Passing Procedures as Parameters in Pascal: program test(output); procedure dummy; begin end; procedure Q(procedure S; n:integer); procedure R; begin writeln(n) end; begin { Q } if n=1 then Q(R,0) else S; end; begin {main} Q(dummy,1) end. The output of this program is ???
Types of Static Scope • Flat: (BASIC, Cobol) • All name sin the same scope, all visible everywhere. • Local/global (Fortan, C, Prolog) • Only two referencing environments: current and global.
Types of Static Scope (cont’d) • Nested procedures (Algol, Pascal, Ada, Modula, RPAL). • Each procedure has its own scope, visible to itself and all procedures nested within it.
Types of Static Scope (cont’d) • Modular scope (Modula, Ada, C++, Java). Scopes defined by modules, which explicitly export names to: • The global scope (public) • The scopes of subclasses (protected) • Nowhere (private)
Nested Scoping Example (in pseudo-Pascal): proc A; var a; proc B; var b: proc C; var c; begin c:=b-1; if b=1 then B else a:=a-c; end;{ C } begin b:=a-4; if b<2 then C; else a:=0; end;{ B } begin a:=5; B; end;{ A } A can only see a. B can see a and b but not c. C can see a, b, and c. C can see many versions of b and a, depending on the calling sequence.
Access to non-locals • Needed to handle nested scoping. • Two methods: • Static links • Displays. • Will cover displays (and contrast them) later.
Static Link • Pointer to the most recent instance of the next statically enclosing procedure (see diagram). • Each instance of B points to the most recent version of A • Each instance of C points to the most recent version of B
Static Link (cont’d) • Compiler keeps track of nesting levels: • variableais at level 1, • variablebis at level 2, • variablecis at level 3. • To access a variable, subtract the variable's nesting depth from the current depth, and follow that many static links.
Examples • ForBto accessa, depth[B]-depth[a] = 2-1= 1; follow 1 static link. • ForCto accessb, depth[C]-depth[b] = 3-2= 1; follow 1 static link. • ForCto accessa, depth[C]-depth[a] = 3-1= 2; follow 2 static links.
Block Scoping • In the C language, execution blocks,delimited with{},define scopes. { int t; t = a; a = b; { float t=3.14; printf("%f",t); } b = t; }
Block Scoping (cont’d) • The variable's scope is limited to the{}block that contains its declaration. • Handled like ordinary local variables: • Space allocated in subroutine prologue (frame setup) • Deallocated in subroutine epilogue (frame destruction). • Compiler's symbol table keeps track of declarations.
Modular Scoping • First languages to incorporate information hiding. • Reduces "cognitive load" on programmers. • CIA principle: if a code segment doesn't need to know about an object, it shouldn't. • Tends to narrow (simplify) interfaces. • Aids in abstraction.
Modular Scoping (cont’d) • Modules allow encapsulation of objects. • Objects inside the module are visible to each other. • Objects inside are only visible outside if explicitly exported. • Objects outside not visible inside unless imported.
Modular Scoping (cont’d) • Various terms for modules: • Clu: clusters • Modula, Ada, Java: packages • C++: namespaces
Example (Pseudo Modula) module Zip; import A; export D; var t:real; proc D(); ... end; end Zip; module Zap; import b,D; export Q; proc Q(); ... end; proc R(); ... end; end Zap; module Zorch; export A,b; var b:integer; var c:real: proc A(); ... end end Zorch; • Procedure A can see b and c. • Procedure D can see A and t, but not b or c. • Procedures Q and R can see b and D, but not A, c, or t.
Module Types and Classes • In Modula-2, Turing, and Ada83, a module can define only one instance of the object (module as manager). • In Simula, Euclid, and ML, programmer can declare an arbitrary number of module objects (module as type).
Module Types and Classes (cont’d) • Historically, this led to classes (Smalltalk, Eiffel, C++, Java), and object-orientation. • Classes define types (abstraction). • Classes encapsulate object data and methods (encapsulation). • Classes hide information (information hiding). • Classes facilitate polymorphism and inheritance (polymorphism).
Symbol Tables • Compiler must keep track of declared names (type, variables, constants, etc.) • Table stores mapping of names to attributes. • Must enforce scope rules. Typical operations: • Enter a new name, with relevant information (type, components, etc.) • Lookup a name. Must return correct instance, in accordance with scope rules.
Symbol Tables (cont’d) • Open_scope. New scope must allow visibility of names in outer scopes, and redeclaration of names in new scope. • Close_scope. Probably non-destructively, without reclaiming space (need debugging info). Restore mapping of previous scope.
Symbol Tables (cont’d) • Must allow forward declarations (name used before it is declared) • Hash coded table, each entry a linked list of hash synonyms.
Example • LeBlanc-Cook symbol table (see text book) • Intrinsics added first (integer, real). • Situation depicts environment inwithstatement. • A2, F2andTare synonyms.
Example (cont’d) • Other mechanisms: Central Reference Tables. • Used to keep track of run-time environments. • Equivalent to RPAL's environment trees.
Binding of Reference Environments • Needed when passing a function/proc as a parameter. • Need subroutine closures: 4 items. • The fact that it is a function. • Functionality (prototype, parameters, etc.) • Pointer to body of fcn/proc. • Referencing environment (environment link in RPAL).
Binding of Reference Environments (cont’d) • In C, functions are second-class. • Can only pass function pointer (item 3) as a parameter. • Fcns/procs are first class in Lisp, ML, Haskell, RPAL, but not in Modula, Ada, C, C++, or Java. Some would argue they are, but ...
Overloading • Multiple meanings for the same name, context dependent. • Most languages allow it in some limited fashion, e.g. arithmetic operators (a+bfor ints and reals). • In C++, one can overload both functions and operators. Can only overload fcns in Java (may change, more later).
Pitfalls in Language Design • In Pascal, functions return values by assigning to the function name (no return statement). If the function name is redeclared, it becomes impossible to return a value. • Example: function f: integer; var f:integer; begin f := 10; // won't return 10 end;
Pitfalls in Language Design (cont’d) • Using an outer scope name, and then declaring it (maybe much later), is illegal in Pascal. Very expensive to check. const m = 0; procedure f; const n = m; { illegal use of m, } { m not yet declared.} ... m = 0; { scope of m is all } { of f } end;
Pitfalls in Language Design (cont’d) • The same applies to functions: procedure f; ... end; procedure A; procedure B; begin f; {intent is to call } {outer f. } end; {error: f used before} {it's declared } ... procedure f; ... end; end;
Pitfalls in Language Design (cont’d) • Some Pascal compilers (and most Pascal successors) specify that the scope of a declaration is limited to the remainder of (not the entire) block. • Confusingly, Pascal allows use of pointer types before they are declared: type aptr = ^a; a = record data: ...; next: aptr; end;
Pitfalls in Language Design (cont’d) • Modula-3 changed this: scope of name is still the entire block, but names need not be declared before they are used. • C, C++, Java have a mixed strategy: variables must be declared before they are used, but not type (class) names. Class names are visible over the entire containing module (package). • Separate compilation (read in book).
Scope Rules Programming Language Principles Lecture 16 Prepared by Manuel E. Bermúdez, Ph.D. Associate Professor University of Florida