4 Bindings and Scope. Bindings and environments. Scope, block structure, and visibility. Declarations. Blocks. 2004, D.A. Watt, University of Glasgow

Save this PDF as:
 WORD  PNG  TXT  JPG

Size: px
Start display at page:

Download "4 Bindings and Scope. Bindings and environments. Scope, block structure, and visibility. Declarations. Blocks. 2004, D.A. Watt, University of Glasgow"

Transcription

1 4 Bindings and Scope Bindings and environments. Scope, block structure, and visibility. Declarations. Blocks. 2004, D.A. Watt, University of Glasgow 1

2 Bindings and environments PL expressions and commands contain identifiers, which are declared elsewhere. Their meanings depend on these declarations. A binding is a (fixed) association between an identifier and an entity such as a value, variable, or procedure. Each declaration produces one or more bindings. An environment (or name space) is a set of bindings. Each expression or command is interpreted in a particular environment. Each identifier used in the expression or command must have a 2

3 Bindings in general Binding is used for many associations, usually an association (function) between a syntactical and a semantical entity 3

4 Binding time (1) Binding time is the moment in the development and deployment process when the binding is defined Possible binding times: Language design time Language implementation time Compile time Load time Runtime e.g., bind operator symbols to operations e.g., bind floating point type to a representation e.g., bind a variable to a type in C or Java e.g., bind a FORTRAN 77 variable to a memory cell (or a C static variable) e.g., bind a nonstatic local variable to a memory cell 4

5 Binding time (2) Def: A binding is static if it first occurs before run time and remains unchanged throughout program execution. Def: A binding is dynamic if it first occurs during execution or can change during execution of the program. 5

6 Example: Ada environments Ada program outline: procedure p is!!z: constant Integer := 0;!c: Character;!!procedure q (x: in Float) is! c: constant Float := 3.0e6;! b: Boolean;!begin!!end q;! begin! end p; Environment {" b a Boolean variable, s: " c the floating-point number , " p a procedure with no parameter, " q a procedure with a Float {" parameter, c a Character variable, "" p x a procedure Float variable, with no parameter, " z the integer 0 } " q a procedure with a Float parameter, 6

7 Scope The scope of a declaration (or of a binding) is the portion of the program text over which it has effect. In some early PLs (such as Cobol), the scope of each declaration was the whole program. In modern PLs, the scope of each declaration is controlled by the program s block structure. 7

8 Block structure A block is a program construct that delimits the scope of any declarations within it. Each PL has its own forms of blocks: C: block commands ({ }), function bodies, compilation units. Java: block commands, method bodies, class declarations, packages. Ada: block commands (declare begin end;), procedure bodies, packages, tasks, etc. A PL s block structure is the way in which blocks are arranged in the program text. 8

9 Example: Ada block structure Ada program outline: " procedure P is!! begin!!declare!!begin!!end;! end P;! procedure Q is! begin! end Q; 9

10 Monolithic block structure Some PLs (such as Cobol) have monolithic block structure: the whole program is a single block. The scope of every declaration is the whole program. declaration of declaration x of y declaration of z scope of declaratio ns of x, y, z 10

11 Flat block structure Some PLs (such as Fortran) have flat block structure: the program is partitioned into nonoverlapping blocks. declaration of x declaration of of y y scope of decl-aration of x scope of decl-aration of y declaration of of z z scope of decl-aration of z 11

12 Nested block structure Modern PLs have nested block structure: blocks may be nested within other blocks. declaration of x declaration of y declaration of z scope of decl-aration of x scope of decl-aration of y scope of decl-aration of z 12

13 Scope and visibility A binding occurrence of identifier I is an occurrence of I where I is bound to some entity X. An applied occurrence of identifier I is an occurrence of I where use is made of the entity X to which I is bound. At this applied occurrence, we say that I denotes X. If the PL is statically scoped (see later), every applied occurrence of I should correspond to exactly one binding occurrence of I. 13

14 Example: Ada binding and applied occurrences Ada program outline: procedure p is!! z : constant Integer := 0;!c : Character;!!procedure q (x : in Float) is! c : constant Float := 3.0e6;! b : Boolean;!begin! b c x z!end q;! begin! c z end p; 14

15 Hiding If identifier I is declared in two different blocks, I denotes a different entity in each block. If identifier I is declared in two nested blocks, I denotes one entity in the outer block and a different entity in the inner block. The inner declaration hides the outer one. declaration of x declaration of x declaration of x declaration of x Here the outer declaration of x is hidden. 15

16 Static vs dynamic scoping (1) A PL is statically scoped if the body of a procedure is executed in the environment of the procedure definition. We can decide at compile-time which binding occurrence of an identifier corresponds to a given applied occurrence. A PL is dynamically scoped if the body of a procedure is executed in the environment of the procedure call. We cannot decide until run-time which binding occurrence of an identifier corresponds to a given applied occurrence, since the environment may vary from one procedure call to another. 16

17 Example: static vs dynamic scoping (1) Program in Ada (which is statically scoped): s : constant Integer := 2;! function f (x : Integer) return Integer is begin!return s * x; end f;! procedure q (y : Integer) is begin!put(f(y)); end q;! procedure q (z : Integer) is!s : constant Integer := 3; begin!put(f(z)); end q; The value of s here is always 2. 17

18 Example: static vs dynamic scoping (2) Same program in a hypothetical dynamically scoped PL: s : constant Integer := 2;! function f (x : Integer) return Integer The value is of begin s here!return s * x; depends on end f; the call site.! procedure q (y : Integer) is begin!put(f(y)); end q;! procedure q (z : Integer) is!s : constant Integer := 3; begin!put(f(z)); end q; multiplies value of y by 2 multiplies value of z by 3 18

19 Static vs dynamic scoping (2) Dynamic scoping fits badly with static typing. In the previous slide, what if the two declarations of s had different types? Nearly all PLs (including C, Java, and Ada) are statically scoped. Only a few PLs (such as Smalltalk and Lisp) are dynamically scoped. Natural language has both: Yesterday he said: I will come tomorrow. (static scoping) Yesterday he said that he would come today. (dynamic scoping) 19

20 Declarations (1) A declaration is a program construct that will be elaborated to produce binding(s). A declaration may have side effects (such as creating a variable). A definition is a declaration whose only effect is to produce binding(s). 20

21 Declarations (2) Forms of declarations: type declarations constant declarations variable declarations procedure definitions collateral declarations sequential declarations recursive declarations. The repertoire of simple declarations depends on the PL. 21

22 Type declarations A type declaration binds an identifier to a type. A type definition binds an identifier to an existing type. Alternatively, a type declaration may introduce a new type, distinct from all existing types. 22

23 Example: C type declarations typedef binds an identifier to an existing type: typedef char* Alpha; Alpha s; char* t; s = t; bound to exist-ing type char* legal " But enum, struct, or union binds an identifier to a new type:! struct Book {Alpha title, int edition}; struct Author {Alpha name, int age}; Book b; Author a; bound to new a = b; types illega l 23

24 Example: Ada type declarations Every Ada type declaration introduces a new and distinct type: type Alpha is array (1.. 32) of Character;! type Book is record!! title: Alpha;!! edition: Integer;! end record; type Author is record!! name: Alpha;!! age: Integer;! end record; b: Book; a: Author; a := b; bound to new types illega l 24

25 Constant declarations A constant declaration binds an identifier to a (constant) value. In Ada, a constant declaration has the form: I : constant T := E; This binds I to the value of the expression E, which must be of type T. Some PLs restrict the expression E to be a literal, or an expression that can be evaluated at compile-time. Some PLs restrict the constant s type T. 25

26 Variable declarations A variable declaration binds an identifier to a variable. In Ada, ordinary variable declarations have the form: I : T := E; This creates a variable of type T, binds I to that variable, and initialises it to the value of the expression E. In Ada, renaming variable declarations have the form: I : T renames V; This binds I to the existing variable V. 26

27 Example: Ada renaming variable declaration Ada code:! type Country is (UK, FR, ); pop : array (Country) of Natural;! declare!c : Country := ;!p : Integer renames pop(c); begin!!p := p + 1;! end; bound to existing variable pop(c) more efficient than pop(c) := pop(c) + 1; 27

28 Procedure definitions A procedure definition binds an identifier to a procedure. In most PLs, we can define both proper procedures and function procedures. 28

29 Example: Ada procedure definitions Function procedure definition:! function even (n: Integer) return Boolean is begin!return (n mod 2 = 0); bound to a function end; proced-ure that tests whether its Integer argument is even " Proper procedure definition:! procedure double (n: in out Integer) is begin!n := n * 2; bound to a proper end; proced-ure that doubles its Integer argument 29

30 Collateral declarations A collateral declaration is a group of subdeclarations that are elaborated independently of one another. A subdeclaration may not use bindings produced by any other subdeclaration. Collateral declarations are found in Java and functional PLs, but not in C or Ada. 30

31 Sequential declarations A sequential declaration is a group of subdeclarations that are elaborated one after another. A subdeclaration may use bindings produced by previous subdeclarations, but not those produced by following subdeclarations. Sequential declarations are found in all imperative and OO PLs. 31

32 Recursive declarations A recursive declaration is one that uses the bindings it produces itself. Ada type declarations: A single type declaration may be recursive. A sequence of type declarations may be made mutually recursive, if preceded by incomplete type declarations. Ada procedure declarations: similarly. Java method definitions: One or more method definitions may be (mutually) recursive. 32

33 Example: Ada recursive type declarations Mutually recursive type declarations:! type IntNode; type IntList is access IntNode; type IntNode is record!! head: Integer;!! tail: IntList;! end record; incomplete type declaration: binds IntNode to an completes unknown type the binding of IntNode 33

34 Example: Ada recursive procedure definitions (1) Recursive procedure definition:! procedure print (n: Natural) is begin!if n < 10 then! put(digit(n));!else! print(n/10);! put(digit(n mod 10));!end if; end; 34

35 Example: Ada recursive procedure definitions (2) Mutually recursive procedure definitions: procedure parse_expression;! procedure parse_primary is begin!if acceptable('(') loop! accept('(');! parse_expression;! accept(')');!else! parse_variable;!end if; end; binds parse_ expression to an unknown procedure 35

36 Example: Ada recursive procedure definitions (3) Mutually recursive procedure definitions (continued):! procedure parse_expression is begin!parse_primary;!while acceptable('+') loop! accept('+');! parse_primary;!end loop; end; completes the binding of parse_ expression 36

37 Blocks A block is a program construct that delimits the scope of any declarations within it. Kinds of blocks: block commands block expressions. 37

38 Block commands A block command is a form of command that contains a local declaration (or group of declarations) D and a subcommand C. The bindings produced by D are used only for executing C. These bindings override any bindings for the same identifiers in the environment outside the block. Block commands are common in imperative and OO PLs. In C and Java: { D C } In Ada: 38

39 Example: Java block command To sort the values of int variables x and y into ascending order:! if (x > y) {! int z = x;!x = y;!y = z; } block command (scope of declaration of z) 39

40 Block expressions A block expression is a form of expression that contains a local declaration (or group of declarations) D and a subexpression E. The bindings produced by D are used only for evaluating E. These bindings override any bindings for the same identifiers in the environment outside the block. Block expressions are uncommon in imperative and OO PLs, but common in functional PLs. Form of block expression in Haskell: let D in E 40

41 Example: Haskell block expression To compute the area of a triangle whose sides have lengths a, b, c:! let!s = (a + b + c)/2.0 in!sqrt(s*(s-a)*(s-b)*(s-c)) The only way to achieve the same effect in Ada (or C) is to declare and call a suitable function:! function area (a, b, c: Float)! return Float is!s: constant Float := (a + b + c)/2.0; begin!return sqrt(s*(s-a)*(s-b)*(s-c)); end; 41