Presentation is loading. Please wait.

Presentation is loading. Please wait.

1 Names, Scopes and Bindings and Bindings. 2 High-level programming languages High-level features relative to assembly language High-level features relative.

Similar presentations


Presentation on theme: "1 Names, Scopes and Bindings and Bindings. 2 High-level programming languages High-level features relative to assembly language High-level features relative."— Presentation transcript:

1 1 Names, Scopes and Bindings and Bindings

2 2 High-level programming languages High-level features relative to assembly language High-level features relative to assembly language ‘Highness’ = degree of abstraction ‘Highness’ = degree of abstraction machine independence machine independence efficient implementation does not depend on a specific machine instruction set efficient implementation does not depend on a specific machine instruction set relatively easy goal relatively easy goal ease of programming ease of programming hard goal hard goal more aesthetics, trial and error than science ? more aesthetics, trial and error than science ? Programming language design Programming language design find the right abstractions find the right abstractions

3 3 Name Mnemonic character string to represent something else Mnemonic character string to represent something else usually identifiers usually identifiers some languages allow names like ‘+’ & ‘:=‘ some languages allow names like ‘+’ & ‘:=‘ Enables programmers to Enables programmers to refer to variables etc. using refer to variables etc. using symbolic names rather than symbolic names rather than low-level hardware addresses abstract their control and data structures abstract their control and data structures express purpose or function instead of implementation express purpose or function instead of implementation make programs manageable make programs manageable control abstraction: subroutines control abstraction: subroutines data abstraction: classes (for example) data abstraction: classes (for example)

4 4 Binding & Binding Time... Binding Binding an association between a name and the thing that is named an association between a name and the thing that is named Binding time Binding time the time at which an implementation decision is made to create a binding the time at which an implementation decision is made to create a binding Language design time Language design time the design of specific program constructs (syntax) the design of specific program constructs (syntax) primitive types primitive types meaning (semantics) meaning (semantics) Language implementation time Language implementation time fixation of implementation constants such as fixation of implementation constants such as numeric precision numeric precision run-time memory sizes run-time memory sizes max identifier name length max identifier name length number and types of built-in exceptions, etc. number and types of built-in exceptions, etc.

5 5...Binding times Program writing time Program writing time programmer’s choice of algorithms and data structures programmer’s choice of algorithms and data structures Compile time Compile time translation of high-level constructs to machine code translation of high-level constructs to machine code choice of memory layout for objects choice of memory layout for objects Link time Link time multiple object codes (machine code files) and libraries are combined into one executable multiple object codes (machine code files) and libraries are combined into one executable Load time Load time operating system loads the executable in memory operating system loads the executable in memory Run time Run time program executes program executes

6 6 Nature of bindings Static: things bound before execution Static: things bound before execution Dynamic: execution-time bindings Dynamic: execution-time bindings Early binding Early binding efficiency (e.g. addressing a global variable in C) efficiency (e.g. addressing a global variable in C) languages tend to be compiled languages tend to be compiled Late binding Late binding flexibility (e.g. polymorphism in Smalltalk) flexibility (e.g. polymorphism in Smalltalk) languages tend to be interpreted languages tend to be interpreted Our current interest Our current interest binding of identifiers to variables they name binding of identifiers to variables they name note: all data has not to be named (e.g. dynamic storage) note: all data has not to be named (e.g. dynamic storage)

7 7 Things we have to keep track of distinguish between names and objects they refer to creation creation of objects of objects of bindings of bindings references to variables etc. (which use bindings) references to variables etc. (which use bindings) deactivation and reactivation of bindings deactivation and reactivation of bindings destruction destruction of bindings of bindings of objects of objects If we don’t keep good track of them we get If we don’t keep good track of them we get garbage: object that outlives it's binding and garbage: object that outlives it's binding and dangling references: bindings that outlive their objects dangling references: bindings that outlive their objects

8 8 Lifetime Binding lifetime Binding lifetime time between the creation and destruction time between the creation and destruction Object lifetime Object lifetime defined similarly, but not necessarily the same as binding lifetime defined similarly, but not necessarily the same as binding lifetime e.g. objects passed as reference parameters e.g. objects passed as reference parameters generally corresponds to the storage allocation mechanism that is used to allocate/deallocate object’s space generally corresponds to the storage allocation mechanism that is used to allocate/deallocate object’s space

9 9 Storage allocation Static objects Static objects have absolute (and same) address through the program execution have absolute (and same) address through the program execution space is ‘part of the program’ space is ‘part of the program’ Stack objects Stack objects allocated/deallocated in LIFO order (usually) in conjunction of subroutine calls/exits allocated/deallocated in LIFO order (usually) in conjunction of subroutine calls/exits Heap objects Heap objects can be allocated/deallocated at arbitrary times can be allocated/deallocated at arbitrary times storage management more complex than with stack storage management more complex than with stack

10 10 Static objects Global variables Global variables Translated machine code Translated machine code subroutine locations in particular subroutine locations in particular Constants Constants large ones in ‘constant pool’ large ones in ‘constant pool’ small ones stored as part of instructions small ones stored as part of instructions Subroutine variables that are declared static Subroutine variables that are declared static Run-time support tables (produced by the compiler) Run-time support tables (produced by the compiler) symbol table, dynamic type checking, exception handling, garbage collection,... symbol table, dynamic type checking, exception handling, garbage collection,... Note: processor-supported memory protection is possible for constant data Note: processor-supported memory protection is possible for constant data read-only memory (e.g., instructions, constants, tables) read-only memory (e.g., instructions, constants, tables)

11 11 Static or non? Local variables in non-recursive languages Local variables in non-recursive languages e.g. early Fortran e.g. early Fortran all data (subroutines included) can be allocated statically all data (subroutines included) can be allocated statically pros: faster execution pros: faster execution cons: wastes space, bad programming practices cons: wastes space, bad programming practices Local constants Local constants compile-time constants can be allocated statically compile-time constants can be allocated statically elaboration-time constants must be allocated from stack elaboration-time constants must be allocated from stack each invocation may have a different value each invocation may have a different value

12 12 Other information associated with subroutines Arguments and return values Arguments and return values compilers try to place these in registers if possible compilers try to place these in registers if possible if not, then the stack is used if not, then the stack is used Temporary variables Temporary variables hold intermediate values of complex calculations hold intermediate values of complex calculations registers / stack registers / stack Bookkeeping information Bookkeeping information return address (dynamic link) return address (dynamic link) saved registers (of the caller) saved registers (of the caller)......

13 13

14 14 Why a stack? Subroutine call / return is ‘stack-like’ Subroutine call / return is ‘stack-like’ stack is the natural data structure to support data allocation & deallocation stack is the natural data structure to support data allocation & deallocation Allows recursion Allows recursion several instances of same subroutine can be active several instances of same subroutine can be active Allows re-using space Allows re-using space even when no recursion is used even when no recursion is used

15 15 Maintaining the stack Each subroutine call creates a stack frame Each subroutine call creates a stack frame a.k.a activation record a.k.a activation record bottom of the frame: arguments and returns bottom of the frame: arguments and returns easy access for the caller easy access for the caller always at same offset always at same offset top of the frame: local variables & temps top of the frame: local variables & temps compiler decides relative ordering compiler decides relative ordering Maintenance of stack is done by (see Section 8.2) Maintenance of stack is done by (see Section 8.2) prologue & epilogue in the subroutine prologue & epilogue in the subroutine saves space to do much here saves space to do much here calling sequence in the caller calling sequence in the caller instructions immediately before/after call/return instructions immediately before/after call/return may save time to do much here may save time to do much here interprocedural optimizations possible interprocedural optimizations possible

16 16 Addressing stack objects Offsets of variables within a frame can be decided at compile-time Offsets of variables within a frame can be decided at compile-time Locations of frames themselves may vary during execution Locations of frames themselves may vary during execution Many machines have Many machines have a special frame pointer register (fp) a special frame pointer register (fp) load/store instructions supporting indirect addressing via fp load/store instructions supporting indirect addressing via fp Address = fp + offset (Fig. 3.2) Address = fp + offset (Fig. 3.2) locals, temps: negative offset locals, temps: negative offset arguments, returns: positive offset arguments, returns: positive offset stack grows ‘downward’ from high addresses to low ones stack grows ‘downward’ from high addresses to low ones push/pop instructions to manipulate both fp and data push/pop instructions to manipulate both fp and data

17 17

18 18 Heap-Based allocation Heap is here not a priority queue Heap is here not a priority queue region of storage to support allocation/deallocation at arbitrary times region of storage to support allocation/deallocation at arbitrary times necessity for dynamic data structures necessity for dynamic data structures dynamically allocated pieces of linked data structures dynamically allocated pieces of linked data structures dynamically resized objects, e.g., fully general character strings, lists, sets dynamically resized objects, e.g., fully general character strings, lists, sets Many space-management strategies Many space-management strategies a part of your data structures course? a part of your data structures course? space & speed concerns; tradeoffs space & speed concerns; tradeoffs space: internal & external fragmentation space: internal & external fragmentation Internal Internal allocation of a block larger than required allocation of a block larger than required happens because of standard-sized blocks happens because of standard-sized blocks External External blocks are scattered around the heap blocks are scattered around the heap lot of free space but in small pieces lot of free space but in small pieces

19 19 Maintain all unallocated blocks in one list Maintain all unallocated blocks in one list a.k.a free list a.k.a free list at each allocation request, look for a block of appropriate size at each allocation request, look for a block of appropriate size Strategies Strategies First-fit: return first large enough First-fit: return first large enough Best-fit: return smallest block large enough Best-fit: return smallest block large enough Neither is better than other (depends on requests) Neither is better than other (depends on requests) Both cases: Both cases: if the block found is much larger than the request, split it in 2 and return the other half to free list if the block found is much larger than the request, split it in 2 and return the other half to free list Deallocation Deallocation add to free list and merge with adjacent regions if possible add to free list and merge with adjacent regions if possible

20 20 Reducing allocation time Scanning the free list Scanning the free list takes linear time in the # of free blocks takes linear time in the # of free blocks maintain separate lists for different (standard) sizes maintain separate lists for different (standard) sizes Fast allocation Fast allocation find appropriate size (constant time) find appropriate size (constant time) return the first block (constant time) return the first block (constant time) Buddy systems & Fibonacci heaps Buddy systems & Fibonacci heaps block sizes powers of 2 or Fibo numbers block sizes powers of 2 or Fibo numbers

21 21 Garbage collection External fragmentation can not be avoided External fragmentation can not be avoided ‘checkerboard’ the heap ‘checkerboard’ the heap we end up with a situation where we end up with a situation where we have a lot of free space we have a lot of free space but no blocks large enough but no blocks large enough  heap must be compacted by moving the allocated blocks  heap must be compacted by moving the allocated blocks complicated because all the references to these blocks must be updated, too! complicated because all the references to these blocks must be updated, too!

22 22 Explicit and implicit deallocation Allocation is always triggered by some program action Allocation is always triggered by some program action Deallocation can be either Deallocation can be either explicit explicit Pascal, C Pascal, C simple, efficient, immediate simple, efficient, immediate allows ‘hand-tailored’ storage management allows ‘hand-tailored’ storage management or implicit or implicit Java, C++, functional languages Java, C++, functional languages garbage collector starts whenever space gets low garbage collector starts whenever space gets low complex, time-consuming complex, time-consuming

23 23 GC or not to GC? Explicit memory management is more efficient Explicit memory management is more efficient But But manual deallocation errors are among the most common and costly bugs manual deallocation errors are among the most common and costly bugs too soon deallocation  dangling references too soon deallocation  dangling references forgotten deallocation  memory leaks forgotten deallocation  memory leaks Automatic GC is considered an essential feature of modern languages Automatic GC is considered an essential feature of modern languages GC algorithms have improved GC algorithms have improved implementations are more complex in general (so adding GC plays not a big role) implementations are more complex in general (so adding GC plays not a big role) large applications make benefits of GC greater large applications make benefits of GC greater

24 24 Scope Scope (of a binding) Scope (of a binding) the (textual) part of the program where the binding is active the (textual) part of the program where the binding is active Scope (in general) is a Scope (in general) is a program section of maximal size in which program section of maximal size in which no bindings change or at least no bindings change or at least no re-declarations are permitted no re-declarations are permitted Lifetime and scope are not necessarily the same Lifetime and scope are not necessarily the same

25 25 Elaboration Subroutine entrance  new scope opens Subroutine entrance  new scope opens create bindings for new local variables create bindings for new local variables deactivate bindings for global variables that are redeclared deactivate bindings for global variables that are redeclared Subroutine exit  scope closes Subroutine exit  scope closes destroy bindings for local variables destroy bindings for local variables reactivate bindings for global variables that were deactivated reactivate bindings for global variables that were deactivated Elaboration Elaboration process of creating bindings when entering a new scope process of creating bindings when entering a new scope also other tasks, for example in Ada: also other tasks, for example in Ada: storage allocation storage allocation starting tasks (processes) starting tasks (processes) propagating exceptions propagating exceptions

26 26 Scope rules Referencing environment of a statement Referencing environment of a statement the set of active bindings the set of active bindings corresponds to a collection of scopes that are examined (in order) to find a binding corresponds to a collection of scopes that are examined (in order) to find a binding Scope rules Scope rules determine that collection and its order determine that collection and its order Static (lexical) scope rules Static (lexical) scope rules scope is defined in terms of the physical (lexical) structure of the program scope is defined in terms of the physical (lexical) structure of the program typically the most recent (active) binding is chosen typically the most recent (active) binding is chosen we study mostly (and first) these here we study mostly (and first) these here Dynamic scope rules Dynamic scope rules bindings depend on the current state of program execution bindings depend on the current state of program execution

27 27 Static scope Related to program structure Related to program structure Basic: one scope (static & global) Basic: one scope (static & global) Fortran: global & local scopes Fortran: global & local scopes COMMON blocks COMMON blocks aim: share global data in separately compiled subroutines aim: share global data in separately compiled subroutines typing errors possible typing errors possible EQUIVALENCE of variables EQUIVALENCE of variables aim: share (and save) space aim: share (and save) space predecessor of variant/union types predecessor of variant/union types lifetime of a local variable? lifetime of a local variable? semantically: execution of the subroutine semantically: execution of the subroutine possible to SAVE variables (static allocation) possible to SAVE variables (static allocation) in practice all variables may behave as if SAVEd  bad programming in practice all variables may behave as if SAVEd  bad programming

28 28 Nested program structure Subroutines within subroutines within... Subroutines within subroutines within...  scopes within scopes within...  scopes within scopes within... thing X declared inside a subroutine  thing X is not visible outside that subroutine thing X declared inside a subroutine  thing X is not visible outside that subroutine Algol 60, Pascal, Ada,... Algol 60, Pascal, Ada,... Resolving bindings Resolving bindings closest nested scope rule closest nested scope rule subsequent declarations may hide surrounding ones (temporarily) subsequent declarations may hide surrounding ones (temporarily) built-in/predefined bindings: special outmost scope built-in/predefined bindings: special outmost scope Example in Figure 3.4 Example in Figure 3.4

29 29 Non-local references Nested subroutine may refer to objects declared in other subroutines (surrounding it) Nested subroutine may refer to objects declared in other subroutines (surrounding it) example 3.4: P3 can access A1, X and A2 example 3.4: P3 can access A1, X and A2 how to access these objects (they are in other stack frames)? how to access these objects (they are in other stack frames)?  need to find the corresponding frame at run-time  need to find the corresponding frame at run-time Difficulty Difficulty deeply nested routine (like P3) can call any visible routine (P1) deeply nested routine (like P3) can call any visible routine (P1)  caller’s scope is not (always) the lexically surrounding scope  caller’s scope is not (always) the lexically surrounding scope however, that surrounding scope must have a stack frame somewhere below in the stack however, that surrounding scope must have a stack frame somewhere below in the stack we can get to P3 only by making it visible first we can get to P3 only by making it visible first P3 gets visible after P1 & P2 have been called P3 gets visible after P1 & P2 have been called

30 30

31 31 Accessing non-local stack objects Parent frame Parent frame most recent invocation of the lexically surrounding subroutine most recent invocation of the lexically surrounding subroutine Augment stack frame with static link Augment stack frame with static link pointer to parent frame pointer to parent frame outermost frame: parent = nil outermost frame: parent = nil links form a static chain through all scopes links form a static chain through all scopes Accessing Accessing routine at nesting depth k refers to an object at depth j routine at nesting depth k refers to an object at depth j follow k - j static links (k - j is known at compile-time) follow k - j static links (k - j is known at compile-time) use offset in that ancestor frame as usual use offset in that ancestor frame as usual Figure 3.5 Figure 3.5

32 32

33 33 Holes in scopes Name-object binding N-O1 Name-object binding N-O1 hidden by a nested declaration N-O2 hidden by a nested declaration N-O2 has a hole in it’s scope (for the lifetime of that nested declaration) has a hole in it’s scope (for the lifetime of that nested declaration) object O1 is inaccessible via N object O1 is inaccessible via N Scope resolution operators Scope resolution operators allow programmer to explicitly use ‘hidden’ bindings allow programmer to explicitly use ‘hidden’ bindings a.k.a qualifiers a.k.a qualifiers Ada: My_Proc.X ( X declared in My_Proc ) Ada: My_Proc.X ( X declared in My_Proc ) C++: ::X (global X) C++: ::X (global X)

34 34 Scopes without subroutines Variable definitions in block statements Variable definitions in block statements either at the beginning of the block or either at the beginning of the block or Algol, C, Ada Algol, C, Ada{ int temp = a; a = b; b = temp; } anywhere where a statement may appear anywhere where a statement may appear C++, Java C++, Java scope extends to the end of the current block scope extends to the end of the current block space allocated from the stack frame space allocated from the stack frame no extra runtime operations needed no extra runtime operations needed space saved by letting allocations overlap each other space saved by letting allocations overlap each other

35 35 Re-declaring bindings Change bindings ‘on the fly’ Change bindings ‘on the fly’ e.g. to fix bugs (rapid prototyping) e.g. to fix bugs (rapid prototyping) interactive languages interactive languages New meaning replaces the old one immediately everywhere New meaning replaces the old one immediately everywhere implemented using some search structure (name  meaning) implemented using some search structure (name  meaning) Problems with ‘half-compiled’ languages (ML) Problems with ‘half-compiled’ languages (ML) old (compiled) bindings may be preserved old (compiled) bindings may be preserved in subroutines that are already elaborated (using the old binding) in subroutines that are already elaborated (using the old binding)

36 36 Modules Great tool to divide programming effort Great tool to divide programming effort information hiding information hiding details are visible only to parts that really need them details are visible only to parts that really need them reduces the ‘cognitive load’ of programmers reduces the ‘cognitive load’ of programmers minimize the amount of information required to understand any part of the system minimize the amount of information required to understand any part of the system changes & updates localized within single modules changes & updates localized within single modules Other benefits Other benefits reduces name clashes reduces name clashes data integrity: only routines inside a module update certain object data integrity: only routines inside a module update certain object errors are localized errors are localized

37 37 Information hiding using subroutines? Hiding is limited to objects defined inside a routine Hiding is limited to objects defined inside a routine lifetime = execution of the routine lifetime = execution of the routine Partial solution: use static local objects Partial solution: use static local objects C: static, Algol: own,... C: static, Algol: own,... Example: Figure 3.6 Example: Figure 3.6 ‘subroutines with memory’ ‘subroutines with memory’ ‘single-routine data abstractions’ ‘single-routine data abstractions’

38 38

39 39 Module: multiple-routine abstraction Combine and hide several routines & data structures Combine and hide several routines & data structures e.g. stack type, push and pop operations e.g. stack type, push and pop operations Ada: package, Clu: cluster, Modula-2: module Ada: package, Clu: cluster, Modula-2: module objects inside a module are objects inside a module are visible to each other visible to each other not visible to the outside unless explicitly exported not visible to the outside unless explicitly exported objects outside a module are objects outside a module are not visible to the inside unless explicitly imported not visible to the inside unless explicitly imported Example: Figure 3.7 Example: Figure 3.7

40 40

41 41 Modules and bindings Bindings made inside a module Bindings made inside a module are inactive outside of it are inactive outside of it but not destroyed but not destroyed module-level objects have ‘same lifetime they would have without the enclosing module’ module-level objects have ‘same lifetime they would have without the enclosing module’ same as the scope they appear in same as the scope they appear in Restrictions on export declarations Restrictions on export declarations possible in many module-based languages possible in many module-based languages variables exported read-only variables exported read-only types exported as opaque (Modula-2) types exported as opaque (Modula-2) variables of the type may be declared, passed as arguments to the module’s subroutines, possibly compared or assigned to each other variables of the type may be declared, passed as arguments to the module’s subroutines, possibly compared or assigned to each other

42 42 Headers and bodies Modules are often divided into Modules are often divided into header/declaration part header/declaration part definitions for users of the module definitions for users of the module the public interface of the module the public interface of the module may also contain private information (for compilation) may also contain private information (for compilation) body/implementation part body/implementation part definitions for the implementation of the module definitions for the implementation of the module Header and body parts can be compiled separately Header and body parts can be compiled separately especially header can be compiled even if body does not exist (yet) especially header can be compiled even if body does not exist (yet) and so can the users of the header and so can the users of the header total recompilation unnecessary if only some modules are updated total recompilation unnecessary if only some modules are updated

43 43 Open and closed scopes Open scope Open scope no imports required (scope rules apply) no imports required (scope rules apply) Ada packages, nested subroutines in most Algol family languages Ada packages, nested subroutines in most Algol family languages Closed scope Closed scope all names must be explicitly imported all names must be explicitly imported Modula-2 modules, Euclid subroutines Modula-2 modules, Euclid subroutines Clu: nonlocal references not possible Clu: nonlocal references not possible import lists import lists document the program (nonlocal references are part of the interface) document the program (nonlocal references are part of the interface) help the compiler to detect aliasing (Euclid, Turing) help the compiler to detect aliasing (Euclid, Turing)

44 44 Aliasing Alias Alias extra name for something that already has a name (in the current scope) extra name for something that already has a name (in the current scope) we may have several we may have several How are they created? How are they created? Fortran: explicit declarations (equivalence) Fortran: explicit declarations (equivalence) variant/union structures variant/union structures languages using pointers languages using pointers reference parameters reference parameters They are considered bad because They are considered bad because they create confusion and hard-to-track errors (Fig. 3.8) they create confusion and hard-to-track errors (Fig. 3.8) compilers can optimize much better if they know there’s no aliasing compilers can optimize much better if they know there’s no aliasing

45 45

46 46 Type manager modules Modules support ‘naturally’ only the creation of one single instance of a given abstraction Modules support ‘naturally’ only the creation of one single instance of a given abstraction Figure 3.7 creates only one stack Figure 3.7 creates only one stack  replicate code?  replicate code? Alternative organization Alternative organization module is a manager for the instances of the type it implements (Fig. 3.9) module is a manager for the instances of the type it implements (Fig. 3.9) additional routines to create/destroy instances additional routines to create/destroy instances additional parameter to each operation (the object in question) additional parameter to each operation (the object in question) Clu: every module is a manager of some type Clu: every module is a manager of some type

47 47

48 48 Module types Each module creates a new type Each module creates a new type possible to declare (any number of) variables of that type possible to declare (any number of) variables of that type Euclid, Simula, Clu Euclid, Simula, Clu Automatic Automatic initialization code and initialization code and finalization code (e.g. to return objects to heap) finalization code (e.g. to return objects to heap) Types and their operations are tightly bound to each other Types and their operations are tightly bound to each other operations ‘belong’ to objects of the module type operations ‘belong’ to objects of the module type conceptually conceptually type approach has a separate push for every stack type approach has a separate push for every stack manager approach has one parameterized push for all stacks manager approach has one parameterized push for all stacks same implementation in practice same implementation in practice

49 49

50 50 Classes Object-oriented programming Object-oriented programming Module types augmented with inheritance mechanism Module types augmented with inheritance mechanism possible to define new modules ‘on top’ of existing ones (refinements, extensions) possible to define new modules ‘on top’ of existing ones (refinements, extensions) objects inherit operations of other objects (no need to rewrite the code) objects inherit operations of other objects (no need to rewrite the code)

51 51 Module types and scopes Note: applies also to classes if we forget inheritance Note: applies also to classes if we forget inheritance Every instance A of a module type has Every instance A of a module type has a separate copy of the module variables which are visible when executing one of A’s operations Indirect visibility (within same type) Indirect visibility (within same type) the instance variables of B may be visible the instance variables of B may be visible to another instance A of the same type if B is passed as a parameter of A’s operation  binary operations of C++  binary operations of C++ opinions vary whether this is a good thing or not opinions vary whether this is a good thing or not

52 52 … Classes an extension of module type an extension of module type inheritance: new classes extensions or refinements of existing inheritance: new classes extensions or refinements of existing operations belonging to objects, new objects can inherit operations operations belonging to objects, new objects can inherit operations example C++ example C++ class stack { … bool deeper ( stack other ) { // function declaration return ( top > other.top ) ; }…}… if ( A.deeper(B)) … in object-oriented langauages in object-oriented langauages roots in Simula-67, Smalltalk, Eiffel, C++, Java in non-object oriented in non-object oriented Modula-3, Ada 95, Oberon

53 53 Dynamic scope... Name-object binding decided at run-time Name-object binding decided at run-time usually the last active declaration usually the last active declaration thus, derived from the order in which subroutines are called (Fig. 3.10) thus, derived from the order in which subroutines are called (Fig. 3.10) flow of control is unpredictable  compilation impossible flow of control is unpredictable  compilation impossible Example languages Example languages early functional languages (Lisp) early functional languages (Lisp) Perl (v5.0 gives also static scope) Perl (v5.0 gives also static scope) environment variables in command shells environment variables in command shells

54 54...Dynamic scope Dynamic scope  dynamic semantics Dynamic scope  dynamic semantics type checking in expressions and parameter passing must be deferred to run-time type checking in expressions and parameter passing must be deferred to run-time Simple implementation Simple implementation maintain declarations in a stack maintain declarations in a stack search stack top  bottom to find bindings search stack top  bottom to find bindings push/pop bindings when entering/leaving subroutines push/pop bindings when entering/leaving subroutines quite slow quite slow

55 55

56 56 Dynamic scope is a bad idea? Cons Cons High run-time costs High run-time costs Non-local references are ‘unpredictable’ Non-local references are ‘unpredictable’ Dynamic programs are hard to understand Dynamic programs are hard to understand

57 57 Pros Pros Easy to customize subroutines ‘on the fly’ Easy to customize subroutines ‘on the fly’ book example book example print integers in different bases print integers in different bases base = non-local (dynamic) reference base = non-local (dynamic) reference 1. begin -- nested block print_base : integer := 16 -- use hexadecimal print_base : integer := 16 -- use hexadecimal print_integer (n) print_integer (n) 2. begin -- nested block print_base_save : integer := print_base print_base := 16 -- use hexadecimal print_integer (n) print_base := print_base_save

58 58 Simulating dynamic scope Workaround 1 Workaround 1 make separate routines for separate cases make separate routines for separate cases default parameters (Ada)  one interface default parameters (Ada)  one interface overloading (C++)  same name overloading (C++)  same name but: calls made under the emulated ‘dynamic scope’ do not ‘inherit’ the mimicked non-local binding but: calls made under the emulated ‘dynamic scope’ do not ‘inherit’ the mimicked non-local binding Workaround 2 Workaround 2 use a global/static variable instead of a non-local reference use a global/static variable instead of a non-local reference store/restore before/after use of the routine store/restore before/after use of the routine

59 59 Symbol tables a data abstraction used in statically scoped programs a data abstraction used in statically scoped programs maps names into the information the compiler knows about them maps names into the information the compiler knows about them insert – to place a new mapping (name to object binding) insert – to place a new mapping (name to object binding) lookup – to retrieve nondestructively the information on a given name lookup – to retrieve nondestructively the information on a given name insert when entering a scope, remove when leaving a scope, impractical insert when entering a scope, remove when leaving a scope, impractical inner declarations may hide outer, so arbitrary number of mapping for a name needed inner declarations may hide outer, so arbitrary number of mapping for a name needed records, nested, but fields become suddenly visible or invisible records, nested, but fields become suddenly visible or invisible names used before declared names used before declared Algol 60, 68, forward references to labels Pascal and other, forward declarations of subroutines, support mutual recursion

60 60 symbolic debugger has access to the table, the table saved completelly symbolic debugger has access to the table, the table saved completelly enter_scope and leave_scope to keep track of visibility enter_scope and leave_scope to keep track of visibility Le Blanc - Cook Le Blanc - Cook scopes are given successive numbers (0, 1,...) as they are encountered scopes are given successive numbers (0, 1,...) as they are encountered names into a single hash table names into a single hash table entries are the symbol name, category (variable, constant, type, procedure, field name, parameter,...), scope number, type (a pointer to another symbol table entry), for imports/exports pointers to the real entries... entries are the symbol name, category (variable, constant, type, procedure, field name, parameter,...), scope number, type (a pointer to another symbol table entry), for imports/exports pointers to the real entries... scope stack scope stack indicates, in order, the scopes that comprise the current referencing environment indicates, in order, the scopes that comprise the current referencing environment entries contain the scope number, closed/opened,... entries contain the scope number, closed/opened,...

61 61

62 62

63 63 Association lists and central reference tables in languages with dynamic scoping in languages with dynamic scoping association lists (A-lists) association lists (A-lists) simple, ellegant, can be very inefficient simple, ellegant, can be very inefficient functions as a stack functions as a stack when execution enters a scope, bindings for names declared in the scope are pushed on the front when execution leaves the scope, the bindings are removed for a meaning of a name the list is searched from the front for a meaning of a name the list is searched from the front each entry contains all data needed for semantic check each entry contains all data needed for semantic check problem: it may take a long time to find an entry problem: it may take a long time to find an entry

64 64 central reference tables central reference tables resemble Le Blank and Cook table, without the scope stack, more work on scope entry and exit, lookup much faster resemble Le Blank and Cook table, without the scope stack, more work on scope entry and exit, lookup much faster a list (stack) of entries for each distinct name in the program, most recent on the beginning a list (stack) of entries for each distinct name in the program, most recent on the beginning when control enters a new scope, a new entry is pushed on the beginning of the list for every (re)declared name when control leaves he scope, these entries are popped more expensive, lookup much faster more expensive, lookup much faster the space can be reclaimed the space can be reclaimed deep and shallow binding/access/search deep and shallow binding/access/search

65 65

66 66 Binding of referencing environments WHEN scope rules should be applied? WHEN scope rules should be applied? usually no problem (just apply scope rules) usually no problem (just apply scope rules) problematic case: references to subroutines problematic case: references to subroutines e.g. function parameters e.g. function parameters these may have non-local references, too! these may have non-local references, too! when the reference was created? when the reference was created? when the referred routine is (finally) used? when the referred routine is (finally) used? In other words In other words WHAT is the referencing environment of a subroutine reference? WHAT is the referencing environment of a subroutine reference?

67 67

68 68 Shallow & deep binding Consider example of Fig. 3.16 (dynamic scoping) Consider example of Fig. 3.16 (dynamic scoping) print_routine print_routine should create its environment just before it’s used should create its environment just before it’s used otherwise the ‘format trick’ would not work this late binding is called shallow binding this late binding is called shallow binding default in dynamically scoped languages default in dynamically scoped languages older_than older_than is designed to use the global threshold variable is designed to use the global threshold variable i.e. it is meant to be used in that one and only environment referencing environment referencing environment should be bound when older_than is passed as a parameter and used when it is finally called this early binding is called deep binding this early binding is called deep binding

69 69 Implementing deep binding Subroutine closure bundles together Subroutine closure bundles together pointer to subroutine code and it’s pointer to subroutine code and it’s referencing environment referencing environment Dynamic scoping Dynamic scoping environment implemented as a binding stack environment implemented as a binding stack book calls this an association list book calls this an association list current top of stack defines the environment current top of stack defines the environment when a routine is passed as a parameter when a routine is passed as a parameter save current top of the stack in the closure & pass closure save current top of the stack in the closure & pass closure when the referenced routine is called when the referenced routine is called use saved pointer as the top of stack use saved pointer as the top of stack if other functions are called, grow another ‘top’ for the stack from this point (list-implemented stack) if other functions are called, grow another ‘top’ for the stack from this point (list-implemented stack)

70 70 Deep binding & static scope Deep binding is default in static scope Deep binding is default in static scope shallow binding does not make much sense shallow binding does not make much sense Does the binding time matter at all? Does the binding time matter at all? generally not generally not name  lexical nesting name  lexical nesting nesting does not change nesting does not change recursion! recursion! we must find the correct instance, too we must find the correct instance, too closure must capture the current instance of every visible object when it is created closure must capture the current instance of every visible object when it is created this saved closure is then used when routines are used this saved closure is then used when routines are used example in Fig. 3.17 example in Fig. 3.17

71 71

72 72 Some notes Binding rules matter (with static scoping) only Binding rules matter (with static scoping) only when referencing objects that are not local neither global when referencing objects that are not local neither global irrelevant in irrelevant in C: no nested structure C: no nested structure Modula-2: only top-level routines can be passed as parameters Modula-2: only top-level routines can be passed as parameters and in all languages that do not permit passing subroutines as arguments and in all languages that do not permit passing subroutines as arguments

73 73 Implementing deep binding Static links define referencing environments Static links define referencing environments pass: create closure with current static link pass: create closure with current static link call: use the saved static link (instead of creating a new one) when creating the frame record call: use the saved static link (instead of creating a new one) when creating the frame record static chain is now the same as at the time the parameter was passed static chain is now the same as at the time the parameter was passed

74 74 Classes of objects (values) First-class objects can be First-class objects can be passed as parameters passed as parameters returned from a subroutine returned from a subroutine assigned to variables assigned to variables e.g. integers in most languages e.g. integers in most languages Second-class objects Second-class objects can only be passed as parameters, not returned from a subroutine, neither assigned into a variable can only be passed as parameters, not returned from a subroutine, neither assigned into a variable e.g. subroutines in most languages, arrays in C/C++ e.g. subroutines in most languages, arrays in C/C++ Third-class objects Third-class objects can not even be passed as a parameter can not even be passed as a parameter e.g. jump labels (in most languages that have a goto-statement) e.g. jump labels (in most languages that have a goto-statement)

75 75 Subroutines & classes First-class First-class functional languages functional languages note: these can even create new subroutines note: these can even create new subroutines Modula-2 & -3, Ada 95, C, C++ Modula-2 & -3, Ada 95, C, C++ language-specific restrictions on use language-specific restrictions on use Second-class Second-class almost all other languages almost all other languages Ada 83: third-class Ada 83: third-class

76 76 Problem with first-class subroutines... Reference to a subroutine Reference to a subroutine may live longer than the scope that created it may live longer than the scope that created it  referencing environment no longer exists when the routine is called  referencing environment no longer exists when the routine is called Functional languages Functional languages unlimited extent of local objects unlimited extent of local objects frames are allocated from the heap (not stack) frames are allocated from the heap (not stack) garbage collected when no references remain garbage collected when no references remain

77 77...Problem with first-class subroutines Imperative languages want to use the stack Imperative languages want to use the stack limited extent of local objects limited extent of local objects frames are deleted from the stack when execution leaves the subroutine frames are deleted from the stack when execution leaves the subroutine  dangling references if 1 st class subroutines  dangling references if 1 st class subroutines Algol-family languages have different workarounds Algol-family languages have different workarounds Modula-2: only top-level subroutines can be referenced to Modula-2: only top-level subroutines can be referenced to Modula-3 Modula-3 only top-level subroutines are 1 st class, others are 2 nd class only top-level subroutines are 1 st class, others are 2 nd class Ada 95 Ada 95 a nested routine can be returned (by a function) only to a scope that contains that routine a nested routine can be returned (by a function) only to a scope that contains that routine  referencing environment will always be alive  referencing environment will always be alive C/C++: no problem (because they have no nested scopes) C/C++: no problem (because they have no nested scopes)

78 78 Overloading Aliasing: multiple names for the same object Aliasing: multiple names for the same object Overloading: one name for several objects Overloading: one name for several objects in the same scope in the same scope semantic rules: context of the name must give enough information to resolve the binding semantic rules: context of the name must give enough information to resolve the binding most programming languages support at least some overloading (arithmetic operations) most programming languages support at least some overloading (arithmetic operations) in symbol table lookup finds all possible entries with the name and semantic analyzer chooses in symbol table lookup finds all possible entries with the name and semantic analyzer chooses

79 79 Overloading of... Enumeration constants Enumeration constants Ada example in Figure 3.18 Ada example in Figure 3.18 dec & oct overloaded dec & oct overloaded print has not sufficient context  explicit qualification required ( print (month’(oct)); ) print has not sufficient context  explicit qualification required ( print (month’(oct)); ) Modula-3: each occurrence must be qualified ( month.dec ) Modula-3: each occurrence must be qualified ( month.dec ) C, C++, Pascal: this kind of overloading is not allowed C, C++, Pascal: this kind of overloading is not allowed Subroutines Subroutines Ada, C++ Ada, C++ arbitrary number as long as parameter types/number are different arbitrary number as long as parameter types/number are different also arithmetic operators (syntactic sugar) also arithmetic operators (syntactic sugar) Figure 3.19 Figure 3.19

80 80

81 81

82 82 Overloading is NOT coercion Coercion Coercion process in which the compiler automatically process in which the compiler automatically converts an object X:T1 to another type T2 converts an object X:T1 to another type T2 when X is used in a context where T2 is expected when X is used in a context where T2 is expected In overloading In overloading separate functions are selected by the compiler for different uses separate functions are selected by the compiler for different usesADA: function abs (n : integer) return integer is... function abs (x : real) return real is... In coercion In coercion there is only one function there is only one function compiler makes the necessary type transformations compiler makes the necessary type transformationsFORTRAN: real function abs (x) real x... C, C++, in Ada only explicit constants, subranges and sometimes arrays C, C++, in Ada only explicit constants, subranges and sometimes arrays

83 83 Overloading is NOT polymorphism Polymorphism Polymorphism polymorphic objects may represent objects of more than one type polymorphic objects may represent objects of more than one type subroutines can manipulate the polymorphic parameters without any conversions subroutines can manipulate the polymorphic parameters without any conversions either all objects have some common characteristics (and only these are used) either all objects have some common characteristics (and only these are used) or objects contain other information so the subroutine can customize itself appropriately or objects contain other information so the subroutine can customize itself appropriately

84 84 Examples of polymorphism abs(x) for any type that supports abs(x) for any type that supports comparison ‘> 0’ and comparison ‘> 0’ and negation negation counting the length of a list (of any type) counting the length of a list (of any type) only succ & empty –tests required only succ & empty –tests required Lisp, Scheme, Smalltalk Lisp, Scheme, Smalltalk to a more limited extent in C++, Java to a more limited extent in C++, Java conformant array parameters conformant array parameters very limited form of polymorphism (Pascal, Ada) very limited form of polymorphism (Pascal, Ada)

85 85 Overloading is NOT generics Generic subroutines (or modules) Generic subroutines (or modules) parameterized templates that can be instantiated to create concrete subroutines parameterized templates that can be instantiated to create concrete subroutines early C++ versions used cpp to do this early C++ versions used cpp to do this Ada example in Fig. 3.20 Ada example in Fig. 3.20 Generics is not polymorphism Generics is not polymorphism polymorphic routine is a single object capable of accepting multiple types polymorphic routine is a single object capable of accepting multiple types compiled to a single body of code compiled to a single body of code generic routines are instantiated to create an own concrete routine for each different use generic routines are instantiated to create an own concrete routine for each different use compiled to several copies of the code compiled to several copies of the code Ada allows these instance names to be overloaded Ada allows these instance names to be overloaded C++ requires them to do so C++ requires them to do so

86 86

87 87 Naming-related pitfalls... Redefinition of function name inside the function Redefinition of function name inside the function recursion impossible recursion impossible Pascal: function name is used to define the return value Pascal: function name is used to define the return value  strange problems  strange problems function foo : integer... type foo =...... begin (* foo *)... foo := 10; (*static semantic error! *) most current languages use return-statement or some special pseudo-variable for return values most current languages use return-statement or some special pseudo-variable for return values

88 88 Scope of a name Scope of a name entire block it is declared in (Pascal) entire block it is declared in (Pascal) names must be declared before they are used names must be declared before they are used strange consequences when names refer to each other strange consequences when names refer to each other do we use ‘external’ or ‘internal’ name? do we use ‘external’ or ‘internal’ name? const missing = -1;... procedure foo; const null = missing; (* static semantic error! *)... missing = 0; or from the declaration to the end of the block? (Ada) or from the declaration to the end of the block? (Ada) or either to the end of the block or next re-definition (ML) or either to the end of the block or next re-definition (ML)

89 89...Naming-related pitfalls Recursive data types Recursive data types need to reference to the not-yet-defined type need to reference to the not-yet-defined type Pascal: pointers are an exception to the general ‘declare before use’ rule Pascal: pointers are an exception to the general ‘declare before use’ rule pointer declaration makes a forward reference pointer declaration makes a forward referencetype Alink = ^A; A = record next : Alink; data :... C, C++, Ada C, C++, Ada forward references are forbidden but incomplete type definitions are allowed forward references are forbidden but incomplete type definitions are allowed type A; type Alink is access A; type A is recordADA next : Alink; data :...

90 90 Mutually recursive subroutines Mutually recursive subroutines need to reference to a not-yet-defined subroutine need to reference to a not-yet-defined subroutine Pascal: forward declarations Pascal: forward declarations Modula-3: order of declarations does not matter Modula-3: order of declarations does not matter Java, C++ Java, C++ variables ‘declared before used’ variables ‘declared before used’ classes can be used before they are (totally) declared classes can be used before they are (totally) declared order of routines does not matter (inside a class) order of routines does not matter (inside a class)


Download ppt "1 Names, Scopes and Bindings and Bindings. 2 High-level programming languages High-level features relative to assembly language High-level features relative."

Similar presentations


Ads by Google